Android как создать миниатюру во время выполнения - PullRequest
61 голосов
/ 05 апреля 2010

У меня изображение большого размера.Во время выполнения я хочу прочитать изображение из хранилища и масштабировать его так, чтобы его вес и размер были уменьшены, и я мог использовать его как эскиз.Когда пользователь нажимает на миниатюру, я хочу отобразить полноразмерное изображение.

Ответы [ 9 ]

128 голосов
/ 06 сентября 2012

Попробуйте это

Bitmap ThumbImage = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(imagePath), THUMBSIZE, THUMBSIZE);

Эта утилита доступна из API_LEVEl 8. [Источник]

44 голосов
/ 09 мая 2011

Мое решение

byte[] imageData = null;

        try     
        {

            final int THUMBNAIL_SIZE = 64;

            FileInputStream fis = new FileInputStream(fileName);
            Bitmap imageBitmap = BitmapFactory.decodeStream(fis);

            imageBitmap = Bitmap.createScaledBitmap(imageBitmap, THUMBNAIL_SIZE, THUMBNAIL_SIZE, false);

            ByteArrayOutputStream baos = new ByteArrayOutputStream();  
            imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
            imageData = baos.toByteArray();

        }
        catch(Exception ex) {

        }
13 голосов
/ 19 ноября 2014

Лучшее решение, которое я нашел, заключается в следующем. По сравнению с другими решениями этому не нужно загружать полное изображение для создания миниатюры, так что это более эффективно! Его предел в том, что вы не можете иметь миниатюру с точной шириной и высотой , но решение должно быть как можно ближе.

File file = ...; // the image file
Options bitmapOptions = new Options();

bitmapOptions.inJustDecodeBounds = true; // obtain the size of the image, without loading it in memory
BitmapFactory.decodeFile(file.getAbsolutePath(), bitmapOptions);

// find the best scaling factor for the desired dimensions
int desiredWidth = 400;
int desiredHeight = 300;
float widthScale = (float)bitmapOptions.outWidth/desiredWidth;
float heightScale = (float)bitmapOptions.outHeight/desiredHeight;
float scale = Math.min(widthScale, heightScale);

int sampleSize = 1;
while (sampleSize < scale) {
    sampleSize *= 2;
}
bitmapOptions.inSampleSize = sampleSize; // this value must be a power of 2,
                                         // this is why you can not have an image scaled as you would like
bitmapOptions.inJustDecodeBounds = false; // now we want to load the image

// Let's load just the part of the image necessary for creating the thumbnail, not the whole image
Bitmap thumbnail = BitmapFactory.decodeFile(file.getAbsolutePath(), bitmapOptions);

// Save the thumbnail
File thumbnailFile = ...;
FileOutputStream fos = new FileOutputStream(thumbnailFile);
thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.flush();
fos.close();

// Use the thumbail on an ImageView or recycle it!
thumbnail.recycle();
9 голосов
/ 29 апреля 2011

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

Кроме того, было бы лучше сделать это масштабирование один раз и сохранить полученное растровое изображение в виде большого двоичного объекта в вашей базе данных Sqlite. Для этого я включил фрагмент о том, как преобразовать растровое изображение в байтовый массив.

public static final int THUMBNAIL_HEIGHT = 48;
public static final int THUMBNAIL_WIDTH = 66;

imageBitmap = BitmapFactory.decodeByteArray(mImageData, 0, mImageData.length);
Float width  = new Float(imageBitmap.getWidth());
Float height = new Float(imageBitmap.getHeight());
Float ratio = width/height;
imageBitmap = Bitmap.createScaledBitmap(imageBitmap, (int)(THUMBNAIL_HEIGHT*ratio), THUMBNAIL_HEIGHT, false);

int padding = (THUMBNAIL_WIDTH - imageBitmap.getWidth())/2;
imageView.setPadding(padding, 0, padding, 0);
imageView.setImageBitmap(imageBitmap);



ByteArrayOutputStream baos = new ByteArrayOutputStream();  
imageBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] byteArray = baos.toByteArray();
6 голосов
/ 05 апреля 2010

Используйте BitmapFactory.decodeFile(...), чтобы получить Bitmap объект и установить его на ImageView с ImageView.setImageBitmap().

На ImageView установите размеры макета на что-нибудь маленькое, например:

android:layout_width="66dip" android:layout_height="48dip"

Добавьте onClickListener к ImageView и запустите новое действие, где вы отобразите изображение в полном размере с помощью

android:layout_width="wrap_content" android:layout_height="wrap_content"

или укажите больший размер.

3 голосов
/ 28 сентября 2012
/**
 * Creates a centered bitmap of the desired size.
 *
 * @param source original bitmap source
 * @param width targeted width
 * @param height targeted height
 * @param options options used during thumbnail extraction
 */
public static Bitmap extractThumbnail(
        Bitmap source, int width, int height, int options) {
    if (source == null) {
        return null;
    }

    float scale;
    if (source.getWidth() < source.getHeight()) {
        scale = width / (float) source.getWidth();
    } else {
        scale = height / (float) source.getHeight();
    }
    Matrix matrix = new Matrix();
    matrix.setScale(scale, scale);
    Bitmap thumbnail = transform(matrix, source, width, height,
            OPTIONS_SCALE_UP | options);
    return thumbnail;
}
1 голос
/ 13 сентября 2017

Я нашел простой способ сделать это

Bitmap thumbnail = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(mPath),200,200)

Синтаксис

Bitmap thumbnail = ThumbnailUtils.extractThumbnail(Bitmap source,int width,int height)

OR

использовать зависимость Пикассо

compile 'com.squareup.picasso: picasso: 2.5.2'

Picasso.with(context)
    .load("file:///android_asset/DvpvklR.png")
    .resize(50, 50)
    .into(imageView2);

Ссылка Пикассо

0 голосов
/ 23 декабря 2017

Этот ответ основан на решении, представленном в https://developer.android.com/topic/performance/graphics/load-bitmap.html (без использования внешних библиотек), с некоторыми изменениями, сделанными мной, чтобы сделать его функциональность лучше и практичнее.

Некоторые замечания об этом решении:

  1. Предполагается, что вы хотите сохранить соотношение сторон . Другими словами:

    finalWidth / finalHeight == sourceBitmap.getWidth() / sourceBitmap.getWidth() (независимо от вопросов о кастинге и округлении)

  2. Предполагается, что у вас есть два значения (maxWidth & maxHeight), которые вы хотите любое из размеры вашего окончательного растрового изображения не превышают его соответствующего значения . Другими словами:

    finalWidth <= maxWidth && finalHeight <= maxHeight

    Итак, minRatio было положено в основу расчетов (см. Реализацию). UNLIKE базовое решение, которое поместило maxRatio в качестве основы для расчетов в фактическом . Кроме того, расчет inSampleSize был намного лучше (более логично, кратко и эффективно).

  3. Предполагается, что вы хотите, чтобы (по крайней мере) одно из окончательных измерений имело точно значение соответствующего ему maxValue (каждое было возможно , учитывая вышеизложенные предположения) . Другими словами:

    finalWidth == maxWidth || finalHeight == maxHeight

    Последний дополнительный шаг по сравнению с базовым решением (Bitmap.createScaledBitmap(...)) - это ограничение " точно ". Очень важное замечание: Вы не должны делать этот шаг вначале (например, принятый ответ ) из-за значительного потребления памяти в случае больших изображений!

  4. Это для декодирования file. Вы можете изменить его как базовое решение для декодирования resource (или всего, что поддерживает BitmapFactory).

Реализация:

public static Bitmap decodeSampledBitmap(String pathName, int maxWidth, int maxHeight) {
    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(pathName, options);

    final float wRatio_inv = (float) options.outWidth / maxWidth,
          hRatio_inv = (float) options.outHeight / maxHeight; // Working with inverse ratios is more comfortable
    final int finalW, finalH, minRatio_inv /* = max{Ratio_inv} */;

    if (wRatio_inv > hRatio_inv) {
        minRatio_inv = (int) wRatio_inv;
        finalW = maxWidth;
        finalH = Math.round(options.outHeight / wRatio_inv);
    } else {
        minRatio_inv = (int) hRatio_inv;
        finalH = maxHeight;
        finalW = Math.round(options.outWidth / hRatio_inv);
    }

    options.inSampleSize = pow2Ceil(minRatio_inv); // pow2Ceil: A utility function that comes later
    options.inJustDecodeBounds = false; // Decode bitmap with inSampleSize set

    return Bitmap.createScaledBitmap(BitmapFactory.decodeFile(pathName, options),
          finalW, finalH, true);
}

/**
 * @return the largest power of 2 that is smaller than or equal to number. 
 * WARNING: return {0b1000000...000} for ZERO input.
 */
public static int pow2Ceil(int number) {
    return 1 << -(Integer.numberOfLeadingZeros(number) + 1); // is equivalent to:
    // return Integer.rotateRight(1, Integer.numberOfLeadingZeros(number) + 1);
}

Пример использования, если у вас есть imageView с определенным значением для layout_width (match_parent или явным значением) и неопределенным значением для layout_height (wrap_content), а вместо этого определенное значение для maxHeight:

imageView.setImageBitmap(decodeSampledBitmap(filePath, 
        imageView.getWidth(), imageView.getMaxHeight()));
0 голосов
/ 25 августа 2016

Если вы хотите получить высококачественный результат, используйте библиотеку [RapidDecoder] [1]. Это просто, как следует:

import rapid.decoder.BitmapDecoder;
...
Bitmap bitmap = BitmapDecoder.from(getResources(), R.drawable.image)
                             .scale(width, height)
                             .useBuiltInDecoder(true)
                             .decode();

Не забудьте использовать встроенный декодер, если вы хотите уменьшить масштаб менее чем на 50% и получить результат HQ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...