Merge remote-tracking branch 'origin/release/v6.1.0' into develop

This commit is contained in:
ElenaSubbotina
2020-10-22 15:56:11 +03:00
190 changed files with 2893 additions and 585 deletions

View File

@ -49,11 +49,11 @@
class DLL_EXP CxFile
{
public:
CxFile(void) { };
virtual ~CxFile() { };
CxFile(void) { }
virtual ~CxFile() { }
virtual bool Close() = 0;
virtual size_t Read(void *buffer, size_t size, size_t count) = 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;
@ -72,4 +72,27 @@ public:
virtual int32_t Scanf(const char *format, void* output) = 0;
};
static void clamp_buffer(void*& buffer, size_t& size, void* limit_start, void* limit_end)
{
if (NULL == limit_start || NULL == limit_end)
return;
uint8_t* _buffer = (uint8_t*)buffer;
uint8_t* _limit_start = (uint8_t*)limit_start;
uint8_t* _limit_end = (uint8_t*)limit_end;
if (_buffer > _limit_end)
{
buffer = limit_end;
size = 0;
return;
}
if (_buffer < _limit_start)
_buffer = _limit_start;
if ((_buffer + size) > _limit_end)
size = (_limit_end - _buffer);
}
#endif //__xfile_h

View File

@ -133,7 +133,7 @@ bool CxImageBMP::Decode(CxFile * hFile)
if (bIsOldBmp){
// convert a old color table (3 byte entries) to a new
// color table (4 byte entries)
hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBTRIPLE),1);
hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBTRIPLE),1,GetDIB(),GetDIBLimit());
for (int32_t i=DibNumColors(&head)-1; i>=0; i--){
pRgb[i].rgbRed = ((RGBTRIPLE *)pRgb)[i].rgbtRed;
pRgb[i].rgbBlue = ((RGBTRIPLE *)pRgb)[i].rgbtBlue;
@ -141,7 +141,7 @@ bool CxImageBMP::Decode(CxFile * hFile)
pRgb[i].rgbReserved = (uint8_t)0;
}
} else {
hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBQUAD),1);
hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBQUAD),1,GetDIB(),GetDIBLimit());
//force rgbReserved=0, to avoid problems with some WinXp bitmaps
for (uint32_t i=0; i<head.biClrUsed; i++) pRgb[i].rgbReserved=0;
}
@ -165,7 +165,7 @@ bool CxImageBMP::Decode(CxFile * hFile)
int32_t imagesize=4*head.biHeight*head.biWidth;
uint8_t* buff32=(uint8_t*)malloc(imagesize);
if (buff32){
hFile->Read(buff32, imagesize,1); // read in the pixels
hFile->Read(buff32, imagesize,1,GetDIB(),GetDIBLimit()); // read in the pixels
#if CXIMAGE_SUPPORT_ALPHA
if (dwCompression == BI_RGB){
@ -195,7 +195,7 @@ bool CxImageBMP::Decode(CxFile * hFile)
case 24 :
if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);
if (dwCompression == BI_RGB){
hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels
hFile->Read(info.pImage, head.biSizeImage,1,GetDIB(),GetDIBLimit()); // read in the pixels
} else cx_throw("unknown compression");
break;
case 16 :
@ -210,7 +210,7 @@ bool CxImageBMP::Decode(CxFile * hFile)
// bf.bfOffBits required after the bitfield mask <Cui Ying Jie>
if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);
// read in the pixels
hFile->Read(info.pImage, head.biHeight*((head.biWidth+1)/2)*4,1);
hFile->Read(info.pImage, head.biHeight*((head.biWidth+1)/2)*4,1,GetDIB(),GetDIBLimit());
// transform into RGB
Bitfield2RGB(info.pImage,bfmask[0],bfmask[1],bfmask[2],16);
break;
@ -229,7 +229,7 @@ bool CxImageBMP::Decode(CxFile * hFile)
}
switch (dwCompression) {
case BI_RGB :
hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels
hFile->Read(info.pImage, head.biSizeImage,1,GetDIB(),GetDIBLimit()); // read in the pixels
break;
case BI_RLE4 :
{
@ -355,7 +355,7 @@ bool CxImageBMP::Decode(CxFile * hFile)
break;
}
default :
hFile->Read((void *)(iter.GetRow(scanline) + bits), sizeof(uint8_t) * status_byte, 1);
hFile->Read((void *)(iter.GetRow(scanline) + bits), sizeof(uint8_t) * status_byte, 1,GetDIB(),GetDIBLimit());
// align run length to even number of bytes
if ((status_byte & 1) == 1)
hFile->Read(&second_byte, sizeof(uint8_t), 1);

View File

@ -165,7 +165,7 @@ bool CxImageJPG::CxExifInfo::DecodeExif(CxFile * hFile, int32_t nReadMode)
// 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) && memcmp(Data+2, "Exif", 4) == 0){
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.
@ -187,6 +187,8 @@ bool CxImageJPG::CxExifInfo::DecodeExif(CxFile * hFile, int32_t nReadMode)
case M_SOF13:
case M_SOF14:
case M_SOF15:
if (itemlen < 8)
return false;
process_SOFn(Data, marker);
break;
default:
@ -208,6 +210,9 @@ bool CxImageJPG::CxExifInfo::process_EXIF(uint8_t * CharBuf, uint32_t length)
/* 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 */
@ -218,6 +223,9 @@ bool CxImageJPG::CxExifInfo::process_EXIF(uint8_t * CharBuf, uint32_t length)
}
}
if (length < 8)
return false;
if (memcmp(CharBuf+6,"II",2) == 0){
MotorolaOrder = 0;
}else{
@ -229,6 +237,9 @@ bool CxImageJPG::CxExifInfo::process_EXIF(uint8_t * CharBuf, uint32_t length)
}
}
if (length < 14)
return false;
/* Check the next two values for correctness. */
if (Get16u(CharBuf+8) != 0x2a){
strcpy(m_szLastError,"Invalid Exif start (1)");
@ -246,6 +257,7 @@ bool CxImageJPG::CxExifInfo::process_EXIF(uint8_t * CharBuf, uint32_t length)
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;
@ -255,6 +267,18 @@ bool CxImageJPG::CxExifInfo::process_EXIF(uint8_t * CharBuf, uint32_t length)
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;
@ -692,6 +716,322 @@ bool CxImageJPG::CxExifInfo::ProcessExifDir(uint8_t * DirStart, uint8_t * Offset
return true;
}
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;
}
////////////////////////////////////////////////////////////////////////////////
/*--------------------------------------------------------------------------
Evaluate number, be it int32_t, rational, or float from directory.
@ -732,6 +1072,58 @@ double CxImageJPG::CxExifInfo::ConvertAnyFormat(void * ValuePtr, int32_t Format)
}
return Value;
}
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);
if (Den == 0){
Value = 0;
}else{
Value = (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)
{
@ -747,7 +1139,7 @@ void CxImageJPG::CxExifInfo::process_COM (const uint8_t * Data, int32_t length)
for (a=2;a<length;a++){
ch = Data[a];
if (ch == '\r' && Data[a+1] == '\n') continue; // Remove cr followed by lf.
if (ch == '\r' && (a < (length - 1) && Data[a+1] == '\n')) continue; // Remove cr followed by lf.
if (isprint(ch) || ch == '\n' || ch == '\t'){
Comment[nch++] = (char)ch;

View File

@ -21,7 +21,7 @@
void CxImage::Startup(uint32_t imagetype)
{
//init pointers
pDib = pSelection = pAlpha = NULL;
pDib = pDibLimit = pSelection = pAlpha = NULL;
ppLayers = ppFrames = NULL;
//init structures
memset(&head,0,sizeof(BITMAPINFOHEADER));
@ -232,6 +232,7 @@ void* CxImage::Create(uint32_t dwWidth, uint32_t dwHeight, uint32_t wBpp, uint32
strcpy(info.szLastError,"CxImage::Create can't allocate memory");
return NULL;
}
pDibLimit = (void*)((uint8_t*)pDib + GetSize());
//clear the palette
RGBQUAD* pal=GetPalette();
@ -278,9 +279,12 @@ uint8_t* CxImage::GetBits(uint32_t row)
/**
* \return the size in bytes of the internal pDib object
*/
int32_t CxImage::GetSize()
uint32_t CxImage::GetSize()
{
return head.biSize + head.biSizeImage + GetPaletteSize();
uint64_t size64 = head.biSize + head.biSizeImage + GetPaletteSize();
if (size64 > 0xFFFFFFFF)
return 0xFFFFFFFF;
return (uint32_t)size64;
}
////////////////////////////////////////////////////////////////////////////////
/**
@ -324,13 +328,14 @@ bool CxImage::Transfer(CxImage &from, bool bTransferFrames /*=true*/)
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.pSelection = from.pAlpha = NULL;
from.pDib = from.pDibLimit = from.pSelection = from.pAlpha = NULL;
from.ppLayers = NULL;
if (bTransferFrames){
@ -352,6 +357,7 @@ void CxImage::Ghost(const CxImage *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;

View File

@ -289,10 +289,11 @@ public:
//@}
/** \addtogroup Attributes */ //@{
int32_t GetSize();
uint32_t GetSize();
uint8_t* GetBits(uint32_t row = 0);
uint8_t GetColorType();
void* GetDIB() const;
void* GetDIBLimit() const;
uint32_t GetHeight() const;
uint32_t GetWidth() const;
uint32_t GetEffWidth() const;
@ -796,6 +797,8 @@ protected:
void bihtoh(BITMAPINFOHEADER* bih);
void* pDib; //contains the header, the palette, the pixels
void* pDibLimit;
BITMAPINFOHEADER head; //standard header
CXIMAGEINFO info; //extended information
uint8_t* pSelection; //selected region

View File

@ -95,9 +95,15 @@ bool CxImageICO::Decode(CxFile *hFile)
// read the palette
RGBQUAD pal[256];
if (bih.biClrUsed)
hFile->Read(pal,bih.biClrUsed*sizeof(RGBQUAD), 1);
{
uint32_t _count = bih.biClrUsed; if (_count > 256) _count = 256;
hFile->Read(pal,_count*sizeof(RGBQUAD), 1);
}
else
hFile->Read(pal,head.biClrUsed*sizeof(RGBQUAD), 1);
{
uint32_t _count = head.biClrUsed; if (_count > 256) _count = 256;
hFile->Read(pal,_count*sizeof(RGBQUAD), 1);
}
SetPalette(pal,head.biClrUsed); //palette assign

View File

@ -181,6 +181,10 @@ void* CxImage::GetDIB() const
{
return pDib;
}
void* CxImage::GetDIBLimit() const
{
return pDibLimit;
}
////////////////////////////////////////////////////////////////////////////////
uint32_t CxImage::GetHeight() const
{

View File

@ -101,6 +101,55 @@ typedef struct tag_Section_t{
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];
@ -118,9 +167,12 @@ protected:
int32_t Get32s(void * Long);
uint32_t Get32u(void * Long);
double ConvertAnyFormat(void * ValuePtr, int32_t Format);
double ConvertAnyFormat2(CSafeReader& reader, int32_t Format);
void* FindSection(int32_t SectionType);
bool ProcessExifDir(uint8_t * DirStart, uint8_t * OffsetBase, unsigned ExifLength,
EXIFINFO * const pInfo, uint8_t ** const LastExifRefdP, int32_t NestingLevel=0);
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];

View File

@ -50,6 +50,9 @@ bool CxImagePCX::Decode(CxFile *hFile)
info.xDPI = pcxHeader.Hres;
info.yDPI = pcxHeader.Vres;
if (Width <= 0 || Height <= 0)
cx_throw("Error: Not a PCX file");
if (info.nEscape == -1){
head.biWidth = Width;
head.biHeight= Height;
@ -76,7 +79,11 @@ bool CxImagePCX::Decode(CxFile *hFile)
//Read the image and check if it's ok
nbytes = pcxHeader.BytesPerLine * pcxHeader.ColorPlanes * Height;
uint32_t pcximage_size = nbytes;
lpHead1 = pcximage = (uint8_t*)malloc(nbytes);
if (!pcximage)
cx_throw("Cancelled");
while (nbytes > 0){
if (hFile == NULL || hFile->Eof()) cx_throw("corrupted PCX");
@ -119,6 +126,9 @@ bool CxImagePCX::Decode(CxFile *hFile)
for (uint32_t idx=0; idx<head.biClrUsed; idx++) SetPaletteColor((uint8_t)idx,ColorMap[idx][0],ColorMap[idx][1],ColorMap[idx][2]);
lpHead2 = pcxpixels = (uint8_t *)malloc(Width + pcxHeader.BytesPerLine * 8);
if (!pcxpixels)
cx_throw("Cancelled");
// Convert the image
for (y = 0; y < Height; y++){
@ -138,7 +148,11 @@ bool CxImagePCX::Decode(CxFile *hFile)
} else if (pcxHeader.ColorPlanes == 4 && pcxHeader.BitsPerPixel == 8){
for (x = 0; x < Width; x++){
SetPixelColor(x,y2,RGB(pcxplanes[x],pcxplanes[pcxHeader.BytesPerLine + x],pcxplanes[2*pcxHeader.BytesPerLine + x]));
AlphaSet(x,y2,pcxplanes[3*pcxHeader.BytesPerLine + x]);
uint32_t alphaIndex = 3*pcxHeader.BytesPerLine + x;
if (alphaIndex < pcximage_size)
AlphaSet(x,y2,pcxplanes[alphaIndex]);
}
continue;
#endif //CXIMAGE_SUPPORT_ALPHA

View File

@ -301,7 +301,8 @@ bool CxImageTIF::Decode(CxFile * hFile)
tilebuf = (uint8_t*)malloc(TIFFTileSize(m_tif));
}
bits = (uint8_t*)malloc(bitspersample==16? bitsize*2 : bitsize); // * VK
int32_t bitsize_correct = bitspersample==16? bitsize*2 : bitsize;
bits = (uint8_t*)malloc(bitsize_correct); // * VK
uint8_t * bits16 = NULL; // + VK
int32_t line16 = 0; // + VK
@ -309,6 +310,7 @@ bool CxImageTIF::Decode(CxFile * hFile)
line16 = line;
line = CalculateLine(width, 8 * samplesperpixel);
bits16 = bits;
bitsize_correct = bitsize;
bits = (uint8_t*)malloc(bitsize);
}
@ -454,9 +456,18 @@ bool CxImageTIF::Decode(CxFile * hFile)
double p,cx,cy,cz,cr,cg,cb;
while (ii</*line*/width){ // * VK
bitsoffset = ii*samplesperpixel+offset;
l=bits[bitsoffset];
a=bits[bitsoffset+1];
b=bits[bitsoffset+2];
if (bitsoffset + 2 < bitsize_correct)
{
l=bits[bitsoffset];
a=bits[bitsoffset+1];
b=bits[bitsoffset+2];
}
else
{
l=0;
a=0;
b=0;
}
if (a>127) a-=256;
if (b>127) b-=256;
// lab to xyz

View File

@ -59,9 +59,10 @@ public:
return (bool)(iErr==0);
}
//////////////////////////////////////////////////////////
virtual size_t Read(void *buffer, size_t size, size_t count)
virtual size_t Read(void *buffer, size_t size, size_t count, void* limit_start = NULL, void* limit_end = NULL)
{
if (!m_fp) return 0;
clamp_buffer(buffer, size, limit_start, limit_end);
return fread(buffer, size, count, m_fp);
}
//////////////////////////////////////////////////////////

View File

@ -45,7 +45,7 @@ uint8_t* CxMemFile::GetBuffer(bool bDetachBuffer)
return m_pBuffer;
}
//////////////////////////////////////////////////////////
size_t CxMemFile::Read(void *buffer, size_t size, size_t count)
size_t CxMemFile::Read(void *buffer, size_t size, size_t count, void* limit_start, void* limit_end)
{
if (buffer==NULL) return 0;
@ -53,7 +53,7 @@ size_t CxMemFile::Read(void *buffer, size_t size, size_t count)
if (m_Position >= (int32_t)m_Size){
m_bEOF = true;
return 0;
}
}
int32_t nCount = (int32_t)(count*size);
if (nCount == 0) return 0;

View File

@ -14,7 +14,7 @@ public:
uint8_t* GetBuffer(bool bDetachBuffer = true);
virtual bool Close();
virtual size_t Read(void *buffer, size_t size, size_t count);
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();