前言:快下班了,弄了一天终于搞定。用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;
}
最后,需要用的人,把几个步骤连起来吧!
如果要展示成精灵,那也很方便。不多说啦。