mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-02-10 18:05:41 +08:00
less me
This commit is contained in:
@ -23,20 +23,20 @@ SOURCES += \
|
||||
$$PWD/../hunspell/src/hunspell/suggestmgr.cxx
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/../hunspell/src/hunspell/affentry.hxx \
|
||||
$$PWD/../hunspell/src/hunspell/affixmgr.hxx \
|
||||
$$PWD/../hunspell/src/hunspell/atypes.hxx \
|
||||
$$PWD/../hunspell/src/hunspell/baseaffix.hxx \
|
||||
$$PWD/../hunspell/src/hunspell/csutil.hxx \
|
||||
$$PWD/../hunspell/src/hunspell/dictmgr.hxx \
|
||||
$$PWD/../hunspell/src/hunspell/filemgr.hxx \
|
||||
$$PWD/../hunspell/src/hunspell/hashmgr.hxx \
|
||||
$$PWD/../hunspell/src/hunspell/htypes.hxx \
|
||||
$$PWD/../hunspell/src/hunspell/hunspell.h \
|
||||
$$PWD/../hunspell/src/hunspell/hunspell.hxx \
|
||||
$$PWD/../hunspell/src/hunspell/hunzip.hxx \
|
||||
$$PWD/../hunspell/src/hunspell/langnum.hxx \
|
||||
$$PWD/../hunspell/src/hunspell/phonet.hxx \
|
||||
$$PWD/../hunspell/src/hunspell/replist.hxx \
|
||||
$$PWD/../hunspell/src/hunspell/suggestmgr.hxx \
|
||||
$$PWD/../hunspell/src/hunspell/w_char.hxx
|
||||
$$PWD/../hunspell/affentry.hxx \
|
||||
$$PWD/../hunspell/affixmgr.hxx \
|
||||
$$PWD/../hunspell/atypes.hxx \
|
||||
$$PWD/../hunspell/baseaffix.hxx \
|
||||
$$PWD/../hunspell/csutil.hxx \
|
||||
$$PWD/../hunspell/dictmgr.hxx \
|
||||
$$PWD/../hunspell/filemgr.hxx \
|
||||
$$PWD/../hunspell/hashmgr.hxx \
|
||||
$$PWD/../hunspell/htypes.hxx \
|
||||
$$PWD/../hunspell/hunspell.h \
|
||||
$$PWD/../hunspell/hunspell.hxx \
|
||||
$$PWD/../hunspell/hunzip.hxx \
|
||||
$$PWD/../hunspell/langnum.hxx \
|
||||
$$PWD/../hunspell/phonet.hxx \
|
||||
$$PWD/../hunspell/replist.hxx \
|
||||
$$PWD/../hunspell/suggestmgr.hxx \
|
||||
$$PWD/../hunspell/w_char.hxx
|
||||
|
||||
@ -102,9 +102,6 @@ typedef T_ULONG64 UINT64;
|
||||
#else
|
||||
|
||||
#if (!defined (_MAC) && (!defined(MIDL_PASS) || defined(__midl)) && (!defined(_M_IX86) || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 64)))
|
||||
#ifdef BUILDING_WASM_MODULE
|
||||
#define __int64 long long
|
||||
#endif
|
||||
typedef __int64 T_LONG64;
|
||||
typedef unsigned __int64 T_ULONG64;
|
||||
typedef T_ULONG64 ULONG64;
|
||||
|
||||
@ -65,6 +65,7 @@ extern "C" {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
|
||||
@ -21,7 +21,6 @@
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CxImage supported formats
|
||||
|
||||
#define CXIMAGE_SUPPORT_BMP 1
|
||||
#define CXIMAGE_SUPPORT_GIF 1
|
||||
#define CXIMAGE_SUPPORT_JPG 1
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
#ifndef __xfile_h
|
||||
#define __xfile_h
|
||||
|
||||
#include "ximadef.h"
|
||||
|
||||
class CxFile
|
||||
{
|
||||
public:
|
||||
CxFile() {}
|
||||
virtual ~CxFile() {}
|
||||
|
||||
virtual bool Close() = 0;
|
||||
virtual size_t Read(void* buffer, size_t size, size_t count, void* limit_start = NULL, void* limit_end = NULL) = 0;
|
||||
virtual size_t Write(const void* buffer, size_t size, size_t count) = 0;
|
||||
virtual bool Seek(int32_t offset, int32_t origin) = 0;
|
||||
virtual int32_t Tell() = 0;
|
||||
virtual bool Flush() = 0;
|
||||
virtual int32_t Error() = 0;
|
||||
virtual bool PutC(uint8_t c)
|
||||
{
|
||||
// Default implementation
|
||||
size_t nWrote = Write(&c, 1, 1);
|
||||
return (bool)(nWrote == 1);
|
||||
}
|
||||
virtual int32_t GetC() = 0;
|
||||
};
|
||||
|
||||
#endif //__xfile_h
|
||||
@ -1,55 +0,0 @@
|
||||
#ifndef __ximacfg_h
|
||||
#define __ximacfg_h
|
||||
|
||||
// CxImage supported features
|
||||
#define CXIMAGE_SUPPORT_ALPHA 1
|
||||
#define CXIMAGE_SUPPORT_SELECTION 1
|
||||
#define CXIMAGE_SUPPORT_TRANSFORMATION 1
|
||||
#define CXIMAGE_SUPPORT_DSP 1
|
||||
#if defined(_WIN32) || defined (_WIN64)
|
||||
#define CXIMAGE_SUPPORT_LAYERS 1
|
||||
#else
|
||||
#define CXIMAGE_SUPPORT_LAYERS 0
|
||||
#endif
|
||||
#define CXIMAGE_SUPPORT_INTERPOLATION 1
|
||||
|
||||
#define CXIMAGE_SUPPORT_DECODE 1
|
||||
#define CXIMAGE_SUPPORT_ENCODE 1
|
||||
#define CXIMAGE_SUPPORT_EXIF 1
|
||||
|
||||
// CxImage supported formats
|
||||
#define CXIMAGE_SUPPORT_BMP 0
|
||||
#define CXIMAGE_SUPPORT_GIF 0
|
||||
#define CXIMAGE_SUPPORT_JPG 1
|
||||
#define CXIMAGE_SUPPORT_PNG 0
|
||||
#define CXIMAGE_SUPPORT_ICO 0
|
||||
#define CXIMAGE_SUPPORT_TIF 0
|
||||
#define CXIMAGE_SUPPORT_TGA 0
|
||||
#define CXIMAGE_SUPPORT_PCX 0
|
||||
#define CXIMAGE_SUPPORT_WBMP 0
|
||||
#define CXIMAGE_SUPPORT_WMF 0
|
||||
|
||||
#define CXIMAGE_SUPPORT_JP2 0
|
||||
#define CXIMAGE_SUPPORT_JPC 0
|
||||
#define CXIMAGE_SUPPORT_PGX 0
|
||||
#define CXIMAGE_SUPPORT_PNM 0
|
||||
#define CXIMAGE_SUPPORT_RAS 0
|
||||
|
||||
#define CXIMAGE_SUPPORT_JBG 0
|
||||
|
||||
#define CXIMAGE_SUPPORT_MNG 0
|
||||
#define CXIMAGE_SUPPORT_SKA 0
|
||||
#define CXIMAGE_SUPPORT_RAW 0
|
||||
#define CXIMAGE_SUPPORT_PSD 0
|
||||
|
||||
#define CXIMAGE_MAX_MEMORY 268435456
|
||||
#define CXIMAGE_DEFAULT_DPI 96
|
||||
|
||||
#define CXIMAGE_ERR_NOFILE "null file handler"
|
||||
#define CXIMAGE_ERR_NOIMAGE "null image!!!"
|
||||
|
||||
#define CXIMAGE_SUPPORT_EXCEPTION_HANDLING 1
|
||||
|
||||
#define RGB2GRAY(r, g, b) (((b) * 117 + (g) * 601 + (r) * 306) >> 10)
|
||||
|
||||
#endif // __ximacfg_h
|
||||
@ -1,48 +0,0 @@
|
||||
#ifndef __ximadef_h
|
||||
#define __ximadef_h
|
||||
|
||||
#include "ximacfg.h"
|
||||
#include <string>
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
#include "stdint.h"
|
||||
#endif
|
||||
|
||||
#ifndef BOOL
|
||||
typedef int BOOL;
|
||||
#endif
|
||||
|
||||
typedef struct tagRECT
|
||||
{
|
||||
int32_t left;
|
||||
int32_t top;
|
||||
int32_t right;
|
||||
int32_t bottom;
|
||||
} RECT;
|
||||
|
||||
typedef struct tagRGBQUAD
|
||||
{
|
||||
uint8_t rgbBlue;
|
||||
uint8_t rgbGreen;
|
||||
uint8_t rgbRed;
|
||||
uint8_t rgbReserved;
|
||||
} RGBQUAD;
|
||||
|
||||
typedef struct tagBITMAPINFOHEADER
|
||||
{
|
||||
uint32_t biSize;
|
||||
int32_t biWidth;
|
||||
int32_t biHeight;
|
||||
uint16_t biPlanes;
|
||||
uint16_t biBitCount;
|
||||
uint32_t biCompression;
|
||||
uint32_t biSizeImage;
|
||||
int32_t biXPelsPerMeter;
|
||||
int32_t biYPelsPerMeter;
|
||||
uint32_t biClrUsed;
|
||||
uint32_t biClrImportant;
|
||||
} BITMAPINFOHEADER;
|
||||
|
||||
#define BI_RGB 0L
|
||||
|
||||
#endif //__ximadef_h
|
||||
@ -1,763 +0,0 @@
|
||||
#include "ximage.h"
|
||||
|
||||
#if CXIMAGE_SUPPORT_JPG
|
||||
#include "ximajpg.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_GIF
|
||||
#include "ximagif.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_PNG
|
||||
#include "ximapng.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_MNG
|
||||
#include "ximamng.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_BMP
|
||||
#include "ximabmp.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_ICO
|
||||
#include "ximaico.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_TIF
|
||||
#include "ximatif.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_TGA
|
||||
#include "ximatga.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_PCX
|
||||
#include "ximapcx.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_WBMP
|
||||
#include "ximawbmp.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_WMF
|
||||
#include "ximawmf.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_JBG
|
||||
#include "ximajbg.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_JASPER
|
||||
#include "ximajas.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_SKA
|
||||
#include "ximaska.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_RAW
|
||||
#include "ximaraw.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_PSD
|
||||
#include "ximapsd.h"
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_DECODE
|
||||
CxImage::CxImage(uint8_t* buffer, uint32_t size, uint32_t imagetype)
|
||||
{
|
||||
Startup(imagetype);
|
||||
CxMemFile stream(buffer, size);
|
||||
Decode(&stream, imagetype);
|
||||
}
|
||||
bool CxImage::Decode(uint8_t* buffer, uint32_t size, uint32_t imagetype)
|
||||
{
|
||||
CxMemFile file(buffer,size);
|
||||
return Decode(&file, imagetype);
|
||||
}
|
||||
bool CxImage::Decode(CxFile* hFile, uint32_t imagetype)
|
||||
{
|
||||
if (hFile == NULL)
|
||||
{
|
||||
strcpy(info.szLastError, CXIMAGE_ERR_NOFILE);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t pos = hFile->Tell();
|
||||
|
||||
#if CXIMAGE_SUPPORT_BMP
|
||||
if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_BMP==imagetype){
|
||||
CxImageBMP *newima = new CxImageBMP;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile)) {
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JPG
|
||||
if (CXIMAGE_FORMAT_UNKNOWN == imagetype || CXIMAGE_FORMAT_JPG == imagetype)
|
||||
{
|
||||
CxImageJPG *newima = new CxImageJPG;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile))
|
||||
{
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(info.szLastError, newima->GetLastError());
|
||||
hFile->Seek(pos, SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN != imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_ICO
|
||||
if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_ICO==imagetype){
|
||||
CxImageICO *newima = new CxImageICO;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile)) {
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
info.nNumFrames = newima->info.nNumFrames;
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_GIF
|
||||
if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_GIF==imagetype){
|
||||
CxImageGIF *newima = new CxImageGIF;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile)) {
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
info.nNumFrames = newima->info.nNumFrames;
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PNG
|
||||
if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_PNG==imagetype){
|
||||
CxImagePNG *newima = new CxImagePNG;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile)) {
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_TIF
|
||||
if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_TIF==imagetype){
|
||||
CxImageTIF *newima = new CxImageTIF;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile)) {
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
info.nNumFrames = newima->info.nNumFrames;
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_MNG
|
||||
if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_MNG==imagetype){
|
||||
CxImageMNG *newima = new CxImageMNG;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile)) {
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
info.nNumFrames = newima->info.nNumFrames;
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_TGA
|
||||
if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_TGA==imagetype){
|
||||
CxImageTGA *newima = new CxImageTGA;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile)) {
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PCX
|
||||
if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_PCX==imagetype){
|
||||
CxImagePCX *newima = new CxImagePCX;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile)) {
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_WBMP
|
||||
if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_WBMP==imagetype){
|
||||
CxImageWBMP *newima = new CxImageWBMP;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile)) {
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS
|
||||
if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_WMF==imagetype){
|
||||
CxImageWMF *newima = new CxImageWMF;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile)) {
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JBG
|
||||
if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_JBG==imagetype){
|
||||
CxImageJBG *newima = new CxImageJBG;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile)) {
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JASPER
|
||||
if (CXIMAGE_FORMAT_UNKNOWN==imagetype ||
|
||||
#if CXIMAGE_SUPPORT_JP2
|
||||
CXIMAGE_FORMAT_JP2==imagetype ||
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JPC
|
||||
CXIMAGE_FORMAT_JPC==imagetype ||
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PGX
|
||||
CXIMAGE_FORMAT_PGX==imagetype ||
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PNM
|
||||
CXIMAGE_FORMAT_PNM==imagetype ||
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_RAS
|
||||
CXIMAGE_FORMAT_RAS==imagetype ||
|
||||
#endif
|
||||
false ){
|
||||
CxImageJAS *newima = new CxImageJAS;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile)) {
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_SKA
|
||||
if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_SKA==imagetype){
|
||||
CxImageSKA *newima = new CxImageSKA;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile)) {
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_RAW
|
||||
if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_RAW==imagetype){
|
||||
CxImageRAW *newima = new CxImageRAW;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile)) {
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PSD
|
||||
if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_PSD==imagetype){
|
||||
CxImagePSD *newima = new CxImagePSD;
|
||||
if (!newima)
|
||||
return false;
|
||||
newima->CopyInfo(*this);
|
||||
if (newima->Decode(hFile)) {
|
||||
Transfer(*newima);
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
delete newima;
|
||||
if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
strcpy(info.szLastError, "Decode: Unknown or wrong format");
|
||||
return false;
|
||||
}
|
||||
#endif // CXIMAGE_SUPPORT_DECODE
|
||||
|
||||
#if CXIMAGE_SUPPORT_ENCODE
|
||||
bool CxImage::EncodeSafeCheck(CxFile* hFile)
|
||||
{
|
||||
if (hFile == NULL)
|
||||
{
|
||||
strcpy(info.szLastError, CXIMAGE_ERR_NOFILE);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pDib == NULL)
|
||||
{
|
||||
strcpy(info.szLastError, CXIMAGE_ERR_NOIMAGE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool CxImage::Encode(uint8_t* &buffer, int32_t &size, uint32_t imagetype)
|
||||
{
|
||||
/*
|
||||
if (buffer != NULL)
|
||||
{
|
||||
strcpy(info.szLastError, "the buffer must be empty");
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
CxMemFile file;
|
||||
file.Open();
|
||||
if (Encode(&file, imagetype))
|
||||
{
|
||||
buffer = file.GetBuffer();
|
||||
size = file.Size();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool CxImage::Encode(CxFile* hFile, uint32_t imagetype)
|
||||
{
|
||||
|
||||
#if CXIMAGE_SUPPORT_BMP
|
||||
if (CXIMAGE_FORMAT_BMP==imagetype){
|
||||
CxImageBMP *newima = new CxImageBMP;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile)){
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_ICO
|
||||
if (CXIMAGE_FORMAT_ICO==imagetype){
|
||||
CxImageICO *newima = new CxImageICO;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile)){
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_TIF
|
||||
if (CXIMAGE_FORMAT_TIF==imagetype){
|
||||
CxImageTIF *newima = new CxImageTIF;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile)){
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JPG
|
||||
if (CXIMAGE_FORMAT_JPG == imagetype)
|
||||
{
|
||||
CxImageJPG* newima = new CxImageJPG;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile))
|
||||
{
|
||||
delete newima;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(info.szLastError, newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_GIF
|
||||
if (CXIMAGE_FORMAT_GIF==imagetype){
|
||||
CxImageGIF *newima = new CxImageGIF;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile)){
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PNG
|
||||
if (CXIMAGE_FORMAT_PNG==imagetype){
|
||||
CxImagePNG *newima = new CxImagePNG;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile)){
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_MNG
|
||||
if (CXIMAGE_FORMAT_MNG==imagetype){
|
||||
CxImageMNG *newima = new CxImageMNG;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile)){
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_TGA
|
||||
if (CXIMAGE_FORMAT_TGA==imagetype){
|
||||
CxImageTGA *newima = new CxImageTGA;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile)){
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PCX
|
||||
if (CXIMAGE_FORMAT_PCX==imagetype){
|
||||
CxImagePCX *newima = new CxImagePCX;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile)){
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_WBMP
|
||||
if (CXIMAGE_FORMAT_WBMP==imagetype){
|
||||
CxImageWBMP *newima = new CxImageWBMP;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile)){
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS // <vho> - WMF/EMF support
|
||||
if (CXIMAGE_FORMAT_WMF==imagetype){
|
||||
CxImageWMF *newima = new CxImageWMF;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile)){
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JBG
|
||||
if (CXIMAGE_FORMAT_JBG==imagetype){
|
||||
CxImageJBG *newima = new CxImageJBG;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile)){
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JASPER
|
||||
if (
|
||||
#if CXIMAGE_SUPPORT_JP2
|
||||
CXIMAGE_FORMAT_JP2==imagetype ||
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JPC
|
||||
CXIMAGE_FORMAT_JPC==imagetype ||
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PGX
|
||||
CXIMAGE_FORMAT_PGX==imagetype ||
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PNM
|
||||
CXIMAGE_FORMAT_PNM==imagetype ||
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_RAS
|
||||
CXIMAGE_FORMAT_RAS==imagetype ||
|
||||
#endif
|
||||
false ){
|
||||
CxImageJAS *newima = new CxImageJAS;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile,imagetype)){
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_SKA
|
||||
if (CXIMAGE_FORMAT_SKA==imagetype){
|
||||
CxImageSKA *newima = new CxImageSKA;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile)){
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_RAW
|
||||
if (CXIMAGE_FORMAT_RAW==imagetype){
|
||||
CxImageRAW *newima = new CxImageRAW;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile)){
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CXIMAGE_SUPPORT_PSD
|
||||
if (CXIMAGE_FORMAT_PSD==imagetype){
|
||||
CxImagePSD *newima = new CxImagePSD;
|
||||
if (!newima) return false;
|
||||
newima->Ghost(this);
|
||||
if (newima->Encode(hFile)){
|
||||
delete newima;
|
||||
return true;
|
||||
} else {
|
||||
strcpy(info.szLastError,newima->GetLastError());
|
||||
delete newima;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
strcpy(info.szLastError, "Encode: Unknown format");
|
||||
return false;
|
||||
}
|
||||
bool CxImage::Encode2RGBA(uint8_t* &buffer, int32_t &size, bool bFlipY)
|
||||
{
|
||||
if (buffer != NULL)
|
||||
{
|
||||
strcpy(info.szLastError, "the buffer must be empty");
|
||||
return false;
|
||||
}
|
||||
CxMemFile file;
|
||||
file.Open();
|
||||
if (Encode2RGBA(&file, bFlipY))
|
||||
{
|
||||
buffer = file.GetBuffer();
|
||||
size = file.Size();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool CxImage::Encode2RGBA(CxFile* hFile, bool bFlipY)
|
||||
{
|
||||
if (EncodeSafeCheck(hFile)) return false;
|
||||
|
||||
for (int32_t y1 = 0; y1 < head.biHeight; y1++)
|
||||
{
|
||||
int32_t y = bFlipY ? head.biHeight - 1 - y1 : y1;
|
||||
for (int32_t x = 0; x < head.biWidth; x++)
|
||||
{
|
||||
RGBQUAD color = BlindGetPixelColor(x, y);
|
||||
hFile->PutC(color.rgbRed);
|
||||
hFile->PutC(color.rgbGreen);
|
||||
hFile->PutC(color.rgbBlue);
|
||||
hFile->PutC(color.rgbReserved);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif //CXIMAGE_SUPPORT_ENCODE
|
||||
@ -1,852 +0,0 @@
|
||||
#include "ximajpg.h"
|
||||
|
||||
#if CXIMAGEJPG_SUPPORT_EXIF
|
||||
|
||||
CxImageJPG::CxExifInfo::CxExifInfo(EXIFINFO* info)
|
||||
{
|
||||
if (info)
|
||||
{
|
||||
m_exifinfo = info;
|
||||
freeinfo = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_exifinfo = new EXIFINFO;
|
||||
memset(m_exifinfo, 0, sizeof(EXIFINFO));
|
||||
freeinfo = true;
|
||||
}
|
||||
|
||||
m_szLastError[0] ='\0';
|
||||
ExifImageWidth = MotorolaOrder = 0;
|
||||
SectionsRead = 0;
|
||||
memset(&Sections, 0, MAX_SECTIONS * sizeof(Section_t));
|
||||
}
|
||||
CxImageJPG::CxExifInfo::~CxExifInfo()
|
||||
{
|
||||
for (int32_t i = 0; i < MAX_SECTIONS; i++) if (Sections[i].Data) free(Sections[i].Data);
|
||||
if (freeinfo) delete m_exifinfo;
|
||||
}
|
||||
bool CxImageJPG::CxExifInfo::DecodeExif(CxFile* hFile, int32_t nReadMode)
|
||||
{
|
||||
int32_t a;
|
||||
int32_t HaveCom = FALSE;
|
||||
|
||||
a = hFile->GetC();
|
||||
|
||||
if (a != 0xff || hFile->GetC() != M_SOI)
|
||||
return FALSE;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int32_t itemlen;
|
||||
int32_t marker = 0;
|
||||
int32_t ll, lh, got;
|
||||
uint8_t* Data;
|
||||
|
||||
if (SectionsRead >= MAX_SECTIONS)
|
||||
{
|
||||
strcpy(m_szLastError, "Too many sections in jpg file");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (a = 0; a < 7; a++)
|
||||
{
|
||||
marker = hFile->GetC();
|
||||
if (marker != 0xff) break;
|
||||
|
||||
if (a >= 6)
|
||||
{
|
||||
printf("too many padding bytes\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (marker == 0xff)
|
||||
{
|
||||
// 0xff is legal padding, but if we get that many, something's wrong.
|
||||
strcpy(m_szLastError, "too many padding bytes!");
|
||||
return false;
|
||||
}
|
||||
|
||||
Sections[SectionsRead].Type = marker;
|
||||
|
||||
// Read the length of the section.
|
||||
lh = hFile->GetC();
|
||||
ll = hFile->GetC();
|
||||
|
||||
itemlen = (lh << 8) | ll;
|
||||
|
||||
if (itemlen < 2)
|
||||
{
|
||||
strcpy(m_szLastError,"invalid marker");
|
||||
return false;
|
||||
}
|
||||
|
||||
Sections[SectionsRead].Size = itemlen;
|
||||
|
||||
Data = (uint8_t *)malloc(itemlen);
|
||||
if (Data == NULL)
|
||||
{
|
||||
strcpy(m_szLastError,"Could not allocate memory");
|
||||
return false;
|
||||
}
|
||||
Sections[SectionsRead].Data = Data;
|
||||
|
||||
// Store first two pre-read bytes.
|
||||
Data[0] = (uint8_t)lh;
|
||||
Data[1] = (uint8_t)ll;
|
||||
|
||||
got = hFile->Read(Data + 2, 1, itemlen - 2); // Read the whole section.
|
||||
if (got != itemlen - 2)
|
||||
{
|
||||
strcpy(m_szLastError, "Premature end of file?");
|
||||
return false;
|
||||
}
|
||||
SectionsRead += 1;
|
||||
|
||||
switch (marker)
|
||||
{
|
||||
|
||||
case M_SOS: // stop before hitting compressed data
|
||||
// If reading entire image is requested, read the rest of the data.
|
||||
if (nReadMode & EXIF_READ_IMAGE)
|
||||
{
|
||||
int32_t cp, ep, size;
|
||||
// Determine how much file is left.
|
||||
cp = hFile->Tell();
|
||||
hFile->Seek(0, SEEK_END);
|
||||
ep = hFile->Tell();
|
||||
hFile->Seek(cp, SEEK_SET);
|
||||
|
||||
size = ep - cp;
|
||||
Data = (uint8_t*)malloc(size);
|
||||
if (Data == NULL)
|
||||
{
|
||||
strcpy(m_szLastError, "could not allocate data for entire image");
|
||||
return false;
|
||||
}
|
||||
|
||||
got = hFile->Read(Data, 1, size);
|
||||
if (got != size)
|
||||
{
|
||||
strcpy(m_szLastError, "could not read the rest of the image");
|
||||
return false;
|
||||
}
|
||||
|
||||
Sections[SectionsRead].Data = Data;
|
||||
Sections[SectionsRead].Size = size;
|
||||
Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER;
|
||||
SectionsRead ++;
|
||||
}
|
||||
return true;
|
||||
|
||||
case M_EOI: // in case it's a tables-only JPEG stream
|
||||
printf("No image in jpeg!\n");
|
||||
return FALSE;
|
||||
|
||||
case M_COM: // Comment section
|
||||
if (HaveCom || ((nReadMode & EXIF_READ_EXIF) == 0))
|
||||
{
|
||||
// Discard this section.
|
||||
free(Sections[--SectionsRead].Data);
|
||||
Sections[SectionsRead].Data=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
process_COM(Data, itemlen);
|
||||
HaveCom = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case M_JFIF:
|
||||
// Regular jpegs always have this tag, exif images have the exif
|
||||
// marker instead, althogh ACDsee will write images with both markers.
|
||||
// this program will re-create this marker on absence of exif marker.
|
||||
// hence no need to keep the copy from the file.
|
||||
free(Sections[--SectionsRead].Data);
|
||||
Sections[SectionsRead].Data = 0;
|
||||
break;
|
||||
|
||||
case M_EXIF:
|
||||
// Seen files from some 'U-lead' software with Vivitar scanner
|
||||
// that uses marker 31 for non exif stuff. Thus make sure
|
||||
// it says 'Exif' in the section before treating it as exif.
|
||||
if ((nReadMode & EXIF_READ_EXIF) && itemlen >= 6 && memcmp(Data + 2, "Exif", 4) == 0)
|
||||
m_exifinfo->IsExif = process_EXIF((uint8_t*)Data + 2, itemlen - 2);
|
||||
else
|
||||
{
|
||||
// Discard this section.
|
||||
free(Sections[--SectionsRead].Data);
|
||||
Sections[SectionsRead].Data = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case M_SOF0:
|
||||
case M_SOF1:
|
||||
case M_SOF2:
|
||||
case M_SOF3:
|
||||
case M_SOF5:
|
||||
case M_SOF6:
|
||||
case M_SOF7:
|
||||
case M_SOF9:
|
||||
case M_SOF10:
|
||||
case M_SOF11:
|
||||
case M_SOF13:
|
||||
case M_SOF14:
|
||||
case M_SOF15:
|
||||
if (itemlen < 8)
|
||||
return false;
|
||||
process_SOFn(Data, marker);
|
||||
break;
|
||||
default:
|
||||
// Skip any other sections.
|
||||
//if (ShowTags) printf("Jpeg section marker 0x%02x size %d\n",marker, itemlen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool CxImageJPG::CxExifInfo::process_EXIF(uint8_t* CharBuf, uint32_t length)
|
||||
{
|
||||
m_exifinfo->FlashUsed = 0;
|
||||
/* If it's from a digicam, and it used flash, it says so. */
|
||||
m_exifinfo->Comments[0] = '\0'; /* Initial value - null string */
|
||||
|
||||
if (length < 6)
|
||||
return false;
|
||||
|
||||
ExifImageWidth = 0;
|
||||
|
||||
{ /* Check the EXIF header component */
|
||||
static const uint8_t ExifHeader[] = "Exif\0\0";
|
||||
if (memcmp(CharBuf + 0, ExifHeader, 6))
|
||||
{
|
||||
strcpy(m_szLastError, "Incorrect Exif header");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (length < 8)
|
||||
return false;
|
||||
|
||||
if (memcmp(CharBuf + 6, "II", 2) == 0)
|
||||
MotorolaOrder = 0;
|
||||
else
|
||||
{
|
||||
if (memcmp(CharBuf + 6, "MM", 2) == 0)
|
||||
MotorolaOrder = 1;
|
||||
else
|
||||
{
|
||||
strcpy(m_szLastError, "Invalid Exif alignment marker.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (length < 14)
|
||||
return false;
|
||||
|
||||
/* Check the next two values for correctness. */
|
||||
if (Get16u(CharBuf + 8) != 0x2a)
|
||||
{
|
||||
strcpy(m_szLastError, "Invalid Exif start (1)");
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t FirstOffset = Get32u(CharBuf + 10);
|
||||
/* <Richard Collins>
|
||||
if (FirstOffset < 8 || FirstOffset > 16){
|
||||
// I used to ensure this was set to 8 (website I used indicated its 8)
|
||||
// but PENTAX Optio 230 has it set differently, and uses it as offset. (Sept 11 2002)
|
||||
strcpy(m_szLastError,"Suspicious offset of first IFD value");
|
||||
return false;
|
||||
}*/
|
||||
|
||||
uint8_t * LastExifRefd = CharBuf;
|
||||
|
||||
#if 0
|
||||
/* First directory starts 16 bytes in. Offsets start at 8 bytes in. */
|
||||
if (!ProcessExifDir(CharBuf+14, CharBuf+6, length-6, m_exifinfo, &LastExifRefd))
|
||||
return false;
|
||||
|
||||
/* <Richard Collins> give a chance for a second directory */
|
||||
if (FirstOffset > 8) {
|
||||
if (!ProcessExifDir(CharBuf+14+FirstOffset-8, CharBuf+6, length-6, m_exifinfo, &LastExifRefd))
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
CSafeReader reader(CharBuf, length);
|
||||
/* First directory starts 16 bytes in. Offsets start at 8 bytes in. */
|
||||
if (!ProcessExifDir2(reader.Offset(14), reader.Offset(6), length - 6, m_exifinfo, &LastExifRefd))
|
||||
return false;
|
||||
|
||||
/* <Richard Collins> give a chance for a second directory */
|
||||
if (FirstOffset > 8)
|
||||
{
|
||||
if (!ProcessExifDir2(reader.Offset(14 + FirstOffset - 8), reader.Offset(6), length - 6, m_exifinfo, &LastExifRefd))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This is how far the interesting (non thumbnail) part of the exif went. */
|
||||
// int32_t ExifSettingsLength = LastExifRefd - CharBuf;
|
||||
|
||||
/* Compute the CCD width, in milimeters. */
|
||||
if (m_exifinfo->FocalplaneXRes != 0)
|
||||
m_exifinfo->CCDWidth = (float)(ExifImageWidth * m_exifinfo->FocalplaneUnits / m_exifinfo->FocalplaneXRes);
|
||||
|
||||
return true;
|
||||
}
|
||||
int32_t CxImageJPG::CxExifInfo::Get16u(void* Short)
|
||||
{
|
||||
if (MotorolaOrder)
|
||||
return (((uint8_t*)Short)[0] << 8) | ((uint8_t*)Short)[1];
|
||||
else
|
||||
return (((uint8_t*)Short)[1] << 8) | ((uint8_t*)Short)[0];
|
||||
}
|
||||
int32_t CxImageJPG::CxExifInfo::Get16m(void * Short)
|
||||
{
|
||||
return (((uint8_t *)Short)[0] << 8) | ((uint8_t *)Short)[1];
|
||||
}
|
||||
int32_t CxImageJPG::CxExifInfo::Get32s(void* Long)
|
||||
{
|
||||
if (MotorolaOrder)
|
||||
return ((( char*)Long)[0] << 24) | (((uint8_t*)Long)[1] << 16)
|
||||
| (((uint8_t*)Long)[2] << 8) | (((uint8_t*)Long)[3] << 0);
|
||||
else
|
||||
return ((( char*)Long)[3] << 24) | (((uint8_t*)Long)[2] << 16)
|
||||
| (((uint8_t*)Long)[1] << 8) | (((uint8_t*)Long)[0] << 0);
|
||||
}
|
||||
uint32_t CxImageJPG::CxExifInfo::Get32u(void* Long)
|
||||
{
|
||||
return (uint32_t)Get32s(Long) & 0xffffffff;
|
||||
}
|
||||
|
||||
/* Describes format descriptor */
|
||||
static const int32_t BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8};
|
||||
#define NUM_FORMATS 12
|
||||
|
||||
#define FMT_BYTE 1
|
||||
#define FMT_STRING 2
|
||||
#define FMT_USHORT 3
|
||||
#define FMT_ULONG 4
|
||||
#define FMT_URATIONAL 5
|
||||
#define FMT_SBYTE 6
|
||||
#define FMT_UNDEFINED 7
|
||||
#define FMT_SSHORT 8
|
||||
#define FMT_SLONG 9
|
||||
#define FMT_SRATIONAL 10
|
||||
#define FMT_SINGLE 11
|
||||
#define FMT_DOUBLE 12
|
||||
|
||||
/* Describes tag values */
|
||||
|
||||
#define TAG_EXIF_VERSION 0x9000
|
||||
#define TAG_EXIF_OFFSET 0x8769
|
||||
#define TAG_INTEROP_OFFSET 0xa005
|
||||
|
||||
#define TAG_MAKE 0x010F
|
||||
#define TAG_MODEL 0x0110
|
||||
|
||||
#define TAG_ORIENTATION 0x0112
|
||||
#define TAG_XRESOLUTION 0x011A
|
||||
#define TAG_YRESOLUTION 0x011B
|
||||
#define TAG_RESOLUTIONUNIT 0x0128
|
||||
|
||||
#define TAG_EXPOSURETIME 0x829A
|
||||
#define TAG_FNUMBER 0x829D
|
||||
|
||||
#define TAG_SHUTTERSPEED 0x9201
|
||||
#define TAG_APERTURE 0x9202
|
||||
#define TAG_BRIGHTNESS 0x9203
|
||||
#define TAG_MAXAPERTURE 0x9205
|
||||
#define TAG_FOCALLENGTH 0x920A
|
||||
|
||||
#define TAG_DATETIME_ORIGINAL 0x9003
|
||||
#define TAG_USERCOMMENT 0x9286
|
||||
|
||||
#define TAG_SUBJECT_DISTANCE 0x9206
|
||||
#define TAG_FLASH 0x9209
|
||||
|
||||
#define TAG_FOCALPLANEXRES 0xa20E
|
||||
#define TAG_FOCALPLANEYRES 0xa20F
|
||||
#define TAG_FOCALPLANEUNITS 0xa210
|
||||
#define TAG_EXIF_IMAGEWIDTH 0xA002
|
||||
#define TAG_EXIF_IMAGELENGTH 0xA003
|
||||
|
||||
/* the following is added 05-jan-2001 vcs */
|
||||
#define TAG_EXPOSURE_BIAS 0x9204
|
||||
#define TAG_WHITEBALANCE 0x9208
|
||||
#define TAG_METERING_MODE 0x9207
|
||||
#define TAG_EXPOSURE_PROGRAM 0x8822
|
||||
#define TAG_ISO_EQUIVALENT 0x8827
|
||||
#define TAG_COMPRESSION_LEVEL 0x9102
|
||||
|
||||
#define TAG_THUMBNAIL_OFFSET 0x0201
|
||||
#define TAG_THUMBNAIL_LENGTH 0x0202
|
||||
|
||||
bool CxImageJPG::CxExifInfo::ProcessExifDir2(CSafeReader DirStart, CSafeReader OffsetBase, unsigned ExifLength,
|
||||
EXIFINFO* const m_exifinfo, uint8_t** const LastExifRefdP, int32_t NestingLevel)
|
||||
{
|
||||
int32_t de;
|
||||
int32_t a;
|
||||
int32_t NumDirEntries;
|
||||
unsigned ThumbnailOffset = 0;
|
||||
unsigned ThumbnailSize = 0;
|
||||
|
||||
if (NestingLevel > 4)
|
||||
{
|
||||
strcpy(m_szLastError,"Maximum directory nesting exceeded (corrupt exif header)");
|
||||
return false;
|
||||
}
|
||||
|
||||
NumDirEntries = DirStart.Check(2) ? Get16u(DirStart.GetData(0)) : 0;
|
||||
|
||||
if ((DirStart.GetData(2 + NumDirEntries * 12 + 2)) > (OffsetBase.GetData(ExifLength)))
|
||||
{
|
||||
strcpy(m_szLastError, "Illegally sized directory");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (de = 0; de < NumDirEntries; de++)
|
||||
{
|
||||
int32_t Tag, Format, Components;
|
||||
CSafeReader ValuePtr;
|
||||
/* This actually can point to a variety of things; it must be
|
||||
cast to other types when used. But we use it as a byte-by-byte
|
||||
cursor, so we declare it as a pointer to a generic byte here.
|
||||
*/
|
||||
int32_t ByteCount;
|
||||
CSafeReader DirEntry = DirStart.Offset(2 + 12 * de);
|
||||
|
||||
Tag = DirEntry.Check(2) ? Get16u(DirEntry.GetData(0)) : 0;
|
||||
Format = DirEntry.Check(2, 2) ? Get16u(DirEntry.GetData(2)) : 0;
|
||||
Components = DirEntry.Check(4, 4) ? Get32u(DirEntry.GetData(4)) : 0;
|
||||
|
||||
if ((Format - 1) >= NUM_FORMATS)
|
||||
{
|
||||
/* (-1) catches illegal zero case as unsigned underflows to positive large */
|
||||
strcpy(m_szLastError, "Illegal format code in EXIF dir");
|
||||
return false;
|
||||
}
|
||||
|
||||
ByteCount = Components * BytesPerFormat[Format];
|
||||
|
||||
if (ByteCount > 4)
|
||||
{
|
||||
unsigned OffsetVal;
|
||||
OffsetVal = DirEntry.Check(8, 4) ? Get32u(DirEntry.GetData(8)) : 0;
|
||||
/* If its bigger than 4 bytes, the dir entry contains an offset.*/
|
||||
if (OffsetVal + ByteCount > ExifLength)
|
||||
{
|
||||
/* Bogus pointer offset and / or bytecount value */
|
||||
strcpy(m_szLastError, "Illegal pointer offset value in EXIF.");
|
||||
return false;
|
||||
}
|
||||
ValuePtr = OffsetBase.Offset(OffsetVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 4 bytes or less and value is in the dir entry itself */
|
||||
ValuePtr = DirEntry.Offset(8);
|
||||
}
|
||||
|
||||
if (*LastExifRefdP < ValuePtr.GetData(ByteCount))
|
||||
{
|
||||
/* Keep track of last byte in the exif header that was
|
||||
actually referenced. That way, we know where the
|
||||
discardable thumbnail data begins.
|
||||
*/
|
||||
*LastExifRefdP = ValuePtr.GetData(ByteCount);
|
||||
}
|
||||
|
||||
/* Extract useful components of tag */
|
||||
switch(Tag)
|
||||
{
|
||||
case TAG_MAKE:
|
||||
if (ValuePtr.Check(31)) strncpy(m_exifinfo->CameraMake, (char*)ValuePtr.GetData(0), 31);
|
||||
break;
|
||||
case TAG_MODEL:
|
||||
if (ValuePtr.Check(39)) strncpy(m_exifinfo->CameraModel, (char*)ValuePtr.GetData(0), 39);
|
||||
break;
|
||||
case TAG_EXIF_VERSION:
|
||||
if (ValuePtr.Check(4)) strncpy(m_exifinfo->Version,(char*)ValuePtr.GetData(0), 4);
|
||||
break;
|
||||
case TAG_DATETIME_ORIGINAL:
|
||||
if (ValuePtr.Check(19)) strncpy(m_exifinfo->DateTime, (char*)ValuePtr.GetData(0), 19);
|
||||
break;
|
||||
case TAG_USERCOMMENT:
|
||||
// Olympus has this padded with trailing spaces. Remove these first.
|
||||
if (ValuePtr.Check(ByteCount))
|
||||
{
|
||||
for (a = ByteCount;;)
|
||||
{
|
||||
a--;
|
||||
if (*((char*)ValuePtr.GetData(a)) == ' ')
|
||||
*((char*)ValuePtr.GetData(a)) = '\0';
|
||||
else
|
||||
break;
|
||||
if (a == 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the comment */
|
||||
if (ValuePtr.Check(5) && memcmp(ValuePtr.GetData(0), "ASCII", 5) == 0)
|
||||
{
|
||||
for (a = 5; a < 10; a++)
|
||||
{
|
||||
char c;
|
||||
c = *((char*)ValuePtr.GetData(a));
|
||||
if (c != '\0' && c != ' ')
|
||||
{
|
||||
if (ValuePtr.Check(a, 199))
|
||||
strncpy(m_exifinfo->Comments, (char*)ValuePtr.GetData(a), 199);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ValuePtr.Check(199))
|
||||
strncpy(m_exifinfo->Comments, (char*)ValuePtr.GetData(0), 199);
|
||||
break;
|
||||
case TAG_FNUMBER:
|
||||
/* Simplest way of expressing aperture, so I trust it the most.
|
||||
(overwrite previously computd value if there is one)
|
||||
*/
|
||||
m_exifinfo->ApertureFNumber = (float)ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
case TAG_APERTURE:
|
||||
case TAG_MAXAPERTURE:
|
||||
/* More relevant info always comes earlier, so only
|
||||
use this field if we don't have appropriate aperture
|
||||
information yet.
|
||||
*/
|
||||
if (m_exifinfo->ApertureFNumber == 0){
|
||||
m_exifinfo->ApertureFNumber = (float)exp(ConvertAnyFormat2(ValuePtr, Format)*log(2.0f)*0.5);
|
||||
}
|
||||
break;
|
||||
case TAG_BRIGHTNESS:
|
||||
m_exifinfo->Brightness = (float)ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
case TAG_FOCALLENGTH:
|
||||
/* Nice digital cameras actually save the focal length
|
||||
as a function of how farthey are zoomed in.
|
||||
*/
|
||||
m_exifinfo->FocalLength = (float)ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
case TAG_SUBJECT_DISTANCE:
|
||||
/* Inidcates the distacne the autofocus camera is focused to.
|
||||
Tends to be less accurate as distance increases.
|
||||
*/
|
||||
m_exifinfo->Distance = (float)ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
case TAG_EXPOSURETIME:
|
||||
/* Simplest way of expressing exposure time, so I
|
||||
trust it most. (overwrite previously computd value
|
||||
if there is one)
|
||||
*/
|
||||
m_exifinfo->ExposureTime =
|
||||
(float)ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
case TAG_SHUTTERSPEED:
|
||||
/* More complicated way of expressing exposure time,
|
||||
so only use this value if we don't already have it
|
||||
from somewhere else.
|
||||
*/
|
||||
if (m_exifinfo->ExposureTime == 0)
|
||||
{
|
||||
m_exifinfo->ExposureTime = (float)
|
||||
(1 / exp(ConvertAnyFormat2(ValuePtr, Format) * log(2.0f)));
|
||||
}
|
||||
break;
|
||||
case TAG_FLASH:
|
||||
if ((int32_t)ConvertAnyFormat2(ValuePtr, Format) & 7)
|
||||
m_exifinfo->FlashUsed = 1;
|
||||
else
|
||||
m_exifinfo->FlashUsed = 0;
|
||||
break;
|
||||
case TAG_ORIENTATION:
|
||||
m_exifinfo->Orientation = (int32_t)ConvertAnyFormat2(ValuePtr, Format);
|
||||
if (m_exifinfo->Orientation < 1 || m_exifinfo->Orientation > 8)
|
||||
{
|
||||
strcpy(m_szLastError,"Undefined rotation value");
|
||||
m_exifinfo->Orientation = 0;
|
||||
}
|
||||
break;
|
||||
case TAG_EXIF_IMAGELENGTH:
|
||||
case TAG_EXIF_IMAGEWIDTH:
|
||||
/* Use largest of height and width to deal with images
|
||||
that have been rotated to portrait format.
|
||||
*/
|
||||
a = (int32_t)ConvertAnyFormat2(ValuePtr, Format);
|
||||
if (ExifImageWidth < a) ExifImageWidth = a;
|
||||
break;
|
||||
case TAG_FOCALPLANEXRES:
|
||||
m_exifinfo->FocalplaneXRes = (float)ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
case TAG_FOCALPLANEYRES:
|
||||
m_exifinfo->FocalplaneYRes = (float)ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
case TAG_RESOLUTIONUNIT:
|
||||
switch ((int32_t)ConvertAnyFormat2(ValuePtr, Format))
|
||||
{
|
||||
case 1: m_exifinfo->ResolutionUnit = 1.0f; break; /* 1 inch */
|
||||
case 2: m_exifinfo->ResolutionUnit = 1.0f; break;
|
||||
case 3: m_exifinfo->ResolutionUnit = 0.3937007874f; break; /* 1 centimeter*/
|
||||
case 4: m_exifinfo->ResolutionUnit = 0.03937007874f; break; /* 1 millimeter*/
|
||||
case 5: m_exifinfo->ResolutionUnit = 0.00003937007874f; /* 1 micrometer*/
|
||||
}
|
||||
break;
|
||||
case TAG_FOCALPLANEUNITS:
|
||||
switch ((int32_t)ConvertAnyFormat2(ValuePtr, Format))
|
||||
{
|
||||
case 1: m_exifinfo->FocalplaneUnits = 1.0f; break; /* 1 inch */
|
||||
case 2: m_exifinfo->FocalplaneUnits = 1.0f; break;
|
||||
case 3: m_exifinfo->FocalplaneUnits = 0.3937007874f; break; /* 1 centimeter*/
|
||||
case 4: m_exifinfo->FocalplaneUnits = 0.03937007874f; break; /* 1 millimeter*/
|
||||
case 5: m_exifinfo->FocalplaneUnits = 0.00003937007874f; /* 1 micrometer*/
|
||||
}
|
||||
break;
|
||||
// Remaining cases contributed by: Volker C. Schoech <schoech(at)gmx(dot)de>
|
||||
case TAG_EXPOSURE_BIAS:
|
||||
m_exifinfo->ExposureBias = (float) ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
case TAG_WHITEBALANCE:
|
||||
m_exifinfo->Whitebalance = (int32_t)ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
case TAG_METERING_MODE:
|
||||
m_exifinfo->MeteringMode = (int32_t)ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
case TAG_EXPOSURE_PROGRAM:
|
||||
m_exifinfo->ExposureProgram = (int32_t)ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
case TAG_ISO_EQUIVALENT:
|
||||
m_exifinfo->ISOequivalent = (int32_t)ConvertAnyFormat2(ValuePtr, Format);
|
||||
if ( m_exifinfo->ISOequivalent < 50 ) m_exifinfo->ISOequivalent *= 200;
|
||||
break;
|
||||
case TAG_COMPRESSION_LEVEL:
|
||||
m_exifinfo->CompressionLevel = (int32_t)ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
case TAG_XRESOLUTION:
|
||||
m_exifinfo->Xresolution = (float)ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
case TAG_YRESOLUTION:
|
||||
m_exifinfo->Yresolution = (float)ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
case TAG_THUMBNAIL_OFFSET:
|
||||
ThumbnailOffset = (unsigned)ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
case TAG_THUMBNAIL_LENGTH:
|
||||
ThumbnailSize = (unsigned)ConvertAnyFormat2(ValuePtr, Format);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET)
|
||||
{
|
||||
unsigned Offset = ValuePtr.Check(4) ? Get32u(ValuePtr.GetData(0)) : 0;
|
||||
if (Offset > 8)
|
||||
{
|
||||
if (!OffsetBase.Check(Offset))
|
||||
{
|
||||
strcpy(m_szLastError, "Illegal subdirectory link");
|
||||
return false;
|
||||
}
|
||||
ProcessExifDir2(OffsetBase.Offset(Offset), OffsetBase, ExifLength, m_exifinfo, LastExifRefdP, NestingLevel + 1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
/* In addition to linking to subdirectories via exif tags,
|
||||
there's also a potential link to another directory at the end
|
||||
of each directory. This has got to be the result of a
|
||||
committee!
|
||||
*/
|
||||
unsigned Offset;
|
||||
Offset = DirStart.Check(2 + 12 * NumDirEntries, 2) ? Get16u(DirStart.GetData(2 + 12 * NumDirEntries)) : 0;
|
||||
if (Offset)
|
||||
{
|
||||
if (!OffsetBase.Check(Offset))
|
||||
{
|
||||
strcpy(m_szLastError, "Illegal subdirectory link");
|
||||
return false;
|
||||
}
|
||||
ProcessExifDir2(OffsetBase.Offset(Offset), OffsetBase, ExifLength, m_exifinfo, LastExifRefdP, NestingLevel + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ThumbnailSize && ThumbnailOffset)
|
||||
{
|
||||
if (ThumbnailSize + ThumbnailOffset <= ExifLength)
|
||||
{
|
||||
/* The thumbnail pointer appears to be valid. Store it. */
|
||||
m_exifinfo->ThumbnailPointer = OffsetBase.GetData(ThumbnailOffset);
|
||||
m_exifinfo->ThumbnailSize = ThumbnailSize;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
double CxImageJPG::CxExifInfo::ConvertAnyFormat2(CSafeReader& reader, int32_t Format)
|
||||
{
|
||||
double Value;
|
||||
Value = 0;
|
||||
|
||||
switch (Format)
|
||||
{
|
||||
case FMT_SBYTE:
|
||||
case FMT_BYTE: if (!reader.Check(1)) {return Value;} break;
|
||||
case FMT_USHORT:
|
||||
case FMT_SSHORT: if (!reader.Check(2)) {return Value;} break;
|
||||
case FMT_ULONG:
|
||||
case FMT_SLONG: if (!reader.Check(4)) {return Value;} break;
|
||||
case FMT_URATIONAL:
|
||||
case FMT_SRATIONAL: if (!reader.Check(8)) {return Value;} break;
|
||||
case FMT_SINGLE: if (!reader.Check(sizeof(float))) {return Value;} break;
|
||||
case FMT_DOUBLE: if (!reader.Check(sizeof(double))) {return Value;} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
void * ValuePtr = (void*)reader.GetData(0);
|
||||
switch(Format)
|
||||
{
|
||||
case FMT_SBYTE: Value = *(signed char *)ValuePtr; break;
|
||||
case FMT_BYTE: Value = *(uint8_t *)ValuePtr; break;
|
||||
case FMT_USHORT: Value = Get16u(ValuePtr); break;
|
||||
case FMT_ULONG: Value = Get32u(ValuePtr); break;
|
||||
case FMT_URATIONAL:
|
||||
case FMT_SRATIONAL:
|
||||
{
|
||||
int32_t Num,Den;
|
||||
Num = Get32s(ValuePtr);
|
||||
Den = Get32s(4 + (char*)ValuePtr);
|
||||
Value = Den == 0 ? 0 : (double)Num / Den;
|
||||
break;
|
||||
}
|
||||
case FMT_SSHORT: Value = (int16_t)Get16u(ValuePtr); break;
|
||||
case FMT_SLONG: Value = Get32s(ValuePtr); break;
|
||||
/* Not sure if this is correct (never seen float used in Exif format) */
|
||||
case FMT_SINGLE: Value = (double)*(float *)ValuePtr; break;
|
||||
case FMT_DOUBLE: Value = *(double*)ValuePtr; break;
|
||||
}
|
||||
return Value;
|
||||
}
|
||||
void CxImageJPG::CxExifInfo::process_COM (const uint8_t* Data, int32_t length)
|
||||
{
|
||||
int32_t ch;
|
||||
char Comment[MAX_COMMENT + 1];
|
||||
int32_t nch;
|
||||
int32_t a;
|
||||
|
||||
nch = 0;
|
||||
|
||||
if (length > MAX_COMMENT) length = MAX_COMMENT; // Truncate if it won't fit in our structure.
|
||||
|
||||
for (a = 2; a < length; a++)
|
||||
{
|
||||
ch = Data[a];
|
||||
|
||||
if (ch == '\r' && (a < (length - 1) && Data[a + 1] == '\n')) continue; // Remove cr followed by lf.
|
||||
|
||||
Comment[nch++] = (isprint(ch) || ch == '\n' || ch == '\t') ? (char)ch : '?';
|
||||
}
|
||||
|
||||
Comment[nch] = '\0'; // Null terminate
|
||||
|
||||
//if (ShowTags) printf("COM marker comment: %s\n",Comment);
|
||||
|
||||
strcpy(m_exifinfo->Comments,Comment);
|
||||
}
|
||||
void CxImageJPG::CxExifInfo::process_SOFn(const uint8_t* Data, int32_t marker)
|
||||
{
|
||||
int32_t data_precision, num_components;
|
||||
|
||||
data_precision = Data[2];
|
||||
m_exifinfo->Height = Get16m((void*)(Data + 3));
|
||||
m_exifinfo->Width = Get16m((void*)(Data + 5));
|
||||
num_components = Data[7];
|
||||
|
||||
m_exifinfo->IsColor = num_components == 3 ? 1 : 0;
|
||||
m_exifinfo->Process = marker;
|
||||
|
||||
//if (ShowTags) printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n",
|
||||
// ImageInfo.Width, ImageInfo.Height, num_components, data_precision);
|
||||
}
|
||||
bool CxImageJPG::CxExifInfo::EncodeExif(CxFile * hFile)
|
||||
{
|
||||
int32_t a;
|
||||
|
||||
if (FindSection(M_SOS) == NULL)
|
||||
{
|
||||
strcpy(m_szLastError, "Can't write exif : didn't read all");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initial static jpeg marker.
|
||||
hFile->PutC(0xff);
|
||||
hFile->PutC(0xd8);
|
||||
|
||||
if (Sections[0].Type != M_EXIF && Sections[0].Type != M_JFIF)
|
||||
{
|
||||
// The image must start with an exif or jfif marker. If we threw those away, create one.
|
||||
static uint8_t JfifHead[18] =
|
||||
{
|
||||
0xff, M_JFIF,
|
||||
0x00, 0x10, 'J' , 'F' , 'I' , 'F' , 0x00, 0x01,
|
||||
0x01, 0x01, 0x01, 0x2C, 0x01, 0x2C, 0x00, 0x00
|
||||
};
|
||||
hFile->Write(JfifHead, 18, 1);
|
||||
}
|
||||
|
||||
// Write all the misc sections
|
||||
for (a = 0; a < SectionsRead - 1; a++)
|
||||
{
|
||||
hFile->PutC(0xff);
|
||||
hFile->PutC((uint8_t)(Sections[a].Type));
|
||||
hFile->Write(Sections[a].Data, Sections[a].Size, 1);
|
||||
}
|
||||
|
||||
// Write the remaining image data.
|
||||
hFile->Write(Sections[a].Data, Sections[a].Size, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
void CxImageJPG::CxExifInfo::DiscardAllButExif()
|
||||
{
|
||||
Section_t ExifKeeper;
|
||||
Section_t CommentKeeper;
|
||||
int32_t a;
|
||||
|
||||
memset(&ExifKeeper, 0, sizeof(ExifKeeper));
|
||||
memset(&CommentKeeper, 0, sizeof(ExifKeeper));
|
||||
|
||||
for (a = 0; a < SectionsRead; a++)
|
||||
{
|
||||
if (Sections[a].Type == M_EXIF && ExifKeeper.Type == 0)
|
||||
ExifKeeper = Sections[a];
|
||||
else if (Sections[a].Type == M_COM && CommentKeeper.Type == 0)
|
||||
CommentKeeper = Sections[a];
|
||||
else
|
||||
{
|
||||
free(Sections[a].Data);
|
||||
Sections[a].Data = 0;
|
||||
}
|
||||
}
|
||||
SectionsRead = 0;
|
||||
if (ExifKeeper.Type)
|
||||
Sections[SectionsRead++] = ExifKeeper;
|
||||
if (CommentKeeper.Type)
|
||||
Sections[SectionsRead++] = CommentKeeper;
|
||||
}
|
||||
void* CxImageJPG::CxExifInfo::FindSection(int32_t SectionType)
|
||||
{
|
||||
int32_t a;
|
||||
for ( a = 0; a < SectionsRead - 1; a++)
|
||||
if (Sections[a].Type == SectionType)
|
||||
return &Sections[a];
|
||||
// Could not be found.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // CXIMAGEJPG_SUPPORT_EXIF
|
||||
@ -1,207 +0,0 @@
|
||||
#include "ximage.h"
|
||||
|
||||
void CxImage::Startup(uint32_t imagetype)
|
||||
{
|
||||
//init pointers
|
||||
pDib = pDibLimit = pSelection = pAlpha = NULL;
|
||||
ppLayers = ppFrames = NULL;
|
||||
//init structures
|
||||
memset(&head, 0, sizeof(BITMAPINFOHEADER));
|
||||
memset(&info, 0, sizeof(CXIMAGEINFO));
|
||||
//init default attributes
|
||||
info.dwType = imagetype;
|
||||
info.fQuality = 90.0f;
|
||||
info.nAlphaMax = 255;
|
||||
info.nBkgndIndex = -1;
|
||||
info.bEnabled = true;
|
||||
info.nJpegScale = 1;
|
||||
SetXDPI(CXIMAGE_DEFAULT_DPI);
|
||||
SetYDPI(CXIMAGE_DEFAULT_DPI);
|
||||
|
||||
int16_t test = 1;
|
||||
info.bLittleEndianHost = (*((char *) &test) == 1);
|
||||
}
|
||||
CxImage::CxImage(uint32_t imagetype)
|
||||
{
|
||||
Startup(imagetype);
|
||||
}
|
||||
bool CxImage::Destroy()
|
||||
{
|
||||
//free this only if it's valid and it's not a ghost
|
||||
if (info.pGhost==NULL)
|
||||
{
|
||||
if (ppLayers)
|
||||
{
|
||||
for (int32_t n = 0; n < info.nNumLayers; n++) delete ppLayers[n];
|
||||
delete[] ppLayers; ppLayers = 0; info.nNumLayers = 0;
|
||||
}
|
||||
if (pSelection) { free(pSelection); pSelection=0; }
|
||||
if (pAlpha) { free(pAlpha); pAlpha=0; }
|
||||
if (pDib) { free(pDib); pDib=0; }
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool CxImage::DestroyFrames()
|
||||
{
|
||||
if (info.pGhost==NULL)
|
||||
{
|
||||
if (ppFrames)
|
||||
{
|
||||
for (int32_t n = 0; n < info.nNumFrames; n++) delete ppFrames[n];
|
||||
delete[] ppFrames; ppFrames = NULL; info.nNumFrames = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void CxImage::CopyInfo(const CxImage &src)
|
||||
{
|
||||
if (pDib == NULL) memcpy(&info, &src.info, sizeof(CXIMAGEINFO));
|
||||
}
|
||||
void* CxImage::Create(uint32_t dwWidth, uint32_t dwHeight, uint32_t wBpp, uint32_t imagetype)
|
||||
{
|
||||
// destroy the existing image (if any)
|
||||
if (!Destroy())
|
||||
return NULL;
|
||||
|
||||
// prevent further actions if width or height are not vaild <Balabasnia>
|
||||
if ((dwWidth == 0) || (dwHeight == 0))
|
||||
{
|
||||
strcpy(info.szLastError, "CxImage::Create : width and height must be greater than zero");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Make sure bits per pixel is valid
|
||||
if (wBpp <= 1) wBpp = 1;
|
||||
else if (wBpp <= 4) wBpp = 4;
|
||||
else if (wBpp <= 8) wBpp = 8;
|
||||
else wBpp = 24;
|
||||
|
||||
// limit memory requirements
|
||||
if ((((float)dwWidth * (float)dwHeight * (float)wBpp) / 8.0f) > (float)CXIMAGE_MAX_MEMORY)
|
||||
{
|
||||
strcpy(info.szLastError, "CXIMAGE_MAX_MEMORY exceeded");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// set the correct bpp value
|
||||
switch (wBpp)
|
||||
{
|
||||
case 1: head.biClrUsed = 2; break;
|
||||
case 4: head.biClrUsed = 16; break;
|
||||
case 8: head.biClrUsed = 256; break;
|
||||
default: head.biClrUsed = 0;
|
||||
}
|
||||
|
||||
//set the common image informations
|
||||
info.dwEffWidth = ((((wBpp * dwWidth) + 31) / 32) * 4);
|
||||
info.dwType = imagetype;
|
||||
|
||||
// initialize BITMAPINFOHEADER
|
||||
head.biSize = sizeof(BITMAPINFOHEADER); //<ralphw>
|
||||
head.biWidth = dwWidth; // fill in width from parameter
|
||||
head.biHeight = dwHeight; // fill in height from parameter
|
||||
head.biPlanes = 1; // must be 1
|
||||
head.biBitCount = (uint16_t)wBpp; // from parameter
|
||||
head.biCompression = BI_RGB;
|
||||
head.biSizeImage = info.dwEffWidth * dwHeight;
|
||||
|
||||
pDib = malloc(GetSize()); // alloc memory block to store our bitmap
|
||||
if (!pDib)
|
||||
{
|
||||
strcpy(info.szLastError, "CxImage::Create can't allocate memory");
|
||||
return NULL;
|
||||
}
|
||||
pDibLimit = (void*)((uint8_t*)pDib + GetSize());
|
||||
|
||||
//clear the palette
|
||||
RGBQUAD* pal = GetPalette();
|
||||
if (pal) memset(pal,0,GetPaletteSize());
|
||||
//Destroy the existing selection
|
||||
#if CXIMAGE_SUPPORT_SELECTION
|
||||
if (pSelection) SelectionDelete();
|
||||
#endif //CXIMAGE_SUPPORT_SELECTION
|
||||
//Destroy the existing alpha channel
|
||||
#if CXIMAGE_SUPPORT_ALPHA
|
||||
if (pAlpha) AlphaDelete();
|
||||
#endif //CXIMAGE_SUPPORT_ALPHA
|
||||
|
||||
// use our bitmap info structure to fill in first part of
|
||||
// our DIB with the BITMAPINFOHEADER
|
||||
BITMAPINFOHEADER* lpbi;
|
||||
lpbi = (BITMAPINFOHEADER*)(pDib);
|
||||
*lpbi = head;
|
||||
|
||||
info.pImage=GetBits();
|
||||
|
||||
return pDib; //return handle to the DIB
|
||||
}
|
||||
uint8_t* CxImage::GetBits(uint32_t row)
|
||||
{
|
||||
if (pDib)
|
||||
{
|
||||
if (row)
|
||||
{
|
||||
if (row < (uint32_t)head.biHeight)
|
||||
return ((uint8_t*)pDib + *(uint32_t*)pDib + GetPaletteSize() + (info.dwEffWidth * row));
|
||||
return NULL;
|
||||
}
|
||||
return ((uint8_t*)pDib + *(uint32_t*)pDib + GetPaletteSize());
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
uint32_t CxImage::GetSize()
|
||||
{
|
||||
uint64_t size64 = head.biSize + head.biSizeImage + GetPaletteSize();
|
||||
if (size64 > 0xFFFFFFFF)
|
||||
return 0xFFFFFFFF;
|
||||
return (uint32_t)size64;
|
||||
}
|
||||
bool CxImage::IsInside(int32_t x, int32_t y)
|
||||
{
|
||||
return (0 <= y && y < head.biHeight && 0 <= x && x < head.biWidth);
|
||||
}
|
||||
bool CxImage::Transfer(CxImage &from, bool bTransferFrames)
|
||||
{
|
||||
if (!Destroy())
|
||||
return false;
|
||||
|
||||
memcpy(&head, &from.head, sizeof(BITMAPINFOHEADER));
|
||||
memcpy(&info, &from.info, sizeof(CXIMAGEINFO));
|
||||
|
||||
pDib = from.pDib;
|
||||
pDibLimit = from.pDibLimit;
|
||||
pSelection = from.pSelection;
|
||||
pAlpha = from.pAlpha;
|
||||
ppLayers = from.ppLayers;
|
||||
|
||||
memset(&from.head, 0, sizeof(BITMAPINFOHEADER));
|
||||
memset(&from.info, 0, sizeof(CXIMAGEINFO));
|
||||
from.pDib = from.pDibLimit = from.pSelection = from.pAlpha = NULL;
|
||||
from.ppLayers = NULL;
|
||||
|
||||
if (bTransferFrames)
|
||||
{
|
||||
DestroyFrames();
|
||||
ppFrames = from.ppFrames;
|
||||
from.ppFrames = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
void CxImage::Ghost(const CxImage* from)
|
||||
{
|
||||
if (from)
|
||||
{
|
||||
memcpy(&head, &from->head, sizeof(BITMAPINFOHEADER));
|
||||
memcpy(&info, &from->info, sizeof(CXIMAGEINFO));
|
||||
pDib = from->pDib;
|
||||
pDibLimit = from->pDibLimit;
|
||||
pSelection = from->pSelection;
|
||||
pAlpha = from->pAlpha;
|
||||
ppLayers = from->ppLayers;
|
||||
ppFrames = from->ppFrames;
|
||||
info.pGhost = (CxImage*)from;
|
||||
}
|
||||
}
|
||||
@ -1,254 +0,0 @@
|
||||
#ifndef __ximage_h
|
||||
#define __ximage_h
|
||||
|
||||
#include "xmemfile.h"
|
||||
#include "ximadef.h"
|
||||
|
||||
enum ENUM_CXIMAGE_FORMATS
|
||||
{
|
||||
CXIMAGE_FORMAT_UNKNOWN = 0,
|
||||
#if CXIMAGE_SUPPORT_BMP
|
||||
CXIMAGE_FORMAT_BMP = 1,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_GIF
|
||||
CXIMAGE_FORMAT_GIF = 2,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JPG
|
||||
CXIMAGE_FORMAT_JPG = 3,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PNG
|
||||
CXIMAGE_FORMAT_PNG = 4,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_ICO
|
||||
CXIMAGE_FORMAT_ICO = 5,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_TIF
|
||||
CXIMAGE_FORMAT_TIF = 6,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_TGA
|
||||
CXIMAGE_FORMAT_TGA = 7,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PCX
|
||||
CXIMAGE_FORMAT_PCX = 8,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_WBMP
|
||||
CXIMAGE_FORMAT_WBMP = 9,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_WMF
|
||||
CXIMAGE_FORMAT_WMF = 10,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JP2
|
||||
CXIMAGE_FORMAT_JP2 = 11,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JPC
|
||||
CXIMAGE_FORMAT_JPC = 12,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PGX
|
||||
CXIMAGE_FORMAT_PGX = 13,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PNM
|
||||
CXIMAGE_FORMAT_PNM = 14,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_RAS
|
||||
CXIMAGE_FORMAT_RAS = 15,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JBG
|
||||
CXIMAGE_FORMAT_JBG = 16,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_MNG
|
||||
CXIMAGE_FORMAT_MNG = 17,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_SKA
|
||||
CXIMAGE_FORMAT_SKA = 18,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_RAW
|
||||
CXIMAGE_FORMAT_RAW = 19,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PSD
|
||||
CXIMAGE_FORMAT_PSD = 20,
|
||||
#endif
|
||||
CMAX_IMAGE_FORMATS = CXIMAGE_SUPPORT_BMP + CXIMAGE_SUPPORT_GIF + CXIMAGE_SUPPORT_JPG +
|
||||
CXIMAGE_SUPPORT_PNG + CXIMAGE_SUPPORT_MNG + CXIMAGE_SUPPORT_ICO +
|
||||
CXIMAGE_SUPPORT_TIF + CXIMAGE_SUPPORT_TGA + CXIMAGE_SUPPORT_PCX +
|
||||
CXIMAGE_SUPPORT_WBMP+ CXIMAGE_SUPPORT_WMF +
|
||||
CXIMAGE_SUPPORT_JBG + CXIMAGE_SUPPORT_JP2 + CXIMAGE_SUPPORT_JPC +
|
||||
CXIMAGE_SUPPORT_PGX + CXIMAGE_SUPPORT_PNM + CXIMAGE_SUPPORT_RAS +
|
||||
CXIMAGE_SUPPORT_SKA + CXIMAGE_SUPPORT_RAW + CXIMAGE_SUPPORT_PSD + 1
|
||||
};
|
||||
|
||||
#if CXIMAGE_SUPPORT_EXIF
|
||||
|
||||
#define MAX_COMMENT 255
|
||||
#define MAX_SECTIONS 20
|
||||
|
||||
typedef struct tag_ExifInfo
|
||||
{
|
||||
char Version [5];
|
||||
char CameraMake [32];
|
||||
char CameraModel [40];
|
||||
char DateTime [20];
|
||||
int32_t Height, Width;
|
||||
int32_t Orientation;
|
||||
int32_t IsColor;
|
||||
int32_t Process;
|
||||
int32_t FlashUsed;
|
||||
float FocalLength;
|
||||
float ExposureTime;
|
||||
float ApertureFNumber;
|
||||
float Distance;
|
||||
float CCDWidth;
|
||||
float ExposureBias;
|
||||
int32_t Whitebalance;
|
||||
int32_t MeteringMode;
|
||||
int32_t ExposureProgram;
|
||||
int32_t ISOequivalent;
|
||||
int32_t CompressionLevel;
|
||||
float FocalplaneXRes;
|
||||
float FocalplaneYRes;
|
||||
float FocalplaneUnits;
|
||||
float Xresolution;
|
||||
float Yresolution;
|
||||
float ResolutionUnit;
|
||||
float Brightness;
|
||||
char Comments[MAX_COMMENT + 1];
|
||||
|
||||
uint8_t* ThumbnailPointer;
|
||||
unsigned ThumbnailSize;
|
||||
|
||||
bool IsExif;
|
||||
} EXIFINFO;
|
||||
|
||||
#endif //CXIMAGE_SUPPORT_EXIF
|
||||
|
||||
class CxImage
|
||||
{
|
||||
typedef struct tagCxImageInfo
|
||||
{
|
||||
uint32_t dwEffWidth;
|
||||
uint8_t* pImage;
|
||||
CxImage* pGhost;
|
||||
CxImage* pParent;
|
||||
uint32_t dwType;
|
||||
char szLastError[256];
|
||||
int32_t nProgress;
|
||||
int32_t nEscape;
|
||||
int32_t nBkgndIndex;
|
||||
RGBQUAD nBkgndColor;
|
||||
float fQuality;
|
||||
uint8_t nJpegScale;
|
||||
int32_t nFrame;
|
||||
int32_t nNumFrames;
|
||||
uint32_t dwFrameDelay;
|
||||
int32_t xDPI;
|
||||
int32_t yDPI;
|
||||
RECT rSelectionBox;
|
||||
uint8_t nAlphaMax;
|
||||
bool bAlphaPaletteEnabled;
|
||||
bool bEnabled;
|
||||
int32_t xOffset;
|
||||
int32_t yOffset;
|
||||
uint32_t dwCodecOpt[CMAX_IMAGE_FORMATS];
|
||||
RGBQUAD last_c;
|
||||
uint8_t last_c_index;
|
||||
bool last_c_isvalid;
|
||||
int32_t nNumLayers;
|
||||
uint32_t dwFlags;
|
||||
uint8_t dispmeth;
|
||||
bool bGetAllFrames;
|
||||
bool bLittleEndianHost;
|
||||
#if CXIMAGE_SUPPORT_EXIF
|
||||
EXIFINFO ExifInfo;
|
||||
#endif
|
||||
} CXIMAGEINFO;
|
||||
public:
|
||||
CxImage(uint32_t imagetype = 0);
|
||||
#if CXIMAGE_SUPPORT_DECODE
|
||||
CxImage(uint8_t* buffer, uint32_t size, uint32_t imagetype);
|
||||
#endif // CXIMAGE_SUPPORT_DECODE
|
||||
virtual ~CxImage() { DestroyFrames(); Destroy(); };
|
||||
|
||||
void* Create(uint32_t dwWidth, uint32_t dwHeight, uint32_t wBpp, uint32_t imagetype = 0);
|
||||
bool Destroy();
|
||||
bool DestroyFrames();
|
||||
bool Transfer(CxImage& from, bool bTransferFrames = true);
|
||||
|
||||
uint32_t GetSize();
|
||||
uint8_t* GetBits(uint32_t row = 0);
|
||||
uint32_t GetHeight() const;
|
||||
uint32_t GetWidth() const;
|
||||
uint32_t GetEffWidth() const;
|
||||
uint32_t GetType() const;
|
||||
const char* GetLastError();
|
||||
|
||||
uint8_t GetJpegQuality() const;
|
||||
|
||||
uint8_t GetJpegScale() const;
|
||||
|
||||
int32_t GetXDPI() const;
|
||||
int32_t GetYDPI() const;
|
||||
void SetXDPI(int32_t dpi);
|
||||
void SetYDPI(int32_t dpi);
|
||||
|
||||
uint32_t GetCodecOption(uint32_t imagetype = 0);
|
||||
|
||||
static uint32_t GetTypeIndexFromId(const uint32_t id);
|
||||
|
||||
bool IsGrayScale();
|
||||
uint32_t GetPaletteSize();
|
||||
RGBQUAD* GetPalette() const;
|
||||
RGBQUAD GetPaletteColor(uint8_t idx);
|
||||
void SetGrayPalette();
|
||||
void SetPalette(uint32_t n, uint8_t* r, uint8_t* g, uint8_t* b);
|
||||
|
||||
bool IsInside(int32_t x, int32_t y);
|
||||
|
||||
protected:
|
||||
uint8_t BlindGetPixelIndex(const int32_t x, const int32_t y);
|
||||
RGBQUAD BlindGetPixelColor(const int32_t x, const int32_t y, bool bGetAlpha = true);
|
||||
|
||||
#if CXIMAGE_SUPPORT_DECODE
|
||||
public:
|
||||
bool Decode(CxFile* hFile, uint32_t imagetype);
|
||||
bool Decode(uint8_t* buffer, uint32_t size, uint32_t imagetype);
|
||||
#endif //CXIMAGE_SUPPORT_DECODE
|
||||
|
||||
#if CXIMAGE_SUPPORT_ENCODE
|
||||
protected:
|
||||
bool EncodeSafeCheck(CxFile* hFile);
|
||||
public:
|
||||
bool Encode(CxFile* hFile, uint32_t imagetype);
|
||||
bool Encode(uint8_t* &buffer, int32_t &size, uint32_t imagetype);
|
||||
bool Encode2RGBA(CxFile* hFile, bool bFlipY = false);
|
||||
bool Encode2RGBA(uint8_t* &buffer, int32_t &size, bool bFlipY = false);
|
||||
#endif //CXIMAGE_SUPPORT_ENCODE
|
||||
|
||||
#if CXIMAGE_SUPPORT_SELECTION
|
||||
public:
|
||||
bool SelectionDelete();
|
||||
#endif //CXIMAGE_SUPPORT_SELECTION
|
||||
|
||||
#if CXIMAGE_SUPPORT_ALPHA
|
||||
public:
|
||||
void AlphaDelete();
|
||||
protected:
|
||||
uint8_t BlindAlphaGet(const int32_t x,const int32_t y);
|
||||
#endif //CXIMAGE_SUPPORT_ALPHA
|
||||
|
||||
protected:
|
||||
void Startup(uint32_t imagetype = 0);
|
||||
void CopyInfo(const CxImage& src);
|
||||
void Ghost (const CxImage* src);
|
||||
void RGBtoBGR(uint8_t* buffer, int32_t length);
|
||||
|
||||
void* pDib;
|
||||
void* pDibLimit;
|
||||
|
||||
BITMAPINFOHEADER head;
|
||||
CXIMAGEINFO info;
|
||||
uint8_t* pSelection;
|
||||
uint8_t* pAlpha;
|
||||
CxImage** ppLayers;
|
||||
CxImage** ppFrames;
|
||||
};
|
||||
|
||||
#endif // __ximage_h
|
||||
@ -1,126 +0,0 @@
|
||||
#include "ximage.h"
|
||||
|
||||
int32_t CxImage::GetXDPI() const
|
||||
{
|
||||
return info.xDPI;
|
||||
}
|
||||
int32_t CxImage::GetYDPI() const
|
||||
{
|
||||
return info.yDPI;
|
||||
}
|
||||
void CxImage::SetXDPI(int32_t dpi)
|
||||
{
|
||||
if (dpi <= 0) dpi = CXIMAGE_DEFAULT_DPI;
|
||||
info.xDPI = dpi;
|
||||
head.biXPelsPerMeter = (int32_t) floor(dpi * 10000.0 / 254.0 + 0.5);
|
||||
if (pDib) ((BITMAPINFOHEADER*)pDib)->biXPelsPerMeter = head.biXPelsPerMeter;
|
||||
}
|
||||
void CxImage::SetYDPI(int32_t dpi)
|
||||
{
|
||||
if (dpi <= 0) dpi = CXIMAGE_DEFAULT_DPI;
|
||||
info.yDPI = dpi;
|
||||
head.biYPelsPerMeter = (int32_t) floor(dpi * 10000.0 / 254.0 + 0.5);
|
||||
if (pDib) ((BITMAPINFOHEADER*)pDib)->biYPelsPerMeter = head.biYPelsPerMeter;
|
||||
}
|
||||
uint32_t CxImage::GetCodecOption(uint32_t imagetype)
|
||||
{
|
||||
imagetype = GetTypeIndexFromId(imagetype);
|
||||
if (imagetype == 0)
|
||||
imagetype = GetTypeIndexFromId(GetType());
|
||||
return info.dwCodecOpt[imagetype];
|
||||
}
|
||||
uint32_t CxImage::GetHeight() const
|
||||
{
|
||||
return head.biHeight;
|
||||
}
|
||||
uint32_t CxImage::GetWidth() const
|
||||
{
|
||||
return head.biWidth;
|
||||
}
|
||||
uint32_t CxImage::GetEffWidth() const
|
||||
{
|
||||
return info.dwEffWidth;
|
||||
}
|
||||
uint32_t CxImage::GetType() const
|
||||
{
|
||||
return info.dwType;
|
||||
}
|
||||
uint32_t CxImage::GetTypeIndexFromId(const uint32_t id)
|
||||
{
|
||||
uint32_t n;
|
||||
n=0; if (id == CXIMAGE_FORMAT_UNKNOWN) return n;
|
||||
#if CXIMAGE_SUPPORT_BMP
|
||||
n++; if (id == CXIMAGE_FORMAT_BMP) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_GIF
|
||||
n++; if (id == CXIMAGE_FORMAT_GIF) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JPG
|
||||
n++; if (id == CXIMAGE_FORMAT_JPG) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PNG
|
||||
n++; if (id == CXIMAGE_FORMAT_PNG) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_ICO
|
||||
n++; if (id == CXIMAGE_FORMAT_ICO) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_TIF
|
||||
n++; if (id == CXIMAGE_FORMAT_TIF) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_TGA
|
||||
n++; if (id == CXIMAGE_FORMAT_TGA) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PCX
|
||||
n++; if (id == CXIMAGE_FORMAT_PCX) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_WBMP
|
||||
n++; if (id == CXIMAGE_FORMAT_WBMP) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_WMF
|
||||
n++; if (id == CXIMAGE_FORMAT_WMF) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JP2
|
||||
n++; if (id == CXIMAGE_FORMAT_JP2) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JPC
|
||||
n++; if (id == CXIMAGE_FORMAT_JPC) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PGX
|
||||
n++; if (id == CXIMAGE_FORMAT_PGX) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PNM
|
||||
n++; if (id == CXIMAGE_FORMAT_PNM) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_RAS
|
||||
n++; if (id == CXIMAGE_FORMAT_RAS) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_JBG
|
||||
n++; if (id == CXIMAGE_FORMAT_JBG) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_MNG
|
||||
n++; if (id == CXIMAGE_FORMAT_MNG) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_SKA
|
||||
n++; if (id == CXIMAGE_FORMAT_SKA) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_RAW
|
||||
n++; if (id == CXIMAGE_FORMAT_RAW) return n;
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_PSD
|
||||
n++; if (id == CXIMAGE_FORMAT_PSD) return n;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
uint8_t CxImage::GetJpegQuality() const
|
||||
{
|
||||
return (uint8_t)(info.fQuality + 0.5f);
|
||||
}
|
||||
uint8_t CxImage::GetJpegScale() const
|
||||
{
|
||||
return info.nJpegScale;
|
||||
}
|
||||
const char* CxImage::GetLastError()
|
||||
{
|
||||
return info.szLastError;
|
||||
}
|
||||
@ -1,74 +0,0 @@
|
||||
#ifndef __ximaiter_h
|
||||
#define __ximaiter_h
|
||||
|
||||
#include "ximage.h"
|
||||
#include "ximadef.h"
|
||||
#include <algorithm>
|
||||
|
||||
class CImageIterator
|
||||
{
|
||||
friend class CxImage;
|
||||
protected:
|
||||
int32_t Itx, Ity; // Counters
|
||||
int32_t Stepx, Stepy;
|
||||
uint8_t* IterImage; // Image pointer
|
||||
CxImage* ima;
|
||||
public:
|
||||
// Constructors
|
||||
CImageIterator();
|
||||
CImageIterator(CxImage* image);
|
||||
operator CxImage* ();
|
||||
|
||||
void Upset();
|
||||
void SetRow(uint8_t* buf, int32_t n);
|
||||
void GetRow(uint8_t* buf, int32_t n);
|
||||
uint8_t* GetRow();
|
||||
BOOL PrevRow();
|
||||
};
|
||||
|
||||
inline CImageIterator::CImageIterator()
|
||||
{
|
||||
ima = 0;
|
||||
IterImage = 0;
|
||||
Itx = Ity = 0;
|
||||
Stepx = Stepy = 0;
|
||||
}
|
||||
inline CImageIterator::CImageIterator(CxImage* imageImpl) : ima(imageImpl)
|
||||
{
|
||||
if (ima) IterImage = ima->GetBits();
|
||||
Itx = Ity = 0;
|
||||
Stepx = Stepy = 0;
|
||||
}
|
||||
inline CImageIterator::operator CxImage* ()
|
||||
{
|
||||
return ima;
|
||||
}
|
||||
inline void CImageIterator::Upset()
|
||||
{
|
||||
Itx = 0;
|
||||
Ity = ima->GetHeight() - 1;
|
||||
IterImage = ima->GetBits() + ima->GetEffWidth() * (ima->GetHeight() - 1);
|
||||
}
|
||||
inline void CImageIterator::SetRow(uint8_t* buf, int32_t n)
|
||||
{
|
||||
if (n < 0) n = (int32_t)ima->GetEffWidth();
|
||||
else n = (std::min)(n, (int32_t)ima->GetEffWidth());
|
||||
|
||||
if ((IterImage != NULL) && (buf != NULL) && (n > 0)) memcpy(IterImage, buf, n);
|
||||
}
|
||||
inline void CImageIterator::GetRow(uint8_t* buf, int32_t n)
|
||||
{
|
||||
if ((IterImage != NULL) && (buf != NULL) && (n > 0))
|
||||
memcpy(buf, IterImage, (std::min)(n, (int32_t)ima->GetEffWidth()));
|
||||
}
|
||||
inline BOOL CImageIterator::PrevRow()
|
||||
{
|
||||
if (--Ity < 0) return 0;
|
||||
IterImage -= ima->GetEffWidth();
|
||||
return 1;
|
||||
}
|
||||
inline uint8_t* CImageIterator::GetRow()
|
||||
{
|
||||
return IterImage;
|
||||
}
|
||||
#endif // __ximaiter_h
|
||||
@ -1,485 +0,0 @@
|
||||
#include "ximajpg.h"
|
||||
|
||||
#if CXIMAGE_SUPPORT_JPG
|
||||
|
||||
#include "../../../../../cximage/jpeg/jmorecfg.h"
|
||||
#include "ximaiter.h"
|
||||
#include <setjmp.h>
|
||||
|
||||
struct jpg_error_mgr
|
||||
{
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
char* buffer; /* error message <CSC>*/
|
||||
};
|
||||
typedef jpg_error_mgr *jpg_error_ptr;
|
||||
|
||||
static void ima_jpeg_error_exit(j_common_ptr cinfo)
|
||||
{
|
||||
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
|
||||
jpg_error_ptr myerr = (jpg_error_ptr) cinfo->err;
|
||||
/* Create the message */
|
||||
myerr->pub.format_message (cinfo, myerr->buffer);
|
||||
/* Send it to stderr, adding a newline */
|
||||
/* Return control to the setjmp point */
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
CxImageJPG::CxImageJPG() : CxImage(CXIMAGE_FORMAT_JPG)
|
||||
{
|
||||
#if CXIMAGEJPG_SUPPORT_EXIF
|
||||
m_exif = NULL;
|
||||
memset(&info.ExifInfo, 0, sizeof(EXIFINFO));
|
||||
#endif
|
||||
}
|
||||
CxImageJPG::~CxImageJPG()
|
||||
{
|
||||
#if CXIMAGEJPG_SUPPORT_EXIF
|
||||
if (m_exif) delete m_exif;
|
||||
#endif
|
||||
}
|
||||
#if CXIMAGEJPG_SUPPORT_EXIF
|
||||
bool CxImageJPG::DecodeExif(CxFile* hFile)
|
||||
{
|
||||
m_exif = new CxExifInfo(&info.ExifInfo);
|
||||
if (m_exif)
|
||||
{
|
||||
int32_t pos = hFile->Tell();
|
||||
m_exif->DecodeExif(hFile);
|
||||
hFile->Seek(pos, SEEK_SET);
|
||||
return m_exif->m_exifinfo->IsExif;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif //CXIMAGEJPG_SUPPORT_EXIF
|
||||
#if CXIMAGE_SUPPORT_DECODE
|
||||
bool CxImageJPG::Decode(CxFile* hFile)
|
||||
{
|
||||
bool is_exif = false;
|
||||
#if CXIMAGEJPG_SUPPORT_EXIF
|
||||
is_exif = DecodeExif(hFile);
|
||||
#endif
|
||||
|
||||
CImageIterator iter(this);
|
||||
/* 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. <CSC> */
|
||||
struct jpg_error_mgr jerr;
|
||||
jerr.buffer=info.szLastError;
|
||||
/* More stuff */
|
||||
JSAMPARRAY buffer; /* Output row buffer */
|
||||
int32_t 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 = ima_jpeg_error_exit;
|
||||
|
||||
CxFileJpg src(hFile);
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
cinfo.src = &src;
|
||||
|
||||
/* Step 3: read file parameters with jpeg_read_header() */
|
||||
(void) jpeg_read_header(&cinfo, TRUE);
|
||||
|
||||
/* Step 4 <chupeev> handle decoder options*/
|
||||
uint32_t dwCodecOptions = GetCodecOption(CXIMAGE_FORMAT_JPG); //[nm_114]
|
||||
if ((dwCodecOptions & DECODE_GRAYSCALE) != 0)
|
||||
cinfo.out_color_space = JCS_GRAYSCALE;
|
||||
if ((dwCodecOptions & DECODE_QUANTIZE) != 0) {
|
||||
cinfo.quantize_colors = TRUE;
|
||||
cinfo.desired_number_of_colors = GetJpegQuality();
|
||||
}
|
||||
if ((dwCodecOptions & DECODE_DITHER) != 0)
|
||||
cinfo.dither_mode = m_nDither;
|
||||
if ((dwCodecOptions & DECODE_ONEPASS) != 0)
|
||||
cinfo.two_pass_quantize = FALSE;
|
||||
if ((dwCodecOptions & DECODE_NOSMOOTH) != 0)
|
||||
cinfo.do_fancy_upsampling = FALSE;
|
||||
|
||||
//<DP>: Load true color images as RGB (no quantize)
|
||||
/* Step 4: set parameters for decompression */
|
||||
/* if (cinfo.jpeg_color_space!=JCS_GRAYSCALE) {
|
||||
* cinfo.quantize_colors = TRUE;
|
||||
* cinfo.desired_number_of_colors = 128;
|
||||
*}
|
||||
*/ //</DP>
|
||||
|
||||
cinfo.scale_num = 1;
|
||||
// Set the scale <ignacio>
|
||||
cinfo.scale_denom = GetJpegScale();
|
||||
|
||||
// Borrowed the idea from GIF implementation <ignacio>
|
||||
if (info.nEscape == -1) {
|
||||
// Return output dimensions only
|
||||
jpeg_calc_output_dimensions(&cinfo);
|
||||
head.biWidth = cinfo.output_width;
|
||||
head.biHeight = cinfo.output_height;
|
||||
info.dwType = CXIMAGE_FORMAT_JPG;
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Step 5: Start decompressor */
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
//Create the image using output dimensions <ignacio>
|
||||
//Create(cinfo.image_width, cinfo.image_height, 8*cinfo.output_components, CXIMAGE_FORMAT_JPG);
|
||||
Create(cinfo.output_width, cinfo.output_height, 8*cinfo.output_components, CXIMAGE_FORMAT_JPG);
|
||||
|
||||
if (!pDib) longjmp(jerr.setjmp_buffer, 1); //<DP> check if the image has been created
|
||||
|
||||
if (is_exif){
|
||||
#if CXIMAGEJPG_SUPPORT_EXIF
|
||||
if ((info.ExifInfo.Xresolution != 0.0) && (info.ExifInfo.ResolutionUnit != 0))
|
||||
SetXDPI((int32_t)(info.ExifInfo.Xresolution/info.ExifInfo.ResolutionUnit));
|
||||
if ((info.ExifInfo.Yresolution != 0.0) && (info.ExifInfo.ResolutionUnit != 0))
|
||||
SetYDPI((int32_t)(info.ExifInfo.Yresolution/info.ExifInfo.ResolutionUnit));
|
||||
#endif
|
||||
} else {
|
||||
switch (cinfo.density_unit)
|
||||
{
|
||||
case 0: // [andy] fix for aspect ratio...
|
||||
if((cinfo.Y_density > 0) && (cinfo.X_density > 0))
|
||||
SetYDPI((int32_t)(GetXDPI()*(float(cinfo.Y_density)/float(cinfo.X_density))));
|
||||
break;
|
||||
case 2: // [andy] fix: cinfo.X/Y_density is pixels per centimeter
|
||||
SetXDPI((int32_t)floor(cinfo.X_density * 2.54 + 0.5));
|
||||
SetYDPI((int32_t)floor(cinfo.Y_density * 2.54 + 0.5));
|
||||
break;
|
||||
default:
|
||||
SetXDPI(cinfo.X_density);
|
||||
SetYDPI(cinfo.Y_density);
|
||||
}
|
||||
}
|
||||
|
||||
if (cinfo.out_color_space==JCS_GRAYSCALE){
|
||||
SetGrayPalette();
|
||||
head.biClrUsed =256;
|
||||
} else {
|
||||
if (cinfo.quantize_colors){
|
||||
SetPalette(cinfo.actual_number_of_colors, cinfo.colormap[0], cinfo.colormap[1], cinfo.colormap[2]);
|
||||
head.biClrUsed=cinfo.actual_number_of_colors;
|
||||
} else {
|
||||
head.biClrUsed=0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
iter.Upset();
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
|
||||
if (info.nEscape) longjmp(jerr.setjmp_buffer, 1); // <vho> - cancel decoding
|
||||
|
||||
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||
// info.nProgress = (int32_t)(100*cinfo.output_scanline/cinfo.output_height);
|
||||
//<DP> Step 6a: CMYK->RGB */
|
||||
if ((cinfo.num_components==4)&&(cinfo.quantize_colors==FALSE)){
|
||||
uint8_t k,*dst,*src;
|
||||
dst = iter.GetRow();
|
||||
src = buffer[0];
|
||||
for(int32_t x3=0,x4=0; x3<(int32_t)info.dwEffWidth && x4<row_stride; x3+=3, x4+=4){
|
||||
k=src[x4+3];
|
||||
dst[x3] =(uint8_t)((k * src[x4+2])/255);
|
||||
dst[x3+1]=(uint8_t)((k * src[x4+1])/255);
|
||||
dst[x3+2]=(uint8_t)((k * src[x4+0])/255);
|
||||
}
|
||||
} else {
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
iter.SetRow(buffer[0], row_stride);
|
||||
}
|
||||
iter.PrevRow();
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
//<DP> Step 7A: Swap red and blue components
|
||||
// not necessary if swapped red and blue definition in jmorecfg.h;ln322 <W. Morrison>
|
||||
if ((cinfo.num_components==3)&&(cinfo.quantize_colors==FALSE)){
|
||||
uint8_t* r0=GetBits();
|
||||
for(int32_t y=0;y<head.biHeight;y++){
|
||||
if (info.nEscape) longjmp(jerr.setjmp_buffer, 1); // <vho> - cancel decoding
|
||||
RGBtoBGR(r0,3*head.biWidth);
|
||||
r0+=info.dwEffWidth;
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 8: Release JPEG decompression object */
|
||||
/* This is an important step since it will release a good deal of memory. */
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
/* 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 true;
|
||||
}
|
||||
#endif //CXIMAGE_SUPPORT_DECODE
|
||||
#if CXIMAGE_SUPPORT_ENCODE
|
||||
bool CxImageJPG::Encode(CxFile* hFile)
|
||||
{
|
||||
if (EncodeSafeCheck(hFile)) return false;
|
||||
|
||||
if (head.biClrUsed != 0 && !IsGrayScale())
|
||||
{
|
||||
strcpy(info.szLastError,"JPEG can save only RGB or GreyScale images");
|
||||
return false;
|
||||
}
|
||||
|
||||
// necessary for EXIF, and for roll backs
|
||||
int32_t pos = hFile->Tell();
|
||||
|
||||
/* This struct contains the JPEG compression parameters and pointers to
|
||||
* working space (which is allocated as needed by the JPEG library).
|
||||
* It is possible to have several such structures, representing multiple
|
||||
* compression/decompression processes, in existence at once. We refer
|
||||
* to any one struct (and its associated working data) as a "JPEG object".
|
||||
*/
|
||||
struct jpeg_compress_struct cinfo;
|
||||
/* This struct represents a JPEG error handler. It is declared separately
|
||||
* because applications often want to supply a specialized error handler
|
||||
* (see the second half of this file for an example). But here we just
|
||||
* take the easy way out and use the standard error handler, which will
|
||||
* print a message on stderr and call exit() if compression fails.
|
||||
* Note that this struct must live as int32_t as the main JPEG parameter
|
||||
* struct, to avoid dangling-pointer problems.
|
||||
*/
|
||||
//struct jpeg_error_mgr jerr;
|
||||
/* We use our private extension JPEG error handler. <CSC> */
|
||||
struct jpg_error_mgr jerr;
|
||||
jerr.buffer = info.szLastError;
|
||||
/* More stuff */
|
||||
int32_t row_stride; /* physical row width in image buffer */
|
||||
JSAMPARRAY buffer; /* Output row buffer */
|
||||
|
||||
/* Step 1: allocate and initialize JPEG compression object */
|
||||
/* We have to set up the error handler first, in case the initialization
|
||||
* step fails. (Unlikely, but it could happen if you are out of memory.)
|
||||
* This routine fills in the contents of struct jerr, and returns jerr's
|
||||
* address which we place into the link field in cinfo.
|
||||
*/
|
||||
//cinfo.err = jpeg_std_error(&jerr); <CSC>
|
||||
/* We set up the normal JPEG error routines, then override error_exit. */
|
||||
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = ima_jpeg_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.
|
||||
*/
|
||||
strcpy(info.szLastError, jerr.buffer); //<CSC>
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Now we can initialize the JPEG compression object. */
|
||||
jpeg_create_compress(&cinfo);
|
||||
/* Step 2: specify data destination (eg, a file) */
|
||||
/* Note: steps 2 and 3 can be done in either order. */
|
||||
/* Here we use the library-supplied code to send compressed data to a
|
||||
* stdio stream. You can also write your own code to do something else.
|
||||
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
|
||||
* requires it in order to write binary files.
|
||||
*/
|
||||
|
||||
//jpeg_stdio_dest(&cinfo, outfile);
|
||||
CxFileJpg dest(hFile);
|
||||
cinfo.dest = &dest;
|
||||
|
||||
/* Step 3: set parameters for compression */
|
||||
/* First we supply a description of the input image.
|
||||
* Four fields of the cinfo struct must be filled in:
|
||||
*/
|
||||
cinfo.image_width = GetWidth(); // image width and height, in pixels
|
||||
cinfo.image_height = GetHeight();
|
||||
|
||||
if (IsGrayScale())
|
||||
{
|
||||
cinfo.input_components = 1; // # of color components per pixel
|
||||
cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */
|
||||
}
|
||||
else
|
||||
{
|
||||
cinfo.input_components = 3; // # of color components per pixel
|
||||
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
|
||||
}
|
||||
|
||||
/* Now use the library's routine to set default compression parameters.
|
||||
* (You must set at least cinfo.in_color_space before calling this,
|
||||
* since the defaults depend on the source color space.)
|
||||
*/
|
||||
jpeg_set_defaults(&cinfo);
|
||||
/* Now you can set any non-default parameters you wish to.
|
||||
* Here we just illustrate the use of quality (quantization table) scaling:
|
||||
*/
|
||||
|
||||
uint32_t dwCodecOptions = GetCodecOption(CXIMAGE_FORMAT_JPG); //[nm_114]
|
||||
//#ifdef C_ARITH_CODING_SUPPORTED
|
||||
if ((dwCodecOptions & ENCODE_ARITHMETIC) != 0)
|
||||
cinfo.arith_code = TRUE;
|
||||
//#endif
|
||||
|
||||
//#ifdef ENTROPY_OPT_SUPPORTED
|
||||
if ((dwCodecOptions & ENCODE_OPTIMIZE) != 0)
|
||||
cinfo.optimize_coding = TRUE;
|
||||
//#endif
|
||||
|
||||
if ((dwCodecOptions & ENCODE_GRAYSCALE) != 0)
|
||||
jpeg_set_colorspace(&cinfo, JCS_GRAYSCALE);
|
||||
|
||||
if ((dwCodecOptions & ENCODE_SMOOTHING) != 0)
|
||||
cinfo.smoothing_factor = m_nSmoothing;
|
||||
|
||||
jpeg_set_quality(&cinfo, GetJpegQuality(), (dwCodecOptions & ENCODE_BASELINE) != 0);
|
||||
|
||||
//#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
if ((dwCodecOptions & ENCODE_PROGRESSIVE) != 0)
|
||||
jpeg_simple_progression(&cinfo);
|
||||
//#endif
|
||||
|
||||
#ifdef C_LOSSLESS_SUPPORTED
|
||||
if ((dwCodecOptions & ENCODE_LOSSLESS) != 0)
|
||||
jpeg_simple_lossless(&cinfo, m_nPredictor, m_nPointTransform);
|
||||
#endif
|
||||
|
||||
//SetCodecOption(ENCODE_SUBSAMPLE_444 | GetCodecOption(CXIMAGE_FORMAT_JPG),CXIMAGE_FORMAT_JPG);
|
||||
|
||||
// 2x2, 1x1, 1x1 (4:1:1) : High (default sub sampling)
|
||||
cinfo.comp_info[0].h_samp_factor = 2;
|
||||
cinfo.comp_info[0].v_samp_factor = 2;
|
||||
cinfo.comp_info[1].h_samp_factor = 1;
|
||||
cinfo.comp_info[1].v_samp_factor = 1;
|
||||
cinfo.comp_info[2].h_samp_factor = 1;
|
||||
cinfo.comp_info[2].v_samp_factor = 1;
|
||||
|
||||
if ((dwCodecOptions & ENCODE_SUBSAMPLE_422) != 0)
|
||||
{
|
||||
// 2x1, 1x1, 1x1 (4:2:2) : Medium
|
||||
cinfo.comp_info[0].h_samp_factor = 2;
|
||||
cinfo.comp_info[0].v_samp_factor = 1;
|
||||
cinfo.comp_info[1].h_samp_factor = 1;
|
||||
cinfo.comp_info[1].v_samp_factor = 1;
|
||||
cinfo.comp_info[2].h_samp_factor = 1;
|
||||
cinfo.comp_info[2].v_samp_factor = 1;
|
||||
}
|
||||
|
||||
if ((dwCodecOptions & ENCODE_SUBSAMPLE_444) != 0)
|
||||
{
|
||||
// 1x1 1x1 1x1 (4:4:4) : None
|
||||
cinfo.comp_info[0].h_samp_factor = 1;
|
||||
cinfo.comp_info[0].v_samp_factor = 1;
|
||||
cinfo.comp_info[1].h_samp_factor = 1;
|
||||
cinfo.comp_info[1].v_samp_factor = 1;
|
||||
cinfo.comp_info[2].h_samp_factor = 1;
|
||||
cinfo.comp_info[2].v_samp_factor = 1;
|
||||
}
|
||||
|
||||
cinfo.density_unit = 1;
|
||||
cinfo.X_density = (uint16_t)GetXDPI();
|
||||
cinfo.Y_density = (uint16_t)GetYDPI();
|
||||
|
||||
/* Step 4: Start compressor */
|
||||
/* TRUE ensures that we will write a complete interchange-JPEG file.
|
||||
* Pass TRUE unless you are very sure of what you're doing.
|
||||
*/
|
||||
jpeg_start_compress(&cinfo, TRUE);
|
||||
|
||||
/* Step 5: while (scan lines remain to be written) */
|
||||
/* jpeg_write_scanlines(...); */
|
||||
/* Here we use the library's state variable cinfo.next_scanline as the
|
||||
* loop counter, so that we don't have to keep track ourselves.
|
||||
* To keep things simple, we pass one scanline per call; you can pass
|
||||
* more if you wish, though.
|
||||
*/
|
||||
row_stride = info.dwEffWidth; /* JSAMPLEs per row in image_buffer */
|
||||
|
||||
//<DP> "8+row_stride" fix heap deallocation problem during debug???
|
||||
buffer = (*cinfo.mem->alloc_sarray)
|
||||
((j_common_ptr) &cinfo, JPOOL_IMAGE, 8 + row_stride, 1);
|
||||
|
||||
CImageIterator iter(this);
|
||||
|
||||
iter.Upset();
|
||||
while (cinfo.next_scanline < cinfo.image_height)
|
||||
{
|
||||
// info.nProgress = (int32_t)(100*cinfo.next_scanline/cinfo.image_height);
|
||||
iter.GetRow(buffer[0], row_stride);
|
||||
// not necessary if swapped red and blue definition in jmorecfg.h;ln322 <W. Morrison>
|
||||
if (head.biClrUsed == 0) // swap R & B for RGB images
|
||||
RGBtoBGR(buffer[0], row_stride); // Lance : 1998/09/01 : Bug ID: EXP-2.1.1-9
|
||||
iter.PrevRow();
|
||||
(void) jpeg_write_scanlines(&cinfo, buffer, 1);
|
||||
}
|
||||
|
||||
/* Step 6: Finish compression */
|
||||
jpeg_finish_compress(&cinfo);
|
||||
|
||||
/* Step 7: release JPEG compression object */
|
||||
/* This is an important step since it will release a good deal of memory. */
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
|
||||
|
||||
#if CXIMAGEJPG_SUPPORT_EXIF
|
||||
if (m_exif && m_exif->m_exifinfo->IsExif){
|
||||
// discard useless sections (if any) read from original image
|
||||
m_exif->DiscardAllButExif();
|
||||
// read new created image, to split the sections
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
m_exif->DecodeExif(hFile,EXIF_READ_IMAGE);
|
||||
// save back the image, adding EXIF section
|
||||
hFile->Seek(pos,SEEK_SET);
|
||||
m_exif->EncodeExif(hFile);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* And we're done! */
|
||||
return true;
|
||||
}
|
||||
#endif // CXIMAGE_SUPPORT_ENCODE
|
||||
#endif // CXIMAGE_SUPPORT_JPG
|
||||
|
||||
@ -1,278 +0,0 @@
|
||||
#ifndef __ximajpg_h
|
||||
#define __ximajpg_h
|
||||
|
||||
#include "ximage.h"
|
||||
|
||||
#if CXIMAGE_SUPPORT_JPG
|
||||
|
||||
#define CXIMAGEJPG_SUPPORT_EXIF CXIMAGE_SUPPORT_EXIF
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "../../../../../cximage/jpeg/jpeglib.h"
|
||||
#include "../../../../../cximage/jpeg/jerror.h"
|
||||
}
|
||||
|
||||
class CxImageJPG: public CxImage
|
||||
{
|
||||
public:
|
||||
CxImageJPG();
|
||||
~CxImageJPG();
|
||||
|
||||
bool Decode(CxFile * hFile);
|
||||
|
||||
#if CXIMAGE_SUPPORT_ENCODE
|
||||
bool Encode(CxFile * hFile);
|
||||
#endif // CXIMAGE_SUPPORT_ENCODE
|
||||
|
||||
#if CXIMAGEJPG_SUPPORT_EXIF
|
||||
|
||||
#define M_SOF0 0xC0
|
||||
#define M_SOF1 0xC1
|
||||
#define M_SOF2 0xC2
|
||||
#define M_SOF3 0xC3
|
||||
#define M_SOF5 0xC5
|
||||
#define M_SOF6 0xC6
|
||||
#define M_SOF7 0xC7
|
||||
#define M_SOF9 0xC9
|
||||
#define M_SOF10 0xCA
|
||||
#define M_SOF11 0xCB
|
||||
#define M_SOF13 0xCD
|
||||
#define M_SOF14 0xCE
|
||||
#define M_SOF15 0xCF
|
||||
#define M_SOI 0xD8
|
||||
#define M_EOI 0xD9
|
||||
#define M_SOS 0xDA
|
||||
#define M_JFIF 0xE0
|
||||
#define M_EXIF 0xE1
|
||||
#define M_COM 0xFE
|
||||
|
||||
#define PSEUDO_IMAGE_MARKER 0x123;
|
||||
|
||||
#define EXIF_READ_EXIF 0x01
|
||||
#define EXIF_READ_IMAGE 0x02
|
||||
|
||||
class CxExifInfo
|
||||
{
|
||||
|
||||
typedef struct tag_Section_t
|
||||
{
|
||||
uint8_t* Data;
|
||||
int32_t Type;
|
||||
unsigned Size;
|
||||
} Section_t;
|
||||
|
||||
public:
|
||||
class CSafeReader
|
||||
{
|
||||
private:
|
||||
uint8_t* data;
|
||||
unsigned int len;
|
||||
|
||||
public:
|
||||
CSafeReader(uint8_t* _data = NULL, unsigned int _len = 0)
|
||||
{
|
||||
data = _data;
|
||||
len = _len;
|
||||
}
|
||||
CSafeReader(const CSafeReader& src)
|
||||
{
|
||||
data = src.data;
|
||||
len = src.len;
|
||||
}
|
||||
CSafeReader& operator=(const CSafeReader& src)
|
||||
{
|
||||
data = src.data;
|
||||
len = src.len;
|
||||
return *this;
|
||||
}
|
||||
CSafeReader Offset(unsigned int offset)
|
||||
{
|
||||
if (offset > len)
|
||||
offset = len;
|
||||
CSafeReader reader(data, len);
|
||||
reader.data += offset;
|
||||
reader.len -= offset;
|
||||
return reader;
|
||||
}
|
||||
bool Check(unsigned int size)
|
||||
{
|
||||
if (len >= size)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool Check(unsigned int offset, unsigned int size)
|
||||
{
|
||||
return Check(offset + size);
|
||||
}
|
||||
uint8_t* GetData(unsigned int offset)
|
||||
{
|
||||
return data + offset;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
EXIFINFO* m_exifinfo;
|
||||
char m_szLastError[256];
|
||||
CxExifInfo(EXIFINFO* info = NULL);
|
||||
~CxExifInfo();
|
||||
bool DecodeExif(CxFile* hFile, int32_t nReadMode = EXIF_READ_EXIF);
|
||||
bool EncodeExif(CxFile* hFile);
|
||||
void DiscardAllButExif();
|
||||
protected:
|
||||
bool process_EXIF(uint8_t* CharBuf, uint32_t length);
|
||||
void process_COM (const uint8_t* Data, int32_t length);
|
||||
void process_SOFn(const uint8_t* Data, int32_t marker);
|
||||
int32_t Get16u(void* Short);
|
||||
int32_t Get16m(void* Short);
|
||||
int32_t Get32s(void* Long);
|
||||
uint32_t Get32u(void* Long);
|
||||
double ConvertAnyFormat2(CSafeReader& reader, int32_t Format);
|
||||
void* FindSection(int32_t SectionType);
|
||||
bool ProcessExifDir2(CSafeReader DirStart, CSafeReader OffsetBase, unsigned ExifLength,
|
||||
EXIFINFO* const pInfo, uint8_t** const LastExifRefdP, int32_t NestingLevel = 0);
|
||||
int32_t ExifImageWidth;
|
||||
int32_t MotorolaOrder;
|
||||
Section_t Sections[MAX_SECTIONS];
|
||||
int32_t SectionsRead;
|
||||
bool freeinfo;
|
||||
};
|
||||
|
||||
CxExifInfo* m_exif;
|
||||
bool DecodeExif(CxFile* hFile);
|
||||
#endif //CXIMAGEJPG_SUPPORT_EXIF
|
||||
|
||||
// thanks to Chris Shearer Cooper <cscooper(at)frii(dot)com>
|
||||
class CxFileJpg : public jpeg_destination_mgr, public jpeg_source_mgr
|
||||
{
|
||||
public:
|
||||
enum { eBufSize = 4096 };
|
||||
CxFileJpg(CxFile* pFile)
|
||||
{
|
||||
m_pFile = pFile;
|
||||
|
||||
init_destination = InitDestination;
|
||||
empty_output_buffer = EmptyOutputBuffer;
|
||||
term_destination = TermDestination;
|
||||
|
||||
init_source = InitSource;
|
||||
fill_input_buffer = FillInputBuffer;
|
||||
skip_input_data = SkipInputData;
|
||||
resync_to_restart = jpeg_resync_to_restart; // use default method
|
||||
term_source = TermSource;
|
||||
next_input_byte = NULL; //* => next byte to read from buffer
|
||||
bytes_in_buffer = 0; //* # of bytes remaining in buffer
|
||||
|
||||
m_pBuffer = new uint8_t[eBufSize];
|
||||
}
|
||||
~CxFileJpg()
|
||||
{
|
||||
delete[] m_pBuffer;
|
||||
}
|
||||
|
||||
static void InitDestination(j_compress_ptr cinfo)
|
||||
{
|
||||
CxFileJpg* pDest = (CxFileJpg*)cinfo->dest;
|
||||
pDest->next_output_byte = pDest->m_pBuffer;
|
||||
pDest->free_in_buffer = eBufSize;
|
||||
}
|
||||
static boolean EmptyOutputBuffer(j_compress_ptr cinfo)
|
||||
{
|
||||
CxFileJpg* pDest = (CxFileJpg*)cinfo->dest;
|
||||
if (pDest->m_pFile->Write(pDest->m_pBuffer,1,eBufSize)!=(size_t)eBufSize)
|
||||
ERREXIT(cinfo, JERR_FILE_WRITE);
|
||||
pDest->next_output_byte = pDest->m_pBuffer;
|
||||
pDest->free_in_buffer = eBufSize;
|
||||
return TRUE;
|
||||
}
|
||||
static void TermDestination(j_compress_ptr cinfo)
|
||||
{
|
||||
CxFileJpg* pDest = (CxFileJpg*)cinfo->dest;
|
||||
size_t datacount = eBufSize - pDest->free_in_buffer;
|
||||
/* Write any data remaining in the buffer */
|
||||
if (datacount > 0) {
|
||||
if (!pDest->m_pFile->Write(pDest->m_pBuffer,1,datacount))
|
||||
ERREXIT(cinfo, JERR_FILE_WRITE);
|
||||
}
|
||||
pDest->m_pFile->Flush();
|
||||
/* Make sure we wrote the output file OK */
|
||||
if (pDest->m_pFile->Error()) ERREXIT(cinfo, JERR_FILE_WRITE);
|
||||
return;
|
||||
}
|
||||
static void InitSource(j_decompress_ptr cinfo)
|
||||
{
|
||||
CxFileJpg* pSource = (CxFileJpg*)cinfo->src;
|
||||
pSource->m_bStartOfFile = TRUE;
|
||||
}
|
||||
static boolean FillInputBuffer(j_decompress_ptr cinfo)
|
||||
{
|
||||
size_t nbytes;
|
||||
CxFileJpg* pSource = (CxFileJpg*)cinfo->src;
|
||||
nbytes = pSource->m_pFile->Read(pSource->m_pBuffer,1,eBufSize);
|
||||
if (nbytes <= 0){
|
||||
if (pSource->m_bStartOfFile) //* Treat empty input file as fatal error
|
||||
ERREXIT(cinfo, JERR_INPUT_EMPTY);
|
||||
WARNMS(cinfo, JWRN_JPEG_EOF);
|
||||
// Insert a fake EOI marker
|
||||
pSource->m_pBuffer[0] = (JOCTET) 0xFF;
|
||||
pSource->m_pBuffer[1] = (JOCTET) JPEG_EOI;
|
||||
nbytes = 2;
|
||||
}
|
||||
pSource->next_input_byte = pSource->m_pBuffer;
|
||||
pSource->bytes_in_buffer = nbytes;
|
||||
pSource->m_bStartOfFile = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
static void SkipInputData(j_decompress_ptr cinfo, long num_bytes)
|
||||
{
|
||||
CxFileJpg* pSource = (CxFileJpg*)cinfo->src;
|
||||
if (num_bytes > 0){
|
||||
while (num_bytes > (int32_t)pSource->bytes_in_buffer){
|
||||
num_bytes -= (int32_t)pSource->bytes_in_buffer;
|
||||
FillInputBuffer(cinfo);
|
||||
// note we assume that fill_input_buffer will never return FALSE,
|
||||
// so suspension need not be handled.
|
||||
}
|
||||
pSource->next_input_byte += (size_t) num_bytes;
|
||||
pSource->bytes_in_buffer -= (size_t) num_bytes;
|
||||
}
|
||||
}
|
||||
static void TermSource(j_decompress_ptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
protected:
|
||||
CxFile* m_pFile;
|
||||
uint8_t* m_pBuffer;
|
||||
bool m_bStartOfFile;
|
||||
};
|
||||
|
||||
public:
|
||||
enum CODEC_OPTION
|
||||
{
|
||||
ENCODE_BASELINE = 0x1,
|
||||
ENCODE_ARITHMETIC = 0x2,
|
||||
ENCODE_GRAYSCALE = 0x4,
|
||||
ENCODE_OPTIMIZE = 0x8,
|
||||
ENCODE_PROGRESSIVE = 0x10,
|
||||
ENCODE_LOSSLESS = 0x20,
|
||||
ENCODE_SMOOTHING = 0x40,
|
||||
DECODE_GRAYSCALE = 0x80,
|
||||
DECODE_QUANTIZE = 0x100,
|
||||
DECODE_DITHER = 0x200,
|
||||
DECODE_ONEPASS = 0x400,
|
||||
DECODE_NOSMOOTH = 0x800,
|
||||
ENCODE_SUBSAMPLE_422 = 0x1000,
|
||||
ENCODE_SUBSAMPLE_444 = 0x2000
|
||||
};
|
||||
|
||||
int32_t m_nPredictor;
|
||||
int32_t m_nPointTransform;
|
||||
int32_t m_nSmoothing;
|
||||
int32_t m_nQuantize;
|
||||
J_DITHER_MODE m_nDither;
|
||||
};
|
||||
|
||||
#endif // CXIMAGE_SUPPORT_JPG
|
||||
|
||||
#endif // __ximajpg_h
|
||||
@ -1,20 +0,0 @@
|
||||
#include "ximage.h"
|
||||
|
||||
#if CXIMAGE_SUPPORT_ALPHA
|
||||
void CxImage::AlphaDelete()
|
||||
{
|
||||
if (pAlpha) { free(pAlpha); pAlpha=0; }
|
||||
}
|
||||
uint8_t CxImage::BlindAlphaGet(const int32_t x, const int32_t y)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (!IsInside(x,y) || (pAlpha == 0))
|
||||
#if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
|
||||
throw 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
#endif
|
||||
return pAlpha[x + y * head.biWidth];
|
||||
}
|
||||
#endif //CXIMAGE_SUPPORT_ALPHA
|
||||
@ -1,138 +0,0 @@
|
||||
#include "ximage.h"
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) (((a)<(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
void CxImage::RGBtoBGR(uint8_t* buffer, int32_t length)
|
||||
{
|
||||
if (buffer && (head.biClrUsed == 0))
|
||||
{
|
||||
uint8_t temp;
|
||||
length = min(length,(int32_t)info.dwEffWidth);
|
||||
length = min(length,(int32_t)(3 * head.biWidth));
|
||||
for (int32_t i = 0; i < length; i += 3)
|
||||
{
|
||||
temp = buffer[i];
|
||||
buffer[i] = buffer[i + 2];
|
||||
buffer[i + 2] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t CxImage::GetPaletteSize()
|
||||
{
|
||||
return (head.biClrUsed * sizeof(RGBQUAD));
|
||||
}
|
||||
RGBQUAD* CxImage::GetPalette() const
|
||||
{
|
||||
if ((pDib) && (head.biClrUsed))
|
||||
return (RGBQUAD*)((uint8_t*)pDib + sizeof(BITMAPINFOHEADER));
|
||||
return NULL;
|
||||
}
|
||||
RGBQUAD CxImage::GetPaletteColor(uint8_t idx)
|
||||
{
|
||||
RGBQUAD rgb = {0, 0, 0, 0};
|
||||
if ((pDib) && (head.biClrUsed))
|
||||
{
|
||||
uint8_t* iDst = (uint8_t*)(pDib) + sizeof(BITMAPINFOHEADER);
|
||||
if (idx < head.biClrUsed)
|
||||
{
|
||||
int32_t ldx = idx * sizeof(RGBQUAD);
|
||||
rgb.rgbBlue = iDst[ldx++];
|
||||
rgb.rgbGreen = iDst[ldx++];
|
||||
rgb.rgbRed = iDst[ldx++];
|
||||
rgb.rgbReserved = iDst[ldx];
|
||||
}
|
||||
}
|
||||
return rgb;
|
||||
}
|
||||
uint8_t CxImage::BlindGetPixelIndex(const int32_t x, const int32_t y)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if ((pDib == NULL) || (head.biClrUsed == 0) || !IsInside(x,y))
|
||||
#if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
|
||||
throw 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif // CXIMAGE_SUPPORT_EXCEPTION_HANDLING
|
||||
#endif // _DEBUG
|
||||
|
||||
if (head.biBitCount == 8)
|
||||
return info.pImage[y * info.dwEffWidth + x];
|
||||
|
||||
uint8_t pos;
|
||||
uint8_t iDst = info.pImage[y * info.dwEffWidth + (x * head.biBitCount >> 3)];
|
||||
if (head.biBitCount == 4)
|
||||
{
|
||||
pos = (uint8_t)(4 * (1 - x % 2));
|
||||
iDst &= (0x0F << pos);
|
||||
return (uint8_t)(iDst >> pos);
|
||||
}
|
||||
else if (head.biBitCount==1)
|
||||
{
|
||||
pos = (uint8_t)(7 - x % 8);
|
||||
iDst &= (0x01 << pos);
|
||||
return (uint8_t)(iDst >> pos);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
RGBQUAD CxImage::BlindGetPixelColor(const int32_t x, const int32_t y, bool bGetAlpha)
|
||||
{
|
||||
RGBQUAD rgb;
|
||||
#ifdef _DEBUG
|
||||
if ((pDib == NULL) || !IsInside(x,y))
|
||||
#if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
|
||||
throw 0;
|
||||
#else
|
||||
{ rgb.rgbReserved = 0; return rgb; }
|
||||
#endif // CXIMAGE_SUPPORT_EXCEPTION_HANDLING
|
||||
#endif // _DEBUG
|
||||
|
||||
if (head.biClrUsed)
|
||||
rgb = GetPaletteColor(BlindGetPixelIndex(x,y));
|
||||
else
|
||||
{
|
||||
uint8_t* iDst = info.pImage + y * info.dwEffWidth + x * 3;
|
||||
rgb.rgbBlue = *iDst++;
|
||||
rgb.rgbGreen = *iDst++;
|
||||
rgb.rgbRed = *iDst;
|
||||
rgb.rgbReserved = 0; //needed for images without alpha layer
|
||||
}
|
||||
#if CXIMAGE_SUPPORT_ALPHA
|
||||
if (pAlpha && bGetAlpha) rgb.rgbReserved = BlindAlphaGet(x,y);
|
||||
#else
|
||||
rgb.rgbReserved = 0;
|
||||
#endif //CXIMAGE_SUPPORT_ALPHA
|
||||
return rgb;
|
||||
}
|
||||
void CxImage::SetGrayPalette()
|
||||
{
|
||||
if ((pDib == NULL) || (head.biClrUsed == 0)) return;
|
||||
RGBQUAD* pal = GetPalette();
|
||||
for (uint32_t ni = 0; ni < head.biClrUsed; ni++)
|
||||
pal[ni].rgbBlue = pal[ni].rgbGreen = pal[ni].rgbRed = (uint8_t)(ni * (255 / (head.biClrUsed - 1)));
|
||||
}
|
||||
void CxImage::SetPalette(uint32_t n, uint8_t* r, uint8_t* g, uint8_t* b)
|
||||
{
|
||||
if ((!r) || (pDib == NULL) || (head.biClrUsed == 0)) return;
|
||||
if (!g) g = r;
|
||||
if (!b) b = g;
|
||||
RGBQUAD* ppal = GetPalette();
|
||||
uint32_t m = min(n,head.biClrUsed);
|
||||
for (uint32_t i = 0; i < m; i++)
|
||||
{
|
||||
ppal[i].rgbRed = r[i];
|
||||
ppal[i].rgbGreen = g[i];
|
||||
ppal[i].rgbBlue = b[i];
|
||||
}
|
||||
info.last_c_isvalid = false;
|
||||
}
|
||||
bool CxImage::IsGrayScale()
|
||||
{
|
||||
RGBQUAD* ppal = GetPalette();
|
||||
if (!(pDib && ppal && head.biClrUsed)) return false;
|
||||
for (uint32_t i = 0; i < head.biClrUsed; i++)
|
||||
if (ppal[i].rgbBlue != i || ppal[i].rgbGreen != i || ppal[i].rgbRed != i)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
#include "ximage.h"
|
||||
|
||||
#if CXIMAGE_SUPPORT_SELECTION
|
||||
|
||||
bool CxImage::SelectionDelete()
|
||||
{
|
||||
if (pSelection)
|
||||
{
|
||||
free(pSelection);
|
||||
pSelection = NULL;
|
||||
}
|
||||
info.rSelectionBox.left = head.biWidth;
|
||||
info.rSelectionBox.bottom = head.biHeight;
|
||||
info.rSelectionBox.right = info.rSelectionBox.top = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif //CXIMAGE_SUPPORT_SELECTION
|
||||
@ -1,165 +0,0 @@
|
||||
#include "xmemfile.h"
|
||||
|
||||
CxMemFile::CxMemFile(uint8_t* pBuffer, uint32_t size)
|
||||
{
|
||||
m_pBuffer = pBuffer;
|
||||
m_Position = 0;
|
||||
m_Size = m_Edge = size;
|
||||
m_bFreeOnClose = (pBuffer == 0);
|
||||
m_bEOF = false;
|
||||
}
|
||||
CxMemFile::~CxMemFile()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
bool CxMemFile::Close()
|
||||
{
|
||||
if ((m_pBuffer) && (m_bFreeOnClose))
|
||||
{
|
||||
free(m_pBuffer);
|
||||
m_pBuffer = NULL;
|
||||
m_Size = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool CxMemFile::Open()
|
||||
{
|
||||
if (m_pBuffer) return false; // Can't re-open without closing first
|
||||
|
||||
m_Position = m_Size = m_Edge = 0;
|
||||
m_pBuffer = (uint8_t*)malloc(1);
|
||||
m_bFreeOnClose = true;
|
||||
|
||||
return (m_pBuffer != 0);
|
||||
}
|
||||
uint8_t* CxMemFile::GetBuffer(bool bDetachBuffer)
|
||||
{
|
||||
if (bDetachBuffer)
|
||||
m_bFreeOnClose = false;
|
||||
return m_pBuffer;
|
||||
}
|
||||
size_t CxMemFile::Read(void* buffer, size_t size, size_t count, void* limit_start, void* limit_end)
|
||||
{
|
||||
if (buffer == NULL) return 0;
|
||||
|
||||
if (m_pBuffer == NULL) return 0;
|
||||
if (m_Position >= (int32_t)m_Size)
|
||||
{
|
||||
m_bEOF = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t nCount = (int32_t)(count * size);
|
||||
if (nCount == 0) return 0;
|
||||
|
||||
int32_t nRead;
|
||||
if (m_Position + nCount > (int32_t)m_Size)
|
||||
{
|
||||
m_bEOF = true;
|
||||
nRead = (m_Size - m_Position);
|
||||
}
|
||||
else
|
||||
nRead = nCount;
|
||||
|
||||
memcpy(buffer, m_pBuffer + m_Position, nRead);
|
||||
m_Position += nRead;
|
||||
|
||||
return (size_t)(nRead / size);
|
||||
}
|
||||
size_t CxMemFile::Write(const void* buffer, size_t size, size_t count)
|
||||
{
|
||||
m_bEOF = false;
|
||||
if (m_pBuffer == NULL) return 0;
|
||||
if (buffer == NULL) return 0;
|
||||
|
||||
int32_t nCount = (int32_t)(count*size);
|
||||
if (nCount == 0) return 0;
|
||||
|
||||
if (m_Position + nCount > m_Edge)
|
||||
if (!Alloc(m_Position + nCount))
|
||||
return false;
|
||||
|
||||
memcpy(m_pBuffer + m_Position, buffer, nCount);
|
||||
|
||||
m_Position += nCount;
|
||||
|
||||
if (m_Position > (int32_t)m_Size) m_Size = m_Position;
|
||||
|
||||
return count;
|
||||
}
|
||||
bool CxMemFile::Seek(int32_t offset, int32_t origin)
|
||||
{
|
||||
m_bEOF = false;
|
||||
if (m_pBuffer == NULL) return false;
|
||||
int32_t lNewPos = m_Position;
|
||||
|
||||
if (origin == SEEK_SET) lNewPos = offset;
|
||||
else if (origin == SEEK_CUR) lNewPos += offset;
|
||||
else if (origin == SEEK_END) lNewPos = m_Size + offset;
|
||||
else return false;
|
||||
|
||||
if (lNewPos < 0) lNewPos = 0;
|
||||
|
||||
m_Position = lNewPos;
|
||||
return true;
|
||||
}
|
||||
int32_t CxMemFile::Tell()
|
||||
{
|
||||
if (m_pBuffer == NULL) return -1;
|
||||
return m_Position;
|
||||
}
|
||||
int32_t CxMemFile::Size()
|
||||
{
|
||||
if (m_pBuffer == NULL) return -1;
|
||||
return m_Size;
|
||||
}
|
||||
bool CxMemFile::Flush()
|
||||
{
|
||||
return m_pBuffer != NULL;
|
||||
}
|
||||
int32_t CxMemFile::Error()
|
||||
{
|
||||
if (m_pBuffer == NULL) return -1;
|
||||
return (m_Position > (int32_t)m_Size);
|
||||
}
|
||||
bool CxMemFile::PutC(uint8_t c)
|
||||
{
|
||||
m_bEOF = false;
|
||||
if (m_pBuffer == NULL) return false;
|
||||
|
||||
if (m_Position >= m_Edge)
|
||||
if (!Alloc(m_Position + 1))
|
||||
return false;
|
||||
|
||||
m_pBuffer[m_Position++] = c;
|
||||
|
||||
if (m_Position > (int32_t)m_Size) m_Size = m_Position;
|
||||
|
||||
return true;
|
||||
}
|
||||
int32_t CxMemFile::GetC()
|
||||
{
|
||||
if (m_pBuffer == NULL || m_Position >= (int32_t)m_Size)
|
||||
{
|
||||
m_bEOF = true;
|
||||
return EOF;
|
||||
}
|
||||
return *(uint8_t*)((uint8_t*)m_pBuffer + m_Position++);
|
||||
}
|
||||
bool CxMemFile::Alloc(uint32_t dwNewLen)
|
||||
{
|
||||
if (dwNewLen > (uint32_t)m_Edge)
|
||||
{
|
||||
// find new buffer size
|
||||
uint32_t dwNewBufferSize = (uint32_t)(((dwNewLen >> 16) + 1)<<16);
|
||||
|
||||
// allocate new buffer
|
||||
if (m_pBuffer == NULL) m_pBuffer = (uint8_t*)malloc(dwNewBufferSize);
|
||||
else m_pBuffer = (uint8_t*)realloc(m_pBuffer, dwNewBufferSize);
|
||||
// I own this buffer now (caller knows nothing about it)
|
||||
m_bFreeOnClose = true;
|
||||
|
||||
m_Edge = dwNewBufferSize;
|
||||
}
|
||||
return (m_pBuffer != 0);
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
#ifndef __xmemfile_h
|
||||
#define __xmemfile_h
|
||||
|
||||
#include "xfile.h"
|
||||
|
||||
class CxMemFile : public CxFile
|
||||
{
|
||||
public:
|
||||
CxMemFile(uint8_t* pBuffer = NULL, uint32_t size = 0);
|
||||
~CxMemFile();
|
||||
|
||||
bool Open();
|
||||
uint8_t* GetBuffer(bool bDetachBuffer = true);
|
||||
|
||||
virtual bool Close();
|
||||
virtual size_t Read(void* buffer, size_t size, size_t count, void* limit_start = NULL, void* limit_end = NULL);
|
||||
virtual size_t Write(const void* buffer, size_t size, size_t count);
|
||||
virtual bool Seek(int32_t offset, int32_t origin);
|
||||
virtual int32_t Tell();
|
||||
virtual int32_t Size();
|
||||
virtual bool Flush();
|
||||
virtual int32_t Error();
|
||||
virtual bool PutC(uint8_t c);
|
||||
virtual int32_t GetC();
|
||||
|
||||
protected:
|
||||
bool Alloc(uint32_t nBytes);
|
||||
|
||||
uint8_t* m_pBuffer;
|
||||
uint32_t m_Size;
|
||||
bool m_bFreeOnClose;
|
||||
int32_t m_Position;
|
||||
int32_t m_Edge;
|
||||
bool m_bEOF;
|
||||
};
|
||||
|
||||
#endif // __xmemfile_h
|
||||
@ -148,7 +148,7 @@ sources.append("wasm/src/base.cpp")
|
||||
|
||||
compiler_flags.append("-I../../../../OfficeUtils/src/zlib-1.2.11")
|
||||
compiler_flags.append("-I" + libJasper_src_path + "/include")
|
||||
compiler_flags.append("-DBUILDING_WASM_MODULE -D_tcsnicmp=strncmp -D_lseek=lseek -D_getcwd=getcwd")
|
||||
compiler_flags.append("-D__linux__ -DBUILDING_WASM_MODULE -D_tcsnicmp=strncmp -D_lseek=lseek -D_getcwd=getcwd")
|
||||
|
||||
# arguments
|
||||
arguments = ""
|
||||
|
||||
Reference in New Issue
Block a user