游戏项目是基于cocos2d-x开发的,但线上发现一个bug就是玩家在设置完自定义头像后直接闪退。凡是在设置该玩家头像的地方,游戏就直接闪退。最终定位到的问题是图片数据源有问题,我的机器是win7,图片能预览,但同事xp系统该图片是无法预览的,默认的系统自带的图片查看工具也无法显示图片。
把图片拉到sublime text中,查看文件二进制,发现它并非一个完整的jpeg格式
没有jpeg格式的结束标识0xff 0xd9
我在windows下调试代码,发现是在CCImageCommon_cpp.h中的_initWithJpgData方法调用jpeg_finish_decompress函数时程序直接退出了
bool CCImage::_initWithJpgData(void * data, int nSize, bool bNeedDecode /*= false*/)
{
int nRandomBytes = 0;
if (bNeedDecode) nRandomBytes = RANDOM_BYTES; if (bNeedDecode)
{
data = (unsigned char *)data + nRandomBytes;
nSize = nSize - nRandomBytes;
} /* these are standard libjpeg structures for reading(decompression) */
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
/* libjpeg data structure for storing one row, that is, scanline of an image */
JSAMPROW row_pointer[1] = {0};
unsigned long location = 0;
unsigned int i = 0; bool bRet = false;
do
{
/* here we set up the standard libjpeg error handler */
cinfo.err = jpeg_std_error( &jerr ); /* setup decompression process and source, then read JPEG header */
jpeg_create_decompress( &cinfo ); jpeg_mem_src( &cinfo, (unsigned char *) data, nSize ); /* reading the image header which contains image information */
jpeg_read_header( &cinfo, true ); // we only support RGB or grayscale
if (cinfo.jpeg_color_space != JCS_RGB)
{
if (cinfo.jpeg_color_space == JCS_GRAYSCALE || cinfo.jpeg_color_space == JCS_YCbCr)
{
cinfo.out_color_space = JCS_RGB;
}
}
else
{
break;
} /* Start decompression jpeg here */
jpeg_start_decompress( &cinfo ); /* init image info */
m_nWidth = (short)(cinfo.image_width);
m_nHeight = (short)(cinfo.image_height);
m_bHasAlpha = false;
m_bPreMulti = false;
m_nBitsPerComponent = 8;
row_pointer[0] = new unsigned char[cinfo.output_width*cinfo.output_components];
CC_BREAK_IF(! row_pointer[0]); m_pData = new unsigned char[cinfo.output_width*cinfo.output_height*cinfo.output_components];
CC_BREAK_IF(! m_pData); /* now actually read the jpeg into the raw buffer */
/* read one scan line at a time */
while( cinfo.output_scanline < cinfo.image_height )
{
jpeg_read_scanlines( &cinfo, row_pointer, 1 );
for( i=0; i<cinfo.image_width*cinfo.output_components;i++)
{
m_pData[location++] = row_pointer[0][i];
}
} jpeg_finish_decompress( &cinfo );
jpeg_destroy_decompress( &cinfo );
/* wrap up decompression, destroy objects, free pointers and close open files */
bRet = true;
} while (0); CC_SAFE_DELETE_ARRAY(row_pointer[0]);
return bRet;
}
后面我用jpegtran(https://github.com/imagemin/jpegtran-bin)工具复制有问题的图片时, 也提示错误了
参考文章:
[2] JPEG File Layout and Format
解决方案可以参考这篇文章:libjpeg解压损坏文件时的错误处理