Iphone 我可以编辑UIImage';CGS属性图像

Iphone 我可以编辑UIImage';CGS属性图像,iphone,cocoa,cocoa-touch,uikit,core-graphics,Iphone,Cocoa,Cocoa Touch,Uikit,Core Graphics,UIImage具有只读属性CGImage。我必须把它的像素读入内存块并编辑它们,然后制作一个新的UIImage来替换旧的UIImage。我想知道是否有办法绕过只读属性直接编辑这些像素 谢谢 谢谢大家。我找到了一个办法。使用以下方法编写一个类: -(void)preProcess:(UIImage*)srcImage { m_Context = ...// Created by calling CGBitmapContextCreate(...) ... CGContex

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];
}

预处理和后处理只调用一次。

简短的回答是否定的。但是,你说你无论如何都必须复制一个副本,那么为什么不直接获取一个NSData对象并操纵它的字节呢

从UIImage上的Apple文档:

因为图像对象是不可变的, 它们也不提供直接访问 它们的底层图像数据。 但是,您可以获得NSData对象 包含PNG或JPEG格式 使用 UIImagePNGRE演示文稿和 UIImageJPEG表示函数

要获取PNG格式的数据,请使用:

NSData * UIImagePNGRepresentation (
   UIImage *image
);
对于JPEG,请使用:

NSData * UIImageJPEGRepresentation (
   UIImage *image,
   CGFloat compressionQuality
);

无法获取原始像素。但是,你可以得到一份副本。一个选择是按照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
}
NSData* newPixelData = [NSData dataWithBytes:pixelBytes length:[pixelData length]];
UIImage* newImage = [UIImage imageWithData:newPixelData]; // Huzzah
我可以帮你


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

对于我们当中比较迟钝的人(阅读:future me),这里有一些基于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);
//加载图像
UIImage*image=[UIImage ImageName:@“test.png”];
CGImageRef imageRef=image.CGImage;
NSData*数据=(NSData*)CGDataProviderCopyData(CGImageGetDataProvider(imageRef));
字符*像素=(字符*)[数据字节];
//这是操纵单个像素的地方
//假设由rgb和alpha组成的4字节像素
//对于没有透明度的PNG,使用i+=3并删除int a
对于(int i=0;i<[数据长度];i+=4)
{
int r=i;
int g=i+1;
int b=i+2;
INTA=i+3;
像素[r]=0;//例如,去除红色
像素[g]=像素[g];
像素[b]=像素[b];
像素[a]=像素[a];
}
//从修改后的像素数据创建新图像
尺寸\u t宽度=CGImageGetWidth(imageRef);
尺寸高度=CGImageGetHeight(imageRef);
大小\u t bitsPerComponent=CGImageGetBitsPerComponent(imageRef);
size_t bitsPerPixel=CGImageGetBitsPerPixel(imageRef);
大小\u t bytesPerRow=CGImageGetBytesPerRow(imageRef);
CGColorSpaceRef colorspace=CGColorSpaceCreateDeviceRGB();
CGBitmapInfo-bitmapInfo=CGImageGetBitmapInfo(imageRef);
CGDataProviderRef provider=CGDataProviderCreateWithData(NULL,像素,[数据长度],NULL);
CGImageRef newImageRef=CGImageCreate(
宽度,
高度,
比特组件,
比特斯派克塞尔,
拜特斯佩罗,
色彩空间,
bitmapInfo,
供应商,
无效的
假,,
kCGrenderingEntentDefault
);
//修改后的图像
UIImage*newImage=[UIImage imageWithCGImage:newImageRef];
//清理
自由(像素);
CGImageRelease(imageRef);
CGCOLORSPACTERELEASE(色彩空间);
CGDataProviderRelease(提供程序);
CGImageRelease(newImageRef);

@shaun Inman的帖子是目前为止我在网络上找到的唯一作品!非常感谢。然而,至少在IOS3中,PNG颜色的保存方式与您所说的略有不同,这对我来说是有效的(仅适用于PNG!):

for(int i=0;i<[数据长度];i+=4){
像素[i+0]=0;//例如alpha?
像素[i+1]=0;//例如红色!
像素[i+2]=0;//例如绿色!
像素[i+3]=像素[i+3];//例如蓝色!
}

如果有人能想出一种适用于任何文件类型的方法,那就太酷了

在Shaun的回答中,将NSData*数据行更改为这一行,它就可以在iOS7中完美工作

 NSData *data        = (NSData *)CFBridgingRelease(CGDataProviderCopyData(CGImageGetDataProvider(imageRef)));

我使用下面的代码在图像的左右两侧添加了两条细细的红线

-(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;
}
-(UIImage*)修改图像:(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=图像尺寸高度/35;
无符号字符*数据=CGBitmapContextGetData(ctx);
对于(int y=0;y
你真的不必在帖子上签名。我们知道你是谁,你的名字和照片不到300像素的权利,你的额外的信号。你也完全失败了
-(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;
}