Cocos2d-x 加载 gif 文件,生成jpg


前言:快下班了,弄了一天终于搞定。用QQ登陆之后,返回的头像是GIF的,CCIMAGE又不能加载GIF的内容。不想每个平台分开实现,所以找了个 giflib ,用它对 gif 图片进行解码,然后获取到位图内存,然后再保存到本地jpg格式。之后就可以随意的去加载这个头像,用 ccsprit 来展现了。


一。下载 giflib-4.2.3.tar

http://download.csdn.net/detail/qhexin/6970455


解压后  搜索   /* Make it into a stream: */”

用下句来替换 

 f = _fdopen(FileHandle, "rb");    /* Make it into a stream: */


替换的原因是,原SDK已经废弃,读取流的时候有问题


二。增加转换函数




bool LocalPhotoAccessMgr::convertGifFileToJpeg(std::string gifFilePath , std::string jpegFileSavePath)
{
BOOL isSuccess = FALSE;


GifFileType* GifFile = NULL;
if ((GifFile = DGifOpenFileName(gifFilePath.c_str())) == NULL) {  
PrintGifError();  
return FALSE;
}  


GifRowType * ScreenBuffer = NULL;//屏幕缓存
if ((ScreenBuffer = (GifRowType *)  
malloc(GifFile->SHeight * sizeof(GifRowType *))) == NULL)  
{
CCLOG("Failed to allocate memory required, aborted.");  
return FALSE;
}


int Size = GifFile->SWidth * sizeof(GifPixelType);/* Size in bytes one row.*/  
if ((ScreenBuffer[0] = (GifRowType) malloc(Size)) == NULL) /* First row. */  
{
CCLOG("Failed to allocate memory required, aborted.");  
return FALSE;
}


int i=0;
for (i = 0; i < GifFile->SWidth; i++)  /* Set its color to BackGround. */  
{
ScreenBuffer[0][i] = GifFile->SBackGroundColor;  
}
for (i = 1; i < GifFile->SHeight; i++) 
{  
/* Allocate the other rows, and set their color to background too: */  
if ((ScreenBuffer[i] = (GifRowType) malloc(Size)) == NULL)  
{
CCLOG("Failed to allocate memory required, aborted.");  
return FALSE;
}


memcpy(ScreenBuffer[i], ScreenBuffer[0], Size);  
}  


GifWord  Row = 0;
GifWord  Col = 0;
GifWord  Width = 0;
GifWord  Height = 0;
int ImageNum = 0;
int Count = 0;
int j=0;
static int InterlacedOffset[]={0,4,2,1},InterlacedJumps[]={8,8,4,2};
SavedImage temp_save;
memset(&temp_save,0,sizeof(temp_save));


bailin::MemBuffer buffer_rgb;//显示到屏幕上的图形

GifRecordType  RecordType = UNDEFINED_RECORD_TYPE;
do {  
if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) 
{  
PrintGifError();  
return FALSE;
}  


switch (RecordType) 
{  
case IMAGE_DESC_RECORD_TYPE:  
{
if (DGifGetImageDesc(GifFile) == GIF_ERROR) {  
PrintGifError();  
return false;
}  
Row = GifFile->Image.Top; /* Image Position relative to Screen. */  
Col = GifFile->Image.Left;  
Width = GifFile->Image.Width;  
Height = GifFile->Image.Height;  
CCLOG("\n%s: Image %d at (%d, %d) [%dx%d]:     ",  
"convert gif to jpeg", ++ImageNum, Col, Row, Width, Height);  
if (GifFile->Image.Left + GifFile->Image.Width > GifFile->SWidth ||  
GifFile->Image.Top + GifFile->Image.Height > GifFile->SHeight) {  
CCLOG("Image %d is not confined to screen dimension, aborted.\n",ImageNum);  
return false; 
}  


if (GifFile->Image.Interlace) {  
/* Need to perform 4 passes on the images: */  
for (Count = i = 0; i < 4; i++)  
for (j = Row + InterlacedOffset[i]; j < Row + Height;  
j += InterlacedJumps[i]) {  
CCLOG("\b\b\b\b%-4d", Count++);  
if (DGifGetLine(GifFile, &ScreenBuffer[j][Col], Width) == GIF_ERROR) {  
PrintGifError();  
return false;
}  
}  
}  
else {  
for (i = 0; i < Height; i++) {  
CCLOG("\b\b\b\b%-4d", i);  
if (DGifGetLine(GifFile, &ScreenBuffer[Row++][Col],  
Width) == GIF_ERROR) {  
PrintGifError();  
return false; 
}  
}  
}  


/* Get the color map */  
ColorMapObject* ColorMap = (GifFile->Image.ColorMap  
? GifFile->Image.ColorMap  
: GifFile->SColorMap);  
if (ColorMap == NULL) 
{  
CCLOG("Gif Image does not have a colormap\n");
return false;
}  


if (buffer_rgb.GetBufferLen() == 0)
{
//创建内存块
buffer_rgb.ReAllocBuffer(GifFile->SWidth * GifFile->SHeight * 4);
DumpScreen2RGBA(ColorMap ,(UINT8*)(buffer_rgb.GetBuffer()), ScreenBuffer, GifFile->SWidth, GifFile->SHeight);  
CCLOG("IMAGE_DESC_RECORD_TYPE find");


CCImage::saveRGBBufferToJPG(jpegFileSavePath.c_str() , (UINT8*)(buffer_rgb.GetBuffer()) ,GifFile->SWidth , GifFile->SHeight , true);


break;
}
}
break;  
case EXTENSION_RECORD_TYPE:  
{
int gifExtCode = 0;
GifByteType ExtDataTemp[2] ;
GifByteType* ExtData = ExtDataTemp ;
int status = DGifGetExtension(GifFile,&gifExtCode,&ExtData);

  while (ExtData != NULL && status == GIF_OK )
{

/* Create an extension block with our data */
if ((status = AddExtensionBlock(&temp_save, ExtData[0], (unsigned char*)&(ExtData[1]))) == GIF_OK)
status = DGifGetExtensionNext(GifFile, &ExtData);
temp_save.Function = 0;
}


CCLOG("EXTENSION_RECORD_TYPE find");
}
break;  
case TERMINATE_RECORD_TYPE:  
{
CCLOG("TERMINATE_RECORD_TYPE find");
}
break;  
default:            /* Should be traps by DGifGetRecordType. */  
break;  

}while (RecordType != TERMINATE_RECORD_TYPE);  




DGifCloseFile(GifFile);

if(buffer_rgb.GetBufferLen() > 0);
{
return true;
}
return false;
}


三。增加保存成JPG的函数



bool CCImage::saveRGBBufferToJPG(const char * pszFilePath , unsigned char* pData  , int imageWidth , int imageHeight ,bool bHasAlpha  )
{
bool bRet = false;
do 
{


CC_BREAK_IF(NULL == pszFilePath);


struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE * outfile;                 /* target file */
JSAMPROW row_pointer[1];        /* pointer to JSAMPLE row[s] */
int     row_stride;          /* physical row width in image buffer */


cinfo.err = jpeg_std_error(&jerr);
/* Now we can initialize the JPEG compression object. */
jpeg_create_compress(&cinfo);


CC_BREAK_IF((outfile = fopen(pszFilePath, "wb")) == NULL);


jpeg_stdio_dest(&cinfo, outfile);


cinfo.image_width = imageWidth;    /* image width and height, in pixels */
cinfo.image_height = imageHeight;
cinfo.input_components = 3;       /* # of color components per pixel */
cinfo.in_color_space = JCS_RGB;       /* colorspace of input image */


jpeg_set_defaults(&cinfo);


jpeg_start_compress(&cinfo, TRUE);


row_stride = imageWidth * 3; /* JSAMPLEs per row in image_buffer */


if (bHasAlpha)
{
unsigned char *pTempData = new unsigned char[imageWidth * imageHeight * 3];
if (NULL == pTempData)
{
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
fclose(outfile);
break;
}


for (int i = 0; i < imageHeight; ++i)
{
for (int j = 0; j < imageWidth; ++j)


{
pTempData[(i * imageWidth + j) * 3] = pData[(i * imageWidth + j) * 4];
pTempData[(i * imageWidth + j) * 3 + 1] = pData[(i * imageWidth + j) * 4 + 1];
pTempData[(i * imageWidth + j) * 3 + 2] = pData[(i * imageWidth + j) * 4 + 2];
}
}


while (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = & pTempData[cinfo.next_scanline * row_stride];
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}

CC_SAFE_DELETE_ARRAY(pTempData);

else
{
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = & pData[cinfo.next_scanline * row_stride];
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
}


jpeg_finish_compress(&cinfo);
fclose(outfile);
jpeg_destroy_compress(&cinfo);


bRet = true;
} while (0);
return bRet;
}



最后,需要用的人,把几个步骤连起来吧!
如果要展示成精灵,那也很方便。不多说啦。





你可能感兴趣的:(Cocos2d-x 加载 gif 文件,生成jpg)