2013-08-09 2 views
0

이미지 크기를 조정하고 jpg로 저장해야하는 앱이 있습니다. 내 테스트 이미지는 하늘에서 매우 부드러운 그라디언트가 적용된 사진입니다. 이 코드를 사용하여 크기 조정 후 JPEG로 저장하기 위해 노력하고있어 :Bitmap.compress 결과가 너무 큽니다.

dstBmp = Bitmap.createBitmap(srcBmp, cropX, 0, tWidth, srcBmp.getHeight()); 
if (android.os.Build.VERSION.SDK_INT > 12) { 
    Log.w("General", "Calling setHasAlpha"); 
    dstBmp.setHasAlpha(true); 
} 
dstBmp = Bitmap.createScaledBitmap(dstBmp, scaledSmaller, scaledLarger, true); 
OutputStream out = null; 
File f = new File(directory + "/f"+x+".jpg"); 
try { 
    f.createNewFile(); 
    out = new FileOutputStream(f); 
} catch (FileNotFoundException e) { 
    e.printStackTrace(); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

dstBmp.compress(CompressFormat.JPEG, jpegQuality, out); 

문제는 내가 그러나 주변에 95에 품질을 충돌하지 않는 과도한 띠는 품질로, 이미지의 기울기에서 발생한다는 것입니다 수준 95, 결과 파일은 150kb 이상입니다. 포토샵에서 이와 동일한 기능을 수행하고 "웹용으로 저장"을 수행하면 이미지 크기가 50kb 인 품질 수준 40까지 줄무늬가 생기는 것을 피할 수 있습니다. 내 웹 서버에서 ImageCR을 사용하면 30kb로 동일하게 수행 할 수 있습니다.

jpeg로 이미지를 더 효율적으로 압축 할 수있는 방법이 있습니까? 아니면 별도의 라이브러리 또는 API를 사용할 수 있습니까? 많은 양의 이미지를 메모리에로드하고 있으며이 속도로 앱이 오래된 장치의 OOM 오류를 위협하고 있습니다. 그것이 최종 결과에 도움이된다면 이미지 조작에 더 많은 시간을 할당하게되어 기쁩니다.

답변

2

요컨대 http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

로부터이 코드를하려고하면 2 개 정적 메소드

이미지의 새로운 크기를 산출하기위한 제를

public static int calculateInSampleSize(
     BitmapFactory.Options options, int reqWidth, int reqHeight) { 
// Raw height and width of image 
final int height = options.outHeight; 
final int width = options.outWidth; 
int inSampleSize = 1; 

if (height > reqHeight || width > reqWidth) { 

    // Calculate ratios of height and width to requested height and width 
    final int heightRatio = Math.round((float) height/(float) reqHeight); 
    final int widthRatio = Math.round((float) width/(float) reqWidth); 

    // Choose the smallest ratio as inSampleSize value, this will guarantee 
    // a final image with both dimensions larger than or equal to the 
    // requested height and width. 
    inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; 
} 

return inSampleSize; 
} 

으로 스케일링 된 크기의 이미지를로드하는 제 2 메모리 :

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
    int reqWidth, int reqHeight) { 

// First decode with inJustDecodeBounds=true to check dimensions 
final BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inJustDecodeBounds = true; 
BitmapFactory.decodeResource(res, resId, options); 

// Calculate inSampleSize 
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

// Decode bitmap with inSampleSize set 
options.inJustDecodeBounds = false; 
return BitmapFactory.decodeResource(res, resId, options); 
} 

및 할 수 있습니다. 이런 모든 기능은 :

BitmapFactory.decodeFile(path, options); 
:

Bitmap b = decodeSampledBitmapFromResource(getResources(), R.id.myimage, 128, 128)); 

당신은 대신 decodeResource의 사용, (이미지 SDCARD에 파일이있는 경우 경로를) 대신 자원의 문자열 parametar 입력을 위해 두 번째 방법을 수정할 수 있습니다

큰 이미지를로드 할 때 항상이 코드를 사용합니다.

+0

감사합니다. 내가 게시 한 코드를 이해하려고합니다. 여전히 Java에있어서 꽤 새로운 것입니다. 이것이 최종 저장 jpg의 품질이나 크기에 어떤 영향을 주는지 설명해 주시겠습니까? – Nicholas

+0

이 코드는 비트 맵을 표시하거나 저장하기 위해로드/스케일링해야 할 때 유용합니다. 비트 맵을 사용할 때 안드로이드 OS는 메모리를 할당하고 런타임에 사용 가능한 메모리가 충분하지 않으면 OutOfMemoryException이 발생할 수 있습니다. 이 메소드는 options.inJustDecodeBounds = true 옵션을 사용하여 이미지의 크기를 확인합니다. 이미지를 메모리에로드하지 않고 크기를 조정합니다. 최종 jpg는 내 예제에서 128x128 픽셀 (정확하지는 않음) 이상이고 크기와 품질은 더 낮습니다. 그런 다음이 크기 조정 된 비트 맵을 사용하여 메모리에 저장할 수 있습니다. – Riste

+0

이것은 스케일링 프로세스의 메모리 풋 프린트를 줄이는 것처럼 보이지만, SD 카드에 저장된 결과 파일의 크기가 같으면 동일한 크기가 주어진 것처럼 보입니다. jpg 크기는 해상도 나 품질의 손실없이 줄이는 것에 대해 우려하고 있습니다. – Nicholas