【问题标题】:Reduce size of captured image from camera in android在android中减小从相机捕获的图像的大小
【发布时间】:2014-01-03 15:54:59
【问题描述】:

在这里,我将拍摄的图像从相机保存在 sdcard 上。在这里,捕获的图像大小大于1 MB。在保存到 sdcard 之前,我想将此大小减小到近 500kb 到 600kb。我怎么能这样做?

try 
        {
            Bitmap mPhoto;
            mPhoto = android.provider.MediaStore.Images.Media.getBitmap(cr, CheckInGallery.mUri);
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            mPhoto.compress(Bitmap.CompressFormat.PNG, 100, bytes);

            File direct = new File(Environment.getExternalStorageDirectory() + "/RetailRun");
            String mydate = java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
            Toast.makeText(getBaseContext(), "Time :" + mydate, 5000).show();

            if(!direct.exists())
            {
                direct.mkdir();
                File file = new File(Environment.getExternalStorageDirectory()+File.separator + "/MyImage/image" + mydate +".jpg");
                file.createNewFile();
                FileOutputStream fo = new FileOutputStream(file);
                fo.write(bytes.toByteArray());
                fo.close();
             }

         else
            {
                File file = new File(Environment.getExternalStorageDirectory()+File.separator + "/MyImage/image" + mydate +".jpg");
                file.createNewFile();
                FileOutputStream fo = new FileOutputStream(file);
                fo.write(bytes.toByteArray());
                fo.close();
            }



        }

        catch (Exception e) 
        {
            Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
        }

【问题讨论】:

    标签: android image android-camera


    【解决方案1】:
    mPhoto.compress(Bitmap.CompressFormat.PNG, 100, bytes);
    

    100 在这个是最好的质量。如果您想减小尺寸,请尝试减小该值

    其他方法可能是使用 BitmapFactory.Options() 的 inSampleSize 参数。那也应该减小尺寸。你可以读到here

    编辑: 一些代码

    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize=2; //4, 8, etc. the more value, the worst quality of image
    
    Bitmap bmp=BitmapFactory.decodeStream(getContentResolver().openInputStream(CheckInGallery.mUri), null, options);
    

    这应该加载质量稍差的图像。

    然后保存图片

    bmp.compress(Bitmap.CompressFormat.PNG, 70, bytes);
    

    【讨论】:

    • 表示我应该尝试使用少于 100 个,例如 80 或 70 个??
    • 是的,这应该会有所帮助
    • 所以尝试第二种方法并阅读 BitmapFactory.Options() 的 inSampleSize 参数。这也应该减少位图的大小。见我上面的编辑
    • 来自 Bitmap.CompressFormat 文档 -> 一些格式,例如无损的 PNG,将忽略质量设置。尝试使用另一种格式,例如 JPEG
    【解决方案2】:

    这对我有用。

        public void onImageSelected(){
        Uri uri=null; // get the uri of the image result from the intent
        try {
    
            Bitmap bitmap = handleSamplingAndRotationBitmap(this, uri);
            byte[] bytes = getBytesFromBitmap(bitmap);
            //getPresenter.upload(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    
    /**
     * returns an aligned bitmap with size not exceeding the MAX_HEIGHT
     * @param context
     * @param selectedImage
     * @return
     * @throws IOException
     */
    public Bitmap handleSamplingAndRotationBitmap(Context context, Uri selectedImage)
            throws IOException {
        Bitmap decoded = getImageSampleOutput(context,selectedImage);
        decoded = rotateImageIfRequired(this, decoded, selectedImage);
        return decoded;
    }
    
    public Bitmap getImageSampleOutput(Context context, Uri selectedImage) throws IOException {
        int MAX_HEIGHT = 1200;
        int MAX_WIDTH = 1600;
    
        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        InputStream imageStream = context.getContentResolver().openInputStream(selectedImage);
        BitmapFactory.decodeStream(imageStream, null, options);
        imageStream.close();
    
        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, MAX_WIDTH, MAX_HEIGHT);
        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        imageStream = context.getContentResolver().openInputStream(selectedImage);
        Bitmap img = BitmapFactory.decodeStream(imageStream, null, options);
        Bitmap decoded = compressImage(img);
        return decoded;
    }
    
    
    /**
     * Used to compress the image to prevent any Memory overflows.
     * @param bitmap
     * @return
     */
    public Bitmap compressImage(Bitmap bitmap) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
        return BitmapFactory.decodeStream(new ByteArrayInputStream(out.toByteArray()));
    }
    
    
    private 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;
    
            // This offers some additional logic in case the image has a strange
            // aspect ratio. For example, a panorama may have a much larger
            // width than height. In these cases the total pixels might still
            // end up being too large to fit comfortably in memory, so we should
            // be more aggressive with sample down the image (=larger inSampleSize).
    
            final float totalPixels = width * height;
    
            // Anything more than 2x the requested pixels we'll sample down further
            final float totalReqPixelsCap = reqWidth * reqHeight * 2;
    
            while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
                inSampleSize++;
            }
        }
        return inSampleSize;
    }
    
    private static Bitmap rotateImageIfRequired(Context context, Bitmap img, Uri selectedImage) {
    
        // Detect rotation
        int rotation = getRotation(context, selectedImage);
        if (rotation != 0) {
            Matrix matrix = new Matrix();
            matrix.postRotate(rotation);
            Bitmap rotatedImg = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true);
            img.recycle();
            return rotatedImg;
        } else {
            return img;
        }
    }
    
    /**
     * Get the rotation of the last image added.
     *
     * @param context
     * @param selectedImage
     * @return
     */
    private static int getRotation(Context context, Uri selectedImage) {
    
        int rotation = 0;
        ContentResolver content = context.getContentResolver();
    
        Cursor mediaCursor = content.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                new String[]{"orientation", "date_added"},
                null, null, "date_added desc");
    
        if (mediaCursor != null && mediaCursor.getCount() != 0) {
            while (mediaCursor.moveToNext()) {
                rotation = mediaCursor.getInt(0);
                break;
            }
        }
        mediaCursor.close();
        return rotation;
    }
    
    public byte[] getBytesFromBitmap(Bitmap bmp){
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.JPEG,70,stream);
        byte[] byteArray = stream.toByteArray();
        return byteArray;
    }
    

    在三星 Galaxy S7 上,我能够将大小减小到 300kb。

    【讨论】:

    • 有时三星Galaxy S7是用来缩小身体部位的...所以我们应该在缩小尺寸之前检查一个条件以限制最小尺寸...
    【解决方案3】:

    设置位图的高度和宽度是特定于设备的...

    @SuppressLint("NewApi")
        public static int getDeviceWidth(Activity activity) {
            int deviceWidth = 0;
    
            Point size = new Point();
            WindowManager windowManager = activity.getWindowManager();
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                windowManager.getDefaultDisplay().getSize(size);
                deviceWidth = size.x;
            } else {
                Display display = windowManager.getDefaultDisplay();
                deviceWidth = display.getWidth();
            }
            return deviceWidth;
        }
    
        @SuppressLint("NewApi")
        public static int getDeviceHeight(Activity activity) {
            int deviceHeight = 0;
    
            Point size = new Point();
            WindowManager windowManager = activity.getWindowManager();
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                windowManager.getDefaultDisplay().getSize(size);
                deviceHeight = size.y;
            } else {
                Display display = windowManager.getDefaultDisplay();
                deviceHeight = display.getHeight();
            }
            return deviceHeight;
        }
    

    此方法可减小图像大小。它在我的项目中起作用。

    【讨论】:

    【解决方案4】:
    **Reduce captured image size and save ..in kb**
    String imagePath = context.getFilesDir().getAbsolutePath() + File.separatorChar + "FolderName" + File.separatorChar + "ImageFolder" + File.separatorChar + imageName + ".jpg";
    
    
    File prescImagefile = new File(imagePath);
    
    try
            {
                if (prescImagefile.exists() == false)
                {
                    prescImagefile.getParentFile().mkdirs();
                    prescImagefile.createNewFile();
    
                }
            }
            catch (IOException e)
            {
                // Log.e("TAG", "Could not create file.", e);
            }
    if (prescImagefile != null)
            {
                mCapturedImageURI = Uri.fromFile(prescImagefile);
                if (mCapturedImageURI != null)
                {
                    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
                    startActivityForResult(cameraIntent, CAMERA_REQUEST);
                }
            }
    @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data)
        {
            if (resultCode == RESULT_OK)
            {
                if (requestCode == CAMERA_REQUEST)
                {
                    try
                    {
                        String path = mCapturedImageURI.getPath();
                        StoreImage(context, mCapturedImageURI, prescImagefile);
    
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
    
                }
    
            }
    
        }
    public static void StoreImage(Context mContext, Uri imgUri, File imageDir)
        {
            Bitmap bm = null;
            try
            {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 2;
                // bm = Media.getBitmap(mContext.getContentResolver(), imageLoc);
                bm = BitmapFactory.decodeStream(mContext.getContentResolver().openInputStream(imgUri), null, options);
                FileOutputStream out = new FileOutputStream(imageDir);
                bm.compress(Bitmap.CompressFormat.JPEG, 20, out);
                bm.recycle();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
    
        }
    

    【讨论】:

      【解决方案5】:

      在阅读了其他答案并没有找到我想要的东西之后,这是我获取适当​​缩放位图的方法。这是对 Prabu 答案的改编。

      它确保您的图片以不变形照片尺寸的方式缩放:

      public saveScaledPhotoToFile() {
          //Convert your photo to a bitmap
          Bitmap photoBm = (Bitmap) "your Bitmap image";
          //get its orginal dimensions
          int bmOriginalWidth = photoBm.getWidth();
          int bmOriginalHeight = photoBm.getHeight();
          double originalWidthToHeightRatio =  1.0 * bmOriginalWidth / bmOriginalHeight;
          double originalHeightToWidthRatio =  1.0 * bmOriginalHeight / bmOriginalWidth;
          //choose a maximum height
          int maxHeight = 1024;
          //choose a max width
          int maxWidth = 1024;
          //call the method to get the scaled bitmap
          photoBm = getScaledBitmap(photoBm, bmOriginalWidth, bmOriginalHeight,
                  originalWidthToHeightRatio, originalHeightToWidthRatio,
                  maxHeight, maxWidth);
      
          /**********THE REST OF THIS IS FROM Prabu's answer*******/
          //create a byte array output stream to hold the photo's bytes
          ByteArrayOutputStream bytes = new ByteArrayOutputStream();
          //compress the photo's bytes into the byte array output stream
          photoBm.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
      
          //construct a File object to save the scaled file to
          File f = new File(Environment.getExternalStorageDirectory()
                  + File.separator + "Imagename.jpg");
          //create the file
          f.createNewFile();
      
          //create an FileOutputStream on the created file
          FileOutputStream fo = new FileOutputStream(f);
          //write the photo's bytes to the file
          fo.write(bytes.toByteArray());
      
          //finish by closing the FileOutputStream
          fo.close();
      }
      
      private static Bitmap getScaledBitmap(Bitmap bm, int bmOriginalWidth, int bmOriginalHeight, double originalWidthToHeightRatio, double originalHeightToWidthRatio, int maxHeight, int maxWidth) {
          if(bmOriginalWidth > maxWidth || bmOriginalHeight > maxHeight) {
              Log.v(TAG, format("RESIZING bitmap FROM %sx%s ", bmOriginalWidth, bmOriginalHeight));
      
              if(bmOriginalWidth > bmOriginalHeight) {
                  bm = scaleDeminsFromWidth(bm, maxWidth, bmOriginalHeight, originalHeightToWidthRatio);
              } else if (bmOriginalHeight > bmOriginalWidth){
                  bm = scaleDeminsFromHeight(bm, maxHeight, bmOriginalHeight, originalWidthToHeightRatio);
              }
      
              Log.v(TAG, format("RESIZED bitmap TO %sx%s ", bm.getWidth(), bm.getHeight()));
          }
          return bm;
      }
      
      private static Bitmap scaleDeminsFromHeight(Bitmap bm, int maxHeight, int bmOriginalHeight, double originalWidthToHeightRatio) {
          int newHeight = (int) Math.max(maxHeight, bmOriginalHeight * .55);
          int newWidth = (int) (newHeight * originalWidthToHeightRatio);
          bm = Bitmap.createScaledBitmap(bm, newWidth, newHeight, true);
          return bm;
      }
      
      private static Bitmap scaleDeminsFromWidth(Bitmap bm, int maxWidth, int bmOriginalWidth, double originalHeightToWidthRatio) {
          //scale the width
          int newWidth = (int) Math.max(maxWidth, bmOriginalWidth * .75);
          int newHeight = (int) (newWidth * originalHeightToWidthRatio);
          bm = Bitmap.createScaledBitmap(bm, newWidth, newHeight, true);
          return bm;
      }
      

      这是我的 GitHub Gist 的相应链接:https://gist.github.com/Lwdthe1/2d1cd0a12f30c18db698

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-14
        • 2012-06-14
        • 1970-01-01
        • 2011-10-09
        • 2011-08-12
        • 1970-01-01
        • 2013-01-01
        • 1970-01-01
        相关资源
        最近更新 更多