4

UIImagePickerControllerによって返されるカメラUIImageのサイズ変更は、この投稿のように通常の方法で行うと、途方もなく長い時間がかかります。

[更新:ここで創造的なアイデアの最後の呼び出し!私の次の選択肢は、Appleに聞いてみるということだと思います。]

はい、それはたくさんのピクセルですが、iPhoneのグラフィックハードウェアは1/60秒でたくさんの1024x1024テクスチャクワッドを画面に完全に描くことができるので、2048x1536画像のサイズをに変更する方法が本当にあるはずです1.5秒未満で640x480。

では、なぜそんなに遅いのですか?OSがピッカーから返す基になる画像データは、どういうわけか描画する準備ができていないので、GPUが支援できない何らかの方法でスウィズルする必要がありますか?

私の推測では、RGBAからABGRなどに変換する必要があります。たとえデータが間違った形式であっても、システムにデータを迅速に提供するように説得することができるかもしれない方法を誰かが考えることができますか?後でそれを自分で処理しますか?

私の知る限り、iPhoneには専用の「グラフィック」メモリがないので、画像データをある場所から別の場所に移動することに問題はありません。

それで、質問:GPUをより活用するCGBitmapContextCreateとCGContextDrawImageを使用する以外に、いくつかの代替の描画方法はありますか?

調査すべき点:画像ピッカーからのものではない同じサイズのUIImageから始めた場合、それは同じくらい遅いですか?どうやらそうではありません...

[info objectForKey:@"UIImagePickerControllerEditedImage"]更新:Matt Longは、手動のカメラコントロールでトリミングを有効にしている場合、ピッカーから取得した画像のサイズを変更するのに30ミリ秒しかかからないことを発見しました。takePictureこれは、プログラムで写真を撮るために使用している場所が気になる場合には役立ちません。編集した画像はですkCGImageAlphaPremultipliedFirstが、元の画像はkCGImageAlphaNoneSkipFirstです。

さらなる更新:Jason Crawfordが提案CGContextSetInterpolationQuality(context, kCGInterpolationLow)しました。これは、実際には時間を約1.5秒から1.3秒に短縮しますが、画質は犠牲になりますが、それでもGPUが可能な速度にはほど遠いです。

週が切れる前の最後の更新:ユーザーrefulgentisがプロファイリングを行いました。これは、キャプチャされたカメラ画像をJPEGとしてディスクに書き込み、それを読み戻すのに1.5秒かかることを示しているようです。trueの場合、非常に奇妙です。

4

5 に答える 5

3

ここでは、真実である場合とそうでない場合があるいくつかの仮定を行ったようです。私の経験はあなたの経験とは異なります。この方法では、カメラからスナップした写真を元のサイズの0.31にスケーリングするときに、3Gで20〜30ミリ秒しかかからないようです。

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

(ちなみに、幅の目盛り640.0/2048.0を取ると0.31になります)

画像が作業中のサイズと同じであることを確認しました。これが私の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>;
}

なぜ違いがあるのか​​わかりません。GPUに関連しているため、質問に答えることはできませんが、1.5秒と30ミリ秒は非常に重要な違いだと思います。たぶん、そのブログ投稿のコードをあなたが使用しているものと比較しますか?

よろしくお願いします。

于 2009-12-07T23:34:51.547 に答える
2

私は同じ問題を抱えていて、長い間頭をぶつけてきました。私の知る限り、画像ピッカーから返されたUIImageに初めてアクセスするときは、速度が遅いだけです。実験として、UIImageを使用して任意の2つの操作のタイミングを調整してみてください。たとえば、スケールダウンしてから、UIImageJPEGRepresentationなどです。次に、順序を切り替えます。過去にこれを行った場合、最初の操作には時間のペナルティがあります。私の最良の仮説は、メモリがまだCCDに残っており、それをメインメモリに転送して何かを行うのが遅いというものです。

permitImageEditing = YESを設定すると、返される画像のサイズが変更され、約320x320にトリミングされます。それはそれをより速くします、しかしそれはおそらくあなたが望むものではありません。

私が見つけた最高のスピードアップは次のとおりです。

CGContextSetInterpolationQuality(context, kCGInterpolationLow)

CGContextDrawImageを実行する前に、CGBitmapContextCreateから取得したコンテキストで。

問題は、縮小した画像の見栄えが悪くなる可能性があることです。ただし、整数係数(1600x1200から800x600など)でスケールダウンしている場合は、問題ないように見えます。

于 2009-12-08T21:47:32.123 に答える
2

Shark を使用してプロファイリングし、何がそんなに時間がかかっているのかを把握します。

私は MediaPlayer.framework で多くの作業を行う必要があり、iPod で曲のプロパティを取得する場合、最初のプロパティ リクエストは後続のリクエストに比べて非常に遅くなります。これは、最初のプロパティ リクエストで MobileMediaPlayer がすべてのプロパティとパスを含むディクショナリをパッケージ化するためです。それを私のアプリに。

ここでも同様の状況が発生していると確信しています。

編集: Matt Long の UIImagePickerControllerEditedImage 状況と一般的な UIImagePickerControllerOriginalImage 状況の両方の時間プロファイルを Shark で実行できました。

どちらの場合も、ほとんどの時間は CGContextDrawImage に費やされます。Matt Long の場合、ユーザーが画像をキャプチャしてから画像が「編集」モードに入るまでの間に、UIImagePickerController がこれを処理します。

CGContextDrawImage = 100% にかかる時間のパーセンテージをスケーリングすると、CGContextDelegateDrawImage が 100% かかり、次に ripc_DrawImage (libRIP.A.dylib から) が 100% かかり、次に ripc_AcquireImage (JPEG を解凍するように見え、そのほとんどを占めます) _cg_jpeg_idct_islow、vec_ycc_bgrx_convert、decompress_onepass、sep_upsample) の時間は 93% の時間を要します。実際に ripc_RenderImage に費やされる時間はわずか 7% であり、これが実際の描画であると私は推測しています。

于 2009-12-14T02:52:26.857 に答える
1

これは私が使用したgitプロジェクトで、うまく機能しているようです。使用法も非常にきれいです - 1 行のコードです。

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

于 2011-06-21T05:12:16.367 に答える
-1

この場合、CGBitmapImageContextCreate を使用しないでください。私はあなたがいるのと同じ状況でほぼ 1 週間過ごしました。代わりに UIGraphicsBeginImageContext を使用します。

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

上記の例 (私自身の画像サイズ変更コードから) では、「rect」は画像よりもかなり小さいです。上記のコードは非常に高速に実行され、必要なことを正確に実行するはずです。

なぜ UIGraphicsBeginImageContext の方がはるかに高速なのかは完全にはわかりませんが、メモリ割り当てと関係があると思います。このアプローチでは、必要なメモリが大幅に少なくて済むことに気付きました。これは、OS がイメージ コンテキスト用のスペースをどこかに既に割り当てていることを意味します。

于 2009-12-14T03:08:02.847 に答える