Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 为什么从相机缩小图像的速度如此之慢?_Iphone_Performance_Uiimage_Uiimagepickercontroller - Fatal编程技术网

Iphone 为什么从相机缩小图像的速度如此之慢?

Iphone 为什么从相机缩小图像的速度如此之慢?,iphone,performance,uiimage,uiimagepickercontroller,Iphone,Performance,Uiimage,Uiimagepickercontroller,如果按照中的常规方法调整UIImagePickerController返回的照相机UIImage的大小,则需要花费相当长的时间 [更新:这里是最后一次征集创意!我想我的下一个选择是去问问苹果公司。] 是的,它有很多像素,但iPhone上的图形硬件完全能够在1/60秒内在屏幕上绘制大量1024x1024纹理的四边形,因此确实应该有一种方法可以在不到1.5秒的时间内将2048x1536图像的大小调整为640x480 那为什么它这么慢呢?操作系统从选择器返回的底层图像数据是否还没有准备好绘制,因此必须

如果按照中的常规方法调整UIImagePickerController返回的照相机UIImage的大小,则需要花费相当长的时间

[更新:这里是最后一次征集创意!我想我的下一个选择是去问问苹果公司。]

是的,它有很多像素,但iPhone上的图形硬件完全能够在1/60秒内在屏幕上绘制大量1024x1024纹理的四边形,因此确实应该有一种方法可以在不到1.5秒的时间内将2048x1536图像的大小调整为640x480

那为什么它这么慢呢?操作系统从选择器返回的底层图像数据是否还没有准备好绘制,因此必须以GPU无法帮助的方式进行旋转

我最好的猜测是,它需要从RGBA转换为ABGR或类似的东西;有谁能想出一种方法,可以说服系统快速给我数据,即使数据格式不正确,我稍后会自己处理

据我所知,iPhone没有任何专用的“图形”内存,因此不应该存在将图像数据从一个地方移动到另一个地方的问题

所以,问题是:除了使用CGBitmapContextCreate和CGContextDrawImage,还有其他更充分利用GPU的绘图方法吗

需要调查的事情:如果我从一个与图像采集器大小相同的UIImage开始,它是否同样慢?显然不是

更新:Matt Long发现,如果您使用手动相机控件启用了裁剪功能,则只需30毫秒即可在
[info objectForKey:@“UIImagePickerControllerEditedImage”
中调整从选择器返回的图像的大小。这对于我关心使用
takePicture
以编程方式拍照的位置的情况没有帮助。我看到编辑的图像是
kgimagealphapremultipliedfirst
,但原始图像是
kgimagealphanoneskipfirst

进一步更新:Jason Crawford建议使用
CGContextSetInterpolationQuality(context,kCGInterpolationLow)
,这确实将时间从大约1.5秒缩短到了1.3秒,但这与GPU应有的速度相差甚远


本周结束前的最后一次更新:用户refulgentis做了一些分析,似乎表明1.5秒的时间用于将捕获的相机图像以JPEG格式写入磁盘,然后再读取回来。如果是真的,那就很奇怪了。

看来你在这里做出了一些假设,这些假设可能是真的,也可能不是真的。我的经验和你的不同。在我的3Gs上,将从相机拍摄的照片缩放到原始大小的0.31时,似乎只需要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>;
}
2009-12-0716:32:12.941图像选择器内容[8709:207]信息:{
UIImagePickerControllerCropRect=NSRect:{0,0},{20481536};
UIImagePickerControllerEditedImage=;
UIImagePickerControllerMediaType=“public.image”;
UIImagePickerController原始图像=;
}
我不知道为什么,我不能回答你的问题,因为它涉及到GPU,但是我会考虑1.5秒和30毫秒的一个非常显著的差异。也许可以将博客文章中的代码与您正在使用的代码进行比较


致以最诚挚的问候。

我也有同样的问题,我的头撞了很久。据我所知,第一次访问图像选择器返回的UIImage时,速度很慢。作为一个实验,尝试使用UIImage对任意两个操作进行计时——例如,缩小比例,然后使用UIImageJPEG表示法或其他方法。然后切换顺序。当我过去这样做的时候,第一次手术会受到时间惩罚。我最好的假设是,内存不知何故仍在CCD上,而将其传输到主内存以执行任何操作的速度都很慢

当设置AllowImageEditing=YES时,返回的图像将调整大小并裁剪到大约320x320。这使它更快,但它可能不是你想要的

我发现最好的加速是:

CGContextSetInterpolationQuality(context, kCGInterpolationLow)
在执行CGContextDrawImage之前,在从CGBitmapContextCreate返回的上下文上


问题是,缩小后的图像可能看起来不太好。但是,如果按整数因子进行缩放(例如,从1600x1200到800x600),则它看起来没问题。

使用Shark,对其进行分析,找出需要这么长时间的原因

我必须大量使用MediaPlayer.framework,当你在iPod上获取歌曲的属性时,第一个属性请求比后续请求慢得多,因为在第一个属性请求中,MobileMediaPlayer打包了一个包含所有属性的字典,并将其传递给我的应用程序

我敢打赌这里也会发生类似的情况


编辑:我能够在Shark中对Matt Long的UIImagePickerControllerEditedImage情况和通用UIImagePickerControllerOriginalImage情况进行时间配置

在这两种情况下,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%的时间。只有7%的时间实际花在ripc_渲染上,我假设这是实际的图形。

在这种情况下不要使用CGBitmapImageContextCreate!
// 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();