Android Question Camera question

Beja

Expert
Licensed User
Longtime User
Hi,
How can I know the color of a portion of picture taken by the camera?
In the attached picture, I want to know the color inside the red square.

Thanks in advance
 

Attachments

  • flower.png
    flower.png
    135.2 KB · Views: 178

strat

Active Member
Licensed User
Longtime User
Simply you can calculate the average colour. Add all pixel colour value and divide the number of pixels in the red square. It should give you ambiance colour of given area.
 
Upvote 0

Beja

Expert
Licensed User
Longtime User
Thanks Strat..
My experience with the camera object and with image processing is not enough to follow your explanations, so if you could give me some detail I would appreciate it.. If I knew the number of pixels in the red square, do you think I can also know their color?
I thought the problem is how to get to that area and isolate it from the entire picture, and then how to know the color of the individual pixels in the area.
Thank you.
 
Upvote 0

strat

Active Member
Licensed User
Longtime User
B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Dim ImageView1 As ImageView
    Dim Button1 As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("Layout1")

End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub getambiencecolor(b As Bitmap,x1,y1,x2,y2 As Int) As Int
    Dim argb() As Int
    Dim i,j As Int
    Dim ta,tr,tg,tb,aa,ar,ag,ab As Int
    Dim numberofpixel,ambiencecolor As Int
    Dim ca,cr,cg,cb As Int
    Dim colorvalue As Int
   
    ta=0
    tr=0
    tg=0
    tb=0
    numberofpixel=0
    For i=x1 To x2
      For j=y1 To y2
        colorvalue=b.getPixel(i,j)
        argb = GetARGB(colorvalue)
        ca=argb(0)
        cr=argb(1)
        cg=argb(2)
        cb=argb(3)
        ta=ta+ca
        tr=tr+cr
        tg=tg+cg
        tb=tb+cb
        numberofpixel=numberofpixel+1
      Next
    Next
    aa=ta/numberofpixel
    ar=tr/numberofpixel
    ag=tg/numberofpixel
    ab=tb/numberofpixel
    ambiencecolor=Colors.argb(aa,ar,ag,ab)
    Return ambiencecolor
End Sub

Sub Button1_Click
    Dim btmp As Bitmap
    Dim rect1 As Rect
    Dim c As Canvas
    Dim ambiencecolor As Int
    btmp.Initialize(File.DirAssets,"flower.png")
    ambiencecolor=getambiencecolor(btmp,129,86,153,106)
    ImageView1.Bitmap=btmp
    ImageView1.Width=btmp.Width
    ImageView1.Height=btmp.Height
   
    'Draw a rect using ambiencecolor
    rect1.Initialize(10,10,50,50)
    c.Initialize(ImageView1)
    c.DrawRect(rect1,ambiencecolor,True,1)
End Sub

Sub GetARGB(Color As Int) As Int()
    Dim res(4) As Int
    res(0) = Bit.UnsignedShiftRight(Bit.AND(Color, 0xff000000), 24)
    res(1) = Bit.UnsignedShiftRight(Bit.AND(Color, 0xff0000), 16)
    res(2) = Bit.UnsignedShiftRight(Bit.AND(Color, 0xff00), 8)
    res(3) = Bit.AND(Color, 0xff)
    Return res
End Sub

Getambiencecolor sub determines the ambience color of given coordinates. It seems a bit compex, addition of colour number didn't work so I had to use ARGB values.
 

Attachments

  • getpixel.zip
    259.8 KB · Views: 204
Upvote 0

Beja

Expert
Licensed User
Longtime User
Hi Strat,
Thanks so much indeed for your valuable efforts to help out with this, I truly appreciate it.. I tested it and working fine.
Know only one thing left.. I have and app that will take a picture, how can I direct your code to that newly taken picture, instead of the one saved in the assets folder.
 
Upvote 0

MaFu

Well-Known Member
Licensed User
Longtime User
strat's code is fine, but for a greater area .getPixel() is to slow.

Instead read the area in an integer array and then extract the colors from this array in a single loop.
Code original posted by klaus:
B4X:
Dim p() As Int
'
p = getPixels(bmpTest1, 0, 0, 10, 10, 200, 200)
'
'
Sub getPixels(bmp As Bitmap, offset As Int, stride As Int, x As Int, y As Int, width As Int, height As Int) As Int()
    Dim jo = bmp As JavaObject
    Dim pixels(width * height) As Int
    jo.RunMethod("getPixels", Array As Object(pixels, offset, stride, x, y, width, height))
    Return pixels
End Sub
"stride" must be >= "width" and is same as "width" in normal case.
 
Upvote 0

Beja

Expert
Licensed User
Longtime User
MaFu, thanks..
As mentioned I am new to camera, and didn't know where to find the saved image so I can subject it to strat's solution then delete it to avoid increment in the file name..
 
Upvote 0

strat

Active Member
Licensed User
Longtime User
@MaFu thank you. it is really useful code. We need every time such code parts in order to make something easy. If beja need more speed, I can use this in my sub.

@Beja if you use cameraexclass, you can take and save picture. Then you can use this picture as your source image. If you need code to save and reload picture by using cameraexclass library, I can help you.
 
Upvote 0

Beja

Expert
Licensed User
Longtime User
Thanks strat, and surely I need that kind of help.. just like the first time if you modified the first code to include
saving and processing the color then that would be of great help.

Edit:

Solved. Erel's example that saved the picture in SQLite
 
Last edited:
Upvote 0

Beja

Expert
Licensed User
Longtime User
Strat,
The example works perfect with the provided picture, but when I took a picture with the phone camera and
tried to process it on-the-fly, I got exception that said something like: should be bitmap.width().. I think
the reason may be the new pic size is too large. how can I solve this?
I want to take a picture, then the subject (red square) with the same dimensions, should be right in the center
of the picture and not in the side as now.
 
Upvote 0

strat

Active Member
Licensed User
Longtime User
Such exceptions may occur when bitmap size is zero. It means bitmap may not initialized.
If you use picture on the fly, how do you initialize the bitmap btmp?
You can log bitmap size before imageview1.bitmap=btmp line to learn bitmap size.
 
Upvote 0

Beja

Expert
Licensed User
Longtime User
Hi strat and I am just wondering that, if 1.jpg is already initialized, then how about if I name the new picture 1.jpg and save it in the same location as then old one. because I am first taking the picture and saving it.. then calling your image processing activity. But even in this I need some help
with how to save the image taken by the camera in the App's folder, instead of the default folder.

Any help appreciated
 
Upvote 0

strat

Active Member
Licensed User
Longtime User
Can you upload your picture take and save code here? Without see your code, it is hard to help you at this time.
 
Upvote 0

Beja

Expert
Licensed User
Longtime User
Sure, one moment and will upload the project.. it is basically the CameraX example.
 
Upvote 0

strat

Active Member
Licensed User
Longtime User
I couldn't open your project because of my B4A version is 3.0, so I didn't realized what the error is.
But I checked your code and one line drew my attention. You save picture as "1.jpg", and initialize bitmap as "flower.png"
It should be the same file and same picture. I think your error is here.

If you save the picture to app folder try file.dirinternal. As far as I know it is your app's subfolder.


You can make these modifications :


camEx.SavePictureToFile(Data, File.Dirinternal, "1.jpg") ' in camerax.b4a
btmp.Initialize(File.Dirinternal,"1.jpg") 'in analize.bas
 
Upvote 0

Beja

Expert
Licensed User
Longtime User
Thanks strat.. it looks like it is working..
after taking to picture it took a few seconds, I think processing the ambience color.. then the screen turned black for 3 seconds, then threw the msg: "Unfotunately b4a example has stopped"
Is this because the img file is big.. it is the file taken by the camera without editing, so it should be from 1 to 2 Megabytes
 
Upvote 0

strat

Active Member
Licensed User
Longtime User
You can see log if you run debug mode.It may be out of memory error.

Use bitmap.initializesample to reduce picture dimension.

B4X:
'instead of this line
btmp.Initialize(File.Dirinternal,"1.jpg") 'in analize.bas

'Use this line
btmp.InitializeSample(File.Dirinternal,"1.jpg", 25%x, 25%y)
 
Upvote 0

Beja

Expert
Licensed User
Longtime User
Strat,
Thank you so much for the help.. it is now working like a charm!
 
Upvote 0
Top