B4A Library NV21utils Lib: camera preview to ARGB888

Hi all!

I am happy to release my first lib, which converts from default camera preview format to ARGB888. The processing method has been written in C and included in the java library (which does not anything more)

The library is included in the attached zip, with a modified version of the cameraEx class example. So, Erel's camera library will be needed to run the example.


What it does:

  • Takes the preview byte array and converts i to ARGB888, rotating and flipping if necessary. putting the result into a mutablebitmap previously generated by the user. So, no need to create and destroy bitmaps each time. (Important: the mutableBitmap must have been created with the proper final orientation and properly scaled dimensions). Also, the mutablebitmap is supposed to be ARGB888 format. If these requirements are not met, the routine will return and do nothing.
  • User can specify the subsampling (1,2,4 or 8, only these values). Depending on your needs, not always full resolution is needed and process time can be decreased this way.
  • It has been compiled for arm devices. Next release I will try to add other plattforms
But:
  • much faster options may exist over there. In case anybody knows of other simple approaches, please let me know, since I am also interested in it.

I don't have much time, but if someone finds it useful for processing, I will add a function which makes the conversion directly onto an array instead of a bitmap.


Please let me know if you decide to use it or find any issues with it.:)
 

Attachments

  • Camera_NV21_example_and_lib.zip
    29.9 KB · Views: 594

JordiCP

Expert
Licensed User
Longtime User
Hi, glad you liked it!:)

I think the more straightforward option is to get some pixels from the subsampled bitmap and get some kind of mean value from them.

Depending on the quantity of pixels you use for your calculation, you could use
a) bitmap.getpixel(x,y) for the chosen pixels
b) use the getpixels() function from HERE posted by Klaus, which will return an array from the bitmap.

I don't know how fast these functions are, but I think it is not critical since you could do it every X frames.

If it does not work, I can modify the lib to give directly an array, but unfortunately I will not be able to do it until next week.
 

freedom2000

Well-Known Member
Licensed User
Longtime User
Hi, glad you liked it!:)

I think the more straightforward option is to get some pixels from the subsampled bitmap and get some kind of mean value from them.

Depending on the quantity of pixels you use for your calculation, you could use
a) bitmap.getpixel(x,y) for the chosen pixels
b) use the getpixels() function from HERE posted by Klaus, which will return an array from the bitmap.

I don't know how fast these functions are, but I think it is not critical since you could do it every X frames.

If it does not work, I can modify the lib to give directly an array, but unfortunately I will not be able to do it until next week.
Thanks for your reply.

I was thinking at the same option : pick a pixel from here to there, average them --> et hop :)

This lib is fantastic, For what I want to do I am pretty sure I will reach the "real time" processing.
The limit will be the ability of the Milight to follow the Android command.
 

yiankos1

Well-Known Member
Licensed User
Longtime User
Hello my friend,
I really liked your lib, but i want to explain you some things why i am trying to use your lib. I tried to use the simple CameraEx lib but at newer devices 4.4 and above, when i try to delete a saved photo and force to refresh the library there is a broken thumbnail at gallery. SO HERE I AM. Correct me if i am wrong, i think that your lib can show a preview of a photo that we took without saving to gallery, right? So, user cam choose if he wants to keep it or not. I tried to catch the preview when i hit the camera button:
B4X:
Sub Camera1_PictureTaken (Data() As Byte)
    If Data.Length<>(3*myBitmap.Width*myScale*myBitmap.Height*myScale/2) Then
        Log("Not processing")
        Return
    End If
    NV21toRGB.proceed( Data, myBitmap.Width*myScale, myBitmap.Height*myScale, myScale, myBitmap, camVertical , camEx.Front, camEx.DispRotation, myIndexEffect )
    myIV.invalidate
End sub
but camera freezes and log shows "Not processing" and of course no image preview. Can you tell if i am at right direction?
Thank you for your time.

P.S. If you dont understand something, feel free to ask.
 

JordiCP

Expert
Licensed User
Longtime User
Thank you yiankos1:)

Your approach will not work since the Data() that you receive in the Preview() event (NV21 format) is not the same format as the Data() in the PictureTaken() event (JPEG format) and my library expects the first one.


I suppose (correct me if I am wrong) that what you want to do is let the user decide wether to save or delete a picture just after it has been taken, avoiding calls to Mediascanner

With my library it could be done, but you would need to:
> Show the bitmap from the latest preview, in an imageview (as in the example)
> Copy the Data() from the PictureTaken event to a global variable
> Then ask the user to save/discard and if he chooses to save, do it.
But it has drawbacks. For instance, if you use the flash, the preview will be very different from the final image


A much more straightforward approach that works is (and without my library):
> On PictureTaken() event, save the picture in a private folder. For instance in "File.DirInternal", always with the same name "tmpFile.jpg"
> Ask the user to save/discard it
> If the user chooses to save, copy this "tmpFile.jpg" file to the output folder that you choose for your app (and rename it for instance using "YYMMDDHHMMSS.jpg")
> If the user decides to discard, just do nothing

This way, there will always be, at most, one "tmpFile.jpg" in your private folder
 
Top