我可以编辑UIImage属性CGImage的像素

Yan*_*Xie 13 iphone cocoa cocoa-touch core-graphics uikit

UIImage有一个只读属性CGImage.我必须将其像素读取到内存块并编辑它们,然后创建一个新的UIImage来替换旧的UIImage.我想知道是否有办法绕过只读属性并直接编辑这些像素.

谢谢.


谢谢大家.我找到了一种方法.用这些方法写一个类:

-(void)preProcess:(UIImage*)srcImage {
    m_Context = ...// Created by calling CGBitmapContextCreate(...)
    ...
    CGContextDrawImage(m_Context, rect, srcImage.CGImage);
    m_Bits = (unsigned char*)CGBitmapContextGetData (mContext);
}

-(void)postProcess {
    CGContextRelease(m_Context);
    free(m_Bits);
}

-(UIImage*)doProcess:(CGPoint)pt {// just a example 
    unsigned char* ppxl = m_Bits + ...
    // do something...
    CGImageRef imRef = CGBitmapContextCreateImage(mContext);
    return [UIImage imageWithCGImage:imRef];
}
Run Code Online (Sandbox Code Playgroud)

preProcess和postProcess只调用一次.

Ita*_*tay 14

你无法获得原始像素.但是,您可以获得一份副本.一个选项是做Matt建议的,并将其转换为PNG/JPG - 但请记住,图像现在已经压缩,您将直接操作压缩文件而不是像素.

如果您想获得原始像素的副本,可以执行以下操作:

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
}
Run Code Online (Sandbox Code Playgroud)

现在,如果你想把它变成一个新的UIImage,你可以这样做:

NSData* newPixelData = [NSData dataWithBytes:pixelBytes length:[pixelData length]];
UIImage* newImage = [UIImage imageWithData:newPixelData]; // Huzzah
Run Code Online (Sandbox Code Playgroud)

  • 我试过但失败了.CGDataProviderCopyData返回CFDataRef,它是根据iPhone doc对不可变CFData对象的引用. (2认同)

Sha*_*man 14

对于我们中间更加迟钝(阅读:未来我),这里有一些基于Itay和Dave R答案的工作代码.它以UIImage开头,以修改后的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);
Run Code Online (Sandbox Code Playgroud)

  • 此示例假定您正在使用具有透明度的png.如果你没有使用透明度,将for循环中的`i + = 4`更改为`i + = 3`(我确信有一种更智能的方法来确定像素大小,但图形编程不是我的强项). (3认同)

Dav*_*e R 6

可能会帮到你.

完成后,您可以使用CGImageCreate创建CGImageRef,然后用于+[UIImage imageWithCGImage:]创建新的UIImage.