2010-02-10 9 views
13

Ich verwende den folgenden Code zum Zuschneiden und Erstellen eines neuen UIImage aus einem größeren. Ich habe das Problem isoliert, um mit der Funktion CGImageCreateWithImageInRect() zu sein, die nicht scheint, einige CGImage-Eigenschaft wie ich möchte. :-) Das Problem ist, dass ein Aufruf der Funktion UIImagePNGRepresentation() fehlschlägt, ein Nil zurückzugeben.UIImage erstellt von CGImageRef schlägt fehl mit UIImagePNGRepresentation

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

...

NSData *data = UIImagePNGRepresentation (imgCrop); 

- libpng Fehler: Jede Idee, was könnte falsch oder Alternative zum Zuschneiden eines rect aus UIImage Keine IDATs in Datei

geschrieben? Danke vielmals!

+0

Ich habe "libpng Fehler: Keine IDATs in die Datei geschrieben", wenn ich die Link-Zeit-Optimierung aktiviert. Hast du diese Option aktiviert? Das Deaktivieren hat es für mich repariert. – rasmus

Antwort

1

In einem PNG sind verschiedene Chunks vorhanden, einige enthalten Paletteninfo, einige aktuelle Bilddaten und einige andere Informationen, es ist ein sehr interessanter Standard. Der IDAT-Chunk ist das Bit, das tatsächlich die Bilddaten enthält. Wenn es kein "IDAT in Datei geschrieben" gibt, dann hat libpng ein Problem beim Erstellen eines PNG aus den Eingabedaten.

Ich weiß nicht genau, was Ihre stillView.image ist, aber was passiert, wenn Sie Ihren Code eine CGImageRef übergeben, die sicherlich gültig ist? Was sind die tatsächlichen Werte in TheRect? Wenn Ihr theRect über die Grenzen des Bildes hinausgeht, könnte der cgCrop, den Sie verwenden möchten, um den UIImage zu erstellen, leicht null sein oder nicht, aber kein Bild oder ein Bild mit der Breite und Höhe 0 enthalten, was libpng nichts bringt mit.

+0

Danke für die Antwort. StillView ist UIImageView. Ich spähte die Eigenschaft und Funktion Rückgabewerte von cgCrop und imgCrop mit gdb p/po Befehle und beide scheinen die richtige Dimension zu haben, imgCrop CGImage Referenzpunkte zu cgCrop etc. Hmmm. Werde einen genaueren Blick von der Arbeit haben. –

1

Es scheint die soultion Sie arbeiten versuchen sollte, aber ich empfehlen, diese zu verwenden:

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); 

Hoffe, es hilft.

+0

Wenn Ihr Originalbild "sehr groß" ist, frage ich mich, ob Sie das Originalbild an der Stelle verwenden möchten, an der Sie das Unterbild benötigen, sondern setzen Sie vor dem Zeichnen eine Schnittmaske. Auf diese Weise können Sie vermeiden, eine Kopie aus dem Originalbild zu erstellen. Dieser Ansatz hat möglicherweise eigene Probleme, daher müssen Sie die beiden Methoden vergleichen und kontrastieren. – nielsbot

+0

ok - was ich vorschlage ist im Grunde, was cidered vorgeschlagen. Ich denke, die Methode von Sicario könnte möglicherweise viel mehr Speicher nutzen. – nielsbot

3

Ich hatte das gleiche Problem, aber nur beim Testen der Kompatibilität auf iOS 3.2. Am 4.2 funktioniert es gut.

Am Ende fand ich diese http://www.hive05.com/2008/11/crop-an-image-using-the-iphone-sdk/, die auf beiden funktioniert, wenn auch etwas ausführlicher!

I umgewandelt diese in eine Kategorie auf 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

Dieser Mechanismus kann in einem anderen Kontext als beim Zuschneiden nützlich sein. Ich hatte eine UIIage, die, vermutlich weil sie in einem ungewöhnlichen Farbraum definiert wurde, von UIImagePNGRepresentation nicht akzeptiert wurde. Ich habe Code verwendet, der dem oben genannten sehr ähnlich ist, um den UII-Fehler in einer für UIImagePNGRepresentation akzeptablen Form zu regenerieren. –

0

hey ich diese Art von Logik verwenden in meinem app, hoffe das hilft dir ...

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]; 

hoffe das hilft dir .... :)