【问题标题】:NSData -> UIImage -> NSDataNSData -> UIImage -> NSData
【发布时间】:2012-03-13 19:39:30
【问题描述】:

我有一个 NSData 对象,其中包含图像的 RGB 值。我想把它变成UIImage(给定宽度和高度)。然后我想将 UIImage 转换回与我开始使用的对象相同的 NSData 对象。

请帮助我,我已经尝试了几个小时了。

以下是我看过/尝试过的一些东西,虽然可能不太正确,因为它不起作用:

CGImageCreate
CGBitmapContextCreateWithData
CGBitmapContextGetData
CGDataProviderCopyData(CGImageGetDataProvider(imageRef))

谢谢!

这是我当前的代码:

NSMutableData *rgb; //made earlier
double len = (double)[rgb length];
len /= 3;
len += 0.5;
len = (int)len;
int diff = len*3-[rgb length];
NSString *str = @"a";
NSData *a = [str dataUsingEncoding:NSUTF8StringEncoding];
for(int i =0; i < diff; i++) {
    [toEncode appendData:a]; //so if my data is RGBRGBR it will turn into RGBRGBR(97)(97)
}
size_t width = (size_t)len;
size_t height = 1;
CGContextRef ctx; 
CFDataRef m_DataRef;
m_DataRef = (__bridge CFDataRef)toEncode;
UInt8 * m_PixelBuf = (UInt8 *) CFDataGetBytePtr(m_DataRef); 
vImage_Buffer src;
src.data = m_PixelBuf;
src.width = width;
src.height = height;
src.rowBytes = 3 * width;
vImage_Buffer dst;
dst.width = width;
dst.height = height;
dst.rowBytes = 4 * width;
vImageConvert_RGB888toARGB8888(&src, NULL, 0, &dst, NO, kvImageNoFlags);
//    free(m_PixelBuf);
//    m_PixelBuf = dst.data;
//    NSUInteger lenB = len * (4/3);
/*
 UInt8 * m_Pixel = malloc(sizeof(UInt8) * lenB);
 int z = 0;
 for(int i = 0; i < lenB; i++) {
 if(i % 4==0) {
 m_Pixel[i] = 0;
 } else {
 m_Pixel[i] = m_PixelBuf[z];
 z++;            
 }
 }*/
//    Byte tmpByte; 

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
/*
 ctx = CGBitmapContextCreate(m_PixelBuf, 
 width, 
 height, 
 8, 
 4*width, 
 colorSpace, 
 kCGImageAlphaPremultipliedFirst ); 
 */
size_t w = (size_t)len;
ctx = CGBitmapContextCreate(dst.data, 
                            w, 
                            height, 
                            8, 
                            4*width, 
                            colorSpace, 
                            kCGImageAlphaNoneSkipFirst );     
CGImageRef imageRef = CGBitmapContextCreateImage (ctx); 
UIImage* rawImage = [UIImage imageWithCGImage:imageRef]; 

CGContextRelease(ctx); 

我收到此错误:&lt;Error&gt;: CGBitmapContextCreate: invalid data bytes/row: should be at least 324 for 8 integer bits/component, 3 components, kCGImageAlphaNoneSkipFirst.

【问题讨论】:

  • 更详细地描述您的输入NSData 格式。向我们展示您尝试过的实际代码,而不是模糊地描述它。
  • 格式只是:R,G,B,R,G,B,R,G,B......所以例如我想创建一个100px x 100px的图像: 100 * 100 * 3 个字节存储在 nsdata 对象中。
  • 您还需要编辑您的问题并粘贴到您的实际代码中。

标签: iphone objective-c image graphics sdk


【解决方案1】:

从 NSData 到 UIImage:

[UIImage imageWithData:]

更多关于UIImage

从 UIImage 到 NSData:

UIImage *img = [UIImage imageNamed:@"some.png"];
NSData *dataObj = UIImageJPEGRepresentation(img, 1.0);

更多关于UIImageJPEGRepresentation()

【讨论】:

  • 这仅适用于已经采用某种标准(很可能是压缩)图像格式(png、jpg...)的数据,但不适用于原始像素数据。
【解决方案2】:

基本过程是使用CGBitmapContextCreateWithData 创建一个位图上下文,然后使用CGBitmapContextCreateImage 创建一个CGImageRef。创建位图上下文的参数取决于原始数据在内存中的布局方式。 Quartz 并不支持所有类型的原始数据。

documentation on CGBitmapContextCreateWithData 非常详细,这是最具挑战性的部分,从上下文中获取 CGImageRef 并将其包装在 UIImage (imageWithCGImage:) 之后是微不足道的。

【讨论】:

  • 我可以将 CGBitmapContextCreate 与 3 通道图像一起使用吗?我的数据是 RGB 而不是 RGBA 格式
  • 实际上,我怎样才能有效地为我的数据添加一个空的 Alpha 通道?例如,如果我的数据当前是:R,G,B,R,G,B,R,G,B 将其转换为 0,R,G,B,0,R,G,B,0,R,G ,B
  • 您可以使用 Accelerate 框架中的 vImageConvert_RGB888toARGB8888 函数来创建包含 Alpha 通道的图像数据的副本。 Documentation
  • 您不能使用 CGBitmapContextCreate 创建 RGB 格式(每像素 24 位)上下文。 iOS 仅支持每像素 32 位上下文和每像素 8 位上下文。
【解决方案3】:

如果您的数据是 RGB 格式,您需要使用 CGBitmapContextCreateCGColorSpaceCreateDeviceRGB 并使用 kCGImageAlphaNone 创建位图。

【讨论】:

  • 我试过了,我得到 CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 24 位/像素;三分量色彩空间; kCGImageAlphaNone;
  • 啊,对。然后使用 alpha 创建位图,但只需跳过设置/读取 alpha 的值。
  • 所以你的意思是像 kCGImageAlphaNoneSkipFirst?现在我正在尝试@rob mayoff 建议在 Accelerate 框架中使用 vImageConvert_RGB888toARGB8888 函数
【解决方案4】:

指出rowBytes 需要至少为324 的错误;除以 4 是 81,这意味着“宽度”小于“w”,并且 w=81。这两个值应该匹配。

尝试将 width 和 w 替换为 5 之类的小数字来验证这一点。我还要注意,您应该在调用 vImageConvert_RGB888toARGB8888 之前通过 malloc 分配 dst.data。

考虑使用 CGImageCreate() 而不是创建位图上下文:

// this will automatically free() dst.data when destData is dealloc
NSData *destData = [NSData dataWithBytesNoCopy:dst.data length:4*width*height];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)destData);
CGImageRef imageRef = CGImageCreate(width,
                                    height,
                                    8,                          //bits per component
                                    8*4,                        //bits per pixel
                                    4*width,                    //bytesPerRow
                                    colorSpace,                 //colorspace
                                    kCGImageAlphaNoneSkipFirst,
                                    provider,                   //CGDataProviderRef
                                    NULL,                       //decode
                                    false,                      //should interpolate
                                    kCGRenderingIntentDefault   //intent
                                    );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    • 2017-03-24
    • 2012-12-14
    • 2011-08-21
    • 1970-01-01
    • 2011-09-22
    相关资源
    最近更新 更多