2013-05-10 78 views
2

我正在处理需要图像像素操作的项目。我现在在做的是使用UIImagePicker从设备库中接收UIImage。然后我将它转换为CGImage,获取RBG值并稍微改变它们。UIImage 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])]; 
+0

对不起,但我没有看到你在任何地方保存图片。当您导入图片时,您有图片的副本,而不是实际的图片,您需要将实际图片保存到照片库中,以使其不会自动完成。如果我错了,并且实际上将照片保存在照片库中,请发送代码 – Radu 2013-05-10 14:36:42

+1

您保存的格式(例如jpg,png)? – bobnoble 2013-05-10 14:37:45

+0

发布包含读取RGB值和编辑RGB值的代码 – Divyu 2013-05-10 14:44:55

回答

1

使用imagePickerController,imagedata被压缩成一个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搜索,你可以找到更多的职位。那些只是我参与的那些。

+0

非常感谢!这给了我很多材料翻翻,并肯定会提供一些必要的答案! – Firo 2013-06-27 15:02:47

1

您需要将图像保存到您的图书馆,你只对矫正它在你的应用程序。试试这个 之后,你有图像尝试将其保存到图片库中添加这行代码:

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代码吗?它可能不会保存正确的图像或可能会被重置。除此之外,我看不到找到一个错误

+0

现在你将有2张图像的原始和修改后的图像。如果您想要修改稍微复杂一点的相同图像,请立即尝试此操作,并告诉我它是否可以正常工作 – Radu 2013-05-13 07:00:56

+0

我尝试使用您的代码并且遇到同样的问题。数据并没有真正改变。在保存位被更改和正确之前,我可以验证,但是当我通过UIImagePicker手动读取图像时,它们保持不变。 如果图像改变了,我保存它应该使用'UIImagePickerControllerOriginalImage'来读取它还是别的东西? – Firo 2013-05-13 20:49:11

+0

好的,使用你的代码我保存图像,我的选择器被调用。我甚至可以用这种方法打印给我的'image'的二进制文件,它是正确的,它被添加到照片库中。然后我将UIImagePicker设置为零,然后重新初始化一个新的。 但是,当我在新添加的图像中读取并打印出二进制文件时,它保持不变! – Firo 2013-05-13 22:35:38