iOS Question Store the previewdata Camera in an Array

joop

Active Member
Licensed User
Longtime User
Hi,
I have an B4A app that uses this routine to get the preview data.
Because I am only interested in the Y data from the YUV format
So with this code I get the Y data from the screensize used.

B4X:
Sub Camera1_Preview (PreviewPic() As Byte)
For i=0 To ((CamEx.PreviewHeight * CamEx.PreviewWidth)-1)
    frames_array(i) = Unsigned(PreviewPic(i))
Next
End Sub

This works great and I spend a lot of time to get this and my app right.

Now I want to step to step convert this to IOS but this
important subroutine Camera1_Preview seems very different for me in IOS

B4X:
Private Sub cam_Preview (Image As Bitmap)
Dim out As OutputStream
out.InitializeToBytesArray(0)
Image.WriteToStream(out, 100, "JPEG")
cam.ReleaseFrame(Image) '<--- very important. New frames will not arrive without this call
End Sub

I have some questions:

1.is it possible to use YUV as in B4a or possible as shown in this link:
http://stackoverflow.com/questions/...deo-from-the-camera-display-it-and-process-it

2.Is the bitmap not compressed if ? so how do I get this in an array.?
What is the format of the bitmap .
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
You can convert the bitmap to an array with this code:
B4X:
Dim d() As Byte = no.NSDataToArray(no.RunMethod("BitmapToArray:", Array(Image)))
...
#if objc
- (NSData*)BitmapToArray:(UIImage*) bmp {
   CGDataProviderRef provider = CGImageGetDataProvider(bmp.CGImage);
   NSData* data = (id)CFBridgingRelease(CGDataProviderCopyData(provider));
   return data;
}
#end if
You can see the structure of this array in this code: https://www.b4x.com/android/forum/threads/getpixelcolor.56922/
 
Upvote 0

joop

Active Member
Licensed User
Longtime User
B4X:
Sub llc_Preview (Image As Bitmap)
    If DateTime.Now > lastPreviewSaved + IntervalMs Then
      lastPreviewSaved = DateTime.Now
      Dim no As NativeObject =Image
      Dim d() As Byte = no.NSDataToArray(no.RunMethod("BitmapToArray:", Array(Image))) ' line 139 with error
      Log (d.Length)
    End If
    llc.ReleaseFrame(Image) '<--- very important. New frames will not arrive without this call
End Sub


#if OBJC
- (NSData*)BitmapToArray:(UIImage*) bmp {
   CGDataProviderRef provider = CGImageGetDataProvider(bmp.CGImage);
   NSData* data = (id)CFBridgingRelease(CGDataProviderCopyData(provider));
   return data;
}
#end if

Raises this error ,
Error occurred on line: 139 (Main)
Method not found: BitmapToArray:, target: <UIImage: 0x14d895d0>, {1080, 1920}

Don't now if Dim no As NativeObject = Image is right
 
Upvote 0

joop

Active Member
Licensed User
Longtime User
Yes, that works Erel I am getting 8355840 as length , wich should be right for rgba.

Is it also possible to convert the array to a bitmap again with some objective c code.?
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
B4X:
Dim bmp As Bitmap = LoadBitmap(File.DirAssets, "smiley.png")
ImageView1.Bitmap = bmp
Dim no As NativeObject = Me
Dim d() As Byte = no.NSDataToArray(no.RunMethod("BitmapToArray:", Array(bmp)))
ImageView2.Bitmap = no.RunMethod("ArrayToBitmap:::", Array(no.ArrayToNSData(d), bmp.Width, bmp.Height))

#if objc
- (NSData*)BitmapToArray:(UIImage*) bmp {
   CGDataProviderRef provider = CGImageGetDataProvider(bmp.CGImage);
   NSData* data = (id)CFBridgingRelease(CGDataProviderCopyData(provider));
   return data;
}
- (UIImage*)ArrayToBitmap:(NSData*)data :(int)width :(int)height {

   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
   CGContextRef bitmapContext = CGBitmapContextCreate(
       data.bytes,
    width,
    height,
    8,
    4*width,
    colorSpace,
    kCGImageAlphaNoneSkipLast);

   CFRelease(colorSpace);
   CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext);
   return [UIImage imageWithCGImage:cgImage];
}

Seems like it losses the alpha channel during the conversion.
 
Upvote 0

joop

Active Member
Licensed User
Longtime User
I've got an -[UIImage object]: unrecognized selector sent to instance 0x15586d30 error
on the last line: is imageview2 correct initialized ?

B4X:
Sub test_bitmap
  Dim bmp As Bitmap = LoadBitmap(File.DirAssets, "smiley.png")
  Dim ImageView2 As ImageView
  ImageView2.Initialize("")
  ImageView1.Bitmap = bmp
  Dim no As NativeObject = Me
  Dim d() As Byte = no.NSDataToArray(no.RunMethod("BitmapToArray:", Array(bmp)))
  ImageView2.Bitmap = no.RunMethod("ArrayToBitmap:::", Array(no.ArrayToNSData(d), bmp.Width, bmp.Height))
End Sub
 
Upvote 0

joop

Active Member
Licensed User
Longtime User
Interesting , I test it on my iphone 5s with 9.2.1 (13D15)

- I set iphone out en on again (to be sure)

and this error dump :

Application_Start
0
500
2
Application_Active
Image W/H = 1080 1920
8355840
Error occurred on line: 146 (Main)
-[UIImage object]: unrecognized selector sent to instance 0x14da2090
Stack Trace: (
CoreFoundation <redacted> + 150
libobjc.A.dylib objc_exception_throw + 38
CoreFoundation <redacted> + 0
CoreFoundation <redacted> + 702
CoreFoundation _CF_forwarding_prep_0 + 24
B4i Example -[B4IImageViewWrapper setBitmap:] + 112
B4i Example -[b4i_main _test_bitmap] + 2778
B4i Example -[b4i_main _llc_preview:] + 3104
CoreFoundation <redacted> + 68
CoreFoundation <redacted> + 292
B4i Example +[B4I runDynamicMethod:method:throwErrorIfMissing:args:] + 1786
B4i Example -[B4IShell runMethod:] + 574
B4i Example -[B4IShell raiseEventImpl:method:args::] + 1998
B4i Example -[B4IShellBI raiseEvent:event:params:] + 1442
B4i Example __50-[B4I raiseEventFromDifferentThread:event:params:]_block_invoke + 74
libdispatch.dylib <redacted> + 10
libdispatch.dylib <redacted> + 22
libdispatch.dylib _dispatch_main_queue_callback_4CF + 1532
CoreFoundation <redacted> + 8
CoreFoundation <redacted> + 1590
CoreFoundation CFRunLoopRunSpecific + 516
CoreFoundation CFRunLoopRunInMode + 108
GraphicsServices GSEventRunModal + 160
UIKit UIApplicationMain + 144
B4i Example main + 108
libdyld.dylib <redacted> + 2
)

What do they mean with selector ?
 
Upvote 0

joop

Active Member
Licensed User
Longtime User
output is :
<UIImage: 0x1768ee50>, {180, 180}
UIImage

yes, I am using the hosted builder
B4I 2.31
 
Upvote 0

joop

Active Member
Licensed User
Longtime User
If I put the preview bitmap from the camera in an array and then back
from the array in a Imageview.bitmap the program ends suddenly after
131 llcam_Preview (ImageAsBitmap) events.
No error is given ,can this be an out of memory error.?

Preset Image bitmap W/H = 1920 1080

See the code


B4X:
Sub llcam_Preview (Image As Bitmap)
   If DateTime.Now > lastPreviewSaved + IntervalMs Then
     lastPreviewSaved = DateTime.Now
     Log("Image bitmap W/H = " & Image.Width & " " & Image.Height )
     Dim no As NativeObject = Me
     Dim d() As Byte = no.NSDataToArray(no.RunMethod("BitmapToArray:", Array(Image)))
     Log (d.Length)
     ImageView2.Bitmap = no.RunMethod("ArrayToBitmap:::", Array(no.ArrayToNSData(d), Image.Width, Image.Height))
     Log("View2 bitmap W/H = " & ImageView2.bitmap.Width & " " & ImageView2.bitmap.Height )
     Log ("Counter " & count ) :count = count +1
  End If


   llcam.ReleaseFrame(Image) '<--- very important. New frames will not arrive without this call

End Sub
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Try it with this code:
B4X:
#if objc
- (NSData*)BitmapToArray:(UIImage*) bmp {
  CGDataProviderRef provider = CGImageGetDataProvider(bmp.CGImage);
  NSData* data = (id)CFBridgingRelease(CGDataProviderCopyData(provider));
  return data;
}
- (UIImage*)ArrayToBitmap:(NSData*)data :(int)width :(int)height {

  CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  CGContextRef bitmapContext = CGBitmapContextCreate(
  data.bytes,
  width,
  height,
  8,
  4*width,
  colorSpace,
  kCGImageAlphaNoneSkipLast);

  CFRelease(colorSpace);
  CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext);
  CGContextRelease(bitmapContext);
  UIImage* img = [UIImage imageWithCGImage:cgImage];
  CGImageRelease(cgImage);
  return img;
}
 
Upvote 0

joop

Active Member
Licensed User
Longtime User
Yes , this is right ,it stays ok now after 2500 events, and the length of the array is also right.
Thanks.
 
Upvote 0
Top