android减少摄像头捕获图像的文件大小小于500 kb

少年恃险若平地,独倚长剑凌清秋。这篇文章主要讲述android减少摄像头捕获图像的文件大小小于500 kb相关的知识,希望能为你提供帮助。
我的要求是将摄像头捕获的图像上传到服务器,但它应该小于500 KB。如果它大于500 KB,则需要将其减小到小于500 KB的大小(但稍微接近它)
为此,我使用以下代码 -

@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { try { super.onActivityResult(requestCode, resultCode, data); if (resultCode == getActivity().RESULT_OK) {if (requestCode == REQUEST_CODE_CAMERA) {try {photo = MediaStore.Images.Media.getBitmap( ctx.getContentResolver(), capturedImageUri); String selectedImagePath = getRealPathFromURI(capturedImageUri); img_file = new File(selectedImagePath); Log.d("img_file_size", "file size in KBs (initially): " + (img_file.length()/1000)); if(CommonUtilities.isImageFileSizeGreaterThan500KB(img_file)) { photo = CommonUtilities.getResizedBitmapLessThan500KB(photo, 500); } photo = CommonUtilities.getCorrectBitmap(photo, selectedImagePath); //// CALL THIS METHOD TO GET THE URI FROM THE BITMAPimg_file = new File(ctx.getCacheDir(), "image.jpg"); img_file.createNewFile(); //Convert bitmap to byte array ByteArrayOutputStream bytes = new ByteArrayOutputStream(); photo.compress(Bitmap.CompressFormat.JPEG, 100, bytes); //write the bytes in file FileOutputStream fo = new FileOutputStream(img_file); fo.write(bytes.toByteArray()); // remember close de FileOutput fo.close(); Log.d("img_file_size", "file size in KBs after image manipulations: " + (img_file.length()/1000)); } catch (Exception e) { Logs.setLogException(class_name, "onActivityResult(), when captured from camera", e); }} } } catch (Exception e) { Logs.setLogException(class_name, "onActivityResult()", e); } catch (OutOfMemoryError e) { Logs.setLogError(class_name, "onActivityResult()", e); } }


public static Bitmap getResizedBitmapLessThan500KB(Bitmap image, int maxSize) { int width = image.getWidth(); int height = image.getHeight(); float bitmapRatio = (float)width / (float) height; if (bitmapRatio > 0) { width = maxSize; height = (int) (width / bitmapRatio); } else { height = maxSize; width = (int) (height * bitmapRatio); } Bitmap reduced_bitmap = Bitmap.createScaledBitmap(image, width, height, true); if(sizeOf(reduced_bitmap) > (500 * 1000)) { return getResizedBitmap(reduced_bitmap, maxSize); } else { return reduced_bitmap; } }

如果需要,旋转图像。
public static Bitmap getCorrectBitmap(Bitmap bitmap, String filePath) { ExifInterface ei; Bitmap rotatedBitmap = bitmap; try { ei = new ExifInterface(filePath); int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); Matrix matrix = new Matrix(); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: matrix.postRotate(90); break; case ExifInterface.ORIENTATION_ROTATE_180: matrix.postRotate(180); break; case ExifInterface.ORIENTATION_ROTATE_270: matrix.postRotate(270); break; }rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return rotatedBitmap; }

这是最初和在减少文件大小的所有操作之后的图像文件大小的输出。
img_file_size:文件大小(KBs)(最初):3294
img_file_size:图像处理后的文件大小(KB):235
请参阅上面的差异(在输出中)。没有那些操作的初始文件大小,以及那些压缩和其他操作之后。我需要这个尺寸有点接近500 kb。
上面的代码对我来说工作得有点好,因为它减少了图像文件的大小,使其小于500 KB。
但是,以下是上述代码的问题 -
  • 此代码即使小于500 KB也会减小文件大小
  • 如果它超过500 KB,减小的文件大小从500 KB变得太小,虽然我需要它更接近。
我需要摆脱2个问题。所以,需要知道我应该在上面的代码中操作什么。
因为我还想纠正EXIF方向(旋转图像),以及我上面提到的要求。
答案您可以在调整大小之前检查大小。如果位图的大小超过500kb,则调整其大小。
另外,为了使更大的位图接近500kb大小,请检查大小和压缩之间的差异。
if(sizeOf(reduced_bitmap) > (500 * 1024)) { return getResizedBitmap(reduced_bitmap, maxSize, sizeOf(reduced_bitmap)); } else { return reduced_bitmap; }

并在调整大小时Bitmap计算大小的差异并相应地压缩
另一答案【android减少摄像头捕获图像的文件大小小于500 kb】这不是您的问题的解决方案,而是您获得非常小的文件的错误。
getResizedBitmapLessThan500KB(photo, 500)中,500是图像像素的最大/高度,而不是kb的最大尺寸。
所以所有压缩文件都少于500x500像素
另一答案为了减少Image的大小我已经使用了这段代码..它的工作对我来说..请检查一次..它可能对你有所帮助..
Bitmap photo1 ; private byte[] imageByteArray1 ; BitmapFactory.Options opt1 = new BitmapFactory.Options(); opt1.inJustDecodeBounds=true; BitmapFactory.decodeFile(imageUrl.get(imgCount).toString(),opt1); // The new size we want to scale to final int REQUIRED_SIZE=320; // Find the correct scale value. It should be the power of 2. int width_tmp=opt1.outWidth,height_tmp=opt1.outHeight; int scale=2; while(true){ if(width_tmp> REQUIRED_SIZE||height_tmp> REQUIRED_SIZE) break; width_tmp/=2; height_tmp/=2; scale*=2; } // Decode with inSampleSize BitmapFactory.Options o2=new BitmapFactory.Options(); o2.inSampleSize=scale; o2.inJustDecodeBounds=false; photo1=BitmapFactory.decodeFile(imageUrl.get(imgCount).toString(),o2); ByteArrayOutputStream baos1=new ByteArrayOutputStream(); photo1.compress(Bitmap.CompressFormat.JPEG,60,baos1); imageByteArray1=baos1.toByteArray();

另一答案您遇到的另一个问题是您正在测量位图的大小(未压缩),然后将其转换为JPG并进行测量。 JPG可能总是会变小,而压缩的程度将是图像的一个因素。有很多相同颜色的大区域?大!一个非常“忙”的模式?压缩不会那么大。
好的,进一步澄清:
如果您要定位某个文件大小,则无法通过查看压缩前的大小来执行此操作。你可以得到一个大概的想法(例如,这些照片的JPEG压缩系数约为15),那么你可以为位图设定500k * 15的目标。但根据照片中的内容,您可能无法完全达到目标。所以你可能想这样做:
  1. 选择一个jpegFactor
  2. bitMapTarget = target * jpegFactor
  3. adjustBitmap大小适合bitMapTarget
  4. 将位图压缩为JPEG
  5. 如果这仍然高于目标,则调整jpegFactor并再试一次。
您可以在#5上采取一些步骤来确定您的接近程度,并尝试将其考虑在内。
另一答案自定义我的getResizedBitmapLessThan500KB()到下面这个,对我有用。
public static final long CAMERA_IMAGE_MAX_DESIRED_SIZE_IN_BYTES = 2524970; public static final double CAMERA_IMAGE_MAX_SIZE_AFTER_COMPRESSSION_IN_BYTES = 1893729.0; public static Bitmap getResizedBitmapLessThan500KB(Bitmap image, int maxSize, long file_size_in_bytes) { int width = image.getWidth(); int height = image.getHeight(); if(file_size_in_bytes < = AppGlobalConstants.CAMERA_IMAGE_MAX_DESIRED_SIZE_IN_BYTES) { if (width > height) { if (width > 500) maxSize = width * 75 / 100; } else { if (height > 500) maxSize = height * 75 / 100; } } else { double percentage = ((AppGlobalConstants.CAMERA_IMAGE_MAX_SIZE_AFTER_COMPRESSSION_IN_BYTES/file_size_in_bytes)*100); if (width > height) { if (width > 500) maxSize = width * (int)percentage / 100; } else { if (height > 500) maxSize = height * (int)percentage / 100; }if(maxSize > 600) { maxSize = 600; }}float bitmapRatio = (float)width / (float) height; if (bitmapRatio > 0) { width = maxSize; height = (int) (width / bitmapRatio); } else { height = maxSize; width = (int) (height * bitmapRatio); } Bitmap reduced_bitmap = Bitmap.createScaledBitmap(image, width, height, true); //Log.d("file_size","file_size_during_manipulation: "+String.valueOf(sizeOf(reduced_bitmap))); if(sizeOf(reduced_bitmap) > (500 * 1000)) { return getResizedBitmap(reduced_bitmap, maxSize, sizeOf(reduced_bitmap)); } else { return reduced_bitmap; } }

另一答案你可以尝试这种方法
public static Bitmap getScaledBitmap(Bitmap b, int reqWidth, int reqHeight) { Matrix m = new Matrix(); m.setRectToRect(new RectF(0, 0, b.getWidth(), b.getHeight()), new RectF(0, 0, reqWidth, reqHeight), Matrix.ScaleToFit.CENTER); return Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, true); }//call this method like Bitmap bm400=getScaledBitmap(bm,500,500);

它对你有帮助。
另一答案我假设您想使用图库或系统相机来获取图像。请注意,通过Intent传输的最大数据有一个上限,这就是为什么你总是得到缩小版图像的原因。
您可以参考https://developer.android.com/training/camera/photobasics.html获取标准解决方案。总之,您应该获得对外部存储的访问权限并为相机生成URI或从gallery应用程序获取URI。然后使用ContentResolver来获取图像。
InputStream inputStream = mContentResolver.openInputStream(mUri);

您可能希望为其他应用程序实现内容解析程序以访问您的数据,这是标准做法。
另一答案请检查此代码是否有用:
final static int COMPRESSED_RATIO = 13; final static int perPixelDataSize = 4; public byte[] getJPGLessThanMaxSize(Bitmap image, int maxSize){ int maxPixelCount = maxSize *1024 * COMPRESSED_RATIO / perPixelDataSize; int imagePixelCount = image.getWidth() * image.getHeight(); Bitmap reducedBitmap; // Adjust Bitmap Dimensions if necessary. if(imagePixelCount > maxPixelCount) reducedBitmap = getResizedBitmapLessThanMaxSize(image, maxSize); else reducedBitmap = image; float compressedRatio = 1; byte[] resultBitmap; ByteArrayOutputStream outStream = new ByteArrayOutputStream(); int jpgQuality = 100; // Adjust Quality until file size is less than maxSize. do{ reducedBitmap.compress(Bitmap.CompressFormat.JPEG, jpgQuality, outStream); resultBitmap = outStream.toByteArray(); compressedRatio = resultBitmap.length / (reducedBitmap.getWidth() * reducedBitmap.getHeight() * perPixelDataSize); if(compressedRatio > (COMPRESSED_RATIO-1)){ jpgQuality -= 1; }else if(compressedRatio > (COMPRESSED_RATIO*0.8)){ jpgQuality -= 5; }else{ jpgQuality -= 10; } }while(resultBitmap.length > (maxSize * 1024)); return resultBitmap; }public Bitmap getResizedBitmapLessThanMaxSize(Bitmap image, int maxSize) { int width = image.getWidth(); int height = image.getHeight(); float bitmapRatio = (float)width / (float) height; // For uncompressed bitmap, the data size is: // H * W * perPixelDataSize = H * H * bitmapRatio * perPixelDataSize // height = (int) Math.sqrt(maxSize * 1024 * COMPRESSED_RATIO / perPixelDataSize / bitmapRatio); width = (int) (height * bitmapRatio); Bitmap reduced_bitmap = Bitmap.createScaledBitmap(image, width, height, true); return reduced_bitmap; }


    推荐阅读