Обрезать изображение в Android, используя идеальное соотношение сторон

Я работал над приложением для Android. В моем приложении есть функция, для которой требуется изображение с точными размерами экрана устройства, для которого я использую этот код,

Intent cropIntent = new Intent("com.android.camera.action.CROP");
cropIntent.setDataAndType(picUri, "image/*");
cropIntent.putExtra("crop", "true");
cropIntent.putExtra("aspectX", 0);
cropIntent.putExtra("aspectY", 0);
cropIntent.putExtra("outputX", width);
cropIntent.putExtra("outputY", height);
cropIntent.putExtra("return-data", true);

но проблема с этим кодом заключается в том, что, поскольку соотношение сторон было установлено равным нулю, на некоторых устройствах, таких как Samsung, окно обрезки имеет квадратный размер и не может быть отрегулировано. Итак, как я могу установить соотношение сторон в поле «AspectX», а также в поле «AspectY», чтобы не было проблем с кадрированием изображения,

Я также написал программу Java для расчета соотношения сторон, но, похоже, она не работает со всеми разрешениями.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

class AspectRatio
{   public static void main(String args[])
    {   BufferedReader buff=new BufferedReader(new InputStreamReader(System.in));
        int width=0,height=0;
        try
        {   System.out.print("Enter the width of the screen:");
            width=Integer.parseInt(buff.readLine());
            System.out.println("Enter the height of the screen:");
            height=Integer.parseInt(buff.readLine());
        }
        catch(IOException e)
        {   e.printStackTrace();
        }
        int factor=0;
        for(int i=2;i<new AspectRatio().minimum(width,height)/2;i++)
        {   if(width%i==0&&height%1==0)
            {   factor=i;
            }
        }
        System.out.println("The aspect ratio is:"+width/factor+":"+height/factor);
    }

    public int minimum(int a,int b)
    {   return (a<b?a:b);
    }
}

person Angad Singh    schedule 19.12.2015    source источник


Ответы (2)


вы можете получить ширину и высоту из системы, используя следующий класс: DisplayMetrics

проверьте ссылку, она также даст пример, как использовать этот класс.

person Itzik Samara    schedule 19.12.2015
comment
А как насчет соотношения сторон..? - person Angad Singh; 19.12.2015
comment
я уже использую этот код для получения ширины и высоты, и он работает только с несколькими устройствами - person Angad Singh; 19.12.2015
comment
во-первых, если вы хотите сохранить Image AspectRatio, просто используйте AspectRatioImageView, предполагая, что вы собираетесь отображать это изображение внутри ImageView.. и для большой души используйте что-то, что система дает вам, например DisplayMetric, вот ссылка для AspectRatioImageView: "https://gist.github.com/JakeWharton/2856179" rel="nofollow noreferrer">gist.github.com/JakeWharton/2856179 - person Itzik Samara; 19.12.2015

это мой вспомогательный класс для уменьшения любого изображения с идеальным соотношением, и он работает с изображением, снятым с камеры, и img на устройстве:

 public class ImageUtils {
    private static final String TAG = "ImageUtils";
    private static final float maxHeight = 1280.0f;
    private static final float maxWidth = 1280.0f;

    public static byte[] compressImage(String imagePath) {
        Bitmap scaledBitmap = null;


        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        Bitmap bmp = BitmapFactory.decodeFile(imagePath, options);

        int actualHeight = options.outHeight;
        int actualWidth = options.outWidth;
        float imgRatio = (float) actualWidth / (float) actualHeight;
        float maxRatio = maxWidth / maxHeight;

        if (actualHeight > maxHeight || actualWidth > maxWidth) {
            if (imgRatio < maxRatio) {
                imgRatio = maxHeight / actualHeight;
                actualWidth = (int) (imgRatio * actualWidth);
                actualHeight = (int) maxHeight;
            } else if (imgRatio > maxRatio) {
                imgRatio = maxWidth / actualWidth;
                actualHeight = (int) (imgRatio * actualHeight);
                actualWidth = (int) maxWidth;
            } else {
                actualHeight = (int) maxHeight;
                actualWidth = (int) maxWidth;

            }
        }

        options.inSampleSize = ImageUtils.calculateInSampleSize(options, actualWidth, actualHeight);
        options.inJustDecodeBounds = false;
        options.inDither = false;
        options.inPurgeable = true;
        options.inInputShareable = true;
        options.inTempStorage = new byte[16 * 1024];

        try {
            bmp = BitmapFactory.decodeFile(imagePath, options);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();

        }
        try {
            scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();
        }

        float ratioX = actualWidth / (float) options.outWidth;
        float ratioY = actualHeight / (float) options.outHeight;
        float middleX = actualWidth / 2.0f;
        float middleY = actualHeight / 2.0f;

        Matrix scaleMatrix = new Matrix();
        scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);

        Canvas canvas = new Canvas(scaledBitmap);
        canvas.setMatrix(scaleMatrix);
        canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));

        ExifInterface exif;
        try {
            exif = new ExifInterface(imagePath);
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
            Matrix matrix = new Matrix();
            if (orientation == 6) {
                matrix.postRotate(90);
            } else if (orientation == 3) {
                matrix.postRotate(180);
            } else if (orientation == 8) {
                matrix.postRotate(270);
            }
            scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 85, out);
        return out.toByteArray();
    }
    public static boolean compressImage(Bitmap image, FileOutputStream fos){
        Bitmap scaledBitmap = null;

        int actualHeight = image.getHeight();
        int actualWidth = image.getWidth();
        float imgRatio = (float) actualWidth / (float) actualHeight;
        float maxRatio = maxWidth / maxHeight;

        if (actualHeight > maxHeight || actualWidth > maxWidth) {
            if (imgRatio < maxRatio) {
                imgRatio = maxHeight / actualHeight;
                actualWidth = (int) (imgRatio * actualWidth);
                actualHeight = (int) maxHeight;
            } else if (imgRatio > maxRatio) {
                imgRatio = maxWidth / actualWidth;
                actualHeight = (int) (imgRatio * actualHeight);
                actualWidth = (int) maxWidth;
            } else {
                actualHeight = (int) maxHeight;
                actualWidth = (int) maxWidth;

            }
        }

        Log.d(TAG, "ActualHeight " + actualHeight);
        Log.d(TAG, "ActualHidht " + actualWidth);
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = ImageUtils.calculateInSampleSize(options, actualWidth, actualHeight);
        options.inJustDecodeBounds = false;
        options.inDither = false;
        options.inPurgeable = true;
        options.inInputShareable = true;
        options.inTempStorage = new byte[16 * 1024];

        Bitmap bmp = null;
        try {
//            int bytes = byteSizeOf(image);
//            //or we can calculate bytes this way. Use a different value than 4 if you don't use 32bit images.
//            //int bytes = b.getWidth()*b.getHeight()*4;
//            ByteBuffer buffer = ByteBuffer.allocate(bytes); //Create a new buffer
//            image.copyPixelsToBuffer(buffer); //Move the byte data to the buffer
//            byte[] array = buffer.array(); //Get the underlying array containing the data.
//            bmp = BitmapFactory.decodeByteArray(array, 0, array.length, options);

            ByteArrayOutputStream blob = new ByteArrayOutputStream();
            image.compress(Bitmap.CompressFormat.PNG, 0 /*ignored for PNG*/, blob);
            byte[] bitmapdata = blob.toByteArray();
            bmp = BitmapFactory.decodeByteArray(bitmapdata , 0, bitmapdata.length);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();
        }

        try {
            scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();
        }

        float ratioX = actualWidth / (float) options.outWidth;
        float ratioY = actualHeight / (float) options.outHeight;
        float middleX = actualWidth / 2.0f;
        float middleY = actualHeight / 2.0f;

        Matrix scaleMatrix = new Matrix();
        scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);

        Canvas canvas = new Canvas(scaledBitmap);
        canvas.setMatrix(scaleMatrix);
        canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));

//        ExifInterface exif;
//        try {
////            exif = new ExifInterface(imagePath);
////            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
////            Matrix matrix = new Matrix();
////            if (orientation == 6) {
////                matrix.postRotate(90);
////            } else if (orientation == 3) {
////                matrix.postRotate(180);
////            } else if (orientation == 8) {
////                matrix.postRotate(270);
////            }
//
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
        scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), null, true);
        scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 85, fos);
        return true;
    }
    public static void compressImage(String imagePath, FileOutputStream fos) {
        Bitmap scaledBitmap = null;

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        Bitmap bmp = BitmapFactory.decodeFile(imagePath, options);

        int actualHeight = options.outHeight;
        int actualWidth = options.outWidth;
        float imgRatio = (float) actualWidth / (float) actualHeight;
        float maxRatio = maxWidth / maxHeight;

        if (actualHeight > maxHeight || actualWidth > maxWidth) {
            if (imgRatio < maxRatio) {
                imgRatio = maxHeight / actualHeight;
                actualWidth = (int) (imgRatio * actualWidth);
                actualHeight = (int) maxHeight;
            } else if (imgRatio > maxRatio) {
                imgRatio = maxWidth / actualWidth;
                actualHeight = (int) (imgRatio * actualHeight);
                actualWidth = (int) maxWidth;
            } else {
                actualHeight = (int) maxHeight;
                actualWidth = (int) maxWidth;

            }
        }

        options.inSampleSize = ImageUtils.calculateInSampleSize(options, actualWidth, actualHeight);
        options.inJustDecodeBounds = false;
        options.inDither = false;
        options.inPurgeable = true;
        options.inInputShareable = true;
        options.inTempStorage = new byte[16 * 1024];

        try {
            bmp = BitmapFactory.decodeFile(imagePath, options);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();

        }
        try {
            scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();
        }

        float ratioX = actualWidth / (float) options.outWidth;
        float ratioY = actualHeight / (float) options.outHeight;
        float middleX = actualWidth / 2.0f;
        float middleY = actualHeight / 2.0f;

        Matrix scaleMatrix = new Matrix();
        scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);

        Canvas canvas = new Canvas(scaledBitmap);
        canvas.setMatrix(scaleMatrix);
        canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));

        ExifInterface exif;
        try {
            exif = new ExifInterface(imagePath);
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
            Matrix matrix = new Matrix();
            if (orientation == 6) {
                matrix.postRotate(90);
            } else if (orientation == 3) {
                matrix.postRotate(180);
            } else if (orientation == 8) {
                matrix.postRotate(270);
            }
            scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //ByteArrayOutputStream out = new ByteArrayOutputStream();
        scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 85, fos);
    }
    public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        final float totalPixels = width * height;
        final float totalReqPixelsCap = reqWidth * reqHeight * 2;

        while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
            inSampleSize++;
        }

        return inSampleSize;
    }
    static protected int byteSizeOf(Bitmap data) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
            return data.getRowBytes() * data.getHeight();
        } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
            return data.getByteCount();
        } else {
            return data.getAllocationByteCount();
        }
    }
}


 /**
 * reduces the size of the image
 * @param image
 * @param maxSize
 * @return
 */
public Bitmap getResizedBitmap(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);
    }
    return Bitmap.createScaledBitmap(image, width, height, true);
}

private void setVideoViewRatio(VideoView vv, int maxSize, int cWidth, int cHeight){
    int width = cWidth;
    int height = cHeight;
    float ratio = (float)cWidth / (float) height;
    if (ratio > 0) {
        width = maxSize;
        height = (int) (width / ratio);
    } else {
        height = maxSize;
        width = (int) (height * ratio);
    }
    vv.setMinimumWidth(width);
    vv.setMinimumHeight(height);
}
person Marco Luongo    schedule 20.12.2015