4

元の画像:ここに画像の説明を入力してください フィルタリングされた画像:ここに画像の説明を入力してください

UIImages(携帯電話のカメラロールの写真)を正方形に切り抜こうとしています。これが私が使用しているコードの一部です。ここで、「image」はトリミングされている画像です。

if( image.size.height > image.size.width )
{
    dimension = image.size.width;
    imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectMake((image.size.height-dimension)/2, 0, dimension, dimension));

元の画像を使用している場合、この時点では次のようになります。ここに画像の説明を入力してください

これは問題なく、私が期待していることです。これを整理する回転アルゴリズムがここには示されていません。

フィルタリングされた画像を使用している場合は、次のようになります。ここに画像の説明を入力してください

...正方形ではなく、奇妙なことにズームインしました。 したがって、これが問題の原因であるように思われます。これらのフィルタリングされた画像の動作が異なる理由はわかりません。

}
else
{
    dimension = image.size.height;
    imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectMake((image.size.width-dimension)/2, 0, dimension, dimension));
}

CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
CGContextRef bitmap;

bitmap = CGBitmapContextCreate(NULL, dimension, dimension, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

私の問題は、その最後の行であるCGBitmapContextCreateで、次のエラーが発生することがあることです。

<Error>: CGBitmapContextCreate: invalid data bytes/row: should be at least 7744 for 8 integer bits/component, 3 components, kCGImageAlphaNoneSkipLast.

奇妙なことに、通常、これは発生しません-これまでのところ、元の画像の高さが幅よりも大きく、Camera+と呼ばれる別のアプリによってフィルタリングされた場合にのみこのエラーが発生しました...以前とまったく同じ写真フィルタリングは問題なく、フィルタリングされた風景写真も問題ないようです。

誰かが私をここに案内したり、実際に何が起こっているのかを説明するのを手伝ってもらえますか?エラーメッセージから、CGImageGetBytesPerRow(imageRef)を7744より大きい任意の数値に置き換えると、エラーは発生しなくなることを十分に理解していますが、このCGImageについては、実際にどのような影響があるのか​​を十分に理解していません。何でも、そしてそれは実際の解決策の多くのように私には思えません。このコードは、私がWebで見た他のトリミングの例に基づいているため、これらのビットマップ関数についての私の理解は限られています。

どんな考えでも大歓迎です!

編集

私はSOでこの質問を見つけました:このCGBitmapContextCreateで、bytesPerRow0はなぜですか?そして、bytesPerRowパラメーターを0に設定するように促されました。これによりエラーは解消されますが、このエラーが以前に発生したときと同じ状況では、トリミングルーチンが正しく機能しません。これには特別な人が答える必要があるかもしれませんが、ポートレート指向のカメラ+フィルタリングされた写真がこのコードによってどういうわけか異なって扱われる理由を推測するのに十分な画像フィルタリングについて知っている人はいますか?質問が少し変わったのでタイトルを更新しました。

EDIT2

上記のコードにサンプル画像を追加しました。最終的に、必要な回転を行った後、最終的にトリミングされた画像は次のようになります。

元の画像で:ここに画像の説明を入力してください-完璧です!

フィルタリングされた画像で:ここに画像の説明を入力してください-ひどい!

これらの最終的な、おそらくトリミングされた画像を作成するために使用されるコードは次のとおりです。

CGContextDrawImage(bitmap, CGRectMake(0, 0, dimension, dimension), imageRef);
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
image = [UIImage imageWithCGImage:ref];
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
4

2 に答える 2

2

つまり、カメラ+でフィルタリングされた画像は、何らかの理由でimageOrientation、元の画像とは異なる値で表示されます。どういうわけか、この事実は次のような行を引き起こします:

imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectMake((image.size.height-dimension)/2, 0, dimension, dimension));

imageOrientationのによって動作が異なりimageます。したがって、画像の向きがまたはの元の画像がこの線で横に回転している間(これが、縦向きと横向きの両方のサイズでxオフセットでトリミングしていた理由です)、フィルター処理された画像の向きはになります。 。このため、期待した回転が得られず、フィルタリングされた画像が引き伸ばされていました。これを解決するために、を呼び出す前に画像の向きを確認しています。画像CGImageCreateWithImageInRectが縦向きで上向きの場合は、xではなくayオフセットでトリミングします(David Hが以下で説明するコード行のように)。

私の推測では、[image CGImage]を呼び出すと、画像が比較的上向きの位置に回転します...したがって、向きが正しい場合、画像は反時計回りに90度回転しますが、向きが上向きの場合、画像は回転しません。まったく。フィルタリングされた画像が元の画像とは異なる向きになる理由はまだわかりませんが、それはcamera+のフィルタリングコードのある種の副作用にすぎないと思います。このオリエンテーションのすべてははるかに単純である可能性がありますが、これは今のところ解決策のようです。

于 2012-08-14T18:49:39.197 に答える
1

いくつかのコメント:

1)2で割ったときの値の16進値を丸めて、小数のピクセル境界に到達しないようにします(user roundf())

2)両方の寸法のケースを同じように扱わない

3)最初の作成では、yではなくxオフセットを設定しています-この変更された行を使用します:

imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectMake(0, (image.size.height-dimension)/2, dimension, dimension));
于 2012-08-11T01:13:13.527 に答える