Intereting Posts
Не удалось инициализировать приемник событий отображения В чем разница между меню опций и меню панели в Android? Просмотр ресайклера вертикального списка прокрутки с горизонтальной прокручиваемой строкой Как воспроизводить звук через динамик, даже если гарнитура подключена? Как добавить водяной знак в виджет Android EditText? Ошибка MODE_PRIVATE в sharedpreferences Холст HTML5 на телефонах Android – перерисовать и выделить проблемы «ArrayAdapter требует, чтобы идентификатор ресурса был проблемой TextView» xml Как показать эмулятор Android без клавиатуры Зависимость монитора Android-устройств от устаревшей среды исполнения Java SE 6 Активность Android без GUI Espresso 2.0 – метод, аннотированный с помощью класса @Test внутри класса, расширяющего тестовую таблицу junit3 Android: Non-Keyboard IME Простой пример использования SwipeRefreshLayout с ListView RELEASE_KEY_ALIAS и RELEASE_KEY_PATH для генерации ключевого хэша

Масштабированный битмап, поддерживающий соотношение сторон

Я хотел бы масштабировать Bitmap для зависящей от времени ширины и высоты, где соотношение сторон поддерживается, а Bitmap заполняет всю ширину и центрирует изображение по вертикали, либо обрезая избыток, либо заполняя зазор 0 альфа-пикселями.

В настоящее время я перерисовываю растровое изображение, создавая Bitmap всех 0 альфа-пикселей и рисуя изображение Bitmap поверх него, масштабируя его до указанной указанной ширины и сохраняя соотношение сторон, однако оно заканчивается тем, что оно теряет / заворачивает пиксель данные.

Вот как я это делаю:

 Bitmap background = Bitmap.createBitmap((int)width, (int)height, Config.ARGB_8888); float originalWidth = originalImage.getWidth(), originalHeight = originalImage.getHeight(); Canvas canvas = new Canvas(background); float scale = width/originalWidth; float xTranslation = 0.0f, yTranslation = (height - originalHeight * scale)/2.0f; Matrix transformation = new Matrix(); transformation.postTranslate(xTranslation, yTranslation); transformation.preScale(scale, scale); canvas.drawBitmap(originalImage, transformation, null); return background; 

Есть ли библиотека там или какой-то лучший код, который может сделать это лучше? Я хотел бы, чтобы изображение выглядело как можно более хрустящим, но я знал, что моя функция не обеспечит отличный результат.

Я знаю, что у меня могло бы быть изображение в порядке, используя масштабирование по целому числу, вместо масштабирования по плавающей ставке, но мне нужно, чтобы ширина была заполнена на 100%.

Кроме того, я знаю о возможностях Gravity.CENTER_CROP ImageView , однако, также использует целочисленное масштабирование, поэтому он отсекает ширину изображения, когда это не должно.

Solutions Collecting From Web of "Масштабированный битмап, поддерживающий соотношение сторон"

Как насчет этого:

 Bitmap background = Bitmap.createBitmap((int)width, (int)height, Config.ARGB_8888); float originalWidth = originalImage.getWidth(); float originalHeight = originalImage.getHeight(); Canvas canvas = new Canvas(background); float scale = width / originalWidth; float xTranslation = 0.0f; float yTranslation = (height - originalHeight * scale) / 2.0f; Matrix transformation = new Matrix(); transformation.postTranslate(xTranslation, yTranslation); transformation.preScale(scale, scale); Paint paint = new Paint(); paint.setFilterBitmap(true); canvas.drawBitmap(originalImage, transformation, paint); return background; 

Я добавил paint для фильтрации масштабированного растрового изображения.

Это будет учитывать maxWidth и maxHeight, что означает, что в результате битмап никогда не будет иметь размеры, большие, чем те:

  private static Bitmap resize(Bitmap image, int maxWidth, int maxHeight) { if (maxHeight > 0 && maxWidth > 0) { int width = image.getWidth(); int height = image.getHeight(); float ratioBitmap = (float) width / (float) height; float ratioMax = (float) maxWidth / (float) maxHeight; int finalWidth = maxWidth; int finalHeight = maxHeight; if (ratioMax > 1) { finalWidth = (int) ((float)maxHeight * ratioBitmap); } else { finalHeight = (int) ((float)maxWidth / ratioBitmap); } image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true); return image; } else { return image; } } 

Здесь у меня есть проверенное решение, где я создаю масштабированный Bitmap из растрового файла:

  int scaleSize =1024; public Bitmap resizeImageForImageView(Bitmap bitmap) { Bitmap resizedBitmap = null; int originalWidth = bitmap.getWidth(); int originalHeight = bitmap.getHeight(); int newWidth = -1; int newHeight = -1; float multFactor = -1.0F; if(originalHeight > originalWidth) { newHeight = scaleSize ; multFactor = (float) originalWidth/(float) originalHeight; newWidth = (int) (newHeight*multFactor); } else if(originalWidth > originalHeight) { newWidth = scaleSize ; multFactor = (float) originalHeight/ (float)originalWidth; newHeight = (int) (newWidth*multFactor); } else if(originalHeight == originalWidth) { newHeight = scaleSize ; newWidth = scaleSize ; } resizedBitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, false); return resizedBitmap; } 

Обратите внимание, что мне нужны масштабированные растровые изображения с максимальным размером 4096×4096 пикселей, но соотношение размеров должно сохраняться при изменении размера. Если вам нужны другие значения ширины или высоты, просто замените значения «4096».

Это просто дополнение к ответу Коэна, но проблема в его коде – это линия, где он вычисляет отношение. Разделение двух целых чисел дает целое число, и если результат равен <1, он будет округлен до 0. Таким образом, это исключает исключение «деление на ноль».

Вот метод из моего класса Utils, который выполняет задание:

 public static Bitmap scaleBitmapAndKeepRation(Bitmap TargetBmp,int reqHeightInPixels,int reqWidthInPixels) { Matrix m = new Matrix(); m.setRectToRect(new RectF(0, 0, TargetBmp.getWidth(), TargetBmp.getHeight()), new RectF(0, 0, reqWidthInPixels, reqHeightInPixels), Matrix.ScaleToFit.CENTER); Bitmap scaledBitmap = Bitmap.createBitmap(TargetBmp, 0, 0, TargetBmp.getWidth(), TargetBmp.getHeight(), m, true); return scaledBitmap; } 

Это также можно сделать, вычислив соотношение самостоятельно, вот так.

 private Bitmap scaleBitmap(Bitmap bm) { int width = bm.getWidth(); int height = bm.getHeight(); Log.v("Pictures", "Width and height are " + width + "--" + height); if (width > height) { // landscape int ratio = width / maxWidth; width = maxWidth; height = height / ratio; } else if (height > width) { // portrait int ratio = height / maxHeight; height = maxHeight; width = width / ratio; } else { // square height = maxHeight; width = maxWidth; } Log.v("Pictures", "after scaling Width and height are " + width + "--" + height); bm = Bitmap.createScaledBitmap(bm, width, height, true); return bm; } 

Более простое решение: обратите внимание, что мы устанавливаем ширину до 500 пикселей

  public void scaleImageKeepAspectRatio() { int imageWidth = scaledGalleryBitmap.getWidth(); int imageHeight = scaledGalleryBitmap.getHeight(); int newHeight = (imageHeight * 500)/imageWidth; scaledGalleryBitmap = Bitmap.createScaledBitmap(scaledGalleryBitmap, 500, newHeight, false); } 
 public static Bitmap scaleBitmap(Bitmap bitmap, int wantedWidth, int wantedHeight) { float originalWidth = bitmap.getWidth(); float originalHeight = bitmap.getHeight(); Bitmap output = Bitmap.createBitmap(wantedWidth, wantedHeight, Config.ARGB_8888); Canvas canvas = new Canvas(output); Matrix m = new Matrix(); float scalex = wantedWidth/originalWidth; float scaley = wantedHeight/originalHeight; float xTranslation = 0.0f, yTranslation = (wantedHeight - originalHeight * scaley)/2.0f; m.postTranslate(xTranslation, yTranslation); m.preScale(scalex, scaley); // m.setScale((float) wantedWidth / bitmap.getWidth(), (float) wantedHeight / bitmap.getHeight()); Paint paint = new Paint(); paint.setFilterBitmap(true); canvas.drawBitmap(bitmap, m, paint); return output; } 

Ни один из вышеперечисленных ответов не был обработан для меня, и я только что создал метод, который устанавливает все измерения в нужные, окрашивая пустую область в черный. Вот мой метод:

 /** * Scale the image preserving the ratio * @param imageToScale Image to be scaled * @param destinationWidth Destination width after scaling * @param destinationHeight Destination height after scaling * @return New scaled bitmap preserving the ratio */ public static Bitmap scalePreserveRatio(Bitmap imageToScale, int destinationWidth, int destinationHeight) { if (destinationHeight > 0 && destinationWidth > 0 && imageToScale != null) { int width = imageToScale.getWidth(); int height = imageToScale.getHeight(); //Calculate the max changing amount and decide which dimension to use float widthRatio = (float) destinationWidth / (float) width; float heightRatio = (float) destinationHeight / (float) height; //Use the ratio that will fit the image into the desired sizes int finalWidth = (int)Math.floor(width * widthRatio); int finalHeight = (int)Math.floor(height * widthRatio); if (finalWidth > destinationWidth || finalHeight > destinationHeight) { finalWidth = (int)Math.floor(width * heightRatio); finalHeight = (int)Math.floor(height * heightRatio); } //Scale given bitmap to fit into the desired area imageToScale = Bitmap.createScaledBitmap(imageToScale, finalWidth, finalHeight, true); //Created a bitmap with desired sizes Bitmap scaledImage = Bitmap.createBitmap(destinationWidth, destinationHeight, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(scaledImage); //Draw background color Paint paint = new Paint(); paint.setColor(Color.BLACK); paint.setStyle(Paint.Style.FILL); canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint); //Calculate the ratios and decide which part will have empty areas (width or height) float ratioBitmap = (float)finalWidth / (float)finalHeight; float destinationRatio = (float) destinationWidth / (float) destinationHeight; float left = ratioBitmap >= destinationRatio ? 0 : (float)(destinationWidth - finalWidth) / 2; float top = ratioBitmap < destinationRatio ? 0: (float)(destinationHeight - finalHeight) / 2; canvas.drawBitmap(imageToScale, left, top, null); return scaledImage; } else { return imageToScale; } } 

Например;

Предположим, что у вас есть изображение размером 100 x 100, но желаемый размер 300×50, тогда этот метод преобразует ваше изображение в 50 x 50 и нарисует его на новое изображение с размерами 300 x 50 (и пустые строки будут черными) ,

Другой пример: предположим, что у вас есть изображение размером 600 x 1000, а желаемые размеры – 300 x 50, тогда ваше изображение будет преобразовано в 30 x 50 и будет нарисовано на вновь созданное изображение размером 300 x 50.

Я думаю, что так оно и должно быть, Rs.

Мое решение было таким, которое поддерживает соотношение сторон и требует только одного размера, например, если у вас есть 1920 * 1080 и 1080 * 1920 изображений, и вы хотите изменить его размер до 1280, первым будет 1280 * 720, а второй Будет 720 * 1280

 public static Bitmap resizeBitmap(final Bitmap temp, final int size) { if (size > 0) { int width = temp.getWidth(); int height = temp.getHeight(); float ratioBitmap = (float) width / (float) height; int finalWidth = size; int finalHeight = size; if (ratioBitmap < 1) { finalWidth = (int) ((float) size * ratioBitmap); } else { finalHeight = (int) ((float) size / ratioBitmap); } return Bitmap.createScaledBitmap(temp, finalWidth, finalHeight, true); } else { return temp; } } 

Это потрясающая библиотека от ArthurHub для обработки изображений как программно, так и интерактивно, если вы не хотите изобретать колесо.

Но если вы предпочитаете не раздутую версию, такую ​​как я .., внутренняя функция, показанная здесь, довольно сложна для выполнения масштабирования изображений с несколькими стандартными параметрами

 /** * Resize the given bitmap to the given width/height by the given option.<br> */ enum RequestSizeOptions { RESIZE_FIT, RESIZE_INSIDE, RESIZE_EXACT } static Bitmap resizeBitmap(Bitmap bitmap, int reqWidth, int reqHeight, RequestSizeOptions options) { try { if (reqWidth > 0 && reqHeight > 0 && (options == RequestSizeOptions.RESIZE_FIT || options == RequestSizeOptions.RESIZE_INSIDE || options == RequestSizeOptions.RESIZE_EXACT)) { Bitmap resized = null; if (options == RequestSizeOptions.RESIZE_EXACT) { resized = Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, false); } else { int width = bitmap.getWidth(); int height = bitmap.getHeight(); float scale = Math.max(width / (float) reqWidth, height / (float) reqHeight); if (scale > 1 || options == RequestSizeOptions.RESIZE_FIT) { resized = Bitmap.createScaledBitmap(bitmap, (int) (width / scale), (int) (height / scale), false); } } if (resized != null) { if (resized != bitmap) { bitmap.recycle(); } return resized; } } } catch (Exception e) { Log.w("AIC", "Failed to resize cropped image, return bitmap before resize", e); } return bitmap; }