上一篇文章在: 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像素,这样图片更美观了。
这个程序比较简单,不怎么占用开销。