2010-02-10 90 views
13

我使用下面的代碼來裁剪並創建一個更大的新UIImage。我已經將CGImageCreateWithImageInRect()函數與CGImage屬性設置爲不符合我想要的方式來解決問題。 :-)問題是調用函數UIImagePNGRepresentation()失敗返回一個零。從CGImageRef創建的UIImage失敗,UIImagePNGRepresentation

CGImageRef origRef = [stillView.image CGImage]; 
CGImageRef cgCrop = CGImageCreateWithImageInRect(origRef, theRect); 
UIImage *imgCrop = [UIImage imageWithCGImage:cgCrop]; 

...

NSData *data = UIImagePNGRepresentation (imgCrop); 

- libpng的錯誤:沒有IDATs寫入文件

任何想法可能錯誤或替代用於裁剪一個矩形出來的UIImage的?非常感謝!

+0

當我啓用鏈接時間優化時,我得到了「libpng錯誤:沒有寫入文件的IDAT」。你啓用了這個選項嗎?禁用它修復了我。 – rasmus 2012-06-23 11:03:54

回答

1

在PNG中存在各種塊,其中一些包含調色板信息,一些實際圖像數據和一些其他信息,這是一個非常有趣的標準。 IDAT塊是實際包含圖像數據的位。如果沒有「寫入文件的IDAT」,那麼libpng從輸入數據創建PNG時遇到了一些問題。

我不確切知道你的stillView.image是什麼,但是當你將代碼傳遞給CGImageRef時會發生什麼,這肯定是有效的? Rect中的實際值是什麼?如果你的theRect超出了圖像的範圍,那麼你試圖用來製作UIImage的cgCrop可能很容易成爲零 - 或不是零,但不包含圖像或寬度和高度爲0的圖像,從而使libpng無法正常工作用。

+0

謝謝你的回答。 stillView是UIImageView。我用gdb p/po命令偷看cgCrop和imgCrop的屬性和函數返回值,並且兩者似乎都有正確的尺寸,imgCrop CGImage引用指向cgCrop等。嗯。下班後會有更詳細的外觀。 – 2010-02-11 08:48:04

1

它似乎你應該工作的soultion,但我建議使用此:

CGImageRef image = [stillView.image CGImage]; 
CGRect cropZone; 

size_t cWitdh = cropZone.size.width; 
size_t cHeight = cropZone.size.height; 
size_t bitsPerComponent = CGImageGetBitsPerComponent(image); 
size_t bytesPerRow = CGImageGetBytesPerRow(image)/CGImageGetWidth(image) * cWidth; 

//Now we build a Context with those dimensions. 
CGContextRef context = CGBitmapContextCreate(nil, cWitdh, cHeight, bitsPerComponent, bytesPerRow, CGColorSpaceCreateDeviceRGB(), CGImageGetBitmapInfo(image)); 

CGContextDrawImage(context, cropZone, image); 

CGImageRef result = CGBitmapContextCreateImage(context); 
UIImage * cropUIImage = [[UIImage alloc] initWithCGImage:tmp]; 

CGContextRelease(context); 
CGImageRelease(mergeResult); 
NSData * imgData = UIImagePNGRepresentation (cropUIImage); 

希望它能幫助。

+0

如果您的原始圖像是「非常大」,我想知道是否有一個選項將使用原始圖像,無論您需要哪個子圖像,但在繪製之前設置剪貼蒙版。這將允許您避免從原始圖像創建「複製」。這種方法可能有它自己的問題,所以你必須「比較和對比」這兩種方法。 – nielsbot 2011-05-02 05:11:18

+0

好 - 我提議的基本上是什麼提出的。我認爲sicario的方法可能會使用更多的內存。 – nielsbot 2011-05-02 05:12:52

3

我有同樣的問題,但只有在iOS 3.2上測試兼容性時。在4.2上它工作正常。

最後我發現這個http://www.hive05.com/2008/11/crop-an-image-using-the-iphone-sdk/這兩個工作,雖然有點冗長!

我上的UIImage轉換成一個類別這樣:

的UIImage + Crop.h

@interface UIImage (Crop) 
- (UIImage*) imageByCroppingToRect:(CGRect)rect; 
@end 

的UIImage + Crop.m

@implementation UIImage (Crop) 

- (UIImage*) imageByCroppingToRect:(CGRect)rect 
{ 
    //create a context to do our clipping in 
    UIGraphicsBeginImageContext(rect.size); 
    CGContextRef currentContext = UIGraphicsGetCurrentContext(); 

    //create a rect with the size we want to crop the image to 
    //the X and Y here are zero so we start at the beginning of our 
    //newly created context 
    CGRect clippedRect = CGRectMake(0, 0, rect.size.width, rect.size.height); 
    CGContextClipToRect(currentContext, clippedRect); 

    //create a rect equivalent to the full size of the image 
    //offset the rect by the X and Y we want to start the crop 
    //from in order to cut off anything before them 
    CGRect drawRect = CGRectMake(rect.origin.x * -1, 
           rect.origin.y * -1, 
           self.size.width, 
           self.size.height); 

    //draw the image to our clipped context using our offset rect 
    CGContextTranslateCTM(currentContext, 0.0, rect.size.height); 
    CGContextScaleCTM(currentContext, 1.0, -1.0); 
    CGContextDrawImage(currentContext, drawRect, self.CGImage); 

    //pull the image from our cropped context 
    UIImage *cropped = UIGraphicsGetImageFromCurrentImageContext(); 

    //pop the context to get back to the default 
    UIGraphicsEndImageContext(); 

    //Note: this is autoreleased 
    return cropped; 
} 


@end 
+0

此機制在裁剪時以外的情況下可能非常有用。我有一個UIImage,大概是因爲已經在一個不尋常的色彩空間中定義的,並沒有被UIImagePNGRepresentation所接受。我使用的代碼非常類似於上面的代碼,以UIImagePNGRepresentation可接受的形式重新生成UIImage。 – 2016-04-06 08:42:23

0

嘿我使用這種類型的邏輯在我應用程序,希望這可以幫助你...

UIImage *croppedImage = [self imageByCropping:yourImageView.image toRect:heredefineyourRect]; 

    CGSize size = CGSizeMake(croppedImage.size.height, croppedImage.size.width); 
    UIGraphicsBeginImageContext(size); 

    CGPoint pointImg1 = CGPointMake(0,0); 
    [croppedImage drawAtPoint:pointImg1 ]; 

    [[UIImage imageNamed:yourImagenameDefine] drawInRect:CGRectMake(0,532, 150,80) ];//here define your Reactangle 

    UIImage* result = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    croppedImage = result; 
    yourCropImageView.image=croppedImage; 
    [yourCropImageView.image retain]; 

希望這可以幫助你.... :)