Обрезка и изменение размера изображения в Android
Я следовал инструкциям ниже, чтобы обрезать изображение.
http://coderzheaven.com/index.php/2011/03/crop-an-image-in-android/
Высота и ширина окончательного обрезанного растрового изображения больше, чем на экране.
В процессе изменения размера и обрезки возникла ошибка нехватки памяти, и приложение было вынуждено завершить работу.
Журнал ошибок:
04-09 11:37:28.658: ERROR/dalvikvm-heap(4003): 435176-byte external allocation too large for this process.
04-09 11:37:28.658: ERROR/GraphicsJNI(4003): VM won't let us allocate 435176 bytes
04-09 11:37:28.668: WARN/dalvikvm(4003): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): FATAL EXCEPTION: main
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.graphics.Bitmap.nativeCreate(Native Method)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.graphics.Bitmap.createBitmap(Bitmap.java:435)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at com.test.Test.onCreate(Test.java:57)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.os.Handler.dispatchMessage(Handler.java:99)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.os.Looper.loop(Looper.java:123)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at android.app.ActivityThread.main(ActivityThread.java:4627)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at java.lang.reflect.Method.invokeNative(Native Method)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at java.lang.reflect.Method.invoke(Method.java:521)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
04-09 11:37:28.708: ERROR/AndroidRuntime(4003): at dalvik.system.NativeStart.main(Native Method)
Кто-нибудь знает, как решить проблему?
Благодарю.
======
Обновление: я решил проблему.
8 ответов
Вы можете использовать кадрирование изображения, используя следующий код, который может решить вашу проблему.
Matrix matrix = new Matrix();
matrix.postScale(0.5f, 0.5f);
Bitmap croppedBitmap = Bitmap.createBitmap(bitmapOriginal, 100, 100,100, 100, matrix, true);
Вышеупомянутый метод делает postScalling изображения перед кадрированием, так что вы можете получить лучший результат с кадрированным изображением без ошибки OOM.
Для более подробной информации вы можете обратиться к этому блогу
Мой коллега только что помог мне с этим API Android... см. ThumbnailUtils.
Это делает изменение размера и обрезку для вас.
http://developer.android.com/reference/android/media/ThumbnailUtils.html, int, int)
Если ваш код отличается от примера, вам придется опубликовать его, чтобы получить точную помощь. В противном случае, основываясь только на журнале - вот ответ:
В примере, который вы используете, разработчик обрезает изображение в папке ресурсов своего приложения (которое может быть относительно небольшим для начала) в растровое изображение размером 300x300. Во-первых, попробуйте обрезать изображение меньшего размера в вашем собственном приложении до меньшего размера вывода, чтобы увидеть, есть ли проблема с кодом, или если вы используете изображение, которое слишком велико для вашего кода или устройства.
Поскольку вы говорите, что конечное изображение, которое вы обрезаете, больше, чем экран, это, вероятно, проблема, и вы столкнулись с основной проблемой использования растровых изображений в Android. Размер растрового файла зависит от ширины пикселя и высоты - они быстро увеличиваются.
Вы можете решить эту проблему, прибегая к помощи других частей вашего журнала, например, "размер растрового изображения превышает бюджет виртуальной машины", и вы найдете несколько потоков в стеке потока, которые помогут, как этот.
Проблема с нехваткой памяти при загрузке изображения в растровый объект
Вы можете решить эту проблему, используя параметры растрового изображения, inSampleSize и другие методы.
//solution for bit map resizing
Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight,Bitmap.Config.ARGB_8888);
RectF rectf = new RectF(0, 0, 800, 400);
Canvas canvas = new Canvas(targetBitmap);
Path path = new Path();
path.addRect(rectf, Path.Direction.CW);
canvas.clipPath(path);
int xaxis=bm.getWidth();
int yaxis=bm.getHeight();
canvas.drawBitmap( bm, new Rect(0, 0, bm.getWidth(), bm.getHeight()),
new Rect(0, 0, targetWidth, targetHeight), paint);
Matrix matrix = new Matrix();
matrix.postScale(1f, 1f);
resizedBitmap = Bitmap.createBitmap(targetBitmap, 0, 0, width, height, matrix, true);
BitmapDrawable bd = new BitmapDrawable(resizedBitmap);
//get screen resolution;
WindowManager display = getWindowManager();
Point size = new Point();
display.getDefaultDisplay().getSize(size);
int width = size.x;
int height = size.y;
// scale the bitmap according to the screen resolution .
Bitmap bMap = BitmapFactory.decodeResource(getResources(), .drawable.ima1);
bMap = Bitmap.createScaledBitmap(bMap, width, height, true);
// then crop under value of the screen size and bitmap!
bMap = Bitmap.createBitmap(bMap, 0, 0, width/2, height);
Drawable drawa = new BitmapDrawable(getResources(),bMap);
я надеюсь быть полезным
04-09 11:37:28.708: ОШИБКА /AndroidRuntime(4003): на com.test.Test.onCreate(Test.java:57)
Если я не ошибаюсь, в
class Test extends Activity ....
на линии 57 у вас есть
Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),R.drawable.image);
Если это так, то ссылочное изображение настолько велико, что, когда Android пытается декодировать его в растровое изображение, он объединяет все свободные кучи виртуальных машин и выдает ошибку. Вы не можете декодировать большие растровые изображения с
private Bitmap decodeFile(){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(),R.drawable.image,o);
//The new size we want to scale to
final int REQUIRED_SIZE=100;
//Find the correct scale value. It should be the power of 2.
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeResource(getResources(),R.drawable.image, o2);
} catch (FileNotFoundException e) {}
return null;
}
Я скопировал код по ссылке, рекомендованной user699618, я использовал его раньше, и это решает проблему).
После этого вы можете просто использовать CENTER_CROP
или что вам нужно на ImageView.setScaleType()
,
Здесь вы можете найти параметры типа шкалы и подробности setScale Type.
Надеюсь это поможет.
я также рекомендовал бы не иметь такие тяжелые картинки в ресурсах. Сделайте их меньше, прежде чем сохранять их в Resorce Forder.
Я также проверил следующие инструкции.
http://coderzheaven.com/index.php/2011/03/crop-an-image-in-android/
Я обнаружил, что коды недостаточно хороши, а некоторые из них являются избыточными.
Чтобы обрезать большое растровое изображение, нет необходимости использовать матрицу для выполнения задачи.
Просто используйте метод canvas.drawBitmap, чтобы обрезать большое изображение!
Также не нужно трогать BitmapFactory.Options.
Теперь я просто обрезаю изображение и позволяю изображению изменить его размер. Нет больше ошибки нехватки памяти. Бинго!
Посмотрите на подобное обсуждение here
кажется, что они имеют одинаковые byte external allocation too large for this process
ошибка.