iOS Question GetPixelColor error [solved]

igodese

Member
Licensed User
Hi all,
I used the GetPixelColor function as suggested on post#5 at this link: https://www.b4x.com/android/forum/threads/getpixelcolor.56922/
It works, but sometimes (very rarely) I receive an error like this:
SignalHandler 11
Error occurred on line: 228 (Main)
Signal - 11
Stack Trace: (
"0 TestApp SignalHandler + 120",
"1 libsystem_platform.dylib 0x0000000181ff8b48 _sigtramp + 36",
"2 TestApp -[b4i_main GetPixelColor:::] + 152",
"3 CoreFoundation <redacted> + 144",
"4 CoreFoundation <redacted> + 284",
"5 TestApp +[B4I runDynamicMethod:method:throwErrorIfMissing:args:] + 1624",
"6 TestApp -[B4INativeObject RunMethod::] + 216",
"7 TestApp -[b4i_main _getpixelcolor:::] + 1924",
"8 TestApp -[b4i_main _pnlcolors_touch:::] + 2304",
"9 CoreFoundation <redacted> + 144"
)
Note that the function is called in a panel touch event (down and move). The problem arises touching the panel continuously. In debug mode I have the error message, in release mode the App simply ends.
I used a Try / Catch structure in order to solve the problem, but it was unsuccessful.
Do you have any suggestion to solve the problem ? Anybody else had the same problem ?
Thank you.
 

igodese

Member
Licensed User
I checked the BitmapCreator class. It's a big amount of code, just to get a pixel colour...

In order to "kill the bug" coming from fast repetition of calls of GetPixelColor, I tried to create my own byte array from a Bitmap (for successive indexing using X and Y to get the RGBA values), but the resulting data is not a real "bit map", but the entire file (with header, preamble etc) for saving the image as PNG or JPEG, depending upon parameter.

Is there some "Bitmap to ByteArray" function that just saves the RGBA values as an Array ?

It will be exactly like the Objective-C used in the mentioned GetPixelColor:
B4X:
    #If OBJC
    - (UIColor *)GetPixelColor:(UIImage *)bitmap :(int)x :(int)y {
        CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(bitmap.CGImage));
        const UInt8* data = CFDataGetBytePtr(pixelData);

        int stride = CGImageGetBytesPerRow(bitmap.CGImage);
        int pixelInfo = (stride  * y) + x*4 ;

        UInt8 red = data[pixelInfo];
        UInt8 green = data[(pixelInfo + 1)];
        UInt8 blue = data[pixelInfo + 2];
        UInt8 alpha = data[pixelInfo + 3];
        CFRelease(pixelData);
        return [UIColor colorWithRed:red/255.0f green:green/255.0f blue:blue/255.0f alpha:alpha/255.0f];
    }
    #End If

This function, as I said before, creates random errors when called as fast as touch-move events on a panel. Such errors can't be intercepted by a Try-Catch structure.

I also noticed that any time I call the function, the entire bitmap is copied to the data[] array and then the pixel color is extracted from there.

I think that in my particular case, where the bitmap is always the same, it will be better to get the bitmap just one time and therefore get the pixel colour always from the same (global) array.

It's possible in B4i to get the bitmap data in the same way the Objective-C does ?
Thank you in advance.
 
Upvote 0

igodese

Member
Licensed User
Oops, it requires B4i v5.0+ (I'm using V4.40)
I will check our commercial to see if he missed to send me the email with links for updating.
In the meantime, do you have an Objective-C function that simply return the byte array with image data (no headers) ?
Thank you.
 
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
In the meantime,
Just as a check that could give a hint about the real cause of the problem, you could log the X,Y values passed to GetPixelColor each time, and see if they are within the bitmap boundaries (touch events can give out-of-bounds values if the movement has been started inside the view, but then moved out of it)
 
Upvote 0

igodese

Member
Licensed User
Thank you, JordiCP. I have a check inside the function that clips the X and Y values to the panel limits. Anyway, I will double check it, to be extra-sure.
 
Upvote 0

igodese

Member
Licensed User
@Erel, about the Objective-C function

Do you intend something like this ?
B4X:
Private Sub GetTrueBmp(srcbmp As Bitmap, dst() As Byte) ' the new B4i function
    Dim no As NativeObject = Me
    Dim mWidth, mHeight As Int
    mWidth = srcbmp.Width ' get bitmap width
    mHeight = srcbmp.Height ' get bitmap height
    no.RunMethod("UIImageToBuffer::::", Array(srcbmp, no.ArrayToNSData(dst), mWidth, mHeight))
End Sub
#if OBJC
- (void)UIImageToBuffer:(UIImage*) bmp :(NSData*)data :(int)width :(int)height{
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate([(NSMutableData*)data mutableBytes],
            width,
            height,
            8,
            4 * width,
            colorSpace,
            kCGImageAlphaPremultipliedLast);
    if(!context) {
        NSLog(@"Failed to create bitmap context");
    }       
    CGColorSpaceRelease(colorSpace);
    CGImageRef imageRef = bmp.CGImage;
    CGRect rect = CGRectMake(0, 0, width, height);
    CGContextDrawImage(context, rect, imageRef);
    CGContextRelease(context);
}
#End If

I tried to copy the bitmap (imageview.bitmap) to a byte array, but there is an error while compiling:
\b4i_main_subs_0.java:1040: error: not a statement
b4i_main._mbmp;

In the parameters of the Objective-C I see 4 values: the pointer to a bitmap (the image source), the pointer to the output buffer and the image width and height.

May be I'm doing something wrong... The created context (with the image) should be created in the memory area corresponding to the output buffer. Why I receive the error ? Help, please.
 
Upvote 0

igodese

Member
Licensed User
The error comes from a line of the main I leaved half-empty while writing the new function :)
Now I'm going to test if it works.
I called the function in the application start, after loading all the views.
The result is:
Application_Start
SignalHandler 11
It doesn't work :(
 
Last edited:
Upvote 0

igodese

Member
Licensed User
#JordiCP: about your advice, I double checked my source file and...
I commented out the X and Y clip in the touch event, due to algorithm changes in my App and forgot to restore the instructions!

Just to avoid the same error in the future, I added the control directly in the function GetPixelColor:
B4X:
Sub GetPixelColor(Bitm As Bitmap, x As Int, y As Int) As Int
    Dim rval As Int
    Dim NativeMe As NativeObject
    Dim UIColor As Object
    If x < 0 Or y < 0 Or x > Bitm.Width-1 Or y > Bitm.Height-1 Then    Return 0 ' return black if invalid x,y
    NativeMe = Me
    UIColor = NativeMe.RunMethod("GetPixelColor:::", Array (Bitm,x,y))
    rval = NativeMe.UIColorToColor(UIColor)
    Return rval
End Sub
Now I'm going to test if the "strange" error fires again in release or debug mode. Thank you very much!

Edited: it seems to be OK!
 
Last edited:
Upvote 0
Top