【问题标题】:UIImage RBG Values Change when Saved to Device Library保存到设备库时 UIImage RBG 值发生变化
【发布时间】:2013-05-10 14:33:44
【问题描述】:

我正在做一个需要图像像素处理的项目。我现在正在做的是使用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])];

【问题讨论】:

  • 对不起,但我没有看到您将图片保存在任何地方。当您导入图片时,您有图片的副本而不是实际图片,您需要将实际图片保存在照片库中才能拥有它,这不会自动完成。如果我错了,实际上将图片保存在照片库中,请发布代码
  • 您保存的格式是什么(例如,jpg、png)?
  • 贴出包含读取RGB值和编辑RGB值的代码
  • @Radu 我添加了那个代码
  • @bobnoble 我不确定,我之前几乎没有对图像做任何事情,并认为它已经为我处理好了。

标签: ios objective-c uiimage cgimage pixel-manipulation


【解决方案1】:

使用 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 上搜索时,您可以找到更多类似的帖子。这些只是我参与的。

【讨论】:

  • 非常感谢!这给了我很多材料可以翻阅,肯定会提供一些需要的答案!
【解决方案2】:

您需要将图像保存到您的库中,您只是在您的应用中修改它。试试这个 获得图像后,尝试将其保存到照片库中,添加以下代码:

UIImageWriteToSavedPhotosAlbum(rawImage, self, @selector(image:didFinishSavingWithError:contextInfo:), self);

并确认保存添加此方法:

    - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{

        NSString *str = @"Saved!!!";

        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Saved." message:str delegate:self cancelButtonTitle:nil otherButtonTitles:@"OK", nil];

        [alert show];

    }

编辑: 我没有看到完整的代码保存过程,对不起我的错误。代码看起来没问题,它应该保存图像你能在保存之前检查图像的 RGB 代码吗?它可能没有保存正确的图像,或者它可能被重置。除了我看不到的故障

【讨论】:

  • 现在您将拥有 2 张原始图像和修改后的图像。如果你想修改稍微复杂一点的同一张图片,现在试试这个,告诉我它是否有效
  • 我尝试使用您的代码并遇到同样的问题。数据并没有真正改变。我可以在保存位已更改且正确之前进行验证,但是当我通过 UIImagePicker 手动读回图像时,它们没有更改。如果图像被更改并且我保存它,我应该使用UIImagePickerControllerOriginalImage来读取它还是其他什么?
  • 好的,使用您的代码我保存图像并调用我的选择器。我什至可以打印用这种方法给我的image 的二进制文件,它是正确的,它被添加到照片库中。然后我将 UIImagePicker 设置为 nil 并重新初始化一个新的。然而,当我读入新添加的图像并打印出二进制文件时,它并没有改变!
  • 二进制真的完全没有改变吗?使用 imagePickerController 将图像数据压缩为 jpg,仅此一项就应该更改数据。您是否只是查看了保存的照片?将它们保存到相机胶卷并对其进行编辑后,您应该能够在手机上看到已保存图片的更改,对吧?
  • @thomketler(抱歉直到现在才看到)。不,我的意思是它已经改变了。感谢您对 jpg 压缩的见解。我想知道是否发生了这样的事情,但找不到有关如何将图像保存到照片库的任何信息。你知道无论如何要防止这种压缩发生吗?此外,如果您将您的评论作为答案,我会接受它,因为它比我拥有的任何其他东西都更有用和信息丰富。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-13
  • 2023-03-25
  • 1970-01-01
  • 2021-12-23
  • 1970-01-01
  • 1970-01-01
  • 2018-11-23
相关资源
最近更新 更多