2011-01-15 18:05:35 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2010 cocos2d-x.org
|
|
|
|
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
2011-06-23 16:31:04 +08:00
|
|
|
#include "CCImage.h"
|
2011-03-09 12:00:04 +08:00
|
|
|
#include "CCCommon.h"
|
2011-03-07 17:11:57 +08:00
|
|
|
#include "CCStdC.h"
|
2011-03-29 11:41:44 +08:00
|
|
|
#include "CCFileUtils.h"
|
2011-01-15 18:05:35 +08:00
|
|
|
#include "png.h"
|
2011-03-09 12:00:04 +08:00
|
|
|
#include <string>
|
2011-07-28 18:02:25 +08:00
|
|
|
#include <ctype.h>
|
2011-02-17 14:31:52 +08:00
|
|
|
|
2011-06-23 16:31:04 +08:00
|
|
|
#if (CC_TARGET_PLATFORM != CC_PLATFORM_IOS)
|
|
|
|
// on ios, we should use platform/ios/CCImage_ios.mm instead
|
|
|
|
|
2011-03-09 17:28:35 +08:00
|
|
|
#define QGLOBAL_H // defined for wophone
|
2011-01-15 18:05:35 +08:00
|
|
|
#include "jpeglib.h"
|
2011-02-17 14:31:52 +08:00
|
|
|
#undef QGLOBAL_H
|
2011-01-15 18:05:35 +08:00
|
|
|
|
2011-03-07 17:11:57 +08:00
|
|
|
#define CC_RGB_PREMULTIPLY_APLHA(vr, vg, vb, va) \
|
2011-03-28 10:44:14 +08:00
|
|
|
(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))
|
2011-01-15 18:05:35 +08:00
|
|
|
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-23 18:22:05 +08:00
|
|
|
NS_CC_BEGIN;
|
2011-01-15 18:05:35 +08:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2011-03-07 17:11:57 +08:00
|
|
|
// Impliment CCImage
|
2011-01-15 18:05:35 +08:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2011-03-07 17:11:57 +08:00
|
|
|
CCImage::CCImage()
|
2011-01-15 18:05:35 +08:00
|
|
|
: m_nWidth(0)
|
|
|
|
, m_nHeight(0)
|
|
|
|
, m_nBitsPerComponent(0)
|
2011-03-28 10:44:14 +08:00
|
|
|
, m_pData(0)
|
2011-01-15 18:05:35 +08:00
|
|
|
, m_bHasAlpha(false)
|
|
|
|
, m_bPreMulti(false)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-03-28 10:44:14 +08:00
|
|
|
CCImage::~CCImage()
|
|
|
|
{
|
|
|
|
CC_SAFE_DELETE_ARRAY(m_pData);
|
|
|
|
}
|
|
|
|
|
2011-03-07 17:11:57 +08:00
|
|
|
bool CCImage::initWithImageFile(const char * strPath, EImageFormat eImgFmt/* = eFmtPng*/)
|
2011-01-15 18:05:35 +08:00
|
|
|
{
|
2011-06-10 17:51:37 +08:00
|
|
|
CC_UNUSED_PARAM(eImgFmt);
|
2011-03-29 11:41:44 +08:00
|
|
|
CCFileData data(CCFileUtils::fullPathFromRelativePath(strPath), "rb");
|
2011-07-24 09:04:08 +08:00
|
|
|
return initWithImageData(data.getBuffer(), data.getSize(), eImgFmt);
|
2011-01-15 18:05:35 +08:00
|
|
|
}
|
|
|
|
|
2011-07-27 16:55:04 +08:00
|
|
|
bool CCImage::initWithImageData(void * pData,
|
|
|
|
int nDataLen,
|
|
|
|
EImageFormat eFmt/* = eSrcFmtPng*/,
|
|
|
|
int nWidth/* = 0*/,
|
|
|
|
int nHeight/* = 0*/,
|
|
|
|
int nBitsPerComponent/* = 8*/)
|
2011-01-15 18:05:35 +08:00
|
|
|
{
|
|
|
|
bool bRet = false;
|
|
|
|
do
|
|
|
|
{
|
2011-03-07 17:11:57 +08:00
|
|
|
CC_BREAK_IF(! pData || nDataLen <= 0);
|
2011-01-15 18:05:35 +08:00
|
|
|
|
2011-01-19 14:23:26 +08:00
|
|
|
if (kFmtPng == eFmt)
|
2011-01-15 18:05:35 +08:00
|
|
|
{
|
|
|
|
bRet = _initWithPngData(pData, nDataLen);
|
|
|
|
break;
|
|
|
|
}
|
2011-01-19 14:23:26 +08:00
|
|
|
else if (kFmtJpg == eFmt)
|
2011-01-15 18:05:35 +08:00
|
|
|
{
|
2011-02-17 16:16:50 +08:00
|
|
|
bRet = _initWithJpgData(pData, nDataLen);
|
2011-01-15 18:05:35 +08:00
|
|
|
break;
|
|
|
|
}
|
2011-07-27 16:55:04 +08:00
|
|
|
else if (kFmtRawData == eFmt)
|
|
|
|
{
|
|
|
|
bRet = _initWithRawData(pData, nDataLen, nWidth, nHeight, nBitsPerComponent);
|
|
|
|
break;
|
|
|
|
}
|
2011-01-15 18:05:35 +08:00
|
|
|
} while (0);
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2011-03-07 17:11:57 +08:00
|
|
|
bool CCImage::_initWithJpgData(void * data, int nSize)
|
2011-01-15 18:05:35 +08:00
|
|
|
{
|
|
|
|
/* 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 */
|
2011-03-28 10:44:14 +08:00
|
|
|
JSAMPROW row_pointer[1] = {0};
|
2011-01-15 18:05:35 +08:00
|
|
|
unsigned long location = 0;
|
|
|
|
unsigned int i = 0;
|
|
|
|
|
2011-03-28 10:44:14 +08:00
|
|
|
bool bRet = false;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
/* here we set up the standard libjpeg error handler */
|
|
|
|
cinfo.err = jpeg_std_error( &jerr );
|
2011-01-15 18:05:35 +08:00
|
|
|
|
2011-03-28 10:44:14 +08:00
|
|
|
/* setup decompression process and source, then read JPEG header */
|
|
|
|
jpeg_create_decompress( &cinfo );
|
2011-01-15 18:05:35 +08:00
|
|
|
|
2011-03-28 10:44:14 +08:00
|
|
|
/* this makes the library read from infile */
|
2011-08-17 11:18:58 +08:00
|
|
|
//TODO in some linux release it use libjpeg62 which does not support jpeg_mem_src instead of libjpeg8
|
|
|
|
// load memory data as stream
|
2011-08-19 13:07:50 +08:00
|
|
|
#if (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
|
2011-08-17 11:18:58 +08:00
|
|
|
FILE * source = fmemopen(data, nSize, "rb");
|
|
|
|
CC_BREAK_IF(!source);
|
|
|
|
jpeg_stdio_src(&cinfo, source);
|
|
|
|
fclose(source);
|
2011-08-19 13:07:50 +08:00
|
|
|
#else
|
2011-09-20 02:19:26 +08:00
|
|
|
jpeg_mem_src( &cinfo, (unsigned char *) data, nSize );
|
2011-08-19 13:07:50 +08:00
|
|
|
#endif
|
2011-01-15 18:05:35 +08:00
|
|
|
|
2011-03-28 10:44:14 +08:00
|
|
|
/* reading the image header which contains image information */
|
|
|
|
jpeg_read_header( &cinfo, true );
|
2011-01-15 18:05:35 +08:00
|
|
|
|
2011-03-28 10:44:14 +08:00
|
|
|
// we only support RGB or grayscale
|
|
|
|
if (cinfo.jpeg_color_space != JCS_RGB)
|
2011-01-15 18:05:35 +08:00
|
|
|
{
|
2011-03-28 10:44:14 +08:00
|
|
|
if (cinfo.jpeg_color_space == JCS_GRAYSCALE || cinfo.jpeg_color_space == JCS_YCbCr)
|
|
|
|
{
|
|
|
|
cinfo.out_color_space = JCS_RGB;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
2011-01-15 18:05:35 +08:00
|
|
|
}
|
|
|
|
|
2011-03-28 10:44:14 +08:00
|
|
|
/* Start decompression jpeg here */
|
|
|
|
jpeg_start_decompress( &cinfo );
|
2011-01-15 18:05:35 +08:00
|
|
|
|
2011-03-28 10:44:14 +08:00
|
|
|
/* init image info */
|
2011-06-10 17:51:37 +08:00
|
|
|
m_nWidth = (short)(cinfo.image_width);
|
|
|
|
m_nHeight = (short)(cinfo.image_height);
|
2011-03-28 10:44:14 +08:00
|
|
|
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]);
|
2011-01-15 18:05:35 +08:00
|
|
|
|
2011-03-28 10:44:14 +08:00
|
|
|
m_pData = new unsigned char[cinfo.output_width*cinfo.output_height*cinfo.output_components];
|
|
|
|
CC_BREAK_IF(! m_pData);
|
2011-01-15 18:05:35 +08:00
|
|
|
|
2011-03-28 10:44:14 +08:00
|
|
|
/* 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.num_components;i++)
|
|
|
|
m_pData[location++] = row_pointer[0][i];
|
|
|
|
}
|
2011-01-15 18:05:35 +08:00
|
|
|
|
2011-03-28 10:44:14 +08:00
|
|
|
jpeg_finish_decompress( &cinfo );
|
|
|
|
jpeg_destroy_decompress( &cinfo );
|
|
|
|
/* wrap up decompression, destroy objects, free pointers and close open files */
|
|
|
|
bRet = true;
|
|
|
|
} while (0);
|
2011-01-15 18:05:35 +08:00
|
|
|
|
2011-03-28 10:44:14 +08:00
|
|
|
CC_SAFE_DELETE_ARRAY(row_pointer[0]);
|
|
|
|
return bRet;
|
2011-01-15 18:05:35 +08:00
|
|
|
}
|
|
|
|
|
2011-03-07 17:11:57 +08:00
|
|
|
bool CCImage::_initWithPngData(void * pData, int nDatalen)
|
2011-01-15 18:05:35 +08:00
|
|
|
{
|
|
|
|
bool bRet = false;
|
|
|
|
png_byte header[8] = {0};
|
2011-03-28 10:44:14 +08:00
|
|
|
png_structp png_ptr = 0;
|
2011-02-23 18:22:05 +08:00
|
|
|
png_infop info_ptr = 0;
|
2011-03-28 10:44:14 +08:00
|
|
|
unsigned char * pImateData = 0;
|
2011-01-15 18:05:35 +08:00
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
// png header len is 8 bytes
|
2011-03-07 17:11:57 +08:00
|
|
|
CC_BREAK_IF(nDatalen < 8);
|
2011-01-15 18:05:35 +08:00
|
|
|
|
|
|
|
// check the data is png or not
|
|
|
|
memcpy(header, pData, 8);
|
2011-03-07 17:11:57 +08:00
|
|
|
CC_BREAK_IF(png_sig_cmp(header, 0, 8));
|
2011-01-15 18:05:35 +08:00
|
|
|
|
|
|
|
// init png_struct
|
2011-02-23 18:22:05 +08:00
|
|
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
|
2011-03-07 17:11:57 +08:00
|
|
|
CC_BREAK_IF(! png_ptr);
|
2011-01-15 18:05:35 +08:00
|
|
|
|
|
|
|
// init png_info
|
|
|
|
info_ptr = png_create_info_struct(png_ptr);
|
2011-09-20 02:19:26 +08:00
|
|
|
CC_BREAK_IF(!info_ptr);
|
|
|
|
#if CC_TARGET_PLATFORM != CC_PLATFORM_BADA
|
|
|
|
CC_BREAK_IF(setjmp(png_jmpbuf(png_ptr)));
|
|
|
|
#endif
|
2011-01-15 18:05:35 +08:00
|
|
|
// set the read call back function
|
|
|
|
tImageSource imageSource;
|
|
|
|
imageSource.data = (unsigned char*)pData;
|
|
|
|
imageSource.size = nDatalen;
|
|
|
|
imageSource.offset = 0;
|
|
|
|
png_set_read_fn(png_ptr, &imageSource, pngReadCallback);
|
|
|
|
|
|
|
|
// read png
|
|
|
|
// PNG_TRANSFORM_EXPAND: perform set_expand()
|
|
|
|
// PNG_TRANSFORM_PACKING: expand 1, 2 and 4-bit samples to bytes
|
|
|
|
// PNG_TRANSFORM_STRIP_16: strip 16-bit samples to 8 bits
|
|
|
|
// PNG_TRANSFORM_GRAY_TO_RGB: expand grayscale samples to RGB (or GA to RGBA)
|
|
|
|
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_PACKING
|
2011-02-23 18:22:05 +08:00
|
|
|
| PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_GRAY_TO_RGB, 0);
|
2011-01-15 18:05:35 +08:00
|
|
|
|
|
|
|
int color_type = 0;
|
|
|
|
png_uint_32 nWidth = 0;
|
|
|
|
png_uint_32 nHeight = 0;
|
|
|
|
int nBitsPerComponent = 0;
|
2011-02-23 18:22:05 +08:00
|
|
|
png_get_IHDR(png_ptr, info_ptr, &nWidth, &nHeight, &nBitsPerComponent, &color_type, 0, 0, 0);
|
2011-01-15 18:05:35 +08:00
|
|
|
|
|
|
|
// init image info
|
|
|
|
m_bPreMulti = true;
|
2011-09-20 02:19:26 +08:00
|
|
|
m_bHasAlpha = ( info_ptr->color_type & PNG_COLOR_MASK_ALPHA ) ? true : false;
|
2011-01-15 18:05:35 +08:00
|
|
|
|
|
|
|
// allocate memory and read data
|
|
|
|
int bytesPerComponent = 3;
|
|
|
|
if (m_bHasAlpha)
|
|
|
|
{
|
|
|
|
bytesPerComponent = 4;
|
|
|
|
}
|
2011-03-28 10:44:14 +08:00
|
|
|
pImateData = new unsigned char[nHeight * nWidth * bytesPerComponent];
|
|
|
|
CC_BREAK_IF(! pImateData);
|
|
|
|
|
2011-01-15 18:05:35 +08:00
|
|
|
png_bytep * rowPointers = png_get_rows(png_ptr, info_ptr);
|
|
|
|
|
|
|
|
// copy data to image info
|
|
|
|
int bytesPerRow = nWidth * bytesPerComponent;
|
|
|
|
if(m_bHasAlpha)
|
|
|
|
{
|
2011-03-28 10:44:14 +08:00
|
|
|
unsigned int *tmp = (unsigned int *)pImateData;
|
2011-01-15 18:05:35 +08:00
|
|
|
for(unsigned int i = 0; i < nHeight; i++)
|
|
|
|
{
|
|
|
|
for(int j = 0; j < bytesPerRow; j += 4)
|
|
|
|
{
|
2011-03-07 17:11:57 +08:00
|
|
|
*tmp++ = CC_RGB_PREMULTIPLY_APLHA( rowPointers[i][j], rowPointers[i][j + 1],
|
2011-01-15 18:05:35 +08:00
|
|
|
rowPointers[i][j + 2], rowPointers[i][j + 3] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (unsigned int j = 0; j < nHeight; ++j)
|
|
|
|
{
|
2011-03-28 10:44:14 +08:00
|
|
|
memcpy(pImateData + j * bytesPerRow, rowPointers[j], bytesPerRow);
|
2011-01-15 18:05:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-28 10:44:14 +08:00
|
|
|
m_nBitsPerComponent = nBitsPerComponent;
|
|
|
|
m_nHeight = (short)nHeight;
|
|
|
|
m_nWidth = (short)nWidth;
|
|
|
|
m_pData = pImateData;
|
|
|
|
pImateData = 0;
|
2011-01-15 18:05:35 +08:00
|
|
|
bRet = true;
|
|
|
|
} while (0);
|
|
|
|
|
2011-03-28 10:44:14 +08:00
|
|
|
CC_SAFE_DELETE_ARRAY(pImateData);
|
|
|
|
|
2011-03-17 14:26:36 +08:00
|
|
|
if (png_ptr)
|
2011-01-15 18:05:35 +08:00
|
|
|
{
|
2011-02-23 18:22:05 +08:00
|
|
|
png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0);
|
2011-01-15 18:05:35 +08:00
|
|
|
}
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2011-07-27 16:55:04 +08:00
|
|
|
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;
|
|
|
|
|
|
|
|
// only RGBA8888 surported
|
|
|
|
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);
|
|
|
|
|
2011-07-28 10:52:09 +08:00
|
|
|
if (NULL == png_ptr)
|
2011-07-27 16:55:04 +08:00
|
|
|
{
|
|
|
|
fclose(fp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
info_ptr = png_create_info_struct(png_ptr);
|
2011-07-28 10:52:09 +08:00
|
|
|
if (NULL == info_ptr)
|
2011-07-27 16:55:04 +08:00
|
|
|
{
|
|
|
|
fclose(fp);
|
|
|
|
png_destroy_write_struct(&png_ptr, NULL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-09-20 02:19:26 +08:00
|
|
|
//cjh if (setjmp(png_jmpbuf(png_ptr)))
|
|
|
|
// {
|
|
|
|
// fclose(fp);
|
|
|
|
// png_destroy_write_struct(&png_ptr, &info_ptr);
|
|
|
|
// break;
|
|
|
|
// }
|
2011-07-27 16:55:04 +08:00
|
|
|
|
|
|
|
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];
|
2011-07-28 10:52:09 +08:00
|
|
|
if (NULL == pTempData)
|
|
|
|
{
|
|
|
|
fclose(fp);
|
|
|
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
|
|
|
break;
|
|
|
|
}
|
2011-07-27 16:55:04 +08:00
|
|
|
|
|
|
|
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; /* 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 = m_nWidth; /* image width and height, in pixels */
|
|
|
|
cinfo.image_height = m_nHeight;
|
|
|
|
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 = m_nWidth * 3; /* JSAMPLEs per row in image_buffer */
|
|
|
|
|
|
|
|
if (m_bHasAlpha)
|
|
|
|
{
|
|
|
|
unsigned char *pTempData = new unsigned char[m_nWidth * m_nHeight * 3];
|
2011-07-28 10:52:09 +08:00
|
|
|
if (NULL == pTempData)
|
|
|
|
{
|
|
|
|
jpeg_finish_compress(&cinfo);
|
|
|
|
jpeg_destroy_compress(&cinfo);
|
|
|
|
fclose(outfile);
|
|
|
|
break;
|
|
|
|
}
|
2011-07-27 16:55:04 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-01-15 18:05:35 +08:00
|
|
|
NS_CC_END;
|
2011-01-19 14:23:26 +08:00
|
|
|
|
2011-06-23 16:31:04 +08:00
|
|
|
#endif // (CC_TARGET_PLATFORM != TARGET_OS_IPHONE)
|
|
|
|
/* ios/CCImage_ios.mm uses "mm" as the extension,
|
|
|
|
so we cannot inclue it in this CCImage.cpp.
|
|
|
|
It makes a little difference on ios */
|
|
|
|
|
2011-03-07 17:11:57 +08:00
|
|
|
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|
|
|
|
#include "win32/CCImage_win32.cpp"
|
2011-01-19 14:23:26 +08:00
|
|
|
#endif
|
2011-02-17 14:31:52 +08:00
|
|
|
|
2011-03-09 17:28:35 +08:00
|
|
|
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WOPHONE)
|
|
|
|
#include "wophone/CCImage_wophone.cpp"
|
2011-02-17 14:31:52 +08:00
|
|
|
#endif
|
2011-02-24 19:42:45 +08:00
|
|
|
|
2011-03-07 17:11:57 +08:00
|
|
|
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
|
|
|
#include "android/CCImage_android.cpp"
|
2011-02-24 19:42:45 +08:00
|
|
|
#endif
|
2011-09-19 17:53:45 +08:00
|
|
|
|
|
|
|
#if (CC_TARGET_PLATFORM == CC_PLATFORM_BADA)
|
|
|
|
#include "bada/CCImage_bada.cpp"
|
|
|
|
#endif
|