Page 1 of 2
Using CGImageCreate to create an image in PureBasic
Posted: Sun May 03, 2015 2:04 pm
by TI-994A
This Objective-C code obtains some raw bitmap information from the given
data object, and then creates a
CGImage from it, which is then converted to an
NSImage:
Code: Select all
CGColorSpaceRef color = CGColorSpaceCreateDeviceGray();
if ([data pixelDataType] == ICScannerPixelDataTypeRGB) color = CGColorSpaceCreateDeviceRGB();
CGDataProviderRef provider = CGDataProviderCreateWithCFData(CFDataCreate(NULL, [[data dataBuffer] bytes], [data dataSize]));
CGImageRef image = CGImageCreate([data fullImageWidth], [data fullImageHeight], [data bitsPerComponent], [data bitsPerPixel],
[data bytesPerRow], color, kCGBitmapByteOrderDefault|kCGImageAlphaNone, provider, NULL, false, kCGRenderingIntentDefault);
NSImage *finImage = [[NSImage alloc] initWithCGImage:image size:NSMakeSize([data fullImageWidth], [data fullImageHeight])];
CGImageRelease(image);
CGDataProviderRelease(provider);
CGColorSpaceRelease(color);
As can be seen from the code, the
CGImage is created using the following properties, which looks somewhat similar to Windows' BITMAPINFOHEADER:
- dataSize
- dataBuffer
- bitsPerPixel
- bytesPerRow
- pixelDataType
- fullImageWidth
- fullImageHeight
- bitsPerComponent
There was a similar example by wilbert,
in this post, which created a PureBasic-usable image from an
NSImage which was created from a
CGImage, but in that example, the source image was returned from a screen capture function instead of being created from raw data.
Would it be possible to duplicate the above code in PureBasic, and to create a PureBasic-usable image from the raw data?
Or better still, would it be possible to use the raw data with PureBasic's native image functions to create an image?
Thanks in advance.

Re: Using CGImageCreate to create an image in PureBasic
Posted: Sun May 03, 2015 3:46 pm
by wilbert
What kind of raw data ?
Is it pixel data or something like tiff encoded ?
Re: Using CGImageCreate to create an image in PureBasic
Posted: Sun May 03, 2015 4:02 pm
by TI-994A
wilbert wrote:What kind of raw data ?
Is it pixel data or something like tiff encoded ?
Hi wilbert; thanks for your quick reply.
This is related to the scanner code that we were working on in the other thread. The raw image data is returned by the
didScanToBandData() method, and presumably it could be the format that was set under the
documentUTI property;
public.png as you had recommended in that example.
However, since this
didScanToBandData() method is only called when scanning in memory transfer mode, it might not comply with the
documentUTI property, which is used only in file transfer mode.
Couldn't it just be raw image data to be built upon the given properties?
(dataSize, dataBuffer, bitsPerPixel, bytesPerRow, pixelDataType, etc.) 
Re: Using CGImageCreate to create an image in PureBasic
Posted: Sun May 03, 2015 5:57 pm
by wilbert
I think you have two options.
One is to create a CGImage like the code from your first post and draw that onto a PB created image.
The other one is to decode the raw pixel data yourself.
Especially if you always use the same bit depth that shouldn't be overly complicated I think.
How do you select if the scan should be color or b/w and the bit depth (1, 8 or 16) ?
Re: Using CGImageCreate to create an image in PureBasic
Posted: Sun May 03, 2015 7:30 pm
by TI-994A
wilbert wrote:One is to create a CGImage like the code from your first post and draw that onto a PB created image.
Hi wilbert. Is it possible to convert that Objective-C
CGImageCreate code into PureBasic? The main point would be to obtain and display an image from the given
image data object.
wilbert wrote:The other one is to decode the raw pixel data yourself.
Especially if you always use the same bit depth that shouldn't be overly complicated I think.
How do you select if the scan should be color or b/w and the bit depth (1, 8 or 16) ?
The bit depths
(1, 8, 16 bits), and the pixel data types
(BW, Gray, RGB, Palette, CMY, CMYK, YUV, YUVK, CIEXYZ), are selectable/obtainable through the scanner unit properties.
Would these be required in order to build the image?
Re: Using CGImageCreate to create an image in PureBasic
Posted: Sun May 03, 2015 8:01 pm
by wilbert
TI-994A wrote:Is it possible to convert that Objective-C CGImageCreate code into PureBasic? The main point would be to obtain and display an image from the given image data object.
Yes, CGImageCreate can be used if you import the function using ImportC.
TI-994A wrote:Would these be required in order to build the image?
Only if you want to decode the dataBuffer yourself.
Re: Using CGImageCreate to create an image in PureBasic
Posted: Sun May 03, 2015 8:33 pm
by TI-994A
wilbert wrote:Yes, CGImageCreate can be used if you import the function using ImportC.
Trying to decode the raw data may be a little overkill for this simple requirement.
When importing these functions, could all the parameters be substituted with integers?
Code: Select all
CFDataCreate(allocator.i, bytes.i, length.i)
CGDataProviderCreateWithCFData(data.i)
CGImageCreate(width.i, height.i, bitsPerComponent.i, bitsPerPixel.i, bytesPerRow.i, colorspace.i, bitmapInfo.i, provider.i, decode.i, shouldInterpolate.i, intent.i)
There seems to be some unique data types, like
CGColorSpace!, CGBitmapInfo, CGDataProvider!, UnsafePointer<CGFloat>, and
CGColorRenderingIntent. 
Re: Using CGImageCreate to create an image in PureBasic
Posted: Mon May 04, 2015 7:08 am
by wilbert
I can't convert the whole thing since I can't test it (no recognized scanner) but here's something that might help you
Code: Select all
#kCGBitmapByteOrderDefault = 0
#kCGImageAlphaNone = 0
#kCGRenderingIntentDefault = 0
ImportC ""
CFDataCreate(allocator, *bytes, length)
CFRelease(cf)
CGColorSpaceCreateDeviceGray()
CGColorSpaceCreateDeviceRGB()
CGColorSpaceRelease(colorspace)
CGDataProviderCreateWithCFData(cfdata)
CGDataProviderRelease(provider)
CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, space, bitmapInfo, provider, *decode, shouldInterpolate, intent)
CGImageRelease(image)
EndImport
; create raw grayscale data
Dim GrayScaleData.a(99, 99)
RandomSeed(0)
RandomData(@GrayScaleData(), 100 * 100)
; create cgimage
color = CGColorSpaceCreateDeviceGray()
cfdata = CFDataCreate(#Null, @GrayScaleData(), 100 * 100)
provider = CGDataProviderCreateWithCFData(cfdata)
image = CGImageCreate(100, 100, 8, 8, 100, color, #kCGBitmapByteOrderDefault|#kCGImageAlphaNone, provider, #Null, #False, #kCGRenderingIntentDefault)
; create purebasic image
size.NSSize\width = 100
size\height = 100
nsimage = CocoaMessage(0, CocoaMessage(0, 0, "NSImage alloc"), "initWithCGImage:", image, "size:@", @size)
CreateImage(0, 100, 100)
StartDrawing(ImageOutput(0))
DrawImage(nsimage, 0, 0)
CocoaMessage(0, nsimage, "release")
StopDrawing()
; release some things
CGDataProviderRelease(provider)
CFRelease(cfdata)
CGColorSpaceRelease(color)
; show result
If OpenWindow(0, 0, 0, 100, 100, "Image test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ImageGadget(0, 0, 0, 100, 100, ImageID(0))
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Re: Using CGImageCreate to create an image in PureBasic
Posted: Mon May 04, 2015 5:20 pm
by TI-994A
wilbert wrote:Code: Select all
color = CGColorSpaceCreateDeviceGray()
cfdata = CFDataCreate(#Null, @GrayScaleData(), 100 * 100)
provider = CGDataProviderCreateWithCFData(cfdata)
image = CGImageCreate(100, 100, 8, 8, 100, color, #kCGBitmapByteOrderDefault|#kCGImageAlphaNone, provider, #Null, #False, #kCGRenderingIntentDefault)
Thanks wilbert! That's precisely what I was looking for.
It's funny how all those fancy NS object types can just be substituted with simple integer references.

Re: Using CGImageCreate to create an image in PureBasic
Posted: Fri Dec 23, 2016 11:07 am
by coder14
wilbert wrote:I can't convert the whole thing since I can't test it (no recognized scanner) but here's something that might help you
Code: Select all
#kCGBitmapByteOrderDefault = 0
#kCGImageAlphaNone = 0
#kCGRenderingIntentDefault = 0
ImportC ""
CFDataCreate(allocator, *bytes, length)
CFRelease(cf)
CGColorSpaceCreateDeviceGray()
CGColorSpaceCreateDeviceRGB()
CGColorSpaceRelease(colorspace)
CGDataProviderCreateWithCFData(cfdata)
CGDataProviderRelease(provider)
CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, space, bitmapInfo, provider, *decode, shouldInterpolate, intent)
CGImageRelease(image)
EndImport
; create raw grayscale data
Dim GrayScaleData.a(99, 99)
RandomSeed(0)
RandomData(@GrayScaleData(), 100 * 100)
; create cgimage
color = CGColorSpaceCreateDeviceGray()
cfdata = CFDataCreate(#Null, @GrayScaleData(), 100 * 100)
provider = CGDataProviderCreateWithCFData(cfdata)
image = CGImageCreate(100, 100, 8, 8, 100, color, #kCGBitmapByteOrderDefault|#kCGImageAlphaNone, provider, #Null, #False, #kCGRenderingIntentDefault)
; create purebasic image
size.NSSize\width = 100
size\height = 100
nsimage = CocoaMessage(0, CocoaMessage(0, 0, "NSImage alloc"), "initWithCGImage:", image, "size:@", @size)
CreateImage(0, 100, 100)
StartDrawing(ImageOutput(0))
DrawImage(nsimage, 0, 0)
CocoaMessage(0, nsimage, "release")
StopDrawing()
; release some things
CGDataProviderRelease(provider)
CFRelease(cfdata)
CGColorSpaceRelease(color)
; show result
If OpenWindow(0, 0, 0, 100, 100, "Image test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ImageGadget(0, 0, 0, 100, 100, ImageID(0))
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Hi wilbert. Do you know why this is not working on newer versions of PB? It works on 5.1 and 5.2 but not on 5.4 and above?
Thanks!
Re: Using CGImageCreate to create an image in PureBasic
Posted: Fri Dec 23, 2016 11:39 am
by wilbert
coder14 wrote:Do you know why this is not working on newer versions of PB? It works on 5.1 and 5.2 but not on 5.4 and above?
I don't know why it isn't working.
For some reason drawing the image using the vector library does seem to work.
Code: Select all
nsimage = CocoaMessage(0, CocoaMessage(0, 0, "NSImage alloc"), "initWithCGImage:", image, "size:@", @size)
CreateImage(0, 100, 100)
StartVectorDrawing(ImageVectorOutput(0))
DrawVectorImage(nsimage)
CocoaMessage(0, nsimage, "release")
StopVectorDrawing()
Re: Using CGImageCreate to create an image in PureBasic
Posted: Fri Dec 23, 2016 12:01 pm
by coder14
wilbert wrote:coder14 wrote:Do you know why this is not working on newer versions of PB? It works on 5.1 and 5.2 but not on 5.4 and above?
I don't know why it isn't working.
For some reason drawing the image using the vector library does seem to work.
Code: Select all
nsimage = CocoaMessage(0, CocoaMessage(0, 0, "NSImage alloc"), "initWithCGImage:", image, "size:@", @size)
CreateImage(0, 100, 100)
StartVectorDrawing(ImageVectorOutput(0))
DrawVectorImage(nsimage)
CocoaMessage(0, nsimage, "release")
StopVectorDrawing()
That works! Thank you wilbert!
Getting weary weeding out this stuff. But some of the new stuff is great too!

Re: Using CGImageCreate to create an image in PureBasic
Posted: Fri Dec 23, 2016 8:22 pm
by wilbert
coder14 wrote:That works! Thank you wilbert!

This alternative might also work
Code: Select all
#kCGBitmapByteOrderDefault = 0
#kCGImageAlphaNone = 0
#kCGRenderingIntentDefault = 0
ImportC ""
CFDataCreate(allocator, *bytes, length)
CFRelease(cf)
CGColorSpaceCreateDeviceGray()
CGColorSpaceCreateDeviceRGB()
CGColorSpaceRelease(colorspace)
CGDataProviderCreateWithCFData(cfdata)
CGDataProviderRelease(provider)
CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, space, bitmapInfo, provider, *decode, shouldInterpolate, intent)
CGImageRelease(image)
EndImport
; create raw grayscale data
Dim GrayScaleData.a(99, 99)
RandomSeed(0)
RandomData(@GrayScaleData(), 100 * 100)
; create cgimage
color = CGColorSpaceCreateDeviceGray()
cfdata = CFDataCreate(#Null, @GrayScaleData(), 100 * 100)
provider = CGDataProviderCreateWithCFData(cfdata)
image = CGImageCreate(100, 100, 8, 8, 100, color, #kCGBitmapByteOrderDefault|#kCGImageAlphaNone, provider, #Null, #False, #kCGRenderingIntentDefault)
; create purebasic image
rect.NSRect\size\width = 100
rect\size\height = 100
nsimage = CocoaMessage(0, CocoaMessage(0, 0, "NSImage alloc"), "initWithCGImage:", image, "size:@", @rect\size)
CreateImage(0, 100, 100)
StartDrawing(ImageOutput(0))
CocoaMessage(0, nsimage, "drawInRect:@", @rect)
CocoaMessage(0, nsimage, "release")
StopDrawing()
; release some things
CGDataProviderRelease(provider)
CFRelease(cfdata)
CGColorSpaceRelease(color)
; show result
If OpenWindow(0, 0, 0, 100, 100, "Image test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ImageGadget(0, 0, 0, 100, 100, ImageID(0))
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
It uses
CocoaMessage(0, nsimage, "drawInRect:@", @rect) to draw the image.
Re: Using CGImageCreate to create an image in PureBasic
Posted: Sat Dec 24, 2016 3:34 am
by coder14
wilbert wrote:It uses CocoaMessage(0, nsimage, "drawInRect:@", @rect) to draw the image.
This does not work on 10.7 but works on 10.11. I get an error that the object does not support drawInRect.
Anyway I am happy that vector drawing works. Any "drawbacks" for using it?

Re: Using CGImageCreate to create an image in PureBasic
Posted: Sat Dec 24, 2016 6:10 am
by wilbert
coder14 wrote:Anyway I am happy that vector drawing works. Any "drawbacks" for using it?

Not that I know of.
