Domanda

il ridimensionamento di una fotocamera UIImage restituito dal UIImagePickerController prende un tempo assurdamente lungo se lo fate il solito modo come in questo post .

[aggiornamento: ultima chiamata per idee creative qui! il mio prossimo opzione è quella di andare a chiedere di Apple, immagino.]

Sì, è un sacco di pixel, ma l'hardware grafico su iPhone è perfettamente in grado di attirare un sacco di 1024x1024 quad texture sullo schermo in 1/60 ° di secondo, quindi c'è davvero dovrebbe essere un modo di ridimensionare una 2048x1536 immagine verso il basso a 640x480 in molto meno di 1,5 secondi.

Allora perché è così lento? È la base dati di immagine del sistema operativo ritorna dal selettore in qualche modo non è pronto a trarre, in modo che deve essere swizzled in qualche modo che la GPU non può aiutare con?

La mia ipotesi migliore è che ha bisogno di essere convertito da RGBA a ABGR o qualcosa di simile; chiunque può pensare ad un modo che potrebbe essere possibile per convincere il sistema di darmi i dati in modo rapido, anche se è nel formato sbagliato, e io ne occupo io me stesso più tardi?

Per quanto ne so, l'iPhone non ha alcuna "grafica" dedicato memoria, quindi non ci dovrebbe essere una questione di spostare i dati di immagine da un luogo ad un altro.

Quindi, la domanda: c'è qualche metodo di disegno alternativo oltre solo utilizzando CGBitmapContextCreate e CGContextDrawImage che richiede più vantaggio dalla GPU

?

Qualcosa da indagare: se mi metto con un UIImage della stessa dimensione che non è dal selettore di immagine, è altrettanto lento? A quanto pare no ...

Aggiornamento: Matt Long ha scoperto che ci vogliono solo 30 ms per ridimensionare l'immagine che si ottiene indietro dal selettore in [info objectForKey:@"UIImagePickerControllerEditedImage"], se hai attivato il ritaglio con i controlli manuali della telecamera. Questo non è utile per il caso che mi interessa dove sto usando takePicture per scattare foto di programmazione. Vedo che che l'immagine modificata è kCGImageAlphaPremultipliedFirst ma l'immagine originale è kCGImageAlphaNoneSkipFirst.

Ulteriore aggiornamento: Jason Crawford ha suggerito CGContextSetInterpolationQuality(context, kCGInterpolationLow), che in effetti ha tagliato il tempo da circa 1,5 sec a 1,3 sec, con un costo in termini di qualità dell'immagine - ma questo è ancora lontano dalla velocità della GPU dovrebbe essere in grado di

Ultimo aggiornamento prima della settimana finisca : refulgentis utente ha fatto un po 'di profilazione che sembra indicare che i 1,5 secondi vengono spesi a scrivere l'immagine della telecamera catturata su disco in formato JPEG e poi leggerlo di nuovo in . Se fosse vero, molto bizzarro.

È stato utile?

Soluzione

Usa Shark, il profilo it, capire cosa sta prendendo così tanto tempo.

Devo lavorare molto con MediaPlayer.framework e quando si arriva proprietà per le canzoni su iPod, la prima richiesta di proprietà è spaventosamente lento rispetto a richieste successive, perché nel primo proprietà pacchetti richiesta MobileMediaPlayer fino un dizionario con tutti i proprietà e lo passa al mio app.

Sarei pronto a scommettere che ci sia una situazione simile che si verifica qui.

EDIT:. Sono stato in grado di fare un profilo temporale in Shark della situazione UIImagePickerControllerEditedImage di entrambi Matt Long e la situazione UIImagePickerControllerOriginalImage generica

In entrambi i casi, la maggior parte del tempo è occupato da CGContextDrawImage. Nel caso di Matt Long, l'UIImagePickerController si prende cura di questo tra l'utente catturare l'immagine e l'immagine di entrare in modalità 'modifica'.

Scaling la percentuale di tempo impiegato per CGContextDrawImage = 100%, poi prende CGContextDelegateDrawImage 100%, poi ripc_DrawImage (da libRIP.A.dylib) calcia 100%, e quindi ripc_AcquireImage (che assomiglia decomprime il JPEG, e occupa la maggior parte del suo tempo in _cg_jpeg_idct_islow, vec_ycc_bgrx_convert, decompress_onepass, sep_upsample) calcia 93% del tempo. Solo il 7% del tempo viene effettivamente speso in ripc_RenderImage, che presumo sia il disegno vero e proprio.

Altri suggerimenti

Sembra che hai fatto diverse ipotesi qui che può o non può essere vero. La mia esperienza è diversa dalla vostra. Questo metodo sembra prendere solo 20-30ms sul mio 3Gs durante il ridimensionamento di un foto scattò dalla fotocamera al 0,31 della dimensione originale con una chiamata a:

CGImageRef scaled = CreateScaledCGImageFromCGImage([image CGImage], 0.31);

(ottengo 0,31 prendendo la scala di larghezza, 640,0 / 2048,0, tra l'altro)

Ho controllato per assicurarsi che l'immagine è la stessa dimensione che si sta lavorando. Ecco la mia uscita NSLog:

2009-12-07 16:32:12.941 ImagePickerThing[8709:207] Info: {
    UIImagePickerControllerCropRect = NSRect: {{0, 0}, {2048, 1536}};
    UIImagePickerControllerEditedImage = <UIImage: 0x16c1e0>;
    UIImagePickerControllerMediaType = "public.image";
    UIImagePickerControllerOriginalImage = <UIImage: 0x184ca0>;
}

Non sono sicuro di perché la differenza e non posso rispondere alla tua domanda in quanto si riferisce alla GPU, però vorrei prendere in considerazione 1,5 secondi e 30ms una differenza molto significativa. Forse confrontare il codice in questo post del blog a quello che si sta utilizzando?

Con i migliori saluti.

Ho avuto lo stesso problema e sbattuto la testa contro di esso per un lungo periodo di tempo. Per quanto posso dire, la prima volta che si accede al UIImage restituito dal selettore di immagini, è solo lento. Come esperimento, provate a temporizzazione ogni due operazioni con l'UIImage -. Per esempio, la vostra scala verso il basso, e quindi UIImageJPEGRepresentation o qualcosa del genere. Poi cambiare l'ordine. Quando ho fatto questo in passato, la prima operazione riceve una penalità di tempo. Il mio migliore ipotesi è che la memoria è ancora sul CCD in qualche modo, e il trasferimento in memoria principale di fare qualsiasi cosa con esso è lento.

Quando si imposta allowsImageEditing = YES, l'immagine che si ottiene indietro viene ridimensionata e ritagliata fino a circa 320x320. Questo lo rende più veloce, ma probabilmente non è ciò che si desidera.

Il miglior aumento di velocità che ho trovato è:

CGContextSetInterpolationQuality(context, kCGInterpolationLow)

sul contesto si torna da CGBitmapContextCreate, prima di fare CGContextDrawImage.

Il problema è che le immagini in scala ridotta potrebbero non guardare buono. Tuttavia, se si sta ridimensionando da un fattore intero -. Per esempio, 1600x1200 a 800x600 -. Allora sembra OK

Ecco un progetto git che ho usato e sembra funzionare bene. L'utilizzo è piuttosto pulito, come pure -. Una riga di codice

https://github.com/AliSoftware/UIImage-Resize

Non utilizzare CGBitmapImageContextCreate in questo caso! Ho trascorso quasi una settimana nella stessa situazione si è in. Performance sarà assolutamente terribile e si mangia la memoria come un matto. Uso UIGraphicsBeginImageContext invece:

// create a new CGImage of the desired size
UIGraphicsBeginImageContext(desiredImageSize);
CGContextRef c = UIGraphicsGetCurrentContext();

// clear the new image
CGContextClearRect(c, CGRectMake(0,0,desiredImageSize.width, desiredImageSize.height));

// draw in the image
CGContextDrawImage(c, rect, [image CGImage]);

// return the result to our parent controller
UIImage * result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Nell'esempio precedente (dal mio proprio codice Image Resize), "rect" è significativamente più piccola dell'immagine. Il codice di cui sopra corre molto veloce, e dovrebbe fare esattamente quello che ti serve.

Non sono del tutto sicuro perché UIGraphicsBeginImageContext è molto più veloce, ma credo che abbia qualcosa a che fare con l'allocazione di memoria. Ho notato che questo approccio richiede molta meno memoria, il che implica che il sistema operativo ha già stanziato lo spazio per un contesto di immagini da qualche parte.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top