
[历史归档]本文原发布于 cstriker1407.info 个人博客内容为历史存档仅供参考。发布时间2014-07-08 标题cocos2dx学习笔记CCImage及获取特定点的颜色值分类编程 / C C / cocos2dx 标签cocos2dx·CCImagecocos2dx学习笔记CCImage及获取特定点的颜色值CCImage简单分析获取特定点颜色的方法备注在进行cocos2dx游戏开发时我们有时候需要知道特定点的颜色这里笔记下如何使用CCImage读取png文件来实现。CCImage简单分析这里我们先简单的分析下CCImage的实现。首先看下【CCImage::initWithImageFile】的实现在文件【\cocos2d-x-2.2.3\cocos2dx\platform\CCImageCommon_cpp.h】中boolCCImage::initWithImageFile(constchar*strPath,EImageFormat eImgFmt/* eFmtPng*/){boolbRetfalse;#ifdefEMSCRIPTEN。。。。。。 。。。。。。#elseunsignedlongnSize0;std::string fullPathCCFileUtils::sharedFileUtils()-fullPathForFilename(strPath);//获取了传入文件的绝对路径//读文件pBuffer为文件内容nSize为内容长度unsignedchar*pBufferCCFileUtils::sharedFileUtils()-getFileData(fullPath.c_str(),rb,nSize);if(pBuffer!NULLnSize0){//进入函数进行处理这里假设我们传入的eImgFmt为png类型的。bRetinitWithImageData(pBuffer,nSize,eImgFmt);}CC_SAFE_DELETE_ARRAY(pBuffer);#endif// EMSCRIPTENreturnbRet;}boolCCImage::initWithImageData(void*pData,intnDataLen,EImageFormat eFmt/* eSrcFmtPng*/,intnWidth/* 0*/,intnHeight/* 0*/,intnBitsPerComponent/* 8*/){boolbRetfalse;do{CC_BREAK_IF(!pData||nDataLen0);if(kFmtPngeFmt){bRet_initWithPngData(pData,nDataLen);break;}//这里我们仅仅分析png格式的读取其他的先略掉。。。。。。 。。。。。。}while(0);returnbRet;}//cocos2dx使用libpng来读取png图片具体的使用方法这里不再展开笔记只笔记下整体的流程boolCCImage::_initWithPngData(void*pData,intnDatalen){// length of bytes to check if it is a valid png file#definePNGSIGSIZE8boolbRetfalse;//先声明libpng需要的结构体png_byte header[PNGSIGSIZE]{0};png_structp png_ptr0;png_infop info_ptr0;do{//各种校验// png header len is 8 bytesCC_BREAK_IF(nDatalenPNGSIGSIZE);// check the data is png or notmemcpy(header,pData,PNGSIGSIZE);CC_BREAK_IF(png_sig_cmp(header,0,PNGSIGSIZE));// init png_struct//初始化结构体png_ptrpng_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);CC_BREAK_IF(!png_ptr);//初始化结构体// init png_infoinfo_ptrpng_create_info_struct(png_ptr);CC_BREAK_IF(!info_ptr);#if(CC_TARGET_PLATFORM!CC_PLATFORM_BADACC_TARGET_PLATFORM!CC_PLATFORM_NACL)CC_BREAK_IF(setjmp(png_jmpbuf(png_ptr)));#endif// set the read call back functiontImageSource imageSource;imageSource.data(unsignedchar*)pData;imageSource.sizenDatalen;imageSource.offset0;//设定了读取的回调函数png_set_read_fn(png_ptr,imageSource,pngReadCallback);// read png header info//读取png文件信息// read png file infopng_read_info(png_ptr,info_ptr);//获取了文件的宽高等信息m_nWidthpng_get_image_width(png_ptr,info_ptr);m_nHeightpng_get_image_height(png_ptr,info_ptr);m_nBitsPerComponentpng_get_bit_depth(png_ptr,info_ptr);png_uint_32 color_typepng_get_color_type(png_ptr,info_ptr);//CCLOG(color type %u, color_type);//将不同的png设置为RGB8888的格式。// force palette images to be expanded to 24-bit RGB// it may include alpha channelif(color_typePNG_COLOR_TYPE_PALETTE){png_set_palette_to_rgb(png_ptr);}// low-bit-depth grayscale images are to be expanded to 8 bitsif(color_typePNG_COLOR_TYPE_GRAYm_nBitsPerComponent8){png_set_expand_gray_1_2_4_to_8(png_ptr);}// expand any tRNS chunk data into a full alpha channelif(png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS)){png_set_tRNS_to_alpha(png_ptr);}// reduce images with 16-bit samples to 8 bitsif(m_nBitsPerComponent16){png_set_strip_16(png_ptr);}// expand grayscale images to RGBif(color_typePNG_COLOR_TYPE_GRAY||color_typePNG_COLOR_TYPE_GRAY_ALPHA){png_set_gray_to_rgb(png_ptr);}// read png data// m_nBitsPerComponent will always be 8m_nBitsPerComponent8;png_uint_32 rowbytes;//根据高度申请行数组每个元素代表一行每个元素的类型为png_bytep即unsigned char*png_bytep*row_pointers(png_bytep*)malloc(sizeof(png_bytep)*m_nHeight);png_read_update_info(png_ptr,info_ptr);//获取存储单行的像素的数据的大小字节也就是宽*4RGBA每个占一字节rowbytespng_get_rowbytes(png_ptr,info_ptr);//根据行数高和单行的数据大小申请存储空间每个元素类型为unsigned char*//用来存储rgba中的一个。即每4个元素构成一个完整的像素m_pDatanewunsignedchar;CC_BREAK_IF(!m_pData);//更新下行数组的节点将每行的起始位置赋值到行数组的节点for(unsignedshorti0;im_nHeight;i){row_pointersm_pDatai*rowbytes;}//按行读取数据png_read_image(png_ptr,row_pointers);//读取结束png_read_end(png_ptr,NULL);//获取单个像素点占用的字节。png_uint_32 channelrowbytes/m_nWidth;if(channel4)//这里必须为4,RGBA{m_bHasAlphatrue;//用unsigned int 类型来处理m_pData,这样一次就可以转到下一个像素点。unsignedint*tmp(unsignedint*)m_pData;for(unsignedshorti0;im_nHeight;i){for(unsignedintj0;jrowbytes;j4){//将RGBA转换下重新放到原位置宏定义在下面//这里需要注意的是tmp的位置和row_pointers其实是一样的。//只不过是类型不同tmp类型为unsigned int一次移动4个字节即一个像素。//row_pointers为png_bytep(unsigned char *)型一次移动1个字节。因此row_pointers//为row_pointers向后移动一个字节。这里每4个字节构成一个完整的像素点。*tmpCC_RGB_PREMULTIPLY_ALPHA(row_pointers,row_pointers,row_pointers,row_pointers);}}m_bPreMultitrue;}CC_SAFE_FREE(row_pointers);bRettrue;}while(0);if(png_ptr){png_destroy_read_struct(png_ptr,(info_ptr)?info_ptr:0,0);}returnbRet;}//非常重要的一个宏通过这个宏我们可以知道rgba在内存中的分布。// premultiply alpha, or the effect will wrong when want to use other pixel format in CCTexture2D,// such as RGB888, RGB5A1#defineCC_RGB_PREMULTIPLY_ALPHA(vr,vg,vb,va)\(unsigned)(((unsigned)((unsignedchar)(vr)*((unsignedchar)(va)1))8)|\((unsigned)((unsignedchar)(vg)*((unsignedchar)(va)1)8)8)|\((unsigned)((unsignedchar)(vb)*((unsignedchar)(va)1)8)16)|\((unsigned)(unsignedchar)(va)24))// on ios, we should use platform/ios/CCImage_ios.mm instead因此根据最后的这个宏CC_RGB_PREMULTIPLY_ALPHA我们就可以得到如下的函数用来获取指定点的颜色获取特定点颜色的方法cocos2d::ccColor4BgetImageColorOfPos(cocos2d::CCImage*pImage,cocos2d::CCPointpt){ccColor4B c{0,0,0,0};//cocos2dx使用的是openGL坐标系y坐标是从下到上递增的。//libpng读取png图片时是从上到下逐行读取的因此这里的纵坐标需要处理下。unsignedintxpt.x,ypImage-getHeight()-pt.y;intwidthpImage-getWidth();unsignedchar*data_pImage-getData();unsignedint*pixel(unsignedint*)data_;//以unsigned int来处理pixelpixel(y*width)x;//跳到指定的像素点。c.a(*pixel24)0xff;floatscale(c.a1.0f)/256;c.r*pixel0xff;c.rc.r/scale;c.g(*pixel8)0xff;c.gc.g/scale;c.b(*pixel16)0xff;c.bc.b/scale;returnc;}//代码示例CCImage*pImagenewCCImage();pImage-initWithImageFile(images.png,CCImage::kFmtPng);ccColor4B colorOfPosgetImageColorOfPos(pImage,ccp(0,0));pImage-release();备注由于获取颜色的代码中有很多数学运算比较复杂这里可以简化一下如果png上所有像素的透明度全部为255那么根据**(255 1)8 1**可以得出c.r*pixel0xff;c.g(*pixel8)0xff;c.b(*pixel16)0xff;c.a(*pixel24)0xff;这样可以简化掉相当多的运算。后续参考加深资料【 http://www.cnblogs.com/xiaoxiaoboke/archive/2012/02/13/2349765.html 】【 http://blog.csdn.net/honghaier/article/details/8032434 】