Подтвердить что ты не робот

Android: вращение изображения без загрузки его в память

Мне интересно, можно ли повернуть изображение, сохраненное на SD-карте, без его загрузки в память.

По этой причине я ищу то, что известно OutOfMemoryError. Я знаю, что могу избежать этого, уменьшив масштаб изображения, но на самом деле я не хочу уменьшать размер этого изображения, я хочу иметь исходное изображение, но поворачиваться на 90 градусов.

Любые предложения об этом приветствуются:)

4b9b3361

Ответ 1

вы должны декодировать декодирование Images using Bitmap`. вы должны следовать Загрузка большого изображения, представленное google о том, как это сделать.. это очень помогло мне, вы заметите большую разницу в ОЗУ использование..

UPDATE, если все, что вам нужно, просто поверните изображение, которое вы можете использовать для этого кода

Matrix matrix = new Matrix();
matrix.setRotate(90);
result = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),bitmap.getHeight(), matrix, false);

если вам просто нужно установить ориентацию изображения (например, ориентацию фото, когда она была сделана), вы можете использовать

ExifInterface exif = new ExifInterface(filePath);

с атрибутом ExifInterface.TAG_ORIENTATION Надеюсь, это поможет вам.

Ответ 2

enter image description here

Для 90-градусных поворотов я действительно охватываю RenderScript, который точно предназначен для обработки растровых изображений и неожиданно даже быстрее, чем значение по умолчанию Bitmap.createBitmap(). Растровое изображение in-process не хранится в куче Java, поэтому не вставляя вас в OutOfMemoryError.

После настройки поддержки RenderScript в вашем проекте с несколькими строками, здесь используется алгоритм RenderScript:

1) Создайте app\src\main\rs\rotator.rs файл RenderScript со следующим содержимым.

#pragma version(1)
#pragma rs java_package_name(ua.kulku.rs)

rs_allocation inImage;
int inWidth;
int inHeight;

uchar4 __attribute__ ((kernel)) rotate_90_clockwise (uchar4 in, uint32_t x, uint32_t y) {
    uint32_t inX  = inWidth - 1 - y;
    uint32_t inY = x;
    const uchar4 *out = rsGetElementAt(inImage, inX, inY);
    return *out;
}

uchar4 __attribute__ ((kernel)) rotate_270_clockwise (uchar4 in, uint32_t x, uint32_t y) {
    uint32_t inX = y;
    uint32_t inY = inHeight - 1 - x;

    const uchar4 *out = rsGetElementAt(inImage, inX, inY);
    return *out;
}

Обратите внимание на ua.kulku.rs, что некоторое имя пакета вы выбираете для автоматического создания интерфейса RS Java.

2) Ссылка на него в коде Java:

import ua.kulku.rs.ScriptC_rotator;

    public Bitmap rotate(Bitmap bitmap) {
        RenderScript rs = RenderScript.create(mContext);
        ScriptC_rotator script = new ScriptC_rotator(rs);
        script.set_inWidth(bitmap.getWidth());
        script.set_inHeight(bitmap.getHeight());
        Allocation sourceAllocation = Allocation.createFromBitmap(rs, bitmap,
                Allocation.MipmapControl.MIPMAP_NONE,
                Allocation.USAGE_SCRIPT);
        bitmap.recycle();
        script.set_inImage(sourceAllocation);

        int targetHeight = bitmap.getWidth();
        int targetWidth = bitmap.getHeight();
        Bitmap.Config config = bitmap.getConfig();
        Bitmap target = Bitmap.createBitmap(targetWidth, targetHeight, config);
        final Allocation targetAllocation = Allocation.createFromBitmap(rs, target,
                Allocation.MipmapControl.MIPMAP_NONE,
                Allocation.USAGE_SCRIPT);
        script.forEach_rotate_90_clockwise(targetAllocation, targetAllocation);
        targetAllocation.copyTo(target);
        rs.destroy();
        return target;
    }

enter image description here

Для 180-градусного вращения решение NDK превосходит RenderScript, как и для меня, из-за использования доступа к последовательному элементу массива, поскольку поворот на 180 градусов - это фактически возврат изображения массив. Алгоритм NDK, который я использовал в этих сравнениях, - это https://github.com/AndroidDeveloperLB/AndroidJniBitmapOperations. Растровое изображение in-process также не сохраняется в куче Java, предотвращая OutOfMemoryError.

Бары статистики указывают, что я получил в миллисекундах на своем Samsung S4 (Android 5.0) для 13-мегапиксельной фотографии.

Ответ 3

Я сделал очень медленное, но удобное для памяти решение здесь.

Я уверен, что есть лучшие способы и хотелось бы узнать о них.

Ответ 4

Если вам нужно обрабатывать разные форматы, это будет боль. Вы должны будете понимать различные форматы и быть в состоянии читать/писать/преобразовывать их, возможно, через потоки. На обычном ПК я бы сказал, чтобы посмотреть ImageMagick, который имеет очень большую поддержку изображения. Я искал порт Android и придумал this. Возможно, стоит попробовать. Однако он выглядит незаконченным, поэтому вам, вероятно, придется сделать некоторую работу для лучшего охвата формата.