Интерпретация YUV_420_888 на Samsung Galaxy S7 (Camera2)

Я написал преобразование из YUV_420_888 в Bitmap, учитывая следующую логику (насколько я понимаю):

введите описание изображения здесь

Подводя итог подходу: координаты ядра x и y совпадают как с x, так и с y незаполненной части Y-Plane (2d-распределение), а также с x и y выходного Bitmap. U- и V-плоскости, однако, имеют другую структуру, чем Y-Plane, потому что они используют 1 байт для покрытия 4 пикселей и, кроме того, могут иметь более одного PixelStride, кроме того, они могут также имеют отступы, которые могут отличаться от заполнения Y-Plane. Следовательно, чтобы ядро ​​эффективно получило доступ к U и V, я поместил их в 1-мерные распределения и создал индекс uvIndex, который дает позицию соответствующих U- и V в этом 1-м распределении для заданного ( x, y) координаты в (без дополнений) Y-плоскости (и, следовательно, в выходном растровом изображении).

Чтобы сохранить rs-Kernel скудным, я исключил область заполнения в yPlane, ограничив диапазон x с помощью LaunchOptions (это отражает RowStride плоскости y, которую, таким образом, можно игнорировать ВНУТРИ ядра). Поэтому нам просто нужно рассмотреть uvPixelStride и uvRowStride в uvIndex, то есть индекс, используемый для доступа к значениям u и v.

Это мой код:

Ядро Renderscript с именем yuv420888.rs

  #pragma version(1)
  #pragma rs java_package_name(com.xxxyyy.testcamera2);
  #pragma rs_fp_relaxed

  int32_t width;
  int32_t height;

  uint picWidth, uvPixelStride, uvRowStride ;
  rs_allocation ypsIn,uIn,vIn;

 // The LaunchOptions ensure that the Kernel does not enter the padding  zone of Y, so yRowStride can be ignored WITHIN the Kernel.
 uchar4 __attribute__((kernel)) doConvert(uint32_t x, uint32_t y) {

 // index for accessing the uIn's and vIn's
uint uvIndex=  uvPixelStride * (x/2) + uvRowStride*(y/2);

// get the y,u,v values
uchar yps= rsGetElementAt_uchar(ypsIn, x, y);
uchar u= rsGetElementAt_uchar(uIn, uvIndex);
uchar v= rsGetElementAt_uchar(vIn, uvIndex);

// calc argb
int4 argb;
    argb.r = yps + v * 1436 / 1024 - 179;
    argb.g =  yps -u * 46549 / 131072 + 44 -v * 93604 / 131072 + 91;
    argb.b = yps +u * 1814 / 1024 - 227;
    argb.a = 255;

uchar4 out = convert_uchar4(clamp(argb, 0, 255));
return out;
}

Сторона Java:

    private Bitmap YUV_420_888_toRGB(Image image, int width, int height){
    // Get the three image planes
    Image.Plane[] planes = image.getPlanes();
    ByteBuffer buffer = planes[0].getBuffer();
    byte[] y = new byte[buffer.remaining()];
    buffer.get(y);

    buffer = planes[1].getBuffer();
    byte[] u = new byte[buffer.remaining()];
    buffer.get(u);

    buffer = planes[2].getBuffer();
    byte[] v = new byte[buffer.remaining()];
    buffer.get(v);

    // get the relevant RowStrides and PixelStrides
    // (we know from documentation that PixelStride is 1 for y)
    int yRowStride= planes[0].getRowStride();
    int uvRowStride= planes[1].getRowStride();  // we know from   documentation that RowStride is the same for u and v.
    int uvPixelStride= planes[1].getPixelStride();  // we know from   documentation that PixelStride is the same for u and v.


    // rs creation just for demo. Create rs just once in onCreate and use it again.
    RenderScript rs = RenderScript.create(this);
    //RenderScript rs = MainActivity.rs;
    ScriptC_yuv420888 mYuv420=new ScriptC_yuv420888 (rs);

    // Y,U,V are defined as global allocations, the out-Allocation is the Bitmap.
    // Note also that uAlloc and vAlloc are 1-dimensional while yAlloc is 2-dimensional.
    Type.Builder typeUcharY = new Type.Builder(rs, Element.U8(rs));

    //using safe height
    typeUcharY.setX(yRowStride).setY(y.length / yRowStride);

    Allocation yAlloc = Allocation.createTyped(rs, typeUcharY.create());
    yAlloc.copyFrom(y);
    mYuv420.set_ypsIn(yAlloc);

    Type.Builder typeUcharUV = new Type.Builder(rs, Element.U8(rs));
    // note that the size of the u's and v's are as follows:
    //      (  (width/2)*PixelStride + padding  ) * (height/2)
    // =    (RowStride                          ) * (height/2)
    // but I noted that on the S7 it is 1 less...
    typeUcharUV.setX(u.length);
    Allocation uAlloc = Allocation.createTyped(rs, typeUcharUV.create());
    uAlloc.copyFrom(u);
    mYuv420.set_uIn(uAlloc);

    Allocation vAlloc = Allocation.createTyped(rs, typeUcharUV.create());
    vAlloc.copyFrom(v);
    mYuv420.set_vIn(vAlloc);

    // handover parameters
    mYuv420.set_picWidth(width);
    mYuv420.set_uvRowStride (uvRowStride);
    mYuv420.set_uvPixelStride (uvPixelStride);

    Bitmap outBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Allocation outAlloc = Allocation.createFromBitmap(rs, outBitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);

    Script.LaunchOptions lo = new Script.LaunchOptions();
    lo.setX(0, width);  // by this we ignore the y’s padding zone, i.e. the right side of x between width and yRowStride
    //using safe height
    lo.setY(0, y.length / yRowStride);

    mYuv420.forEach_doConvert(outAlloc,lo);
    outAlloc.copyTo(outBitmap);

    return outBitmap;
}

Тестирование на Nexus 7 (API 22) возвращает красивые цветные растровые изображения. Однако это устройство имеет тривиальные пиксельные переходы (= 1) и отсутствие отступов (т. Е. Rowstride = width). При тестировании на новеньком Samsung S7 (API 23) я получаю некорректные по цвету изображения, кроме зеленого. Но Картинка не показывает общего уклона в сторону зеленого, просто кажется, что незеленые цвета воспроизводятся некорректно. Обратите внимание, что S7 применяет шаг пикселя u / v равный 2 и не применяет отступы.

Поскольку наиболее важная строка кода находится внутри rs-кода, то доступ к плоскостям u / v uint uvIndex = (...) Я думаю, что здесь может быть проблема, вероятно, с неправильным учетом пикселей. Кто-нибудь видит решение? Спасибо.

ОБНОВЛЕНИЕ: я все проверил и почти уверен, что код доступа к y, u, v правильный. Так что проблема должна быть в самих значениях u и v. Не зеленые цвета имеют пурпурный оттенок, и, глядя на значения u, v, кажется, что они находятся в довольно узком диапазоне примерно 110–150. Возможно ли, что нам нужно справиться с YUV для конкретных устройств - ›преобразование RBG ...?! Я что-нибудь пропустил?

ОБНОВЛЕНИЕ 2: исправили код, теперь он работает, благодаря отзывам Эдди.


person Settembrini    schedule 25.03.2016    source источник
comment
давая мне RSIllegalArgumentException: массив слишком мал для типа распределения. в строке yAlloc.copyFrom (y); любая идея. Тестовый телефон - Nexus 6p   -  person Umair    schedule 19.09.2016
comment
какие значения у вас есть для lenght [y], yRowStride, width и height?   -  person Settembrini    schedule 19.09.2016
comment
@Settembrini Я использую этот код и отлично работает на большинстве устройств, но на Pixel он выдает android.support.v8.renderscript.RSIllegalArgumentException: Array too small for allocation type. исключение. Как мне это решить? Не удалось найти много в Google   -  person priyank    schedule 24.11.2016
comment
@ Риан. Возможно, это общая проблема совместимости этого устройства с режимом поддержки rs. Поэтому я бы попытался отключить режим поддержки Renderscript и использовать типы Rendersript вместо типов support.v8.renderscript.   -  person Settembrini    schedule 24.11.2016
comment
@Settembrini Awesome, впервые слышу о скрипте рендеринга. Можете ли вы также помочь опубликовать версию yuv NV12 для RGB? Я пытаюсь это сделать, но мне не повезло, так как я мало что знаю об этом.   -  person beetlej    schedule 25.04.2017
comment
Привет! Я тестировал ваше решение на нескольких телефонах, и оно работает хорошо, хотя на устройстве Samsung S4 (GT-I9805) с версией Android 5.0.1 оно дает зеленые изображения. Похоже, что @Steven описал аналогичную проблему в этом ответе. У вас есть идеи, как решить эту проблему? Буду очень признателен за вашу помощь. В любом случае спасибо за этот обходной путь, все еще очень помог.   -  person Levente Püsök    schedule 09.05.2017
comment
ОБНОВЛЕНИЕ: на основе this, похоже, что эта проблема характерна для устройств 5.0.1.   -  person Levente Püsök    schedule 09.05.2017
comment
@Levente: да. API 21 не поддерживает YUV_420_888. Это одна из раздражающих вещей, которая официально не подтверждена Google, но была обнаружена здесь многими людьми. API ›= 22 работает.   -  person Settembrini    schedule 29.05.2017
comment
@beetlej: это то, что делает встроенная функция ScriptIntrinsicYuvToRGB. Не нужно его программировать.   -  person Settembrini    schedule 29.05.2017
comment
Я рекомендую изменить typeUcharY.setX(yRowStride).setY(height); на typeUcharY.setX(yRowStride).setY(y.length / yRowStride);, чтобы избежать RSIllegalArgumentException   -  person Peter    schedule 17.07.2018
comment
эта команда mYuv420.forEach_doConvert (outAlloc, lo); отображает ошибку в консоли E / ANDR-PERF: IPerf :: tryGetService failed!   -  person Systemsplanet    schedule 29.12.2019


Ответы (8)


смотреть на

floor((float) uvPixelStride*(x)/2)

который вычисляет смещение строки U, V (uv_row_offset) от координаты Y по оси X.

если uvPixelStride = 2, то по мере увеличения x:

x = 0, uv_row_offset = 0
x = 1, uv_row_offset = 1
x = 2, uv_row_offset = 2
x = 3, uv_row_offset = 3

а это неверно. При uv_row_offset = 1 или 3 нет допустимого значения пикселя U / V, поскольку uvPixelStride = 2.

Вы хотите

uvPixelStride * floor(x/2)

(при условии, что вы не доверяете себе помнить критическое поведение округления целочисленного деления, если вы это сделаете):

uvPixelStride * (x/2)

должно быть достаточно

При этом ваше отображение становится:

x = 0, uv_row_offset = 0
x = 1, uv_row_offset = 0
x = 2, uv_row_offset = 2
x = 3, uv_row_offset = 2

Посмотрите, исправит ли это цветовые ошибки. На практике неправильная адресация здесь будет означать, что любой другой образец цвета будет из неправильной цветовой плоскости, поскольку вполне вероятно, что базовые данные YUV являются полуплоскостными (так что плоскость U начинается с плоскости V + 1 байт, с двумя чередующимися плоскостями)

person Eddy Talvala    schedule 25.03.2016
comment
Спасибо, Эдди, это была глупая ошибка, которую он не заметил. Теперь все работает идеально. Что касается плоскостей чередования: я заметил, что байт i в плоскости u повторяется в байте i + 1 в плоскости v, а байт j в плоскости v повторяется байтом j-1 в плоскости u. Как вы думаете, могут ли быть другие случаи, когда чередование происходит в других формах, так что мы не можем просто предположить, что получаем все данные u из плоскости [1] и все данные v из плоскости [2]? - person Settembrini; 25.03.2016
comment
В документации говорится: порядок плоскостей в массиве, возвращаемом Image # getPlanes () ГАРАНТИРУЕТСЯ таким образом, что плоскость № 0 всегда Y, плоскость № 1 всегда U (Cb), а плоскость № 2 всегда V (Cr). - person Settembrini; 25.03.2016
comment
В качестве обновления: если экземпляры RenderScript и ScriptC_yuv420888 уже созданы в onCreate, полное преобразование занимает 50 мс для изображения 1280x720, что, на мой взгляд, вполне удовлетворительно. - person Settembrini; 26.03.2016
comment
Хотя на большинстве устройств, которые, как мне известно, имеют шаг пикселя 2, данные Cb / Cr действительно чередуются, и, как правило, в конфигурации NV21, вероятно, делать это предположение, по крайней мере, в Java-мире небезопасно. Конечно, порядок памяти самолетов может быть разным; хотя plane [1] всегда Cb, это не означает, что его данные находятся в памяти раньше, чем plane [2]. Это могло быть где угодно. - person Eddy Talvala; 28.03.2016
comment
Вы имеете в виду, что в настоящее время нет систематического подхода, который гарантирует правильный сбор данных U и V на всех устройствах? Если это так, я ожидаю, что будущие API-интерфейсы будут включать некоторый параметр, который информирует о применяемом методе чередования, в противном случае я не вижу возможности надежно работать с этим YUV-форматом. - person Settembrini; 28.03.2016
comment
Нет, документация ImageReader всегда точна: плоскость [0] - это Y, плоскость [1] - это U / Cb, а плоскость [2] - это V / Cr. Я имел в виду, что то, можете ли вы сделать оптимизацию, такую ​​как предположение, что plane [1] и plane [2] действительно чередуются в памяти, зависит от устройства. Но вам не нужно знать это, чтобы правильно использовать данные - просто используйте правильную математику доступа и не предполагайте ничего о структуре памяти, кроме шагов. - person Eddy Talvala; 30.03.2016
comment
Спасибо, Эдди, за пояснение. Итак, я считаю, что приведенный выше код соответствует документации, и он работает на всех устройствах, которые я мог тестировать (некоторые с шагом пикселей 2, другие с шагом пикселей 1). Если кто-нибудь найдет устройство на API ›= 22, на котором оно работает некорректно, дайте мне знать - спасибо. - person Settembrini; 30.03.2016
comment
Я должен добавить - вы можете просто подключить Allocation непосредственно к камере, и вам не придется делать копии из Image в byte []. Основным недостатком этого является то, что управлять потоком сложнее, поскольку Allocation не дает вам доступа к отдельным буферам, а только к последним, отправленным при вызове ioReceive (), но это более эффективно, если это не имеет значения в ваш вариант использования. - person Eddy Talvala; 17.08.2016

Для людей, которые сталкиваются с ошибкой

android.support.v8.renderscript.RSIllegalArgumentException: Array too small for allocation type

используйте buffer.capacity() вместо buffer.remaining()

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

person Lolo    schedule 21.12.2016
comment
Я получаю сообщение об ошибке, но buffer.capacity()==buffer.remaining() и я не выполнял никаких операций с изображением. Использование yAlloc.copy1DRangeFrom(0, y.length, y); в качестве описателя выше устранило проблему. - person Stelian Morariu; 18.10.2017

Кроме того, для всех, кто получает

android.support.v8.renderscript.RSIllegalArgumentException: массив слишком мал для типа распределения

Я исправил это, изменив yAlloc.copyFrom(y); на yAlloc.copy1DRangeFrom(0, y.length, y);

person user2486946    schedule 02.02.2017
comment
Я нашел лучшее решение - изменить typeUcharY.setX(yRowStride).setY(height); на typeUcharY.setX(yRowStride).setY(y.length / yRowStride); - решение copy1DRangeFrom приводит к сбою преобразования на некоторых устройствах. - person Peter; 17.07.2018
comment
Это исправило мою ошибку OnePlus A6013 Error: android.renderscript.RSIllegalArgumentException: Array too small for allocation type. - person Jelle de Fries; 04.07.2019

Публикация полного решения для преобразования YUV-> BGR (может быть адаптировано и для других форматов), а также для поворота изображения в вертикальное положение с помощью renderscript. Выделение используется как ввод, а массив байтов - как вывод. Он был протестирован на Android 8+, в том числе на устройствах Samsung.

Ява

/**
 * Renderscript-based process to convert YUV_420_888 to BGR_888 and rotation to upright.
 */
public class ImageProcessor {

    protected final String TAG = this.getClass().getSimpleName();

    private Allocation mInputAllocation;
    private Allocation mOutAllocLand;
    private Allocation mOutAllocPort;

    private Handler mProcessingHandler;
    private ScriptC_yuv_bgr mConvertScript;
    private byte[] frameBGR;

    public ProcessingTask mTask;
    private ImageListener listener;
    private Supplier<Integer> rotation;

    public ImageProcessor(RenderScript rs, Size dimensions, ImageListener listener, Supplier<Integer> rotation) {

        this.listener = listener;
        this.rotation = rotation;
        int w = dimensions.getWidth();
        int h = dimensions.getHeight();

        Type.Builder yuvTypeBuilder = new Type.Builder(rs, Element.YUV(rs));
        yuvTypeBuilder.setX(w);
        yuvTypeBuilder.setY(h);
        yuvTypeBuilder.setYuvFormat(ImageFormat.YUV_420_888);
        mInputAllocation = Allocation.createTyped(rs, yuvTypeBuilder.create(),
                Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT);

        //keep 2 allocations to handle different image rotations
        mOutAllocLand = createOutBGRAlloc(rs, w, h);
        mOutAllocPort = createOutBGRAlloc(rs, h, w);

        frameBGR = new byte[w*h*3];

        HandlerThread processingThread = new HandlerThread(this.getClass().getSimpleName());
        processingThread.start();
        mProcessingHandler = new Handler(processingThread.getLooper());

        mConvertScript = new ScriptC_yuv_bgr(rs);
        mConvertScript.set_inWidth(w);
        mConvertScript.set_inHeight(h);

        mTask = new ProcessingTask(mInputAllocation);
    }

    private Allocation createOutBGRAlloc(RenderScript rs, int width, int height) {
        //Stored as Vec4, it's impossible to store as Vec3, buffer size will be for Vec4 anyway
        //using RGB_888 as alternative for BGR_888, can be just U8_3 type
        Type.Builder rgbTypeBuilderPort = new Type.Builder(rs, Element.RGB_888(rs));
        rgbTypeBuilderPort.setX(width);
        rgbTypeBuilderPort.setY(height);
        Allocation allocation = Allocation.createTyped(
            rs, rgbTypeBuilderPort.create(), Allocation.USAGE_SCRIPT
        );
        //Use auto-padding to be able to copy to x*h*3 bytes array
        allocation.setAutoPadding(true);

        return allocation;
    }

    public Surface getInputSurface() {
        return mInputAllocation.getSurface();
    }

    /**
     * Simple class to keep track of incoming frame count,
     * and to process the newest one in the processing thread
     */
    class ProcessingTask implements Runnable, Allocation.OnBufferAvailableListener {

        private int mPendingFrames = 0;

        private Allocation mInputAllocation;

        public ProcessingTask(Allocation input) {
            mInputAllocation = input;
            mInputAllocation.setOnBufferAvailableListener(this);
        }

        @Override
        public void onBufferAvailable(Allocation a) {
            synchronized(this) {
                mPendingFrames++;
                mProcessingHandler.post(this);
            }
        }

        @Override
        public void run() {
            // Find out how many frames have arrived
            int pendingFrames;
            synchronized(this) {
                pendingFrames = mPendingFrames;
                mPendingFrames = 0;

                // Discard extra messages in case processing is slower than frame rate
                mProcessingHandler.removeCallbacks(this);
            }

            // Get to newest input
            for (int i = 0; i < pendingFrames; i++) {
                mInputAllocation.ioReceive();
            }

            int rot = rotation.get();

            mConvertScript.set_currentYUVFrame(mInputAllocation);
            mConvertScript.set_rotation(rot);

            Allocation allocOut = rot==90 || rot== 270 ? mOutAllocPort : mOutAllocLand;

            // Run processing
            // ain allocation isn't really used, global frame param is used to get data from
            mConvertScript.forEach_yuv_bgr(allocOut);

            //Save to byte array, BGR 24bit
            allocOut.copyTo(frameBGR);

            int w = allocOut.getType().getX();
            int h = allocOut.getType().getY();

            if (listener != null) {
                listener.onImageAvailable(frameBGR, w, h);
            }
        }
    }

    public interface ImageListener {

        /**
         * Called when there is available image, image is in upright position.
         *
         * @param bgr BGR 24bit bytes
         * @param width image width
         * @param height image height
         */
        void onImageAvailable(byte[] bgr, int width, int height);
    }
}

RS

#pragma version(1)
#pragma rs java_package_name(com.affectiva.camera)
#pragma rs_fp_relaxed

//Script convers YUV to BGR(uchar3)

//current YUV frame to read pixels from
rs_allocation currentYUVFrame;

//input image rotation: 0,90,180,270 clockwise
uint32_t rotation;
uint32_t inWidth;
uint32_t inHeight;

//method returns uchar3  BGR which will be set to x,y in output allocation
uchar3 __attribute__((kernel)) yuv_bgr(uint32_t x, uint32_t y) {

    // Read in pixel values from latest frame - YUV color space

    uchar3 inPixel;
    uint32_t xRot = x;
    uint32_t yRot = y;

    //Do not rotate if 0
    if (rotation==90) {
      //rotate 270 clockwise
      xRot = y;
      yRot = inHeight - 1 - x;
    } else if (rotation==180) {
      xRot = inWidth - 1 - x;
      yRot = inHeight - 1 - y;
    } else if (rotation==270) {
      //rotate 90 clockwise
      xRot = inWidth - 1 - y;
      yRot = x;
    }

    inPixel.r = rsGetElementAtYuv_uchar_Y(currentYUVFrame, xRot, yRot);
    inPixel.g = rsGetElementAtYuv_uchar_U(currentYUVFrame, xRot, yRot);
    inPixel.b = rsGetElementAtYuv_uchar_V(currentYUVFrame, xRot, yRot);

    // Convert YUV to RGB, JFIF transform with fixed-point math
    // R = Y + 1.402 * (V - 128)
    // G = Y - 0.34414 * (U - 128) - 0.71414 * (V - 128)
    // B = Y + 1.772 * (U - 128)

    int3 bgr;
    //get red pixel and assing to b
    bgr.b = inPixel.r +
            inPixel.b * 1436 / 1024 - 179;
    bgr.g = inPixel.r -
            inPixel.g * 46549 / 131072 + 44 -
            inPixel.b * 93604 / 131072 + 91;
    //get blue pixel and assign to red
    bgr.r = inPixel.r +
            inPixel.g * 1814 / 1024 - 227;

    // Write out
    return convert_uchar3(clamp(bgr, 0, 255));
}
person Andrei .F    schedule 19.12.2019

На планшете Samsung Galaxy Tab 5 (планшет) версии Android 5.1.1 (22) с предполагаемым форматом YUV_420_888 следующий алгоритм рендеринга работает хорошо и дает правильные цвета:

uchar yValue    = rsGetElementAt_uchar(gCurrentFrame, x + y * yRowStride);
uchar vValue    = rsGetElementAt_uchar(gCurrentFrame, ( (x/2) + (y/4) * yRowStride ) + (xSize * ySize) );
uchar uValue    = rsGetElementAt_uchar(gCurrentFrame, ( (x/2) + (y/4) * yRowStride ) + (xSize * ySize) + (xSize * ySize) / 4);

Я не понимаю, почему значение по горизонтали (т.е. y) масштабируется в четыре раза вместо двух, но это работает хорошо. Мне также нужно было избегать использования rsGetElementAtYuv_uchar_Y | U | V. Я считаю, что соответствующее значение шага распределения установлено на ноль, а не на что-то правильное. Использование rsGetElementAt_uchar () - разумный обходной путь.

На Samsung Galaxy S5 (смартфон), версия Android 5.0 (21) с предполагаемым форматом YUV_420_888 я не могу восстановить значения u и v, они отображаются как все нули. В результате изображение выглядит зеленым. Светится нормально, но изображение переворачивается по вертикали.

person Steven Punte    schedule 04.04.2016

Этот код требует использования библиотеки совместимости RenderScript (android.support.v8.renderscript. *).

Чтобы библиотека совместимости работала с Android API 23, я обновился до gradle-plugin 2.1.0 и Build-Tools 23.0.3 в соответствии с ответом Мяо Ванга на Как создавать скрипты Renderscript в Android Studio и запускать их?

Если вы последуете его ответу и получите сообщение об ошибке «Требуется версия Gradle 2.10», НЕ меняйте

classpath 'com.android.tools.build:gradle:2.1.0'

Вместо этого обновите поле distributionUrl файла Project \ gradle \ wrapper \ gradle-wrapper.properties до

distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip

и измените Файл> Настройки> Сборки, выполнение, развертывание> Инструменты сборки> Gradle> Gradle на Использовать оболочку gradle по умолчанию согласно Требуется Gradle версии 2.10. Ошибка.

person Nick    schedule 11.05.2016

Re: RSIllegalArgumentException

В моем случае это был тот случай, когда buffer.remaining () не был кратным шагу: длина последней строки была меньше шага (т.е. только до того места, где были фактические данные).

person Takashi Matsuzawa    schedule 23.07.2019

К вашему сведению, если кто-то еще это получит, поскольку я также получал android.support.v8.renderscript.RSIllegalArgumentException: массив слишком мал для типа распределения при тестировании кода. В моем случае оказалось, что при выделении буфера для Y мне пришлось перемотать буфер, потому что он оставался не на том конце и не копировал данные. Выполняя buffer.rewind (); перед распределением новый массив байтов заставляет его работать нормально.

person draekko    schedule 27.08.2020