2017-04-18 9 views
0

미리 정의 된 파일 크기 (내 경우 512KB)로 새 이미지를 생성하기 위해 이미지 크기를 조정 (파일로 저장)하는 작은 방법이 있습니다.). 방법은 같이 보입니다 다음안드로이드 - 이미지 크기를 줄이면 같은 비율로 크기가 줄어들지 않습니다

private static final int maximumFileSizeInKBs = 512; 

public static Uri resizeImage(Context context, Uri imageUri) { 
    // get image width and height 
    BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    Bitmap imageBitmap = BitmapFactory.decodeFile(new File(imageUri.getPath()).getAbsolutePath(), options); 
    int imageWidth = options.outWidth; 
    int imageHeight = options.outHeight; 

    // get image file size (in KBs) 
    File file = new File(imageUri.getPath()); 
    int fileSizeInKBs = Integer.parseInt(String.valueOf(file.length()/1024)); 

    // get the scaling factor 
    // (square root because when we scale both the width and height by the 
    // square root of the scaling factor, then the size of the final image 
    // will be scaled by the scaling factor) 
    double scalingFactor = Math.sqrt(fileSizeInKBs/maximumFileSizeInKBs); 

    // no need to scale if file already within maximum file size limit 
    if(scalingFactor <= 1) { 
     return imageUri; 
    } 

    // get scaled dimensions 
    int scaledImageWidth = (int) Math.floor(imageWidth/scalingFactor); 
    int scaledImageHeight = (int) Math.floor(imageHeight/scalingFactor); 

    // load original bitmap (load a scaled copy to avoid OutOfMemory errors) 
    options = new BitmapFactory.Options(); 
    options.inSampleSize = Math.max(imageHeight/scaledImageWidth, imageHeight/scaledImageHeight); 
    imageBitmap = BitmapFactory.decodeFile(new File(imageUri.getPath()).getAbsolutePath(), options); 

    // the scaled image above will be scaled by a value equal to the 
    // nearest power of 2, hence it wont be scaled to the exact value 
    // that we want. So, we need to calculate new scaling factors 
    // based on the scaled loaded bitmap 
    Matrix m = new Matrix(); 
    RectF inRect = new RectF(0, 0, imageWidth, imageHeight); 
    RectF outRect = new RectF(0, 0, scaledImageWidth, scaledImageHeight); 
    m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER); 
    float[] values = new float[9]; 
    m.getValues(values); 

    // create a scaled bitmap with required file size 
    Bitmap scaledBitmap = Bitmap.createScaledBitmap(imageBitmap, (int) (imageWidth*values[0]), (int) (imageHeight*values[4]), true); 

    // delete original image 
    new File(imageUri.getPath()).delete(); 

    // write bitmap to file 
    File newImageFile = BaseResourceClass.makeTempResourceFile(Slide.ResourceType.IMAGE, context); 
    try { 
     newImageFile.createNewFile(); 
     FileOutputStream fos = new FileOutputStream(newImageFile); 
     scaledBitmap.compress(Bitmap.CompressFormat.PNG, 1, fos); 
     fos.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     Toast.makeText(context, "Something went wrong", Toast.LENGTH_SHORT).show(); 
    } 

    // recycle bitmaps to reallocate memory 
    Storage.recycleBitmap(imageBitmap); 
    Storage.recycleBitmap(scaledBitmap); 

    // scaling done, return new Image 
    return Uri.fromFile(newImageFile); 
} 

이 방법을 실행하면 이미지 크기가 (나는 그것이 것으로 기대 같이) 정확한 크기로 줄어들지 만, KB의에서 이미지의 크기가 축소되지 않는다 같은 요인으로 예를 들어,이 방법을 실행 한 후 나는 이미지에서 너무 많은 픽셀을 제거한 후 그것을 이해하지 못하고 다음 번호

before resizing 
imageWidth : 3120, imageHeight : 4160, fileSize : 2960 KB 

after resizing 
imageWidth : 1395, imageHeight : 1860, fileSize : 2491 KB 

을 얻고, 무엇을 그것은을 유지하기 위해 너무 많은 공간을 차지 즉 이미지 파일 크기는이 정도. 다른 StackOverflow 질문 및 안드로이드 BitmapFactory 및 비트 맵 클래스 설명서를 보려고했지만이 문제는 어디에도 언급되어 있지 않습니다. 어떤 도움을 주시면 감사하겠습니다!

답변

1

왜 이런 일이 발생하는지는 사용자가 읽는 이미지 유형 (JPG, GIF, PNG, BMP), 압축 된 품질 (JPG 인 경우) 이미지 크기를 줄인 후 이미지를 저장하는 방법에 대해 설명합니다.

예제에서 사용한 이미지 또는 사용한 이미지 압축 유형을 표시하지 않습니다. 하지만 코드에서 PNG 이미지로 저장하는 것을 볼 수 있습니다.

좋은 품질의 2MB jpg 이미지를 찍었을 때와 마찬가지로 크기를 줄이지 만 PNG (저음질)로 저장하면 이전보다 더 큰 파일로 끝납니다.

JPG 이미지는 압축 알고리즘을 사용하여 이미지를 원본과 가능한 비슷하게 저장하지만 훨씬 적은 공간을 차지합니다. 품질에 따라 큰 파일 크기로 원본 이미지와 거의 같은 이미지를 얻을 수도 있고 불과 몇 킬로바이트 밖에 걸리지 않는 끔찍한 이미지를 얻을 수 있습니다.

이미지를 PNG로 저장하면 원래 이미지와 똑같은 이미지를 얻을 수 있습니다.이 때문에 이미지를 잃을 필요가 없습니다. 따라서 압축을 통해 많은 파일 크기를 저장할 수 없습니다.

PNG를 입력으로 사용하고 축소 된 버전을 PNG로 저장하면 "비례 파일 크기"아이디어에 훨씬 더 가까워집니다. 크기를 줄이면 앤티 앨리어싱을 통해 결과 이미지에 새로운 색상을 만들 수 있고 압축 성능을 약간 줄일 수 있습니다.

JPG 이미지를 사용하면 원본 이미지와 결과를 압축하는 데 사용 된 품질이 모두 예측할 수 없으므로 두 결과 모두 파일 크기에 영향을 미칩니다.

0

이미지가 압축되지 않은 경우 이미지 파일 크기가 이미지 너비 x 높이에 비례 할 것으로 예상 할 수 있습니다. BMP 형식에만 해당됩니다.

PNG 형식으로 저장된 이미지를 처리하고 있습니다. PNG는 이미지 압축을 사용하여 이미지를 저장합니다. 그래서 이미지 크기는 이미지의 세부 묘사 정도와 이미지 너비가 작은 & 높이에 더 의존합니다.

경우에 따라 이미지 크기가 두 번째 매개 변수 인 품질에 가장 많이 좌우됩니다.

scaledBitmap.compress (Bitmap.CompressFormat.PNG, , fos);

파일을 작게 만들려면이 값을 0으로 변경할 수 있습니다.

image