5

I am trying to create a new Image from raw data in unsigned char *. I have the bits per pixel from the data stored. I tried converting raw data into NSData, But result image was nil,

unsigned char *bitmap = myData;

NSUInteger myImageDataLength = strlen( (const char*)bitmap);

NSData *d = [NSData dataWithBytes:bitmap length:myImageDataLength];

imgView.image = [UIImage imageWithData:d];

Then I tried using context to create an image as follows:

CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
int width = mWidth;
int height = mHeight;
size_t bpp = mBpp;
size_t bpc = 8;
size_t bpr = (width * 4);
CGContextRef context = CGBitmapContextCreate(bitmap, width, height, 8, bpr, colorspace, kCGImageAlphaNone);
CGImageRef cgImage = nil;
if (context != nil) {
    cgImage = CGBitmapContextCreateImage (context);
    CGContextRelease(context);
}
CGColorSpaceRelease(colorspace);
UIImage *newImage = [UIImage imageWithCGImage:cgImage];

I am getting an error message like <Error>: CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 24 bits/pixel; 3-component color space; kCGImageAlphaNone; 64 bytes/row.

I tried solving it by setting many values but cant find any result. I googled on internet to find this solution but all others are creating an image from existing images so they get the values of bits per components and all that... How can I create image from this data???

Original Image:

enter image description here

Resulting image:

enter image description here

Resulting image should be warped. (Warped same as fatBooth and other application)

Community
  • 1
  • 1
DivineDesert
  • 6,924
  • 1
  • 29
  • 61
  • Which image format do you have the data in? – Chaitanya Gupta Aug 29 '11 at 04:27
  • 1
    Why are you computing the length of your bitmap data with `strlen()`? It will stop when it sees a null character. Aren't you storing your png image in a binary format? – Chaitanya Gupta Aug 29 '11 at 04:41
  • No... Actually unsigned char * comes after some manipulations. I dont know what is the size, So I calculated like this. Can u suggest any other way??? Data is not coming from any pre created image. I want to create an UIImage from this data. – DivineDesert Aug 29 '11 at 04:44
  • 1
    Typically, in C, most array operations pass the array length alongwith a pointer to the first element of the array. If you don't have it, maybe you will need to parse the PNG data to compuate the length -- http://en.wikipedia.org/wiki/Portable_Network_Graphics#Technical_details – Chaitanya Gupta Aug 29 '11 at 05:17
  • Well you have the same problem in bitmap -- binary format, so you can't use strlen() to get the length. You will have to either get the length from somewhere else or go through the bitmap headers to determine the length. – Chaitanya Gupta Aug 29 '11 at 05:35
  • Can you suggest How to get this length.. I am bit confused now...! – DivineDesert Aug 29 '11 at 05:36
  • I am sorry I don't understand the bitmap format. You will have to read it on your own. How do you get your image data in the first place? – Chaitanya Gupta Aug 29 '11 at 05:39
  • Means??? The image data is from a C library... – DivineDesert Aug 29 '11 at 05:42
  • Can you be more specific about the image format? There isn't any graphics format called "bitmap". Do you mean Windows BMP? Or do you have the raw pixel data in your char array? If yes, where is the remaining data such as image width and height? – Codo Aug 29 '11 at 05:50
  • I dont know much about image manipulation. It not windows BMP. I was considering the type of files as image formats. If I am wrong then clarify me plz. I can say it is raw pixel data. Image width and height is coming from a class which creates this image. I also get bytes per pixel from that call, and also the scanWidth... – DivineDesert Aug 29 '11 at 05:56
  • Since this seems to be an artifical image (as opposed to a photo), can you also post how the image should look like? And it seems the image has been scaled. It would be better to show the images in full resolution (possibly only the top part). – Codo Aug 29 '11 at 09:17
  • This application is working cool in .net – DivineDesert Aug 29 '11 at 09:22
  • 1
    The image is very far from what it's supposed to look. Most likley bytesPerPixel is wrong. Try to change from 3 to 4 or vice versa. But even then: are you sure the raw pixel data contains a valid image? Have you tried to display the original image without the warping? – Codo Aug 29 '11 at 09:48
  • @Codo let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/2949/discussion-between-dimple-panchal-and-codo) – DivineDesert Aug 29 '11 at 10:00
  • Hey, my original image is also creating problem.. Check out the discussion link.. plz.. – DivineDesert Aug 29 '11 at 10:10
  • I changes Bpp and original Image is now working fine – DivineDesert Aug 29 '11 at 10:13

2 Answers2

6

The following code creates a UIImage instance from raw pixel data assuming you have:

  • pixelData: the raw pixel data
  • imageWidth, imageHeight: the image dimensions
  • scanWidth: the number of bytes per scanline
  • bytesPerPixel: the number of bytes used per pixel, usually 4

The resulting UIImage is assigned to the variable uiImage.

CGDataProviderRef provider = CGDataProviderCreateWithData(
    NULL, 
    pixelData, 
    imageHeight * scanWidth, 
    NULL);

CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

CGImageRef imageRef = CGImageCreate(imageWidth,
    imageHeight,
    8,
    bytesPerPixel * 8,
    scanWidth,
    colorSpaceRef,
    bitmapInfo,
    provider,
    NULL,
    NO,
    renderingIntent);

UIImage *uiImage = [UIImage imageWithCGImage:imageRef];
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpaceRef);
CGImageRelease(imageRef);
Codo
  • 75,595
  • 17
  • 168
  • 206
  • For those of you using the newfangled Swift, here's a translated and slightly modified version: https://gist.github.com/irskep/e560be65163efcb04115 – Steve Landey Dec 05 '14 at 03:13
  • Should we also release `provider`? [Docs](https://developer.apple.com/documentation/coregraphics/1408288-cgdataprovidercreatewithdata) on `CGDataProviderCreateWithData()` say: `You are responsible for releasing this object using CGDataProviderRelease.` – Alexander Abakumov Mar 12 '18 at 16:22
  • Yes, indeed. That was missing. I've added it to the code. – Codo Mar 12 '18 at 22:35
0

Try This :-

CGRect screenBounds = [[UIScreen mainScreen] bounds];
GLuint *buffer;
//point the buffer to memory location code that here accordingly
int backingWidth = screenBounds.size.width;
int backingHeight =screenBounds.size.height;    
NSInteger myDataLength = backingWidth * backingHeight * 4;


CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, myDataLength, releaseScreenshotData);
const int bitsPerComponent = 8;
const int bitsPerPixel = 4 * bitsPerComponent;
const int bytesPerRow = 4 * backingWidth;

CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef imageRef = CGImageCreate(backingWidth,backingHeight, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
CGColorSpaceRelease(colorSpaceRef);
CGDataProviderRelease(provider);

 UIImage *myImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
 [uiimageviewobject setImage:myImage];
 [self addSubview:uiimageviewobject];
Tornado
  • 1,069
  • 12
  • 28