Merge pull request #7839 from minggo/revert-ccimage

Revert ccimage
This commit is contained in:
minggo 2014-08-21 16:21:54 +08:00
commit f94717de94
4 changed files with 522 additions and 136 deletions

View File

@ -214,6 +214,9 @@ LOCAL_EXPORT_LDLIBS := -lGLESv2 \
LOCAL_STATIC_LIBRARIES := cocos_freetype2_static
LOCAL_STATIC_LIBRARIES += chipmunk_static
LOCAL_STATIC_LIBRARIES += cocos_png_static
LOCAL_STATIC_LIBRARIES += cocos_jpeg_static
LOCAL_STATIC_LIBRARIES += cocos_tiff_static
LOCAL_STATIC_LIBRARIES += cocos_webp_static
LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dxandroid_static
# define the macro to compile through support/zip_support/ioapi.c
@ -228,3 +231,6 @@ $(call import-module,freetype2/prebuilt/android)
$(call import-module,chipmunk)
$(call import-module,platform/android)
$(call import-module,png/prebuilt/android)
$(call import-module,jpeg/prebuilt/android)
$(call import-module,tiff/prebuilt/android)
$(call import-module,webp/prebuilt/android)

View File

@ -269,6 +269,24 @@ To enable set it to a value different than 0. Disabled by default.
#define CC_USE_PHYSICS 1
#endif
/** Support JPEG or not. If your application don't use jpeg format picture, you can undefine this macro to save package size.
*/
#ifndef CC_USE_JPEG
#define CC_USE_JPEG 1
#endif // CC_USE_JPEG
/** Support TIFF or not. If your application don't use TIFF format picture, you can undefine this macro to save package size.
*/
#ifndef CC_USE_TIFF
#define CC_USE_TIFF 1
#endif // CC_USE_TIFF
/** Support webp or not. If your application don't use webp format picture, you can undefine this macro to save package size.
*/
#ifndef CC_USE_WEBP
#define CC_USE_WEBP 1
#endif // CC_USE_WEBP
/** Enable Script binding */
#ifndef CC_ENABLE_SCRIPT_BINDING
#define CC_ENABLE_SCRIPT_BINDING 1

View File

@ -30,6 +30,7 @@ THE SOFTWARE.
#include <ctype.h>
#include "base/CCData.h"
#include "base/ccConfig.h" // CC_USE_JPEG, CC_USE_TIFF, CC_USE_WEBP
extern "C"
{
@ -51,21 +52,31 @@ extern "C"
{
return strerror(errnum);
}
// int fputs(const char * __restrict, FILE * __restrict) __DARWIN_ALIAS(fputs);
int fputs$UNIX2003(const char *str, FILE *stream)
{
return fputs(str, stream);
}
#endif
#endif
#include "png.h"
#if CC_USE_TIFF
#include "tiffio.h"
#endif //CC_USE_TIFF
#include "base/etc1.h"
#if CC_USE_JPEG
#include "jpeglib.h"
#endif // CC_USE_JPEG
}
#include "base/s3tc.h"
#include "base/atitc.h"
#include "base/pvr.h"
#include "base/TGAlib.h"
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WP8) && (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT)
#if CC_USE_WEBP
#include "decode.h"
#endif // CC_USE_WEBP
#endif
#include "base/ccMacros.h"
#include "CCCommon.h"
#include "CCStdC.h"
@ -73,7 +84,6 @@ extern "C"
#include "base/CCConfiguration.h"
#include "base/ccUtils.h"
#include "base/ZipUtils.h"
#include "base/CCModuleManager.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "android/CCFileUtilsAndroid.h"
#endif
@ -90,6 +100,7 @@ NS_CC_BEGIN
namespace
{
static const int PVR_TEXTURE_FLAG_TYPE_MASK = 0xff;
static bool _PVRHaveAlphaPremultiplied = false;
// Values taken from PVRTexture.h from http://www.imgtec.com
@ -752,35 +763,172 @@ bool Image::isCompressed()
return Texture2D::getPixelFormatInfoMap().at(_renderFormat).compressed;
}
namespace
{
/*
* ERROR HANDLING:
*
* The JPEG library's standard error handler (jerror.c) is divided into
* several "methods" which you can override individually. This lets you
* adjust the behavior without duplicating a lot of code, which you might
* have to update with each future release.
*
* We override the "error_exit" method so that control is returned to the
* library's caller when a fatal error occurs, rather than calling exit()
* as the standard error_exit method does.
*
* We use C's setjmp/longjmp facility to return control. This means that the
* routine which calls the JPEG library must first execute a setjmp() call to
* establish the return point. We want the replacement error_exit to do a
* longjmp(). But we need to make the setjmp buffer accessible to the
* error_exit routine. To do this, we make a private extension of the
* standard JPEG error handler object. (If we were using C++, we'd say we
* were making a subclass of the regular error handler.)
*
* Here's the extended error handler struct:
*/
#if CC_USE_JPEG
struct MyErrorMgr
{
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
};
typedef struct MyErrorMgr * MyErrorPtr;
/*
* Here's the routine that will replace the standard error_exit method:
*/
METHODDEF(void)
myErrorExit(j_common_ptr cinfo)
{
/* cinfo->err really points to a MyErrorMgr struct, so coerce pointer */
MyErrorPtr myerr = (MyErrorPtr) cinfo->err;
/* Always display the message. */
/* We could postpone this until after returning, if we chose. */
/* internal message function cann't show error message in some platforms, so we rewrite it here.
* edit it if has version confilict.
*/
//(*cinfo->err->output_message) (cinfo);
char buffer[JMSG_LENGTH_MAX];
(*cinfo->err->format_message) (cinfo, buffer);
CCLOG("jpeg error: %s", buffer);
/* Return control to the setjmp point */
longjmp(myerr->setjmp_buffer, 1);
}
#endif // CC_USE_JPEG
}
bool Image::initWithJpgData(const unsigned char * data, ssize_t dataLen)
{
_hasPremultipliedAlpha = false;
JPEGModule *jpegModule = static_cast<JPEGModule*>(ModuleManager::getModule("jpeg"));
if (jpegModule)
#if CC_USE_JPEG
/* these are standard libjpeg structures for reading(decompression) */
struct jpeg_decompress_struct cinfo;
/* We use our private extension JPEG error handler.
* Note that this struct must live as long as the main JPEG parameter
* struct, to avoid dangling-pointer problems.
*/
struct MyErrorMgr jerr;
/* libjpeg data structure for storing one row, that is, scanline of an image */
JSAMPROW row_pointer[1] = {0};
unsigned long location = 0;
unsigned int i = 0;
bool ret = false;
do
{
DataFromModule dataFromJPEGInit;
bool result = jpegModule->initWithJPEGData(data, dataLen, dataFromJPEGInit);
_width = dataFromJPEGInit.width;
_height = dataFromJPEGInit.height;
_renderFormat = dataFromJPEGInit.renderFormat;
_dataLen = dataFromJPEGInit.dataLength;
_data = dataFromJPEGInit.data;
return result;
}
else
/* We set up the normal JPEG error routines, then override error_exit. */
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = myErrorExit;
/* Establish the setjmp return context for MyErrorExit to use. */
if (setjmp(jerr.setjmp_buffer))
{
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
jpeg_destroy_decompress(&cinfo);
break;
}
/* setup decompression process and source, then read JPEG header */
jpeg_create_decompress( &cinfo );
#ifndef CC_TARGET_QT5
jpeg_mem_src(&cinfo, const_cast<unsigned char*>(data), dataLen);
#endif /* CC_TARGET_QT5 */
/* reading the image header which contains image information */
#if (JPEG_LIB_VERSION >= 90)
// libjpeg 0.9 adds stricter types.
jpeg_read_header(&cinfo, TRUE);
#else
jpeg_read_header(&cinfo, TRUE);
#endif
// we only support RGB or grayscale
if (cinfo.jpeg_color_space == JCS_GRAYSCALE)
{
_renderFormat = Texture2D::PixelFormat::I8;
}else
{
cinfo.out_color_space = JCS_RGB;
_renderFormat = Texture2D::PixelFormat::RGB888;
}
/* Start decompression jpeg here */
jpeg_start_decompress( &cinfo );
/* init image info */
_width = cinfo.output_width;
_height = cinfo.output_height;
_hasPremultipliedAlpha = false;
row_pointer[0] = static_cast<unsigned char*>(malloc(cinfo.output_width*cinfo.output_components * sizeof(unsigned char)));
CC_BREAK_IF(! row_pointer[0]);
_dataLen = cinfo.output_width*cinfo.output_height*cinfo.output_components;
_data = static_cast<unsigned char*>(malloc(_dataLen * sizeof(unsigned char)));
CC_BREAK_IF(! _data);
/* now actually read the jpeg into the raw buffer */
/* read one scan line at a time */
while (cinfo.output_scanline < cinfo.output_height)
{
jpeg_read_scanlines( &cinfo, row_pointer, 1 );
for (i=0; i<cinfo.output_width*cinfo.output_components; i++)
{
_data[location++] = row_pointer[0][i];
}
}
/* When read image file with broken data, jpeg_finish_decompress() may cause error.
* Besides, jpeg_destroy_decompress() shall deallocate and release all memory associated
* with the decompression object.
* So it doesn't need to call jpeg_finish_decompress().
*/
//jpeg_finish_decompress( &cinfo );
jpeg_destroy_decompress( &cinfo );
/* wrap up decompression, destroy objects, free pointers and close open files */
ret = true;
} while (0);
if (row_pointer[0] != nullptr)
{
CCLOG("jpeg module is not enabled");
return false;
}
free(row_pointer[0]);
};
return ret;
#else
return false;
#endif // CC_USE_JPEG
}
bool Image::initWithPngData(const unsigned char * data, ssize_t dataLen)
{
// length of bytes to check if it is a valid png file
#define PNGSIGSIZE 8
bool bRet = false;
bool ret = false;
png_byte header[PNGSIGSIZE] = {0};
png_structp png_ptr = 0;
png_infop info_ptr = 0;
@ -849,7 +997,8 @@ bool Image::initWithPngData(const unsigned char * data, ssize_t dataLen)
}
// Expanded earlier for grayscale, now take care of palette and rgb
if (bit_depth < 8) {
if (bit_depth < 8)
{
png_set_packing(png_ptr);
}
// update info
@ -883,7 +1032,7 @@ bool Image::initWithPngData(const unsigned char * data, ssize_t dataLen)
_dataLen = rowbytes * _height;
_data = static_cast<unsigned char*>(malloc(_dataLen * sizeof(unsigned char)));
if(!_data)
if (!_data)
{
if (row_pointers != nullptr)
{
@ -915,38 +1064,192 @@ bool Image::initWithPngData(const unsigned char * data, ssize_t dataLen)
free(row_pointers);
}
bRet = true;
ret = true;
} while (0);
if (png_ptr)
{
png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0);
}
return bRet;
return ret;
}
#if CC_USE_TIFF
namespace
{
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 >= (uint64)isource->size);
ret = isource->offset = (uint32)off;
}
else if (whence == SEEK_CUR)
{
CC_BREAK_IF(isource->offset + off >= (uint64)isource->size);
ret = isource->offset += (uint32)off;
}
else if (whence == SEEK_END)
{
CC_BREAK_IF(off >= (uint64)isource->size);
ret = isource->offset = (uint32)(isource->size-1 - off);
}
else
{
CC_BREAK_IF(off >= (uint64)isource->size);
ret = isource->offset = (uint32)off;
}
} while (0);
return ret;
}
static uint64 tiffSizeProc(thandle_t fd)
{
tImageSource* imageSrc = (tImageSource*)fd;
return imageSrc->size;
}
static int tiffCloseProc(thandle_t fd)
{
CC_UNUSED_PARAM(fd);
return 0;
}
static int tiffMapProc(thandle_t fd, void** base, toff_t* size)
{
CC_UNUSED_PARAM(fd);
CC_UNUSED_PARAM(base);
CC_UNUSED_PARAM(size);
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);
}
}
#endif // CC_USE_TIFF
bool Image::initWithTiffData(const unsigned char * data, ssize_t dataLen)
{
_hasPremultipliedAlpha = true;
TIFFModule *tiffModule = static_cast<TIFFModule*>(ModuleManager::getModule("tiff"));
if (tiffModule)
#if CC_USE_TIFF
bool ret = false;
do
{
DataFromModule dataFromTIFFInit;
bool result = tiffModule->initWithTIFFData(data, dataLen, dataFromTIFFInit);
_width = dataFromTIFFInit.width;
_height = dataFromTIFFInit.height;
_renderFormat = dataFromTIFFInit.renderFormat;
_dataLen = dataFromTIFFInit.dataLength;
_data = dataFromTIFFInit.data;
// set the read call back function
tImageSource imageSource;
imageSource.data = data;
imageSource.size = dataLen;
imageSource.offset = 0;
TIFF* tif = TIFFClientOpen("file.tif", "r", (thandle_t)&imageSource,
tiffReadProc, tiffWriteProc,
tiffSeekProc, tiffCloseProc, tiffSizeProc,
tiffMapProc,
tiffUnmapProc);
CC_BREAK_IF(nullptr == tif);
uint32 w = 0, h = 0;
uint16 bitsPerSample = 0, samplePerPixel = 0, planarConfig = 0;
size_t npixels = 0;
return result;
}
else
{
CCLOG("tiff module is not enabled");
return false;
}
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;
_renderFormat = Texture2D::PixelFormat::RGBA8888;
_width = w;
_height = h;
_dataLen = npixels * sizeof (uint32);
_data = static_cast<unsigned char*>(malloc(_dataLen * sizeof(unsigned char)));
uint32* raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
if (raster != nullptr)
{
if (TIFFReadRGBAImageOriented(tif, w, h, raster, ORIENTATION_TOPLEFT, 0))
{
/* the raster data is pre-multiplied by the alpha component
after invoking TIFFReadRGBAImageOriented*/
_hasPremultipliedAlpha = true;
memcpy(_data, raster, npixels*sizeof (uint32));
}
_TIFFfree(raster);
}
TIFFClose(tif);
ret = true;
} while (0);
return ret;
#else
CCLOG("tiff is not enabled, please enalbe it in ccConfig.h");
return false;
#endif
}
namespace
@ -1067,7 +1370,7 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen)
{
switch (formatFlags) {
case PVR2TexturePixelFormat::PVRTC2BPP_RGBA:
if(!Configuration::getInstance()->supportsPVRTC())
if (!Configuration::getInstance()->supportsPVRTC())
{
CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder");
_unpack = true;
@ -1081,7 +1384,7 @@ bool Image::initWithPVRv2Data(const unsigned char * data, ssize_t dataLen)
heightBlocks = height / 4;
break;
case PVR2TexturePixelFormat::PVRTC4BPP_RGBA:
if(!Configuration::getInstance()->supportsPVRTC())
if (!Configuration::getInstance()->supportsPVRTC())
{
CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder");
_unpack = true;
@ -1221,7 +1524,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen)
{
case PVR3TexturePixelFormat::PVRTC2BPP_RGB :
case PVR3TexturePixelFormat::PVRTC2BPP_RGBA :
if(!Configuration::getInstance()->supportsPVRTC())
if (!Configuration::getInstance()->supportsPVRTC())
{
CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder");
_unpack = true;
@ -1236,7 +1539,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen)
break;
case PVR3TexturePixelFormat::PVRTC4BPP_RGB :
case PVR3TexturePixelFormat::PVRTC4BPP_RGBA :
if(!Configuration::getInstance()->supportsPVRTC())
if (!Configuration::getInstance()->supportsPVRTC())
{
CCLOG("cocos2d: Hardware PVR decoder not present. Using software decoder");
_unpack = true;
@ -1250,7 +1553,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen)
heightBlocks = height / 4;
break;
case PVR3TexturePixelFormat::ETC1:
if(!Configuration::getInstance()->supportsETC())
if (!Configuration::getInstance()->supportsETC())
{
CCLOG("cocos2d: Hardware ETC1 decoder not present. Using software decoder");
int bytePerPixel = 3;
@ -1268,7 +1571,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen)
heightBlocks = height / 4;
break;
case PVR3TexturePixelFormat::BGRA8888:
if( ! Configuration::getInstance()->supportsBGRA8888())
if (! Configuration::getInstance()->supportsBGRA8888())
{
CCLOG("cocos2d: Image. BGRA8888 not supported on this device");
return false;
@ -1308,7 +1611,7 @@ bool Image::initWithPVRv3Data(const unsigned char * data, ssize_t dataLen)
height = MAX(height >> 1, 1);
}
if(_unpack)
if (_unpack)
{
_data = _mipmaps[0].address;
_dataLen = _mipmaps[0].len;
@ -1322,7 +1625,7 @@ bool Image::initWithETCData(const unsigned char * data, ssize_t dataLen)
const etc1_byte* header = static_cast<const etc1_byte*>(data);
//check the data
if(!etc1_pkm_is_valid(header))
if (! etc1_pkm_is_valid(header))
{
return false;
}
@ -1330,12 +1633,12 @@ bool Image::initWithETCData(const unsigned char * data, ssize_t dataLen)
_width = etc1_pkm_get_width(header);
_height = etc1_pkm_get_height(header);
if( 0 == _width || 0 == _height )
if (0 == _width || 0 == _height)
{
return false;
}
if(Configuration::getInstance()->supportsETC())
if (Configuration::getInstance()->supportsETC())
{
//old opengl version has no define for GL_ETC1_RGB8_OES, add macro to make compiler happy.
#ifdef GL_ETC1_RGB8_OES
@ -1727,35 +2030,53 @@ bool Image::initWithPVRData(const unsigned char * data, ssize_t dataLen)
bool Image::initWithWebpData(const unsigned char * data, ssize_t dataLen)
{
#if CC_USE_WEBP
bool ret = false;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
CCLOG("WEBP image format not supported on WinRT or WP8");
return false;
#else
WEBPModule *webpModule = static_cast<WEBPModule*>(ModuleManager::getModule("webp"));
if (webpModule)
{
DataFromModule dataFromWEBPInit;
bool result = webpModule->initWithWEBPData(data, dataLen, dataFromWEBPInit);
_width = dataFromWEBPInit.width;
_height = dataFromWEBPInit.height;
_renderFormat = dataFromWEBPInit.renderFormat;
_dataLen = dataFromWEBPInit.dataLength;
_data = dataFromWEBPInit.data;
do
{
WebPDecoderConfig config;
if (WebPInitDecoderConfig(&config) == 0) break;
if (WebPGetFeatures(static_cast<const uint8_t*>(data), dataLen, &config.input) != VP8_STATUS_OK) break;
if (config.input.width == 0 || config.input.height == 0) break;
return result;
}
else
{
CCLOG("webp module is not enabled");
return false;
}
#endif
config.output.colorspace = MODE_RGBA;
_renderFormat = Texture2D::PixelFormat::RGBA8888;
_width = config.input.width;
_height = config.input.height;
_dataLen = _width * _height * 4;
_data = static_cast<unsigned char*>(malloc(_dataLen * sizeof(unsigned char)));
config.output.u.RGBA.rgba = static_cast<uint8_t*>(_data);
config.output.u.RGBA.stride = _width * 4;
config.output.u.RGBA.size = _dataLen;
config.output.is_external_memory = 1;
if (WebPDecode(static_cast<const uint8_t*>(data), dataLen, &config) != VP8_STATUS_OK)
{
free(_data);
_data = nullptr;
break;
}
ret = true;
} while (0);
#endif // (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
return ret;
#else
CCLOG("webp is not enabled, please enable it in ccConfig.h");
return false;
#endif // CC_USE_WEBP
}
bool Image::initWithRawData(const unsigned char * data, ssize_t dataLen, int width, int height, int bitsPerComponent, bool preMulti)
{
bool bRet = false;
bool ret = false;
do
{
CC_BREAK_IF(0 == width || 0 == height);
@ -1772,15 +2093,15 @@ bool Image::initWithRawData(const unsigned char * data, ssize_t dataLen, int wid
CC_BREAK_IF(! _data);
memcpy(_data, data, _dataLen);
bRet = true;
ret = true;
} while (0);
return bRet;
return ret;
}
#if (CC_TARGET_PLATFORM != CC_PLATFORM_IOS)
bool Image::saveToFile(const std::string& filename, bool bIsToRGB)
bool Image::saveToFile(const std::string& filename, bool isToRGB)
{
//only support for Texture2D::PixelFormat::RGB888 or Texture2D::PixelFormat::RGBA8888 uncompressed data
if (isCompressed() || (_renderFormat != Texture2D::PixelFormat::RGB888 && _renderFormat != Texture2D::PixelFormat::RGBA8888))
@ -1789,7 +2110,7 @@ bool Image::saveToFile(const std::string& filename, bool bIsToRGB)
return false;
}
bool bRet = false;
bool ret = false;
do
{
@ -1804,7 +2125,7 @@ bool Image::saveToFile(const std::string& filename, bool bIsToRGB)
if (std::string::npos != strLowerCasePath.find(".png"))
{
CC_BREAK_IF(!saveImageToPNG(filename, bIsToRGB));
CC_BREAK_IF(!saveImageToPNG(filename, isToRGB));
}
else if (std::string::npos != strLowerCasePath.find(".jpg"))
{
@ -1815,16 +2136,16 @@ bool Image::saveToFile(const std::string& filename, bool bIsToRGB)
break;
}
bRet = true;
ret = true;
} while (0);
return bRet;
return ret;
}
#endif
bool Image::saveImageToPNG(const std::string& filePath, bool isToRGB)
{
bool bRet = false;
bool ret = false;
do
{
FILE *fp;
@ -1903,8 +2224,8 @@ bool Image::saveImageToPNG(const std::string& filePath, bool isToRGB)
{
if (isToRGB)
{
unsigned char *pTempData = static_cast<unsigned char*>(malloc(_width * _height * 3 * sizeof(unsigned char)));
if (nullptr == pTempData)
unsigned char *tempData = static_cast<unsigned char*>(malloc(_width * _height * 3 * sizeof(unsigned char)));
if (nullptr == tempData)
{
fclose(fp);
png_destroy_write_struct(&png_ptr, &info_ptr);
@ -1918,15 +2239,15 @@ bool Image::saveImageToPNG(const std::string& filePath, bool isToRGB)
{
for (int j = 0; j < _width; ++j)
{
pTempData[(i * _width + j) * 3] = _data[(i * _width + j) * 4];
pTempData[(i * _width + j) * 3 + 1] = _data[(i * _width + j) * 4 + 1];
pTempData[(i * _width + j) * 3 + 2] = _data[(i * _width + j) * 4 + 2];
tempData[(i * _width + j) * 3] = _data[(i * _width + j) * 4];
tempData[(i * _width + j) * 3 + 1] = _data[(i * _width + j) * 4 + 1];
tempData[(i * _width + j) * 3 + 2] = _data[(i * _width + j) * 4 + 2];
}
}
for (int i = 0; i < (int)_height; i++)
{
row_pointers[i] = (png_bytep)pTempData + i * _width * 3;
row_pointers[i] = (png_bytep)tempData + i * _width * 3;
}
png_write_image(png_ptr, row_pointers);
@ -1934,9 +2255,9 @@ bool Image::saveImageToPNG(const std::string& filePath, bool isToRGB)
free(row_pointers);
row_pointers = nullptr;
if (pTempData != nullptr)
if (tempData != nullptr)
{
free(pTempData);
free(tempData);
}
}
else
@ -1962,22 +2283,94 @@ bool Image::saveImageToPNG(const std::string& filePath, bool isToRGB)
fclose(fp);
bRet = true;
ret = true;
} while (0);
return bRet;
return ret;
}
bool Image::saveImageToJPG(const std::string& filePath)
{
JPEGModule *jpegModule = static_cast<JPEGModule*>(ModuleManager::getModule("jpeg"));
if (jpegModule)
#if CC_USE_JPEG
bool ret = false;
do
{
return jpegModule->saveImage(filePath, this);
}
else
{
CCLOG("jpeg module is not enabled");
return false;
}
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(filePath.c_str(), "wb")) == nullptr);
jpeg_stdio_dest(&cinfo, outfile);
cinfo.image_width = _width; /* image width and height, in pixels */
cinfo.image_height = _height;
cinfo.input_components = 3; /* # of color components per pixel */
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, 90, TRUE);
jpeg_start_compress(&cinfo, TRUE);
row_stride = _width * 3; /* JSAMPLEs per row in image_buffer */
if (hasAlpha())
{
unsigned char *tempData = static_cast<unsigned char*>(malloc(_width * _height * 3 * sizeof(unsigned char)));
if (nullptr == tempData)
{
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
fclose(outfile);
break;
}
for (int i = 0; i < _height; ++i)
{
for (int j = 0; j < _width; ++j)
{
tempData[(i * _width + j) * 3] = _data[(i * _width + j) * 4];
tempData[(i * _width + j) * 3 + 1] = _data[(i * _width + j) * 4 + 1];
tempData[(i * _width + j) * 3 + 2] = _data[(i * _width + j) * 4 + 2];
}
}
while (cinfo.next_scanline < cinfo.image_height)
{
row_pointer[0] = & tempData[cinfo.next_scanline * row_stride];
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
if (tempData != nullptr)
{
free(tempData);
}
}
else
{
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = & _data[cinfo.next_scanline * row_stride];
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
}
jpeg_finish_compress(&cinfo);
fclose(outfile);
jpeg_destroy_compress(&cinfo);
ret = true;
} while (0);
return ret;
#else
CCLOG("jpeg is not enabled, please enable it in ccConfig.h");
return false;
#endif // CC_USE_JPEG
}
void Image::premultipliedAlpha()
@ -1994,6 +2387,7 @@ void Image::premultipliedAlpha()
_hasPremultipliedAlpha = true;
}
void Image::setPVRImagesHavePremultipliedAlpha(bool haveAlphaPremultiplied)
{
_PVRHaveAlphaPremultiplied = haveAlphaPremultiplied;

View File

@ -26,8 +26,6 @@ THE SOFTWARE.
#ifndef __CC_IMAGE_H__
#define __CC_IMAGE_H__
#include <functional>
#include <string>
#include "base/CCRef.h"
#include "renderer/CCTexture2D.h"
@ -169,7 +167,6 @@ protected:
void premultipliedAlpha();
protected:
/**
@brief Determine how many mipmaps can we have.
@ -215,35 +212,6 @@ protected:
bool isATITC(const unsigned char *data, ssize_t dataLen);
};
/* Data returned from jpeg/tiff/webp module initialization
*/
typedef struct DataFromModule
{
Texture2D::PixelFormat renderFormat;
int width;
int height;
ssize_t dataLength;
unsigned char* data;
bool hasPremultiAlpha;
} DataFromModule;
struct JPEGModule
{
std::function<bool(const std::string &filePath, Image *image)> saveImage;
std::function<bool(const unsigned char*, ssize_t, DataFromModule &dataFromJPEGInit)> initWithJPEGData;
};
struct TIFFModule
{
std::function<bool(const unsigned char*, ssize_t, DataFromModule &dataFromJPEGInit)> initWithTIFFData;
};
struct WEBPModule
{
std::function<bool(const unsigned char*, ssize_t, DataFromModule &dataFromJPEGInit)> initWithWEBPData;
};
// end of platform group
/// @}