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 .
 

joop

Active Member
Licensed User
Longtime User
So I am trying to figure out objective C in B4I


This will not work , and I dont know why , it should give back an array
filled with 55,Is the objective C code right ?

The input Image is from the llcam_Preview (Image As Bitmap) event
B4X:
Dim PreviewPic () As Byte = no.NSDataToArray(no.RunMethod("BitmapToArray:", Array(Image)))

B4X:
#if objc
- (NSData*)BitmapToArray:(UIImage*) bmp {
  CGDataProviderRef provider = CGImageGetDataProvider(bmp.CGImage);
  NSData* data = (id)CFBridgingRelease(CGDataProviderCopyData(provider));
  const uint8_t* bytes = [data bytes];
    for(int i = 0; i < [data length]; i += 1)
    {
     bytes[i]   = 55;    ' this line gives the error
     }
  return data;
#End If
}
 
Upvote 0

joop

Active Member
Licensed User
Longtime User
Well I tried it in B4i ,like this.
B4X:
Sub llcam_Preview (Image As Bitmap)
    If DateTime.Now > lastPreviewSaved + interval_frm Then
      lastPreviewSaved = DateTime.Now   
      If frame = 0 Then Log("Image bitmap W/H = " & Image.Width & " " & Image.Height )   

      Dim no As NativeObject = Me
      Dim PreviewPic () As Byte = no.NSDataToArray(no.RunMethod("BitmapToArray:", Array(Image)))
     'Previewpic array is now loaded with array
  
    'let change a byte in this array
     PreviewPic(255) = 55
    'no can't do this no error is given ?  can only be read ?
    
    End If
    llcam.ReleaseFrame(Image)
End Sub


PreviewPic Array can only be read ?
 
Upvote 0

joop

Active Member
Licensed User
Longtime User
Image bitmap W/H = 352 288 (x4)
PreviewPic.Length 405504

Image bitmap W/H = 1920 1080 (x4)
PreviewPic.Length 8294400

seems oke, but I cant write to it
 
Upvote 0

JackKirk

Well-Known 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;
}
A little tip that might save someone some hours of frustration.

If you are mucking around with bitmaps with an alpha channel - in my case parts of the bitmap are transparent - then you need to change:

kCGImageAlphaNoneSkipLast

to:

kCGImageAlphaPremultipliedLast

otherwise you will get transparent bits turning out black.
 
Upvote 0
Top