Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Renderscript allocation from bitmap

I'm trying to get into render script and was confused regarding allocations usage. Almost all examples show next algorithm:

  1. Create In and Out Bitmap
  2. Create In and Out Allocation from Bitmaps In and Out correspondingly
  3. Configure script and perform forEach method
  4. copy result from Out allocation into bitmap using copyTo method

Something like that:

    Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.lena);
    Bitmap dstBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());

    Allocation allocationIn = Allocation.createFromBitmap(renderScript, srcBitmap);
    Allocation allocationOut = Allocation.createFromBitmap(renderScript, dstBitmap);

    scriptColorMatrix.setGreyscale();

    scriptColorMatrix.forEach(allocationIn, allocationOut);

    //no difference after removing this line
    allocationOut.copyTo(dstBitmap);

    imagePreview.setImageBitmap(dstBitmap);

This works, but it also works even if I omit step 4 by removing:

allocationOut.copyTo(dstBitmap);

Lets go further and lower brightness after grayscale:

    Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.lena);
    Bitmap dstBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());

    Allocation allocationIn = Allocation.createFromBitmap(renderScript, srcBitmap);
    Allocation allocationOut = Allocation.createFromBitmap(renderScript, dstBitmap);

    scriptColorMatrix.setGreyscale();

    scriptColorMatrix.forEach(allocationIn, allocationOut);

    //reset color matrix
    scriptColorMatrix.setColorMatrix(new Matrix4f());

    //adjust brightness
    scriptColorMatrix.setAdd(-0.5f, -0.5f, -0.5f, 0f);

    //Performing forEach vise versa (from out to in)
    scriptColorMatrix.forEach(allocationOut, allocationIn);

    imagePreview.setImageBitmap(srcBitmap);

Shortly describing the code above, we performed grayscale collor matrix from In allocation into Out one, and brightness adjustment in backward direction. I never called copyTo method, but at the end I've got result in srcBitmap and it was correct.

That's not the end. Lets go deeper. I'll leave only one bitmap and one Allocation:

    Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.lena);

    Allocation allocationIn = Allocation.createFromBitmap(renderScript, srcBitmap);

    scriptColorMatrix.setGreyscale();

    scriptColorMatrix.forEach(allocationIn, allocationIn);

    //reset color matrix
    scriptColorMatrix.setColorMatrix(new Matrix4f());

    //adjust brightness
    scriptColorMatrix.setAdd(-0.5f, -0.5f, -0.5f, 0f);

    scriptColorMatrix.forEach(allocationIn, allocationIn);

    imagePreview.setImageBitmap(srcBitmap);

The result is the same...



Can anybody explain why does it happen and where to use copyTo and where I can use targeting Bitmap without it?

like image 495
VinSmile Avatar asked Feb 10 '23 03:02

VinSmile


1 Answers

The Allocation objects are needed in order to provide the proper mapping of Bitmap to something Renderscript understands. If you are targeting API 18 or higher, the Allocation.createFromBitmap() methods you are using are automatically giving in the flag USAGE_SHARED, which tries to have the Allocation use the same backing memory as the Bitmap object. So the two are linked but technically the copyTo() method is still needed as the RS implementation may need to synchronize it back. On some platforms this may have already happened where others may cause this to pause as DMA or other mechanisms are updating the Bitmap's backing memory with whatever changes were made by the RS code.

As for why you can reverse the in/out Allocation order when calling scripts - it's valid and up to you to get the arguments and order correct. To RS they are just objects which point to some type of backing data to be manipulated. Since both were created with the Allocation.createFromBitmap() call, they can be used as either input or output as long as the Bitmap objects are mutable.

Similarly, using the same Allocation for the input and output is not normal, but also not invalid. It just means your input is changing on the fly. As long as your script is not accessing other Elements in the data when the root function is called for a specific Element, then it should work (as you are seeing.)

like image 65
Larry Schiefer Avatar answered Mar 23 '23 23:03

Larry Schiefer