Merge pull request #440 from flyingpacer/savecrash

fixed #649 the user could save any domain of the render texture
This commit is contained in:
minggo 2011-08-02 03:16:20 -07:00
commit b9374663cd
2 changed files with 63 additions and 21 deletions

View File

@ -86,14 +86,28 @@ public:
/** saves the texture into a file */
// para szFilePath the absolute path to save
bool saveBuffer(const char *szFilePath);
/** saves the texture into a file. The format can be JPG or PNG */
bool saveBuffer(const char *name, int format);
// para x,y the lower left corner coordinates of the buffer to save
// pare nWidth,nHeight the size of the buffer to save
// when nWidth = 0 and nHeight = 0, the image size to save equals to buffer texture size
bool saveBuffer(const char *szFilePath, int x = 0, int y = 0, int nWidth = 0, int nHeight = 0);
/** saves the texture into a file.
// para name the file name to save
// para format the image format to save, here it supports kCCImageFormatPNG and kCCImageFormatJPG */
// para x,y the lower left corner coordinates of the buffer to save
// pare nWidth,nHeight the size of the buffer to save
// when nWidth = 0 and nHeight = 0, the image size to save equals to buffer texture size
bool saveBuffer(int format, const char *name, int x = 0, int y = 0, int nWidth = 0, int nHeight = 0);
/* get buffer as UIImage, can only save a render buffer which has a RGBA8888 pixel format */
CCData *getUIImageAsDataFromBuffer(int format);
bool getUIImageFromBuffer(CCImage *pImage);
/** save the buffer data to a CCImage */
// para pImage the CCImage to save
// para x,y the lower left corner coordinates of the buffer to save
// pare nWidth,nHeight the size of the buffer to save
// when nWidth = 0 and nHeight = 0, the image size to save equals to buffer texture size
bool getUIImageFromBuffer(CCImage *pImage, int x = 0, int y = 0, int nWidth = 0, int nHeight = 0);
protected:
GLuint m_uFBO;

View File

@ -216,12 +216,12 @@ void CCRenderTexture::clear(float r, float g, float b, float a)
this->end();
}
bool CCRenderTexture::saveBuffer(const char *szFilePath)
bool CCRenderTexture::saveBuffer(const char *szFilePath, int x, int y, int nWidth, int nHeight)
{
bool bRet = false;
CCImage *pImage = new CCImage();
if (pImage != NULL && getUIImageFromBuffer(pImage))
if (pImage != NULL && getUIImageFromBuffer(pImage, x, y, nWidth, nHeight))
{
bRet = pImage->saveToFile(szFilePath);
}
@ -229,14 +229,14 @@ bool CCRenderTexture::saveBuffer(const char *szFilePath)
CC_SAFE_DELETE(pImage);
return bRet;
}
bool CCRenderTexture::saveBuffer(const char *fileName, int format)
bool CCRenderTexture::saveBuffer(int format, const char *fileName, int x, int y, int nWidth, int nHeight)
{
bool bRet = false;
CCAssert(format == kCCImageFormatJPG || format == kCCImageFormatPNG,
"the image can only be saved as JPG or PNG format");
CCImage *pImage = new CCImage();
if (pImage != NULL && getUIImageFromBuffer(pImage))
if (pImage != NULL && getUIImageFromBuffer(pImage, x, y, nWidth, nHeight))
{
std::string fullpath = CCFileUtils::getWriteablePath() + fileName;
if (kCCImageFormatPNG == format)
@ -257,13 +257,46 @@ bool CCRenderTexture::saveBuffer(const char *fileName, int format)
}
/* get buffer as UIImage */
bool CCRenderTexture::getUIImageFromBuffer(CCImage *pImage)
bool CCRenderTexture::getUIImageFromBuffer(CCImage *pImage, int x, int y, int nWidth, int nHeight)
{
if (NULL == pImage)
if (NULL == pImage || NULL == m_pTexture)
{
return false;
}
CCSize s = m_pTexture->getContentSizeInPixels();
int tx = (int)s.width;
int ty = (int)s.height;
if (x < 0 || x >= tx || y < 0 || y >= ty)
{
return false;
}
if (nWidth < 0
|| nHeight < 0
|| (0 == nWidth && 0 != nHeight)
|| (0 == nHeight && 0 != nWidth))
{
return false;
}
// to get the image size to save
// if the saving image domain exeeds the buffer texture domain,
// it should be cut
int nSavedBufferWidth = nWidth;
int nSavedBufferHeight = nHeight;
if (0 == nWidth)
{
nSavedBufferWidth = tx;
}
if (0 == nHeight)
{
nSavedBufferHeight = ty;
}
nSavedBufferWidth = x + nSavedBufferWidth > tx ? (tx - x): nSavedBufferWidth;
nSavedBufferHeight = y + nSavedBufferHeight > ty ? (ty - y): nSavedBufferHeight;
GLubyte *pBuffer = NULL;
GLubyte *pTempData = NULL;
bool bRet = false;
@ -272,12 +305,7 @@ bool CCRenderTexture::getUIImageFromBuffer(CCImage *pImage)
{
CCAssert(m_ePixelFormat == kCCTexture2DPixelFormat_RGBA8888, "only RGBA8888 can be saved as image");
CCSize s = m_pTexture->getContentSizeInPixels();
int tx = (int)s.width;
int ty = (int)s.height;
CC_BREAK_IF(! (pBuffer = new GLubyte[tx * ty * 4]));
CC_BREAK_IF(! (pTempData = new GLubyte[tx * ty * 4]));
CC_BREAK_IF(! (pBuffer = new GLubyte[nSavedBufferWidth * nSavedBufferHeight * 4]));
// On some machines, like Samsung i9000, Motorola Defy,
// the dimension need to be a power of 2
@ -301,14 +329,14 @@ bool CCRenderTexture::getUIImageFromBuffer(CCImage *pImage)
// to get the actual texture data
// #640 the image read from rendertexture is upseted
for (int i = 0; i < ty; ++i)
for (int i = 0; i < nSavedBufferHeight; ++i)
{
memcpy(&pBuffer[i * tx * 4],
&pTempData[(ty - i - 1) * nReadBufferWidth * 4],
tx * 4);
memcpy(&pBuffer[i * nSavedBufferWidth * 4],
&pTempData[(y + nSavedBufferHeight - i - 1) * nReadBufferWidth * 4 + x * 4],
nSavedBufferWidth * 4);
}
bRet = pImage->initWithImageData(pBuffer, tx * ty * 4, CCImage::kFmtRawData, tx, ty, 8);
bRet = pImage->initWithImageData(pBuffer, nSavedBufferWidth * nSavedBufferHeight * 4, CCImage::kFmtRawData, nSavedBufferWidth, nSavedBufferHeight, 8);
} while (0);
CC_SAFE_DELETE_ARRAY(pBuffer);