Android 在安卓系统中减少摄像头拍摄图像的大小

Android 在安卓系统中减少摄像头拍摄图像的大小,android,image,android-camera,Android,Image,Android Camera,在这里,我将从相机中捕获的图像保存在SD卡上。这里,捕获的图像大小大于1 MB。在保存到SD卡之前,我想将此大小减少到近500kb到600kb。我怎么能这么做 try { Bitmap mPhoto; mPhoto = android.provider.MediaStore.Images.Media.getBitmap(cr, CheckInGallery.mUri); ByteArrayOutputStr

在这里,我将从相机中捕获的图像保存在SD卡上。这里,捕获的图像大小大于
1 MB
。在保存到SD卡之前,我想将此大小减少到近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();
        }
100在这是最好的质量。如果要减小大小,请尝试减小该值

其他方法可能是使用BitmapFactory.Options()的inSampleSize参数。这也应该减少尺寸。你可以读一下

编辑: 一些代码

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);

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

@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;
    }

这种方法可以减小图像大小。这在我的项目中很有用。

在阅读了其他答案后,没有找到我想要的,下面是我获取适当缩放位图的方法。这是对普拉布答案的改编

**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();
        }

    }
它确保图片的缩放方式不会使图片的尺寸变形:

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要点相对应的链接:

这就是我的工作原理

    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;
}
public void onImageSelected(){
Uri=null;//从意图中获取图像结果的Uri
试一试{
位图位图=handleSamplingAndRotationBitmap(此,uri);
字节[]字节=getBytesFromBitmap(位图);
//getPresenter.upload(字节);
}捕获(IOE异常){
e、 printStackTrace();
}
}
/**
*返回大小不超过最大高度的对齐位图
*@param上下文
*@param selectedImage
*@返回
*@抛出异常
*/
公共位图句柄采样和旋转位图(上下文上下文,Uri selectedImage)
抛出IOException{
解码位图=getImageSampleOutput(上下文,选择图像);
解码=旋转图像如果需要(此,解码,选择图像);
返回解码;
}
公共位图getImageSampleOutput(上下文上下文,Uri selectedImage)引发IOException{
int最大高度=1200;
int MAX_WIDTH=1600;
//使用INJUSTDECBOUNDS首次解码=true检查尺寸
final BitmapFactory.Options=new BitmapFactory.Options();
options.inJustDecodeBounds=true;
InputStream imageStream=context.getContentResolver().openInputStream(SelecteImage);
解码流(imageStream,null,选项);
imageStream.close();
//计算样本大小
options.inSampleSize=计算样本大小(选项、最大宽度、最大高度);
//使用inSampleSize集合解码位图
options.inJustDecodeBounds=false;
imageStream=context.getContentResolver().openInputStream(SelecteImage);
位图img=BitmapFactory.decodeStream(imageStream,null,选项);
解码位图=压缩图像(img);
返回解码;
}
/**
*用于压缩图像以防止内存溢出。
*@param位图
*@返回
*/
公共位图压缩图像(位图位图){
ByteArrayOutputStream out=新建ByteArrayOutputStream();
bitmap.compress(bitmap.CompressFormat.JPEG,100,out);
返回BitmapFactory.decodeStream(新的ByteArrayInputStream(out.toByteArray());
}
私有静态int-calculateInSampleSize(BitmapFactory.Options,
输入要求宽度,输入要求高度){
//图像的原始高度和宽度
最终内部高度=options.outHeight;
最终整数宽度=options.outWidth;
int inSampleSize=1;
如果(高度>要求高度| |宽度>要求宽度){
//计算高度和宽度与所需高度和宽度的比率
最终内部高度比=数学圆((浮动)高度/(浮动)要求高度);
最终整数宽度比=数学圆((浮动)宽度/(浮动)宽度);
//选择最小比率作为inSampleSize值,这将保证最终图像
//两个尺寸都大于或等于要求的高度和宽度。
inSampleSize=高度比<宽度比?高度比:宽度比;
//这提供了一些额外的逻辑,以防图像有奇怪的颜色
//宽高比。例如,全景图可能具有更大的宽高比
//宽度大于高度。在这些情况下,总像素可能仍然
//结果是太大而不能舒服地放在记忆中,所以我们应该
//在图像下采样时更具攻击性(=采样尺寸更大)。
最终浮点总数像素=宽度*高度;
//任何超过所需像素2倍的像素,我们将进一步采样
最终浮点totalReqPixelsCap=reqWidth*reqHeight*2;
而(totalPixels/(inSampleSize*inSampleSize)>totalReqPixelsCap){
inSampleSize++;
}
}
返回样本大小;
}
私有静态位图rotateImageIfRequired(上下文上下文、位图img、Uri selectedImage){
//检测旋转
int rotation=getRotation(上下文,选择图像);
如果(旋转!=0){
矩阵=新矩阵();
矩阵。后旋转(旋转);
Bitmap rotatedImg=Bitmap.createBitmap(img,0,0,img.getWidth(),img.getHeight(),matrix,true);
img.recycle();
返回旋转dIMG;
}否则{
返回img;
}
}
/**
*获取最后添加的图像的旋转。
*
*@param上下文
*@param selectedImage
*@返回
*/
私有静态int-getRotation(上下文,Uri-selectedImage){
整数旋转=0;
ContentResolver content=context.getContentResolver();
游标mediaCursor=content.query(MediaStore.Images.Media.EXTERNAL\u content\u URI,
新字符串[]{“方向”,“添加日期”},
空,空,“添加说明的日期”);
if(mediaCursor!=null&&mediaCursor.getCount()!=0){
while(mediaCursor.moveToNext()){
旋转=mediaCursor.getInt(0);
打破
}
}
mediaCursor.close();
返回旋转;
}
公共字节[]getBytesFromBitmap(位图bmp){
ByteArrayOutputStream=新建ByteArrayOutputStream();
bmp.compress(位图.CompressFormat
    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;
}