Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Google Sign In with OpenID

CGImage pixel array

alfmasteralfmaster Posts: 15Registered Users
edited November 2009 in iPhone SDK Development
How can i get and work with pixel array of CGImage. Or help me with other way of editing bitmap image!
Post edited by alfmaster on

Replies

  • _sjc__sjc_ Posts: 226Registered Users
    edited November 2009
    You can get the address of the pixels with:
    CGDataProviderRef dataProvider = CGImageGetDataProvider(yourCGImage);
    CFDataRef imageData = CGDataProviderCopyData(dataProvider);
    void *pixels = CFDataGetBytePtr(imageData);
    
    (Because the CFDataRef came from a ...copy... call you're responsible for freeing it. The data provider you don't have to.)

    If you want to edit the bitmap by drawing into it, you need to create a graphics context. eg.
    CGContextRef context = CGBitmapContextCreate(
       pixels, // from above
       CGImageGetWidth(yourCGImage),
       CGImageGetHeight(yourCGImage),
       CGImageGetBitsPerComponent(yourCGImage),
       CGImageGetBytesPerRow(yourCGImage),
       CGColorSpaceCreateDeviceRGB(), // this leaks, so assign it to a var and then release it
       CGImageGetBitmapInfo(yourCGImage)
    );
    
    Draw into the image using any of the CGContext... commands, and release the context when you're done.
    <a href="http://www.jaml.co.uk/simcap.html" target="_blank">SimCap</a> - Simple iPhone <b>and iPad</b> Simulator screen capture
  • alfmasteralfmaster Posts: 15Registered Users
    edited November 2009
    _sjc_ wrote: »
    You can get the address of the pixels with:
    CGDataProviderRef dataProvider = CGImageGetDataProvider(yourCGImage);
    CFDataRef imageData = CGDataProviderCopyData(dataProvider);
    void *pixels = CFDataGetBytePtr(imageData);
    
    (Because the CFDataRef came from a ...copy... call you're responsible for freeing it. The data provider you don't have to.)

    If you want to edit the bitmap by drawing into it, you need to create a graphics context. eg.
    CGContextRef context = CGBitmapContextCreate(
       pixels, // from above
       CGImageGetWidth(yourCGImage),
       CGImageGetHeight(yourCGImage),
       CGImageGetBitsPerComponent(yourCGImage),
       CGImageGetBytesPerRow(yourCGImage),
       CGColorSpaceCreateDeviceRGB(), // this leaks, so assign it to a var and then release it
       CGImageGetBitmapInfo(yourCGImage)
    );
    
    Draw into the image using any of the CGContext... commands, and release the context when you're done.

    Thank you very much! But i have one more problem! How can i show my image on the screen of my device outside of draw rect method?
  • _sjc__sjc_ Posts: 226Registered Users
    edited November 2009
    alfmaster wrote: »
    Thank you very much! But i have one more problem! How can i show my image on the screen of my device outside of draw rect method?

    Well, you could create a UIImage from your CGImageRef and then add that to an image view in your UI:
    UIImage *image = [UIImage imageWithCGImage: yourCGImage];
    yourImageView.image = image;
    
    <a href="http://www.jaml.co.uk/simcap.html" target="_blank">SimCap</a> - Simple iPhone <b>and iPad</b> Simulator screen capture
  • alfmasteralfmaster Posts: 15Registered Users
    edited November 2009
    _sjc_ wrote: »
    Well, you could create a UIImage from your CGImageRef and then add that to an image view in your UI:
    UIImage *image = [UIImage imageWithCGImage: yourCGImage];
    yourImageView.image = image;
    

    Ok, but how can i than edit this image? for example, i want to put point on it in place, where user touched my picture?
  • _sjc__sjc_ Posts: 226Registered Users
    edited November 2009
    If you want to update the image data quickly and more than a couple of times (eg. in response to user interaction), then I'd say your best bet was to design a custom UIView subclass which holds your CGImageRef and an open graphics context. This will mean implementing drawRect to update the view whenever something changes.
    <a href="http://www.jaml.co.uk/simcap.html" target="_blank">SimCap</a> - Simple iPhone <b>and iPad</b> Simulator screen capture
  • alfmasteralfmaster Posts: 15Registered Users
    edited November 2009
    sorry for so many questions? but how can my UIView can hold an open graphics context?
  • _sjc__sjc_ Posts: 226Registered Users
    edited November 2009
    alfmaster wrote: »
    sorry for so many questions? but how can my UIView can hold an open graphics context?

    You design and create a new object which inherits from UIView and you give it a CGImageRef as a property, eg. in the .h
    @interface MyView : UIView {
        CGImageRef _theCGImage;
        CGContextRef _theContext;
    }
    
    // etc.
    
    @end
    
    Create an init method which takes the CGImageRef (along with a frame rectangle) and opens the contexts there.
    <a href="http://www.jaml.co.uk/simcap.html" target="_blank">SimCap</a> - Simple iPhone <b>and iPad</b> Simulator screen capture
  • alfmasteralfmaster Posts: 15Registered Users
    edited November 2009
    _sjc_ wrote: »
    You design and create a new object which inherits from UIView and you give it a CGImageRef as a property, eg. in the .h
    @interface MyView : UIView {
        CGImageRef _theCGImage;
        CGContextRef _theContext;
    }
    
    // etc.
    
    @end
    
    Create an init method which takes the CGImageRef (along with a frame rectangle) and opens the contexts there.

    Did like you said; Created context DrawingContext and showed it on the view. But, for example, next code doesn't show changes in view
    -(void) DrawRectangle:(CGRect)rect
    {
    	CGContextFillRect(DrawingContext, rect);
    	CGImageRef i = CGBitmapContextCreateImage(DrawingContext);
    	self.MainImage = [UIImage imageWithCGImage:i];
    	//CGImageRelease(i);
    	self.image = self.MainImage;
    
    }
    
    
  • alfmasteralfmaster Posts: 15Registered Users
    edited November 2009
    Lets return to pixel array! Can i get information about concrette pixel or edit it, for example - edit color?
  • fiftysixtyfiftysixty Posts: 310Registered Users
    edited November 2009
    alfmaster wrote: »
    Did like you said; Created context DrawingContext and showed it on the view. But, for example, next code doesn't show changes in view
    -(void) DrawRectangle:(CGRect)rect
    {
    	CGContextFillRect(DrawingContext, rect);
    	CGImageRef i = CGBitmapContextCreateImage(DrawingContext);
    	self.MainImage = [UIImage imageWithCGImage:i];
    	//CGImageRelease(i);
    	self.image = self.MainImage;
    
    }
    
    

    The name of the method should be drawRect, not DrawRectangle. Another things is that if your class inherits from UIView, and if you haven't added MainImage as a subview of your view, then you should draw the image to your UIView in drawRect. That can be done like this:
    - (void) drawRect:(CGRect)rect {
        // get the graphics context used for drawing on this view
        CGContextRef viewContext = UIGraphicsGetCurrentContext();
        CGContextDrawImage(viewContext, self.bounds, image);
    }
    

    About the pixel array, the pointer you get using the methods in the 2nd post points to the beginning of the pixel array, to the first byte. You're likely dealing with an RGBA8888 format image, which means that there is one byte for red, green, blue and alpha values. So, using the pointer you can access the color components of a pixel in the image with the following formula:

    pixel in coordinates x, y
    imageWidth is the width of the image, in pixels
    bytesPerPixel is the number of bytes used to store the pixel color components, in RGBA8888 format it is 4

    red_component(x,y) = pointer + (y*imageWidth + x)*bytesPerPixel
    green_component(x,y) = pointer + (y*imageWidth + x)*bytesPerPixel
    blue_component(x,y) = pointer + (y*imageWidth + x)*bytesPerPixel
    alpha_component(x,y) = pointer + (y*imageWidth + x)*bytesPerPixel

    These are pointers to a byte, using them you can manipulate the pixel values directly. I hope I didn't make mistakes, but if I did I apologize.
    <a href="http://www.fiftysixtysoftware.com" target="_blank">Fifty Sixty Software</a><br />
    <a href="http://www.fiftysixtysoftware.com/blog" target="_blank">iPhone development tips and tutorials</a><br />
    <br />
    <b>Apps in store:</b><br />
    <a href="htt
Sign In or Register to comment.