访问已调整大小的图像的原始像素数据时出错

时间:2011-07-15 10:42:15

标签: ios image resize core-graphics cgcontext

我在访问相机图像时遇到了一些问题(甚至是来自photalbum的图像)。

调整UIImage的大小后(我测试了几种不同的调整大小方法,它们都会导致相同的错误)我想访问每个单独的像素,以便移交给复杂的算法。

问题是,当使用CGImageGetDataProvider - >访问原始像素数据时,通常会有一个bytesPerRow值与图像大小(例如宽度* 4)不匹配。导致EXC_BAD_ACCESS错误。

也许我们在这里有一个iOS错误...

尽管如此,这是代码:

// UIImage  capturedImage from Camera

CGImageRef capturedImageRef = capturedImage.CGImage;

// getting bits per component from capturedImage
size_t bitsPerComponentOfCapturedImage = CGImageGetBitsPerComponent(capturedImageRef);
CGImageAlphaInfo alphaInfoOfCapturedImage = CGImageGetAlphaInfo(capturedImageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

// calculate new size from interface data. 
// with respect to aspect ratio

// ...

// newWidth = XYZ;
// newHeight = XYZ;

CGContextRef context = CGBitmapContextCreate(NULL, newWidth, newHeight, bitsPerComponentOfCapturedImage,0 , colorSpace, alphaInfoOfCapturedImage);

// I also tried to make use getBytesPerRow for CGBitmapContextCreate resulting in the same error

// if image was rotated
if(capturedImage.imageOrientation == UIImageOrientationRight) {
  CGContextRotateCTM(context, -M_PI_2);
  CGContextTranslateCTM(context, -newHeight, 0.0f);
}

// draw on new context with new size
CGContextDrawImage(context, CGRectMake(0, 0, newWidth, newHeight), capturedImage.CGImage);

CGImageRef scaledImage=CGBitmapContextCreateImage(context);

// release
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
theImage = [UIImage imageWithCGImage: scaledImage];

CGImageRelease(scaledImage);

之后,我想通过

访问缩放图像
CGImageRef imageRef = theImage.CGImage;
NSData *data        = (NSData *) CGDataProviderCopyData(CGImageGetDataProvider(imageRef));

unsigned char *pixels        = (unsigned char *)[data bytes];

// 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);

CGDataProviderRef provider      = CGDataProviderCreateWithData(NULL, pixels, [data length], NULL);

NSLog(@"bytesPerRow: %f ", (float)bytesPerRow);
NSLog(@"Image width: %f ", (float)width);
NSLog(@"Image height: %f ", (float)height);

// manipulate the individual pixels
for(int i = 0; i < [data length]; i += 4) {

  // accessing (float) pixels[i];
  // accessing (float) pixels[i+1];
  // accessing (float) pixels[i+2];

}

因此,例如当我使用511x768像素访问图像并将其缩小到290x436时,我得到以下输出:

图片宽度: 290.000000

图片高度:436.000000

bitsPerComponent: 8.000000

bitsPerPixel: 32.000000

bytesPerRow: 1184.000000

你可以清楚地看到bytesPerRow(尽管cocoa自动选择)与<{1}}图像匹配。

我很乐意看到任何帮助


width

上使用iOS SDK 4.3

1 个答案:

答案 0 :(得分:1)

您忽略了可能的换行符,因此会收到无效结果。添加以下代码并替换循环;

size_t bytesPerPixel = bitsPerPixel / bitsPerComponent;
//calculate the padding just to see what is happening
size_t padding = bytesPerRow - (width * bytesPerPixel);
size_t offset = 0;
// manipulate the individual pixels
while (offset < [data length])
{
  for (size_t x=0; x < width; x += bytesPerPixel)
  {
    // accessing (float) pixels[offset+x];
    // accessing (float) pixels[offset+x+1];
    // accessing (float) pixels[offset+x+2];
  }
  offset += bytesPerRow;
};

附录:行填充的基本推理是优化单个行到32位边界的内存访问。这确实很常见,并且是出于优化目的而做的。