mirror of https://github.com/axmolengine/axmol.git
commit
f94717de94
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
/// @}
|
||||
|
||||
|
|
Loading…
Reference in New Issue