游戲項目是基於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解壓損壞文件時的錯誤處理