ios - UIImage RBG 值在保存到设备库时发生变化

标签 ios objective-c uiimage cgimage pixel-manipulation

我正在开发一个需要图像像素处理的项目。我现在正在做的是使用 UIImagePicker 从设备库接收 UIImage 。然后,我将其转换为 CGImage,获取 RBG 值并稍微更改它们。

然后,我将其转换回 UIImage 并将其写入磁盘。问题是当我从 UIImagePicker 读回图像时,RBG 值不相同。我已验证这些值更改之后以及图像实际写出之前是正确的。仅当我读回像素值时,像素值才有所不同,然后仅相差几个值。我很好奇,为什么会发生这种情况,有什么办法可以解决这个问题吗?我想取回完全相同的 RBG 值。

这是一些代码,如果您想要具体的内容,请告诉我。

- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info {

    // I only ever manipulate self.editingImage which is directly read from the photo library
    // self.editingImage is a UIImage property
    self.editingImage = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
    self.imageView.image = self.editingImage;

    if (self.option == EDITPIXELS) {
        // After this method completes it automatically calls READPIXELS and the values are correct
        // converts self.editingImage to a CGImage before editing pixels
        [self editImage:self.editingImage];
    } else if (self.option == READPIXELS) {
        // converts self.editingImage to a CGImage before reading pixels, then logs RBG values
        [self readImage:self.editingImage];
    }

    [self.imagePickerPopoverController dismissPopoverAnimated:YES];
}

编辑: 我正在使用category from here要保存我的图像,请使用类别中的代码:

-(void)saveImage:(UIImage*)image toAlbum:(NSString*)albumName withCompletionBlock:(SaveImageCompletion)completionBlock {

    //write the image data to the assets library (camera roll)
    [self writeImageToSavedPhotosAlbum:image.CGImage orientation:(ALAssetOrientation)image.imageOrientation 
                       completionBlock:^(NSURL* assetURL, NSError* error) {

                      //error handling
                      if (error!=nil) {
                          completionBlock(error);
                          return;
                      }
                      //add the asset to the custom photo album
                      [self addAssetURL: assetURL 
                                toAlbum:albumName 
                    withCompletionBlock:completionBlock];
                  }];
}

我在操作按钮上调用它:

- (IBAction)saveImage:(id)sender {
    // Called before saving to verify the RBG values, they are correct
    [self readImage:self.editingImage];

    // saving image
    [self.library saveImage:self.editingImage toAlbum:@"My Album" withCompletionBlock:^(NSError *error){}];
}

这是我用来编辑 RBG 值的代码:

+ (UIImage *) fromImage:(UIImage *)source toRedColors:(NSArray *)redColorArray {

    // Code adapted from: http://brandontreb.com/image-manipulation-retrieving-and-updating-pixel-values-for-a-uiimage/
    CGContextRef ctx;
    CGImageRef imageRef = [source CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    byte *rawData = malloc(height * width * 4);
    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    CGContextRef context = CGBitmapContextCreate(rawData, width, height, 
                                     bitsPerComponent, bytesPerRow, colorSpace, 
                                     kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
    CGContextRelease(context);

    int byteIndex = 0;

    for (NSNumber *n in redColorArray) {
        rawData[byteIndex] = Clamp255([n integerValue]);
        byteIndex += 4;
    }
    ctx = CGBitmapContextCreate(rawData,
                            CGImageGetWidth( imageRef ),
                            CGImageGetHeight( imageRef ),
                            8,
                            bytesPerRow,
                            colorSpace,
                            kCGImageAlphaPremultipliedLast );
    CGColorSpaceRelease(colorSpace);
    imageRef = CGBitmapContextCreateImage (ctx);
    UIImage* rawImage = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    CGContextRelease(ctx);
    free(rawData);

    return rawImage;
}

读取值使用几乎完全相同的代码,除了我将值存储到数组中并仅返回 RBG 值数组(我不返回所有 RBG 值,仅返回其中一些值)。所以代替:

rawData[byteIndex] = Clamp255([n integerValue]);

我使用:

[myMutableArray addObject:@(rawData[byteIndex])];

最佳答案

使用 imagePickerController 将图像数据压缩为 jpg,仅此一项就会更改数据。

当您想要进行一些严肃的图像处理时,您将需要使用 AVFoundation。文档中的 AVCam 项目提供了示例代码,您可以将其用作引用。据我所知,iOS 的问题是它只提供 jpg 和 png 作为将数据保存为图片的可能性。

对于我的应用程序,我使用 OpenCV 库将图像数据保存为手机上的 BMP。 In this post you can see my solution 。此外,您还可以看到 "645 PRO" 描述的链接。应用程序。这些程序员面临着同样的问题,并一般性地描述了他们的应用程序如何解决这个问题。

如果您只需要保存数据一段时间以便再次在应用中使用它,您可以尝试将图像数据保存在 NSData 对象中并将其写入手机上。

Capture still UIImage without compression (from CMSampleBufferRef)?提供了对此问题的更多见解。 OpenCV imread() returns no image data on iOS .

当您在 stackoverflow 上搜索时,您可以找到更多类似的帖子。这些只是我参与的。

关于ios - UIImage RBG 值在保存到设备库时发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16484687/

相关文章:

ios - 在iOS上验证分离的PKCS7签名:验证错误:证书目的不受支持

ios - 无法打开依赖文件 SwiftStdLibToolInputDependencies.dep

iphone - 是否有用于高级日期+时间处理的 cocoa 库?

iphone - 使 UIImagePickerController (相机 View )仅显示一定数量的像素

objective-c - 检测 NSURL 是否是 UIImage 类支持的文件格式的 URL

ios - NSMutableDictionary 的 NSMutableArray 不显示数据

objective-c - UITextField 的初始键盘动画的超慢滞后/延迟

iphone - 如果应用程序在多任务处理中关闭,有什么方法吗?

ios - strokeEnd 上的 CABasicAnimation

ios - 以像素为单位的 UIImage 大小