1

我正在制作一个博客应用程序。要撰写新条目,有一个“撰写条目”视图,用户可以在其中选择照片并输入文本。对于照片,有一个 UIImageView 占位符,单击此占位符后,会出现一个自定义 ImagePicker,用户可以在其中选择最多 3 张照片。

这就是问题所在。我不需要来自 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];
        }
    }

在这里,从全分辨率图像中,我创建了两个图像:一个预览图像(长端最大 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
      });
    }
});

你必须以这种方式思考一些不同的事情。例如,您现在已经将过去的单个步骤分解为多个步骤。在此之后运行的代码将在图像调整大小完成之前或在您实际对图像执行任何操作之前运行,因此您需要确保您对这些图像没有任何依赖关系,否则您可能会崩溃。

于 2012-05-02T15:04:52.763 回答
3

一个迟到的答案,但对于那些在这个问题上磕磕绊绊的人,您可能需要考虑使用 .而fullScreenImage不是fullResolutionImage. defaultRepresentation它通常要小得多,但仍然足够大,可以为较大的缩略图保持良好的质量。

于 2015-01-08T13:18:13.053 回答