Can I edit the pixels of the UIImage's property CGImage

前端 未结 7 1408
野趣味
野趣味 2020-11-28 05:04

UIImage has a read-only property CGImage. I have to read its pixels to a memory block and edit them and then make a new UIImage to replace the old one. I want to know if th

相关标签:
7条回答
  • 2020-11-28 05:11

    The short answer is no. However, you say you have to make a copy anyhow, so why not just get an NSData object and manipulate its bytes.

    From the Apple docs on UIImage:

    Because image objects are immutable, they also do not provide direct access to their underlying image data. However, you can get an NSData object containing either a PNG or JPEG representation of the image data using the UIImagePNGRepresentation and UIImageJPEGRepresentation functions.

    To get the data as a PNG, use:

    NSData * UIImagePNGRepresentation (
       UIImage *image
    );
    

    for JPEG, use:

    NSData * UIImageJPEGRepresentation (
       UIImage *image,
       CGFloat compressionQuality
    );
    
    0 讨论(0)
  • 2020-11-28 05:12

    You cannot get at the original pixels. However, you can get a copy. One option is to do what Matt suggested, and convert it into a PNG/JPG - though remember, the image is now compressed, and you will be manipulating the compressed file and not the pixels directly.

    If you want to get at a copy of the raw pixels, you can do something like:

    UIImage* image = ...; // An image
    NSData* pixelData = (NSData*) CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
    void* pixelBytes = [pixelData bytes];
    
    // Take away the red pixel, assuming 32-bit RGBA
    for(int i = 0; i < [pixelData length]; i += 4) {
        bytes[i] = 0; // red
        bytes[i+1] = bytes[i+1]; // green
        bytes[i+2] = bytes[i+2]; // blue
        bytes[i+3] = bytes[i+3]; // alpha
    }
    

    Now, if you wanted to make this into a new UIImage, you can do something like:

    NSData* newPixelData = [NSData dataWithBytes:pixelBytes length:[pixelData length]];
    UIImage* newImage = [UIImage imageWithData:newPixelData]; // Huzzah
    
    0 讨论(0)
  • 2020-11-28 05:12

    I used the following code to add 2 thin red lines at right and left of an image

    -(UIImage*)ModifyImage:(UIImage*) img
    {
        UIGraphicsBeginImageContext(img.size);
    
        [img drawInRect:CGRectMake(0,0,img.size.width,img.size.height) blendMode:kCGBlendModeSourceOut alpha:1.0f];
    
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        int w =img.size.width;
        int cw,ch;
    
        cw = img.size.width / 35;
        ch = img.size.height / 35;
    
        unsigned char* data = CGBitmapContextGetData (ctx);
    
        for(int y = 0 ; y < img.size.height ; y++)
        {
            for(int x = 0 ; x < img.size.width ; x++)
            {
                //int offset = 4*((w * y) + x);
    
                int offset = (CGBitmapContextGetBytesPerRow(ctx)*y) + (4 * x);
    
                int blue    =  data[offset];
                int green   = data[offset+1];
                int red     = data[offset+2];
                //int alpha   = data[offset+3];
    
                if(x <= (cw * 2) || x >= (cw * 35))
                {
                    data[offset]    = 0;
                    data[offset+1]  = 0;
                    data[offset+2]  = 255;
                    data[offset+3]  = 255;
                }
            }
        }
    
        UIImage *rtimg = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return rtimg;
    }
    
    0 讨论(0)
  • 2020-11-28 05:13

    For the more obtuse among us (read: future me) here's some working code based on Itay and Dave R's answers. It starts with a UIImage and ends with a modified UIImage:

        // load image
        UIImage *image      = [UIImage imageNamed:@"test.png"];
        CGImageRef imageRef = image.CGImage;
        NSData *data        = (NSData *)CGDataProviderCopyData(CGImageGetDataProvider(imageRef));
        char *pixels        = (char *)[data bytes];
    
        // this is where you manipulate the individual pixels
        // assumes a 4 byte pixel consisting of rgb and alpha
        // for PNGs without transparency use i+=3 and remove int a
        for(int i = 0; i < [data length]; i += 4)
        {
            int r = i;
            int g = i+1;
            int b = i+2;
            int a = i+3;
    
            pixels[r]   = 0; // eg. remove red
            pixels[g]   = pixels[g];
            pixels[b]   = pixels[b];
            pixels[a]   = pixels[a];
        }
    
        // create a new image from the modified pixel data
        size_t width                    = CGImageGetWidth(imageRef);
        size_t height                   = CGImageGetHeight(imageRef);
        size_t bitsPerComponent         = CGImageGetBitsPerComponent(imageRef);
        size_t bitsPerPixel             = CGImageGetBitsPerPixel(imageRef);
        size_t bytesPerRow              = CGImageGetBytesPerRow(imageRef);
    
        CGColorSpaceRef colorspace      = CGColorSpaceCreateDeviceRGB();
        CGBitmapInfo bitmapInfo         = CGImageGetBitmapInfo(imageRef);
        CGDataProviderRef provider      = CGDataProviderCreateWithData(NULL, pixels, [data length], NULL);
    
        CGImageRef newImageRef = CGImageCreate (
                                  width,
                                  height,
                                  bitsPerComponent,
                                  bitsPerPixel,
                                  bytesPerRow,
                                  colorspace,
                                  bitmapInfo,
                                  provider,
                                  NULL,
                                  false,
                                  kCGRenderingIntentDefault
                                  );
        // the modified image
        UIImage *newImage   = [UIImage imageWithCGImage:newImageRef];
    
        // cleanup
        free(pixels);
        CGImageRelease(imageRef);
        CGColorSpaceRelease(colorspace);
        CGDataProviderRelease(provider);
        CGImageRelease(newImageRef);
    
    0 讨论(0)
  • 2020-11-28 05:21

    @shaun Inman's post has been the only working i've found on the web so far! THANK YOU! However it seems like at least in IOS3 the PNG colors are saved a bit different to what you stated, this is what worked for me (only for PNG!):

    for(int i = 0; i < [data length]; i += 4) {
        pixels[i+0]   = 0; // eg. alpha?
        pixels[i+1]   = 0; // eg. red!
        pixels[i+2]   = 0; // eg. green!
        pixels[i+3]   = pixels[i+3]; // eg. blue!
    }
    

    Would be cool if someone could figure out a way that worked for any filetype!

    0 讨论(0)
  • 2020-11-28 05:24

    This may help you out.

    When you're done, you can use CGImageCreate to create a CGImageRef, then use +[UIImage imageWithCGImage:] to create a new UIImage.

    0 讨论(0)
提交回复
热议问题