open source
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,312 @@
|
||||
/**
|
||||
@file JCGifImg.h
|
||||
@brief
|
||||
@author James
|
||||
@version 1.0
|
||||
@date 2016_7_13
|
||||
*/
|
||||
|
||||
#ifndef __JCGifImg_H__
|
||||
#define __JCGifImg_H__
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
namespace laya
|
||||
{
|
||||
/*
|
||||
* 图像扩展参数
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bool active; //本结构中的其它参数是否可用
|
||||
unsigned int disposalMethod; //处理方法(见gif89a.doc,可忽略)
|
||||
bool userInputFlag; //是否期待用户输入
|
||||
bool trsFlag; //是否有透明色
|
||||
unsigned short delayTime; //延时时间(单位1/100秒)
|
||||
unsigned int trsColorIndex; //透明色调色板索引
|
||||
}GCTRLEXT;
|
||||
|
||||
/*
|
||||
* 一帧图象的参数
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned short imageLPos; //图象左边沿到逻辑屏幕的距离(单位像素)
|
||||
unsigned short imageTPos; //图象上边沿到逻辑屏幕的距离(单位像素)
|
||||
unsigned short imageWidth; //图象的宽度(单位像素)
|
||||
unsigned short imageHeight; //图象的高度(单位像素)
|
||||
bool lFlag; //是否有局部调色板(决定其他调色板参数是否有效)
|
||||
bool interlaceFlag; //图象数据是否交错
|
||||
bool sortFlag; //局部调色板数据是否按优先排序
|
||||
unsigned int lSize; //局部调色板大小(有多少个实际入口)
|
||||
unsigned char* pColorTable; //指向局部调色板的指针(256个入口,每个入口三字节)
|
||||
unsigned char* dataBuf; //调色板格式请参看gif89a.doc
|
||||
GCTRLEXT ctrlExt; //图象数据指针
|
||||
}FRAME; //图象扩展参数(与透明背景和动画有关)
|
||||
typedef FRAME *LPFRAME;
|
||||
typedef const FRAME *LPCFRAME;
|
||||
|
||||
/*
|
||||
* GIF文件的全局参数
|
||||
*/
|
||||
typedef struct
|
||||
{ //GIF文件的全局参数
|
||||
unsigned int frames; //文件中图象帧数
|
||||
unsigned short scrWidth, scrHeight; //逻辑屏幕的宽度和高度(单位像素)
|
||||
bool gFlag; //是否有全局调色板(决定其他调色板参数是否有效)
|
||||
unsigned int colorRes; //色彩分辨率(不使用)
|
||||
bool gSort; //全局调色板是否按优先排序
|
||||
unsigned int gSize; //全局调色板大小(有多少个实际入口)
|
||||
unsigned int BKColorIdx; //背景色的调色板索引
|
||||
unsigned int pixelAspectRatio; //像素长宽比例
|
||||
unsigned char *gColorTable; //指向全局调色板的指针(256个入口,每个入口三字节)
|
||||
}GLOBAL_INFO; //调色板格式请参看gif89a.doc
|
||||
typedef GLOBAL_INFO *LPGLOBAL_INFO;
|
||||
typedef const GLOBAL_INFO *LPCGLOBAL_INFO;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned int len;
|
||||
unsigned char* p;
|
||||
}STRING_TABLE_ENTRY;
|
||||
|
||||
|
||||
class BufferIOStream
|
||||
{
|
||||
public:
|
||||
BufferIOStream(char* p_sBuffer, int p_nBufferSize)
|
||||
{
|
||||
m_pBuffer = p_sBuffer;
|
||||
m_nSize = p_nBufferSize;
|
||||
m_nCurPos = 0;
|
||||
}
|
||||
~BufferIOStream()
|
||||
{
|
||||
close();
|
||||
}
|
||||
bool read(char* p_pRet, int p_nSize)
|
||||
{
|
||||
if ((m_nCurPos + p_nSize) > m_nSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
char* pCur = m_pBuffer + m_nCurPos;
|
||||
memcpy(p_pRet, pCur, p_nSize);
|
||||
m_nCurPos += p_nSize;
|
||||
return true;
|
||||
}
|
||||
bool good()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
int tellg()
|
||||
{
|
||||
return m_nCurPos;
|
||||
}
|
||||
void close()
|
||||
{
|
||||
/*直接拿的指针应该在外面释放
|
||||
if( m_pBuffer != NULL )
|
||||
{
|
||||
delete[] m_pBuffer;
|
||||
m_pBuffer = NULL;
|
||||
}
|
||||
*/
|
||||
m_nSize = 0;
|
||||
m_nCurPos = 0;
|
||||
}
|
||||
bool eof()
|
||||
{
|
||||
return (m_nCurPos >= m_nSize);
|
||||
}
|
||||
void seekg(int p_nPos)
|
||||
{
|
||||
m_nCurPos = p_nPos;
|
||||
}
|
||||
void seekg(int p_nPos, int p_nMark)
|
||||
{
|
||||
if (p_nMark == 0)
|
||||
{
|
||||
m_nCurPos = 0 + p_nPos;
|
||||
}
|
||||
else if (p_nMark == 1)
|
||||
{
|
||||
m_nCurPos += p_nPos;
|
||||
}
|
||||
else if (p_nMark == 2)
|
||||
{
|
||||
m_nCurPos = m_nSize + p_nPos;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
char* m_pBuffer;
|
||||
int m_nSize;
|
||||
int m_nCurPos;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gif类
|
||||
*/
|
||||
class GifLoader
|
||||
{
|
||||
public:
|
||||
|
||||
/** @brief
|
||||
* 构造函数
|
||||
*/
|
||||
GifLoader(void);
|
||||
|
||||
/** @brief 构造函数
|
||||
* @param[in] 文件名字
|
||||
* @param[in] 是否一次性读取完成
|
||||
* @return
|
||||
*/
|
||||
GifLoader(const char* p_sFileName, bool p_bInMem);
|
||||
|
||||
|
||||
GifLoader(unsigned char* p_pBuffer, int p_nBufferSize);
|
||||
|
||||
/** @brief
|
||||
* 析构函数
|
||||
*/
|
||||
~GifLoader(void);
|
||||
|
||||
/** @brief
|
||||
* 重载错误符号
|
||||
*/
|
||||
bool operator!(void);
|
||||
|
||||
/** @brief 打开图片
|
||||
* @param[in] 图片路径
|
||||
* @param[in] 是否一次性读取完成
|
||||
* @return
|
||||
*/
|
||||
bool open(const char* p_sFileName, bool p_bInMem);
|
||||
|
||||
/** @brief 关闭
|
||||
*
|
||||
*/
|
||||
void close(void);
|
||||
|
||||
/** @brief 获得版本
|
||||
*
|
||||
*/
|
||||
char* getVersion(void);
|
||||
|
||||
/** @brief 获得下一帧
|
||||
*
|
||||
*/
|
||||
LPCFRAME getNextFrame(void);
|
||||
|
||||
/** @brief 获得图片的全局信息
|
||||
*
|
||||
*/
|
||||
LPCGLOBAL_INFO getGlobalInfo();
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public:
|
||||
|
||||
|
||||
|
||||
//从内存读取的方法 现在代码比较恶心,回头把ifstream 和 bufferIOStream 封装成一个类
|
||||
bool open(void);
|
||||
|
||||
unsigned int checkFrames(BufferIOStream& p_kStrteam);
|
||||
|
||||
bool getAllFrames(BufferIOStream& p_kIOStream);
|
||||
|
||||
bool extractData(FRAME* p_pFrame, BufferIOStream& p_kStrteam);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
功能 :检查文件中图象帧数。
|
||||
参数 :ifs:对文件流的引用。
|
||||
返回值:文件中图象帧数。
|
||||
*/
|
||||
unsigned int checkFrames(ifstream& p_kStrteam);
|
||||
|
||||
/*
|
||||
功能 :将所有图象帧数据读入内存。
|
||||
参数 :ifs:对文件流的引用。
|
||||
返回值:操作是否成功,为真成功,为假失败。
|
||||
*/
|
||||
bool getAllFrames(ifstream& p_kStrteam);
|
||||
|
||||
/*
|
||||
功能 :解压缩一帧图象数据。
|
||||
参数 :f:指向用于保存图象数据的结构。
|
||||
ifs:对文件流的引用。
|
||||
返回值:操作是否成功,为真成功,为假失败。
|
||||
*/
|
||||
bool extractData(FRAME* p_pFrame, ifstream& p_kStrteam);
|
||||
|
||||
/*
|
||||
功能 :初始化字符串表。
|
||||
参数 :strTable:指向字符串表的指针。
|
||||
rootSize:初始化的入口数。
|
||||
返回值:操作是否成功,为真成功,为假失败。
|
||||
*/
|
||||
bool initStrTable(STRING_TABLE_ENTRY* p_pSTable, unsigned int p_nRootSize);
|
||||
|
||||
/*
|
||||
功能 :在字符串表中增加一项。
|
||||
参数 :strTable:指向字符串表的指针。
|
||||
addIdx:增加的入口索引。
|
||||
idx:用于构造要增加的字符串的入口索引。
|
||||
c:用于构造要增加的字符串的字符。
|
||||
返回值:操作是否成功,为真成功,为假失败。
|
||||
*/
|
||||
bool addStrTable(STRING_TABLE_ENTRY* p_pSTable, unsigned int p_nAddInedx, unsigned int p_nIndex, unsigned char p_cBuf);
|
||||
|
||||
public:
|
||||
|
||||
FRAME* m_vAllFrames; //指向所有图象帧的指针(inMem为真时用)
|
||||
|
||||
private:
|
||||
|
||||
GLOBAL_INFO m_kGInfo; //GIF文件的全局参数
|
||||
|
||||
FRAME m_kCurFrame; //当前帧的参数(inMem为假时用)
|
||||
|
||||
GCTRLEXT m_kCtrlExt; //图象扩展参数(读入数据时临时使用)
|
||||
|
||||
private:
|
||||
|
||||
BufferIOStream* m_pBufferIOStream; //用于读取内存的
|
||||
|
||||
ifstream m_kIOStream; //用于读文件的文件流
|
||||
|
||||
char m_sVersion[4]; //版本字符串
|
||||
|
||||
bool m_bError; //类实例变量创建时是否出错的标志
|
||||
|
||||
bool m_bOpened; //是否处于打开状态
|
||||
|
||||
bool m_bInMem; //图象数据是否一次读入内存
|
||||
|
||||
unsigned char m_vGColorTable[256 * 3]; //全局调色板
|
||||
|
||||
unsigned char m_vLColorTable[256 * 3]; //局部调色板(inMem为假时用)
|
||||
|
||||
streampos m_kDataStart; //保存文件流中图象数据开始的地方
|
||||
|
||||
unsigned int m_nCurIndex; //当前帧的索引(inMem为真时用)
|
||||
|
||||
};
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif //__JCGifImg_H__
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
@@ -0,0 +1,569 @@
|
||||
/**
|
||||
@file JCImageRW.cpp
|
||||
@brief
|
||||
@author hugao
|
||||
@version 1.0
|
||||
@date 2016_5_11
|
||||
*/
|
||||
|
||||
#include "JCImageRW.h"
|
||||
#include "../misc/JCWorkerThread.h"
|
||||
#include "../buffer/JCBuffer.h"
|
||||
#include "../fileSystem/JCFileSystem.h"
|
||||
#include <cmath>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
namespace laya
|
||||
{
|
||||
BitmapData::BitmapData() {
|
||||
m_nImageID = 0;
|
||||
m_nWidth = 0;
|
||||
m_nHeight = 0;
|
||||
m_nBpp = 32;
|
||||
m_pImageData = 0;
|
||||
m_nImageType = ImgType_unknow;
|
||||
|
||||
}
|
||||
BitmapData::BitmapData(char* p_pData, int p_nWidth, int p_nHeight) {
|
||||
m_nWidth = p_nWidth;
|
||||
m_nHeight = p_nHeight;
|
||||
m_nBpp = 32;
|
||||
m_pImageData = p_pData;
|
||||
m_nImageType = ImgType_unknow;
|
||||
}
|
||||
BitmapData::BitmapData(int p_nWidth, int p_nHeight, bool p_bTranslate, int p_nFillColor) {
|
||||
m_nWidth = p_nWidth;
|
||||
m_nHeight = p_nHeight;
|
||||
m_nBpp = 32;
|
||||
m_pImageData = (char*) new int[p_nWidth*p_nHeight];
|
||||
if (p_nFillColor == 0)
|
||||
memset(m_pImageData, 0, p_nWidth*p_nHeight*sizeof(int));
|
||||
else
|
||||
for (int i = 0; i < m_nWidth*m_nHeight; i++) ((int*)m_pImageData)[i] = p_nFillColor;
|
||||
m_nImageType = ImgType_unknow;
|
||||
}
|
||||
|
||||
void BitmapData::reconfigure(int width, int height, int bpp, ImageType imageType)
|
||||
{
|
||||
bool isChanged = false;
|
||||
|
||||
if (m_nWidth != width)
|
||||
{
|
||||
isChanged = true;
|
||||
m_nWidth = width;
|
||||
}
|
||||
|
||||
if (m_nHeight != height)
|
||||
{
|
||||
isChanged = true;
|
||||
m_nHeight = height;
|
||||
}
|
||||
|
||||
if (m_nBpp != bpp)
|
||||
{
|
||||
isChanged = true;
|
||||
m_nBpp = bpp;
|
||||
}
|
||||
|
||||
if(m_pImageData == nullptr) {
|
||||
isChanged = true;
|
||||
}
|
||||
|
||||
m_nImageType = imageType;
|
||||
|
||||
if (isChanged)
|
||||
{
|
||||
releaseData();
|
||||
int bufferLength = this->m_nWidth * this->m_nHeight * (this->m_nBpp / 8);
|
||||
m_pImageData = new char[bufferLength];
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapData::copyData(char* dataPtr)
|
||||
{
|
||||
int bufferLength = this->m_nWidth * this->m_nHeight * (this->m_nBpp / 8);
|
||||
memcpy(m_pImageData, dataPtr, bufferLength);
|
||||
}
|
||||
|
||||
#ifndef WEBASM
|
||||
unsigned char* ReadPNGFromMem(unsigned char* data, int dataSize, PNG_UINT32* w, PNG_UINT32* h);
|
||||
int LoadJpegFromMem (BitmapData* pBitmapData,unsigned char * memData, int size );
|
||||
int LoadGif(BitmapData* pBitmapData, unsigned char * memData, int size);
|
||||
bool saveJpeg(int width ,int height,int bpp, char *buffer, int quality, const char*filename);
|
||||
JCWorkerThread* g_DecThread=NULL; //全局的解码线程
|
||||
|
||||
bool loadImageMemSync( const char* p_pMem, int p_nLenth, BitmapData& p_bmp ){
|
||||
ImageType imgType = getImgType(p_pMem, p_nLenth);
|
||||
p_bmp.m_nImageType = imgType;
|
||||
p_bmp.m_nBpp = 32;
|
||||
switch( imgType ){
|
||||
case ImgType_jpeg:
|
||||
return LoadJpegFromMem(&p_bmp,(unsigned char*)p_pMem,p_nLenth)!=0;
|
||||
break;
|
||||
case ImgType_png:
|
||||
p_bmp.m_pImageData = (char*)ReadPNGFromMem((unsigned char*)p_pMem, p_nLenth, (PNG_UINT32*)&p_bmp.m_nWidth, (PNG_UINT32*)&p_bmp.m_nHeight);
|
||||
return p_bmp.m_pImageData!=0;
|
||||
break;
|
||||
case ImgType_gif:
|
||||
return LoadGif(&p_bmp, (unsigned char*)p_pMem, p_nLenth) != 0;
|
||||
break;
|
||||
case ImgType_unknow:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
BitmapData loadLocalImageSync( const char* p_pszFile ){
|
||||
BitmapData bmp;
|
||||
JCBuffer buf;
|
||||
readFileSync(p_pszFile,buf);
|
||||
bool b = loadImageMemSync(buf.m_pPtr, buf.m_nLen, bmp);
|
||||
if(!b){
|
||||
bmp.m_pImageData=NULL;
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
void _AsyncLoadImage(std::shared_ptr<char> p_pBuff, int p_nLenth, imgDecodeCB p_CB){
|
||||
std::shared_ptr<char> pMem = p_pBuff;
|
||||
BitmapData bmp;
|
||||
bool b = loadImageMemSync(pMem.get(), p_nLenth, bmp );
|
||||
if( b ){
|
||||
p_CB(bmp);
|
||||
}else{
|
||||
if(bmp.m_pImageData ) delete [] bmp.m_pImageData ;
|
||||
bmp.m_pImageData = 0;
|
||||
p_CB(bmp);
|
||||
}
|
||||
}
|
||||
void loadImageMemASync(std::shared_ptr<char> p_pBuff, int p_nLenth, imgDecodeCB p_CB){
|
||||
g_DecThread->post( std::bind(_AsyncLoadImage, p_pBuff, p_nLenth,p_CB ) );
|
||||
}
|
||||
ImageType getImgType( const char* p_pMem, int p_nLength ){
|
||||
static int jpegID = 0x00ffd8ff; //最高位00那个位置不一定是什么
|
||||
static int gifID = 0x38464947;
|
||||
static int pngID = 0x474e5089;
|
||||
|
||||
int idval = *(int*)p_pMem;
|
||||
if( idval == pngID )return ImgType_png;
|
||||
else if( idval==gifID ) return ImgType_gif;
|
||||
else if( (idval &0xffffff) == jpegID ) return ImgType_jpeg;
|
||||
return ImgType_unknow;
|
||||
}
|
||||
bool getImageBaseInfo( const char* p_pMem, int p_nLength, ImageBaseInfo& p_Info ){
|
||||
return true;
|
||||
}
|
||||
extern int SavePng(char* png_file_name, char **data, int width, int height, int bit_depth);
|
||||
bool saveAsPng(const char* p_pData, int w, int h, const char* p_pszFile ){
|
||||
char** pngline = new char*[h];
|
||||
for( int i=0; i<h; i++){
|
||||
pngline[i]=(char*)(p_pData+w*4*i);
|
||||
}
|
||||
SavePng((char*)p_pszFile, pngline, w, h, 8);
|
||||
delete [] pngline;
|
||||
return true;
|
||||
}
|
||||
bool saveAsJpeg(const char* p_pData, ImageBaseInfo& p_Info, const char* p_pszFile ){
|
||||
char* pData = (char*)p_pData;
|
||||
int width = p_Info.m_nWidth;
|
||||
int height = p_Info.m_nHeight;
|
||||
int bpp = p_Info.m_nBpp;
|
||||
|
||||
//32转24
|
||||
if( bpp==32){
|
||||
pData = new char[width*height*3];
|
||||
char* pSrc = (char*)p_pData;
|
||||
char* pDst = pData;
|
||||
for( int y=0; y<height; y++){
|
||||
for(int x=0; x<width; x++){
|
||||
pDst[0]=pSrc[0];pDst[1]=pSrc[1];pDst[2]=pSrc[2];
|
||||
pSrc+=4;
|
||||
pDst+=3;
|
||||
}
|
||||
}
|
||||
}
|
||||
saveJpeg(width, height, 24,(char*)pData, 80, p_pszFile);
|
||||
if( bpp==32)
|
||||
delete [] pData;
|
||||
|
||||
return false;
|
||||
}
|
||||
bool saveAsBmp(const char* p_pData, ImageBaseInfo& p_Info){
|
||||
return false;
|
||||
}
|
||||
//把一个浮点数转换成分数。注意现在是用遍历的方法,速度有限,且只处理到分母为2048
|
||||
void getFraction(float v,int& a, int& b){
|
||||
float e=1e-4f;
|
||||
for(int i=1; i<2048; i++){
|
||||
float f1 = i*v;
|
||||
float ff = f1-(int)f1;
|
||||
if(f1-(int)f1<e){
|
||||
b=i;
|
||||
a=(int)(b*v+e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
class RGBAColor
|
||||
{
|
||||
public:
|
||||
RGBAColor(){
|
||||
fa=fr=fg=fb=0.0f;
|
||||
}
|
||||
RGBAColor(int color){
|
||||
set(color);
|
||||
}
|
||||
RGBAColor(const RGBAColor& color){
|
||||
fa=color.fa;fr=color.fr;fg=color.fg;fb=color.fb;
|
||||
}
|
||||
void operator += (const RGBAColor& b){
|
||||
fa+=b.fa;
|
||||
fr+=b.fr;
|
||||
fg+=b.fg;
|
||||
fb+=b.fb;
|
||||
}
|
||||
int toInt32(){
|
||||
int ret=0;
|
||||
unsigned char* pRGBA = (unsigned char*)&ret;
|
||||
unsigned char& a = pRGBA[0];
|
||||
unsigned char& r = pRGBA[1];
|
||||
unsigned char& g = pRGBA[2];
|
||||
unsigned char& b = pRGBA[3];
|
||||
|
||||
a=(unsigned char)(fa*255); a=a>255?255:a;
|
||||
r=(unsigned char)(fr*255); r=r>255?255:r;
|
||||
g=(unsigned char)(fg*255); g=g>255?255:g;
|
||||
b=(unsigned char)(fb*255); b=b>255?255:b;
|
||||
return ret;
|
||||
}
|
||||
void set(int color){
|
||||
unsigned char* pRGBA = (unsigned char*)&color;
|
||||
fa = pRGBA[0]/255.0f;
|
||||
fr = pRGBA[1]/255.0f;
|
||||
fg = pRGBA[2]/255.0f;
|
||||
fb = pRGBA[3]/255.0f;
|
||||
}
|
||||
void clear(){
|
||||
fa=fr=fg=fb=0.0f;
|
||||
}
|
||||
RGBAColor operator *(float f){
|
||||
RGBAColor ret;
|
||||
ret.fa=fa*f;
|
||||
ret.fr=fr*f;
|
||||
ret.fg=fg*f;
|
||||
ret.fb=fb*f;
|
||||
return ret;
|
||||
}
|
||||
void operator *=(float f){
|
||||
fa*=f;fr*=f;fg*=f;fb*=f;
|
||||
}
|
||||
private:
|
||||
float fa,fr,fg,fb;
|
||||
};
|
||||
//求一条线的颜色的和
|
||||
RGBAColor _getLineColor(int* pData, int colorNum, float stk, float midk, float edk){
|
||||
RGBAColor res;
|
||||
res+=RGBAColor(*pData++)*stk;
|
||||
RGBAColor resmid;
|
||||
for(int i=0; i<colorNum-2; i++) resmid+=RGBAColor(*pData++);
|
||||
res+=resmid*midk;
|
||||
res+=RGBAColor(*pData++)*edk;
|
||||
return res;
|
||||
}
|
||||
//fsx,fsy。这种方法只适用于w>1,h>1的情况,即缩小图片。而且也不是很精确,没有考虑插值。
|
||||
RGBAColor _getBmpRectColor(BitmapData& bmp,float fsx, float fsy, float w, float h ){
|
||||
if(w<1.0f||h<1.0f){
|
||||
throw -1;
|
||||
}
|
||||
RGBAColor res;
|
||||
float dstposx=0.0f;
|
||||
float dstposy=0.0f;
|
||||
int sx=(int)fsx;
|
||||
int sy=(int)fsy;
|
||||
int ex=(int)ceil(fsx+w); ex=ex>bmp.m_nWidth?bmp.m_nWidth:ex;
|
||||
int ey=(int)ceil(fsy+h); ey=ey>bmp.m_nHeight?bmp.m_nHeight:ey;
|
||||
//TODO 对于整幅图像的缩小,下面几个值每个目标像素都要重算一遍,效率低
|
||||
float fracfsx = fsx-sx;
|
||||
float fracfsy = fsy-sy;
|
||||
float sxk = fracfsx==0.0f?1:(1.0f-fracfsx);
|
||||
float syk = fracfsy==0.0f?1:(1.0f-fracfsy);
|
||||
float exk = (fsx+w)-(ex-1); if(exk<0)exk=1.0f;
|
||||
float eyk = (fsy+h)-(ey-1); if(eyk<0)eyk=1.0f;
|
||||
int rectw = ex-sx;
|
||||
int recth = ey-sy;
|
||||
if(recth<=0) return res;
|
||||
int y=sy;
|
||||
int* pCurData = ((int*)bmp.m_pImageData)+sy*bmp.m_nWidth+sx;
|
||||
//第一行
|
||||
res += _getLineColor(pCurData,rectw,sxk*syk,syk,exk*syk);
|
||||
y++;
|
||||
pCurData+=bmp.m_nWidth;
|
||||
//中间行
|
||||
for( ; y<ey-1; y++){
|
||||
res += _getLineColor(pCurData,rectw,sxk,1,exk);
|
||||
pCurData+=bmp.m_nWidth;
|
||||
}
|
||||
//最后一行
|
||||
if(y<ey)
|
||||
res += _getLineColor(pCurData, rectw, sxk*eyk,eyk,exk*eyk);
|
||||
return res;
|
||||
}
|
||||
bool downsampleBmp( BitmapData& src, BitmapData& dst, int* pFrcation, bool rbBorder ){
|
||||
int& wa=pFrcation[0];
|
||||
int& wb=pFrcation[1];
|
||||
int& ha=pFrcation[2];
|
||||
int& hb=pFrcation[3];
|
||||
if(wa==wb&&ha==hb){
|
||||
//先不处理不变的情况
|
||||
throw -1;
|
||||
return false;
|
||||
}
|
||||
if( wa>wb || ha>hb ){
|
||||
//不支持放大
|
||||
throw -1;
|
||||
return false;
|
||||
}
|
||||
int& srcw = src.m_nWidth;
|
||||
int& srch = src.m_nHeight;
|
||||
int& dstw = dst.m_nWidth;
|
||||
int& dsth = dst.m_nHeight;
|
||||
dstw = (int)ceil((float)srcw*wa/wb);
|
||||
dsth = (int)ceil((float)srch*ha/hb);
|
||||
int borderAdd=0;
|
||||
if(rbBorder){
|
||||
dstw++;
|
||||
dsth++;
|
||||
borderAdd=1;
|
||||
}
|
||||
//实际图片
|
||||
dst.m_pImageData = new char[dstw*dsth*4];
|
||||
#ifdef _DEBUG
|
||||
memset(dst.m_pImageData,0x86,dstw*dsth*4);
|
||||
#endif
|
||||
dst.m_nBpp = 32;
|
||||
int* pdst = (int*)dst.m_pImageData;
|
||||
float fsx=0.0f,fsy=0.0f,fw=(float)wb/wa,fh=(float)hb/ha;
|
||||
RGBAColor res;
|
||||
for(int y=0; y<dsth; y++){
|
||||
fsx=0;
|
||||
for(int x=0; x<dstw; x++){
|
||||
res = _getBmpRectColor(src,fsx,fsy,fw,fh);
|
||||
res *= (((float)wa*ha)/(wb*hb));
|
||||
*pdst++=res.toInt32();
|
||||
fsx+=fw;
|
||||
}
|
||||
fsy+=fh;
|
||||
}
|
||||
return true;
|
||||
/*
|
||||
int stx = 0;
|
||||
//行
|
||||
RGBAColor res,cur;
|
||||
float dsrc = ((float)wa)/wb;//源每前进一步,对应新的步长
|
||||
int* pcurSrc=(int*)src.m_pImageData;
|
||||
for( int y=0; y<dsth; y++){
|
||||
int num = dstw/srcw;
|
||||
for(int x=0; x<num; x++,stx+=wb){
|
||||
float fcurpos=0.0f;
|
||||
float vk=1.0f;
|
||||
for( int cx=stx; cx<stx+wb; cx++){
|
||||
//取一个颜色
|
||||
cur.set(*pcurSrc++);
|
||||
//这个颜色可能全给新的像素了,也可能只给了一部分
|
||||
float d1 = 1.0f-fcurpos;
|
||||
if(d1>dsrc){//全部
|
||||
res+=cur;
|
||||
}else{//部分
|
||||
vk = d1/dsrc;//一定<1
|
||||
res+=(cur*vk);
|
||||
}
|
||||
fcurpos+=dsrc;
|
||||
}
|
||||
}
|
||||
//剩下的
|
||||
int left = dstw%srcw;
|
||||
}
|
||||
//列
|
||||
*/
|
||||
}
|
||||
bool downsampleBmp( BitmapData& src, BitmapData& dst, int windw, int windh, bool rbBorder ){
|
||||
if( src.m_pImageData==NULL) return false;
|
||||
if(windw<1 || windh<1)return false;
|
||||
if(windw==1 && windh==1){
|
||||
//这个怎么处理.这么用是浪费的
|
||||
throw -1;
|
||||
}
|
||||
int& srcw = src.m_nWidth;
|
||||
int& srch = src.m_nHeight;
|
||||
int& dstw = dst.m_nWidth;
|
||||
int& dsth = dst.m_nHeight;
|
||||
//取整。可能会丢掉一部分
|
||||
dstw = srcw/windw;
|
||||
dsth = srch/windh;
|
||||
//TODO
|
||||
//采用先水平扫描的方法,这样可能会快一些
|
||||
int borderAdd=0;
|
||||
if(rbBorder){
|
||||
dstw++;
|
||||
dsth++;
|
||||
borderAdd=1;
|
||||
}
|
||||
//实际图片
|
||||
dst.m_pImageData = new char[dstw*dsth*4];
|
||||
dst.m_nBpp = 32;
|
||||
int snum=windw*windh;
|
||||
int* psrc = (int*)src.m_pImageData;
|
||||
int* pdst = (int*)dst.m_pImageData;
|
||||
for( int y=0; y<dsth-borderAdd; y++ ){
|
||||
int* pcurdst=pdst;
|
||||
for( int x=0; x<dstw-borderAdd; x++ ){
|
||||
unsigned int valr = 0,valg=0,valb=0,vala=0;
|
||||
unsigned char* pcurc = (unsigned char*)&psrc[x*windw + (y*windh)*srcw];
|
||||
//下面开始处理一个块
|
||||
for(int sy=0;sy<windh; sy++){
|
||||
unsigned char* tmpSrc=pcurc;
|
||||
for(int sx=0; sx<windw; sx++){
|
||||
valr+=*tmpSrc++; valg+=*tmpSrc++; valb+=*tmpSrc++; vala+=*tmpSrc++;
|
||||
}
|
||||
//下一行的块开头
|
||||
pcurc += srcw*4;
|
||||
}
|
||||
valr/=snum; valg/=snum; valb/=snum; vala/=snum;
|
||||
unsigned char avgval[]={static_cast<unsigned char>(valr),static_cast<unsigned char>(valg),static_cast<unsigned char>(valb),static_cast<unsigned char>(vala)};
|
||||
*pcurdst++=*(int*)avgval;
|
||||
}
|
||||
//水平复制最后一个
|
||||
if(borderAdd){
|
||||
int lastv = *(pcurdst-1);
|
||||
*pcurdst++ = lastv;
|
||||
}
|
||||
pdst+=dstw; //这个要实际到下一行,考虑包边
|
||||
}
|
||||
//复制最后一行
|
||||
if(borderAdd){
|
||||
int* pcurimg = (int*)dst.m_pImageData;
|
||||
memcpy(pcurimg+dstw*(dsth-1),pcurimg+dstw*(dsth-2), dstw*sizeof(int));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void createGridBmp( BitmapData& out, int w, int h, int gridw){
|
||||
out.m_nBpp=32;
|
||||
out.m_nWidth=w;
|
||||
out.m_nHeight=h;
|
||||
out.m_pImageData=(char*)new int[w*h];
|
||||
int* pData = (int*)out.m_pImageData;
|
||||
for(int y=0;y<h;y++){
|
||||
for(int x=0; x<w; x++){
|
||||
int v = (((x/gridw)%2)^((y/gridw)%2))?(0xffffffff):(0x77777777);
|
||||
*pData++=v;
|
||||
}
|
||||
}
|
||||
}
|
||||
void copy8BitBmp( BitmapData& dst, int nSx, int nSy, unsigned char* pSrc, int nSrcW, int nSrcH, int nSrcColor ){
|
||||
int srcsx=0,srcsy=0;
|
||||
int dstsx=nSx,dstsy=nSy;
|
||||
int dtw=nSrcW,dth=nSrcH;
|
||||
if(dstsx<0){
|
||||
srcsx = -dstsx;
|
||||
dtw+=dstsx;
|
||||
dstsx=0;
|
||||
}
|
||||
if( dstsy<0){
|
||||
srcsy = -dstsy;
|
||||
dth+=dstsy;
|
||||
dstsy=0;
|
||||
}
|
||||
int ex = dstsx+dtw;
|
||||
int ey = dstsy+dth;
|
||||
if(ex>dst.m_nWidth){
|
||||
dtw -= (ex - dst.m_nWidth);
|
||||
}
|
||||
if(ey>dst.m_nHeight){
|
||||
dth -= (ey - dst.m_nHeight);
|
||||
}
|
||||
unsigned int* pdst = (unsigned int*)(dst.m_pImageData+(dstsy*dst.m_nWidth+dstsx)*4);
|
||||
unsigned char* psrc = pSrc+srcsy*nSrcW+srcsx;
|
||||
for( int y=0; y<dth; y++){
|
||||
unsigned int* pdstl=pdst;
|
||||
unsigned char* psrcl=psrc;
|
||||
for( int x=0; x<dtw; x++){
|
||||
unsigned char alpha = *pSrc++;
|
||||
int col = nSrcColor&0x00ffffff;
|
||||
col|=(alpha<<24);
|
||||
*pdstl++=col;
|
||||
}
|
||||
pdst+=dst.m_nWidth;
|
||||
psrc+=nSrcW;
|
||||
}
|
||||
}
|
||||
void copy32BitBmp(BitmapData& dst, int nSx, int nSy,int nDstW, unsigned char* pSrc, int nSrcW, int nSrcH, int srcPitch )
|
||||
{
|
||||
int srcsx = 0, srcsy = 0;
|
||||
int dstsx = nSx, dstsy = nSy;
|
||||
int dtw = nSrcW, dth = nSrcH;
|
||||
if (dstsx < 0) {
|
||||
srcsx = -dstsx;
|
||||
dtw += dstsx;
|
||||
dstsx = 0;
|
||||
}
|
||||
if (dstsy < 0) {
|
||||
srcsy = -dstsy;
|
||||
dth += dstsy;
|
||||
dstsy = 0;
|
||||
}
|
||||
int ex = dstsx + dtw;
|
||||
int ey = dstsy + dth;
|
||||
if (ex > nDstW) {
|
||||
dtw -= (ex - nDstW);
|
||||
}
|
||||
if (ey > dst.m_nHeight) {
|
||||
dth -= (ey - dst.m_nHeight);
|
||||
}
|
||||
if (dtw < 0) dtw = 0;
|
||||
char* pdst = dst.m_pImageData + (dstsy*nDstW + dstsx) * 4;
|
||||
unsigned char* psrc = pSrc + srcsy*srcPitch + srcsx*4;
|
||||
for (int y = 0; y < dth; y++) {
|
||||
memcpy(pdst, psrc, dtw * 4);
|
||||
pdst += nDstW *4;
|
||||
psrc += srcPitch;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
void convertRGBA8888ToRGB888(const unsigned char* data, size_t dataLen, unsigned char* outData)
|
||||
{
|
||||
for (size_t i = 0, l = dataLen - 3; i < l; i += 4)
|
||||
{
|
||||
*outData++ = data[i];
|
||||
*outData++ = data[i + 1];
|
||||
*outData++ = data[i + 2];
|
||||
}
|
||||
}
|
||||
void convertRGBA8888ToA8(const unsigned char* data, size_t dataLen, unsigned char* outData)
|
||||
{
|
||||
for (size_t i = 0, l = dataLen - 3; i < l; i += 4)
|
||||
{
|
||||
*outData++ = data[i + 3];
|
||||
}
|
||||
}
|
||||
void convertRGBA8888ToFormat(const unsigned char* data, size_t dataLen, GLenum format, unsigned char** outData, size_t* outDataLen)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GL_RGB:
|
||||
*outDataLen = dataLen / 4 * 3;
|
||||
*outData = new unsigned char[sizeof(unsigned char) * (*outDataLen)];
|
||||
convertRGBA8888ToRGB888(data, dataLen, *outData);
|
||||
break;
|
||||
case GL_ALPHA:
|
||||
*outDataLen = dataLen / 4;
|
||||
*outData = new unsigned char[sizeof(unsigned char) * (*outDataLen)];
|
||||
convertRGBA8888ToA8(data, dataLen, *outData);
|
||||
break;
|
||||
default:
|
||||
*outData = (unsigned char*)data;
|
||||
*outDataLen = dataLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
@file JCImageRW.h
|
||||
@brief
|
||||
@author hugao
|
||||
@version 1.0
|
||||
@date 2016_5_11
|
||||
*/
|
||||
|
||||
#ifndef __JCImageRW_H__
|
||||
#define __JCImageRW_H__
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#define PNG_UINT32 unsigned int
|
||||
#if __APPLE__
|
||||
#include <OpenGLES/ES3/gl.h>
|
||||
#else
|
||||
#include <GLES3/gl3.h>
|
||||
#endif
|
||||
|
||||
namespace laya
|
||||
{
|
||||
enum ImageType
|
||||
{
|
||||
ImgType_unknow,
|
||||
ImgType_jpeg,
|
||||
ImgType_png,
|
||||
ImgType_gif,
|
||||
ImgType_ETC1,
|
||||
ImgType_ETC2,
|
||||
ImgType_PVR,
|
||||
};
|
||||
|
||||
struct ImageBaseInfo
|
||||
{
|
||||
int m_nWidth, m_nHeight, m_nBpp;
|
||||
};
|
||||
|
||||
class BitmapData:public ImageBaseInfo
|
||||
{
|
||||
public:
|
||||
BitmapData();
|
||||
BitmapData(char* p_pData, int p_nWidth, int p_nHeight );
|
||||
BitmapData(int p_nWidth, int p_nHeight, bool p_bTranslate, int p_nFillColor );
|
||||
void releaseData()
|
||||
{
|
||||
if(m_pImageData)
|
||||
{
|
||||
delete [] m_pImageData;
|
||||
m_pImageData=0;
|
||||
}
|
||||
}
|
||||
int m_nImageID;
|
||||
char* m_pImageData;
|
||||
ImageType m_nImageType;
|
||||
|
||||
void reconfigure(int width, int height, int bpp, ImageType imageType);
|
||||
void copyData(char* dataPtr);
|
||||
};
|
||||
|
||||
#ifndef WEBASM
|
||||
|
||||
//参数是对象实例而不是引用。因为实际对象可能是临时对象
|
||||
typedef std::function<void(BitmapData bmp)> imgDecodeCB;
|
||||
|
||||
/** @brief 在函数内部会给 p_pData 分配空间。注意是一维数组,不是二维的 这里只负责解码图片,没有缓存管理等功能。
|
||||
* 返回的是函数内部分配的指针。需要外部释放
|
||||
* @param[in] 内存数据
|
||||
* @param[in] 长度
|
||||
* @param[in] 获得到的bitmap
|
||||
* @return 是否解码成功
|
||||
*/
|
||||
bool loadImageMemSync( const char* p_pMem, int p_nLenth, BitmapData& p_bmp );
|
||||
|
||||
/** @brief
|
||||
直接加载一个图片文件。
|
||||
* @param[in] p_pszFile 本地文件的路径,绝对路径。
|
||||
* @return
|
||||
返回一个Bitmap对象,注意需要自己手动删除其中的指针。
|
||||
*/
|
||||
BitmapData loadLocalImageSync( const char* p_pszFile );
|
||||
|
||||
|
||||
void loadImageMemASync(std::shared_ptr<char> p_pBuff, int p_nLenth, imgDecodeCB p_CB);
|
||||
|
||||
ImageType getImgType( const char* p_pMem, int p_nLength );
|
||||
|
||||
/** @brief 获得图片的基本信息。要求快速,如果不必解码就不要解码 同步函数
|
||||
* @param[in] 内存数据
|
||||
* @param[in] 内存长度
|
||||
* @param[in] 图片基本信息
|
||||
* @return 是否解码成功
|
||||
*/
|
||||
bool getImageBaseInfo( const char* p_pMem, int p_nLength, ImageBaseInfo& p_Info );
|
||||
|
||||
/** @brief 保存png
|
||||
* @param[in] 图片数据
|
||||
* @param[in] w
|
||||
* @param[in] h
|
||||
* @param[in] 文件名字
|
||||
* @return 是否保存成功
|
||||
*/
|
||||
bool saveAsPng(const char* p_pData, int w, int h, const char* p_pszFile );
|
||||
|
||||
/** @brief 保存jpg
|
||||
* @param[in] 图片数据
|
||||
* @param[in] 图片信息
|
||||
* @param[in] 文件名字
|
||||
* @return 是否保存成功
|
||||
*/
|
||||
bool saveAsJpeg(const char* p_pData, ImageBaseInfo& p_Info, const char* p_pszFile );
|
||||
|
||||
/** @brief 保存bmp
|
||||
* @param[in] 图片数据
|
||||
* @param[in] 图片信息
|
||||
* @return 是否保存成功
|
||||
*/
|
||||
bool saveAsBmp(const char* p_pData, ImageBaseInfo& p_Info);
|
||||
|
||||
/** @brief windw是每隔几个采样一个。windh类推。
|
||||
* @param[in]
|
||||
* @param[in]
|
||||
* @param[in]
|
||||
* @param[out]
|
||||
* @return 返回的dst是在函数内部分配的
|
||||
*/
|
||||
bool downsampleBmp( BitmapData& src, BitmapData& dst, int windw, int windh, bool rbBorder );
|
||||
|
||||
/** @brief pFrcation 是4个int表示的宽高缩放。[宽分子,宽分母,高分子,高分母]
|
||||
* @param[in]
|
||||
* @param[in]
|
||||
* @param[in]
|
||||
* @param[out]
|
||||
* @return
|
||||
*/
|
||||
bool downsampleBmp( BitmapData& src, BitmapData& dst, int* pFrcation, bool rbBorder );
|
||||
|
||||
void createGridBmp( BitmapData& out, int w, int h, int gridw);
|
||||
|
||||
/** @brief
|
||||
* 把一个灰度图转换成某种颜色,拷贝到dst中。
|
||||
* @param[in] dst 目标BitmapData。
|
||||
* @param[in] nSx 目标bmp的起点x
|
||||
* @param[in] nSy 目标bmp的起点y
|
||||
* @param[in] pSrc 源图片。是一个灰度图。灰度值表示颜色的深浅。
|
||||
* @param[in] nSrcW 源图片的宽
|
||||
* @param[in] nSrcH 源图片的高
|
||||
* @param[in] nSrcColor 颜色。
|
||||
* @return void
|
||||
*/
|
||||
void copy8BitBmp( BitmapData& dst, int nSx, int nSy, unsigned char* pSrc, int nSrcW, int nSrcH, int nSrcColor );
|
||||
|
||||
void copy32BitBmp(BitmapData& dst, int nSx, int nSy,int nDstW, unsigned char* pSrc, int nSrcW, int nSrcH, int srcPitch);
|
||||
|
||||
std::pair<unsigned char*, unsigned long> convertBitmapToJpeg(const char* p_pData, int nWidth, int nHeight, int nBpp);
|
||||
|
||||
std::pair<unsigned char*, unsigned long> convertBitmapToPng(const char* p_pData, int nWidth, int nHeight, int nBitDepth);
|
||||
|
||||
void convertRGBA8888ToFormat(const unsigned char* data, size_t dataLen, GLenum format, unsigned char** outData, size_t* outDataLen);
|
||||
#endif
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif //__JCImageRW_H__
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
@@ -0,0 +1,425 @@
|
||||
/**
|
||||
@file JCJpegImg.cpp
|
||||
@brief
|
||||
@author hugao
|
||||
@version 1.0
|
||||
@date 2016_5_11
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
#include "JCImageRW.h"
|
||||
#include "../util/JCCommonMethod.h"
|
||||
#pragma warning (disable: 4996)
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Include file for users of JPEG library.
|
||||
* You will need to have included system headers that define at least
|
||||
* the typedefs FILE and size_t before you can include jpeglib.h.
|
||||
* (stdio.h is sufficient on ANSI-conforming systems.)
|
||||
* You may also wish to include "jerror.h".
|
||||
*/
|
||||
#include "jpeglib.h"
|
||||
/*
|
||||
* <setjmp.h> is used for the optional error recovery mechanism shown in
|
||||
* the second part of the example.
|
||||
*/
|
||||
#include <setjmp.h>
|
||||
namespace laya
|
||||
{
|
||||
/******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/
|
||||
|
||||
/* This half of the example shows how to feed data into the JPEG compressor.
|
||||
* We present a minimal version that does not worry about refinements such
|
||||
* as error recovery (the JPEG code will just exit() if it gets an error).
|
||||
*/
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Our example here shows how to 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:
|
||||
*/
|
||||
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
};
|
||||
|
||||
typedef struct my_error_mgr * my_error_ptr;
|
||||
|
||||
/*
|
||||
* Here's the routine that will replace the standard error_exit method:
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
my_error_exit (j_common_ptr cinfo)
|
||||
{
|
||||
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
|
||||
my_error_ptr myerr = (my_error_ptr) cinfo->err;
|
||||
|
||||
/* Always display the message. */
|
||||
/* We could postpone this until after returning, if we chose. */
|
||||
(*cinfo->err->output_message) (cinfo);
|
||||
|
||||
/* Return control to the setjmp point */
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Sample routine for JPEG decompression. We assume that the source file name
|
||||
* is passed in. We want to return 1 on success, 0 on error.
|
||||
*/
|
||||
unsigned char* readFile(const char* filename,int &size)
|
||||
{
|
||||
unsigned char *infile;
|
||||
FILE* fInput;
|
||||
if ((fInput = fopen(filename, "rb")) == NULL)
|
||||
{
|
||||
fprintf(stderr, "can't open %s\n", filename);
|
||||
return 0;
|
||||
}
|
||||
fseek(fInput,0L,SEEK_END);
|
||||
size=ftell(fInput);
|
||||
fseek(fInput,0L,SEEK_SET);
|
||||
infile = (unsigned char*)malloc(size);
|
||||
if (!infile) {
|
||||
throw - 3;
|
||||
}
|
||||
else {
|
||||
size = fread(infile, 1, size, fInput);
|
||||
}
|
||||
fclose(fInput);
|
||||
return infile;
|
||||
}
|
||||
|
||||
GLOBAL(int) LoadJpegFromMem (BitmapData * texture,unsigned char * infile,int size )
|
||||
{
|
||||
/* This struct contains the JPEG decompression parameters and pointers to
|
||||
* working space (which is allocated as needed by the JPEG library).
|
||||
*/
|
||||
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 my_error_mgr jerr;
|
||||
/* More stuff */
|
||||
JSAMPARRAY buffer; /* Output row buffer */
|
||||
int row_stride; /* physical row width in output buffer */
|
||||
|
||||
/* In this example we want to open the input file before doing anything else,
|
||||
* so that the setjmp() error recovery below can assume the file is open.
|
||||
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
|
||||
* requires it in order to read binary files.
|
||||
*/
|
||||
/* Step 1: allocate and initialize JPEG decompression object */
|
||||
|
||||
/* We set up the normal JPEG error routines, then override error_exit. */
|
||||
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
/* Establish the setjmp return context for my_error_exit 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);
|
||||
//fclose(infile);
|
||||
return 0;
|
||||
}
|
||||
/* Now we can initialize the JPEG decompression object. */
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
/* Step 2: specify data source (eg, a file) */
|
||||
|
||||
//jpeg_stdio_src(&cinfo, infile);
|
||||
jpeg_mem_src(&cinfo, infile,size);
|
||||
|
||||
/* Step 3: read file parameters with jpeg_read_header() */
|
||||
|
||||
(void) jpeg_read_header(&cinfo, TRUE);
|
||||
/* We can ignore the return value from jpeg_read_header since
|
||||
* (a) suspension is not possible with the stdio data source, and
|
||||
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
|
||||
* See libjpeg.txt for more info.
|
||||
*/
|
||||
|
||||
/* Step 4: set parameters for decompression */
|
||||
|
||||
/* In this example, we don't need to change any of the defaults set by
|
||||
* jpeg_read_header(), so we do nothing here.
|
||||
*/
|
||||
|
||||
if (cinfo.jpeg_color_space == JCS_GRAYSCALE)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
cinfo.out_color_space = JCS_RGB;
|
||||
}
|
||||
|
||||
/* Step 5: Start decompressor */
|
||||
|
||||
(void) jpeg_start_decompress(&cinfo);
|
||||
/* We can ignore the return value since suspension is not possible
|
||||
* with the stdio data source.
|
||||
*/
|
||||
|
||||
texture->m_nWidth = cinfo.image_width;
|
||||
texture->m_nHeight = cinfo.output_height;
|
||||
texture->m_nBpp = 32;//cinfo.output_components * 8;
|
||||
/*if(cinfo.output_components!=3)
|
||||
{
|
||||
(void)jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return false;
|
||||
}*/
|
||||
#if 0
|
||||
if(cinfo.output_components == 3)
|
||||
{
|
||||
texture->type = GL_RGB;
|
||||
}
|
||||
else // Else if its 32 BPP
|
||||
{
|
||||
texture->type = GL_RGBA;
|
||||
}
|
||||
texture->imageData = std::shared_ptr<GLubyte> (new GLubyte[texture->width*texture->height*cinfo.output_components], std::default_delete<char[]>());
|
||||
#endif
|
||||
|
||||
//texture->type = GL_RGBA;
|
||||
texture->m_pImageData = /*std::shared_array<char> */(new char[texture->m_nWidth*texture->m_nHeight*texture->m_nBpp / 8]);
|
||||
if(texture->m_pImageData == NULL) // If no space was allocated
|
||||
{
|
||||
//fclose(infile); // Close the file
|
||||
(void)jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return false; // Return failed
|
||||
}
|
||||
|
||||
/* We may need to do some setup of our own at this point before reading
|
||||
* the data. After jpeg_start_decompress() we have the correct scaled
|
||||
* output image dimensions available, as well as the output colormap
|
||||
* if we asked for color quantization.
|
||||
* In this example, we need to make an output work buffer of the right size.
|
||||
*/
|
||||
/* JSAMPLEs per row in output buffer */
|
||||
row_stride = cinfo.output_width * cinfo.output_components;
|
||||
/* Make a one-row-high sample array that will go away when done with image */
|
||||
buffer = (*cinfo.mem->alloc_sarray)
|
||||
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
||||
|
||||
/* Step 6: while (scan lines remain to be read) */
|
||||
/* jpeg_read_scanlines(...); */
|
||||
|
||||
/* Here we use the library's state variable cinfo.output_scanline as the
|
||||
* loop counter, so that we don't have to keep track ourselves.
|
||||
*/
|
||||
#if 0
|
||||
int bufOffset = 0;
|
||||
int line =1;
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
/* jpeg_read_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could ask for
|
||||
* more than one scanline at a time if that's more convenient.
|
||||
*/
|
||||
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
bufOffset = (cinfo.output_height-line)*row_stride;
|
||||
memcpy(texture->imageData+bufOffset,buffer[0],row_stride); //kuo
|
||||
line++;
|
||||
}
|
||||
#else
|
||||
int line =0;
|
||||
int pixels = 0;
|
||||
if (cinfo.jpeg_color_space == JCS_GRAYSCALE)
|
||||
{
|
||||
pixels = row_stride;
|
||||
}
|
||||
else
|
||||
{
|
||||
pixels = row_stride / 3;
|
||||
}
|
||||
while (cinfo.output_scanline < cinfo.output_height)
|
||||
{
|
||||
/* jpeg_read_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could ask for
|
||||
* more than one scanline at a time if that's more convenient.
|
||||
*/
|
||||
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||
unsigned char* startBuffer = (unsigned char*)texture->m_pImageData+line*pixels*4;
|
||||
if (cinfo.jpeg_color_space == JCS_GRAYSCALE)
|
||||
{
|
||||
for (int i = 0; i < pixels; ++i)
|
||||
{
|
||||
startBuffer[i * 4 + 0] = buffer[0][i];
|
||||
startBuffer[i * 4 + 1] = buffer[0][i];
|
||||
startBuffer[i * 4 + 2] = buffer[0][i];
|
||||
startBuffer[i * 4 + 3] = 255;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < pixels; ++i)
|
||||
{
|
||||
startBuffer[i * 4 + 0] = buffer[0][i * 3 + 0];
|
||||
startBuffer[i * 4 + 1] = buffer[0][i * 3 + 1];
|
||||
startBuffer[i * 4 + 2] = buffer[0][i * 3 + 2];
|
||||
startBuffer[i * 4 + 3] = 255;
|
||||
}
|
||||
}
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
//memcpy(texture->imageData+line*row_stride,buffer[0],row_stride); //kuo
|
||||
line++;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* Step 7: Finish decompression */
|
||||
|
||||
(void) jpeg_finish_decompress(&cinfo);
|
||||
/* We can ignore the return value since suspension is not possible
|
||||
* with the stdio data source.
|
||||
*/
|
||||
|
||||
/* Step 8: Release JPEG decompression object */
|
||||
|
||||
/* This is an important step since it will release a good deal of memory. */
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
/* After finish_decompress, we can close the input file.
|
||||
* Here we postpone it until after no more JPEG errors are possible,
|
||||
* so as to simplify the setjmp error logic above. (Actually, I don't
|
||||
* think that jpeg_destroy can do an error exit, but why assume anything...)
|
||||
*/
|
||||
//fclose(infile);
|
||||
|
||||
|
||||
/* At this point you may want to check to see whether any corrupt-data
|
||||
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
|
||||
*/
|
||||
|
||||
/* And we're done! */
|
||||
return 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool LoadJpegWH( const char* p_sFileName,int& p_nWidth,int& p_nHeight )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
//保存jpeg图片,要求格式必须为rgb的
|
||||
bool saveJpeg(int width ,int height,int bpp, char *buffer, int quality, const char*filename){
|
||||
int components = bpp/8;
|
||||
if( components!=1 && components!=3 )
|
||||
return false;
|
||||
jpeg_compress_struct jcs;
|
||||
jpeg_error_mgr jem;
|
||||
FILE *fp;
|
||||
JSAMPROW row_pointer[1];//?一行位图?
|
||||
int row_stride; //?每一行的字节数
|
||||
jcs.err = jpeg_std_error(&jem);
|
||||
jpeg_create_compress(&jcs);
|
||||
fp = fopen(filename,"wb");
|
||||
if(fp==NULL)
|
||||
return false;
|
||||
jpeg_stdio_dest(&jcs,fp);
|
||||
jcs.image_width = width; //位图的宽和高,单位为像素
|
||||
jcs.image_height = height;
|
||||
jcs.input_components =components; //?在此为1,表示灰度图,?如果是彩色位图,则为3?
|
||||
jcs.in_color_space = components==3?JCS_RGB:JCS_GRAYSCALE;//JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像??
|
||||
jpeg_set_defaults(&jcs);
|
||||
jpeg_set_quality(&jcs, quality, (boolean)true);
|
||||
jpeg_start_compress(&jcs,(boolean)true);
|
||||
row_stride = jcs.input_components*width; /* JSAMPLEs per row in image_buffer */
|
||||
while(jcs.next_scanline < jcs.image_height){
|
||||
row_pointer[0] = (JSAMPROW)&buffer[jcs.next_scanline * row_stride ];
|
||||
jpeg_write_scanlines(&jcs, row_pointer, 1);
|
||||
}
|
||||
jpeg_finish_compress(&jcs);
|
||||
jpeg_destroy_compress(&jcs);
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
std::pair<unsigned char*, unsigned long> convertBitmapToJpeg(int uWidth, int uHeight, int bpp, unsigned char* pImg, int iQuality)
|
||||
{
|
||||
std::pair<unsigned char*, unsigned long> mRes = std::make_pair((unsigned char*)NULL, 0);
|
||||
int components = bpp / 8;
|
||||
if (components != 1 && components != 3)
|
||||
return mRes;
|
||||
jpeg_compress_struct jcInfo;
|
||||
jpeg_error_mgr jErr;
|
||||
jcInfo.err = jpeg_std_error(&jErr);
|
||||
|
||||
jpeg_create_compress(&jcInfo);
|
||||
|
||||
jpeg_mem_dest(&jcInfo, &mRes.first, &mRes.second);
|
||||
|
||||
jcInfo.image_width = uWidth;
|
||||
jcInfo.image_height = uHeight;
|
||||
jcInfo.input_components = 3;
|
||||
jcInfo.in_color_space = JCS_RGB;
|
||||
|
||||
|
||||
jpeg_set_defaults(&jcInfo);
|
||||
|
||||
jpeg_set_quality(&jcInfo, iQuality, TRUE);
|
||||
|
||||
jpeg_start_compress(&jcInfo, TRUE);
|
||||
int iRowStride = jcInfo.image_width * jcInfo.input_components;
|
||||
while (jcInfo.next_scanline < jcInfo.image_height) {
|
||||
JSAMPROW pData = &(pImg[jcInfo.next_scanline * iRowStride]);
|
||||
jpeg_write_scanlines(&jcInfo, &pData, 1);
|
||||
}
|
||||
|
||||
jpeg_finish_compress(&jcInfo);
|
||||
|
||||
jpeg_destroy_compress(&jcInfo);
|
||||
|
||||
return mRes;
|
||||
}
|
||||
std::pair<unsigned char*, unsigned long> convertBitmapToJpeg(const char* p_pData, int nWidth, int nHeight, int nBpp)
|
||||
{
|
||||
char* pData = (char*)p_pData;
|
||||
|
||||
//32转24
|
||||
if (nBpp == 32) {
|
||||
pData = new char[nWidth*nHeight * 3];
|
||||
char* pSrc = (char*)p_pData;
|
||||
char* pDst = pData;
|
||||
for (int y = 0; y < nHeight; y++) {
|
||||
for (int x = 0; x < nWidth; x++) {
|
||||
pDst[0] = pSrc[0]; pDst[1] = pSrc[1]; pDst[2] = pSrc[2];
|
||||
pSrc += 4;
|
||||
pDst += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::pair<unsigned char*, unsigned long> ret = convertBitmapToJpeg(nWidth, nHeight, 24, (unsigned char*)pData, 80);
|
||||
if (nBpp == 32)
|
||||
delete[] pData;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
@@ -0,0 +1,313 @@
|
||||
/**
|
||||
@file JCPngImg.cpp
|
||||
@brief
|
||||
@author hugao
|
||||
@version 1.0
|
||||
@date 2016_5_11
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "png.h"
|
||||
#include "pngconf.h"
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
#include "../util/JCCommonMethod.h"
|
||||
#include "JCImageRW.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#pragma warning (disable: 4996)
|
||||
namespace laya
|
||||
{
|
||||
typedef struct
|
||||
{
|
||||
unsigned char* data;
|
||||
int size;
|
||||
int offset;
|
||||
}ImageSource;
|
||||
|
||||
//从内存读取PNG图片的回调函数
|
||||
static void pngReadCallback(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
ImageSource* isource = (ImageSource*)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");
|
||||
}
|
||||
void my_error_fn(png_structp png_ptr, png_const_charp error_msg)
|
||||
{
|
||||
|
||||
}
|
||||
void my_warning_fn(png_structp png_ptr,png_const_charp warning_msg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static unsigned int multiply_alpha(unsigned int alpha, unsigned int color)
|
||||
{
|
||||
unsigned int temp = alpha * color + 0x80;
|
||||
return (temp + (temp >> 8)) >> 8;
|
||||
}
|
||||
|
||||
static void premultiply_data(png_structp png, png_row_infop row_info, png_bytep data)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < row_info->rowbytes; i += 4)
|
||||
{
|
||||
unsigned char* base = &data[i];
|
||||
unsigned int alpha = base[3];
|
||||
|
||||
|
||||
if (alpha == 0)
|
||||
base[0] = base[1] = base[2] = base[3] = 0;
|
||||
|
||||
else
|
||||
{
|
||||
unsigned int red = base[0];
|
||||
unsigned int green = base[1];
|
||||
unsigned int blue = base[2];
|
||||
|
||||
|
||||
if (alpha != 0xFF)
|
||||
{
|
||||
red = multiply_alpha(alpha, red);
|
||||
green = multiply_alpha(alpha, green);
|
||||
blue = multiply_alpha(alpha, blue);
|
||||
}
|
||||
|
||||
base[0] = (unsigned char)red;
|
||||
base[1] = (unsigned char)green;
|
||||
base[2] = (unsigned char)blue;
|
||||
base[3] = (unsigned char)alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned char* ReadPNGFromMem(unsigned char* data, int dataSize, PNG_UINT32* w, PNG_UINT32* h)
|
||||
{
|
||||
//unsigned char sig[8];
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
unsigned char* image_data;
|
||||
int bit_depth;
|
||||
int color_type;
|
||||
unsigned int rowbytes;
|
||||
png_uint_32 i;
|
||||
png_bytepp row_pointers;
|
||||
|
||||
if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, my_error_fn, my_warning_fn)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
|
||||
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ImageSource imgsource;
|
||||
imgsource.data = data;
|
||||
imgsource.size = dataSize;
|
||||
imgsource.offset = 0;
|
||||
png_set_read_fn(png_ptr, &imgsource,pngReadCallback);
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
png_set_sig_bytes(png_ptr, 8);
|
||||
png_get_IHDR(png_ptr, info_ptr, w, h, &bit_depth, &color_type, NULL, NULL, NULL);
|
||||
|
||||
//预乘alpha
|
||||
//png_set_read_user_transform_fn(png_ptr, premultiply_data);
|
||||
|
||||
//if (color_type & PNG_COLOR_MASK_ALPHA)
|
||||
// png_set_strip_alpha(png_ptr); //去掉alhpa信息了。TODO 以后要加上。
|
||||
if (bit_depth >8)
|
||||
png_set_strip_16(png_ptr); //16bit的通道要转换成8bit的
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb(png_ptr);
|
||||
if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha(png_ptr);
|
||||
// if (color_type == PNG_COLOR_TYPE_RGB)
|
||||
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);//PNG_FILLER_BEFORE);
|
||||
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
|
||||
rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
if ((image_data =(unsigned char *) malloc(*h * rowbytes)) == NULL) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
return NULL;
|
||||
}
|
||||
if ((row_pointers =(png_bytepp) malloc(*h * sizeof(png_bytep))) == NULL) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
free(image_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < *h; i++)
|
||||
//row_pointers[*h - 1 - i] = image_data + i*rowbytes;
|
||||
row_pointers[i] = image_data + i*rowbytes;
|
||||
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
free(row_pointers);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
|
||||
return image_data;
|
||||
}
|
||||
/*
|
||||
//获得宽高信息,并不最终解码
|
||||
bool LoadPngWH( const char* p_sFileName,int& p_nWidth,int& p_nHeight )
|
||||
{
|
||||
FILE* f;
|
||||
unsigned char sig[8];
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
//unsigned char* image_data;
|
||||
int bit_depth;
|
||||
int color_type;
|
||||
//unsigned int rowbytes;
|
||||
//png_uint_32 i;
|
||||
//png_bytepp row_pointers;
|
||||
|
||||
if ((f = fopen(p_sFileName, "rb")) == NULL)
|
||||
return false;
|
||||
fread(sig, sizeof(*sig), sizeof(sig), f);
|
||||
if (!png_check_sig(sig, sizeof(*sig))) {
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL) {
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
|
||||
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
png_ptr->io_ptr = (png_voidp) f;
|
||||
png_set_sig_bytes(png_ptr, 8);
|
||||
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
png_uint_32 w,h;
|
||||
png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, NULL, NULL, NULL);
|
||||
p_nWidth = w;
|
||||
p_nHeight = h;
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
int SavePng(char* png_file_name, char **data, int width, int height, int bit_depth)
|
||||
{
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
FILE *png_file = fopen(png_file_name, "wb");
|
||||
//assert(png_file);
|
||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if(png_ptr == NULL)
|
||||
{
|
||||
//cerr<<"ERROR:png_create_write_struct/n";
|
||||
if (png_file)
|
||||
fclose(png_file);
|
||||
return 0;
|
||||
}
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if(info_ptr == NULL)
|
||||
{
|
||||
//cerr<<"ERROR:png_create_info_struct/n";
|
||||
if (png_file) {
|
||||
fclose(png_file);
|
||||
}
|
||||
png_destroy_write_struct(&png_ptr, NULL);
|
||||
return 0;
|
||||
}
|
||||
png_init_io(png_ptr, png_file);
|
||||
png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_RGB_ALPHA,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
//png_set_PLTE(png_ptr, info_ptr, palette, palette_len);
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
png_bytepp row_pointers = new png_bytep[height];
|
||||
for (int i=0; i<height; ++i)
|
||||
{
|
||||
row_pointers[i] = (png_bytep)data[i];
|
||||
}
|
||||
png_write_image(png_ptr, row_pointers);
|
||||
delete[] row_pointers;
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
//png_free(png_ptr, palette);
|
||||
//palette=NULL;
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
fclose(png_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef unsigned char ui8;
|
||||
static void PngWriteToMemoryFunc(png_structp png_ptr, png_bytep data, png_size_t length) {
|
||||
std::vector<ui8> *p = (std::vector<ui8>*)png_get_io_ptr(png_ptr);
|
||||
p->insert(p->end(), data, data + length);
|
||||
}
|
||||
|
||||
std::pair<unsigned char*, unsigned long> convertBitmapToPng(const char* p_pData, int nWidth, int nHeight, int nBitDepth)
|
||||
{
|
||||
std::vector<unsigned char> buffer;
|
||||
buffer.reserve(nWidth * nHeight * 4);
|
||||
|
||||
|
||||
std::pair<unsigned char*, unsigned long> res
|
||||
= std::make_pair((unsigned char*)NULL, 0);
|
||||
|
||||
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);
|
||||
if (!png_ptr)
|
||||
return res;
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr)
|
||||
return res;
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
return res;
|
||||
|
||||
png_set_write_fn(png_ptr, &buffer, PngWriteToMemoryFunc, NULL);
|
||||
|
||||
|
||||
png_set_IHDR(png_ptr, info_ptr,
|
||||
nWidth,
|
||||
nHeight,
|
||||
8,
|
||||
PNG_COLOR_TYPE_RGB_ALPHA,
|
||||
PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_DEFAULT,
|
||||
PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
for (int i = 0; i < nHeight; i++)
|
||||
png_write_row(png_ptr, (unsigned char*)p_pData + i * nWidth * 4);
|
||||
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
|
||||
unsigned long nByte = buffer.size();
|
||||
unsigned char* pBuffer = new unsigned char[nByte];
|
||||
memcpy(pBuffer, &buffer[0], nByte);
|
||||
res.first = pBuffer;
|
||||
res.second = nByte;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
Reference in New Issue
Block a user