Developer от Бога

DV

пятница, 7 июля 2017 г.

Android. RenderScript. C

В прошлой статье был рассмотрен пример кода использования RenderScript с помощью обычных Java - классов. Такой подход можно использовать в обычной обработке изображений (размытие, матрица свертки). Чтоб использовать все ресурсы RenderScript - не обойтись без написания кода на языке С (стандарта С99). Такой код пишется в отдельный файл с расширением .rs и содержится в специальной папке с названием "rs". Пример программы будет выглядеть следующим образом: Java файл.


  1. import android.content.Context;
  2. import android.graphics.Bitmap;
  3. import android.os.Handler;
  4. import android.support.v8.renderscript.Allocation;
  5. import android.support.v8.renderscript.RenderScript;
  6. import ivarious.xyz.Filters.ScriptC_draw;
  7. public class RenderScriptClass {
  8. Context context;
  9. Handler handler;
  10. private Bitmap mBitmapIn;
  11. private Bitmap mBitmapsOut;
  12. private RenderScript mRS;
  13. private Allocation mInAllocation;
  14. private Allocation mOutAllocations;
  15. private ScriptC_draw mScript;
  16. public MiandrRenderScript(Context arg, Bitmap arg_){
  17. mBitmapIn = arg_;
  18. context = arg;
  19. mBitmapsOut = Bitmap.createBitmap(mBitmapIn.getWidth(),mBitmapIn.getHeight(), Bitmap.Config.ARGB_8888);
  20. mRS = RenderScript.create(context);
  21. runScript();
  22. }
  23. public void runScript() {
  24. mInAllocation = Allocation.createFromBitmap(mRS,mBitmapIn);
  25. mOutAllocations = Allocation.createTyped(mRS, mInAllocation.getType());
  26. mScript = new ScriptC_draw(mRS);
  27. mScript.set_inputAlloc(mInAllocation);
  28. mScript.set_bWidht(mBitmapIn.getWidth());
  29. mScript.set_bHeight(mBitmapIn.getHeight());
  30. mScript.forEach_median(mInAllocation, mOutAllocations);
  31. mOutAllocations.copyTo(mBitmapsOut);
  32. }
  33. } }  


Этот класс принимает в конструктор два параметра Context и Bitmap. Контекст нужен для инициализации RenderScript, а Bitmap - входящее изображение для обработки. Также нужно Создать копию по параметрам входящего изображения для результата (mBitmapsOut). Входящий и исходящий Bitmap должен быть сконфигурирован как .ARGB_8888 или .ARGB_4444 ( с альфа каналом ), на других форматах могут быть ошибки. Подключение файла .rs происходит через класс ScriptC_"название файла" ( в данном случае это ScriptC_draw - файл draw.rs). Запуск процесса идет через функцию mScript.forEach_"название функции"(...);


  1. rs_allocation inputAlloc;
  2. uchar4 __attribute__((kernel)) median(uchar4 in, uint32_t x, uint32_t y)
  3. {
  4. uchar4 arrpix[9];
  5. uchar4 buff;
  6. if((x<bWidht-1) && (y<bHeight-1)&&(x>=1) && (y>=1)){
  7. arrpix[0] = rsGetElementAt_uchar4(inputAlloc, x -1, y - 1);
  8. arrpix[1] = rsGetElementAt_uchar4(inputAlloc, x , y - 1);
  9. arrpix[2] = rsGetElementAt_uchar4(inputAlloc, x +1, y - 1);
  10. arrpix[3] = rsGetElementAt_uchar4(inputAlloc, x -1, y );
  11. arrpix[4] = rsGetElementAt_uchar4(inputAlloc, x , y );
  12. arrpix[5] = rsGetElementAt_uchar4(inputAlloc, x +1, y );
  13. arrpix[6] = rsGetElementAt_uchar4(inputAlloc, x -1, y+1);
  14. arrpix[7] = rsGetElementAt_uchar4(inputAlloc, x , y+1);
  15. arrpix[8] = rsGetElementAt_uchar4(inputAlloc, x +1, y+1);
  16. for(int i=0; i<=4; i++)
  17. for(int i=0; i<=8; i++){
  18. if(arrpix[i].r>arrpix[i+1].r){
  19. buff.r = arrpix[i].r; arrpix[i].r = arrpix[i+1].r;
  20. arrpix[i+1].r = buff.r;}
  21. if(arrpix[i].g>arrpix[i+1].g){
  22. buff.g = arrpix[i].g; arrpix[i].g = arrpix[i+1].g;
  23. arrpix[i+1].g = buff.g;}
  24. if(arrpix[i].b>arrpix[i+1].b){
  25. buff.b = arrpix[i].b; arrpix[i].b = arrpix[i+1].b;
  26. arrpix[i+1].b = buff.b;}
  27. }
  28. return arrpix[4];
  29. }
  30. else return in;
  31. } else return in;
  32.  

Стоит отметить сразу во избежании путаницы: Функция uchar4 __attribute__((kernel)) median(...) вызывается каждый раз для каждого пикселя отдельно, то есть функция обрабатывает только один пиксель за один раз, который передается в параметрах функции uchar4 in. Если необходимо задать цвет пикселя в зависимости от окружающих пикселей ( как на примере - медианный фильтр ) то необходимо в файл .rs передать целый обьект: mScript.set_"название переменной в файле .rs"(mInAllocation); В самом файле .rs создать переменную которая будет принимать байты пикселей всего изображения: rs_allocation inputAlloc; Функция uchar4 __attribute__((kernel)) median(...) также может принимать от системы координаты текущего пикселя uint32_t x, uint32_t y, от которого можно вычислять остальные. В конечном результате доступ к другим пикселям можно получить используя функцию uchar4 buff = rsGetElementAt_uchar4(inputAlloc, x + a , y + b); В RenderScript есть несколько типов переменных - векторов. Каждый вектор содержит данные о пикселе. Получать доступ к ним можно через оператор - точку : in.r = 255.

Комментариев нет:

Отправить комментарий