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
Please do not post the same thing multiple times. The board software automatically flags certain posts as needing moderator attention. This happens the most often for new users. I'm pretty sure this is made clear at the time you attempt to post. Posting the same thing over and over again just makes that many more posts the moderators have to weed through later. This makes us sad. Don't make us sad. If your post/thread doesn't appear, just wait a while. Don't post it again. If it hasn't shown up by the next day, then you can try again. I normally go through posts in the mornings, and try to check a few times throughout the day, but I'm not here 24/7. There will typically be a significant delay before posts are approved. Just be patient.

CGImage pixel array

alfmasteralfmaster Posts: 15Registered Users
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
    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.
    SimCap - Simple iPhone and iPad Simulator screen capture
  • alfmasteralfmaster Posts: 15Registered Users
    _sjc_;145562 said:
    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
    alfmaster;145717 said:
    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;
    SimCap - Simple iPhone and iPad Simulator screen capture
  • alfmasteralfmaster Posts: 15Registered Users
    _sjc_;145724 said:
    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
    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.
    SimCap - Simple iPhone and iPad Simulator screen capture
  • alfmasteralfmaster Posts: 15Registered Users
    sorry for so many questions? but how can my UIView can hold an open graphics context?
  • _sjc__sjc_ Posts: 226Registered Users
    alfmaster;145729 said:
    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.
    SimCap - Simple iPhone and iPad Simulator screen capture
  • alfmasteralfmaster Posts: 15Registered Users
    _sjc_;145738 said:
    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
    Lets return to pixel array! Can i get information about concrette pixel or edit it, for example - edit color?
  • fiftysixtyfiftysixty Posts: 310Registered Users
    alfmaster;145784 said:
    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.
Sign In or Register to comment.