1

私が作っているブログアプリケーションがあります。新しいエントリを作成するには、ユーザーが写真を選択してテキストを入力できる「エントリの作成」ビューがあります。写真の場合、UIImageView プレースホルダーがあり、これをクリックすると、ユーザーが最大 3 枚の写真を選択できるカスタム ImagePicker が表示されます。

ここで問題が発生します。ALAsset からのフル解像度の写真は必要ありませんが、同時にサムネイルの解像度が低すぎて使用できません。

この時点で行っているのは、fullResolution の写真のサイズを小さいサイズに変更することです。ただし、特に 3 枚までの写真を小さいサイズにリサイズする場合は、時間がかかります。

これは、私が何をしているのかを示すために切り取られたコードです。

    ALAssetRepresentation *rep = [[dict objectForKey:@"assetObject"] defaultRepresentation];

    CGImageRef iref = [rep fullResolutionImage];
    if (iref) 
    {
        CGRect screenBounds = [[UIScreen mainScreen] bounds];

        UIImage *previewImage;
        UIImage *largeImage;

        if([rep orientation] == ALAssetOrientationUp) //landscape image
        {
            largeImage = [[UIImage imageWithCGImage:iref] scaledToWidth:screenBounds.size.width];
            previewImage = [[UIImage imageWithCGImage:iref] scaledToWidth:300];
        }
        else  // portrait image
        {
            previewImage = [[[UIImage imageWithCGImage:iref] scaledToHeight:300] imageRotatedByDegrees:90];
            largeImage = [[[UIImage imageWithCGImage:iref] scaledToHeight:screenBounds.size.height] imageRotatedByDegrees:90];
        }
    }

ここでは、フル解像度の画像から 2 つの画像を作成しています。プレビュー画像 (長辺で最大 300 ピクセル) と大きな画像 (長辺で最大 960 ピクセルまたは 640 ピクセル) です。プレビュー画像は、「新しいエントリ」プレビューでアプリ自体に表示されるものです。大きな画像は、サーバーにアップロードするときに使用されるものです。

サイズ変更に使用している実際のコードは、次の場所から取得しました。

-(UIImage*)scaledToWidth:(float)i_width
{
    float oldWidth = self.size.width;
    float scaleFactor = i_width / oldWidth;

    float newHeight = self.size.height * scaleFactor;
    float newWidth = oldWidth * scaleFactor;

    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
    [self drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    
    UIGraphicsEndImageContext();
    return newImage;
}

私はここで間違ったことをしていますか?現状では、ALAsset のサムネイルは明瞭度が低すぎます。同時に、完全な解像度は必要ありません。現在はすべて機能していますが、サイズ変更には時間がかかります。これは単に必要な結果ですか?

ありがとう!

4

2 に答える 2

3

画像のサイズを変更すると、ある程度の時間がかかります。どの程度かは、デバイス、アセットの解像度、およびアセットの形式によって異なります。しかし、あなたはそれを制御することはできません。ただし、サイズ変更が行われる場所を制御できます。現在、メインスレッドで画像のサイズを変更していると思われます。これにより、サイズ変更中に UI が停止してしまいます。十分な数の画像を表示すると、アプリが長時間ハングしているように見えるので、ユーザーはその場を離れて別のことをするようになります (おそらく、App Store で競合するアプリをチェックしてください)。

あなたがすべきことは、メインスレッドからサイズ変更を実行することです。iOS 4 以降では、Grand Central Dispatch を使用してサイズ変更を行うことができるため、これははるかに簡単になりました。上記のコードの元のブロックを取得して、次のようにブロックでラップできます。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
  ALAssetRepresentation *rep = [[dict objectForKey:@"assetObject"] defaultRepresentation];

  CGImageRef iref = [rep fullResolutionImage];
  if (iref) 
  {
      CGRect screenBounds = [[UIScreen mainScreen] bounds];

      __block UIImage *previewImage;
      __block UIImage *largeImage;

      if([rep orientation] == ALAssetOrientationUp) //landscape image
      {
          largeImage = [[UIImage imageWithCGImage:iref] scaledToWidth:screenBounds.size.width];
          previewImage = [[UIImage imageWithCGImage:iref] scaledToWidth:300];
      }
      else  // portrait image
      {
          previewImage = [[[UIImage imageWithCGImage:iref] scaledToHeight:300] imageRotatedByDegrees:90];
          largeImage = [[[UIImage imageWithCGImage:iref] scaledToHeight:screenBounds.size.height] imageRotatedByDegrees:90];
      }
      dispatch_async(dispatch_get_main_queue(), ^{
        // do what ever you need to do in the main thread here once your image is resized.
        // this is going to be things like setting the UIImageViews to show your new images
        // or adding new views to your view hierarchy
      });
    }
});

このように、物事を少し違った方法で考える必要があります。たとえば、以前は 1 つのステップだったものが複数のステップに分割されました。これ以降に実行されていたコードは、イメージのサイズ変更が完了する前、またはイメージに対して実際に何かを行う前に実行されてしまうため、それらのイメージに依存関係がないことを確認する必要があります。そうしないと、クラッシュする可能性があります。

于 2012-05-02T15:04:52.763 に答える
3

遅い答えですが、この質問に出くわした人は、 のfullScreenImageではなく のfullResolutionImage使用を検討することをお勧めしますdefaultRepresentation。通常ははるかに小さいですが、より大きなサムネイルでも良好な品質を維持するのに十分な大きさです。

于 2015-01-08T13:18:13.053 に答える