2013-05-10 75 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