AIR客户端-高效处理图片缩略图的解决思路2

7 篇文章 0 订阅
4 篇文章 0 订阅

上一篇文章在: AIR客户端-高效处理图片的解决思路

这篇文章最后是采取系统的GDI读取文件缩略图的方案,本以为项目就这么OK了,但是经过测试,发现一些大图,用GetThumbnailImage读取缩略图,会有一些黑边。

具体如图所示:

一:从图片DIP上的分析

1.jpg和2.jpg是我用的同一个原图,只是对DPI做了少量的修改后的效果。

1.jpg 是没有黑边,2.jpg,8.jpg,9.jpg都是有黑边的。

开始我都怀疑是否是DPI的问题,2.jpg原图DPI是300,1.jpg我修改后的DPI是72。 后来就找了几个同类300DPI的图,发现不一定会有黑边。 问题就陷入僵局,因为是用的系统的API获取的缩略图,里面具体的计算方式方法,我是无从了解。

为了是确认是系统API的问题,而不是我的代码调用问题,我又采用了上篇文章中所有的方法,查看系统生成的db文件,发现在db文件里看到的缩略图确实是有黑边的,只是很奇怪的是,在我们查看文件的时候,它又不会显示黑边。

二:图片其他高级属性分析

1.佳能相机的问题?

对于第二个问题,就要做大量的图片测试了,图片所有有黑边的是原图,没有经过处理的。结果对比分析,我惊奇的发现,我测试的照片里,有黑边的是佳能的相机,欣喜若狂一番,以为找到原因了,后来又去找佳能的原片,再去测试,发现这个问题不是必然出现,所以只能排除这个方法!

2.图片大小的问题?

测试一般大于5M的照片,出现的概率较高,又去找大量图测试,发现也不是这个规律,3-4M的有时候又有黑边,没规律。排除!

3.图片属性里,分辨率单位:2,颜色表示:sRGB ?

经过测试,也不一定是这个问题,放弃!

4.最后没办法,干脆在C++代码里Debug

抓取图片的信息,对已知会生成黑边的图片,做仔细对比,发现完全没规律,放弃!(个人始终认为在这里,应该有一些信息的,只是苦于C++ 不熟悉,只能看些表面的东西)

三:C++在生成图片的时候,编码处理

所谓的编码处理,就是在图片生成缩略图后,save的时候,把一些图片处理的参数带进去,结果是可以解决黑边问题,但是效率很低,转了一圈,回到历史的问题,所以只能放弃

四:既然都有缩略图了,AIR来处理黑边了

获得缩略图体积都几kb,所以AIR再去加载处理去黑边,完全没压力,没有办法的办法。

采取的方法就是,针对宽图和窄图不同的计算方法,从像素上判断是否带有黑边,这里面有一套逻辑算法,可以快速排除掉PNG图(png图测试是不会有黑边的),只对jpg图做处理

提供逻辑,代码就不上了:

针对宽图,就是需要计算这个黑边的高度,从像素来说,只要x=0,y递增的情况下,都是黑色的,当不是黑色像素的时候,就是它的实际黑边高度,至于下方的高度,因为是对称的关系,上下是一致的。

原理是简单,但实际操作起来,又遇到一个坑,看似都是黑色像素,但是系统生成的黑色像素是有差值,不是完全的黑,只是一个近似值。

这个问题估计是flashPlayer虚拟机自身的问题,就算我们随便定义一个颜色,传值进去,到后面获取的值,都有一个偏差,可能是计算的算法问题,我稍后会补充一个简单示例。

示例占位

关键判断的代码:

/**
		 * 检查当前像素是否是颜色黑值
		 * @param	$checkPixel
		 * @return
		 */
		private function checkPixelIsBlack($checkPixel:uint):Boolean {
			var argb:Object = hextoargb($checkPixel);
			trace(argb.red,argb.green,argb.blue);
			if (argb.red < MAX_BLACK_UINT && argb.green < MAX_BLACK_UINT && argb.blue < MAX_BLACK_UINT) {
				return true;
			}
	                return false;
		}
               /**
         * RBG换算,获取对应通道的数值
         * @param    val
         */
        private function hextoargb(val:Number){
            var col={};
            col.alpha = (val>>24) & 0xFF;
            col.red = (val>>16) & 0xFF;
            col.green = (val>>8) & 0xFF
            col.blue = val & 0xFF;
            return col;
        } 

MAX_BLACK_UINT 这个是一个常量,我定义的是20,及RGB各自通道内都小于20,就可以近似判断为黑色。数值越小越准确,但是我经过测试,有些通道到了15,都还是黑色,所以保险点,我用了20.

接着上面的思路,获取了黑色的高度后,因为这只是当前x=0的一个判断,所以我们需要对这个假设的黑色框内颜色值做随机调取判断,换句话说,就是x坐标随机,y坐标也随机的去取颜色值,判断,如果都符合的话,就可以确认该图是黑色的边框了。

这个只是一个处理逻辑,宽度这这样的,窄图就反过来,原理一样。

判断完了图片是否有边框后,接下来的工作就是切图,切图就是需要把黑色边框切掉,以恢复原貌,这里走的比较顺畅,就是为了切图效果好点,可以对之前那个黑色框切的值,范围可以增加1-2像素,这样图片更美观了。

这个程序比较简单,不怎么占用开销。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值