2010-02-10 8 views
13

Sto usando il seguente codice per ritagliare e creare un nuovo UIImage su uno più grande. Ho isolato il problema con la funzione CGImageCreateWithImageInRect() che sembra non impostare alcune proprietà CGImage nel modo che voglio. :-) Il problema è che una chiamata alla funzione UIImagePNGRepresentation() non restituisce un valore nullo.UIImage creato da CGImageRef non riesce con UIImagePNGRepresentation

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

...

NSData *data = UIImagePNGRepresentation (imgCrop); 

- Errore di libpng: Nessun IDATs scritti nel file di

Qualche idea di cosa potrebbe sbagliato o alternativa per ritagliare un rettangolo di UIImage? Grazie molto!

+0

Ho ottenuto "errore libpng: IDAT non scritti nel file" quando ho attivato l'ottimizzazione del tempo di collegamento. Hai abilitato questa opzione? Disabilitarlo ha risolto per me. – rasmus

risposta

1

In un PNG ci sono vari blocchi presenti, alcuni contenenti informazioni sulla tavolozza, alcuni dati di immagine reali e altre informazioni, è uno standard molto interessante. Il pezzo IDAT è il bit che contiene effettivamente i dati dell'immagine. Se non c'è "IDAT scritto nel file" allora libpng ha avuto qualche problema nel creare un PNG dai dati di input.

Non so esattamente cosa sia il tuo stillView.image, ma cosa succede quando passi un codice CGImageRef che è certamente valido? Quali sono i valori effettivi in ​​theRect? Se yourRect è oltre i limiti dell'immagine allora il cgCrop che stai cercando di usare per rendere UIImage potrebbe essere facilmente nullo - o non nullo, ma non contenere alcuna immagine o un'immagine con larghezza e altezza 0, dando a libpng niente a che fare con.

+0

Grazie per la risposta. stillView è UIImageView. Ho dato un'occhiata alla proprietà e ho restituito i valori restituiti da cgCrop e imgCrop con i comandi gdb p/po ed entrambi sembrano avere dimensione corretta, punti di riferimento imgCrop CGImage a cgCrop ecc. Hmmm. Avrà un aspetto più dettagliato quando tornerai dal lavoro. –

1

Sembra che il soultion si sta cercando dovrebbe funzionare, ma vi consiglio di utilizzare questo:

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

Speranza che aiuta.

+0

Se l'immagine originale è "molto grande", mi chiedo se un'opzione possa utilizzare l'immagine originale ovunque sia necessaria l'immagine secondaria, ma impostare una maschera di ritaglio prima del disegno. Ciò consentirebbe di evitare di creare una "copia" dall'immagine originale. Questo approccio potrebbe avere i suoi problemi, quindi dovrai "confrontare e confrontare" i 2 metodi. – nielsbot

+0

ok - quello che sto proponendo è fondamentalmente ciò che sidro proposto. Penso che il metodo di sicario potrebbe potenzialmente usare molta più memoria. – nielsbot

3

Ho avuto lo stesso problema, ma solo quando testavo la compatibilità su iOS 3.2. Il 4.2 funziona perfettamente.

Alla fine ho trovato questo http://www.hive05.com/2008/11/crop-an-image-using-the-iphone-sdk/ che funziona su entrambi, anche se un po 'più prolisso!

ho trasformato questo in una categoria a 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

Questo meccanismo può essere utile in un contesto diverso da quando si ritaglia. Ho avuto un UIImage che, presumibilmente a causa di essere stato definito in uno spazio colore insolito, non è stato accettato da UIImagePNGRepresentation. Ho usato un codice molto simile a quello sopra per rigenerare UIImage in una forma accettabile per UIImagePNGRepresentation. –

0

hey io uso questo tipo di logica nel mio app, spero che questo ti aiuti ...

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

spero che questo ti aiuti .... :)