123
This commit is contained in:
258
RenderDll/Common/Textures/Image/BmpImage.cpp
Normal file
258
RenderDll/Common/Textures/Image/BmpImage.cpp
Normal file
@@ -0,0 +1,258 @@
|
||||
/*=============================================================================
|
||||
BmpImage.cpp : BMP image file format implementation.
|
||||
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
||||
|
||||
Revision history:
|
||||
* Created by Khonich Andrey
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "RenderPCH.h"
|
||||
#include "CImage.h"
|
||||
#include "BmpImage.h"
|
||||
|
||||
#include "SHEndian.h"
|
||||
|
||||
//===========================================================================
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Some platforms require strict-alignment, which means that values of
|
||||
// primitive types must be accessed at memory locations which are multiples
|
||||
// of the size of those types. For instance, a 'long' can only be accessed
|
||||
// at a memory location which is a multiple of four. Consequently, the
|
||||
// following endian-conversion functions first copy the raw data into a
|
||||
// variable of the proper data type using memcpy() prior to attempting to
|
||||
// access it as the given type.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static inline ushort us_endian (const byte* ptr)
|
||||
{
|
||||
short n;
|
||||
memcpy(&n, ptr, sizeof(n));
|
||||
return convert_endian(n);
|
||||
}
|
||||
|
||||
static inline unsigned long ul_endian (const byte* ptr)
|
||||
{
|
||||
long n;
|
||||
memcpy(&n, ptr, sizeof(n));
|
||||
return convert_endian(n);
|
||||
}
|
||||
|
||||
static inline long l_endian (const byte* ptr)
|
||||
{
|
||||
long n;
|
||||
memcpy(&n, ptr, sizeof(n));
|
||||
return convert_endian(n);
|
||||
}
|
||||
|
||||
#define BFTYPE(x) us_endian((x) + 0)
|
||||
#define BFSIZE(x) ul_endian((x) + 2)
|
||||
#define BFOFFBITS(x) ul_endian((x) + 10)
|
||||
#define BISIZE(x) ul_endian((x) + 14)
|
||||
#define BIWIDTH(x) l_endian ((x) + 18)
|
||||
#define BIHEIGHT(x) l_endian ((x) + 22)
|
||||
#define BITCOUNT(x) us_endian((x) + 28)
|
||||
#define BICOMP(x) ul_endian((x) + 30)
|
||||
#define IMAGESIZE(x) ul_endian((x) + 34)
|
||||
#define BICLRUSED(x) ul_endian((x) + 46)
|
||||
#define BICLRIMP(x) ul_endian((x) + 50)
|
||||
#define BIPALETTE(x) ((x) + 54)
|
||||
|
||||
// Type ID
|
||||
#define BM "BM" // Windows 3.1x, 95, NT, ...
|
||||
#define BA "BA" // OS/2 Bitmap Array
|
||||
#define CI "CI" // OS/2 Color Icon
|
||||
#define CP "CP" // OS/2 Color Pointer
|
||||
#define IC "IC" // OS/2 Icon
|
||||
#define PT "PT" // OS/2 Pointer
|
||||
|
||||
// Possible values for the header size
|
||||
#define WinHSize 0x28
|
||||
#define OS21xHSize 0x0C
|
||||
#define OS22xHSize 0xF0
|
||||
|
||||
// Possible values for the BPP setting
|
||||
#define Mono 1 // Monochrome bitmap
|
||||
#define _16Color 4 // 16 color bitmap
|
||||
#define _256Color 8 // 256 color bitmap
|
||||
#define HIGHCOLOR 16 // 16bit (high color) bitmap
|
||||
#define TRUECOLOR24 24 // 24bit (true color) bitmap
|
||||
#define TRUECOLOR32 32 // 32bit (true color) bitmap
|
||||
|
||||
// Compression Types
|
||||
#ifndef BI_RGB
|
||||
#define BI_RGB 0 // none
|
||||
#define BI_RLE8 1 // RLE 8-bit / pixel
|
||||
#define BI_RLE4 2 // RLE 4-bit / pixel
|
||||
#define BI_BITFIELDS 3 // Bitfields
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void CImageBmpFile::mfLoadWindowsBitmap (byte* iBuffer, long iSize)
|
||||
{
|
||||
mfSet_dimensions (BIWIDTH(iBuffer), BIHEIGHT(iBuffer));
|
||||
const int bmp_size = m_Width * m_Height;
|
||||
m_eFormat = eIF_Bmp;
|
||||
|
||||
byte *iPtr = iBuffer + BFOFFBITS(iBuffer);
|
||||
|
||||
// The last scanline in BMP corresponds to the top line in the image
|
||||
int buffer_y = m_Width * (m_Height - 1);
|
||||
bool blip = false;
|
||||
|
||||
if (BITCOUNT(iBuffer) == _256Color && BICLRUSED(iBuffer))
|
||||
{
|
||||
mfSet_ImageSize(m_Width * m_Height);
|
||||
byte *buffer = mfGet_image();
|
||||
m_pPal = new SRGBPixel [256];
|
||||
SRGBPixel *pwork = m_pPal;
|
||||
byte *inpal = BIPALETTE(iBuffer);
|
||||
mfSet_bps(8);
|
||||
|
||||
for (int color=0; color<256; color++, pwork++)
|
||||
{
|
||||
// Whacky BMP palette is in BGR order.
|
||||
pwork->blue = *inpal++;
|
||||
pwork->green = *inpal++;
|
||||
pwork->red = *inpal++;
|
||||
pwork->alpha = 255;
|
||||
inpal++; // Skip unused byte.
|
||||
}
|
||||
|
||||
if (BICOMP(iBuffer) == BI_RGB)
|
||||
{
|
||||
// Read the pixels from "top" to "bottom"
|
||||
while (iPtr < iBuffer + iSize && buffer_y >= 0)
|
||||
{
|
||||
memcpy (buffer + buffer_y, iPtr, m_Width);
|
||||
iPtr += m_Width;
|
||||
buffer_y -= m_Width;
|
||||
} /* endwhile */
|
||||
}
|
||||
else
|
||||
if (BICOMP(iBuffer) == BI_RLE8)
|
||||
{
|
||||
// Decompress pixel data
|
||||
byte rl, rl1, i; // runlength
|
||||
byte clridx, clridx1; // colorindex
|
||||
int buffer_x = 0;
|
||||
while (iPtr < iBuffer + iSize && buffer_y >= 0)
|
||||
{
|
||||
rl = rl1 = *iPtr++;
|
||||
clridx = clridx1 = *iPtr++;
|
||||
if (rl == 0)
|
||||
if (clridx == 0)
|
||||
{
|
||||
// new scanline
|
||||
if (!blip)
|
||||
{
|
||||
// if we didnt already jumped to the new line, do it now
|
||||
buffer_x = 0;
|
||||
buffer_y -= m_Width;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
if (clridx == 1)
|
||||
// end of bitmap
|
||||
break;
|
||||
else
|
||||
if (clridx == 2)
|
||||
{
|
||||
// next 2 bytes mean column- and scanline- offset
|
||||
buffer_x += *iPtr++;
|
||||
buffer_y -= (m_Width * (*iPtr++));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
if (clridx > 2)
|
||||
rl1 = clridx;
|
||||
|
||||
for ( i = 0; i < rl1; i++ )
|
||||
{
|
||||
if (!rl)
|
||||
clridx1 = *iPtr++;
|
||||
buffer [buffer_y + buffer_x] = clridx1;
|
||||
|
||||
if (++buffer_x >= m_Width)
|
||||
{
|
||||
buffer_x = 0;
|
||||
buffer_y -= m_Width;
|
||||
blip = true;
|
||||
}
|
||||
else
|
||||
blip = false;
|
||||
}
|
||||
// pad in case rl == 0 and clridx in [3..255]
|
||||
if (rl == 0 && (clridx & 0x01))
|
||||
iPtr++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (!BICLRUSED(iBuffer) && BITCOUNT(iBuffer) == TRUECOLOR24)
|
||||
{
|
||||
mfSet_ImageSize(m_Width * m_Height * 4);
|
||||
mfSet_bps (24);
|
||||
SRGBPixel *buffer = (SRGBPixel *)mfGet_image();
|
||||
|
||||
while (iPtr < iBuffer + iSize && buffer_y >= 0)
|
||||
{
|
||||
SRGBPixel *d = buffer + buffer_y;
|
||||
for (int x = m_Width; x; x--)
|
||||
{
|
||||
d->blue = *iPtr++;
|
||||
d->green = *iPtr++;
|
||||
d->red = *iPtr++;
|
||||
d->alpha = 255;
|
||||
d++;
|
||||
} /* endfor */
|
||||
|
||||
buffer_y -= m_Width;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (!BICLRUSED(iBuffer) && BITCOUNT(iBuffer) == TRUECOLOR32)
|
||||
{
|
||||
mfSet_ImageSize(m_Width * m_Height * 4);
|
||||
mfSet_bps (32);
|
||||
SRGBPixel *buffer = (SRGBPixel *)mfGet_image();
|
||||
|
||||
while (iPtr < iBuffer + iSize && buffer_y >= 0)
|
||||
{
|
||||
SRGBPixel *d = buffer + buffer_y;
|
||||
for (int x = m_Width; x; x--)
|
||||
{
|
||||
d->blue = *iPtr++;
|
||||
d->green = *iPtr++;
|
||||
d->red = *iPtr++;
|
||||
d->alpha = *iPtr++;
|
||||
d++;
|
||||
} /* endfor */
|
||||
|
||||
buffer_y -= m_Width;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mfSet_error (eIFE_BadFormat, "Unknown BMP image format");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CImageBmpFile::CImageBmpFile (byte* ptr, long filesize) : CImageFile ()
|
||||
{
|
||||
if ((memcmp (ptr, BM, 2) == 0) && BISIZE(ptr) == WinHSize)
|
||||
mfLoadWindowsBitmap (ptr, filesize);
|
||||
else
|
||||
mfSet_error (eIFE_BadFormat, "Not a Windows BMP file");
|
||||
return;
|
||||
}
|
||||
|
||||
CImageBmpFile::~CImageBmpFile ()
|
||||
{
|
||||
}
|
||||
26
RenderDll/Common/Textures/Image/BmpImage.h
Normal file
26
RenderDll/Common/Textures/Image/BmpImage.h
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
#ifndef BMPIMAGE_H
|
||||
#define BMPIMAGE_H
|
||||
|
||||
/**
|
||||
* An ImageFile subclass for reading BMP files.
|
||||
*/
|
||||
class CImageBmpFile : public CImageFile
|
||||
{
|
||||
///
|
||||
friend class CImageFile; // For constructor
|
||||
|
||||
private:
|
||||
/// Read the BMP file from the buffer.
|
||||
CImageBmpFile (byte* buf, long size);
|
||||
void mfLoadWindowsBitmap (byte* ptr, long filesize);
|
||||
|
||||
public:
|
||||
///
|
||||
virtual ~CImageBmpFile ();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
186
RenderDll/Common/Textures/Image/CImage.cpp
Normal file
186
RenderDll/Common/Textures/Image/CImage.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
/*=============================================================================
|
||||
CImage.cpp : Common Image class implementation.
|
||||
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
||||
|
||||
Revision history:
|
||||
* Created by Khonich Andrey
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "RenderPCH.h"
|
||||
|
||||
|
||||
#include "PcxImage.h"
|
||||
#include "DDSImage.h"
|
||||
#include "BmpImage.h"
|
||||
#include "TgaImage.h"
|
||||
#include "JpgImage.h"
|
||||
|
||||
#ifdef PS2
|
||||
#include "XtfImage.h"
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
EImFileError CImageFile::m_eError = eIFE_OK;
|
||||
char CImageFile::m_Error_detail[256];
|
||||
char CImageFile::m_CurFileName[128];
|
||||
|
||||
CImageFile::CImageFile ()
|
||||
{
|
||||
m_pByteImage = NULL;
|
||||
m_pPal = NULL;
|
||||
m_eError = eIFE_OK;
|
||||
m_Error_detail[0] = 0;
|
||||
m_eFormat = eIF_Unknown;
|
||||
m_NumMips = 0;
|
||||
m_Flags = 0;
|
||||
m_ImgSize = 0;
|
||||
m_Depth = 1;
|
||||
}
|
||||
|
||||
CImageFile::~CImageFile ()
|
||||
{
|
||||
SAFE_DELETE_ARRAY(m_pByteImage);
|
||||
SAFE_DELETE_ARRAY(m_pPal)
|
||||
}
|
||||
|
||||
void CImageFile::mfSet_dimensions (int w, int h)
|
||||
{
|
||||
m_Width = w;
|
||||
m_Height = h;
|
||||
}
|
||||
|
||||
void CImageFile::mfSet_error (EImFileError error, char* detail)
|
||||
{
|
||||
CImageFile::m_eError = error;
|
||||
if (detail)
|
||||
strcpy (m_Error_detail, detail);
|
||||
m_Error_detail[0] = 0;
|
||||
}
|
||||
|
||||
void CImageFile::mfWrite_error (char* extra)
|
||||
{
|
||||
if (m_eError == eIFE_OK)
|
||||
return;
|
||||
char buf[1000];
|
||||
int idx = 0;
|
||||
if (extra)
|
||||
idx += sprintf (buf+idx, "'%s': ", extra);
|
||||
switch (m_eError)
|
||||
{
|
||||
case eIFE_OK:
|
||||
return;
|
||||
|
||||
case eIFE_IOerror:
|
||||
idx += sprintf (buf+idx, "IO error");
|
||||
break;
|
||||
|
||||
case eIFE_OutOfMemory:
|
||||
idx += sprintf (buf+idx, "Out of memory");
|
||||
break;
|
||||
|
||||
case eIFE_BadFormat:
|
||||
idx += sprintf (buf+idx, "Bad format");
|
||||
break;
|
||||
}
|
||||
if (m_Error_detail[0])
|
||||
sprintf (buf+idx, " (%s)!\n", m_Error_detail);
|
||||
else
|
||||
sprintf (buf+idx, "!\n");
|
||||
iConsole->Exit ("%s", buf);
|
||||
}
|
||||
|
||||
float gFOpenTime;
|
||||
int nRejectFOpen;
|
||||
int nAcceptFOpen;
|
||||
|
||||
CImageFile* CImageFile::mfLoad_file (char* szFileName)
|
||||
{
|
||||
double dTime0 = 0;
|
||||
ticks(dTime0);
|
||||
|
||||
FILE* pRawFile = iSystem->GetIPak()->FOpen (szFileName, "rb");
|
||||
|
||||
unticks(dTime0);
|
||||
gFOpenTime += (float)(dTime0*1000.0*g_SecondsPerCycle);
|
||||
|
||||
if (!pRawFile)
|
||||
{
|
||||
nRejectFOpen++;
|
||||
return NULL;
|
||||
}
|
||||
nAcceptFOpen++;
|
||||
|
||||
strcpy(m_CurFileName, szFileName);
|
||||
strlwr(m_CurFileName);
|
||||
CImageFile* pImageFile = mfLoad_file (pRawFile);
|
||||
if (pImageFile)
|
||||
{
|
||||
strcpy(pImageFile->m_FileName, m_CurFileName);
|
||||
iSystem->GetIPak()->FClose (pRawFile);
|
||||
}
|
||||
else
|
||||
iSystem->GetILog()->LogToFile("\002Warning: Cannot load texture %s, pImageFile format is invalid", szFileName);
|
||||
return pImageFile;
|
||||
}
|
||||
|
||||
CImageFile* CImageFile::mfLoad_file (FILE* fp)
|
||||
{
|
||||
iSystem->GetIPak()->FSeek (fp, 0, SEEK_END);
|
||||
long size = iSystem->GetIPak()->FTell (fp);
|
||||
iSystem->GetIPak()->FSeek (fp, 0, SEEK_SET);
|
||||
CHK (byte* buf = new byte [size+1]);
|
||||
iSystem->GetIPak()->FRead (buf, 1, size + 1, fp);
|
||||
CImageFile* file = mfLoad_file (buf, size);
|
||||
CHK (delete [] buf);
|
||||
return file;
|
||||
}
|
||||
|
||||
CImageFile* CImageFile::mfLoad_file (byte* buf, long size)
|
||||
{
|
||||
CImageFile* file = NULL;
|
||||
CImageFile::m_eError = eIFE_OK;
|
||||
|
||||
// Catch NULL pointers (for example, when ZIP file is corrupt)
|
||||
assert (buf);
|
||||
|
||||
const char *ext = GetExtension(m_CurFileName);
|
||||
|
||||
#ifdef PS2
|
||||
// Try XTF first
|
||||
if (!strcmp(ext, ".xtf"))
|
||||
CHK (file = (CImageFile *)new CImageXtfFile (buf, (int)size));
|
||||
#endif
|
||||
|
||||
// Try DDS first
|
||||
if (!strcmp(ext, ".dds") || !strcmp(ext, ".ddn") || !strcmp(ext, ".ddp") || !strcmp(ext, ".ddt"))
|
||||
CHK (file = (CImageFile *)new CImageDDSFile (buf, size));
|
||||
|
||||
// If failed, try BMP
|
||||
if (!strcmp(ext, ".bmp"))
|
||||
CHK (file = (CImageFile *)new CImageBmpFile (buf, size));
|
||||
|
||||
// If failed, try PCX
|
||||
if (!strcmp(ext, ".pcx"))
|
||||
CHK (file = (CImageFile *)new CImagePcxFile (buf, size));
|
||||
#if !defined(NULL_RENDERER)
|
||||
// Try JPG next
|
||||
if (!strcmp(ext, ".jpg") || !strcmp(ext, ".jpeg"))
|
||||
CHK (file = (CImageFile *)new CImageJpgFile (buf, size));
|
||||
#endif
|
||||
// As a last resort, try TGA
|
||||
if (!strcmp(ext, ".tga"))
|
||||
CHK (file = (CImageFile *)new CImageTgaFile (buf, size));
|
||||
|
||||
if (file && (CImageFile::mfGet_error () != eIFE_OK))
|
||||
{
|
||||
CHK (delete file);
|
||||
file = NULL;
|
||||
} /* endif */
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
203
RenderDll/Common/Textures/Image/CImage.h
Normal file
203
RenderDll/Common/Textures/Image/CImage.h
Normal file
@@ -0,0 +1,203 @@
|
||||
|
||||
#ifndef CIMAGE_H
|
||||
#define CIMAGE_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define CHK(x) x
|
||||
|
||||
#define SH_LITTLE_ENDIAN
|
||||
|
||||
// The mask for extracting just R/G/B from an ulong or SRGBPixel
|
||||
#ifdef SH_BIG_ENDIAN
|
||||
# define RGB_MASK 0xffffff00
|
||||
#else
|
||||
# define RGB_MASK 0x00ffffff
|
||||
#endif
|
||||
|
||||
/**
|
||||
* An RGB pixel.
|
||||
*/
|
||||
struct SRGBPixel
|
||||
{
|
||||
uchar blue, green, red, alpha;
|
||||
SRGBPixel () /* : red(0), green(0), blue(0), alpha(255) {} */
|
||||
{ *(unsigned long *)this = (unsigned long)~RGB_MASK; }
|
||||
SRGBPixel (int r, int g, int b) : red (r), green (g), blue (b), alpha (255) {}
|
||||
bool eq (const SRGBPixel& p) const { return ((*(unsigned long *)this) & RGB_MASK) == ((*(unsigned long *)&p) & RGB_MASK); }
|
||||
/// Get the pixel intensity
|
||||
int Intensity () { return (red + green + blue) / 3; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An RGB palette entry with statistics information.
|
||||
*/
|
||||
struct SRGBPalEntry
|
||||
{
|
||||
uchar red, green, blue;
|
||||
long count;
|
||||
};
|
||||
|
||||
/**
|
||||
* Possible errors for CImageFile::mfGet_error.
|
||||
*/
|
||||
enum EImFileError { eIFE_OK = 0, eIFE_IOerror, eIFE_OutOfMemory, eIFE_BadFormat };
|
||||
|
||||
/**
|
||||
* Eye sensivity to different color components, from NTSC grayscale equation.
|
||||
* The coefficients are multiplied by 100 and rounded towards nearest integer,
|
||||
* to facilitate integer math. The squared coefficients are also multiplied
|
||||
* by 100 and rounded to nearest integer (thus 173 == 1.73, 242 == 2.42 etc).
|
||||
*/
|
||||
/// Red component sensivity
|
||||
#define R_COEF 173
|
||||
/// Green component sensivity
|
||||
#define G_COEF 242
|
||||
/// Blue component sensivity
|
||||
#define B_COEF 107
|
||||
/// Eye sensivity to different color components, squared
|
||||
/// Red component sensivity, squared
|
||||
#define R_COEF_SQ 299
|
||||
/// Green component sensivity, squared
|
||||
#define G_COEF_SQ 587
|
||||
/// Blue component sensivity, squared
|
||||
#define B_COEF_SQ 114
|
||||
|
||||
#define FIM_NORMALMAP 1
|
||||
#define FIM_DSDT 2
|
||||
|
||||
/**
|
||||
* An abstract class implementing an image loader. For every image
|
||||
* type supported, a subclass should be created for loading that image
|
||||
* type and ImageFile::load_file should be extended to recognize that
|
||||
* image format.
|
||||
*/
|
||||
class CImageFile
|
||||
{
|
||||
friend class CImageDDSFile;
|
||||
friend class CImageCCTFile;
|
||||
friend class CImageBmpFile;
|
||||
friend class CImagePcxFile;
|
||||
friend class CImageJpgFile;
|
||||
friend class CTexMan;
|
||||
|
||||
private:
|
||||
/// Width of image.
|
||||
int m_Width;
|
||||
/// Height of image.
|
||||
int m_Height;
|
||||
/// Depth of image.
|
||||
int m_Depth;
|
||||
|
||||
int m_Bps;
|
||||
int m_ImgSize;
|
||||
|
||||
int m_NumMips;
|
||||
int m_Flags;
|
||||
|
||||
/// The image data.
|
||||
union
|
||||
{
|
||||
SRGBPixel* m_pPixImage;
|
||||
byte* m_pByteImage;
|
||||
};
|
||||
|
||||
/// Last error code.
|
||||
static EImFileError m_eError;
|
||||
/// Last error detail information.
|
||||
static char m_Error_detail[256];
|
||||
|
||||
protected:
|
||||
|
||||
EImFormat m_eFormat;
|
||||
SRGBPixel* m_pPal;
|
||||
|
||||
/**
|
||||
* Constructor is private since this object can only be
|
||||
* created by load_file.
|
||||
*/
|
||||
CImageFile ();
|
||||
|
||||
/**
|
||||
* Before failing, a ImageFile subclass should call set_error to
|
||||
* set the code and detail.
|
||||
*/
|
||||
static void mfSet_error (EImFileError error, char* detail = NULL);
|
||||
|
||||
/**
|
||||
* Set the width and height. This will also allocate the 'image'
|
||||
* buffer to hold the bitmap.
|
||||
*/
|
||||
void mfSet_dimensions (int w, int h);
|
||||
|
||||
public:
|
||||
static char m_CurFileName[128];
|
||||
char m_FileName[128];
|
||||
|
||||
///
|
||||
virtual ~CImageFile ();
|
||||
|
||||
///
|
||||
int mfGet_width () { return m_Width; }
|
||||
///
|
||||
int mfGet_height () { return m_Height; }
|
||||
///
|
||||
int mfGet_depth () { return m_Depth; }
|
||||
///
|
||||
byte* mfGet_image ()
|
||||
{
|
||||
if (!m_pByteImage)
|
||||
{
|
||||
if (m_ImgSize)
|
||||
m_pByteImage = new byte [m_ImgSize];
|
||||
}
|
||||
return m_pByteImage;
|
||||
}
|
||||
///
|
||||
SRGBPixel* mfGet_palette () { return m_pPal; }
|
||||
|
||||
int mfGet_bps () { return m_Bps; }
|
||||
void mfSet_bps(int b) { m_Bps = b; }
|
||||
void mfSet_ImageSize (int Size) {m_ImgSize = Size;}
|
||||
int mfGet_ImageSize () {return m_ImgSize;}
|
||||
|
||||
EImFormat mfGetFormat() { return m_eFormat; }
|
||||
|
||||
void mfSet_numMips (int num) { m_NumMips = num; }
|
||||
int mfGet_numMips (void) { return m_NumMips; }
|
||||
void mfSet_Flags (int Flags) { m_Flags |= Flags; }
|
||||
int mfGet_Flags () { return m_Flags; }
|
||||
|
||||
///
|
||||
static EImFileError mfGet_error () { return m_eError; }
|
||||
///
|
||||
static char* mfGet_error_detail () { return m_Error_detail ? m_Error_detail : (char *)""; }
|
||||
/// Write a message describing the error on screen.
|
||||
static void mfWrite_error (char* extra);
|
||||
|
||||
/**
|
||||
* Load the file given the filename.
|
||||
* This routine will open the file and call load_file (FILE*).
|
||||
*/
|
||||
static CImageFile* mfLoad_file (char* filename);
|
||||
|
||||
/**
|
||||
* Load the file given a file pointer.
|
||||
* This routine will read from the file pointer and call load_file (UByte*, long).
|
||||
*/
|
||||
static CImageFile* mfLoad_file (FILE* fp);
|
||||
|
||||
/**
|
||||
* Load the file from a buffer.
|
||||
* This routine will try to recognize the image file type and then
|
||||
* created an appropriate ImageFile subclass.
|
||||
*/
|
||||
static CImageFile* mfLoad_file (byte* buf, long size);
|
||||
};
|
||||
|
||||
#include "Quantize.h"
|
||||
#include "Inv_cmap.h"
|
||||
|
||||
#endif
|
||||
|
||||
339
RenderDll/Common/Textures/Image/DDSImage.cpp
Normal file
339
RenderDll/Common/Textures/Image/DDSImage.cpp
Normal file
@@ -0,0 +1,339 @@
|
||||
/*=============================================================================
|
||||
DDSImage.cpp : DDS image file format implementation.
|
||||
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
||||
|
||||
Revision history:
|
||||
* Created by Khonich Andrey
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "RenderPCH.h"
|
||||
#include "CImage.h"
|
||||
#include "DDSImage.h"
|
||||
|
||||
/* needed for DirectX's DDSURFACEDESC2 structure definition */
|
||||
#if !defined(_XBOX) && !defined(PS2) && !defined(LINUX)
|
||||
#include <ddraw.h>
|
||||
#else
|
||||
#define FOURCC_DXT1 (MAKEFOURCC('D','X','T','1'))
|
||||
#define FOURCC_DXT2 (MAKEFOURCC('D','X','T','2'))
|
||||
#define FOURCC_DXT3 (MAKEFOURCC('D','X','T','3'))
|
||||
#define FOURCC_DXT4 (MAKEFOURCC('D','X','T','4'))
|
||||
#define FOURCC_DXT5 (MAKEFOURCC('D','X','T','5'))
|
||||
#endif
|
||||
|
||||
#include "dds.h"
|
||||
#if defined(LINUX)
|
||||
#include "ILog.h"
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static int sDDSSize(int sx, int sy, EImFormat eF )
|
||||
{
|
||||
switch (eF)
|
||||
{
|
||||
case eIF_DXT1:
|
||||
case eIF_DXT3:
|
||||
case eIF_DXT5:
|
||||
{
|
||||
int blockSize = (eF == eIF_DXT1) ? 8 : 16;
|
||||
return ((sx+3)/4)*((sy+3)/4)*blockSize;
|
||||
}
|
||||
break;
|
||||
case eIF_DDS_LUMINANCE:
|
||||
return sx * sy;
|
||||
break;
|
||||
case eIF_DDS_RGB8:
|
||||
case eIF_DDS_SIGNED_RGB8:
|
||||
return sx*sy*3;
|
||||
break;
|
||||
case eIF_DDS_RGBA8:
|
||||
return sx*sy*4;
|
||||
break;
|
||||
case eIF_DDS_RGBA4:
|
||||
return sx*sy*2;
|
||||
break;
|
||||
case eIF_DDS_DSDT:
|
||||
return sx*sy*3;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CImageDDSFile::mfSizeWithMips(int filesize, int sx, int sy, int nMips)
|
||||
{
|
||||
int nSize = 0;
|
||||
for (int i=0; i<nMips; i++)
|
||||
{
|
||||
assert(sx || sy);
|
||||
if (!sx)
|
||||
sx = 1;
|
||||
if (!sy)
|
||||
sy = 1;
|
||||
nSize += sDDSSize(sx, sy, m_eFormat);
|
||||
sx >>= 1;
|
||||
sy >>= 1;
|
||||
}
|
||||
assert((int)(filesize-sizeof(DDS_HEADER)-4) >= nSize);
|
||||
return nSize;
|
||||
}
|
||||
|
||||
static FILE *sFILELog;
|
||||
|
||||
CImageDDSFile::CImageDDSFile (byte* ptr, long filesize) : CImageFile ()
|
||||
{
|
||||
int sx, sy;
|
||||
int numMips;
|
||||
|
||||
DWORD dwMagic;
|
||||
DDS_HEADER *ddsh;
|
||||
|
||||
dwMagic = *(DWORD *)ptr;
|
||||
ptr += sizeof(DWORD);
|
||||
if (dwMagic != MAKEFOURCC('D','D','S',' '))
|
||||
{
|
||||
mfSet_error (eIFE_BadFormat, "Not a DDS file");
|
||||
return;
|
||||
}
|
||||
ddsh = (DDS_HEADER *)ptr;
|
||||
ptr += sizeof(DDS_HEADER);
|
||||
if (ddsh->dwSize != sizeof(DDS_HEADER))
|
||||
{
|
||||
mfSet_error (eIFE_BadFormat, "Unknown DDS file header");
|
||||
return;
|
||||
}
|
||||
sx = ddsh->dwWidth;
|
||||
sy = ddsh->dwHeight;
|
||||
numMips = ddsh->dwMipMapCount;
|
||||
if (numMips == 0)
|
||||
numMips = 1;
|
||||
|
||||
if (ddsh->ddspf.dwFourCC == FOURCC_DXT1)
|
||||
m_eFormat = eIF_DXT1;
|
||||
else
|
||||
if (ddsh->ddspf.dwFourCC == FOURCC_DXT3)
|
||||
m_eFormat = eIF_DXT3;
|
||||
else
|
||||
if (ddsh->ddspf.dwFourCC == FOURCC_DXT5)
|
||||
m_eFormat = eIF_DXT5;
|
||||
else
|
||||
if (ddsh->ddspf.dwFlags == DDS_RGBA && ddsh->ddspf.dwRGBBitCount == 32 && ddsh->ddspf.dwABitMask == 0xff000000)
|
||||
m_eFormat = eIF_DDS_RGBA8;
|
||||
else
|
||||
if (ddsh->ddspf.dwFlags == DDS_RGBA && ddsh->ddspf.dwRGBBitCount == 16)
|
||||
m_eFormat = eIF_DDS_RGBA4;
|
||||
else
|
||||
if (ddsh->ddspf.dwFlags == DDS_RGB && ddsh->ddspf.dwRGBBitCount == 24)
|
||||
m_eFormat = eIF_DDS_RGB8;
|
||||
else
|
||||
if (ddsh->ddspf.dwFlags == DDS_RGB && ddsh->ddspf.dwRGBBitCount == 32)
|
||||
m_eFormat = eIF_DDS_RGBA8;
|
||||
else
|
||||
if (ddsh->ddspf.dwFlags == DDS_LUMINANCE && ddsh->ddspf.dwRGBBitCount == 8)
|
||||
m_eFormat = eIF_DDS_LUMINANCE;
|
||||
else
|
||||
{
|
||||
mfSet_error (eIFE_BadFormat, "Unknown DDS image format");
|
||||
return;
|
||||
}
|
||||
mfSet_numMips(numMips);
|
||||
const char *ext = GetExtension(m_CurFileName);
|
||||
if ((ddsh->dwReserved1[0] & DDS_RESF1_NORMALMAP) ||
|
||||
!stricmp(ext, ".ddn") || !stricmp(ext, ".ddp") ||
|
||||
(strlen(m_CurFileName)>4 && (strstr(m_CurFileName, "_ddn") || strstr(m_CurFileName, "_ddp"))))
|
||||
mfSet_Flags(FIM_NORMALMAP);
|
||||
else
|
||||
if ((ddsh->dwReserved1[0] & DDS_RESF1_DSDT) ||
|
||||
!stricmp(ext, ".ddt") ||
|
||||
(strlen(m_CurFileName)>4 && strstr(m_CurFileName, "_ddt")))
|
||||
{
|
||||
mfSet_Flags(FIM_DSDT);
|
||||
m_eFormat = eIF_DDS_DSDT;
|
||||
}
|
||||
int nDepth = ddsh->dwDepth;
|
||||
if (nDepth <= 0)
|
||||
nDepth = 1;
|
||||
m_Width = sx;
|
||||
m_Height = sy;
|
||||
m_Depth = nDepth;
|
||||
|
||||
SAFE_DELETE_ARRAY(m_pByteImage);
|
||||
int size = filesize - sizeof(DDS_HEADER) - 4;
|
||||
if (m_eFormat == eIF_DDS_DSDT || m_eFormat == eIF_DDS_RGB8)
|
||||
{
|
||||
size = mfSizeWithMips(filesize, sx, sy, numMips);
|
||||
size = size/3*4*nDepth;
|
||||
}
|
||||
mfSet_ImageSize(size);
|
||||
mfGet_image();
|
||||
|
||||
int nOffsSrc = 0;
|
||||
int nOffsDst = 0;
|
||||
|
||||
for (int dpt=0; dpt<nDepth; dpt++)
|
||||
{
|
||||
if (m_eFormat == eIF_DXT1 || m_eFormat == eIF_DXT3 || m_eFormat == eIF_DXT5)
|
||||
{
|
||||
int size = mfSizeWithMips(filesize, sx, sy, numMips);
|
||||
cryMemcpy(&m_pByteImage[nOffsDst], &ptr[nOffsSrc], size);
|
||||
nOffsSrc += size;
|
||||
nOffsDst += size;
|
||||
}
|
||||
else
|
||||
if (m_eFormat == eIF_DDS_LUMINANCE)
|
||||
{
|
||||
int size = mfSizeWithMips(filesize, sx, sy, numMips);
|
||||
cryMemcpy(&m_pByteImage[nOffsDst], &ptr[nOffsSrc], size);
|
||||
nOffsSrc += size;
|
||||
nOffsDst += size;
|
||||
}
|
||||
else
|
||||
if (m_eFormat == eIF_DDS_RGBA8 || m_eFormat == eIF_DDS_RGBA4)
|
||||
{
|
||||
int size = mfSizeWithMips(filesize, sx, sy, numMips);
|
||||
cryMemcpy(&m_pByteImage[nOffsDst], &ptr[nOffsSrc], size);
|
||||
nOffsSrc += size;
|
||||
nOffsDst += size;
|
||||
}
|
||||
else
|
||||
if (m_eFormat == eIF_DDS_RGB8)
|
||||
{
|
||||
int size = mfSizeWithMips(filesize, sx, sy, numMips);
|
||||
int n = size/3;
|
||||
int sizeDst = n * 4;
|
||||
for (int i=0; i<n; i++)
|
||||
{
|
||||
m_pByteImage[i*4+nOffsDst+0] = ptr[i*3+nOffsSrc+0];
|
||||
m_pByteImage[i*4+nOffsDst+1] = ptr[i*3+nOffsSrc+1];
|
||||
m_pByteImage[i*4+nOffsDst+2] = ptr[i*3+nOffsSrc+2];
|
||||
m_pByteImage[i*4+nOffsDst+3] = 255;
|
||||
}
|
||||
nOffsSrc += size;
|
||||
nOffsDst += sizeDst;
|
||||
if (CRenderer::CV_r_logusedtextures == 10 && (m_Flags & FIM_NORMALMAP))
|
||||
{
|
||||
if (!sFILELog)
|
||||
sFILELog = fopen("LogBumpTexturesNoAlpha.txt", "w");
|
||||
if (sFILELog)
|
||||
{
|
||||
fprintf(sFILELog, "%s\n", m_CurFileName);
|
||||
fflush(sFILELog);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (m_eFormat == eIF_DDS_DSDT)
|
||||
{
|
||||
int size = mfSizeWithMips(filesize, sx, sy, numMips);
|
||||
int n = size/3;
|
||||
int sizeDst = n * 4;
|
||||
for (int i=0; i<n; i++)
|
||||
{
|
||||
m_pByteImage[i*4+nOffsDst+0] = ptr[i*3+nOffsSrc+2];
|
||||
m_pByteImage[i*4+nOffsDst+1] = ptr[i*3+nOffsSrc+1];
|
||||
m_pByteImage[i*4+nOffsDst+2] = ptr[i*3+nOffsSrc+0];
|
||||
m_pByteImage[i*4+nOffsDst+3] = 255;
|
||||
}
|
||||
nOffsSrc += size;
|
||||
nOffsDst += sizeDst;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CImageDDSFile::~CImageDDSFile ()
|
||||
{
|
||||
}
|
||||
|
||||
void WriteDDS(byte *dat, int wdt, int hgt, int Size, const char *name, EImFormat eF, int NumMips)
|
||||
{
|
||||
DWORD dwMagic;
|
||||
DDS_HEADER ddsh;
|
||||
memset(&ddsh, 0, sizeof(ddsh));
|
||||
|
||||
FILE *fp = fxopen(name, "wb");
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
dwMagic = MAKEFOURCC('D','D','S',' ');
|
||||
fwrite(&dwMagic, 1, sizeof(DWORD), fp);
|
||||
|
||||
ddsh.dwSize = sizeof(DDS_HEADER);
|
||||
ddsh.dwWidth = wdt;
|
||||
ddsh.dwHeight = hgt;
|
||||
ddsh.dwMipMapCount = NumMips;
|
||||
if (!NumMips)
|
||||
ddsh.dwMipMapCount = 1;
|
||||
ddsh.dwHeaderFlags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP;
|
||||
ddsh.dwSurfaceFlags = DDS_SURFACE_FLAGS_TEXTURE | DDS_SURFACE_FLAGS_MIPMAP;
|
||||
size_t len = strlen(name);
|
||||
if (len > 4)
|
||||
{
|
||||
if (!stricmp(&name[len-4], ".ddn"))
|
||||
ddsh.dwReserved1[0] = DDS_RESF1_NORMALMAP;
|
||||
else
|
||||
if (!stricmp(&name[len-4], ".ddt"))
|
||||
ddsh.dwReserved1[0] = DDS_RESF1_DSDT;
|
||||
}
|
||||
|
||||
switch (eF)
|
||||
{
|
||||
case eIF_DXT1:
|
||||
ddsh.ddspf = DDSPF_DXT1;
|
||||
break;
|
||||
case eIF_DXT3:
|
||||
ddsh.ddspf = DDSPF_DXT3;
|
||||
break;
|
||||
case eIF_DXT5:
|
||||
ddsh.ddspf = DDSPF_DXT5;
|
||||
break;
|
||||
case eIF_DDS_RGB8:
|
||||
case eIF_DDS_SIGNED_RGB8:
|
||||
case eIF_DDS_DSDT:
|
||||
ddsh.ddspf = DDSPF_R8G8B8;
|
||||
break;
|
||||
case eIF_DDS_RGBA8:
|
||||
ddsh.ddspf = DDSPF_A8R8G8B8;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
fwrite(&ddsh, 1, sizeof(ddsh), fp);
|
||||
|
||||
byte *data = NULL;
|
||||
|
||||
if (eF == eIF_DDS_RGB8 || eF == eIF_DDS_SIGNED_RGB8 || eF == eIF_DDS_DSDT)
|
||||
{
|
||||
data = new byte[Size];
|
||||
int n = Size / 3;
|
||||
for (int i=0; i<n; i++)
|
||||
{
|
||||
data[i*3+0] = dat[i*3+2];
|
||||
data[i*3+1] = dat[i*3+1];
|
||||
data[i*3+2] = dat[i*3+0];
|
||||
}
|
||||
fwrite(data, 1, Size, fp);
|
||||
}
|
||||
else
|
||||
if (eF == eIF_DDS_RGBA8)
|
||||
{
|
||||
data = new byte[Size];
|
||||
int n = Size / 4;
|
||||
for (int i=0; i<n; i++)
|
||||
{
|
||||
data[i*4+0] = dat[i*4+2];
|
||||
data[i*4+1] = dat[i*4+1];
|
||||
data[i*4+2] = dat[i*4+0];
|
||||
data[i*4+3] = dat[i*4+3];
|
||||
}
|
||||
}
|
||||
else
|
||||
fwrite(dat, 1, Size, fp);
|
||||
|
||||
SAFE_DELETE_ARRAY(data);
|
||||
|
||||
fclose (fp);
|
||||
}
|
||||
27
RenderDll/Common/Textures/Image/DDSImage.h
Normal file
27
RenderDll/Common/Textures/Image/DDSImage.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef DDSIMAGE_H
|
||||
#define DDSIMAGE_H
|
||||
|
||||
/**
|
||||
* An ImageFile subclass for reading DDS files.
|
||||
*/
|
||||
class CImageDDSFile : public CImageFile
|
||||
{
|
||||
///
|
||||
friend class CImageFile; // For constructor
|
||||
|
||||
private:
|
||||
|
||||
public:
|
||||
/// Read the DDS file from the buffer.
|
||||
CImageDDSFile (byte* buf, long size);
|
||||
int mfSizeWithMips(int filesize, int sx, int sy, int numMips);
|
||||
///
|
||||
virtual ~CImageDDSFile ();
|
||||
};
|
||||
|
||||
void WriteDDS(byte *dat, int wdt, int hgt, int Size, char *name, EImFormat eF, int NumMips);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
210
RenderDll/Common/Textures/Image/DXTCImage.h
Normal file
210
RenderDll/Common/Textures/Image/DXTCImage.h
Normal file
@@ -0,0 +1,210 @@
|
||||
/*********************************************************************NVMH2****
|
||||
File: Image_DXTC.h
|
||||
|
||||
Copyright (C) 1999, 2000 NVIDIA Corporation
|
||||
Copyright (C) 2002, Ubi Soft Milan
|
||||
Tiziano Sardone
|
||||
|
||||
|
||||
Comments:
|
||||
A class to load and decompress DXT textures to 32-bit raw image data format.
|
||||
.RAW output files can be loaded into photoshop by specifying the resolution
|
||||
and 4 color channels of 8-bit, interleaved.
|
||||
|
||||
A few approaches to block decompression are in place and a simple code timing
|
||||
function is called. Output of timing test is saved to a local .txt file.
|
||||
|
||||
TiZ: some modification to adapt the code to run under PS2.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
|
||||
#if !defined(AFX_IMAGE_DXTC_H__4B89D8D0_7857_11D4_9630_00A0C996DE3D__INCLUDED_)
|
||||
#define AFX_IMAGE_DXTC_H__4B89D8D0_7857_11D4_9630_00A0C996DE3D__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#ifdef WIN32
|
||||
#include <d3d.h>
|
||||
#endif
|
||||
|
||||
#ifdef PS2
|
||||
/////////////////////////////////////
|
||||
// should be in ddraw.h
|
||||
|
||||
#ifndef MAKEFOURCC
|
||||
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
|
||||
((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
|
||||
((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
|
||||
#endif //defined(MAKEFOURCC)
|
||||
|
||||
#endif
|
||||
|
||||
struct TimingInfo; // defined in Image_DXTC.cpp
|
||||
|
||||
#define byte unsigned char
|
||||
#define BYTE unsigned char
|
||||
//#ifndef PS2
|
||||
#define WORD unsigned short
|
||||
#define DWORD unsigned int
|
||||
#define LONG unsigned int
|
||||
#define LPVOID void*
|
||||
#define VOID void
|
||||
#define CHAR char
|
||||
#define LARGE_INTEGER int
|
||||
//#endif
|
||||
|
||||
enum PixFormat
|
||||
{
|
||||
PF_ARGB,
|
||||
PF_DXT1,
|
||||
PF_DXT2,
|
||||
PF_DXT3,
|
||||
PF_DXT4,
|
||||
PF_DXT5,
|
||||
PF_UNKNOWN,
|
||||
};
|
||||
|
||||
#define COMPRESSED_S3TC_DXT1 PF_DXT1
|
||||
|
||||
typedef struct _DDSCAPS2 {
|
||||
DWORD dwCaps;
|
||||
DWORD dwCaps2;
|
||||
DWORD dwCaps3;
|
||||
DWORD dwCaps4;
|
||||
} DDSCAPS2, *LPDDSCAPS2;
|
||||
|
||||
typedef struct _DDPIXELFORMAT {
|
||||
DWORD dwSize;
|
||||
DWORD dwFlags;
|
||||
DWORD dwFourCC;
|
||||
union {
|
||||
DWORD dwRGBBitCount;
|
||||
DWORD dwYUVBitCount;
|
||||
DWORD dwZBufferBitDepth;
|
||||
DWORD dwAlphaBitDepth;
|
||||
DWORD dwLuminanceBitCount;
|
||||
DWORD dwBumpBitCount;
|
||||
DWORD dwPrivateFormatBitCount;
|
||||
} ;
|
||||
union {
|
||||
DWORD dwRBitMask;
|
||||
DWORD dwYBitMask;
|
||||
DWORD dwStencilBitDepth;
|
||||
DWORD dwLuminanceBitMask;
|
||||
DWORD dwBumpDuBitMask;
|
||||
DWORD dwOperations;
|
||||
} ;
|
||||
union {
|
||||
DWORD dwGBitMask;
|
||||
DWORD dwUBitMask;
|
||||
DWORD dwZBitMask;
|
||||
DWORD dwBumpDvBitMask;
|
||||
struct {
|
||||
WORD wFlipMSTypes;
|
||||
WORD wBltMSTypes;
|
||||
} MultiSampleCaps;
|
||||
} ;
|
||||
union {
|
||||
DWORD dwBBitMask;
|
||||
DWORD dwVBitMask;
|
||||
DWORD dwStencilBitMask;
|
||||
DWORD dwBumpLuminanceBitMask;
|
||||
} ;
|
||||
union {
|
||||
DWORD dwRGBAlphaBitMask;
|
||||
DWORD dwYUVAlphaBitMask;
|
||||
DWORD dwLuminanceAlphaBitMask;
|
||||
DWORD dwRGBZBitMask;
|
||||
DWORD dwYUVZBitMask;
|
||||
} ;
|
||||
} DDPIXELFORMAT, *LPDDPIXELFORMAT;
|
||||
|
||||
typedef struct _DDCOLORKEY{
|
||||
DWORD dwColorSpaceLowValue;
|
||||
DWORD dwColorSpaceHighValue;
|
||||
} DDCOLORKEY, *LPDDCOLORKEY;
|
||||
|
||||
typedef struct _DDSURFACEDESC2 {
|
||||
DWORD dwSize;
|
||||
DWORD dwFlags;
|
||||
DWORD dwHeight;
|
||||
DWORD dwWidth;
|
||||
union
|
||||
{
|
||||
LONG lPitch;
|
||||
DWORD dwLinearSize;
|
||||
} DUMMYUNIONNAMEN_1;
|
||||
DWORD dwBackBufferCount;
|
||||
union
|
||||
{
|
||||
DWORD dwMipMapCount;
|
||||
DWORD dwRefreshRate;
|
||||
} DUMMYUNIONNAMEN_2;
|
||||
DWORD dwAlphaBitDepth;
|
||||
DWORD dwReserved;
|
||||
LPVOID lpSurface;
|
||||
DDCOLORKEY ddckCKDestOverlay;
|
||||
DDCOLORKEY ddckCKDestBlt;
|
||||
DDCOLORKEY ddckCKSrcOverlay;
|
||||
DDCOLORKEY ddckCKSrcBlt;
|
||||
DDPIXELFORMAT ddpfPixelFormat;
|
||||
DDSCAPS2 ddsCaps;
|
||||
DWORD dwTextureStage;
|
||||
} DDSURFACEDESC2, *LPDDSURFACEDESC2;
|
||||
|
||||
|
||||
class Image_DXTC
|
||||
{
|
||||
public:
|
||||
unsigned char * m_pCompBytes; // compressed image bytes
|
||||
unsigned char * m_pDecompBytes;
|
||||
|
||||
int m_nCompSize;
|
||||
int m_nCompLineSz;
|
||||
|
||||
|
||||
char m_strFormat[256];
|
||||
PixFormat m_CompFormat;
|
||||
|
||||
DDSURFACEDESC2 m_DDSD; // read from dds file
|
||||
bool m_bMipTexture; // texture has mipmaps?
|
||||
|
||||
|
||||
int m_nWidth; // in pixels of uncompressed image
|
||||
int m_nHeight;
|
||||
|
||||
bool LoadFromFile( char * filename ); // true if success
|
||||
|
||||
VOID DecodePixelFormat( CHAR* strPixelFormat, DDPIXELFORMAT* pddpf );
|
||||
|
||||
void AllocateDecompBytes();
|
||||
|
||||
void Decompress();
|
||||
|
||||
void DecompressDXT1();
|
||||
void DecompressDXT2();
|
||||
void DecompressDXT3();
|
||||
void DecompressDXT4();
|
||||
void DecompressDXT5();
|
||||
|
||||
void SaveAsRaw8888(const char *name); // save decompressed bits
|
||||
void SaveAsRaw888(const char *name); // save decompressed bits
|
||||
|
||||
void RunTimingSession(); // run a few methods & time the code
|
||||
// must use dxt5 texture
|
||||
void Time_Decomp5_01( int ntimes, TimingInfo * info );
|
||||
void Time_Decomp5_02( int ntimes, TimingInfo * info );
|
||||
void Time_Decomp5_03( int ntimes, TimingInfo * info );
|
||||
void Time_Decomp5_04( int ntimes, TimingInfo * info );
|
||||
|
||||
|
||||
Image_DXTC();
|
||||
virtual ~Image_DXTC();
|
||||
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_IMAGE_DXTC_H__4B89D8D0_7857_11D4_9630_00A0C996DE3D__INCLUDED_)
|
||||
24
RenderDll/Common/Textures/Image/GifImage.h
Normal file
24
RenderDll/Common/Textures/Image/GifImage.h
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
#ifndef GIFIMAGE_H
|
||||
#define GIFIMAGE_H
|
||||
|
||||
/**
|
||||
* An ImageFile subclass for reading GIF files.
|
||||
*/
|
||||
class CImageGifFile : public CImageFile
|
||||
{
|
||||
///
|
||||
friend class CImageFile; // For constructor
|
||||
|
||||
private:
|
||||
/// Read the GIF file from the buffer.
|
||||
CImageGifFile (byte* buf, long size);
|
||||
|
||||
public:
|
||||
///
|
||||
virtual ~CImageGifFile ();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
143
RenderDll/Common/Textures/Image/Jmemsrc.c
Normal file
143
RenderDll/Common/Textures/Image/Jmemsrc.c
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
Copyright (C) 1998 by Tor Andersson and Jorrit Tyberghein
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* !!! not standard... written by Tor Andersson !!!
|
||||
* get data from memory buffer instead of from file
|
||||
* assumes that the entire file is in one large block of memory
|
||||
*
|
||||
*/
|
||||
|
||||
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
|
||||
#include "Jpeg6/jinclude.h"
|
||||
#include "Jpeg6/jpeglib.h"
|
||||
#include "Jpeg6/jerror.h"
|
||||
|
||||
|
||||
/* Expanded data source object for stdio input */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_source_mgr pub; /* public fields */
|
||||
|
||||
FILE * infile; /* source stream */
|
||||
JOCTET * buffer; /* start of buffer */
|
||||
boolean start_of_file; /* have we gotten any data yet? */
|
||||
} my_source_mgr;
|
||||
|
||||
typedef my_source_mgr * my_src_ptr;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize source --- called by jpeg_read_header
|
||||
* before any data is actually read.
|
||||
*/
|
||||
|
||||
static void
|
||||
init_source (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||
|
||||
/* We reset the empty-input-file flag for each image,
|
||||
* but we don't clear the input buffer.
|
||||
* This is correct behavior for reading a series of images from one source.
|
||||
*/
|
||||
src->start_of_file = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fill the input buffer --- called whenever buffer is emptied.
|
||||
* should never happen :)
|
||||
*/
|
||||
|
||||
static boolean
|
||||
fill_input_buffer (j_decompress_ptr cinfo)
|
||||
{
|
||||
/* no-op */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Skip data --- used to skip over a potentially large amount of
|
||||
* uninteresting data (such as an APPn marker).
|
||||
*/
|
||||
|
||||
static void
|
||||
skip_input_data (j_decompress_ptr cinfo, long num_bytes)
|
||||
{
|
||||
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||
|
||||
if (num_bytes > 0) {
|
||||
src->pub.next_input_byte += (size_t) num_bytes;
|
||||
src->pub.bytes_in_buffer -= (size_t) num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Terminate source --- called by jpeg_finish_decompress
|
||||
* after all data has been read. Often a no-op.
|
||||
*
|
||||
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
|
||||
* application must deal with any cleanup that should happen even
|
||||
* for error exit.
|
||||
*/
|
||||
|
||||
static void
|
||||
term_source (j_decompress_ptr cinfo)
|
||||
{
|
||||
/* no work necessary here */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prepare for input from mem buffer.
|
||||
* Leaves buffer untouched.
|
||||
*/
|
||||
|
||||
void
|
||||
my_jpeg_memory_src (j_decompress_ptr cinfo, char * inbfr, int len)
|
||||
{
|
||||
my_src_ptr src;
|
||||
|
||||
/* The source object and input buffer are made permanent so that a series
|
||||
* of JPEG images can be read from the same file by calling jpeg_stdio_src
|
||||
* only before the first one. (If we discarded the buffer at the end of
|
||||
* one image, we'd likely lose the start of the next one.)
|
||||
* This makes it unsafe to use this manager and a different source
|
||||
* manager serially with the same JPEG object. Caveat programmer.
|
||||
*/
|
||||
if (cinfo->src == NULL) { /* first time for this JPEG object? */
|
||||
cinfo->src = (struct jpeg_source_mgr *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
SIZEOF(my_source_mgr));
|
||||
src = (my_src_ptr) cinfo->src;
|
||||
src->buffer = (JOCTET *) inbfr;
|
||||
}
|
||||
|
||||
src = (my_src_ptr) cinfo->src;
|
||||
src->pub.init_source = init_source;
|
||||
src->pub.fill_input_buffer = fill_input_buffer;
|
||||
src->pub.skip_input_data = skip_input_data;
|
||||
src->pub.resync_to_restart = my_jpeg_resync_to_restart; /* use default method */
|
||||
src->pub.term_source = term_source;
|
||||
src->infile = 0L;
|
||||
src->pub.bytes_in_buffer = len; /*!!! sets to entire file len */
|
||||
src->pub.next_input_byte = (JOCTET *)inbfr; /*!!! at start of buffer */
|
||||
}
|
||||
|
||||
430
RenderDll/Common/Textures/Image/JpgImage.cpp
Normal file
430
RenderDll/Common/Textures/Image/JpgImage.cpp
Normal file
@@ -0,0 +1,430 @@
|
||||
/*=============================================================================
|
||||
JpgImage.cpp : JPG image file format implementation.
|
||||
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
||||
|
||||
Revision history:
|
||||
* Created by Khonich Andrey
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "RenderPCH.h"
|
||||
#include "CImage.h"
|
||||
#include "JpgImage.h"
|
||||
|
||||
#if !defined(WIN64) && !defined(LINUX)
|
||||
|
||||
#if defined(PS2)
|
||||
|
||||
#include "jpeglib.h"
|
||||
#include "PS2GDriver.h"
|
||||
|
||||
#else
|
||||
extern "C" {
|
||||
#include "ijl.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* ==== Constructor ==== */
|
||||
CImageJpgFile::~CImageJpgFile () {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
CImageJpgFile::CImageJpgFile (byte* ptr, long filesize) : CImageFile ()
|
||||
{
|
||||
#ifdef PS2
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
u_char *pImage=NULL;
|
||||
|
||||
pImage=(u_char *)PS2GDRV_LoadJpegImage(mCurFileName, cinfo);
|
||||
if(pImage)
|
||||
{
|
||||
m_eFormat = eIF_Jpg;
|
||||
|
||||
mfSet_bps(32);
|
||||
|
||||
mfSet_dimensions (cinfo.image_width,cinfo.image_height);
|
||||
mfSet_ImageSize(m_Width * m_Height * 4);
|
||||
|
||||
SRGBPixel *pixels = mfGet_image ();
|
||||
u_char *pix=pImage;
|
||||
|
||||
for(int j=0; j<cinfo.image_height; j++)
|
||||
{
|
||||
for(int i=0; i<cinfo.image_width; i++)
|
||||
{
|
||||
pixels[0].red=*pix++;
|
||||
pixels[0].green=*pix++;
|
||||
pixels[0].blue=*pix++;
|
||||
pixels[0].alpha=255;
|
||||
|
||||
pixels++;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] pImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
mfSet_error (eIFE_BadFormat,"Cannot read JPEG file header");
|
||||
return;
|
||||
}
|
||||
#else
|
||||
JPEG_CORE_PROPERTIES image;
|
||||
ZeroStruct( image );
|
||||
SRGBPixel *pixels;
|
||||
m_eFormat = eIF_Jpg;
|
||||
|
||||
if( ijlInit( &image ) != IJL_OK )
|
||||
{
|
||||
mfSet_error (eIFE_BadFormat,"Cannot initialize Intel JPEG library");
|
||||
return;
|
||||
}
|
||||
image.JPGBytes = ptr;
|
||||
image.JPGSizeBytes = filesize;
|
||||
if( ijlRead( &image, IJL_JBUFF_READPARAMS ) != IJL_OK )
|
||||
{
|
||||
mfSet_error (eIFE_BadFormat,"Cannot read JPEG file header");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the JPG color space ... this will always be
|
||||
// somewhat of an educated guess at best because JPEG
|
||||
// is "color blind" (i.e., nothing in the bit stream
|
||||
// tells you what color space the data was encoded from).
|
||||
// However, in this example we assume that we are
|
||||
// reading JFIF files which means that 3 channel images
|
||||
// are in the YCbCr color space and 1 channel images are
|
||||
// in the Y color space.
|
||||
switch(image.JPGChannels)
|
||||
{
|
||||
case 1:
|
||||
image.JPGColor = IJL_G;
|
||||
image.DIBChannels = 3;
|
||||
image.DIBColor = IJL_RGB;
|
||||
mfSet_bps(24);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
image.JPGColor = IJL_YCBCR;
|
||||
image.DIBChannels = 3;
|
||||
image.DIBColor = IJL_RGB;
|
||||
mfSet_bps(24);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
image.JPGColor = IJL_YCBCRA_FPX;
|
||||
image.DIBChannels = 4;
|
||||
image.DIBColor = IJL_RGBA_FPX;
|
||||
mfSet_bps(32);
|
||||
break;
|
||||
|
||||
default:
|
||||
// This catches everything else, but no
|
||||
// color twist will be performed by the IJL.
|
||||
image.DIBColor = (IJL_COLOR)IJL_OTHER;
|
||||
image.JPGColor = (IJL_COLOR)IJL_OTHER;
|
||||
image.DIBChannels = image.JPGChannels;
|
||||
break;
|
||||
}
|
||||
|
||||
image.DIBWidth = image.JPGWidth;
|
||||
image.DIBHeight = image.JPGHeight;
|
||||
image.DIBPadBytes = IJL_DIB_PAD_BYTES(image.DIBWidth,image.DIBChannels);
|
||||
|
||||
mfSet_dimensions (image.DIBWidth, image.DIBHeight);
|
||||
mfSet_ImageSize(m_Width * m_Height * 4);
|
||||
pixels = (SRGBPixel *)mfGet_image ();
|
||||
|
||||
int imageSize = (image.DIBWidth * image.DIBChannels + image.DIBPadBytes) * image.DIBHeight;
|
||||
|
||||
byte *imageData = new BYTE[ imageSize ];
|
||||
if( imageData == NULL )
|
||||
{
|
||||
mfSet_error (eIFE_OutOfMemory,"Cannot allocate memory for image");
|
||||
ijlFree( &image );
|
||||
return;
|
||||
}
|
||||
|
||||
image.DIBBytes = imageData;
|
||||
|
||||
if( ijlRead( &image, IJL_JBUFF_READWHOLEIMAGE ) != IJL_OK )
|
||||
{
|
||||
mfSet_error (eIFE_IOerror,"Cannot read image data");
|
||||
ijlFree( &image );
|
||||
return;
|
||||
}
|
||||
|
||||
if( ijlFree( &image ) != IJL_OK )
|
||||
{
|
||||
mfSet_error (eIFE_IOerror,"Cannot free Intel(R) JPEG library");
|
||||
return;
|
||||
}
|
||||
|
||||
byte *src = imageData;
|
||||
int width = image.DIBWidth;
|
||||
int height = image.DIBHeight;
|
||||
int pad = IJL_DIB_PAD_BYTES(width,4);
|
||||
|
||||
if (image.DIBColor == IJL_RGBA_FPX)
|
||||
{
|
||||
int line_width = image.DIBWidth * 4 + pad;
|
||||
for(int i=0; i<height; i++)
|
||||
{
|
||||
src = imageData + line_width*i;
|
||||
for(int j=0; j<width; j++)
|
||||
{
|
||||
pixels->red = src[0];
|
||||
pixels->green = src[1];
|
||||
pixels->blue = src[2];
|
||||
pixels->alpha = src[3];
|
||||
pixels++;
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SRGBPixel *pix = pixels;
|
||||
int line_width = image.DIBWidth * 3 + pad;
|
||||
for(int i=0; i<height; i++)
|
||||
{
|
||||
src = imageData + line_width*i;
|
||||
for(int j=0; j<width; j++)
|
||||
{
|
||||
pixels->red = src[0];
|
||||
pixels->green = src[1];
|
||||
pixels->blue = src[2];
|
||||
pixels->alpha = 255;
|
||||
pixels++;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete [] imageData;
|
||||
|
||||
/* And we're done! */
|
||||
#endif //PS2
|
||||
}
|
||||
|
||||
#endif // WIN64
|
||||
|
||||
#ifdef WIN64
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "Jpeg6/Jpeglib.h"
|
||||
#include "Jmemsrc.c" // include buffer source input code
|
||||
}
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
/* ==== Error mgmnt ==== */
|
||||
static char jpg_err_msg[256];
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
};
|
||||
typedef struct my_error_mgr *my_error_ptr;
|
||||
static void my_error_exit (j_common_ptr cinfo)
|
||||
{
|
||||
char errmsg [256];
|
||||
|
||||
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
|
||||
my_error_ptr myerr = (my_error_ptr) cinfo->err;
|
||||
|
||||
/* Always display the message. */
|
||||
/* We could postpone this until after returning, if we chose. */
|
||||
(*cinfo->err->format_message) (cinfo,errmsg);
|
||||
strcpy (jpg_err_msg,errmsg);
|
||||
|
||||
/* Return control to the setjmp point */
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
|
||||
/* ==== Constructor ==== */
|
||||
CImageJpgFile::~CImageJpgFile () {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
CImageJpgFile::CImageJpgFile (byte* ptr, long filesize) : CImageFile () {
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct my_error_mgr jerr;
|
||||
JSAMPARRAY buffer; /* Output row buffer */
|
||||
int row_stride; /* physical row width in output buffer */
|
||||
|
||||
int bufp;
|
||||
int i;
|
||||
SRGBPixel *pixels;
|
||||
|
||||
m_eFormat = eIF_Jpg;
|
||||
|
||||
/* ==== Step 1: allocate and initialize JPEG decompression object */
|
||||
/* We set up the normal JPEG error routines, then override error_exit. */
|
||||
cinfo.err = my_jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
if (setjmp(jerr.setjmp_buffer)) {
|
||||
my_jpeg_destroy_decompress(&cinfo);
|
||||
mfSet_error (eIFE_BadFormat,jpg_err_msg);
|
||||
return;
|
||||
}
|
||||
/* Now we can initialize the JPEG decompression object. */
|
||||
my_jpeg_create_decompress(&cinfo);
|
||||
|
||||
/* ==== Step 2: specify data source (memory buffer, in this case) */
|
||||
my_jpeg_memory_src(&cinfo, (char *)ptr, filesize);
|
||||
|
||||
/* ==== Step 3: read file parameters with jpeg_read_header() */
|
||||
(void) my_jpeg_read_header(&cinfo, TRUE);
|
||||
|
||||
/* ==== Step 4: set parameters for decompression */
|
||||
/* In this example, we don't need to change any of the defaults set by
|
||||
* jpeg_read_header(), so we do nothing here.
|
||||
*/
|
||||
|
||||
/* ==== Step 5: Start decompressor */
|
||||
|
||||
(void) my_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.
|
||||
* In this example, we need to make an output work buffer of the right size.
|
||||
*/
|
||||
|
||||
mfSet_dimensions (cinfo.output_width, cinfo.output_height);
|
||||
mfSet_ImageSize(cinfo.output_width * cinfo.output_height * 4);
|
||||
pixels = (SRGBPixel *)mfGet_image();
|
||||
bufp = 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.
|
||||
*/
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
/* jpeg_read_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could ask for
|
||||
* more than one scanline at a time if that's more convenient.
|
||||
*/
|
||||
(void) my_jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
/* put_scanline_someplace(buffer[0], row_stride); */
|
||||
if (cinfo.output_components == 1)
|
||||
{ /* grey scale */
|
||||
for (i=0;i<row_stride;i++)
|
||||
{
|
||||
pixels[bufp].red = buffer[0][i];
|
||||
pixels[bufp].green = buffer[0][i];
|
||||
pixels[bufp].blue = buffer[0][i];
|
||||
pixels[bufp].alpha = 255;
|
||||
bufp ++;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (cinfo.output_components == 3)
|
||||
{ /* rgb triplets */
|
||||
for (i = 0; i < (int)cinfo.output_width; i++)
|
||||
{
|
||||
pixels[bufp].red = buffer[0][i*3+0];
|
||||
pixels[bufp].green = buffer[0][i*3+1];
|
||||
pixels[bufp].blue = buffer[0][i*3+2];
|
||||
pixels[bufp].alpha = 255;
|
||||
bufp ++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < (int)cinfo.output_width; i++)
|
||||
{
|
||||
pixels[bufp].red = buffer[0][i*4+0];
|
||||
pixels[bufp].green = buffer[0][i*4+1];
|
||||
pixels[bufp].blue = buffer[0][i*4+2];
|
||||
pixels[bufp].alpha = 255;
|
||||
bufp ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ==== Step 7: Finish decompression */
|
||||
|
||||
(void) my_jpeg_finish_decompress(&cinfo);
|
||||
/* We can ignore the return value since suspension is not possible
|
||||
* with the buffer data source.
|
||||
*/
|
||||
|
||||
/* ==== Step 8: Release JPEG decompression object */
|
||||
/* This is an important step since it will release a good deal of memory. */
|
||||
my_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! */
|
||||
}
|
||||
#endif //WIN64
|
||||
|
||||
|
||||
|
||||
void WriteJPG(byte *dat, int wdt, int hgt, char *name)
|
||||
{
|
||||
#if !defined(PS2) && !defined(WIN64) && !defined(NULL_RENDERER)
|
||||
JPEG_CORE_PROPERTIES image;
|
||||
ZeroMemory( &image, sizeof( JPEG_CORE_PROPERTIES ) );
|
||||
|
||||
if( ijlInit( &image ) != IJL_OK )
|
||||
return;
|
||||
|
||||
byte *data = new byte [wdt*hgt*3];
|
||||
for (int i=0; i<wdt*hgt; i++)
|
||||
{
|
||||
data[i*3+0] = dat[i*4+0];
|
||||
data[i*3+1] = dat[i*4+1];
|
||||
data[i*3+2] = dat[i*4+2];
|
||||
}
|
||||
|
||||
// Setup DIB
|
||||
image.DIBWidth = wdt;
|
||||
image.DIBHeight = hgt;
|
||||
image.DIBBytes = data;
|
||||
image.DIBPadBytes = 0; //IJL_DIB_PAD_BYTES(image.DIBWidth,3);
|
||||
|
||||
// Setup JPEG
|
||||
image.JPGFile = name;
|
||||
image.JPGWidth = wdt;
|
||||
image.JPGHeight = hgt;
|
||||
|
||||
image.jquality = 100;
|
||||
|
||||
image.DIBColor = IJL_RGB;
|
||||
|
||||
if( ijlWrite( &image, IJL_JFILE_WRITEWHOLEIMAGE ) != IJL_OK )
|
||||
{
|
||||
delete [] data;
|
||||
return;
|
||||
}
|
||||
|
||||
if( ijlFree( &image ) != IJL_OK )
|
||||
{
|
||||
delete [] data;
|
||||
return;
|
||||
}
|
||||
|
||||
delete [] data;
|
||||
#else
|
||||
OutputDebugString("Not Implemented");
|
||||
#endif //!defined(PS2) && !defined(WIN64)
|
||||
}
|
||||
24
RenderDll/Common/Textures/Image/JpgImage.h
Normal file
24
RenderDll/Common/Textures/Image/JpgImage.h
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
#ifndef JPGIMAGE_H
|
||||
#define JPGIMAGE_H
|
||||
|
||||
/**
|
||||
* An ImageFile subclass for reading JPG files.<p>
|
||||
* This implementation needs libjpeg to read JFIF files.
|
||||
*/
|
||||
class CImageJpgFile : public CImageFile
|
||||
{
|
||||
///
|
||||
friend class CImageFile; // For constructor
|
||||
|
||||
private:
|
||||
/// Read the JPG file from the buffer.
|
||||
CImageJpgFile (byte* buf, long size);
|
||||
|
||||
public:
|
||||
///
|
||||
virtual ~CImageJpgFile ();
|
||||
};
|
||||
|
||||
#endif //JPGIMAGE_H
|
||||
|
||||
179
RenderDll/Common/Textures/Image/JpgImage_XBox.cpp
Normal file
179
RenderDll/Common/Textures/Image/JpgImage_XBox.cpp
Normal file
@@ -0,0 +1,179 @@
|
||||
/*=============================================================================
|
||||
JpgImage.cpp : JPG image file format implementation.
|
||||
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
||||
|
||||
Revision history:
|
||||
* Created by Khonich Andrey
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#if !defined(LINUX)
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "CImage.h"
|
||||
#include "JpgImage.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "Jpeg6/Jpeglib.h"
|
||||
#include "Jmemsrc.c" // include buffer source input code
|
||||
}
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
/* ==== Error mgmnt ==== */
|
||||
static char jpg_err_msg[256];
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
};
|
||||
typedef struct my_error_mgr *my_error_ptr;
|
||||
static void my_error_exit (j_common_ptr cinfo)
|
||||
{
|
||||
char errmsg [256];
|
||||
|
||||
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
|
||||
my_error_ptr myerr = (my_error_ptr) cinfo->err;
|
||||
|
||||
/* Always display the message. */
|
||||
/* We could postpone this until after returning, if we chose. */
|
||||
(*cinfo->err->format_message) (cinfo,errmsg);
|
||||
strcpy (jpg_err_msg,errmsg);
|
||||
|
||||
/* Return control to the setjmp point */
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
|
||||
/* ==== Constructor ==== */
|
||||
CImageJpgFile::~CImageJpgFile () {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
CImageJpgFile::CImageJpgFile (byte* ptr, long filesize) : CImageFile () {
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct my_error_mgr jerr;
|
||||
JSAMPARRAY buffer; /* Output row buffer */
|
||||
int row_stride; /* physical row width in output buffer */
|
||||
|
||||
int bufp;
|
||||
int i;
|
||||
SRGBPixel *pixels;
|
||||
|
||||
m_eFormat = eIF_Jpg;
|
||||
|
||||
/* ==== Step 1: allocate and initialize JPEG decompression object */
|
||||
/* We set up the normal JPEG error routines, then override error_exit. */
|
||||
cinfo.err = my_jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
if (setjmp(jerr.setjmp_buffer)) {
|
||||
my_jpeg_destroy_decompress(&cinfo);
|
||||
mfSet_error (eIFE_BadFormat,jpg_err_msg);
|
||||
return;
|
||||
}
|
||||
/* Now we can initialize the JPEG decompression object. */
|
||||
my_jpeg_create_decompress(&cinfo);
|
||||
|
||||
/* ==== Step 2: specify data source (memory buffer, in this case) */
|
||||
my_jpeg_memory_src(&cinfo, (char *)ptr, filesize);
|
||||
|
||||
/* ==== Step 3: read file parameters with jpeg_read_header() */
|
||||
(void) my_jpeg_read_header(&cinfo, TRUE);
|
||||
|
||||
/* ==== Step 4: set parameters for decompression */
|
||||
/* In this example, we don't need to change any of the defaults set by
|
||||
* jpeg_read_header(), so we do nothing here.
|
||||
*/
|
||||
|
||||
/* ==== Step 5: Start decompressor */
|
||||
|
||||
(void) my_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.
|
||||
* In this example, we need to make an output work buffer of the right size.
|
||||
*/
|
||||
|
||||
mfSet_dimensions (cinfo.output_width, cinfo.output_height);
|
||||
mfSet_ImageSize(cinfo.output_width * cinfo.output_height * 4);
|
||||
pixels = (SRGBPixel *)mfGet_image();
|
||||
bufp = 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.
|
||||
*/
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
/* jpeg_read_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could ask for
|
||||
* more than one scanline at a time if that's more convenient.
|
||||
*/
|
||||
(void) my_jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
/* put_scanline_someplace(buffer[0], row_stride); */
|
||||
if (cinfo.output_components == 1)
|
||||
{ /* grey scale */
|
||||
for (i=0;i<row_stride;i++)
|
||||
{
|
||||
pixels[bufp].red = buffer[0][i];
|
||||
pixels[bufp].green = buffer[0][i];
|
||||
pixels[bufp].blue = buffer[0][i];
|
||||
pixels[bufp].alpha = 255;
|
||||
bufp ++;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (cinfo.output_components == 3)
|
||||
{ /* rgb triplets */
|
||||
for (i = 0; i < (int)cinfo.output_width; i++)
|
||||
{
|
||||
pixels[bufp].red = buffer[0][i*3+0];
|
||||
pixels[bufp].green = buffer[0][i*3+1];
|
||||
pixels[bufp].blue = buffer[0][i*3+2];
|
||||
pixels[bufp].alpha = 255;
|
||||
bufp ++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < (int)cinfo.output_width; i++)
|
||||
{
|
||||
pixels[bufp].red = buffer[0][i*4+0];
|
||||
pixels[bufp].green = buffer[0][i*4+1];
|
||||
pixels[bufp].blue = buffer[0][i*4+2];
|
||||
pixels[bufp].alpha = 255;
|
||||
bufp ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ==== Step 7: Finish decompression */
|
||||
|
||||
(void) my_jpeg_finish_decompress(&cinfo);
|
||||
/* We can ignore the return value since suspension is not possible
|
||||
* with the buffer data source.
|
||||
*/
|
||||
|
||||
/* ==== Step 8: Release JPEG decompression object */
|
||||
/* This is an important step since it will release a good deal of memory. */
|
||||
my_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! */
|
||||
}
|
||||
|
||||
#endif
|
||||
166
RenderDll/Common/Textures/Image/PcxImage.cpp
Normal file
166
RenderDll/Common/Textures/Image/PcxImage.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
/*=============================================================================
|
||||
PcxImage.cpp : PCX image file format implementation.
|
||||
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
||||
|
||||
Revision history:
|
||||
* Created by Khonich Andrey
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "RenderPCH.h"
|
||||
#include "CImage.h"
|
||||
#include "PcxImage.h"
|
||||
#if defined(LINUX)
|
||||
#include "ILog.h"
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char manufacturer;
|
||||
char version;
|
||||
char encoding;
|
||||
char bits_per_pixel;
|
||||
short xmin;
|
||||
short ymin;
|
||||
short xmax;
|
||||
short ymax;
|
||||
short hres;
|
||||
short vres;
|
||||
byte palette[48];
|
||||
char reserved;
|
||||
char color_planes;
|
||||
short bytes_per_line;
|
||||
short palette_type;
|
||||
char filler[58];
|
||||
byte data;
|
||||
} pcx_header;
|
||||
|
||||
CImagePcxFile::~CImagePcxFile ()
|
||||
{
|
||||
}
|
||||
|
||||
CImagePcxFile::CImagePcxFile (byte* ptr, long filesize) : CImageFile ()
|
||||
{
|
||||
pcx_header *pcx;
|
||||
byte* raw, *p, dat;
|
||||
int x, y, runLength;
|
||||
int sx, sy;
|
||||
|
||||
//
|
||||
// parse the PCX file
|
||||
//
|
||||
pcx = (pcx_header *)ptr;
|
||||
raw = &pcx->data;
|
||||
|
||||
if (pcx->manufacturer != 0x0a
|
||||
|| pcx->version != 5
|
||||
|| pcx->encoding != 1
|
||||
|| pcx->bits_per_pixel != 8
|
||||
|| pcx->xmax >= 640
|
||||
|| pcx->ymax >= 480)
|
||||
{
|
||||
mfSet_error (eIFE_BadFormat, "not a PCX file");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
sx=pcx->xmax+1;
|
||||
sy=pcx->ymax+1;
|
||||
|
||||
m_eFormat = eIF_Pcx;
|
||||
|
||||
/* Read in global colormap. */
|
||||
CHK (m_pPal = new SRGBPixel [256]);
|
||||
|
||||
p = (byte *)pcx + filesize - 768;
|
||||
int i;
|
||||
for (i=0; i<256; i++)
|
||||
{
|
||||
m_pPal[i].red = p[0];
|
||||
m_pPal[i].green = p[1];
|
||||
m_pPal[i].blue = p[2];
|
||||
m_pPal[i].alpha = 255;
|
||||
p += 3;
|
||||
}
|
||||
|
||||
// Set the dimensions which will also allocate the image data
|
||||
// buffer.
|
||||
mfSet_dimensions (sx, sy);
|
||||
mfSet_ImageSize(m_Width * m_Height);
|
||||
byte *IndexImage = mfGet_image ();
|
||||
p = IndexImage;
|
||||
|
||||
i = 0;
|
||||
for (y=0 ; y<=pcx->ymax ; y++, p += pcx->xmax+1)
|
||||
{
|
||||
for (x=0 ; x<=pcx->xmax ; )
|
||||
{
|
||||
dat = *raw++;
|
||||
|
||||
if((dat & 0xC0) == 0xC0)
|
||||
{
|
||||
runLength = dat & 0x3F;
|
||||
dat = *raw++;
|
||||
}
|
||||
else
|
||||
runLength = 1;
|
||||
|
||||
while(runLength-- > 0)
|
||||
{
|
||||
p[x++] = dat;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WritePCX (char *name, byte *data, byte *pal, int width, int height)
|
||||
{
|
||||
int i, j, len;
|
||||
pcx_header *pcx;
|
||||
byte *pack;
|
||||
FILE *fp;
|
||||
|
||||
pcx = (pcx_header*)malloc (width*height*2+1000);
|
||||
pcx->manufacturer = 10; // Some programs complains if this is 0
|
||||
pcx->version = 5;
|
||||
pcx->encoding = 1;
|
||||
pcx->bits_per_pixel = 8;
|
||||
pcx->xmin = 0;
|
||||
pcx->ymin = 0;
|
||||
pcx->xmax = width - 1;
|
||||
pcx->ymax = height - 1;
|
||||
pcx->hres = width;
|
||||
pcx->vres = height;
|
||||
memset (pcx->palette, 0, sizeof(pcx->palette));
|
||||
pcx->color_planes = 1;
|
||||
pcx->bytes_per_line = width;
|
||||
pcx->palette_type = 2;
|
||||
memset (pcx->filler, 0, sizeof(pcx->filler));
|
||||
pack = &(pcx->data);
|
||||
|
||||
for (i=0; i<height; i++)
|
||||
{
|
||||
for (j=0; j<width; j++)
|
||||
{
|
||||
if ((*data & 0xc0) != 0xc0)
|
||||
*pack++ = *data++;
|
||||
else
|
||||
{
|
||||
*pack++ = 0xc1;
|
||||
*pack++ = *data++;
|
||||
}
|
||||
}
|
||||
// data += width;
|
||||
}
|
||||
*pack++ = 0x0c;
|
||||
for (i=0; i<768; i++)
|
||||
*pack++ = *pal++;
|
||||
len = pack - (byte *)pcx;
|
||||
fp = fxopen (name, "wb");
|
||||
if (!fp)
|
||||
return;
|
||||
fwrite (pcx, len, 1, fp);
|
||||
fclose (fp);
|
||||
free (pcx);
|
||||
}
|
||||
25
RenderDll/Common/Textures/Image/PcxImage.h
Normal file
25
RenderDll/Common/Textures/Image/PcxImage.h
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
#ifndef PCXIMAGE_H
|
||||
#define PCXIMAGE_H
|
||||
|
||||
/**
|
||||
* An ImageFile subclass for reading PCX files.
|
||||
*/
|
||||
class CImagePcxFile : public CImageFile
|
||||
{
|
||||
///
|
||||
friend class CImageFile; // For constructor
|
||||
|
||||
private:
|
||||
/// Read the PCX file from the buffer.
|
||||
CImagePcxFile (byte* buf, long size);
|
||||
|
||||
public:
|
||||
///
|
||||
virtual ~CImagePcxFile ();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
737
RenderDll/Common/Textures/Image/Quantize.cpp
Normal file
737
RenderDll/Common/Textures/Image/Quantize.cpp
Normal file
@@ -0,0 +1,737 @@
|
||||
/*=============================================================================
|
||||
PcxImage.cpp : PCX image file format implementation.
|
||||
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
||||
|
||||
Revision history:
|
||||
* Created by Khonich Andrey
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "RenderPCH.h"
|
||||
#include "CImage.h"
|
||||
|
||||
#define HIST_R_BITS 5
|
||||
#define HIST_G_BITS 6
|
||||
#define HIST_B_BITS 5
|
||||
|
||||
// Amount to shift left R value to get max (hist_r, hist_g, hist_b)
|
||||
#define HIST_SHIFT_R 1
|
||||
#define HIST_SHIFT_G 0
|
||||
#define HIST_SHIFT_B 1
|
||||
|
||||
#define HIST_R_MAX (1 << HIST_R_BITS)
|
||||
#define HIST_G_MAX (1 << HIST_G_BITS)
|
||||
#define HIST_B_MAX (1 << HIST_B_BITS)
|
||||
|
||||
#ifdef SH_LITTLE_ENDIAN
|
||||
# define R_BIT 0
|
||||
# define G_BIT 8
|
||||
# define B_BIT 16
|
||||
#else
|
||||
# define R_BIT 24
|
||||
# define G_BIT 16
|
||||
# define B_BIT 8
|
||||
#endif
|
||||
|
||||
|
||||
// Compute masks for effectively separating R,G and B components from a unsigned long.
|
||||
// For a little-endian machine they are respectively
|
||||
// 0x000000f8, 0x0000fc00 and 0x00f80000
|
||||
// For a big-endian machine they are respectively
|
||||
// 0xf8000000, 0x00fc0000 and 0x0000f800
|
||||
#define R_MASK ((HIST_R_MAX - 1) << (R_BIT + 8 - HIST_R_BITS))
|
||||
#define G_MASK ((HIST_G_MAX - 1) << (G_BIT + 8 - HIST_G_BITS))
|
||||
#define B_MASK ((HIST_B_MAX - 1) << (B_BIT + 8 - HIST_B_BITS))
|
||||
// The following macro extract the respective color components from a unsigned long
|
||||
// and transform them into a index in the histogram.
|
||||
#define INDEX_R(l) ((l & R_MASK) >> (R_BIT + 8 - HIST_R_BITS))
|
||||
#define INDEX_G(l) ((l & G_MASK) >> (G_BIT + 8 - HIST_G_BITS - HIST_R_BITS))
|
||||
#define INDEX_B(l) ((l & B_MASK) >> (B_BIT + 8 - HIST_B_BITS - HIST_G_BITS - HIST_R_BITS))
|
||||
// Calculate index into histogram for given R,G,B components
|
||||
#define INDEX(r,g,b) (r + (g << HIST_R_BITS) + (b << (HIST_R_BITS + HIST_G_BITS)))
|
||||
|
||||
// The storage for color usage histogram
|
||||
static ushort *hist = NULL;
|
||||
// Total number of colors that were used to create the histogram
|
||||
static unsigned hist_pixels;
|
||||
|
||||
/*
|
||||
* A box in color space.
|
||||
* Both minimal and maximal component bounds are inclusive, that is, the bounds
|
||||
* Rm = 0, Rx = 255 means the box covers the entire R component range.
|
||||
* <p>
|
||||
* This structure is meant to be highly fast, thus only atomic operations
|
||||
* are implemented for it. After some operations the box may be left in a
|
||||
* invalid state, thus take care.
|
||||
*/
|
||||
struct shColorBox
|
||||
{
|
||||
// The minimal and maximal R
|
||||
byte Rm,Rx;
|
||||
// The minimal and maximal G
|
||||
byte Gm,Gx;
|
||||
// The minimal and maximal B
|
||||
byte Bm,Bx;
|
||||
// Color box volume
|
||||
unsigned Volume;
|
||||
// Number of pixels in this box
|
||||
unsigned PixelCount;
|
||||
// Number of non-zero different color values in this box
|
||||
unsigned ColorCount;
|
||||
|
||||
// Useful function
|
||||
static inline unsigned Sqr (int x)
|
||||
{ return x * x; }
|
||||
// Set box to given bounds
|
||||
void Set (byte rm, byte rx, byte gm, byte gx, byte bm, byte bx)
|
||||
{ Rm = rm; Rx = rx; Gm = gm; Gx = gx; Bm = bm; Bx = bx; }
|
||||
// Compute the volume of box
|
||||
void ComputeVolume ()
|
||||
{
|
||||
// We compute the length of the diagonal of the box rather than the
|
||||
// proper volume. This also has the side effect that a long narrow
|
||||
// box looks more "voluminous" thus its more probably that it will
|
||||
// be split rather than a relatively cubic one.
|
||||
Volume = Sqr (Rx - Rm) * (R_COEF_SQ << HIST_SHIFT_R) +
|
||||
Sqr (Gx - Gm) * (G_COEF_SQ << HIST_SHIFT_G) +
|
||||
Sqr (Bx - Bm) * (B_COEF_SQ << HIST_SHIFT_B);
|
||||
}
|
||||
// Count number of non-zero colors within this box
|
||||
void CountPixels ()
|
||||
{
|
||||
PixelCount = ColorCount = 0;
|
||||
for (int b = Bm; b <= Bx; b++)
|
||||
for (int g = Gm; g <= Gx; g++)
|
||||
{
|
||||
ushort *hp = &hist [INDEX (Rm, g, b)];
|
||||
for (int r = Rx - Rm; r >= 0; r--, hp++)
|
||||
if (*hp)
|
||||
{
|
||||
PixelCount += *hp;
|
||||
ColorCount++;
|
||||
} /* endif */
|
||||
} /* endfor */
|
||||
}
|
||||
// Move Rm up until we find pixels that contain this value
|
||||
bool ShrinkRm ()
|
||||
{
|
||||
byte iRm = Rm;
|
||||
for (; Rm <= Rx; Rm++)
|
||||
for (byte b = Bm; b <= Bx; b++)
|
||||
{
|
||||
ushort *hp = &hist [INDEX (Rm, Gm, b)];
|
||||
for (int g = Gx - Gm; g >= 0; g--, hp += HIST_R_MAX)
|
||||
if (*hp) return (Rm != iRm);
|
||||
}
|
||||
return (Rm != iRm);
|
||||
}
|
||||
// Move Rx down until we find pixels that contain this value
|
||||
bool ShrinkRx ()
|
||||
{
|
||||
byte iRx = Rx;
|
||||
for (; Rx >= Rm; Rx--)
|
||||
for (byte b = Bm; b <= Bx; b++)
|
||||
{
|
||||
ushort *hp = &hist [INDEX (Rx, Gm, b)];
|
||||
for (int g = Gx - Gm; g >= 0; g--, hp += HIST_R_MAX)
|
||||
if (*hp) return (Rx != iRx);
|
||||
}
|
||||
return (Rx != iRx);
|
||||
}
|
||||
// Move Gm up until we find pixels that contain this value
|
||||
bool ShrinkGm ()
|
||||
{
|
||||
byte iGm = Gm;
|
||||
for (; Gm <= Gx; Gm++)
|
||||
for (byte b = Bm; b <= Bx; b++)
|
||||
{
|
||||
ushort *hp = &hist [INDEX (Rm, Gm, b)];
|
||||
for (int r = Rx - Rm; r >= 0; r--, hp++)
|
||||
if (*hp) return (Gm != iGm);
|
||||
}
|
||||
return (Gm != iGm);
|
||||
}
|
||||
// Move Gx down until we find pixels that contain this value
|
||||
bool ShrinkGx ()
|
||||
{
|
||||
byte iGx = Gx;
|
||||
for (; Gx >= Gm; Gx--)
|
||||
for (byte b = Bm; b <= Bx; b++)
|
||||
{
|
||||
ushort *hp = &hist [INDEX (Rm, Gx, b)];
|
||||
for (int r = Rx - Rm; r >= 0; r--, hp++)
|
||||
if (*hp) return (Gx != iGx);
|
||||
}
|
||||
return (Gx != iGx);
|
||||
}
|
||||
// Move Bm up until we find pixels that contain this value
|
||||
bool ShrinkBm ()
|
||||
{
|
||||
byte iBm = Bm;
|
||||
for (; Bm <= Bx; Bm++)
|
||||
for (byte g = Gm; g <= Gx; g++)
|
||||
{
|
||||
ushort *hp = &hist [INDEX (Rm, g, Bm)];
|
||||
for (int r = Rx - Rm; r >= 0; r--, hp++)
|
||||
if (*hp) return (Bm != iBm);
|
||||
}
|
||||
return (Bm != iBm);
|
||||
}
|
||||
// Move Bx down until we find pixels that contain this value
|
||||
bool ShrinkBx ()
|
||||
{
|
||||
byte iBx = Bx;
|
||||
for (; Bx >= Bm; Bx--)
|
||||
for (byte g = Gm; g <= Gx; g++)
|
||||
{
|
||||
ushort *hp = &hist [INDEX (Rm, g, Bx)];
|
||||
for (int r = Rx - Rm; r >= 0; r--, hp++)
|
||||
if (*hp) return (Bx != iBx);
|
||||
}
|
||||
return (Bx != iBx);
|
||||
}
|
||||
// Shrink box: move min/max bounds until we hit an existing color
|
||||
void Shrink ()
|
||||
{
|
||||
ShrinkRm (); ShrinkRx ();
|
||||
ShrinkGm (); ShrinkGx ();
|
||||
ShrinkBm (); ShrinkBx ();
|
||||
}
|
||||
/**
|
||||
* Compute the mean color for this box.
|
||||
* The computation is performed by taking into account each color's
|
||||
* weight, i.e. number of pixels with this color. Thus resulting palette
|
||||
* is biased towards most often used colors.
|
||||
*/
|
||||
void GetMeanColor (SRGBPixel &color)
|
||||
{
|
||||
unsigned rs = 0, gs = 0, bs = 0;
|
||||
unsigned count = 0;
|
||||
for (int b = Bm; b <= Bx; b++)
|
||||
for (int g = Gm; g <= Gx; g++)
|
||||
{
|
||||
ushort *hp = &hist [INDEX (Rm, g, b)];
|
||||
for (int r = Rm; r <= Rx; r++, hp++)
|
||||
if (*hp)
|
||||
{
|
||||
unsigned pixc = *hp;
|
||||
count += pixc;
|
||||
rs += pixc * r;
|
||||
gs += pixc * g;
|
||||
bs += pixc * b;
|
||||
} /* endif */
|
||||
} /* endfor */
|
||||
// In some extreme cases (textures with zero pixels or
|
||||
// single-color textures with 1 transparent color)
|
||||
// we can end here with count == 0; avoid division by zero
|
||||
if (!count)
|
||||
{
|
||||
color = SRGBPixel (0, 0, 0);
|
||||
return;
|
||||
}
|
||||
color.red = ((rs + count / 2) << (8 - HIST_R_BITS)) / count;
|
||||
color.green = ((gs + count / 2) << (8 - HIST_G_BITS)) / count;
|
||||
color.blue = ((bs + count / 2) << (8 - HIST_B_BITS)) / count;
|
||||
}
|
||||
void FillInverseCMap (byte *icmap, byte index)
|
||||
{
|
||||
int Rcount = Rx - Rm + 1;
|
||||
for (int b = Bm; b <= Bx; b++)
|
||||
for (int g = Gm; g <= Gx; g++)
|
||||
memset (&icmap [INDEX (Rm, g, b)], index, Rcount);
|
||||
}
|
||||
};
|
||||
|
||||
// The storage for color space boxes
|
||||
static shColorBox *box = NULL;
|
||||
// Number of valid color boxes
|
||||
static int boxcount;
|
||||
// The storage for color indices
|
||||
static byte *color_index = NULL;
|
||||
|
||||
static int __cdecl compare_boxes (const void *i1, const void *i2)
|
||||
{
|
||||
int count1 = box [*(byte *)i1].PixelCount;
|
||||
int count2 = box [*(byte *)i2].PixelCount;
|
||||
return (count1 > count2) ? -1 : (count1 == count2) ? 0 : +1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------- The API ------//
|
||||
|
||||
// The state of quantization variables
|
||||
static enum
|
||||
{
|
||||
// Uninitialized: initial state
|
||||
qsNone,
|
||||
// Counting color frequencies
|
||||
qsCount,
|
||||
// Remapping input images to output
|
||||
qsRemap
|
||||
} qState = qsNone;
|
||||
|
||||
void shQuantizeBegin ()
|
||||
{
|
||||
// Clean up, if previous quantization sequence was not finished
|
||||
shQuantizeEnd ();
|
||||
|
||||
// First, allocate the histogram
|
||||
hist = new ushort [HIST_R_MAX * HIST_G_MAX * HIST_B_MAX];
|
||||
memset (hist, 0, HIST_R_MAX * HIST_G_MAX * HIST_B_MAX * sizeof (ushort));
|
||||
|
||||
hist_pixels = 0;
|
||||
qState = qsCount;
|
||||
}
|
||||
|
||||
void shQuantizeEnd ()
|
||||
{
|
||||
delete [] color_index; color_index = NULL;
|
||||
delete [] box; box = NULL;
|
||||
delete [] hist; hist = NULL;
|
||||
}
|
||||
|
||||
void shQuantizeCount (SRGBPixel *image, int pixels, SRGBPixel *transp)
|
||||
{
|
||||
// Sanity check
|
||||
if (!pixels || qState != qsCount)
|
||||
return;
|
||||
|
||||
hist_pixels += pixels;
|
||||
|
||||
// Now, count all colors in image
|
||||
unsigned long *src = (unsigned long *)image;
|
||||
if (transp)
|
||||
{
|
||||
unsigned long tc = (*(unsigned long *)transp) & RGB_MASK;
|
||||
while (pixels--)
|
||||
{
|
||||
unsigned long pix = *src++;
|
||||
if (tc != (pix & RGB_MASK))
|
||||
{
|
||||
ushort &pa = hist [INDEX_R (pix) + INDEX_G (pix) + INDEX_B (pix)];
|
||||
// do not permit overflow here; stick to MAX_ushort
|
||||
if (!++pa) --pa;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
while (pixels--)
|
||||
{
|
||||
unsigned long pix = *src++;
|
||||
ushort &pa = hist [INDEX_R (pix) + INDEX_G (pix) + INDEX_B (pix)];
|
||||
// do not permit overflow here; stick to MAX_ushort
|
||||
if (!++pa) --pa;
|
||||
}
|
||||
}
|
||||
|
||||
void shQuantizeBias (SRGBPixel *colors, int count, int weight)
|
||||
{
|
||||
// Sanity check
|
||||
if (!count || qState != qsCount)
|
||||
return;
|
||||
|
||||
unsigned delta;
|
||||
if (hist_pixels < (0xffffffff / 100))
|
||||
delta = ((hist_pixels + 1) * weight / (100 * count));
|
||||
else
|
||||
delta = ((hist_pixels / count + 1) * weight) / 100;
|
||||
if (delta > 0xffff)
|
||||
delta = 0xffff;
|
||||
else if (!delta)
|
||||
return;
|
||||
|
||||
// Now, count all colors in image
|
||||
unsigned long *src = (unsigned long *)colors;
|
||||
while (count--)
|
||||
{
|
||||
unsigned long pix = *src++;
|
||||
ushort &pa = hist [INDEX_R (pix) + INDEX_G (pix) + INDEX_B (pix)];
|
||||
// do not permit overflow here; stick to MAX_ushort
|
||||
if (unsigned (pa) + delta > 0xffff) pa = 0xffff; else pa += delta;
|
||||
}
|
||||
}
|
||||
|
||||
void shQuantizePalette (SRGBPixel *&outpalette, int &maxcolors, SRGBPixel *transp)
|
||||
{
|
||||
// Sanity check
|
||||
if (qState != qsCount || !maxcolors)
|
||||
return;
|
||||
|
||||
// Good. Now we create the array of color space boxes.
|
||||
box = new shColorBox [maxcolors];
|
||||
box [0].Set (0, HIST_R_MAX - 1, 0, HIST_G_MAX - 1, 0, HIST_B_MAX - 1);
|
||||
box [0].Shrink ();
|
||||
box [0].ComputeVolume ();
|
||||
box [0].CountPixels ();
|
||||
boxcount = 1;
|
||||
|
||||
if (transp)
|
||||
maxcolors--;
|
||||
|
||||
// Loop until we have enough boxes (or we're out of pixels)
|
||||
while (boxcount < maxcolors)
|
||||
{
|
||||
// Find the box that should be split
|
||||
// We're making this decision the following way:
|
||||
// - first half of palette we prefer to split boxes that are
|
||||
// most populated with different colors.
|
||||
// - the rest of palette we prefer to split largest boxes.
|
||||
int bi, bestbox = -1;
|
||||
unsigned bestrating = 0;
|
||||
if (boxcount < maxcolors / 2)
|
||||
{
|
||||
for (bi = 0; bi < boxcount; bi++)
|
||||
if (bestrating < box [bi].ColorCount)
|
||||
{
|
||||
bestrating = box [bi].ColorCount;
|
||||
bestbox = bi;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (bi = 0; bi < boxcount; bi++)
|
||||
if (bestrating < box [bi].Volume)
|
||||
{
|
||||
bestrating = box [bi].Volume;
|
||||
bestbox = bi;
|
||||
}
|
||||
}
|
||||
// Out of splittable boxes?
|
||||
if (bestrating <= 1)
|
||||
break;
|
||||
|
||||
shColorBox &srcbox = box [bestbox];
|
||||
shColorBox &dstbox = box [boxcount++];
|
||||
dstbox = srcbox;
|
||||
|
||||
// Decide along which of R/G/B axis to split the box
|
||||
int rlen = (dstbox.Rx - dstbox.Rm) * (R_COEF << HIST_SHIFT_R);
|
||||
int glen = (dstbox.Gx - dstbox.Gm) * (G_COEF << HIST_SHIFT_G);
|
||||
int blen = (dstbox.Bx - dstbox.Bm) * (B_COEF << HIST_SHIFT_B);
|
||||
|
||||
enum { axisR, axisG, axisB } axis =
|
||||
(glen < rlen) ?
|
||||
((rlen < blen) ? axisB : axisR) :
|
||||
((glen < blen) ? axisB : axisG);
|
||||
|
||||
//
|
||||
// We split each box into two by the plane that goes through given color
|
||||
// component (one of R,G,B as choosen above). Any of resulting split boxes
|
||||
// possibly can become smaller if we move one of the five its faces (the
|
||||
// sixth face sure can't move because it was checked before - the one that
|
||||
// is opposed to the just-created new face, in the place of split).
|
||||
// Here goes some ASCII art:
|
||||
//
|
||||
// C G K The initial color box ABCD-IJKL was split by a
|
||||
// *-------*-------* plane and two boxes ABCD-EFGH and EFGH-IJKL
|
||||
// /| /| /| were created. The boxes cannot be shrinked
|
||||
// B/ | F/ | J/ | by moving faces ABCD and IJKL (because the
|
||||
// *-------*-------* | boxes were previously adjusted and any surface
|
||||
// | *----|--*----|--* passes through at least one used color).
|
||||
// | /D | /H | /L Now we also see that if the left box
|
||||
// |/ |/ |/ can be shrinked by moving face, say, ABFE
|
||||
// *-------*-------* towards DCGH, it is impossible for the right
|
||||
// A E I box to be shrinked by moving EFJI towards HGKL,
|
||||
// because the previous whole face ABJI is known
|
||||
// to pass through at least one used color (and if it is not in the ABFE
|
||||
// are, then it is surely in the EFJI area). We can say the same about
|
||||
// the DCGH/HGKL, BCGF/FGKJ and ADHE/EHLI pairs.
|
||||
//
|
||||
switch (axis)
|
||||
{
|
||||
case axisR:
|
||||
srcbox.Rx = (srcbox.Rm + srcbox.Rx) / 2;
|
||||
dstbox.Rm = srcbox.Rx + 1;
|
||||
srcbox.ShrinkRx ();
|
||||
dstbox.ShrinkRm ();
|
||||
if (!srcbox.ShrinkGm ())
|
||||
dstbox.ShrinkGm ();
|
||||
if (!srcbox.ShrinkGx ())
|
||||
dstbox.ShrinkGx ();
|
||||
if (!srcbox.ShrinkBm ())
|
||||
dstbox.ShrinkBm ();
|
||||
if (!srcbox.ShrinkBx ())
|
||||
dstbox.ShrinkBx ();
|
||||
break;
|
||||
case axisG:
|
||||
srcbox.Gx = (srcbox.Gm + srcbox.Gx) / 2;
|
||||
dstbox.Gm = srcbox.Gx + 1;
|
||||
srcbox.ShrinkGx ();
|
||||
dstbox.ShrinkGm ();
|
||||
if (!srcbox.ShrinkRm ())
|
||||
dstbox.ShrinkRm ();
|
||||
if (!srcbox.ShrinkRx ())
|
||||
dstbox.ShrinkRx ();
|
||||
if (!srcbox.ShrinkBm ())
|
||||
dstbox.ShrinkBm ();
|
||||
if (!srcbox.ShrinkBx ())
|
||||
dstbox.ShrinkBx ();
|
||||
break;
|
||||
case axisB:
|
||||
srcbox.Bx = (srcbox.Bm + srcbox.Bx) / 2;
|
||||
dstbox.Bm = srcbox.Bx + 1;
|
||||
srcbox.ShrinkBx ();
|
||||
dstbox.ShrinkBm ();
|
||||
if (!srcbox.ShrinkRm ())
|
||||
dstbox.ShrinkRm ();
|
||||
if (!srcbox.ShrinkRx ())
|
||||
dstbox.ShrinkRx ();
|
||||
if (!srcbox.ShrinkGm ())
|
||||
dstbox.ShrinkGm ();
|
||||
if (!srcbox.ShrinkGx ())
|
||||
dstbox.ShrinkGx ();
|
||||
break;
|
||||
} /* endswitch */
|
||||
|
||||
dstbox.CountPixels ();
|
||||
srcbox.PixelCount -= dstbox.PixelCount;
|
||||
srcbox.ColorCount -= dstbox.ColorCount;
|
||||
srcbox.ComputeVolume ();
|
||||
dstbox.ComputeVolume ();
|
||||
} /* endwhile */
|
||||
|
||||
// Either we're out of splittable boxes, or we have palsize boxes.
|
||||
|
||||
// Assign successive palette indices to all boxes
|
||||
int count, delta = transp ? 1 : 0;
|
||||
color_index = new byte [boxcount + delta];
|
||||
for (count = 0; count < boxcount; count++)
|
||||
color_index [count] = count;
|
||||
// Sort palette indices by usage (a side bonus to quantization)
|
||||
qsort (color_index, boxcount, sizeof (byte), compare_boxes);
|
||||
|
||||
// Allocate the palette, if not already allocated
|
||||
if (!outpalette)
|
||||
outpalette = new SRGBPixel [maxcolors + delta];
|
||||
|
||||
// Fill the unused colormap entries with zeros
|
||||
memset (&outpalette [boxcount + delta], 0,
|
||||
(maxcolors - boxcount) * sizeof (SRGBPixel));
|
||||
|
||||
// Now compute the mean color for each box
|
||||
for (count = 0; count < boxcount; count++)
|
||||
box [color_index [count]].GetMeanColor (outpalette [count + delta]);
|
||||
|
||||
// If we have a transparent color, set colormap entry 0 to it
|
||||
if (delta)
|
||||
{
|
||||
for (count = boxcount; count; count--)
|
||||
color_index [count] = color_index [count - 1] + 1;
|
||||
color_index [0] = 0;
|
||||
outpalette [0] = SRGBPixel (0, 0, 0);
|
||||
}
|
||||
|
||||
maxcolors = boxcount + delta;
|
||||
}
|
||||
|
||||
void shQuantizeRemap (SRGBPixel *image, int pixels,
|
||||
byte *&outimage, SRGBPixel *transp)
|
||||
{
|
||||
// Sanity check
|
||||
if (qState != qsCount && qState != qsRemap)
|
||||
return;
|
||||
|
||||
int count;
|
||||
|
||||
// We will re-use the histogram memory for a inverse colormap. However, we
|
||||
// will need just a byte per element, so we'll assign the address of
|
||||
// histogram memory block to a pointer of suitable type, and the second
|
||||
// half of histogram storage remains unused.
|
||||
byte *icmap = (byte *)hist;
|
||||
|
||||
int delta = transp ? 1 : 0;
|
||||
if (qState == qsCount)
|
||||
{
|
||||
// Now, fill inverse colormap with color indices
|
||||
for (count = 0; count < boxcount; count++)
|
||||
box [color_index [count + delta] - delta].FillInverseCMap (icmap, count + delta);
|
||||
qState = qsRemap;
|
||||
}
|
||||
|
||||
// Allocate the picture and the palette
|
||||
if (!outimage) outimage = new byte [pixels];
|
||||
|
||||
unsigned long *src = (unsigned long *)image;
|
||||
byte *dst = outimage;
|
||||
count = pixels;
|
||||
|
||||
if (transp)
|
||||
{
|
||||
unsigned long tc = (*(unsigned long *)transp) & RGB_MASK;
|
||||
while (count--)
|
||||
{
|
||||
unsigned long pix = *src++;
|
||||
if (tc == (pix & RGB_MASK))
|
||||
*dst++ = 0;
|
||||
else
|
||||
*dst++ = icmap [INDEX_R (pix) + INDEX_G (pix) + INDEX_B (pix)];
|
||||
}
|
||||
}
|
||||
else
|
||||
while (count--)
|
||||
{
|
||||
unsigned long pix = *src++;
|
||||
*dst++ = icmap [INDEX_R (pix) + INDEX_G (pix) + INDEX_B (pix)];
|
||||
}
|
||||
}
|
||||
|
||||
void shQuantizeRemapDither (SRGBPixel *image, int pixels, int pixperline,
|
||||
SRGBPixel *palette, int colors, byte *&outimage, SRGBPixel *transp)
|
||||
{
|
||||
// Sanity check
|
||||
if (qState != qsCount && qState != qsRemap)
|
||||
return;
|
||||
|
||||
int count;
|
||||
|
||||
// We will re-use the histogram memory for a inverse colormap. However, we
|
||||
// will need just a byte per element, so we'll assign the address of
|
||||
// histogram memory block to a pointer of suitable type, and the second
|
||||
// half of histogram storage remains unused.
|
||||
byte *icmap = (byte *)hist;
|
||||
|
||||
int delta = transp ? 1 : 0;
|
||||
if (qState == qsCount)
|
||||
{
|
||||
// Build an inverse colormap (since during dithering we can get color
|
||||
// indices that did not existed in the original image)
|
||||
shInverseColormap (colors - delta, palette + delta,
|
||||
HIST_R_BITS, HIST_G_BITS, HIST_B_BITS, icmap);
|
||||
if (transp)
|
||||
for (int i = 0; i < HIST_R_MAX * HIST_G_MAX * HIST_B_MAX; i++)
|
||||
icmap [i]++;
|
||||
qState = qsRemap;
|
||||
}
|
||||
|
||||
// Allocate the picture and the palette
|
||||
if (!outimage) outimage = new byte [pixels];
|
||||
|
||||
SRGBPixel *src = image;
|
||||
byte *dst = outimage;
|
||||
count = pixels;
|
||||
|
||||
int *fserr = (int *)malloc (2 * 3 * (pixperline + 2) * sizeof (int));
|
||||
memset (fserr, 0, 3 * (pixperline + 2) * sizeof (int));
|
||||
// odd/even row
|
||||
unsigned char odd = 0;
|
||||
while (count > 0)
|
||||
{
|
||||
// The alogorithm implements the widely-known and used Floyd-Steinberg
|
||||
// error distribution - based dithering. The errors are distributed with
|
||||
// the following weights to the surrounding pixels:
|
||||
//
|
||||
// (here) 7/16
|
||||
// 3/16 5/16 1/16
|
||||
//
|
||||
// Even lines are traversed left to right, odd lines backwards.
|
||||
|
||||
SRGBPixel *cursrc;
|
||||
byte *curdst;
|
||||
int *curerr, *nexterr;
|
||||
int dir;
|
||||
|
||||
if (odd)
|
||||
{
|
||||
cursrc = src + pixperline - 1;
|
||||
curdst = dst + pixperline - 1;
|
||||
curerr = fserr + 2 * 3 * (pixperline + 2) - 6;
|
||||
nexterr = fserr + 3 * (pixperline + 2) - 3;
|
||||
dir = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursrc = src;
|
||||
curdst = dst;
|
||||
curerr = fserr + 3;
|
||||
nexterr = fserr + 3 * (pixperline + 2);
|
||||
dir = 1;
|
||||
}
|
||||
int dir3 = dir * 3;
|
||||
|
||||
// We will keep the errors for pixels (x+1, y) in the variable "err10",
|
||||
// the error for the pixel right below us (x, y + 1) in "err01", and
|
||||
// the error at (x + 1, y + 1) in "err11". The error for the pixel at
|
||||
// (x - 1, y + 1) will be flushed into the errors array. This way, we
|
||||
// will have just one memory read and one memory write per pixel.
|
||||
// Well, in fact we have much more (x86 is terribly lacking registers)
|
||||
// but anyway they go through the cache.
|
||||
int err10r = 0, err01r = 0, err11r = 0;
|
||||
int err10g = 0, err01g = 0, err11g = 0;
|
||||
int err10b = 0, err01b = 0, err11b = 0;
|
||||
|
||||
for (int fspix = pixperline; fspix; fspix--,
|
||||
cursrc += dir, curdst += dir,
|
||||
curerr += dir3, nexterr += dir3)
|
||||
{
|
||||
SRGBPixel srcpix = *cursrc;
|
||||
|
||||
if (transp && transp->eq (srcpix))
|
||||
{
|
||||
*curdst = 0;
|
||||
err10r = err10g = err10b = 0;
|
||||
nexterr [0] = err01r; nexterr [1] = err01g; nexterr [2] = err01b;
|
||||
err01r = err11r; err01g = err11g; err01b = err11b;
|
||||
err11r = err11g = err11b = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
int r = srcpix.red + ((err10r + curerr [0]) / 16);
|
||||
if (r < 0) r = 0; if (r > 255) r = 255;
|
||||
|
||||
int g = srcpix.green + ((err10g + curerr [1]) / 16);
|
||||
if (g < 0) g = 0; if (g > 255) g = 255;
|
||||
|
||||
int b = srcpix.blue + ((err10b + curerr [2]) / 16);
|
||||
if (b < 0) b = 0; if (b > 255) b = 255;
|
||||
|
||||
byte pix = icmap [((r >> (8 - HIST_R_BITS)) << (HIST_G_BITS + HIST_B_BITS)) |
|
||||
((g >> (8 - HIST_G_BITS)) << HIST_B_BITS) |
|
||||
((b >> (8 - HIST_B_BITS)))];
|
||||
*curdst = pix;
|
||||
|
||||
SRGBPixel realcolor = palette [pix];
|
||||
|
||||
err10r = r - realcolor.red;
|
||||
nexterr [0] = err01r + err10r * 3; // * 3
|
||||
err01r = err11r + err10r * 5; // * 5
|
||||
err11r = err10r; // * 1
|
||||
err10r *= 7; // * 7
|
||||
|
||||
err10g = g - realcolor.green;
|
||||
nexterr [1] = err01g + err10g * 3; // * 3
|
||||
err01g = err11g + err10g * 5; // * 5
|
||||
err11g = err10g; // * 1
|
||||
err10g *= 7; // * 7
|
||||
|
||||
err10b = b - realcolor.blue;
|
||||
nexterr [2] = err01b + err10b * 3; // * 3
|
||||
err01b = err11b + err10b * 5; // * 5
|
||||
err11b = err10b; // * 1
|
||||
err10b *= 7; // * 7
|
||||
}
|
||||
// flush cached errors into error array
|
||||
nexterr [0] = err01r;
|
||||
nexterr [1] = err01g;
|
||||
nexterr [2] = err01b;
|
||||
|
||||
src += pixperline;
|
||||
dst += pixperline;
|
||||
odd ^= 1;
|
||||
count -= pixperline;
|
||||
}
|
||||
free(fserr);
|
||||
}
|
||||
|
||||
void shQuantizeRGB (SRGBPixel *image, int pixels, int pixperline,
|
||||
byte *&outimage, SRGBPixel *&outpalette, int &maxcolors, bool dither)
|
||||
{
|
||||
shQuantizeBegin ();
|
||||
|
||||
shQuantizeCount (image, pixels);
|
||||
shQuantizePalette (outpalette, maxcolors);
|
||||
if (dither)
|
||||
shQuantizeRemapDither (image, pixels, pixperline, outpalette, maxcolors, outimage);
|
||||
else
|
||||
shQuantizeRemap (image, pixels, outimage);
|
||||
|
||||
shQuantizeEnd ();
|
||||
}
|
||||
28
RenderDll/Common/Textures/Image/Quantize.h
Normal file
28
RenderDll/Common/Textures/Image/Quantize.h
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
#ifndef __QUANTIZE_H__
|
||||
#define __QUANTIZE_H__
|
||||
|
||||
extern void shQuantizeRGB (SRGBPixel *image, int pixels, int pixperline,
|
||||
byte *&outimage, SRGBPixel *&outpalette, int &maxcolors, bool dither);
|
||||
|
||||
|
||||
/// Begin quantization
|
||||
extern void shQuantizeBegin ();
|
||||
/// Finish quantization
|
||||
extern void shQuantizeEnd ();
|
||||
/// Count the colors in a image and update the color histogram
|
||||
extern void shQuantizeCount (SRGBPixel *image, int pixels,
|
||||
SRGBPixel *transp = NULL);
|
||||
/// Bias the color histogram towards given colors (weight = 0..100)
|
||||
extern void shQuantizeBias (SRGBPixel *colors, int count, int weight);
|
||||
/// Compute the optimal palette for all images passed to QuantizeCount()
|
||||
extern void shQuantizePalette (SRGBPixel *&outpalette, int &maxcolors,
|
||||
SRGBPixel *transp = NULL);
|
||||
/// Remap a image to the palette computed by shQuantizePalette()
|
||||
extern void shQuantizeRemap (SRGBPixel *image, int pixels,
|
||||
byte *&outimage, SRGBPixel *transp = NULL);
|
||||
/// Same but apply Floyd-Steinberg dithering for nicer (but slower) results
|
||||
extern void shQuantizeRemapDither (SRGBPixel *image, int pixels, int pixperline,
|
||||
SRGBPixel *palette, int colors, byte *&outimage, SRGBPixel *transp = NULL);
|
||||
|
||||
#endif // __QUANTIZE_H__
|
||||
216
RenderDll/Common/Textures/Image/SHendian.h
Normal file
216
RenderDll/Common/Textures/Image/SHendian.h
Normal file
@@ -0,0 +1,216 @@
|
||||
#ifndef __SHENDIAN_H__
|
||||
#define __SHENDIAN_H__
|
||||
|
||||
#define CS_LITTLE_ENDIAN
|
||||
/*
|
||||
* This is a bit of overkill but if you're sure your CPU doesn't require
|
||||
* strict alignment add your CPU to the !defined below to get slightly
|
||||
* smaller and faster code in some cases.
|
||||
*/
|
||||
#if !defined (PROC_INTEL)
|
||||
# define PROC_NEEDS_STRICT_ALIGNMENT
|
||||
#endif
|
||||
|
||||
struct swap_4
|
||||
{
|
||||
unsigned char b1, b2, b3, b4;
|
||||
};
|
||||
|
||||
#ifdef CS_BIG_ENDIAN
|
||||
# define big_endian_long(x) x
|
||||
# define big_endian_short(x) x
|
||||
# define big_endian_float(x) x
|
||||
#else
|
||||
|
||||
/// Convert a long from big-endian to machine format
|
||||
static inline unsigned long big_endian_long (unsigned long l)
|
||||
{ return (l >> 24) | ((l >> 8) & 0xff00) | ((l << 8) & 0xff0000) | (l << 24); }
|
||||
|
||||
/// Convert a short from big-endian to machine format
|
||||
static inline ushort big_endian_short (ushort s)
|
||||
{ return (s >> 8) | (s << 8); }
|
||||
|
||||
/// Convert a big-endian floating-point number to machine format
|
||||
//@@WARNING: Should be removed -- use float2long instead
|
||||
static inline float big_endian_float (float f)
|
||||
{
|
||||
unsigned char tmp;
|
||||
swap_4 *pf = (swap_4 *)&f;
|
||||
tmp = pf->b1; pf->b1 = pf->b4; pf->b4 = tmp;
|
||||
tmp = pf->b2; pf->b2 = pf->b3; pf->b3 = tmp;
|
||||
return f;
|
||||
}
|
||||
|
||||
#endif // CS_BIG_ENDIAN
|
||||
|
||||
#ifdef CS_LITTLE_ENDIAN
|
||||
# define little_endian_long(x) x
|
||||
# define little_endian_short(x) x
|
||||
# define little_endian_float(x) x
|
||||
#else
|
||||
|
||||
/// Convert a long from little-endian to machine format
|
||||
static inline unsigned long little_endian_long (unsigned long l)
|
||||
{ return (l >> 24) | ((l >> 8) & 0xff00) | ((l << 8) & 0xff0000) | (l << 24); }
|
||||
|
||||
/// Convert a short from little-endian to machine format
|
||||
static inline ushort little_endian_short (ushort s)
|
||||
{ return (s >> 8) | (s << 8); }
|
||||
|
||||
/// Convert a little-endian floating-point number to machine format
|
||||
static inline float little_endian_float (float f)
|
||||
{
|
||||
unsigned char tmp;
|
||||
swap_4 *pf = (swap_4 *)&f;
|
||||
tmp = pf->b1; pf->b1 = pf->b4; pf->b4 = tmp;
|
||||
tmp = pf->b2; pf->b2 = pf->b3; pf->b3 = tmp;
|
||||
return f;
|
||||
}
|
||||
|
||||
#endif // CS_LITTLE_ENDIAN
|
||||
|
||||
/*
|
||||
To be able to painlessly transfer files betwen platforms, we should
|
||||
avoid using native floating-point format. Here are a couple of routines
|
||||
that are guaranteed to work on all platforms.
|
||||
|
||||
The floating point is converted to a fixed 1.7.25 bits format
|
||||
(one bit sign, 7 bits exponent, 25 bits mantissa) and back,
|
||||
so that we can binary store floating-point number without
|
||||
cross-platform problems. If you wonder why 1+7+25 = 33 while we
|
||||
only have 32 bits, we'll ommit the most significant bit of mantissa
|
||||
since it is always 1 (we use normalized numbers). This increases the
|
||||
precision twice.
|
||||
*/
|
||||
|
||||
/// Convert a float to a cross-platform 32-bit format (no endianess adjustments!)
|
||||
static inline long float2long (float f)
|
||||
{
|
||||
int exp;
|
||||
long mant = QRound ((float)frexp (f, &exp) * (float)0x1000000);
|
||||
long sign = mant & 0x80000000;
|
||||
if (mant < 0) mant = -mant;
|
||||
if (exp > 63) exp = 63; else if (exp < -64) exp = -64;
|
||||
return sign | ((exp & 0x7f) << 24) | (mant & 0xffffff);
|
||||
}
|
||||
|
||||
/// Convert a 32-bit cross-platform float to native format (no endianess adjustments!)
|
||||
static inline float long2float (long l)
|
||||
{
|
||||
int exp = (l >> 24) & 0x7f;
|
||||
if (exp & 0x40) exp = exp | ~0x7f;
|
||||
float mant = float (l & 0x00ffffff) / 0x1000000;
|
||||
if (l & 0x80000000) mant = -mant;
|
||||
return (float)ldexp (mant, exp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The following routines are used for converting floating-point numbers
|
||||
* into 16-bit shorts and back. This is useful for low-precision data.
|
||||
* They use the 1.4.12 format. The range of numbers that can be represented
|
||||
* in this format is from 2^-8 to 2^7. The precision for numbers near to
|
||||
* 2^-8 (0.00390625) is near 0.000001, for numbers near 2^7 (128) is near 0.03.
|
||||
*/
|
||||
|
||||
/// Convert a float to a cross-platform 16-bit format (no endianess adjustments!)
|
||||
static inline short float2short (float f)
|
||||
{
|
||||
int exp;
|
||||
long mant = QRound ((float)frexp (f, &exp) * (float)0x1000);
|
||||
long sign = mant & 0x8000;
|
||||
if (mant < 0) mant = -mant;
|
||||
if (exp > 7) mant = 0x7ff, exp = 7; else if (exp < -8) mant = 0, exp = -8;
|
||||
return (short)(sign | ((exp & 0xf) << 11) | (mant & 0x7ff));
|
||||
}
|
||||
|
||||
/// Convert a 16-bit cross-platform float to native format (no endianess adjustments!)
|
||||
static inline float short2float (short s)
|
||||
{
|
||||
int exp = (s >> 11) & 0xf;
|
||||
if (exp & 0x8) exp = exp | ~0xf;
|
||||
float mant = float ((s & 0x07ff) | 0x0800) / 0x1000;
|
||||
if (s & 0x8000) mant = -mant;
|
||||
return (float)ldexp (mant, exp);
|
||||
}
|
||||
|
||||
/// Swap the bytes in a unsigned long value.
|
||||
static inline unsigned long convert_endian (unsigned long l)
|
||||
{ return little_endian_long (l); }
|
||||
|
||||
/// Swap the bytes in a long value.
|
||||
static inline long convert_endian (long l)
|
||||
{ return little_endian_long (l); }
|
||||
|
||||
/// Swap the bytes in a int value.
|
||||
static inline int convert_endian (int i)
|
||||
{ return little_endian_long (i); }
|
||||
|
||||
/// Swap the bytes in a short value.
|
||||
static inline ushort convert_endian (ushort s)
|
||||
{ return little_endian_short (s); }
|
||||
|
||||
/// Swap the bytes in a float value.
|
||||
static inline float convert_endian (float f)
|
||||
{ return little_endian_float (f); }
|
||||
|
||||
/// Read a little-endian short from address
|
||||
inline ushort get_le_short (void *buff)
|
||||
{
|
||||
#ifdef PROC_NEEDS_STRICT_ALIGNMENT
|
||||
ushort s; memcpy (&s, buff, sizeof (s));
|
||||
return little_endian_short (s);
|
||||
#else
|
||||
return little_endian_short (*(ushort *)buff);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Read a little-endian long from address
|
||||
inline unsigned long get_le_long (void *buff)
|
||||
{
|
||||
#ifdef PROC_NEEDS_STRICT_ALIGNMENT
|
||||
unsigned long l; memcpy (&l, buff, sizeof (l));
|
||||
return little_endian_long (l);
|
||||
#else
|
||||
return little_endian_long (*(unsigned long *)buff);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Read a little-endian 32-bit float from address
|
||||
inline float get_le_float32 (void *buff)
|
||||
{ unsigned long l = get_le_long (buff); return long2float (l); }
|
||||
|
||||
/// Read a little-endian 16-bit float from address
|
||||
inline float get_le_float16 (void *buff)
|
||||
{ ushort s = get_le_short (buff); return short2float (s); }
|
||||
|
||||
/// Set a little-endian short on a address
|
||||
inline void set_le_short (void *buff, ushort s)
|
||||
{
|
||||
#ifdef PROC_NEEDS_STRICT_ALIGNMENT
|
||||
s = little_endian_short (s);
|
||||
memcpy (buff, &s, sizeof (s));
|
||||
#else
|
||||
*((ushort *)buff) = little_endian_short (s);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Set a little-endian long on a address
|
||||
inline void set_le_long (void *buff, unsigned long l)
|
||||
{
|
||||
#ifdef PROC_NEEDS_STRICT_ALIGNMENT
|
||||
l = little_endian_long (l);
|
||||
memcpy (buff, &l, sizeof (l));
|
||||
#else
|
||||
*((unsigned long *)buff) = little_endian_long (l);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Set a little-endian 32-bit float on a address
|
||||
inline void set_le_float32 (void *buff, float f)
|
||||
{ set_le_long (buff, float2long (f)); }
|
||||
|
||||
/// Set a little-endian 16-bit float on a address
|
||||
inline void set_le_float16 (void *buff, float f)
|
||||
{ set_le_short (buff, float2short (f)); }
|
||||
|
||||
#endif // __SHENDIAN_H__
|
||||
553
RenderDll/Common/Textures/Image/TgaImage.cpp
Normal file
553
RenderDll/Common/Textures/Image/TgaImage.cpp
Normal file
@@ -0,0 +1,553 @@
|
||||
/*=============================================================================
|
||||
TgaImage.cpp : TGA image file format implementation.
|
||||
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
||||
|
||||
Revision history:
|
||||
* Created by Khonich Andrey
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "RenderPCH.h"
|
||||
#include "CImage.h"
|
||||
#include "TgaImage.h"
|
||||
|
||||
|
||||
|
||||
#define MAXCOLORS 16384
|
||||
|
||||
static int mapped, rlencoded;
|
||||
|
||||
static SRGBPixel ColorMap[MAXCOLORS];
|
||||
static int RLE_count = 0, RLE_flag = 0;
|
||||
|
||||
static void readtga ( byte*& ptr, struct SImageHeader* tgaP );
|
||||
static void get_map_entry ( byte*& ptr, SRGBPixel* Value, int Size );
|
||||
static void get_pixel ( byte*& ptr, SRGBPixel* dest, int Size );
|
||||
static byte getbyte ( byte*& ptr );
|
||||
|
||||
CImageTgaFile::~CImageTgaFile ()
|
||||
{
|
||||
}
|
||||
|
||||
CImageTgaFile::CImageTgaFile (byte* ptr, long filesize) : CImageFile ()
|
||||
{
|
||||
(void)filesize;
|
||||
struct SImageHeader tga_head;
|
||||
int i;
|
||||
unsigned int temp1, temp2;
|
||||
int rows, cols, row, col, realrow, truerow, baserow;
|
||||
int maxval;
|
||||
SRGBPixel *pixels;
|
||||
|
||||
/* @@@ to do: Add TGA format detection */
|
||||
|
||||
/* Read the Targa file header. */
|
||||
readtga (ptr, &tga_head);
|
||||
|
||||
rows = ( (int) tga_head.Height_lo ) + ( (int) tga_head.Height_hi ) * 256;
|
||||
cols = ( (int) tga_head.Width_lo ) + ( (int) tga_head.Width_hi ) * 256;
|
||||
|
||||
m_eFormat = eIF_Tga;
|
||||
|
||||
switch ( tga_head.ImgType )
|
||||
{
|
||||
case TGA_Map:
|
||||
case TGA_RGB:
|
||||
case TGA_Mono:
|
||||
case TGA_RLEMap:
|
||||
case TGA_RLERGB:
|
||||
case TGA_RLEMono:
|
||||
break;
|
||||
|
||||
default:
|
||||
mfSet_error (eIFE_BadFormat, "Unknown Targa image type");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( tga_head.ImgType == TGA_Map ||
|
||||
tga_head.ImgType == TGA_RLEMap ||
|
||||
tga_head.ImgType == TGA_CompMap ||
|
||||
tga_head.ImgType == TGA_CompMap4 )
|
||||
{ /* Color-mapped image */
|
||||
if ( tga_head.CoMapType != 1 )
|
||||
{
|
||||
mfSet_error (eIFE_BadFormat, "Mapped image with bad color map type");
|
||||
return;
|
||||
}
|
||||
mapped = 1;
|
||||
/* Figure maxval from CoSize. */
|
||||
switch ( tga_head.CoSize )
|
||||
{
|
||||
case 8:
|
||||
case 24:
|
||||
case 32:
|
||||
maxval = 255;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
case 16:
|
||||
maxval = 31;
|
||||
break;
|
||||
|
||||
default:
|
||||
mfSet_error (eIFE_BadFormat, "Unknown colormap pixel size");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* Not colormap, so figure maxval from PixelSize. */
|
||||
mapped = 0;
|
||||
switch ( tga_head.PixelSize )
|
||||
{
|
||||
case 8:
|
||||
case 24:
|
||||
case 32:
|
||||
maxval = 255;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
case 16:
|
||||
maxval = 31;
|
||||
break;
|
||||
|
||||
default:
|
||||
mfSet_error (eIFE_BadFormat, "Unknown pixel size");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mfSet_bps(tga_head.PixelSize);
|
||||
|
||||
/* If required, read the color map information. */
|
||||
if ( tga_head.CoMapType != 0 )
|
||||
{
|
||||
temp1 = tga_head.Index_lo + tga_head.Index_hi * 256;
|
||||
temp2 = tga_head.Length_lo + tga_head.Length_hi * 256;
|
||||
if ( ( temp1 + temp2 + 1 ) >= MAXCOLORS )
|
||||
{
|
||||
mfSet_error (eIFE_BadFormat, "Too many colors in colormap");
|
||||
return;
|
||||
}
|
||||
for ( i = temp1; i < (int)( temp1 + temp2 ); ++i )
|
||||
get_map_entry( ptr, &ColorMap[i], (int) tga_head.CoSize );
|
||||
}
|
||||
|
||||
/* Check run-length encoding. */
|
||||
if ( tga_head.ImgType == TGA_RLEMap || tga_head.ImgType == TGA_RLERGB || tga_head.ImgType == TGA_RLEMono )
|
||||
rlencoded = 1;
|
||||
else
|
||||
rlencoded = 0;
|
||||
|
||||
/* Read the Targa file body and convert to portable format. */
|
||||
mfSet_dimensions (cols, rows);
|
||||
mfSet_ImageSize(cols * rows * 4);
|
||||
pixels = (SRGBPixel *)mfGet_image();
|
||||
|
||||
truerow = 0;
|
||||
baserow = 0;
|
||||
for ( row = 0; row < rows; ++row )
|
||||
{
|
||||
realrow = truerow;
|
||||
if ( tga_head.OrgBit == 0 )
|
||||
realrow = rows - realrow - 1;
|
||||
|
||||
for ( col = 0; col < cols; ++col )
|
||||
get_pixel( ptr, &(pixels[realrow*cols+col]), (int) tga_head.PixelSize );
|
||||
if ( tga_head.IntrLve == TGA_IL_Four )
|
||||
truerow += 4;
|
||||
else
|
||||
if ( tga_head.IntrLve == TGA_IL_Two )
|
||||
truerow += 2;
|
||||
else
|
||||
++truerow;
|
||||
if ( truerow >= rows )
|
||||
truerow = ++baserow;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void readtga (byte*& ptr, SImageHeader* tgaP)
|
||||
{
|
||||
byte flags;
|
||||
|
||||
tgaP->IDLength = getbyte( ptr );
|
||||
tgaP->CoMapType = getbyte( ptr );
|
||||
tgaP->ImgType = getbyte( ptr );
|
||||
tgaP->Index_lo = getbyte( ptr );
|
||||
tgaP->Index_hi = getbyte( ptr );
|
||||
tgaP->Length_lo = getbyte( ptr );
|
||||
tgaP->Length_hi = getbyte( ptr );
|
||||
tgaP->CoSize = getbyte( ptr );
|
||||
tgaP->X_org_lo = getbyte( ptr );
|
||||
tgaP->X_org_hi = getbyte( ptr );
|
||||
tgaP->Y_org_lo = getbyte( ptr );
|
||||
tgaP->Y_org_hi = getbyte( ptr );
|
||||
tgaP->Width_lo = getbyte( ptr );
|
||||
tgaP->Width_hi = getbyte( ptr );
|
||||
tgaP->Height_lo = getbyte( ptr );
|
||||
tgaP->Height_hi = getbyte( ptr );
|
||||
tgaP->PixelSize = getbyte( ptr );
|
||||
flags = getbyte( ptr );
|
||||
tgaP->AttBits = flags & 0xf;
|
||||
tgaP->Rsrvd = ( flags & 0x10 ) >> 4;
|
||||
tgaP->OrgBit = ( flags & 0x20 ) >> 5;
|
||||
tgaP->IntrLve = ( flags & 0xc0 ) >> 6;
|
||||
|
||||
if ( tgaP->IDLength != 0 )
|
||||
ptr += tgaP->IDLength;
|
||||
}
|
||||
|
||||
static void get_map_entry (byte*& ptr, SRGBPixel* Value, int Size)
|
||||
{
|
||||
byte j, k, r, g, b;
|
||||
r=g=b=0; /* get rid of 'might be used uninited' warning */
|
||||
|
||||
/* Read appropriate number of bytes, break into rgb & put in map. */
|
||||
switch ( Size )
|
||||
{
|
||||
case 8: /* Grey scale, read and triplicate. */
|
||||
r = g = b = getbyte( ptr );
|
||||
break;
|
||||
|
||||
case 16: /* 5 bits each of red green and blue. */
|
||||
case 15: /* Watch for byte order. */
|
||||
j = getbyte( ptr );
|
||||
k = getbyte( ptr );
|
||||
r = ( k & 0x7C ) >> 2;
|
||||
g = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 );
|
||||
b = j & 0x1F;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
case 24: /* 8 bits each of blue green and red. */
|
||||
b = getbyte( ptr );
|
||||
g = getbyte( ptr );
|
||||
r = getbyte( ptr );
|
||||
if ( Size == 32 )
|
||||
(void) getbyte( ptr ); /* Read alpha byte & throw away. */
|
||||
break;
|
||||
|
||||
default:
|
||||
//mfSet_error (eIFE_BadFormat, "Unknown colormap pixel size");
|
||||
return;
|
||||
}
|
||||
Value->red=r; Value->green=g; Value->blue=b;
|
||||
}
|
||||
|
||||
static void get_pixel (byte*& ptr, SRGBPixel* dest, int Size)
|
||||
{
|
||||
static int Red, Grn, Blu, Alpha;
|
||||
byte j, k;
|
||||
static unsigned int l;
|
||||
|
||||
if (Size != 32)
|
||||
Alpha = 255;
|
||||
/* Check if run length encoded. */
|
||||
if ( rlencoded )
|
||||
{
|
||||
if ( RLE_count == 0 )
|
||||
{ /* Have to restart run. */
|
||||
byte i;
|
||||
i = getbyte( ptr );
|
||||
RLE_flag = ( i & 0x80 );
|
||||
if ( RLE_flag == 0 )
|
||||
/* Stream of unencoded pixels. */
|
||||
RLE_count = i + 1;
|
||||
else
|
||||
/* Single pixel replicated. */
|
||||
RLE_count = i - 127;
|
||||
/* Decrement count & get pixel. */
|
||||
--RLE_count;
|
||||
}
|
||||
else
|
||||
{ /* Have already read count & (at least) first pixel. */
|
||||
--RLE_count;
|
||||
if ( RLE_flag != 0 )
|
||||
/* Replicated pixels. */
|
||||
goto PixEncode;
|
||||
}
|
||||
}
|
||||
/* Read appropriate number of bytes, break into RGB. */
|
||||
switch ( Size )
|
||||
{
|
||||
case 8: /* Grey scale, read and triplicate. */
|
||||
Red = Grn = Blu = l = getbyte( ptr );
|
||||
break;
|
||||
|
||||
case 16: /* 5 bits each of red green and blue. */
|
||||
case 15: /* Watch byte order. */
|
||||
j = getbyte( ptr );
|
||||
k = getbyte( ptr );
|
||||
l = ( (unsigned int) k << 8 ) + j;
|
||||
Red = ( k & 0x7C ) >> 2;
|
||||
Grn = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 );
|
||||
Blu = j & 0x1F;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
case 24: /* 8 bits each of blue green and red. */
|
||||
Blu = getbyte( ptr );
|
||||
Grn = getbyte( ptr );
|
||||
Red = getbyte( ptr );
|
||||
if ( Size == 32 )
|
||||
Alpha = getbyte( ptr ); /* Read alpha byte & throw away. */
|
||||
l = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
//mfSet_error (eIFE_BadFormat, "Unknown pixel size");
|
||||
return;
|
||||
}
|
||||
|
||||
PixEncode:
|
||||
if ( mapped )
|
||||
*dest = ColorMap[l];
|
||||
else
|
||||
{
|
||||
dest->red=Red;dest->green=Grn;dest->blue=Blu;
|
||||
dest->alpha = Alpha;
|
||||
}
|
||||
}
|
||||
|
||||
static byte getbyte (byte*& ptr)
|
||||
{
|
||||
byte c = *ptr++;
|
||||
return c;
|
||||
}
|
||||
|
||||
//=============================================================
|
||||
|
||||
#if !defined(LINUX)
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
static FILE *sFileData;
|
||||
static int src_bits_per_pixel;
|
||||
|
||||
static void bwrite(unsigned char data)
|
||||
{
|
||||
fputc(data, sFileData);
|
||||
}
|
||||
|
||||
void wwrite(unsigned short data)
|
||||
{
|
||||
unsigned char h, l;
|
||||
|
||||
l = data & 0xFF;
|
||||
h = data >> 8;
|
||||
bwrite(l);
|
||||
bwrite(h);
|
||||
}
|
||||
|
||||
|
||||
static void WritePixel(int depth, unsigned long a, unsigned long r, unsigned long g, unsigned long b)
|
||||
{
|
||||
DWORD color16;
|
||||
|
||||
switch(depth)
|
||||
{
|
||||
case 32:
|
||||
bwrite((byte)b); // b
|
||||
bwrite((byte)g); // g
|
||||
bwrite((byte)r); // r
|
||||
bwrite((byte)a); // a
|
||||
break;
|
||||
|
||||
case 24:
|
||||
bwrite((byte)b); // b
|
||||
bwrite((byte)g); // g
|
||||
bwrite((byte)r); // r
|
||||
break;
|
||||
|
||||
case 16:
|
||||
r >>= 3;
|
||||
g >>= 3;
|
||||
b >>= 3;
|
||||
|
||||
r &= 0x1F;
|
||||
g &= 0x1F;
|
||||
b &= 0x1F;
|
||||
|
||||
color16 = (r << 10) | (g << 5) | b;
|
||||
|
||||
wwrite((unsigned short)color16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void GetPixel(unsigned char * data, int depth, unsigned long &a, unsigned long &r, unsigned long &g, unsigned long &b)
|
||||
{
|
||||
switch(depth)
|
||||
{
|
||||
case 32:
|
||||
r = *data++;
|
||||
g = *data++;
|
||||
b = *data++;
|
||||
a = *data++;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
r = *data++;
|
||||
g = *data++;
|
||||
b = *data++;
|
||||
a = 0xFF;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WriteTGA8(byte *data8, int width, int height, char *filename)
|
||||
{
|
||||
unsigned char * data32 = new unsigned char [width*height*4];
|
||||
for(int i=0; i<width*height; i++)
|
||||
{
|
||||
data32[i*4+0] = data8[i];
|
||||
data32[i*4+1] = data8[i];
|
||||
data32[i*4+2] = data8[i];
|
||||
data32[i*4+3] = 255;
|
||||
}
|
||||
|
||||
WriteTGA(data32, width, height, filename, 32);
|
||||
delete [] data32;
|
||||
}
|
||||
|
||||
void WriteTGA(byte *data, int width, int height, char *filename, int dest_bits_per_pixel)
|
||||
{
|
||||
#ifndef PS2
|
||||
int i;
|
||||
unsigned long r,g,b,a;
|
||||
|
||||
src_bits_per_pixel = 32;
|
||||
|
||||
if ((sFileData = fopen(filename, "wb")) == NULL)
|
||||
return;
|
||||
|
||||
//mdesc |= LR; // left right
|
||||
//m_desc |= UL_TGA_BT; // top
|
||||
|
||||
int id_length = 0;
|
||||
int x_org = 0;
|
||||
int y_org = 0;
|
||||
int desc = 0;
|
||||
|
||||
// 32 bpp
|
||||
|
||||
int cm_index = 0;
|
||||
int cm_length = 0;
|
||||
int cm_entry_size = 0;
|
||||
int color_map_type = 0;
|
||||
|
||||
int type = 2;
|
||||
|
||||
bwrite(id_length);
|
||||
bwrite(color_map_type);
|
||||
bwrite(type);
|
||||
|
||||
wwrite(cm_index);
|
||||
wwrite(cm_length);
|
||||
|
||||
bwrite(cm_entry_size);
|
||||
|
||||
wwrite(x_org);
|
||||
wwrite(y_org);
|
||||
wwrite((unsigned short) width);
|
||||
wwrite((unsigned short) height);
|
||||
|
||||
bwrite( dest_bits_per_pixel );
|
||||
|
||||
bwrite(desc);
|
||||
|
||||
int hxw = height * width;
|
||||
|
||||
int right = 0;
|
||||
int top = 1;
|
||||
|
||||
DWORD * temp_dp = (DWORD*) data; // data = input pointer
|
||||
|
||||
DWORD * swap = 0;
|
||||
|
||||
|
||||
if( !top )
|
||||
{
|
||||
assert( src_bits_per_pixel == 32 );
|
||||
|
||||
swap = (DWORD *) new DWORD[ hxw ];
|
||||
|
||||
// copy whole image data to swap buffer
|
||||
cryMemcpy(swap, temp_dp, hxw * sizeof( DWORD ));
|
||||
|
||||
DWORD * src, * dest;
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
// copy lines from old into new buffer
|
||||
|
||||
src = & temp_dp[ ( height - i - 1) * width ];
|
||||
|
||||
dest = & swap[ i * width ];
|
||||
|
||||
cryMemcpy(dest, src, width * sizeof(DWORD) );
|
||||
}
|
||||
// use the swapped area in further processing & to write out the data
|
||||
data = (unsigned char *)swap;
|
||||
}
|
||||
|
||||
UINT src_bytes_per_pixel = src_bits_per_pixel / 8;
|
||||
|
||||
UINT size_in_bytes = hxw * src_bytes_per_pixel;
|
||||
|
||||
if( src_bits_per_pixel == dest_bits_per_pixel)
|
||||
{
|
||||
fwrite(data, hxw, src_bytes_per_pixel, sFileData);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < hxw; i++)
|
||||
{
|
||||
GetPixel( data, src_bits_per_pixel, a, b, g, r);
|
||||
WritePixel( dest_bits_per_pixel, a, b, g, r);
|
||||
data += src_bytes_per_pixel;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(sFileData);
|
||||
|
||||
SAFE_DELETE_ARRAY(swap);
|
||||
#else
|
||||
OutputDebugString("Not Implemented");
|
||||
#endif
|
||||
}
|
||||
|
||||
void BlurImage8(byte * pImage, int nSize, int nPassesNum)
|
||||
{
|
||||
#define DATA_TMP(_x,_y) (pTemp [(_x)+nSize*(_y)])
|
||||
#define DATA_IMG(_x,_y) (pImage[(_x)+nSize*(_y)])
|
||||
|
||||
byte * pTemp = new byte [nSize*nSize];
|
||||
|
||||
for(int nPass=0; nPass<nPassesNum; nPass++)
|
||||
{
|
||||
cryMemcpy(pTemp,pImage,nSize*nSize);
|
||||
|
||||
for(int x=1; x<nSize-1; x++)
|
||||
for(int y=1; y<nSize-1; y++)
|
||||
{
|
||||
float fVal = 0;
|
||||
fVal += DATA_TMP(x,y);
|
||||
fVal += DATA_TMP(x+1,y+1);
|
||||
fVal += DATA_TMP(x-1,y+1);
|
||||
fVal += DATA_TMP(x+1,y-1);
|
||||
fVal += DATA_TMP(x-1,y-1);
|
||||
DATA_IMG(x,y) = uchar(fVal*0.2f);
|
||||
}
|
||||
}
|
||||
|
||||
delete [] pTemp;
|
||||
|
||||
#undef DATA_IMG
|
||||
#undef DATA_TMP
|
||||
}
|
||||
60
RenderDll/Common/Textures/Image/TgaImage.h
Normal file
60
RenderDll/Common/Textures/Image/TgaImage.h
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
#ifndef TGAIMAGE_H
|
||||
#define TGAIMAGE_H
|
||||
|
||||
/**
|
||||
* An ImageFile subclass for reading TGA files.
|
||||
*/
|
||||
class CImageTgaFile : public CImageFile
|
||||
{
|
||||
///
|
||||
friend class CImageFile; // For constructor
|
||||
|
||||
private:
|
||||
/// Read the TGA file from the buffer.
|
||||
CImageTgaFile (byte* buf, long size);
|
||||
|
||||
public:
|
||||
///
|
||||
virtual ~CImageTgaFile ();
|
||||
};
|
||||
|
||||
/* Header definition. */
|
||||
struct SImageHeader {
|
||||
unsigned char IDLength; /* length of Identifier String */
|
||||
unsigned char CoMapType; /* 0 = no map */
|
||||
unsigned char ImgType; /* image type (see below for values) */
|
||||
unsigned char Index_lo, Index_hi; /* index of first color map entry */
|
||||
unsigned char Length_lo, Length_hi; /* number of entries in color map */
|
||||
unsigned char CoSize; /* size of color map entry (15,16,24,32) */
|
||||
unsigned char X_org_lo, X_org_hi; /* x origin of image */
|
||||
unsigned char Y_org_lo, Y_org_hi; /* y origin of image */
|
||||
unsigned char Width_lo, Width_hi; /* width of image */
|
||||
unsigned char Height_lo, Height_hi; /* height of image */
|
||||
unsigned char PixelSize; /* pixel size (8,16,24,32) */
|
||||
unsigned char AttBits; /* 4 bits, number of attribute bits per pixel */
|
||||
unsigned char Rsrvd; /* 1 bit, reserved */
|
||||
unsigned char OrgBit; /* 1 bit, origin: 0=lower left, 1=upper left */
|
||||
unsigned char IntrLve; /* 2 bits, interleaving flag */
|
||||
};
|
||||
|
||||
typedef char ImageIDField[256];
|
||||
|
||||
/* Definitions for image types. */
|
||||
#define TGA_Null 0
|
||||
#define TGA_Map 1
|
||||
#define TGA_RGB 2
|
||||
#define TGA_Mono 3
|
||||
#define TGA_RLEMap 9
|
||||
#define TGA_RLERGB 10
|
||||
#define TGA_RLEMono 11
|
||||
#define TGA_CompMap 32
|
||||
#define TGA_CompMap4 33
|
||||
|
||||
/* Definitions for interleave flag. */
|
||||
#define TGA_IL_None 0
|
||||
#define TGA_IL_Two 1
|
||||
#define TGA_IL_Four 2
|
||||
|
||||
#endif
|
||||
|
||||
185
RenderDll/Common/Textures/Image/XtfImage.cpp
Normal file
185
RenderDll/Common/Textures/Image/XtfImage.cpp
Normal file
@@ -0,0 +1,185 @@
|
||||
#if !defined(LINUX)
|
||||
|
||||
#include "XtfImage.h"
|
||||
|
||||
CImageXtfFile::CImageXtfFile(byte* ptr, long filesize)
|
||||
{
|
||||
/* SXtfHeader *pMyTexture = (SXtfHeader *)ptr;
|
||||
u_char *pRawData = ptr+sizeof(SXtfHeader);
|
||||
|
||||
|
||||
//Check type
|
||||
if(pMyTexture->Type!=XTF_FILE_TYPE)
|
||||
{
|
||||
mfSet_error(eIFE_BadFormat,"File Type Error");
|
||||
}
|
||||
|
||||
//Check version
|
||||
if(pMyTexture->Version!=XTF_FILE_VERSION)
|
||||
{
|
||||
mfSet_error(eIFE_BadFormat,"File Version Error");
|
||||
}
|
||||
|
||||
mfSet_dimensions(pMyTexture->Info.m_Width,pMyTexture->Info.m_Height);
|
||||
|
||||
//Set the image raw data
|
||||
SRGBPixel *CurImage = mfGet_image();
|
||||
|
||||
memcpy(CurImage,MyTexture->Info.m_pData32,MyTexture->Info.m_Width*MyTexture->Info.m_Height*2);
|
||||
|
||||
mfSet_Flags(MyTexture->Info.Flags);
|
||||
*/
|
||||
OutputDebugString("Constructor non supported");
|
||||
mfSet_error(eIFE_BadFormat,"");
|
||||
}
|
||||
|
||||
CImageXtfFile::~CImageXtfFile ()
|
||||
{
|
||||
}
|
||||
|
||||
bool CImageXtfFile::CImageXtfFileSave(const char *name, STexPic *pTexture)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
SXtfHeader MyTexture;
|
||||
FILE *MyFile;
|
||||
char NewName[255];
|
||||
|
||||
if(name)
|
||||
{
|
||||
strcpy(NewName,name);
|
||||
if(NewName[strlen(NewName)-4]=='.')
|
||||
NewName[strlen(NewName)-4]='\0';
|
||||
else
|
||||
if(NewName[strlen(NewName)-3]=='.')
|
||||
NewName[strlen(NewName)-3]='\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(NewName,0,255);
|
||||
int PathLength=strlen(pTexture->m_Pak);
|
||||
int i=0;
|
||||
while((i<PathLength) && pTexture->m_Pak[i]!='.' )
|
||||
{
|
||||
NewName[i]=pTexture->m_Pak[i];
|
||||
i++;
|
||||
}
|
||||
if (pTexture->m_Pak[i]=='.')
|
||||
{
|
||||
while((i>=0) && pTexture->m_Pak[i]!='\\' )
|
||||
{
|
||||
i--;
|
||||
}
|
||||
NewName[i]=0;
|
||||
}
|
||||
strcat(NewName,"\\");
|
||||
strcat(NewName,pTexture->m_Name);
|
||||
}
|
||||
|
||||
|
||||
strcat(NewName,".xtf");
|
||||
MyFile=fopen(NewName,"w");
|
||||
if(!MyFile)
|
||||
return false;
|
||||
|
||||
MyTexture.Type = XTF_FILE_TYPE;
|
||||
MyTexture.Version = XTF_FILE_VERSION;
|
||||
MyTexture.Info = *pTexture;
|
||||
|
||||
fwrite(&MyTexture,sizeof(SXtfHeader),1,MyFile);
|
||||
fwrite((const void *)pTexture->m_pData32,pTexture->m_Width*pTexture->m_Height*2,1,MyFile);
|
||||
|
||||
fclose(MyFile);
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CImageXtfFile::CImageXtfFileSave(const char *name, u_char *pTexture, u_int dimx, u_int dimy)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
SXtfHeader MyTexture;
|
||||
FILE *MyFile;
|
||||
char NewName[255];
|
||||
|
||||
strcpy(NewName,name);
|
||||
NewName[strlen(NewName)-4]='\0';
|
||||
strcat(NewName,".xtf");
|
||||
MyFile=fopen(NewName,"w");
|
||||
if(!MyFile)
|
||||
return false;
|
||||
|
||||
MyTexture.Type = XTF_FILE_TYPE;
|
||||
MyTexture.Version = XTF_FILE_VERSION;
|
||||
MyTexture.Info.m_Width=dimx;
|
||||
MyTexture.Info.m_Height=dimy;
|
||||
MyTexture.Info.m_pData32=pTexture;
|
||||
|
||||
fwrite(&MyTexture,sizeof(SXtfHeader),1,MyFile);
|
||||
fwrite((const void *)MyTexture.Info.m_pData32,MyTexture.Info.m_Width*MyTexture.Info.m_Height*2,1,MyFile);
|
||||
|
||||
fclose(MyFile);
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
///Load the texture in .xtf file format
|
||||
STexPic* CImageXtfFile::CImageXtfFileLoad (const char *FileName)
|
||||
{
|
||||
FILE *TextureFile;
|
||||
SXtfHeader *MyTexture;
|
||||
STexPic *pTexturePic;
|
||||
u_char *pRawData;
|
||||
|
||||
TextureFile=fopen(FileName,"r");
|
||||
if(!TextureFile)
|
||||
{
|
||||
mfSet_error(eIFE_BadFormat,"File Not Found");
|
||||
return NULL;
|
||||
}
|
||||
u_int FileSize=CXFile::GetLength(FileName);
|
||||
|
||||
|
||||
MyTexture = new SXtfHeader;
|
||||
pRawData = new u_char[FileSize-sizeof(SXtfHeader)];
|
||||
fread(MyTexture,sizeof(SXtfHeader),1,TextureFile);
|
||||
fread(pRawData,FileSize-sizeof(SXtfHeader),1,TextureFile);
|
||||
|
||||
|
||||
//Check type
|
||||
if(MyTexture->Type!=XTF_FILE_TYPE)
|
||||
{
|
||||
delete MyTexture;
|
||||
fclose(TextureFile);
|
||||
mfSet_error(eIFE_BadFormat,"File Type Error");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Check version
|
||||
if(MyTexture->Version!=XTF_FILE_VERSION)
|
||||
{
|
||||
delete MyTexture;
|
||||
fclose(TextureFile);
|
||||
mfSet_error(eIFE_BadFormat,"File Version Error");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
MyTexture->Info.m_pData32=pRawData;
|
||||
|
||||
fclose(TextureFile);
|
||||
mfSet_error(eIFE_OK,"");
|
||||
|
||||
pTexturePic = new STexPic;
|
||||
*pTexturePic = MyTexture->Info;
|
||||
|
||||
pTexturePic->m_WidthReal=MyTexture->Info.m_Width;
|
||||
pTexturePic->m_HeightReal=MyTexture->Info.m_Height;
|
||||
|
||||
delete MyTexture;
|
||||
|
||||
return pTexturePic;
|
||||
}
|
||||
|
||||
#endif
|
||||
55
RenderDll/Common/Textures/Image/XtfImage.h
Normal file
55
RenderDll/Common/Textures/Image/XtfImage.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
**----------------------------------------------------------------------------
|
||||
**
|
||||
** Xtf File load/save for PS2
|
||||
**
|
||||
** (C) 2002, Ubi Soft
|
||||
**
|
||||
** Author: Tiziano Sardone
|
||||
**----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef XTFIMAGE_H
|
||||
#define XTFIMAGE_H
|
||||
|
||||
#define XTF_FILE_TYPE 0xABBA ///<file type
|
||||
#define XTF_FILE_VERSION 0x0001 ///<file version
|
||||
|
||||
///Xtf file format
|
||||
typedef struct _SXtfHeader
|
||||
{
|
||||
u_short Type; ///<File version
|
||||
u_short Version; ///<File version
|
||||
STexPic Info; ///<Texture information
|
||||
u_char Pad __attribute__ ( ( aligned( 16 ) ) );
|
||||
}SXtfHeader;
|
||||
|
||||
|
||||
/**
|
||||
* An ImageFile subclass for reading XTF files.
|
||||
*/
|
||||
class CImageXtfFile : public CImageFile
|
||||
{
|
||||
///
|
||||
friend class CImageFile; // For constructor
|
||||
|
||||
SXtfHeader XtfFile;
|
||||
|
||||
private:
|
||||
CImageXtfFile (void);
|
||||
CImageXtfFile(byte* ptr, long filesize);
|
||||
|
||||
static bool CImageXtfFileSave(const char *name, STexPic *pTexture);
|
||||
static bool CImageXtfFileSave(const char *name, u_char *pTexture, u_int dimx, u_int dimy);
|
||||
|
||||
/// Read the XTF file
|
||||
static STexPic* CImageXtfFileLoad (const char *Filename);
|
||||
public:
|
||||
///
|
||||
virtual ~CImageXtfFile ();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
BIN
RenderDll/Common/Textures/Image/ZLib.lib
Normal file
BIN
RenderDll/Common/Textures/Image/ZLib.lib
Normal file
Binary file not shown.
104
RenderDll/Common/Textures/Image/dds.h
Normal file
104
RenderDll/Common/Textures/Image/dds.h
Normal file
@@ -0,0 +1,104 @@
|
||||
// dds.h
|
||||
//
|
||||
// This header defines constants and structures that are useful when parsing
|
||||
// DDS files. DDS files were originally designed to use several structures
|
||||
// and constants that are native to DirectDraw and are defined in ddraw.h,
|
||||
// such as DDSURFACEDESC2 and DDSCAPS2. This file defines similar
|
||||
// (compatible) constants and structures so that one can use DDS files
|
||||
// without needing to include ddraw.h.
|
||||
|
||||
#ifndef _DDS_H_
|
||||
#define _DDS_H_
|
||||
|
||||
struct DDS_PIXELFORMAT
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwFlags;
|
||||
DWORD dwFourCC;
|
||||
DWORD dwRGBBitCount;
|
||||
DWORD dwRBitMask;
|
||||
DWORD dwGBitMask;
|
||||
DWORD dwBBitMask;
|
||||
DWORD dwABitMask;
|
||||
};
|
||||
|
||||
#define DDS_FOURCC 0x00000004 // DDPF_FOURCC
|
||||
#define DDS_RGB 0x00000040 // DDPF_RGB
|
||||
#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE
|
||||
#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_DXT1 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_DXT2 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','2'), 0, 0, 0, 0, 0 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_DXT3 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_DXT4 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_DXT5 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_A8R8G8B8 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_A1R5G5B5 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_A4R4G4B4 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x0000f000, 0x000000f0, 0x0000000f, 0x0000f000 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_R8G8B8 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 };
|
||||
|
||||
const DDS_PIXELFORMAT DDSPF_R5G6B5 =
|
||||
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 };
|
||||
|
||||
#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
|
||||
#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT
|
||||
#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH
|
||||
#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH
|
||||
#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE
|
||||
|
||||
#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE
|
||||
#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
|
||||
#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX
|
||||
|
||||
#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX
|
||||
#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX
|
||||
#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY
|
||||
#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY
|
||||
#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ
|
||||
#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ
|
||||
|
||||
#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\
|
||||
DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\
|
||||
DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ )
|
||||
|
||||
#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME
|
||||
|
||||
#define DDS_RESF1_NORMALMAP 0x01000000
|
||||
#define DDS_RESF1_DSDT 0x02000000
|
||||
|
||||
|
||||
struct DDS_HEADER
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwHeaderFlags;
|
||||
DWORD dwHeight;
|
||||
DWORD dwWidth;
|
||||
DWORD dwPitchOrLinearSize;
|
||||
DWORD dwDepth; // only if DDS_HEADER_FLAGS_VOLUME is set in dwHeaderFlags
|
||||
DWORD dwMipMapCount;
|
||||
DWORD dwReserved1[11];
|
||||
DDS_PIXELFORMAT ddspf;
|
||||
DWORD dwSurfaceFlags;
|
||||
DWORD dwCubemapFlags;
|
||||
DWORD dwReserved2[3];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
1518
RenderDll/Common/Textures/Image/ijl.h
Normal file
1518
RenderDll/Common/Textures/Image/ijl.h
Normal file
File diff suppressed because it is too large
Load Diff
454
RenderDll/Common/Textures/Image/inv_cmap.cpp
Normal file
454
RenderDll/Common/Textures/Image/inv_cmap.cpp
Normal file
@@ -0,0 +1,454 @@
|
||||
/*=============================================================================
|
||||
inv_cmap.cpp :
|
||||
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
||||
|
||||
Revision history:
|
||||
* Created by Honitch Andrey
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "RenderPCH.h"
|
||||
#include "CImage.h"
|
||||
|
||||
static int bcenter, gcenter, rcenter;
|
||||
static long gdist, rdist, cdist;
|
||||
static long cbinc, cginc, crinc;
|
||||
static unsigned long *gdp, *rdp, *cdp;
|
||||
static unsigned char *grgbp, *rrgbp, *crgbp;
|
||||
static long gstride, rstride;
|
||||
static long rx, gx, bx;
|
||||
static long rxsqr, gxsqr, bxsqr;
|
||||
static long rcolormax, gcolormax, bcolormax;
|
||||
static int cindex;
|
||||
|
||||
static void maxfill (unsigned long *, long, long, long);
|
||||
static int redloop (void);
|
||||
static int greenloop (int);
|
||||
static int blueloop (int);
|
||||
|
||||
/*
|
||||
* Here's the idea: scan from the "center" of each cell "out"
|
||||
* until we hit the "edge" of the cell -- that is, the point
|
||||
* at which some other color is closer -- and stop. In 1-D,
|
||||
* this is simple:
|
||||
* for i := here to max do
|
||||
* if closer then buffer[i] = this color
|
||||
* else break
|
||||
* repeat above loop with i := here-1 to min by -1
|
||||
*
|
||||
* In 2-D, it's trickier, because along a "scan-line", the
|
||||
* region might start "after" the "center" point. A picture
|
||||
* might clarify:
|
||||
* | ...
|
||||
* | ... .
|
||||
* ... .
|
||||
* ... | .
|
||||
* . + .
|
||||
* . .
|
||||
* . .
|
||||
* .........
|
||||
*
|
||||
* The + marks the "center" of the above region. On the top 2
|
||||
* lines, the region "begins" to the right of the "center".
|
||||
*
|
||||
* Thus, we need a loop like this:
|
||||
* detect := false
|
||||
* for i := here to max do
|
||||
* if closer then
|
||||
* buffer[..., i] := this color
|
||||
* if !detect then
|
||||
* here = i
|
||||
* detect = true
|
||||
* else
|
||||
* if detect then
|
||||
* break
|
||||
*
|
||||
* Repeat the above loop with i := here-1 to min by -1. Note that
|
||||
* the "detect" value should not be reinitialized. If it was
|
||||
* "true", and center is not inside the cell, then none of the
|
||||
* cell lies to the left and this loop should exit
|
||||
* immediately.
|
||||
*
|
||||
* The outer loops are similar, except that the "closer" test
|
||||
* is replaced by a call to the "next in" loop; its "detect"
|
||||
* value serves as the test. (No assignment to the buffer is
|
||||
* done, either.)
|
||||
*
|
||||
* Each time an outer loop starts, the "here", "min", and
|
||||
* "max" values of the next inner loop should be
|
||||
* re-initialized to the center of the cell, 0, and cube size,
|
||||
* respectively. Otherwise, these values will carry over from
|
||||
* one "call" to the inner loop to the next. This tracks the
|
||||
* edges of the cell and minimizes the number of
|
||||
* "unproductive" comparisons that must be made.
|
||||
*
|
||||
* Finally, the inner-most loop can have the "if !detect"
|
||||
* optimized out of it by splitting it into two loops: one
|
||||
* that finds the first color value on the scan line that is
|
||||
* in this cell, and a second that fills the cell until
|
||||
* another one is closer:
|
||||
* if !detect then {needed for "down" loop}
|
||||
* for i := here to max do
|
||||
* if closer then
|
||||
* buffer[..., i] := this color
|
||||
* detect := true
|
||||
* break
|
||||
* for i := i+1 to max do
|
||||
* if closer then
|
||||
* buffer[..., i] := this color
|
||||
* else
|
||||
* break
|
||||
*
|
||||
* In this implementation, each level will require the
|
||||
* following variables. Variables labelled (l) are local to each
|
||||
* procedure. The ? should be replaced with r, g, or b:
|
||||
* cdist: The distance at the starting point.
|
||||
* ?center: The value of this component of the color
|
||||
* c?inc: The initial increment at the ?center position.
|
||||
* ?stride: The amount to add to the buffer
|
||||
* pointers (dp and rgbp) to get to the
|
||||
* "next row".
|
||||
* min(l): The "low edge" of the cell, init to 0
|
||||
* max(l): The "high edge" of the cell, init to
|
||||
* colormax-1
|
||||
* detect(l): True if this row has changed some
|
||||
* buffer entries.
|
||||
* i(l): The index for this row.
|
||||
* ?xx: The accumulated increment value.
|
||||
*
|
||||
* here(l): The starting index for this color. The
|
||||
* following variables are associated with here,
|
||||
* in the sense that they must be updated if here
|
||||
* is changed.
|
||||
* ?dist: The current distance for this level. The
|
||||
* value of dist from the previous level (g or r,
|
||||
* for level b or g) initializes dist on this
|
||||
* level. Thus gdist is associated with here(b)).
|
||||
* ?inc: The initial increment for the row.
|
||||
* ?dp: Pointer into the distance buffer. The value
|
||||
* from the previous level initializes this level.
|
||||
* ?rgbp: Pointer into the rgb buffer. The value
|
||||
* from the previous level initializes this level.
|
||||
*
|
||||
* The blue and green levels modify 'here-associated' variables (dp,
|
||||
* rgbp, dist) on the green and red levels, respectively, when here is
|
||||
* changed.
|
||||
*/
|
||||
|
||||
void shInverseColormap (int colors, SRGBPixel *colormap,
|
||||
int rbits, int gbits, int bbits, byte *&rgbmap, unsigned long *dist_buf)
|
||||
{
|
||||
int rnbits = 8 - rbits;
|
||||
int gnbits = 8 - gbits;
|
||||
int bnbits = 8 - bbits;
|
||||
|
||||
rcolormax = 1 << rbits;
|
||||
gcolormax = 1 << gbits;
|
||||
bcolormax = 1 << bbits;
|
||||
rx = 1 << rnbits;
|
||||
gx = 1 << gnbits;
|
||||
bx = 1 << bnbits;
|
||||
rxsqr = 1 << (2 * rnbits);
|
||||
gxsqr = 1 << (2 * gnbits);
|
||||
bxsqr = 1 << (2 * bnbits);
|
||||
|
||||
/* Compute "strides" for accessing the arrays. */
|
||||
gstride = bcolormax;
|
||||
rstride = gcolormax * bcolormax;
|
||||
|
||||
bool free_dist_buf = false;
|
||||
if (!dist_buf)
|
||||
{
|
||||
free_dist_buf = true;
|
||||
dist_buf = new unsigned long [rcolormax * gcolormax * bcolormax];
|
||||
}
|
||||
maxfill (dist_buf, rcolormax, gcolormax, bcolormax);
|
||||
|
||||
// Allocate inverse colormap if not already done
|
||||
if (!rgbmap)
|
||||
rgbmap = new byte [rcolormax * gcolormax * bcolormax];
|
||||
|
||||
for (cindex = 0; cindex < colors; cindex++)
|
||||
{
|
||||
/*
|
||||
* Distance formula is
|
||||
* (red - map[0])^2 + (green - map[1])^2 + (blue - map[2])^2
|
||||
*
|
||||
* Because of quantization, we will measure from the center of
|
||||
* each quantized "cube", so blue distance is
|
||||
* (blue + x/2 - map[2])^2,
|
||||
* where x = 2^(8 - bits).
|
||||
* The step size is x, so the blue increment is
|
||||
* 2*x*blue - 2*x*map[2] + 2*x^2
|
||||
*
|
||||
* Now, b in the code below is actually blue/x, so our
|
||||
* increment will be 2*(b*x^2 + x^2 - x*map[2]). For
|
||||
* efficiency, we will maintain this quantity in a separate variable
|
||||
* that will be updated incrementally by adding 2*x^2 each time.
|
||||
*/
|
||||
|
||||
/* The initial position is the cell containing the colormap
|
||||
* entry. We get this by quantizing the colormap values.
|
||||
*/
|
||||
rcenter = colormap [cindex].red >> rnbits;
|
||||
gcenter = colormap [cindex].green >> gnbits;
|
||||
bcenter = colormap [cindex].blue >> bnbits;
|
||||
|
||||
rdist = colormap [cindex].red - (rcenter * rx + rx / 2);
|
||||
gdist = colormap [cindex].green - (gcenter * gx + gx / 2);
|
||||
cdist = colormap [cindex].blue - (bcenter * bx + bx / 2);
|
||||
cdist = rdist * rdist + gdist * gdist + cdist * cdist;
|
||||
|
||||
crinc = 2 * ((rcenter + 1) * rxsqr - (colormap [cindex].red * rx));
|
||||
cginc = 2 * ((gcenter + 1) * gxsqr - (colormap [cindex].green * gx));
|
||||
cbinc = 2 * ((bcenter + 1) * bxsqr - (colormap [cindex].blue * bx));
|
||||
|
||||
/* Array starting points. */
|
||||
cdp = dist_buf + rcenter * rstride + gcenter * gstride + bcenter;
|
||||
crgbp = rgbmap + rcenter * rstride + gcenter * gstride + bcenter;
|
||||
|
||||
(void) redloop ();
|
||||
}
|
||||
|
||||
if (free_dist_buf)
|
||||
delete [] dist_buf;
|
||||
}
|
||||
|
||||
/* redloop -- loop up and down from red center. */
|
||||
static int redloop ()
|
||||
{
|
||||
int detect;
|
||||
int r;
|
||||
int first;
|
||||
long txsqr = rxsqr + rxsqr;
|
||||
static long rxx;
|
||||
|
||||
detect = 0;
|
||||
|
||||
/* Basic loop up. */
|
||||
for (r = rcenter, rdist = cdist, rxx = crinc,
|
||||
rdp = cdp, rrgbp = crgbp, first = 1;
|
||||
r < rcolormax;
|
||||
r++, rdp += rstride, rrgbp += rstride,
|
||||
rdist += rxx, rxx += txsqr, first = 0)
|
||||
{
|
||||
if (greenloop (first))
|
||||
detect = 1;
|
||||
else if (detect)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Basic loop down. */
|
||||
for (r = rcenter - 1, rxx = crinc - txsqr, rdist = cdist - rxx,
|
||||
rdp = cdp - rstride, rrgbp = crgbp - rstride, first = 1;
|
||||
r >= 0;
|
||||
r--, rdp -= rstride, rrgbp -= rstride,
|
||||
rxx -= txsqr, rdist -= rxx, first = 0)
|
||||
{
|
||||
if (greenloop (first))
|
||||
detect = 1;
|
||||
else if (detect)
|
||||
break;
|
||||
}
|
||||
|
||||
return detect;
|
||||
}
|
||||
|
||||
/* greenloop -- loop up and down from green center. */
|
||||
static int greenloop (int restart)
|
||||
{
|
||||
int detect;
|
||||
int g;
|
||||
int first;
|
||||
long txsqr = gxsqr + gxsqr;
|
||||
static int here, min, max;
|
||||
static long ginc, gxx, gcdist; /* "gc" variables maintain correct */
|
||||
static unsigned long *gcdp; /* values for bcenter position, */
|
||||
static unsigned char *gcrgbp; /* despite modifications by blueloop */
|
||||
|
||||
/* to gdist, gdp, grgbp. */
|
||||
|
||||
if (restart)
|
||||
{
|
||||
here = gcenter;
|
||||
min = 0;
|
||||
max = gcolormax - 1;
|
||||
ginc = cginc;
|
||||
}
|
||||
|
||||
detect = 0;
|
||||
|
||||
/* Basic loop up. */
|
||||
for (g = here, gcdist = gdist = rdist, gxx = ginc,
|
||||
gcdp = gdp = rdp, gcrgbp = grgbp = rrgbp, first = 1;
|
||||
g <= max;
|
||||
g++, gdp += gstride, gcdp += gstride, grgbp += gstride, gcrgbp += gstride,
|
||||
gdist += gxx, gcdist += gxx, gxx += txsqr, first = 0)
|
||||
{
|
||||
if (blueloop (first))
|
||||
{
|
||||
if (!detect)
|
||||
{
|
||||
/* Remember here and associated data! */
|
||||
if (g > here)
|
||||
{
|
||||
here = g;
|
||||
rdp = gcdp;
|
||||
rrgbp = gcrgbp;
|
||||
rdist = gcdist;
|
||||
ginc = gxx;
|
||||
}
|
||||
detect = 1;
|
||||
}
|
||||
}
|
||||
else if (detect)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Basic loop down. */
|
||||
for (g = here - 1, gxx = ginc - txsqr, gcdist = gdist = rdist - gxx,
|
||||
gcdp = gdp = rdp - gstride, gcrgbp = grgbp = rrgbp - gstride,
|
||||
first = 1;
|
||||
g >= min;
|
||||
g--, gdp -= gstride, gcdp -= gstride, grgbp -= gstride, gcrgbp -= gstride,
|
||||
gxx -= txsqr, gdist -= gxx, gcdist -= gxx, first = 0)
|
||||
{
|
||||
if (blueloop (first))
|
||||
{
|
||||
if (!detect)
|
||||
{
|
||||
/* Remember here! */
|
||||
here = g;
|
||||
rdp = gcdp;
|
||||
rrgbp = gcrgbp;
|
||||
rdist = gcdist;
|
||||
ginc = gxx;
|
||||
detect = 1;
|
||||
}
|
||||
}
|
||||
else if (detect)
|
||||
break;
|
||||
}
|
||||
|
||||
return detect;
|
||||
}
|
||||
|
||||
/* blueloop -- loop up and down from blue center. */
|
||||
static int blueloop (int restart)
|
||||
{
|
||||
int detect;
|
||||
register unsigned long *dp;
|
||||
register unsigned char *rgbp;
|
||||
register unsigned long bdist, bxx;
|
||||
register int b, i = cindex;
|
||||
register long txsqr = bxsqr + bxsqr;
|
||||
register int lim;
|
||||
static int here, min, max;
|
||||
static long binc;
|
||||
|
||||
if (restart)
|
||||
{
|
||||
here = bcenter;
|
||||
min = 0;
|
||||
max = bcolormax - 1;
|
||||
binc = cbinc;
|
||||
}
|
||||
|
||||
detect = 0;
|
||||
|
||||
/* Basic loop up. */
|
||||
/* First loop just finds first applicable cell. */
|
||||
for (b = here, bdist = gdist, bxx = binc, dp = gdp, rgbp = grgbp, lim = max;
|
||||
b <= lim;
|
||||
b++, dp++, rgbp++,
|
||||
bdist += bxx, bxx += txsqr)
|
||||
{
|
||||
if (*dp > bdist)
|
||||
{
|
||||
/* Remember new 'here' and associated data! */
|
||||
if (b > here)
|
||||
{
|
||||
here = b;
|
||||
gdp = dp;
|
||||
grgbp = rgbp;
|
||||
gdist = bdist;
|
||||
binc = bxx;
|
||||
}
|
||||
detect = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Second loop fills in a run of closer cells. */
|
||||
for (;
|
||||
b <= lim;
|
||||
b++, dp++, rgbp++,
|
||||
bdist += bxx, bxx += txsqr)
|
||||
{
|
||||
if (*dp > bdist)
|
||||
{
|
||||
*dp = bdist;
|
||||
*rgbp = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Basic loop down. */
|
||||
/* Do initializations here, since the 'find' loop might not get executed. */
|
||||
lim = min;
|
||||
b = here - 1;
|
||||
bxx = binc - txsqr;
|
||||
bdist = gdist - bxx;
|
||||
dp = gdp - 1;
|
||||
rgbp = grgbp - 1;
|
||||
/* The 'find' loop is executed only if we didn't already find something. */
|
||||
if (!detect)
|
||||
for (;
|
||||
b >= lim;
|
||||
b--, dp--, rgbp--,
|
||||
bxx -= txsqr, bdist -= bxx)
|
||||
{
|
||||
if (*dp > bdist)
|
||||
{
|
||||
/* Remember here! */
|
||||
/* No test for b against here necessary because b < here by definition. */
|
||||
here = b;
|
||||
gdp = dp;
|
||||
grgbp = rgbp;
|
||||
gdist = bdist;
|
||||
binc = bxx;
|
||||
detect = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* The 'update' loop. */
|
||||
for (;
|
||||
b >= lim;
|
||||
b--, dp--, rgbp--,
|
||||
bxx -= txsqr, bdist -= bxx)
|
||||
{
|
||||
if (*dp > bdist)
|
||||
{
|
||||
*dp = bdist;
|
||||
*rgbp = i;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we saw something, update the edge trackers. */
|
||||
|
||||
return detect;
|
||||
}
|
||||
|
||||
static void maxfill (unsigned long *buffer, long rside, long gside, long bside)
|
||||
{
|
||||
register unsigned long maxv = ~0UL;
|
||||
register long i;
|
||||
register unsigned long *bp;
|
||||
|
||||
for (i = rside * gside * bside, bp = buffer; i > 0; i--, bp++)
|
||||
*bp = maxv;
|
||||
}
|
||||
9
RenderDll/Common/Textures/Image/inv_cmap.h
Normal file
9
RenderDll/Common/Textures/Image/inv_cmap.h
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
#ifndef __INV_CMAP_H__
|
||||
#define __INV_CMAP_H__
|
||||
|
||||
extern void shInverseColormap (int colors, SRGBPixel *colormap,
|
||||
int rbits, int gbits, int bbits, byte *&rgbmap,
|
||||
unsigned long *dist_buf = NULL);
|
||||
|
||||
#endif // __INV_CMAP_H__
|
||||
34
RenderDll/Common/Textures/Image/jpeg6/jchuff.h
Normal file
34
RenderDll/Common/Textures/Image/jpeg6/jchuff.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* jchuff.h
|
||||
*
|
||||
* Copyright (C) 1991-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains declarations for Huffman entropy encoding routines
|
||||
* that are shared between the sequential encoder (jchuff.c) and the
|
||||
* progressive encoder (jcphuff.c). No other modules need to see these.
|
||||
*/
|
||||
|
||||
/* Derived data constructed for each Huffman table */
|
||||
|
||||
typedef struct {
|
||||
unsigned int ehufco[256]; /* code for each symbol */
|
||||
char ehufsi[256]; /* length of code for each symbol */
|
||||
/* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */
|
||||
} c_derived_tbl;
|
||||
|
||||
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||
|
||||
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||
#define jpeg_make_c_derived_tbl jMkCDerived
|
||||
#define jpeg_gen_optimal_table jGenOptTbl
|
||||
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||
|
||||
/* Expand a Huffman table definition into the derived format */
|
||||
EXTERN void jpeg_make_c_derived_tbl JPP((j_compress_ptr cinfo,
|
||||
JHUFF_TBL * htbl, c_derived_tbl ** pdtbl));
|
||||
|
||||
/* Generate an optimal table definition given the specified counts */
|
||||
EXTERN void jpeg_gen_optimal_table JPP((j_compress_ptr cinfo,
|
||||
JHUFF_TBL * htbl, long freq[]));
|
||||
94
RenderDll/Common/Textures/Image/jpeg6/jcomapi.cpp
Normal file
94
RenderDll/Common/Textures/Image/jpeg6/jcomapi.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* jcomapi.c
|
||||
*
|
||||
* Copyright (C) 1994, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains application interface routines that are used for both
|
||||
* compression and decompression.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
|
||||
/*
|
||||
* Abort processing of a JPEG compression or decompression operation,
|
||||
* but don't destroy the object itself.
|
||||
*
|
||||
* For this, we merely clean up all the nonpermanent memory pools.
|
||||
* Note that temp files (virtual arrays) are not allowed to belong to
|
||||
* the permanent pool, so we will be able to close all temp files here.
|
||||
* Closing a data source or destination, if necessary, is the application's
|
||||
* responsibility.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_abort (j_common_ptr cinfo)
|
||||
{
|
||||
int pool;
|
||||
|
||||
/* Releasing pools in reverse order might help avoid fragmentation
|
||||
* with some (brain-damaged) malloc libraries.
|
||||
*/
|
||||
for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) {
|
||||
(*cinfo->mem->free_pool) (cinfo, pool);
|
||||
}
|
||||
|
||||
/* Reset overall state for possible reuse of object */
|
||||
cinfo->global_state = (cinfo->is_decompressor ? DSTATE_START : CSTATE_START);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Destruction of a JPEG object.
|
||||
*
|
||||
* Everything gets deallocated except the master jpeg_compress_struct itself
|
||||
* and the error manager struct. Both of these are supplied by the application
|
||||
* and must be freed, if necessary, by the application. (Often they are on
|
||||
* the stack and so don't need to be freed anyway.)
|
||||
* Closing a data source or destination, if necessary, is the application's
|
||||
* responsibility.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_destroy (j_common_ptr cinfo)
|
||||
{
|
||||
/* We need only tell the memory manager to release everything. */
|
||||
/* NB: mem pointer is NULL if memory mgr failed to initialize. */
|
||||
if (cinfo->mem != NULL)
|
||||
(*cinfo->mem->self_destruct) (cinfo);
|
||||
cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */
|
||||
cinfo->global_state = 0; /* mark it destroyed */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convenience routines for allocating quantization and Huffman tables.
|
||||
* (Would jutils.c be a more reasonable place to put these?)
|
||||
*/
|
||||
|
||||
GLOBAL JQUANT_TBL *
|
||||
my_jpeg_alloc_quant_table (j_common_ptr cinfo)
|
||||
{
|
||||
JQUANT_TBL *tbl;
|
||||
|
||||
tbl = (JQUANT_TBL *)
|
||||
(*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL));
|
||||
tbl->sent_table = FALSE; /* make sure this is false in any new table */
|
||||
return tbl;
|
||||
}
|
||||
|
||||
|
||||
GLOBAL JHUFF_TBL *
|
||||
my_jpeg_alloc_huff_table (j_common_ptr cinfo)
|
||||
{
|
||||
JHUFF_TBL *tbl;
|
||||
|
||||
tbl = (JHUFF_TBL *)
|
||||
(*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL));
|
||||
tbl->sent_table = FALSE; /* make sure this is false in any new table */
|
||||
return tbl;
|
||||
}
|
||||
41
RenderDll/Common/Textures/Image/jpeg6/jconfig.h
Normal file
41
RenderDll/Common/Textures/Image/jpeg6/jconfig.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* jconfig.wat --- jconfig.h for Watcom C/C++ on MS-DOS or OS/2. */
|
||||
/* see jconfig.doc for explanations */
|
||||
|
||||
#define HAVE_PROTOTYPES
|
||||
#define HAVE_UNSIGNED_CHAR
|
||||
#define HAVE_UNSIGNED_SHORT
|
||||
/* #define void char */
|
||||
/* #define const */
|
||||
#define CHAR_IS_UNSIGNED
|
||||
#define HAVE_STDDEF_H
|
||||
#define HAVE_STDLIB_H
|
||||
#undef NEED_BSD_STRINGS
|
||||
#undef NEED_SYS_TYPES_H
|
||||
#undef NEED_FAR_POINTERS /* Watcom uses flat 32-bit addressing */
|
||||
#undef NEED_SHORT_EXTERNAL_NAMES
|
||||
#undef INCOMPLETE_TYPES_BROKEN
|
||||
|
||||
#define JDCT_DEFAULT JDCT_FLOAT
|
||||
#define JDCT_FASTEST JDCT_FLOAT
|
||||
|
||||
#ifdef JPEG_INTERNALS
|
||||
|
||||
#undef RIGHT_SHIFT_IS_UNSIGNED
|
||||
|
||||
#endif /* JPEG_INTERNALS */
|
||||
|
||||
#ifdef JPEG_CJPEG_DJPEG
|
||||
|
||||
#define BMP_SUPPORTED /* BMP image file format */
|
||||
#define GIF_SUPPORTED /* GIF image file format */
|
||||
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
|
||||
#undef RLE_SUPPORTED /* Utah RLE image file format */
|
||||
#define TARGA_SUPPORTED /* Targa image file format */
|
||||
|
||||
#undef TWO_FILE_COMMANDLINE /* optional */
|
||||
#define USE_SETMODE /* Needed to make one-file style work in Watcom */
|
||||
#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */
|
||||
#undef DONT_USE_B_MODE
|
||||
#undef PROGRESS_REPORT /* optional */
|
||||
|
||||
#endif /* JPEG_CJPEG_DJPEG */
|
||||
400
RenderDll/Common/Textures/Image/jpeg6/jdapimin.cpp
Normal file
400
RenderDll/Common/Textures/Image/jpeg6/jdapimin.cpp
Normal file
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
* jdapimin.c
|
||||
*
|
||||
* Copyright (C) 1994-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains application interface code for the decompression half
|
||||
* of the JPEG library. These are the "minimum" API routines that may be
|
||||
* needed in either the normal full-decompression case or the
|
||||
* transcoding-only case.
|
||||
*
|
||||
* Most of the routines intended to be called directly by an application
|
||||
* are in this file or in jdapistd.c. But also see jcomapi.c for routines
|
||||
* shared by compression and decompression, and jdtrans.c for the transcoding
|
||||
* case.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
|
||||
/*
|
||||
* Initialization of a JPEG decompression object.
|
||||
* The error manager must already be set up (in case memory manager fails).
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_create_decompress (j_decompress_ptr cinfo)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* For debugging purposes, zero the whole master structure.
|
||||
* But error manager pointer is already there, so save and restore it.
|
||||
*/
|
||||
{
|
||||
struct jpeg_error_mgr * err = cinfo->err;
|
||||
i = sizeof(struct jpeg_decompress_struct);
|
||||
i = SIZEOF(struct jpeg_decompress_struct);
|
||||
MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct));
|
||||
cinfo->err = err;
|
||||
}
|
||||
cinfo->is_decompressor = TRUE;
|
||||
|
||||
/* Initialize a memory manager instance for this object */
|
||||
jinit_memory_mgr((j_common_ptr) cinfo);
|
||||
|
||||
/* Zero out pointers to permanent structures. */
|
||||
cinfo->progress = NULL;
|
||||
cinfo->src = NULL;
|
||||
|
||||
for (i = 0; i < NUM_QUANT_TBLS; i++)
|
||||
cinfo->quant_tbl_ptrs[i] = NULL;
|
||||
|
||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||
cinfo->dc_huff_tbl_ptrs[i] = NULL;
|
||||
cinfo->ac_huff_tbl_ptrs[i] = NULL;
|
||||
}
|
||||
|
||||
/* Initialize marker processor so application can override methods
|
||||
* for COM, APPn markers before calling jpeg_read_header.
|
||||
*/
|
||||
jinit_marker_reader(cinfo);
|
||||
|
||||
/* And initialize the overall input controller. */
|
||||
jinit_input_controller(cinfo);
|
||||
|
||||
/* OK, I'm ready */
|
||||
cinfo->global_state = DSTATE_START;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Destruction of a JPEG decompression object
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_destroy_decompress (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Abort processing of a JPEG decompression operation,
|
||||
* but don't destroy the object itself.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_abort_decompress (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_jpeg_abort((j_common_ptr) cinfo); /* use common routine */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Install a special processing method for COM or APPn markers.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code,
|
||||
jpeg_marker_parser_method routine)
|
||||
{
|
||||
if (marker_code == JPEG_COM)
|
||||
cinfo->marker->process_COM = routine;
|
||||
else if (marker_code >= JPEG_APP0 && marker_code <= JPEG_APP0+15)
|
||||
cinfo->marker->process_APPn[marker_code-JPEG_APP0] = routine;
|
||||
else
|
||||
ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set default decompression parameters.
|
||||
*/
|
||||
|
||||
LOCAL void
|
||||
default_decompress_parms (j_decompress_ptr cinfo)
|
||||
{
|
||||
/* Guess the input colorspace, and set output colorspace accordingly. */
|
||||
/* (Wish JPEG committee had provided a real way to specify this...) */
|
||||
/* Note application may override our guesses. */
|
||||
switch (cinfo->num_components) {
|
||||
case 1:
|
||||
cinfo->jpeg_color_space = JCS_GRAYSCALE;
|
||||
cinfo->out_color_space = JCS_GRAYSCALE;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (cinfo->saw_JFIF_marker) {
|
||||
cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */
|
||||
} else if (cinfo->saw_Adobe_marker) {
|
||||
switch (cinfo->Adobe_transform) {
|
||||
case 0:
|
||||
cinfo->jpeg_color_space = JCS_RGB;
|
||||
break;
|
||||
case 1:
|
||||
cinfo->jpeg_color_space = JCS_YCbCr;
|
||||
break;
|
||||
default:
|
||||
WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
|
||||
cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Saw no special markers, try to guess from the component IDs */
|
||||
int cid0 = cinfo->comp_info[0].component_id;
|
||||
int cid1 = cinfo->comp_info[1].component_id;
|
||||
int cid2 = cinfo->comp_info[2].component_id;
|
||||
|
||||
if (cid0 == 1 && cid1 == 2 && cid2 == 3)
|
||||
cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */
|
||||
else if (cid0 == 82 && cid1 == 71 && cid2 == 66)
|
||||
cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
|
||||
else {
|
||||
TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2);
|
||||
cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
|
||||
}
|
||||
}
|
||||
/* Always guess RGB is proper output colorspace. */
|
||||
cinfo->out_color_space = JCS_RGB;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (cinfo->saw_Adobe_marker) {
|
||||
switch (cinfo->Adobe_transform) {
|
||||
case 0:
|
||||
cinfo->jpeg_color_space = JCS_CMYK;
|
||||
break;
|
||||
case 2:
|
||||
cinfo->jpeg_color_space = JCS_YCCK;
|
||||
break;
|
||||
default:
|
||||
WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
|
||||
cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* No special markers, assume straight CMYK. */
|
||||
cinfo->jpeg_color_space = JCS_CMYK;
|
||||
}
|
||||
cinfo->out_color_space = JCS_CMYK;
|
||||
break;
|
||||
|
||||
default:
|
||||
cinfo->jpeg_color_space = JCS_UNKNOWN;
|
||||
cinfo->out_color_space = JCS_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set defaults for other decompression parameters. */
|
||||
cinfo->scale_num = 1; /* 1:1 scaling */
|
||||
cinfo->scale_denom = 1;
|
||||
cinfo->output_gamma = 1.0;
|
||||
cinfo->buffered_image = FALSE;
|
||||
cinfo->raw_data_out = FALSE;
|
||||
cinfo->dct_method = JDCT_DEFAULT;
|
||||
cinfo->do_fancy_upsampling = TRUE;
|
||||
cinfo->do_block_smoothing = TRUE;
|
||||
cinfo->quantize_colors = FALSE;
|
||||
/* We set these in case application only sets quantize_colors. */
|
||||
cinfo->dither_mode = JDITHER_FS;
|
||||
#ifdef QUANT_2PASS_SUPPORTED
|
||||
cinfo->two_pass_quantize = TRUE;
|
||||
#else
|
||||
cinfo->two_pass_quantize = FALSE;
|
||||
#endif
|
||||
cinfo->desired_number_of_colors = 256;
|
||||
cinfo->colormap = NULL;
|
||||
/* Initialize for no mode change in buffered-image mode. */
|
||||
cinfo->enable_1pass_quant = FALSE;
|
||||
cinfo->enable_external_quant = FALSE;
|
||||
cinfo->enable_2pass_quant = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decompression startup: read start of JPEG datastream to see what's there.
|
||||
* Need only initialize JPEG object and supply a data source before calling.
|
||||
*
|
||||
* This routine will read as far as the first SOS marker (ie, actual start of
|
||||
* compressed data), and will save all tables and parameters in the JPEG
|
||||
* object. It will also initialize the decompression parameters to default
|
||||
* values, and finally return JPEG_HEADER_OK. On return, the application may
|
||||
* adjust the decompression parameters and then call jpeg_start_decompress.
|
||||
* (Or, if the application only wanted to determine the image parameters,
|
||||
* the data need not be decompressed. In that case, call jpeg_abort or
|
||||
* jpeg_destroy to release any temporary space.)
|
||||
* If an abbreviated (tables only) datastream is presented, the routine will
|
||||
* return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then
|
||||
* re-use the JPEG object to read the abbreviated image datastream(s).
|
||||
* It is unnecessary (but OK) to call jpeg_abort in this case.
|
||||
* The JPEG_SUSPENDED return code only occurs if the data source module
|
||||
* requests suspension of the decompressor. In this case the application
|
||||
* should load more source data and then re-call jpeg_read_header to resume
|
||||
* processing.
|
||||
* If a non-suspending data source is used and require_image is TRUE, then the
|
||||
* return code need not be inspected since only JPEG_HEADER_OK is possible.
|
||||
*
|
||||
* This routine is now just a front end to jpeg_consume_input, with some
|
||||
* extra error checking.
|
||||
*/
|
||||
|
||||
GLOBAL int
|
||||
my_jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
|
||||
{
|
||||
int retcode;
|
||||
|
||||
if (cinfo->global_state != DSTATE_START &&
|
||||
cinfo->global_state != DSTATE_INHEADER)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
|
||||
retcode = my_jpeg_consume_input(cinfo);
|
||||
|
||||
switch (retcode) {
|
||||
case JPEG_REACHED_SOS:
|
||||
retcode = JPEG_HEADER_OK;
|
||||
break;
|
||||
case JPEG_REACHED_EOI:
|
||||
if (require_image) /* Complain if application wanted an image */
|
||||
ERREXIT(cinfo, JERR_NO_IMAGE);
|
||||
/* Reset to start state; it would be safer to require the application to
|
||||
* call jpeg_abort, but we can't change it now for compatibility reasons.
|
||||
* A side effect is to free any temporary memory (there shouldn't be any).
|
||||
*/
|
||||
my_jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */
|
||||
retcode = JPEG_HEADER_TABLES_ONLY;
|
||||
break;
|
||||
case JPEG_SUSPENDED:
|
||||
/* no work */
|
||||
break;
|
||||
}
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Consume data in advance of what the decompressor requires.
|
||||
* This can be called at any time once the decompressor object has
|
||||
* been created and a data source has been set up.
|
||||
*
|
||||
* This routine is essentially a state machine that handles a couple
|
||||
* of critical state-transition actions, namely initial setup and
|
||||
* transition from header scanning to ready-for-start_decompress.
|
||||
* All the actual input is done via the input controller's consume_input
|
||||
* method.
|
||||
*/
|
||||
|
||||
GLOBAL int
|
||||
my_jpeg_consume_input (j_decompress_ptr cinfo)
|
||||
{
|
||||
int retcode = JPEG_SUSPENDED;
|
||||
|
||||
/* NB: every possible DSTATE value should be listed in this switch */
|
||||
switch (cinfo->global_state) {
|
||||
case DSTATE_START:
|
||||
/* Start-of-datastream actions: reset appropriate modules */
|
||||
(*cinfo->inputctl->reset_input_controller) (cinfo);
|
||||
/* Initialize application's data source module */
|
||||
(*cinfo->src->init_source) (cinfo);
|
||||
cinfo->global_state = DSTATE_INHEADER;
|
||||
/*FALLTHROUGH*/
|
||||
case DSTATE_INHEADER:
|
||||
retcode = (*cinfo->inputctl->consume_input) (cinfo);
|
||||
if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */
|
||||
/* Set up default parameters based on header data */
|
||||
default_decompress_parms(cinfo);
|
||||
/* Set global state: ready for start_decompress */
|
||||
cinfo->global_state = DSTATE_READY;
|
||||
}
|
||||
break;
|
||||
case DSTATE_READY:
|
||||
/* Can't advance past first SOS until start_decompress is called */
|
||||
retcode = JPEG_REACHED_SOS;
|
||||
break;
|
||||
case DSTATE_PRELOAD:
|
||||
case DSTATE_PRESCAN:
|
||||
case DSTATE_SCANNING:
|
||||
case DSTATE_RAW_OK:
|
||||
case DSTATE_BUFIMAGE:
|
||||
case DSTATE_BUFPOST:
|
||||
case DSTATE_STOPPING:
|
||||
retcode = (*cinfo->inputctl->consume_input) (cinfo);
|
||||
break;
|
||||
default:
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
}
|
||||
return retcode;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Have we finished reading the input file?
|
||||
*/
|
||||
|
||||
GLOBAL boolean
|
||||
my_jpeg_input_complete (j_decompress_ptr cinfo)
|
||||
{
|
||||
/* Check for valid jpeg object */
|
||||
if (cinfo->global_state < DSTATE_START ||
|
||||
cinfo->global_state > DSTATE_STOPPING)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
return cinfo->inputctl->eoi_reached;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Is there more than one scan?
|
||||
*/
|
||||
|
||||
GLOBAL boolean
|
||||
my_jpeg_has_multiple_scans (j_decompress_ptr cinfo)
|
||||
{
|
||||
/* Only valid after jpeg_read_header completes */
|
||||
if (cinfo->global_state < DSTATE_READY ||
|
||||
cinfo->global_state > DSTATE_STOPPING)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
return cinfo->inputctl->has_multiple_scans;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish JPEG decompression.
|
||||
*
|
||||
* This will normally just verify the file trailer and release temp storage.
|
||||
*
|
||||
* Returns FALSE if suspended. The return value need be inspected only if
|
||||
* a suspending data source is used.
|
||||
*/
|
||||
|
||||
GLOBAL boolean
|
||||
my_jpeg_finish_decompress (j_decompress_ptr cinfo)
|
||||
{
|
||||
if ((cinfo->global_state == DSTATE_SCANNING ||
|
||||
cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) {
|
||||
/* Terminate final pass of non-buffered mode */
|
||||
if (cinfo->output_scanline < cinfo->output_height)
|
||||
ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
|
||||
(*cinfo->master->finish_output_pass) (cinfo);
|
||||
cinfo->global_state = DSTATE_STOPPING;
|
||||
} else if (cinfo->global_state == DSTATE_BUFIMAGE) {
|
||||
/* Finishing after a buffered-image operation */
|
||||
cinfo->global_state = DSTATE_STOPPING;
|
||||
} else if (cinfo->global_state != DSTATE_STOPPING) {
|
||||
/* STOPPING = repeat call after a suspension, anything else is error */
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
}
|
||||
/* Read until EOI */
|
||||
while (! cinfo->inputctl->eoi_reached) {
|
||||
if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
|
||||
return FALSE; /* Suspend, come back later */
|
||||
}
|
||||
/* Do final cleanup */
|
||||
(*cinfo->src->term_source) (cinfo);
|
||||
/* We can use jpeg_abort to release memory and reset global_state */
|
||||
my_jpeg_abort((j_common_ptr) cinfo);
|
||||
return TRUE;
|
||||
}
|
||||
275
RenderDll/Common/Textures/Image/jpeg6/jdapistd.cpp
Normal file
275
RenderDll/Common/Textures/Image/jpeg6/jdapistd.cpp
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* jdapistd.c
|
||||
*
|
||||
* Copyright (C) 1994-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains application interface code for the decompression half
|
||||
* of the JPEG library. These are the "standard" API routines that are
|
||||
* used in the normal full-decompression case. They are not used by a
|
||||
* transcoding-only application. Note that if an application links in
|
||||
* jpeg_start_decompress, it will end up linking in the entire decompressor.
|
||||
* We thus must separate this file from jdapimin.c to avoid linking the
|
||||
* whole decompression library into a transcoder.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
LOCAL boolean output_pass_setup JPP((j_decompress_ptr cinfo));
|
||||
|
||||
|
||||
/*
|
||||
* Decompression initialization.
|
||||
* jpeg_read_header must be completed before calling this.
|
||||
*
|
||||
* If a multipass operating mode was selected, this will do all but the
|
||||
* last pass, and thus may take a great deal of time.
|
||||
*
|
||||
* Returns FALSE if suspended. The return value need be inspected only if
|
||||
* a suspending data source is used.
|
||||
*/
|
||||
|
||||
GLOBAL boolean
|
||||
my_jpeg_start_decompress (j_decompress_ptr cinfo)
|
||||
{
|
||||
if (cinfo->global_state == DSTATE_READY) {
|
||||
/* First call: initialize master control, select active modules */
|
||||
jinit_master_decompress(cinfo);
|
||||
if (cinfo->buffered_image) {
|
||||
/* No more work here; expecting jpeg_start_output next */
|
||||
cinfo->global_state = DSTATE_BUFIMAGE;
|
||||
return TRUE;
|
||||
}
|
||||
cinfo->global_state = DSTATE_PRELOAD;
|
||||
}
|
||||
if (cinfo->global_state == DSTATE_PRELOAD) {
|
||||
/* If file has multiple scans, absorb them all into the coef buffer */
|
||||
if (cinfo->inputctl->has_multiple_scans) {
|
||||
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||
for (;;) {
|
||||
int retcode;
|
||||
/* Call progress monitor hook if present */
|
||||
if (cinfo->progress != NULL)
|
||||
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
||||
/* Absorb some more input */
|
||||
retcode = (*cinfo->inputctl->consume_input) (cinfo);
|
||||
if (retcode == JPEG_SUSPENDED)
|
||||
return FALSE;
|
||||
if (retcode == JPEG_REACHED_EOI)
|
||||
break;
|
||||
/* Advance progress counter if appropriate */
|
||||
if (cinfo->progress != NULL &&
|
||||
(retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
|
||||
if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
|
||||
/* jdmaster underestimated number of scans; ratchet up one scan */
|
||||
cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif /* D_MULTISCAN_FILES_SUPPORTED */
|
||||
}
|
||||
cinfo->output_scan_number = cinfo->input_scan_number;
|
||||
} else if (cinfo->global_state != DSTATE_PRESCAN)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
/* Perform any dummy output passes, and set up for the final pass */
|
||||
return output_pass_setup(cinfo);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set up for an output pass, and perform any dummy pass(es) needed.
|
||||
* Common subroutine for jpeg_start_decompress and jpeg_start_output.
|
||||
* Entry: global_state = DSTATE_PRESCAN only if previously suspended.
|
||||
* Exit: If done, returns TRUE and sets global_state for proper output mode.
|
||||
* If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN.
|
||||
*/
|
||||
|
||||
LOCAL boolean
|
||||
output_pass_setup (j_decompress_ptr cinfo)
|
||||
{
|
||||
if (cinfo->global_state != DSTATE_PRESCAN) {
|
||||
/* First call: do pass setup */
|
||||
(*cinfo->master->prepare_for_output_pass) (cinfo);
|
||||
cinfo->output_scanline = 0;
|
||||
cinfo->global_state = DSTATE_PRESCAN;
|
||||
}
|
||||
/* Loop over any required dummy passes */
|
||||
while (cinfo->master->is_dummy_pass) {
|
||||
#ifdef QUANT_2PASS_SUPPORTED
|
||||
/* Crank through the dummy pass */
|
||||
while (cinfo->output_scanline < cinfo->output_height) {
|
||||
JDIMENSION last_scanline;
|
||||
/* Call progress monitor hook if present */
|
||||
if (cinfo->progress != NULL) {
|
||||
cinfo->progress->pass_counter = (long) cinfo->output_scanline;
|
||||
cinfo->progress->pass_limit = (long) cinfo->output_height;
|
||||
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
||||
}
|
||||
/* Process some data */
|
||||
last_scanline = cinfo->output_scanline;
|
||||
(*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL,
|
||||
&cinfo->output_scanline, (JDIMENSION) 0);
|
||||
if (cinfo->output_scanline == last_scanline)
|
||||
return FALSE; /* No progress made, must suspend */
|
||||
}
|
||||
/* Finish up dummy pass, and set up for another one */
|
||||
(*cinfo->master->finish_output_pass) (cinfo);
|
||||
(*cinfo->master->prepare_for_output_pass) (cinfo);
|
||||
cinfo->output_scanline = 0;
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif /* QUANT_2PASS_SUPPORTED */
|
||||
}
|
||||
/* Ready for application to drive output pass through
|
||||
* jpeg_read_scanlines or jpeg_read_raw_data.
|
||||
*/
|
||||
cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read some scanlines of data from the JPEG decompressor.
|
||||
*
|
||||
* The return value will be the number of lines actually read.
|
||||
* This may be less than the number requested in several cases,
|
||||
* including bottom of image, data source suspension, and operating
|
||||
* modes that emit multiple scanlines at a time.
|
||||
*
|
||||
* Note: we warn about excess calls to jpeg_read_scanlines() since
|
||||
* this likely signals an application programmer error. However,
|
||||
* an oversize buffer (max_lines > scanlines remaining) is not an error.
|
||||
*/
|
||||
|
||||
GLOBAL JDIMENSION
|
||||
my_jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
|
||||
JDIMENSION max_lines)
|
||||
{
|
||||
JDIMENSION row_ctr;
|
||||
|
||||
if (cinfo->global_state != DSTATE_SCANNING)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
if (cinfo->output_scanline >= cinfo->output_height) {
|
||||
WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Call progress monitor hook if present */
|
||||
if (cinfo->progress != NULL) {
|
||||
cinfo->progress->pass_counter = (long) cinfo->output_scanline;
|
||||
cinfo->progress->pass_limit = (long) cinfo->output_height;
|
||||
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
||||
}
|
||||
|
||||
/* Process some data */
|
||||
row_ctr = 0;
|
||||
(*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines);
|
||||
cinfo->output_scanline += row_ctr;
|
||||
return row_ctr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Alternate entry point to read raw data.
|
||||
* Processes exactly one iMCU row per call, unless suspended.
|
||||
*/
|
||||
|
||||
GLOBAL JDIMENSION
|
||||
my_jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
|
||||
JDIMENSION max_lines)
|
||||
{
|
||||
JDIMENSION lines_per_iMCU_row;
|
||||
|
||||
if (cinfo->global_state != DSTATE_RAW_OK)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
if (cinfo->output_scanline >= cinfo->output_height) {
|
||||
WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Call progress monitor hook if present */
|
||||
if (cinfo->progress != NULL) {
|
||||
cinfo->progress->pass_counter = (long) cinfo->output_scanline;
|
||||
cinfo->progress->pass_limit = (long) cinfo->output_height;
|
||||
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
||||
}
|
||||
|
||||
/* Verify that at least one iMCU row can be returned. */
|
||||
lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size;
|
||||
if (max_lines < lines_per_iMCU_row)
|
||||
ERREXIT(cinfo, JERR_BUFFER_SIZE);
|
||||
|
||||
/* Decompress directly into user's buffer. */
|
||||
if (! (*cinfo->coef->decompress_data) (cinfo, data))
|
||||
return 0; /* suspension forced, can do nothing more */
|
||||
|
||||
/* OK, we processed one iMCU row. */
|
||||
cinfo->output_scanline += lines_per_iMCU_row;
|
||||
return lines_per_iMCU_row;
|
||||
}
|
||||
|
||||
|
||||
/* Additional entry points for buffered-image mode. */
|
||||
|
||||
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||
|
||||
/*
|
||||
* Initialize for an output pass in buffered-image mode.
|
||||
*/
|
||||
|
||||
GLOBAL boolean
|
||||
my_jpeg_start_output (j_decompress_ptr cinfo, int scan_number)
|
||||
{
|
||||
if (cinfo->global_state != DSTATE_BUFIMAGE &&
|
||||
cinfo->global_state != DSTATE_PRESCAN)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
/* Limit scan number to valid range */
|
||||
if (scan_number <= 0)
|
||||
scan_number = 1;
|
||||
if (cinfo->inputctl->eoi_reached &&
|
||||
scan_number > cinfo->input_scan_number)
|
||||
scan_number = cinfo->input_scan_number;
|
||||
cinfo->output_scan_number = scan_number;
|
||||
/* Perform any dummy output passes, and set up for the real pass */
|
||||
return output_pass_setup(cinfo);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up after an output pass in buffered-image mode.
|
||||
*
|
||||
* Returns FALSE if suspended. The return value need be inspected only if
|
||||
* a suspending data source is used.
|
||||
*/
|
||||
|
||||
GLOBAL boolean
|
||||
my_jpeg_finish_output (j_decompress_ptr cinfo)
|
||||
{
|
||||
if ((cinfo->global_state == DSTATE_SCANNING ||
|
||||
cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) {
|
||||
/* Terminate this pass. */
|
||||
/* We do not require the whole pass to have been completed. */
|
||||
(*cinfo->master->finish_output_pass) (cinfo);
|
||||
cinfo->global_state = DSTATE_BUFPOST;
|
||||
} else if (cinfo->global_state != DSTATE_BUFPOST) {
|
||||
/* BUFPOST = repeat call after a suspension, anything else is error */
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
}
|
||||
/* Read markers looking for SOS or EOI */
|
||||
while (cinfo->input_scan_number <= cinfo->output_scan_number &&
|
||||
! cinfo->inputctl->eoi_reached) {
|
||||
if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
|
||||
return FALSE; /* Suspend, come back later */
|
||||
}
|
||||
cinfo->global_state = DSTATE_BUFIMAGE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif /* D_MULTISCAN_FILES_SUPPORTED */
|
||||
204
RenderDll/Common/Textures/Image/jpeg6/jdatasrc.cpp
Normal file
204
RenderDll/Common/Textures/Image/jpeg6/jdatasrc.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* jdatasrc.c
|
||||
*
|
||||
* Copyright (C) 1994, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains decompression data source routines for the case of
|
||||
* reading JPEG data from a file (or any stdio stream). While these routines
|
||||
* are sufficient for most applications, some will want to use a different
|
||||
* source manager.
|
||||
* IMPORTANT: we assume that fread() will correctly transcribe an array of
|
||||
* JOCTETs from 8-bit-wide elements on external storage. If char is wider
|
||||
* than 8 bits on your machine, you may need to do some tweaking.
|
||||
*/
|
||||
|
||||
|
||||
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jerror.h"
|
||||
|
||||
|
||||
/* Expanded data source object for stdio input */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_source_mgr pub; /* public fields */
|
||||
|
||||
unsigned char *infile; /* source stream */
|
||||
JOCTET * buffer; /* start of buffer */
|
||||
boolean start_of_file; /* have we gotten any data yet? */
|
||||
} my_source_mgr;
|
||||
|
||||
typedef my_source_mgr * my_src_ptr;
|
||||
|
||||
#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize source --- called by jpeg_read_header
|
||||
* before any data is actually read.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
init_source (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||
|
||||
/* We reset the empty-input-file flag for each image,
|
||||
* but we don't clear the input buffer.
|
||||
* This is correct behavior for reading a series of images from one source.
|
||||
*/
|
||||
src->start_of_file = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fill the input buffer --- called whenever buffer is emptied.
|
||||
*
|
||||
* In typical applications, this should read fresh data into the buffer
|
||||
* (ignoring the current state of next_input_byte & bytes_in_buffer),
|
||||
* reset the pointer & count to the start of the buffer, and return TRUE
|
||||
* indicating that the buffer has been reloaded. It is not necessary to
|
||||
* fill the buffer entirely, only to obtain at least one more byte.
|
||||
*
|
||||
* There is no such thing as an EOF return. If the end of the file has been
|
||||
* reached, the routine has a choice of ERREXIT() or inserting fake data into
|
||||
* the buffer. In most cases, generating a warning message and inserting a
|
||||
* fake EOI marker is the best course of action --- this will allow the
|
||||
* decompressor to output however much of the image is there. However,
|
||||
* the resulting error message is misleading if the real problem is an empty
|
||||
* input file, so we handle that case specially.
|
||||
*
|
||||
* In applications that need to be able to suspend compression due to input
|
||||
* not being available yet, a FALSE return indicates that no more data can be
|
||||
* obtained right now, but more may be forthcoming later. In this situation,
|
||||
* the decompressor will return to its caller (with an indication of the
|
||||
* number of scanlines it has read, if any). The application should resume
|
||||
* decompression after it has loaded more data into the input buffer. Note
|
||||
* that there are substantial restrictions on the use of suspension --- see
|
||||
* the documentation.
|
||||
*
|
||||
* When suspending, the decompressor will back up to a convenient restart point
|
||||
* (typically the start of the current MCU). next_input_byte & bytes_in_buffer
|
||||
* indicate where the restart point will be if the current call returns FALSE.
|
||||
* Data beyond this point must be rescanned after resumption, so move it to
|
||||
* the front of the buffer rather than discarding it.
|
||||
*/
|
||||
|
||||
METHODDEF boolean
|
||||
fill_input_buffer (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||
|
||||
memcpy( src->buffer, src->infile, INPUT_BUF_SIZE );
|
||||
|
||||
src->infile += INPUT_BUF_SIZE;
|
||||
|
||||
src->pub.next_input_byte = src->buffer;
|
||||
src->pub.bytes_in_buffer = INPUT_BUF_SIZE;
|
||||
src->start_of_file = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Skip data --- used to skip over a potentially large amount of
|
||||
* uninteresting data (such as an APPn marker).
|
||||
*
|
||||
* Writers of suspendable-input applications must note that skip_input_data
|
||||
* is not granted the right to give a suspension return. If the skip extends
|
||||
* beyond the data currently in the buffer, the buffer can be marked empty so
|
||||
* that the next read will cause a fill_input_buffer call that can suspend.
|
||||
* Arranging for additional bytes to be discarded before reloading the input
|
||||
* buffer is the application writer's problem.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
skip_input_data (j_decompress_ptr cinfo, long num_bytes)
|
||||
{
|
||||
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||
|
||||
/* Just a dumb implementation for now. Could use fseek() except
|
||||
* it doesn't work on pipes. Not clear that being smart is worth
|
||||
* any trouble anyway --- large skips are infrequent.
|
||||
*/
|
||||
if (num_bytes > 0) {
|
||||
while (num_bytes > (long) src->pub.bytes_in_buffer) {
|
||||
num_bytes -= (long) src->pub.bytes_in_buffer;
|
||||
(void) fill_input_buffer(cinfo);
|
||||
/* note we assume that fill_input_buffer will never return FALSE,
|
||||
* so suspension need not be handled.
|
||||
*/
|
||||
}
|
||||
src->pub.next_input_byte += (size_t) num_bytes;
|
||||
src->pub.bytes_in_buffer -= (size_t) num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* An additional method that can be provided by data source modules is the
|
||||
* resync_to_restart method for error recovery in the presence of RST markers.
|
||||
* For the moment, this source module just uses the default resync method
|
||||
* provided by the JPEG library. That method assumes that no backtracking
|
||||
* is possible.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Terminate source --- called by jpeg_finish_decompress
|
||||
* after all data has been read. Often a no-op.
|
||||
*
|
||||
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
|
||||
* application must deal with any cleanup that should happen even
|
||||
* for error exit.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
term_source (j_decompress_ptr cinfo)
|
||||
{
|
||||
/* no work necessary here */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prepare for input from a stdio stream.
|
||||
* The caller must have already opened the stream, and is responsible
|
||||
* for closing it after finishing decompression.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_stdio_src (j_decompress_ptr cinfo, unsigned char *infile)
|
||||
{
|
||||
my_src_ptr src;
|
||||
|
||||
/* The source object and input buffer are made permanent so that a series
|
||||
* of JPEG images can be read from the same file by calling jpeg_stdio_src
|
||||
* only before the first one. (If we discarded the buffer at the end of
|
||||
* one image, we'd likely lose the start of the next one.)
|
||||
* This makes it unsafe to use this manager and a different source
|
||||
* manager serially with the same JPEG object. Caveat programmer.
|
||||
*/
|
||||
if (cinfo->src == NULL) { /* first time for this JPEG object? */
|
||||
cinfo->src = (struct jpeg_source_mgr *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
SIZEOF(my_source_mgr));
|
||||
src = (my_src_ptr) cinfo->src;
|
||||
src->buffer = (JOCTET *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
INPUT_BUF_SIZE * SIZEOF(JOCTET));
|
||||
}
|
||||
|
||||
src = (my_src_ptr) cinfo->src;
|
||||
src->pub.init_source = init_source;
|
||||
src->pub.fill_input_buffer = fill_input_buffer;
|
||||
src->pub.skip_input_data = skip_input_data;
|
||||
src->pub.resync_to_restart = my_jpeg_resync_to_restart; /* use default method */
|
||||
src->pub.term_source = term_source;
|
||||
src->infile = infile;
|
||||
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
|
||||
src->pub.next_input_byte = NULL; /* until buffer loaded */
|
||||
}
|
||||
725
RenderDll/Common/Textures/Image/jpeg6/jdcoefct.cpp
Normal file
725
RenderDll/Common/Textures/Image/jpeg6/jdcoefct.cpp
Normal file
@@ -0,0 +1,725 @@
|
||||
/*
|
||||
* jdcoefct.c
|
||||
*
|
||||
* Copyright (C) 1994-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the coefficient buffer controller for decompression.
|
||||
* This controller is the top level of the JPEG decompressor proper.
|
||||
* The coefficient buffer lies between entropy decoding and inverse-DCT steps.
|
||||
*
|
||||
* In buffered-image mode, this controller is the interface between
|
||||
* input-oriented processing and output-oriented processing.
|
||||
* Also, the input side (only) is used when reading a file for transcoding.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
/* Block smoothing is only applicable for progressive JPEG, so: */
|
||||
#ifndef D_PROGRESSIVE_SUPPORTED
|
||||
#undef BLOCK_SMOOTHING_SUPPORTED
|
||||
#endif
|
||||
|
||||
/* Private buffer controller object */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_d_coef_controller pub; /* public fields */
|
||||
|
||||
/* These variables keep track of the current location of the input side. */
|
||||
/* cinfo->input_iMCU_row is also used for this. */
|
||||
JDIMENSION MCU_ctr; /* counts MCUs processed in current row */
|
||||
int MCU_vert_offset; /* counts MCU rows within iMCU row */
|
||||
int MCU_rows_per_iMCU_row; /* number of such rows needed */
|
||||
|
||||
/* The output side's location is represented by cinfo->output_iMCU_row. */
|
||||
|
||||
/* In single-pass modes, it's sufficient to buffer just one MCU.
|
||||
* We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks,
|
||||
* and let the entropy decoder write into that workspace each time.
|
||||
* (On 80x86, the workspace is FAR even though it's not really very big;
|
||||
* this is to keep the module interfaces unchanged when a large coefficient
|
||||
* buffer is necessary.)
|
||||
* In multi-pass modes, this array points to the current MCU's blocks
|
||||
* within the virtual arrays; it is used only by the input side.
|
||||
*/
|
||||
JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU];
|
||||
|
||||
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||
/* In multi-pass modes, we need a virtual block array for each component. */
|
||||
jvirt_barray_ptr whole_image[MAX_COMPONENTS];
|
||||
#endif
|
||||
|
||||
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||
/* When doing block smoothing, we latch coefficient Al values here */
|
||||
int * coef_bits_latch;
|
||||
#define SAVED_COEFS 6 /* we save coef_bits[0..5] */
|
||||
#endif
|
||||
} my_coef_controller;
|
||||
|
||||
typedef my_coef_controller * my_coef_ptr;
|
||||
|
||||
/* Forward declarations */
|
||||
METHODDEF int decompress_onepass
|
||||
JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
|
||||
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||
METHODDEF int decompress_data
|
||||
JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
|
||||
#endif
|
||||
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||
LOCAL boolean smoothing_ok JPP((j_decompress_ptr cinfo));
|
||||
METHODDEF int decompress_smooth_data
|
||||
JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
|
||||
#endif
|
||||
|
||||
|
||||
LOCAL void
|
||||
start_iMCU_row (j_decompress_ptr cinfo)
|
||||
/* Reset within-iMCU-row counters for a new row (input side) */
|
||||
{
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
|
||||
/* In an interleaved scan, an MCU row is the same as an iMCU row.
|
||||
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
|
||||
* But at the bottom of the image, process only what's left.
|
||||
*/
|
||||
if (cinfo->comps_in_scan > 1) {
|
||||
coef->MCU_rows_per_iMCU_row = 1;
|
||||
} else {
|
||||
if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
|
||||
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
|
||||
else
|
||||
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
|
||||
}
|
||||
|
||||
coef->MCU_ctr = 0;
|
||||
coef->MCU_vert_offset = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for an input processing pass.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
start_input_pass (j_decompress_ptr cinfo)
|
||||
{
|
||||
cinfo->input_iMCU_row = 0;
|
||||
start_iMCU_row(cinfo);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for an output processing pass.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
start_output_pass (j_decompress_ptr cinfo)
|
||||
{
|
||||
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
|
||||
/* If multipass, check to see whether to use block smoothing on this pass */
|
||||
if (coef->pub.coef_arrays != NULL) {
|
||||
if (cinfo->do_block_smoothing && smoothing_ok(cinfo))
|
||||
coef->pub.decompress_data = decompress_smooth_data;
|
||||
else
|
||||
coef->pub.decompress_data = decompress_data;
|
||||
}
|
||||
#endif
|
||||
cinfo->output_iMCU_row = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decompress and return some data in the single-pass case.
|
||||
* Always attempts to emit one fully interleaved MCU row ("iMCU" row).
|
||||
* Input and output must run in lockstep since we have only a one-MCU buffer.
|
||||
* Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
|
||||
*
|
||||
* NB: output_buf contains a plane for each component in image.
|
||||
* For single pass, this is the same as the components in the scan.
|
||||
*/
|
||||
|
||||
METHODDEF int
|
||||
decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
{
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
|
||||
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||
int blkn, ci, xindex, yindex, yoffset, useful_width;
|
||||
JSAMPARRAY output_ptr;
|
||||
JDIMENSION start_col, output_col;
|
||||
jpeg_component_info *compptr;
|
||||
inverse_DCT_method_ptr inverse_DCT;
|
||||
|
||||
/* Loop to process as much as one whole iMCU row */
|
||||
for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
|
||||
yoffset++) {
|
||||
for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col;
|
||||
MCU_col_num++) {
|
||||
/* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */
|
||||
jzero_far((void FAR *) coef->MCU_buffer[0],
|
||||
(size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK)));
|
||||
if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||
/* Suspension forced; update state counters and exit */
|
||||
coef->MCU_vert_offset = yoffset;
|
||||
coef->MCU_ctr = MCU_col_num;
|
||||
return JPEG_SUSPENDED;
|
||||
}
|
||||
/* Determine where data should go in output_buf and do the IDCT thing.
|
||||
* We skip dummy blocks at the right and bottom edges (but blkn gets
|
||||
* incremented past them!). Note the inner loop relies on having
|
||||
* allocated the MCU_buffer[] blocks sequentially.
|
||||
*/
|
||||
blkn = 0; /* index of current DCT block within MCU */
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
/* Don't bother to IDCT an uninteresting component. */
|
||||
if (! compptr->component_needed) {
|
||||
blkn += compptr->MCU_blocks;
|
||||
continue;
|
||||
}
|
||||
inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index];
|
||||
useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
|
||||
: compptr->last_col_width;
|
||||
output_ptr = output_buf[ci] + yoffset * compptr->DCT_scaled_size;
|
||||
start_col = MCU_col_num * compptr->MCU_sample_width;
|
||||
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
|
||||
if (cinfo->input_iMCU_row < last_iMCU_row ||
|
||||
yoffset+yindex < compptr->last_row_height) {
|
||||
output_col = start_col;
|
||||
for (xindex = 0; xindex < useful_width; xindex++) {
|
||||
(*inverse_DCT) (cinfo, compptr,
|
||||
(JCOEFPTR) coef->MCU_buffer[blkn+xindex],
|
||||
output_ptr, output_col);
|
||||
output_col += compptr->DCT_scaled_size;
|
||||
}
|
||||
}
|
||||
blkn += compptr->MCU_width;
|
||||
output_ptr += compptr->DCT_scaled_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Completed an MCU row, but perhaps not an iMCU row */
|
||||
coef->MCU_ctr = 0;
|
||||
}
|
||||
/* Completed the iMCU row, advance counters for next one */
|
||||
cinfo->output_iMCU_row++;
|
||||
if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
|
||||
start_iMCU_row(cinfo);
|
||||
return JPEG_ROW_COMPLETED;
|
||||
}
|
||||
/* Completed the scan */
|
||||
(*cinfo->inputctl->finish_input_pass) (cinfo);
|
||||
return JPEG_SCAN_COMPLETED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Dummy consume-input routine for single-pass operation.
|
||||
*/
|
||||
|
||||
METHODDEF int
|
||||
dummy_consume_data (j_decompress_ptr cinfo)
|
||||
{
|
||||
return JPEG_SUSPENDED; /* Always indicate nothing was done */
|
||||
}
|
||||
|
||||
|
||||
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||
|
||||
/*
|
||||
* Consume input data and store it in the full-image coefficient buffer.
|
||||
* We read as much as one fully interleaved MCU row ("iMCU" row) per call,
|
||||
* ie, v_samp_factor block rows for each component in the scan.
|
||||
* Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
|
||||
*/
|
||||
|
||||
METHODDEF int
|
||||
consume_data (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
JDIMENSION MCU_col_num; /* index of current MCU within row */
|
||||
int blkn, ci, xindex, yindex, yoffset;
|
||||
JDIMENSION start_col;
|
||||
JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
|
||||
JBLOCKROW buffer_ptr;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Align the virtual buffers for the components used in this scan. */
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
buffer[ci] = (*cinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
|
||||
cinfo->input_iMCU_row * compptr->v_samp_factor,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
/* Note: entropy decoder expects buffer to be zeroed,
|
||||
* but this is handled automatically by the memory manager
|
||||
* because we requested a pre-zeroed array.
|
||||
*/
|
||||
}
|
||||
|
||||
/* Loop to process one whole iMCU row */
|
||||
for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
|
||||
yoffset++) {
|
||||
for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row;
|
||||
MCU_col_num++) {
|
||||
/* Construct list of pointers to DCT blocks belonging to this MCU */
|
||||
blkn = 0; /* index of current DCT block within MCU */
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
start_col = MCU_col_num * compptr->MCU_width;
|
||||
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
|
||||
buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
|
||||
for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
|
||||
coef->MCU_buffer[blkn++] = buffer_ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Try to fetch the MCU. */
|
||||
if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
|
||||
/* Suspension forced; update state counters and exit */
|
||||
coef->MCU_vert_offset = yoffset;
|
||||
coef->MCU_ctr = MCU_col_num;
|
||||
return JPEG_SUSPENDED;
|
||||
}
|
||||
}
|
||||
/* Completed an MCU row, but perhaps not an iMCU row */
|
||||
coef->MCU_ctr = 0;
|
||||
}
|
||||
/* Completed the iMCU row, advance counters for next one */
|
||||
if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
|
||||
start_iMCU_row(cinfo);
|
||||
return JPEG_ROW_COMPLETED;
|
||||
}
|
||||
/* Completed the scan */
|
||||
(*cinfo->inputctl->finish_input_pass) (cinfo);
|
||||
return JPEG_SCAN_COMPLETED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decompress and return some data in the multi-pass case.
|
||||
* Always attempts to emit one fully interleaved MCU row ("iMCU" row).
|
||||
* Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
|
||||
*
|
||||
* NB: output_buf contains a plane for each component in image.
|
||||
*/
|
||||
|
||||
METHODDEF int
|
||||
decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
{
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||
JDIMENSION block_num;
|
||||
int ci, block_row, block_rows;
|
||||
JBLOCKARRAY buffer;
|
||||
JBLOCKROW buffer_ptr;
|
||||
JSAMPARRAY output_ptr;
|
||||
JDIMENSION output_col;
|
||||
jpeg_component_info *compptr;
|
||||
inverse_DCT_method_ptr inverse_DCT;
|
||||
|
||||
/* Force some input to be done if we are getting ahead of the input. */
|
||||
while (cinfo->input_scan_number < cinfo->output_scan_number ||
|
||||
(cinfo->input_scan_number == cinfo->output_scan_number &&
|
||||
cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) {
|
||||
if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
|
||||
return JPEG_SUSPENDED;
|
||||
}
|
||||
|
||||
/* OK, output from the virtual arrays. */
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* Don't bother to IDCT an uninteresting component. */
|
||||
if (! compptr->component_needed)
|
||||
continue;
|
||||
/* Align the virtual buffer for this component. */
|
||||
buffer = (*cinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) cinfo, coef->whole_image[ci],
|
||||
cinfo->output_iMCU_row * compptr->v_samp_factor,
|
||||
(JDIMENSION) compptr->v_samp_factor, FALSE);
|
||||
/* Count non-dummy DCT block rows in this iMCU row. */
|
||||
if (cinfo->output_iMCU_row < last_iMCU_row)
|
||||
block_rows = compptr->v_samp_factor;
|
||||
else {
|
||||
/* NB: can't use last_row_height here; it is input-side-dependent! */
|
||||
block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||
if (block_rows == 0) block_rows = compptr->v_samp_factor;
|
||||
}
|
||||
inverse_DCT = cinfo->idct->inverse_DCT[ci];
|
||||
output_ptr = output_buf[ci];
|
||||
/* Loop over all DCT blocks to be processed. */
|
||||
for (block_row = 0; block_row < block_rows; block_row++) {
|
||||
buffer_ptr = buffer[block_row];
|
||||
output_col = 0;
|
||||
for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) {
|
||||
(*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr,
|
||||
output_ptr, output_col);
|
||||
buffer_ptr++;
|
||||
output_col += compptr->DCT_scaled_size;
|
||||
}
|
||||
output_ptr += compptr->DCT_scaled_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
|
||||
return JPEG_ROW_COMPLETED;
|
||||
return JPEG_SCAN_COMPLETED;
|
||||
}
|
||||
|
||||
#endif /* D_MULTISCAN_FILES_SUPPORTED */
|
||||
|
||||
|
||||
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||
|
||||
/*
|
||||
* This code applies interblock smoothing as described by section K.8
|
||||
* of the JPEG standard: the first 5 AC coefficients are estimated from
|
||||
* the DC values of a DCT block and its 8 neighboring blocks.
|
||||
* We apply smoothing only for progressive JPEG decoding, and only if
|
||||
* the coefficients it can estimate are not yet known to full precision.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Determine whether block smoothing is applicable and safe.
|
||||
* We also latch the current states of the coef_bits[] entries for the
|
||||
* AC coefficients; otherwise, if the input side of the decompressor
|
||||
* advances into a new scan, we might think the coefficients are known
|
||||
* more accurately than they really are.
|
||||
*/
|
||||
|
||||
LOCAL boolean
|
||||
smoothing_ok (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
boolean smoothing_useful = FALSE;
|
||||
int ci, coefi;
|
||||
jpeg_component_info *compptr;
|
||||
JQUANT_TBL * qtable;
|
||||
int * coef_bits;
|
||||
int * coef_bits_latch;
|
||||
|
||||
if (! cinfo->progressive_mode || cinfo->coef_bits == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* Allocate latch area if not already done */
|
||||
if (coef->coef_bits_latch == NULL)
|
||||
coef->coef_bits_latch = (int *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
cinfo->num_components *
|
||||
(SAVED_COEFS * SIZEOF(int)));
|
||||
coef_bits_latch = coef->coef_bits_latch;
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* All components' quantization values must already be latched. */
|
||||
if ((qtable = compptr->quant_table) == NULL)
|
||||
return FALSE;
|
||||
/* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */
|
||||
for (coefi = 0; coefi <= 5; coefi++) {
|
||||
if (qtable->quantval[coefi] == 0)
|
||||
return FALSE;
|
||||
}
|
||||
/* DC values must be at least partly known for all components. */
|
||||
coef_bits = cinfo->coef_bits[ci];
|
||||
if (coef_bits[0] < 0)
|
||||
return FALSE;
|
||||
/* Block smoothing is helpful if some AC coefficients remain inaccurate. */
|
||||
for (coefi = 1; coefi <= 5; coefi++) {
|
||||
coef_bits_latch[coefi] = coef_bits[coefi];
|
||||
if (coef_bits[coefi] != 0)
|
||||
smoothing_useful = TRUE;
|
||||
}
|
||||
coef_bits_latch += SAVED_COEFS;
|
||||
}
|
||||
|
||||
return smoothing_useful;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Variant of decompress_data for use when doing block smoothing.
|
||||
*/
|
||||
|
||||
METHODDEF int
|
||||
decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
|
||||
{
|
||||
my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
|
||||
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
|
||||
JDIMENSION block_num, last_block_column;
|
||||
int ci, block_row, block_rows, access_rows;
|
||||
JBLOCKARRAY buffer;
|
||||
JBLOCKROW buffer_ptr, prev_block_row, next_block_row;
|
||||
JSAMPARRAY output_ptr;
|
||||
JDIMENSION output_col;
|
||||
jpeg_component_info *compptr;
|
||||
inverse_DCT_method_ptr inverse_DCT;
|
||||
boolean first_row, last_row;
|
||||
JBLOCK workspace;
|
||||
int *coef_bits;
|
||||
JQUANT_TBL *quanttbl;
|
||||
INT32 Q00,Q01,Q02,Q10,Q11,Q20, num;
|
||||
int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9;
|
||||
int Al, pred;
|
||||
|
||||
/* Force some input to be done if we are getting ahead of the input. */
|
||||
while (cinfo->input_scan_number <= cinfo->output_scan_number &&
|
||||
! cinfo->inputctl->eoi_reached) {
|
||||
if (cinfo->input_scan_number == cinfo->output_scan_number) {
|
||||
/* If input is working on current scan, we ordinarily want it to
|
||||
* have completed the current row. But if input scan is DC,
|
||||
* we want it to keep one row ahead so that next block row's DC
|
||||
* values are up to date.
|
||||
*/
|
||||
JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0;
|
||||
if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta)
|
||||
break;
|
||||
}
|
||||
if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
|
||||
return JPEG_SUSPENDED;
|
||||
}
|
||||
|
||||
/* OK, output from the virtual arrays. */
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* Don't bother to IDCT an uninteresting component. */
|
||||
if (! compptr->component_needed)
|
||||
continue;
|
||||
/* Count non-dummy DCT block rows in this iMCU row. */
|
||||
if (cinfo->output_iMCU_row < last_iMCU_row) {
|
||||
block_rows = compptr->v_samp_factor;
|
||||
access_rows = block_rows * 2; /* this and next iMCU row */
|
||||
last_row = FALSE;
|
||||
} else {
|
||||
/* NB: can't use last_row_height here; it is input-side-dependent! */
|
||||
block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||
if (block_rows == 0) block_rows = compptr->v_samp_factor;
|
||||
access_rows = block_rows; /* this iMCU row only */
|
||||
last_row = TRUE;
|
||||
}
|
||||
/* Align the virtual buffer for this component. */
|
||||
if (cinfo->output_iMCU_row > 0) {
|
||||
access_rows += compptr->v_samp_factor; /* prior iMCU row too */
|
||||
buffer = (*cinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) cinfo, coef->whole_image[ci],
|
||||
(cinfo->output_iMCU_row - 1) * compptr->v_samp_factor,
|
||||
(JDIMENSION) access_rows, FALSE);
|
||||
buffer += compptr->v_samp_factor; /* point to current iMCU row */
|
||||
first_row = FALSE;
|
||||
} else {
|
||||
buffer = (*cinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) cinfo, coef->whole_image[ci],
|
||||
(JDIMENSION) 0, (JDIMENSION) access_rows, FALSE);
|
||||
first_row = TRUE;
|
||||
}
|
||||
/* Fetch component-dependent info */
|
||||
coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS);
|
||||
quanttbl = compptr->quant_table;
|
||||
Q00 = quanttbl->quantval[0];
|
||||
Q01 = quanttbl->quantval[1];
|
||||
Q10 = quanttbl->quantval[2];
|
||||
Q20 = quanttbl->quantval[3];
|
||||
Q11 = quanttbl->quantval[4];
|
||||
Q02 = quanttbl->quantval[5];
|
||||
inverse_DCT = cinfo->idct->inverse_DCT[ci];
|
||||
output_ptr = output_buf[ci];
|
||||
/* Loop over all DCT blocks to be processed. */
|
||||
for (block_row = 0; block_row < block_rows; block_row++) {
|
||||
buffer_ptr = buffer[block_row];
|
||||
if (first_row && block_row == 0)
|
||||
prev_block_row = buffer_ptr;
|
||||
else
|
||||
prev_block_row = buffer[block_row-1];
|
||||
if (last_row && block_row == block_rows-1)
|
||||
next_block_row = buffer_ptr;
|
||||
else
|
||||
next_block_row = buffer[block_row+1];
|
||||
/* We fetch the surrounding DC values using a sliding-register approach.
|
||||
* Initialize all nine here so as to do the right thing on narrow pics.
|
||||
*/
|
||||
DC1 = DC2 = DC3 = (int) prev_block_row[0][0];
|
||||
DC4 = DC5 = DC6 = (int) buffer_ptr[0][0];
|
||||
DC7 = DC8 = DC9 = (int) next_block_row[0][0];
|
||||
output_col = 0;
|
||||
last_block_column = compptr->width_in_blocks - 1;
|
||||
for (block_num = 0; block_num <= last_block_column; block_num++) {
|
||||
/* Fetch current DCT block into workspace so we can modify it. */
|
||||
jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1);
|
||||
/* Update DC values */
|
||||
if (block_num < last_block_column) {
|
||||
DC3 = (int) prev_block_row[1][0];
|
||||
DC6 = (int) buffer_ptr[1][0];
|
||||
DC9 = (int) next_block_row[1][0];
|
||||
}
|
||||
/* Compute coefficient estimates per K.8.
|
||||
* An estimate is applied only if coefficient is still zero,
|
||||
* and is not known to be fully accurate.
|
||||
*/
|
||||
/* AC01 */
|
||||
if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) {
|
||||
num = 36 * Q00 * (DC4 - DC6);
|
||||
if (num >= 0) {
|
||||
pred = (int) (((Q01<<7) + num) / (Q01<<8));
|
||||
if (Al > 0 && pred >= (1<<Al))
|
||||
pred = (1<<Al)-1;
|
||||
} else {
|
||||
pred = (int) (((Q01<<7) - num) / (Q01<<8));
|
||||
if (Al > 0 && pred >= (1<<Al))
|
||||
pred = (1<<Al)-1;
|
||||
pred = -pred;
|
||||
}
|
||||
workspace[1] = (JCOEF) pred;
|
||||
}
|
||||
/* AC10 */
|
||||
if ((Al=coef_bits[2]) != 0 && workspace[8] == 0) {
|
||||
num = 36 * Q00 * (DC2 - DC8);
|
||||
if (num >= 0) {
|
||||
pred = (int) (((Q10<<7) + num) / (Q10<<8));
|
||||
if (Al > 0 && pred >= (1<<Al))
|
||||
pred = (1<<Al)-1;
|
||||
} else {
|
||||
pred = (int) (((Q10<<7) - num) / (Q10<<8));
|
||||
if (Al > 0 && pred >= (1<<Al))
|
||||
pred = (1<<Al)-1;
|
||||
pred = -pred;
|
||||
}
|
||||
workspace[8] = (JCOEF) pred;
|
||||
}
|
||||
/* AC20 */
|
||||
if ((Al=coef_bits[3]) != 0 && workspace[16] == 0) {
|
||||
num = 9 * Q00 * (DC2 + DC8 - 2*DC5);
|
||||
if (num >= 0) {
|
||||
pred = (int) (((Q20<<7) + num) / (Q20<<8));
|
||||
if (Al > 0 && pred >= (1<<Al))
|
||||
pred = (1<<Al)-1;
|
||||
} else {
|
||||
pred = (int) (((Q20<<7) - num) / (Q20<<8));
|
||||
if (Al > 0 && pred >= (1<<Al))
|
||||
pred = (1<<Al)-1;
|
||||
pred = -pred;
|
||||
}
|
||||
workspace[16] = (JCOEF) pred;
|
||||
}
|
||||
/* AC11 */
|
||||
if ((Al=coef_bits[4]) != 0 && workspace[9] == 0) {
|
||||
num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
|
||||
if (num >= 0) {
|
||||
pred = (int) (((Q11<<7) + num) / (Q11<<8));
|
||||
if (Al > 0 && pred >= (1<<Al))
|
||||
pred = (1<<Al)-1;
|
||||
} else {
|
||||
pred = (int) (((Q11<<7) - num) / (Q11<<8));
|
||||
if (Al > 0 && pred >= (1<<Al))
|
||||
pred = (1<<Al)-1;
|
||||
pred = -pred;
|
||||
}
|
||||
workspace[9] = (JCOEF) pred;
|
||||
}
|
||||
/* AC02 */
|
||||
if ((Al=coef_bits[5]) != 0 && workspace[2] == 0) {
|
||||
num = 9 * Q00 * (DC4 + DC6 - 2*DC5);
|
||||
if (num >= 0) {
|
||||
pred = (int) (((Q02<<7) + num) / (Q02<<8));
|
||||
if (Al > 0 && pred >= (1<<Al))
|
||||
pred = (1<<Al)-1;
|
||||
} else {
|
||||
pred = (int) (((Q02<<7) - num) / (Q02<<8));
|
||||
if (Al > 0 && pred >= (1<<Al))
|
||||
pred = (1<<Al)-1;
|
||||
pred = -pred;
|
||||
}
|
||||
workspace[2] = (JCOEF) pred;
|
||||
}
|
||||
/* OK, do the IDCT */
|
||||
(*inverse_DCT) (cinfo, compptr, (JCOEFPTR) workspace,
|
||||
output_ptr, output_col);
|
||||
/* Advance for next column */
|
||||
DC1 = DC2; DC2 = DC3;
|
||||
DC4 = DC5; DC5 = DC6;
|
||||
DC7 = DC8; DC8 = DC9;
|
||||
buffer_ptr++, prev_block_row++, next_block_row++;
|
||||
output_col += compptr->DCT_scaled_size;
|
||||
}
|
||||
output_ptr += compptr->DCT_scaled_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
|
||||
return JPEG_ROW_COMPLETED;
|
||||
return JPEG_SCAN_COMPLETED;
|
||||
}
|
||||
|
||||
#endif /* BLOCK_SMOOTHING_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize coefficient buffer controller.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
|
||||
{
|
||||
my_coef_ptr coef;
|
||||
|
||||
coef = (my_coef_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(my_coef_controller));
|
||||
cinfo->coef = (struct jpeg_d_coef_controller *) coef;
|
||||
coef->pub.start_input_pass = start_input_pass;
|
||||
coef->pub.start_output_pass = start_output_pass;
|
||||
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||
coef->coef_bits_latch = NULL;
|
||||
#endif
|
||||
|
||||
/* Create the coefficient buffer. */
|
||||
if (need_full_buffer) {
|
||||
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||
/* Allocate a full-image virtual array for each component, */
|
||||
/* padded to a multiple of samp_factor DCT blocks in each direction. */
|
||||
/* Note we ask for a pre-zeroed array. */
|
||||
int ci, access_rows;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
access_rows = compptr->v_samp_factor;
|
||||
#ifdef BLOCK_SMOOTHING_SUPPORTED
|
||||
/* If block smoothing could be used, need a bigger window */
|
||||
if (cinfo->progressive_mode)
|
||||
access_rows *= 3;
|
||||
#endif
|
||||
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
|
||||
(long) compptr->v_samp_factor),
|
||||
(JDIMENSION) access_rows);
|
||||
}
|
||||
coef->pub.consume_data = consume_data;
|
||||
coef->pub.decompress_data = decompress_data;
|
||||
coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
/* We only need a single-MCU buffer. */
|
||||
JBLOCKROW buffer;
|
||||
int i;
|
||||
|
||||
buffer = (JBLOCKROW)
|
||||
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
|
||||
for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) {
|
||||
coef->MCU_buffer[i] = buffer + i;
|
||||
}
|
||||
coef->pub.consume_data = dummy_consume_data;
|
||||
coef->pub.decompress_data = decompress_onepass;
|
||||
coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */
|
||||
}
|
||||
}
|
||||
367
RenderDll/Common/Textures/Image/jpeg6/jdcolor.cpp
Normal file
367
RenderDll/Common/Textures/Image/jpeg6/jdcolor.cpp
Normal file
@@ -0,0 +1,367 @@
|
||||
/*
|
||||
* jdcolor.c
|
||||
*
|
||||
* Copyright (C) 1991-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains output colorspace conversion routines.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
|
||||
/* Private subobject */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_color_deconverter pub; /* public fields */
|
||||
|
||||
/* Private state for YCC->RGB conversion */
|
||||
int * Cr_r_tab; /* => table for Cr to R conversion */
|
||||
int * Cb_b_tab; /* => table for Cb to B conversion */
|
||||
INT32 * Cr_g_tab; /* => table for Cr to G conversion */
|
||||
INT32 * Cb_g_tab; /* => table for Cb to G conversion */
|
||||
} my_color_deconverter;
|
||||
|
||||
typedef my_color_deconverter * my_cconvert_ptr;
|
||||
|
||||
|
||||
/**************** YCbCr -> RGB conversion: most common case **************/
|
||||
|
||||
/*
|
||||
* YCbCr is defined per CCIR 601-1, except that Cb and Cr are
|
||||
* normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
|
||||
* The conversion equations to be implemented are therefore
|
||||
* R = Y + 1.40200 * Cr
|
||||
* G = Y - 0.34414 * Cb - 0.71414 * Cr
|
||||
* B = Y + 1.77200 * Cb
|
||||
* where Cb and Cr represent the incoming values less CENTERJSAMPLE.
|
||||
* (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
|
||||
*
|
||||
* To avoid floating-point arithmetic, we represent the fractional constants
|
||||
* as integers scaled up by 2^16 (about 4 digits precision); we have to divide
|
||||
* the products by 2^16, with appropriate rounding, to get the correct answer.
|
||||
* Notice that Y, being an integral input, does not contribute any fraction
|
||||
* so it need not participate in the rounding.
|
||||
*
|
||||
* For even more speed, we avoid doing any multiplications in the inner loop
|
||||
* by precalculating the constants times Cb and Cr for all possible values.
|
||||
* For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
|
||||
* for 12-bit samples it is still acceptable. It's not very reasonable for
|
||||
* 16-bit samples, but if you want lossless storage you shouldn't be changing
|
||||
* colorspace anyway.
|
||||
* The Cr=>R and Cb=>B values can be rounded to integers in advance; the
|
||||
* values for the G calculation are left scaled up, since we must add them
|
||||
* together before rounding.
|
||||
*/
|
||||
|
||||
#define SCALEBITS 16 /* speediest right-shift on some machines */
|
||||
#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
|
||||
#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
|
||||
|
||||
|
||||
/*
|
||||
* Initialize tables for YCC->RGB colorspace conversion.
|
||||
*/
|
||||
|
||||
LOCAL void
|
||||
build_ycc_rgb_table (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||
int i;
|
||||
INT32 x;
|
||||
SHIFT_TEMPS
|
||||
|
||||
cconvert->Cr_r_tab = (int *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
(MAXJSAMPLE+1) * SIZEOF(int));
|
||||
cconvert->Cb_b_tab = (int *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
(MAXJSAMPLE+1) * SIZEOF(int));
|
||||
cconvert->Cr_g_tab = (INT32 *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
(MAXJSAMPLE+1) * SIZEOF(INT32));
|
||||
cconvert->Cb_g_tab = (INT32 *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
(MAXJSAMPLE+1) * SIZEOF(INT32));
|
||||
|
||||
for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
|
||||
/* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
|
||||
/* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
|
||||
/* Cr=>R value is nearest int to 1.40200 * x */
|
||||
cconvert->Cr_r_tab[i] = (int)
|
||||
RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
|
||||
/* Cb=>B value is nearest int to 1.77200 * x */
|
||||
cconvert->Cb_b_tab[i] = (int)
|
||||
RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
|
||||
/* Cr=>G value is scaled-up -0.71414 * x */
|
||||
cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
|
||||
/* Cb=>G value is scaled-up -0.34414 * x */
|
||||
/* We also add in ONE_HALF so that need not do it in inner loop */
|
||||
cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert some rows of samples to the output colorspace.
|
||||
*
|
||||
* Note that we change from noninterleaved, one-plane-per-component format
|
||||
* to interleaved-pixel format. The output buffer is therefore three times
|
||||
* as wide as the input buffer.
|
||||
* A starting row offset is provided only for the input buffer. The caller
|
||||
* can easily adjust the passed output_buf value to accommodate any row
|
||||
* offset required on that side.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
ycc_rgb_convert (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||
JSAMPARRAY output_buf, int num_rows)
|
||||
{
|
||||
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||
register int y, cb, cr;
|
||||
register JSAMPROW outptr;
|
||||
register JSAMPROW inptr0, inptr1, inptr2;
|
||||
register JDIMENSION col;
|
||||
JDIMENSION num_cols = cinfo->output_width;
|
||||
/* copy these pointers into registers if possible */
|
||||
register JSAMPLE * range_limit = cinfo->sample_range_limit;
|
||||
register int * Crrtab = cconvert->Cr_r_tab;
|
||||
register int * Cbbtab = cconvert->Cb_b_tab;
|
||||
register INT32 * Crgtab = cconvert->Cr_g_tab;
|
||||
register INT32 * Cbgtab = cconvert->Cb_g_tab;
|
||||
SHIFT_TEMPS
|
||||
|
||||
while (--num_rows >= 0) {
|
||||
inptr0 = input_buf[0][input_row];
|
||||
inptr1 = input_buf[1][input_row];
|
||||
inptr2 = input_buf[2][input_row];
|
||||
input_row++;
|
||||
outptr = *output_buf++;
|
||||
for (col = 0; col < num_cols; col++) {
|
||||
y = GETJSAMPLE(inptr0[col]);
|
||||
cb = GETJSAMPLE(inptr1[col]);
|
||||
cr = GETJSAMPLE(inptr2[col]);
|
||||
/* Range-limiting is essential due to noise introduced by DCT losses. */
|
||||
outptr[RGB_RED] = range_limit[y + Crrtab[cr]];
|
||||
outptr[RGB_GREEN] = range_limit[y +
|
||||
((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
|
||||
SCALEBITS))];
|
||||
outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]];
|
||||
outptr += RGB_PIXELSIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************** Cases other than YCbCr -> RGB **************/
|
||||
|
||||
|
||||
/*
|
||||
* Color conversion for no colorspace change: just copy the data,
|
||||
* converting from separate-planes to interleaved representation.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
null_convert (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||
JSAMPARRAY output_buf, int num_rows)
|
||||
{
|
||||
register JSAMPROW inptr, outptr;
|
||||
register JDIMENSION count;
|
||||
register int num_components = cinfo->num_components;
|
||||
JDIMENSION num_cols = cinfo->output_width;
|
||||
int ci;
|
||||
|
||||
while (--num_rows >= 0) {
|
||||
for (ci = 0; ci < num_components; ci++) {
|
||||
inptr = input_buf[ci][input_row];
|
||||
outptr = output_buf[0] + ci;
|
||||
for (count = num_cols; count > 0; count--) {
|
||||
*outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */
|
||||
outptr += num_components;
|
||||
}
|
||||
}
|
||||
input_row++;
|
||||
output_buf++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Color conversion for grayscale: just copy the data.
|
||||
* This also works for YCbCr -> grayscale conversion, in which
|
||||
* we just copy the Y (luminance) component and ignore chrominance.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
grayscale_convert (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||
JSAMPARRAY output_buf, int num_rows)
|
||||
{
|
||||
jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
|
||||
num_rows, cinfo->output_width);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Adobe-style YCCK->CMYK conversion.
|
||||
* We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
|
||||
* conversion as above, while passing K (black) unchanged.
|
||||
* We assume build_ycc_rgb_table has been called.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
ycck_cmyk_convert (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||
JSAMPARRAY output_buf, int num_rows)
|
||||
{
|
||||
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||
register int y, cb, cr;
|
||||
register JSAMPROW outptr;
|
||||
register JSAMPROW inptr0, inptr1, inptr2, inptr3;
|
||||
register JDIMENSION col;
|
||||
JDIMENSION num_cols = cinfo->output_width;
|
||||
/* copy these pointers into registers if possible */
|
||||
register JSAMPLE * range_limit = cinfo->sample_range_limit;
|
||||
register int * Crrtab = cconvert->Cr_r_tab;
|
||||
register int * Cbbtab = cconvert->Cb_b_tab;
|
||||
register INT32 * Crgtab = cconvert->Cr_g_tab;
|
||||
register INT32 * Cbgtab = cconvert->Cb_g_tab;
|
||||
SHIFT_TEMPS
|
||||
|
||||
while (--num_rows >= 0) {
|
||||
inptr0 = input_buf[0][input_row];
|
||||
inptr1 = input_buf[1][input_row];
|
||||
inptr2 = input_buf[2][input_row];
|
||||
inptr3 = input_buf[3][input_row];
|
||||
input_row++;
|
||||
outptr = *output_buf++;
|
||||
for (col = 0; col < num_cols; col++) {
|
||||
y = GETJSAMPLE(inptr0[col]);
|
||||
cb = GETJSAMPLE(inptr1[col]);
|
||||
cr = GETJSAMPLE(inptr2[col]);
|
||||
/* Range-limiting is essential due to noise introduced by DCT losses. */
|
||||
outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */
|
||||
outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */
|
||||
((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
|
||||
SCALEBITS)))];
|
||||
outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */
|
||||
/* K passes through unchanged */
|
||||
outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */
|
||||
outptr += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Empty method for start_pass.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
start_pass_dcolor (j_decompress_ptr cinfo)
|
||||
{
|
||||
/* no work needed */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Module initialization routine for output colorspace conversion.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jinit_color_deconverter (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_cconvert_ptr cconvert;
|
||||
int ci;
|
||||
|
||||
cconvert = (my_cconvert_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(my_color_deconverter));
|
||||
cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
|
||||
cconvert->pub.start_pass = start_pass_dcolor;
|
||||
|
||||
/* Make sure num_components agrees with jpeg_color_space */
|
||||
switch (cinfo->jpeg_color_space) {
|
||||
case JCS_GRAYSCALE:
|
||||
if (cinfo->num_components != 1)
|
||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||
break;
|
||||
|
||||
case JCS_RGB:
|
||||
case JCS_YCbCr:
|
||||
if (cinfo->num_components != 3)
|
||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||
break;
|
||||
|
||||
case JCS_CMYK:
|
||||
case JCS_YCCK:
|
||||
if (cinfo->num_components != 4)
|
||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||
break;
|
||||
|
||||
default: /* JCS_UNKNOWN can be anything */
|
||||
if (cinfo->num_components < 1)
|
||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set out_color_components and conversion method based on requested space.
|
||||
* Also clear the component_needed flags for any unused components,
|
||||
* so that earlier pipeline stages can avoid useless computation.
|
||||
*/
|
||||
|
||||
switch (cinfo->out_color_space) {
|
||||
case JCS_GRAYSCALE:
|
||||
cinfo->out_color_components = 1;
|
||||
if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
|
||||
cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||
cconvert->pub.color_convert = grayscale_convert;
|
||||
/* For color->grayscale conversion, only the Y (0) component is needed */
|
||||
for (ci = 1; ci < cinfo->num_components; ci++)
|
||||
cinfo->comp_info[ci].component_needed = FALSE;
|
||||
} else
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
break;
|
||||
|
||||
case JCS_RGB:
|
||||
cinfo->out_color_components = RGB_PIXELSIZE;
|
||||
if (cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||
cconvert->pub.color_convert = ycc_rgb_convert;
|
||||
build_ycc_rgb_table(cinfo);
|
||||
} else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) {
|
||||
cconvert->pub.color_convert = null_convert;
|
||||
} else
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
break;
|
||||
|
||||
case JCS_CMYK:
|
||||
cinfo->out_color_components = 4;
|
||||
if (cinfo->jpeg_color_space == JCS_YCCK) {
|
||||
cconvert->pub.color_convert = ycck_cmyk_convert;
|
||||
build_ycc_rgb_table(cinfo);
|
||||
} else if (cinfo->jpeg_color_space == JCS_CMYK) {
|
||||
cconvert->pub.color_convert = null_convert;
|
||||
} else
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Permit null conversion to same output space */
|
||||
if (cinfo->out_color_space == cinfo->jpeg_color_space) {
|
||||
cinfo->out_color_components = cinfo->num_components;
|
||||
cconvert->pub.color_convert = null_convert;
|
||||
} else /* unsupported non-null conversion */
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cinfo->quantize_colors)
|
||||
cinfo->output_components = 1; /* single colormapped output component */
|
||||
else
|
||||
cinfo->output_components = cinfo->out_color_components;
|
||||
}
|
||||
176
RenderDll/Common/Textures/Image/jpeg6/jdct.h
Normal file
176
RenderDll/Common/Textures/Image/jpeg6/jdct.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* jdct.h
|
||||
*
|
||||
* Copyright (C) 1994, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This include file contains common declarations for the forward and
|
||||
* inverse DCT modules. These declarations are private to the DCT managers
|
||||
* (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms.
|
||||
* The individual DCT algorithms are kept in separate files to ease
|
||||
* machine-dependent tuning (e.g., assembly coding).
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* A forward DCT routine is given a pointer to a work area of type DCTELEM[];
|
||||
* the DCT is to be performed in-place in that buffer. Type DCTELEM is int
|
||||
* for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT
|
||||
* implementations use an array of type FAST_FLOAT, instead.)
|
||||
* The DCT inputs are expected to be signed (range +-CENTERJSAMPLE).
|
||||
* The DCT outputs are returned scaled up by a factor of 8; they therefore
|
||||
* have a range of +-8K for 8-bit data, +-128K for 12-bit data. This
|
||||
* convention improves accuracy in integer implementations and saves some
|
||||
* work in floating-point ones.
|
||||
* Quantization of the output coefficients is done by jcdctmgr.c.
|
||||
*/
|
||||
|
||||
#if BITS_IN_JSAMPLE == 8
|
||||
typedef int DCTELEM; /* 16 or 32 bits is fine */
|
||||
#else
|
||||
typedef INT32 DCTELEM; /* must have 32 bits */
|
||||
#endif
|
||||
|
||||
typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data));
|
||||
typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data));
|
||||
|
||||
|
||||
/*
|
||||
* An inverse DCT routine is given a pointer to the input JBLOCK and a pointer
|
||||
* to an output sample array. The routine must dequantize the input data as
|
||||
* well as perform the IDCT; for dequantization, it uses the multiplier table
|
||||
* pointed to by compptr->dct_table. The output data is to be placed into the
|
||||
* sample array starting at a specified column. (Any row offset needed will
|
||||
* be applied to the array pointer before it is passed to the IDCT code.)
|
||||
* Note that the number of samples emitted by the IDCT routine is
|
||||
* DCT_scaled_size * DCT_scaled_size.
|
||||
*/
|
||||
|
||||
/* typedef inverse_DCT_method_ptr is declared in jpegint.h */
|
||||
|
||||
/*
|
||||
* Each IDCT routine has its own ideas about the best dct_table element type.
|
||||
*/
|
||||
|
||||
typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */
|
||||
#if BITS_IN_JSAMPLE == 8
|
||||
typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */
|
||||
#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */
|
||||
#else
|
||||
typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */
|
||||
#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */
|
||||
#endif
|
||||
typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
|
||||
|
||||
|
||||
/*
|
||||
* Each IDCT routine is responsible for range-limiting its results and
|
||||
* converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could
|
||||
* be quite far out of range if the input data is corrupt, so a bulletproof
|
||||
* range-limiting step is required. We use a mask-and-table-lookup method
|
||||
* to do the combined operations quickly. See the comments with
|
||||
* prepare_range_limit_table (in jdmaster.c) for more info.
|
||||
*/
|
||||
|
||||
#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE)
|
||||
|
||||
#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */
|
||||
|
||||
|
||||
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||
|
||||
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||
#define my_jpeg_fdct_islow jFDislow
|
||||
#define my_jpeg_fdct_ifast jFDifast
|
||||
#define my_jpeg_fdct_float jFDfloat
|
||||
#define my_jpeg_idct_islow jRDislow
|
||||
#define my_jpeg_idct_ifast jRDifast
|
||||
#define my_jpeg_idct_float jRDfloat
|
||||
#define my_jpeg_idct_4x4 jRD4x4
|
||||
#define my_jpeg_idct_2x2 jRD2x2
|
||||
#define my_jpeg_idct_1x1 jRD1x1
|
||||
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||
|
||||
/* Extern declarations for the forward and inverse DCT routines. */
|
||||
|
||||
EXTERN void my_jpeg_fdct_islow JPP((DCTELEM * data));
|
||||
EXTERN void my_jpeg_fdct_ifast JPP((DCTELEM * data));
|
||||
EXTERN void my_jpeg_fdct_float JPP((FAST_FLOAT * data));
|
||||
|
||||
EXTERN void my_jpeg_idct_islow
|
||||
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||
EXTERN void my_jpeg_idct_ifast
|
||||
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||
EXTERN void my_jpeg_idct_float
|
||||
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||
EXTERN void my_jpeg_idct_4x4
|
||||
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||
EXTERN void my_jpeg_idct_2x2
|
||||
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||
EXTERN void my_jpeg_idct_1x1
|
||||
JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||
|
||||
|
||||
/*
|
||||
* Macros for handling fixed-point arithmetic; these are used by many
|
||||
* but not all of the DCT/IDCT modules.
|
||||
*
|
||||
* All values are expected to be of type INT32.
|
||||
* Fractional constants are scaled left by CONST_BITS bits.
|
||||
* CONST_BITS is defined within each module using these macros,
|
||||
* and may differ from one module to the next.
|
||||
*/
|
||||
|
||||
#define ONE ((INT32) 1)
|
||||
#define CONST_SCALE (ONE << CONST_BITS)
|
||||
|
||||
/* Convert a positive real constant to an integer scaled by CONST_SCALE.
|
||||
* Caution: some C compilers fail to reduce "FIX(constant)" at compile time,
|
||||
* thus causing a lot of useless floating-point operations at run time.
|
||||
*/
|
||||
|
||||
#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
|
||||
|
||||
/* Descale and correctly round an INT32 value that's scaled by N bits.
|
||||
* We assume RIGHT_SHIFT rounds towards minus infinity, so adding
|
||||
* the fudge factor is correct for either sign of X.
|
||||
*/
|
||||
|
||||
#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
|
||||
|
||||
/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
|
||||
* This macro is used only when the two inputs will actually be no more than
|
||||
* 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a
|
||||
* full 32x32 multiply. This provides a useful speedup on many machines.
|
||||
* Unfortunately there is no way to specify a 16x16->32 multiply portably
|
||||
* in C, but some C compilers will do the right thing if you provide the
|
||||
* correct combination of casts.
|
||||
*/
|
||||
|
||||
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
|
||||
#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const)))
|
||||
#endif
|
||||
#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
|
||||
#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const)))
|
||||
#endif
|
||||
|
||||
#ifndef MULTIPLY16C16 /* default definition */
|
||||
#define MULTIPLY16C16(var,const) ((var) * (const))
|
||||
#endif
|
||||
|
||||
/* Same except both inputs are variables. */
|
||||
|
||||
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
|
||||
#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2)))
|
||||
#endif
|
||||
|
||||
#ifndef MULTIPLY16V16 /* default definition */
|
||||
#define MULTIPLY16V16(var1,var2) ((var1) * (var2))
|
||||
#endif
|
||||
270
RenderDll/Common/Textures/Image/jpeg6/jddctmgr.cpp
Normal file
270
RenderDll/Common/Textures/Image/jpeg6/jddctmgr.cpp
Normal file
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* jddctmgr.c
|
||||
*
|
||||
* Copyright (C) 1994-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the inverse-DCT management logic.
|
||||
* This code selects a particular IDCT implementation to be used,
|
||||
* and it performs related housekeeping chores. No code in this file
|
||||
* is executed per IDCT step, only during output pass setup.
|
||||
*
|
||||
* Note that the IDCT routines are responsible for performing coefficient
|
||||
* dequantization as well as the IDCT proper. This module sets up the
|
||||
* dequantization multiplier table needed by the IDCT routine.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jdct.h" /* Private declarations for DCT subsystem */
|
||||
|
||||
|
||||
/*
|
||||
* The decompressor input side (jdinput.c) saves away the appropriate
|
||||
* quantization table for each component at the start of the first scan
|
||||
* involving that component. (This is necessary in order to correctly
|
||||
* decode files that reuse Q-table slots.)
|
||||
* When we are ready to make an output pass, the saved Q-table is converted
|
||||
* to a multiplier table that will actually be used by the IDCT routine.
|
||||
* The multiplier table contents are IDCT-method-dependent. To support
|
||||
* application changes in IDCT method between scans, we can remake the
|
||||
* multiplier tables if necessary.
|
||||
* In buffered-image mode, the first output pass may occur before any data
|
||||
* has been seen for some components, and thus before their Q-tables have
|
||||
* been saved away. To handle this case, multiplier tables are preset
|
||||
* to zeroes; the result of the IDCT will be a neutral gray level.
|
||||
*/
|
||||
|
||||
|
||||
/* Private subobject for this module */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_inverse_dct pub; /* public fields */
|
||||
|
||||
/* This array contains the IDCT method code that each multiplier table
|
||||
* is currently set up for, or -1 if it's not yet set up.
|
||||
* The actual multiplier tables are pointed to by dct_table in the
|
||||
* per-component comp_info structures.
|
||||
*/
|
||||
int cur_method[MAX_COMPONENTS];
|
||||
} my_idct_controller;
|
||||
|
||||
typedef my_idct_controller * my_idct_ptr;
|
||||
|
||||
|
||||
/* Allocated multiplier tables: big enough for any supported variant */
|
||||
|
||||
typedef union {
|
||||
ISLOW_MULT_TYPE islow_array[DCTSIZE2];
|
||||
#ifdef DCT_IFAST_SUPPORTED
|
||||
IFAST_MULT_TYPE ifast_array[DCTSIZE2];
|
||||
#endif
|
||||
#ifdef DCT_FLOAT_SUPPORTED
|
||||
FLOAT_MULT_TYPE float_array[DCTSIZE2];
|
||||
#endif
|
||||
} multiplier_table;
|
||||
|
||||
|
||||
/* The current scaled-IDCT routines require ISLOW-style multiplier tables,
|
||||
* so be sure to compile that code if either ISLOW or SCALING is requested.
|
||||
*/
|
||||
#ifdef DCT_ISLOW_SUPPORTED
|
||||
#define PROVIDE_ISLOW_TABLES
|
||||
#else
|
||||
#ifdef IDCT_SCALING_SUPPORTED
|
||||
#define PROVIDE_ISLOW_TABLES
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Prepare for an output pass.
|
||||
* Here we select the proper IDCT routine for each component and build
|
||||
* a matching multiplier table.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
start_pass (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_idct_ptr idct = (my_idct_ptr) cinfo->idct;
|
||||
int ci, i;
|
||||
jpeg_component_info *compptr;
|
||||
int method = 0;
|
||||
inverse_DCT_method_ptr method_ptr = NULL;
|
||||
JQUANT_TBL * qtbl;
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* Select the proper IDCT routine for this component's scaling */
|
||||
switch (compptr->DCT_scaled_size) {
|
||||
#ifdef IDCT_SCALING_SUPPORTED
|
||||
case 1:
|
||||
method_ptr = jpeg_idct_1x1;
|
||||
method = JDCT_ISLOW; /* jidctred uses islow-style table */
|
||||
break;
|
||||
case 2:
|
||||
method_ptr = jpeg_idct_2x2;
|
||||
method = JDCT_ISLOW; /* jidctred uses islow-style table */
|
||||
break;
|
||||
case 4:
|
||||
method_ptr = jpeg_idct_4x4;
|
||||
method = JDCT_ISLOW; /* jidctred uses islow-style table */
|
||||
break;
|
||||
#endif
|
||||
case DCTSIZE:
|
||||
switch (cinfo->dct_method) {
|
||||
#ifdef DCT_ISLOW_SUPPORTED
|
||||
case JDCT_ISLOW:
|
||||
method_ptr = jpeg_idct_islow;
|
||||
method = JDCT_ISLOW;
|
||||
break;
|
||||
#endif
|
||||
#ifdef DCT_IFAST_SUPPORTED
|
||||
case JDCT_IFAST:
|
||||
method_ptr = jpeg_idct_ifast;
|
||||
method = JDCT_IFAST;
|
||||
break;
|
||||
#endif
|
||||
#ifdef DCT_FLOAT_SUPPORTED
|
||||
case JDCT_FLOAT:
|
||||
method_ptr = my_jpeg_idct_float;
|
||||
method = JDCT_FLOAT;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size);
|
||||
break;
|
||||
}
|
||||
idct->pub.inverse_DCT[ci] = method_ptr;
|
||||
/* Create multiplier table from quant table.
|
||||
* However, we can skip this if the component is uninteresting
|
||||
* or if we already built the table. Also, if no quant table
|
||||
* has yet been saved for the component, we leave the
|
||||
* multiplier table all-zero; we'll be reading zeroes from the
|
||||
* coefficient controller's buffer anyway.
|
||||
*/
|
||||
if (! compptr->component_needed || idct->cur_method[ci] == method)
|
||||
continue;
|
||||
qtbl = compptr->quant_table;
|
||||
if (qtbl == NULL) /* happens if no data yet for component */
|
||||
continue;
|
||||
idct->cur_method[ci] = method;
|
||||
switch (method) {
|
||||
#ifdef PROVIDE_ISLOW_TABLES
|
||||
case JDCT_ISLOW:
|
||||
{
|
||||
/* For LL&M IDCT method, multipliers are equal to raw quantization
|
||||
* coefficients, but are stored in natural order as ints.
|
||||
*/
|
||||
ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table;
|
||||
for (i = 0; i < DCTSIZE2; i++) {
|
||||
ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[jpeg_zigzag_order[i]];
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef DCT_IFAST_SUPPORTED
|
||||
case JDCT_IFAST:
|
||||
{
|
||||
/* For AA&N IDCT method, multipliers are equal to quantization
|
||||
* coefficients scaled by scalefactor[row]*scalefactor[col], where
|
||||
* scalefactor[0] = 1
|
||||
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
|
||||
* For integer operation, the multiplier table is to be scaled by
|
||||
* IFAST_SCALE_BITS. The multipliers are stored in natural order.
|
||||
*/
|
||||
IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table;
|
||||
#define CONST_BITS 14
|
||||
static const INT16 aanscales[DCTSIZE2] = {
|
||||
/* precomputed values scaled up by 14 bits */
|
||||
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
|
||||
22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
|
||||
21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
|
||||
19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
|
||||
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
|
||||
12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
|
||||
8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
|
||||
4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
|
||||
};
|
||||
SHIFT_TEMPS
|
||||
|
||||
for (i = 0; i < DCTSIZE2; i++) {
|
||||
ifmtbl[i] = (IFAST_MULT_TYPE)
|
||||
DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[jpeg_zigzag_order[i]],
|
||||
(INT32) aanscales[i]),
|
||||
CONST_BITS-IFAST_SCALE_BITS);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef DCT_FLOAT_SUPPORTED
|
||||
case JDCT_FLOAT:
|
||||
{
|
||||
/* For float AA&N IDCT method, multipliers are equal to quantization
|
||||
* coefficients scaled by scalefactor[row]*scalefactor[col], where
|
||||
* scalefactor[0] = 1
|
||||
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
|
||||
* The multipliers are stored in natural order.
|
||||
*/
|
||||
FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table;
|
||||
int row, col;
|
||||
static const double aanscalefactor[DCTSIZE] = {
|
||||
1.0, 1.387039845, 1.306562965, 1.175875602,
|
||||
1.0, 0.785694958, 0.541196100, 0.275899379
|
||||
};
|
||||
|
||||
i = 0;
|
||||
for (row = 0; row < DCTSIZE; row++) {
|
||||
for (col = 0; col < DCTSIZE; col++) {
|
||||
fmtbl[i] = (FLOAT_MULT_TYPE)
|
||||
((double) qtbl->quantval[jpeg_zigzag_order[i]] *
|
||||
aanscalefactor[row] * aanscalefactor[col]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize IDCT manager.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jinit_inverse_dct (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_idct_ptr idct;
|
||||
int ci;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
idct = (my_idct_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(my_idct_controller));
|
||||
cinfo->idct = (struct jpeg_inverse_dct *) idct;
|
||||
idct->pub.start_pass = start_pass;
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* Allocate and pre-zero a multiplier table for each component */
|
||||
compptr->dct_table =
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(multiplier_table));
|
||||
MEMZERO(compptr->dct_table, SIZEOF(multiplier_table));
|
||||
/* Mark multiplier table not yet set up for any method */
|
||||
idct->cur_method[ci] = -1;
|
||||
}
|
||||
}
|
||||
574
RenderDll/Common/Textures/Image/jpeg6/jdhuff.cpp
Normal file
574
RenderDll/Common/Textures/Image/jpeg6/jdhuff.cpp
Normal file
@@ -0,0 +1,574 @@
|
||||
/*
|
||||
* jdhuff.c
|
||||
*
|
||||
* Copyright (C) 1991-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains Huffman entropy decoding routines.
|
||||
*
|
||||
* Much of the complexity here has to do with supporting input suspension.
|
||||
* If the data source module demands suspension, we want to be able to back
|
||||
* up to the start of the current MCU. To do this, we copy state variables
|
||||
* into local working storage, and update them back to the permanent
|
||||
* storage only upon successful completion of an MCU.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jdhuff.h" /* Declarations shared with jdphuff.c */
|
||||
|
||||
|
||||
/*
|
||||
* Expanded entropy decoder object for Huffman decoding.
|
||||
*
|
||||
* The savable_state subrecord contains fields that change within an MCU,
|
||||
* but must not be updated permanently until we complete the MCU.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
|
||||
} savable_state;
|
||||
|
||||
/* This macro is to work around compilers with missing or broken
|
||||
* structure assignment. You'll need to fix this code if you have
|
||||
* such a compiler and you change MAX_COMPS_IN_SCAN.
|
||||
*/
|
||||
|
||||
#ifndef NO_STRUCT_ASSIGN
|
||||
#define ASSIGN_STATE(dest,src) ((dest) = (src))
|
||||
#else
|
||||
#if MAX_COMPS_IN_SCAN == 4
|
||||
#define ASSIGN_STATE(dest,src) \
|
||||
((dest).last_dc_val[0] = (src).last_dc_val[0], \
|
||||
(dest).last_dc_val[1] = (src).last_dc_val[1], \
|
||||
(dest).last_dc_val[2] = (src).last_dc_val[2], \
|
||||
(dest).last_dc_val[3] = (src).last_dc_val[3])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_entropy_decoder pub; /* public fields */
|
||||
|
||||
/* These fields are loaded into local variables at start of each MCU.
|
||||
* In case of suspension, we exit WITHOUT updating them.
|
||||
*/
|
||||
bitread_perm_state bitstate; /* Bit buffer at start of MCU */
|
||||
savable_state saved; /* Other state at start of MCU */
|
||||
|
||||
/* These fields are NOT loaded into local working state. */
|
||||
unsigned int restarts_to_go; /* MCUs left in this restart interval */
|
||||
|
||||
/* Pointers to derived tables (these workspaces have image lifespan) */
|
||||
d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
|
||||
d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
|
||||
} huff_entropy_decoder;
|
||||
|
||||
typedef huff_entropy_decoder * huff_entropy_ptr;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for a Huffman-compressed scan.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
start_pass_huff_decoder (j_decompress_ptr cinfo)
|
||||
{
|
||||
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
|
||||
int ci, dctbl, actbl;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
/* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
|
||||
* This ought to be an error condition, but we make it a warning because
|
||||
* there are some baseline files out there with all zeroes in these bytes.
|
||||
*/
|
||||
if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 ||
|
||||
cinfo->Ah != 0 || cinfo->Al != 0)
|
||||
WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
dctbl = compptr->dc_tbl_no;
|
||||
actbl = compptr->ac_tbl_no;
|
||||
/* Make sure requested tables are present */
|
||||
if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS ||
|
||||
cinfo->dc_huff_tbl_ptrs[dctbl] == NULL)
|
||||
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
|
||||
if (actbl < 0 || actbl >= NUM_HUFF_TBLS ||
|
||||
cinfo->ac_huff_tbl_ptrs[actbl] == NULL)
|
||||
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl);
|
||||
/* Compute derived values for Huffman tables */
|
||||
/* We may do this more than once for a table, but it's not expensive */
|
||||
my_jpeg_make_d_derived_tbl(cinfo, cinfo->dc_huff_tbl_ptrs[dctbl],
|
||||
& entropy->dc_derived_tbls[dctbl]);
|
||||
my_jpeg_make_d_derived_tbl(cinfo, cinfo->ac_huff_tbl_ptrs[actbl],
|
||||
& entropy->ac_derived_tbls[actbl]);
|
||||
/* Initialize DC predictions to 0 */
|
||||
entropy->saved.last_dc_val[ci] = 0;
|
||||
}
|
||||
|
||||
/* Initialize bitread state variables */
|
||||
entropy->bitstate.bits_left = 0;
|
||||
entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
|
||||
entropy->bitstate.printed_eod = FALSE;
|
||||
|
||||
/* Initialize restart counter */
|
||||
entropy->restarts_to_go = cinfo->restart_interval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compute the derived values for a Huffman table.
|
||||
* Note this is also used by jdphuff.c.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, JHUFF_TBL * htbl,
|
||||
d_derived_tbl ** pdtbl)
|
||||
{
|
||||
d_derived_tbl *dtbl;
|
||||
int p, i, l, si;
|
||||
int lookbits, ctr;
|
||||
char huffsize[257];
|
||||
unsigned int huffcode[257];
|
||||
unsigned int code;
|
||||
|
||||
/* Allocate a workspace if we haven't already done so. */
|
||||
if (*pdtbl == NULL)
|
||||
*pdtbl = (d_derived_tbl *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(d_derived_tbl));
|
||||
dtbl = *pdtbl;
|
||||
dtbl->pub = htbl; /* fill in back link */
|
||||
|
||||
/* Figure C.1: make table of Huffman code length for each symbol */
|
||||
/* Note that this is in code-length order. */
|
||||
|
||||
p = 0;
|
||||
for (l = 1; l <= 16; l++) {
|
||||
for (i = 1; i <= (int) htbl->bits[l]; i++)
|
||||
huffsize[p++] = (char) l;
|
||||
}
|
||||
huffsize[p] = 0;
|
||||
|
||||
/* Figure C.2: generate the codes themselves */
|
||||
/* Note that this is in code-length order. */
|
||||
|
||||
code = 0;
|
||||
si = huffsize[0];
|
||||
p = 0;
|
||||
while (huffsize[p]) {
|
||||
while (((int) huffsize[p]) == si) {
|
||||
huffcode[p++] = code;
|
||||
code++;
|
||||
}
|
||||
code <<= 1;
|
||||
si++;
|
||||
}
|
||||
|
||||
/* Figure F.15: generate decoding tables for bit-sequential decoding */
|
||||
|
||||
p = 0;
|
||||
for (l = 1; l <= 16; l++) {
|
||||
if (htbl->bits[l]) {
|
||||
dtbl->valptr[l] = p; /* huffval[] index of 1st symbol of code length l */
|
||||
dtbl->mincode[l] = huffcode[p]; /* minimum code of length l */
|
||||
p += htbl->bits[l];
|
||||
dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
|
||||
} else {
|
||||
dtbl->maxcode[l] = -1; /* -1 if no codes of this length */
|
||||
}
|
||||
}
|
||||
dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */
|
||||
|
||||
/* Compute lookahead tables to speed up decoding.
|
||||
* First we set all the table entries to 0, indicating "too long";
|
||||
* then we iterate through the Huffman codes that are short enough and
|
||||
* fill in all the entries that correspond to bit sequences starting
|
||||
* with that code.
|
||||
*/
|
||||
|
||||
MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits));
|
||||
|
||||
p = 0;
|
||||
for (l = 1; l <= HUFF_LOOKAHEAD; l++) {
|
||||
for (i = 1; i <= (int) htbl->bits[l]; i++, p++) {
|
||||
/* l = current code's length, p = its index in huffcode[] & huffval[]. */
|
||||
/* Generate left-justified code followed by all possible bit sequences */
|
||||
lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
|
||||
for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) {
|
||||
dtbl->look_nbits[lookbits] = l;
|
||||
dtbl->look_sym[lookbits] = htbl->huffval[p];
|
||||
lookbits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Out-of-line code for bit fetching (shared with jdphuff.c).
|
||||
* See jdhuff.h for info about usage.
|
||||
* Note: current values of get_buffer and bits_left are passed as parameters,
|
||||
* but are returned in the corresponding fields of the state struct.
|
||||
*
|
||||
* On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width
|
||||
* of get_buffer to be used. (On machines with wider words, an even larger
|
||||
* buffer could be used.) However, on some machines 32-bit shifts are
|
||||
* quite slow and take time proportional to the number of places shifted.
|
||||
* (This is true with most PC compilers, for instance.) In this case it may
|
||||
* be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the
|
||||
* average shift distance at the cost of more calls to jpeg_fill_bit_buffer.
|
||||
*/
|
||||
|
||||
#ifdef SLOW_SHIFT_32
|
||||
#define MIN_GET_BITS 15 /* minimum allowable value */
|
||||
#else
|
||||
#define MIN_GET_BITS (BIT_BUF_SIZE-7)
|
||||
#endif
|
||||
|
||||
|
||||
GLOBAL boolean
|
||||
my_jpeg_fill_bit_buffer (bitread_working_state * state,
|
||||
register bit_buf_type get_buffer, register int bits_left,
|
||||
int nbits)
|
||||
/* Load up the bit buffer to a depth of at least nbits */
|
||||
{
|
||||
/* Copy heavily used state fields into locals (hopefully registers) */
|
||||
register const JOCTET * next_input_byte = state->next_input_byte;
|
||||
register size_t bytes_in_buffer = state->bytes_in_buffer;
|
||||
register int c;
|
||||
|
||||
/* Attempt to load at least MIN_GET_BITS bits into get_buffer. */
|
||||
/* (It is assumed that no request will be for more than that many bits.) */
|
||||
|
||||
while (bits_left < MIN_GET_BITS) {
|
||||
/* Attempt to read a byte */
|
||||
if (state->unread_marker != 0)
|
||||
goto no_more_data; /* can't advance past a marker */
|
||||
|
||||
if (bytes_in_buffer == 0) {
|
||||
if (! (*state->cinfo->src->fill_input_buffer) (state->cinfo))
|
||||
return FALSE;
|
||||
next_input_byte = state->cinfo->src->next_input_byte;
|
||||
bytes_in_buffer = state->cinfo->src->bytes_in_buffer;
|
||||
}
|
||||
bytes_in_buffer--;
|
||||
c = GETJOCTET(*next_input_byte++);
|
||||
|
||||
/* If it's 0xFF, check and discard stuffed zero byte */
|
||||
if (c == 0xFF) {
|
||||
do {
|
||||
if (bytes_in_buffer == 0) {
|
||||
if (! (*state->cinfo->src->fill_input_buffer) (state->cinfo))
|
||||
return FALSE;
|
||||
next_input_byte = state->cinfo->src->next_input_byte;
|
||||
bytes_in_buffer = state->cinfo->src->bytes_in_buffer;
|
||||
}
|
||||
bytes_in_buffer--;
|
||||
c = GETJOCTET(*next_input_byte++);
|
||||
} while (c == 0xFF);
|
||||
|
||||
if (c == 0) {
|
||||
/* Found FF/00, which represents an FF data byte */
|
||||
c = 0xFF;
|
||||
} else {
|
||||
/* Oops, it's actually a marker indicating end of compressed data. */
|
||||
/* Better put it back for use later */
|
||||
state->unread_marker = c;
|
||||
|
||||
no_more_data:
|
||||
/* There should be enough bits still left in the data segment; */
|
||||
/* if so, just break out of the outer while loop. */
|
||||
if (bits_left >= nbits)
|
||||
break;
|
||||
/* Uh-oh. Report corrupted data to user and stuff zeroes into
|
||||
* the data stream, so that we can produce some kind of image.
|
||||
* Note that this code will be repeated for each byte demanded
|
||||
* for the rest of the segment. We use a nonvolatile flag to ensure
|
||||
* that only one warning message appears.
|
||||
*/
|
||||
if (! *(state->printed_eod_ptr)) {
|
||||
WARNMS(state->cinfo, JWRN_HIT_MARKER);
|
||||
*(state->printed_eod_ptr) = TRUE;
|
||||
}
|
||||
c = 0; /* insert a zero byte into bit buffer */
|
||||
}
|
||||
}
|
||||
|
||||
/* OK, load c into get_buffer */
|
||||
get_buffer = (get_buffer << 8) | c;
|
||||
bits_left += 8;
|
||||
}
|
||||
|
||||
/* Unload the local registers */
|
||||
state->next_input_byte = next_input_byte;
|
||||
state->bytes_in_buffer = bytes_in_buffer;
|
||||
state->get_buffer = get_buffer;
|
||||
state->bits_left = bits_left;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Out-of-line code for Huffman code decoding.
|
||||
* See jdhuff.h for info about usage.
|
||||
*/
|
||||
|
||||
GLOBAL int
|
||||
my_jpeg_huff_decode (bitread_working_state * state,
|
||||
register bit_buf_type get_buffer, register int bits_left,
|
||||
d_derived_tbl * htbl, int min_bits)
|
||||
{
|
||||
register int l = min_bits;
|
||||
register INT32 code;
|
||||
|
||||
/* HUFF_DECODE has determined that the code is at least min_bits */
|
||||
/* bits long, so fetch that many bits in one swoop. */
|
||||
|
||||
CHECK_BIT_BUFFER(*state, l, return -1);
|
||||
code = GET_BITS(l);
|
||||
|
||||
/* Collect the rest of the Huffman code one bit at a time. */
|
||||
/* This is per Figure F.16 in the JPEG spec. */
|
||||
|
||||
while (code > htbl->maxcode[l]) {
|
||||
code <<= 1;
|
||||
CHECK_BIT_BUFFER(*state, 1, return -1);
|
||||
code |= GET_BITS(1);
|
||||
l++;
|
||||
}
|
||||
|
||||
/* Unload the local registers */
|
||||
state->get_buffer = get_buffer;
|
||||
state->bits_left = bits_left;
|
||||
|
||||
/* With garbage input we may reach the sentinel value l = 17. */
|
||||
|
||||
if (l > 16) {
|
||||
WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE);
|
||||
return 0; /* fake a zero as the safest result */
|
||||
}
|
||||
|
||||
return htbl->pub->huffval[ htbl->valptr[l] +
|
||||
((int) (code - htbl->mincode[l])) ];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Figure F.12: extend sign bit.
|
||||
* On some machines, a shift and add will be faster than a table lookup.
|
||||
*/
|
||||
|
||||
#ifdef AVOID_TABLES
|
||||
|
||||
#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
|
||||
|
||||
#else
|
||||
|
||||
#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
|
||||
|
||||
static const int extend_test[16] = /* entry n is 2**(n-1) */
|
||||
{ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
|
||||
0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
|
||||
|
||||
static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
|
||||
{ 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
|
||||
((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
|
||||
((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
|
||||
((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
|
||||
|
||||
#endif /* AVOID_TABLES */
|
||||
|
||||
|
||||
/*
|
||||
* Check for a restart marker & resynchronize decoder.
|
||||
* Returns FALSE if must suspend.
|
||||
*/
|
||||
|
||||
LOCAL boolean
|
||||
process_restart (j_decompress_ptr cinfo)
|
||||
{
|
||||
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
|
||||
int ci;
|
||||
|
||||
/* Throw away any unused bits remaining in bit buffer; */
|
||||
/* include any full bytes in next_marker's count of discarded bytes */
|
||||
cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
|
||||
entropy->bitstate.bits_left = 0;
|
||||
|
||||
/* Advance past the RSTn marker */
|
||||
if (! (*cinfo->marker->read_restart_marker) (cinfo))
|
||||
return FALSE;
|
||||
|
||||
/* Re-initialize DC predictions to 0 */
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++)
|
||||
entropy->saved.last_dc_val[ci] = 0;
|
||||
|
||||
/* Reset restart counter */
|
||||
entropy->restarts_to_go = cinfo->restart_interval;
|
||||
|
||||
/* Next segment can get another out-of-data warning */
|
||||
entropy->bitstate.printed_eod = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decode and return one MCU's worth of Huffman-compressed coefficients.
|
||||
* The coefficients are reordered from zigzag order into natural array order,
|
||||
* but are not dequantized.
|
||||
*
|
||||
* The i'th block of the MCU is stored into the block pointed to by
|
||||
* MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER.
|
||||
* (Wholesale zeroing is usually a little faster than retail...)
|
||||
*
|
||||
* Returns FALSE if data source requested suspension. In that case no
|
||||
* changes have been made to permanent state. (Exception: some output
|
||||
* coefficients may already have been assigned. This is harmless for
|
||||
* this module, since we'll just re-assign them on the next call.)
|
||||
*/
|
||||
|
||||
METHODDEF boolean
|
||||
decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
|
||||
{
|
||||
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
|
||||
register int s, k, r;
|
||||
int blkn, ci;
|
||||
JBLOCKROW block;
|
||||
BITREAD_STATE_VARS;
|
||||
savable_state state;
|
||||
d_derived_tbl * dctbl;
|
||||
d_derived_tbl * actbl;
|
||||
jpeg_component_info * compptr;
|
||||
|
||||
/* Process restart marker if needed; may have to suspend */
|
||||
if (cinfo->restart_interval) {
|
||||
if (entropy->restarts_to_go == 0)
|
||||
if (! process_restart(cinfo))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Load up working state */
|
||||
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
|
||||
ASSIGN_STATE(state, entropy->saved);
|
||||
|
||||
/* Outer loop handles each block in the MCU */
|
||||
|
||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||
block = MCU_data[blkn];
|
||||
ci = cinfo->MCU_membership[blkn];
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
dctbl = entropy->dc_derived_tbls[compptr->dc_tbl_no];
|
||||
actbl = entropy->ac_derived_tbls[compptr->ac_tbl_no];
|
||||
|
||||
/* Decode a single block's worth of coefficients */
|
||||
|
||||
/* Section F.2.2.1: decode the DC coefficient difference */
|
||||
HUFF_DECODE(s, br_state, dctbl, return FALSE, label1);
|
||||
if (s) {
|
||||
CHECK_BIT_BUFFER(br_state, s, return FALSE);
|
||||
r = GET_BITS(s);
|
||||
s = HUFF_EXTEND(r, s);
|
||||
}
|
||||
|
||||
/* Shortcut if component's values are not interesting */
|
||||
if (! compptr->component_needed)
|
||||
goto skip_ACs;
|
||||
|
||||
/* Convert DC difference to actual value, update last_dc_val */
|
||||
s += state.last_dc_val[ci];
|
||||
state.last_dc_val[ci] = s;
|
||||
/* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
|
||||
(*block)[0] = (JCOEF) s;
|
||||
|
||||
/* Do we need to decode the AC coefficients for this component? */
|
||||
if (compptr->DCT_scaled_size > 1) {
|
||||
|
||||
/* Section F.2.2.2: decode the AC coefficients */
|
||||
/* Since zeroes are skipped, output area must be cleared beforehand */
|
||||
for (k = 1; k < DCTSIZE2; k++) {
|
||||
HUFF_DECODE(s, br_state, actbl, return FALSE, label2);
|
||||
|
||||
r = s >> 4;
|
||||
s &= 15;
|
||||
|
||||
if (s) {
|
||||
k += r;
|
||||
CHECK_BIT_BUFFER(br_state, s, return FALSE);
|
||||
r = GET_BITS(s);
|
||||
s = HUFF_EXTEND(r, s);
|
||||
/* Output coefficient in natural (dezigzagged) order.
|
||||
* Note: the extra entries in jpeg_natural_order[] will save us
|
||||
* if k >= DCTSIZE2, which could happen if the data is corrupted.
|
||||
*/
|
||||
(*block)[jpeg_natural_order[k]] = (JCOEF) s;
|
||||
} else {
|
||||
if (r != 15)
|
||||
break;
|
||||
k += 15;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
skip_ACs:
|
||||
|
||||
/* Section F.2.2.2: decode the AC coefficients */
|
||||
/* In this path we just discard the values */
|
||||
for (k = 1; k < DCTSIZE2; k++) {
|
||||
HUFF_DECODE(s, br_state, actbl, return FALSE, label3);
|
||||
|
||||
r = s >> 4;
|
||||
s &= 15;
|
||||
|
||||
if (s) {
|
||||
k += r;
|
||||
CHECK_BIT_BUFFER(br_state, s, return FALSE);
|
||||
DROP_BITS(s);
|
||||
} else {
|
||||
if (r != 15)
|
||||
break;
|
||||
k += 15;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Completed MCU, so update state */
|
||||
BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
|
||||
ASSIGN_STATE(entropy->saved, state);
|
||||
|
||||
/* Account for restart interval (no-op if not using restarts) */
|
||||
entropy->restarts_to_go--;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Module initialization routine for Huffman entropy decoding.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jinit_huff_decoder (j_decompress_ptr cinfo)
|
||||
{
|
||||
huff_entropy_ptr entropy;
|
||||
int i;
|
||||
|
||||
entropy = (huff_entropy_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(huff_entropy_decoder));
|
||||
cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
|
||||
entropy->pub.start_pass = start_pass_huff_decoder;
|
||||
entropy->pub.decode_mcu = decode_mcu;
|
||||
|
||||
/* Mark tables unallocated */
|
||||
for (i = 0; i < NUM_HUFF_TBLS; i++) {
|
||||
entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
|
||||
}
|
||||
}
|
||||
202
RenderDll/Common/Textures/Image/jpeg6/jdhuff.h
Normal file
202
RenderDll/Common/Textures/Image/jpeg6/jdhuff.h
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* jdhuff.h
|
||||
*
|
||||
* Copyright (C) 1991-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains declarations for Huffman entropy decoding routines
|
||||
* that are shared between the sequential decoder (jdhuff.c) and the
|
||||
* progressive decoder (jdphuff.c). No other modules need to see these.
|
||||
*/
|
||||
|
||||
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||
|
||||
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||
#define my_jpeg_make_d_derived_tbl jMkDDerived
|
||||
#define my_jpeg_fill_bit_buffer jFilBitBuf
|
||||
#define my_jpeg_huff_decode jHufDecode
|
||||
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||
|
||||
|
||||
/* Derived data constructed for each Huffman table */
|
||||
|
||||
#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */
|
||||
|
||||
typedef struct {
|
||||
/* Basic tables: (element [0] of each array is unused) */
|
||||
INT32 mincode[17]; /* smallest code of length k */
|
||||
INT32 maxcode[18]; /* largest code of length k (-1 if none) */
|
||||
/* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */
|
||||
int valptr[17]; /* huffval[] index of 1st symbol of length k */
|
||||
|
||||
/* Link to public Huffman table (needed only in jpeg_huff_decode) */
|
||||
JHUFF_TBL *pub;
|
||||
|
||||
/* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of
|
||||
* the input data stream. If the next Huffman code is no more
|
||||
* than HUFF_LOOKAHEAD bits long, we can obtain its length and
|
||||
* the corresponding symbol directly from these tables.
|
||||
*/
|
||||
int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */
|
||||
UINT8 look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */
|
||||
} d_derived_tbl;
|
||||
|
||||
/* Expand a Huffman table definition into the derived format */
|
||||
EXTERN void my_jpeg_make_d_derived_tbl JPP((j_decompress_ptr cinfo,
|
||||
JHUFF_TBL * htbl, d_derived_tbl ** pdtbl));
|
||||
|
||||
|
||||
/*
|
||||
* Fetching the next N bits from the input stream is a time-critical operation
|
||||
* for the Huffman decoders. We implement it with a combination of inline
|
||||
* macros and out-of-line subroutines. Note that N (the number of bits
|
||||
* demanded at one time) never exceeds 15 for JPEG use.
|
||||
*
|
||||
* We read source bytes into get_buffer and dole out bits as needed.
|
||||
* If get_buffer already contains enough bits, they are fetched in-line
|
||||
* by the macros CHECK_BIT_BUFFER and GET_BITS. When there aren't enough
|
||||
* bits, jpeg_fill_bit_buffer is called; it will attempt to fill get_buffer
|
||||
* as full as possible (not just to the number of bits needed; this
|
||||
* prefetching reduces the overhead cost of calling jpeg_fill_bit_buffer).
|
||||
* Note that jpeg_fill_bit_buffer may return FALSE to indicate suspension.
|
||||
* On TRUE return, jpeg_fill_bit_buffer guarantees that get_buffer contains
|
||||
* at least the requested number of bits --- dummy zeroes are inserted if
|
||||
* necessary.
|
||||
*/
|
||||
|
||||
typedef INT32 bit_buf_type; /* type of bit-extraction buffer */
|
||||
#define BIT_BUF_SIZE 32 /* size of buffer in bits */
|
||||
|
||||
/* If long is > 32 bits on your machine, and shifting/masking longs is
|
||||
* reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE
|
||||
* appropriately should be a win. Unfortunately we can't do this with
|
||||
* something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8)
|
||||
* because not all machines measure sizeof in 8-bit bytes.
|
||||
*/
|
||||
|
||||
typedef struct { /* Bitreading state saved across MCUs */
|
||||
bit_buf_type get_buffer; /* current bit-extraction buffer */
|
||||
int bits_left; /* # of unused bits in it */
|
||||
boolean printed_eod; /* flag to suppress multiple warning msgs */
|
||||
} bitread_perm_state;
|
||||
|
||||
typedef struct { /* Bitreading working state within an MCU */
|
||||
/* current data source state */
|
||||
const JOCTET * next_input_byte; /* => next byte to read from source */
|
||||
size_t bytes_in_buffer; /* # of bytes remaining in source buffer */
|
||||
int unread_marker; /* nonzero if we have hit a marker */
|
||||
/* bit input buffer --- note these values are kept in register variables,
|
||||
* not in this struct, inside the inner loops.
|
||||
*/
|
||||
bit_buf_type get_buffer; /* current bit-extraction buffer */
|
||||
int bits_left; /* # of unused bits in it */
|
||||
/* pointers needed by jpeg_fill_bit_buffer */
|
||||
j_decompress_ptr cinfo; /* back link to decompress master record */
|
||||
boolean * printed_eod_ptr; /* => flag in permanent state */
|
||||
} bitread_working_state;
|
||||
|
||||
/* Macros to declare and load/save bitread local variables. */
|
||||
#define BITREAD_STATE_VARS \
|
||||
register bit_buf_type get_buffer; \
|
||||
register int bits_left; \
|
||||
bitread_working_state br_state
|
||||
|
||||
#define BITREAD_LOAD_STATE(cinfop,permstate) \
|
||||
br_state.cinfo = cinfop; \
|
||||
br_state.next_input_byte = cinfop->src->next_input_byte; \
|
||||
br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \
|
||||
br_state.unread_marker = cinfop->unread_marker; \
|
||||
get_buffer = permstate.get_buffer; \
|
||||
bits_left = permstate.bits_left; \
|
||||
br_state.printed_eod_ptr = & permstate.printed_eod
|
||||
|
||||
#define BITREAD_SAVE_STATE(cinfop,permstate) \
|
||||
cinfop->src->next_input_byte = br_state.next_input_byte; \
|
||||
cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \
|
||||
cinfop->unread_marker = br_state.unread_marker; \
|
||||
permstate.get_buffer = get_buffer; \
|
||||
permstate.bits_left = bits_left
|
||||
|
||||
/*
|
||||
* These macros provide the in-line portion of bit fetching.
|
||||
* Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer
|
||||
* before using GET_BITS, PEEK_BITS, or DROP_BITS.
|
||||
* The variables get_buffer and bits_left are assumed to be locals,
|
||||
* but the state struct might not be (jpeg_huff_decode needs this).
|
||||
* CHECK_BIT_BUFFER(state,n,action);
|
||||
* Ensure there are N bits in get_buffer; if suspend, take action.
|
||||
* val = GET_BITS(n);
|
||||
* Fetch next N bits.
|
||||
* val = PEEK_BITS(n);
|
||||
* Fetch next N bits without removing them from the buffer.
|
||||
* DROP_BITS(n);
|
||||
* Discard next N bits.
|
||||
* The value N should be a simple variable, not an expression, because it
|
||||
* is evaluated multiple times.
|
||||
*/
|
||||
|
||||
#define CHECK_BIT_BUFFER(state,nbits,action) \
|
||||
{ if (bits_left < (nbits)) { \
|
||||
if (! my_jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \
|
||||
{ action; } \
|
||||
get_buffer = (state).get_buffer; bits_left = (state).bits_left; } }
|
||||
|
||||
#define GET_BITS(nbits) \
|
||||
(((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1))
|
||||
|
||||
#define PEEK_BITS(nbits) \
|
||||
(((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1))
|
||||
|
||||
#define DROP_BITS(nbits) \
|
||||
(bits_left -= (nbits))
|
||||
|
||||
/* Load up the bit buffer to a depth of at least nbits */
|
||||
EXTERN boolean my_jpeg_fill_bit_buffer JPP((bitread_working_state * state,
|
||||
register bit_buf_type get_buffer, register int bits_left,
|
||||
int nbits));
|
||||
|
||||
|
||||
/*
|
||||
* Code for extracting next Huffman-coded symbol from input bit stream.
|
||||
* Again, this is time-critical and we make the main paths be macros.
|
||||
*
|
||||
* We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits
|
||||
* without looping. Usually, more than 95% of the Huffman codes will be 8
|
||||
* or fewer bits long. The few overlength codes are handled with a loop,
|
||||
* which need not be inline code.
|
||||
*
|
||||
* Notes about the HUFF_DECODE macro:
|
||||
* 1. Near the end of the data segment, we may fail to get enough bits
|
||||
* for a lookahead. In that case, we do it the hard way.
|
||||
* 2. If the lookahead table contains no entry, the next code must be
|
||||
* more than HUFF_LOOKAHEAD bits long.
|
||||
* 3. jpeg_huff_decode returns -1 if forced to suspend.
|
||||
*/
|
||||
|
||||
#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \
|
||||
{ register int nb, look; \
|
||||
if (bits_left < HUFF_LOOKAHEAD) { \
|
||||
if (! my_jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \
|
||||
get_buffer = state.get_buffer; bits_left = state.bits_left; \
|
||||
if (bits_left < HUFF_LOOKAHEAD) { \
|
||||
nb = 1; goto slowlabel; \
|
||||
} \
|
||||
} \
|
||||
look = PEEK_BITS(HUFF_LOOKAHEAD); \
|
||||
if ((nb = htbl->look_nbits[look]) != 0) { \
|
||||
DROP_BITS(nb); \
|
||||
result = htbl->look_sym[look]; \
|
||||
} else { \
|
||||
nb = HUFF_LOOKAHEAD+1; \
|
||||
slowlabel: \
|
||||
if ((result=my_jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \
|
||||
{ failaction; } \
|
||||
get_buffer = state.get_buffer; bits_left = state.bits_left; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Out-of-line case for Huffman code fetching */
|
||||
EXTERN int my_jpeg_huff_decode JPP((bitread_working_state * state,
|
||||
register bit_buf_type get_buffer, register int bits_left,
|
||||
d_derived_tbl * htbl, int min_bits));
|
||||
381
RenderDll/Common/Textures/Image/jpeg6/jdinput.cpp
Normal file
381
RenderDll/Common/Textures/Image/jpeg6/jdinput.cpp
Normal file
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
* jdinput.c
|
||||
*
|
||||
* Copyright (C) 1991-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains input control logic for the JPEG decompressor.
|
||||
* These routines are concerned with controlling the decompressor's input
|
||||
* processing (marker reading and coefficient decoding). The actual input
|
||||
* reading is done in jdmarker.c, jdhuff.c, and jdphuff.c.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
|
||||
/* Private state */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_input_controller pub; /* public fields */
|
||||
|
||||
boolean inheaders; /* TRUE until first SOS is reached */
|
||||
} my_input_controller;
|
||||
|
||||
typedef my_input_controller * my_inputctl_ptr;
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
METHODDEF int consume_markers JPP((j_decompress_ptr cinfo));
|
||||
|
||||
|
||||
/*
|
||||
* Routines to calculate various quantities related to the size of the image.
|
||||
*/
|
||||
|
||||
LOCAL void
|
||||
initial_setup (j_decompress_ptr cinfo)
|
||||
/* Called once, when first SOS marker is reached */
|
||||
{
|
||||
int ci;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Make sure image isn't bigger than I can handle */
|
||||
if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
|
||||
(long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
|
||||
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
|
||||
|
||||
/* For now, precision must match compiled-in value... */
|
||||
if (cinfo->data_precision != BITS_IN_JSAMPLE)
|
||||
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
|
||||
|
||||
/* Check that number of components won't exceed internal array sizes */
|
||||
if (cinfo->num_components > MAX_COMPONENTS)
|
||||
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
|
||||
MAX_COMPONENTS);
|
||||
|
||||
/* Compute maximum sampling factors; check factor validity */
|
||||
cinfo->max_h_samp_factor = 1;
|
||||
cinfo->max_v_samp_factor = 1;
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
|
||||
compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
|
||||
ERREXIT(cinfo, JERR_BAD_SAMPLING);
|
||||
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
|
||||
compptr->h_samp_factor);
|
||||
cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
|
||||
compptr->v_samp_factor);
|
||||
}
|
||||
|
||||
/* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE.
|
||||
* In the full decompressor, this will be overridden by jdmaster.c;
|
||||
* but in the transcoder, jdmaster.c is not used, so we must do it here.
|
||||
*/
|
||||
cinfo->min_DCT_scaled_size = DCTSIZE;
|
||||
|
||||
/* Compute dimensions of components */
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
compptr->DCT_scaled_size = DCTSIZE;
|
||||
/* Size in DCT blocks */
|
||||
compptr->width_in_blocks = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
|
||||
(long) (cinfo->max_h_samp_factor * DCTSIZE));
|
||||
compptr->height_in_blocks = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
|
||||
(long) (cinfo->max_v_samp_factor * DCTSIZE));
|
||||
/* downsampled_width and downsampled_height will also be overridden by
|
||||
* jdmaster.c if we are doing full decompression. The transcoder library
|
||||
* doesn't use these values, but the calling application might.
|
||||
*/
|
||||
/* Size in samples */
|
||||
compptr->downsampled_width = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
|
||||
(long) cinfo->max_h_samp_factor);
|
||||
compptr->downsampled_height = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
|
||||
(long) cinfo->max_v_samp_factor);
|
||||
/* Mark component needed, until color conversion says otherwise */
|
||||
compptr->component_needed = TRUE;
|
||||
/* Mark no quantization table yet saved for component */
|
||||
compptr->quant_table = NULL;
|
||||
}
|
||||
|
||||
/* Compute number of fully interleaved MCU rows. */
|
||||
cinfo->total_iMCU_rows = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height,
|
||||
(long) (cinfo->max_v_samp_factor*DCTSIZE));
|
||||
|
||||
/* Decide whether file contains multiple scans */
|
||||
if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode)
|
||||
cinfo->inputctl->has_multiple_scans = TRUE;
|
||||
else
|
||||
cinfo->inputctl->has_multiple_scans = FALSE;
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
per_scan_setup (j_decompress_ptr cinfo)
|
||||
/* Do computations that are needed before processing a JPEG scan */
|
||||
/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */
|
||||
{
|
||||
int ci, mcublks, tmp;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
if (cinfo->comps_in_scan == 1) {
|
||||
|
||||
/* Noninterleaved (single-component) scan */
|
||||
compptr = cinfo->cur_comp_info[0];
|
||||
|
||||
/* Overall image size in MCUs */
|
||||
cinfo->MCUs_per_row = compptr->width_in_blocks;
|
||||
cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
|
||||
|
||||
/* For noninterleaved scan, always one block per MCU */
|
||||
compptr->MCU_width = 1;
|
||||
compptr->MCU_height = 1;
|
||||
compptr->MCU_blocks = 1;
|
||||
compptr->MCU_sample_width = compptr->DCT_scaled_size;
|
||||
compptr->last_col_width = 1;
|
||||
/* For noninterleaved scans, it is convenient to define last_row_height
|
||||
* as the number of block rows present in the last iMCU row.
|
||||
*/
|
||||
tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
|
||||
if (tmp == 0) tmp = compptr->v_samp_factor;
|
||||
compptr->last_row_height = tmp;
|
||||
|
||||
/* Prepare array describing MCU composition */
|
||||
cinfo->blocks_in_MCU = 1;
|
||||
cinfo->MCU_membership[0] = 0;
|
||||
|
||||
} else {
|
||||
|
||||
/* Interleaved (multi-component) scan */
|
||||
if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
|
||||
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
|
||||
MAX_COMPS_IN_SCAN);
|
||||
|
||||
/* Overall image size in MCUs */
|
||||
cinfo->MCUs_per_row = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width,
|
||||
(long) (cinfo->max_h_samp_factor*DCTSIZE));
|
||||
cinfo->MCU_rows_in_scan = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height,
|
||||
(long) (cinfo->max_v_samp_factor*DCTSIZE));
|
||||
|
||||
cinfo->blocks_in_MCU = 0;
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
/* Sampling factors give # of blocks of component in each MCU */
|
||||
compptr->MCU_width = compptr->h_samp_factor;
|
||||
compptr->MCU_height = compptr->v_samp_factor;
|
||||
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
|
||||
compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size;
|
||||
/* Figure number of non-dummy blocks in last MCU column & row */
|
||||
tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
|
||||
if (tmp == 0) tmp = compptr->MCU_width;
|
||||
compptr->last_col_width = tmp;
|
||||
tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
|
||||
if (tmp == 0) tmp = compptr->MCU_height;
|
||||
compptr->last_row_height = tmp;
|
||||
/* Prepare array describing MCU composition */
|
||||
mcublks = compptr->MCU_blocks;
|
||||
if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU)
|
||||
ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
|
||||
while (mcublks-- > 0) {
|
||||
cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save away a copy of the Q-table referenced by each component present
|
||||
* in the current scan, unless already saved during a prior scan.
|
||||
*
|
||||
* In a multiple-scan JPEG file, the encoder could assign different components
|
||||
* the same Q-table slot number, but change table definitions between scans
|
||||
* so that each component uses a different Q-table. (The IJG encoder is not
|
||||
* currently capable of doing this, but other encoders might.) Since we want
|
||||
* to be able to dequantize all the components at the end of the file, this
|
||||
* means that we have to save away the table actually used for each component.
|
||||
* We do this by copying the table at the start of the first scan containing
|
||||
* the component.
|
||||
* The JPEG spec prohibits the encoder from changing the contents of a Q-table
|
||||
* slot between scans of a component using that slot. If the encoder does so
|
||||
* anyway, this decoder will simply use the Q-table values that were current
|
||||
* at the start of the first scan for the component.
|
||||
*
|
||||
* The decompressor output side looks only at the saved quant tables,
|
||||
* not at the current Q-table slots.
|
||||
*/
|
||||
|
||||
LOCAL void
|
||||
latch_quant_tables (j_decompress_ptr cinfo)
|
||||
{
|
||||
int ci, qtblno;
|
||||
jpeg_component_info *compptr;
|
||||
JQUANT_TBL * qtbl;
|
||||
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
/* No work if we already saved Q-table for this component */
|
||||
if (compptr->quant_table != NULL)
|
||||
continue;
|
||||
/* Make sure specified quantization table is present */
|
||||
qtblno = compptr->quant_tbl_no;
|
||||
if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
|
||||
cinfo->quant_tbl_ptrs[qtblno] == NULL)
|
||||
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
|
||||
/* OK, save away the quantization table */
|
||||
qtbl = (JQUANT_TBL *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(JQUANT_TBL));
|
||||
MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL));
|
||||
compptr->quant_table = qtbl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the input modules to read a scan of compressed data.
|
||||
* The first call to this is done by jdmaster.c after initializing
|
||||
* the entire decompressor (during jpeg_start_decompress).
|
||||
* Subsequent calls come from consume_markers, below.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
start_input_pass (j_decompress_ptr cinfo)
|
||||
{
|
||||
per_scan_setup(cinfo);
|
||||
latch_quant_tables(cinfo);
|
||||
(*cinfo->entropy->start_pass) (cinfo);
|
||||
(*cinfo->coef->start_input_pass) (cinfo);
|
||||
cinfo->inputctl->consume_input = cinfo->coef->consume_data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up after inputting a compressed-data scan.
|
||||
* This is called by the coefficient controller after it's read all
|
||||
* the expected data of the scan.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
finish_input_pass (j_decompress_ptr cinfo)
|
||||
{
|
||||
cinfo->inputctl->consume_input = consume_markers;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read JPEG markers before, between, or after compressed-data scans.
|
||||
* Change state as necessary when a new scan is reached.
|
||||
* Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
|
||||
*
|
||||
* The consume_input method pointer points either here or to the
|
||||
* coefficient controller's consume_data routine, depending on whether
|
||||
* we are reading a compressed data segment or inter-segment markers.
|
||||
*/
|
||||
|
||||
METHODDEF int
|
||||
consume_markers (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
|
||||
int val;
|
||||
|
||||
if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */
|
||||
return JPEG_REACHED_EOI;
|
||||
|
||||
val = (*cinfo->marker->read_markers) (cinfo);
|
||||
|
||||
switch (val) {
|
||||
case JPEG_REACHED_SOS: /* Found SOS */
|
||||
if (inputctl->inheaders) { /* 1st SOS */
|
||||
initial_setup(cinfo);
|
||||
inputctl->inheaders = FALSE;
|
||||
/* Note: start_input_pass must be called by jdmaster.c
|
||||
* before any more input can be consumed. jdapi.c is
|
||||
* responsible for enforcing this sequencing.
|
||||
*/
|
||||
} else { /* 2nd or later SOS marker */
|
||||
if (! inputctl->pub.has_multiple_scans)
|
||||
ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */
|
||||
start_input_pass(cinfo);
|
||||
}
|
||||
break;
|
||||
case JPEG_REACHED_EOI: /* Found EOI */
|
||||
inputctl->pub.eoi_reached = TRUE;
|
||||
if (inputctl->inheaders) { /* Tables-only datastream, apparently */
|
||||
if (cinfo->marker->saw_SOF)
|
||||
ERREXIT(cinfo, JERR_SOF_NO_SOS);
|
||||
} else {
|
||||
/* Prevent infinite loop in coef ctlr's decompress_data routine
|
||||
* if user set output_scan_number larger than number of scans.
|
||||
*/
|
||||
if (cinfo->output_scan_number > cinfo->input_scan_number)
|
||||
cinfo->output_scan_number = cinfo->input_scan_number;
|
||||
}
|
||||
break;
|
||||
case JPEG_SUSPENDED:
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reset state to begin a fresh datastream.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
reset_input_controller (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
|
||||
|
||||
inputctl->pub.consume_input = consume_markers;
|
||||
inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
|
||||
inputctl->pub.eoi_reached = FALSE;
|
||||
inputctl->inheaders = TRUE;
|
||||
/* Reset other modules */
|
||||
(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
|
||||
(*cinfo->marker->reset_marker_reader) (cinfo);
|
||||
/* Reset progression state -- would be cleaner if entropy decoder did this */
|
||||
cinfo->coef_bits = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the input controller module.
|
||||
* This is called only once, when the decompression object is created.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jinit_input_controller (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_inputctl_ptr inputctl;
|
||||
|
||||
/* Create subobject in permanent pool */
|
||||
inputctl = (my_inputctl_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
SIZEOF(my_input_controller));
|
||||
cinfo->inputctl = (struct jpeg_input_controller *) inputctl;
|
||||
/* Initialize method pointers */
|
||||
inputctl->pub.consume_input = consume_markers;
|
||||
inputctl->pub.reset_input_controller = reset_input_controller;
|
||||
inputctl->pub.start_input_pass = start_input_pass;
|
||||
inputctl->pub.finish_input_pass = finish_input_pass;
|
||||
/* Initialize state: can't use reset_input_controller since we don't
|
||||
* want to try to reset other modules yet.
|
||||
*/
|
||||
inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
|
||||
inputctl->pub.eoi_reached = FALSE;
|
||||
inputctl->inheaders = TRUE;
|
||||
}
|
||||
512
RenderDll/Common/Textures/Image/jpeg6/jdmainct.cpp
Normal file
512
RenderDll/Common/Textures/Image/jpeg6/jdmainct.cpp
Normal file
@@ -0,0 +1,512 @@
|
||||
/*
|
||||
* jdmainct.c
|
||||
*
|
||||
* Copyright (C) 1994-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the main buffer controller for decompression.
|
||||
* The main buffer lies between the JPEG decompressor proper and the
|
||||
* post-processor; it holds downsampled data in the JPEG colorspace.
|
||||
*
|
||||
* Note that this code is bypassed in raw-data mode, since the application
|
||||
* supplies the equivalent of the main buffer in that case.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
|
||||
/*
|
||||
* In the current system design, the main buffer need never be a full-image
|
||||
* buffer; any full-height buffers will be found inside the coefficient or
|
||||
* postprocessing controllers. Nonetheless, the main controller is not
|
||||
* trivial. Its responsibility is to provide context rows for upsampling/
|
||||
* rescaling, and doing this in an efficient fashion is a bit tricky.
|
||||
*
|
||||
* Postprocessor input data is counted in "row groups". A row group
|
||||
* is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
|
||||
* sample rows of each component. (We require DCT_scaled_size values to be
|
||||
* chosen such that these numbers are integers. In practice DCT_scaled_size
|
||||
* values will likely be powers of two, so we actually have the stronger
|
||||
* condition that DCT_scaled_size / min_DCT_scaled_size is an integer.)
|
||||
* Upsampling will typically produce max_v_samp_factor pixel rows from each
|
||||
* row group (times any additional scale factor that the upsampler is
|
||||
* applying).
|
||||
*
|
||||
* The coefficient controller will deliver data to us one iMCU row at a time;
|
||||
* each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or
|
||||
* exactly min_DCT_scaled_size row groups. (This amount of data corresponds
|
||||
* to one row of MCUs when the image is fully interleaved.) Note that the
|
||||
* number of sample rows varies across components, but the number of row
|
||||
* groups does not. Some garbage sample rows may be included in the last iMCU
|
||||
* row at the bottom of the image.
|
||||
*
|
||||
* Depending on the vertical scaling algorithm used, the upsampler may need
|
||||
* access to the sample row(s) above and below its current input row group.
|
||||
* The upsampler is required to set need_context_rows TRUE at global selection
|
||||
* time if so. When need_context_rows is FALSE, this controller can simply
|
||||
* obtain one iMCU row at a time from the coefficient controller and dole it
|
||||
* out as row groups to the postprocessor.
|
||||
*
|
||||
* When need_context_rows is TRUE, this controller guarantees that the buffer
|
||||
* passed to postprocessing contains at least one row group's worth of samples
|
||||
* above and below the row group(s) being processed. Note that the context
|
||||
* rows "above" the first passed row group appear at negative row offsets in
|
||||
* the passed buffer. At the top and bottom of the image, the required
|
||||
* context rows are manufactured by duplicating the first or last real sample
|
||||
* row; this avoids having special cases in the upsampling inner loops.
|
||||
*
|
||||
* The amount of context is fixed at one row group just because that's a
|
||||
* convenient number for this controller to work with. The existing
|
||||
* upsamplers really only need one sample row of context. An upsampler
|
||||
* supporting arbitrary output rescaling might wish for more than one row
|
||||
* group of context when shrinking the image; tough, we don't handle that.
|
||||
* (This is justified by the assumption that downsizing will be handled mostly
|
||||
* by adjusting the DCT_scaled_size values, so that the actual scale factor at
|
||||
* the upsample step needn't be much less than one.)
|
||||
*
|
||||
* To provide the desired context, we have to retain the last two row groups
|
||||
* of one iMCU row while reading in the next iMCU row. (The last row group
|
||||
* can't be processed until we have another row group for its below-context,
|
||||
* and so we have to save the next-to-last group too for its above-context.)
|
||||
* We could do this most simply by copying data around in our buffer, but
|
||||
* that'd be very slow. We can avoid copying any data by creating a rather
|
||||
* strange pointer structure. Here's how it works. We allocate a workspace
|
||||
* consisting of M+2 row groups (where M = min_DCT_scaled_size is the number
|
||||
* of row groups per iMCU row). We create two sets of redundant pointers to
|
||||
* the workspace. Labeling the physical row groups 0 to M+1, the synthesized
|
||||
* pointer lists look like this:
|
||||
* M+1 M-1
|
||||
* master pointer --> 0 master pointer --> 0
|
||||
* 1 1
|
||||
* ... ...
|
||||
* M-3 M-3
|
||||
* M-2 M
|
||||
* M-1 M+1
|
||||
* M M-2
|
||||
* M+1 M-1
|
||||
* 0 0
|
||||
* We read alternate iMCU rows using each master pointer; thus the last two
|
||||
* row groups of the previous iMCU row remain un-overwritten in the workspace.
|
||||
* The pointer lists are set up so that the required context rows appear to
|
||||
* be adjacent to the proper places when we pass the pointer lists to the
|
||||
* upsampler.
|
||||
*
|
||||
* The above pictures describe the normal state of the pointer lists.
|
||||
* At top and bottom of the image, we diddle the pointer lists to duplicate
|
||||
* the first or last sample row as necessary (this is cheaper than copying
|
||||
* sample rows around).
|
||||
*
|
||||
* This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that
|
||||
* situation each iMCU row provides only one row group so the buffering logic
|
||||
* must be different (eg, we must read two iMCU rows before we can emit the
|
||||
* first row group). For now, we simply do not support providing context
|
||||
* rows when min_DCT_scaled_size is 1. That combination seems unlikely to
|
||||
* be worth providing --- if someone wants a 1/8th-size preview, they probably
|
||||
* want it quick and dirty, so a context-free upsampler is sufficient.
|
||||
*/
|
||||
|
||||
|
||||
/* Private buffer controller object */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_d_main_controller pub; /* public fields */
|
||||
|
||||
/* Pointer to allocated workspace (M or M+2 row groups). */
|
||||
JSAMPARRAY buffer[MAX_COMPONENTS];
|
||||
|
||||
boolean buffer_full; /* Have we gotten an iMCU row from decoder? */
|
||||
JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */
|
||||
|
||||
/* Remaining fields are only used in the context case. */
|
||||
|
||||
/* These are the master pointers to the funny-order pointer lists. */
|
||||
JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */
|
||||
|
||||
int whichptr; /* indicates which pointer set is now in use */
|
||||
int context_state; /* process_data state machine status */
|
||||
JDIMENSION rowgroups_avail; /* row groups available to postprocessor */
|
||||
JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */
|
||||
} my_main_controller;
|
||||
|
||||
typedef my_main_controller * my_main_ptr;
|
||||
|
||||
/* context_state values: */
|
||||
#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */
|
||||
#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */
|
||||
#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
METHODDEF void process_data_simple_main
|
||||
JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
|
||||
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
|
||||
METHODDEF void process_data_context_main
|
||||
JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
|
||||
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
|
||||
#ifdef QUANT_2PASS_SUPPORTED
|
||||
METHODDEF void process_data_crank_post
|
||||
JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
|
||||
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
|
||||
#endif
|
||||
|
||||
|
||||
LOCAL void
|
||||
alloc_funny_pointers (j_decompress_ptr cinfo)
|
||||
/* Allocate space for the funny pointer lists.
|
||||
* This is done only once, not once per pass.
|
||||
*/
|
||||
{
|
||||
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||
int ci, rgroup;
|
||||
int M = cinfo->min_DCT_scaled_size;
|
||||
jpeg_component_info *compptr;
|
||||
JSAMPARRAY xbuf;
|
||||
|
||||
/* Get top-level space for component array pointers.
|
||||
* We alloc both arrays with one call to save a few cycles.
|
||||
*/
|
||||
main->xbuffer[0] = (JSAMPIMAGE)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
cinfo->num_components * 2 * SIZEOF(JSAMPARRAY));
|
||||
main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components;
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||
/* Get space for pointer lists --- M+4 row groups in each list.
|
||||
* We alloc both pointer lists with one call to save a few cycles.
|
||||
*/
|
||||
xbuf = (JSAMPARRAY)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW));
|
||||
xbuf += rgroup; /* want one row group at negative offsets */
|
||||
main->xbuffer[0][ci] = xbuf;
|
||||
xbuf += rgroup * (M + 4);
|
||||
main->xbuffer[1][ci] = xbuf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
make_funny_pointers (j_decompress_ptr cinfo)
|
||||
/* Create the funny pointer lists discussed in the comments above.
|
||||
* The actual workspace is already allocated (in main->buffer),
|
||||
* and the space for the pointer lists is allocated too.
|
||||
* This routine just fills in the curiously ordered lists.
|
||||
* This will be repeated at the beginning of each pass.
|
||||
*/
|
||||
{
|
||||
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||
int ci, i, rgroup;
|
||||
int M = cinfo->min_DCT_scaled_size;
|
||||
jpeg_component_info *compptr;
|
||||
JSAMPARRAY buf, xbuf0, xbuf1;
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||
xbuf0 = main->xbuffer[0][ci];
|
||||
xbuf1 = main->xbuffer[1][ci];
|
||||
/* First copy the workspace pointers as-is */
|
||||
buf = main->buffer[ci];
|
||||
for (i = 0; i < rgroup * (M + 2); i++) {
|
||||
xbuf0[i] = xbuf1[i] = buf[i];
|
||||
}
|
||||
/* In the second list, put the last four row groups in swapped order */
|
||||
for (i = 0; i < rgroup * 2; i++) {
|
||||
xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i];
|
||||
xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i];
|
||||
}
|
||||
/* The wraparound pointers at top and bottom will be filled later
|
||||
* (see set_wraparound_pointers, below). Initially we want the "above"
|
||||
* pointers to duplicate the first actual data line. This only needs
|
||||
* to happen in xbuffer[0].
|
||||
*/
|
||||
for (i = 0; i < rgroup; i++) {
|
||||
xbuf0[i - rgroup] = xbuf0[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
set_wraparound_pointers (j_decompress_ptr cinfo)
|
||||
/* Set up the "wraparound" pointers at top and bottom of the pointer lists.
|
||||
* This changes the pointer list state from top-of-image to the normal state.
|
||||
*/
|
||||
{
|
||||
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||
int ci, i, rgroup;
|
||||
int M = cinfo->min_DCT_scaled_size;
|
||||
jpeg_component_info *compptr;
|
||||
JSAMPARRAY xbuf0, xbuf1;
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||
xbuf0 = main->xbuffer[0][ci];
|
||||
xbuf1 = main->xbuffer[1][ci];
|
||||
for (i = 0; i < rgroup; i++) {
|
||||
xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i];
|
||||
xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i];
|
||||
xbuf0[rgroup*(M+2) + i] = xbuf0[i];
|
||||
xbuf1[rgroup*(M+2) + i] = xbuf1[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL void
|
||||
set_bottom_pointers (j_decompress_ptr cinfo)
|
||||
/* Change the pointer lists to duplicate the last sample row at the bottom
|
||||
* of the image. whichptr indicates which xbuffer holds the final iMCU row.
|
||||
* Also sets rowgroups_avail to indicate number of nondummy row groups in row.
|
||||
*/
|
||||
{
|
||||
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||
int ci, i, rgroup, iMCUheight, rows_left;
|
||||
jpeg_component_info *compptr;
|
||||
JSAMPARRAY xbuf;
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* Count sample rows in one iMCU row and in one row group */
|
||||
iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size;
|
||||
rgroup = iMCUheight / cinfo->min_DCT_scaled_size;
|
||||
/* Count nondummy sample rows remaining for this component */
|
||||
rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight);
|
||||
if (rows_left == 0) rows_left = iMCUheight;
|
||||
/* Count nondummy row groups. Should get same answer for each component,
|
||||
* so we need only do it once.
|
||||
*/
|
||||
if (ci == 0) {
|
||||
main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1);
|
||||
}
|
||||
/* Duplicate the last real sample row rgroup*2 times; this pads out the
|
||||
* last partial rowgroup and ensures at least one full rowgroup of context.
|
||||
*/
|
||||
xbuf = main->xbuffer[main->whichptr][ci];
|
||||
for (i = 0; i < rgroup * 2; i++) {
|
||||
xbuf[rows_left + i] = xbuf[rows_left-1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for a processing pass.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||
{
|
||||
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||
|
||||
switch (pass_mode) {
|
||||
case JBUF_PASS_THRU:
|
||||
if (cinfo->upsample->need_context_rows) {
|
||||
main->pub.process_data = process_data_context_main;
|
||||
make_funny_pointers(cinfo); /* Create the xbuffer[] lists */
|
||||
main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */
|
||||
main->context_state = CTX_PREPARE_FOR_IMCU;
|
||||
main->iMCU_row_ctr = 0;
|
||||
} else {
|
||||
/* Simple case with no context needed */
|
||||
main->pub.process_data = process_data_simple_main;
|
||||
}
|
||||
main->buffer_full = FALSE; /* Mark buffer empty */
|
||||
main->rowgroup_ctr = 0;
|
||||
break;
|
||||
#ifdef QUANT_2PASS_SUPPORTED
|
||||
case JBUF_CRANK_DEST:
|
||||
/* For last pass of 2-pass quantization, just crank the postprocessor */
|
||||
main->pub.process_data = process_data_crank_post;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process some data.
|
||||
* This handles the simple case where no context is required.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
process_data_simple_main (j_decompress_ptr cinfo,
|
||||
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail)
|
||||
{
|
||||
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||
JDIMENSION rowgroups_avail;
|
||||
|
||||
/* Read input data if we haven't filled the main buffer yet */
|
||||
if (! main->buffer_full) {
|
||||
if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer))
|
||||
return; /* suspension forced, can do nothing more */
|
||||
main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
|
||||
}
|
||||
|
||||
/* There are always min_DCT_scaled_size row groups in an iMCU row. */
|
||||
rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size;
|
||||
/* Note: at the bottom of the image, we may pass extra garbage row groups
|
||||
* to the postprocessor. The postprocessor has to check for bottom
|
||||
* of image anyway (at row resolution), so no point in us doing it too.
|
||||
*/
|
||||
|
||||
/* Feed the postprocessor */
|
||||
(*cinfo->post->post_process_data) (cinfo, main->buffer,
|
||||
&main->rowgroup_ctr, rowgroups_avail,
|
||||
output_buf, out_row_ctr, out_rows_avail);
|
||||
|
||||
/* Has postprocessor consumed all the data yet? If so, mark buffer empty */
|
||||
if (main->rowgroup_ctr >= rowgroups_avail) {
|
||||
main->buffer_full = FALSE;
|
||||
main->rowgroup_ctr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process some data.
|
||||
* This handles the case where context rows must be provided.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
process_data_context_main (j_decompress_ptr cinfo,
|
||||
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail)
|
||||
{
|
||||
my_main_ptr main = (my_main_ptr) cinfo->main;
|
||||
|
||||
/* Read input data if we haven't filled the main buffer yet */
|
||||
if (! main->buffer_full) {
|
||||
if (! (*cinfo->coef->decompress_data) (cinfo,
|
||||
main->xbuffer[main->whichptr]))
|
||||
return; /* suspension forced, can do nothing more */
|
||||
main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
|
||||
main->iMCU_row_ctr++; /* count rows received */
|
||||
}
|
||||
|
||||
/* Postprocessor typically will not swallow all the input data it is handed
|
||||
* in one call (due to filling the output buffer first). Must be prepared
|
||||
* to exit and restart. This switch lets us keep track of how far we got.
|
||||
* Note that each case falls through to the next on successful completion.
|
||||
*/
|
||||
switch (main->context_state) {
|
||||
case CTX_POSTPONED_ROW:
|
||||
/* Call postprocessor using previously set pointers for postponed row */
|
||||
(*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
|
||||
&main->rowgroup_ctr, main->rowgroups_avail,
|
||||
output_buf, out_row_ctr, out_rows_avail);
|
||||
if (main->rowgroup_ctr < main->rowgroups_avail)
|
||||
return; /* Need to suspend */
|
||||
main->context_state = CTX_PREPARE_FOR_IMCU;
|
||||
if (*out_row_ctr >= out_rows_avail)
|
||||
return; /* Postprocessor exactly filled output buf */
|
||||
/*FALLTHROUGH*/
|
||||
case CTX_PREPARE_FOR_IMCU:
|
||||
/* Prepare to process first M-1 row groups of this iMCU row */
|
||||
main->rowgroup_ctr = 0;
|
||||
main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1);
|
||||
/* Check for bottom of image: if so, tweak pointers to "duplicate"
|
||||
* the last sample row, and adjust rowgroups_avail to ignore padding rows.
|
||||
*/
|
||||
if (main->iMCU_row_ctr == cinfo->total_iMCU_rows)
|
||||
set_bottom_pointers(cinfo);
|
||||
main->context_state = CTX_PROCESS_IMCU;
|
||||
/*FALLTHROUGH*/
|
||||
case CTX_PROCESS_IMCU:
|
||||
/* Call postprocessor using previously set pointers */
|
||||
(*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
|
||||
&main->rowgroup_ctr, main->rowgroups_avail,
|
||||
output_buf, out_row_ctr, out_rows_avail);
|
||||
if (main->rowgroup_ctr < main->rowgroups_avail)
|
||||
return; /* Need to suspend */
|
||||
/* After the first iMCU, change wraparound pointers to normal state */
|
||||
if (main->iMCU_row_ctr == 1)
|
||||
set_wraparound_pointers(cinfo);
|
||||
/* Prepare to load new iMCU row using other xbuffer list */
|
||||
main->whichptr ^= 1; /* 0=>1 or 1=>0 */
|
||||
main->buffer_full = FALSE;
|
||||
/* Still need to process last row group of this iMCU row, */
|
||||
/* which is saved at index M+1 of the other xbuffer */
|
||||
main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1);
|
||||
main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2);
|
||||
main->context_state = CTX_POSTPONED_ROW;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process some data.
|
||||
* Final pass of two-pass quantization: just call the postprocessor.
|
||||
* Source data will be the postprocessor controller's internal buffer.
|
||||
*/
|
||||
|
||||
#ifdef QUANT_2PASS_SUPPORTED
|
||||
|
||||
METHODDEF void
|
||||
process_data_crank_post (j_decompress_ptr cinfo,
|
||||
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail)
|
||||
{
|
||||
(*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL,
|
||||
(JDIMENSION *) NULL, (JDIMENSION) 0,
|
||||
output_buf, out_row_ctr, out_rows_avail);
|
||||
}
|
||||
|
||||
#endif /* QUANT_2PASS_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize main buffer controller.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
|
||||
{
|
||||
my_main_ptr main;
|
||||
int ci, rgroup, ngroups;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
main = (my_main_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(my_main_controller));
|
||||
cinfo->main = (struct jpeg_d_main_controller *) main;
|
||||
main->pub.start_pass = start_pass_main;
|
||||
|
||||
if (need_full_buffer) /* shouldn't happen */
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
|
||||
/* Allocate the workspace.
|
||||
* ngroups is the number of row groups we need.
|
||||
*/
|
||||
if (cinfo->upsample->need_context_rows) {
|
||||
if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */
|
||||
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||
alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */
|
||||
ngroups = cinfo->min_DCT_scaled_size + 2;
|
||||
} else {
|
||||
ngroups = cinfo->min_DCT_scaled_size;
|
||||
}
|
||||
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||
cinfo->min_DCT_scaled_size; /* height of a row group of component */
|
||||
main->buffer[ci] = (*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
compptr->width_in_blocks * compptr->DCT_scaled_size,
|
||||
(JDIMENSION) (rgroup * ngroups));
|
||||
}
|
||||
}
|
||||
1052
RenderDll/Common/Textures/Image/jpeg6/jdmarker.cpp
Normal file
1052
RenderDll/Common/Textures/Image/jpeg6/jdmarker.cpp
Normal file
File diff suppressed because it is too large
Load Diff
557
RenderDll/Common/Textures/Image/jpeg6/jdmaster.cpp
Normal file
557
RenderDll/Common/Textures/Image/jpeg6/jdmaster.cpp
Normal file
@@ -0,0 +1,557 @@
|
||||
/*
|
||||
* jdmaster.c
|
||||
*
|
||||
* Copyright (C) 1991-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains master control logic for the JPEG decompressor.
|
||||
* These routines are concerned with selecting the modules to be executed
|
||||
* and with determining the number of passes and the work to be done in each
|
||||
* pass.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
|
||||
/* Private state */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_decomp_master pub; /* public fields */
|
||||
|
||||
int pass_number; /* # of passes completed */
|
||||
|
||||
boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */
|
||||
|
||||
/* Saved references to initialized quantizer modules,
|
||||
* in case we need to switch modes.
|
||||
*/
|
||||
struct jpeg_color_quantizer * quantizer_1pass;
|
||||
struct jpeg_color_quantizer * quantizer_2pass;
|
||||
} my_decomp_master;
|
||||
|
||||
typedef my_decomp_master * my_master_ptr;
|
||||
|
||||
|
||||
/*
|
||||
* Determine whether merged upsample/color conversion should be used.
|
||||
* CRUCIAL: this must match the actual capabilities of jdmerge.c!
|
||||
*/
|
||||
|
||||
LOCAL boolean
|
||||
use_merged_upsample (j_decompress_ptr cinfo)
|
||||
{
|
||||
#ifdef UPSAMPLE_MERGING_SUPPORTED
|
||||
/* Merging is the equivalent of plain box-filter upsampling */
|
||||
if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling)
|
||||
return FALSE;
|
||||
/* jdmerge.c only supports YCC=>RGB color conversion */
|
||||
if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 ||
|
||||
cinfo->out_color_space != JCS_RGB ||
|
||||
cinfo->out_color_components != RGB_PIXELSIZE)
|
||||
return FALSE;
|
||||
/* and it only handles 2h1v or 2h2v sampling ratios */
|
||||
if (cinfo->comp_info[0].h_samp_factor != 2 ||
|
||||
cinfo->comp_info[1].h_samp_factor != 1 ||
|
||||
cinfo->comp_info[2].h_samp_factor != 1 ||
|
||||
cinfo->comp_info[0].v_samp_factor > 2 ||
|
||||
cinfo->comp_info[1].v_samp_factor != 1 ||
|
||||
cinfo->comp_info[2].v_samp_factor != 1)
|
||||
return FALSE;
|
||||
/* furthermore, it doesn't work if we've scaled the IDCTs differently */
|
||||
if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
|
||||
cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
|
||||
cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size)
|
||||
return FALSE;
|
||||
/* ??? also need to test for upsample-time rescaling, when & if supported */
|
||||
return TRUE; /* by golly, it'll work... */
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compute output image dimensions and related values.
|
||||
* NOTE: this is exported for possible use by application.
|
||||
* Hence it mustn't do anything that can't be done twice.
|
||||
* Also note that it may be called before the master module is initialized!
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_calc_output_dimensions (j_decompress_ptr cinfo)
|
||||
/* Do computations that are needed before master selection phase */
|
||||
{
|
||||
#if 0 // JDC: commented out to remove warning
|
||||
int ci;
|
||||
jpeg_component_info *compptr;
|
||||
#endif
|
||||
|
||||
/* Prevent application from calling me at wrong times */
|
||||
if (cinfo->global_state != DSTATE_READY)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
|
||||
#ifdef IDCT_SCALING_SUPPORTED
|
||||
|
||||
/* Compute actual output image dimensions and DCT scaling choices. */
|
||||
if (cinfo->scale_num * 8 <= cinfo->scale_denom) {
|
||||
/* Provide 1/8 scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width, 8L);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height, 8L);
|
||||
cinfo->min_DCT_scaled_size = 1;
|
||||
} else if (cinfo->scale_num * 4 <= cinfo->scale_denom) {
|
||||
/* Provide 1/4 scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width, 4L);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height, 4L);
|
||||
cinfo->min_DCT_scaled_size = 2;
|
||||
} else if (cinfo->scale_num * 2 <= cinfo->scale_denom) {
|
||||
/* Provide 1/2 scaling */
|
||||
cinfo->output_width = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width, 2L);
|
||||
cinfo->output_height = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height, 2L);
|
||||
cinfo->min_DCT_scaled_size = 4;
|
||||
} else {
|
||||
/* Provide 1/1 scaling */
|
||||
cinfo->output_width = cinfo->image_width;
|
||||
cinfo->output_height = cinfo->image_height;
|
||||
cinfo->min_DCT_scaled_size = DCTSIZE;
|
||||
}
|
||||
/* In selecting the actual DCT scaling for each component, we try to
|
||||
* scale up the chroma components via IDCT scaling rather than upsampling.
|
||||
* This saves time if the upsampler gets to use 1:1 scaling.
|
||||
* Note this code assumes that the supported DCT scalings are powers of 2.
|
||||
*/
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
int ssize = cinfo->min_DCT_scaled_size;
|
||||
while (ssize < DCTSIZE &&
|
||||
(compptr->h_samp_factor * ssize * 2 <=
|
||||
cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) &&
|
||||
(compptr->v_samp_factor * ssize * 2 <=
|
||||
cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) {
|
||||
ssize = ssize * 2;
|
||||
}
|
||||
compptr->DCT_scaled_size = ssize;
|
||||
}
|
||||
|
||||
/* Recompute downsampled dimensions of components;
|
||||
* application needs to know these if using raw downsampled data.
|
||||
*/
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* Size in samples, after IDCT scaling */
|
||||
compptr->downsampled_width = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_width *
|
||||
(long) (compptr->h_samp_factor * compptr->DCT_scaled_size),
|
||||
(long) (cinfo->max_h_samp_factor * DCTSIZE));
|
||||
compptr->downsampled_height = (JDIMENSION)
|
||||
jdiv_round_up((long) cinfo->image_height *
|
||||
(long) (compptr->v_samp_factor * compptr->DCT_scaled_size),
|
||||
(long) (cinfo->max_v_samp_factor * DCTSIZE));
|
||||
}
|
||||
|
||||
#else /* !IDCT_SCALING_SUPPORTED */
|
||||
|
||||
/* Hardwire it to "no scaling" */
|
||||
cinfo->output_width = cinfo->image_width;
|
||||
cinfo->output_height = cinfo->image_height;
|
||||
/* jdinput.c has already initialized DCT_scaled_size to DCTSIZE,
|
||||
* and has computed unscaled downsampled_width and downsampled_height.
|
||||
*/
|
||||
|
||||
#endif /* IDCT_SCALING_SUPPORTED */
|
||||
|
||||
/* Report number of components in selected colorspace. */
|
||||
/* Probably this should be in the color conversion module... */
|
||||
switch (cinfo->out_color_space) {
|
||||
case JCS_GRAYSCALE:
|
||||
cinfo->out_color_components = 1;
|
||||
break;
|
||||
case JCS_RGB:
|
||||
#if RGB_PIXELSIZE != 3
|
||||
cinfo->out_color_components = RGB_PIXELSIZE;
|
||||
break;
|
||||
#endif /* else share code with YCbCr */
|
||||
case JCS_YCbCr:
|
||||
cinfo->out_color_components = 3;
|
||||
break;
|
||||
case JCS_CMYK:
|
||||
case JCS_YCCK:
|
||||
cinfo->out_color_components = 4;
|
||||
break;
|
||||
default: /* else must be same colorspace as in file */
|
||||
cinfo->out_color_components = cinfo->num_components;
|
||||
break;
|
||||
}
|
||||
cinfo->output_components = (cinfo->quantize_colors ? 1 :
|
||||
cinfo->out_color_components);
|
||||
|
||||
/* See if upsampler will want to emit more than one row at a time */
|
||||
if (use_merged_upsample(cinfo))
|
||||
cinfo->rec_outbuf_height = cinfo->max_v_samp_factor;
|
||||
else
|
||||
cinfo->rec_outbuf_height = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Several decompression processes need to range-limit values to the range
|
||||
* 0..MAXJSAMPLE; the input value may fall somewhat outside this range
|
||||
* due to noise introduced by quantization, roundoff error, etc. These
|
||||
* processes are inner loops and need to be as fast as possible. On most
|
||||
* machines, particularly CPUs with pipelines or instruction prefetch,
|
||||
* a (subscript-check-less) C table lookup
|
||||
* x = sample_range_limit[x];
|
||||
* is faster than explicit tests
|
||||
* if (x < 0) x = 0;
|
||||
* else if (x > MAXJSAMPLE) x = MAXJSAMPLE;
|
||||
* These processes all use a common table prepared by the routine below.
|
||||
*
|
||||
* For most steps we can mathematically guarantee that the initial value
|
||||
* of x is within MAXJSAMPLE+1 of the legal range, so a table running from
|
||||
* -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial
|
||||
* limiting step (just after the IDCT), a wildly out-of-range value is
|
||||
* possible if the input data is corrupt. To avoid any chance of indexing
|
||||
* off the end of memory and getting a bad-pointer trap, we perform the
|
||||
* post-IDCT limiting thus:
|
||||
* x = range_limit[x & MASK];
|
||||
* where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit
|
||||
* samples. Under normal circumstances this is more than enough range and
|
||||
* a correct output will be generated; with bogus input data the mask will
|
||||
* cause wraparound, and we will safely generate a bogus-but-in-range output.
|
||||
* For the post-IDCT step, we want to convert the data from signed to unsigned
|
||||
* representation by adding CENTERJSAMPLE at the same time that we limit it.
|
||||
* So the post-IDCT limiting table ends up looking like this:
|
||||
* CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE,
|
||||
* MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
|
||||
* 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
|
||||
* 0,1,...,CENTERJSAMPLE-1
|
||||
* Negative inputs select values from the upper half of the table after
|
||||
* masking.
|
||||
*
|
||||
* We can save some space by overlapping the start of the post-IDCT table
|
||||
* with the simpler range limiting table. The post-IDCT table begins at
|
||||
* sample_range_limit + CENTERJSAMPLE.
|
||||
*
|
||||
* Note that the table is allocated in near data space on PCs; it's small
|
||||
* enough and used often enough to justify this.
|
||||
*/
|
||||
|
||||
LOCAL void
|
||||
prepare_range_limit_table (j_decompress_ptr cinfo)
|
||||
/* Allocate and fill in the sample_range_limit table */
|
||||
{
|
||||
JSAMPLE * table;
|
||||
int i;
|
||||
|
||||
table = (JSAMPLE *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
(5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE));
|
||||
table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */
|
||||
cinfo->sample_range_limit = table;
|
||||
/* First segment of "simple" table: limit[x] = 0 for x < 0 */
|
||||
MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE));
|
||||
/* Main part of "simple" table: limit[x] = x */
|
||||
for (i = 0; i <= MAXJSAMPLE; i++)
|
||||
table[i] = (JSAMPLE) i;
|
||||
table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */
|
||||
/* End of simple table, rest of first half of post-IDCT table */
|
||||
for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++)
|
||||
table[i] = MAXJSAMPLE;
|
||||
/* Second half of post-IDCT table */
|
||||
MEMZERO(table + (2 * (MAXJSAMPLE+1)),
|
||||
(2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE));
|
||||
MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE),
|
||||
cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Master selection of decompression modules.
|
||||
* This is done once at jpeg_start_decompress time. We determine
|
||||
* which modules will be used and give them appropriate initialization calls.
|
||||
* We also initialize the decompressor input side to begin consuming data.
|
||||
*
|
||||
* Since jpeg_read_header has finished, we know what is in the SOF
|
||||
* and (first) SOS markers. We also have all the application parameter
|
||||
* settings.
|
||||
*/
|
||||
|
||||
LOCAL void
|
||||
master_selection (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||
boolean use_c_buffer;
|
||||
long samplesperrow;
|
||||
JDIMENSION jd_samplesperrow;
|
||||
|
||||
/* Initialize dimensions and other stuff */
|
||||
my_jpeg_calc_output_dimensions(cinfo);
|
||||
prepare_range_limit_table(cinfo);
|
||||
|
||||
/* Width of an output scanline must be representable as JDIMENSION. */
|
||||
samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components;
|
||||
jd_samplesperrow = (JDIMENSION) samplesperrow;
|
||||
if ((long) jd_samplesperrow != samplesperrow)
|
||||
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
|
||||
|
||||
/* Initialize my private state */
|
||||
master->pass_number = 0;
|
||||
master->using_merged_upsample = use_merged_upsample(cinfo);
|
||||
|
||||
/* Color quantizer selection */
|
||||
master->quantizer_1pass = NULL;
|
||||
master->quantizer_2pass = NULL;
|
||||
/* No mode changes if not using buffered-image mode. */
|
||||
if (! cinfo->quantize_colors || ! cinfo->buffered_image) {
|
||||
cinfo->enable_1pass_quant = FALSE;
|
||||
cinfo->enable_external_quant = FALSE;
|
||||
cinfo->enable_2pass_quant = FALSE;
|
||||
}
|
||||
if (cinfo->quantize_colors) {
|
||||
if (cinfo->raw_data_out)
|
||||
ERREXIT(cinfo, JERR_NOTIMPL);
|
||||
/* 2-pass quantizer only works in 3-component color space. */
|
||||
if (cinfo->out_color_components != 3) {
|
||||
cinfo->enable_1pass_quant = TRUE;
|
||||
cinfo->enable_external_quant = FALSE;
|
||||
cinfo->enable_2pass_quant = FALSE;
|
||||
cinfo->colormap = NULL;
|
||||
} else if (cinfo->colormap != NULL) {
|
||||
cinfo->enable_external_quant = TRUE;
|
||||
} else if (cinfo->two_pass_quantize) {
|
||||
cinfo->enable_2pass_quant = TRUE;
|
||||
} else {
|
||||
cinfo->enable_1pass_quant = TRUE;
|
||||
}
|
||||
|
||||
if (cinfo->enable_1pass_quant) {
|
||||
#ifdef QUANT_1PASS_SUPPORTED
|
||||
jinit_1pass_quantizer(cinfo);
|
||||
master->quantizer_1pass = cinfo->cquantize;
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* We use the 2-pass code to map to external colormaps. */
|
||||
if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) {
|
||||
#ifdef QUANT_2PASS_SUPPORTED
|
||||
jinit_2pass_quantizer(cinfo);
|
||||
master->quantizer_2pass = cinfo->cquantize;
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
}
|
||||
/* If both quantizers are initialized, the 2-pass one is left active;
|
||||
* this is necessary for starting with quantization to an external map.
|
||||
*/
|
||||
}
|
||||
|
||||
/* Post-processing: in particular, color conversion first */
|
||||
if (! cinfo->raw_data_out) {
|
||||
if (master->using_merged_upsample) {
|
||||
#ifdef UPSAMPLE_MERGING_SUPPORTED
|
||||
jinit_merged_upsampler(cinfo); /* does color conversion too */
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else {
|
||||
jinit_color_deconverter(cinfo);
|
||||
jinit_upsampler(cinfo);
|
||||
}
|
||||
jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant);
|
||||
}
|
||||
/* Inverse DCT */
|
||||
jinit_inverse_dct(cinfo);
|
||||
/* Entropy decoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
} else {
|
||||
if (cinfo->progressive_mode) {
|
||||
#ifdef D_PROGRESSIVE_SUPPORTED
|
||||
jinit_phuff_decoder(cinfo);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else
|
||||
jinit_huff_decoder(cinfo);
|
||||
}
|
||||
|
||||
/* Initialize principal buffer controllers. */
|
||||
use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
|
||||
jinit_d_coef_controller(cinfo, use_c_buffer);
|
||||
|
||||
if (! cinfo->raw_data_out)
|
||||
jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */);
|
||||
|
||||
/* We can now tell the memory manager to allocate virtual arrays. */
|
||||
(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
|
||||
|
||||
/* Initialize input side of decompressor to consume first scan. */
|
||||
(*cinfo->inputctl->start_input_pass) (cinfo);
|
||||
|
||||
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||
/* If jpeg_start_decompress will read the whole file, initialize
|
||||
* progress monitoring appropriately. The input step is counted
|
||||
* as one pass.
|
||||
*/
|
||||
if (cinfo->progress != NULL && ! cinfo->buffered_image &&
|
||||
cinfo->inputctl->has_multiple_scans) {
|
||||
int nscans;
|
||||
/* Estimate number of scans to set pass_limit. */
|
||||
if (cinfo->progressive_mode) {
|
||||
/* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
|
||||
nscans = 2 + 3 * cinfo->num_components;
|
||||
} else {
|
||||
/* For a nonprogressive multiscan file, estimate 1 scan per component. */
|
||||
nscans = cinfo->num_components;
|
||||
}
|
||||
cinfo->progress->pass_counter = 0L;
|
||||
cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
|
||||
cinfo->progress->completed_passes = 0;
|
||||
cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2);
|
||||
/* Count the input pass as done */
|
||||
master->pass_number++;
|
||||
}
|
||||
#endif /* D_MULTISCAN_FILES_SUPPORTED */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Per-pass setup.
|
||||
* This is called at the beginning of each output pass. We determine which
|
||||
* modules will be active during this pass and give them appropriate
|
||||
* start_pass calls. We also set is_dummy_pass to indicate whether this
|
||||
* is a "real" output pass or a dummy pass for color quantization.
|
||||
* (In the latter case, jdapi.c will crank the pass to completion.)
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
prepare_for_output_pass (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||
|
||||
if (master->pub.is_dummy_pass) {
|
||||
#ifdef QUANT_2PASS_SUPPORTED
|
||||
/* Final pass of 2-pass quantization */
|
||||
master->pub.is_dummy_pass = FALSE;
|
||||
(*cinfo->cquantize->start_pass) (cinfo, FALSE);
|
||||
(*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST);
|
||||
(*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif /* QUANT_2PASS_SUPPORTED */
|
||||
} else {
|
||||
if (cinfo->quantize_colors && cinfo->colormap == NULL) {
|
||||
/* Select new quantization method */
|
||||
if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) {
|
||||
cinfo->cquantize = master->quantizer_2pass;
|
||||
master->pub.is_dummy_pass = TRUE;
|
||||
} else if (cinfo->enable_1pass_quant) {
|
||||
cinfo->cquantize = master->quantizer_1pass;
|
||||
} else {
|
||||
ERREXIT(cinfo, JERR_MODE_CHANGE);
|
||||
}
|
||||
}
|
||||
(*cinfo->idct->start_pass) (cinfo);
|
||||
(*cinfo->coef->start_output_pass) (cinfo);
|
||||
if (! cinfo->raw_data_out) {
|
||||
if (! master->using_merged_upsample)
|
||||
(*cinfo->cconvert->start_pass) (cinfo);
|
||||
(*cinfo->upsample->start_pass) (cinfo);
|
||||
if (cinfo->quantize_colors)
|
||||
(*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass);
|
||||
(*cinfo->post->start_pass) (cinfo,
|
||||
(master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
|
||||
(*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up progress monitor's pass info if present */
|
||||
if (cinfo->progress != NULL) {
|
||||
cinfo->progress->completed_passes = master->pass_number;
|
||||
cinfo->progress->total_passes = master->pass_number +
|
||||
(master->pub.is_dummy_pass ? 2 : 1);
|
||||
/* In buffered-image mode, we assume one more output pass if EOI not
|
||||
* yet reached, but no more passes if EOI has been reached.
|
||||
*/
|
||||
if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) {
|
||||
cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finish up at end of an output pass.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
finish_output_pass (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||
|
||||
if (cinfo->quantize_colors)
|
||||
(*cinfo->cquantize->finish_pass) (cinfo);
|
||||
master->pass_number++;
|
||||
}
|
||||
|
||||
|
||||
#ifdef D_MULTISCAN_FILES_SUPPORTED
|
||||
|
||||
/*
|
||||
* Switch to a new external colormap between output passes.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_new_colormap (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_master_ptr master = (my_master_ptr) cinfo->master;
|
||||
|
||||
/* Prevent application from calling me at wrong times */
|
||||
if (cinfo->global_state != DSTATE_BUFIMAGE)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
|
||||
if (cinfo->quantize_colors && cinfo->enable_external_quant &&
|
||||
cinfo->colormap != NULL) {
|
||||
/* Select 2-pass quantizer for external colormap use */
|
||||
cinfo->cquantize = master->quantizer_2pass;
|
||||
/* Notify quantizer of colormap change */
|
||||
(*cinfo->cquantize->new_color_map) (cinfo);
|
||||
master->pub.is_dummy_pass = FALSE; /* just in case */
|
||||
} else
|
||||
ERREXIT(cinfo, JERR_MODE_CHANGE);
|
||||
}
|
||||
|
||||
#endif /* D_MULTISCAN_FILES_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize master decompression control and select active modules.
|
||||
* This is performed at the start of jpeg_start_decompress.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jinit_master_decompress (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_master_ptr master;
|
||||
|
||||
master = (my_master_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(my_decomp_master));
|
||||
cinfo->master = (struct jpeg_decomp_master *) master;
|
||||
master->pub.prepare_for_output_pass = prepare_for_output_pass;
|
||||
master->pub.finish_output_pass = finish_output_pass;
|
||||
|
||||
master->pub.is_dummy_pass = FALSE;
|
||||
|
||||
master_selection(cinfo);
|
||||
}
|
||||
290
RenderDll/Common/Textures/Image/jpeg6/jdpostct.cpp
Normal file
290
RenderDll/Common/Textures/Image/jpeg6/jdpostct.cpp
Normal file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* jdpostct.c
|
||||
*
|
||||
* Copyright (C) 1994-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains the decompression postprocessing controller.
|
||||
* This controller manages the upsampling, color conversion, and color
|
||||
* quantization/reduction steps; specifically, it controls the buffering
|
||||
* between upsample/color conversion and color quantization/reduction.
|
||||
*
|
||||
* If no color quantization/reduction is required, then this module has no
|
||||
* work to do, and it just hands off to the upsample/color conversion code.
|
||||
* An integrated upsample/convert/quantize process would replace this module
|
||||
* entirely.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
|
||||
/* Private buffer controller object */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_d_post_controller pub; /* public fields */
|
||||
|
||||
/* Color quantization source buffer: this holds output data from
|
||||
* the upsample/color conversion step to be passed to the quantizer.
|
||||
* For two-pass color quantization, we need a full-image buffer;
|
||||
* for one-pass operation, a strip buffer is sufficient.
|
||||
*/
|
||||
jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */
|
||||
JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */
|
||||
JDIMENSION strip_height; /* buffer size in rows */
|
||||
/* for two-pass mode only: */
|
||||
JDIMENSION starting_row; /* row # of first row in current strip */
|
||||
JDIMENSION next_row; /* index of next row to fill/empty in strip */
|
||||
} my_post_controller;
|
||||
|
||||
typedef my_post_controller * my_post_ptr;
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
METHODDEF void post_process_1pass
|
||||
JPP((j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
|
||||
JDIMENSION in_row_groups_avail,
|
||||
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail));
|
||||
#ifdef QUANT_2PASS_SUPPORTED
|
||||
METHODDEF void post_process_prepass
|
||||
JPP((j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
|
||||
JDIMENSION in_row_groups_avail,
|
||||
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail));
|
||||
METHODDEF void post_process_2pass
|
||||
JPP((j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
|
||||
JDIMENSION in_row_groups_avail,
|
||||
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail));
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for a processing pass.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
|
||||
{
|
||||
my_post_ptr post = (my_post_ptr) cinfo->post;
|
||||
|
||||
switch (pass_mode) {
|
||||
case JBUF_PASS_THRU:
|
||||
if (cinfo->quantize_colors) {
|
||||
/* Single-pass processing with color quantization. */
|
||||
post->pub.post_process_data = post_process_1pass;
|
||||
/* We could be doing buffered-image output before starting a 2-pass
|
||||
* color quantization; in that case, jinit_d_post_controller did not
|
||||
* allocate a strip buffer. Use the virtual-array buffer as workspace.
|
||||
*/
|
||||
if (post->buffer == NULL) {
|
||||
post->buffer = (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, post->whole_image,
|
||||
(JDIMENSION) 0, post->strip_height, TRUE);
|
||||
}
|
||||
} else {
|
||||
/* For single-pass processing without color quantization,
|
||||
* I have no work to do; just call the upsampler directly.
|
||||
*/
|
||||
post->pub.post_process_data = cinfo->upsample->upsample;
|
||||
}
|
||||
break;
|
||||
#ifdef QUANT_2PASS_SUPPORTED
|
||||
case JBUF_SAVE_AND_PASS:
|
||||
/* First pass of 2-pass quantization */
|
||||
if (post->whole_image == NULL)
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
post->pub.post_process_data = post_process_prepass;
|
||||
break;
|
||||
case JBUF_CRANK_DEST:
|
||||
/* Second pass of 2-pass quantization */
|
||||
if (post->whole_image == NULL)
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
post->pub.post_process_data = post_process_2pass;
|
||||
break;
|
||||
#endif /* QUANT_2PASS_SUPPORTED */
|
||||
default:
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
break;
|
||||
}
|
||||
post->starting_row = post->next_row = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process some data in the one-pass (strip buffer) case.
|
||||
* This is used for color precision reduction as well as one-pass quantization.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
post_process_1pass (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
|
||||
JDIMENSION in_row_groups_avail,
|
||||
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail)
|
||||
{
|
||||
my_post_ptr post = (my_post_ptr) cinfo->post;
|
||||
JDIMENSION num_rows, max_rows;
|
||||
|
||||
/* Fill the buffer, but not more than what we can dump out in one go. */
|
||||
/* Note we rely on the upsampler to detect bottom of image. */
|
||||
max_rows = out_rows_avail - *out_row_ctr;
|
||||
if (max_rows > post->strip_height)
|
||||
max_rows = post->strip_height;
|
||||
num_rows = 0;
|
||||
(*cinfo->upsample->upsample) (cinfo,
|
||||
input_buf, in_row_group_ctr, in_row_groups_avail,
|
||||
post->buffer, &num_rows, max_rows);
|
||||
/* Quantize and emit data. */
|
||||
(*cinfo->cquantize->color_quantize) (cinfo,
|
||||
post->buffer, output_buf + *out_row_ctr, (int) num_rows);
|
||||
*out_row_ctr += num_rows;
|
||||
}
|
||||
|
||||
|
||||
#ifdef QUANT_2PASS_SUPPORTED
|
||||
|
||||
/*
|
||||
* Process some data in the first pass of 2-pass quantization.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
post_process_prepass (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
|
||||
JDIMENSION in_row_groups_avail,
|
||||
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail)
|
||||
{
|
||||
my_post_ptr post = (my_post_ptr) cinfo->post;
|
||||
JDIMENSION old_next_row, num_rows;
|
||||
|
||||
/* Reposition virtual buffer if at start of strip. */
|
||||
if (post->next_row == 0) {
|
||||
post->buffer = (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, post->whole_image,
|
||||
post->starting_row, post->strip_height, TRUE);
|
||||
}
|
||||
|
||||
/* Upsample some data (up to a strip height's worth). */
|
||||
old_next_row = post->next_row;
|
||||
(*cinfo->upsample->upsample) (cinfo,
|
||||
input_buf, in_row_group_ctr, in_row_groups_avail,
|
||||
post->buffer, &post->next_row, post->strip_height);
|
||||
|
||||
/* Allow quantizer to scan new data. No data is emitted, */
|
||||
/* but we advance out_row_ctr so outer loop can tell when we're done. */
|
||||
if (post->next_row > old_next_row) {
|
||||
num_rows = post->next_row - old_next_row;
|
||||
(*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row,
|
||||
(JSAMPARRAY) NULL, (int) num_rows);
|
||||
*out_row_ctr += num_rows;
|
||||
}
|
||||
|
||||
/* Advance if we filled the strip. */
|
||||
if (post->next_row >= post->strip_height) {
|
||||
post->starting_row += post->strip_height;
|
||||
post->next_row = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process some data in the second pass of 2-pass quantization.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
post_process_2pass (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
|
||||
JDIMENSION in_row_groups_avail,
|
||||
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail)
|
||||
{
|
||||
my_post_ptr post = (my_post_ptr) cinfo->post;
|
||||
JDIMENSION num_rows, max_rows;
|
||||
|
||||
/* Reposition virtual buffer if at start of strip. */
|
||||
if (post->next_row == 0) {
|
||||
post->buffer = (*cinfo->mem->access_virt_sarray)
|
||||
((j_common_ptr) cinfo, post->whole_image,
|
||||
post->starting_row, post->strip_height, FALSE);
|
||||
}
|
||||
|
||||
/* Determine number of rows to emit. */
|
||||
num_rows = post->strip_height - post->next_row; /* available in strip */
|
||||
max_rows = out_rows_avail - *out_row_ctr; /* available in output area */
|
||||
if (num_rows > max_rows)
|
||||
num_rows = max_rows;
|
||||
/* We have to check bottom of image here, can't depend on upsampler. */
|
||||
max_rows = cinfo->output_height - post->starting_row;
|
||||
if (num_rows > max_rows)
|
||||
num_rows = max_rows;
|
||||
|
||||
/* Quantize and emit data. */
|
||||
(*cinfo->cquantize->color_quantize) (cinfo,
|
||||
post->buffer + post->next_row, output_buf + *out_row_ctr,
|
||||
(int) num_rows);
|
||||
*out_row_ctr += num_rows;
|
||||
|
||||
/* Advance if we filled the strip. */
|
||||
post->next_row += num_rows;
|
||||
if (post->next_row >= post->strip_height) {
|
||||
post->starting_row += post->strip_height;
|
||||
post->next_row = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* QUANT_2PASS_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize postprocessing controller.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
|
||||
{
|
||||
my_post_ptr post;
|
||||
|
||||
post = (my_post_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(my_post_controller));
|
||||
cinfo->post = (struct jpeg_d_post_controller *) post;
|
||||
post->pub.start_pass = start_pass_dpost;
|
||||
post->whole_image = NULL; /* flag for no virtual arrays */
|
||||
post->buffer = NULL; /* flag for no strip buffer */
|
||||
|
||||
/* Create the quantization buffer, if needed */
|
||||
if (cinfo->quantize_colors) {
|
||||
/* The buffer strip height is max_v_samp_factor, which is typically
|
||||
* an efficient number of rows for upsampling to return.
|
||||
* (In the presence of output rescaling, we might want to be smarter?)
|
||||
*/
|
||||
post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor;
|
||||
if (need_full_buffer) {
|
||||
/* Two-pass color quantization: need full-image storage. */
|
||||
/* We round up the number of rows to a multiple of the strip height. */
|
||||
#ifdef QUANT_2PASS_SUPPORTED
|
||||
post->whole_image = (*cinfo->mem->request_virt_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
|
||||
cinfo->output_width * cinfo->out_color_components,
|
||||
(JDIMENSION) jround_up((long) cinfo->output_height,
|
||||
(long) post->strip_height),
|
||||
post->strip_height);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
|
||||
#endif /* QUANT_2PASS_SUPPORTED */
|
||||
} else {
|
||||
/* One-pass color quantization: just make a strip buffer. */
|
||||
post->buffer = (*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
cinfo->output_width * cinfo->out_color_components,
|
||||
post->strip_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
478
RenderDll/Common/Textures/Image/jpeg6/jdsample.cpp
Normal file
478
RenderDll/Common/Textures/Image/jpeg6/jdsample.cpp
Normal file
@@ -0,0 +1,478 @@
|
||||
/*
|
||||
* jdsample.c
|
||||
*
|
||||
* Copyright (C) 1991-1994, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains upsampling routines.
|
||||
*
|
||||
* Upsampling input data is counted in "row groups". A row group
|
||||
* is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
|
||||
* sample rows of each component. Upsampling will normally produce
|
||||
* max_v_samp_factor pixel rows from each row group (but this could vary
|
||||
* if the upsampler is applying a scale factor of its own).
|
||||
*
|
||||
* An excellent reference for image resampling is
|
||||
* Digital Image Warping, George Wolberg, 1990.
|
||||
* Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
|
||||
/* Pointer to routine to upsample a single component */
|
||||
typedef JMETHOD(void, upsample1_ptr,
|
||||
(j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
|
||||
|
||||
/* Private subobject */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_upsampler pub; /* public fields */
|
||||
|
||||
/* Color conversion buffer. When using separate upsampling and color
|
||||
* conversion steps, this buffer holds one upsampled row group until it
|
||||
* has been color converted and output.
|
||||
* Note: we do not allocate any storage for component(s) which are full-size,
|
||||
* ie do not need rescaling. The corresponding entry of color_buf[] is
|
||||
* simply set to point to the input data array, thereby avoiding copying.
|
||||
*/
|
||||
JSAMPARRAY color_buf[MAX_COMPONENTS];
|
||||
|
||||
/* Per-component upsampling method pointers */
|
||||
upsample1_ptr methods[MAX_COMPONENTS];
|
||||
|
||||
int next_row_out; /* counts rows emitted from color_buf */
|
||||
JDIMENSION rows_to_go; /* counts rows remaining in image */
|
||||
|
||||
/* Height of an input row group for each component. */
|
||||
int rowgroup_height[MAX_COMPONENTS];
|
||||
|
||||
/* These arrays save pixel expansion factors so that int_expand need not
|
||||
* recompute them each time. They are unused for other upsampling methods.
|
||||
*/
|
||||
UINT8 h_expand[MAX_COMPONENTS];
|
||||
UINT8 v_expand[MAX_COMPONENTS];
|
||||
} my_upsampler;
|
||||
|
||||
typedef my_upsampler * my_upsample_ptr;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize for an upsampling pass.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
start_pass_upsample (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
|
||||
|
||||
/* Mark the conversion buffer empty */
|
||||
upsample->next_row_out = cinfo->max_v_samp_factor;
|
||||
/* Initialize total-height counter for detecting bottom of image */
|
||||
upsample->rows_to_go = cinfo->output_height;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Control routine to do upsampling (and color conversion).
|
||||
*
|
||||
* In this version we upsample each component independently.
|
||||
* We upsample one row group into the conversion buffer, then apply
|
||||
* color conversion a row at a time.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
sep_upsample (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
|
||||
JDIMENSION in_row_groups_avail,
|
||||
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail)
|
||||
{
|
||||
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
|
||||
int ci;
|
||||
jpeg_component_info * compptr;
|
||||
JDIMENSION num_rows;
|
||||
|
||||
/* Fill the conversion buffer, if it's empty */
|
||||
if (upsample->next_row_out >= cinfo->max_v_samp_factor) {
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* Invoke per-component upsample method. Notice we pass a POINTER
|
||||
* to color_buf[ci], so that fullsize_upsample can change it.
|
||||
*/
|
||||
(*upsample->methods[ci]) (cinfo, compptr,
|
||||
input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]),
|
||||
upsample->color_buf + ci);
|
||||
}
|
||||
upsample->next_row_out = 0;
|
||||
}
|
||||
|
||||
/* Color-convert and emit rows */
|
||||
|
||||
/* How many we have in the buffer: */
|
||||
num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out);
|
||||
/* Not more than the distance to the end of the image. Need this test
|
||||
* in case the image height is not a multiple of max_v_samp_factor:
|
||||
*/
|
||||
if (num_rows > upsample->rows_to_go)
|
||||
num_rows = upsample->rows_to_go;
|
||||
/* And not more than what the client can accept: */
|
||||
out_rows_avail -= *out_row_ctr;
|
||||
if (num_rows > out_rows_avail)
|
||||
num_rows = out_rows_avail;
|
||||
|
||||
(*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf,
|
||||
(JDIMENSION) upsample->next_row_out,
|
||||
output_buf + *out_row_ctr,
|
||||
(int) num_rows);
|
||||
|
||||
/* Adjust counts */
|
||||
*out_row_ctr += num_rows;
|
||||
upsample->rows_to_go -= num_rows;
|
||||
upsample->next_row_out += num_rows;
|
||||
/* When the buffer is emptied, declare this input row group consumed */
|
||||
if (upsample->next_row_out >= cinfo->max_v_samp_factor)
|
||||
(*in_row_group_ctr)++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* These are the routines invoked by sep_upsample to upsample pixel values
|
||||
* of a single component. One row group is processed per call.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* For full-size components, we just make color_buf[ci] point at the
|
||||
* input buffer, and thus avoid copying any data. Note that this is
|
||||
* safe only because sep_upsample doesn't declare the input row group
|
||||
* "consumed" until we are done color converting and emitting it.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
|
||||
{
|
||||
*output_data_ptr = input_data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is a no-op version used for "uninteresting" components.
|
||||
* These components will not be referenced by color conversion.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
|
||||
{
|
||||
*output_data_ptr = NULL; /* safety check */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This version handles any integral sampling ratios.
|
||||
* This is not used for typical JPEG files, so it need not be fast.
|
||||
* Nor, for that matter, is it particularly accurate: the algorithm is
|
||||
* simple replication of the input pixel onto the corresponding output
|
||||
* pixels. The hi-falutin sampling literature refers to this as a
|
||||
* "box filter". A box filter tends to introduce visible artifacts,
|
||||
* so if you are actually going to use 3:1 or 4:1 sampling ratios
|
||||
* you would be well advised to improve this code.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
|
||||
{
|
||||
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
|
||||
JSAMPARRAY output_data = *output_data_ptr;
|
||||
register JSAMPROW inptr, outptr;
|
||||
register JSAMPLE invalue;
|
||||
register int h;
|
||||
JSAMPROW outend;
|
||||
int h_expand, v_expand;
|
||||
int inrow, outrow;
|
||||
|
||||
h_expand = upsample->h_expand[compptr->component_index];
|
||||
v_expand = upsample->v_expand[compptr->component_index];
|
||||
|
||||
inrow = outrow = 0;
|
||||
while (outrow < cinfo->max_v_samp_factor) {
|
||||
/* Generate one output row with proper horizontal expansion */
|
||||
inptr = input_data[inrow];
|
||||
outptr = output_data[outrow];
|
||||
outend = outptr + cinfo->output_width;
|
||||
while (outptr < outend) {
|
||||
invalue = *inptr++; /* don't need GETJSAMPLE() here */
|
||||
for (h = h_expand; h > 0; h--) {
|
||||
*outptr++ = invalue;
|
||||
}
|
||||
}
|
||||
/* Generate any additional output rows by duplicating the first one */
|
||||
if (v_expand > 1) {
|
||||
jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
|
||||
v_expand-1, cinfo->output_width);
|
||||
}
|
||||
inrow++;
|
||||
outrow += v_expand;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fast processing for the common case of 2:1 horizontal and 1:1 vertical.
|
||||
* It's still a box filter.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
|
||||
{
|
||||
JSAMPARRAY output_data = *output_data_ptr;
|
||||
register JSAMPROW inptr, outptr;
|
||||
register JSAMPLE invalue;
|
||||
JSAMPROW outend;
|
||||
int inrow;
|
||||
|
||||
for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
|
||||
inptr = input_data[inrow];
|
||||
outptr = output_data[inrow];
|
||||
outend = outptr + cinfo->output_width;
|
||||
while (outptr < outend) {
|
||||
invalue = *inptr++; /* don't need GETJSAMPLE() here */
|
||||
*outptr++ = invalue;
|
||||
*outptr++ = invalue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fast processing for the common case of 2:1 horizontal and 2:1 vertical.
|
||||
* It's still a box filter.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
|
||||
{
|
||||
JSAMPARRAY output_data = *output_data_ptr;
|
||||
register JSAMPROW inptr, outptr;
|
||||
register JSAMPLE invalue;
|
||||
JSAMPROW outend;
|
||||
int inrow, outrow;
|
||||
|
||||
inrow = outrow = 0;
|
||||
while (outrow < cinfo->max_v_samp_factor) {
|
||||
inptr = input_data[inrow];
|
||||
outptr = output_data[outrow];
|
||||
outend = outptr + cinfo->output_width;
|
||||
while (outptr < outend) {
|
||||
invalue = *inptr++; /* don't need GETJSAMPLE() here */
|
||||
*outptr++ = invalue;
|
||||
*outptr++ = invalue;
|
||||
}
|
||||
jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
|
||||
1, cinfo->output_width);
|
||||
inrow++;
|
||||
outrow += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fancy processing for the common case of 2:1 horizontal and 1:1 vertical.
|
||||
*
|
||||
* The upsampling algorithm is linear interpolation between pixel centers,
|
||||
* also known as a "triangle filter". This is a good compromise between
|
||||
* speed and visual quality. The centers of the output pixels are 1/4 and 3/4
|
||||
* of the way between input pixel centers.
|
||||
*
|
||||
* A note about the "bias" calculations: when rounding fractional values to
|
||||
* integer, we do not want to always round 0.5 up to the next integer.
|
||||
* If we did that, we'd introduce a noticeable bias towards larger values.
|
||||
* Instead, this code is arranged so that 0.5 will be rounded up or down at
|
||||
* alternate pixel locations (a simple ordered dither pattern).
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
|
||||
{
|
||||
JSAMPARRAY output_data = *output_data_ptr;
|
||||
register JSAMPROW inptr, outptr;
|
||||
register int invalue;
|
||||
register JDIMENSION colctr;
|
||||
int inrow;
|
||||
|
||||
for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
|
||||
inptr = input_data[inrow];
|
||||
outptr = output_data[inrow];
|
||||
/* Special case for first column */
|
||||
invalue = GETJSAMPLE(*inptr++);
|
||||
*outptr++ = (JSAMPLE) invalue;
|
||||
*outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2);
|
||||
|
||||
for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
|
||||
/* General case: 3/4 * nearer pixel + 1/4 * further pixel */
|
||||
invalue = GETJSAMPLE(*inptr++) * 3;
|
||||
*outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2);
|
||||
*outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
|
||||
}
|
||||
|
||||
/* Special case for last column */
|
||||
invalue = GETJSAMPLE(*inptr);
|
||||
*outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
|
||||
*outptr++ = (JSAMPLE) invalue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fancy processing for the common case of 2:1 horizontal and 2:1 vertical.
|
||||
* Again a triangle filter; see comments for h2v1 case, above.
|
||||
*
|
||||
* It is OK for us to reference the adjacent input rows because we demanded
|
||||
* context from the main buffer controller (see initialization code).
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
|
||||
{
|
||||
JSAMPARRAY output_data = *output_data_ptr;
|
||||
register JSAMPROW inptr0, inptr1, outptr;
|
||||
#if BITS_IN_JSAMPLE == 8
|
||||
register int thiscolsum, lastcolsum, nextcolsum;
|
||||
#else
|
||||
register INT32 thiscolsum, lastcolsum, nextcolsum;
|
||||
#endif
|
||||
register JDIMENSION colctr;
|
||||
int inrow, outrow, v;
|
||||
|
||||
inrow = outrow = 0;
|
||||
while (outrow < cinfo->max_v_samp_factor) {
|
||||
for (v = 0; v < 2; v++) {
|
||||
/* inptr0 points to nearest input row, inptr1 points to next nearest */
|
||||
inptr0 = input_data[inrow];
|
||||
if (v == 0) /* next nearest is row above */
|
||||
inptr1 = input_data[inrow-1];
|
||||
else /* next nearest is row below */
|
||||
inptr1 = input_data[inrow+1];
|
||||
outptr = output_data[outrow++];
|
||||
|
||||
/* Special case for first column */
|
||||
thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
|
||||
nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
|
||||
*outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4);
|
||||
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
|
||||
lastcolsum = thiscolsum; thiscolsum = nextcolsum;
|
||||
|
||||
for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
|
||||
/* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */
|
||||
/* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
|
||||
nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
|
||||
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
|
||||
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
|
||||
lastcolsum = thiscolsum; thiscolsum = nextcolsum;
|
||||
}
|
||||
|
||||
/* Special case for last column */
|
||||
*outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
|
||||
*outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4);
|
||||
}
|
||||
inrow++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Module initialization routine for upsampling.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
jinit_upsampler (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_upsample_ptr upsample;
|
||||
int ci;
|
||||
jpeg_component_info * compptr;
|
||||
boolean need_buffer, do_fancy;
|
||||
int h_in_group, v_in_group, h_out_group, v_out_group;
|
||||
|
||||
upsample = (my_upsample_ptr)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
SIZEOF(my_upsampler));
|
||||
cinfo->upsample = (struct jpeg_upsampler *) upsample;
|
||||
upsample->pub.start_pass = start_pass_upsample;
|
||||
upsample->pub.upsample = sep_upsample;
|
||||
upsample->pub.need_context_rows = FALSE; /* until we find out differently */
|
||||
|
||||
if (cinfo->CCIR601_sampling) /* this isn't supported */
|
||||
ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
|
||||
|
||||
/* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1,
|
||||
* so don't ask for it.
|
||||
*/
|
||||
do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1;
|
||||
|
||||
/* Verify we can handle the sampling factors, select per-component methods,
|
||||
* and create storage as needed.
|
||||
*/
|
||||
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
|
||||
ci++, compptr++) {
|
||||
/* Compute size of an "input group" after IDCT scaling. This many samples
|
||||
* are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
|
||||
*/
|
||||
h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) /
|
||||
cinfo->min_DCT_scaled_size;
|
||||
v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
|
||||
cinfo->min_DCT_scaled_size;
|
||||
h_out_group = cinfo->max_h_samp_factor;
|
||||
v_out_group = cinfo->max_v_samp_factor;
|
||||
upsample->rowgroup_height[ci] = v_in_group; /* save for use later */
|
||||
need_buffer = TRUE;
|
||||
if (! compptr->component_needed) {
|
||||
/* Don't bother to upsample an uninteresting component. */
|
||||
upsample->methods[ci] = noop_upsample;
|
||||
need_buffer = FALSE;
|
||||
} else if (h_in_group == h_out_group && v_in_group == v_out_group) {
|
||||
/* Fullsize components can be processed without any work. */
|
||||
upsample->methods[ci] = fullsize_upsample;
|
||||
need_buffer = FALSE;
|
||||
} else if (h_in_group * 2 == h_out_group &&
|
||||
v_in_group == v_out_group) {
|
||||
/* Special cases for 2h1v upsampling */
|
||||
if (do_fancy && compptr->downsampled_width > 2)
|
||||
upsample->methods[ci] = h2v1_fancy_upsample;
|
||||
else
|
||||
upsample->methods[ci] = h2v1_upsample;
|
||||
} else if (h_in_group * 2 == h_out_group &&
|
||||
v_in_group * 2 == v_out_group) {
|
||||
/* Special cases for 2h2v upsampling */
|
||||
if (do_fancy && compptr->downsampled_width > 2) {
|
||||
upsample->methods[ci] = h2v2_fancy_upsample;
|
||||
upsample->pub.need_context_rows = TRUE;
|
||||
} else
|
||||
upsample->methods[ci] = h2v2_upsample;
|
||||
} else if ((h_out_group % h_in_group) == 0 &&
|
||||
(v_out_group % v_in_group) == 0) {
|
||||
/* Generic integral-factors upsampling method */
|
||||
upsample->methods[ci] = int_upsample;
|
||||
upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group);
|
||||
upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group);
|
||||
} else
|
||||
ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
|
||||
if (need_buffer) {
|
||||
upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
(JDIMENSION) jround_up((long) cinfo->output_width,
|
||||
(long) cinfo->max_h_samp_factor),
|
||||
(JDIMENSION) cinfo->max_v_samp_factor);
|
||||
}
|
||||
}
|
||||
}
|
||||
122
RenderDll/Common/Textures/Image/jpeg6/jdtrans.cpp
Normal file
122
RenderDll/Common/Textures/Image/jpeg6/jdtrans.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* jdtrans.c
|
||||
*
|
||||
* Copyright (C) 1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains library routines for transcoding decompression,
|
||||
* that is, reading raw DCT coefficient arrays from an input JPEG file.
|
||||
* The routines in jdapimin.c will also be needed by a transcoder.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
LOCAL void transdecode_master_selection JPP((j_decompress_ptr cinfo));
|
||||
|
||||
|
||||
/*
|
||||
* Read the coefficient arrays from a JPEG file.
|
||||
* jpeg_read_header must be completed before calling this.
|
||||
*
|
||||
* The entire image is read into a set of virtual coefficient-block arrays,
|
||||
* one per component. The return value is a pointer to the array of
|
||||
* virtual-array descriptors. These can be manipulated directly via the
|
||||
* JPEG memory manager, or handed off to jpeg_write_coefficients().
|
||||
* To release the memory occupied by the virtual arrays, call
|
||||
* jpeg_finish_decompress() when done with the data.
|
||||
*
|
||||
* Returns NULL if suspended. This case need be checked only if
|
||||
* a suspending data source is used.
|
||||
*/
|
||||
|
||||
GLOBAL jvirt_barray_ptr *
|
||||
my_jpeg_read_coefficients (j_decompress_ptr cinfo)
|
||||
{
|
||||
if (cinfo->global_state == DSTATE_READY) {
|
||||
/* First call: initialize active modules */
|
||||
transdecode_master_selection(cinfo);
|
||||
cinfo->global_state = DSTATE_RDCOEFS;
|
||||
} else if (cinfo->global_state != DSTATE_RDCOEFS)
|
||||
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
|
||||
/* Absorb whole file into the coef buffer */
|
||||
for (;;) {
|
||||
int retcode;
|
||||
/* Call progress monitor hook if present */
|
||||
if (cinfo->progress != NULL)
|
||||
(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
|
||||
/* Absorb some more input */
|
||||
retcode = (*cinfo->inputctl->consume_input) (cinfo);
|
||||
if (retcode == JPEG_SUSPENDED)
|
||||
return NULL;
|
||||
if (retcode == JPEG_REACHED_EOI)
|
||||
break;
|
||||
/* Advance progress counter if appropriate */
|
||||
if (cinfo->progress != NULL &&
|
||||
(retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
|
||||
if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
|
||||
/* startup underestimated number of scans; ratchet up one scan */
|
||||
cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Set state so that jpeg_finish_decompress does the right thing */
|
||||
cinfo->global_state = DSTATE_STOPPING;
|
||||
return cinfo->coef->coef_arrays;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Master selection of decompression modules for transcoding.
|
||||
* This substitutes for jdmaster.c's initialization of the full decompressor.
|
||||
*/
|
||||
|
||||
LOCAL void
|
||||
transdecode_master_selection (j_decompress_ptr cinfo)
|
||||
{
|
||||
/* Entropy decoding: either Huffman or arithmetic coding. */
|
||||
if (cinfo->arith_code) {
|
||||
ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
|
||||
} else {
|
||||
if (cinfo->progressive_mode) {
|
||||
#ifdef D_PROGRESSIVE_SUPPORTED
|
||||
jinit_phuff_decoder(cinfo);
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
} else
|
||||
jinit_huff_decoder(cinfo);
|
||||
}
|
||||
|
||||
/* Always get a full-image coefficient buffer. */
|
||||
jinit_d_coef_controller(cinfo, TRUE);
|
||||
|
||||
/* We can now tell the memory manager to allocate virtual arrays. */
|
||||
(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
|
||||
|
||||
/* Initialize input side of decompressor to consume first scan. */
|
||||
(*cinfo->inputctl->start_input_pass) (cinfo);
|
||||
|
||||
/* Initialize progress monitoring. */
|
||||
if (cinfo->progress != NULL) {
|
||||
int nscans;
|
||||
/* Estimate number of scans to set pass_limit. */
|
||||
if (cinfo->progressive_mode) {
|
||||
/* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
|
||||
nscans = 2 + 3 * cinfo->num_components;
|
||||
} else if (cinfo->inputctl->has_multiple_scans) {
|
||||
/* For a nonprogressive multiscan file, estimate 1 scan per component. */
|
||||
nscans = cinfo->num_components;
|
||||
} else {
|
||||
nscans = 1;
|
||||
}
|
||||
cinfo->progress->pass_counter = 0L;
|
||||
cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
|
||||
cinfo->progress->completed_passes = 0;
|
||||
cinfo->progress->total_passes = 1;
|
||||
}
|
||||
}
|
||||
231
RenderDll/Common/Textures/Image/jpeg6/jerror.cpp
Normal file
231
RenderDll/Common/Textures/Image/jpeg6/jerror.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* jerror.c
|
||||
*
|
||||
* Copyright (C) 1991-1994, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains simple error-reporting and trace-message routines.
|
||||
* These are suitable for Unix-like systems and others where writing to
|
||||
* stderr is the right thing to do. Many applications will want to replace
|
||||
* some or all of these routines.
|
||||
*
|
||||
* These routines are used by both the compression and decompression code.
|
||||
*/
|
||||
|
||||
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jversion.h"
|
||||
#include "jerror.h"
|
||||
|
||||
#ifndef EXIT_FAILURE /* define exit() codes if not provided */
|
||||
#define EXIT_FAILURE 1
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Create the message string table.
|
||||
* We do this from the master message list in jerror.h by re-reading
|
||||
* jerror.h with a suitable definition for macro JMESSAGE.
|
||||
* The message table is made an external symbol just in case any applications
|
||||
* want to refer to it directly.
|
||||
*/
|
||||
|
||||
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||
#define jpeg_std_message_table jMsgTable
|
||||
#endif
|
||||
|
||||
#define JMESSAGE(code,string) string ,
|
||||
|
||||
const char * const jpeg_std_message_table[] = {
|
||||
#include "jerror.h"
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Error exit handler: must not return to caller.
|
||||
*
|
||||
* Applications may override this if they want to get control back after
|
||||
* an error. Typically one would longjmp somewhere instead of exiting.
|
||||
* The setjmp buffer can be made a private field within an expanded error
|
||||
* handler object. Note that the info needed to generate an error message
|
||||
* is stored in the error object, so you can generate the message now or
|
||||
* later, at your convenience.
|
||||
* You should make sure that the JPEG object is cleaned up (with jpeg_abort
|
||||
* or jpeg_destroy) at some point.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
error_exit (j_common_ptr cinfo)
|
||||
{
|
||||
char buffer[JMSG_LENGTH_MAX];
|
||||
|
||||
/* Create the message */
|
||||
(*cinfo->err->format_message) (cinfo, buffer);
|
||||
|
||||
/* Let the memory manager delete any temp files before we die */
|
||||
my_jpeg_destroy(cinfo);
|
||||
|
||||
// FIXME: need to get this setup with an error handler
|
||||
//Error("%s\n", buffer );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Actual output of an error or trace message.
|
||||
* Applications may override this method to send JPEG messages somewhere
|
||||
* other than stderr.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
output_message (j_common_ptr cinfo)
|
||||
{
|
||||
char buffer[JMSG_LENGTH_MAX];
|
||||
|
||||
/* Create the message */
|
||||
(*cinfo->err->format_message) (cinfo, buffer);
|
||||
|
||||
/* Send it to stderr, adding a newline */
|
||||
printf("%s\n", buffer);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decide whether to emit a trace or warning message.
|
||||
* msg_level is one of:
|
||||
* -1: recoverable corrupt-data warning, may want to abort.
|
||||
* 0: important advisory messages (always display to user).
|
||||
* 1: first level of tracing detail.
|
||||
* 2,3,...: successively more detailed tracing messages.
|
||||
* An application might override this method if it wanted to abort on warnings
|
||||
* or change the policy about which messages to display.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
emit_message (j_common_ptr cinfo, int msg_level)
|
||||
{
|
||||
struct jpeg_error_mgr * err = cinfo->err;
|
||||
|
||||
if (msg_level < 0) {
|
||||
/* It's a warning message. Since corrupt files may generate many warnings,
|
||||
* the policy implemented here is to show only the first warning,
|
||||
* unless trace_level >= 3.
|
||||
*/
|
||||
if (err->num_warnings == 0 || err->trace_level >= 3)
|
||||
(*err->output_message) (cinfo);
|
||||
/* Always count warnings in num_warnings. */
|
||||
err->num_warnings++;
|
||||
} else {
|
||||
/* It's a trace message. Show it if trace_level >= msg_level. */
|
||||
if (err->trace_level >= msg_level)
|
||||
(*err->output_message) (cinfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Format a message string for the most recent JPEG error or message.
|
||||
* The message is stored into buffer, which should be at least JMSG_LENGTH_MAX
|
||||
* characters. Note that no '\n' character is added to the string.
|
||||
* Few applications should need to override this method.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
format_message (j_common_ptr cinfo, char * buffer)
|
||||
{
|
||||
struct jpeg_error_mgr * err = cinfo->err;
|
||||
int msg_code = err->msg_code;
|
||||
const char * msgtext = NULL;
|
||||
const char * msgptr;
|
||||
char ch;
|
||||
boolean isstring;
|
||||
|
||||
/* Look up message string in proper table */
|
||||
if (msg_code > 0 && msg_code <= err->last_jpeg_message) {
|
||||
msgtext = err->jpeg_message_table[msg_code];
|
||||
} else if (err->addon_message_table != NULL &&
|
||||
msg_code >= err->first_addon_message &&
|
||||
msg_code <= err->last_addon_message) {
|
||||
msgtext = err->addon_message_table[msg_code - err->first_addon_message];
|
||||
}
|
||||
|
||||
/* Defend against bogus message number */
|
||||
if (msgtext == NULL) {
|
||||
err->msg_parm.i[0] = msg_code;
|
||||
msgtext = err->jpeg_message_table[0];
|
||||
}
|
||||
|
||||
/* Check for string parameter, as indicated by %s in the message text */
|
||||
isstring = FALSE;
|
||||
msgptr = msgtext;
|
||||
while ((ch = *msgptr++) != '\0') {
|
||||
if (ch == '%') {
|
||||
if (*msgptr == 's') isstring = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Format the message into the passed buffer */
|
||||
if (isstring)
|
||||
sprintf(buffer, msgtext, err->msg_parm.s);
|
||||
else
|
||||
sprintf(buffer, msgtext,
|
||||
err->msg_parm.i[0], err->msg_parm.i[1],
|
||||
err->msg_parm.i[2], err->msg_parm.i[3],
|
||||
err->msg_parm.i[4], err->msg_parm.i[5],
|
||||
err->msg_parm.i[6], err->msg_parm.i[7]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reset error state variables at start of a new image.
|
||||
* This is called during compression startup to reset trace/error
|
||||
* processing to default state, without losing any application-specific
|
||||
* method pointers. An application might possibly want to override
|
||||
* this method if it has additional error processing state.
|
||||
*/
|
||||
|
||||
METHODDEF void
|
||||
reset_error_mgr (j_common_ptr cinfo)
|
||||
{
|
||||
cinfo->err->num_warnings = 0;
|
||||
/* trace_level is not reset since it is an application-supplied parameter */
|
||||
cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fill in the standard error-handling methods in a jpeg_error_mgr object.
|
||||
* Typical call is:
|
||||
* struct jpeg_compress_struct cinfo;
|
||||
* struct jpeg_error_mgr err;
|
||||
*
|
||||
* cinfo.err = jpeg_std_error(&err);
|
||||
* after which the application may override some of the methods.
|
||||
*/
|
||||
|
||||
GLOBAL struct jpeg_error_mgr *
|
||||
my_jpeg_std_error (struct jpeg_error_mgr * err)
|
||||
{
|
||||
err->error_exit = error_exit;
|
||||
err->emit_message = emit_message;
|
||||
err->output_message = output_message;
|
||||
err->format_message = format_message;
|
||||
err->reset_error_mgr = reset_error_mgr;
|
||||
|
||||
err->trace_level = 0; /* default = no tracing */
|
||||
err->num_warnings = 0; /* no warnings emitted yet */
|
||||
err->msg_code = 0; /* may be useful as a flag for "no error" */
|
||||
|
||||
/* Initialize message table pointers */
|
||||
err->jpeg_message_table = jpeg_std_message_table;
|
||||
err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1;
|
||||
|
||||
err->addon_message_table = NULL;
|
||||
err->first_addon_message = 0; /* for safety */
|
||||
err->last_addon_message = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
273
RenderDll/Common/Textures/Image/jpeg6/jerror.h
Normal file
273
RenderDll/Common/Textures/Image/jpeg6/jerror.h
Normal file
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* jerror.h
|
||||
*
|
||||
* Copyright (C) 1994-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file defines the error and message codes for the JPEG library.
|
||||
* Edit this file to add new codes, or to translate the message strings to
|
||||
* some other language.
|
||||
* A set of error-reporting macros are defined too. Some applications using
|
||||
* the JPEG library may wish to include this file to get the error codes
|
||||
* and/or the macros.
|
||||
*/
|
||||
|
||||
/*
|
||||
* To define the enum list of message codes, include this file without
|
||||
* defining macro JMESSAGE. To create a message string table, include it
|
||||
* again with a suitable JMESSAGE definition (see jerror.c for an example).
|
||||
*/
|
||||
#ifndef JMESSAGE
|
||||
#ifndef JERROR_H
|
||||
/* First time through, define the enum list */
|
||||
#define JMAKE_ENUM_LIST
|
||||
#else
|
||||
/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
|
||||
#define JMESSAGE(code,string)
|
||||
#endif /* JERROR_H */
|
||||
#endif /* JMESSAGE */
|
||||
|
||||
#ifdef JMAKE_ENUM_LIST
|
||||
|
||||
typedef enum {
|
||||
|
||||
#define JMESSAGE(code,string) code ,
|
||||
|
||||
#endif /* JMAKE_ENUM_LIST */
|
||||
|
||||
JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
|
||||
|
||||
/* For maintenance convenience, list is alphabetical by message code name */
|
||||
JMESSAGE(JERR_ARITH_NOTIMPL,
|
||||
"Sorry, there are legal restrictions on arithmetic coding")
|
||||
JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
|
||||
JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
|
||||
JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
|
||||
JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
|
||||
JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
|
||||
JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
|
||||
JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
|
||||
JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
|
||||
JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
|
||||
JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
|
||||
JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
|
||||
JMESSAGE(JERR_BAD_PROGRESSION,
|
||||
"Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d")
|
||||
JMESSAGE(JERR_BAD_PROG_SCRIPT,
|
||||
"Invalid progressive parameters at scan script entry %d")
|
||||
JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
|
||||
JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
|
||||
JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
|
||||
JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
|
||||
JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
|
||||
JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
|
||||
JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
|
||||
JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
|
||||
JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
|
||||
JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d")
|
||||
JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x")
|
||||
JMESSAGE(JERR_DHT_COUNTS, "Bogus DHT counts")
|
||||
JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d")
|
||||
JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d")
|
||||
JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)")
|
||||
JMESSAGE(JERR_EMS_READ, "Read from EMS failed")
|
||||
JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed")
|
||||
JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan")
|
||||
JMESSAGE(JERR_FILE_READ, "Input file read error")
|
||||
JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")
|
||||
JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet")
|
||||
JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow")
|
||||
JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry")
|
||||
JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels")
|
||||
JMESSAGE(JERR_INPUT_EMPTY, "Empty input file")
|
||||
JMESSAGE(JERR_INPUT_EOF, "Premature end of input file")
|
||||
JMESSAGE(JERR_MISMATCHED_QUANT_TABLE,
|
||||
"Cannot transcode due to multiple use of quantization table %d")
|
||||
JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data")
|
||||
JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change")
|
||||
JMESSAGE(JERR_NOTIMPL, "Not implemented yet")
|
||||
JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
|
||||
JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported")
|
||||
JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
|
||||
JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
|
||||
JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
|
||||
JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
|
||||
JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
|
||||
JMESSAGE(JERR_QUANT_COMPONENTS,
|
||||
"Cannot quantize more than %d color components")
|
||||
JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors")
|
||||
JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors")
|
||||
JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers")
|
||||
JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker")
|
||||
JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x")
|
||||
JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers")
|
||||
JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF")
|
||||
JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s")
|
||||
JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file")
|
||||
JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file")
|
||||
JMESSAGE(JERR_TFILE_WRITE,
|
||||
"Write failed on temporary file --- out of disk space?")
|
||||
JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines")
|
||||
JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x")
|
||||
JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up")
|
||||
JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation")
|
||||
JMESSAGE(JERR_XMS_READ, "Read from XMS failed")
|
||||
JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed")
|
||||
JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT)
|
||||
JMESSAGE(JMSG_VERSION, JVERSION)
|
||||
JMESSAGE(JTRC_16BIT_TABLES,
|
||||
"Caution: quantization tables are too coarse for baseline JPEG")
|
||||
JMESSAGE(JTRC_ADOBE,
|
||||
"Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d")
|
||||
JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u")
|
||||
JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u")
|
||||
JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x")
|
||||
JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x")
|
||||
JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d")
|
||||
JMESSAGE(JTRC_DRI, "Define Restart Interval %u")
|
||||
JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u")
|
||||
JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u")
|
||||
JMESSAGE(JTRC_EOI, "End Of Image")
|
||||
JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d")
|
||||
JMESSAGE(JTRC_JFIF, "JFIF APP0 marker, density %dx%d %d")
|
||||
JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
|
||||
"Warning: thumbnail image size does not match data length %u")
|
||||
JMESSAGE(JTRC_JFIF_MINOR, "Unknown JFIF minor revision number %d.%02d")
|
||||
JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image")
|
||||
JMESSAGE(JTRC_MISC_MARKER, "Skipping marker 0x%02x, length %u")
|
||||
JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
|
||||
JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u")
|
||||
JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors")
|
||||
JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors")
|
||||
JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization")
|
||||
JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d")
|
||||
JMESSAGE(JTRC_RST, "RST%d")
|
||||
JMESSAGE(JTRC_SMOOTH_NOTIMPL,
|
||||
"Smoothing not supported with nonstandard sampling ratios")
|
||||
JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d")
|
||||
JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d")
|
||||
JMESSAGE(JTRC_SOI, "Start of Image")
|
||||
JMESSAGE(JTRC_SOS, "Start Of Scan: %d components")
|
||||
JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d")
|
||||
JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d")
|
||||
JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s")
|
||||
JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s")
|
||||
JMESSAGE(JTRC_UNKNOWN_IDS,
|
||||
"Unrecognized component IDs %d %d %d, assuming YCbCr")
|
||||
JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
|
||||
JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
|
||||
JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
|
||||
JMESSAGE(JWRN_BOGUS_PROGRESSION,
|
||||
"Inconsistent progression sequence for component %d coefficient %d")
|
||||
JMESSAGE(JWRN_EXTRANEOUS_DATA,
|
||||
"Corrupt JPEG data: %u extraneous bytes before marker 0x%02x")
|
||||
JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
|
||||
JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
|
||||
JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d")
|
||||
JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
|
||||
JMESSAGE(JWRN_MUST_RESYNC,
|
||||
"Corrupt JPEG data: found marker 0x%02x instead of RST%d")
|
||||
JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
|
||||
JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
|
||||
|
||||
#ifdef JMAKE_ENUM_LIST
|
||||
|
||||
JMSG_LASTMSGCODE
|
||||
} J_MESSAGE_CODE;
|
||||
|
||||
#undef JMAKE_ENUM_LIST
|
||||
#endif /* JMAKE_ENUM_LIST */
|
||||
|
||||
/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
|
||||
#undef JMESSAGE
|
||||
|
||||
|
||||
#ifndef JERROR_H
|
||||
#define JERROR_H
|
||||
|
||||
/* Macros to simplify using the error and trace message stuff */
|
||||
/* The first parameter is either type of cinfo pointer */
|
||||
|
||||
/* Fatal errors (print message and exit) */
|
||||
#define ERREXIT(cinfo,code) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||
#define ERREXIT1(cinfo,code,p1) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||
#define ERREXIT2(cinfo,code,p1,p2) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||
#define ERREXIT3(cinfo,code,p1,p2,p3) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(cinfo)->err->msg_parm.i[2] = (p3), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||
#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(cinfo)->err->msg_parm.i[2] = (p3), \
|
||||
(cinfo)->err->msg_parm.i[3] = (p4), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||
#define ERREXITS(cinfo,code,str) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
|
||||
|
||||
#define MAKESTMT(stuff) do { stuff } while (0)
|
||||
|
||||
/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
|
||||
#define WARNMS(cinfo,code) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
|
||||
#define WARNMS1(cinfo,code,p1) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
|
||||
#define WARNMS2(cinfo,code,p1,p2) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
|
||||
|
||||
/* Informational/debugging messages */
|
||||
#define TRACEMS(cinfo,lvl,code) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
|
||||
#define TRACEMS1(cinfo,lvl,code,p1) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
|
||||
#define TRACEMS2(cinfo,lvl,code,p1,p2) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
|
||||
#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \
|
||||
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
|
||||
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
|
||||
(cinfo)->err->msg_code = (code); \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
|
||||
#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \
|
||||
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
|
||||
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
|
||||
(cinfo)->err->msg_code = (code); \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
|
||||
#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \
|
||||
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
|
||||
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
|
||||
_mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
|
||||
(cinfo)->err->msg_code = (code); \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
|
||||
#define TRACEMSS(cinfo,lvl,code,str) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
|
||||
|
||||
#endif /* JERROR_H */
|
||||
168
RenderDll/Common/Textures/Image/jpeg6/jfdctflt.cpp
Normal file
168
RenderDll/Common/Textures/Image/jpeg6/jfdctflt.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* jfdctflt.c
|
||||
*
|
||||
* Copyright (C) 1994, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains a floating-point implementation of the
|
||||
* forward DCT (Discrete Cosine Transform).
|
||||
*
|
||||
* This implementation should be more accurate than either of the integer
|
||||
* DCT implementations. However, it may not give the same results on all
|
||||
* machines because of differences in roundoff behavior. Speed will depend
|
||||
* on the hardware's floating point capacity.
|
||||
*
|
||||
* A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
|
||||
* on each column. Direct algorithms are also available, but they are
|
||||
* much more complex and seem not to be any faster when reduced to code.
|
||||
*
|
||||
* This implementation is based on Arai, Agui, and Nakajima's algorithm for
|
||||
* scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
|
||||
* Japanese, but the algorithm is described in the Pennebaker & Mitchell
|
||||
* JPEG textbook (see REFERENCES section in file README). The following code
|
||||
* is based directly on figure 4-8 in P&M.
|
||||
* While an 8-point DCT cannot be done in less than 11 multiplies, it is
|
||||
* possible to arrange the computation so that many of the multiplies are
|
||||
* simple scalings of the final outputs. These multiplies can then be
|
||||
* folded into the multiplications or divisions by the JPEG quantization
|
||||
* table entries. The AA&N method leaves only 5 multiplies and 29 adds
|
||||
* to be done in the DCT itself.
|
||||
* The primary disadvantage of this method is that with a fixed-point
|
||||
* implementation, accuracy is lost due to imprecise representation of the
|
||||
* scaled quantization values. However, that problem does not arise if
|
||||
* we use floating point arithmetic.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jdct.h" /* Private declarations for DCT subsystem */
|
||||
|
||||
#ifdef DCT_FLOAT_SUPPORTED
|
||||
|
||||
|
||||
/*
|
||||
* This module is specialized to the case DCTSIZE = 8.
|
||||
*/
|
||||
|
||||
#if DCTSIZE != 8
|
||||
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Perform the forward DCT on one block of samples.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_fdct_float (FAST_FLOAT * data)
|
||||
{
|
||||
FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
|
||||
FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
|
||||
FAST_FLOAT z1, z2, z3, z4, z5, z11, z13;
|
||||
FAST_FLOAT *dataptr;
|
||||
int ctr;
|
||||
|
||||
/* Pass 1: process rows. */
|
||||
|
||||
dataptr = data;
|
||||
for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
|
||||
tmp0 = dataptr[0] + dataptr[7];
|
||||
tmp7 = dataptr[0] - dataptr[7];
|
||||
tmp1 = dataptr[1] + dataptr[6];
|
||||
tmp6 = dataptr[1] - dataptr[6];
|
||||
tmp2 = dataptr[2] + dataptr[5];
|
||||
tmp5 = dataptr[2] - dataptr[5];
|
||||
tmp3 = dataptr[3] + dataptr[4];
|
||||
tmp4 = dataptr[3] - dataptr[4];
|
||||
|
||||
/* Even part */
|
||||
|
||||
tmp10 = tmp0 + tmp3; /* phase 2 */
|
||||
tmp13 = tmp0 - tmp3;
|
||||
tmp11 = tmp1 + tmp2;
|
||||
tmp12 = tmp1 - tmp2;
|
||||
|
||||
dataptr[0] = tmp10 + tmp11; /* phase 3 */
|
||||
dataptr[4] = tmp10 - tmp11;
|
||||
|
||||
z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
|
||||
dataptr[2] = tmp13 + z1; /* phase 5 */
|
||||
dataptr[6] = tmp13 - z1;
|
||||
|
||||
/* Odd part */
|
||||
|
||||
tmp10 = tmp4 + tmp5; /* phase 2 */
|
||||
tmp11 = tmp5 + tmp6;
|
||||
tmp12 = tmp6 + tmp7;
|
||||
|
||||
/* The rotator is modified from fig 4-8 to avoid extra negations. */
|
||||
z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
|
||||
z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
|
||||
z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
|
||||
z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
|
||||
|
||||
z11 = tmp7 + z3; /* phase 5 */
|
||||
z13 = tmp7 - z3;
|
||||
|
||||
dataptr[5] = z13 + z2; /* phase 6 */
|
||||
dataptr[3] = z13 - z2;
|
||||
dataptr[1] = z11 + z4;
|
||||
dataptr[7] = z11 - z4;
|
||||
|
||||
dataptr += DCTSIZE; /* advance pointer to next row */
|
||||
}
|
||||
|
||||
/* Pass 2: process columns. */
|
||||
|
||||
dataptr = data;
|
||||
for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
|
||||
tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
|
||||
tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
|
||||
tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
|
||||
tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
|
||||
tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
|
||||
tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
|
||||
tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
|
||||
tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
|
||||
|
||||
/* Even part */
|
||||
|
||||
tmp10 = tmp0 + tmp3; /* phase 2 */
|
||||
tmp13 = tmp0 - tmp3;
|
||||
tmp11 = tmp1 + tmp2;
|
||||
tmp12 = tmp1 - tmp2;
|
||||
|
||||
dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
|
||||
dataptr[DCTSIZE*4] = tmp10 - tmp11;
|
||||
|
||||
z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
|
||||
dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
|
||||
dataptr[DCTSIZE*6] = tmp13 - z1;
|
||||
|
||||
/* Odd part */
|
||||
|
||||
tmp10 = tmp4 + tmp5; /* phase 2 */
|
||||
tmp11 = tmp5 + tmp6;
|
||||
tmp12 = tmp6 + tmp7;
|
||||
|
||||
/* The rotator is modified from fig 4-8 to avoid extra negations. */
|
||||
z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
|
||||
z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
|
||||
z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
|
||||
z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
|
||||
|
||||
z11 = tmp7 + z3; /* phase 5 */
|
||||
z13 = tmp7 - z3;
|
||||
|
||||
dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
|
||||
dataptr[DCTSIZE*3] = z13 - z2;
|
||||
dataptr[DCTSIZE*1] = z11 + z4;
|
||||
dataptr[DCTSIZE*7] = z11 - z4;
|
||||
|
||||
dataptr++; /* advance pointer to next column */
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DCT_FLOAT_SUPPORTED */
|
||||
241
RenderDll/Common/Textures/Image/jpeg6/jidctflt.cpp
Normal file
241
RenderDll/Common/Textures/Image/jpeg6/jidctflt.cpp
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* jidctflt.c
|
||||
*
|
||||
* Copyright (C) 1994, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains a floating-point implementation of the
|
||||
* inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
|
||||
* must also perform dequantization of the input coefficients.
|
||||
*
|
||||
* This implementation should be more accurate than either of the integer
|
||||
* IDCT implementations. However, it may not give the same results on all
|
||||
* machines because of differences in roundoff behavior. Speed will depend
|
||||
* on the hardware's floating point capacity.
|
||||
*
|
||||
* A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
|
||||
* on each row (or vice versa, but it's more convenient to emit a row at
|
||||
* a time). Direct algorithms are also available, but they are much more
|
||||
* complex and seem not to be any faster when reduced to code.
|
||||
*
|
||||
* This implementation is based on Arai, Agui, and Nakajima's algorithm for
|
||||
* scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
|
||||
* Japanese, but the algorithm is described in the Pennebaker & Mitchell
|
||||
* JPEG textbook (see REFERENCES section in file README). The following code
|
||||
* is based directly on figure 4-8 in P&M.
|
||||
* While an 8-point DCT cannot be done in less than 11 multiplies, it is
|
||||
* possible to arrange the computation so that many of the multiplies are
|
||||
* simple scalings of the final outputs. These multiplies can then be
|
||||
* folded into the multiplications or divisions by the JPEG quantization
|
||||
* table entries. The AA&N method leaves only 5 multiplies and 29 adds
|
||||
* to be done in the DCT itself.
|
||||
* The primary disadvantage of this method is that with a fixed-point
|
||||
* implementation, accuracy is lost due to imprecise representation of the
|
||||
* scaled quantization values. However, that problem does not arise if
|
||||
* we use floating point arithmetic.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jdct.h" /* Private declarations for DCT subsystem */
|
||||
|
||||
#ifdef DCT_FLOAT_SUPPORTED
|
||||
|
||||
|
||||
/*
|
||||
* This module is specialized to the case DCTSIZE = 8.
|
||||
*/
|
||||
|
||||
#if DCTSIZE != 8
|
||||
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
|
||||
#endif
|
||||
|
||||
|
||||
/* Dequantize a coefficient by multiplying it by the multiplier-table
|
||||
* entry; produce a float result.
|
||||
*/
|
||||
|
||||
#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval))
|
||||
|
||||
|
||||
/*
|
||||
* Perform dequantization and inverse DCT on one block of coefficients.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JCOEFPTR coef_block,
|
||||
JSAMPARRAY output_buf, JDIMENSION output_col)
|
||||
{
|
||||
FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
|
||||
FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
|
||||
FAST_FLOAT z5, z10, z11, z12, z13;
|
||||
JCOEFPTR inptr;
|
||||
FLOAT_MULT_TYPE * quantptr;
|
||||
FAST_FLOAT * wsptr;
|
||||
JSAMPROW outptr;
|
||||
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
|
||||
int ctr;
|
||||
FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */
|
||||
SHIFT_TEMPS
|
||||
|
||||
/* Pass 1: process columns from input, store into work array. */
|
||||
|
||||
inptr = coef_block;
|
||||
quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table;
|
||||
wsptr = workspace;
|
||||
for (ctr = DCTSIZE; ctr > 0; ctr--) {
|
||||
/* Due to quantization, we will usually find that many of the input
|
||||
* coefficients are zero, especially the AC terms. We can exploit this
|
||||
* by short-circuiting the IDCT calculation for any column in which all
|
||||
* the AC terms are zero. In that case each output is equal to the
|
||||
* DC coefficient (with scale factor as needed).
|
||||
* With typical images and quantization tables, half or more of the
|
||||
* column DCT calculations can be simplified this way.
|
||||
*/
|
||||
|
||||
if ((inptr[DCTSIZE*1] | inptr[DCTSIZE*2] | inptr[DCTSIZE*3] |
|
||||
inptr[DCTSIZE*4] | inptr[DCTSIZE*5] | inptr[DCTSIZE*6] |
|
||||
inptr[DCTSIZE*7]) == 0) {
|
||||
/* AC terms all zero */
|
||||
FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
|
||||
|
||||
wsptr[DCTSIZE*0] = dcval;
|
||||
wsptr[DCTSIZE*1] = dcval;
|
||||
wsptr[DCTSIZE*2] = dcval;
|
||||
wsptr[DCTSIZE*3] = dcval;
|
||||
wsptr[DCTSIZE*4] = dcval;
|
||||
wsptr[DCTSIZE*5] = dcval;
|
||||
wsptr[DCTSIZE*6] = dcval;
|
||||
wsptr[DCTSIZE*7] = dcval;
|
||||
|
||||
inptr++; /* advance pointers to next column */
|
||||
quantptr++;
|
||||
wsptr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Even part */
|
||||
|
||||
tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
|
||||
tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
|
||||
tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
|
||||
tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
|
||||
|
||||
tmp10 = tmp0 + tmp2; /* phase 3 */
|
||||
tmp11 = tmp0 - tmp2;
|
||||
|
||||
tmp13 = tmp1 + tmp3; /* phases 5-3 */
|
||||
tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */
|
||||
|
||||
tmp0 = tmp10 + tmp13; /* phase 2 */
|
||||
tmp3 = tmp10 - tmp13;
|
||||
tmp1 = tmp11 + tmp12;
|
||||
tmp2 = tmp11 - tmp12;
|
||||
|
||||
/* Odd part */
|
||||
|
||||
tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
|
||||
tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
|
||||
tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
|
||||
tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
|
||||
|
||||
z13 = tmp6 + tmp5; /* phase 6 */
|
||||
z10 = tmp6 - tmp5;
|
||||
z11 = tmp4 + tmp7;
|
||||
z12 = tmp4 - tmp7;
|
||||
|
||||
tmp7 = z11 + z13; /* phase 5 */
|
||||
tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */
|
||||
|
||||
z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
|
||||
tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
|
||||
tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
|
||||
|
||||
tmp6 = tmp12 - tmp7; /* phase 2 */
|
||||
tmp5 = tmp11 - tmp6;
|
||||
tmp4 = tmp10 + tmp5;
|
||||
|
||||
wsptr[DCTSIZE*0] = tmp0 + tmp7;
|
||||
wsptr[DCTSIZE*7] = tmp0 - tmp7;
|
||||
wsptr[DCTSIZE*1] = tmp1 + tmp6;
|
||||
wsptr[DCTSIZE*6] = tmp1 - tmp6;
|
||||
wsptr[DCTSIZE*2] = tmp2 + tmp5;
|
||||
wsptr[DCTSIZE*5] = tmp2 - tmp5;
|
||||
wsptr[DCTSIZE*4] = tmp3 + tmp4;
|
||||
wsptr[DCTSIZE*3] = tmp3 - tmp4;
|
||||
|
||||
inptr++; /* advance pointers to next column */
|
||||
quantptr++;
|
||||
wsptr++;
|
||||
}
|
||||
|
||||
/* Pass 2: process rows from work array, store into output array. */
|
||||
/* Note that we must descale the results by a factor of 8 == 2**3. */
|
||||
|
||||
wsptr = workspace;
|
||||
for (ctr = 0; ctr < DCTSIZE; ctr++) {
|
||||
outptr = output_buf[ctr] + output_col;
|
||||
/* Rows of zeroes can be exploited in the same way as we did with columns.
|
||||
* However, the column calculation has created many nonzero AC terms, so
|
||||
* the simplification applies less often (typically 5% to 10% of the time).
|
||||
* And testing floats for zero is relatively expensive, so we don't bother.
|
||||
*/
|
||||
|
||||
/* Even part */
|
||||
|
||||
tmp10 = wsptr[0] + wsptr[4];
|
||||
tmp11 = wsptr[0] - wsptr[4];
|
||||
|
||||
tmp13 = wsptr[2] + wsptr[6];
|
||||
tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13;
|
||||
|
||||
tmp0 = tmp10 + tmp13;
|
||||
tmp3 = tmp10 - tmp13;
|
||||
tmp1 = tmp11 + tmp12;
|
||||
tmp2 = tmp11 - tmp12;
|
||||
|
||||
/* Odd part */
|
||||
|
||||
z13 = wsptr[5] + wsptr[3];
|
||||
z10 = wsptr[5] - wsptr[3];
|
||||
z11 = wsptr[1] + wsptr[7];
|
||||
z12 = wsptr[1] - wsptr[7];
|
||||
|
||||
tmp7 = z11 + z13;
|
||||
tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562);
|
||||
|
||||
z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
|
||||
tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
|
||||
tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
|
||||
|
||||
tmp6 = tmp12 - tmp7;
|
||||
tmp5 = tmp11 - tmp6;
|
||||
tmp4 = tmp10 + tmp5;
|
||||
|
||||
/* Final output stage: scale down by a factor of 8 and range-limit */
|
||||
|
||||
outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3)
|
||||
& RANGE_MASK];
|
||||
outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3)
|
||||
& RANGE_MASK];
|
||||
outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3)
|
||||
& RANGE_MASK];
|
||||
outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3)
|
||||
& RANGE_MASK];
|
||||
outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3)
|
||||
& RANGE_MASK];
|
||||
outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3)
|
||||
& RANGE_MASK];
|
||||
outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3)
|
||||
& RANGE_MASK];
|
||||
outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3)
|
||||
& RANGE_MASK];
|
||||
|
||||
wsptr += DCTSIZE; /* advance pointer to next row */
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DCT_FLOAT_SUPPORTED */
|
||||
91
RenderDll/Common/Textures/Image/jpeg6/jinclude.h
Normal file
91
RenderDll/Common/Textures/Image/jpeg6/jinclude.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* jinclude.h
|
||||
*
|
||||
* Copyright (C) 1991-1994, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file exists to provide a single place to fix any problems with
|
||||
* including the wrong system include files. (Common problems are taken
|
||||
* care of by the standard jconfig symbols, but on really weird systems
|
||||
* you may have to edit this file.)
|
||||
*
|
||||
* NOTE: this file is NOT intended to be included by applications using the
|
||||
* JPEG library. Most applications need only include jpeglib.h.
|
||||
*/
|
||||
|
||||
|
||||
/* Include auto-config file to find out which system include files we need. */
|
||||
|
||||
#include "jconfig.h" /* auto configuration options */
|
||||
#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */
|
||||
|
||||
/*
|
||||
* We need the NULL macro and size_t typedef.
|
||||
* On an ANSI-conforming system it is sufficient to include <stddef.h>.
|
||||
* Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to
|
||||
* pull in <sys/types.h> as well.
|
||||
* Note that the core JPEG library does not require <stdio.h>;
|
||||
* only the default error handler and data source/destination modules do.
|
||||
* But we must pull it in because of the references to FILE in jpeglib.h.
|
||||
* You can remove those references if you want to compile without <stdio.h>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_STDDEF_H
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef NEED_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* We need memory copying and zeroing functions, plus strncpy().
|
||||
* ANSI and System V implementations declare these in <string.h>.
|
||||
* BSD doesn't have the mem() functions, but it does have bcopy()/bzero().
|
||||
* Some systems may declare memset and memcpy in <memory.h>.
|
||||
*
|
||||
* NOTE: we assume the size parameters to these functions are of type size_t.
|
||||
* Change the casts in these macros if not!
|
||||
*/
|
||||
|
||||
#ifdef NEED_BSD_STRINGS
|
||||
|
||||
#include <strings.h>
|
||||
#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size))
|
||||
#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size))
|
||||
|
||||
#else /* not BSD, assume ANSI/SysV string lib */
|
||||
|
||||
#include <string.h>
|
||||
#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
|
||||
#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In ANSI C, and indeed any rational implementation, size_t is also the
|
||||
* type returned by sizeof(). However, it seems there are some irrational
|
||||
* implementations out there, in which sizeof() returns an int even though
|
||||
* size_t is defined as long or unsigned long. To ensure consistent results
|
||||
* we always use this SIZEOF() macro in place of using sizeof() directly.
|
||||
*/
|
||||
|
||||
#define SIZEOF(object) ((size_t) sizeof(object))
|
||||
|
||||
/*
|
||||
* The modules that use fread() and fwrite() always invoke them through
|
||||
* these macros. On some systems you may need to twiddle the argument casts.
|
||||
* CAUTION: argument order is different from underlying functions!
|
||||
*/
|
||||
|
||||
#define JFREAD(file,buf,sizeofbuf) \
|
||||
((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
|
||||
#define JFWRITE(file,buf,sizeofbuf) \
|
||||
((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
|
||||
1117
RenderDll/Common/Textures/Image/jpeg6/jmemmgr.cpp
Normal file
1117
RenderDll/Common/Textures/Image/jpeg6/jmemmgr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
103
RenderDll/Common/Textures/Image/jpeg6/jmemnobs.cpp
Normal file
103
RenderDll/Common/Textures/Image/jpeg6/jmemnobs.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* jmemnobs.c
|
||||
*
|
||||
* Copyright (C) 1992-1994, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file provides a really simple implementation of the system-
|
||||
* dependent portion of the JPEG memory manager. This implementation
|
||||
* assumes that no backing-store files are needed: all required space
|
||||
* can be obtained from ri.Malloc().
|
||||
* This is very portable in the sense that it'll compile on almost anything,
|
||||
* but you'd better have lots of main memory (or virtual memory) if you want
|
||||
* to process big images.
|
||||
* Note that the max_memory_to_use option is ignored by this implementation.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jmemsys.h" /* import the system-dependent declarations */
|
||||
|
||||
/*
|
||||
* Memory allocation and ri.Freeing are controlled by the regular library
|
||||
* routines ri.Malloc() and ri.Free().
|
||||
*/
|
||||
|
||||
GLOBAL void *
|
||||
my_jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
|
||||
{
|
||||
return (void *) malloc(sizeofobject);
|
||||
}
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
|
||||
{
|
||||
free(object);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* "Large" objects are treated the same as "small" ones.
|
||||
* NB: although we include FAR keywords in the routine declarations,
|
||||
* this file won't actually work in 80x86 small/medium model; at least,
|
||||
* you probably won't be able to process useful-size images in only 64KB.
|
||||
*/
|
||||
|
||||
GLOBAL void FAR *
|
||||
my_jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
|
||||
{
|
||||
return (void FAR *) malloc(sizeofobject);
|
||||
}
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
|
||||
{
|
||||
free(object);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine computes the total memory space available for allocation.
|
||||
* Here we always say, "we got all you want bud!"
|
||||
*/
|
||||
|
||||
GLOBAL long
|
||||
my_jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
|
||||
long max_bytes_needed, long already_allocated)
|
||||
{
|
||||
return max_bytes_needed;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Backing store (temporary file) management.
|
||||
* Since jpeg_mem_available always promised the moon,
|
||||
* this should never be called and we can just error out.
|
||||
*/
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
long total_bytes_needed)
|
||||
{
|
||||
ERREXIT(cinfo, JERR_NO_BACKING_STORE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* These routines take care of any system-dependent initialization and
|
||||
* cleanup required. Here, there isn't any.
|
||||
*/
|
||||
|
||||
GLOBAL long
|
||||
my_jpeg_mem_init (j_common_ptr cinfo)
|
||||
{
|
||||
return 0; /* just set max_memory_to_use to 0 */
|
||||
}
|
||||
|
||||
GLOBAL void
|
||||
my_jpeg_mem_term (j_common_ptr cinfo)
|
||||
{
|
||||
/* no work */
|
||||
}
|
||||
182
RenderDll/Common/Textures/Image/jpeg6/jmemsys.h
Normal file
182
RenderDll/Common/Textures/Image/jpeg6/jmemsys.h
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* jmemsys.h
|
||||
*
|
||||
* Copyright (C) 1992-1994, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This include file defines the interface between the system-independent
|
||||
* and system-dependent portions of the JPEG memory manager. No other
|
||||
* modules need include it. (The system-independent portion is jmemmgr.c;
|
||||
* there are several different versions of the system-dependent portion.)
|
||||
*
|
||||
* This file works as-is for the system-dependent memory managers supplied
|
||||
* in the IJG distribution. You may need to modify it if you write a
|
||||
* custom memory manager. If system-dependent changes are needed in
|
||||
* this file, the best method is to #ifdef them based on a configuration
|
||||
* symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR.
|
||||
*/
|
||||
|
||||
|
||||
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||
|
||||
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||
#define my_jpeg_get_small jGetSmall
|
||||
#define my_jpeg_free_small jFreeSmall
|
||||
#define my_jpeg_get_large jGetLarge
|
||||
#define my_jpeg_free_large jFreeLarge
|
||||
#define my_jpeg_mem_available jMemAvail
|
||||
#define my_jpeg_open_backing_store jOpenBackStore
|
||||
#define my_jpeg_mem_init jMemInit
|
||||
#define my_jpeg_mem_term jMemTerm
|
||||
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||
|
||||
|
||||
/*
|
||||
* These two functions are used to allocate and release small chunks of
|
||||
* memory. (Typically the total amount requested through jpeg_get_small is
|
||||
* no more than 20K or so; this will be requested in chunks of a few K each.)
|
||||
* Behavior should be the same as for the standard library functions malloc
|
||||
* and free; in particular, jpeg_get_small must return NULL on failure.
|
||||
* On most systems, these ARE malloc and free. jpeg_free_small is passed the
|
||||
* size of the object being freed, just in case it's needed.
|
||||
* On an 80x86 machine using small-data memory model, these manage near heap.
|
||||
*/
|
||||
|
||||
EXTERN void * my_jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject));
|
||||
EXTERN void my_jpeg_free_small JPP((j_common_ptr cinfo, void * object,
|
||||
size_t sizeofobject));
|
||||
|
||||
/*
|
||||
* These two functions are used to allocate and release large chunks of
|
||||
* memory (up to the total free space designated by jpeg_mem_available).
|
||||
* The interface is the same as above, except that on an 80x86 machine,
|
||||
* far pointers are used. On most other machines these are identical to
|
||||
* the jpeg_get/free_small routines; but we keep them separate anyway,
|
||||
* in case a different allocation strategy is desirable for large chunks.
|
||||
*/
|
||||
|
||||
EXTERN void FAR * my_jpeg_get_large JPP((j_common_ptr cinfo,size_t sizeofobject));
|
||||
EXTERN void my_jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object,
|
||||
size_t sizeofobject));
|
||||
|
||||
/*
|
||||
* The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may
|
||||
* be requested in a single call to jpeg_get_large (and jpeg_get_small for that
|
||||
* matter, but that case should never come into play). This macro is needed
|
||||
* to model the 64Kb-segment-size limit of far addressing on 80x86 machines.
|
||||
* On those machines, we expect that jconfig.h will provide a proper value.
|
||||
* On machines with 32-bit flat address spaces, any large constant may be used.
|
||||
*
|
||||
* NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type
|
||||
* size_t and will be a multiple of sizeof(align_type).
|
||||
*/
|
||||
|
||||
#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */
|
||||
#define MAX_ALLOC_CHUNK 1000000000L
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This routine computes the total space still available for allocation by
|
||||
* jpeg_get_large. If more space than this is needed, backing store will be
|
||||
* used. NOTE: any memory already allocated must not be counted.
|
||||
*
|
||||
* There is a minimum space requirement, corresponding to the minimum
|
||||
* feasible buffer sizes; jmemmgr.c will request that much space even if
|
||||
* jpeg_mem_available returns zero. The maximum space needed, enough to hold
|
||||
* all working storage in memory, is also passed in case it is useful.
|
||||
* Finally, the total space already allocated is passed. If no better
|
||||
* method is available, cinfo->mem->max_memory_to_use - already_allocated
|
||||
* is often a suitable calculation.
|
||||
*
|
||||
* It is OK for jpeg_mem_available to underestimate the space available
|
||||
* (that'll just lead to more backing-store access than is really necessary).
|
||||
* However, an overestimate will lead to failure. Hence it's wise to subtract
|
||||
* a slop factor from the true available space. 5% should be enough.
|
||||
*
|
||||
* On machines with lots of virtual memory, any large constant may be returned.
|
||||
* Conversely, zero may be returned to always use the minimum amount of memory.
|
||||
*/
|
||||
|
||||
EXTERN long my_jpeg_mem_available JPP((j_common_ptr cinfo,
|
||||
long min_bytes_needed,
|
||||
long max_bytes_needed,
|
||||
long already_allocated));
|
||||
|
||||
|
||||
/*
|
||||
* This structure holds whatever state is needed to access a single
|
||||
* backing-store object. The read/write/close method pointers are called
|
||||
* by jmemmgr.c to manipulate the backing-store object; all other fields
|
||||
* are private to the system-dependent backing store routines.
|
||||
*/
|
||||
|
||||
#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */
|
||||
|
||||
#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */
|
||||
|
||||
typedef unsigned short XMSH; /* type of extended-memory handles */
|
||||
typedef unsigned short EMSH; /* type of expanded-memory handles */
|
||||
|
||||
typedef union {
|
||||
short file_handle; /* DOS file handle if it's a temp file */
|
||||
XMSH xms_handle; /* handle if it's a chunk of XMS */
|
||||
EMSH ems_handle; /* handle if it's a chunk of EMS */
|
||||
} handle_union;
|
||||
|
||||
#endif /* USE_MSDOS_MEMMGR */
|
||||
|
||||
typedef struct backing_store_struct * backing_store_ptr;
|
||||
|
||||
typedef struct backing_store_struct {
|
||||
/* Methods for reading/writing/closing this backing-store object */
|
||||
JMETHOD(void, read_backing_store, (j_common_ptr cinfo,
|
||||
backing_store_ptr info,
|
||||
void FAR * buffer_address,
|
||||
long file_offset, long byte_count));
|
||||
JMETHOD(void, write_backing_store, (j_common_ptr cinfo,
|
||||
backing_store_ptr info,
|
||||
void FAR * buffer_address,
|
||||
long file_offset, long byte_count));
|
||||
JMETHOD(void, close_backing_store, (j_common_ptr cinfo,
|
||||
backing_store_ptr info));
|
||||
|
||||
/* Private fields for system-dependent backing-store management */
|
||||
#ifdef USE_MSDOS_MEMMGR
|
||||
/* For the MS-DOS manager (jmemdos.c), we need: */
|
||||
handle_union handle; /* reference to backing-store storage object */
|
||||
char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */
|
||||
#else
|
||||
/* For a typical implementation with temp files, we need: */
|
||||
FILE * temp_file; /* stdio reference to temp file */
|
||||
char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */
|
||||
#endif
|
||||
} backing_store_info;
|
||||
|
||||
/*
|
||||
* Initial opening of a backing-store object. This must fill in the
|
||||
* read/write/close pointers in the object. The read/write routines
|
||||
* may take an error exit if the specified maximum file size is exceeded.
|
||||
* (If jpeg_mem_available always returns a large value, this routine can
|
||||
* just take an error exit.)
|
||||
*/
|
||||
|
||||
EXTERN void my_jpeg_open_backing_store JPP((j_common_ptr cinfo,
|
||||
backing_store_ptr info,
|
||||
long total_bytes_needed));
|
||||
|
||||
|
||||
/*
|
||||
* These routines take care of any system-dependent initialization and
|
||||
* cleanup required. jpeg_mem_init will be called before anything is
|
||||
* allocated (and, therefore, nothing in cinfo is of use except the error
|
||||
* manager pointer). It should return a suitable default value for
|
||||
* max_memory_to_use; this may subsequently be overridden by the surrounding
|
||||
* application. (Note that max_memory_to_use is only important if
|
||||
* jpeg_mem_available chooses to consult it ... no one else will.)
|
||||
* jpeg_mem_term may assume that all requested memory has been freed and that
|
||||
* all opened backing-store objects have been closed.
|
||||
*/
|
||||
|
||||
EXTERN long my_jpeg_mem_init JPP((j_common_ptr cinfo));
|
||||
EXTERN void my_jpeg_mem_term JPP((j_common_ptr cinfo));
|
||||
346
RenderDll/Common/Textures/Image/jpeg6/jmorecfg.h
Normal file
346
RenderDll/Common/Textures/Image/jpeg6/jmorecfg.h
Normal file
@@ -0,0 +1,346 @@
|
||||
/*
|
||||
* jmorecfg.h
|
||||
*
|
||||
* Copyright (C) 1991-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains additional configuration options that customize the
|
||||
* JPEG software for special applications or support machine-dependent
|
||||
* optimizations. Most users will not need to touch this file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Define BITS_IN_JSAMPLE as either
|
||||
* 8 for 8-bit sample values (the usual setting)
|
||||
* 12 for 12-bit sample values
|
||||
* Only 8 and 12 are legal data precisions for lossy JPEG according to the
|
||||
* JPEG standard, and the IJG code does not support anything else!
|
||||
* We do not support run-time selection of data precision, sorry.
|
||||
*/
|
||||
|
||||
#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */
|
||||
|
||||
|
||||
/*
|
||||
* Maximum number of components (color channels) allowed in JPEG image.
|
||||
* To meet the letter of the JPEG spec, set this to 255. However, darn
|
||||
* few applications need more than 4 channels (maybe 5 for CMYK + alpha
|
||||
* mask). We recommend 10 as a reasonable compromise; use 4 if you are
|
||||
* really short on memory. (Each allowed component costs a hundred or so
|
||||
* bytes of storage, whether actually used in an image or not.)
|
||||
*/
|
||||
|
||||
#define MAX_COMPONENTS 10 /* maximum number of image components */
|
||||
|
||||
|
||||
/*
|
||||
* Basic data types.
|
||||
* You may need to change these if you have a machine with unusual data
|
||||
* type sizes; for example, "char" not 8 bits, "short" not 16 bits,
|
||||
* or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits,
|
||||
* but it had better be at least 16.
|
||||
*/
|
||||
|
||||
/* Representation of a single sample (pixel element value).
|
||||
* We frequently allocate large arrays of these, so it's important to keep
|
||||
* them small. But if you have memory to burn and access to char or short
|
||||
* arrays is very slow on your hardware, you might want to change these.
|
||||
*/
|
||||
|
||||
#if BITS_IN_JSAMPLE == 8
|
||||
/* JSAMPLE should be the smallest type that will hold the values 0..255.
|
||||
* You can use a signed char by having GETJSAMPLE mask it with 0xFF.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_UNSIGNED_CHAR
|
||||
|
||||
typedef unsigned char JSAMPLE;
|
||||
#define GETJSAMPLE(value) ((int) (value))
|
||||
|
||||
#else /* not HAVE_UNSIGNED_CHAR */
|
||||
|
||||
typedef char JSAMPLE;
|
||||
#ifdef CHAR_IS_UNSIGNED
|
||||
#define GETJSAMPLE(value) ((int) (value))
|
||||
#else
|
||||
#define GETJSAMPLE(value) ((int) (value) & 0xFF)
|
||||
#endif /* CHAR_IS_UNSIGNED */
|
||||
|
||||
#endif /* HAVE_UNSIGNED_CHAR */
|
||||
|
||||
#define MAXJSAMPLE 255
|
||||
#define CENTERJSAMPLE 128
|
||||
|
||||
#endif /* BITS_IN_JSAMPLE == 8 */
|
||||
|
||||
|
||||
#if BITS_IN_JSAMPLE == 12
|
||||
/* JSAMPLE should be the smallest type that will hold the values 0..4095.
|
||||
* On nearly all machines "short" will do nicely.
|
||||
*/
|
||||
|
||||
typedef short JSAMPLE;
|
||||
#define GETJSAMPLE(value) ((int) (value))
|
||||
|
||||
#define MAXJSAMPLE 4095
|
||||
#define CENTERJSAMPLE 2048
|
||||
|
||||
#endif /* BITS_IN_JSAMPLE == 12 */
|
||||
|
||||
|
||||
/* Representation of a DCT frequency coefficient.
|
||||
* This should be a signed value of at least 16 bits; "short" is usually OK.
|
||||
* Again, we allocate large arrays of these, but you can change to int
|
||||
* if you have memory to burn and "short" is really slow.
|
||||
*/
|
||||
|
||||
typedef short JCOEF;
|
||||
|
||||
|
||||
/* Compressed datastreams are represented as arrays of JOCTET.
|
||||
* These must be EXACTLY 8 bits wide, at least once they are written to
|
||||
* external storage. Note that when using the stdio data source/destination
|
||||
* managers, this is also the data type passed to fread/fwrite.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_UNSIGNED_CHAR
|
||||
|
||||
typedef unsigned char JOCTET;
|
||||
#define GETJOCTET(value) (value)
|
||||
|
||||
#else /* not HAVE_UNSIGNED_CHAR */
|
||||
|
||||
typedef char JOCTET;
|
||||
#ifdef CHAR_IS_UNSIGNED
|
||||
#define GETJOCTET(value) (value)
|
||||
#else
|
||||
#define GETJOCTET(value) ((value) & 0xFF)
|
||||
#endif /* CHAR_IS_UNSIGNED */
|
||||
|
||||
#endif /* HAVE_UNSIGNED_CHAR */
|
||||
|
||||
|
||||
/* These typedefs are used for various table entries and so forth.
|
||||
* They must be at least as wide as specified; but making them too big
|
||||
* won't cost a huge amount of memory, so we don't provide special
|
||||
* extraction code like we did for JSAMPLE. (In other words, these
|
||||
* typedefs live at a different point on the speed/space tradeoff curve.)
|
||||
*/
|
||||
|
||||
/* UINT8 must hold at least the values 0..255. */
|
||||
|
||||
#ifdef HAVE_UNSIGNED_CHAR
|
||||
typedef unsigned char UINT8;
|
||||
#else /* not HAVE_UNSIGNED_CHAR */
|
||||
#ifdef CHAR_IS_UNSIGNED
|
||||
typedef char UINT8;
|
||||
#else /* not CHAR_IS_UNSIGNED */
|
||||
typedef short UINT8;
|
||||
#endif /* CHAR_IS_UNSIGNED */
|
||||
#endif /* HAVE_UNSIGNED_CHAR */
|
||||
|
||||
/* UINT16 must hold at least the values 0..65535. */
|
||||
|
||||
#ifdef HAVE_UNSIGNED_SHORT
|
||||
typedef unsigned short UINT16;
|
||||
#else /* not HAVE_UNSIGNED_SHORT */
|
||||
typedef unsigned int UINT16;
|
||||
#endif /* HAVE_UNSIGNED_SHORT */
|
||||
|
||||
/* INT16 must hold at least the values -32768..32767. */
|
||||
|
||||
#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */
|
||||
typedef short INT16;
|
||||
#endif
|
||||
|
||||
/* INT32 must hold at least signed 32-bit values. */
|
||||
|
||||
//#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
|
||||
//typedef long INT32;
|
||||
//#endif
|
||||
|
||||
/* Datatype used for image dimensions. The JPEG standard only supports
|
||||
* images up to 64K*64K due to 16-bit fields in SOF markers. Therefore
|
||||
* "unsigned int" is sufficient on all machines. However, if you need to
|
||||
* handle larger images and you don't mind deviating from the spec, you
|
||||
* can change this datatype.
|
||||
*/
|
||||
|
||||
typedef unsigned int JDIMENSION;
|
||||
|
||||
#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */
|
||||
|
||||
|
||||
/* These defines are used in all function definitions and extern declarations.
|
||||
* You could modify them if you need to change function linkage conventions.
|
||||
* Another application is to make all functions global for use with debuggers
|
||||
* or code profilers that require it.
|
||||
*/
|
||||
|
||||
#define METHODDEF static /* a function called through method pointers */
|
||||
#define LOCAL static /* a function used only in its module */
|
||||
#define GLOBAL /* a function referenced thru EXTERNs */
|
||||
#define EXTERN extern /* a reference to a GLOBAL function */
|
||||
|
||||
|
||||
/* Here is the pseudo-keyword for declaring pointers that must be "far"
|
||||
* on 80x86 machines. Most of the specialized coding for 80x86 is handled
|
||||
* by just saying "FAR *" where such a pointer is needed. In a few places
|
||||
* explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol.
|
||||
*/
|
||||
|
||||
#ifdef NEED_FAR_POINTERS
|
||||
#undef FAR
|
||||
#define FAR far
|
||||
#else
|
||||
#undef FAR
|
||||
#define FAR
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* On a few systems, type boolean and/or its values FALSE, TRUE may appear
|
||||
* in standard header files. Or you may have conflicts with application-
|
||||
* specific header files that you want to include together with these files.
|
||||
* Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
|
||||
*/
|
||||
|
||||
//#ifndef HAVE_BOOLEAN
|
||||
//typedef int boolean;
|
||||
//#endif
|
||||
#ifndef FALSE /* in case these macros already exist */
|
||||
#define FALSE 0 /* values of boolean */
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* The remaining options affect code selection within the JPEG library,
|
||||
* but they don't need to be visible to most applications using the library.
|
||||
* To minimize application namespace pollution, the symbols won't be
|
||||
* defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined.
|
||||
*/
|
||||
|
||||
#ifdef JPEG_INTERNALS
|
||||
#define JPEG_INTERNAL_OPTIONS
|
||||
#endif
|
||||
|
||||
#ifdef JPEG_INTERNAL_OPTIONS
|
||||
|
||||
|
||||
/*
|
||||
* These defines indicate whether to include various optional functions.
|
||||
* Undefining some of these symbols will produce a smaller but less capable
|
||||
* library. Note that you can leave certain source files out of the
|
||||
* compilation/linking process if you've #undef'd the corresponding symbols.
|
||||
* (You may HAVE to do that if your compiler doesn't like null source files.)
|
||||
*/
|
||||
|
||||
/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */
|
||||
|
||||
/* Capability options common to encoder and decoder: */
|
||||
|
||||
#undef DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */
|
||||
#undef DCT_IFAST_SUPPORTED /* faster, less accurate integer method */
|
||||
#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */
|
||||
|
||||
/* Encoder capability options: */
|
||||
|
||||
#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
|
||||
#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
|
||||
#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
|
||||
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
|
||||
/* Note: if you selected 12-bit data precision, it is dangerous to turn off
|
||||
* ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
|
||||
* precision, so jchuff.c normally uses entropy optimization to compute
|
||||
* usable tables for higher precision. If you don't want to do optimization,
|
||||
* you'll have to supply different default Huffman tables.
|
||||
* The exact same statements apply for progressive JPEG: the default tables
|
||||
* don't work for progressive mode. (This may get fixed, however.)
|
||||
*/
|
||||
#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */
|
||||
|
||||
/* Decoder capability options: */
|
||||
|
||||
#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
|
||||
#undef D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
|
||||
#undef D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
|
||||
#undef BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */
|
||||
#undef IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */
|
||||
#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */
|
||||
#undef UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */
|
||||
#undef QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */
|
||||
#undef QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */
|
||||
|
||||
/* more capability options later, no doubt */
|
||||
|
||||
|
||||
/*
|
||||
* Ordering of RGB data in scanlines passed to or from the application.
|
||||
* If your application wants to deal with data in the order B,G,R, just
|
||||
* change these macros. You can also deal with formats such as R,G,B,X
|
||||
* (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing
|
||||
* the offsets will also change the order in which colormap data is organized.
|
||||
* RESTRICTIONS:
|
||||
* 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats.
|
||||
* 2. These macros only affect RGB<=>YCbCr color conversion, so they are not
|
||||
* useful if you are using JPEG color spaces other than YCbCr or grayscale.
|
||||
* 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE
|
||||
* is not 3 (they don't understand about dummy color components!). So you
|
||||
* can't use color quantization if you change that value.
|
||||
*/
|
||||
|
||||
#define RGB_RED 0 /* Offset of Red in an RGB scanline element */
|
||||
#define RGB_GREEN 1 /* Offset of Green */
|
||||
#define RGB_BLUE 2 /* Offset of Blue */
|
||||
#define RGB_PIXELSIZE 4 /* JSAMPLEs per RGB scanline element */
|
||||
|
||||
|
||||
/* Definitions for speed-related optimizations. */
|
||||
|
||||
|
||||
/* If your compiler supports inline functions, define INLINE
|
||||
* as the inline keyword; otherwise define it as empty.
|
||||
*/
|
||||
|
||||
#ifndef INLINE
|
||||
#ifdef __GNUC__ /* for instance, GNU C knows about inline */
|
||||
#define INLINE __inline__
|
||||
#endif
|
||||
#ifndef INLINE
|
||||
#define INLINE /* default is to define it as empty */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying
|
||||
* two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER
|
||||
* as short on such a machine. MULTIPLIER must be at least 16 bits wide.
|
||||
*/
|
||||
|
||||
#ifndef MULTIPLIER
|
||||
#define MULTIPLIER int /* type for fastest integer multiply */
|
||||
#endif
|
||||
|
||||
|
||||
/* FAST_FLOAT should be either float or double, whichever is done faster
|
||||
* by your compiler. (Note that this type is only used in the floating point
|
||||
* DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.)
|
||||
* Typically, float is faster in ANSI C compilers, while double is faster in
|
||||
* pre-ANSI compilers (because they insist on converting to double anyway).
|
||||
* The code below therefore chooses float if we have ANSI-style prototypes.
|
||||
*/
|
||||
|
||||
#ifndef FAST_FLOAT
|
||||
#ifdef HAVE_PROTOTYPES
|
||||
#define FAST_FLOAT float
|
||||
#else
|
||||
#define FAST_FLOAT double
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* JPEG_INTERNAL_OPTIONS */
|
||||
388
RenderDll/Common/Textures/Image/jpeg6/jpegint.h
Normal file
388
RenderDll/Common/Textures/Image/jpeg6/jpegint.h
Normal file
@@ -0,0 +1,388 @@
|
||||
/*
|
||||
* jpegint.h
|
||||
*
|
||||
* Copyright (C) 1991-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file provides common declarations for the various JPEG modules.
|
||||
* These declarations are considered internal to the JPEG library; most
|
||||
* applications using the library shouldn't need to include this file.
|
||||
*/
|
||||
|
||||
|
||||
/* Declarations for both compression & decompression */
|
||||
|
||||
typedef enum { /* Operating modes for buffer controllers */
|
||||
JBUF_PASS_THRU, /* Plain stripwise operation */
|
||||
/* Remaining modes require a full-image buffer to have been created */
|
||||
JBUF_SAVE_SOURCE, /* Run source subobject only, save output */
|
||||
JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */
|
||||
JBUF_SAVE_AND_PASS /* Run both subobjects, save output */
|
||||
} J_BUF_MODE;
|
||||
|
||||
/* Values of global_state field (jdapi.c has some dependencies on ordering!) */
|
||||
#define CSTATE_START 100 /* after create_compress */
|
||||
#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */
|
||||
#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */
|
||||
#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */
|
||||
#define DSTATE_START 200 /* after create_decompress */
|
||||
#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */
|
||||
#define DSTATE_READY 202 /* found SOS, ready for start_decompress */
|
||||
#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/
|
||||
#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */
|
||||
#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */
|
||||
#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */
|
||||
#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */
|
||||
#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */
|
||||
#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */
|
||||
#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */
|
||||
|
||||
|
||||
/* Declarations for compression modules */
|
||||
|
||||
/* Master control module */
|
||||
struct jpeg_comp_master {
|
||||
JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, pass_startup, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
|
||||
|
||||
/* State variables made visible to other modules */
|
||||
boolean call_pass_startup; /* True if pass_startup must be called */
|
||||
boolean is_last_pass; /* True during last pass */
|
||||
};
|
||||
|
||||
/* Main buffer control (downsampled-data buffer) */
|
||||
struct jpeg_c_main_controller {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, process_data, (j_compress_ptr cinfo,
|
||||
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
|
||||
JDIMENSION in_rows_avail));
|
||||
};
|
||||
|
||||
/* Compression preprocessing (downsampling input buffer control) */
|
||||
struct jpeg_c_prep_controller {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, pre_process_data, (j_compress_ptr cinfo,
|
||||
JSAMPARRAY input_buf,
|
||||
JDIMENSION *in_row_ctr,
|
||||
JDIMENSION in_rows_avail,
|
||||
JSAMPIMAGE output_buf,
|
||||
JDIMENSION *out_row_group_ctr,
|
||||
JDIMENSION out_row_groups_avail));
|
||||
};
|
||||
|
||||
/* Coefficient buffer control */
|
||||
struct jpeg_c_coef_controller {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(boolean, compress_data, (j_compress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf));
|
||||
};
|
||||
|
||||
/* Colorspace conversion */
|
||||
struct jpeg_color_converter {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, color_convert, (j_compress_ptr cinfo,
|
||||
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
|
||||
JDIMENSION output_row, int num_rows));
|
||||
};
|
||||
|
||||
/* Downsampling */
|
||||
struct jpeg_downsampler {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, downsample, (j_compress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION in_row_index,
|
||||
JSAMPIMAGE output_buf,
|
||||
JDIMENSION out_row_group_index));
|
||||
|
||||
boolean need_context_rows; /* TRUE if need rows above & below */
|
||||
};
|
||||
|
||||
/* Forward DCT (also controls coefficient quantization) */
|
||||
struct jpeg_forward_dct {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
|
||||
/* perhaps this should be an array??? */
|
||||
JMETHOD(void, forward_DCT, (j_compress_ptr cinfo,
|
||||
jpeg_component_info * compptr,
|
||||
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
|
||||
JDIMENSION start_row, JDIMENSION start_col,
|
||||
JDIMENSION num_blocks));
|
||||
};
|
||||
|
||||
/* Entropy encoding */
|
||||
struct jpeg_entropy_encoder {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics));
|
||||
JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data));
|
||||
JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
|
||||
};
|
||||
|
||||
/* Marker writing */
|
||||
struct jpeg_marker_writer {
|
||||
/* write_any_marker is exported for use by applications */
|
||||
/* Probably only COM and APPn markers should be written */
|
||||
JMETHOD(void, write_any_marker, (j_compress_ptr cinfo, int marker,
|
||||
const JOCTET *dataptr, unsigned int datalen));
|
||||
JMETHOD(void, write_file_header, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_frame_header, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_scan_header, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_tables_only, (j_compress_ptr cinfo));
|
||||
};
|
||||
|
||||
|
||||
/* Declarations for decompression modules */
|
||||
|
||||
/* Master control module */
|
||||
struct jpeg_decomp_master {
|
||||
JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo));
|
||||
|
||||
/* State variables made visible to other modules */
|
||||
boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */
|
||||
};
|
||||
|
||||
/* Input control module */
|
||||
struct jpeg_input_controller {
|
||||
JMETHOD(int, consume_input, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo));
|
||||
|
||||
/* State variables made visible to other modules */
|
||||
boolean has_multiple_scans; /* True if file has multiple scans */
|
||||
boolean eoi_reached; /* True when EOI has been consumed */
|
||||
};
|
||||
|
||||
/* Main buffer control (downsampled-data buffer) */
|
||||
struct jpeg_d_main_controller {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, process_data, (j_decompress_ptr cinfo,
|
||||
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail));
|
||||
};
|
||||
|
||||
/* Coefficient buffer control */
|
||||
struct jpeg_d_coef_controller {
|
||||
JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(int, consume_data, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(int, decompress_data, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE output_buf));
|
||||
/* Pointer to array of coefficient virtual arrays, or NULL if none */
|
||||
jvirt_barray_ptr *coef_arrays;
|
||||
};
|
||||
|
||||
/* Decompression postprocessing (color quantization buffer control) */
|
||||
struct jpeg_d_post_controller {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, post_process_data, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf,
|
||||
JDIMENSION *in_row_group_ctr,
|
||||
JDIMENSION in_row_groups_avail,
|
||||
JSAMPARRAY output_buf,
|
||||
JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail));
|
||||
};
|
||||
|
||||
/* Marker reading & parsing */
|
||||
struct jpeg_marker_reader {
|
||||
JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo));
|
||||
/* Read markers until SOS or EOI.
|
||||
* Returns same codes as are defined for jpeg_consume_input:
|
||||
* JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
|
||||
*/
|
||||
JMETHOD(int, read_markers, (j_decompress_ptr cinfo));
|
||||
/* Read a restart marker --- exported for use by entropy decoder only */
|
||||
jpeg_marker_parser_method read_restart_marker;
|
||||
/* Application-overridable marker processing methods */
|
||||
jpeg_marker_parser_method process_COM;
|
||||
jpeg_marker_parser_method process_APPn[16];
|
||||
|
||||
/* State of marker reader --- nominally internal, but applications
|
||||
* supplying COM or APPn handlers might like to know the state.
|
||||
*/
|
||||
boolean saw_SOI; /* found SOI? */
|
||||
boolean saw_SOF; /* found SOF? */
|
||||
int next_restart_num; /* next restart number expected (0-7) */
|
||||
unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */
|
||||
};
|
||||
|
||||
/* Entropy decoding */
|
||||
struct jpeg_entropy_decoder {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo,
|
||||
JBLOCKROW *MCU_data));
|
||||
};
|
||||
|
||||
/* Inverse DCT (also performs dequantization) */
|
||||
typedef JMETHOD(void, inverse_DCT_method_ptr,
|
||||
(j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JCOEFPTR coef_block,
|
||||
JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||
|
||||
struct jpeg_inverse_dct {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
/* It is useful to allow each component to have a separate IDCT method. */
|
||||
inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
|
||||
};
|
||||
|
||||
/* Upsampling (note that upsampler must also call color converter) */
|
||||
struct jpeg_upsampler {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, upsample, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf,
|
||||
JDIMENSION *in_row_group_ctr,
|
||||
JDIMENSION in_row_groups_avail,
|
||||
JSAMPARRAY output_buf,
|
||||
JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail));
|
||||
|
||||
boolean need_context_rows; /* TRUE if need rows above & below */
|
||||
};
|
||||
|
||||
/* Colorspace conversion */
|
||||
struct jpeg_color_deconverter {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, color_convert, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||
JSAMPARRAY output_buf, int num_rows));
|
||||
};
|
||||
|
||||
/* Color quantization or color precision reduction */
|
||||
struct jpeg_color_quantizer {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan));
|
||||
JMETHOD(void, color_quantize, (j_decompress_ptr cinfo,
|
||||
JSAMPARRAY input_buf, JSAMPARRAY output_buf,
|
||||
int num_rows));
|
||||
JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, new_color_map, (j_decompress_ptr cinfo));
|
||||
};
|
||||
|
||||
|
||||
/* Miscellaneous useful macros */
|
||||
|
||||
#undef MAX
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#undef MIN
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
|
||||
/* We assume that right shift corresponds to signed division by 2 with
|
||||
* rounding towards minus infinity. This is correct for typical "arithmetic
|
||||
* shift" instructions that shift in copies of the sign bit. But some
|
||||
* C compilers implement >> with an unsigned shift. For these machines you
|
||||
* must define RIGHT_SHIFT_IS_UNSIGNED.
|
||||
* RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
|
||||
* It is only applied with constant shift counts. SHIFT_TEMPS must be
|
||||
* included in the variables of any routine using RIGHT_SHIFT.
|
||||
*/
|
||||
|
||||
#ifdef RIGHT_SHIFT_IS_UNSIGNED
|
||||
#define SHIFT_TEMPS INT32 shift_temp;
|
||||
#define RIGHT_SHIFT(x,shft) \
|
||||
((shift_temp = (x)) < 0 ? \
|
||||
(shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
|
||||
(shift_temp >> (shft)))
|
||||
#else
|
||||
#define SHIFT_TEMPS
|
||||
#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
|
||||
#endif
|
||||
|
||||
|
||||
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||
|
||||
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||
#define jinit_compress_master jICompress
|
||||
#define jinit_c_master_control jICMaster
|
||||
#define jinit_c_main_controller jICMainC
|
||||
#define jinit_c_prep_controller jICPrepC
|
||||
#define jinit_c_coef_controller jICCoefC
|
||||
#define jinit_color_converter jICColor
|
||||
#define jinit_downsampler jIDownsampler
|
||||
#define jinit_forward_dct jIFDCT
|
||||
#define jinit_huff_encoder jIHEncoder
|
||||
#define jinit_phuff_encoder jIPHEncoder
|
||||
#define jinit_marker_writer jIMWriter
|
||||
#define jinit_master_decompress jIDMaster
|
||||
#define jinit_d_main_controller jIDMainC
|
||||
#define jinit_d_coef_controller jIDCoefC
|
||||
#define jinit_d_post_controller jIDPostC
|
||||
#define jinit_input_controller jIInCtlr
|
||||
#define jinit_marker_reader jIMReader
|
||||
#define jinit_huff_decoder jIHDecoder
|
||||
#define jinit_phuff_decoder jIPHDecoder
|
||||
#define jinit_inverse_dct jIIDCT
|
||||
#define jinit_upsampler jIUpsampler
|
||||
#define jinit_color_deconverter jIDColor
|
||||
#define jinit_1pass_quantizer jI1Quant
|
||||
#define jinit_2pass_quantizer jI2Quant
|
||||
#define jinit_merged_upsampler jIMUpsampler
|
||||
#define jinit_memory_mgr jIMemMgr
|
||||
#define jdiv_round_up jDivRound
|
||||
#define jround_up jRound
|
||||
#define jcopy_sample_rows jCopySamples
|
||||
#define jcopy_block_row jCopyBlocks
|
||||
#define jzero_far jZeroFar
|
||||
#define jpeg_zigzag_order jZIGTable
|
||||
#define jpeg_natural_order jZAGTable
|
||||
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||
|
||||
|
||||
/* Compression module initialization routines */
|
||||
EXTERN void jinit_compress_master JPP((j_compress_ptr cinfo));
|
||||
EXTERN void jinit_c_master_control JPP((j_compress_ptr cinfo,
|
||||
boolean transcode_only));
|
||||
EXTERN void jinit_c_main_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN void jinit_c_prep_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN void jinit_c_coef_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN void jinit_color_converter JPP((j_compress_ptr cinfo));
|
||||
EXTERN void jinit_downsampler JPP((j_compress_ptr cinfo));
|
||||
EXTERN void jinit_forward_dct JPP((j_compress_ptr cinfo));
|
||||
EXTERN void jinit_huff_encoder JPP((j_compress_ptr cinfo));
|
||||
EXTERN void jinit_phuff_encoder JPP((j_compress_ptr cinfo));
|
||||
EXTERN void jinit_marker_writer JPP((j_compress_ptr cinfo));
|
||||
/* Decompression module initialization routines */
|
||||
EXTERN void jinit_master_decompress JPP((j_decompress_ptr cinfo));
|
||||
EXTERN void jinit_d_main_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN void jinit_d_coef_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN void jinit_d_post_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN void jinit_input_controller JPP((j_decompress_ptr cinfo));
|
||||
EXTERN void jinit_marker_reader JPP((j_decompress_ptr cinfo));
|
||||
EXTERN void jinit_huff_decoder JPP((j_decompress_ptr cinfo));
|
||||
EXTERN void jinit_phuff_decoder JPP((j_decompress_ptr cinfo));
|
||||
EXTERN void jinit_inverse_dct JPP((j_decompress_ptr cinfo));
|
||||
EXTERN void jinit_upsampler JPP((j_decompress_ptr cinfo));
|
||||
EXTERN void jinit_color_deconverter JPP((j_decompress_ptr cinfo));
|
||||
EXTERN void jinit_1pass_quantizer JPP((j_decompress_ptr cinfo));
|
||||
EXTERN void jinit_2pass_quantizer JPP((j_decompress_ptr cinfo));
|
||||
EXTERN void jinit_merged_upsampler JPP((j_decompress_ptr cinfo));
|
||||
/* Memory manager initialization */
|
||||
EXTERN void jinit_memory_mgr JPP((j_common_ptr cinfo));
|
||||
|
||||
/* Utility routines in jutils.c */
|
||||
EXTERN long jdiv_round_up JPP((long a, long b));
|
||||
EXTERN long jround_up JPP((long a, long b));
|
||||
EXTERN void jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row,
|
||||
JSAMPARRAY output_array, int dest_row,
|
||||
int num_rows, JDIMENSION num_cols));
|
||||
EXTERN void jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row,
|
||||
JDIMENSION num_blocks));
|
||||
EXTERN void jzero_far JPP((void FAR * target, size_t bytestozero));
|
||||
/* Constant tables in jutils.c */
|
||||
extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */
|
||||
extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */
|
||||
|
||||
/* Suppress undefined-structure complaints if necessary. */
|
||||
|
||||
#ifdef INCOMPLETE_TYPES_BROKEN
|
||||
#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */
|
||||
struct jvirt_sarray_control { long dummy; };
|
||||
struct jvirt_barray_control { long dummy; };
|
||||
#endif
|
||||
#endif /* INCOMPLETE_TYPES_BROKEN */
|
||||
1084
RenderDll/Common/Textures/Image/jpeg6/jpeglib.h
Normal file
1084
RenderDll/Common/Textures/Image/jpeg6/jpeglib.h
Normal file
File diff suppressed because it is too large
Load Diff
175
RenderDll/Common/Textures/Image/jpeg6/jutils.cpp
Normal file
175
RenderDll/Common/Textures/Image/jpeg6/jutils.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* jutils.c
|
||||
*
|
||||
* Copyright (C) 1991-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains tables and miscellaneous utility routines needed
|
||||
* for both compression and decompression.
|
||||
* Note we prefix all global names with "j" to minimize conflicts with
|
||||
* a surrounding application.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
|
||||
/*
|
||||
* jpeg_zigzag_order[i] is the zigzag-order position of the i'th element
|
||||
* of a DCT block read in natural order (left to right, top to bottom).
|
||||
*/
|
||||
|
||||
const int jpeg_zigzag_order[DCTSIZE2] = {
|
||||
0, 1, 5, 6, 14, 15, 27, 28,
|
||||
2, 4, 7, 13, 16, 26, 29, 42,
|
||||
3, 8, 12, 17, 25, 30, 41, 43,
|
||||
9, 11, 18, 24, 31, 40, 44, 53,
|
||||
10, 19, 23, 32, 39, 45, 52, 54,
|
||||
20, 22, 33, 38, 46, 51, 55, 60,
|
||||
21, 34, 37, 47, 50, 56, 59, 61,
|
||||
35, 36, 48, 49, 57, 58, 62, 63
|
||||
};
|
||||
|
||||
/*
|
||||
* jpeg_natural_order[i] is the natural-order position of the i'th element
|
||||
* of zigzag order.
|
||||
*
|
||||
* When reading corrupted data, the Huffman decoders could attempt
|
||||
* to reference an entry beyond the end of this array (if the decoded
|
||||
* zero run length reaches past the end of the block). To prevent
|
||||
* wild stores without adding an inner-loop test, we put some extra
|
||||
* "63"s after the real entries. This will cause the extra coefficient
|
||||
* to be stored in location 63 of the block, not somewhere random.
|
||||
* The worst case would be a run-length of 15, which means we need 16
|
||||
* fake entries.
|
||||
*/
|
||||
|
||||
const int jpeg_natural_order[DCTSIZE2+16] = {
|
||||
0, 1, 8, 16, 9, 2, 3, 10,
|
||||
17, 24, 32, 25, 18, 11, 4, 5,
|
||||
12, 19, 26, 33, 40, 48, 41, 34,
|
||||
27, 20, 13, 6, 7, 14, 21, 28,
|
||||
35, 42, 49, 56, 57, 50, 43, 36,
|
||||
29, 22, 15, 23, 30, 37, 44, 51,
|
||||
58, 59, 52, 45, 38, 31, 39, 46,
|
||||
53, 60, 61, 54, 47, 55, 62, 63,
|
||||
63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */
|
||||
63, 63, 63, 63, 63, 63, 63, 63
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Arithmetic utilities
|
||||
*/
|
||||
|
||||
GLOBAL long
|
||||
jdiv_round_up (long a, long b)
|
||||
/* Compute a/b rounded up to next integer, ie, ceil(a/b) */
|
||||
/* Assumes a >= 0, b > 0 */
|
||||
{
|
||||
return (a + b - 1L) / b;
|
||||
}
|
||||
|
||||
|
||||
GLOBAL long
|
||||
jround_up (long a, long b)
|
||||
/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */
|
||||
/* Assumes a >= 0, b > 0 */
|
||||
{
|
||||
a += b - 1L;
|
||||
return a - (a % b);
|
||||
}
|
||||
|
||||
|
||||
/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays
|
||||
* and coefficient-block arrays. This won't work on 80x86 because the arrays
|
||||
* are FAR and we're assuming a small-pointer memory model. However, some
|
||||
* DOS compilers provide far-pointer versions of memcpy() and memset() even
|
||||
* in the small-model libraries. These will be used if USE_FMEM is defined.
|
||||
* Otherwise, the routines below do it the hard way. (The performance cost
|
||||
* is not all that great, because these routines aren't very heavily used.)
|
||||
*/
|
||||
|
||||
#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */
|
||||
#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size)
|
||||
#define FMEMZERO(target,size) MEMZERO(target,size)
|
||||
#else /* 80x86 case, define if we can */
|
||||
#ifdef USE_FMEM
|
||||
#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size))
|
||||
#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
GLOBAL void
|
||||
jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
|
||||
JSAMPARRAY output_array, int dest_row,
|
||||
int num_rows, JDIMENSION num_cols)
|
||||
/* Copy some rows of samples from one place to another.
|
||||
* num_rows rows are copied from input_array[source_row++]
|
||||
* to output_array[dest_row++]; these areas may overlap for duplication.
|
||||
* The source and destination arrays must be at least as wide as num_cols.
|
||||
*/
|
||||
{
|
||||
register JSAMPROW inptr, outptr;
|
||||
#ifdef FMEMCOPY
|
||||
register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE));
|
||||
#else
|
||||
register JDIMENSION count;
|
||||
#endif
|
||||
register int row;
|
||||
|
||||
input_array += source_row;
|
||||
output_array += dest_row;
|
||||
|
||||
for (row = num_rows; row > 0; row--) {
|
||||
inptr = *input_array++;
|
||||
outptr = *output_array++;
|
||||
#ifdef FMEMCOPY
|
||||
FMEMCOPY(outptr, inptr, count);
|
||||
#else
|
||||
for (count = num_cols; count > 0; count--)
|
||||
*outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GLOBAL void
|
||||
jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row,
|
||||
JDIMENSION num_blocks)
|
||||
/* Copy a row of coefficient blocks from one place to another. */
|
||||
{
|
||||
#ifdef FMEMCOPY
|
||||
FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF)));
|
||||
#else
|
||||
register JCOEFPTR inptr, outptr;
|
||||
register long count;
|
||||
|
||||
inptr = (JCOEFPTR) input_row;
|
||||
outptr = (JCOEFPTR) output_row;
|
||||
for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) {
|
||||
*outptr++ = *inptr++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
GLOBAL void
|
||||
jzero_far (void FAR * target, size_t bytestozero)
|
||||
/* Zero out a chunk of FAR memory. */
|
||||
/* This might be sample-array data, block-array data, or alloc_large data. */
|
||||
{
|
||||
#ifdef FMEMZERO
|
||||
FMEMZERO(target, bytestozero);
|
||||
#else
|
||||
register char FAR * ptr = (char FAR *) target;
|
||||
register size_t count;
|
||||
|
||||
for (count = bytestozero; count > 0; count--) {
|
||||
*ptr++ = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
14
RenderDll/Common/Textures/Image/jpeg6/jversion.h
Normal file
14
RenderDll/Common/Textures/Image/jpeg6/jversion.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* jversion.h
|
||||
*
|
||||
* Copyright (C) 1991-1995, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains software version identification.
|
||||
*/
|
||||
|
||||
|
||||
#define JVERSION "6 2-Aug-95"
|
||||
|
||||
#define JCOPYRIGHT "Copyright (C) 1995, Thomas G. Lane"
|
||||
BIN
RenderDll/Common/Textures/Image/nvDXTlib.lib
Normal file
BIN
RenderDll/Common/Textures/Image/nvDXTlib.lib
Normal file
Binary file not shown.
279
RenderDll/Common/Textures/Image/zlib/zconf.h
Normal file
279
RenderDll/Common/Textures/Image/zlib/zconf.h
Normal file
@@ -0,0 +1,279 @@
|
||||
/* zconf.h -- configuration of the zlib compression library
|
||||
* Copyright (C) 1995-1998 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#ifndef _ZCONF_H
|
||||
#define _ZCONF_H
|
||||
|
||||
/*
|
||||
* If you *really* need a unique prefix for all types and library functions,
|
||||
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
|
||||
*/
|
||||
#ifdef Z_PREFIX
|
||||
# define deflateInit_ z_deflateInit_
|
||||
# define deflate z_deflate
|
||||
# define deflateEnd z_deflateEnd
|
||||
# define inflateInit_ z_inflateInit_
|
||||
# define inflate z_inflate
|
||||
# define inflateEnd z_inflateEnd
|
||||
# define deflateInit2_ z_deflateInit2_
|
||||
# define deflateSetDictionary z_deflateSetDictionary
|
||||
# define deflateCopy z_deflateCopy
|
||||
# define deflateReset z_deflateReset
|
||||
# define deflateParams z_deflateParams
|
||||
# define inflateInit2_ z_inflateInit2_
|
||||
# define inflateSetDictionary z_inflateSetDictionary
|
||||
# define inflateSync z_inflateSync
|
||||
# define inflateSyncPoint z_inflateSyncPoint
|
||||
# define inflateReset z_inflateReset
|
||||
# define compress z_compress
|
||||
# define compress2 z_compress2
|
||||
# define uncompress z_uncompress
|
||||
# define adler32 z_adler32
|
||||
# define crc32 z_crc32
|
||||
# define get_crc_table z_get_crc_table
|
||||
|
||||
# define Byte z_Byte
|
||||
# define uInt z_uInt
|
||||
# define uLong z_uLong
|
||||
# define Bytef z_Bytef
|
||||
# define charf z_charf
|
||||
# define intf z_intf
|
||||
# define uIntf z_uIntf
|
||||
# define uLongf z_uLongf
|
||||
# define voidpf z_voidpf
|
||||
# define voidp z_voidp
|
||||
#endif
|
||||
|
||||
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
|
||||
# define WIN32
|
||||
#endif
|
||||
#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
|
||||
# ifndef __32BIT__
|
||||
# define __32BIT__
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__MSDOS__) && !defined(MSDOS)
|
||||
# define MSDOS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
|
||||
* than 64k bytes at a time (needed on systems with 16-bit int).
|
||||
*/
|
||||
#if defined(MSDOS) && !defined(__32BIT__)
|
||||
# define MAXSEG_64K
|
||||
#endif
|
||||
#ifdef MSDOS
|
||||
# define UNALIGNED_OK
|
||||
#endif
|
||||
|
||||
#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC)
|
||||
# define STDC
|
||||
#endif
|
||||
#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)
|
||||
# ifndef STDC
|
||||
# define STDC
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef STDC
|
||||
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
|
||||
# define const
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Some Mac compilers merge all .h files incorrectly: */
|
||||
#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
|
||||
# define NO_DUMMY_DECL
|
||||
#endif
|
||||
|
||||
/* Old Borland C incorrectly complains about missing returns: */
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
|
||||
# define NEED_DUMMY_RETURN
|
||||
#endif
|
||||
|
||||
|
||||
/* Maximum value for memLevel in deflateInit2 */
|
||||
#ifndef MAX_MEM_LEVEL
|
||||
# ifdef MAXSEG_64K
|
||||
# define MAX_MEM_LEVEL 8
|
||||
# else
|
||||
# define MAX_MEM_LEVEL 9
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
|
||||
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
|
||||
* created by gzip. (Files created by minigzip can still be extracted by
|
||||
* gzip.)
|
||||
*/
|
||||
#ifndef MAX_WBITS
|
||||
# define MAX_WBITS 15 /* 32K LZ77 window */
|
||||
#endif
|
||||
|
||||
/* The memory requirements for deflate are (in bytes):
|
||||
(1 << (windowBits+2)) + (1 << (memLevel+9))
|
||||
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
|
||||
plus a few kilobytes for small objects. For example, if you want to reduce
|
||||
the default memory requirements from 256K to 128K, compile with
|
||||
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
|
||||
Of course this will generally degrade compression (there's no free lunch).
|
||||
|
||||
The memory requirements for inflate are (in bytes) 1 << windowBits
|
||||
that is, 32K for windowBits=15 (default value) plus a few kilobytes
|
||||
for small objects.
|
||||
*/
|
||||
|
||||
/* Type declarations */
|
||||
|
||||
#ifndef OF /* function prototypes */
|
||||
# ifdef STDC
|
||||
# define OF(args) args
|
||||
# else
|
||||
# define OF(args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The following definitions for FAR are needed only for MSDOS mixed
|
||||
* model programming (small or medium model with some far allocations).
|
||||
* This was tested only with MSC; for other MSDOS compilers you may have
|
||||
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
|
||||
* just define FAR to be empty.
|
||||
*/
|
||||
#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
|
||||
/* MSC small or medium model */
|
||||
# define SMALL_MEDIUM
|
||||
# ifdef _MSC_VER
|
||||
# define FAR _far
|
||||
# else
|
||||
# define FAR far
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
|
||||
# ifndef __32BIT__
|
||||
# define SMALL_MEDIUM
|
||||
# define FAR _far
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Compile with -DZLIB_DLL for Windows DLL support */
|
||||
#if defined(ZLIB_DLL)
|
||||
# if defined(_WINDOWS) || defined(WINDOWS)
|
||||
# ifdef FAR
|
||||
# undef FAR
|
||||
# endif
|
||||
# include <windows.h>
|
||||
# define ZEXPORT WINAPI
|
||||
# ifdef WIN32
|
||||
# define ZEXPORTVA WINAPIV
|
||||
# else
|
||||
# define ZEXPORTVA FAR _cdecl _export
|
||||
# endif
|
||||
# endif
|
||||
# if defined (__BORLANDC__)
|
||||
# if (__BORLANDC__ >= 0x0500) && defined (WIN32)
|
||||
# include <windows.h>
|
||||
# define ZEXPORT __declspec(dllexport) WINAPI
|
||||
# define ZEXPORTRVA __declspec(dllexport) WINAPIV
|
||||
# else
|
||||
# if defined (_Windows) && defined (__DLL__)
|
||||
# define ZEXPORT _export
|
||||
# define ZEXPORTVA _export
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (__BEOS__)
|
||||
# if defined (ZLIB_DLL)
|
||||
# define ZEXTERN extern __declspec(dllexport)
|
||||
# else
|
||||
# define ZEXTERN extern __declspec(dllimport)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ZEXPORT
|
||||
# define ZEXPORT
|
||||
#endif
|
||||
#ifndef ZEXPORTVA
|
||||
# define ZEXPORTVA
|
||||
#endif
|
||||
#ifndef ZEXTERN
|
||||
# define ZEXTERN extern
|
||||
#endif
|
||||
|
||||
#ifndef FAR
|
||||
# define FAR
|
||||
#endif
|
||||
|
||||
#if !defined(MACOS) && !defined(TARGET_OS_MAC)
|
||||
typedef unsigned char Byte; /* 8 bits */
|
||||
#endif
|
||||
typedef unsigned int uInt; /* 16 bits or more */
|
||||
typedef unsigned long uLong; /* 32 bits or more */
|
||||
|
||||
#ifdef SMALL_MEDIUM
|
||||
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
|
||||
# define Bytef Byte FAR
|
||||
#else
|
||||
typedef Byte FAR Bytef;
|
||||
#endif
|
||||
typedef char FAR charf;
|
||||
typedef int FAR intf;
|
||||
typedef uInt FAR uIntf;
|
||||
typedef uLong FAR uLongf;
|
||||
|
||||
#ifdef STDC
|
||||
typedef void FAR *voidpf;
|
||||
typedef void *voidp;
|
||||
#else
|
||||
typedef Byte FAR *voidpf;
|
||||
typedef Byte *voidp;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <sys/types.h> /* for off_t */
|
||||
# include <unistd.h> /* for SEEK_* and off_t */
|
||||
# define z_off_t off_t
|
||||
#endif
|
||||
#ifndef SEEK_SET
|
||||
# define SEEK_SET 0 /* Seek from beginning of file. */
|
||||
# define SEEK_CUR 1 /* Seek from current position. */
|
||||
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
|
||||
#endif
|
||||
#ifndef z_off_t
|
||||
# define z_off_t long
|
||||
#endif
|
||||
|
||||
/* MVS linker does not support external names larger than 8 bytes */
|
||||
#if defined(__MVS__)
|
||||
# pragma map(deflateInit_,"DEIN")
|
||||
# pragma map(deflateInit2_,"DEIN2")
|
||||
# pragma map(deflateEnd,"DEEND")
|
||||
# pragma map(inflateInit_,"ININ")
|
||||
# pragma map(inflateInit2_,"ININ2")
|
||||
# pragma map(inflateEnd,"INEND")
|
||||
# pragma map(inflateSync,"INSY")
|
||||
# pragma map(inflateSetDictionary,"INSEDI")
|
||||
# pragma map(inflate_blocks,"INBL")
|
||||
# pragma map(inflate_blocks_new,"INBLNE")
|
||||
# pragma map(inflate_blocks_free,"INBLFR")
|
||||
# pragma map(inflate_blocks_reset,"INBLRE")
|
||||
# pragma map(inflate_codes_free,"INCOFR")
|
||||
# pragma map(inflate_codes,"INCO")
|
||||
# pragma map(inflate_fast,"INFA")
|
||||
# pragma map(inflate_flush,"INFLU")
|
||||
# pragma map(inflate_mask,"INMA")
|
||||
# pragma map(inflate_set_dictionary,"INSEDI2")
|
||||
# pragma map(inflate_copyright,"INCOPY")
|
||||
# pragma map(inflate_trees_bits,"INTRBI")
|
||||
# pragma map(inflate_trees_dynamic,"INTRDY")
|
||||
# pragma map(inflate_trees_fixed,"INTRFI")
|
||||
# pragma map(inflate_trees_free,"INTRFR")
|
||||
#endif
|
||||
|
||||
#endif /* _ZCONF_H */
|
||||
893
RenderDll/Common/Textures/Image/zlib/zlib.h
Normal file
893
RenderDll/Common/Textures/Image/zlib/zlib.h
Normal file
@@ -0,0 +1,893 @@
|
||||
/* zlib.h -- interface of the 'zlib' general purpose compression library
|
||||
version 1.1.3, July 9th, 1998
|
||||
|
||||
Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
|
||||
The data format used by the zlib library is described by RFCs (Request for
|
||||
Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
|
||||
(zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
|
||||
*/
|
||||
|
||||
#ifndef _ZLIB_H
|
||||
#define _ZLIB_H
|
||||
|
||||
#include "zconf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ZLIB_VERSION "1.1.3"
|
||||
|
||||
/*
|
||||
The 'zlib' compression library provides in-memory compression and
|
||||
decompression functions, including integrity checks of the uncompressed
|
||||
data. This version of the library supports only one compression method
|
||||
(deflation) but other algorithms will be added later and will have the same
|
||||
stream interface.
|
||||
|
||||
Compression can be done in a single step if the buffers are large
|
||||
enough (for example if an input file is mmap'ed), or can be done by
|
||||
repeated calls of the compression function. In the latter case, the
|
||||
application must provide more input and/or consume the output
|
||||
(providing more output space) before each call.
|
||||
|
||||
The library also supports reading and writing files in gzip (.gz) format
|
||||
with an interface similar to that of stdio.
|
||||
|
||||
The library does not install any signal handler. The decoder checks
|
||||
the consistency of the compressed data, so the library should never
|
||||
crash even in case of corrupted input.
|
||||
*/
|
||||
|
||||
typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
|
||||
typedef void (*free_func) OF((voidpf opaque, voidpf address));
|
||||
|
||||
struct internal_state;
|
||||
|
||||
typedef struct z_stream_s {
|
||||
Bytef *next_in; /* next input byte */
|
||||
uInt avail_in; /* number of bytes available at next_in */
|
||||
uLong total_in; /* total nb of input bytes read so far */
|
||||
|
||||
Bytef *next_out; /* next output byte should be put there */
|
||||
uInt avail_out; /* remaining free space at next_out */
|
||||
uLong total_out; /* total nb of bytes output so far */
|
||||
|
||||
char *msg; /* last error message, NULL if no error */
|
||||
struct internal_state FAR *state; /* not visible by applications */
|
||||
|
||||
alloc_func zalloc; /* used to allocate the internal state */
|
||||
free_func zfree; /* used to free the internal state */
|
||||
voidpf opaque; /* private data object passed to zalloc and zfree */
|
||||
|
||||
int data_type; /* best guess about the data type: ascii or binary */
|
||||
uLong adler; /* adler32 value of the uncompressed data */
|
||||
uLong reserved; /* reserved for future use */
|
||||
} z_stream;
|
||||
|
||||
typedef z_stream FAR *z_streamp;
|
||||
|
||||
/*
|
||||
The application must update next_in and avail_in when avail_in has
|
||||
dropped to zero. It must update next_out and avail_out when avail_out
|
||||
has dropped to zero. The application must initialize zalloc, zfree and
|
||||
opaque before calling the init function. All other fields are set by the
|
||||
compression library and must not be updated by the application.
|
||||
|
||||
The opaque value provided by the application will be passed as the first
|
||||
parameter for calls of zalloc and zfree. This can be useful for custom
|
||||
memory management. The compression library attaches no meaning to the
|
||||
opaque value.
|
||||
|
||||
zalloc must return Z_NULL if there is not enough memory for the object.
|
||||
If zlib is used in a multi-threaded application, zalloc and zfree must be
|
||||
thread safe.
|
||||
|
||||
On 16-bit systems, the functions zalloc and zfree must be able to allocate
|
||||
exactly 65536 bytes, but will not be required to allocate more than this
|
||||
if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
|
||||
pointers returned by zalloc for objects of exactly 65536 bytes *must*
|
||||
have their offset normalized to zero. The default allocation function
|
||||
provided by this library ensures this (see zutil.c). To reduce memory
|
||||
requirements and avoid any allocation of 64K objects, at the expense of
|
||||
compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
|
||||
|
||||
The fields total_in and total_out can be used for statistics or
|
||||
progress reports. After compression, total_in holds the total size of
|
||||
the uncompressed data and may be saved for use in the decompressor
|
||||
(particularly if the decompressor wants to decompress everything in
|
||||
a single step).
|
||||
*/
|
||||
|
||||
/* constants */
|
||||
|
||||
#define Z_NO_FLUSH 0
|
||||
#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
|
||||
#define Z_SYNC_FLUSH 2
|
||||
#define Z_FULL_FLUSH 3
|
||||
#define Z_FINISH 4
|
||||
/* Allowed flush values; see deflate() below for details */
|
||||
|
||||
#define Z_OK 0
|
||||
#define Z_STREAM_END 1
|
||||
#define Z_NEED_DICT 2
|
||||
#define Z_ERRNO (-1)
|
||||
#define Z_STREAM_ERROR (-2)
|
||||
#define Z_DATA_ERROR (-3)
|
||||
#define Z_MEM_ERROR (-4)
|
||||
#define Z_BUF_ERROR (-5)
|
||||
#define Z_VERSION_ERROR (-6)
|
||||
/* Return codes for the compression/decompression functions. Negative
|
||||
* values are errors, positive values are used for special but normal events.
|
||||
*/
|
||||
|
||||
#define Z_NO_COMPRESSION 0
|
||||
#define Z_BEST_SPEED 1
|
||||
#define Z_BEST_COMPRESSION 9
|
||||
#define Z_DEFAULT_COMPRESSION (-1)
|
||||
/* compression levels */
|
||||
|
||||
#define Z_FILTERED 1
|
||||
#define Z_HUFFMAN_ONLY 2
|
||||
#define Z_DEFAULT_STRATEGY 0
|
||||
/* compression strategy; see deflateInit2() below for details */
|
||||
|
||||
#define Z_BINARY 0
|
||||
#define Z_ASCII 1
|
||||
#define Z_UNKNOWN 2
|
||||
/* Possible values of the data_type field */
|
||||
|
||||
#define Z_DEFLATED 8
|
||||
/* The deflate compression method (the only one supported in this version) */
|
||||
|
||||
#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
|
||||
|
||||
#define zlib_version zlibVersion()
|
||||
/* for compatibility with versions < 1.0.2 */
|
||||
|
||||
/* basic functions */
|
||||
|
||||
ZEXTERN const char * ZEXPORT zlibVersion OF((void));
|
||||
/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
|
||||
If the first character differs, the library code actually used is
|
||||
not compatible with the zlib.h header file used by the application.
|
||||
This check is automatically made by deflateInit and inflateInit.
|
||||
*/
|
||||
|
||||
/*
|
||||
ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
|
||||
|
||||
Initializes the internal stream state for compression. The fields
|
||||
zalloc, zfree and opaque must be initialized before by the caller.
|
||||
If zalloc and zfree are set to Z_NULL, deflateInit updates them to
|
||||
use default allocation functions.
|
||||
|
||||
The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
|
||||
1 gives best speed, 9 gives best compression, 0 gives no compression at
|
||||
all (the input data is simply copied a block at a time).
|
||||
Z_DEFAULT_COMPRESSION requests a default compromise between speed and
|
||||
compression (currently equivalent to level 6).
|
||||
|
||||
deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||
enough memory, Z_STREAM_ERROR if level is not a valid compression level,
|
||||
Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
|
||||
with the version assumed by the caller (ZLIB_VERSION).
|
||||
msg is set to null if there is no error message. deflateInit does not
|
||||
perform any compression: this will be done by deflate().
|
||||
*/
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
|
||||
/*
|
||||
deflate compresses as much data as possible, and stops when the input
|
||||
buffer becomes empty or the output buffer becomes full. It may introduce some
|
||||
output latency (reading input without producing any output) except when
|
||||
forced to flush.
|
||||
|
||||
The detailed semantics are as follows. deflate performs one or both of the
|
||||
following actions:
|
||||
|
||||
- Compress more input starting at next_in and update next_in and avail_in
|
||||
accordingly. If not all input can be processed (because there is not
|
||||
enough room in the output buffer), next_in and avail_in are updated and
|
||||
processing will resume at this point for the next call of deflate().
|
||||
|
||||
- Provide more output starting at next_out and update next_out and avail_out
|
||||
accordingly. This action is forced if the parameter flush is non zero.
|
||||
Forcing flush frequently degrades the compression ratio, so this parameter
|
||||
should be set only when necessary (in interactive applications).
|
||||
Some output may be provided even if flush is not set.
|
||||
|
||||
Before the call of deflate(), the application should ensure that at least
|
||||
one of the actions is possible, by providing more input and/or consuming
|
||||
more output, and updating avail_in or avail_out accordingly; avail_out
|
||||
should never be zero before the call. The application can consume the
|
||||
compressed output when it wants, for example when the output buffer is full
|
||||
(avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
|
||||
and with zero avail_out, it must be called again after making room in the
|
||||
output buffer because there might be more output pending.
|
||||
|
||||
If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
|
||||
flushed to the output buffer and the output is aligned on a byte boundary, so
|
||||
that the decompressor can get all input data available so far. (In particular
|
||||
avail_in is zero after the call if enough output space has been provided
|
||||
before the call.) Flushing may degrade compression for some compression
|
||||
algorithms and so it should be used only when necessary.
|
||||
|
||||
If flush is set to Z_FULL_FLUSH, all output is flushed as with
|
||||
Z_SYNC_FLUSH, and the compression state is reset so that decompression can
|
||||
restart from this point if previous compressed data has been damaged or if
|
||||
random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
|
||||
the compression.
|
||||
|
||||
If deflate returns with avail_out == 0, this function must be called again
|
||||
with the same value of the flush parameter and more output space (updated
|
||||
avail_out), until the flush is complete (deflate returns with non-zero
|
||||
avail_out).
|
||||
|
||||
If the parameter flush is set to Z_FINISH, pending input is processed,
|
||||
pending output is flushed and deflate returns with Z_STREAM_END if there
|
||||
was enough output space; if deflate returns with Z_OK, this function must be
|
||||
called again with Z_FINISH and more output space (updated avail_out) but no
|
||||
more input data, until it returns with Z_STREAM_END or an error. After
|
||||
deflate has returned Z_STREAM_END, the only possible operations on the
|
||||
stream are deflateReset or deflateEnd.
|
||||
|
||||
Z_FINISH can be used immediately after deflateInit if all the compression
|
||||
is to be done in a single step. In this case, avail_out must be at least
|
||||
0.1% larger than avail_in plus 12 bytes. If deflate does not return
|
||||
Z_STREAM_END, then it must be called again as described above.
|
||||
|
||||
deflate() sets strm->adler to the adler32 checksum of all input read
|
||||
so far (that is, total_in bytes).
|
||||
|
||||
deflate() may update data_type if it can make a good guess about
|
||||
the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
|
||||
binary. This field is only for information purposes and does not affect
|
||||
the compression algorithm in any manner.
|
||||
|
||||
deflate() returns Z_OK if some progress has been made (more input
|
||||
processed or more output produced), Z_STREAM_END if all input has been
|
||||
consumed and all output has been produced (only when flush is set to
|
||||
Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
|
||||
if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
|
||||
(for example avail_in or avail_out was zero).
|
||||
*/
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
|
||||
/*
|
||||
All dynamically allocated data structures for this stream are freed.
|
||||
This function discards any unprocessed input and does not flush any
|
||||
pending output.
|
||||
|
||||
deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
|
||||
stream state was inconsistent, Z_DATA_ERROR if the stream was freed
|
||||
prematurely (some input or output was discarded). In the error case,
|
||||
msg may be set but then points to a static string (which must not be
|
||||
deallocated).
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
|
||||
|
||||
Initializes the internal stream state for decompression. The fields
|
||||
next_in, avail_in, zalloc, zfree and opaque must be initialized before by
|
||||
the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
|
||||
value depends on the compression method), inflateInit determines the
|
||||
compression method from the zlib header and allocates all data structures
|
||||
accordingly; otherwise the allocation will be deferred to the first call of
|
||||
inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
|
||||
use default allocation functions.
|
||||
|
||||
inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
|
||||
version assumed by the caller. msg is set to null if there is no error
|
||||
message. inflateInit does not perform any decompression apart from reading
|
||||
the zlib header if present: this will be done by inflate(). (So next_in and
|
||||
avail_in may be modified, but next_out and avail_out are unchanged.)
|
||||
*/
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
|
||||
/*
|
||||
inflate decompresses as much data as possible, and stops when the input
|
||||
buffer becomes empty or the output buffer becomes full. It may some
|
||||
introduce some output latency (reading input without producing any output)
|
||||
except when forced to flush.
|
||||
|
||||
The detailed semantics are as follows. inflate performs one or both of the
|
||||
following actions:
|
||||
|
||||
- Decompress more input starting at next_in and update next_in and avail_in
|
||||
accordingly. If not all input can be processed (because there is not
|
||||
enough room in the output buffer), next_in is updated and processing
|
||||
will resume at this point for the next call of inflate().
|
||||
|
||||
- Provide more output starting at next_out and update next_out and avail_out
|
||||
accordingly. inflate() provides as much output as possible, until there
|
||||
is no more input data or no more space in the output buffer (see below
|
||||
about the flush parameter).
|
||||
|
||||
Before the call of inflate(), the application should ensure that at least
|
||||
one of the actions is possible, by providing more input and/or consuming
|
||||
more output, and updating the next_* and avail_* values accordingly.
|
||||
The application can consume the uncompressed output when it wants, for
|
||||
example when the output buffer is full (avail_out == 0), or after each
|
||||
call of inflate(). If inflate returns Z_OK and with zero avail_out, it
|
||||
must be called again after making room in the output buffer because there
|
||||
might be more output pending.
|
||||
|
||||
If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
|
||||
output as possible to the output buffer. The flushing behavior of inflate is
|
||||
not specified for values of the flush parameter other than Z_SYNC_FLUSH
|
||||
and Z_FINISH, but the current implementation actually flushes as much output
|
||||
as possible anyway.
|
||||
|
||||
inflate() should normally be called until it returns Z_STREAM_END or an
|
||||
error. However if all decompression is to be performed in a single step
|
||||
(a single call of inflate), the parameter flush should be set to
|
||||
Z_FINISH. In this case all pending input is processed and all pending
|
||||
output is flushed; avail_out must be large enough to hold all the
|
||||
uncompressed data. (The size of the uncompressed data may have been saved
|
||||
by the compressor for this purpose.) The next operation on this stream must
|
||||
be inflateEnd to deallocate the decompression state. The use of Z_FINISH
|
||||
is never required, but can be used to inform inflate that a faster routine
|
||||
may be used for the single inflate() call.
|
||||
|
||||
If a preset dictionary is needed at this point (see inflateSetDictionary
|
||||
below), inflate sets strm-adler to the adler32 checksum of the
|
||||
dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise
|
||||
it sets strm->adler to the adler32 checksum of all output produced
|
||||
so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
|
||||
an error code as described below. At the end of the stream, inflate()
|
||||
checks that its computed adler32 checksum is equal to that saved by the
|
||||
compressor and returns Z_STREAM_END only if the checksum is correct.
|
||||
|
||||
inflate() returns Z_OK if some progress has been made (more input processed
|
||||
or more output produced), Z_STREAM_END if the end of the compressed data has
|
||||
been reached and all uncompressed output has been produced, Z_NEED_DICT if a
|
||||
preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
|
||||
corrupted (input stream not conforming to the zlib format or incorrect
|
||||
adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
|
||||
(for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
|
||||
enough memory, Z_BUF_ERROR if no progress is possible or if there was not
|
||||
enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
|
||||
case, the application may then call inflateSync to look for a good
|
||||
compression block.
|
||||
*/
|
||||
|
||||
|
||||
ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
|
||||
/*
|
||||
All dynamically allocated data structures for this stream are freed.
|
||||
This function discards any unprocessed input and does not flush any
|
||||
pending output.
|
||||
|
||||
inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
|
||||
was inconsistent. In the error case, msg may be set but then points to a
|
||||
static string (which must not be deallocated).
|
||||
*/
|
||||
|
||||
/* Advanced functions */
|
||||
|
||||
/*
|
||||
The following functions are needed only in some special applications.
|
||||
*/
|
||||
|
||||
/*
|
||||
ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
|
||||
int level,
|
||||
int method,
|
||||
int windowBits,
|
||||
int memLevel,
|
||||
int strategy));
|
||||
|
||||
This is another version of deflateInit with more compression options. The
|
||||
fields next_in, zalloc, zfree and opaque must be initialized before by
|
||||
the caller.
|
||||
|
||||
The method parameter is the compression method. It must be Z_DEFLATED in
|
||||
this version of the library.
|
||||
|
||||
The windowBits parameter is the base two logarithm of the window size
|
||||
(the size of the history buffer). It should be in the range 8..15 for this
|
||||
version of the library. Larger values of this parameter result in better
|
||||
compression at the expense of memory usage. The default value is 15 if
|
||||
deflateInit is used instead.
|
||||
|
||||
The memLevel parameter specifies how much memory should be allocated
|
||||
for the internal compression state. memLevel=1 uses minimum memory but
|
||||
is slow and reduces compression ratio; memLevel=9 uses maximum memory
|
||||
for optimal speed. The default value is 8. See zconf.h for total memory
|
||||
usage as a function of windowBits and memLevel.
|
||||
|
||||
The strategy parameter is used to tune the compression algorithm. Use the
|
||||
value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
|
||||
filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
|
||||
string match). Filtered data consists mostly of small values with a
|
||||
somewhat random distribution. In this case, the compression algorithm is
|
||||
tuned to compress them better. The effect of Z_FILTERED is to force more
|
||||
Huffman coding and less string matching; it is somewhat intermediate
|
||||
between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
|
||||
the compression ratio but not the correctness of the compressed output even
|
||||
if it is not set appropriately.
|
||||
|
||||
deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
|
||||
method). msg is set to null if there is no error message. deflateInit2 does
|
||||
not perform any compression: this will be done by deflate().
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
|
||||
const Bytef *dictionary,
|
||||
uInt dictLength));
|
||||
/*
|
||||
Initializes the compression dictionary from the given byte sequence
|
||||
without producing any compressed output. This function must be called
|
||||
immediately after deflateInit, deflateInit2 or deflateReset, before any
|
||||
call of deflate. The compressor and decompressor must use exactly the same
|
||||
dictionary (see inflateSetDictionary).
|
||||
|
||||
The dictionary should consist of strings (byte sequences) that are likely
|
||||
to be encountered later in the data to be compressed, with the most commonly
|
||||
used strings preferably put towards the end of the dictionary. Using a
|
||||
dictionary is most useful when the data to be compressed is short and can be
|
||||
predicted with good accuracy; the data can then be compressed better than
|
||||
with the default empty dictionary.
|
||||
|
||||
Depending on the size of the compression data structures selected by
|
||||
deflateInit or deflateInit2, a part of the dictionary may in effect be
|
||||
discarded, for example if the dictionary is larger than the window size in
|
||||
deflate or deflate2. Thus the strings most likely to be useful should be
|
||||
put at the end of the dictionary, not at the front.
|
||||
|
||||
Upon return of this function, strm->adler is set to the Adler32 value
|
||||
of the dictionary; the decompressor may later use this value to determine
|
||||
which dictionary has been used by the compressor. (The Adler32 value
|
||||
applies to the whole dictionary even if only a subset of the dictionary is
|
||||
actually used by the compressor.)
|
||||
|
||||
deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
|
||||
parameter is invalid (such as NULL dictionary) or the stream state is
|
||||
inconsistent (for example if deflate has already been called for this stream
|
||||
or if the compression method is bsort). deflateSetDictionary does not
|
||||
perform any compression: this will be done by deflate().
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
|
||||
z_streamp source));
|
||||
/*
|
||||
Sets the destination stream as a complete copy of the source stream.
|
||||
|
||||
This function can be useful when several compression strategies will be
|
||||
tried, for example when there are several ways of pre-processing the input
|
||||
data with a filter. The streams that will be discarded should then be freed
|
||||
by calling deflateEnd. Note that deflateCopy duplicates the internal
|
||||
compression state which can be quite large, so this strategy is slow and
|
||||
can consume lots of memory.
|
||||
|
||||
deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||
enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
|
||||
(such as zalloc being NULL). msg is left unchanged in both source and
|
||||
destination.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
|
||||
/*
|
||||
This function is equivalent to deflateEnd followed by deflateInit,
|
||||
but does not free and reallocate all the internal compression state.
|
||||
The stream will keep the same compression level and any other attributes
|
||||
that may have been set by deflateInit2.
|
||||
|
||||
deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
|
||||
stream state was inconsistent (such as zalloc or state being NULL).
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
|
||||
int level,
|
||||
int strategy));
|
||||
/*
|
||||
Dynamically update the compression level and compression strategy. The
|
||||
interpretation of level and strategy is as in deflateInit2. This can be
|
||||
used to switch between compression and straight copy of the input data, or
|
||||
to switch to a different kind of input data requiring a different
|
||||
strategy. If the compression level is changed, the input available so far
|
||||
is compressed with the old level (and may be flushed); the new level will
|
||||
take effect only at the next call of deflate().
|
||||
|
||||
Before the call of deflateParams, the stream state must be set as for
|
||||
a call of deflate(), since the currently available input may have to
|
||||
be compressed and flushed. In particular, strm->avail_out must be non-zero.
|
||||
|
||||
deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
|
||||
stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
|
||||
if strm->avail_out was zero.
|
||||
*/
|
||||
|
||||
/*
|
||||
ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
|
||||
int windowBits));
|
||||
|
||||
This is another version of inflateInit with an extra parameter. The
|
||||
fields next_in, avail_in, zalloc, zfree and opaque must be initialized
|
||||
before by the caller.
|
||||
|
||||
The windowBits parameter is the base two logarithm of the maximum window
|
||||
size (the size of the history buffer). It should be in the range 8..15 for
|
||||
this version of the library. The default value is 15 if inflateInit is used
|
||||
instead. If a compressed stream with a larger window size is given as
|
||||
input, inflate() will return with the error code Z_DATA_ERROR instead of
|
||||
trying to allocate a larger window.
|
||||
|
||||
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
|
||||
memLevel). msg is set to null if there is no error message. inflateInit2
|
||||
does not perform any decompression apart from reading the zlib header if
|
||||
present: this will be done by inflate(). (So next_in and avail_in may be
|
||||
modified, but next_out and avail_out are unchanged.)
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
|
||||
const Bytef *dictionary,
|
||||
uInt dictLength));
|
||||
/*
|
||||
Initializes the decompression dictionary from the given uncompressed byte
|
||||
sequence. This function must be called immediately after a call of inflate
|
||||
if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
|
||||
can be determined from the Adler32 value returned by this call of
|
||||
inflate. The compressor and decompressor must use exactly the same
|
||||
dictionary (see deflateSetDictionary).
|
||||
|
||||
inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
|
||||
parameter is invalid (such as NULL dictionary) or the stream state is
|
||||
inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
|
||||
expected one (incorrect Adler32 value). inflateSetDictionary does not
|
||||
perform any decompression: this will be done by subsequent calls of
|
||||
inflate().
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
|
||||
/*
|
||||
Skips invalid compressed data until a full flush point (see above the
|
||||
description of deflate with Z_FULL_FLUSH) can be found, or until all
|
||||
available input is skipped. No output is provided.
|
||||
|
||||
inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
|
||||
if no more input was provided, Z_DATA_ERROR if no flush point has been found,
|
||||
or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
|
||||
case, the application may save the current current value of total_in which
|
||||
indicates where valid compressed data was found. In the error case, the
|
||||
application may repeatedly call inflateSync, providing more input each time,
|
||||
until success or end of the input data.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
|
||||
/*
|
||||
This function is equivalent to inflateEnd followed by inflateInit,
|
||||
but does not free and reallocate all the internal decompression state.
|
||||
The stream will keep attributes that may have been set by inflateInit2.
|
||||
|
||||
inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
|
||||
stream state was inconsistent (such as zalloc or state being NULL).
|
||||
*/
|
||||
|
||||
|
||||
/* utility functions */
|
||||
|
||||
/*
|
||||
The following utility functions are implemented on top of the
|
||||
basic stream-oriented functions. To simplify the interface, some
|
||||
default options are assumed (compression level and memory usage,
|
||||
standard memory allocation functions). The source code of these
|
||||
utility functions can easily be modified if you need special options.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
|
||||
const Bytef *source, uLong sourceLen));
|
||||
/*
|
||||
Compresses the source buffer into the destination buffer. sourceLen is
|
||||
the byte length of the source buffer. Upon entry, destLen is the total
|
||||
size of the destination buffer, which must be at least 0.1% larger than
|
||||
sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
|
||||
compressed buffer.
|
||||
This function can be used to compress a whole file at once if the
|
||||
input file is mmap'ed.
|
||||
compress returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||
enough memory, Z_BUF_ERROR if there was not enough room in the output
|
||||
buffer.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
|
||||
const Bytef *source, uLong sourceLen,
|
||||
int level));
|
||||
/*
|
||||
Compresses the source buffer into the destination buffer. The level
|
||||
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
||||
length of the source buffer. Upon entry, destLen is the total size of the
|
||||
destination buffer, which must be at least 0.1% larger than sourceLen plus
|
||||
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
|
||||
|
||||
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
||||
Z_STREAM_ERROR if the level parameter is invalid.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
|
||||
const Bytef *source, uLong sourceLen));
|
||||
/*
|
||||
Decompresses the source buffer into the destination buffer. sourceLen is
|
||||
the byte length of the source buffer. Upon entry, destLen is the total
|
||||
size of the destination buffer, which must be large enough to hold the
|
||||
entire uncompressed data. (The size of the uncompressed data must have
|
||||
been saved previously by the compressor and transmitted to the decompressor
|
||||
by some mechanism outside the scope of this compression library.)
|
||||
Upon exit, destLen is the actual size of the compressed buffer.
|
||||
This function can be used to decompress a whole file at once if the
|
||||
input file is mmap'ed.
|
||||
|
||||
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||
enough memory, Z_BUF_ERROR if there was not enough room in the output
|
||||
buffer, or Z_DATA_ERROR if the input data was corrupted.
|
||||
*/
|
||||
|
||||
|
||||
typedef voidp gzFile;
|
||||
|
||||
ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
|
||||
/*
|
||||
Opens a gzip (.gz) file for reading or writing. The mode parameter
|
||||
is as in fopen ("rb" or "wb") but can also include a compression level
|
||||
("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
|
||||
Huffman only compression as in "wb1h". (See the description
|
||||
of deflateInit2 for more information about the strategy parameter.)
|
||||
|
||||
gzopen can be used to read a file which is not in gzip format; in this
|
||||
case gzread will directly read from the file without decompression.
|
||||
|
||||
gzopen returns NULL if the file could not be opened or if there was
|
||||
insufficient memory to allocate the (de)compression state; errno
|
||||
can be checked to distinguish the two cases (if errno is zero, the
|
||||
zlib error is Z_MEM_ERROR). */
|
||||
|
||||
ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
|
||||
/*
|
||||
gzdopen() associates a gzFile with the file descriptor fd. File
|
||||
descriptors are obtained from calls like open, dup, creat, pipe or
|
||||
fileno (in the file has been previously opened with fopen).
|
||||
The mode parameter is as in gzopen.
|
||||
The next call of gzclose on the returned gzFile will also close the
|
||||
file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
|
||||
descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
|
||||
gzdopen returns NULL if there was insufficient memory to allocate
|
||||
the (de)compression state.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
|
||||
/*
|
||||
Dynamically update the compression level or strategy. See the description
|
||||
of deflateInit2 for the meaning of these parameters.
|
||||
gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
|
||||
opened for writing.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
|
||||
/*
|
||||
Reads the given number of uncompressed bytes from the compressed file.
|
||||
If the input file was not in gzip format, gzread copies the given number
|
||||
of bytes into the buffer.
|
||||
gzread returns the number of uncompressed bytes actually read (0 for
|
||||
end of file, -1 for error). */
|
||||
|
||||
ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
|
||||
const voidp buf, unsigned len));
|
||||
/*
|
||||
Writes the given number of uncompressed bytes into the compressed file.
|
||||
gzwrite returns the number of uncompressed bytes actually written
|
||||
(0 in case of error).
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
|
||||
/*
|
||||
Converts, formats, and writes the args to the compressed file under
|
||||
control of the format string, as in fprintf. gzprintf returns the number of
|
||||
uncompressed bytes actually written (0 in case of error).
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
|
||||
/*
|
||||
Writes the given null-terminated string to the compressed file, excluding
|
||||
the terminating null character.
|
||||
gzputs returns the number of characters written, or -1 in case of error.
|
||||
*/
|
||||
|
||||
ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
|
||||
/*
|
||||
Reads bytes from the compressed file until len-1 characters are read, or
|
||||
a newline character is read and transferred to buf, or an end-of-file
|
||||
condition is encountered. The string is then terminated with a null
|
||||
character.
|
||||
gzgets returns buf, or Z_NULL in case of error.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
|
||||
/*
|
||||
Writes c, converted to an unsigned char, into the compressed file.
|
||||
gzputc returns the value that was written, or -1 in case of error.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
|
||||
/*
|
||||
Reads one byte from the compressed file. gzgetc returns this byte
|
||||
or -1 in case of end of file or error.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
|
||||
/*
|
||||
Flushes all pending output into the compressed file. The parameter
|
||||
flush is as in the deflate() function. The return value is the zlib
|
||||
error number (see function gzerror below). gzflush returns Z_OK if
|
||||
the flush parameter is Z_FINISH and all output could be flushed.
|
||||
gzflush should be called only when strictly necessary because it can
|
||||
degrade compression.
|
||||
*/
|
||||
|
||||
ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
|
||||
z_off_t offset, int whence));
|
||||
/*
|
||||
Sets the starting position for the next gzread or gzwrite on the
|
||||
given compressed file. The offset represents a number of bytes in the
|
||||
uncompressed data stream. The whence parameter is defined as in lseek(2);
|
||||
the value SEEK_END is not supported.
|
||||
If the file is opened for reading, this function is emulated but can be
|
||||
extremely slow. If the file is opened for writing, only forward seeks are
|
||||
supported; gzseek then compresses a sequence of zeroes up to the new
|
||||
starting position.
|
||||
|
||||
gzseek returns the resulting offset location as measured in bytes from
|
||||
the beginning of the uncompressed stream, or -1 in case of error, in
|
||||
particular if the file is opened for writing and the new starting position
|
||||
would be before the current position.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
|
||||
/*
|
||||
Rewinds the given file. This function is supported only for reading.
|
||||
|
||||
gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
|
||||
*/
|
||||
|
||||
ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
|
||||
/*
|
||||
Returns the starting position for the next gzread or gzwrite on the
|
||||
given compressed file. This position represents a number of bytes in the
|
||||
uncompressed data stream.
|
||||
|
||||
gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzeof OF((gzFile file));
|
||||
/*
|
||||
Returns 1 when EOF has previously been detected reading the given
|
||||
input stream, otherwise zero.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzclose OF((gzFile file));
|
||||
/*
|
||||
Flushes all pending output if necessary, closes the compressed file
|
||||
and deallocates all the (de)compression state. The return value is the zlib
|
||||
error number (see function gzerror below).
|
||||
*/
|
||||
|
||||
ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
|
||||
/*
|
||||
Returns the error message for the last error which occurred on the
|
||||
given compressed file. errnum is set to zlib error number. If an
|
||||
error occurred in the file system and not in the compression library,
|
||||
errnum is set to Z_ERRNO and the application may consult errno
|
||||
to get the exact error code.
|
||||
*/
|
||||
|
||||
/* checksum functions */
|
||||
|
||||
/*
|
||||
These functions are not related to compression but are exported
|
||||
anyway because they might be useful in applications using the
|
||||
compression library.
|
||||
*/
|
||||
|
||||
ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
|
||||
|
||||
/*
|
||||
Update a running Adler-32 checksum with the bytes buf[0..len-1] and
|
||||
return the updated checksum. If buf is NULL, this function returns
|
||||
the required initial value for the checksum.
|
||||
An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
|
||||
much faster. Usage example:
|
||||
|
||||
uLong adler = adler32(0L, Z_NULL, 0);
|
||||
|
||||
while (read_buffer(buffer, length) != EOF) {
|
||||
adler = adler32(adler, buffer, length);
|
||||
}
|
||||
if (adler != original_adler) error();
|
||||
*/
|
||||
|
||||
ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
|
||||
/*
|
||||
Update a running crc with the bytes buf[0..len-1] and return the updated
|
||||
crc. If buf is NULL, this function returns the required initial value
|
||||
for the crc. Pre- and post-conditioning (one's complement) is performed
|
||||
within this function so it shouldn't be done by the application.
|
||||
Usage example:
|
||||
|
||||
uLong crc = crc32(0L, Z_NULL, 0);
|
||||
|
||||
while (read_buffer(buffer, length) != EOF) {
|
||||
crc = crc32(crc, buffer, length);
|
||||
}
|
||||
if (crc != original_crc) error();
|
||||
*/
|
||||
|
||||
|
||||
/* various hacks, don't look :) */
|
||||
|
||||
/* deflateInit and inflateInit are macros to allow checking the zlib version
|
||||
* and the compiler's view of z_stream:
|
||||
*/
|
||||
ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
|
||||
const char *version, int stream_size));
|
||||
ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
|
||||
const char *version, int stream_size));
|
||||
ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
|
||||
int windowBits, int memLevel,
|
||||
int strategy, const char *version,
|
||||
int stream_size));
|
||||
ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
|
||||
const char *version, int stream_size));
|
||||
#define deflateInit(strm, level) \
|
||||
deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
|
||||
#define inflateInit(strm) \
|
||||
inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
|
||||
#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
|
||||
deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
|
||||
(strategy), ZLIB_VERSION, sizeof(z_stream))
|
||||
#define inflateInit2(strm, windowBits) \
|
||||
inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
|
||||
|
||||
|
||||
#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
|
||||
struct internal_state {int dummy;}; /* hack for buggy compilers */
|
||||
#endif
|
||||
|
||||
ZEXTERN const char * ZEXPORT zError OF((int err));
|
||||
ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z));
|
||||
ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ZLIB_H */
|
||||
Reference in New Issue
Block a user