标签:
[Cocos2d-x相关教程来源于红孩儿的游戏编程之路 CSDN博客地址:http://blog.csdn.net/honghaier]
红孩儿Cocos2d-X学习园地QQ群:249941957 加群写:Cocos2d-x
Cocos2d-x之CCImage深入分析
本节所用Cocos2d-x版本:cocos2d-2.0-x-2.0.2
CCImage类:支持从JPG,PNG,TIFF以及数据流,字符串中创建供Cocos2d-x进行访问的图片数据对象。
这是一个非常重要的类,因为它是你使用cocos2d-x来加载图片的基础。目前此类只支持JPG,PNG,TIFF三种图像文件,对于这三种图像文 件,CCImage分别使用libjpg,libpng,libtiff进行读取访问和写文件的操作。有兴趣的同学可以上网查询相关图像库的分析和使用, 同时建议有能力的同学对此类进行扩展,令它支持更多的图像格式,是为“举一反三”。
学之前最好先了解一下libjpg,libpng,libtiff等图片功能库的使用。可以参见文章底部的参考资料。
现在,先来看CCImage图像头文件:
- #ifndef __CC_IMAGE_H__
- #define __CC_IMAGE_H__
- #include "cocoa/CCObject.h"
- NS_CC_BEGIN
-
- class CC_DLL CCImage : public CCObject
- {
- public:
-
- CCImage();
-
- ~CCImage();
-
- typedef enum
- {
- kFmtJpg = 0,
- kFmtPng,
- kFmtTiff,
- kFmtRawData,
- kFmtUnKnown
- }EImageFormat;
-
- typedef enum
- {
- kAlignCenter = 0x33,
- kAlignTop = 0x13,
- kAlignTopRight = 0x12,
- kAlignRight = 0x32,
- kAlignBottomRight = 0x22,
- kAlignBottom = 0x23,
- kAlignBottomLeft = 0x21,
- kAlignLeft = 0x31,
- kAlignTopLeft = 0x11,
- }ETextAlign;
-
-
- bool initWithImageFile(const char * strPath, EImageFormat imageType = kFmtPng);
-
-
- bool initWithImageFileThreadSafe(const char *fullpath, EImageFormat imageType = kFmtPng);
-
-
-
-
-
-
-
-
- bool initWithImageData(void * pData,
- int nDataLen,
- EImageFormat eFmt = kFmtUnKnown,
- int nWidth = 0,
- int nHeight = 0,
- int nBitsPerComponent = 8);
-
-
-
-
-
-
-
-
- bool initWithString(
- const char * pText,
- int nWidth = 0,
- int nHeight = 0,
- ETextAlign eAlignMask = kAlignCenter,
- const char * pFontName = 0,
- int nSize = 0);
-
-
- unsigned char * getData() { return m_pData; }
-
- int getDataLen() { return m_nWidth * m_nHeight; }
-
- bool hasAlpha() { return m_bHasAlpha; }
-
- bool isPremultipliedAlpha() { return m_bPreMulti; }
-
-
-
-
- bool saveToFile(const char *pszFilePath, bool bIsToRGB = true);
-
- CC_SYNTHESIZE_READONLY(unsigned short, m_nWidth, Width);
-
- CC_SYNTHESIZE_READONLY(unsigned short, m_nHeight, Height);
-
- CC_SYNTHESIZE_READONLY(int, m_nBitsPerComponent, BitsPerComponent);
-
- protected:
-
-
-
- bool _initWithJpgData(void *pData, int nDatalen);
-
- bool _initWithPngData(void *pData, int nDatalen);
-
- bool _initWithTiffData(void* pData, int nDataLen);
-
-
-
-
-
-
- bool _initWithRawData(void *pData, int nDatalen, int nWidth, int nHeight, int nBitsPerComponent);
-
- bool _saveImageToPNG(const char *pszFilePath, bool bIsToRGB = true);
-
- bool _saveImageToJPG(const char *pszFilePath);
-
- unsigned char *m_pData;
-
- bool m_bHasAlpha;
-
-
- private:
-
- CCImage(const CCImage& rImg);
- CCImage & operator=(const CCImage&);
- };
-
- NS_CC_END
-
- #endif // __CC_IMAGE_H__
继续分析CPP文件,其CPP文件由两个文件构成:
CCImageCommon_cpp.h和CCImage.cpp。在CCImage.cpp的起始代码处:
//定义 基于平台的CCImage的CPP标记宏
#define __CC_PLATFORM_IMAGE_CPP__
可以看到这里引用了头文件CCImageCommon_cpp.h。那我们就打开CCImageCommon_cpp.h:
- #ifndef __CC_PLATFORM_IMAGE_CPP__
-
- #error "CCFileUtilsCommon_cpp.h can only be included for CCFileUtils.cpp in platform/win32(android,...)"
- #endif /* __CC_PLATFORM_IMAGE_CPP__ */
-
- #include "CCImage.h"
- #include "CCCommon.h"
- #include "CCStdC.h"
- #include "CCFileUtils.h"
- #include "png.h"
- #include "jpeglib.h"
- #include "tiffio.h"
- #include <string>
- #include <ctype.h>
- NS_CC_BEGIN
-
- #define CC_RGB_PREMULTIPLY_APLHA(vr, vg, vb, va) \
- (unsigned)(((unsigned)((unsigned char)(vr) * ((unsigned char)(va) + 1)) >> 8) | \
- ((unsigned)((unsigned char)(vg) * ((unsigned char)(va) + 1) >> 8) << 8) | \
- ((unsigned)((unsigned char)(vb) * ((unsigned char)(va) + 1) >> 8) << 16) | \
- ((unsigned)(unsigned char)(va) << 24))
-
- typedef struct
- {
- unsigned char* data;
- int size;
- int offset;
- }tImageSource;
- static void pngReadCallback(png_structp png_ptr, png_bytep data, png_size_t length)
- {
-
- tImageSource* isource = (tImageSource*)png_get_io_ptr(png_ptr);
-
- if((int)(isource->offset + length) <= isource->size)
- {
- memcpy(data, isource->data+isource->offset, length);
- isource->offset += length;
- }
- else
- {
- png_error(png_ptr, "pngReaderCallback failed");
- }
- }
-
- CCImage::CCImage()
- : m_nWidth(0)
- , m_nHeight(0)
- , m_nBitsPerComponent(0)
- , m_pData(0)
- , m_bHasAlpha(false)
- , m_bPreMulti(false)
- {
-
- }
- CCImage::~CCImage()
- {
-
- CC_SAFE_DELETE_ARRAY(m_pData);
- }
- bool CCImage::initWithImageFile(const char * strPath, EImageFormat eImgFmt
- {
- bool bRet = false;
- unsigned long nSize = 0;
-
- unsigned char* pBuffer = CCFileUtils::sharedFileUtils()->getFileData(CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(strPath), "rb", &nSize);
- if (pBuffer != NULL && nSize > 0)
- {
-
- bRet = initWithImageData(pBuffer, nSize, eImgFmt);
- }
-
- CC_SAFE_DELETE_ARRAY(pBuffer);
- return bRet;
- }
-
- bool CCImage::initWithImageFileThreadSafe(const char *fullpath, EImageFormat imageType)
- {
- bool bRet = false;
- unsigned long nSize = 0;
-
- unsigned char *pBuffer = CCFileUtils::sharedFileUtils()->getFileData(fullpath, "rb", &nSize);
- if (pBuffer != NULL && nSize > 0)
- {
-
- bRet = initWithImageData(pBuffer, nSize, imageType);
- }
-
- CC_SAFE_DELETE_ARRAY(pBuffer);
- return bRet;
- }
-
- bool CCImage::initWithImageData(void * pData,
- int nDataLen,
- EImageFormat eFmt
- int nWidth
- int nHeight
- int nBitsPerComponent
- {
- bool bRet = false;
- do
- {
-
- CC_BREAK_IF(! pData || nDataLen <= 0);
-
- if (kFmtPng == eFmt)
- {
-
- bRet = _initWithPngData(pData, nDataLen);
- break;
- }
- else if (kFmtJpg == eFmt)
- {
-
- bRet = _initWithJpgData(pData, nDataLen);
- break;
- }
- else if (kFmtTiff == eFmt)
- {
-
- bRet = _initWithTiffData(pData, nDataLen);
- break;
- }
- else if (kFmtRawData == eFmt)
- {
-
- bRet = _initWithRawData(pData, nDataLen, nWidth, nHeight, nBitsPerComponent);
- break;
- }
- else
- {
-
-
- if (nDataLen > 8)
- {
- unsigned char* pHead = (unsigned char*)pData;
- if ( pHead[0] == 0x89
- && pHead[1] == 0x50
- && pHead[2] == 0x4E
- && pHead[3] == 0x47
- && pHead[4] == 0x0D
- && pHead[5] == 0x0A
- && pHead[6] == 0x1A
- && pHead[7] == 0x0A)
- {
-
- bRet = _initWithPngData(pData, nDataLen);
- break;
- }
- }
-
- if (nDataLen > 2)
- {
- unsigned char* pHead = (unsigned char*)pData;
- if ( (pHead[0] == 0x49 && pHead[1] == 0x49)
- || (pHead[0] == 0x4d && pHead[1] == 0x4d)
- )
- {
- bRet = _initWithTiffData(pData, nDataLen);
- break;
- }
- }
-
- if (nDataLen > 2)
- {
- unsigned char* pHead = (unsigned char*)pData;
- if ( pHead[0] == 0xff
- && pHead[1] == 0xd8)
- {
- bRet = _initWithJpgData(pData, nDataLen);
- break;
- }
- }
- }
- } while (0);
- return bRet;
- }
- bool CCImage::_initWithJpgData(void * data, int nSize)
- {
-
- struct jpeg_decompress_struct cinfo;
- struct jpeg_error_mgr jerr;
- JSAMPROW row_pointer[1] = {0};
- unsigned long location = 0;
- unsigned int i = 0;
-
- bool bRet = false;
- do
- {
-
-
- cinfo.err = jpeg_std_error( &jerr );
- jpeg_create_decompress( &cinfo );
- jpeg_mem_src( &cinfo, (unsigned char *) data, nSize );
- jpeg_read_header( &cinfo, true );
-
-
- 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;
- }
-
- jpeg_start_decompress( &cinfo );
-
-
- 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);
-
-
- 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 );
- bRet = true;
- } while (0);
-
- CC_SAFE_DELETE_ARRAY(row_pointer[0]);
- return bRet;
- }
- bool CCImage::_initWithPngData(void * pData, int nDatalen)
- {
- #define PNGSIGSIZE 8
- bool bRet = false;
-
- png_byte header[PNGSIGSIZE] = {0};
-
- png_structp png_ptr = 0;
-
- png_infop info_ptr = 0;
-
- do
- {
-
- CC_BREAK_IF(nDatalen < PNGSIGSIZE);
-
-
- memcpy(header, pData, PNGSIGSIZE);
- CC_BREAK_IF(png_sig_cmp(header, 0, PNGSIGSIZE));
-
-
- png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
- CC_BREAK_IF(! png_ptr);
-
-
- info_ptr = png_create_info_struct(png_ptr);
- CC_BREAK_IF(!info_ptr);
-
- #if (CC_TARGET_PLATFORM != CC_PLATFORM_BADA)
- CC_BREAK_IF(setjmp(png_jmpbuf(png_ptr)));
- #endif
-
-
- tImageSource imageSource;
- imageSource.data = (unsigned char*)pData;
- imageSource.size = nDatalen;
- imageSource.offset = 0;
-
- png_set_read_fn(png_ptr, &imageSource, pngReadCallback);
-
-
- png_read_info(png_ptr, info_ptr);
-
- m_nWidth = png_get_image_width(png_ptr, info_ptr);
- m_nHeight = png_get_image_height(png_ptr, info_ptr);
- m_nBitsPerComponent = png_get_bit_depth(png_ptr, info_ptr);
- png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr);
-
-
-
-
- if (color_type == PNG_COLOR_TYPE_PALETTE)
- {
- png_set_palette_to_rgb(png_ptr);
- }
-
- if (color_type == PNG_COLOR_TYPE_GRAY && m_nBitsPerComponent < 8)
- {
- png_set_expand_gray_1_2_4_to_8(png_ptr);
- }
-
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
- {
- png_set_tRNS_to_alpha(png_ptr);
- }
-
- if (m_nBitsPerComponent == 16)
- {
- png_set_strip_16(png_ptr);
- }
-
- if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
- {
- png_set_gray_to_rgb(png_ptr);
- }
-
-
-
- m_nBitsPerComponent = 8;
- png_uint_32 rowbytes;
-
- png_bytep* row_pointers = (png_bytep*)malloc( sizeof(png_bytep) * m_nHeight );
-
- png_read_update_info(png_ptr, info_ptr);
-
- rowbytes = png_get_rowbytes(png_ptr, info_ptr);
-
- m_pData = new unsigned char[rowbytes * m_nHeight];
- CC_BREAK_IF(!m_pData);
-
- for (unsigned short i = 0; i < m_nHeight; ++i)
- {
- row_pointers[i] = m_pData + i*rowbytes;
- }
-
- png_read_image(png_ptr, row_pointers);
-
- png_read_end(png_ptr, NULL);
-
- png_uint_32 channel = rowbytes/m_nWidth;
- if (channel == 4)
- {
-
- m_bHasAlpha = true;
-
- unsigned int *tmp = (unsigned int *)m_pData;
-
- for(unsigned short i = 0; i < m_nHeight; i++)
- {
- for(unsigned int j = 0; j < rowbytes; j += 4)
- {
-
- *tmp++ = CC_RGB_PREMULTIPLY_APLHA( row_pointers[i][j], row_pointers[i][j + 1],
- row_pointers[i][j + 2], row_pointers[i][j + 3] );
- }
- }
-
- m_bPreMulti = true;
- }
-
- CC_SAFE_FREE(row_pointers);
-
- bRet = true;
- } while (0);
-
- if (png_ptr)
- {
-
- png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0);
- }
- return bRet;
- }
- static tmsize_t _tiffReadProc(thandle_t fd, void* buf, tmsize_t size)
- {
-
- tImageSource* isource = (tImageSource*)fd;
- uint8* ma;
- uint64 mb;
-
- unsigned long n;
-
- unsigned long o;
-
- tmsize_t p;
-
- ma=(uint8*)buf;
-
- mb=size;
- p=0;
-
- while (mb>0)
- {
- n=0x80000000UL;
- if ((uint64)n>mb)
- n=(unsigned long)mb;
-
-
- if((int)(isource->offset + n) <= isource->size)
- {
- memcpy(ma, isource->data+isource->offset, n);
- isource->offset += n;
- o = n;
- }
- else
- {
- return 0;
- }
-
- ma+=o;
-
- mb-=o;
-
- p+=o;
-
- if (o!=n)
- {
- break;
- }
- }
- return p;
- }
- static tmsize_t _tiffWriteProc(thandle_t fd, void* buf, tmsize_t size)
- {
- CC_UNUSED_PARAM(fd);
- CC_UNUSED_PARAM(buf);
- CC_UNUSED_PARAM(size);
- return 0;
- }
-
- static uint64 _tiffSeekProc(thandle_t fd, uint64 off, int whence)
- {
-
- tImageSource* isource = (tImageSource*)fd;
- uint64 ret = -1;
- do
- {
-
- if (whence == SEEK_SET)
- {
- CC_BREAK_IF(off > isource->size-1);
- ret = isource->offset = (uint32)off;
- }
- else if (whence == SEEK_CUR)
- {
- CC_BREAK_IF(isource->offset + off > isource->size-1);
- ret = isource->offset += (uint32)off;
- }
- else if (whence == SEEK_END)
- {
- CC_BREAK_IF(off > isource->size-1);
- ret = isource->offset = (uint32)(isource->size-1 - off);
- }
- else
- {
- CC_BREAK_IF(off > isource->size-1);
- ret = isource->offset = (uint32)off;
- }
- } while (0);
-
- return ret;
- }
- static uint64 _tiffSizeProc(thandle_t fd)
- {
- tImageSource* pImageSrc = (tImageSource*)fd;
- return pImageSrc->size;
- }
- static int _tiffCloseProc(thandle_t fd)
- {
- CC_UNUSED_PARAM(fd);
- return 0;
- }
- static int _tiffMapProc(thandle_t fd, void** pbase, toff_t* psize)
- {
- CC_UNUSED_PARAM(fd);
- CC_UNUSED_PARAM(pbase);
- CC_UNUSED_PARAM(psize);
- return 0;
- }
- static void _tiffUnmapProc(thandle_t fd, void* base, toff_t size)
- {
- CC_UNUSED_PARAM(fd);
- CC_UNUSED_PARAM(base);
- CC_UNUSED_PARAM(size);
- }
- bool CCImage::_initWithTiffData(void* pData, int nDataLen)
- {
- bool bRet = false;
- do
- {
-
- tImageSource imageSource;
- imageSource.data = (unsigned char*)pData;
- imageSource.size = nDataLen;
- imageSource.offset = 0;
-
- TIFF* tif = TIFFClientOpen("file.tif", "r", (thandle_t)&imageSource,
- _tiffReadProc, _tiffWriteProc,
- _tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
- _tiffMapProc,
- _tiffUnmapProc);
-
- CC_BREAK_IF(NULL == tif);
-
- uint32 w = 0, h = 0;
- uint16 bitsPerSample = 0, samplePerPixel = 0, planarConfig = 0;
-
- size_t npixels = 0;
-
-
- TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
-
- TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
-
- TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitsPerSample);
-
- TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplePerPixel);
-
- TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planarConfig);
-
- npixels = w * h;
-
- m_bHasAlpha = true;
- m_nWidth = w;
- m_nHeight = h;
- m_nBitsPerComponent = 8;
-
- m_pData = new unsigned char[npixels * sizeof (uint32)];
-
- uint32* raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
- if (raster != NULL)
- {
-
- if (TIFFReadRGBAImageOriented(tif, w, h, raster, ORIENTATION_TOPLEFT, 0))
- {
-
-
- unsigned char* src = (unsigned char*)raster;
-
- unsigned int* tmp = (unsigned int*)m_pData;
-
-
-
- m_bPreMulti = true;
-
- memcpy(m_pData, raster, npixels*sizeof (uint32));
- }
-
- _TIFFfree(raster);
- }
-
-
-
- TIFFClose(tif);
-
- bRet = true;
- } while (0);
- return bRet;
- }
- bool CCImage::_initWithRawData(void * pData, int nDatalen, int nWidth, int nHeight, int nBitsPerComponent)
- {
- bool bRet = false;
- do
- {
-
- CC_BREAK_IF(0 == nWidth || 0 == nHeight);
-
- m_nBitsPerComponent = nBitsPerComponent;
- m_nHeight = (short)nHeight;
- m_nWidth = (short)nWidth;
- m_bHasAlpha = true;
-
-
- int nBytesPerComponent = 4;
- int nSize = nHeight * nWidth * nBytesPerComponent;
-
- m_pData = new unsigned char[nSize];
-
- CC_BREAK_IF(! m_pData);
-
- memcpy(m_pData, pData, nSize);
-
- bRet = true;
- } while (0);
- return bRet;
- }
- bool CCImage::saveToFile(const char *pszFilePath, bool bIsToRGB)
- {
- bool bRet = false;
-
- do
- {
-
- CC_BREAK_IF(NULL == pszFilePath);
-
- std::string strFilePath(pszFilePath);
- CC_BREAK_IF(strFilePath.size() <= 4);
-
- std::string strLowerCasePath(strFilePath);
- for (unsigned int i = 0; i < strLowerCasePath.length(); ++i)
- {
- strLowerCasePath[i] = tolower(strFilePath[i]);
- }
-
-
- if (std::string::npos != strLowerCasePath.find(".png"))
- {
- CC_BREAK_IF(!_saveImageToPNG(pszFilePath, bIsToRGB));
- }
-
- else if (std::string::npos != strLowerCasePath.find(".jpg"))
- {
- CC_BREAK_IF(!_saveImageToJPG(pszFilePath));
- }
- else
- {
-
- break;
- }
-
- bRet = true;
- } while (0);
-
- return bRet;
- }
- bool CCImage::_saveImageToPNG(const char * pszFilePath, bool bIsToRGB)
- {
- bool bRet = false;
- do
- {
-
- CC_BREAK_IF(NULL == pszFilePath);
-
-
- FILE *fp;
-
- png_structp png_ptr;
- png_infop info_ptr;
- png_colorp palette;
- png_bytep *row_pointers;
-
- fp = fopen(pszFilePath, "wb");
- CC_BREAK_IF(NULL == fp);
-
- png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-
- if (NULL == png_ptr)
- {
- fclose(fp);
- break;
- }
-
- info_ptr = png_create_info_struct(png_ptr);
- if (NULL == info_ptr)
- {
- fclose(fp);
- png_destroy_write_struct(&png_ptr, NULL);
- break;
- }
- #if (CC_TARGET_PLATFORM != CC_PLATFORM_BADA)
- if (setjmp(png_jmpbuf(png_ptr)))
- {
- fclose(fp);
- png_destroy_write_struct(&png_ptr, &info_ptr);
- break;
- }
- #endif
-
- png_init_io(png_ptr, fp);
-
- if (!bIsToRGB && m_bHasAlpha)
- {
- png_set_IHDR(png_ptr, info_ptr, m_nWidth, m_nHeight, 8, PNG_COLOR_TYPE_RGB_ALPHA,
- PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
- }
- else
- {
- png_set_IHDR(png_ptr, info_ptr, m_nWidth, m_nHeight, 8, PNG_COLOR_TYPE_RGB,
- PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
- }
-
- palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * sizeof (png_color));
-
- png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);
-
- png_write_info(png_ptr, info_ptr);
-
- png_set_packing(png_ptr);
-
- row_pointers = (png_bytep *)malloc(m_nHeight * sizeof(png_bytep));
- if(row_pointers == NULL)
- {
- fclose(fp);
- png_destroy_write_struct(&png_ptr, &info_ptr);
- break;
- }
-
- if (!m_bHasAlpha)
- {
-
- for (int i = 0; i < (int)m_nHeight; i++)
- {
- row_pointers[i] = (png_bytep)m_pData + i * m_nWidth * 3;
- }
-
- png_write_image(png_ptr, row_pointers);
-
-
- free(row_pointers);
- row_pointers = NULL;
- }
- else
- {
-
-
- if (bIsToRGB)
- {
-
- unsigned char *pTempData = new unsigned char[m_nWidth * m_nHeight * 3];
- if (NULL == pTempData)
- {
- fclose(fp);
- png_destroy_write_struct(&png_ptr, &info_ptr);
- break;
- }
-
- for (int i = 0; i < m_nHeight; ++i)
- {
- for (int j = 0; j < m_nWidth; ++j)
- {
- pTempData[(i * m_nWidth + j) * 3] = m_pData[(i * m_nWidth + j) * 4];
- pTempData[(i * m_nWidth + j) * 3 + 1] = m_pData[(i * m_nWidth + j) * 4 + 1];
- pTempData[(i * m_nWidth + j) * 3 + 2] = m_pData[(i * m_nWidth + j) * 4 + 2];
- }
- }
-
- for (int i = 0; i < (int)m_nHeight; i++)
- {
- row_pointers[i] = (png_bytep)pTempData + i * m_nWidth * 3;
- }
-
- png_write_image(png_ptr, row_pointers);
-
- free(row_pointers);
- row_pointers = NULL;
-
- CC_SAFE_DELETE_ARRAY(pTempData);
- }
- else
- {
-
-
- for (int i = 0; i < (int)m_nHeight; i++)
- {
- row_pointers[i] = (png_bytep)m_pData + i * m_nWidth * 4;
- }
-
- png_write_image(png_ptr, row_pointers);
-
-
- free(row_pointers);
- row_pointers = NULL;
- }
- }
-
- png_write_end(png_ptr, info_ptr);
-
- png_free(png_ptr, palette);
- palette = NULL;
- png_destroy_write_struct(&png_ptr, &info_ptr);
-
- fclose(fp);
-
- bRet = true;
- } while (0);
- return bRet;
- }
-
- bool CCImage::_saveImageToJPG(const char * pszFilePath)
- {
- bool bRet = false;
- do
- {
-
- CC_BREAK_IF(NULL == pszFilePath);
-
- struct jpeg_compress_struct cinfo;
- struct jpeg_error_mgr jerr;
- FILE * outfile;
- JSAMPROW row_pointer[1];
- int row_stride;
-
- cinfo.err = jpeg_std_error(&jerr);
- jpeg_create_compress(&cinfo);
-
- CC_BREAK_IF((outfile = fopen(pszFilePath, "wb")) == NULL);
-
- jpeg_stdio_dest(&cinfo, outfile);
-
- cinfo.image_width = m_nWidth;
- cinfo.image_height = m_nHeight;
- cinfo.input_components = 3;
- cinfo.in_color_space = JCS_RGB;
-
- jpeg_set_defaults(&cinfo);
-
- jpeg_start_compress(&cinfo, TRUE);
-
- row_stride = m_nWidth * 3;
-
- if (m_bHasAlpha)
- {
-
- unsigned char *pTempData = new unsigned char[m_nWidth * m_nHeight * 3];
- if (NULL == pTempData)
- {
- jpeg_finish_compress(&cinfo);
- jpeg_destroy_compress(&cinfo);
- fclose(outfile);
- break;
- }
-
- for (int i = 0; i < m_nHeight; ++i)
- {
- for (int j = 0; j < m_nWidth; ++j)
-
- {
-
- pTempData[(i * m_nWidth + j) * 3] = m_pData[(i * m_nWidth + j) * 4];
- pTempData[(i * m_nWidth + j) * 3 + 1] = m_pData[(i * m_nWidth + j) * 4 + 1];
- pTempData[(i * m_nWidth + j) * 3 + 2] = m_pData[(i * m_nWidth + 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] = & m_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;
- }
-
- NS_CC_END
现在我们回到CCImage.cpp:
- #define __CC_PLATFORM_IMAGE_CPP__
- #include "platform/CCImageCommon_cpp.h"
-
- NS_CC_BEGIN
-
- class BitmapDC
- {
- public:
-
- BitmapDC(HWND hWnd = NULL)
- : m_hDC(NULL)
- , m_hBmp(NULL)
- , m_hFont((HFONT)GetStockObject(DEFAULT_GUI_FONT))
- , m_hWnd(NULL)
- {
-
- m_hWnd = hWnd;
-
- HDC hdc = GetDC(hWnd);
-
- m_hDC = CreateCompatibleDC(hdc);
-
- ReleaseDC(hWnd, hdc);
- }
-
- ~BitmapDC()
- {
- prepareBitmap(0, 0);
- if (m_hDC)
- {
- DeleteDC(m_hDC);
- }
-
- HFONT hDefFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
- if (hDefFont != m_hFont)
- {
- DeleteObject(m_hFont);
- m_hFont = hDefFont;
- }
-
- if (m_curFontPath.size() > 0)
- {
- wchar_t * pwszBuffer = utf8ToUtf16(m_curFontPath);
- if (pwszBuffer)
- {
- RemoveFontResource(pwszBuffer);
- SendMessage( m_hWnd, WM_FONTCHANGE, 0, 0);
- delete [] pwszBuffer;
- pwszBuffer = NULL;
- }
- }
- }
-
- wchar_t * utf8ToUtf16(std::string nString)
- {
- wchar_t * pwszBuffer = NULL;
- do
- {
- if (nString.size() < 0)
- {
- break;
- }
-
- int nLen = nString.size();
- int nBufLen = nLen + 1;
- pwszBuffer = new wchar_t[nBufLen];
- CC_BREAK_IF(! pwszBuffer);
- memset(pwszBuffer,0,nBufLen);
- nLen = MultiByteToWideChar(CP_UTF8, 0, nString.c_str(), nLen, pwszBuffer, nBufLen);
- pwszBuffer[nLen] = ‘\0‘;
- } while (0);
- return pwszBuffer;
-
- }
-
- bool setFont(const char * pFontName = NULL, int nSize = 0)
- {
- bool bRet = false;
- do
- {
-
- std::string fontName = pFontName;
- std::string fontPath;
- HFONT hDefFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
- LOGFONTA tNewFont = {0};
- LOGFONTA tOldFont = {0};
- GetObjectA(hDefFont, sizeof(tNewFont), &tNewFont);
- if (fontName.c_str())
- {
-
- int nFindttf = fontName.find(".ttf");
- int nFindTTF = fontName.find(".TTF");
- if (nFindttf >= 0 || nFindTTF >= 0)
- {
- fontPath = CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(fontName.c_str());
- int nFindPos = fontName.rfind("/");
- fontName = &fontName[nFindPos+1];
- nFindPos = fontName.rfind(".");
- fontName = fontName.substr(0,nFindPos);
- }
- tNewFont.lfCharSet = DEFAULT_CHARSET;
- strcpy_s(tNewFont.lfFaceName, LF_FACESIZE, fontName.c_str());
- }
- if (nSize)
- {
- tNewFont.lfHeight = -nSize;
- }
-
- GetObjectA(m_hFont, sizeof(tOldFont), &tOldFont);
-
- if (tOldFont.lfHeight == tNewFont.lfHeight
- && ! strcpy(tOldFont.lfFaceName, tNewFont.lfFaceName))
- {
-
- bRet = true;
- break;
- }
-
-
- if (m_hFont != hDefFont)
- {
- DeleteObject(m_hFont);
-
- if (m_curFontPath.size() > 0)
- {
- wchar_t * pwszBuffer = utf8ToUtf16(m_curFontPath);
- if (pwszBuffer)
- {
- if(RemoveFontResource(pwszBuffer))
- {
- SendMessage( m_hWnd, WM_FONTCHANGE, 0, 0);
- }
- delete [] pwszBuffer;
- pwszBuffer = NULL;
- }
- }
- fontPath.size()>0?(m_curFontPath = fontPath):(m_curFontPath.clear());
-
- if (m_curFontPath.size() > 0)
- {
- wchar_t * pwszBuffer = utf8ToUtf16(m_curFontPath);
- if (pwszBuffer)
- {
- if(AddFontResource(pwszBuffer))
- {
- SendMessage( m_hWnd, WM_FONTCHANGE, 0, 0);
- }
- delete [] pwszBuffer;
- pwszBuffer = NULL;
- }
- }
- }
- m_hFont = NULL;
-
-
- tNewFont.lfQuality = ANTIALIASED_QUALITY;
-
-
- m_hFont = CreateFontIndirectA(&tNewFont);
- if (! m_hFont)
- {
-
- m_hFont = hDefFont;
- break;
- }
-
- bRet = true;
- } while (0);
- return bRet;
- }
-
- SIZE sizeWithText(const wchar_t * pszText, int nLen, DWORD dwFmt, LONG nWidthLimit)
- {
- SIZE tRet = {0};
- do
- {
- CC_BREAK_IF(! pszText || nLen <= 0);
-
- RECT rc = {0, 0, 0, 0};
- DWORD dwCalcFmt = DT_CALCRECT;
-
- if (nWidthLimit > 0)
- {
- rc.right = nWidthLimit;
- dwCalcFmt |= DT_WORDBREAK
- | (dwFmt & DT_CENTER)
- | (dwFmt & DT_RIGHT);
- }
-
- HGDIOBJ hOld = SelectObject(m_hDC, m_hFont);
-
-
- DrawTextW(m_hDC, pszText, nLen, &rc, dwCalcFmt);
- SelectObject(m_hDC, hOld);
-
- tRet.cx = rc.right;
- tRet.cy = rc.bottom;
- } while (0);
-
- return tRet;
- }
-
- bool prepareBitmap(int nWidth, int nHeight)
- {
-
- if (m_hBmp)
- {
- DeleteObject(m_hBmp);
- m_hBmp = NULL;
- }
- if (nWidth > 0 && nHeight > 0)
- {
- m_hBmp = CreateBitmap(nWidth, nHeight, 1, 32, NULL);
- if (! m_hBmp)
- {
- return false;
- }
- }
- return true;
- }
-
-
-
-
- int drawText(const char * pszText, SIZE& tSize, CCImage::ETextAlign eAlign)
- {
- int nRet = 0;
- wchar_t * pwszBuffer = 0;
- do
- {
- CC_BREAK_IF(! pszText);
-
- DWORD dwFmt = DT_WORDBREAK;
- DWORD dwHoriFlag = eAlign & 0x0f;
- DWORD dwVertFlag = (eAlign & 0xf0) >> 4;
-
- switch (dwHoriFlag)
- {
- case 1:
- dwFmt |= DT_LEFT;
- break;
- case 2:
- dwFmt |= DT_RIGHT;
- break;
- case 3:
- dwFmt |= DT_CENTER;
- break;
- }
-
- int nLen = strlen(pszText);
- int nBufLen = nLen + 1;
-
- pwszBuffer = new wchar_t[nBufLen];
- CC_BREAK_IF(! pwszBuffer);
-
- memset(pwszBuffer, 0, sizeof(wchar_t)*nBufLen);
-
- nLen = MultiByteToWideChar(CP_UTF8, 0, pszText, nLen, pwszBuffer, nBufLen);
-
- SIZE newSize = sizeWithText(pwszBuffer, nLen, dwFmt, tSize.cx);
-
- RECT rcText = {0};
-
- if (tSize.cx <= 0)
- {
- tSize = newSize;
- rcText.right = newSize.cx;
- rcText.bottom = newSize.cy;
- }
- else
- {
- LONG offsetX = 0;
- LONG offsetY = 0;
- rcText.right = newSize.cx;
-
- if (1 != dwHoriFlag
- && newSize.cx < tSize.cx)
- {
- offsetX = (2 == dwHoriFlag) ? tSize.cx - newSize.cx : (tSize.cx - newSize.cx) / 2; }
-
- if (tSize.cy <= 0)
- {
- tSize.cy = newSize.cy;
- dwFmt |= DT_NOCLIP;
- rcText.bottom = newSize.cy;
- }
- else if (tSize.cy < newSize.cy)
- {
-
- rcText.bottom = tSize.cy;
- }
- else
- {
- rcText.bottom = newSize.cy;
-
-
- dwFmt |= DT_NOCLIP;
-
-
- offsetY = (2 == dwVertFlag) ? tSize.cy - newSize.cy
-
- if (offsetX || offsetY)
- {
- OffsetRect(&rcText, offsetX, offsetY);
- }
- }
-
- CC_BREAK_IF(! prepareBitmap(tSize.cx, tSize.cy));
-
- HGDIOBJ hOldFont = SelectObject(m_hDC, m_hFont);
- HGDIOBJ hOldBmp = SelectObject(m_hDC, m_hBmp);
-
- SetBkMode(m_hDC, TRANSPARENT);
- SetTextColor(m_hDC, RGB(255, 255, 255));
-
- nRet = DrawTextW(m_hDC, pwszBuffer, nLen, &rcText, dwFmt);
-
-
- SelectObject(m_hDC, hOldBmp);
- SelectObject(m_hDC, hOldFont);
- } while (0);
-
- CC_SAFE_DELETE_ARRAY(pwszBuffer);
- return nRet;
- }
-
- CC_SYNTHESIZE_READONLY(HDC, m_hDC, DC);
-
- CC_SYNTHESIZE_READONLY(HBITMAP, m_hBmp, Bitmap);
- private:
-
- friend class CCImage;
-
- HFONT m_hFont;
-
- HWND m_hWnd;
-
- std::string m_curFontPath;
- };
- static BitmapDC& sharedBitmapDC()
- {
- static BitmapDC s_BmpDC;
- return s_BmpDC;
- }
- bool CCImage::initWithString(
- const char * pText,
- int nWidth
- int nHeight
- ETextAlign eAlignMask
- const char * pFontName
- int nSize
- {
- bool bRet = false;
- unsigned char * pImageData = 0;
- do
- {
- CC_BREAK_IF(! pText);
-
- BitmapDC& dc = sharedBitmapDC();
-
- if (! dc.setFont(pFontName, nSize))
- {
- CCLog("Can‘t found font(%s), use system default", pFontName);
- }
-
-
- SIZE size = {nWidth, nHeight};
- CC_BREAK_IF(! dc.drawText(pText, size, eAlignMask));
-
-
- pImageData = new unsigned char[size.cx * size.cy * 4];
- CC_BREAK_IF(! pImageData);
-
- struct
- {
- BITMAPINFOHEADER bmiHeader;
- int mask[4];
- } bi = {0};
- bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
-
- CC_BREAK_IF(! GetDIBits(dc.getDC(), dc.getBitmap(), 0, 0,
- NULL, (LPBITMAPINFO)&bi, DIB_RGB_COLORS));
-
- m_nWidth = (short)size.cx;
- m_nHeight = (short)size.cy;
- m_bHasAlpha = true;
- m_bPreMulti = false;
- m_pData = pImageData;
- pImageData = 0;
- m_nBitsPerComponent = 8;
-
- bi.bmiHeader.biHeight = (bi.bmiHeader.biHeight > 0)
- ? - bi.bmiHeader.biHeight : bi.bmiHeader.biHeight;
- GetDIBits(dc.getDC(), dc.getBitmap(), 0, m_nHeight, m_pData,
- (LPBITMAPINFO)&bi, DIB_RGB_COLORS);
-
-
- COLORREF * pPixel = NULL;
- for (int y = 0; y < m_nHeight; ++y)
- {
- pPixel = (COLORREF *)m_pData + y * m_nWidth;
- for (int x = 0; x < m_nWidth; ++x)
- {
- COLORREF& clr = *pPixel;
- if (GetRValue(clr) || GetGValue(clr) || GetBValue(clr))
- {
- clr |= 0xff000000;
- }
- ++pPixel;
- }
- }
-
- bRet = true;
- } while (0);
-
- return bRet;
- }
-
- NS_CC_END
CCImage类的代码都解析完了,其内部并没有对png,jpg,tiff做真正的解析,只是利用第三方的库进行相应的处理。经过处理
后,CCImage会被图片文件的数据读取转换为Cocos2d-x所用的图像数据,存储在m_pData中。如果我们不是使用这些图片文件,那么我们就
需要自已增加接口函数进行相应的处理。比如有时候做游戏不希望使用标准的图像格式以防止别人能够很容易打开图片进行查看,或者有时候将多个图片组成一个数
据包。
例如:
我们想读取一个自定义二进制图片数据(假设为Pic格式)
(1)我们可以先定义一个新的图片类型kFmtPic,
(2)然后定义函数
bool _initWithPicData(void *pData, int nDatalen);
在其中将自定义图片文件数据pData解析到m_pData中,并设置一些属性变量。
(3) 然后在initWithImageData函数中加入:
- else if (kFmtPic == eFmt)
-
-
- bRet = _initWithPicData(pData, nDataLen);
- break;
这样我们就可以让CCImage支持将我们自已定义的图像数据包加载为Cocos2d-x支持的图像类型了。
最后,祝大家双节快乐!下课~
本节用到的图片功能库参考资料:
图像解码之一——使用libjpeg解码jpeg图片 :http://www.cnblogs.com/xiaoxiaoboke/archive/2012/02/13/2349763.html
图像解码之二——使用libpng解码png图片:
http://www.cnblogs.com/xiaoxiaoboke/archive/2012/02/13/2349765.html
图像解码之三——giflib解码gif图片:
http://www.cnblogs.com/xiaoxiaoboke/archive/2012/02/13/2349770.html
VC下使用LibTiff处理TIFF文件:
http://wenku.baidu.com/view/63b08afaaef8941ea76e05bc.html
Cocos2d-x之CCImage深入分析
标签:
原文地址:http://www.cnblogs.com/dudu580231/p/4936504.html