24

メールで、画像を追加して送信しようとすると、送信する画像のサイズをすぐに尋ねられます。スクリーンショットを参照してください:

ここに画像の説明を入力

画像をアップロードするアプリで同様のことを行い、アップロードする前にユーザーが画像のサイズを変更できるようにしたいと考えています。Apple がここで行っているように、ファイル サイズを見積もる最良の方法は何ですか?

サイズを確認するためだけにサイズ変更された各画像を実際に作成するには、時間がかかりすぎるようです。より良い方法はありますか?

この Apple のサンプル コードは少し役に立ちましたが、正直言って圧倒されてしまいました。:)

4

5 に答える 5

14

最終的な圧縮画像サイズを決定する最大の要因は、画像サイズや JPEG 圧縮品質ではなく、画像の複雑さ (文字通りのエントロピー) です。(無地のカラー フィールドやグラデーションとは対照的に) 非常に詳細な写真を常に処理することがわかっている場合、その次元に沿った分散はいくらか減少しますが...

この問題の数値解析にかなりの時間を費やしました。9 つの異なる JPEG 品質レベルで、10% 単位で縮小された詳細な高解像度画像の圧縮画像サイズをサンプリングしました。これにより、陰関数 z = (x, y) を記述する 3 次元データ セットが作成されました。ここで、x はスケーリングされた画像のサイズ (ピクセル単位) (w*h)、y は JPEG 圧縮品質、z は結果の画像のサイズです。バイト単位。

結果のサーフェスは推定が困難です。直感に反して、振動と複数の変曲点があります。つまり、x と y の両方で次数 2 の関数では近似に不十分であり、多項式の次数を増やしてカスタム フィッティング関数を作成しても、それほど良い結果は得られませんでした。線形関係ではないだけでなく、単調な関係でもありません。それはただ複雑です。

実践しましょう。Apple が画像サイズの入力を求めてきたときに注意してください。メール作成ビューに画像が最初に表示されたときではなく、「送信」を押したときです。これにより、推定画像サイズの準備が整う前にメッセージを作成するのにかかる時間が与えられます。だから私の疑いはこれです:彼らはそれを難し​​い方法でやっています. 画像をさまざまなサイズにスケーリングすることは、並列化してバックグラウンドで実行できます。iPhone 4-calibur ハードウェアでは数秒かかりますが、そのすべての作業をユーザーから隠すことができます。メモリ使用量が気になる場合は、イメージを一時ファイルに書き込んで、並列ではなく順次レンダリングすることができます。これにより、メモリ内の圧縮されていないファイルの最大 2 倍のメモリが使用されます。

要約すると、圧縮している画像の予想されるエントロピーについてよく知っていない限り、推定関数は、一部のクラスの画像に対して非常に不正確になります。それを処理できれば、いくつかのサンプルデータに対して線形または二次近似を実行し、推定目的で関数を生成するのはかなり簡単です。ただし、Apple のように近づけたい場合は、実際のサイズ変更作業をバックグラウンドで実行する必要がある可能性があります。常に適切なヒューリスティックを構築するには要素が多すぎるためです。

于 2012-09-29T16:40:29.503 に答える
1

次のように、画像のサイズを変更するメソッドを作成しました。

-(UIImage *)resizeImage:(UIImage *)image width:(CGFloat)resizedWidth height:(CGFloat)resizedHeight
{
CGImageRef imageRef = [image CGImage];

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bitmap = CGBitmapContextCreate(NULL, resizedWidth, resizedHeight, 8, 4 * resizedWidth, colorSpace, kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(bitmap, CGRectMake(0, 0, resizedWidth, resizedHeight), imageRef);
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage *result = [UIImage imageWithCGImage:ref];

CGContextRelease(bitmap);
CGImageRelease(ref);

return result;
}

画像のサイズを取得するには、画像を に変換しNSData、長さを尋ねる必要があります。

 UIImage* actualImage = [UIImage imageNamed:@"image"];

NSData* actualImageData = UIImagePNGRepresentation(actualImage);

NSLog(@"Actual %f KB", (CGFloat)actualImageData.length / (CGFloat)1024);


UIImage* largeImage = [self resizeImage:actualImage width:actualImage.size.width * 0.8 height:actualImage.size.height * 0.8];

NSData* largeImageData = UIImagePNGRepresentation(largeImage);

NSLog(@"Large %f KB", (CGFloat)largeImageData.length / (CGFloat)1024);


UIImage* mediumImage = [self resizeImage:actualImage width:actualImage.size.width * 0.5 height:actualImage.size.height * 0.5];

NSData* mediumImageData = UIImagePNGRepresentation(mediumImage);

NSLog(@"Medium %f KB", (CGFloat)mediumImageData.length / (CGFloat)1024);


UIImage* smallImage = [self resizeImage:actualImage width:actualImage.size.width * 0.3 height:actualImage.size.height * 0.3];

NSData* smallImageData = UIImagePNGRepresentation(smallImage);

NSLog(@"Small %f KB", (CGFloat)smallImageData.length / (CGFloat)1024);
于 2012-09-27T12:39:06.357 に答える
0

メールアプリで提供される画像サイズは推定値であり、送信される画像の実際のファイルサイズは異なります。また、ファイルサイズを取得するためだけに、フルサイズの画像(iPhone4Sでは3264x 2448)をさまざまなサイズに変換するには遅すぎます。

[編集]

圧縮ファイルサイズは線形ではないため、numPixels / filesizeを取得して、小さい画像のファイルサイズを正確に見積もることはできません。

したがって、この答えは完全に役に立たないわけではありません。Mail.appがエクスポートする画像のサイズは次のとおりです。

小:320x240中:640x480大:1224x1632

于 2012-09-26T18:01:53.357 に答える
0

いつでもを使用しUIImageJPEGRepresentationて画像を圧縮できます。4つのオプションは、0.25、0.5、0.75、1.0の範囲の値にすることができ、同じ方法を適用した後、画像の計算によってサイズを簡単に見つけることができます。

于 2012-09-27T10:54:03.800 に答える
0

保存する場合は、含まれているバイト数を取得するためにNSData呼び出し、それを分割して適切なサイズを kB または MB で取得できます。[NSData length]

于 2012-09-25T11:49:06.473 に答える