Format with ClangFormat

This commit is contained in:
Andrew Murray 2021-01-03 14:17:51 +11:00
parent e2d00f8cf8
commit 46b7e86bab
101 changed files with 14097 additions and 13889 deletions

View File

@ -79,18 +79,20 @@ typedef struct Tcl_Interp Tcl_Interp;
typedef struct Tcl_Command_ *Tcl_Command; typedef struct Tcl_Command_ *Tcl_Command;
typedef void *ClientData; typedef void *ClientData;
typedef int (Tcl_CmdProc) (ClientData clientData, Tcl_Interp typedef int(Tcl_CmdProc)(
*interp, int argc, const char *argv[]); ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[]);
typedef void (Tcl_CmdDeleteProc) (ClientData clientData); typedef void(Tcl_CmdDeleteProc)(ClientData clientData);
/* Typedefs derived from function signatures in Tcl header */ /* Typedefs derived from function signatures in Tcl header */
/* Tcl_CreateCommand */ /* Tcl_CreateCommand */
typedef Tcl_Command (*Tcl_CreateCommand_t)(Tcl_Interp *interp, typedef Tcl_Command (*Tcl_CreateCommand_t)(
const char *cmdName, Tcl_CmdProc *proc, Tcl_Interp *interp,
ClientData clientData, const char *cmdName,
Tcl_CmdDeleteProc *deleteProc); Tcl_CmdProc *proc,
ClientData clientData,
Tcl_CmdDeleteProc *deleteProc);
/* Tcl_AppendResult */ /* Tcl_AppendResult */
typedef void (*Tcl_AppendResult_t) (Tcl_Interp *interp, ...); typedef void (*Tcl_AppendResult_t)(Tcl_Interp *interp, ...);
/* Tk header excerpts */ /* Tk header excerpts */
@ -107,8 +109,7 @@ typedef struct Tk_Window_ *Tk_Window;
typedef void *Tk_PhotoHandle; typedef void *Tk_PhotoHandle;
typedef struct Tk_PhotoImageBlock typedef struct Tk_PhotoImageBlock {
{
unsigned char *pixelPtr; unsigned char *pixelPtr;
int width; int width;
int height; int height;
@ -119,23 +120,30 @@ typedef struct Tk_PhotoImageBlock
/* Typedefs derived from function signatures in Tk header */ /* Typedefs derived from function signatures in Tk header */
/* Tk_PhotoPutBlock for Tk <= 8.4 */ /* Tk_PhotoPutBlock for Tk <= 8.4 */
typedef void (*Tk_PhotoPutBlock_84_t) (Tk_PhotoHandle handle, typedef void (*Tk_PhotoPutBlock_84_t)(
Tk_PhotoImageBlock *blockPtr, int x, int y, Tk_PhotoHandle handle,
int width, int height, int compRule); Tk_PhotoImageBlock *blockPtr,
int x,
int y,
int width,
int height,
int compRule);
/* Tk_PhotoPutBlock for Tk >= 8.5 */ /* Tk_PhotoPutBlock for Tk >= 8.5 */
typedef int (*Tk_PhotoPutBlock_85_t) (Tcl_Interp * interp, typedef int (*Tk_PhotoPutBlock_85_t)(
Tk_PhotoHandle handle, Tcl_Interp *interp,
Tk_PhotoImageBlock * blockPtr, int x, int y, Tk_PhotoHandle handle,
int width, int height, int compRule); Tk_PhotoImageBlock *blockPtr,
int x,
int y,
int width,
int height,
int compRule);
/* Tk_PhotoSetSize for Tk <= 8.4 */ /* Tk_PhotoSetSize for Tk <= 8.4 */
typedef void (*Tk_PhotoSetSize_84_t) (Tk_PhotoHandle handle, typedef void (*Tk_PhotoSetSize_84_t)(Tk_PhotoHandle handle, int width, int height);
int width, int height);
/* Tk_FindPhoto */ /* Tk_FindPhoto */
typedef Tk_PhotoHandle (*Tk_FindPhoto_t) (Tcl_Interp *interp, typedef Tk_PhotoHandle (*Tk_FindPhoto_t)(Tcl_Interp *interp, const char *imageName);
const char *imageName);
/* Tk_PhotoGetImage */ /* Tk_PhotoGetImage */
typedef int (*Tk_PhotoGetImage_t) (Tk_PhotoHandle handle, typedef int (*Tk_PhotoGetImage_t)(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr);
Tk_PhotoImageBlock * blockPtr);
/* /*
* end block for C++ * end block for C++

View File

@ -58,8 +58,7 @@ static Tk_PhotoSetSize_84_t TK_PHOTO_SET_SIZE_84;
static Tk_PhotoPutBlock_85_t TK_PHOTO_PUT_BLOCK_85; static Tk_PhotoPutBlock_85_t TK_PHOTO_PUT_BLOCK_85;
static Imaging static Imaging
ImagingFind(const char* name) ImagingFind(const char *name) {
{
Py_ssize_t id; Py_ssize_t id;
/* FIXME: use CObject instead? */ /* FIXME: use CObject instead? */
@ -72,41 +71,37 @@ ImagingFind(const char* name)
return NULL; return NULL;
} }
return (Imaging) id; return (Imaging)id;
} }
static int static int
PyImagingPhotoPut(ClientData clientdata, Tcl_Interp* interp, PyImagingPhotoPut(
int argc, const char **argv) ClientData clientdata, Tcl_Interp *interp, int argc, const char **argv) {
{
Imaging im; Imaging im;
Tk_PhotoHandle photo; Tk_PhotoHandle photo;
Tk_PhotoImageBlock block; Tk_PhotoImageBlock block;
if (argc != 3) { if (argc != 3) {
TCL_APPEND_RESULT(interp, "usage: ", argv[0], TCL_APPEND_RESULT(
" destPhoto srcImage", (char *) NULL); interp, "usage: ", argv[0], " destPhoto srcImage", (char *)NULL);
return TCL_ERROR; return TCL_ERROR;
} }
/* get Tcl PhotoImage handle */ /* get Tcl PhotoImage handle */
photo = TK_FIND_PHOTO(interp, argv[1]); photo = TK_FIND_PHOTO(interp, argv[1]);
if (photo == NULL) { if (photo == NULL) {
TCL_APPEND_RESULT( TCL_APPEND_RESULT(interp, "destination photo must exist", (char *)NULL);
interp, "destination photo must exist", (char *) NULL
);
return TCL_ERROR; return TCL_ERROR;
} }
/* get PIL Image handle */ /* get PIL Image handle */
im = ImagingFind(argv[2]); im = ImagingFind(argv[2]);
if (!im) { if (!im) {
TCL_APPEND_RESULT(interp, "bad name", (char*) NULL); TCL_APPEND_RESULT(interp, "bad name", (char *)NULL);
return TCL_ERROR; return TCL_ERROR;
} }
if (!im->block) { if (!im->block) {
TCL_APPEND_RESULT(interp, "bad display memory", (char*) NULL); TCL_APPEND_RESULT(interp, "bad display memory", (char *)NULL);
return TCL_ERROR; return TCL_ERROR;
} }
@ -126,18 +121,18 @@ PyImagingPhotoPut(ClientData clientdata, Tcl_Interp* interp,
block.offset[3] = 0; /* no alpha */ block.offset[3] = 0; /* no alpha */
} }
} else { } else {
TCL_APPEND_RESULT(interp, "Bad mode", (char*) NULL); TCL_APPEND_RESULT(interp, "Bad mode", (char *)NULL);
return TCL_ERROR; return TCL_ERROR;
} }
block.width = im->xsize; block.width = im->xsize;
block.height = im->ysize; block.height = im->ysize;
block.pitch = im->linesize; block.pitch = im->linesize;
block.pixelPtr = (unsigned char*) im->block; block.pixelPtr = (unsigned char *)im->block;
if (TK_LT_85) { /* Tk 8.4 */ if (TK_LT_85) { /* Tk 8.4 */
TK_PHOTO_PUT_BLOCK_84(photo, &block, 0, 0, block.width, block.height, TK_PHOTO_PUT_BLOCK_84(
TK_PHOTO_COMPOSITE_SET); photo, &block, 0, 0, block.width, block.height, TK_PHOTO_COMPOSITE_SET);
if (strcmp(im->mode, "RGBA") == 0) { if (strcmp(im->mode, "RGBA") == 0) {
/* Tk workaround: we need apply ToggleComplexAlphaIfNeeded */ /* Tk workaround: we need apply ToggleComplexAlphaIfNeeded */
/* (fixed in Tk 8.5a3) */ /* (fixed in Tk 8.5a3) */
@ -145,50 +140,54 @@ PyImagingPhotoPut(ClientData clientdata, Tcl_Interp* interp,
} }
} else { } else {
/* Tk >=8.5 */ /* Tk >=8.5 */
TK_PHOTO_PUT_BLOCK_85(interp, photo, &block, 0, 0, block.width, TK_PHOTO_PUT_BLOCK_85(
block.height, TK_PHOTO_COMPOSITE_SET); interp,
photo,
&block,
0,
0,
block.width,
block.height,
TK_PHOTO_COMPOSITE_SET);
} }
return TCL_OK; return TCL_OK;
} }
static int static int
PyImagingPhotoGet(ClientData clientdata, Tcl_Interp* interp, PyImagingPhotoGet(
int argc, const char **argv) ClientData clientdata, Tcl_Interp *interp, int argc, const char **argv) {
{
Imaging im; Imaging im;
Tk_PhotoHandle photo; Tk_PhotoHandle photo;
Tk_PhotoImageBlock block; Tk_PhotoImageBlock block;
int x, y, z; int x, y, z;
if (argc != 3) { if (argc != 3) {
TCL_APPEND_RESULT(interp, "usage: ", argv[0], TCL_APPEND_RESULT(
" srcPhoto destImage", (char *) NULL); interp, "usage: ", argv[0], " srcPhoto destImage", (char *)NULL);
return TCL_ERROR; return TCL_ERROR;
} }
/* get Tcl PhotoImage handle */ /* get Tcl PhotoImage handle */
photo = TK_FIND_PHOTO(interp, argv[1]); photo = TK_FIND_PHOTO(interp, argv[1]);
if (photo == NULL) { if (photo == NULL) {
TCL_APPEND_RESULT( TCL_APPEND_RESULT(interp, "source photo must exist", (char *)NULL);
interp, "source photo must exist", (char *) NULL
);
return TCL_ERROR; return TCL_ERROR;
} }
/* get PIL Image handle */ /* get PIL Image handle */
im = ImagingFind(argv[2]); im = ImagingFind(argv[2]);
if (!im) { if (!im) {
TCL_APPEND_RESULT(interp, "bad name", (char*) NULL); TCL_APPEND_RESULT(interp, "bad name", (char *)NULL);
return TCL_ERROR; return TCL_ERROR;
} }
TK_PHOTO_GET_IMAGE(photo, &block); TK_PHOTO_GET_IMAGE(photo, &block);
for (y = 0; y < block.height; y++) { for (y = 0; y < block.height; y++) {
UINT8* out = (UINT8*)im->image32[y]; UINT8 *out = (UINT8 *)im->image32[y];
for (x = 0; x < block.pitch; x += block.pixelSize) { for (x = 0; x < block.pitch; x += block.pixelSize) {
for (z=0; z < block.pixelSize; z++) { for (z = 0; z < block.pixelSize; z++) {
int offset = block.offset[z]; int offset = block.offset[z];
out[x + offset] = block.pixelPtr[y * block.pitch + x + offset]; out[x + offset] = block.pixelPtr[y * block.pitch + x + offset];
} }
@ -198,14 +197,20 @@ PyImagingPhotoGet(ClientData clientdata, Tcl_Interp* interp,
return TCL_OK; return TCL_OK;
} }
void void
TkImaging_Init(Tcl_Interp* interp) TkImaging_Init(Tcl_Interp *interp) {
{ TCL_CREATE_COMMAND(
TCL_CREATE_COMMAND(interp, "PyImagingPhoto", PyImagingPhotoPut, interp,
(ClientData) 0, (Tcl_CmdDeleteProc*) NULL); "PyImagingPhoto",
TCL_CREATE_COMMAND(interp, "PyImagingPhotoGet", PyImagingPhotoGet, PyImagingPhotoPut,
(ClientData) 0, (Tcl_CmdDeleteProc*) NULL); (ClientData)0,
(Tcl_CmdDeleteProc *)NULL);
TCL_CREATE_COMMAND(
interp,
"PyImagingPhotoGet",
PyImagingPhotoGet,
(ClientData)0,
(Tcl_CmdDeleteProc *)NULL);
} }
/* /*
@ -230,13 +235,13 @@ TkImaging_Init(Tcl_Interp* interp)
#define TKINTER_PKG "tkinter" #define TKINTER_PKG "tkinter"
FARPROC _dfunc(HMODULE lib_handle, const char *func_name) FARPROC
{ _dfunc(HMODULE lib_handle, const char *func_name) {
/* /*
* Load function `func_name` from `lib_handle`. * Load function `func_name` from `lib_handle`.
* Set Python exception if we can't find `func_name` in `lib_handle`. * Set Python exception if we can't find `func_name` in `lib_handle`.
* Returns function pointer or NULL if not present. * Returns function pointer or NULL if not present.
*/ */
char message[100]; char message[100];
@ -248,24 +253,26 @@ FARPROC _dfunc(HMODULE lib_handle, const char *func_name)
return func; return func;
} }
int get_tcl(HMODULE hMod) int
{ get_tcl(HMODULE hMod) {
/* /*
* Try to fill Tcl global vars with function pointers. Return 0 for no * Try to fill Tcl global vars with function pointers. Return 0 for no
* functions found, 1 for all functions found, -1 for some but not all * functions found, 1 for all functions found, -1 for some but not all
* functions found. * functions found.
*/ */
if ((TCL_CREATE_COMMAND = (Tcl_CreateCommand_t) if ((TCL_CREATE_COMMAND =
GetProcAddress(hMod, "Tcl_CreateCommand")) == NULL) { (Tcl_CreateCommand_t)GetProcAddress(hMod, "Tcl_CreateCommand")) == NULL) {
return 0; /* Maybe not Tcl module */ return 0; /* Maybe not Tcl module */
} }
return ((TCL_APPEND_RESULT = (Tcl_AppendResult_t) _dfunc(hMod, return ((TCL_APPEND_RESULT =
"Tcl_AppendResult")) == NULL) ? -1 : 1; (Tcl_AppendResult_t)_dfunc(hMod, "Tcl_AppendResult")) == NULL)
? -1
: 1;
} }
int get_tk(HMODULE hMod) int
{ get_tk(HMODULE hMod) {
/* /*
* Try to fill Tk global vars with function pointers. Return 0 for no * Try to fill Tk global vars with function pointers. Return 0 for no
* functions found, 1 for all functions found, -1 for some but not all * functions found, 1 for all functions found, -1 for some but not all
@ -273,26 +280,31 @@ int get_tk(HMODULE hMod)
*/ */
FARPROC func = GetProcAddress(hMod, "Tk_PhotoPutBlock"); FARPROC func = GetProcAddress(hMod, "Tk_PhotoPutBlock");
if (func == NULL) { /* Maybe not Tk module */ if (func == NULL) { /* Maybe not Tk module */
return 0; return 0;
} }
if ((TK_PHOTO_GET_IMAGE = (Tk_PhotoGetImage_t) if ((TK_PHOTO_GET_IMAGE = (Tk_PhotoGetImage_t)_dfunc(hMod, "Tk_PhotoGetImage")) ==
_dfunc(hMod, "Tk_PhotoGetImage")) == NULL) { return -1; }; NULL) {
if ((TK_FIND_PHOTO = (Tk_FindPhoto_t) return -1;
_dfunc(hMod, "Tk_FindPhoto")) == NULL) { return -1; }; };
if ((TK_FIND_PHOTO = (Tk_FindPhoto_t)_dfunc(hMod, "Tk_FindPhoto")) == NULL) {
return -1;
};
TK_LT_85 = GetProcAddress(hMod, "Tk_PhotoPutBlock_Panic") == NULL; TK_LT_85 = GetProcAddress(hMod, "Tk_PhotoPutBlock_Panic") == NULL;
/* Tk_PhotoPutBlock_Panic defined as of 8.5.0 */ /* Tk_PhotoPutBlock_Panic defined as of 8.5.0 */
if (TK_LT_85) { if (TK_LT_85) {
TK_PHOTO_PUT_BLOCK_84 = (Tk_PhotoPutBlock_84_t) func; TK_PHOTO_PUT_BLOCK_84 = (Tk_PhotoPutBlock_84_t)func;
return ((TK_PHOTO_SET_SIZE_84 = (Tk_PhotoSetSize_84_t) return ((TK_PHOTO_SET_SIZE_84 =
_dfunc(hMod, "Tk_PhotoSetSize")) == NULL) ? -1 : 1; (Tk_PhotoSetSize_84_t)_dfunc(hMod, "Tk_PhotoSetSize")) == NULL)
? -1
: 1;
} }
TK_PHOTO_PUT_BLOCK_85 = (Tk_PhotoPutBlock_85_t) func; TK_PHOTO_PUT_BLOCK_85 = (Tk_PhotoPutBlock_85_t)func;
return 1; return 1;
} }
int load_tkinter_funcs(void) int
{ load_tkinter_funcs(void) {
/* /*
* Load Tcl and Tk functions by searching all modules in current process. * Load Tcl and Tk functions by searching all modules in current process.
* Return 0 for success, non-zero for failure. * Return 0 for success, non-zero for failure.
@ -344,7 +356,7 @@ int load_tkinter_funcs(void)
return 1; return 1;
} }
#else /* not Windows */ #else /* not Windows */
/* /*
* On Unix, we can get the Tcl and Tk symbols from the tkinter module, because * On Unix, we can get the Tcl and Tk symbols from the tkinter module, because
@ -353,9 +365,9 @@ int load_tkinter_funcs(void)
*/ */
/* From module __file__ attribute to char *string for dlopen. */ /* From module __file__ attribute to char *string for dlopen. */
char *fname2char(PyObject *fname) char *
{ fname2char(PyObject *fname) {
PyObject* bytes; PyObject *bytes;
bytes = PyUnicode_EncodeFSDefault(fname); bytes = PyUnicode_EncodeFSDefault(fname);
if (bytes == NULL) { if (bytes == NULL) {
return NULL; return NULL;
@ -365,15 +377,15 @@ char *fname2char(PyObject *fname)
#include <dlfcn.h> #include <dlfcn.h>
void *_dfunc(void *lib_handle, const char *func_name) void *
{ _dfunc(void *lib_handle, const char *func_name) {
/* /*
* Load function `func_name` from `lib_handle`. * Load function `func_name` from `lib_handle`.
* Set Python exception if we can't find `func_name` in `lib_handle`. * Set Python exception if we can't find `func_name` in `lib_handle`.
* Returns function pointer or NULL if not present. * Returns function pointer or NULL if not present.
*/ */
void* func; void *func;
/* Reset errors. */ /* Reset errors. */
dlerror(); dlerror();
func = dlsym(lib_handle, func_name); func = dlsym(lib_handle, func_name);
@ -384,35 +396,44 @@ void *_dfunc(void *lib_handle, const char *func_name)
return func; return func;
} }
int _func_loader(void *lib) int
{ _func_loader(void *lib) {
/* /*
* Fill global function pointers from dynamic lib. * Fill global function pointers from dynamic lib.
* Return 1 if any pointer is NULL, 0 otherwise. * Return 1 if any pointer is NULL, 0 otherwise.
*/ */
if ((TCL_CREATE_COMMAND = (Tcl_CreateCommand_t) if ((TCL_CREATE_COMMAND = (Tcl_CreateCommand_t)_dfunc(lib, "Tcl_CreateCommand")) ==
_dfunc(lib, "Tcl_CreateCommand")) == NULL) { return 1; } NULL) {
if ((TCL_APPEND_RESULT = (Tcl_AppendResult_t) _dfunc(lib, return 1;
"Tcl_AppendResult")) == NULL) { return 1; } }
if ((TK_PHOTO_GET_IMAGE = (Tk_PhotoGetImage_t) if ((TCL_APPEND_RESULT = (Tcl_AppendResult_t)_dfunc(lib, "Tcl_AppendResult")) ==
_dfunc(lib, "Tk_PhotoGetImage")) == NULL) { return 1; } NULL) {
if ((TK_FIND_PHOTO = (Tk_FindPhoto_t) return 1;
_dfunc(lib, "Tk_FindPhoto")) == NULL) { return 1; } }
if ((TK_PHOTO_GET_IMAGE = (Tk_PhotoGetImage_t)_dfunc(lib, "Tk_PhotoGetImage")) ==
NULL) {
return 1;
}
if ((TK_FIND_PHOTO = (Tk_FindPhoto_t)_dfunc(lib, "Tk_FindPhoto")) == NULL) {
return 1;
}
/* Tk_PhotoPutBlock_Panic defined as of 8.5.0 */ /* Tk_PhotoPutBlock_Panic defined as of 8.5.0 */
TK_LT_85 = (dlsym(lib, "Tk_PhotoPutBlock_Panic") == NULL); TK_LT_85 = (dlsym(lib, "Tk_PhotoPutBlock_Panic") == NULL);
if (TK_LT_85) { if (TK_LT_85) {
return (((TK_PHOTO_PUT_BLOCK_84 = (Tk_PhotoPutBlock_84_t) return (
_dfunc(lib, "Tk_PhotoPutBlock")) == NULL) || ((TK_PHOTO_PUT_BLOCK_84 =
((TK_PHOTO_SET_SIZE_84 = (Tk_PhotoSetSize_84_t) (Tk_PhotoPutBlock_84_t)_dfunc(lib, "Tk_PhotoPutBlock")) == NULL) ||
_dfunc(lib, "Tk_PhotoSetSize")) == NULL)); ((TK_PHOTO_SET_SIZE_84 =
(Tk_PhotoSetSize_84_t)_dfunc(lib, "Tk_PhotoSetSize")) == NULL));
} }
return ((TK_PHOTO_PUT_BLOCK_85 = (Tk_PhotoPutBlock_85_t) return (
_dfunc(lib, "Tk_PhotoPutBlock")) == NULL); (TK_PHOTO_PUT_BLOCK_85 =
(Tk_PhotoPutBlock_85_t)_dfunc(lib, "Tk_PhotoPutBlock")) == NULL);
} }
int load_tkinter_funcs(void) int
{ load_tkinter_funcs(void) {
/* /*
* Load tkinter global funcs from tkinter compiled module. * Load tkinter global funcs from tkinter compiled module.
* Return 0 for success, non-zero for failure. * Return 0 for success, non-zero for failure.
@ -447,8 +468,7 @@ int load_tkinter_funcs(void)
} }
tkinter_lib = dlopen(tkinter_libname, RTLD_LAZY); tkinter_lib = dlopen(tkinter_libname, RTLD_LAZY);
if (tkinter_lib == NULL) { if (tkinter_lib == NULL) {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError, "Cannot dlopen tkinter module file");
"Cannot dlopen tkinter module file");
goto exit; goto exit;
} }
ret = _func_loader(tkinter_lib); ret = _func_loader(tkinter_lib);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -23,50 +23,51 @@
#define MAX_INT32 2147483647.0 #define MAX_INT32 2147483647.0
#define MIN_INT32 -2147483648.0 #define MIN_INT32 -2147483648.0
#define UNOP(name, op, type)\ #define UNOP(name, op, type) \
void name(Imaging out, Imaging im1)\ void name(Imaging out, Imaging im1) { \
{\ int x, y; \
int x, y;\ for (y = 0; y < out->ysize; y++) { \
for (y = 0; y < out->ysize; y++) {\ type *p0 = (type *)out->image[y]; \
type* p0 = (type*) out->image[y];\ type *p1 = (type *)im1->image[y]; \
type* p1 = (type*) im1->image[y];\ for (x = 0; x < out->xsize; x++) { \
for (x = 0; x < out->xsize; x++) {\ *p0 = op(type, *p1); \
*p0 = op(type, *p1);\ p0++; \
p0++; p1++;\ p1++; \
}\ } \
}\ } \
} }
#define BINOP(name, op, type)\ #define BINOP(name, op, type) \
void name(Imaging out, Imaging im1, Imaging im2)\ void name(Imaging out, Imaging im1, Imaging im2) { \
{\ int x, y; \
int x, y;\ for (y = 0; y < out->ysize; y++) { \
for (y = 0; y < out->ysize; y++) {\ type *p0 = (type *)out->image[y]; \
type* p0 = (type*) out->image[y];\ type *p1 = (type *)im1->image[y]; \
type* p1 = (type*) im1->image[y];\ type *p2 = (type *)im2->image[y]; \
type* p2 = (type*) im2->image[y];\ for (x = 0; x < out->xsize; x++) { \
for (x = 0; x < out->xsize; x++) {\ *p0 = op(type, *p1, *p2); \
*p0 = op(type, *p1, *p2);\ p0++; \
p0++; p1++; p2++;\ p1++; \
}\ p2++; \
}\ } \
} } \
}
#define NEG(type, v1) -(v1) #define NEG(type, v1) -(v1)
#define INVERT(type, v1) ~(v1) #define INVERT(type, v1) ~(v1)
#define ADD(type, v1, v2) (v1)+(v2) #define ADD(type, v1, v2) (v1) + (v2)
#define SUB(type, v1, v2) (v1)-(v2) #define SUB(type, v1, v2) (v1) - (v2)
#define MUL(type, v1, v2) (v1)*(v2) #define MUL(type, v1, v2) (v1) * (v2)
#define MIN(type, v1, v2) ((v1)<(v2))?(v1):(v2) #define MIN(type, v1, v2) ((v1) < (v2)) ? (v1) : (v2)
#define MAX(type, v1, v2) ((v1)>(v2))?(v1):(v2) #define MAX(type, v1, v2) ((v1) > (v2)) ? (v1) : (v2)
#define AND(type, v1, v2) (v1)&(v2) #define AND(type, v1, v2) (v1) & (v2)
#define OR(type, v1, v2) (v1)|(v2) #define OR(type, v1, v2) (v1) | (v2)
#define XOR(type, v1, v2) (v1)^(v2) #define XOR(type, v1, v2) (v1) ^ (v2)
#define LSHIFT(type, v1, v2) (v1)<<(v2) #define LSHIFT(type, v1, v2) (v1) << (v2)
#define RSHIFT(type, v1, v2) (v1)>>(v2) #define RSHIFT(type, v1, v2) (v1) >> (v2)
#define ABS_I(type, v1) abs((v1)) #define ABS_I(type, v1) abs((v1))
#define ABS_F(type, v1) fabs((v1)) #define ABS_F(type, v1) fabs((v1))
@ -79,14 +80,14 @@ void name(Imaging out, Imaging im1, Imaging im2)\
* PyFPE_END_PROTECT(result) * PyFPE_END_PROTECT(result)
*/ */
#define DIV_I(type, v1, v2) ((v2)!=0)?(v1)/(v2):0 #define DIV_I(type, v1, v2) ((v2) != 0) ? (v1) / (v2) : 0
#define DIV_F(type, v1, v2) ((v2)!=0.0F)?(v1)/(v2):0.0F #define DIV_F(type, v1, v2) ((v2) != 0.0F) ? (v1) / (v2) : 0.0F
#define MOD_I(type, v1, v2) ((v2)!=0)?(v1)%(v2):0 #define MOD_I(type, v1, v2) ((v2) != 0) ? (v1) % (v2) : 0
#define MOD_F(type, v1, v2) ((v2)!=0.0F)?fmod((v1),(v2)):0.0F #define MOD_F(type, v1, v2) ((v2) != 0.0F) ? fmod((v1), (v2)) : 0.0F
static int powi(int x, int y) static int
{ powi(int x, int y) {
double v = pow(x, y) + 0.5; double v = pow(x, y) + 0.5;
if (errno == EDOM) { if (errno == EDOM) {
return 0; return 0;
@ -96,21 +97,21 @@ static int powi(int x, int y)
} else if (v > MAX_INT32) { } else if (v > MAX_INT32) {
v = MAX_INT32; v = MAX_INT32;
} }
return (int) v; return (int)v;
} }
#define POW_I(type, v1, v2) powi(v1, v2) #define POW_I(type, v1, v2) powi(v1, v2)
#define POW_F(type, v1, v2) powf(v1, v2) /* FIXME: EDOM handling */ #define POW_F(type, v1, v2) powf(v1, v2) /* FIXME: EDOM handling */
#define DIFF_I(type, v1, v2) abs((v1)-(v2)) #define DIFF_I(type, v1, v2) abs((v1) - (v2))
#define DIFF_F(type, v1, v2) fabs((v1)-(v2)) #define DIFF_F(type, v1, v2) fabs((v1) - (v2))
#define EQ(type, v1, v2) (v1)==(v2) #define EQ(type, v1, v2) (v1) == (v2)
#define NE(type, v1, v2) (v1)!=(v2) #define NE(type, v1, v2) (v1) != (v2)
#define LT(type, v1, v2) (v1)<(v2) #define LT(type, v1, v2) (v1) < (v2)
#define LE(type, v1, v2) (v1)<=(v2) #define LE(type, v1, v2) (v1) <= (v2)
#define GT(type, v1, v2) (v1)>(v2) #define GT(type, v1, v2) (v1) > (v2)
#define GE(type, v1, v2) (v1)>=(v2) #define GE(type, v1, v2) (v1) >= (v2)
UNOP(abs_I, ABS_I, INT32) UNOP(abs_I, ABS_I, INT32)
UNOP(neg_I, NEG, INT32) UNOP(neg_I, NEG, INT32)
@ -162,8 +163,7 @@ BINOP(gt_F, GT, FLOAT32)
BINOP(ge_F, GE, FLOAT32) BINOP(ge_F, GE, FLOAT32)
static PyObject * static PyObject *
_unop(PyObject* self, PyObject* args) _unop(PyObject *self, PyObject *args) {
{
Imaging out; Imaging out;
Imaging im1; Imaging im1;
void (*unop)(Imaging, Imaging); void (*unop)(Imaging, Imaging);
@ -173,10 +173,10 @@ _unop(PyObject* self, PyObject* args)
return NULL; return NULL;
} }
out = (Imaging) i0; out = (Imaging)i0;
im1 = (Imaging) i1; im1 = (Imaging)i1;
unop = (void*) op; unop = (void *)op;
unop(out, im1); unop(out, im1);
@ -185,8 +185,7 @@ _unop(PyObject* self, PyObject* args)
} }
static PyObject * static PyObject *
_binop(PyObject* self, PyObject* args) _binop(PyObject *self, PyObject *args) {
{
Imaging out; Imaging out;
Imaging im1; Imaging im1;
Imaging im2; Imaging im2;
@ -197,11 +196,11 @@ _binop(PyObject* self, PyObject* args)
return NULL; return NULL;
} }
out = (Imaging) i0; out = (Imaging)i0;
im1 = (Imaging) i1; im1 = (Imaging)i1;
im2 = (Imaging) i2; im2 = (Imaging)i2;
binop = (void*) op; binop = (void *)op;
binop(out, im1, im2); binop(out, im1, im2);
@ -210,15 +209,11 @@ _binop(PyObject* self, PyObject* args)
} }
static PyMethodDef _functions[] = { static PyMethodDef _functions[] = {
{"unop", _unop, 1}, {"unop", _unop, 1}, {"binop", _binop, 1}, {NULL, NULL}};
{"binop", _binop, 1},
{NULL, NULL}
};
static void static void
install(PyObject *d, char* name, void* value) install(PyObject *d, char *name, void *value) {
{ PyObject *v = PyLong_FromSsize_t((Py_ssize_t)value);
PyObject *v = PyLong_FromSsize_t((Py_ssize_t) value);
if (!v || PyDict_SetItemString(d, name, v)) { if (!v || PyDict_SetItemString(d, name, v)) {
PyErr_Clear(); PyErr_Clear();
} }
@ -226,8 +221,8 @@ install(PyObject *d, char* name, void* value)
} }
static int static int
setup_module(PyObject* m) { setup_module(PyObject *m) {
PyObject* d = PyModule_GetDict(m); PyObject *d = PyModule_GetDict(m);
install(d, "abs_I", abs_I); install(d, "abs_I", abs_I);
install(d, "neg_I", neg_I); install(d, "neg_I", neg_I);
@ -279,14 +274,14 @@ setup_module(PyObject* m) {
PyMODINIT_FUNC PyMODINIT_FUNC
PyInit__imagingmath(void) { PyInit__imagingmath(void) {
PyObject* m; PyObject *m;
static PyModuleDef module_def = { static PyModuleDef module_def = {
PyModuleDef_HEAD_INIT, PyModuleDef_HEAD_INIT,
"_imagingmath", /* m_name */ "_imagingmath", /* m_name */
NULL, /* m_doc */ NULL, /* m_doc */
-1, /* m_size */ -1, /* m_size */
_functions, /* m_methods */ _functions, /* m_methods */
}; };
m = PyModule_Create(&module_def); m = PyModule_Create(&module_def);

View File

@ -14,7 +14,7 @@
#include "Python.h" #include "Python.h"
#include "libImaging/Imaging.h" #include "libImaging/Imaging.h"
#define LUT_SIZE (1<<9) #define LUT_SIZE (1 << 9)
/* Apply a morphologic LUT to a binary image. Outputs a /* Apply a morphologic LUT to a binary image. Outputs a
a new binary image. a new binary image.
@ -27,9 +27,8 @@
Returns number of changed pixels. Returns number of changed pixels.
*/ */
static PyObject* static PyObject *
apply(PyObject *self, PyObject* args) apply(PyObject *self, PyObject *args) {
{
const char *lut; const char *lut;
PyObject *py_lut; PyObject *py_lut;
Py_ssize_t lut_len, i0, i1; Py_ssize_t lut_len, i0, i1;
@ -58,18 +57,16 @@ apply(PyObject *self, PyObject* args)
lut = PyBytes_AsString(py_lut); lut = PyBytes_AsString(py_lut);
imgin = (Imaging) i0; imgin = (Imaging)i0;
imgout = (Imaging) i1; imgout = (Imaging)i1;
width = imgin->xsize; width = imgin->xsize;
height = imgin->ysize; height = imgin->ysize;
if (imgin->type != IMAGING_TYPE_UINT8 || if (imgin->type != IMAGING_TYPE_UINT8 || imgin->bands != 1) {
imgin->bands != 1) {
PyErr_SetString(PyExc_RuntimeError, "Unsupported image type"); PyErr_SetString(PyExc_RuntimeError, "Unsupported image type");
return NULL; return NULL;
} }
if (imgout->type != IMAGING_TYPE_UINT8 || if (imgout->type != IMAGING_TYPE_UINT8 || imgout->bands != 1) {
imgout->bands != 1) {
PyErr_SetString(PyExc_RuntimeError, "Unsupported image type"); PyErr_SetString(PyExc_RuntimeError, "Unsupported image type");
return NULL; return NULL;
} }
@ -77,52 +74,46 @@ apply(PyObject *self, PyObject* args)
inrows = imgin->image8; inrows = imgin->image8;
outrows = imgout->image8; outrows = imgout->image8;
for (row_idx=0; row_idx < height; row_idx++) { for (row_idx = 0; row_idx < height; row_idx++) {
UINT8 *outrow = outrows[row_idx]; UINT8 *outrow = outrows[row_idx];
UINT8 *inrow = inrows[row_idx]; UINT8 *inrow = inrows[row_idx];
UINT8 *prow, *nrow; /* Previous and next row */ UINT8 *prow, *nrow; /* Previous and next row */
/* zero boundary conditions. TBD support other modes */ /* zero boundary conditions. TBD support other modes */
outrow[0] = outrow[width-1] = 0; outrow[0] = outrow[width - 1] = 0;
if (row_idx==0 || row_idx == height-1) { if (row_idx == 0 || row_idx == height - 1) {
for(col_idx=0; col_idx<width; col_idx++) { for (col_idx = 0; col_idx < width; col_idx++) {
outrow[col_idx] = 0; outrow[col_idx] = 0;
} }
continue; continue;
} }
prow = inrows[row_idx-1]; prow = inrows[row_idx - 1];
nrow = inrows[row_idx+1]; nrow = inrows[row_idx + 1];
for (col_idx=1; col_idx<width-1; col_idx++) { for (col_idx = 1; col_idx < width - 1; col_idx++) {
int cim = col_idx-1; int cim = col_idx - 1;
int cip = col_idx+1; int cip = col_idx + 1;
unsigned char b0 = prow[cim] &1; unsigned char b0 = prow[cim] & 1;
unsigned char b1 = prow[col_idx]&1; unsigned char b1 = prow[col_idx] & 1;
unsigned char b2 = prow[cip]&1; unsigned char b2 = prow[cip] & 1;
unsigned char b3 = inrow[cim]&1; unsigned char b3 = inrow[cim] & 1;
unsigned char b4 = inrow[col_idx]&1; unsigned char b4 = inrow[col_idx] & 1;
unsigned char b5 = inrow[cip]&1; unsigned char b5 = inrow[cip] & 1;
unsigned char b6 = nrow[cim]&1; unsigned char b6 = nrow[cim] & 1;
unsigned char b7 = nrow[col_idx]&1; unsigned char b7 = nrow[col_idx] & 1;
unsigned char b8 = nrow[cip]&1; unsigned char b8 = nrow[cip] & 1;
int lut_idx = (b0 int lut_idx =
|(b1 << 1) (b0 | (b1 << 1) | (b2 << 2) | (b3 << 3) | (b4 << 4) | (b5 << 5) |
|(b2 << 2) (b6 << 6) | (b7 << 7) | (b8 << 8));
|(b3 << 3) outrow[col_idx] = 255 * (lut[lut_idx] & 1);
|(b4 << 4) num_changed_pixels += ((b4 & 1) != (outrow[col_idx] & 1));
|(b5 << 5)
|(b6 << 6)
|(b7 << 7)
|(b8 << 8));
outrow[col_idx] = 255*(lut[lut_idx]&1);
num_changed_pixels += ((b4&1)!=(outrow[col_idx]&1));
} }
} }
return Py_BuildValue("i",num_changed_pixels); return Py_BuildValue("i", num_changed_pixels);
} }
/* Match a morphologic LUT to a binary image and return a list /* Match a morphologic LUT to a binary image and return a list
@ -135,9 +126,8 @@ apply(PyObject *self, PyObject* args)
Returns list of matching pixels. Returns list of matching pixels.
*/ */
static PyObject* static PyObject *
match(PyObject *self, PyObject* args) match(PyObject *self, PyObject *args) {
{
const char *lut; const char *lut;
PyObject *py_lut; PyObject *py_lut;
Py_ssize_t lut_len, i0; Py_ssize_t lut_len, i0;
@ -165,10 +155,9 @@ match(PyObject *self, PyObject* args)
} }
lut = PyBytes_AsString(py_lut); lut = PyBytes_AsString(py_lut);
imgin = (Imaging) i0; imgin = (Imaging)i0;
if (imgin->type != IMAGING_TYPE_UINT8 || if (imgin->type != IMAGING_TYPE_UINT8 || imgin->bands != 1) {
imgin->bands != 1) {
PyErr_SetString(PyExc_RuntimeError, "Unsupported image type"); PyErr_SetString(PyExc_RuntimeError, "Unsupported image type");
return NULL; return NULL;
} }
@ -177,39 +166,33 @@ match(PyObject *self, PyObject* args)
width = imgin->xsize; width = imgin->xsize;
height = imgin->ysize; height = imgin->ysize;
for (row_idx=1; row_idx < height-1; row_idx++) { for (row_idx = 1; row_idx < height - 1; row_idx++) {
UINT8 *inrow = inrows[row_idx]; UINT8 *inrow = inrows[row_idx];
UINT8 *prow, *nrow; UINT8 *prow, *nrow;
prow = inrows[row_idx-1]; prow = inrows[row_idx - 1];
nrow = inrows[row_idx+1]; nrow = inrows[row_idx + 1];
for (col_idx=1; col_idx<width-1; col_idx++) { for (col_idx = 1; col_idx < width - 1; col_idx++) {
int cim = col_idx-1; int cim = col_idx - 1;
int cip = col_idx+1; int cip = col_idx + 1;
unsigned char b0 = prow[cim] &1; unsigned char b0 = prow[cim] & 1;
unsigned char b1 = prow[col_idx]&1; unsigned char b1 = prow[col_idx] & 1;
unsigned char b2 = prow[cip]&1; unsigned char b2 = prow[cip] & 1;
unsigned char b3 = inrow[cim]&1; unsigned char b3 = inrow[cim] & 1;
unsigned char b4 = inrow[col_idx]&1; unsigned char b4 = inrow[col_idx] & 1;
unsigned char b5 = inrow[cip]&1; unsigned char b5 = inrow[cip] & 1;
unsigned char b6 = nrow[cim]&1; unsigned char b6 = nrow[cim] & 1;
unsigned char b7 = nrow[col_idx]&1; unsigned char b7 = nrow[col_idx] & 1;
unsigned char b8 = nrow[cip]&1; unsigned char b8 = nrow[cip] & 1;
int lut_idx = (b0 int lut_idx =
|(b1 << 1) (b0 | (b1 << 1) | (b2 << 2) | (b3 << 3) | (b4 << 4) | (b5 << 5) |
|(b2 << 2) (b6 << 6) | (b7 << 7) | (b8 << 8));
|(b3 << 3)
|(b4 << 4)
|(b5 << 5)
|(b6 << 6)
|(b7 << 7)
|(b8 << 8));
if (lut[lut_idx]) { if (lut[lut_idx]) {
PyObject *coordObj = Py_BuildValue("(nn)",col_idx,row_idx); PyObject *coordObj = Py_BuildValue("(nn)", col_idx, row_idx);
PyList_Append(ret, coordObj); PyList_Append(ret, coordObj);
} }
} }
@ -222,9 +205,8 @@ match(PyObject *self, PyObject* args)
May be used to extract features after a sequence of MorphOps were applied. May be used to extract features after a sequence of MorphOps were applied.
This is faster than match as only 1x1 lookup is made. This is faster than match as only 1x1 lookup is made.
*/ */
static PyObject* static PyObject *
get_on_pixels(PyObject *self, PyObject* args) get_on_pixels(PyObject *self, PyObject *args) {
{
Py_ssize_t i0; Py_ssize_t i0;
Imaging img; Imaging img;
UINT8 **rows; UINT8 **rows;
@ -237,16 +219,16 @@ get_on_pixels(PyObject *self, PyObject* args)
return NULL; return NULL;
} }
img = (Imaging) i0; img = (Imaging)i0;
rows = img->image8; rows = img->image8;
width = img->xsize; width = img->xsize;
height = img->ysize; height = img->ysize;
for (row_idx=0; row_idx < height; row_idx++) { for (row_idx = 0; row_idx < height; row_idx++) {
UINT8 *row = rows[row_idx]; UINT8 *row = rows[row_idx];
for (col_idx=0; col_idx<width; col_idx++) { for (col_idx = 0; col_idx < width; col_idx++) {
if (row[col_idx]) { if (row[col_idx]) {
PyObject *coordObj = Py_BuildValue("(nn)",col_idx,row_idx); PyObject *coordObj = Py_BuildValue("(nn)", col_idx, row_idx);
PyList_Append(ret, coordObj); PyList_Append(ret, coordObj);
} }
} }
@ -254,11 +236,9 @@ get_on_pixels(PyObject *self, PyObject* args)
return ret; return ret;
} }
static int static int
setup_module(PyObject* m) setup_module(PyObject *m) {
{ PyObject *d = PyModule_GetDict(m);
PyObject* d = PyModule_GetDict(m);
PyDict_SetItemString(d, "__version", PyUnicode_FromString("0.1")); PyDict_SetItemString(d, "__version", PyUnicode_FromString("0.1"));
@ -270,19 +250,18 @@ static PyMethodDef functions[] = {
{"apply", (PyCFunction)apply, METH_VARARGS, NULL}, {"apply", (PyCFunction)apply, METH_VARARGS, NULL},
{"get_on_pixels", (PyCFunction)get_on_pixels, METH_VARARGS, NULL}, {"get_on_pixels", (PyCFunction)get_on_pixels, METH_VARARGS, NULL},
{"match", (PyCFunction)match, METH_VARARGS, NULL}, {"match", (PyCFunction)match, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}};
};
PyMODINIT_FUNC PyMODINIT_FUNC
PyInit__imagingmorph(void) { PyInit__imagingmorph(void) {
PyObject* m; PyObject *m;
static PyModuleDef module_def = { static PyModuleDef module_def = {
PyModuleDef_HEAD_INIT, PyModuleDef_HEAD_INIT,
"_imagingmorph", /* m_name */ "_imagingmorph", /* m_name */
"A module for doing image morphology", /* m_doc */ "A module for doing image morphology", /* m_doc */
-1, /* m_size */ -1, /* m_size */
functions, /* m_methods */ functions, /* m_methods */
}; };
m = PyModule_Create(&module_def); m = PyModule_Create(&module_def);

View File

@ -12,43 +12,42 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Python.h" #include "Python.h"
#include "libImaging/Imaging.h" #include "libImaging/Imaging.h"
#include "Tk/_tkmini.h" #include "Tk/_tkmini.h"
/* must link with Tk/tkImaging.c */ /* must link with Tk/tkImaging.c */
extern void TkImaging_Init(Tcl_Interp* interp); extern void
extern int load_tkinter_funcs(void); TkImaging_Init(Tcl_Interp *interp);
extern int
load_tkinter_funcs(void);
/* copied from _tkinter.c (this isn't as bad as it may seem: for new /* copied from _tkinter.c (this isn't as bad as it may seem: for new
versions, we use _tkinter's interpaddr hook instead, and all older versions, we use _tkinter's interpaddr hook instead, and all older
versions use this structure layout) */ versions use this structure layout) */
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD Tcl_Interp *interp;
Tcl_Interp* interp;
} TkappObject; } TkappObject;
static PyObject* static PyObject *
_tkinit(PyObject* self, PyObject* args) _tkinit(PyObject *self, PyObject *args) {
{ Tcl_Interp *interp;
Tcl_Interp* interp;
PyObject* arg; PyObject *arg;
int is_interp; int is_interp;
if (!PyArg_ParseTuple(args, "Oi", &arg, &is_interp)) { if (!PyArg_ParseTuple(args, "Oi", &arg, &is_interp)) {
return NULL; return NULL;
} }
if (is_interp) { if (is_interp) {
interp = (Tcl_Interp*)PyLong_AsVoidPtr(arg); interp = (Tcl_Interp *)PyLong_AsVoidPtr(arg);
} else { } else {
TkappObject* app; TkappObject *app;
/* Do it the hard way. This will break if the TkappObject /* Do it the hard way. This will break if the TkappObject
layout changes */ layout changes */
app = (TkappObject*)PyLong_AsVoidPtr(arg); app = (TkappObject *)PyLong_AsVoidPtr(arg);
interp = app->interp; interp = app->interp;
} }
@ -69,10 +68,10 @@ PyMODINIT_FUNC
PyInit__imagingtk(void) { PyInit__imagingtk(void) {
static PyModuleDef module_def = { static PyModuleDef module_def = {
PyModuleDef_HEAD_INIT, PyModuleDef_HEAD_INIT,
"_imagingtk", /* m_name */ "_imagingtk", /* m_name */
NULL, /* m_doc */ NULL, /* m_doc */
-1, /* m_size */ -1, /* m_size */
functions, /* m_methods */ functions, /* m_methods */
}; };
PyObject *m; PyObject *m;
m = PyModule_Create(&module_def); m = PyModule_Create(&module_def);

View File

@ -21,12 +21,14 @@
#endif #endif
void ImagingSectionEnter(ImagingSectionCookie* cookie) { void
*cookie = (PyThreadState *) PyEval_SaveThread(); ImagingSectionEnter(ImagingSectionCookie *cookie) {
*cookie = (PyThreadState *)PyEval_SaveThread();
} }
void ImagingSectionLeave(ImagingSectionCookie* cookie) { void
PyEval_RestoreThread((PyThreadState*) *cookie); ImagingSectionLeave(ImagingSectionCookie *cookie) {
PyEval_RestoreThread((PyThreadState *)*cookie);
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
@ -35,12 +37,15 @@ void ImagingSectionLeave(ImagingSectionCookie* cookie) {
#ifdef HAVE_WEBPMUX #ifdef HAVE_WEBPMUX
static const char* const kErrorMessages[-WEBP_MUX_NOT_ENOUGH_DATA + 1] = { static const char *const kErrorMessages[-WEBP_MUX_NOT_ENOUGH_DATA + 1] = {
"WEBP_MUX_NOT_FOUND", "WEBP_MUX_INVALID_ARGUMENT", "WEBP_MUX_BAD_DATA", "WEBP_MUX_NOT_FOUND",
"WEBP_MUX_MEMORY_ERROR", "WEBP_MUX_NOT_ENOUGH_DATA" "WEBP_MUX_INVALID_ARGUMENT",
}; "WEBP_MUX_BAD_DATA",
"WEBP_MUX_MEMORY_ERROR",
"WEBP_MUX_NOT_ENOUGH_DATA"};
PyObject* HandleMuxError(WebPMuxError err, char* chunk) { PyObject *
HandleMuxError(WebPMuxError err, char *chunk) {
char message[100]; char message[100];
int message_len; int message_len;
assert(err <= WEBP_MUX_NOT_FOUND && err >= WEBP_MUX_NOT_ENOUGH_DATA); assert(err <= WEBP_MUX_NOT_FOUND && err >= WEBP_MUX_NOT_ENOUGH_DATA);
@ -52,9 +57,11 @@ PyObject* HandleMuxError(WebPMuxError err, char* chunk) {
// Create the error message // Create the error message
if (chunk == NULL) { if (chunk == NULL) {
message_len = sprintf(message, "could not assemble chunks: %s", kErrorMessages[-err]); message_len =
sprintf(message, "could not assemble chunks: %s", kErrorMessages[-err]);
} else { } else {
message_len = sprintf(message, "could not set %.4s chunk: %s", chunk, kErrorMessages[-err]); message_len = sprintf(
message, "could not set %.4s chunk: %s", chunk, kErrorMessages[-err]);
} }
if (message_len < 0) { if (message_len < 0) {
PyErr_SetString(PyExc_RuntimeError, "failed to construct error message"); PyErr_SetString(PyExc_RuntimeError, "failed to construct error message");
@ -90,8 +97,7 @@ PyObject* HandleMuxError(WebPMuxError err, char* chunk) {
// Encoder type // Encoder type
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD WebPAnimEncoder *enc;
WebPAnimEncoder* enc;
WebPPicture frame; WebPPicture frame;
} WebPAnimEncoderObject; } WebPAnimEncoderObject;
@ -99,18 +105,17 @@ static PyTypeObject WebPAnimEncoder_Type;
// Decoder type // Decoder type
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD WebPAnimDecoder *dec;
WebPAnimDecoder* dec;
WebPAnimInfo info; WebPAnimInfo info;
WebPData data; WebPData data;
char* mode; char *mode;
} WebPAnimDecoderObject; } WebPAnimDecoderObject;
static PyTypeObject WebPAnimDecoder_Type; static PyTypeObject WebPAnimDecoder_Type;
// Encoder functions // Encoder functions
PyObject* _anim_encoder_new(PyObject* self, PyObject* args) PyObject *
{ _anim_encoder_new(PyObject *self, PyObject *args) {
int width, height; int width, height;
uint32_t bgcolor; uint32_t bgcolor;
int loop_count; int loop_count;
@ -119,12 +124,21 @@ PyObject* _anim_encoder_new(PyObject* self, PyObject* args)
int allow_mixed; int allow_mixed;
int verbose; int verbose;
WebPAnimEncoderOptions enc_options; WebPAnimEncoderOptions enc_options;
WebPAnimEncoderObject* encp = NULL; WebPAnimEncoderObject *encp = NULL;
WebPAnimEncoder* enc = NULL; WebPAnimEncoder *enc = NULL;
if (!PyArg_ParseTuple(args, "iiIiiiiii", if (!PyArg_ParseTuple(
&width, &height, &bgcolor, &loop_count, &minimize_size, args,
&kmin, &kmax, &allow_mixed, &verbose)) { "iiIiiiiii",
&width,
&height,
&bgcolor,
&loop_count,
&minimize_size,
&kmin,
&kmax,
&allow_mixed,
&verbose)) {
return NULL; return NULL;
} }
@ -154,7 +168,7 @@ PyObject* _anim_encoder_new(PyObject* self, PyObject* args)
enc = WebPAnimEncoderNew(width, height, &enc_options); enc = WebPAnimEncoderNew(width, height, &enc_options);
if (enc) { if (enc) {
encp->enc = enc; encp->enc = enc;
return (PyObject*) encp; return (PyObject *)encp;
} }
WebPPictureFree(&(encp->frame)); WebPPictureFree(&(encp->frame));
} }
@ -164,33 +178,42 @@ PyObject* _anim_encoder_new(PyObject* self, PyObject* args)
return NULL; return NULL;
} }
PyObject* _anim_encoder_dealloc(PyObject* self) PyObject *
{ _anim_encoder_dealloc(PyObject *self) {
WebPAnimEncoderObject* encp = (WebPAnimEncoderObject*)self; WebPAnimEncoderObject *encp = (WebPAnimEncoderObject *)self;
WebPPictureFree(&(encp->frame)); WebPPictureFree(&(encp->frame));
WebPAnimEncoderDelete(encp->enc); WebPAnimEncoderDelete(encp->enc);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PyObject* _anim_encoder_add(PyObject* self, PyObject* args) PyObject *
{ _anim_encoder_add(PyObject *self, PyObject *args) {
uint8_t* rgb; uint8_t *rgb;
Py_ssize_t size; Py_ssize_t size;
int timestamp; int timestamp;
int width; int width;
int height; int height;
char* mode; char *mode;
int lossless; int lossless;
float quality_factor; float quality_factor;
int method; int method;
WebPConfig config; WebPConfig config;
WebPAnimEncoderObject* encp = (WebPAnimEncoderObject*)self; WebPAnimEncoderObject *encp = (WebPAnimEncoderObject *)self;
WebPAnimEncoder* enc = encp->enc; WebPAnimEncoder *enc = encp->enc;
WebPPicture* frame = &(encp->frame); WebPPicture *frame = &(encp->frame);
if (!PyArg_ParseTuple(args, "z#iiisifi", if (!PyArg_ParseTuple(
(char**)&rgb, &size, &timestamp, &width, &height, &mode, args,
&lossless, &quality_factor, &method)) { "z#iiisifi",
(char **)&rgb,
&size,
&timestamp,
&width,
&height,
&mode,
&lossless,
&quality_factor,
&method)) {
return NULL; return NULL;
} }
@ -218,10 +241,10 @@ PyObject* _anim_encoder_add(PyObject* self, PyObject* args)
// Populate the frame with raw bytes passed to us // Populate the frame with raw bytes passed to us
frame->width = width; frame->width = width;
frame->height = height; frame->height = height;
frame->use_argb = 1; // Don't convert RGB pixels to YUV frame->use_argb = 1; // Don't convert RGB pixels to YUV
if (strcmp(mode, "RGBA")==0) { if (strcmp(mode, "RGBA") == 0) {
WebPPictureImportRGBA(frame, rgb, 4 * width); WebPPictureImportRGBA(frame, rgb, 4 * width);
} else if (strcmp(mode, "RGBX")==0) { } else if (strcmp(mode, "RGBX") == 0) {
WebPPictureImportRGBX(frame, rgb, 4 * width); WebPPictureImportRGBX(frame, rgb, 4 * width);
} else { } else {
WebPPictureImportRGB(frame, rgb, 3 * width); WebPPictureImportRGB(frame, rgb, 3 * width);
@ -236,22 +259,29 @@ PyObject* _anim_encoder_add(PyObject* self, PyObject* args)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PyObject* _anim_encoder_assemble(PyObject* self, PyObject* args) PyObject *
{ _anim_encoder_assemble(PyObject *self, PyObject *args) {
uint8_t* icc_bytes; uint8_t *icc_bytes;
uint8_t* exif_bytes; uint8_t *exif_bytes;
uint8_t* xmp_bytes; uint8_t *xmp_bytes;
Py_ssize_t icc_size; Py_ssize_t icc_size;
Py_ssize_t exif_size; Py_ssize_t exif_size;
Py_ssize_t xmp_size; Py_ssize_t xmp_size;
WebPData webp_data; WebPData webp_data;
WebPAnimEncoderObject* encp = (WebPAnimEncoderObject*)self; WebPAnimEncoderObject *encp = (WebPAnimEncoderObject *)self;
WebPAnimEncoder* enc = encp->enc; WebPAnimEncoder *enc = encp->enc;
WebPMux* mux = NULL; WebPMux *mux = NULL;
PyObject* ret = NULL; PyObject *ret = NULL;
if (!PyArg_ParseTuple(args, "s#s#s#", if (!PyArg_ParseTuple(
&icc_bytes, &icc_size, &exif_bytes, &exif_size, &xmp_bytes, &xmp_size)) { args,
"s#s#s#",
&icc_bytes,
&icc_size,
&exif_bytes,
&exif_size,
&xmp_bytes,
&xmp_size)) {
return NULL; return NULL;
} }
@ -270,9 +300,9 @@ PyObject* _anim_encoder_assemble(PyObject* self, PyObject* args)
int i_icc_size = (int)icc_size; int i_icc_size = (int)icc_size;
int i_exif_size = (int)exif_size; int i_exif_size = (int)exif_size;
int i_xmp_size = (int)xmp_size; int i_xmp_size = (int)xmp_size;
WebPData icc_profile = { icc_bytes, i_icc_size }; WebPData icc_profile = {icc_bytes, i_icc_size};
WebPData exif = { exif_bytes, i_exif_size }; WebPData exif = {exif_bytes, i_exif_size};
WebPData xmp = { xmp_bytes, i_xmp_size }; WebPData xmp = {xmp_bytes, i_xmp_size};
mux = WebPMuxCreate(&webp_data, 1); mux = WebPMuxCreate(&webp_data, 1);
if (mux == NULL) { if (mux == NULL) {
@ -312,7 +342,7 @@ PyObject* _anim_encoder_assemble(PyObject* self, PyObject* args)
} }
// Convert to Python bytes // Convert to Python bytes
ret = PyBytes_FromStringAndSize((char*)webp_data.bytes, webp_data.size); ret = PyBytes_FromStringAndSize((char *)webp_data.bytes, webp_data.size);
WebPDataClear(&webp_data); WebPDataClear(&webp_data);
// If we had to re-mux, we should free it now that we're done with it // If we had to re-mux, we should free it now that we're done with it
@ -324,21 +354,21 @@ PyObject* _anim_encoder_assemble(PyObject* self, PyObject* args)
} }
// Decoder functions // Decoder functions
PyObject* _anim_decoder_new(PyObject* self, PyObject* args) PyObject *
{ _anim_decoder_new(PyObject *self, PyObject *args) {
PyBytesObject *webp_string; PyBytesObject *webp_string;
const uint8_t *webp; const uint8_t *webp;
Py_ssize_t size; Py_ssize_t size;
WebPData webp_src; WebPData webp_src;
char* mode; char *mode;
WebPDecoderConfig config; WebPDecoderConfig config;
WebPAnimDecoderObject* decp = NULL; WebPAnimDecoderObject *decp = NULL;
WebPAnimDecoder* dec = NULL; WebPAnimDecoder *dec = NULL;
if (!PyArg_ParseTuple(args, "S", &webp_string)) { if (!PyArg_ParseTuple(args, "S", &webp_string)) {
return NULL; return NULL;
} }
PyBytes_AsStringAndSize((PyObject *)webp_string, (char**)&webp, &size); PyBytes_AsStringAndSize((PyObject *)webp_string, (char **)&webp, &size);
webp_src.bytes = webp; webp_src.bytes = webp;
webp_src.size = size; webp_src.size = size;
@ -359,7 +389,7 @@ PyObject* _anim_decoder_new(PyObject* self, PyObject* args)
if (dec) { if (dec) {
if (WebPAnimDecoderGetInfo(dec, &(decp->info))) { if (WebPAnimDecoderGetInfo(dec, &(decp->info))) {
decp->dec = dec; decp->dec = dec;
return (PyObject*)decp; return (PyObject *)decp;
} }
} }
} }
@ -369,33 +399,34 @@ PyObject* _anim_decoder_new(PyObject* self, PyObject* args)
return NULL; return NULL;
} }
PyObject* _anim_decoder_dealloc(PyObject* self) PyObject *
{ _anim_decoder_dealloc(PyObject *self) {
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject *)self; WebPAnimDecoderObject *decp = (WebPAnimDecoderObject *)self;
WebPDataClear(&(decp->data)); WebPDataClear(&(decp->data));
WebPAnimDecoderDelete(decp->dec); WebPAnimDecoderDelete(decp->dec);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PyObject* _anim_decoder_get_info(PyObject* self) PyObject *
{ _anim_decoder_get_info(PyObject *self) {
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject *)self; WebPAnimDecoderObject *decp = (WebPAnimDecoderObject *)self;
WebPAnimInfo* info = &(decp->info); WebPAnimInfo *info = &(decp->info);
return Py_BuildValue("IIIIIs", return Py_BuildValue(
info->canvas_width, info->canvas_height, "IIIIIs",
info->canvas_width,
info->canvas_height,
info->loop_count, info->loop_count,
info->bgcolor, info->bgcolor,
info->frame_count, info->frame_count,
decp->mode decp->mode);
);
} }
PyObject* _anim_decoder_get_chunk(PyObject* self, PyObject* args) PyObject *
{ _anim_decoder_get_chunk(PyObject *self, PyObject *args) {
char* mode; char *mode;
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject *)self; WebPAnimDecoderObject *decp = (WebPAnimDecoderObject *)self;
const WebPDemuxer* demux; const WebPDemuxer *demux;
WebPChunkIterator iter; WebPChunkIterator iter;
PyObject *ret; PyObject *ret;
@ -408,27 +439,27 @@ PyObject* _anim_decoder_get_chunk(PyObject* self, PyObject* args)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
ret = PyBytes_FromStringAndSize((const char*)iter.chunk.bytes, iter.chunk.size); ret = PyBytes_FromStringAndSize((const char *)iter.chunk.bytes, iter.chunk.size);
WebPDemuxReleaseChunkIterator(&iter); WebPDemuxReleaseChunkIterator(&iter);
return ret; return ret;
} }
PyObject* _anim_decoder_get_next(PyObject* self) PyObject *
{ _anim_decoder_get_next(PyObject *self) {
uint8_t* buf; uint8_t *buf;
int timestamp; int timestamp;
PyObject* bytes; PyObject *bytes;
PyObject* ret; PyObject *ret;
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject*)self; WebPAnimDecoderObject *decp = (WebPAnimDecoderObject *)self;
if (!WebPAnimDecoderGetNext(decp->dec, &buf, &timestamp)) { if (!WebPAnimDecoderGetNext(decp->dec, &buf, &timestamp)) {
PyErr_SetString(PyExc_OSError, "failed to read next frame"); PyErr_SetString(PyExc_OSError, "failed to read next frame");
return NULL; return NULL;
} }
bytes = PyBytes_FromStringAndSize((char *)buf, bytes = PyBytes_FromStringAndSize(
decp->info.canvas_width * 4 * decp->info.canvas_height); (char *)buf, decp->info.canvas_width * 4 * decp->info.canvas_height);
ret = Py_BuildValue("Si", bytes, timestamp); ret = Py_BuildValue("Si", bytes, timestamp);
@ -436,9 +467,9 @@ PyObject* _anim_decoder_get_next(PyObject* self)
return ret; return ret;
} }
PyObject* _anim_decoder_reset(PyObject* self) PyObject *
{ _anim_decoder_reset(PyObject *self) {
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject *)self; WebPAnimDecoderObject *decp = (WebPAnimDecoderObject *)self;
WebPAnimDecoderReset(decp->dec); WebPAnimDecoderReset(decp->dec);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@ -456,37 +487,36 @@ static struct PyMethodDef _anim_encoder_methods[] = {
// WebPAnimDecoder type definition // WebPAnimDecoder type definition
static PyTypeObject WebPAnimEncoder_Type = { static PyTypeObject WebPAnimEncoder_Type = {
PyVarObject_HEAD_INIT(NULL, 0) PyVarObject_HEAD_INIT(NULL, 0) "WebPAnimEncoder", /*tp_name */
"WebPAnimEncoder", /*tp_name */ sizeof(WebPAnimEncoderObject), /*tp_size */
sizeof(WebPAnimEncoderObject), /*tp_size */ 0, /*tp_itemsize */
0, /*tp_itemsize */
/* methods */ /* methods */
(destructor)_anim_encoder_dealloc, /*tp_dealloc*/ (destructor)_anim_encoder_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
0, /*tp_repr*/ 0, /*tp_repr*/
0, /*tp_as_number */ 0, /*tp_as_number */
0, /*tp_as_sequence */ 0, /*tp_as_sequence */
0, /*tp_as_mapping */ 0, /*tp_as_mapping */
0, /*tp_hash*/ 0, /*tp_hash*/
0, /*tp_call*/ 0, /*tp_call*/
0, /*tp_str*/ 0, /*tp_str*/
0, /*tp_getattro*/ 0, /*tp_getattro*/
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/ 0, /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
0, /*tp_richcompare*/ 0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/ 0, /*tp_weaklistoffset*/
0, /*tp_iter*/ 0, /*tp_iter*/
0, /*tp_iternext*/ 0, /*tp_iternext*/
_anim_encoder_methods, /*tp_methods*/ _anim_encoder_methods, /*tp_methods*/
0, /*tp_members*/ 0, /*tp_members*/
0, /*tp_getset*/ 0, /*tp_getset*/
}; };
// WebPAnimDecoder methods // WebPAnimDecoder methods
@ -500,37 +530,36 @@ static struct PyMethodDef _anim_decoder_methods[] = {
// WebPAnimDecoder type definition // WebPAnimDecoder type definition
static PyTypeObject WebPAnimDecoder_Type = { static PyTypeObject WebPAnimDecoder_Type = {
PyVarObject_HEAD_INIT(NULL, 0) PyVarObject_HEAD_INIT(NULL, 0) "WebPAnimDecoder", /*tp_name */
"WebPAnimDecoder", /*tp_name */ sizeof(WebPAnimDecoderObject), /*tp_size */
sizeof(WebPAnimDecoderObject), /*tp_size */ 0, /*tp_itemsize */
0, /*tp_itemsize */
/* methods */ /* methods */
(destructor)_anim_decoder_dealloc, /*tp_dealloc*/ (destructor)_anim_decoder_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
0, /*tp_repr*/ 0, /*tp_repr*/
0, /*tp_as_number */ 0, /*tp_as_number */
0, /*tp_as_sequence */ 0, /*tp_as_sequence */
0, /*tp_as_mapping */ 0, /*tp_as_mapping */
0, /*tp_hash*/ 0, /*tp_hash*/
0, /*tp_call*/ 0, /*tp_call*/
0, /*tp_str*/ 0, /*tp_str*/
0, /*tp_getattro*/ 0, /*tp_getattro*/
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/ 0, /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
0, /*tp_richcompare*/ 0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/ 0, /*tp_weaklistoffset*/
0, /*tp_iter*/ 0, /*tp_iter*/
0, /*tp_iternext*/ 0, /*tp_iternext*/
_anim_decoder_methods, /*tp_methods*/ _anim_decoder_methods, /*tp_methods*/
0, /*tp_members*/ 0, /*tp_members*/
0, /*tp_getset*/ 0, /*tp_getset*/
}; };
#endif #endif
@ -539,19 +568,19 @@ static PyTypeObject WebPAnimDecoder_Type = {
/* Legacy WebP Support */ /* Legacy WebP Support */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args) PyObject *
{ WebPEncode_wrapper(PyObject *self, PyObject *args) {
int width; int width;
int height; int height;
int lossless; int lossless;
float quality_factor; float quality_factor;
int method; int method;
uint8_t* rgb; uint8_t *rgb;
uint8_t* icc_bytes; uint8_t *icc_bytes;
uint8_t* exif_bytes; uint8_t *exif_bytes;
uint8_t* xmp_bytes; uint8_t *xmp_bytes;
uint8_t* output; uint8_t *output;
char* mode; char *mode;
Py_ssize_t size; Py_ssize_t size;
Py_ssize_t icc_size; Py_ssize_t icc_size;
Py_ssize_t exif_size; Py_ssize_t exif_size;
@ -565,9 +594,23 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args)
WebPMemoryWriter writer; WebPMemoryWriter writer;
WebPPicture pic; WebPPicture pic;
if (!PyArg_ParseTuple(args, "y#iiifss#is#s#", if (!PyArg_ParseTuple(
(char**)&rgb, &size, &width, &height, &lossless, &quality_factor, &mode, args,
&icc_bytes, &icc_size, &method, &exif_bytes, &exif_size, &xmp_bytes, &xmp_size)) { "y#iiifss#is#s#",
(char **)&rgb,
&size,
&width,
&height,
&lossless,
&quality_factor,
&mode,
&icc_bytes,
&icc_size,
&method,
&exif_bytes,
&exif_size,
&xmp_bytes,
&xmp_size)) {
return NULL; return NULL;
} }
@ -602,7 +645,7 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args)
} }
pic.width = width; pic.width = width;
pic.height = height; pic.height = height;
pic.use_argb = 1; // Don't convert RGB pixels to YUV pic.use_argb = 1; // Don't convert RGB pixels to YUV
if (rgba_mode) { if (rgba_mode) {
WebPPictureImportRGBA(&pic, rgb, channels * width); WebPPictureImportRGBA(&pic, rgb, channels * width);
@ -628,98 +671,100 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args)
#ifndef HAVE_WEBPMUX #ifndef HAVE_WEBPMUX
if (ret_size > 0) { if (ret_size > 0) {
PyObject *ret = PyBytes_FromStringAndSize((char*)output, ret_size); PyObject *ret = PyBytes_FromStringAndSize((char *)output, ret_size);
free(output); free(output);
return ret; return ret;
} }
#else #else
{ {
/* I want to truncate the *_size items that get passed into WebP /* I want to truncate the *_size items that get passed into WebP
data. Pypy2.1.0 had some issues where the Py_ssize_t items had data. Pypy2.1.0 had some issues where the Py_ssize_t items had
data in the upper byte. (Not sure why, it shouldn't have been there) data in the upper byte. (Not sure why, it shouldn't have been there)
*/ */
int i_icc_size = (int)icc_size; int i_icc_size = (int)icc_size;
int i_exif_size = (int)exif_size; int i_exif_size = (int)exif_size;
int i_xmp_size = (int)xmp_size; int i_xmp_size = (int)xmp_size;
WebPData output_data = {0}; WebPData output_data = {0};
WebPData image = { output, ret_size }; WebPData image = {output, ret_size};
WebPData icc_profile = { icc_bytes, i_icc_size }; WebPData icc_profile = {icc_bytes, i_icc_size};
WebPData exif = { exif_bytes, i_exif_size }; WebPData exif = {exif_bytes, i_exif_size};
WebPData xmp = { xmp_bytes, i_xmp_size }; WebPData xmp = {xmp_bytes, i_xmp_size};
WebPMuxError err; WebPMuxError err;
int dbg = 0; int dbg = 0;
int copy_data = 0; // value 1 indicates given data WILL be copied to the mux int copy_data = 0; // value 1 indicates given data WILL be copied to the mux
// and value 0 indicates data will NOT be copied. // and value 0 indicates data will NOT be copied.
WebPMux* mux = WebPMuxNew(); WebPMux *mux = WebPMuxNew();
WebPMuxSetImage(mux, &image, copy_data); WebPMuxSetImage(mux, &image, copy_data);
if (dbg) {
/* was getting %ld icc_size == 0, icc_size>0 was true */
fprintf(stderr, "icc size %d, %d \n", i_icc_size, i_icc_size > 0);
}
if (i_icc_size > 0) {
if (dbg) { if (dbg) {
fprintf(stderr, "Adding ICC Profile\n"); /* was getting %ld icc_size == 0, icc_size>0 was true */
fprintf(stderr, "icc size %d, %d \n", i_icc_size, i_icc_size > 0);
}
if (i_icc_size > 0) {
if (dbg) {
fprintf(stderr, "Adding ICC Profile\n");
}
err = WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data);
if (err != WEBP_MUX_OK) {
return HandleMuxError(err, "ICCP");
}
} }
err = WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data);
if (err != WEBP_MUX_OK) {
return HandleMuxError(err, "ICCP");
}
}
if (dbg) {
fprintf(stderr, "exif size %d \n", i_exif_size);
}
if (i_exif_size > 0) {
if (dbg) { if (dbg) {
fprintf(stderr, "Adding Exif Data\n"); fprintf(stderr, "exif size %d \n", i_exif_size);
} }
err = WebPMuxSetChunk(mux, "EXIF", &exif, copy_data); if (i_exif_size > 0) {
if (err != WEBP_MUX_OK) { if (dbg) {
return HandleMuxError(err, "EXIF"); fprintf(stderr, "Adding Exif Data\n");
}
err = WebPMuxSetChunk(mux, "EXIF", &exif, copy_data);
if (err != WEBP_MUX_OK) {
return HandleMuxError(err, "EXIF");
}
} }
}
if (dbg) { if (dbg) {
fprintf(stderr, "xmp size %d \n", i_xmp_size); fprintf(stderr, "xmp size %d \n", i_xmp_size);
}
if (i_xmp_size > 0) {
if (dbg){
fprintf(stderr, "Adding XMP Data\n");
} }
err = WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data); if (i_xmp_size > 0) {
if (err != WEBP_MUX_OK) { if (dbg) {
return HandleMuxError(err, "XMP "); fprintf(stderr, "Adding XMP Data\n");
}
err = WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data);
if (err != WEBP_MUX_OK) {
return HandleMuxError(err, "XMP ");
}
} }
}
WebPMuxAssemble(mux, &output_data); WebPMuxAssemble(mux, &output_data);
WebPMuxDelete(mux); WebPMuxDelete(mux);
free(output); free(output);
ret_size = output_data.size; ret_size = output_data.size;
if (ret_size > 0) { if (ret_size > 0) {
PyObject *ret = PyBytes_FromStringAndSize((char*)output_data.bytes, ret_size); PyObject *ret =
WebPDataClear(&output_data); PyBytes_FromStringAndSize((char *)output_data.bytes, ret_size);
return ret; WebPDataClear(&output_data);
} return ret;
}
} }
#endif #endif
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args) PyObject *
{ WebPDecode_wrapper(PyObject *self, PyObject *args) {
PyBytesObject* webp_string; PyBytesObject *webp_string;
const uint8_t* webp; const uint8_t *webp;
Py_ssize_t size; Py_ssize_t size;
PyObject *ret = Py_None, *bytes = NULL, *pymode = NULL, *icc_profile = NULL, *exif = NULL; PyObject *ret = Py_None, *bytes = NULL, *pymode = NULL, *icc_profile = NULL,
*exif = NULL;
WebPDecoderConfig config; WebPDecoderConfig config;
VP8StatusCode vp8_status_code = VP8_STATUS_OK; VP8StatusCode vp8_status_code = VP8_STATUS_OK;
char* mode = "RGB"; char *mode = "RGB";
if (!PyArg_ParseTuple(args, "S", &webp_string)) { if (!PyArg_ParseTuple(args, "S", &webp_string)) {
return NULL; return NULL;
@ -729,7 +774,7 @@ PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PyBytes_AsStringAndSize((PyObject*) webp_string, (char**)&webp, &size); PyBytes_AsStringAndSize((PyObject *)webp_string, (char **)&webp, &size);
vp8_status_code = WebPGetFeatures(webp, size, &config.input); vp8_status_code = WebPGetFeatures(webp, size, &config.input);
if (vp8_status_code == VP8_STATUS_OK) { if (vp8_status_code == VP8_STATUS_OK) {
@ -743,39 +788,40 @@ PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args)
#ifndef HAVE_WEBPMUX #ifndef HAVE_WEBPMUX
vp8_status_code = WebPDecode(webp, size, &config); vp8_status_code = WebPDecode(webp, size, &config);
#else #else
{
int copy_data = 0;
WebPData data = { webp, size };
WebPMuxFrameInfo image;
WebPData icc_profile_data = {0};
WebPData exif_data = {0};
WebPMux* mux = WebPMuxCreate(&data, copy_data);
if (NULL == mux) {
goto end;
}
if (WEBP_MUX_OK != WebPMuxGetFrame(mux, 1, &image))
{ {
int copy_data = 0;
WebPData data = {webp, size};
WebPMuxFrameInfo image;
WebPData icc_profile_data = {0};
WebPData exif_data = {0};
WebPMux *mux = WebPMuxCreate(&data, copy_data);
if (NULL == mux) {
goto end;
}
if (WEBP_MUX_OK != WebPMuxGetFrame(mux, 1, &image)) {
WebPMuxDelete(mux);
goto end;
}
webp = image.bitstream.bytes;
size = image.bitstream.size;
vp8_status_code = WebPDecode(webp, size, &config);
if (WEBP_MUX_OK == WebPMuxGetChunk(mux, "ICCP", &icc_profile_data)) {
icc_profile = PyBytes_FromStringAndSize(
(const char *)icc_profile_data.bytes, icc_profile_data.size);
}
if (WEBP_MUX_OK == WebPMuxGetChunk(mux, "EXIF", &exif_data)) {
exif = PyBytes_FromStringAndSize(
(const char *)exif_data.bytes, exif_data.size);
}
WebPDataClear(&image.bitstream);
WebPMuxDelete(mux); WebPMuxDelete(mux);
goto end;
}
webp = image.bitstream.bytes;
size = image.bitstream.size;
vp8_status_code = WebPDecode(webp, size, &config);
if (WEBP_MUX_OK == WebPMuxGetChunk(mux, "ICCP", &icc_profile_data)) {
icc_profile = PyBytes_FromStringAndSize((const char*)icc_profile_data.bytes, icc_profile_data.size);
}
if (WEBP_MUX_OK == WebPMuxGetChunk(mux, "EXIF", &exif_data)) {
exif = PyBytes_FromStringAndSize((const char*)exif_data.bytes, exif_data.size);
}
WebPDataClear(&image.bitstream);
WebPMuxDelete(mux);
} }
#endif #endif
} }
@ -785,20 +831,24 @@ PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args)
} }
if (config.output.colorspace < MODE_YUV) { if (config.output.colorspace < MODE_YUV) {
bytes = PyBytes_FromStringAndSize((char*)config.output.u.RGBA.rgba, bytes = PyBytes_FromStringAndSize(
config.output.u.RGBA.size); (char *)config.output.u.RGBA.rgba, config.output.u.RGBA.size);
} else { } else {
// Skipping YUV for now. Need Test Images. // Skipping YUV for now. Need Test Images.
// UNDONE -- unclear if we'll ever get here if we set mode_rgb* // UNDONE -- unclear if we'll ever get here if we set mode_rgb*
bytes = PyBytes_FromStringAndSize((char*)config.output.u.YUVA.y, bytes = PyBytes_FromStringAndSize(
config.output.u.YUVA.y_size); (char *)config.output.u.YUVA.y, config.output.u.YUVA.y_size);
} }
pymode = PyUnicode_FromString(mode); pymode = PyUnicode_FromString(mode);
ret = Py_BuildValue("SiiSSS", bytes, config.output.width, ret = Py_BuildValue(
config.output.height, pymode, "SiiSSS",
NULL == icc_profile ? Py_None : icc_profile, bytes,
NULL == exif ? Py_None : exif); config.output.width,
config.output.height,
pymode,
NULL == icc_profile ? Py_None : icc_profile,
NULL == exif ? Py_None : exif);
end: end:
WebPFreeDecBuffer(&config.output); WebPFreeDecBuffer(&config.output);
@ -817,17 +867,22 @@ end:
// Return the decoder's version number, packed in hexadecimal using 8bits for // Return the decoder's version number, packed in hexadecimal using 8bits for
// each of major/minor/revision. E.g: v2.5.7 is 0x020507. // each of major/minor/revision. E.g: v2.5.7 is 0x020507.
PyObject* WebPDecoderVersion_wrapper() { PyObject *
WebPDecoderVersion_wrapper() {
return Py_BuildValue("i", WebPGetDecoderVersion()); return Py_BuildValue("i", WebPGetDecoderVersion());
} }
// Version as string // Version as string
const char* const char *
WebPDecoderVersion_str(void) WebPDecoderVersion_str(void) {
{
static char version[20]; static char version[20];
int version_number = WebPGetDecoderVersion(); int version_number = WebPGetDecoderVersion();
sprintf(version, "%d.%d.%d", version_number >> 16, (version_number >> 8) % 0x100, version_number % 0x100); sprintf(
version,
"%d.%d.%d",
version_number >> 16,
(version_number >> 8) % 0x100,
version_number % 0x100);
return version; return version;
} }
@ -835,11 +890,13 @@ WebPDecoderVersion_str(void)
* The version of webp that ships with (0.1.3) Ubuntu 12.04 doesn't handle alpha well. * The version of webp that ships with (0.1.3) Ubuntu 12.04 doesn't handle alpha well.
* Files that are valid with 0.3 are reported as being invalid. * Files that are valid with 0.3 are reported as being invalid.
*/ */
int WebPDecoderBuggyAlpha(void) { int
return WebPGetDecoderVersion()==0x0103; WebPDecoderBuggyAlpha(void) {
return WebPGetDecoderVersion() == 0x0103;
} }
PyObject* WebPDecoderBuggyAlpha_wrapper() { PyObject *
WebPDecoderBuggyAlpha_wrapper() {
return Py_BuildValue("i", WebPDecoderBuggyAlpha()); return Py_BuildValue("i", WebPDecoderBuggyAlpha());
} }
@ -847,8 +904,7 @@ PyObject* WebPDecoderBuggyAlpha_wrapper() {
/* Module Setup */ /* Module Setup */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
static PyMethodDef webpMethods[] = static PyMethodDef webpMethods[] = {
{
#ifdef HAVE_WEBPANIM #ifdef HAVE_WEBPANIM
{"WebPAnimDecoder", _anim_decoder_new, METH_VARARGS, "WebPAnimDecoder"}, {"WebPAnimDecoder", _anim_decoder_new, METH_VARARGS, "WebPAnimDecoder"},
{"WebPAnimEncoder", _anim_encoder_new, METH_VARARGS, "WebPAnimEncoder"}, {"WebPAnimEncoder", _anim_encoder_new, METH_VARARGS, "WebPAnimEncoder"},
@ -856,11 +912,14 @@ static PyMethodDef webpMethods[] =
{"WebPEncode", WebPEncode_wrapper, METH_VARARGS, "WebPEncode"}, {"WebPEncode", WebPEncode_wrapper, METH_VARARGS, "WebPEncode"},
{"WebPDecode", WebPDecode_wrapper, METH_VARARGS, "WebPDecode"}, {"WebPDecode", WebPDecode_wrapper, METH_VARARGS, "WebPDecode"},
{"WebPDecoderVersion", WebPDecoderVersion_wrapper, METH_NOARGS, "WebPVersion"}, {"WebPDecoderVersion", WebPDecoderVersion_wrapper, METH_NOARGS, "WebPVersion"},
{"WebPDecoderBuggyAlpha", WebPDecoderBuggyAlpha_wrapper, METH_NOARGS, "WebPDecoderBuggyAlpha"}, {"WebPDecoderBuggyAlpha",
{NULL, NULL} WebPDecoderBuggyAlpha_wrapper,
}; METH_NOARGS,
"WebPDecoderBuggyAlpha"},
{NULL, NULL}};
void addMuxFlagToModule(PyObject* m) { void
addMuxFlagToModule(PyObject *m) {
#ifdef HAVE_WEBPMUX #ifdef HAVE_WEBPMUX
PyModule_AddObject(m, "HAVE_WEBPMUX", Py_True); PyModule_AddObject(m, "HAVE_WEBPMUX", Py_True);
#else #else
@ -868,7 +927,8 @@ void addMuxFlagToModule(PyObject* m) {
#endif #endif
} }
void addAnimFlagToModule(PyObject* m) { void
addAnimFlagToModule(PyObject *m) {
#ifdef HAVE_WEBPANIM #ifdef HAVE_WEBPANIM
PyModule_AddObject(m, "HAVE_WEBPANIM", Py_True); PyModule_AddObject(m, "HAVE_WEBPANIM", Py_True);
#else #else
@ -876,18 +936,21 @@ void addAnimFlagToModule(PyObject* m) {
#endif #endif
} }
void addTransparencyFlagToModule(PyObject* m) { void
PyModule_AddObject(m, "HAVE_TRANSPARENCY", addTransparencyFlagToModule(PyObject *m) {
PyBool_FromLong(!WebPDecoderBuggyAlpha())); PyModule_AddObject(
m, "HAVE_TRANSPARENCY", PyBool_FromLong(!WebPDecoderBuggyAlpha()));
} }
static int setup_module(PyObject* m) { static int
PyObject* d = PyModule_GetDict(m); setup_module(PyObject *m) {
PyObject *d = PyModule_GetDict(m);
addMuxFlagToModule(m); addMuxFlagToModule(m);
addAnimFlagToModule(m); addAnimFlagToModule(m);
addTransparencyFlagToModule(m); addTransparencyFlagToModule(m);
PyDict_SetItemString(d, "webpdecoder_version", PyUnicode_FromString(WebPDecoderVersion_str())); PyDict_SetItemString(
d, "webpdecoder_version", PyUnicode_FromString(WebPDecoderVersion_str()));
#ifdef HAVE_WEBPANIM #ifdef HAVE_WEBPANIM
/* Ready object types */ /* Ready object types */
@ -901,14 +964,14 @@ static int setup_module(PyObject* m) {
PyMODINIT_FUNC PyMODINIT_FUNC
PyInit__webp(void) { PyInit__webp(void) {
PyObject* m; PyObject *m;
static PyModuleDef module_def = { static PyModuleDef module_def = {
PyModuleDef_HEAD_INIT, PyModuleDef_HEAD_INIT,
"_webp", /* m_name */ "_webp", /* m_name */
NULL, /* m_doc */ NULL, /* m_doc */
-1, /* m_size */ -1, /* m_size */
webpMethods, /* m_methods */ webpMethods, /* m_methods */
}; };
m = PyModule_Create(&module_def); m = PyModule_Create(&module_def);

View File

@ -39,31 +39,28 @@
#include "libImaging/Bit.h" #include "libImaging/Bit.h"
#include "libImaging/Sgi.h" #include "libImaging/Sgi.h"
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Common */ /* Common */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD int (*decode)(
int (*decode)(Imaging im, ImagingCodecState state, Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
UINT8* buffer, Py_ssize_t bytes);
int (*cleanup)(ImagingCodecState state); int (*cleanup)(ImagingCodecState state);
struct ImagingCodecStateInstance state; struct ImagingCodecStateInstance state;
Imaging im; Imaging im;
PyObject* lock; PyObject *lock;
int pulls_fd; int pulls_fd;
} ImagingDecoderObject; } ImagingDecoderObject;
static PyTypeObject ImagingDecoderType; static PyTypeObject ImagingDecoderType;
static ImagingDecoderObject* static ImagingDecoderObject *
PyImaging_DecoderNew(int contextsize) PyImaging_DecoderNew(int contextsize) {
{
ImagingDecoderObject *decoder; ImagingDecoderObject *decoder;
void *context; void *context;
if(PyType_Ready(&ImagingDecoderType) < 0) { if (PyType_Ready(&ImagingDecoderType) < 0) {
return NULL; return NULL;
} }
@ -77,10 +74,10 @@ PyImaging_DecoderNew(int contextsize)
/* Allocate decoder context */ /* Allocate decoder context */
if (contextsize > 0) { if (contextsize > 0) {
context = (void*) calloc(1, contextsize); context = (void *)calloc(1, contextsize);
if (!context) { if (!context) {
Py_DECREF(decoder); Py_DECREF(decoder);
(void) ImagingError_MemoryError(); (void)ImagingError_MemoryError();
return NULL; return NULL;
} }
} else { } else {
@ -105,8 +102,7 @@ PyImaging_DecoderNew(int contextsize)
} }
static void static void
_dealloc(ImagingDecoderObject* decoder) _dealloc(ImagingDecoderObject *decoder) {
{
if (decoder->cleanup) { if (decoder->cleanup) {
decoder->cleanup(&decoder->state); decoder->cleanup(&decoder->state);
} }
@ -117,10 +113,9 @@ _dealloc(ImagingDecoderObject* decoder)
PyObject_Del(decoder); PyObject_Del(decoder);
} }
static PyObject* static PyObject *
_decode(ImagingDecoderObject* decoder, PyObject* args) _decode(ImagingDecoderObject *decoder, PyObject *args) {
{ UINT8 *buffer;
UINT8* buffer;
Py_ssize_t bufsize; Py_ssize_t bufsize;
int status; int status;
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
@ -142,26 +137,23 @@ _decode(ImagingDecoderObject* decoder, PyObject* args)
return Py_BuildValue("ii", status, decoder->state.errcode); return Py_BuildValue("ii", status, decoder->state.errcode);
} }
static PyObject* static PyObject *
_decode_cleanup(ImagingDecoderObject* decoder, PyObject* args) _decode_cleanup(ImagingDecoderObject *decoder, PyObject *args) {
{
int status = 0; int status = 0;
if (decoder->cleanup){ if (decoder->cleanup) {
status = decoder->cleanup(&decoder->state); status = decoder->cleanup(&decoder->state);
} }
return Py_BuildValue("i", status); return Py_BuildValue("i", status);
} }
extern Imaging
PyImaging_AsImaging(PyObject *op);
static PyObject *
extern Imaging PyImaging_AsImaging(PyObject *op); _setimage(ImagingDecoderObject *decoder, PyObject *args) {
PyObject *op;
static PyObject*
_setimage(ImagingDecoderObject* decoder, PyObject* args)
{
PyObject* op;
Imaging im; Imaging im;
ImagingCodecState state; ImagingCodecState state;
int x0, y0, x1, y1; int x0, y0, x1, y1;
@ -192,10 +184,8 @@ _setimage(ImagingDecoderObject* decoder, PyObject* args)
state->ysize = y1 - y0; state->ysize = y1 - y0;
} }
if (state->xsize <= 0 || if (state->xsize <= 0 || state->xsize + state->xoff > (int)im->xsize ||
state->xsize + state->xoff > (int) im->xsize || state->ysize <= 0 || state->ysize + state->yoff > (int)im->ysize) {
state->ysize <= 0 ||
state->ysize + state->yoff > (int) im->ysize) {
PyErr_SetString(PyExc_ValueError, "tile cannot extend outside image"); PyErr_SetString(PyExc_ValueError, "tile cannot extend outside image");
return NULL; return NULL;
} }
@ -203,13 +193,13 @@ _setimage(ImagingDecoderObject* decoder, PyObject* args)
/* Allocate memory buffer (if bits field is set) */ /* Allocate memory buffer (if bits field is set) */
if (state->bits > 0) { if (state->bits > 0) {
if (!state->bytes) { if (!state->bytes) {
if (state->xsize > ((INT_MAX / state->bits)-7)){ if (state->xsize > ((INT_MAX / state->bits) - 7)) {
return ImagingError_MemoryError(); return ImagingError_MemoryError();
} }
state->bytes = (state->bits * state->xsize+7)/8; state->bytes = (state->bits * state->xsize + 7) / 8;
} }
/* malloc check ok, overflow checked above */ /* malloc check ok, overflow checked above */
state->buffer = (UINT8*) malloc(state->bytes); state->buffer = (UINT8 *)malloc(state->bytes);
if (!state->buffer) { if (!state->buffer) {
return ImagingError_MemoryError(); return ImagingError_MemoryError();
} }
@ -225,10 +215,9 @@ _setimage(ImagingDecoderObject* decoder, PyObject* args)
return Py_None; return Py_None;
} }
static PyObject* static PyObject *
_setfd(ImagingDecoderObject* decoder, PyObject* args) _setfd(ImagingDecoderObject *decoder, PyObject *args) {
{ PyObject *fd;
PyObject* fd;
ImagingCodecState state; ImagingCodecState state;
if (!PyArg_ParseTuple(args, "O", &fd)) { if (!PyArg_ParseTuple(args, "O", &fd)) {
@ -244,10 +233,8 @@ _setfd(ImagingDecoderObject* decoder, PyObject* args)
return Py_None; return Py_None;
} }
static PyObject * static PyObject *
_get_pulls_fd(ImagingDecoderObject *decoder) _get_pulls_fd(ImagingDecoderObject *decoder) {
{
return PyBool_FromLong(decoder->pulls_fd); return PyBool_FromLong(decoder->pulls_fd);
} }
@ -260,52 +247,51 @@ static struct PyMethodDef methods[] = {
}; };
static struct PyGetSetDef getseters[] = { static struct PyGetSetDef getseters[] = {
{"pulls_fd", (getter)_get_pulls_fd, NULL, {"pulls_fd",
(getter)_get_pulls_fd,
NULL,
"True if this decoder expects to pull from self.fd itself.", "True if this decoder expects to pull from self.fd itself.",
NULL}, NULL},
{NULL, NULL, NULL, NULL, NULL} /* sentinel */ {NULL, NULL, NULL, NULL, NULL} /* sentinel */
}; };
static PyTypeObject ImagingDecoderType = { static PyTypeObject ImagingDecoderType = {
PyVarObject_HEAD_INIT(NULL, 0) PyVarObject_HEAD_INIT(NULL, 0) "ImagingDecoder", /*tp_name*/
"ImagingDecoder", /*tp_name*/ sizeof(ImagingDecoderObject), /*tp_size*/
sizeof(ImagingDecoderObject), /*tp_size*/ 0, /*tp_itemsize*/
0, /*tp_itemsize*/
/* methods */ /* methods */
(destructor)_dealloc, /*tp_dealloc*/ (destructor)_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
0, /*tp_repr*/ 0, /*tp_repr*/
0, /*tp_as_number */ 0, /*tp_as_number */
0, /*tp_as_sequence */ 0, /*tp_as_sequence */
0, /*tp_as_mapping */ 0, /*tp_as_mapping */
0, /*tp_hash*/ 0, /*tp_hash*/
0, /*tp_call*/ 0, /*tp_call*/
0, /*tp_str*/ 0, /*tp_str*/
0, /*tp_getattro*/ 0, /*tp_getattro*/
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/ 0, /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
0, /*tp_richcompare*/ 0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/ 0, /*tp_weaklistoffset*/
0, /*tp_iter*/ 0, /*tp_iter*/
0, /*tp_iternext*/ 0, /*tp_iternext*/
methods, /*tp_methods*/ methods, /*tp_methods*/
0, /*tp_members*/ 0, /*tp_members*/
getseters, /*tp_getset*/ getseters, /*tp_getset*/
}; };
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
int int
get_unpacker(ImagingDecoderObject* decoder, const char* mode, get_unpacker(ImagingDecoderObject *decoder, const char *mode, const char *rawmode) {
const char* rawmode)
{
int bits; int bits;
ImagingShuffler unpack; ImagingShuffler unpack;
@ -322,24 +308,21 @@ get_unpacker(ImagingDecoderObject* decoder, const char* mode,
return 0; return 0;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* BIT (packed fields) */ /* BIT (packed fields) */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
PyObject* PyObject *
PyImaging_BitDecoderNew(PyObject* self, PyObject* args) PyImaging_BitDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
char* mode; char *mode;
int bits = 8; int bits = 8;
int pad = 8; int pad = 8;
int fill = 0; int fill = 0;
int sign = 0; int sign = 0;
int ystep = 1; int ystep = 1;
if (!PyArg_ParseTuple(args, "s|iiiii", &mode, &bits, &pad, &fill, if (!PyArg_ParseTuple(args, "s|iiiii", &mode, &bits, &pad, &fill, &sign, &ystep)) {
&sign, &ystep)) {
return NULL; return NULL;
} }
@ -357,26 +340,24 @@ PyImaging_BitDecoderNew(PyObject* self, PyObject* args)
decoder->state.ystep = ystep; decoder->state.ystep = ystep;
((BITSTATE*)decoder->state.context)->bits = bits; ((BITSTATE *)decoder->state.context)->bits = bits;
((BITSTATE*)decoder->state.context)->pad = pad; ((BITSTATE *)decoder->state.context)->pad = pad;
((BITSTATE*)decoder->state.context)->fill = fill; ((BITSTATE *)decoder->state.context)->fill = fill;
((BITSTATE*)decoder->state.context)->sign = sign; ((BITSTATE *)decoder->state.context)->sign = sign;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* BCn: GPU block-compressed texture formats */ /* BCn: GPU block-compressed texture formats */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
PyObject* PyObject *
PyImaging_BcnDecoderNew(PyObject* self, PyObject* args) PyImaging_BcnDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
char* mode; char *mode;
char* actual; char *actual;
int n = 0; int n = 0;
int ystep = 1; int ystep = 1;
if (!PyArg_ParseTuple(args, "s|ii", &mode, &n, &ystep)) { if (!PyArg_ParseTuple(args, "s|ii", &mode, &n, &ystep)) {
@ -384,20 +365,23 @@ PyImaging_BcnDecoderNew(PyObject* self, PyObject* args)
} }
switch (n) { switch (n) {
case 1: /* BC1: 565 color, 1-bit alpha */ case 1: /* BC1: 565 color, 1-bit alpha */
case 2: /* BC2: 565 color, 4-bit alpha */ case 2: /* BC2: 565 color, 4-bit alpha */
case 3: /* BC3: 565 color, 2-endpoint 8-bit interpolated alpha */ case 3: /* BC3: 565 color, 2-endpoint 8-bit interpolated alpha */
case 5: /* BC5: 2-channel 8-bit via 2 BC3 alpha blocks */ case 5: /* BC5: 2-channel 8-bit via 2 BC3 alpha blocks */
case 7: /* BC7: 4-channel 8-bit via everything */ case 7: /* BC7: 4-channel 8-bit via everything */
actual = "RGBA"; break; actual = "RGBA";
case 4: /* BC4: 1-channel 8-bit via 1 BC3 alpha block */ break;
actual = "L"; break; case 4: /* BC4: 1-channel 8-bit via 1 BC3 alpha block */
case 6: /* BC6: 3-channel 16-bit float */ actual = "L";
/* TODO: support 4-channel floating point images */ break;
actual = "RGBAF"; break; case 6: /* BC6: 3-channel 16-bit float */
default: /* TODO: support 4-channel floating point images */
PyErr_SetString(PyExc_ValueError, "block compression type unknown"); actual = "RGBAF";
return NULL; break;
default:
PyErr_SetString(PyExc_ValueError, "block compression type unknown");
return NULL;
} }
if (strcmp(mode, actual) != 0) { if (strcmp(mode, actual) != 0) {
@ -414,18 +398,16 @@ PyImaging_BcnDecoderNew(PyObject* self, PyObject* args)
decoder->state.state = n; decoder->state.state = n;
decoder->state.ystep = ystep; decoder->state.ystep = ystep;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* FLI */ /* FLI */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
PyObject* PyObject *
PyImaging_FliDecoderNew(PyObject* self, PyObject* args) PyImaging_FliDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
decoder = PyImaging_DecoderNew(0); decoder = PyImaging_DecoderNew(0);
if (decoder == NULL) { if (decoder == NULL) {
@ -434,20 +416,18 @@ PyImaging_FliDecoderNew(PyObject* self, PyObject* args)
decoder->decode = ImagingFliDecode; decoder->decode = ImagingFliDecode;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* GIF */ /* GIF */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
PyObject* PyObject *
PyImaging_GifDecoderNew(PyObject* self, PyObject* args) PyImaging_GifDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
char* mode; char *mode;
int bits = 8; int bits = 8;
int interlace = 0; int interlace = 0;
if (!PyArg_ParseTuple(args, "s|ii", &mode, &bits, &interlace)) { if (!PyArg_ParseTuple(args, "s|ii", &mode, &bits, &interlace)) {
@ -466,24 +446,22 @@ PyImaging_GifDecoderNew(PyObject* self, PyObject* args)
decoder->decode = ImagingGifDecode; decoder->decode = ImagingGifDecode;
((GIFDECODERSTATE*)decoder->state.context)->bits = bits; ((GIFDECODERSTATE *)decoder->state.context)->bits = bits;
((GIFDECODERSTATE*)decoder->state.context)->interlace = interlace; ((GIFDECODERSTATE *)decoder->state.context)->interlace = interlace;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* HEX */ /* HEX */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
PyObject* PyObject *
PyImaging_HexDecoderNew(PyObject* self, PyObject* args) PyImaging_HexDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
char* mode; char *mode;
char* rawmode; char *rawmode;
if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) { if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) {
return NULL; return NULL;
} }
@ -499,10 +477,9 @@ PyImaging_HexDecoderNew(PyObject* self, PyObject* args)
decoder->decode = ImagingHexDecode; decoder->decode = ImagingHexDecode;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* LibTiff */ /* LibTiff */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
@ -513,17 +490,16 @@ PyImaging_HexDecoderNew(PyObject* self, PyObject* args)
#include <string.h> #include <string.h>
PyObject* PyObject *
PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args) PyImaging_LibTiffDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder; char *mode;
char* mode; char *rawmode;
char* rawmode; char *compname;
char* compname;
int fp; int fp;
uint32 ifdoffset; uint32 ifdoffset;
if (! PyArg_ParseTuple(args, "sssiI", &mode, &rawmode, &compname, &fp, &ifdoffset)) { if (!PyArg_ParseTuple(args, "sssiI", &mode, &rawmode, &compname, &fp, &ifdoffset)) {
return NULL; return NULL;
} }
@ -538,31 +514,29 @@ PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args)
return NULL; return NULL;
} }
if (! ImagingLibTiffInit(&decoder->state, fp, ifdoffset)) { if (!ImagingLibTiffInit(&decoder->state, fp, ifdoffset)) {
Py_DECREF(decoder); Py_DECREF(decoder);
PyErr_SetString(PyExc_RuntimeError, "tiff codec initialization failed"); PyErr_SetString(PyExc_RuntimeError, "tiff codec initialization failed");
return NULL; return NULL;
} }
decoder->decode = ImagingLibTiffDecode; decoder->decode = ImagingLibTiffDecode;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
#endif #endif
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* PackBits */ /* PackBits */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
PyObject* PyObject *
PyImaging_PackbitsDecoderNew(PyObject* self, PyObject* args) PyImaging_PackbitsDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
char* mode; char *mode;
char* rawmode; char *rawmode;
if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) { if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) {
return NULL; return NULL;
} }
@ -578,18 +552,16 @@ PyImaging_PackbitsDecoderNew(PyObject* self, PyObject* args)
decoder->decode = ImagingPackbitsDecode; decoder->decode = ImagingPackbitsDecode;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* PCD */ /* PCD */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
PyObject* PyObject *
PyImaging_PcdDecoderNew(PyObject* self, PyObject* args) PyImaging_PcdDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
decoder = PyImaging_DecoderNew(0); decoder = PyImaging_DecoderNew(0);
if (decoder == NULL) { if (decoder == NULL) {
@ -603,21 +575,19 @@ PyImaging_PcdDecoderNew(PyObject* self, PyObject* args)
decoder->decode = ImagingPcdDecode; decoder->decode = ImagingPcdDecode;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* PCX */ /* PCX */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
PyObject* PyObject *
PyImaging_PcxDecoderNew(PyObject* self, PyObject* args) PyImaging_PcxDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
char* mode; char *mode;
char* rawmode; char *rawmode;
int stride; int stride;
if (!PyArg_ParseTuple(args, "ssi", &mode, &rawmode, &stride)) { if (!PyArg_ParseTuple(args, "ssi", &mode, &rawmode, &stride)) {
return NULL; return NULL;
@ -636,23 +606,21 @@ PyImaging_PcxDecoderNew(PyObject* self, PyObject* args)
decoder->decode = ImagingPcxDecode; decoder->decode = ImagingPcxDecode;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* RAW */ /* RAW */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
PyObject* PyObject *
PyImaging_RawDecoderNew(PyObject* self, PyObject* args) PyImaging_RawDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
char* mode; char *mode;
char* rawmode; char *rawmode;
int stride = 0; int stride = 0;
int ystep = 1; int ystep = 1;
if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &stride, &ystep)) { if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &stride, &ystep)) {
return NULL; return NULL;
} }
@ -670,23 +638,21 @@ PyImaging_RawDecoderNew(PyObject* self, PyObject* args)
decoder->state.ystep = ystep; decoder->state.ystep = ystep;
((RAWSTATE*)decoder->state.context)->stride = stride; ((RAWSTATE *)decoder->state.context)->stride = stride;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* SGI RLE */ /* SGI RLE */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
PyObject* PyObject *
PyImaging_SgiRleDecoderNew(PyObject* self, PyObject* args) PyImaging_SgiRleDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
char* mode; char *mode;
char* rawmode; char *rawmode;
int ystep = 1; int ystep = 1;
int bpc = 1; int bpc = 1;
if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &ystep, &bpc)) { if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &ystep, &bpc)) {
@ -706,23 +672,21 @@ PyImaging_SgiRleDecoderNew(PyObject* self, PyObject* args)
decoder->decode = ImagingSgiRleDecode; decoder->decode = ImagingSgiRleDecode;
decoder->state.ystep = ystep; decoder->state.ystep = ystep;
((SGISTATE*)decoder->state.context)->bpc = bpc; ((SGISTATE *)decoder->state.context)->bpc = bpc;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* SUN RLE */ /* SUN RLE */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
PyObject* PyObject *
PyImaging_SunRleDecoderNew(PyObject* self, PyObject* args) PyImaging_SunRleDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
char* mode; char *mode;
char* rawmode; char *rawmode;
if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) { if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) {
return NULL; return NULL;
} }
@ -738,21 +702,19 @@ PyImaging_SunRleDecoderNew(PyObject* self, PyObject* args)
decoder->decode = ImagingSunRleDecode; decoder->decode = ImagingSunRleDecode;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* TGA RLE */ /* TGA RLE */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
PyObject* PyObject *
PyImaging_TgaRleDecoderNew(PyObject* self, PyObject* args) PyImaging_TgaRleDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
char* mode; char *mode;
char* rawmode; char *rawmode;
int ystep = 1; int ystep = 1;
int depth = 8; int depth = 8;
if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &ystep, &depth)) { if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &ystep, &depth)) {
@ -773,18 +735,16 @@ PyImaging_TgaRleDecoderNew(PyObject* self, PyObject* args)
decoder->state.ystep = ystep; decoder->state.ystep = ystep;
decoder->state.count = depth / 8; decoder->state.count = depth / 8;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* XBM */ /* XBM */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
PyObject* PyObject *
PyImaging_XbmDecoderNew(PyObject* self, PyObject* args) PyImaging_XbmDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
decoder = PyImaging_DecoderNew(0); decoder = PyImaging_DecoderNew(0);
if (decoder == NULL) { if (decoder == NULL) {
@ -797,10 +757,9 @@ PyImaging_XbmDecoderNew(PyObject* self, PyObject* args)
decoder->decode = ImagingXbmDecode; decoder->decode = ImagingXbmDecode;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* ZIP */ /* ZIP */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
@ -809,13 +768,12 @@ PyImaging_XbmDecoderNew(PyObject* self, PyObject* args)
#include "libImaging/ZipCodecs.h" #include "libImaging/ZipCodecs.h"
PyObject* PyObject *
PyImaging_ZipDecoderNew(PyObject* self, PyObject* args) PyImaging_ZipDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
char* mode; char *mode;
char* rawmode; char *rawmode;
int interlaced = 0; int interlaced = 0;
if (!PyArg_ParseTuple(args, "ss|i", &mode, &rawmode, &interlaced)) { if (!PyArg_ParseTuple(args, "ss|i", &mode, &rawmode, &interlaced)) {
return NULL; return NULL;
@ -833,13 +791,12 @@ PyImaging_ZipDecoderNew(PyObject* self, PyObject* args)
decoder->decode = ImagingZipDecode; decoder->decode = ImagingZipDecode;
decoder->cleanup = ImagingZipDecodeCleanup; decoder->cleanup = ImagingZipDecodeCleanup;
((ZIPSTATE*)decoder->state.context)->interlaced = interlaced; ((ZIPSTATE *)decoder->state.context)->interlaced = interlaced;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
#endif #endif
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* JPEG */ /* JPEG */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
@ -849,31 +806,29 @@ PyImaging_ZipDecoderNew(PyObject* self, PyObject* args)
/* We better define this decoder last in this file, so the following /* We better define this decoder last in this file, so the following
undef's won't mess things up for the Imaging library proper. */ undef's won't mess things up for the Imaging library proper. */
#undef HAVE_PROTOTYPES #undef HAVE_PROTOTYPES
#undef HAVE_STDDEF_H #undef HAVE_STDDEF_H
#undef HAVE_STDLIB_H #undef HAVE_STDLIB_H
#undef UINT8 #undef UINT8
#undef UINT16 #undef UINT16
#undef UINT32 #undef UINT32
#undef INT8 #undef INT8
#undef INT16 #undef INT16
#undef INT32 #undef INT32
#include "libImaging/Jpeg.h" #include "libImaging/Jpeg.h"
PyObject* PyObject *
PyImaging_JpegDecoderNew(PyObject* self, PyObject* args) PyImaging_JpegDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
char* mode; char *mode;
char* rawmode; /* what we want from the decoder */ char *rawmode; /* what we want from the decoder */
char* jpegmode; /* what's in the file */ char *jpegmode; /* what's in the file */
int scale = 1; int scale = 1;
int draft = 0; int draft = 0;
if (!PyArg_ParseTuple(args, "ssz|ii", &mode, &rawmode, &jpegmode, if (!PyArg_ParseTuple(args, "ssz|ii", &mode, &rawmode, &jpegmode, &scale, &draft)) {
&scale, &draft)) {
return NULL; return NULL;
} }
@ -900,13 +855,13 @@ PyImaging_JpegDecoderNew(PyObject* self, PyObject* args)
decoder->decode = ImagingJpegDecode; decoder->decode = ImagingJpegDecode;
decoder->cleanup = ImagingJpegDecodeCleanup; decoder->cleanup = ImagingJpegDecodeCleanup;
strncpy(((JPEGSTATE*)decoder->state.context)->rawmode, rawmode, 8); strncpy(((JPEGSTATE *)decoder->state.context)->rawmode, rawmode, 8);
strncpy(((JPEGSTATE*)decoder->state.context)->jpegmode, jpegmode, 8); strncpy(((JPEGSTATE *)decoder->state.context)->jpegmode, jpegmode, 8);
((JPEGSTATE*)decoder->state.context)->scale = scale; ((JPEGSTATE *)decoder->state.context)->scale = scale;
((JPEGSTATE*)decoder->state.context)->draft = draft; ((JPEGSTATE *)decoder->state.context)->draft = draft;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
#endif #endif
@ -918,22 +873,21 @@ PyImaging_JpegDecoderNew(PyObject* self, PyObject* args)
#include "libImaging/Jpeg2K.h" #include "libImaging/Jpeg2K.h"
PyObject* PyObject *
PyImaging_Jpeg2KDecoderNew(PyObject* self, PyObject* args) PyImaging_Jpeg2KDecoderNew(PyObject *self, PyObject *args) {
{ ImagingDecoderObject *decoder;
ImagingDecoderObject* decoder;
JPEG2KDECODESTATE *context; JPEG2KDECODESTATE *context;
char* mode; char *mode;
char* format; char *format;
OPJ_CODEC_FORMAT codec_format; OPJ_CODEC_FORMAT codec_format;
int reduce = 0; int reduce = 0;
int layers = 0; int layers = 0;
int fd = -1; int fd = -1;
PY_LONG_LONG length = -1; PY_LONG_LONG length = -1;
if (!PyArg_ParseTuple(args, "ss|iiiL", &mode, &format, if (!PyArg_ParseTuple(
&reduce, &layers, &fd, &length)) { args, "ss|iiiL", &mode, &format, &reduce, &layers, &fd, &length)) {
return NULL; return NULL;
} }
@ -964,7 +918,6 @@ PyImaging_Jpeg2KDecoderNew(PyObject* self, PyObject* args)
context->reduce = reduce; context->reduce = reduce;
context->layers = layers; context->layers = layers;
return (PyObject*) decoder; return (PyObject *)decoder;
} }
#endif /* HAVE_OPENJPEG */ #endif /* HAVE_OPENJPEG */

View File

@ -41,15 +41,13 @@
#endif #endif
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD ImagingDIB dib;
ImagingDIB dib;
} ImagingDisplayObject; } ImagingDisplayObject;
static PyTypeObject ImagingDisplayType; static PyTypeObject ImagingDisplayType;
static ImagingDisplayObject* static ImagingDisplayObject *
_new(const char* mode, int xsize, int ysize) _new(const char *mode, int xsize, int ysize) {
{
ImagingDisplayObject *display; ImagingDisplayObject *display;
if (PyType_Ready(&ImagingDisplayType) < 0) { if (PyType_Ready(&ImagingDisplayType) < 0) {
@ -71,17 +69,15 @@ _new(const char* mode, int xsize, int ysize)
} }
static void static void
_delete(ImagingDisplayObject* display) _delete(ImagingDisplayObject *display) {
{
if (display->dib) { if (display->dib) {
ImagingDeleteDIB(display->dib); ImagingDeleteDIB(display->dib);
} }
PyObject_Del(display); PyObject_Del(display);
} }
static PyObject* static PyObject *
_expose(ImagingDisplayObject* display, PyObject* args) _expose(ImagingDisplayObject *display, PyObject *args) {
{
HDC hdc; HDC hdc;
if (!PyArg_ParseTuple(args, F_HANDLE, &hdc)) { if (!PyArg_ParseTuple(args, F_HANDLE, &hdc)) {
return NULL; return NULL;
@ -93,15 +89,23 @@ _expose(ImagingDisplayObject* display, PyObject* args)
return Py_None; return Py_None;
} }
static PyObject* static PyObject *
_draw(ImagingDisplayObject* display, PyObject* args) _draw(ImagingDisplayObject *display, PyObject *args) {
{
HDC hdc; HDC hdc;
int dst[4]; int dst[4];
int src[4]; int src[4];
if (!PyArg_ParseTuple(args, F_HANDLE "(iiii)(iiii)", &hdc, if (!PyArg_ParseTuple(
dst+0, dst+1, dst+2, dst+3, args,
src+0, src+1, src+2, src+3)) { F_HANDLE "(iiii)(iiii)",
&hdc,
dst + 0,
dst + 1,
dst + 2,
dst + 3,
src + 0,
src + 1,
src + 2,
src + 3)) {
return NULL; return NULL;
} }
@ -111,17 +115,17 @@ _draw(ImagingDisplayObject* display, PyObject* args)
return Py_None; return Py_None;
} }
extern Imaging PyImaging_AsImaging(PyObject *op); extern Imaging
PyImaging_AsImaging(PyObject *op);
static PyObject* static PyObject *
_paste(ImagingDisplayObject* display, PyObject* args) _paste(ImagingDisplayObject *display, PyObject *args) {
{
Imaging im; Imaging im;
PyObject* op; PyObject *op;
int xy[4]; int xy[4];
xy[0] = xy[1] = xy[2] = xy[3] = 0; xy[0] = xy[1] = xy[2] = xy[3] = 0;
if (!PyArg_ParseTuple(args, "O|(iiii)", &op, xy+0, xy+1, xy+2, xy+3)) { if (!PyArg_ParseTuple(args, "O|(iiii)", &op, xy + 0, xy + 1, xy + 2, xy + 3)) {
return NULL; return NULL;
} }
im = PyImaging_AsImaging(op); im = PyImaging_AsImaging(op);
@ -142,9 +146,8 @@ _paste(ImagingDisplayObject* display, PyObject* args)
return Py_None; return Py_None;
} }
static PyObject* static PyObject *
_query_palette(ImagingDisplayObject* display, PyObject* args) _query_palette(ImagingDisplayObject *display, PyObject *args) {
{
HDC hdc; HDC hdc;
int status; int status;
@ -157,9 +160,8 @@ _query_palette(ImagingDisplayObject* display, PyObject* args)
return Py_BuildValue("i", status); return Py_BuildValue("i", status);
} }
static PyObject* static PyObject *
_getdc(ImagingDisplayObject* display, PyObject* args) _getdc(ImagingDisplayObject *display, PyObject *args) {
{
HWND window; HWND window;
HDC dc; HDC dc;
@ -176,9 +178,8 @@ _getdc(ImagingDisplayObject* display, PyObject* args)
return Py_BuildValue(F_HANDLE, dc); return Py_BuildValue(F_HANDLE, dc);
} }
static PyObject* static PyObject *
_releasedc(ImagingDisplayObject* display, PyObject* args) _releasedc(ImagingDisplayObject *display, PyObject *args) {
{
HWND window; HWND window;
HDC dc; HDC dc;
@ -192,10 +193,9 @@ _releasedc(ImagingDisplayObject* display, PyObject* args)
return Py_None; return Py_None;
} }
static PyObject* static PyObject *
_frombytes(ImagingDisplayObject* display, PyObject* args) _frombytes(ImagingDisplayObject *display, PyObject *args) {
{ char *ptr;
char* ptr;
Py_ssize_t bytes; Py_ssize_t bytes;
if (!PyArg_ParseTuple(args, "y#:frombytes", &ptr, &bytes)) { if (!PyArg_ParseTuple(args, "y#:frombytes", &ptr, &bytes)) {
@ -213,16 +213,14 @@ _frombytes(ImagingDisplayObject* display, PyObject* args)
return Py_None; return Py_None;
} }
static PyObject* static PyObject *
_tobytes(ImagingDisplayObject* display, PyObject* args) _tobytes(ImagingDisplayObject *display, PyObject *args) {
{
if (!PyArg_ParseTuple(args, ":tobytes")) { if (!PyArg_ParseTuple(args, ":tobytes")) {
return NULL; return NULL;
} }
return PyBytes_FromStringAndSize( return PyBytes_FromStringAndSize(
display->dib->bits, display->dib->ysize * display->dib->linesize display->dib->bits, display->dib->ysize * display->dib->linesize);
);
} }
static struct PyMethodDef methods[] = { static struct PyMethodDef methods[] = {
@ -237,62 +235,55 @@ static struct PyMethodDef methods[] = {
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
static PyObject* static PyObject *
_getattr_mode(ImagingDisplayObject* self, void* closure) _getattr_mode(ImagingDisplayObject *self, void *closure) {
{
return Py_BuildValue("s", self->dib->mode); return Py_BuildValue("s", self->dib->mode);
} }
static PyObject* static PyObject *
_getattr_size(ImagingDisplayObject* self, void* closure) _getattr_size(ImagingDisplayObject *self, void *closure) {
{
return Py_BuildValue("ii", self->dib->xsize, self->dib->ysize); return Py_BuildValue("ii", self->dib->xsize, self->dib->ysize);
} }
static struct PyGetSetDef getsetters[] = { static struct PyGetSetDef getsetters[] = {
{ "mode", (getter) _getattr_mode }, {"mode", (getter)_getattr_mode}, {"size", (getter)_getattr_size}, {NULL}};
{ "size", (getter) _getattr_size },
{ NULL }
};
static PyTypeObject ImagingDisplayType = { static PyTypeObject ImagingDisplayType = {
PyVarObject_HEAD_INIT(NULL, 0) PyVarObject_HEAD_INIT(NULL, 0) "ImagingDisplay", /*tp_name*/
"ImagingDisplay", /*tp_name*/ sizeof(ImagingDisplayObject), /*tp_size*/
sizeof(ImagingDisplayObject),/*tp_size*/ 0, /*tp_itemsize*/
0, /*tp_itemsize*/
/* methods */ /* methods */
(destructor)_delete, /*tp_dealloc*/ (destructor)_delete, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
0, /*tp_repr*/ 0, /*tp_repr*/
0, /*tp_as_number */ 0, /*tp_as_number */
0, /*tp_as_sequence */ 0, /*tp_as_sequence */
0, /*tp_as_mapping */ 0, /*tp_as_mapping */
0, /*tp_hash*/ 0, /*tp_hash*/
0, /*tp_call*/ 0, /*tp_call*/
0, /*tp_str*/ 0, /*tp_str*/
0, /*tp_getattro*/ 0, /*tp_getattro*/
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/ 0, /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
0, /*tp_richcompare*/ 0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/ 0, /*tp_weaklistoffset*/
0, /*tp_iter*/ 0, /*tp_iter*/
0, /*tp_iternext*/ 0, /*tp_iternext*/
methods, /*tp_methods*/ methods, /*tp_methods*/
0, /*tp_members*/ 0, /*tp_members*/
getsetters, /*tp_getset*/ getsetters, /*tp_getset*/
}; };
PyObject* PyObject *
PyImaging_DisplayWin32(PyObject* self, PyObject* args) PyImaging_DisplayWin32(PyObject *self, PyObject *args) {
{ ImagingDisplayObject *display;
ImagingDisplayObject* display;
char *mode; char *mode;
int xsize, ysize; int xsize, ysize;
@ -305,12 +296,11 @@ PyImaging_DisplayWin32(PyObject* self, PyObject* args)
return NULL; return NULL;
} }
return (PyObject*) display; return (PyObject *)display;
} }
PyObject* PyObject *
PyImaging_DisplayModeWin32(PyObject* self, PyObject* args) PyImaging_DisplayModeWin32(PyObject *self, PyObject *args) {
{
char *mode; char *mode;
int size[2]; int size[2];
@ -322,18 +312,17 @@ PyImaging_DisplayModeWin32(PyObject* self, PyObject* args)
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Windows screen grabber */ /* Windows screen grabber */
typedef HANDLE(__stdcall* Func_SetThreadDpiAwarenessContext)(HANDLE); typedef HANDLE(__stdcall *Func_SetThreadDpiAwarenessContext)(HANDLE);
PyObject* PyObject *
PyImaging_GrabScreenWin32(PyObject* self, PyObject* args) PyImaging_GrabScreenWin32(PyObject *self, PyObject *args) {
{
int x = 0, y = 0, width, height; int x = 0, y = 0, width, height;
int includeLayeredWindows = 0, all_screens = 0; int includeLayeredWindows = 0, all_screens = 0;
HBITMAP bitmap; HBITMAP bitmap;
BITMAPCOREHEADER core; BITMAPCOREHEADER core;
HDC screen, screen_copy; HDC screen, screen_copy;
DWORD rop; DWORD rop;
PyObject* buffer; PyObject *buffer;
HANDLE dpiAwareness; HANDLE dpiAwareness;
HMODULE user32; HMODULE user32;
Func_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContext_function; Func_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContext_function;
@ -352,11 +341,11 @@ PyImaging_GrabScreenWin32(PyObject* self, PyObject* args)
// loaded dynamically to avoid link errors // loaded dynamically to avoid link errors
user32 = LoadLibraryA("User32.dll"); user32 = LoadLibraryA("User32.dll");
SetThreadDpiAwarenessContext_function = SetThreadDpiAwarenessContext_function =
(Func_SetThreadDpiAwarenessContext) (Func_SetThreadDpiAwarenessContext)GetProcAddress(
GetProcAddress(user32, "SetThreadDpiAwarenessContext"); user32, "SetThreadDpiAwarenessContext");
if (SetThreadDpiAwarenessContext_function != NULL) { if (SetThreadDpiAwarenessContext_function != NULL) {
// DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = ((DPI_CONTEXT_HANDLE)-3) // DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = ((DPI_CONTEXT_HANDLE)-3)
dpiAwareness = SetThreadDpiAwarenessContext_function((HANDLE) -3); dpiAwareness = SetThreadDpiAwarenessContext_function((HANDLE)-3);
} }
if (all_screens) { if (all_screens) {
@ -396,7 +385,7 @@ PyImaging_GrabScreenWin32(PyObject* self, PyObject* args)
/* step 3: extract bits from bitmap */ /* step 3: extract bits from bitmap */
buffer = PyBytes_FromStringAndSize(NULL, height * ((width*3 + 3) & -4)); buffer = PyBytes_FromStringAndSize(NULL, height * ((width * 3 + 3) & -4));
if (!buffer) { if (!buffer) {
return NULL; return NULL;
} }
@ -406,8 +395,14 @@ PyImaging_GrabScreenWin32(PyObject* self, PyObject* args)
core.bcHeight = height; core.bcHeight = height;
core.bcPlanes = 1; core.bcPlanes = 1;
core.bcBitCount = 24; core.bcBitCount = 24;
if (!GetDIBits(screen_copy, bitmap, 0, height, PyBytes_AS_STRING(buffer), if (!GetDIBits(
(BITMAPINFO*) &core, DIB_RGB_COLORS)) { screen_copy,
bitmap,
0,
height,
PyBytes_AS_STRING(buffer),
(BITMAPINFO *)&core,
DIB_RGB_COLORS)) {
goto error; goto error;
} }
@ -426,11 +421,11 @@ error:
return NULL; return NULL;
} }
static BOOL CALLBACK list_windows_callback(HWND hwnd, LPARAM lParam) static BOOL CALLBACK
{ list_windows_callback(HWND hwnd, LPARAM lParam) {
PyObject* window_list = (PyObject*) lParam; PyObject *window_list = (PyObject *)lParam;
PyObject* item; PyObject *item;
PyObject* title; PyObject *title;
RECT inner, outer; RECT inner, outer;
int title_size; int title_size;
int status; int status;
@ -440,7 +435,7 @@ static BOOL CALLBACK list_windows_callback(HWND hwnd, LPARAM lParam)
if (title_size > 0) { if (title_size > 0) {
title = PyUnicode_FromStringAndSize(NULL, title_size); title = PyUnicode_FromStringAndSize(NULL, title_size);
if (title) { if (title) {
GetWindowTextW(hwnd, PyUnicode_AS_UNICODE(title), title_size+1); GetWindowTextW(hwnd, PyUnicode_AS_UNICODE(title), title_size + 1);
} }
} else { } else {
title = PyUnicode_FromString(""); title = PyUnicode_FromString("");
@ -454,10 +449,17 @@ static BOOL CALLBACK list_windows_callback(HWND hwnd, LPARAM lParam)
GetWindowRect(hwnd, &outer); GetWindowRect(hwnd, &outer);
item = Py_BuildValue( item = Py_BuildValue(
F_HANDLE "N(iiii)(iiii)", hwnd, title, F_HANDLE "N(iiii)(iiii)",
inner.left, inner.top, inner.right, inner.bottom, hwnd,
outer.left, outer.top, outer.right, outer.bottom title,
); inner.left,
inner.top,
inner.right,
inner.bottom,
outer.left,
outer.top,
outer.right,
outer.bottom);
if (!item) { if (!item) {
return 0; return 0;
} }
@ -473,17 +475,16 @@ static BOOL CALLBACK list_windows_callback(HWND hwnd, LPARAM lParam)
return 1; return 1;
} }
PyObject* PyObject *
PyImaging_ListWindowsWin32(PyObject* self, PyObject* args) PyImaging_ListWindowsWin32(PyObject *self, PyObject *args) {
{ PyObject *window_list;
PyObject* window_list;
window_list = PyList_New(0); window_list = PyList_New(0);
if (!window_list) { if (!window_list) {
return NULL; return NULL;
} }
EnumWindows(list_windows_callback, (LPARAM) window_list); EnumWindows(list_windows_callback, (LPARAM)window_list);
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
Py_DECREF(window_list); Py_DECREF(window_list);
@ -496,17 +497,16 @@ PyImaging_ListWindowsWin32(PyObject* self, PyObject* args)
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Windows clipboard grabber */ /* Windows clipboard grabber */
PyObject* PyObject *
PyImaging_GrabClipboardWin32(PyObject* self, PyObject* args) PyImaging_GrabClipboardWin32(PyObject *self, PyObject *args) {
{
int clip; int clip;
HANDLE handle = NULL; HANDLE handle = NULL;
int size; int size;
void* data; void *data;
PyObject* result; PyObject *result;
UINT format; UINT format;
UINT formats[] = { CF_DIB, CF_DIBV5, CF_HDROP, RegisterClipboardFormatA("PNG"), 0 }; UINT formats[] = {CF_DIB, CF_DIBV5, CF_HDROP, RegisterClipboardFormatA("PNG"), 0};
LPCSTR format_names[] = { "DIB", "DIB", "file", "png", NULL }; LPCSTR format_names[] = {"DIB", "DIB", "file", "png", NULL};
if (!OpenClipboard(NULL)) { if (!OpenClipboard(NULL)) {
PyErr_SetString(PyExc_OSError, "failed to open clipboard"); PyErr_SetString(PyExc_OSError, "failed to open clipboard");
@ -551,15 +551,14 @@ PyImaging_GrabClipboardWin32(PyObject* self, PyObject* args)
static int mainloop = 0; static int mainloop = 0;
static void static void
callback_error(const char* handler) callback_error(const char *handler) {
{ PyObject *sys_stderr;
PyObject* sys_stderr;
sys_stderr = PySys_GetObject("stderr"); sys_stderr = PySys_GetObject("stderr");
if (sys_stderr) { if (sys_stderr) {
PyFile_WriteString("*** ImageWin: error in ", sys_stderr); PyFile_WriteString("*** ImageWin: error in ", sys_stderr);
PyFile_WriteString((char*) handler, sys_stderr); PyFile_WriteString((char *)handler, sys_stderr);
PyFile_WriteString(":\n", sys_stderr); PyFile_WriteString(":\n", sys_stderr);
} }
@ -568,109 +567,119 @@ callback_error(const char* handler)
} }
static LRESULT CALLBACK static LRESULT CALLBACK
windowCallback(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) windowCallback(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) {
{
PAINTSTRUCT ps; PAINTSTRUCT ps;
PyObject* callback = NULL; PyObject *callback = NULL;
PyObject* result; PyObject *result;
PyThreadState* threadstate; PyThreadState *threadstate;
PyThreadState* current_threadstate; PyThreadState *current_threadstate;
HDC dc; HDC dc;
RECT rect; RECT rect;
LRESULT status = 0; LRESULT status = 0;
/* set up threadstate for messages that calls back into python */ /* set up threadstate for messages that calls back into python */
switch (message) { switch (message) {
case WM_CREATE: case WM_CREATE:
mainloop++; mainloop++;
break; break;
case WM_DESTROY: case WM_DESTROY:
mainloop--; mainloop--;
/* fall through... */ /* fall through... */
case WM_PAINT: case WM_PAINT:
case WM_SIZE: case WM_SIZE:
callback = (PyObject*) GetWindowLongPtr(wnd, 0); callback = (PyObject *)GetWindowLongPtr(wnd, 0);
if (callback) { if (callback) {
threadstate = (PyThreadState*) threadstate =
GetWindowLongPtr(wnd, sizeof(PyObject*)); (PyThreadState *)GetWindowLongPtr(wnd, sizeof(PyObject *));
current_threadstate = PyThreadState_Swap(NULL); current_threadstate = PyThreadState_Swap(NULL);
PyEval_RestoreThread(threadstate); PyEval_RestoreThread(threadstate);
} else { } else {
return DefWindowProc(wnd, message, wParam, lParam); return DefWindowProc(wnd, message, wParam, lParam);
} }
} }
/* process message */ /* process message */
switch (message) { switch (message) {
case WM_PAINT:
/* redraw (part of) window. this generates a WCK-style
damage/clear/repair cascade */
BeginPaint(wnd, &ps);
dc = GetDC(wnd);
GetWindowRect(wnd, &rect); /* in screen coordinates */
case WM_PAINT: result = PyObject_CallFunction(
/* redraw (part of) window. this generates a WCK-style callback,
damage/clear/repair cascade */ "siiii",
BeginPaint(wnd, &ps); "damage",
dc = GetDC(wnd); ps.rcPaint.left,
GetWindowRect(wnd, &rect); /* in screen coordinates */ ps.rcPaint.top,
ps.rcPaint.right,
ps.rcPaint.bottom);
if (result) {
Py_DECREF(result);
} else {
callback_error("window damage callback");
}
result = PyObject_CallFunction( result = PyObject_CallFunction(
callback, "siiii", "damage", callback,
ps.rcPaint.left, ps.rcPaint.top, "s" F_HANDLE "iiii",
ps.rcPaint.right, ps.rcPaint.bottom "clear",
); dc,
if (result) { 0,
Py_DECREF(result); 0,
} else { rect.right - rect.left,
callback_error("window damage callback"); rect.bottom - rect.top);
} if (result) {
Py_DECREF(result);
} else {
callback_error("window clear callback");
}
result = PyObject_CallFunction( result = PyObject_CallFunction(
callback, "s" F_HANDLE "iiii", "clear", dc, callback,
0, 0, rect.right-rect.left, rect.bottom-rect.top "s" F_HANDLE "iiii",
); "repair",
if (result) { dc,
Py_DECREF(result); 0,
} else { 0,
callback_error("window clear callback"); rect.right - rect.left,
} rect.bottom - rect.top);
if (result) {
Py_DECREF(result);
} else {
callback_error("window repair callback");
}
result = PyObject_CallFunction( ReleaseDC(wnd, dc);
callback, "s" F_HANDLE "iiii", "repair", dc, EndPaint(wnd, &ps);
0, 0, rect.right-rect.left, rect.bottom-rect.top break;
);
if (result) {
Py_DECREF(result);
} else {
callback_error("window repair callback");
}
ReleaseDC(wnd, dc); case WM_SIZE:
EndPaint(wnd, &ps); /* resize window */
break; result = PyObject_CallFunction(
callback, "sii", "resize", LOWORD(lParam), HIWORD(lParam));
if (result) {
InvalidateRect(wnd, NULL, 1);
Py_DECREF(result);
} else {
callback_error("window resize callback");
}
break;
case WM_SIZE: case WM_DESTROY:
/* resize window */ /* destroy window */
result = PyObject_CallFunction( result = PyObject_CallFunction(callback, "s", "destroy");
callback, "sii", "resize", LOWORD(lParam), HIWORD(lParam) if (result) {
); Py_DECREF(result);
if (result) { } else {
InvalidateRect(wnd, NULL, 1); callback_error("window destroy callback");
Py_DECREF(result); }
} else { Py_DECREF(callback);
callback_error("window resize callback"); break;
}
break;
case WM_DESTROY: default:
/* destroy window */ status = DefWindowProc(wnd, message, wParam, lParam);
result = PyObject_CallFunction(callback, "s", "destroy");
if (result) {
Py_DECREF(result);
} else {
callback_error("window destroy callback");
}
Py_DECREF(callback);
break;
default:
status = DefWindowProc(wnd, message, wParam, lParam);
} }
if (callback) { if (callback) {
@ -682,14 +691,13 @@ windowCallback(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
return status; return status;
} }
PyObject* PyObject *
PyImaging_CreateWindowWin32(PyObject* self, PyObject* args) PyImaging_CreateWindowWin32(PyObject *self, PyObject *args) {
{
HWND wnd; HWND wnd;
WNDCLASS windowClass; WNDCLASS windowClass;
char* title; char *title;
PyObject* callback; PyObject *callback;
int width = 0, height = 0; int width = 0, height = 0;
if (!PyArg_ParseTuple(args, "sO|ii", &title, &callback, &width, &height)) { if (!PyArg_ParseTuple(args, "sO|ii", &title, &callback, &width, &height)) {
return NULL; return NULL;
@ -705,7 +713,7 @@ PyImaging_CreateWindowWin32(PyObject* self, PyObject* args)
/* register toplevel window class */ /* register toplevel window class */
windowClass.style = CS_CLASSDC; windowClass.style = CS_CLASSDC;
windowClass.cbClsExtra = 0; windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = sizeof(PyObject*) + sizeof(PyThreadState*); windowClass.cbWndExtra = sizeof(PyObject *) + sizeof(PyThreadState *);
windowClass.hInstance = GetModuleHandle(NULL); windowClass.hInstance = GetModuleHandle(NULL);
/* windowClass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); */ /* windowClass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); */
windowClass.hbrBackground = NULL; windowClass.hbrBackground = NULL;
@ -718,11 +726,18 @@ PyImaging_CreateWindowWin32(PyObject* self, PyObject* args)
RegisterClass(&windowClass); /* FIXME: check return status */ RegisterClass(&windowClass); /* FIXME: check return status */
wnd = CreateWindowEx( wnd = CreateWindowEx(
0, windowClass.lpszClassName, title, 0,
windowClass.lpszClassName,
title,
WS_OVERLAPPEDWINDOW, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, width, height, CW_USEDEFAULT,
HWND_DESKTOP, NULL, NULL, NULL CW_USEDEFAULT,
); width,
height,
HWND_DESKTOP,
NULL,
NULL,
NULL);
if (!wnd) { if (!wnd) {
PyErr_SetString(PyExc_OSError, "failed to create window"); PyErr_SetString(PyExc_OSError, "failed to create window");
@ -731,76 +746,76 @@ PyImaging_CreateWindowWin32(PyObject* self, PyObject* args)
/* register window callback */ /* register window callback */
Py_INCREF(callback); Py_INCREF(callback);
SetWindowLongPtr(wnd, 0, (LONG_PTR) callback); SetWindowLongPtr(wnd, 0, (LONG_PTR)callback);
SetWindowLongPtr(wnd, sizeof(callback), (LONG_PTR) PyThreadState_Get()); SetWindowLongPtr(wnd, sizeof(callback), (LONG_PTR)PyThreadState_Get());
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS ShowWindow(wnd, SW_SHOWNORMAL);
ShowWindow(wnd, SW_SHOWNORMAL);
SetForegroundWindow(wnd); /* to make sure it's visible */ SetForegroundWindow(wnd); /* to make sure it's visible */
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
return Py_BuildValue(F_HANDLE, wnd); return Py_BuildValue(F_HANDLE, wnd);
} }
PyObject* PyObject *
PyImaging_EventLoopWin32(PyObject* self, PyObject* args) PyImaging_EventLoopWin32(PyObject *self, PyObject *args) {
{
MSG msg; MSG msg;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS while (mainloop && GetMessage(&msg, NULL, 0, 0)) {
while (mainloop && GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessage(&msg); DispatchMessage(&msg);
} }
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* windows WMF renderer */ /* windows WMF renderer */
#define GET32(p,o) ((DWORD*)(p+o))[0] #define GET32(p, o) ((DWORD *)(p + o))[0]
PyObject * PyObject *
PyImaging_DrawWmf(PyObject* self, PyObject* args) PyImaging_DrawWmf(PyObject *self, PyObject *args) {
{
HBITMAP bitmap; HBITMAP bitmap;
HENHMETAFILE meta; HENHMETAFILE meta;
BITMAPCOREHEADER core; BITMAPCOREHEADER core;
HDC dc; HDC dc;
RECT rect; RECT rect;
PyObject* buffer = NULL; PyObject *buffer = NULL;
char* ptr; char *ptr;
char* data; char *data;
Py_ssize_t datasize; Py_ssize_t datasize;
int width, height; int width, height;
int x0, y0, x1, y1; int x0, y0, x1, y1;
if (!PyArg_ParseTuple(args, "y#(ii)(iiii):_load", &data, &datasize, if (!PyArg_ParseTuple(
&width, &height, &x0, &x1, &y0, &y1)) { args,
"y#(ii)(iiii):_load",
&data,
&datasize,
&width,
&height,
&x0,
&x1,
&y0,
&y1)) {
return NULL; return NULL;
} }
/* step 1: copy metafile contents into METAFILE object */ /* step 1: copy metafile contents into METAFILE object */
if (datasize > 22 && GET32(data, 0) == 0x9ac6cdd7) { if (datasize > 22 && GET32(data, 0) == 0x9ac6cdd7) {
/* placeable windows metafile (22-byte aldus header) */ /* placeable windows metafile (22-byte aldus header) */
meta = SetWinMetaFileBits(datasize-22, data+22, NULL, NULL); meta = SetWinMetaFileBits(datasize - 22, data + 22, NULL, NULL);
} else if (datasize > 80 && GET32(data, 0) == 1 &&
GET32(data, 40) == 0x464d4520) {
} else if (datasize > 80 && GET32(data, 0) == 1 && GET32(data, 40) == 0x464d4520) {
/* enhanced metafile */ /* enhanced metafile */
meta = SetEnhMetaFileBits(datasize, data); meta = SetEnhMetaFileBits(datasize, data);
} else { } else {
/* unknown meta format */ /* unknown meta format */
meta = NULL; meta = NULL;
} }
if (!meta) { if (!meta) {
@ -818,9 +833,7 @@ PyImaging_DrawWmf(PyObject* self, PyObject* args)
dc = CreateCompatibleDC(NULL); dc = CreateCompatibleDC(NULL);
bitmap = CreateDIBSection( bitmap = CreateDIBSection(dc, (BITMAPINFO *)&core, DIB_RGB_COLORS, &ptr, NULL, 0);
dc, (BITMAPINFO*) &core, DIB_RGB_COLORS, &ptr, NULL, 0
);
if (!bitmap) { if (!bitmap) {
PyErr_SetString(PyExc_OSError, "cannot create bitmap"); PyErr_SetString(PyExc_OSError, "cannot create bitmap");
@ -850,7 +863,7 @@ PyImaging_DrawWmf(PyObject* self, PyObject* args)
GdiFlush(); GdiFlush();
buffer = PyBytes_FromStringAndSize(ptr, height * ((width*3 + 3) & -4)); buffer = PyBytes_FromStringAndSize(ptr, height * ((width * 3 + 3) & -4));
error: error:
DeleteEnhMetaFile(meta); DeleteEnhMetaFile(meta);
@ -875,18 +888,17 @@ error:
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* X11 screen grabber */ /* X11 screen grabber */
PyObject* PyObject *
PyImaging_GrabScreenX11(PyObject* self, PyObject* args) PyImaging_GrabScreenX11(PyObject *self, PyObject *args) {
{
int width, height; int width, height;
char* display_name; char *display_name;
xcb_connection_t* connection; xcb_connection_t *connection;
int screen_number; int screen_number;
xcb_screen_iterator_t iter; xcb_screen_iterator_t iter;
xcb_screen_t* screen = NULL; xcb_screen_t *screen = NULL;
xcb_get_image_reply_t* reply; xcb_get_image_reply_t *reply;
xcb_generic_error_t* error; xcb_generic_error_t *error;
PyObject* buffer = NULL; PyObject *buffer = NULL;
if (!PyArg_ParseTuple(args, "|z", &display_name)) { if (!PyArg_ParseTuple(args, "|z", &display_name)) {
return NULL; return NULL;
@ -896,7 +908,10 @@ PyImaging_GrabScreenX11(PyObject* self, PyObject* args)
connection = xcb_connect(display_name, &screen_number); connection = xcb_connect(display_name, &screen_number);
if (xcb_connection_has_error(connection)) { if (xcb_connection_has_error(connection)) {
PyErr_Format(PyExc_OSError, "X connection failed: error %i", xcb_connection_has_error(connection)); PyErr_Format(
PyExc_OSError,
"X connection failed: error %i",
xcb_connection_has_error(connection));
xcb_disconnect(connection); xcb_disconnect(connection);
return NULL; return NULL;
} }
@ -920,13 +935,26 @@ PyImaging_GrabScreenX11(PyObject* self, PyObject* args)
/* get image data */ /* get image data */
reply = xcb_get_image_reply(connection, reply = xcb_get_image_reply(
xcb_get_image(connection, XCB_IMAGE_FORMAT_Z_PIXMAP, screen->root, connection,
0, 0, width, height, 0x00ffffff), xcb_get_image(
&error); connection,
XCB_IMAGE_FORMAT_Z_PIXMAP,
screen->root,
0,
0,
width,
height,
0x00ffffff),
&error);
if (reply == NULL) { if (reply == NULL) {
PyErr_Format(PyExc_OSError, "X get_image failed: error %i (%i, %i, %i)", PyErr_Format(
error->error_code, error->major_code, error->minor_code, error->resource_id); PyExc_OSError,
"X get_image failed: error %i (%i, %i, %i)",
error->error_code,
error->major_code,
error->minor_code,
error->resource_id);
free(error); free(error);
xcb_disconnect(connection); xcb_disconnect(connection);
return NULL; return NULL;
@ -935,8 +963,8 @@ PyImaging_GrabScreenX11(PyObject* self, PyObject* args)
/* store data in Python buffer */ /* store data in Python buffer */
if (reply->depth == 24) { if (reply->depth == 24) {
buffer = PyBytes_FromStringAndSize((char*)xcb_get_image_data(reply), buffer = PyBytes_FromStringAndSize(
xcb_get_image_data_length(reply)); (char *)xcb_get_image_data(reply), xcb_get_image_data_length(reply));
} else { } else {
PyErr_Format(PyExc_OSError, "unsupported bit depth: %i", reply->depth); PyErr_Format(PyExc_OSError, "unsupported bit depth: %i", reply->depth);
} }

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,6 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
/* use Tests/make_hash.py to calculate these values */ /* use Tests/make_hash.py to calculate these values */
@ -19,23 +18,25 @@
static struct ImagingAccessInstance access_table[ACCESS_TABLE_SIZE]; static struct ImagingAccessInstance access_table[ACCESS_TABLE_SIZE];
static inline UINT32 static inline UINT32
hash(const char* mode) hash(const char *mode) {
{
UINT32 i = ACCESS_TABLE_HASH; UINT32 i = ACCESS_TABLE_HASH;
while (*mode) { while (*mode) {
i = ((i<<5) + i) ^ (UINT8) *mode++; i = ((i << 5) + i) ^ (UINT8)*mode++;
} }
return i % ACCESS_TABLE_SIZE; return i % ACCESS_TABLE_SIZE;
} }
static ImagingAccess static ImagingAccess
add_item(const char* mode) add_item(const char *mode) {
{
UINT32 i = hash(mode); UINT32 i = hash(mode);
/* printf("hash %s => %d\n", mode, i); */ /* printf("hash %s => %d\n", mode, i); */
if (access_table[i].mode && strcmp(access_table[i].mode, mode) != 0) { if (access_table[i].mode && strcmp(access_table[i].mode, mode) != 0) {
fprintf(stderr, "AccessInit: hash collision: %d for both %s and %s\n", fprintf(
i, mode, access_table[i].mode); stderr,
"AccessInit: hash collision: %d for both %s and %s\n",
i,
mode,
access_table[i].mode);
exit(1); exit(1);
} }
access_table[i].mode = mode; access_table[i].mode = mode;
@ -44,37 +45,33 @@ add_item(const char* mode)
/* fetch pointer to pixel line */ /* fetch pointer to pixel line */
static void* static void *
line_8(Imaging im, int x, int y) line_8(Imaging im, int x, int y) {
{
return &im->image8[y][x]; return &im->image8[y][x];
} }
static void* static void *
line_16(Imaging im, int x, int y) line_16(Imaging im, int x, int y) {
{ return &im->image8[y][x + x];
return &im->image8[y][x+x];
} }
static void* static void *
line_32(Imaging im, int x, int y) line_32(Imaging im, int x, int y) {
{
return &im->image32[y][x]; return &im->image32[y][x];
} }
/* fetch individual pixel */ /* fetch individual pixel */
static void static void
get_pixel(Imaging im, int x, int y, void* color) get_pixel(Imaging im, int x, int y, void *color) {
{ char *out = color;
char* out = color;
/* generic pixel access*/ /* generic pixel access*/
if (im->image8) { if (im->image8) {
out[0] = im->image8[y][x]; out[0] = im->image8[y][x];
} else { } else {
UINT8* p = (UINT8*) &im->image32[y][x]; UINT8 *p = (UINT8 *)&im->image32[y][x];
if (im->type == IMAGING_TYPE_UINT8 && im->bands == 2) { if (im->type == IMAGING_TYPE_UINT8 && im->bands == 2) {
out[0] = p[0]; out[0] = p[0];
out[1] = p[3]; out[1] = p[3];
@ -85,18 +82,16 @@ get_pixel(Imaging im, int x, int y, void* color)
} }
static void static void
get_pixel_8(Imaging im, int x, int y, void* color) get_pixel_8(Imaging im, int x, int y, void *color) {
{ char *out = color;
char* out = color;
out[0] = im->image8[y][x]; out[0] = im->image8[y][x];
} }
static void static void
get_pixel_16L(Imaging im, int x, int y, void* color) get_pixel_16L(Imaging im, int x, int y, void *color) {
{ UINT8 *in = (UINT8 *)&im->image[y][x + x];
UINT8* in = (UINT8*) &im->image[y][x+x];
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
UINT16 out = in[0] + (in[1]<<8); UINT16 out = in[0] + (in[1] << 8);
memcpy(color, &out, sizeof(out)); memcpy(color, &out, sizeof(out));
#else #else
memcpy(color, in, sizeof(UINT16)); memcpy(color, in, sizeof(UINT16));
@ -104,29 +99,26 @@ get_pixel_16L(Imaging im, int x, int y, void* color)
} }
static void static void
get_pixel_16B(Imaging im, int x, int y, void* color) get_pixel_16B(Imaging im, int x, int y, void *color) {
{ UINT8 *in = (UINT8 *)&im->image[y][x + x];
UINT8* in = (UINT8*) &im->image[y][x+x];
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
memcpy(color, in, sizeof(UINT16)); memcpy(color, in, sizeof(UINT16));
#else #else
UINT16 out = in[1] + (in[0]<<8); UINT16 out = in[1] + (in[0] << 8);
memcpy(color, &out, sizeof(out)); memcpy(color, &out, sizeof(out));
#endif #endif
} }
static void static void
get_pixel_32(Imaging im, int x, int y, void* color) get_pixel_32(Imaging im, int x, int y, void *color) {
{
memcpy(color, &im->image32[y][x], sizeof(INT32)); memcpy(color, &im->image32[y][x], sizeof(INT32));
} }
static void static void
get_pixel_32L(Imaging im, int x, int y, void* color) get_pixel_32L(Imaging im, int x, int y, void *color) {
{ UINT8 *in = (UINT8 *)&im->image[y][x * 4];
UINT8* in = (UINT8*) &im->image[y][x*4];
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
INT32 out = in[0] + (in[1]<<8) + (in[2]<<16) + (in[3]<<24); INT32 out = in[0] + (in[1] << 8) + (in[2] << 16) + (in[3] << 24);
memcpy(color, &out, sizeof(out)); memcpy(color, &out, sizeof(out));
#else #else
memcpy(color, in, sizeof(INT32)); memcpy(color, in, sizeof(INT32));
@ -134,13 +126,12 @@ get_pixel_32L(Imaging im, int x, int y, void* color)
} }
static void static void
get_pixel_32B(Imaging im, int x, int y, void* color) get_pixel_32B(Imaging im, int x, int y, void *color) {
{ UINT8 *in = (UINT8 *)&im->image[y][x * 4];
UINT8* in = (UINT8*) &im->image[y][x*4];
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
memcpy(color, in, sizeof(INT32)); memcpy(color, in, sizeof(INT32));
#else #else
INT32 out = in[3] + (in[2]<<8) + (in[1]<<16) + (in[0]<<24); INT32 out = in[3] + (in[2] << 8) + (in[1] << 16) + (in[0] << 24);
memcpy(color, &out, sizeof(out)); memcpy(color, &out, sizeof(out));
#endif #endif
} }
@ -148,47 +139,41 @@ get_pixel_32B(Imaging im, int x, int y, void* color)
/* store individual pixel */ /* store individual pixel */
static void static void
put_pixel(Imaging im, int x, int y, const void* color) put_pixel(Imaging im, int x, int y, const void *color) {
{
if (im->image8) { if (im->image8) {
im->image8[y][x] = *((UINT8*) color); im->image8[y][x] = *((UINT8 *)color);
} else { } else {
memcpy(&im->image32[y][x], color, sizeof(INT32)); memcpy(&im->image32[y][x], color, sizeof(INT32));
} }
} }
static void static void
put_pixel_8(Imaging im, int x, int y, const void* color) put_pixel_8(Imaging im, int x, int y, const void *color) {
{ im->image8[y][x] = *((UINT8 *)color);
im->image8[y][x] = *((UINT8*) color);
} }
static void static void
put_pixel_16L(Imaging im, int x, int y, const void* color) put_pixel_16L(Imaging im, int x, int y, const void *color) {
{ memcpy(&im->image8[y][x + x], color, 2);
memcpy(&im->image8[y][x+x], color, 2);
} }
static void static void
put_pixel_16B(Imaging im, int x, int y, const void* color) put_pixel_16B(Imaging im, int x, int y, const void *color) {
{ const char *in = color;
const char* in = color; UINT8 *out = (UINT8 *)&im->image8[y][x + x];
UINT8* out = (UINT8*) &im->image8[y][x+x];
out[0] = in[1]; out[0] = in[1];
out[1] = in[0]; out[1] = in[0];
} }
static void static void
put_pixel_32L(Imaging im, int x, int y, const void* color) put_pixel_32L(Imaging im, int x, int y, const void *color) {
{ memcpy(&im->image8[y][x * 4], color, 4);
memcpy(&im->image8[y][x*4], color, 4);
} }
static void static void
put_pixel_32B(Imaging im, int x, int y, const void* color) put_pixel_32B(Imaging im, int x, int y, const void *color) {
{ const char *in = color;
const char* in = color; UINT8 *out = (UINT8 *)&im->image8[y][x * 4];
UINT8* out = (UINT8*) &im->image8[y][x*4];
out[0] = in[3]; out[0] = in[3];
out[1] = in[2]; out[1] = in[2];
out[2] = in[1]; out[2] = in[1];
@ -196,19 +181,18 @@ put_pixel_32B(Imaging im, int x, int y, const void* color)
} }
static void static void
put_pixel_32(Imaging im, int x, int y, const void* color) put_pixel_32(Imaging im, int x, int y, const void *color) {
{
memcpy(&im->image32[y][x], color, sizeof(INT32)); memcpy(&im->image32[y][x], color, sizeof(INT32));
} }
void void
ImagingAccessInit() ImagingAccessInit() {
{ #define ADD(mode_, line_, get_pixel_, put_pixel_) \
#define ADD(mode_, line_, get_pixel_, put_pixel_) \ { \
{ ImagingAccess access = add_item(mode_); \ ImagingAccess access = add_item(mode_); \
access->line = line_; \ access->line = line_; \
access->get_pixel = get_pixel_; \ access->get_pixel = get_pixel_; \
access->put_pixel = put_pixel_; \ access->put_pixel = put_pixel_; \
} }
/* populate access table */ /* populate access table */
@ -236,8 +220,7 @@ ImagingAccessInit()
} }
ImagingAccess ImagingAccess
ImagingAccessNew(Imaging im) ImagingAccessNew(Imaging im) {
{
ImagingAccess access = &access_table[hash(im->mode)]; ImagingAccess access = &access_table[hash(im->mode)];
if (im->mode[0] != access->mode[0] || strcmp(im->mode, access->mode) != 0) { if (im->mode[0] != access->mode[0] || strcmp(im->mode, access->mode) != 0) {
return NULL; return NULL;
@ -246,7 +229,4 @@ ImagingAccessNew(Imaging im)
} }
void void
_ImagingAccessDelete(Imaging im, ImagingAccess access) _ImagingAccessDelete(Imaging im, ImagingAccess access) {}
{
}

View File

@ -8,39 +8,30 @@
* See the README file for details on usage and redistribution. * See the README file for details on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#define PRECISION_BITS 7 #define PRECISION_BITS 7
typedef struct typedef struct {
{
UINT8 r; UINT8 r;
UINT8 g; UINT8 g;
UINT8 b; UINT8 b;
UINT8 a; UINT8 a;
} rgba8; } rgba8;
Imaging Imaging
ImagingAlphaComposite(Imaging imDst, Imaging imSrc) ImagingAlphaComposite(Imaging imDst, Imaging imSrc) {
{
Imaging imOut; Imaging imOut;
int x, y; int x, y;
/* Check arguments */ /* Check arguments */
if (!imDst || !imSrc || if (!imDst || !imSrc || strcmp(imDst->mode, "RGBA") ||
strcmp(imDst->mode, "RGBA") || imDst->type != IMAGING_TYPE_UINT8 || imDst->bands != 4) {
imDst->type != IMAGING_TYPE_UINT8 ||
imDst->bands != 4) {
return ImagingError_ModeError(); return ImagingError_ModeError();
} }
if (strcmp(imDst->mode, imSrc->mode) || if (strcmp(imDst->mode, imSrc->mode) || imDst->type != imSrc->type ||
imDst->type != imSrc->type || imDst->bands != imSrc->bands || imDst->xsize != imSrc->xsize ||
imDst->bands != imSrc->bands ||
imDst->xsize != imSrc->xsize ||
imDst->ysize != imSrc->ysize) { imDst->ysize != imSrc->ysize) {
return ImagingError_Mismatch(); return ImagingError_Mismatch();
} }
@ -51,11 +42,11 @@ ImagingAlphaComposite(Imaging imDst, Imaging imSrc)
} }
for (y = 0; y < imDst->ysize; y++) { for (y = 0; y < imDst->ysize; y++) {
rgba8* dst = (rgba8*) imDst->image[y]; rgba8 *dst = (rgba8 *)imDst->image[y];
rgba8* src = (rgba8*) imSrc->image[y]; rgba8 *src = (rgba8 *)imSrc->image[y];
rgba8* out = (rgba8*) imOut->image[y]; rgba8 *out = (rgba8 *)imOut->image[y];
for (x = 0; x < imDst->xsize; x ++) { for (x = 0; x < imDst->xsize; x++) {
if (src->a == 0) { if (src->a == 0) {
// Copy 4 bytes at once. // Copy 4 bytes at once.
*out = *dst; *out = *dst;
@ -69,21 +60,25 @@ ImagingAlphaComposite(Imaging imDst, Imaging imSrc)
UINT32 outa255 = src->a * 255 + blend; UINT32 outa255 = src->a * 255 + blend;
// There we use 7 bits for precision. // There we use 7 bits for precision.
// We could use more, but we go beyond 32 bits. // We could use more, but we go beyond 32 bits.
UINT32 coef1 = src->a * 255 * 255 * (1<<PRECISION_BITS) / outa255; UINT32 coef1 = src->a * 255 * 255 * (1 << PRECISION_BITS) / outa255;
UINT32 coef2 = 255 * (1<<PRECISION_BITS) - coef1; UINT32 coef2 = 255 * (1 << PRECISION_BITS) - coef1;
tmpr = src->r * coef1 + dst->r * coef2; tmpr = src->r * coef1 + dst->r * coef2;
tmpg = src->g * coef1 + dst->g * coef2; tmpg = src->g * coef1 + dst->g * coef2;
tmpb = src->b * coef1 + dst->b * coef2; tmpb = src->b * coef1 + dst->b * coef2;
out->r = SHIFTFORDIV255(tmpr + (0x80<<PRECISION_BITS)) >> PRECISION_BITS; out->r =
out->g = SHIFTFORDIV255(tmpg + (0x80<<PRECISION_BITS)) >> PRECISION_BITS; SHIFTFORDIV255(tmpr + (0x80 << PRECISION_BITS)) >> PRECISION_BITS;
out->b = SHIFTFORDIV255(tmpb + (0x80<<PRECISION_BITS)) >> PRECISION_BITS; out->g =
SHIFTFORDIV255(tmpg + (0x80 << PRECISION_BITS)) >> PRECISION_BITS;
out->b =
SHIFTFORDIV255(tmpb + (0x80 << PRECISION_BITS)) >> PRECISION_BITS;
out->a = SHIFTFORDIV255(outa255 + 0x80); out->a = SHIFTFORDIV255(outa255 + 0x80);
} }
dst++; src++; out++; dst++;
src++;
out++;
} }
} }
return imOut; return imOut;

View File

@ -15,23 +15,20 @@
* See the README file for details on usage and redistribution. * See the README file for details on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
Imaging Imaging
ImagingGetBand(Imaging imIn, int band) ImagingGetBand(Imaging imIn, int band) {
{
Imaging imOut; Imaging imOut;
int x, y; int x, y;
/* Check arguments */ /* Check arguments */
if (!imIn || imIn->type != IMAGING_TYPE_UINT8) { if (!imIn || imIn->type != IMAGING_TYPE_UINT8) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
if (band < 0 || band >= imIn->bands) { if (band < 0 || band >= imIn->bands) {
return (Imaging) ImagingError_ValueError("band index out of range"); return (Imaging)ImagingError_ValueError("band index out of range");
} }
/* Shortcuts */ /* Shortcuts */
@ -51,8 +48,8 @@ ImagingGetBand(Imaging imIn, int band)
/* Extract band from image */ /* Extract band from image */
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
UINT8* in = (UINT8*) imIn->image[y] + band; UINT8 *in = (UINT8 *)imIn->image[y] + band;
UINT8* out = imOut->image8[y]; UINT8 *out = imOut->image8[y];
x = 0; x = 0;
for (; x < imIn->xsize - 3; x += 4) { for (; x < imIn->xsize - 3; x += 4) {
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]); UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
@ -68,15 +65,13 @@ ImagingGetBand(Imaging imIn, int band)
return imOut; return imOut;
} }
int int
ImagingSplit(Imaging imIn, Imaging bands[4]) ImagingSplit(Imaging imIn, Imaging bands[4]) {
{
int i, j, x, y; int i, j, x, y;
/* Check arguments */ /* Check arguments */
if (!imIn || imIn->type != IMAGING_TYPE_UINT8) { if (!imIn || imIn->type != IMAGING_TYPE_UINT8) {
(void) ImagingError_ModeError(); (void)ImagingError_ModeError();
return 0; return 0;
} }
@ -88,7 +83,7 @@ ImagingSplit(Imaging imIn, Imaging bands[4])
for (i = 0; i < imIn->bands; i++) { for (i = 0; i < imIn->bands; i++) {
bands[i] = ImagingNewDirty("L", imIn->xsize, imIn->ysize); bands[i] = ImagingNewDirty("L", imIn->xsize, imIn->ysize);
if ( ! bands[i]) { if (!bands[i]) {
for (j = 0; j < i; ++j) { for (j = 0; j < i; ++j) {
ImagingDelete(bands[j]); ImagingDelete(bands[j]);
} }
@ -99,14 +94,14 @@ ImagingSplit(Imaging imIn, Imaging bands[4])
/* Extract bands from image */ /* Extract bands from image */
if (imIn->bands == 2) { if (imIn->bands == 2) {
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
UINT8* in = (UINT8*) imIn->image[y]; UINT8 *in = (UINT8 *)imIn->image[y];
UINT8* out0 = bands[0]->image8[y]; UINT8 *out0 = bands[0]->image8[y];
UINT8* out1 = bands[1]->image8[y]; UINT8 *out1 = bands[1]->image8[y];
x = 0; x = 0;
for (; x < imIn->xsize - 3; x += 4) { for (; x < imIn->xsize - 3; x += 4) {
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]); UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
memcpy(out0 + x, &v, sizeof(v)); memcpy(out0 + x, &v, sizeof(v));
v = MAKE_UINT32(in[0+3], in[4+3], in[8+3], in[12+3]); v = MAKE_UINT32(in[0 + 3], in[4 + 3], in[8 + 3], in[12 + 3]);
memcpy(out1 + x, &v, sizeof(v)); memcpy(out1 + x, &v, sizeof(v));
in += 16; in += 16;
} }
@ -118,17 +113,17 @@ ImagingSplit(Imaging imIn, Imaging bands[4])
} }
} else if (imIn->bands == 3) { } else if (imIn->bands == 3) {
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
UINT8* in = (UINT8*) imIn->image[y]; UINT8 *in = (UINT8 *)imIn->image[y];
UINT8* out0 = bands[0]->image8[y]; UINT8 *out0 = bands[0]->image8[y];
UINT8* out1 = bands[1]->image8[y]; UINT8 *out1 = bands[1]->image8[y];
UINT8* out2 = bands[2]->image8[y]; UINT8 *out2 = bands[2]->image8[y];
x = 0; x = 0;
for (; x < imIn->xsize - 3; x += 4) { for (; x < imIn->xsize - 3; x += 4) {
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]); UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
memcpy(out0 + x, &v, sizeof(v)); memcpy(out0 + x, &v, sizeof(v));
v = MAKE_UINT32(in[0+1], in[4+1], in[8+1], in[12+1]); v = MAKE_UINT32(in[0 + 1], in[4 + 1], in[8 + 1], in[12 + 1]);
memcpy(out1 + x, &v, sizeof(v)); memcpy(out1 + x, &v, sizeof(v));
v = MAKE_UINT32(in[0+2], in[4+2], in[8+2], in[12+2]); v = MAKE_UINT32(in[0 + 2], in[4 + 2], in[8 + 2], in[12 + 2]);
memcpy(out2 + x, &v, sizeof(v)); memcpy(out2 + x, &v, sizeof(v));
in += 16; in += 16;
} }
@ -141,20 +136,20 @@ ImagingSplit(Imaging imIn, Imaging bands[4])
} }
} else { } else {
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
UINT8* in = (UINT8*) imIn->image[y]; UINT8 *in = (UINT8 *)imIn->image[y];
UINT8* out0 = bands[0]->image8[y]; UINT8 *out0 = bands[0]->image8[y];
UINT8* out1 = bands[1]->image8[y]; UINT8 *out1 = bands[1]->image8[y];
UINT8* out2 = bands[2]->image8[y]; UINT8 *out2 = bands[2]->image8[y];
UINT8* out3 = bands[3]->image8[y]; UINT8 *out3 = bands[3]->image8[y];
x = 0; x = 0;
for (; x < imIn->xsize - 3; x += 4) { for (; x < imIn->xsize - 3; x += 4) {
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]); UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
memcpy(out0 + x, &v, sizeof(v)); memcpy(out0 + x, &v, sizeof(v));
v = MAKE_UINT32(in[0+1], in[4+1], in[8+1], in[12+1]); v = MAKE_UINT32(in[0 + 1], in[4 + 1], in[8 + 1], in[12 + 1]);
memcpy(out1 + x, &v, sizeof(v)); memcpy(out1 + x, &v, sizeof(v));
v = MAKE_UINT32(in[0+2], in[4+2], in[8+2], in[12+2]); v = MAKE_UINT32(in[0 + 2], in[4 + 2], in[8 + 2], in[12 + 2]);
memcpy(out2 + x, &v, sizeof(v)); memcpy(out2 + x, &v, sizeof(v));
v = MAKE_UINT32(in[0+3], in[4+3], in[8+3], in[12+3]); v = MAKE_UINT32(in[0 + 3], in[4 + 3], in[8 + 3], in[12 + 3]);
memcpy(out3 + x, &v, sizeof(v)); memcpy(out3 + x, &v, sizeof(v));
in += 16; in += 16;
} }
@ -171,25 +166,22 @@ ImagingSplit(Imaging imIn, Imaging bands[4])
return imIn->bands; return imIn->bands;
} }
Imaging Imaging
ImagingPutBand(Imaging imOut, Imaging imIn, int band) ImagingPutBand(Imaging imOut, Imaging imIn, int band) {
{
int x, y; int x, y;
/* Check arguments */ /* Check arguments */
if (!imIn || imIn->bands != 1 || !imOut) { if (!imIn || imIn->bands != 1 || !imOut) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
if (band < 0 || band >= imOut->bands) { if (band < 0 || band >= imOut->bands) {
return (Imaging) ImagingError_ValueError("band index out of range"); return (Imaging)ImagingError_ValueError("band index out of range");
} }
if (imIn->type != imOut->type || if (imIn->type != imOut->type || imIn->xsize != imOut->xsize ||
imIn->xsize != imOut->xsize ||
imIn->ysize != imOut->ysize) { imIn->ysize != imOut->ysize) {
return (Imaging) ImagingError_Mismatch(); return (Imaging)ImagingError_Mismatch();
} }
/* Shortcuts */ /* Shortcuts */
@ -204,8 +196,8 @@ ImagingPutBand(Imaging imOut, Imaging imIn, int band)
/* Insert band into image */ /* Insert band into image */
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
UINT8* in = imIn->image8[y]; UINT8 *in = imIn->image8[y];
UINT8* out = (UINT8*) imOut->image[y] + band; UINT8 *out = (UINT8 *)imOut->image[y] + band;
for (x = 0; x < imIn->xsize; x++) { for (x = 0; x < imIn->xsize; x++) {
*out = in[x]; *out = in[x];
out += 4; out += 4;
@ -216,17 +208,16 @@ ImagingPutBand(Imaging imOut, Imaging imIn, int band)
} }
Imaging Imaging
ImagingFillBand(Imaging imOut, int band, int color) ImagingFillBand(Imaging imOut, int band, int color) {
{
int x, y; int x, y;
/* Check arguments */ /* Check arguments */
if (!imOut || imOut->type != IMAGING_TYPE_UINT8) { if (!imOut || imOut->type != IMAGING_TYPE_UINT8) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
if (band < 0 || band >= imOut->bands) { if (band < 0 || band >= imOut->bands) {
return (Imaging) ImagingError_ValueError("band index out of range"); return (Imaging)ImagingError_ValueError("band index out of range");
} }
/* Special case for LXXA etc */ /* Special case for LXXA etc */
@ -238,9 +229,9 @@ ImagingFillBand(Imaging imOut, int band, int color)
/* Insert color into image */ /* Insert color into image */
for (y = 0; y < imOut->ysize; y++) { for (y = 0; y < imOut->ysize; y++) {
UINT8* out = (UINT8*) imOut->image[y] + band; UINT8 *out = (UINT8 *)imOut->image[y] + band;
for (x = 0; x < imOut->xsize; x++) { for (x = 0; x < imOut->xsize; x++) {
*out = (UINT8) color; *out = (UINT8)color;
out += 4; out += 4;
} }
} }
@ -249,40 +240,39 @@ ImagingFillBand(Imaging imOut, int band, int color)
} }
Imaging Imaging
ImagingMerge(const char* mode, Imaging bands[4]) ImagingMerge(const char *mode, Imaging bands[4]) {
{
int i, x, y; int i, x, y;
int bandsCount = 0; int bandsCount = 0;
Imaging imOut; Imaging imOut;
Imaging firstBand; Imaging firstBand;
firstBand = bands[0]; firstBand = bands[0];
if ( ! firstBand) { if (!firstBand) {
return (Imaging) ImagingError_ValueError("wrong number of bands"); return (Imaging)ImagingError_ValueError("wrong number of bands");
} }
for (i = 0; i < 4; ++i) { for (i = 0; i < 4; ++i) {
if ( ! bands[i]) { if (!bands[i]) {
break; break;
} }
if (bands[i]->bands != 1) { if (bands[i]->bands != 1) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
if (bands[i]->xsize != firstBand->xsize if (bands[i]->xsize != firstBand->xsize ||
|| bands[i]->ysize != firstBand->ysize) { bands[i]->ysize != firstBand->ysize) {
return (Imaging) ImagingError_Mismatch(); return (Imaging)ImagingError_Mismatch();
} }
} }
bandsCount = i; bandsCount = i;
imOut = ImagingNewDirty(mode, firstBand->xsize, firstBand->ysize); imOut = ImagingNewDirty(mode, firstBand->xsize, firstBand->ysize);
if ( ! imOut) { if (!imOut) {
return NULL; return NULL;
} }
if (imOut->bands != bandsCount) { if (imOut->bands != bandsCount) {
ImagingDelete(imOut); ImagingDelete(imOut);
return (Imaging) ImagingError_ValueError("wrong number of bands"); return (Imaging)ImagingError_ValueError("wrong number of bands");
} }
if (imOut->bands == 1) { if (imOut->bands == 1) {
@ -291,30 +281,30 @@ ImagingMerge(const char* mode, Imaging bands[4])
if (imOut->bands == 2) { if (imOut->bands == 2) {
for (y = 0; y < imOut->ysize; y++) { for (y = 0; y < imOut->ysize; y++) {
UINT8* in0 = bands[0]->image8[y]; UINT8 *in0 = bands[0]->image8[y];
UINT8* in1 = bands[1]->image8[y]; UINT8 *in1 = bands[1]->image8[y];
UINT32* out = (UINT32*) imOut->image32[y]; UINT32 *out = (UINT32 *)imOut->image32[y];
for (x = 0; x < imOut->xsize; x++) { for (x = 0; x < imOut->xsize; x++) {
out[x] = MAKE_UINT32(in0[x], 0, 0, in1[x]); out[x] = MAKE_UINT32(in0[x], 0, 0, in1[x]);
} }
} }
} else if (imOut->bands == 3) { } else if (imOut->bands == 3) {
for (y = 0; y < imOut->ysize; y++) { for (y = 0; y < imOut->ysize; y++) {
UINT8* in0 = bands[0]->image8[y]; UINT8 *in0 = bands[0]->image8[y];
UINT8* in1 = bands[1]->image8[y]; UINT8 *in1 = bands[1]->image8[y];
UINT8* in2 = bands[2]->image8[y]; UINT8 *in2 = bands[2]->image8[y];
UINT32* out = (UINT32*) imOut->image32[y]; UINT32 *out = (UINT32 *)imOut->image32[y];
for (x = 0; x < imOut->xsize; x++) { for (x = 0; x < imOut->xsize; x++) {
out[x] = MAKE_UINT32(in0[x], in1[x], in2[x], 0); out[x] = MAKE_UINT32(in0[x], in1[x], in2[x], 0);
} }
} }
} else if (imOut->bands == 4) { } else if (imOut->bands == 4) {
for (y = 0; y < imOut->ysize; y++) { for (y = 0; y < imOut->ysize; y++) {
UINT8* in0 = bands[0]->image8[y]; UINT8 *in0 = bands[0]->image8[y];
UINT8* in1 = bands[1]->image8[y]; UINT8 *in1 = bands[1]->image8[y];
UINT8* in2 = bands[2]->image8[y]; UINT8 *in2 = bands[2]->image8[y];
UINT8* in3 = bands[3]->image8[y]; UINT8 *in3 = bands[3]->image8[y];
UINT32* out = (UINT32*) imOut->image32[y]; UINT32 *out = (UINT32 *)imOut->image32[y];
for (x = 0; x < imOut->xsize; x++) { for (x = 0; x < imOut->xsize; x++) {
out[x] = MAKE_UINT32(in0[x], in1[x], in2[x], in3[x]); out[x] = MAKE_UINT32(in0[x], in1[x], in2[x], in3[x]);
} }

View File

@ -11,10 +11,8 @@
* https://creativecommons.org/publicdomain/zero/1.0/ * https://creativecommons.org/publicdomain/zero/1.0/
*/ */
#include "Imaging.h" #include "Imaging.h"
typedef struct { typedef struct {
UINT8 r, g, b, a; UINT8 r, g, b, a;
} rgba; } rgba;
@ -37,23 +35,24 @@ typedef struct {
UINT8 lut[6]; UINT8 lut[6];
} bc3_alpha; } bc3_alpha;
#define LOAD16(p) \ #define LOAD16(p) (p)[0] | ((p)[1] << 8)
(p)[0] | ((p)[1] << 8)
#define LOAD32(p) \ #define LOAD32(p) (p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24)
(p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24)
static void bc1_color_load(bc1_color *dst, const UINT8 *src) { static void
bc1_color_load(bc1_color *dst, const UINT8 *src) {
dst->c0 = LOAD16(src); dst->c0 = LOAD16(src);
dst->c1 = LOAD16(src + 2); dst->c1 = LOAD16(src + 2);
dst->lut = LOAD32(src + 4); dst->lut = LOAD32(src + 4);
} }
static void bc3_alpha_load(bc3_alpha *dst, const UINT8 *src) { static void
bc3_alpha_load(bc3_alpha *dst, const UINT8 *src) {
memcpy(dst, src, sizeof(bc3_alpha)); memcpy(dst, src, sizeof(bc3_alpha));
} }
static rgba decode_565(UINT16 x) { static rgba
decode_565(UINT16 x) {
rgba c; rgba c;
int r, g, b; int r, g, b;
r = (x & 0xf800) >> 8; r = (x & 0xf800) >> 8;
@ -69,7 +68,8 @@ static rgba decode_565(UINT16 x) {
return c; return c;
} }
static void decode_bc1_color(rgba *dst, const UINT8 *src) { static void
decode_bc1_color(rgba *dst, const UINT8 *src) {
bc1_color col; bc1_color col;
rgba p[4]; rgba p[4];
int n, cw; int n, cw;
@ -85,13 +85,13 @@ static void decode_bc1_color(rgba *dst, const UINT8 *src) {
g1 = p[1].g; g1 = p[1].g;
b1 = p[1].b; b1 = p[1].b;
if (col.c0 > col.c1) { if (col.c0 > col.c1) {
p[2].r = (2*r0 + 1*r1) / 3; p[2].r = (2 * r0 + 1 * r1) / 3;
p[2].g = (2*g0 + 1*g1) / 3; p[2].g = (2 * g0 + 1 * g1) / 3;
p[2].b = (2*b0 + 1*b1) / 3; p[2].b = (2 * b0 + 1 * b1) / 3;
p[2].a = 0xff; p[2].a = 0xff;
p[3].r = (1*r0 + 2*r1) / 3; p[3].r = (1 * r0 + 2 * r1) / 3;
p[3].g = (1*g0 + 2*g1) / 3; p[3].g = (1 * g0 + 2 * g1) / 3;
p[3].b = (1*b0 + 2*b1) / 3; p[3].b = (1 * b0 + 2 * b1) / 3;
p[3].a = 0xff; p[3].a = 0xff;
} else { } else {
p[2].r = (r0 + r1) / 2; p[2].r = (r0 + r1) / 2;
@ -109,7 +109,8 @@ static void decode_bc1_color(rgba *dst, const UINT8 *src) {
} }
} }
static void decode_bc3_alpha(char *dst, const UINT8 *src, int stride, int o) { static void
decode_bc3_alpha(char *dst, const UINT8 *src, int stride, int o) {
bc3_alpha b; bc3_alpha b;
UINT16 a0, a1; UINT16 a0, a1;
UINT8 a[8]; UINT8 a[8];
@ -121,17 +122,17 @@ static void decode_bc3_alpha(char *dst, const UINT8 *src, int stride, int o) {
a[0] = (UINT8)a0; a[0] = (UINT8)a0;
a[1] = (UINT8)a1; a[1] = (UINT8)a1;
if (a0 > a1) { if (a0 > a1) {
a[2] = (6*a0 + 1*a1) / 7; a[2] = (6 * a0 + 1 * a1) / 7;
a[3] = (5*a0 + 2*a1) / 7; a[3] = (5 * a0 + 2 * a1) / 7;
a[4] = (4*a0 + 3*a1) / 7; a[4] = (4 * a0 + 3 * a1) / 7;
a[5] = (3*a0 + 4*a1) / 7; a[5] = (3 * a0 + 4 * a1) / 7;
a[6] = (2*a0 + 5*a1) / 7; a[6] = (2 * a0 + 5 * a1) / 7;
a[7] = (1*a0 + 6*a1) / 7; a[7] = (1 * a0 + 6 * a1) / 7;
} else { } else {
a[2] = (4*a0 + 1*a1) / 5; a[2] = (4 * a0 + 1 * a1) / 5;
a[3] = (3*a0 + 2*a1) / 5; a[3] = (3 * a0 + 2 * a1) / 5;
a[4] = (2*a0 + 3*a1) / 5; a[4] = (2 * a0 + 3 * a1) / 5;
a[5] = (1*a0 + 4*a1) / 5; a[5] = (1 * a0 + 4 * a1) / 5;
a[6] = 0; a[6] = 0;
a[7] = 0xff; a[7] = 0xff;
} }
@ -143,15 +144,17 @@ static void decode_bc3_alpha(char *dst, const UINT8 *src, int stride, int o) {
lut = b.lut[3] | (b.lut[4] << 8) | (b.lut[5] << 16); lut = b.lut[3] | (b.lut[4] << 8) | (b.lut[5] << 16);
for (n = 0; n < 8; n++) { for (n = 0; n < 8; n++) {
aw = 7 & (lut >> (3 * n)); aw = 7 & (lut >> (3 * n));
dst[stride * (8+n) + o] = a[aw]; dst[stride * (8 + n) + o] = a[aw];
} }
} }
static void decode_bc1_block(rgba *col, const UINT8* src) { static void
decode_bc1_block(rgba *col, const UINT8 *src) {
decode_bc1_color(col, src); decode_bc1_color(col, src);
} }
static void decode_bc2_block(rgba *col, const UINT8* src) { static void
decode_bc2_block(rgba *col, const UINT8 *src) {
int n, bitI, byI, av; int n, bitI, byI, av;
decode_bc1_color(col, src + 8); decode_bc1_color(col, src + 8);
for (n = 0; n < 16; n++) { for (n = 0; n < 16; n++) {
@ -163,30 +166,36 @@ static void decode_bc2_block(rgba *col, const UINT8* src) {
} }
} }
static void decode_bc3_block(rgba *col, const UINT8* src) { static void
decode_bc3_block(rgba *col, const UINT8 *src) {
decode_bc1_color(col, src + 8); decode_bc1_color(col, src + 8);
decode_bc3_alpha((char *)col, src, sizeof(col[0]), 3); decode_bc3_alpha((char *)col, src, sizeof(col[0]), 3);
} }
static void decode_bc4_block(lum *col, const UINT8* src) { static void
decode_bc4_block(lum *col, const UINT8 *src) {
decode_bc3_alpha((char *)col, src, sizeof(col[0]), 0); decode_bc3_alpha((char *)col, src, sizeof(col[0]), 0);
} }
static void decode_bc5_block(rgba *col, const UINT8* src) { static void
decode_bc5_block(rgba *col, const UINT8 *src) {
decode_bc3_alpha((char *)col, src, sizeof(col[0]), 0); decode_bc3_alpha((char *)col, src, sizeof(col[0]), 0);
decode_bc3_alpha((char *)col, src + 8, sizeof(col[0]), 1); decode_bc3_alpha((char *)col, src + 8, sizeof(col[0]), 1);
} }
/* BC6 and BC7 are described here: /* BC6 and BC7 are described here:
https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_bptc.txt */ https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_bptc.txt
*/
static UINT8 get_bit(const UINT8* src, int bit) { static UINT8
get_bit(const UINT8 *src, int bit) {
int by = bit >> 3; int by = bit >> 3;
bit &= 7; bit &= 7;
return (src[by] >> bit) & 1; return (src[by] >> bit) & 1;
} }
static UINT8 get_bits(const UINT8* src, int bit, int count) { static UINT8
get_bits(const UINT8 *src, int bit, int count) {
UINT8 v; UINT8 v;
int x; int x;
int by = bit >> 3; int by = bit >> 3;
@ -197,7 +206,7 @@ static UINT8 get_bits(const UINT8* src, int bit, int count) {
if (bit + count <= 8) { if (bit + count <= 8) {
v = (src[by] >> bit) & ((1 << count) - 1); v = (src[by] >> bit) & ((1 << count) - 1);
} else { } else {
x = src[by] | (src[by+1] << 8); x = src[by] | (src[by + 1] << 8);
v = (x >> bit) & ((1 << count) - 1); v = (x >> bit) & ((1 << count) - 1);
} }
return v; return v;
@ -225,73 +234,51 @@ static const bc7_mode_info bc7_modes[] = {
{1, 0, 2, 1, 5, 6, 0, 0, 2, 3}, {1, 0, 2, 1, 5, 6, 0, 0, 2, 3},
{1, 0, 2, 0, 7, 8, 0, 0, 2, 2}, {1, 0, 2, 0, 7, 8, 0, 0, 2, 2},
{1, 0, 0, 0, 7, 7, 1, 0, 4, 0}, {1, 0, 0, 0, 7, 7, 1, 0, 4, 0},
{2, 6, 0, 0, 5, 5, 1, 0, 2, 0} {2, 6, 0, 0, 5, 5, 1, 0, 2, 0}};
};
/* Subset indices: /* Subset indices:
Table.P2, 1 bit per index */ Table.P2, 1 bit per index */
static const UINT16 bc7_si2[] = { static const UINT16 bc7_si2[] = {
0xcccc, 0x8888, 0xeeee, 0xecc8, 0xc880, 0xfeec, 0xfec8, 0xec80, 0xcccc, 0x8888, 0xeeee, 0xecc8, 0xc880, 0xfeec, 0xfec8, 0xec80, 0xc800, 0xffec,
0xc800, 0xffec, 0xfe80, 0xe800, 0xffe8, 0xff00, 0xfff0, 0xf000, 0xfe80, 0xe800, 0xffe8, 0xff00, 0xfff0, 0xf000, 0xf710, 0x008e, 0x7100, 0x08ce,
0xf710, 0x008e, 0x7100, 0x08ce, 0x008c, 0x7310, 0x3100, 0x8cce, 0x008c, 0x7310, 0x3100, 0x8cce, 0x088c, 0x3110, 0x6666, 0x366c, 0x17e8, 0x0ff0,
0x088c, 0x3110, 0x6666, 0x366c, 0x17e8, 0x0ff0, 0x718e, 0x399c, 0x718e, 0x399c, 0xaaaa, 0xf0f0, 0x5a5a, 0x33cc, 0x3c3c, 0x55aa, 0x9696, 0xa55a,
0xaaaa, 0xf0f0, 0x5a5a, 0x33cc, 0x3c3c, 0x55aa, 0x9696, 0xa55a, 0x73ce, 0x13c8, 0x324c, 0x3bdc, 0x6996, 0xc33c, 0x9966, 0x0660, 0x0272, 0x04e4,
0x73ce, 0x13c8, 0x324c, 0x3bdc, 0x6996, 0xc33c, 0x9966, 0x0660, 0x4e40, 0x2720, 0xc936, 0x936c, 0x39c6, 0x639c, 0x9336, 0x9cc6, 0x817e, 0xe718,
0x0272, 0x04e4, 0x4e40, 0x2720, 0xc936, 0x936c, 0x39c6, 0x639c, 0xccf0, 0x0fcc, 0x7744, 0xee22};
0x9336, 0x9cc6, 0x817e, 0xe718, 0xccf0, 0x0fcc, 0x7744, 0xee22};
/* Table.P3, 2 bits per index */ /* Table.P3, 2 bits per index */
static const UINT32 bc7_si3[] = { static const UINT32 bc7_si3[] = {
0xaa685050, 0x6a5a5040, 0x5a5a4200, 0x5450a0a8, 0xaa685050, 0x6a5a5040, 0x5a5a4200, 0x5450a0a8, 0xa5a50000, 0xa0a05050, 0x5555a0a0,
0xa5a50000, 0xa0a05050, 0x5555a0a0, 0x5a5a5050, 0x5a5a5050, 0xaa550000, 0xaa555500, 0xaaaa5500, 0x90909090, 0x94949494, 0xa4a4a4a4,
0xaa550000, 0xaa555500, 0xaaaa5500, 0x90909090, 0xa9a59450, 0x2a0a4250, 0xa5945040, 0x0a425054, 0xa5a5a500, 0x55a0a0a0, 0xa8a85454,
0x94949494, 0xa4a4a4a4, 0xa9a59450, 0x2a0a4250, 0x6a6a4040, 0xa4a45000, 0x1a1a0500, 0x0050a4a4, 0xaaa59090, 0x14696914, 0x69691400,
0xa5945040, 0x0a425054, 0xa5a5a500, 0x55a0a0a0, 0xa08585a0, 0xaa821414, 0x50a4a450, 0x6a5a0200, 0xa9a58000, 0x5090a0a8, 0xa8a09050,
0xa8a85454, 0x6a6a4040, 0xa4a45000, 0x1a1a0500, 0x24242424, 0x00aa5500, 0x24924924, 0x24499224, 0x50a50a50, 0x500aa550, 0xaaaa4444,
0x0050a4a4, 0xaaa59090, 0x14696914, 0x69691400, 0x66660000, 0xa5a0a5a0, 0x50a050a0, 0x69286928, 0x44aaaa44, 0x66666600, 0xaa444444,
0xa08585a0, 0xaa821414, 0x50a4a450, 0x6a5a0200, 0x54a854a8, 0x95809580, 0x96969600, 0xa85454a8, 0x80959580, 0xaa141414, 0x96960000,
0xa9a58000, 0x5090a0a8, 0xa8a09050, 0x24242424, 0xaaaa1414, 0xa05050a0, 0xa0a5a5a0, 0x96000000, 0x40804080, 0xa9a8a9a8, 0xaaaaaa44,
0x00aa5500, 0x24924924, 0x24499224, 0x50a50a50, 0x2a4a5254};
0x500aa550, 0xaaaa4444, 0x66660000, 0xa5a0a5a0,
0x50a050a0, 0x69286928, 0x44aaaa44, 0x66666600,
0xaa444444, 0x54a854a8, 0x95809580, 0x96969600,
0xa85454a8, 0x80959580, 0xaa141414, 0x96960000,
0xaaaa1414, 0xa05050a0, 0xa0a5a5a0, 0x96000000,
0x40804080, 0xa9a8a9a8, 0xaaaaaa44, 0x2a4a5254};
/* Anchor indices: /* Anchor indices:
Table.A2 */ Table.A2 */
static const char bc7_ai0[] = { static const char bc7_ai0[] = {
15,15,15,15,15,15,15,15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 8, 2, 2, 8,
15,15,15,15,15,15,15,15, 8, 15, 2, 8, 2, 2, 8, 8, 2, 2, 15, 15, 6, 8, 2, 8, 15, 15, 2, 8, 2, 2,
15, 2, 8, 2, 2, 8, 8,15, 2, 15, 15, 6, 6, 2, 6, 8, 15, 15, 2, 2, 15, 15, 15, 15, 15, 2, 2, 15};
2, 8, 2, 2, 8, 8, 2, 2,
15,15, 6, 8, 2, 8,15,15,
2, 8, 2, 2, 2,15,15, 6,
6, 2, 6, 8,15,15, 2, 2,
15,15,15,15,15, 2, 2,15};
/* Table.A3a */ /* Table.A3a */
static const char bc7_ai1[] = { static const char bc7_ai1[] = {
3, 3,15,15, 8, 3,15,15, 3, 3, 15, 15, 8, 3, 15, 15, 8, 8, 6, 6, 6, 5, 3, 3, 3, 3, 8, 15, 3, 3,
8, 8, 6, 6, 6, 5, 3, 3, 6, 10, 5, 8, 8, 6, 8, 5, 15, 15, 8, 15, 3, 5, 6, 10, 8, 15, 15, 3, 15, 5,
3, 3, 8,15, 3, 3, 6,10, 15, 15, 15, 15, 3, 15, 5, 5, 5, 8, 5, 10, 5, 10, 8, 13, 15, 12, 3, 3};
5, 8, 8, 6, 8, 5,15,15,
8,15, 3, 5, 6,10, 8,15,
15, 3,15, 5,15,15,15,15,
3,15, 5, 5, 5, 8, 5,10,
5,10, 8,13,15,12, 3, 3};
/* Table.A3b */ /* Table.A3b */
static const char bc7_ai2[] = { static const char bc7_ai2[] = {15, 8, 8, 3, 15, 15, 3, 8, 15, 15, 15, 15, 15,
15, 8, 8, 3,15,15, 3, 8, 15, 15, 8, 15, 8, 15, 3, 15, 8, 15, 8, 3, 15,
15,15,15,15,15,15,15, 8, 6, 10, 15, 15, 10, 8, 15, 3, 15, 10, 10, 8, 9,
15, 8,15, 3,15, 8,15, 8, 10, 6, 15, 8, 15, 3, 6, 6, 8, 15, 3, 15, 15,
3,15, 6,10,15,15,10, 8, 15, 15, 15, 15, 15, 15, 15, 15, 3, 15, 15, 8};
15, 3,15,10,10, 8, 9,10,
6,15, 8,15, 3, 6, 6, 8,
15, 3,15,15,15,15,15,15,
15,15,15,15, 3,15,15, 8};
/* Interpolation weights */ /* Interpolation weights */
static const char bc7_weights2[] = {0, 21, 43, 64}; static const char bc7_weights2[] = {0, 21, 43, 64};
@ -299,7 +286,8 @@ static const char bc7_weights3[] = {0, 9, 18, 27, 37, 46, 55, 64};
static const char bc7_weights4[] = { static const char bc7_weights4[] = {
0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64}; 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64};
static const char *bc7_get_weights(int n) { static const char *
bc7_get_weights(int n) {
if (n == 2) { if (n == 2) {
return bc7_weights2; return bc7_weights2;
} }
@ -309,7 +297,8 @@ static const char *bc7_get_weights(int n) {
return bc7_weights4; return bc7_weights4;
} }
static int bc7_get_subset(int ns, int partition, int n) { static int
bc7_get_subset(int ns, int partition, int n) {
if (ns == 2) { if (ns == 2) {
return 1 & (bc7_si2[partition] >> n); return 1 & (bc7_si2[partition] >> n);
} }
@ -319,12 +308,14 @@ static int bc7_get_subset(int ns, int partition, int n) {
return 0; return 0;
} }
static UINT8 expand_quantized(UINT8 v, int bits) { static UINT8
expand_quantized(UINT8 v, int bits) {
v = v << (8 - bits); v = v << (8 - bits);
return v | (v >> bits); return v | (v >> bits);
} }
static void bc7_lerp(rgba *dst, const rgba *e, int s0, int s1) { static void
bc7_lerp(rgba *dst, const rgba *e, int s0, int s1) {
int t0 = 64 - s0; int t0 = 64 - s0;
int t1 = 64 - s1; int t1 = 64 - s1;
dst->r = (UINT8)((t0 * e[0].r + s0 * e[1].r + 32) >> 6); dst->r = (UINT8)((t0 * e[0].r + s0 * e[1].r + 32) >> 6);
@ -333,7 +324,8 @@ static void bc7_lerp(rgba *dst, const rgba *e, int s0, int s1) {
dst->a = (UINT8)((t1 * e[0].a + s1 * e[1].a + 32) >> 6); dst->a = (UINT8)((t1 * e[0].a + s1 * e[1].a + 32) >> 6);
} }
static void decode_bc7_block(rgba *col, const UINT8* src) { static void
decode_bc7_block(rgba *col, const UINT8 *src) {
rgba endpoints[6]; rgba endpoints[6];
int bit = 0, cibit, aibit; int bit = 0, cibit, aibit;
int mode = src[0]; int mode = src[0];
@ -352,7 +344,8 @@ static void decode_bc7_block(rgba *col, const UINT8* src) {
} }
return; return;
} }
while (!(mode & (1 << bit++))) ; while (!(mode & (1 << bit++)))
;
mode = bit - 1; mode = bit - 1;
info = &bc7_modes[mode]; info = &bc7_modes[mode];
/* color selection bits: {subset}{endpoint} */ /* color selection bits: {subset}{endpoint} */
@ -361,7 +354,7 @@ static void decode_bc7_block(rgba *col, const UINT8* src) {
cw = bc7_get_weights(info->ib); cw = bc7_get_weights(info->ib);
aw = bc7_get_weights((ab && info->ib2) ? info->ib2 : info->ib); aw = bc7_get_weights((ab && info->ib2) ? info->ib2 : info->ib);
#define LOAD(DST, N) \ #define LOAD(DST, N) \
DST = get_bits(src, bit, N); \ DST = get_bits(src, bit, N); \
bit += N; bit += N;
LOAD(partition, info->pb); LOAD(partition, info->pb);
@ -421,14 +414,14 @@ static void decode_bc7_block(rgba *col, const UINT8* src) {
if (ab) { if (ab) {
ab++; ab++;
} }
for (i = 0; i < numep; i+=2) { for (i = 0; i < numep; i += 2) {
LOAD(val, 1); LOAD(val, 1);
for (j = 0; j < 2; j++) { for (j = 0; j < 2; j++) {
ASSIGN_P(endpoints[i+j].r); ASSIGN_P(endpoints[i + j].r);
ASSIGN_P(endpoints[i+j].g); ASSIGN_P(endpoints[i + j].g);
ASSIGN_P(endpoints[i+j].b); ASSIGN_P(endpoints[i + j].b);
if (ab) { if (ab) {
ASSIGN_P(endpoints[i+j].a); ASSIGN_P(endpoints[i + j].a);
} }
} }
} }
@ -482,9 +475,9 @@ static void decode_bc7_block(rgba *col, const UINT8* src) {
bc7_lerp(&col[i], &endpoints[s], cw[i0], cw[i0]); bc7_lerp(&col[i], &endpoints[s], cw[i0], cw[i0]);
} }
#define ROTATE(x, y) \ #define ROTATE(x, y) \
val = x; \ val = x; \
x = y; \ x = y; \
y = val y = val
if (rotation == 1) { if (rotation == 1) {
ROTATE(col[i].r, col[i].a); ROTATE(col[i].r, col[i].a);
} else if (rotation == 2) { } else if (rotation == 2) {
@ -498,106 +491,102 @@ static void decode_bc7_block(rgba *col, const UINT8* src) {
/* BC6 */ /* BC6 */
typedef struct { typedef struct {
char ns; /* number of subsets (also called regions) */ char ns; /* number of subsets (also called regions) */
char tr; /* whether endpoints are delta-compressed */ char tr; /* whether endpoints are delta-compressed */
char pb; /* partition bits */ char pb; /* partition bits */
char epb; /* endpoint bits */ char epb; /* endpoint bits */
char rb; /* red bits (delta) */ char rb; /* red bits (delta) */
char gb; /* green bits (delta) */ char gb; /* green bits (delta) */
char bb; /* blue bits (delta) */ char bb; /* blue bits (delta) */
} bc6_mode_info; } bc6_mode_info;
static const bc6_mode_info bc6_modes[] = { static const bc6_mode_info bc6_modes[] = {
// 00 // 00
{2, 1, 5, 10, 5, 5, 5}, {2, 1, 5, 10, 5, 5, 5},
// 01 // 01
{2, 1, 5, 7, 6, 6, 6}, {2, 1, 5, 7, 6, 6, 6},
// 10 // 10
{2, 1, 5, 11, 5, 4, 4}, {2, 1, 5, 11, 5, 4, 4},
{2, 1, 5, 11, 4, 5, 4}, {2, 1, 5, 11, 4, 5, 4},
{2, 1, 5, 11, 4, 4, 5}, {2, 1, 5, 11, 4, 4, 5},
{2, 1, 5, 9, 5, 5, 5}, {2, 1, 5, 9, 5, 5, 5},
{2, 1, 5, 8, 6, 5, 5}, {2, 1, 5, 8, 6, 5, 5},
{2, 1, 5, 8, 5, 6, 5}, {2, 1, 5, 8, 5, 6, 5},
{2, 1, 5, 8, 5, 5, 6}, {2, 1, 5, 8, 5, 5, 6},
{2, 0, 5, 6, 6, 6, 6}, {2, 0, 5, 6, 6, 6, 6},
// 11 // 11
{1, 0, 0, 10, 10, 10, 10}, {1, 0, 0, 10, 10, 10, 10},
{1, 1, 0, 11, 9, 9, 9}, {1, 1, 0, 11, 9, 9, 9},
{1, 1, 0, 12, 8, 8, 8}, {1, 1, 0, 12, 8, 8, 8},
{1, 1, 0, 16, 4, 4, 4} {1, 1, 0, 16, 4, 4, 4}};
};
/* Table.F, encoded as a sequence of bit indices */ /* Table.F, encoded as a sequence of bit indices */
static const UINT8 bc6_bit_packings[][75] = { static const UINT8 bc6_bit_packings[][75] = {
{116, 132, 176, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, {116, 132, 176, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17,
23, 24, 25, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 52, 18, 19, 20, 21, 22, 23, 24, 25, 32, 33, 34, 35, 36, 37, 38,
164, 112, 113, 114, 115, 64, 65, 66, 67, 68, 172, 160, 161, 162, 163, 80, 39, 40, 41, 48, 49, 50, 51, 52, 164, 112, 113, 114, 115, 64, 65,
81, 82, 83, 84, 173, 128, 129, 130, 131, 96, 97, 98, 99, 100, 174, 144, 66, 67, 68, 172, 160, 161, 162, 163, 80, 81, 82, 83, 84, 173, 128,
145, 146, 147, 148, 175}, 129, 130, 131, 96, 97, 98, 99, 100, 174, 144, 145, 146, 147, 148, 175},
{117, 164, 165, 0, 1, 2, 3, 4, 5, 6, 172, 173, 132, 16, 17, 18, 19, 20, 21, {117, 164, 165, 0, 1, 2, 3, 4, 5, 6, 172, 173, 132, 16, 17,
22, 133, 174, 116, 32, 33, 34, 35, 36, 37, 38, 175, 177, 176, 48, 49, 50, 18, 19, 20, 21, 22, 133, 174, 116, 32, 33, 34, 35, 36, 37, 38,
51, 52, 53, 112, 113, 114, 115, 64, 65, 66, 67, 68, 69, 160, 161, 162, 163, 175, 177, 176, 48, 49, 50, 51, 52, 53, 112, 113, 114, 115, 64, 65,
80, 81, 82, 83, 84, 85, 128, 129, 130, 131, 96, 97, 98, 99, 100, 101, 144, 66, 67, 68, 69, 160, 161, 162, 163, 80, 81, 82, 83, 84, 85, 128,
145, 146, 147, 148, 149}, 129, 130, 131, 96, 97, 98, 99, 100, 101, 144, 145, 146, 147, 148, 149},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 32, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20,
33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 52, 10, 112, 113, 114, 21, 22, 23, 24, 25, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
115, 64, 65, 66, 67, 26, 172, 160, 161, 162, 163, 80, 81, 82, 83, 42, 173, 48, 49, 50, 51, 52, 10, 112, 113, 114, 115, 64, 65, 66, 67, 26,
128, 129, 130, 131, 96, 97, 98, 99, 100, 174, 144, 145, 146, 147, 148, 172, 160, 161, 162, 163, 80, 81, 82, 83, 42, 173, 128, 129, 130, 131,
175}, 96, 97, 98, 99, 100, 174, 144, 145, 146, 147, 148, 175},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 32, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20,
33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 10, 164, 112, 113, 114, 21, 22, 23, 24, 25, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
115, 64, 65, 66, 67, 68, 26, 160, 161, 162, 163, 80, 81, 82, 83, 42, 173, 48, 49, 50, 51, 10, 164, 112, 113, 114, 115, 64, 65, 66, 67, 68,
128, 129, 130, 131, 96, 97, 98, 99, 172, 174, 144, 145, 146, 147, 116, 26, 160, 161, 162, 163, 80, 81, 82, 83, 42, 173, 128, 129, 130, 131,
175}, 96, 97, 98, 99, 172, 174, 144, 145, 146, 147, 116, 175},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 32, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20,
33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 10, 132, 112, 113, 114, 21, 22, 23, 24, 25, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
115, 64, 65, 66, 67, 26, 172, 160, 161, 162, 163, 80, 81, 82, 83, 84, 42, 48, 49, 50, 51, 10, 132, 112, 113, 114, 115, 64, 65, 66, 67, 26,
128, 129, 130, 131, 96, 97, 98, 99, 173, 174, 144, 145, 146, 147, 176, 172, 160, 161, 162, 163, 80, 81, 82, 83, 84, 42, 128, 129, 130, 131,
175}, 96, 97, 98, 99, 173, 174, 144, 145, 146, 147, 176, 175},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 132, 16, 17, 18, 19, 20, 21, 22, 23, 24, 116, {0, 1, 2, 3, 4, 5, 6, 7, 8, 132, 16, 17, 18, 19, 20,
32, 33, 34, 35, 36, 37, 38, 39, 40, 176, 48, 49, 50, 51, 52, 164, 112, 113, 21, 22, 23, 24, 116, 32, 33, 34, 35, 36, 37, 38, 39, 40, 176,
114, 115, 64, 65, 66, 67, 68, 172, 160, 161, 162, 163, 80, 81, 82, 83, 84, 48, 49, 50, 51, 52, 164, 112, 113, 114, 115, 64, 65, 66, 67, 68,
173, 128, 129, 130, 131, 96, 97, 98, 99, 100, 174, 144, 145, 146, 147, 148, 172, 160, 161, 162, 163, 80, 81, 82, 83, 84, 173, 128, 129, 130, 131,
175}, 96, 97, 98, 99, 100, 174, 144, 145, 146, 147, 148, 175},
{0, 1, 2, 3, 4, 5, 6, 7, 164, 132, 16, 17, 18, 19, 20, 21, 22, 23, 174, 116, {0, 1, 2, 3, 4, 5, 6, 7, 164, 132, 16, 17, 18, 19, 20,
32, 33, 34, 35, 36, 37, 38, 39, 175, 176, 48, 49, 50, 51, 52, 53, 112, 113, 21, 22, 23, 174, 116, 32, 33, 34, 35, 36, 37, 38, 39, 175, 176,
114, 115, 64, 65, 66, 67, 68, 172, 160, 161, 162, 163, 80, 81, 82, 83, 84, 48, 49, 50, 51, 52, 53, 112, 113, 114, 115, 64, 65, 66, 67, 68,
173, 128, 129, 130, 131, 96, 97, 98, 99, 100, 101, 144, 145, 146, 147, 148, 172, 160, 161, 162, 163, 80, 81, 82, 83, 84, 173, 128, 129, 130, 131,
149}, 96, 97, 98, 99, 100, 101, 144, 145, 146, 147, 148, 149},
{0, 1, 2, 3, 4, 5, 6, 7, 172, 132, 16, 17, 18, 19, 20, 21, 22, 23, 117, 116, {0, 1, 2, 3, 4, 5, 6, 7, 172, 132, 16, 17, 18, 19, 20,
32, 33, 34, 35, 36, 37, 38, 39, 165, 176, 48, 49, 50, 51, 52, 164, 112, 21, 22, 23, 117, 116, 32, 33, 34, 35, 36, 37, 38, 39, 165, 176,
113, 114, 115, 64, 65, 66, 67, 68, 69, 160, 161, 162, 163, 80, 81, 82, 83, 48, 49, 50, 51, 52, 164, 112, 113, 114, 115, 64, 65, 66, 67, 68,
84, 173, 128, 129, 130, 131, 96, 97, 98, 99, 100, 174, 144, 145, 146, 147, 69, 160, 161, 162, 163, 80, 81, 82, 83, 84, 173, 128, 129, 130, 131,
148, 175}, 96, 97, 98, 99, 100, 174, 144, 145, 146, 147, 148, 175},
{0, 1, 2, 3, 4, 5, 6, 7, 173, 132, 16, 17, 18, 19, 20, 21, 22, 23, 133, 116, {0, 1, 2, 3, 4, 5, 6, 7, 173, 132, 16, 17, 18, 19, 20,
32, 33, 34, 35, 36, 37, 38, 39, 177, 176, 48, 49, 50, 51, 52, 164, 112, 21, 22, 23, 133, 116, 32, 33, 34, 35, 36, 37, 38, 39, 177, 176,
113, 114, 115, 64, 65, 66, 67, 68, 172, 160, 161, 162, 163, 80, 81, 82, 83, 48, 49, 50, 51, 52, 164, 112, 113, 114, 115, 64, 65, 66, 67, 68,
84, 85, 128, 129, 130, 131, 96, 97, 98, 99, 100, 174, 144, 145, 146, 147, 172, 160, 161, 162, 163, 80, 81, 82, 83, 84, 85, 128, 129, 130, 131,
148, 175}, 96, 97, 98, 99, 100, 174, 144, 145, 146, 147, 148, 175},
{0, 1, 2, 3, 4, 5, 164, 172, 173, 132, 16, 17, 18, 19, 20, 21, 117, 133, {0, 1, 2, 3, 4, 5, 164, 172, 173, 132, 16, 17, 18, 19, 20,
174, 116, 32, 33, 34, 35, 36, 37, 165, 175, 177, 176, 48, 49, 50, 51, 52, 21, 117, 133, 174, 116, 32, 33, 34, 35, 36, 37, 165, 175, 177, 176,
53, 112, 113, 114, 115, 64, 65, 66, 67, 68, 69, 160, 161, 162, 163, 80, 81, 48, 49, 50, 51, 52, 53, 112, 113, 114, 115, 64, 65, 66, 67, 68,
82, 83, 84, 85, 128, 129, 130, 131, 96, 97, 98, 99, 100, 101, 144, 145, 69, 160, 161, 162, 163, 80, 81, 82, 83, 84, 85, 128, 129, 130, 131,
146, 147, 148, 149}, 96, 97, 98, 99, 100, 101, 144, 145, 146, 147, 148, 149},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 32, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 80, 81, 82, 83, 84, 85, 86, 87, 88, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89},
89}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 32, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 52, 53, 54, 55, 56, 10,
33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 52, 53, 54, 55, 56, 10, 64, 65, 66, 67, 68, 69, 70, 71, 72, 26, 80, 81, 82, 83, 84, 85, 86, 87, 88, 42},
64, 65, 66, 67, 68, 69, 70, 71, 72, 26, 80, 81, 82, 83, 84, 85, 86, 87, 88, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
42}, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 52, 53, 54, 55, 11, 10,
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 32, 64, 65, 66, 67, 68, 69, 70, 71, 27, 26, 80, 81, 82, 83, 84, 85, 86, 87, 43, 42},
33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 52, 53, 54, 55, 11, 10, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
64, 65, 66, 67, 68, 69, 70, 71, 27, 26, 80, 81, 82, 83, 84, 85, 86, 87, 43, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 15, 14, 13, 12, 11, 10,
42}, 64, 65, 66, 67, 31, 30, 29, 28, 27, 26, 80, 81, 82, 83, 47, 46, 45, 44, 43, 42}};
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 32,
33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 15, 14, 13, 12, 11, 10,
64, 65, 66, 67, 31, 30, 29, 28, 27, 26, 80, 81, 82, 83, 47, 46, 45, 44, 43,
42}};
static void bc6_sign_extend(UINT16 *v, int prec) { static void
bc6_sign_extend(UINT16 *v, int prec) {
int x = *v; int x = *v;
if (x & (1 << (prec - 1))) { if (x & (1 << (prec - 1))) {
x |= -1 << prec; x |= -1 << prec;
@ -605,7 +594,8 @@ static void bc6_sign_extend(UINT16 *v, int prec) {
*v = (UINT16)x; *v = (UINT16)x;
} }
static int bc6_unquantize(UINT16 v, int prec, int sign) { static int
bc6_unquantize(UINT16 v, int prec, int sign) {
int s = 0; int s = 0;
int x; int x;
if (!sign) { if (!sign) {
@ -645,7 +635,8 @@ static int bc6_unquantize(UINT16 v, int prec, int sign) {
} }
} }
static float half_to_float(UINT16 h) { static float
half_to_float(UINT16 h) {
/* https://gist.github.com/rygorous/2144712 */ /* https://gist.github.com/rygorous/2144712 */
union { union {
UINT32 u; UINT32 u;
@ -662,7 +653,8 @@ static float half_to_float(UINT16 h) {
return o.f; return o.f;
} }
static float bc6_finalize(int v, int sign) { static float
bc6_finalize(int v, int sign) {
if (sign) { if (sign) {
if (v < 0) { if (v < 0) {
v = ((-v) * 31) / 32; v = ((-v) * 31) / 32;
@ -675,7 +667,8 @@ static float bc6_finalize(int v, int sign) {
} }
} }
static void bc6_lerp(rgb32f *col, int *e0, int *e1, int s, int sign) { static void
bc6_lerp(rgb32f *col, int *e0, int *e1, int s, int sign) {
int r, g, b; int r, g, b;
int t = 64 - s; int t = 64 - s;
r = (e0[0] * t + e1[0] * s) >> 6; r = (e0[0] * t + e1[0] * s) >> 6;
@ -686,7 +679,8 @@ static void bc6_lerp(rgb32f *col, int *e0, int *e1, int s, int sign) {
col->b = bc6_finalize(b, sign); col->b = bc6_finalize(b, sign);
} }
static void decode_bc6_block(rgb32f *col, const UINT8* src, int sign) { static void
decode_bc6_block(rgb32f *col, const UINT8 *src, int sign) {
UINT16 endpoints[12]; /* storage for r0, g0, b0, r1, ... */ UINT16 endpoints[12]; /* storage for r0, g0, b0, r1, ... */
int ueps[12]; int ueps[12];
int i, i0, ib2, di, dw, mask, numep, s; int i, i0, ib2, di, dw, mask, numep, s;
@ -736,9 +730,9 @@ static void decode_bc6_block(rgb32f *col, const UINT8* src, int sign) {
} }
if (sign || info->tr) { /* sign-extend e1,2,3 if signed or deltas */ if (sign || info->tr) { /* sign-extend e1,2,3 if signed or deltas */
for (i = 3; i < numep; i += 3) { for (i = 3; i < numep; i += 3) {
bc6_sign_extend(&endpoints[i+0], info->rb); bc6_sign_extend(&endpoints[i + 0], info->rb);
bc6_sign_extend(&endpoints[i+1], info->gb); bc6_sign_extend(&endpoints[i + 1], info->gb);
bc6_sign_extend(&endpoints[i+2], info->bb); bc6_sign_extend(&endpoints[i + 2], info->bb);
} }
} }
if (info->tr) { /* apply deltas */ if (info->tr) { /* apply deltas */
@ -747,9 +741,9 @@ static void decode_bc6_block(rgb32f *col, const UINT8* src, int sign) {
} }
if (sign) { if (sign) {
for (i = 3; i < numep; i += 3) { for (i = 3; i < numep; i += 3) {
bc6_sign_extend(&endpoints[i+0], info->rb); bc6_sign_extend(&endpoints[i + 0], info->rb);
bc6_sign_extend(&endpoints[i+1], info->gb); bc6_sign_extend(&endpoints[i + 1], info->gb);
bc6_sign_extend(&endpoints[i+2], info->bb); bc6_sign_extend(&endpoints[i + 2], info->bb);
} }
} }
} }
@ -769,11 +763,12 @@ static void decode_bc6_block(rgb32f *col, const UINT8* src, int sign) {
i0 = get_bits(src, bit, ib2); i0 = get_bits(src, bit, ib2);
bit += ib2; bit += ib2;
bc6_lerp(&col[i], &ueps[s], &ueps[s+3], cw[i0], sign); bc6_lerp(&col[i], &ueps[s], &ueps[s + 3], cw[i0], sign);
} }
} }
static void put_block(Imaging im, ImagingCodecState state, const char *col, int sz, int C) { static void
put_block(Imaging im, ImagingCodecState state, const char *col, int sz, int C) {
int width = state->xsize; int width = state->xsize;
int height = state->ysize; int height = state->ysize;
int xmax = width + state->xoff; int xmax = width + state->xoff;
@ -795,15 +790,15 @@ static void put_block(Imaging im, ImagingCodecState state, const char *col, int
if (x >= width) { if (x >= width) {
continue; continue;
} }
memcpy(dst + sz*x, col + sz*(j*4 + i), sz); memcpy(dst + sz * x, col + sz * (j * 4 + i), sz);
} }
} else { } else {
if (state->ystep < 0) { if (state->ystep < 0) {
y = state->yoff + ymax - y - 1; y = state->yoff + ymax - y - 1;
} }
x = state->x; x = state->x;
dst = im->image[y] + sz*x; dst = im->image[y] + sz * x;
memcpy(dst, col + sz*(j*4), 4 * sz); memcpy(dst, col + sz * (j * 4), 4 * sz);
} }
} }
state->x += 4; state->x += 4;
@ -813,23 +808,25 @@ static void put_block(Imaging im, ImagingCodecState state, const char *col, int
} }
} }
static int decode_bcn(Imaging im, ImagingCodecState state, const UINT8* src, int bytes, int N, int C) { static int
decode_bcn(
Imaging im, ImagingCodecState state, const UINT8 *src, int bytes, int N, int C) {
int ymax = state->ysize + state->yoff; int ymax = state->ysize + state->yoff;
const UINT8 *ptr = src; const UINT8 *ptr = src;
switch (N) { switch (N) {
#define DECODE_LOOP(NN, SZ, TY, ...) \ #define DECODE_LOOP(NN, SZ, TY, ...) \
case NN: \ case NN: \
while (bytes >= SZ) { \ while (bytes >= SZ) { \
TY col[16]; \ TY col[16]; \
memset(col, 0, 16 * sizeof(col[0])); \ memset(col, 0, 16 * sizeof(col[0])); \
decode_bc##NN##_block(col, ptr); \ decode_bc##NN##_block(col, ptr); \
put_block(im, state, (const char *)col, sizeof(col[0]), C); \ put_block(im, state, (const char *)col, sizeof(col[0]), C); \
ptr += SZ; \ ptr += SZ; \
bytes -= SZ; \ bytes -= SZ; \
if (state->y >= ymax) {\ if (state->y >= ymax) { \
return -1; \ return -1; \
}\ } \
} \ } \
break break
DECODE_LOOP(1, 8, rgba); DECODE_LOOP(1, 8, rgba);
@ -844,18 +841,19 @@ static int decode_bcn(Imaging im, ImagingCodecState state, const UINT8* src, int
put_block(im, state, (const char *)col, sizeof(col[0]), C); put_block(im, state, (const char *)col, sizeof(col[0]), C);
ptr += 16; ptr += 16;
bytes -= 16; bytes -= 16;
if (state->y >= ymax) {\ if (state->y >= ymax) {
return -1; \ return -1;
}\ }
} }
break; break;
DECODE_LOOP(7, 16, rgba); DECODE_LOOP(7, 16, rgba);
#undef DECODE_LOOP #undef DECODE_LOOP
} }
return (int)(ptr - src); return (int)(ptr - src);
} }
int ImagingBcnDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes) { int
ImagingBcnDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
int N = state->state & 0xf; int N = state->state & 0xf;
int width = state->xsize; int width = state->xsize;
int height = state->ysize; int height = state->ysize;

View File

@ -1,7 +1,6 @@
/* Bit.h */ /* Bit.h */
typedef struct { typedef struct {
/* CONFIGURATION */ /* CONFIGURATION */
/* Number of bits per pixel */ /* Number of bits per pixel */
@ -19,7 +18,7 @@ typedef struct {
/* Lookup table (not implemented) */ /* Lookup table (not implemented) */
unsigned long lutsize; unsigned long lutsize;
FLOAT32* lut; FLOAT32 *lut;
/* INTERNAL */ /* INTERNAL */
unsigned long mask; unsigned long mask;

View File

@ -13,20 +13,16 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#include "Bit.h" #include "Bit.h"
int int
ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes) ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
{ BITSTATE *bitstate = state->context;
BITSTATE* bitstate = state->context; UINT8 *ptr;
UINT8* ptr;
if (state->state == 0) { if (state->state == 0) {
/* Initialize context variables */ /* Initialize context variables */
/* this decoder only works for float32 image buffers */ /* this decoder only works for float32 image buffers */
@ -41,37 +37,35 @@ ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
return -1; return -1;
} }
bitstate->mask = (1<<bitstate->bits)-1; bitstate->mask = (1 << bitstate->bits) - 1;
if (bitstate->sign) { if (bitstate->sign) {
bitstate->signmask = (1<<(bitstate->bits-1)); bitstate->signmask = (1 << (bitstate->bits - 1));
} }
/* check image orientation */ /* check image orientation */
if (state->ystep < 0) { if (state->ystep < 0) {
state->y = state->ysize-1; state->y = state->ysize - 1;
state->ystep = -1; state->ystep = -1;
} else { } else {
state->ystep = 1; state->ystep = 1;
} }
state->state = 1; state->state = 1;
} }
ptr = buf; ptr = buf;
while (bytes > 0) { while (bytes > 0) {
UINT8 byte = *ptr; UINT8 byte = *ptr;
ptr++; ptr++;
bytes--; bytes--;
/* get a byte from the input stream and insert in the bit buffer */ /* get a byte from the input stream and insert in the bit buffer */
if (bitstate->fill&1) { if (bitstate->fill & 1) {
/* fill MSB first */ /* fill MSB first */
bitstate->bitbuffer |= (unsigned long) byte << bitstate->bitcount; bitstate->bitbuffer |= (unsigned long)byte << bitstate->bitcount;
} else { } else {
/* fill LSB first */ /* fill LSB first */
bitstate->bitbuffer = (bitstate->bitbuffer << 8) | byte; bitstate->bitbuffer = (bitstate->bitbuffer << 8) | byte;
@ -80,26 +74,24 @@ ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
bitstate->bitcount += 8; bitstate->bitcount += 8;
while (bitstate->bitcount >= bitstate->bits) { while (bitstate->bitcount >= bitstate->bits) {
/* get a pixel from the bit buffer */ /* get a pixel from the bit buffer */
unsigned long data; unsigned long data;
FLOAT32 pixel; FLOAT32 pixel;
if (bitstate->fill&2) { if (bitstate->fill & 2) {
/* store LSB first */ /* store LSB first */
data = bitstate->bitbuffer & bitstate->mask; data = bitstate->bitbuffer & bitstate->mask;
if (bitstate->bitcount > 32) { if (bitstate->bitcount > 32) {
/* bitbuffer overflow; restore it from last input byte */ /* bitbuffer overflow; restore it from last input byte */
bitstate->bitbuffer = byte >> (8 - (bitstate->bitcount - bitstate->bitbuffer =
bitstate->bits)); byte >> (8 - (bitstate->bitcount - bitstate->bits));
} else { } else {
bitstate->bitbuffer >>= bitstate->bits; bitstate->bitbuffer >>= bitstate->bits;
} }
} else { } else {
/* store MSB first */ /* store MSB first */
data = (bitstate->bitbuffer >> (bitstate->bitcount - data = (bitstate->bitbuffer >> (bitstate->bitcount - bitstate->bits)) &
bitstate->bits)) bitstate->mask;
& bitstate->mask;
} }
bitstate->bitcount -= bitstate->bits; bitstate->bitcount -= bitstate->bits;
@ -109,7 +101,7 @@ ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
if (data <= 0) { if (data <= 0) {
pixel = bitstate->lut[0]; pixel = bitstate->lut[0];
} else if (data >= bitstate->lutsize) { } else if (data >= bitstate->lutsize) {
pixel = bitstate->lut[bitstate->lutsize-1]; pixel = bitstate->lut[bitstate->lutsize - 1];
} else { } else {
pixel = bitstate->lut[data]; pixel = bitstate->lut[data];
} }
@ -117,13 +109,13 @@ ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
/* convert */ /* convert */
if (data & bitstate->signmask) { if (data & bitstate->signmask) {
/* image memory contains signed data */ /* image memory contains signed data */
pixel = (FLOAT32) (INT32) (data | ~bitstate->mask); pixel = (FLOAT32)(INT32)(data | ~bitstate->mask);
} else { } else {
pixel = (FLOAT32) data; pixel = (FLOAT32)data;
} }
} }
*(FLOAT32*)(&im->image32[state->y][state->x]) = pixel; *(FLOAT32 *)(&im->image32[state->y][state->x]) = pixel;
/* step forward */ /* step forward */
if (++state->x >= state->xsize) { if (++state->x >= state->xsize) {

View File

@ -15,27 +15,22 @@
* See the README file for details on usage and redistribution. * See the README file for details on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
Imaging Imaging
ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha) ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha) {
{
Imaging imOut; Imaging imOut;
int x, y; int x, y;
/* Check arguments */ /* Check arguments */
if (!imIn1 || !imIn2 || imIn1->type != IMAGING_TYPE_UINT8 if (!imIn1 || !imIn2 || imIn1->type != IMAGING_TYPE_UINT8 || imIn1->palette ||
|| imIn1->palette || strcmp(imIn1->mode, "1") == 0 strcmp(imIn1->mode, "1") == 0 || imIn2->palette ||
|| imIn2->palette || strcmp(imIn2->mode, "1") == 0) { strcmp(imIn2->mode, "1") == 0) {
return ImagingError_ModeError(); return ImagingError_ModeError();
} }
if (imIn1->type != imIn2->type || if (imIn1->type != imIn2->type || imIn1->bands != imIn2->bands ||
imIn1->bands != imIn2->bands || imIn1->xsize != imIn2->xsize || imIn1->ysize != imIn2->ysize) {
imIn1->xsize != imIn2->xsize ||
imIn1->ysize != imIn2->ysize) {
return ImagingError_Mismatch(); return ImagingError_Mismatch();
} }
@ -54,29 +49,27 @@ ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha)
if (alpha >= 0 && alpha <= 1.0) { if (alpha >= 0 && alpha <= 1.0) {
/* Interpolate between bands */ /* Interpolate between bands */
for (y = 0; y < imIn1->ysize; y++) { for (y = 0; y < imIn1->ysize; y++) {
UINT8* in1 = (UINT8*) imIn1->image[y]; UINT8 *in1 = (UINT8 *)imIn1->image[y];
UINT8* in2 = (UINT8*) imIn2->image[y]; UINT8 *in2 = (UINT8 *)imIn2->image[y];
UINT8* out = (UINT8*) imOut->image[y]; UINT8 *out = (UINT8 *)imOut->image[y];
for (x = 0; x < imIn1->linesize; x++) { for (x = 0; x < imIn1->linesize; x++) {
out[x] = (UINT8) out[x] = (UINT8)((int)in1[x] + alpha * ((int)in2[x] - (int)in1[x]));
((int) in1[x] + alpha * ((int) in2[x] - (int) in1[x]));
} }
} }
} else { } else {
/* Extrapolation; must make sure to clip resulting values */ /* Extrapolation; must make sure to clip resulting values */
for (y = 0; y < imIn1->ysize; y++) { for (y = 0; y < imIn1->ysize; y++) {
UINT8* in1 = (UINT8*) imIn1->image[y]; UINT8 *in1 = (UINT8 *)imIn1->image[y];
UINT8* in2 = (UINT8*) imIn2->image[y]; UINT8 *in2 = (UINT8 *)imIn2->image[y];
UINT8* out = (UINT8*) imOut->image[y]; UINT8 *out = (UINT8 *)imOut->image[y];
for (x = 0; x < imIn1->linesize; x++) { for (x = 0; x < imIn1->linesize; x++) {
float temp = (float) float temp = (float)((int)in1[x] + alpha * ((int)in2[x] - (int)in1[x]));
((int) in1[x] + alpha * ((int) in2[x] - (int) in1[x]));
if (temp <= 0.0) { if (temp <= 0.0) {
out[x] = 0; out[x] = 0;
} else if (temp >= 255.0) { } else if (temp >= 255.0) {
out[x] = 255; out[x] = 255;
} else { } else {
out[x] = (UINT8) temp; out[x] = (UINT8)temp;
} }
} }
} }

View File

@ -1,37 +1,40 @@
#include "Imaging.h" #include "Imaging.h"
#define MAX(x, y) (((x) > (y)) ? (x) : (y)) #define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y)) #define MIN(x, y) (((x) < (y)) ? (x) : (y))
typedef UINT8 pixel[4]; typedef UINT8 pixel[4];
void static inline void static inline ImagingLineBoxBlur32(
ImagingLineBoxBlur32(pixel *lineOut, pixel *lineIn, int lastx, int radius, int edgeA, pixel *lineOut,
int edgeB, UINT32 ww, UINT32 fw) pixel *lineIn,
{ int lastx,
int radius,
int edgeA,
int edgeB,
UINT32 ww,
UINT32 fw) {
int x; int x;
UINT32 acc[4]; UINT32 acc[4];
UINT32 bulk[4]; UINT32 bulk[4];
#define MOVE_ACC(acc, subtract, add) \ #define MOVE_ACC(acc, subtract, add) \
acc[0] += lineIn[add][0] - lineIn[subtract][0]; \ acc[0] += lineIn[add][0] - lineIn[subtract][0]; \
acc[1] += lineIn[add][1] - lineIn[subtract][1]; \ acc[1] += lineIn[add][1] - lineIn[subtract][1]; \
acc[2] += lineIn[add][2] - lineIn[subtract][2]; \ acc[2] += lineIn[add][2] - lineIn[subtract][2]; \
acc[3] += lineIn[add][3] - lineIn[subtract][3]; acc[3] += lineIn[add][3] - lineIn[subtract][3];
#define ADD_FAR(bulk, acc, left, right) \ #define ADD_FAR(bulk, acc, left, right) \
bulk[0] = (acc[0] * ww) + (lineIn[left][0] + lineIn[right][0]) * fw; \ bulk[0] = (acc[0] * ww) + (lineIn[left][0] + lineIn[right][0]) * fw; \
bulk[1] = (acc[1] * ww) + (lineIn[left][1] + lineIn[right][1]) * fw; \ bulk[1] = (acc[1] * ww) + (lineIn[left][1] + lineIn[right][1]) * fw; \
bulk[2] = (acc[2] * ww) + (lineIn[left][2] + lineIn[right][2]) * fw; \ bulk[2] = (acc[2] * ww) + (lineIn[left][2] + lineIn[right][2]) * fw; \
bulk[3] = (acc[3] * ww) + (lineIn[left][3] + lineIn[right][3]) * fw; bulk[3] = (acc[3] * ww) + (lineIn[left][3] + lineIn[right][3]) * fw;
#define SAVE(x, bulk) \ #define SAVE(x, bulk) \
lineOut[x][0] = (UINT8)((bulk[0] + (1 << 23)) >> 24); \ lineOut[x][0] = (UINT8)((bulk[0] + (1 << 23)) >> 24); \
lineOut[x][1] = (UINT8)((bulk[1] + (1 << 23)) >> 24); \ lineOut[x][1] = (UINT8)((bulk[1] + (1 << 23)) >> 24); \
lineOut[x][2] = (UINT8)((bulk[2] + (1 << 23)) >> 24); \ lineOut[x][2] = (UINT8)((bulk[2] + (1 << 23)) >> 24); \
lineOut[x][3] = (UINT8)((bulk[3] + (1 << 23)) >> 24); lineOut[x][3] = (UINT8)((bulk[3] + (1 << 23)) >> 24);
/* Compute acc for -1 pixel (outside of image): /* Compute acc for -1 pixel (outside of image):
From "-radius-1" to "-1" get first pixel, From "-radius-1" to "-1" get first pixel,
@ -53,8 +56,7 @@ ImagingLineBoxBlur32(pixel *lineOut, pixel *lineIn, int lastx, int radius, int e
acc[2] += lineIn[lastx][2] * (radius - edgeA + 1); acc[2] += lineIn[lastx][2] * (radius - edgeA + 1);
acc[3] += lineIn[lastx][3] * (radius - edgeA + 1); acc[3] += lineIn[lastx][3] * (radius - edgeA + 1);
if (edgeA <= edgeB) if (edgeA <= edgeB) {
{
/* Subtract pixel from left ("0"). /* Subtract pixel from left ("0").
Add pixels from radius. */ Add pixels from radius. */
for (x = 0; x < edgeA; x++) { for (x = 0; x < edgeA; x++) {
@ -76,9 +78,7 @@ ImagingLineBoxBlur32(pixel *lineOut, pixel *lineIn, int lastx, int radius, int e
ADD_FAR(bulk, acc, x - radius - 1, lastx); ADD_FAR(bulk, acc, x - radius - 1, lastx);
SAVE(x, bulk); SAVE(x, bulk);
} }
} } else {
else
{
for (x = 0; x < edgeB; x++) { for (x = 0; x < edgeB; x++) {
MOVE_ACC(acc, 0, x + radius); MOVE_ACC(acc, 0, x + radius);
ADD_FAR(bulk, acc, 0, x + radius + 1); ADD_FAR(bulk, acc, 0, x + radius + 1);
@ -96,28 +96,30 @@ ImagingLineBoxBlur32(pixel *lineOut, pixel *lineIn, int lastx, int radius, int e
} }
} }
#undef MOVE_ACC #undef MOVE_ACC
#undef ADD_FAR #undef ADD_FAR
#undef SAVE #undef SAVE
} }
void static inline ImagingLineBoxBlur8(
void static inline UINT8 *lineOut,
ImagingLineBoxBlur8(UINT8 *lineOut, UINT8 *lineIn, int lastx, int radius, int edgeA, UINT8 *lineIn,
int edgeB, UINT32 ww, UINT32 fw) int lastx,
{ int radius,
int edgeA,
int edgeB,
UINT32 ww,
UINT32 fw) {
int x; int x;
UINT32 acc; UINT32 acc;
UINT32 bulk; UINT32 bulk;
#define MOVE_ACC(acc, subtract, add) \ #define MOVE_ACC(acc, subtract, add) acc += lineIn[add] - lineIn[subtract];
acc += lineIn[add] - lineIn[subtract];
#define ADD_FAR(bulk, acc, left, right) \ #define ADD_FAR(bulk, acc, left, right) \
bulk = (acc * ww) + (lineIn[left] + lineIn[right]) * fw; bulk = (acc * ww) + (lineIn[left] + lineIn[right]) * fw;
#define SAVE(x, bulk) \ #define SAVE(x, bulk) lineOut[x] = (UINT8)((bulk + (1 << 23)) >> 24)
lineOut[x] = (UINT8)((bulk + (1 << 23)) >> 24)
acc = lineIn[0] * (radius + 1); acc = lineIn[0] * (radius + 1);
for (x = 0; x < edgeA - 1; x++) { for (x = 0; x < edgeA - 1; x++) {
@ -125,8 +127,7 @@ ImagingLineBoxBlur8(UINT8 *lineOut, UINT8 *lineIn, int lastx, int radius, int ed
} }
acc += lineIn[lastx] * (radius - edgeA + 1); acc += lineIn[lastx] * (radius - edgeA + 1);
if (edgeA <= edgeB) if (edgeA <= edgeB) {
{
for (x = 0; x < edgeA; x++) { for (x = 0; x < edgeA; x++) {
MOVE_ACC(acc, 0, x + radius); MOVE_ACC(acc, 0, x + radius);
ADD_FAR(bulk, acc, 0, x + radius + 1); ADD_FAR(bulk, acc, 0, x + radius + 1);
@ -142,9 +143,7 @@ ImagingLineBoxBlur8(UINT8 *lineOut, UINT8 *lineIn, int lastx, int radius, int ed
ADD_FAR(bulk, acc, x - radius - 1, lastx); ADD_FAR(bulk, acc, x - radius - 1, lastx);
SAVE(x, bulk); SAVE(x, bulk);
} }
} } else {
else
{
for (x = 0; x < edgeB; x++) { for (x = 0; x < edgeB; x++) {
MOVE_ACC(acc, 0, x + radius); MOVE_ACC(acc, 0, x + radius);
ADD_FAR(bulk, acc, 0, x + radius + 1); ADD_FAR(bulk, acc, 0, x + radius + 1);
@ -162,22 +161,19 @@ ImagingLineBoxBlur8(UINT8 *lineOut, UINT8 *lineIn, int lastx, int radius, int ed
} }
} }
#undef MOVE_ACC #undef MOVE_ACC
#undef ADD_FAR #undef ADD_FAR
#undef SAVE #undef SAVE
} }
Imaging Imaging
ImagingHorizontalBoxBlur(Imaging imOut, Imaging imIn, float floatRadius) ImagingHorizontalBoxBlur(Imaging imOut, Imaging imIn, float floatRadius) {
{
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
int y; int y;
int radius = (int) floatRadius; int radius = (int)floatRadius;
UINT32 ww = (UINT32) (1 << 24) / (floatRadius * 2 + 1); UINT32 ww = (UINT32)(1 << 24) / (floatRadius * 2 + 1);
UINT32 fw = ((1 << 24) - (radius * 2 + 1) * ww) / 2; UINT32 fw = ((1 << 24) - (radius * 2 + 1) * ww) / 2;
int edgeA = MIN(radius + 1, imIn->xsize); int edgeA = MIN(radius + 1, imIn->xsize);
@ -192,32 +188,33 @@ ImagingHorizontalBoxBlur(Imaging imOut, Imaging imIn, float floatRadius)
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
if (imIn->image8) if (imIn->image8) {
{
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
ImagingLineBoxBlur8( ImagingLineBoxBlur8(
(imIn == imOut ? (UINT8 *) lineOut : imOut->image8[y]), (imIn == imOut ? (UINT8 *)lineOut : imOut->image8[y]),
imIn->image8[y], imIn->image8[y],
imIn->xsize - 1, imIn->xsize - 1,
radius, edgeA, edgeB, radius,
ww, fw edgeA,
); edgeB,
ww,
fw);
if (imIn == imOut) { if (imIn == imOut) {
// Commit. // Commit.
memcpy(imOut->image8[y], lineOut, imIn->xsize); memcpy(imOut->image8[y], lineOut, imIn->xsize);
} }
} }
} } else {
else
{
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
ImagingLineBoxBlur32( ImagingLineBoxBlur32(
imIn == imOut ? (pixel *) lineOut : (pixel *) imOut->image32[y], imIn == imOut ? (pixel *)lineOut : (pixel *)imOut->image32[y],
(pixel *) imIn->image32[y], (pixel *)imIn->image32[y],
imIn->xsize - 1, imIn->xsize - 1,
radius, edgeA, edgeB, radius,
ww, fw edgeA,
); edgeB,
ww,
fw);
if (imIn == imOut) { if (imIn == imOut) {
// Commit. // Commit.
memcpy(imOut->image32[y], lineOut, imIn->xsize * 4); memcpy(imOut->image32[y], lineOut, imIn->xsize * 4);
@ -232,23 +229,17 @@ ImagingHorizontalBoxBlur(Imaging imOut, Imaging imIn, float floatRadius)
return imOut; return imOut;
} }
Imaging Imaging
ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n) ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n) {
{
int i; int i;
Imaging imTransposed; Imaging imTransposed;
if (n < 1) { if (n < 1) {
return ImagingError_ValueError( return ImagingError_ValueError("number of passes must be greater than zero");
"number of passes must be greater than zero"
);
} }
if (strcmp(imIn->mode, imOut->mode) || if (strcmp(imIn->mode, imOut->mode) || imIn->type != imOut->type ||
imIn->type != imOut->type || imIn->bands != imOut->bands || imIn->xsize != imOut->xsize ||
imIn->bands != imOut->bands ||
imIn->xsize != imOut->xsize ||
imIn->ysize != imOut->ysize) { imIn->ysize != imOut->ysize) {
return ImagingError_Mismatch(); return ImagingError_Mismatch();
} }
@ -257,14 +248,10 @@ ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n)
return ImagingError_ModeError(); return ImagingError_ModeError();
} }
if (!(strcmp(imIn->mode, "RGB") == 0 || if (!(strcmp(imIn->mode, "RGB") == 0 || strcmp(imIn->mode, "RGBA") == 0 ||
strcmp(imIn->mode, "RGBA") == 0 || strcmp(imIn->mode, "RGBa") == 0 || strcmp(imIn->mode, "RGBX") == 0 ||
strcmp(imIn->mode, "RGBa") == 0 || strcmp(imIn->mode, "CMYK") == 0 || strcmp(imIn->mode, "L") == 0 ||
strcmp(imIn->mode, "RGBX") == 0 || strcmp(imIn->mode, "LA") == 0 || strcmp(imIn->mode, "La") == 0)) {
strcmp(imIn->mode, "CMYK") == 0 ||
strcmp(imIn->mode, "L") == 0 ||
strcmp(imIn->mode, "LA") == 0 ||
strcmp(imIn->mode, "La") == 0)) {
return ImagingError_ModeError(); return ImagingError_ModeError();
} }
@ -277,14 +264,14 @@ ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n)
Use imOut as a destination at first pass, Use imOut as a destination at first pass,
then use imOut as a source too. */ then use imOut as a source too. */
ImagingHorizontalBoxBlur(imOut, imIn, radius); ImagingHorizontalBoxBlur(imOut, imIn, radius);
for (i = 1; i < n; i ++) { for (i = 1; i < n; i++) {
ImagingHorizontalBoxBlur(imOut, imOut, radius); ImagingHorizontalBoxBlur(imOut, imOut, radius);
} }
/* Transpose result for blur in another direction. */ /* Transpose result for blur in another direction. */
ImagingTranspose(imTransposed, imOut); ImagingTranspose(imTransposed, imOut);
/* Reuse imTransposed as a source and destination there. */ /* Reuse imTransposed as a source and destination there. */
for (i = 0; i < n; i ++) { for (i = 0; i < n; i++) {
ImagingHorizontalBoxBlur(imTransposed, imTransposed, radius); ImagingHorizontalBoxBlur(imTransposed, imTransposed, radius);
} }
/* Restore original orientation. */ /* Restore original orientation. */
@ -295,10 +282,8 @@ ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n)
return imOut; return imOut;
} }
Imaging
Imaging ImagingGaussianBlur(Imaging imOut, Imaging imIn, float radius, ImagingGaussianBlur(Imaging imOut, Imaging imIn, float radius, int passes) {
int passes)
{
float sigma2, L, l, a; float sigma2, L, l, a;
sigma2 = radius * radius / passes; sigma2 = radius * radius / passes;

View File

@ -16,62 +16,59 @@
* See the README file for details on usage and redistribution. * See the README file for details on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#define CHOP(operation)\ #define CHOP(operation) \
int x, y;\ int x, y; \
Imaging imOut;\ Imaging imOut; \
imOut = create(imIn1, imIn2, NULL);\ imOut = create(imIn1, imIn2, NULL); \
if (!imOut) {\ if (!imOut) { \
return NULL;\ return NULL; \
}\ } \
for (y = 0; y < imOut->ysize; y++) {\ for (y = 0; y < imOut->ysize; y++) { \
UINT8* out = (UINT8*) imOut->image[y];\ UINT8 *out = (UINT8 *)imOut->image[y]; \
UINT8* in1 = (UINT8*) imIn1->image[y];\ UINT8 *in1 = (UINT8 *)imIn1->image[y]; \
UINT8* in2 = (UINT8*) imIn2->image[y];\ UINT8 *in2 = (UINT8 *)imIn2->image[y]; \
for (x = 0; x < imOut->linesize; x++) {\ for (x = 0; x < imOut->linesize; x++) { \
int temp = operation;\ int temp = operation; \
if (temp <= 0) {\ if (temp <= 0) { \
out[x] = 0;\ out[x] = 0; \
} else if (temp >= 255) {\ } else if (temp >= 255) { \
out[x] = 255;\ out[x] = 255; \
} else {\ } else { \
out[x] = temp;\ out[x] = temp; \
}\ } \
}\ } \
}\ } \
return imOut; return imOut;
#define CHOP2(operation, mode)\ #define CHOP2(operation, mode) \
int x, y;\ int x, y; \
Imaging imOut;\ Imaging imOut; \
imOut = create(imIn1, imIn2, mode);\ imOut = create(imIn1, imIn2, mode); \
if (!imOut) {\ if (!imOut) { \
return NULL;\ return NULL; \
}\ } \
for (y = 0; y < imOut->ysize; y++) {\ for (y = 0; y < imOut->ysize; y++) { \
UINT8* out = (UINT8*) imOut->image[y];\ UINT8 *out = (UINT8 *)imOut->image[y]; \
UINT8* in1 = (UINT8*) imIn1->image[y];\ UINT8 *in1 = (UINT8 *)imIn1->image[y]; \
UINT8* in2 = (UINT8*) imIn2->image[y];\ UINT8 *in2 = (UINT8 *)imIn2->image[y]; \
for (x = 0; x < imOut->linesize; x++) {\ for (x = 0; x < imOut->linesize; x++) { \
out[x] = operation;\ out[x] = operation; \
}\ } \
}\ } \
return imOut; return imOut;
static Imaging static Imaging
create(Imaging im1, Imaging im2, char* mode) create(Imaging im1, Imaging im2, char *mode) {
{
int xsize, ysize; int xsize, ysize;
if (!im1 || !im2 || im1->type != IMAGING_TYPE_UINT8 || if (!im1 || !im2 || im1->type != IMAGING_TYPE_UINT8 ||
(mode != NULL && (strcmp(im1->mode, "1") || strcmp(im2->mode, "1")))) { (mode != NULL && (strcmp(im1->mode, "1") || strcmp(im2->mode, "1")))) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
if (im1->type != im2->type || if (im1->type != im2->type || im1->bands != im2->bands) {
im1->bands != im2->bands) { return (Imaging)ImagingError_Mismatch();
return (Imaging) ImagingError_Mismatch();
} }
xsize = (im1->xsize < im2->xsize) ? im1->xsize : im2->xsize; xsize = (im1->xsize < im2->xsize) ? im1->xsize : im2->xsize;
@ -81,97 +78,85 @@ create(Imaging im1, Imaging im2, char* mode)
} }
Imaging Imaging
ImagingChopLighter(Imaging imIn1, Imaging imIn2) ImagingChopLighter(Imaging imIn1, Imaging imIn2) {
{
CHOP((in1[x] > in2[x]) ? in1[x] : in2[x]); CHOP((in1[x] > in2[x]) ? in1[x] : in2[x]);
} }
Imaging Imaging
ImagingChopDarker(Imaging imIn1, Imaging imIn2) ImagingChopDarker(Imaging imIn1, Imaging imIn2) {
{
CHOP((in1[x] < in2[x]) ? in1[x] : in2[x]); CHOP((in1[x] < in2[x]) ? in1[x] : in2[x]);
} }
Imaging Imaging
ImagingChopDifference(Imaging imIn1, Imaging imIn2) ImagingChopDifference(Imaging imIn1, Imaging imIn2) {
{ CHOP(abs((int)in1[x] - (int)in2[x]));
CHOP(abs((int) in1[x] - (int) in2[x]));
} }
Imaging Imaging
ImagingChopMultiply(Imaging imIn1, Imaging imIn2) ImagingChopMultiply(Imaging imIn1, Imaging imIn2) {
{ CHOP((int)in1[x] * (int)in2[x] / 255);
CHOP((int) in1[x] * (int) in2[x] / 255);
} }
Imaging Imaging
ImagingChopScreen(Imaging imIn1, Imaging imIn2) ImagingChopScreen(Imaging imIn1, Imaging imIn2) {
{ CHOP(255 - ((int)(255 - in1[x]) * (int)(255 - in2[x])) / 255);
CHOP(255 - ((int) (255 - in1[x]) * (int) (255 - in2[x])) / 255);
} }
Imaging Imaging
ImagingChopAdd(Imaging imIn1, Imaging imIn2, float scale, int offset) ImagingChopAdd(Imaging imIn1, Imaging imIn2, float scale, int offset) {
{ CHOP(((int)in1[x] + (int)in2[x]) / scale + offset);
CHOP(((int) in1[x] + (int) in2[x]) / scale + offset);
} }
Imaging Imaging
ImagingChopSubtract(Imaging imIn1, Imaging imIn2, float scale, int offset) ImagingChopSubtract(Imaging imIn1, Imaging imIn2, float scale, int offset) {
{ CHOP(((int)in1[x] - (int)in2[x]) / scale + offset);
CHOP(((int) in1[x] - (int) in2[x]) / scale + offset);
} }
Imaging Imaging
ImagingChopAnd(Imaging imIn1, Imaging imIn2) ImagingChopAnd(Imaging imIn1, Imaging imIn2) {
{
CHOP2((in1[x] && in2[x]) ? 255 : 0, "1"); CHOP2((in1[x] && in2[x]) ? 255 : 0, "1");
} }
Imaging Imaging
ImagingChopOr(Imaging imIn1, Imaging imIn2) ImagingChopOr(Imaging imIn1, Imaging imIn2) {
{
CHOP2((in1[x] || in2[x]) ? 255 : 0, "1"); CHOP2((in1[x] || in2[x]) ? 255 : 0, "1");
} }
Imaging Imaging
ImagingChopXor(Imaging imIn1, Imaging imIn2) ImagingChopXor(Imaging imIn1, Imaging imIn2) {
{
CHOP2(((in1[x] != 0) ^ (in2[x] != 0)) ? 255 : 0, "1"); CHOP2(((in1[x] != 0) ^ (in2[x] != 0)) ? 255 : 0, "1");
} }
Imaging Imaging
ImagingChopAddModulo(Imaging imIn1, Imaging imIn2) ImagingChopAddModulo(Imaging imIn1, Imaging imIn2) {
{
CHOP2(in1[x] + in2[x], NULL); CHOP2(in1[x] + in2[x], NULL);
} }
Imaging Imaging
ImagingChopSubtractModulo(Imaging imIn1, Imaging imIn2) ImagingChopSubtractModulo(Imaging imIn1, Imaging imIn2) {
{
CHOP2(in1[x] - in2[x], NULL); CHOP2(in1[x] - in2[x], NULL);
} }
Imaging Imaging
ImagingChopSoftLight(Imaging imIn1, Imaging imIn2) ImagingChopSoftLight(Imaging imIn1, Imaging imIn2) {
{ CHOP2(
CHOP2( (((255-in1[x]) * (in1[x]*in2[x]) ) / 65536) + (((255 - in1[x]) * (in1[x] * in2[x])) / 65536) +
(in1[x] * ( 255 - ( (255 - in1[x]) * (255 - in2[x] ) / 255) )) / 255 (in1[x] * (255 - ((255 - in1[x]) * (255 - in2[x]) / 255))) / 255,
, NULL ); NULL);
} }
Imaging Imaging
ImagingChopHardLight(Imaging imIn1, Imaging imIn2) ImagingChopHardLight(Imaging imIn1, Imaging imIn2) {
{ CHOP2(
CHOP2( (in2[x]<128) ? ( (in1[x]*in2[x])/127) (in2[x] < 128) ? ((in1[x] * in2[x]) / 127)
: 255 - ( ((255-in2[x]) * (255-in1[x])) / 127) : 255 - (((255 - in2[x]) * (255 - in1[x])) / 127),
, NULL); NULL);
} }
Imaging Imaging
ImagingOverlay(Imaging imIn1, Imaging imIn2) ImagingOverlay(Imaging imIn1, Imaging imIn2) {
{ CHOP2(
CHOP2( (in1[x]<128) ? ( (in1[x]*in2[x])/127) (in1[x] < 128) ? ((in1[x] * in2[x]) / 127)
: 255 - ( ((255-in1[x]) * (255-in2[x])) / 127) : 255 - (((255 - in1[x]) * (255 - in2[x])) / 127),
, NULL); NULL);
} }

View File

@ -1,52 +1,45 @@
#include "Imaging.h" #include "Imaging.h"
#include <math.h> #include <math.h>
/* 8 bits for result. Table can overflow [0, 1.0] range, /* 8 bits for result. Table can overflow [0, 1.0] range,
so we need extra bits for overflow and negative values. so we need extra bits for overflow and negative values.
NOTE: This value should be the same as in _imaging/_prepare_lut_table() */ NOTE: This value should be the same as in _imaging/_prepare_lut_table() */
#define PRECISION_BITS (16 - 8 - 2) #define PRECISION_BITS (16 - 8 - 2)
#define PRECISION_ROUNDING (1<<(PRECISION_BITS-1)) #define PRECISION_ROUNDING (1 << (PRECISION_BITS - 1))
/* 8 — scales are multiplied on byte. /* 8 — scales are multiplied on byte.
6 max index in the table 6 max index in the table
(max size is 65, but index 64 is not reachable) */ (max size is 65, but index 64 is not reachable) */
#define SCALE_BITS (32 - 8 - 6) #define SCALE_BITS (32 - 8 - 6)
#define SCALE_MASK ((1<<SCALE_BITS) - 1) #define SCALE_MASK ((1 << SCALE_BITS) - 1)
#define SHIFT_BITS (16 - 1) #define SHIFT_BITS (16 - 1)
static inline UINT8
static inline UINT8 clip8(int in) clip8(int in) {
{
return clip8_lookups[(in + PRECISION_ROUNDING) >> PRECISION_BITS]; return clip8_lookups[(in + PRECISION_ROUNDING) >> PRECISION_BITS];
} }
static inline void static inline void
interpolate3(INT16 out[3], const INT16 a[3], const INT16 b[3], INT16 shift) interpolate3(INT16 out[3], const INT16 a[3], const INT16 b[3], INT16 shift) {
{ out[0] = (a[0] * ((1 << SHIFT_BITS) - shift) + b[0] * shift) >> SHIFT_BITS;
out[0] = (a[0] * ((1<<SHIFT_BITS)-shift) + b[0] * shift) >> SHIFT_BITS; out[1] = (a[1] * ((1 << SHIFT_BITS) - shift) + b[1] * shift) >> SHIFT_BITS;
out[1] = (a[1] * ((1<<SHIFT_BITS)-shift) + b[1] * shift) >> SHIFT_BITS; out[2] = (a[2] * ((1 << SHIFT_BITS) - shift) + b[2] * shift) >> SHIFT_BITS;
out[2] = (a[2] * ((1<<SHIFT_BITS)-shift) + b[2] * shift) >> SHIFT_BITS;
} }
static inline void static inline void
interpolate4(INT16 out[4], const INT16 a[4], const INT16 b[4], INT16 shift) interpolate4(INT16 out[4], const INT16 a[4], const INT16 b[4], INT16 shift) {
{ out[0] = (a[0] * ((1 << SHIFT_BITS) - shift) + b[0] * shift) >> SHIFT_BITS;
out[0] = (a[0] * ((1<<SHIFT_BITS)-shift) + b[0] * shift) >> SHIFT_BITS; out[1] = (a[1] * ((1 << SHIFT_BITS) - shift) + b[1] * shift) >> SHIFT_BITS;
out[1] = (a[1] * ((1<<SHIFT_BITS)-shift) + b[1] * shift) >> SHIFT_BITS; out[2] = (a[2] * ((1 << SHIFT_BITS) - shift) + b[2] * shift) >> SHIFT_BITS;
out[2] = (a[2] * ((1<<SHIFT_BITS)-shift) + b[2] * shift) >> SHIFT_BITS; out[3] = (a[3] * ((1 << SHIFT_BITS) - shift) + b[3] * shift) >> SHIFT_BITS;
out[3] = (a[3] * ((1<<SHIFT_BITS)-shift) + b[3] * shift) >> SHIFT_BITS;
} }
static inline int static inline int
table_index3D(int index1D, int index2D, int index3D, table_index3D(int index1D, int index2D, int index3D, int size1D, int size1D_2D) {
int size1D, int size1D_2D)
{
return index1D + index2D * size1D + index3D * size1D_2D; return index1D + index2D * size1D + index3D * size1D_2D;
} }
/* /*
Transforms colors of imIn using provided 3D lookup table Transforms colors of imIn using provided 3D lookup table
and puts the result in imOut. Returns imOut on success or 0 on error. and puts the result in imOut. Returns imOut on success or 0 on error.
@ -63,10 +56,14 @@ table_index3D(int index1D, int index2D, int index3D,
and 255 << PRECISION_BITS (16320) is highest value. and 255 << PRECISION_BITS (16320) is highest value.
*/ */
Imaging Imaging
ImagingColorLUT3D_linear(Imaging imOut, Imaging imIn, int table_channels, ImagingColorLUT3D_linear(
int size1D, int size2D, int size3D, Imaging imOut,
INT16* table) Imaging imIn,
{ int table_channels,
int size1D,
int size2D,
int size3D,
INT16 *table) {
/* This float to int conversion doesn't have rounding /* This float to int conversion doesn't have rounding
error compensation (+0.5) for two reasons: error compensation (+0.5) for two reasons:
1. As we don't hit the highest value, 1. As we don't hit the highest value,
@ -77,9 +74,9 @@ ImagingColorLUT3D_linear(Imaging imOut, Imaging imIn, int table_channels,
+1 cells will be outside of the table. +1 cells will be outside of the table.
With this compensation we never hit the upper cells With this compensation we never hit the upper cells
but this also doesn't introduce any noticeable difference. */ but this also doesn't introduce any noticeable difference. */
UINT32 scale1D = (size1D - 1) / 255.0 * (1<<SCALE_BITS); UINT32 scale1D = (size1D - 1) / 255.0 * (1 << SCALE_BITS);
UINT32 scale2D = (size2D - 1) / 255.0 * (1<<SCALE_BITS); UINT32 scale2D = (size2D - 1) / 255.0 * (1 << SCALE_BITS);
UINT32 scale3D = (size3D - 1) / 255.0 * (1<<SCALE_BITS); UINT32 scale3D = (size3D - 1) / 255.0 * (1 << SCALE_BITS);
int size1D_2D = size1D * size2D; int size1D_2D = size1D * size2D;
int x, y; int x, y;
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
@ -89,75 +86,97 @@ ImagingColorLUT3D_linear(Imaging imOut, Imaging imIn, int table_channels,
return NULL; return NULL;
} }
if (imIn->type != IMAGING_TYPE_UINT8 || if (imIn->type != IMAGING_TYPE_UINT8 || imOut->type != IMAGING_TYPE_UINT8 ||
imOut->type != IMAGING_TYPE_UINT8 || imIn->bands < 3 || imOut->bands < table_channels) {
imIn->bands < 3 || return (Imaging)ImagingError_ModeError();
imOut->bands < table_channels
) {
return (Imaging) ImagingError_ModeError();
} }
/* In case we have one extra band in imOut and don't have in imIn.*/ /* In case we have one extra band in imOut and don't have in imIn.*/
if (imOut->bands > table_channels && imOut->bands > imIn->bands) { if (imOut->bands > table_channels && imOut->bands > imIn->bands) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
for (y = 0; y < imOut->ysize; y++) { for (y = 0; y < imOut->ysize; y++) {
UINT8* rowIn = (UINT8 *)imIn->image[y]; UINT8 *rowIn = (UINT8 *)imIn->image[y];
char* rowOut = (char *)imOut->image[y]; char *rowOut = (char *)imOut->image[y];
for (x = 0; x < imOut->xsize; x++) { for (x = 0; x < imOut->xsize; x++) {
UINT32 index1D = rowIn[x*4 + 0] * scale1D; UINT32 index1D = rowIn[x * 4 + 0] * scale1D;
UINT32 index2D = rowIn[x*4 + 1] * scale2D; UINT32 index2D = rowIn[x * 4 + 1] * scale2D;
UINT32 index3D = rowIn[x*4 + 2] * scale3D; UINT32 index3D = rowIn[x * 4 + 2] * scale3D;
INT16 shift1D = (SCALE_MASK & index1D) >> (SCALE_BITS - SHIFT_BITS); INT16 shift1D = (SCALE_MASK & index1D) >> (SCALE_BITS - SHIFT_BITS);
INT16 shift2D = (SCALE_MASK & index2D) >> (SCALE_BITS - SHIFT_BITS); INT16 shift2D = (SCALE_MASK & index2D) >> (SCALE_BITS - SHIFT_BITS);
INT16 shift3D = (SCALE_MASK & index3D) >> (SCALE_BITS - SHIFT_BITS); INT16 shift3D = (SCALE_MASK & index3D) >> (SCALE_BITS - SHIFT_BITS);
int idx = table_channels * table_index3D( int idx = table_channels * table_index3D(
index1D >> SCALE_BITS, index2D >> SCALE_BITS, index1D >> SCALE_BITS,
index3D >> SCALE_BITS, size1D, size1D_2D); index2D >> SCALE_BITS,
index3D >> SCALE_BITS,
size1D,
size1D_2D);
INT16 result[4], left[4], right[4]; INT16 result[4], left[4], right[4];
INT16 leftleft[4], leftright[4], rightleft[4], rightright[4]; INT16 leftleft[4], leftright[4], rightleft[4], rightright[4];
if (table_channels == 3) { if (table_channels == 3) {
UINT32 v; UINT32 v;
interpolate3(leftleft, &table[idx + 0], &table[idx + 3], shift1D); interpolate3(leftleft, &table[idx + 0], &table[idx + 3], shift1D);
interpolate3(leftright, &table[idx + size1D*3], interpolate3(
&table[idx + size1D*3 + 3], shift1D); leftright,
&table[idx + size1D * 3],
&table[idx + size1D * 3 + 3],
shift1D);
interpolate3(left, leftleft, leftright, shift2D); interpolate3(left, leftleft, leftright, shift2D);
interpolate3(rightleft, &table[idx + size1D_2D*3], interpolate3(
&table[idx + size1D_2D*3 + 3], shift1D); rightleft,
interpolate3(rightright, &table[idx + size1D_2D*3 + size1D*3], &table[idx + size1D_2D * 3],
&table[idx + size1D_2D*3 + size1D*3 + 3], shift1D); &table[idx + size1D_2D * 3 + 3],
shift1D);
interpolate3(
rightright,
&table[idx + size1D_2D * 3 + size1D * 3],
&table[idx + size1D_2D * 3 + size1D * 3 + 3],
shift1D);
interpolate3(right, rightleft, rightright, shift2D); interpolate3(right, rightleft, rightright, shift2D);
interpolate3(result, left, right, shift3D); interpolate3(result, left, right, shift3D);
v = MAKE_UINT32( v = MAKE_UINT32(
clip8(result[0]), clip8(result[1]), clip8(result[0]),
clip8(result[2]), rowIn[x*4 + 3]); clip8(result[1]),
clip8(result[2]),
rowIn[x * 4 + 3]);
memcpy(rowOut + x * sizeof(v), &v, sizeof(v)); memcpy(rowOut + x * sizeof(v), &v, sizeof(v));
} }
if (table_channels == 4) { if (table_channels == 4) {
UINT32 v; UINT32 v;
interpolate4(leftleft, &table[idx + 0], &table[idx + 4], shift1D); interpolate4(leftleft, &table[idx + 0], &table[idx + 4], shift1D);
interpolate4(leftright, &table[idx + size1D*4], interpolate4(
&table[idx + size1D*4 + 4], shift1D); leftright,
&table[idx + size1D * 4],
&table[idx + size1D * 4 + 4],
shift1D);
interpolate4(left, leftleft, leftright, shift2D); interpolate4(left, leftleft, leftright, shift2D);
interpolate4(rightleft, &table[idx + size1D_2D*4], interpolate4(
&table[idx + size1D_2D*4 + 4], shift1D); rightleft,
interpolate4(rightright, &table[idx + size1D_2D*4 + size1D*4], &table[idx + size1D_2D * 4],
&table[idx + size1D_2D*4 + size1D*4 + 4], shift1D); &table[idx + size1D_2D * 4 + 4],
shift1D);
interpolate4(
rightright,
&table[idx + size1D_2D * 4 + size1D * 4],
&table[idx + size1D_2D * 4 + size1D * 4 + 4],
shift1D);
interpolate4(right, rightleft, rightright, shift2D); interpolate4(right, rightleft, rightright, shift2D);
interpolate4(result, left, right, shift3D); interpolate4(result, left, right, shift3D);
v = MAKE_UINT32( v = MAKE_UINT32(
clip8(result[0]), clip8(result[1]), clip8(result[0]),
clip8(result[2]), clip8(result[3])); clip8(result[1]),
clip8(result[2]),
clip8(result[3]));
memcpy(rowOut + x * sizeof(v), &v, sizeof(v)); memcpy(rowOut + x * sizeof(v), &v, sizeof(v));
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -28,356 +28,332 @@
#define SCALE 6 /* bits */ #define SCALE 6 /* bits */
static INT16 Y_R[] = { 0, 19, 38, 57, 77, 96, 115, 134, 153, 172, 191, static INT16 Y_R[] = {
210, 230, 249, 268, 287, 306, 325, 344, 364, 383, 402, 421, 440, 459, 0, 19, 38, 57, 77, 96, 115, 134, 153, 172, 191, 210, 230, 249,
478, 498, 517, 536, 555, 574, 593, 612, 631, 651, 670, 689, 708, 727, 268, 287, 306, 325, 344, 364, 383, 402, 421, 440, 459, 478, 498, 517,
746, 765, 785, 804, 823, 842, 861, 880, 899, 919, 938, 957, 976, 995, 536, 555, 574, 593, 612, 631, 651, 670, 689, 708, 727, 746, 765, 785,
1014, 1033, 1052, 1072, 1091, 1110, 1129, 1148, 1167, 1186, 1206, 804, 823, 842, 861, 880, 899, 919, 938, 957, 976, 995, 1014, 1033, 1052,
1225, 1244, 1263, 1282, 1301, 1320, 1340, 1359, 1378, 1397, 1416, 1072, 1091, 1110, 1129, 1148, 1167, 1186, 1206, 1225, 1244, 1263, 1282, 1301, 1320,
1435, 1454, 1473, 1493, 1512, 1531, 1550, 1569, 1588, 1607, 1627, 1340, 1359, 1378, 1397, 1416, 1435, 1454, 1473, 1493, 1512, 1531, 1550, 1569, 1588,
1646, 1665, 1684, 1703, 1722, 1741, 1761, 1780, 1799, 1818, 1837, 1607, 1627, 1646, 1665, 1684, 1703, 1722, 1741, 1761, 1780, 1799, 1818, 1837, 1856,
1856, 1875, 1894, 1914, 1933, 1952, 1971, 1990, 2009, 2028, 2048, 1875, 1894, 1914, 1933, 1952, 1971, 1990, 2009, 2028, 2048, 2067, 2086, 2105, 2124,
2067, 2086, 2105, 2124, 2143, 2162, 2182, 2201, 2220, 2239, 2258, 2143, 2162, 2182, 2201, 2220, 2239, 2258, 2277, 2296, 2315, 2335, 2354, 2373, 2392,
2277, 2296, 2315, 2335, 2354, 2373, 2392, 2411, 2430, 2449, 2469, 2411, 2430, 2449, 2469, 2488, 2507, 2526, 2545, 2564, 2583, 2602, 2622, 2641, 2660,
2488, 2507, 2526, 2545, 2564, 2583, 2602, 2622, 2641, 2660, 2679, 2679, 2698, 2717, 2736, 2756, 2775, 2794, 2813, 2832, 2851, 2870, 2890, 2909, 2928,
2698, 2717, 2736, 2756, 2775, 2794, 2813, 2832, 2851, 2870, 2890, 2947, 2966, 2985, 3004, 3023, 3043, 3062, 3081, 3100, 3119, 3138, 3157, 3177, 3196,
2909, 2928, 2947, 2966, 2985, 3004, 3023, 3043, 3062, 3081, 3100, 3215, 3234, 3253, 3272, 3291, 3311, 3330, 3349, 3368, 3387, 3406, 3425, 3444, 3464,
3119, 3138, 3157, 3177, 3196, 3215, 3234, 3253, 3272, 3291, 3311, 3483, 3502, 3521, 3540, 3559, 3578, 3598, 3617, 3636, 3655, 3674, 3693, 3712, 3732,
3330, 3349, 3368, 3387, 3406, 3425, 3444, 3464, 3483, 3502, 3521, 3751, 3770, 3789, 3808, 3827, 3846, 3865, 3885, 3904, 3923, 3942, 3961, 3980, 3999,
3540, 3559, 3578, 3598, 3617, 3636, 3655, 3674, 3693, 3712, 3732, 4019, 4038, 4057, 4076, 4095, 4114, 4133, 4153, 4172, 4191, 4210, 4229, 4248, 4267,
3751, 3770, 3789, 3808, 3827, 3846, 3865, 3885, 3904, 3923, 3942, 4286, 4306, 4325, 4344, 4363, 4382, 4401, 4420, 4440, 4459, 4478, 4497, 4516, 4535,
3961, 3980, 3999, 4019, 4038, 4057, 4076, 4095, 4114, 4133, 4153, 4554, 4574, 4593, 4612, 4631, 4650, 4669, 4688, 4707, 4727, 4746, 4765, 4784, 4803,
4172, 4191, 4210, 4229, 4248, 4267, 4286, 4306, 4325, 4344, 4363, 4822, 4841, 4861, 4880};
4382, 4401, 4420, 4440, 4459, 4478, 4497, 4516, 4535, 4554, 4574,
4593, 4612, 4631, 4650, 4669, 4688, 4707, 4727, 4746, 4765, 4784,
4803, 4822, 4841, 4861, 4880 };
static INT16 Y_G[] = { 0, 38, 75, 113, 150, 188, 225, 263, 301, 338, static INT16 Y_G[] = {
376, 413, 451, 488, 526, 564, 601, 639, 676, 714, 751, 789, 826, 864, 0, 38, 75, 113, 150, 188, 225, 263, 301, 338, 376, 413, 451, 488,
902, 939, 977, 1014, 1052, 1089, 1127, 1165, 1202, 1240, 1277, 1315, 526, 564, 601, 639, 676, 714, 751, 789, 826, 864, 902, 939, 977, 1014,
1352, 1390, 1428, 1465, 1503, 1540, 1578, 1615, 1653, 1691, 1728, 1052, 1089, 1127, 1165, 1202, 1240, 1277, 1315, 1352, 1390, 1428, 1465, 1503, 1540,
1766, 1803, 1841, 1878, 1916, 1954, 1991, 2029, 2066, 2104, 2141, 1578, 1615, 1653, 1691, 1728, 1766, 1803, 1841, 1878, 1916, 1954, 1991, 2029, 2066,
2179, 2217, 2254, 2292, 2329, 2367, 2404, 2442, 2479, 2517, 2555, 2104, 2141, 2179, 2217, 2254, 2292, 2329, 2367, 2404, 2442, 2479, 2517, 2555, 2592,
2592, 2630, 2667, 2705, 2742, 2780, 2818, 2855, 2893, 2930, 2968, 2630, 2667, 2705, 2742, 2780, 2818, 2855, 2893, 2930, 2968, 3005, 3043, 3081, 3118,
3005, 3043, 3081, 3118, 3156, 3193, 3231, 3268, 3306, 3344, 3381, 3156, 3193, 3231, 3268, 3306, 3344, 3381, 3419, 3456, 3494, 3531, 3569, 3607, 3644,
3419, 3456, 3494, 3531, 3569, 3607, 3644, 3682, 3719, 3757, 3794, 3682, 3719, 3757, 3794, 3832, 3870, 3907, 3945, 3982, 4020, 4057, 4095, 4132, 4170,
3832, 3870, 3907, 3945, 3982, 4020, 4057, 4095, 4132, 4170, 4208, 4208, 4245, 4283, 4320, 4358, 4395, 4433, 4471, 4508, 4546, 4583, 4621, 4658, 4696,
4245, 4283, 4320, 4358, 4395, 4433, 4471, 4508, 4546, 4583, 4621, 4734, 4771, 4809, 4846, 4884, 4921, 4959, 4997, 5034, 5072, 5109, 5147, 5184, 5222,
4658, 4696, 4734, 4771, 4809, 4846, 4884, 4921, 4959, 4997, 5034, 5260, 5297, 5335, 5372, 5410, 5447, 5485, 5522, 5560, 5598, 5635, 5673, 5710, 5748,
5072, 5109, 5147, 5184, 5222, 5260, 5297, 5335, 5372, 5410, 5447, 5785, 5823, 5861, 5898, 5936, 5973, 6011, 6048, 6086, 6124, 6161, 6199, 6236, 6274,
5485, 5522, 5560, 5598, 5635, 5673, 5710, 5748, 5785, 5823, 5861, 6311, 6349, 6387, 6424, 6462, 6499, 6537, 6574, 6612, 6650, 6687, 6725, 6762, 6800,
5898, 5936, 5973, 6011, 6048, 6086, 6124, 6161, 6199, 6236, 6274, 6837, 6875, 6913, 6950, 6988, 7025, 7063, 7100, 7138, 7175, 7213, 7251, 7288, 7326,
6311, 6349, 6387, 6424, 6462, 6499, 6537, 6574, 6612, 6650, 6687, 7363, 7401, 7438, 7476, 7514, 7551, 7589, 7626, 7664, 7701, 7739, 7777, 7814, 7852,
6725, 6762, 6800, 6837, 6875, 6913, 6950, 6988, 7025, 7063, 7100, 7889, 7927, 7964, 8002, 8040, 8077, 8115, 8152, 8190, 8227, 8265, 8303, 8340, 8378,
7138, 7175, 7213, 7251, 7288, 7326, 7363, 7401, 7438, 7476, 7514, 8415, 8453, 8490, 8528, 8566, 8603, 8641, 8678, 8716, 8753, 8791, 8828, 8866, 8904,
7551, 7589, 7626, 7664, 7701, 7739, 7777, 7814, 7852, 7889, 7927, 8941, 8979, 9016, 9054, 9091, 9129, 9167, 9204, 9242, 9279, 9317, 9354, 9392, 9430,
7964, 8002, 8040, 8077, 8115, 8152, 8190, 8227, 8265, 8303, 8340, 9467, 9505, 9542, 9580};
8378, 8415, 8453, 8490, 8528, 8566, 8603, 8641, 8678, 8716, 8753,
8791, 8828, 8866, 8904, 8941, 8979, 9016, 9054, 9091, 9129, 9167,
9204, 9242, 9279, 9317, 9354, 9392, 9430, 9467, 9505, 9542, 9580 };
static INT16 Y_B[] = { 0, 7, 15, 22, 29, 36, 44, 51, 58, 66, 73, 80, static INT16 Y_B[] = {
88, 95, 102, 109, 117, 124, 131, 139, 146, 153, 161, 168, 175, 182, 0, 7, 15, 22, 29, 36, 44, 51, 58, 66, 73, 80, 88, 95,
190, 197, 204, 212, 219, 226, 233, 241, 248, 255, 263, 270, 277, 285, 102, 109, 117, 124, 131, 139, 146, 153, 161, 168, 175, 182, 190, 197,
292, 299, 306, 314, 321, 328, 336, 343, 350, 358, 365, 372, 379, 387, 204, 212, 219, 226, 233, 241, 248, 255, 263, 270, 277, 285, 292, 299,
394, 401, 409, 416, 423, 430, 438, 445, 452, 460, 467, 474, 482, 489, 306, 314, 321, 328, 336, 343, 350, 358, 365, 372, 379, 387, 394, 401,
496, 503, 511, 518, 525, 533, 540, 547, 554, 562, 569, 576, 584, 591, 409, 416, 423, 430, 438, 445, 452, 460, 467, 474, 482, 489, 496, 503,
598, 606, 613, 620, 627, 635, 642, 649, 657, 664, 671, 679, 686, 693, 511, 518, 525, 533, 540, 547, 554, 562, 569, 576, 584, 591, 598, 606,
700, 708, 715, 722, 730, 737, 744, 751, 759, 766, 773, 781, 788, 795, 613, 620, 627, 635, 642, 649, 657, 664, 671, 679, 686, 693, 700, 708,
803, 810, 817, 824, 832, 839, 846, 854, 861, 868, 876, 883, 890, 897, 715, 722, 730, 737, 744, 751, 759, 766, 773, 781, 788, 795, 803, 810,
905, 912, 919, 927, 934, 941, 948, 956, 963, 970, 978, 985, 992, 1000, 817, 824, 832, 839, 846, 854, 861, 868, 876, 883, 890, 897, 905, 912,
1007, 1014, 1021, 1029, 1036, 1043, 1051, 1058, 1065, 1073, 1080, 919, 927, 934, 941, 948, 956, 963, 970, 978, 985, 992, 1000, 1007, 1014,
1087, 1094, 1102, 1109, 1116, 1124, 1131, 1138, 1145, 1153, 1160, 1021, 1029, 1036, 1043, 1051, 1058, 1065, 1073, 1080, 1087, 1094, 1102, 1109, 1116,
1167, 1175, 1182, 1189, 1197, 1204, 1211, 1218, 1226, 1233, 1240, 1124, 1131, 1138, 1145, 1153, 1160, 1167, 1175, 1182, 1189, 1197, 1204, 1211, 1218,
1248, 1255, 1262, 1270, 1277, 1284, 1291, 1299, 1306, 1313, 1321, 1226, 1233, 1240, 1248, 1255, 1262, 1270, 1277, 1284, 1291, 1299, 1306, 1313, 1321,
1328, 1335, 1342, 1350, 1357, 1364, 1372, 1379, 1386, 1394, 1401, 1328, 1335, 1342, 1350, 1357, 1364, 1372, 1379, 1386, 1394, 1401, 1408, 1415, 1423,
1408, 1415, 1423, 1430, 1437, 1445, 1452, 1459, 1466, 1474, 1481, 1430, 1437, 1445, 1452, 1459, 1466, 1474, 1481, 1488, 1496, 1503, 1510, 1518, 1525,
1488, 1496, 1503, 1510, 1518, 1525, 1532, 1539, 1547, 1554, 1561, 1532, 1539, 1547, 1554, 1561, 1569, 1576, 1583, 1591, 1598, 1605, 1612, 1620, 1627,
1569, 1576, 1583, 1591, 1598, 1605, 1612, 1620, 1627, 1634, 1642, 1634, 1642, 1649, 1656, 1663, 1671, 1678, 1685, 1693, 1700, 1707, 1715, 1722, 1729,
1649, 1656, 1663, 1671, 1678, 1685, 1693, 1700, 1707, 1715, 1722, 1736, 1744, 1751, 1758, 1766, 1773, 1780, 1788, 1795, 1802, 1809, 1817, 1824, 1831,
1729, 1736, 1744, 1751, 1758, 1766, 1773, 1780, 1788, 1795, 1802, 1839, 1846, 1853, 1860};
1809, 1817, 1824, 1831, 1839, 1846, 1853, 1860 };
static INT16 Cb_R[] = { 0, -10, -21, -31, -42, -53, -64, -75, -85, static INT16 Cb_R[] = {
-96, -107, -118, -129, -139, -150, -161, -172, -183, -193, -204, -215, 0, -10, -21, -31, -42, -53, -64, -75, -85, -96, -107, -118,
-226, -237, -247, -258, -269, -280, -291, -301, -312, -323, -334, -129, -139, -150, -161, -172, -183, -193, -204, -215, -226, -237, -247,
-345, -355, -366, -377, -388, -399, -409, -420, -431, -442, -453, -258, -269, -280, -291, -301, -312, -323, -334, -345, -355, -366, -377,
-463, -474, -485, -496, -507, -517, -528, -539, -550, -561, -571, -388, -399, -409, -420, -431, -442, -453, -463, -474, -485, -496, -507,
-582, -593, -604, -615, -625, -636, -647, -658, -669, -679, -690, -517, -528, -539, -550, -561, -571, -582, -593, -604, -615, -625, -636,
-701, -712, -723, -733, -744, -755, -766, -777, -787, -798, -809, -647, -658, -669, -679, -690, -701, -712, -723, -733, -744, -755, -766,
-820, -831, -841, -852, -863, -874, -885, -895, -906, -917, -928, -777, -787, -798, -809, -820, -831, -841, -852, -863, -874, -885, -895,
-939, -949, -960, -971, -982, -993, -1003, -1014, -1025, -1036, -1047, -906, -917, -928, -939, -949, -960, -971, -982, -993, -1003, -1014, -1025,
-1057, -1068, -1079, -1090, -1101, -1111, -1122, -1133, -1144, -1155, -1036, -1047, -1057, -1068, -1079, -1090, -1101, -1111, -1122, -1133, -1144, -1155,
-1165, -1176, -1187, -1198, -1209, -1219, -1230, -1241, -1252, -1263, -1165, -1176, -1187, -1198, -1209, -1219, -1230, -1241, -1252, -1263, -1273, -1284,
-1273, -1284, -1295, -1306, -1317, -1327, -1338, -1349, -1360, -1371, -1295, -1306, -1317, -1327, -1338, -1349, -1360, -1371, -1381, -1392, -1403, -1414,
-1381, -1392, -1403, -1414, -1425, -1435, -1446, -1457, -1468, -1479, -1425, -1435, -1446, -1457, -1468, -1479, -1489, -1500, -1511, -1522, -1533, -1543,
-1489, -1500, -1511, -1522, -1533, -1543, -1554, -1565, -1576, -1587, -1554, -1565, -1576, -1587, -1597, -1608, -1619, -1630, -1641, -1651, -1662, -1673,
-1597, -1608, -1619, -1630, -1641, -1651, -1662, -1673, -1684, -1694, -1684, -1694, -1705, -1716, -1727, -1738, -1748, -1759, -1770, -1781, -1792, -1802,
-1705, -1716, -1727, -1738, -1748, -1759, -1770, -1781, -1792, -1802, -1813, -1824, -1835, -1846, -1856, -1867, -1878, -1889, -1900, -1910, -1921, -1932,
-1813, -1824, -1835, -1846, -1856, -1867, -1878, -1889, -1900, -1910, -1943, -1954, -1964, -1975, -1986, -1997, -2008, -2018, -2029, -2040, -2051, -2062,
-1921, -1932, -1943, -1954, -1964, -1975, -1986, -1997, -2008, -2018, -2072, -2083, -2094, -2105, -2116, -2126, -2137, -2148, -2159, -2170, -2180, -2191,
-2029, -2040, -2051, -2062, -2072, -2083, -2094, -2105, -2116, -2126, -2202, -2213, -2224, -2234, -2245, -2256, -2267, -2278, -2288, -2299, -2310, -2321,
-2137, -2148, -2159, -2170, -2180, -2191, -2202, -2213, -2224, -2234, -2332, -2342, -2353, -2364, -2375, -2386, -2396, -2407, -2418, -2429, -2440, -2450,
-2245, -2256, -2267, -2278, -2288, -2299, -2310, -2321, -2332, -2342, -2461, -2472, -2483, -2494, -2504, -2515, -2526, -2537, -2548, -2558, -2569, -2580,
-2353, -2364, -2375, -2386, -2396, -2407, -2418, -2429, -2440, -2450, -2591, -2602, -2612, -2623, -2634, -2645, -2656, -2666, -2677, -2688, -2699, -2710,
-2461, -2472, -2483, -2494, -2504, -2515, -2526, -2537, -2548, -2558, -2720, -2731, -2742, -2753};
-2569, -2580, -2591, -2602, -2612, -2623, -2634, -2645, -2656, -2666,
-2677, -2688, -2699, -2710, -2720, -2731, -2742, -2753 };
static INT16 Cb_G[] = { 0, -20, -41, -63, -84, -105, -126, -147, -169, static INT16 Cb_G[] = {
-190, -211, -232, -253, -275, -296, -317, -338, -359, -381, -402, 0, -20, -41, -63, -84, -105, -126, -147, -169, -190, -211, -232,
-423, -444, -465, -487, -508, -529, -550, -571, -593, -614, -635, -253, -275, -296, -317, -338, -359, -381, -402, -423, -444, -465, -487,
-656, -677, -699, -720, -741, -762, -783, -805, -826, -847, -868, -508, -529, -550, -571, -593, -614, -635, -656, -677, -699, -720, -741,
-889, -911, -932, -953, -974, -995, -1017, -1038, -1059, -1080, -1101, -762, -783, -805, -826, -847, -868, -889, -911, -932, -953, -974, -995,
-1123, -1144, -1165, -1186, -1207, -1229, -1250, -1271, -1292, -1313, -1017, -1038, -1059, -1080, -1101, -1123, -1144, -1165, -1186, -1207, -1229, -1250,
-1335, -1356, -1377, -1398, -1419, -1441, -1462, -1483, -1504, -1525, -1271, -1292, -1313, -1335, -1356, -1377, -1398, -1419, -1441, -1462, -1483, -1504,
-1547, -1568, -1589, -1610, -1631, -1653, -1674, -1695, -1716, -1737, -1525, -1547, -1568, -1589, -1610, -1631, -1653, -1674, -1695, -1716, -1737, -1759,
-1759, -1780, -1801, -1822, -1843, -1865, -1886, -1907, -1928, -1949, -1780, -1801, -1822, -1843, -1865, -1886, -1907, -1928, -1949, -1971, -1992, -2013,
-1971, -1992, -2013, -2034, -2055, -2077, -2098, -2119, -2140, -2161, -2034, -2055, -2077, -2098, -2119, -2140, -2161, -2183, -2204, -2225, -2246, -2267,
-2183, -2204, -2225, -2246, -2267, -2289, -2310, -2331, -2352, -2373, -2289, -2310, -2331, -2352, -2373, -2395, -2416, -2437, -2458, -2479, -2501, -2522,
-2395, -2416, -2437, -2458, -2479, -2501, -2522, -2543, -2564, -2585, -2543, -2564, -2585, -2607, -2628, -2649, -2670, -2691, -2713, -2734, -2755, -2776,
-2607, -2628, -2649, -2670, -2691, -2713, -2734, -2755, -2776, -2797, -2797, -2819, -2840, -2861, -2882, -2903, -2925, -2946, -2967, -2988, -3009, -3031,
-2819, -2840, -2861, -2882, -2903, -2925, -2946, -2967, -2988, -3009, -3052, -3073, -3094, -3115, -3137, -3158, -3179, -3200, -3221, -3243, -3264, -3285,
-3031, -3052, -3073, -3094, -3115, -3137, -3158, -3179, -3200, -3221, -3306, -3328, -3349, -3370, -3391, -3412, -3434, -3455, -3476, -3497, -3518, -3540,
-3243, -3264, -3285, -3306, -3328, -3349, -3370, -3391, -3412, -3434, -3561, -3582, -3603, -3624, -3646, -3667, -3688, -3709, -3730, -3752, -3773, -3794,
-3455, -3476, -3497, -3518, -3540, -3561, -3582, -3603, -3624, -3646, -3815, -3836, -3858, -3879, -3900, -3921, -3942, -3964, -3985, -4006, -4027, -4048,
-3667, -3688, -3709, -3730, -3752, -3773, -3794, -3815, -3836, -3858, -4070, -4091, -4112, -4133, -4154, -4176, -4197, -4218, -4239, -4260, -4282, -4303,
-3879, -3900, -3921, -3942, -3964, -3985, -4006, -4027, -4048, -4070, -4324, -4345, -4366, -4388, -4409, -4430, -4451, -4472, -4494, -4515, -4536, -4557,
-4091, -4112, -4133, -4154, -4176, -4197, -4218, -4239, -4260, -4282, -4578, -4600, -4621, -4642, -4663, -4684, -4706, -4727, -4748, -4769, -4790, -4812,
-4303, -4324, -4345, -4366, -4388, -4409, -4430, -4451, -4472, -4494, -4833, -4854, -4875, -4896, -4918, -4939, -4960, -4981, -5002, -5024, -5045, -5066,
-4515, -4536, -4557, -4578, -4600, -4621, -4642, -4663, -4684, -4706, -5087, -5108, -5130, -5151, -5172, -5193, -5214, -5236, -5257, -5278, -5299, -5320,
-4727, -4748, -4769, -4790, -4812, -4833, -4854, -4875, -4896, -4918, -5342, -5363, -5384, -5405};
-4939, -4960, -4981, -5002, -5024, -5045, -5066, -5087, -5108, -5130,
-5151, -5172, -5193, -5214, -5236, -5257, -5278, -5299, -5320, -5342,
-5363, -5384, -5405 };
static INT16 Cb_B[] = { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, static INT16 Cb_B[] = {
320, 352, 384, 416, 448, 480, 512, 544, 576, 608, 640, 672, 704, 736, 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416,
768, 800, 832, 864, 896, 928, 960, 992, 1024, 1056, 1088, 1120, 1152, 448, 480, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864,
1184, 1216, 1248, 1280, 1312, 1344, 1376, 1408, 1440, 1472, 1504, 896, 928, 960, 992, 1024, 1056, 1088, 1120, 1152, 1184, 1216, 1248, 1280, 1312,
1536, 1568, 1600, 1632, 1664, 1696, 1728, 1760, 1792, 1824, 1856, 1344, 1376, 1408, 1440, 1472, 1504, 1536, 1568, 1600, 1632, 1664, 1696, 1728, 1760,
1888, 1920, 1952, 1984, 2016, 2048, 2080, 2112, 2144, 2176, 2208, 1792, 1824, 1856, 1888, 1920, 1952, 1984, 2016, 2048, 2080, 2112, 2144, 2176, 2208,
2240, 2272, 2304, 2336, 2368, 2400, 2432, 2464, 2496, 2528, 2560, 2240, 2272, 2304, 2336, 2368, 2400, 2432, 2464, 2496, 2528, 2560, 2592, 2624, 2656,
2592, 2624, 2656, 2688, 2720, 2752, 2784, 2816, 2848, 2880, 2912, 2688, 2720, 2752, 2784, 2816, 2848, 2880, 2912, 2944, 2976, 3008, 3040, 3072, 3104,
2944, 2976, 3008, 3040, 3072, 3104, 3136, 3168, 3200, 3232, 3264, 3136, 3168, 3200, 3232, 3264, 3296, 3328, 3360, 3392, 3424, 3456, 3488, 3520, 3552,
3296, 3328, 3360, 3392, 3424, 3456, 3488, 3520, 3552, 3584, 3616, 3584, 3616, 3648, 3680, 3712, 3744, 3776, 3808, 3840, 3872, 3904, 3936, 3968, 4000,
3648, 3680, 3712, 3744, 3776, 3808, 3840, 3872, 3904, 3936, 3968, 4032, 4064, 4096, 4128, 4160, 4192, 4224, 4256, 4288, 4320, 4352, 4384, 4416, 4448,
4000, 4032, 4064, 4096, 4128, 4160, 4192, 4224, 4256, 4288, 4320, 4480, 4512, 4544, 4576, 4608, 4640, 4672, 4704, 4736, 4768, 4800, 4832, 4864, 4896,
4352, 4384, 4416, 4448, 4480, 4512, 4544, 4576, 4608, 4640, 4672, 4928, 4960, 4992, 5024, 5056, 5088, 5120, 5152, 5184, 5216, 5248, 5280, 5312, 5344,
4704, 4736, 4768, 4800, 4832, 4864, 4896, 4928, 4960, 4992, 5024, 5376, 5408, 5440, 5472, 5504, 5536, 5568, 5600, 5632, 5664, 5696, 5728, 5760, 5792,
5056, 5088, 5120, 5152, 5184, 5216, 5248, 5280, 5312, 5344, 5376, 5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080, 6112, 6144, 6176, 6208, 6240,
5408, 5440, 5472, 5504, 5536, 5568, 5600, 5632, 5664, 5696, 5728, 6272, 6304, 6336, 6368, 6400, 6432, 6464, 6496, 6528, 6560, 6592, 6624, 6656, 6688,
5760, 5792, 5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080, 6720, 6752, 6784, 6816, 6848, 6880, 6912, 6944, 6976, 7008, 7040, 7072, 7104, 7136,
6112, 6144, 6176, 6208, 6240, 6272, 6304, 6336, 6368, 6400, 6432, 7168, 7200, 7232, 7264, 7296, 7328, 7360, 7392, 7424, 7456, 7488, 7520, 7552, 7584,
6464, 6496, 6528, 6560, 6592, 6624, 6656, 6688, 6720, 6752, 6784, 7616, 7648, 7680, 7712, 7744, 7776, 7808, 7840, 7872, 7904, 7936, 7968, 8000, 8032,
6816, 6848, 6880, 6912, 6944, 6976, 7008, 7040, 7072, 7104, 7136, 8064, 8096, 8128, 8160};
7168, 7200, 7232, 7264, 7296, 7328, 7360, 7392, 7424, 7456, 7488,
7520, 7552, 7584, 7616, 7648, 7680, 7712, 7744, 7776, 7808, 7840,
7872, 7904, 7936, 7968, 8000, 8032, 8064, 8096, 8128, 8160 };
#define Cr_R Cb_B #define Cr_R Cb_B
static INT16 Cr_G[] = { 0, -26, -53, -79, -106, -133, -160, -187, static INT16 Cr_G[] = {
-213, -240, -267, -294, -321, -347, -374, -401, -428, -455, -481, 0, -26, -53, -79, -106, -133, -160, -187, -213, -240, -267, -294,
-508, -535, -562, -589, -615, -642, -669, -696, -722, -749, -776, -321, -347, -374, -401, -428, -455, -481, -508, -535, -562, -589, -615,
-803, -830, -856, -883, -910, -937, -964, -990, -1017, -1044, -1071, -642, -669, -696, -722, -749, -776, -803, -830, -856, -883, -910, -937,
-1098, -1124, -1151, -1178, -1205, -1232, -1258, -1285, -1312, -1339, -964, -990, -1017, -1044, -1071, -1098, -1124, -1151, -1178, -1205, -1232, -1258,
-1366, -1392, -1419, -1446, -1473, -1500, -1526, -1553, -1580, -1607, -1285, -1312, -1339, -1366, -1392, -1419, -1446, -1473, -1500, -1526, -1553, -1580,
-1634, -1660, -1687, -1714, -1741, -1768, -1794, -1821, -1848, -1875, -1607, -1634, -1660, -1687, -1714, -1741, -1768, -1794, -1821, -1848, -1875, -1902,
-1902, -1928, -1955, -1982, -2009, -2036, -2062, -2089, -2116, -2143, -1928, -1955, -1982, -2009, -2036, -2062, -2089, -2116, -2143, -2169, -2196, -2223,
-2169, -2196, -2223, -2250, -2277, -2303, -2330, -2357, -2384, -2411, -2250, -2277, -2303, -2330, -2357, -2384, -2411, -2437, -2464, -2491, -2518, -2545,
-2437, -2464, -2491, -2518, -2545, -2571, -2598, -2625, -2652, -2679, -2571, -2598, -2625, -2652, -2679, -2705, -2732, -2759, -2786, -2813, -2839, -2866,
-2705, -2732, -2759, -2786, -2813, -2839, -2866, -2893, -2920, -2947, -2893, -2920, -2947, -2973, -3000, -3027, -3054, -3081, -3107, -3134, -3161, -3188,
-2973, -3000, -3027, -3054, -3081, -3107, -3134, -3161, -3188, -3215, -3215, -3241, -3268, -3295, -3322, -3349, -3375, -3402, -3429, -3456, -3483, -3509,
-3241, -3268, -3295, -3322, -3349, -3375, -3402, -3429, -3456, -3483, -3536, -3563, -3590, -3616, -3643, -3670, -3697, -3724, -3750, -3777, -3804, -3831,
-3509, -3536, -3563, -3590, -3616, -3643, -3670, -3697, -3724, -3750, -3858, -3884, -3911, -3938, -3965, -3992, -4018, -4045, -4072, -4099, -4126, -4152,
-3777, -3804, -3831, -3858, -3884, -3911, -3938, -3965, -3992, -4018, -4179, -4206, -4233, -4260, -4286, -4313, -4340, -4367, -4394, -4420, -4447, -4474,
-4045, -4072, -4099, -4126, -4152, -4179, -4206, -4233, -4260, -4286, -4501, -4528, -4554, -4581, -4608, -4635, -4662, -4688, -4715, -4742, -4769, -4796,
-4313, -4340, -4367, -4394, -4420, -4447, -4474, -4501, -4528, -4554, -4822, -4849, -4876, -4903, -4929, -4956, -4983, -5010, -5037, -5063, -5090, -5117,
-4581, -4608, -4635, -4662, -4688, -4715, -4742, -4769, -4796, -4822, -5144, -5171, -5197, -5224, -5251, -5278, -5305, -5331, -5358, -5385, -5412, -5439,
-4849, -4876, -4903, -4929, -4956, -4983, -5010, -5037, -5063, -5090, -5465, -5492, -5519, -5546, -5573, -5599, -5626, -5653, -5680, -5707, -5733, -5760,
-5117, -5144, -5171, -5197, -5224, -5251, -5278, -5305, -5331, -5358, -5787, -5814, -5841, -5867, -5894, -5921, -5948, -5975, -6001, -6028, -6055, -6082,
-5385, -5412, -5439, -5465, -5492, -5519, -5546, -5573, -5599, -5626, -6109, -6135, -6162, -6189, -6216, -6243, -6269, -6296, -6323, -6350, -6376, -6403,
-5653, -5680, -5707, -5733, -5760, -5787, -5814, -5841, -5867, -5894, -6430, -6457, -6484, -6510, -6537, -6564, -6591, -6618, -6644, -6671, -6698, -6725,
-5921, -5948, -5975, -6001, -6028, -6055, -6082, -6109, -6135, -6162, -6752, -6778, -6805, -6832};
-6189, -6216, -6243, -6269, -6296, -6323, -6350, -6376, -6403, -6430,
-6457, -6484, -6510, -6537, -6564, -6591, -6618, -6644, -6671, -6698,
-6725, -6752, -6778, -6805, -6832 };
static INT16 Cr_B[] = { 0, -4, -9, -15, -20, -25, -30, -35, -41, -46, static INT16 Cr_B[] = {
-51, -56, -61, -67, -72, -77, -82, -87, -93, -98, -103, -108, -113, 0, -4, -9, -15, -20, -25, -30, -35, -41, -46, -51, -56,
-119, -124, -129, -134, -140, -145, -150, -155, -160, -166, -171, -61, -67, -72, -77, -82, -87, -93, -98, -103, -108, -113, -119,
-176, -181, -186, -192, -197, -202, -207, -212, -218, -223, -228, -124, -129, -134, -140, -145, -150, -155, -160, -166, -171, -176, -181,
-233, -238, -244, -249, -254, -259, -264, -270, -275, -280, -285, -186, -192, -197, -202, -207, -212, -218, -223, -228, -233, -238, -244,
-290, -296, -301, -306, -311, -316, -322, -327, -332, -337, -342, -249, -254, -259, -264, -270, -275, -280, -285, -290, -296, -301, -306,
-348, -353, -358, -363, -368, -374, -379, -384, -389, -394, -400, -311, -316, -322, -327, -332, -337, -342, -348, -353, -358, -363, -368,
-405, -410, -415, -421, -426, -431, -436, -441, -447, -452, -457, -374, -379, -384, -389, -394, -400, -405, -410, -415, -421, -426, -431,
-462, -467, -473, -478, -483, -488, -493, -499, -504, -509, -514, -436, -441, -447, -452, -457, -462, -467, -473, -478, -483, -488, -493,
-519, -525, -530, -535, -540, -545, -551, -556, -561, -566, -571, -499, -504, -509, -514, -519, -525, -530, -535, -540, -545, -551, -556,
-577, -582, -587, -592, -597, -603, -608, -613, -618, -623, -629, -561, -566, -571, -577, -582, -587, -592, -597, -603, -608, -613, -618,
-634, -639, -644, -649, -655, -660, -665, -670, -675, -681, -686, -623, -629, -634, -639, -644, -649, -655, -660, -665, -670, -675, -681,
-691, -696, -702, -707, -712, -717, -722, -728, -733, -738, -743, -686, -691, -696, -702, -707, -712, -717, -722, -728, -733, -738, -743,
-748, -754, -759, -764, -769, -774, -780, -785, -790, -795, -800, -748, -754, -759, -764, -769, -774, -780, -785, -790, -795, -800, -806,
-806, -811, -816, -821, -826, -832, -837, -842, -847, -852, -858, -811, -816, -821, -826, -832, -837, -842, -847, -852, -858, -863, -868,
-863, -868, -873, -878, -884, -889, -894, -899, -904, -910, -915, -873, -878, -884, -889, -894, -899, -904, -910, -915, -920, -925, -930,
-920, -925, -930, -936, -941, -946, -951, -957, -962, -967, -972, -936, -941, -946, -951, -957, -962, -967, -972, -977, -983, -988, -993,
-977, -983, -988, -993, -998, -1003, -1009, -1014, -1019, -1024, -998, -1003, -1009, -1014, -1019, -1024, -1029, -1035, -1040, -1045, -1050, -1055,
-1029, -1035, -1040, -1045, -1050, -1055, -1061, -1066, -1071, -1076, -1061, -1066, -1071, -1076, -1081, -1087, -1092, -1097, -1102, -1107, -1113, -1118,
-1081, -1087, -1092, -1097, -1102, -1107, -1113, -1118, -1123, -1128, -1123, -1128, -1133, -1139, -1144, -1149, -1154, -1159, -1165, -1170, -1175, -1180,
-1133, -1139, -1144, -1149, -1154, -1159, -1165, -1170, -1175, -1180, -1185, -1191, -1196, -1201, -1206, -1211, -1217, -1222, -1227, -1232, -1238, -1243,
-1185, -1191, -1196, -1201, -1206, -1211, -1217, -1222, -1227, -1232, -1248, -1253, -1258, -1264, -1269, -1274, -1279, -1284, -1290, -1295, -1300, -1305,
-1238, -1243, -1248, -1253, -1258, -1264, -1269, -1274, -1279, -1284, -1310, -1316, -1321, -1326};
-1290, -1295, -1300, -1305, -1310, -1316, -1321, -1326 };
static INT16 R_Cr[] = { -11484, -11394, -11305, -11215, -11125, static INT16 R_Cr[] = {
-11036, -10946, -10856, -10766, -10677, -10587, -10497, -10407, -11484, -11394, -11305, -11215, -11125, -11036, -10946, -10856, -10766, -10677,
-10318, -10228, -10138, -10049, -9959, -9869, -9779, -9690, -9600, -10587, -10497, -10407, -10318, -10228, -10138, -10049, -9959, -9869, -9779,
-9510, -9420, -9331, -9241, -9151, -9062, -8972, -8882, -8792, -8703, -9690, -9600, -9510, -9420, -9331, -9241, -9151, -9062, -8972, -8882,
-8613, -8523, -8433, -8344, -8254, -8164, -8075, -7985, -7895, -7805, -8792, -8703, -8613, -8523, -8433, -8344, -8254, -8164, -8075, -7985,
-7716, -7626, -7536, -7446, -7357, -7267, -7177, -7088, -6998, -6908, -7895, -7805, -7716, -7626, -7536, -7446, -7357, -7267, -7177, -7088,
-6818, -6729, -6639, -6549, -6459, -6370, -6280, -6190, -6101, -6011, -6998, -6908, -6818, -6729, -6639, -6549, -6459, -6370, -6280, -6190,
-5921, -5831, -5742, -5652, -5562, -5472, -5383, -5293, -5203, -5113, -6101, -6011, -5921, -5831, -5742, -5652, -5562, -5472, -5383, -5293,
-5024, -4934, -4844, -4755, -4665, -4575, -4485, -4396, -4306, -4216, -5203, -5113, -5024, -4934, -4844, -4755, -4665, -4575, -4485, -4396,
-4126, -4037, -3947, -3857, -3768, -3678, -3588, -3498, -3409, -3319, -4306, -4216, -4126, -4037, -3947, -3857, -3768, -3678, -3588, -3498,
-3229, -3139, -3050, -2960, -2870, -2781, -2691, -2601, -2511, -2422, -3409, -3319, -3229, -3139, -3050, -2960, -2870, -2781, -2691, -2601,
-2332, -2242, -2152, -2063, -1973, -1883, -1794, -1704, -1614, -1524, -2511, -2422, -2332, -2242, -2152, -2063, -1973, -1883, -1794, -1704,
-1435, -1345, -1255, -1165, -1076, -986, -896, -807, -717, -627, -537, -1614, -1524, -1435, -1345, -1255, -1165, -1076, -986, -896, -807,
-448, -358, -268, -178, -89, 0, 90, 179, 269, 359, 449, 538, 628, 718, -717, -627, -537, -448, -358, -268, -178, -89, 0, 90,
808, 897, 987, 1077, 1166, 1256, 1346, 1436, 1525, 1615, 1705, 1795, 179, 269, 359, 449, 538, 628, 718, 808, 897, 987,
1884, 1974, 2064, 2153, 2243, 2333, 2423, 2512, 2602, 2692, 2782, 1077, 1166, 1256, 1346, 1436, 1525, 1615, 1705, 1795, 1884,
2871, 2961, 3051, 3140, 3230, 3320, 3410, 3499, 3589, 3679, 3769, 1974, 2064, 2153, 2243, 2333, 2423, 2512, 2602, 2692, 2782,
3858, 3948, 4038, 4127, 4217, 4307, 4397, 4486, 4576, 4666, 4756, 2871, 2961, 3051, 3140, 3230, 3320, 3410, 3499, 3589, 3679,
4845, 4935, 5025, 5114, 5204, 5294, 5384, 5473, 5563, 5653, 5743, 3769, 3858, 3948, 4038, 4127, 4217, 4307, 4397, 4486, 4576,
5832, 5922, 6012, 6102, 6191, 6281, 6371, 6460, 6550, 6640, 6730, 4666, 4756, 4845, 4935, 5025, 5114, 5204, 5294, 5384, 5473,
6819, 6909, 6999, 7089, 7178, 7268, 7358, 7447, 7537, 7627, 7717, 5563, 5653, 5743, 5832, 5922, 6012, 6102, 6191, 6281, 6371,
7806, 7896, 7986, 8076, 8165, 8255, 8345, 8434, 8524, 8614, 8704, 6460, 6550, 6640, 6730, 6819, 6909, 6999, 7089, 7178, 7268,
8793, 8883, 8973, 9063, 9152, 9242, 9332, 9421, 9511, 9601, 9691, 7358, 7447, 7537, 7627, 7717, 7806, 7896, 7986, 8076, 8165,
9780, 9870, 9960, 10050, 10139, 10229, 10319, 10408, 10498, 10588, 8255, 8345, 8434, 8524, 8614, 8704, 8793, 8883, 8973, 9063,
10678, 10767, 10857, 10947, 11037, 11126, 11216, 11306, 11395 }; 9152, 9242, 9332, 9421, 9511, 9601, 9691, 9780, 9870, 9960,
10050, 10139, 10229, 10319, 10408, 10498, 10588, 10678, 10767, 10857,
10947, 11037, 11126, 11216, 11306, 11395};
static INT16 G_Cb[] = { 2819, 2797, 2775, 2753, 2731, 2709, 2687, static INT16 G_Cb[] = {
2665, 2643, 2621, 2599, 2577, 2555, 2533, 2511, 2489, 2467, 2445, 2819, 2797, 2775, 2753, 2731, 2709, 2687, 2665, 2643, 2621, 2599, 2577,
2423, 2401, 2379, 2357, 2335, 2313, 2291, 2269, 2247, 2225, 2202, 2555, 2533, 2511, 2489, 2467, 2445, 2423, 2401, 2379, 2357, 2335, 2313,
2180, 2158, 2136, 2114, 2092, 2070, 2048, 2026, 2004, 1982, 1960, 2291, 2269, 2247, 2225, 2202, 2180, 2158, 2136, 2114, 2092, 2070, 2048,
1938, 1916, 1894, 1872, 1850, 1828, 1806, 1784, 1762, 1740, 1718, 2026, 2004, 1982, 1960, 1938, 1916, 1894, 1872, 1850, 1828, 1806, 1784,
1696, 1674, 1652, 1630, 1608, 1586, 1564, 1542, 1520, 1498, 1476, 1762, 1740, 1718, 1696, 1674, 1652, 1630, 1608, 1586, 1564, 1542, 1520,
1454, 1432, 1410, 1388, 1366, 1344, 1321, 1299, 1277, 1255, 1233, 1498, 1476, 1454, 1432, 1410, 1388, 1366, 1344, 1321, 1299, 1277, 1255,
1211, 1189, 1167, 1145, 1123, 1101, 1079, 1057, 1035, 1013, 991, 969, 1233, 1211, 1189, 1167, 1145, 1123, 1101, 1079, 1057, 1035, 1013, 991,
947, 925, 903, 881, 859, 837, 815, 793, 771, 749, 727, 705, 683, 661, 969, 947, 925, 903, 881, 859, 837, 815, 793, 771, 749, 727,
639, 617, 595, 573, 551, 529, 507, 485, 463, 440, 418, 396, 374, 352, 705, 683, 661, 639, 617, 595, 573, 551, 529, 507, 485, 463,
330, 308, 286, 264, 242, 220, 198, 176, 154, 132, 110, 88, 66, 44, 22, 440, 418, 396, 374, 352, 330, 308, 286, 264, 242, 220, 198,
0, -21, -43, -65, -87, -109, -131, -153, -175, -197, -219, -241, -263, 176, 154, 132, 110, 88, 66, 44, 22, 0, -21, -43, -65,
-285, -307, -329, -351, -373, -395, -417, -439, -462, -484, -506, -87, -109, -131, -153, -175, -197, -219, -241, -263, -285, -307, -329,
-528, -550, -572, -594, -616, -638, -660, -682, -704, -726, -748, -351, -373, -395, -417, -439, -462, -484, -506, -528, -550, -572, -594,
-770, -792, -814, -836, -858, -880, -902, -924, -946, -968, -990, -616, -638, -660, -682, -704, -726, -748, -770, -792, -814, -836, -858,
-1012, -1034, -1056, -1078, -1100, -1122, -1144, -1166, -1188, -1210, -880, -902, -924, -946, -968, -990, -1012, -1034, -1056, -1078, -1100, -1122,
-1232, -1254, -1276, -1298, -1320, -1343, -1365, -1387, -1409, -1431, -1144, -1166, -1188, -1210, -1232, -1254, -1276, -1298, -1320, -1343, -1365, -1387,
-1453, -1475, -1497, -1519, -1541, -1563, -1585, -1607, -1629, -1651, -1409, -1431, -1453, -1475, -1497, -1519, -1541, -1563, -1585, -1607, -1629, -1651,
-1673, -1695, -1717, -1739, -1761, -1783, -1805, -1827, -1849, -1871, -1673, -1695, -1717, -1739, -1761, -1783, -1805, -1827, -1849, -1871, -1893, -1915,
-1893, -1915, -1937, -1959, -1981, -2003, -2025, -2047, -2069, -2091, -1937, -1959, -1981, -2003, -2025, -2047, -2069, -2091, -2113, -2135, -2157, -2179,
-2113, -2135, -2157, -2179, -2201, -2224, -2246, -2268, -2290, -2312, -2201, -2224, -2246, -2268, -2290, -2312, -2334, -2356, -2378, -2400, -2422, -2444,
-2334, -2356, -2378, -2400, -2422, -2444, -2466, -2488, -2510, -2532, -2466, -2488, -2510, -2532, -2554, -2576, -2598, -2620, -2642, -2664, -2686, -2708,
-2554, -2576, -2598, -2620, -2642, -2664, -2686, -2708, -2730, -2752, -2730, -2752, -2774, -2796};
-2774, -2796 };
static INT16 G_Cr[] = { 5850, 5805, 5759, 5713, 5667, 5622, 5576, static INT16 G_Cr[] = {
5530, 5485, 5439, 5393, 5347, 5302, 5256, 5210, 5165, 5119, 5073, 5850, 5805, 5759, 5713, 5667, 5622, 5576, 5530, 5485, 5439, 5393, 5347,
5028, 4982, 4936, 4890, 4845, 4799, 4753, 4708, 4662, 4616, 4570, 5302, 5256, 5210, 5165, 5119, 5073, 5028, 4982, 4936, 4890, 4845, 4799,
4525, 4479, 4433, 4388, 4342, 4296, 4251, 4205, 4159, 4113, 4068, 4753, 4708, 4662, 4616, 4570, 4525, 4479, 4433, 4388, 4342, 4296, 4251,
4022, 3976, 3931, 3885, 3839, 3794, 3748, 3702, 3656, 3611, 3565, 4205, 4159, 4113, 4068, 4022, 3976, 3931, 3885, 3839, 3794, 3748, 3702,
3519, 3474, 3428, 3382, 3336, 3291, 3245, 3199, 3154, 3108, 3062, 3656, 3611, 3565, 3519, 3474, 3428, 3382, 3336, 3291, 3245, 3199, 3154,
3017, 2971, 2925, 2879, 2834, 2788, 2742, 2697, 2651, 2605, 2559, 3108, 3062, 3017, 2971, 2925, 2879, 2834, 2788, 2742, 2697, 2651, 2605,
2514, 2468, 2422, 2377, 2331, 2285, 2240, 2194, 2148, 2102, 2057, 2559, 2514, 2468, 2422, 2377, 2331, 2285, 2240, 2194, 2148, 2102, 2057,
2011, 1965, 1920, 1874, 1828, 1782, 1737, 1691, 1645, 1600, 1554, 2011, 1965, 1920, 1874, 1828, 1782, 1737, 1691, 1645, 1600, 1554, 1508,
1508, 1463, 1417, 1371, 1325, 1280, 1234, 1188, 1143, 1097, 1051, 1463, 1417, 1371, 1325, 1280, 1234, 1188, 1143, 1097, 1051, 1006, 960,
1006, 960, 914, 868, 823, 777, 731, 686, 640, 594, 548, 503, 457, 411, 914, 868, 823, 777, 731, 686, 640, 594, 548, 503, 457, 411,
366, 320, 274, 229, 183, 137, 91, 46, 0, -45, -90, -136, -182, -228, 366, 320, 274, 229, 183, 137, 91, 46, 0, -45, -90, -136,
-273, -319, -365, -410, -456, -502, -547, -593, -639, -685, -730, -182, -228, -273, -319, -365, -410, -456, -502, -547, -593, -639, -685,
-776, -822, -867, -913, -959, -1005, -1050, -1096, -1142, -1187, -730, -776, -822, -867, -913, -959, -1005, -1050, -1096, -1142, -1187, -1233,
-1233, -1279, -1324, -1370, -1416, -1462, -1507, -1553, -1599, -1644, -1279, -1324, -1370, -1416, -1462, -1507, -1553, -1599, -1644, -1690, -1736, -1781,
-1690, -1736, -1781, -1827, -1873, -1919, -1964, -2010, -2056, -2101, -1827, -1873, -1919, -1964, -2010, -2056, -2101, -2147, -2193, -2239, -2284, -2330,
-2147, -2193, -2239, -2284, -2330, -2376, -2421, -2467, -2513, -2558, -2376, -2421, -2467, -2513, -2558, -2604, -2650, -2696, -2741, -2787, -2833, -2878,
-2604, -2650, -2696, -2741, -2787, -2833, -2878, -2924, -2970, -3016, -2924, -2970, -3016, -3061, -3107, -3153, -3198, -3244, -3290, -3335, -3381, -3427,
-3061, -3107, -3153, -3198, -3244, -3290, -3335, -3381, -3427, -3473, -3473, -3518, -3564, -3610, -3655, -3701, -3747, -3793, -3838, -3884, -3930, -3975,
-3518, -3564, -3610, -3655, -3701, -3747, -3793, -3838, -3884, -3930, -4021, -4067, -4112, -4158, -4204, -4250, -4295, -4341, -4387, -4432, -4478, -4524,
-3975, -4021, -4067, -4112, -4158, -4204, -4250, -4295, -4341, -4387, -4569, -4615, -4661, -4707, -4752, -4798, -4844, -4889, -4935, -4981, -5027, -5072,
-4432, -4478, -4524, -4569, -4615, -4661, -4707, -4752, -4798, -4844, -5118, -5164, -5209, -5255, -5301, -5346, -5392, -5438, -5484, -5529, -5575, -5621,
-4889, -4935, -4981, -5027, -5072, -5118, -5164, -5209, -5255, -5301, -5666, -5712, -5758, -5804};
-5346, -5392, -5438, -5484, -5529, -5575, -5621, -5666, -5712, -5758,
-5804 };
static INT16 B_Cb[] = { -14515, -14402, -14288, -14175, -14062,
-13948, -13835, -13721, -13608, -13495, -13381, -13268, -13154,
-13041, -12928, -12814, -12701, -12587, -12474, -12360, -12247,
-12134, -12020, -11907, -11793, -11680, -11567, -11453, -11340,
-11226, -11113, -11000, -10886, -10773, -10659, -10546, -10433,
-10319, -10206, -10092, -9979, -9865, -9752, -9639, -9525, -9412,
-9298, -9185, -9072, -8958, -8845, -8731, -8618, -8505, -8391, -8278,
-8164, -8051, -7938, -7824, -7711, -7597, -7484, -7371, -7257, -7144,
-7030, -6917, -6803, -6690, -6577, -6463, -6350, -6236, -6123, -6010,
-5896, -5783, -5669, -5556, -5443, -5329, -5216, -5102, -4989, -4876,
-4762, -4649, -4535, -4422, -4309, -4195, -4082, -3968, -3855, -3741,
-3628, -3515, -3401, -3288, -3174, -3061, -2948, -2834, -2721, -2607,
-2494, -2381, -2267, -2154, -2040, -1927, -1814, -1700, -1587, -1473,
-1360, -1246, -1133, -1020, -906, -793, -679, -566, -453, -339, -226,
-112, 0, 113, 227, 340, 454, 567, 680, 794, 907, 1021, 1134, 1247,
1361, 1474, 1588, 1701, 1815, 1928, 2041, 2155, 2268, 2382, 2495,
2608, 2722, 2835, 2949, 3062, 3175, 3289, 3402, 3516, 3629, 3742,
3856, 3969, 4083, 4196, 4310, 4423, 4536, 4650, 4763, 4877, 4990,
5103, 5217, 5330, 5444, 5557, 5670, 5784, 5897, 6011, 6124, 6237,
6351, 6464, 6578, 6691, 6804, 6918, 7031, 7145, 7258, 7372, 7485,
7598, 7712, 7825, 7939, 8052, 8165, 8279, 8392, 8506, 8619, 8732,
8846, 8959, 9073, 9186, 9299, 9413, 9526, 9640, 9753, 9866, 9980,
10093, 10207, 10320, 10434, 10547, 10660, 10774, 10887, 11001, 11114,
11227, 11341, 11454, 11568, 11681, 11794, 11908, 12021, 12135, 12248,
12361, 12475, 12588, 12702, 12815, 12929, 13042, 13155, 13269, 13382,
13496, 13609, 13722, 13836, 13949, 14063, 14176, 14289, 14403 };
static INT16 B_Cb[] = {
-14515, -14402, -14288, -14175, -14062, -13948, -13835, -13721, -13608, -13495,
-13381, -13268, -13154, -13041, -12928, -12814, -12701, -12587, -12474, -12360,
-12247, -12134, -12020, -11907, -11793, -11680, -11567, -11453, -11340, -11226,
-11113, -11000, -10886, -10773, -10659, -10546, -10433, -10319, -10206, -10092,
-9979, -9865, -9752, -9639, -9525, -9412, -9298, -9185, -9072, -8958,
-8845, -8731, -8618, -8505, -8391, -8278, -8164, -8051, -7938, -7824,
-7711, -7597, -7484, -7371, -7257, -7144, -7030, -6917, -6803, -6690,
-6577, -6463, -6350, -6236, -6123, -6010, -5896, -5783, -5669, -5556,
-5443, -5329, -5216, -5102, -4989, -4876, -4762, -4649, -4535, -4422,
-4309, -4195, -4082, -3968, -3855, -3741, -3628, -3515, -3401, -3288,
-3174, -3061, -2948, -2834, -2721, -2607, -2494, -2381, -2267, -2154,
-2040, -1927, -1814, -1700, -1587, -1473, -1360, -1246, -1133, -1020,
-906, -793, -679, -566, -453, -339, -226, -112, 0, 113,
227, 340, 454, 567, 680, 794, 907, 1021, 1134, 1247,
1361, 1474, 1588, 1701, 1815, 1928, 2041, 2155, 2268, 2382,
2495, 2608, 2722, 2835, 2949, 3062, 3175, 3289, 3402, 3516,
3629, 3742, 3856, 3969, 4083, 4196, 4310, 4423, 4536, 4650,
4763, 4877, 4990, 5103, 5217, 5330, 5444, 5557, 5670, 5784,
5897, 6011, 6124, 6237, 6351, 6464, 6578, 6691, 6804, 6918,
7031, 7145, 7258, 7372, 7485, 7598, 7712, 7825, 7939, 8052,
8165, 8279, 8392, 8506, 8619, 8732, 8846, 8959, 9073, 9186,
9299, 9413, 9526, 9640, 9753, 9866, 9980, 10093, 10207, 10320,
10434, 10547, 10660, 10774, 10887, 11001, 11114, 11227, 11341, 11454,
11568, 11681, 11794, 11908, 12021, 12135, 12248, 12361, 12475, 12588,
12702, 12815, 12929, 13042, 13155, 13269, 13382, 13496, 13609, 13722,
13836, 13949, 14063, 14176, 14289, 14403};
void void
ImagingConvertRGB2YCbCr(UINT8* out, const UINT8* in, int pixels) ImagingConvertRGB2YCbCr(UINT8 *out, const UINT8 *in, int pixels) {
{
int x;
UINT8 a;
int r, g, b;
int y, cr, cb;
for (x = 0; x < pixels; x++, in +=4, out += 4) {
r = in[0];
g = in[1];
b = in[2];
a = in[3];
y = (Y_R[r] + Y_G[g] + Y_B[b]) >> SCALE;
cb = ((Cb_R[r] + Cb_G[g] + Cb_B[b]) >> SCALE) + 128;
cr = ((Cr_R[r] + Cr_G[g] + Cr_B[b]) >> SCALE) + 128;
out[0] = (UINT8) y;
out[1] = (UINT8) cb;
out[2] = (UINT8) cr;
out[3] = a;
}
}
void
ImagingConvertYCbCr2RGB(UINT8* out, const UINT8* in, int pixels)
{
int x; int x;
UINT8 a; UINT8 a;
int r, g, b; int r, g, b;
int y, cr, cb; int y, cr, cb;
for (x = 0; x < pixels; x++, in += 4, out += 4) { for (x = 0; x < pixels; x++, in += 4, out += 4) {
r = in[0];
g = in[1];
b = in[2];
a = in[3];
y = (Y_R[r] + Y_G[g] + Y_B[b]) >> SCALE;
cb = ((Cb_R[r] + Cb_G[g] + Cb_B[b]) >> SCALE) + 128;
cr = ((Cr_R[r] + Cr_G[g] + Cr_B[b]) >> SCALE) + 128;
out[0] = (UINT8)y;
out[1] = (UINT8)cb;
out[2] = (UINT8)cr;
out[3] = a;
}
}
void
ImagingConvertYCbCr2RGB(UINT8 *out, const UINT8 *in, int pixels) {
int x;
UINT8 a;
int r, g, b;
int y, cr, cb;
for (x = 0; x < pixels; x++, in += 4, out += 4) {
y = in[0]; y = in[0];
cb = in[1]; cb = in[1];
cr = in[2]; cr = in[2];
a = in[3]; a = in[3];
r = y + (( R_Cr[cr]) >> SCALE); r = y + ((R_Cr[cr]) >> SCALE);
g = y + ((G_Cb[cb] + G_Cr[cr]) >> SCALE); g = y + ((G_Cb[cb] + G_Cr[cr]) >> SCALE);
b = y + ((B_Cb[cb] ) >> SCALE); b = y + ((B_Cb[cb]) >> SCALE);
out[0] = (r <= 0) ? 0 : (r >= 255) ? 255 : r; out[0] = (r <= 0) ? 0 : (r >= 255) ? 255 : r;
out[1] = (g <= 0) ? 0 : (g >= 255) ? 255 : g; out[1] = (g <= 0) ? 0 : (g >= 255) ? 255 : g;

View File

@ -15,18 +15,15 @@
* See the README file for details on usage and redistribution. * See the README file for details on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
static Imaging static Imaging
_copy(Imaging imOut, Imaging imIn) _copy(Imaging imOut, Imaging imIn) {
{
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
int y; int y;
if (!imIn) { if (!imIn) {
return (Imaging) ImagingError_ValueError(NULL); return (Imaging)ImagingError_ValueError(NULL);
} }
imOut = ImagingNew2Dirty(imIn->mode, imOut, imIn); imOut = ImagingNew2Dirty(imIn->mode, imOut, imIn);
@ -50,13 +47,11 @@ _copy(Imaging imOut, Imaging imIn)
} }
Imaging Imaging
ImagingCopy(Imaging imIn) ImagingCopy(Imaging imIn) {
{
return _copy(NULL, imIn); return _copy(NULL, imIn);
} }
Imaging Imaging
ImagingCopy2(Imaging imOut, Imaging imIn) ImagingCopy2(Imaging imOut, Imaging imIn) {
{
return _copy(imOut, imIn); return _copy(imOut, imIn);
} }

View File

@ -15,20 +15,17 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
Imaging Imaging
ImagingCrop(Imaging imIn, int sx0, int sy0, int sx1, int sy1) ImagingCrop(Imaging imIn, int sx0, int sy0, int sx1, int sy1) {
{
Imaging imOut; Imaging imOut;
int xsize, ysize; int xsize, ysize;
int dx0, dy0, dx1, dy1; int dx0, dy0, dx1, dy1;
INT32 zero = 0; INT32 zero = 0;
if (!imIn) { if (!imIn) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
xsize = sx1 - sx0; xsize = sx1 - sx0;
@ -48,7 +45,7 @@ ImagingCrop(Imaging imIn, int sx0, int sy0, int sx1, int sy1)
ImagingCopyPalette(imOut, imIn); ImagingCopyPalette(imOut, imIn);
if (sx0 < 0 || sy0 < 0 || sx1 > imIn->xsize || sy1 > imIn->ysize) { if (sx0 < 0 || sy0 < 0 || sx1 > imIn->xsize || sy1 > imIn->ysize) {
(void) ImagingFill(imOut, &zero); (void)ImagingFill(imOut, &zero);
} }
dx0 = -sx0; dx0 = -sx0;

View File

@ -19,21 +19,18 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#ifdef _WIN32 #ifdef _WIN32
#include "ImDib.h" #include "ImDib.h"
char *
char* ImagingGetModeDIB(int size_out[2]) {
ImagingGetModeDIB(int size_out[2])
{
/* Get device characteristics */ /* Get device characteristics */
HDC dc; HDC dc;
char* mode; char *mode;
dc = CreateCompatibleDC(NULL); dc = CreateCompatibleDC(NULL);
@ -55,10 +52,8 @@ ImagingGetModeDIB(int size_out[2])
return mode; return mode;
} }
ImagingDIB ImagingDIB
ImagingNewDIB(const char *mode, int xsize, int ysize) ImagingNewDIB(const char *mode, int xsize, int ysize) {
{
/* Create a Windows bitmap */ /* Create a Windows bitmap */
ImagingDIB dib; ImagingDIB dib;
@ -66,23 +61,21 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
int i; int i;
/* Check mode */ /* Check mode */
if (strcmp(mode, "1") != 0 && strcmp(mode, "L") != 0 && if (strcmp(mode, "1") != 0 && strcmp(mode, "L") != 0 && strcmp(mode, "RGB") != 0) {
strcmp(mode, "RGB") != 0) { return (ImagingDIB)ImagingError_ModeError();
return (ImagingDIB) ImagingError_ModeError();
} }
/* Create DIB context and info header */ /* Create DIB context and info header */
/* malloc check ok, small constant allocation */ /* malloc check ok, small constant allocation */
dib = (ImagingDIB) malloc(sizeof(*dib)); dib = (ImagingDIB)malloc(sizeof(*dib));
if (!dib) { if (!dib) {
return (ImagingDIB) ImagingError_MemoryError(); return (ImagingDIB)ImagingError_MemoryError();
} }
/* malloc check ok, small constant allocation */ /* malloc check ok, small constant allocation */
dib->info = (BITMAPINFO*) malloc(sizeof(BITMAPINFOHEADER) + dib->info = (BITMAPINFO *)malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
256 * sizeof(RGBQUAD));
if (!dib->info) { if (!dib->info) {
free(dib); free(dib);
return (ImagingDIB) ImagingError_MemoryError(); return (ImagingDIB)ImagingError_MemoryError();
} }
memset(dib->info, 0, sizeof(BITMAPINFOHEADER)); memset(dib->info, 0, sizeof(BITMAPINFOHEADER));
@ -90,7 +83,7 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
dib->info->bmiHeader.biWidth = xsize; dib->info->bmiHeader.biWidth = xsize;
dib->info->bmiHeader.biHeight = ysize; dib->info->bmiHeader.biHeight = ysize;
dib->info->bmiHeader.biPlanes = 1; dib->info->bmiHeader.biPlanes = 1;
dib->info->bmiHeader.biBitCount = strlen(mode)*8; dib->info->bmiHeader.biBitCount = strlen(mode) * 8;
dib->info->bmiHeader.biCompression = BI_RGB; dib->info->bmiHeader.biCompression = BI_RGB;
/* Create DIB */ /* Create DIB */
@ -98,15 +91,15 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
if (!dib->dc) { if (!dib->dc) {
free(dib->info); free(dib->info);
free(dib); free(dib);
return (ImagingDIB) ImagingError_MemoryError(); return (ImagingDIB)ImagingError_MemoryError();
} }
dib->bitmap = CreateDIBSection(dib->dc, dib->info, DIB_RGB_COLORS, dib->bitmap =
&dib->bits, NULL, 0); CreateDIBSection(dib->dc, dib->info, DIB_RGB_COLORS, &dib->bits, NULL, 0);
if (!dib->bitmap) { if (!dib->bitmap) {
free(dib->info); free(dib->info);
free(dib); free(dib);
return (ImagingDIB) ImagingError_MemoryError(); return (ImagingDIB)ImagingError_MemoryError();
} }
strcpy(dib->mode, mode); strcpy(dib->mode, mode);
@ -117,7 +110,7 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
dib->linesize = (xsize * dib->pixelsize + 3) & -4; dib->linesize = (xsize * dib->pixelsize + 3) & -4;
if (dib->pixelsize == 1) { if (dib->pixelsize == 1) {
dib->pack = dib->unpack = (ImagingShuffler) memcpy; dib->pack = dib->unpack = (ImagingShuffler)memcpy;
} else { } else {
dib->pack = ImagingPackBGR; dib->pack = ImagingPackBGR;
dib->unpack = ImagingPackBGR; dib->unpack = ImagingPackBGR;
@ -131,9 +124,7 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
/* Bind a palette to it as well (only required for 8-bit DIBs) */ /* Bind a palette to it as well (only required for 8-bit DIBs) */
if (dib->pixelsize == 1) { if (dib->pixelsize == 1) {
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
palette[i].rgbRed = palette[i].rgbRed = palette[i].rgbGreen = palette[i].rgbBlue = i;
palette[i].rgbGreen =
palette[i].rgbBlue = i;
palette[i].rgbReserved = 0; palette[i].rgbReserved = 0;
} }
SetDIBColorTable(dib->dc, 0, 256, palette); SetDIBColorTable(dib->dc, 0, 256, palette);
@ -141,9 +132,8 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
/* Create an associated palette (for 8-bit displays only) */ /* Create an associated palette (for 8-bit displays only) */
if (strcmp(ImagingGetModeDIB(NULL), "P") == 0) { if (strcmp(ImagingGetModeDIB(NULL), "P") == 0) {
char palbuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];
char palbuf[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)]; LPLOGPALETTE pal = (LPLOGPALETTE)palbuf;
LPLOGPALETTE pal = (LPLOGPALETTE) palbuf;
int i, r, g, b; int i, r, g, b;
/* Load system palette */ /* Load system palette */
@ -152,7 +142,6 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry); GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry);
if (strcmp(mode, "L") == 0) { if (strcmp(mode, "L") == 0) {
/* Greyscale DIB. Fill all 236 slots with a greyscale ramp /* Greyscale DIB. Fill all 236 slots with a greyscale ramp
* (this is usually overkill on Windows since VGA only offers * (this is usually overkill on Windows since VGA only offers
* 6 bits greyscale resolution). Ignore the slots already * 6 bits greyscale resolution). Ignore the slots already
@ -160,16 +149,14 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
i = 10; i = 10;
for (r = 0; r < 236; r++) { for (r = 0; r < 236; r++) {
pal->palPalEntry[i].peRed = pal->palPalEntry[i].peRed = pal->palPalEntry[i].peGreen =
pal->palPalEntry[i].peGreen = pal->palPalEntry[i].peBlue = i;
pal->palPalEntry[i].peBlue = i;
i++; i++;
} }
dib->palette = CreatePalette(pal); dib->palette = CreatePalette(pal);
} else if (strcmp(mode, "RGB") == 0) { } else if (strcmp(mode, "RGB") == 0) {
#ifdef CUBE216 #ifdef CUBE216
/* Colour DIB. Create a 6x6x6 colour cube (216 entries) and /* Colour DIB. Create a 6x6x6 colour cube (216 entries) and
@ -187,11 +174,10 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
} }
} }
} }
for (r = 1; r < 22-1; r++) { for (r = 1; r < 22 - 1; r++) {
/* Black and white are already provided by the cube. */ /* Black and white are already provided by the cube. */
pal->palPalEntry[i].peRed = pal->palPalEntry[i].peRed = pal->palPalEntry[i].peGreen =
pal->palPalEntry[i].peGreen = pal->palPalEntry[i].peBlue = r * 255 / (22 - 1);
pal->palPalEntry[i].peBlue = r * 255 / (22-1);
i++; i++;
} }
@ -214,76 +200,91 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
#endif #endif
dib->palette = CreatePalette(pal); dib->palette = CreatePalette(pal);
} }
} }
return dib; return dib;
} }
void void
ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4]) ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4]) {
{
/* Paste image data into a bitmap */ /* Paste image data into a bitmap */
/* FIXME: check size! */ /* FIXME: check size! */
int y; int y;
for (y = 0; y < im->ysize; y++) { for (y = 0; y < im->ysize; y++) {
dib->pack(dib->bits + dib->linesize*(dib->ysize-(xy[1]+y)-1) + dib->pack(
xy[0]*dib->pixelsize, im->image[y], im->xsize); dib->bits + dib->linesize * (dib->ysize - (xy[1] + y) - 1) +
xy[0] * dib->pixelsize,
im->image[y],
im->xsize);
} }
} }
void void
ImagingExposeDIB(ImagingDIB dib, void *dc) ImagingExposeDIB(ImagingDIB dib, void *dc) {
{
/* Copy bitmap to display */ /* Copy bitmap to display */
if (dib->palette != 0) { if (dib->palette != 0) {
SelectPalette((HDC) dc, dib->palette, FALSE); SelectPalette((HDC)dc, dib->palette, FALSE);
} }
BitBlt((HDC) dc, 0, 0, dib->xsize, dib->ysize, dib->dc, 0, 0, SRCCOPY); BitBlt((HDC)dc, 0, 0, dib->xsize, dib->ysize, dib->dc, 0, 0, SRCCOPY);
} }
void void
ImagingDrawDIB(ImagingDIB dib, void *dc, int dst[4], int src[4]) ImagingDrawDIB(ImagingDIB dib, void *dc, int dst[4], int src[4]) {
{
/* Copy bitmap to printer/display */ /* Copy bitmap to printer/display */
if (GetDeviceCaps((HDC) dc, RASTERCAPS) & RC_STRETCHDIB) { if (GetDeviceCaps((HDC)dc, RASTERCAPS) & RC_STRETCHDIB) {
/* stretchdib (printers) */ /* stretchdib (printers) */
StretchDIBits((HDC) dc, dst[0], dst[1], dst[2]-dst[0], dst[3]-dst[1], StretchDIBits(
src[0], src[1], src[2]-src[0], src[3]-src[1], dib->bits, (HDC)dc,
dib->info, DIB_RGB_COLORS, SRCCOPY); dst[0],
dst[1],
dst[2] - dst[0],
dst[3] - dst[1],
src[0],
src[1],
src[2] - src[0],
src[3] - src[1],
dib->bits,
dib->info,
DIB_RGB_COLORS,
SRCCOPY);
} else { } else {
/* stretchblt (displays) */ /* stretchblt (displays) */
if (dib->palette != 0) { if (dib->palette != 0) {
SelectPalette((HDC) dc, dib->palette, FALSE); SelectPalette((HDC)dc, dib->palette, FALSE);
} }
StretchBlt((HDC) dc, dst[0], dst[1], dst[2]-dst[0], dst[3]-dst[1], StretchBlt(
dib->dc, src[0], src[1], src[2]-src[0], src[3]-src[1], (HDC)dc,
SRCCOPY); dst[0],
dst[1],
dst[2] - dst[0],
dst[3] - dst[1],
dib->dc,
src[0],
src[1],
src[2] - src[0],
src[3] - src[1],
SRCCOPY);
} }
} }
int int
ImagingQueryPaletteDIB(ImagingDIB dib, void *dc) ImagingQueryPaletteDIB(ImagingDIB dib, void *dc) {
{
/* Install bitmap palette */ /* Install bitmap palette */
int n; int n;
if (dib->palette != 0) { if (dib->palette != 0) {
/* Realize associated palette */ /* Realize associated palette */
HPALETTE now = SelectPalette((HDC) dc, dib->palette, FALSE); HPALETTE now = SelectPalette((HDC)dc, dib->palette, FALSE);
n = RealizePalette((HDC) dc); n = RealizePalette((HDC)dc);
/* Restore palette */ /* Restore palette */
SelectPalette((HDC) dc, now, FALSE); SelectPalette((HDC)dc, now, FALSE);
} else { } else {
n = 0; n = 0;
@ -293,8 +294,7 @@ ImagingQueryPaletteDIB(ImagingDIB dib, void *dc)
} }
void void
ImagingDeleteDIB(ImagingDIB dib) ImagingDeleteDIB(ImagingDIB dib) {
{
/* Clean up */ /* Clean up */
if (dib->palette) { if (dib->palette) {

File diff suppressed because it is too large Load Diff

View File

@ -15,14 +15,12 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#include <math.h> #include <math.h>
Imaging Imaging
ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality) ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality) {
{
/* Generate a Mandelbrot set covering the given extent */ /* Generate a Mandelbrot set covering the given extent */
Imaging im; Imaging im;
@ -32,10 +30,10 @@ ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality)
double dr, di; double dr, di;
/* Check arguments */ /* Check arguments */
width = extent[2] - extent[0]; width = extent[2] - extent[0];
height = extent[3] - extent[1]; height = extent[3] - extent[1];
if (width < 0.0 || height < 0.0 || quality < 2) { if (width < 0.0 || height < 0.0 || quality < 2) {
return (Imaging) ImagingError_ValueError(NULL); return (Imaging)ImagingError_ValueError(NULL);
} }
im = ImagingNewDirty("L", xsize, ysize); im = ImagingNewDirty("L", xsize, ysize);
@ -43,24 +41,24 @@ ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality)
return NULL; return NULL;
} }
dr = width/(xsize-1); dr = width / (xsize - 1);
di = height/(ysize-1); di = height / (ysize - 1);
radius = 100.0; radius = 100.0;
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
UINT8* buf = im->image8[y]; UINT8 *buf = im->image8[y];
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
x1 = y1 = xi2 = yi2 = 0.0; x1 = y1 = xi2 = yi2 = 0.0;
cr = x*dr + extent[0]; cr = x * dr + extent[0];
ci = y*di + extent[1]; ci = y * di + extent[1];
for (k = 1;; k++) { for (k = 1;; k++) {
y1 = 2*x1*y1 + ci; y1 = 2 * x1 * y1 + ci;
x1 = xi2 - yi2 + cr; x1 = xi2 - yi2 + cr;
xi2 = x1*x1; xi2 = x1 * x1;
yi2 = y1*y1; yi2 = y1 * y1;
if ((xi2 + yi2) > radius) { if ((xi2 + yi2) > radius) {
buf[x] = k*255/quality; buf[x] = k * 255 / quality;
break; break;
} }
if (k > quality) { if (k > quality) {
@ -74,8 +72,7 @@ ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality)
} }
Imaging Imaging
ImagingEffectNoise(int xsize, int ysize, float sigma) ImagingEffectNoise(int xsize, int ysize, float sigma) {
{
/* Generate Gaussian noise centered around 128 */ /* Generate Gaussian noise centered around 128 */
Imaging imOut; Imaging imOut;
@ -92,7 +89,7 @@ ImagingEffectNoise(int xsize, int ysize, float sigma)
nextok = 0; nextok = 0;
for (y = 0; y < imOut->ysize; y++) { for (y = 0; y < imOut->ysize; y++) {
UINT8* out = imOut->image8[y]; UINT8 *out = imOut->image8[y];
for (x = 0; x < imOut->xsize; x++) { for (x = 0; x < imOut->xsize; x++) {
if (nextok) { if (nextok) {
this = next; this = next;
@ -101,11 +98,11 @@ ImagingEffectNoise(int xsize, int ysize, float sigma)
/* after numerical recipes */ /* after numerical recipes */
double v1, v2, radius, factor; double v1, v2, radius, factor;
do { do {
v1 = rand()*(2.0/RAND_MAX) - 1.0; v1 = rand() * (2.0 / RAND_MAX) - 1.0;
v2 = rand()*(2.0/RAND_MAX) - 1.0; v2 = rand() * (2.0 / RAND_MAX) - 1.0;
radius= v1*v1 + v2*v2; radius = v1 * v1 + v2 * v2;
} while (radius >= 1.0); } while (radius >= 1.0);
factor = sqrt(-2.0*log(radius)/radius); factor = sqrt(-2.0 * log(radius) / radius);
this = factor * v1; this = factor * v1;
next = factor * v2; next = factor * v2;
} }
@ -117,8 +114,7 @@ ImagingEffectNoise(int xsize, int ysize, float sigma)
} }
Imaging Imaging
ImagingEffectSpread(Imaging imIn, int distance) ImagingEffectSpread(Imaging imIn, int distance) {
{
/* Randomly spread pixels in an image */ /* Randomly spread pixels in an image */
Imaging imOut; Imaging imOut;
@ -130,26 +126,26 @@ ImagingEffectSpread(Imaging imIn, int distance)
return NULL; return NULL;
} }
#define SPREAD(type, image)\ #define SPREAD(type, image) \
if (distance == 0) {\ if (distance == 0) { \
for (y = 0; y < imOut->ysize; y++) {\ for (y = 0; y < imOut->ysize; y++) { \
for (x = 0; x < imOut->xsize; x++) {\ for (x = 0; x < imOut->xsize; x++) { \
imOut->image[y][x] = imIn->image[y][x];\ imOut->image[y][x] = imIn->image[y][x]; \
}\ } \
}\ } \
} else {\ } else { \
for (y = 0; y < imOut->ysize; y++) {\ for (y = 0; y < imOut->ysize; y++) { \
for (x = 0; x < imOut->xsize; x++) {\ for (x = 0; x < imOut->xsize; x++) { \
int xx = x + (rand() % distance) - distance/2;\ int xx = x + (rand() % distance) - distance / 2; \
int yy = y + (rand() % distance) - distance/2;\ int yy = y + (rand() % distance) - distance / 2; \
if (xx >= 0 && xx < imIn->xsize && yy >= 0 && yy < imIn->ysize) {\ if (xx >= 0 && xx < imIn->xsize && yy >= 0 && yy < imIn->ysize) { \
imOut->image[yy][xx] = imIn->image[y][x];\ imOut->image[yy][xx] = imIn->image[y][x]; \
imOut->image[y][x] = imIn->image[yy][xx];\ imOut->image[y][x] = imIn->image[yy][xx]; \
} else {\ } else { \
imOut->image[y][x] = imIn->image[y][x];\ imOut->image[y][x] = imIn->image[y][x]; \
}\ } \
}\ } \
}\ } \
} }
if (imIn->image8) { if (imIn->image8) {

View File

@ -17,28 +17,24 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
int int
ImagingEpsEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) ImagingEpsEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
{ enum { HEXBYTE = 1, NEWLINE };
enum { HEXBYTE=1, NEWLINE };
const char *hex = "0123456789abcdef"; const char *hex = "0123456789abcdef";
UINT8* ptr = buf; UINT8 *ptr = buf;
UINT8* in, i; UINT8 *in, i;
if (!state->state) { if (!state->state) {
state->state = HEXBYTE; state->state = HEXBYTE;
state->xsize *= im->pixelsize; /* Hack! */ state->xsize *= im->pixelsize; /* Hack! */
} }
in = (UINT8*) im->image[state->y]; in = (UINT8 *)im->image[state->y];
for (;;) { for (;;) {
if (state->state == NEWLINE) { if (state->state == NEWLINE) {
if (bytes < 1) { if (bytes < 1) {
break; break;
@ -53,8 +49,8 @@ ImagingEpsEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
} }
i = in[state->x++]; i = in[state->x++];
*ptr++ = hex[(i>>4)&15]; *ptr++ = hex[(i >> 4) & 15];
*ptr++ = hex[i&15]; *ptr++ = hex[i & 15];
bytes -= 2; bytes -= 2;
/* Skip junk bytes */ /* Skip junk bytes */
@ -62,7 +58,7 @@ ImagingEpsEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
state->x++; state->x++;
} }
if (++state->count >= 79/2) { if (++state->count >= 79 / 2) {
state->state = NEWLINE; state->state = NEWLINE;
state->count = 0; state->count = 0;
} }
@ -73,11 +69,9 @@ ImagingEpsEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
state->errcode = IMAGING_CODEC_END; state->errcode = IMAGING_CODEC_END;
break; break;
} }
in = (UINT8*) im->image[state->y]; in = (UINT8 *)im->image[state->y];
} }
} }
return ptr - buf; return ptr - buf;
} }

View File

@ -19,41 +19,34 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
/* exception state */ /* exception state */
void * void *
ImagingError_OSError(void) ImagingError_OSError(void) {
{
fprintf(stderr, "*** exception: file access error\n"); fprintf(stderr, "*** exception: file access error\n");
return NULL; return NULL;
} }
void * void *
ImagingError_MemoryError(void) ImagingError_MemoryError(void) {
{
fprintf(stderr, "*** exception: out of memory\n"); fprintf(stderr, "*** exception: out of memory\n");
return NULL; return NULL;
} }
void * void *
ImagingError_ModeError(void) ImagingError_ModeError(void) {
{
return ImagingError_ValueError("bad image mode"); return ImagingError_ValueError("bad image mode");
} }
void * void *
ImagingError_Mismatch(void) ImagingError_Mismatch(void) {
{
return ImagingError_ValueError("images don't match"); return ImagingError_ValueError("images don't match");
} }
void * void *
ImagingError_ValueError(const char *message) ImagingError_ValueError(const char *message) {
{
if (!message) { if (!message) {
message = "exception: bad argument to function"; message = "exception: bad argument to function";
} }
@ -62,21 +55,18 @@ ImagingError_ValueError(const char *message)
} }
void void
ImagingError_Clear(void) ImagingError_Clear(void) {
{
/* nop */; /* nop */;
} }
/* thread state */ /* thread state */
void void
ImagingSectionEnter(ImagingSectionCookie* cookie) ImagingSectionEnter(ImagingSectionCookie *cookie) {
{
/* pass */ /* pass */
} }
void void
ImagingSectionLeave(ImagingSectionCookie* cookie) ImagingSectionLeave(ImagingSectionCookie *cookie) {
{
/* pass */ /* pass */
} }

View File

@ -15,19 +15,15 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#include <ctype.h> #include <ctype.h>
int int
ImagingSaveRaw(Imaging im, FILE* fp) ImagingSaveRaw(Imaging im, FILE *fp) {
{
int x, y, i; int x, y, i;
if (strcmp(im->mode, "1") == 0 || strcmp(im->mode, "L") == 0) { if (strcmp(im->mode, "1") == 0 || strcmp(im->mode, "L") == 0) {
/* @PIL227: FIXME: for mode "1", map != 0 to 255 */ /* @PIL227: FIXME: for mode "1", map != 0 to 255 */
/* PGM "L" */ /* PGM "L" */
@ -36,33 +32,29 @@ ImagingSaveRaw(Imaging im, FILE* fp)
} }
} else { } else {
/* PPM "RGB" or other internal format */ /* PPM "RGB" or other internal format */
for (y = 0; y < im->ysize; y++) { for (y = 0; y < im->ysize; y++) {
for (x = i = 0; x < im->xsize; x++, i += im->pixelsize) { for (x = i = 0; x < im->xsize; x++, i += im->pixelsize) {
fwrite(im->image[y]+i, 1, im->bands, fp); fwrite(im->image[y] + i, 1, im->bands, fp);
} }
} }
} }
return 1; return 1;
} }
int int
ImagingSavePPM(Imaging im, const char* outfile) ImagingSavePPM(Imaging im, const char *outfile) {
{ FILE *fp;
FILE* fp;
if (!im) { if (!im) {
(void) ImagingError_ValueError(NULL); (void)ImagingError_ValueError(NULL);
return 0; return 0;
} }
fp = fopen(outfile, "wb"); fp = fopen(outfile, "wb");
if (!fp) { if (!fp) {
(void) ImagingError_OSError(); (void)ImagingError_OSError();
return 0; return 0;
} }
@ -74,7 +66,7 @@ ImagingSavePPM(Imaging im, const char* outfile)
fprintf(fp, "P6\n%d %d\n255\n", im->xsize, im->ysize); fprintf(fp, "P6\n%d %d\n255\n", im->xsize, im->ysize);
} else { } else {
fclose(fp); fclose(fp);
(void) ImagingError_ModeError(); (void)ImagingError_ModeError();
return 0; return 0;
} }
@ -84,4 +76,3 @@ ImagingSavePPM(Imaging im, const char* outfile)
return 1; return 1;
} }

View File

@ -15,14 +15,12 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#include "math.h" #include "math.h"
Imaging Imaging
ImagingFill(Imaging im, const void* colour) ImagingFill(Imaging im, const void *colour) {
{
int x, y; int x, y;
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
@ -53,7 +51,7 @@ ImagingFill(Imaging im, const void* colour)
} }
} }
} else { } else {
unsigned char cc = (unsigned char) *(UINT8*) colour; unsigned char cc = (unsigned char)*(UINT8 *)colour;
for (y = 0; y < im->ysize; y++) { for (y = 0; y < im->ysize; y++) {
memset(im->image[y], cc, im->linesize); memset(im->image[y], cc, im->linesize);
} }
@ -65,13 +63,12 @@ ImagingFill(Imaging im, const void* colour)
} }
Imaging Imaging
ImagingFillLinearGradient(const char *mode) ImagingFillLinearGradient(const char *mode) {
{
Imaging im; Imaging im;
int y; int y;
if (strlen(mode) != 1) { if (strlen(mode) != 1) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
im = ImagingNewDirty(mode, 256, 256); im = ImagingNewDirty(mode, 256, 256);
@ -80,21 +77,20 @@ ImagingFillLinearGradient(const char *mode)
} }
for (y = 0; y < 256; y++) { for (y = 0; y < 256; y++) {
memset(im->image8[y], (unsigned char) y, 256); memset(im->image8[y], (unsigned char)y, 256);
} }
return im; return im;
} }
Imaging Imaging
ImagingFillRadialGradient(const char *mode) ImagingFillRadialGradient(const char *mode) {
{
Imaging im; Imaging im;
int x, y; int x, y;
int d; int d;
if (strlen(mode) != 1) { if (strlen(mode) != 1) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
im = ImagingNewDirty(mode, 256, 256); im = ImagingNewDirty(mode, 256, 256);
@ -104,7 +100,8 @@ ImagingFillRadialGradient(const char *mode)
for (y = 0; y < 256; y++) { for (y = 0; y < 256; y++) {
for (x = 0; x < 256; x++) { for (x = 0; x < 256; x++) {
d = (int) sqrt((double) ((x-128)*(x-128) + (y-128)*(y-128)) * 2.0); d = (int)sqrt(
(double)((x - 128) * (x - 128) + (y - 128) * (y - 128)) * 2.0);
if (d >= 255) { if (d >= 255) {
im->image8[y][x] = 255; im->image8[y][x] = 255;
} else { } else {

View File

@ -26,59 +26,59 @@
#include "Imaging.h" #include "Imaging.h"
static inline UINT8
static inline UINT8 clip8(float in) clip8(float in) {
{
if (in <= 0.0) { if (in <= 0.0) {
return 0; return 0;
} }
if (in >= 255.0) { if (in >= 255.0) {
return 255; return 255;
} }
return (UINT8) in; return (UINT8)in;
} }
Imaging Imaging
ImagingExpand(Imaging imIn, int xmargin, int ymargin, int mode) ImagingExpand(Imaging imIn, int xmargin, int ymargin, int mode) {
{
Imaging imOut; Imaging imOut;
int x, y; int x, y;
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
if (xmargin < 0 && ymargin < 0) { if (xmargin < 0 && ymargin < 0) {
return (Imaging) ImagingError_ValueError("bad kernel size"); return (Imaging)ImagingError_ValueError("bad kernel size");
} }
imOut = ImagingNewDirty( imOut = ImagingNewDirty(
imIn->mode, imIn->xsize+2*xmargin, imIn->ysize+2*ymargin); imIn->mode, imIn->xsize + 2 * xmargin, imIn->ysize + 2 * ymargin);
if (!imOut) { if (!imOut) {
return NULL; return NULL;
} }
#define EXPAND_LINE(type, image, yin, yout) {\ #define EXPAND_LINE(type, image, yin, yout) \
for (x = 0; x < xmargin; x++) {\ { \
imOut->image[yout][x] = imIn->image[yin][0];\ for (x = 0; x < xmargin; x++) { \
}\ imOut->image[yout][x] = imIn->image[yin][0]; \
for (x = 0; x < imIn->xsize; x++) {\ } \
imOut->image[yout][x+xmargin] = imIn->image[yin][x];\ for (x = 0; x < imIn->xsize; x++) { \
}\ imOut->image[yout][x + xmargin] = imIn->image[yin][x]; \
for (x = 0; x < xmargin; x++) {\ } \
imOut->image[yout][xmargin+imIn->xsize+x] =\ for (x = 0; x < xmargin; x++) { \
imIn->image[yin][imIn->xsize-1];\ imOut->image[yout][xmargin + imIn->xsize + x] = \
}\ imIn->image[yin][imIn->xsize - 1]; \
} } \
}
#define EXPAND(type, image) {\ #define EXPAND(type, image) \
for (y = 0; y < ymargin; y++) {\ { \
EXPAND_LINE(type, image, 0, y);\ for (y = 0; y < ymargin; y++) { \
}\ EXPAND_LINE(type, image, 0, y); \
for (y = 0; y < imIn->ysize; y++) {\ } \
EXPAND_LINE(type, image, y, y+ymargin);\ for (y = 0; y < imIn->ysize; y++) { \
}\ EXPAND_LINE(type, image, y, y + ymargin); \
for (y = 0; y < ymargin; y++) {\ } \
EXPAND_LINE(type, image, imIn->ysize-1, ymargin+imIn->ysize+y);\ for (y = 0; y < ymargin; y++) { \
}\ EXPAND_LINE(type, image, imIn->ysize - 1, ymargin + imIn->ysize + y); \
} } \
}
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
if (imIn->image8) { if (imIn->image8) {
@ -93,15 +93,11 @@ ImagingExpand(Imaging imIn, int xmargin, int ymargin, int mode)
return imOut; return imOut;
} }
void void
ImagingFilter3x3(Imaging imOut, Imaging im, const float* kernel, ImagingFilter3x3(Imaging imOut, Imaging im, const float *kernel, float offset) {
float offset) #define KERNEL1x3(in0, x, kernel, d) \
{ (_i2f((UINT8)in0[x - d]) * (kernel)[0] + _i2f((UINT8)in0[x]) * (kernel)[1] + \
#define KERNEL1x3(in0, x, kernel, d) ( \ _i2f((UINT8)in0[x + d]) * (kernel)[2])
_i2f((UINT8) in0[x-d]) * (kernel)[0] + \
_i2f((UINT8) in0[x]) * (kernel)[1] + \
_i2f((UINT8) in0[x+d]) * (kernel)[2])
int x = 0, y = 0; int x = 0, y = 0;
@ -109,86 +105,84 @@ ImagingFilter3x3(Imaging imOut, Imaging im, const float* kernel,
if (im->bands == 1) { if (im->bands == 1) {
// Add one time for rounding // Add one time for rounding
offset += 0.5; offset += 0.5;
for (y = 1; y < im->ysize-1; y++) { for (y = 1; y < im->ysize - 1; y++) {
UINT8* in_1 = (UINT8*) im->image[y-1]; UINT8 *in_1 = (UINT8 *)im->image[y - 1];
UINT8* in0 = (UINT8*) im->image[y]; UINT8 *in0 = (UINT8 *)im->image[y];
UINT8* in1 = (UINT8*) im->image[y+1]; UINT8 *in1 = (UINT8 *)im->image[y + 1];
UINT8* out = (UINT8*) imOut->image[y]; UINT8 *out = (UINT8 *)imOut->image[y];
out[0] = in0[0]; out[0] = in0[0];
for (x = 1; x < im->xsize-1; x++) { for (x = 1; x < im->xsize - 1; x++) {
float ss = offset; float ss = offset;
ss += KERNEL1x3(in1, x, &kernel[0], 1); ss += KERNEL1x3(in1, x, &kernel[0], 1);
ss += KERNEL1x3(in0, x, &kernel[3], 1); ss += KERNEL1x3(in0, x, &kernel[3], 1);
ss += KERNEL1x3(in_1, x, &kernel[6], 1); ss += KERNEL1x3(in_1, x, &kernel[6], 1);
out[x] = clip8(ss); out[x] = clip8(ss);
} }
out[x] = in0[x]; out[x] = in0[x];
} }
} else { } else {
// Add one time for rounding // Add one time for rounding
offset += 0.5; offset += 0.5;
for (y = 1; y < im->ysize-1; y++) { for (y = 1; y < im->ysize - 1; y++) {
UINT8* in_1 = (UINT8*) im->image[y-1]; UINT8 *in_1 = (UINT8 *)im->image[y - 1];
UINT8* in0 = (UINT8*) im->image[y]; UINT8 *in0 = (UINT8 *)im->image[y];
UINT8* in1 = (UINT8*) im->image[y+1]; UINT8 *in1 = (UINT8 *)im->image[y + 1];
UINT8* out = (UINT8*) imOut->image[y]; UINT8 *out = (UINT8 *)imOut->image[y];
memcpy(out, in0, sizeof(UINT32)); memcpy(out, in0, sizeof(UINT32));
if (im->bands == 2) { if (im->bands == 2) {
for (x = 1; x < im->xsize-1; x++) { for (x = 1; x < im->xsize - 1; x++) {
float ss0 = offset; float ss0 = offset;
float ss3 = offset; float ss3 = offset;
UINT32 v; UINT32 v;
ss0 += KERNEL1x3(in1, x*4+0, &kernel[0], 4); ss0 += KERNEL1x3(in1, x * 4 + 0, &kernel[0], 4);
ss3 += KERNEL1x3(in1, x*4+3, &kernel[0], 4); ss3 += KERNEL1x3(in1, x * 4 + 3, &kernel[0], 4);
ss0 += KERNEL1x3(in0, x*4+0, &kernel[3], 4); ss0 += KERNEL1x3(in0, x * 4 + 0, &kernel[3], 4);
ss3 += KERNEL1x3(in0, x*4+3, &kernel[3], 4); ss3 += KERNEL1x3(in0, x * 4 + 3, &kernel[3], 4);
ss0 += KERNEL1x3(in_1, x*4+0, &kernel[6], 4); ss0 += KERNEL1x3(in_1, x * 4 + 0, &kernel[6], 4);
ss3 += KERNEL1x3(in_1, x*4+3, &kernel[6], 4); ss3 += KERNEL1x3(in_1, x * 4 + 3, &kernel[6], 4);
v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3)); v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3));
memcpy(out + x * sizeof(v), &v, sizeof(v)); memcpy(out + x * sizeof(v), &v, sizeof(v));
} }
} else if (im->bands == 3) { } else if (im->bands == 3) {
for (x = 1; x < im->xsize-1; x++) { for (x = 1; x < im->xsize - 1; x++) {
float ss0 = offset; float ss0 = offset;
float ss1 = offset; float ss1 = offset;
float ss2 = offset; float ss2 = offset;
UINT32 v; UINT32 v;
ss0 += KERNEL1x3(in1, x*4+0, &kernel[0], 4); ss0 += KERNEL1x3(in1, x * 4 + 0, &kernel[0], 4);
ss1 += KERNEL1x3(in1, x*4+1, &kernel[0], 4); ss1 += KERNEL1x3(in1, x * 4 + 1, &kernel[0], 4);
ss2 += KERNEL1x3(in1, x*4+2, &kernel[0], 4); ss2 += KERNEL1x3(in1, x * 4 + 2, &kernel[0], 4);
ss0 += KERNEL1x3(in0, x*4+0, &kernel[3], 4); ss0 += KERNEL1x3(in0, x * 4 + 0, &kernel[3], 4);
ss1 += KERNEL1x3(in0, x*4+1, &kernel[3], 4); ss1 += KERNEL1x3(in0, x * 4 + 1, &kernel[3], 4);
ss2 += KERNEL1x3(in0, x*4+2, &kernel[3], 4); ss2 += KERNEL1x3(in0, x * 4 + 2, &kernel[3], 4);
ss0 += KERNEL1x3(in_1, x*4+0, &kernel[6], 4); ss0 += KERNEL1x3(in_1, x * 4 + 0, &kernel[6], 4);
ss1 += KERNEL1x3(in_1, x*4+1, &kernel[6], 4); ss1 += KERNEL1x3(in_1, x * 4 + 1, &kernel[6], 4);
ss2 += KERNEL1x3(in_1, x*4+2, &kernel[6], 4); ss2 += KERNEL1x3(in_1, x * 4 + 2, &kernel[6], 4);
v = MAKE_UINT32( v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), 0);
clip8(ss0), clip8(ss1), clip8(ss2), 0);
memcpy(out + x * sizeof(v), &v, sizeof(v)); memcpy(out + x * sizeof(v), &v, sizeof(v));
} }
} else if (im->bands == 4) { } else if (im->bands == 4) {
for (x = 1; x < im->xsize-1; x++) { for (x = 1; x < im->xsize - 1; x++) {
float ss0 = offset; float ss0 = offset;
float ss1 = offset; float ss1 = offset;
float ss2 = offset; float ss2 = offset;
float ss3 = offset; float ss3 = offset;
UINT32 v; UINT32 v;
ss0 += KERNEL1x3(in1, x*4+0, &kernel[0], 4); ss0 += KERNEL1x3(in1, x * 4 + 0, &kernel[0], 4);
ss1 += KERNEL1x3(in1, x*4+1, &kernel[0], 4); ss1 += KERNEL1x3(in1, x * 4 + 1, &kernel[0], 4);
ss2 += KERNEL1x3(in1, x*4+2, &kernel[0], 4); ss2 += KERNEL1x3(in1, x * 4 + 2, &kernel[0], 4);
ss3 += KERNEL1x3(in1, x*4+3, &kernel[0], 4); ss3 += KERNEL1x3(in1, x * 4 + 3, &kernel[0], 4);
ss0 += KERNEL1x3(in0, x*4+0, &kernel[3], 4); ss0 += KERNEL1x3(in0, x * 4 + 0, &kernel[3], 4);
ss1 += KERNEL1x3(in0, x*4+1, &kernel[3], 4); ss1 += KERNEL1x3(in0, x * 4 + 1, &kernel[3], 4);
ss2 += KERNEL1x3(in0, x*4+2, &kernel[3], 4); ss2 += KERNEL1x3(in0, x * 4 + 2, &kernel[3], 4);
ss3 += KERNEL1x3(in0, x*4+3, &kernel[3], 4); ss3 += KERNEL1x3(in0, x * 4 + 3, &kernel[3], 4);
ss0 += KERNEL1x3(in_1, x*4+0, &kernel[6], 4); ss0 += KERNEL1x3(in_1, x * 4 + 0, &kernel[6], 4);
ss1 += KERNEL1x3(in_1, x*4+1, &kernel[6], 4); ss1 += KERNEL1x3(in_1, x * 4 + 1, &kernel[6], 4);
ss2 += KERNEL1x3(in_1, x*4+2, &kernel[6], 4); ss2 += KERNEL1x3(in_1, x * 4 + 2, &kernel[6], 4);
ss3 += KERNEL1x3(in_1, x*4+3, &kernel[6], 4); ss3 += KERNEL1x3(in_1, x * 4 + 3, &kernel[6], 4);
v = MAKE_UINT32( v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3));
clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3));
memcpy(out + x * sizeof(v), &v, sizeof(v)); memcpy(out + x * sizeof(v), &v, sizeof(v));
} }
} }
@ -198,17 +192,13 @@ ImagingFilter3x3(Imaging imOut, Imaging im, const float* kernel,
memcpy(imOut->image[y], im->image[y], im->linesize); memcpy(imOut->image[y], im->image[y], im->linesize);
} }
void void
ImagingFilter5x5(Imaging imOut, Imaging im, const float* kernel, ImagingFilter5x5(Imaging imOut, Imaging im, const float *kernel, float offset) {
float offset) #define KERNEL1x5(in0, x, kernel, d) \
{ (_i2f((UINT8)in0[x - d - d]) * (kernel)[0] + \
#define KERNEL1x5(in0, x, kernel, d) ( \ _i2f((UINT8)in0[x - d]) * (kernel)[1] + _i2f((UINT8)in0[x]) * (kernel)[2] + \
_i2f((UINT8) in0[x-d-d]) * (kernel)[0] + \ _i2f((UINT8)in0[x + d]) * (kernel)[3] + \
_i2f((UINT8) in0[x-d]) * (kernel)[1] + \ _i2f((UINT8)in0[x + d + d]) * (kernel)[4])
_i2f((UINT8) in0[x]) * (kernel)[2] + \
_i2f((UINT8) in0[x+d]) * (kernel)[3] + \
_i2f((UINT8) in0[x+d+d]) * (kernel)[4])
int x = 0, y = 0; int x = 0, y = 0;
@ -217,17 +207,17 @@ ImagingFilter5x5(Imaging imOut, Imaging im, const float* kernel,
if (im->bands == 1) { if (im->bands == 1) {
// Add one time for rounding // Add one time for rounding
offset += 0.5; offset += 0.5;
for (y = 2; y < im->ysize-2; y++) { for (y = 2; y < im->ysize - 2; y++) {
UINT8* in_2 = (UINT8*) im->image[y-2]; UINT8 *in_2 = (UINT8 *)im->image[y - 2];
UINT8* in_1 = (UINT8*) im->image[y-1]; UINT8 *in_1 = (UINT8 *)im->image[y - 1];
UINT8* in0 = (UINT8*) im->image[y]; UINT8 *in0 = (UINT8 *)im->image[y];
UINT8* in1 = (UINT8*) im->image[y+1]; UINT8 *in1 = (UINT8 *)im->image[y + 1];
UINT8* in2 = (UINT8*) im->image[y+2]; UINT8 *in2 = (UINT8 *)im->image[y + 2];
UINT8* out = (UINT8*) imOut->image[y]; UINT8 *out = (UINT8 *)imOut->image[y];
out[0] = in0[0]; out[0] = in0[0];
out[1] = in0[1]; out[1] = in0[1];
for (x = 2; x < im->xsize-2; x++) { for (x = 2; x < im->xsize - 2; x++) {
float ss = offset; float ss = offset;
ss += KERNEL1x5(in2, x, &kernel[0], 1); ss += KERNEL1x5(in2, x, &kernel[0], 1);
ss += KERNEL1x5(in1, x, &kernel[5], 1); ss += KERNEL1x5(in1, x, &kernel[5], 1);
@ -236,112 +226,109 @@ ImagingFilter5x5(Imaging imOut, Imaging im, const float* kernel,
ss += KERNEL1x5(in_2, x, &kernel[20], 1); ss += KERNEL1x5(in_2, x, &kernel[20], 1);
out[x] = clip8(ss); out[x] = clip8(ss);
} }
out[x+0] = in0[x+0]; out[x + 0] = in0[x + 0];
out[x+1] = in0[x+1]; out[x + 1] = in0[x + 1];
} }
} else { } else {
// Add one time for rounding // Add one time for rounding
offset += 0.5; offset += 0.5;
for (y = 2; y < im->ysize-2; y++) { for (y = 2; y < im->ysize - 2; y++) {
UINT8* in_2 = (UINT8*) im->image[y-2]; UINT8 *in_2 = (UINT8 *)im->image[y - 2];
UINT8* in_1 = (UINT8*) im->image[y-1]; UINT8 *in_1 = (UINT8 *)im->image[y - 1];
UINT8* in0 = (UINT8*) im->image[y]; UINT8 *in0 = (UINT8 *)im->image[y];
UINT8* in1 = (UINT8*) im->image[y+1]; UINT8 *in1 = (UINT8 *)im->image[y + 1];
UINT8* in2 = (UINT8*) im->image[y+2]; UINT8 *in2 = (UINT8 *)im->image[y + 2];
UINT8* out = (UINT8*) imOut->image[y]; UINT8 *out = (UINT8 *)imOut->image[y];
memcpy(out, in0, sizeof(UINT32) * 2); memcpy(out, in0, sizeof(UINT32) * 2);
if (im->bands == 2) { if (im->bands == 2) {
for (x = 2; x < im->xsize-2; x++) { for (x = 2; x < im->xsize - 2; x++) {
float ss0 = offset; float ss0 = offset;
float ss3 = offset; float ss3 = offset;
UINT32 v; UINT32 v;
ss0 += KERNEL1x5(in2, x*4+0, &kernel[0], 4); ss0 += KERNEL1x5(in2, x * 4 + 0, &kernel[0], 4);
ss3 += KERNEL1x5(in2, x*4+3, &kernel[0], 4); ss3 += KERNEL1x5(in2, x * 4 + 3, &kernel[0], 4);
ss0 += KERNEL1x5(in1, x*4+0, &kernel[5], 4); ss0 += KERNEL1x5(in1, x * 4 + 0, &kernel[5], 4);
ss3 += KERNEL1x5(in1, x*4+3, &kernel[5], 4); ss3 += KERNEL1x5(in1, x * 4 + 3, &kernel[5], 4);
ss0 += KERNEL1x5(in0, x*4+0, &kernel[10], 4); ss0 += KERNEL1x5(in0, x * 4 + 0, &kernel[10], 4);
ss3 += KERNEL1x5(in0, x*4+3, &kernel[10], 4); ss3 += KERNEL1x5(in0, x * 4 + 3, &kernel[10], 4);
ss0 += KERNEL1x5(in_1, x*4+0, &kernel[15], 4); ss0 += KERNEL1x5(in_1, x * 4 + 0, &kernel[15], 4);
ss3 += KERNEL1x5(in_1, x*4+3, &kernel[15], 4); ss3 += KERNEL1x5(in_1, x * 4 + 3, &kernel[15], 4);
ss0 += KERNEL1x5(in_2, x*4+0, &kernel[20], 4); ss0 += KERNEL1x5(in_2, x * 4 + 0, &kernel[20], 4);
ss3 += KERNEL1x5(in_2, x*4+3, &kernel[20], 4); ss3 += KERNEL1x5(in_2, x * 4 + 3, &kernel[20], 4);
v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3)); v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3));
memcpy(out + x * sizeof(v), &v, sizeof(v)); memcpy(out + x * sizeof(v), &v, sizeof(v));
} }
} else if (im->bands == 3) { } else if (im->bands == 3) {
for (x = 2; x < im->xsize-2; x++) { for (x = 2; x < im->xsize - 2; x++) {
float ss0 = offset; float ss0 = offset;
float ss1 = offset; float ss1 = offset;
float ss2 = offset; float ss2 = offset;
UINT32 v; UINT32 v;
ss0 += KERNEL1x5(in2, x*4+0, &kernel[0], 4); ss0 += KERNEL1x5(in2, x * 4 + 0, &kernel[0], 4);
ss1 += KERNEL1x5(in2, x*4+1, &kernel[0], 4); ss1 += KERNEL1x5(in2, x * 4 + 1, &kernel[0], 4);
ss2 += KERNEL1x5(in2, x*4+2, &kernel[0], 4); ss2 += KERNEL1x5(in2, x * 4 + 2, &kernel[0], 4);
ss0 += KERNEL1x5(in1, x*4+0, &kernel[5], 4); ss0 += KERNEL1x5(in1, x * 4 + 0, &kernel[5], 4);
ss1 += KERNEL1x5(in1, x*4+1, &kernel[5], 4); ss1 += KERNEL1x5(in1, x * 4 + 1, &kernel[5], 4);
ss2 += KERNEL1x5(in1, x*4+2, &kernel[5], 4); ss2 += KERNEL1x5(in1, x * 4 + 2, &kernel[5], 4);
ss0 += KERNEL1x5(in0, x*4+0, &kernel[10], 4); ss0 += KERNEL1x5(in0, x * 4 + 0, &kernel[10], 4);
ss1 += KERNEL1x5(in0, x*4+1, &kernel[10], 4); ss1 += KERNEL1x5(in0, x * 4 + 1, &kernel[10], 4);
ss2 += KERNEL1x5(in0, x*4+2, &kernel[10], 4); ss2 += KERNEL1x5(in0, x * 4 + 2, &kernel[10], 4);
ss0 += KERNEL1x5(in_1, x*4+0, &kernel[15], 4); ss0 += KERNEL1x5(in_1, x * 4 + 0, &kernel[15], 4);
ss1 += KERNEL1x5(in_1, x*4+1, &kernel[15], 4); ss1 += KERNEL1x5(in_1, x * 4 + 1, &kernel[15], 4);
ss2 += KERNEL1x5(in_1, x*4+2, &kernel[15], 4); ss2 += KERNEL1x5(in_1, x * 4 + 2, &kernel[15], 4);
ss0 += KERNEL1x5(in_2, x*4+0, &kernel[20], 4); ss0 += KERNEL1x5(in_2, x * 4 + 0, &kernel[20], 4);
ss1 += KERNEL1x5(in_2, x*4+1, &kernel[20], 4); ss1 += KERNEL1x5(in_2, x * 4 + 1, &kernel[20], 4);
ss2 += KERNEL1x5(in_2, x*4+2, &kernel[20], 4); ss2 += KERNEL1x5(in_2, x * 4 + 2, &kernel[20], 4);
v = MAKE_UINT32( v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), 0);
clip8(ss0), clip8(ss1), clip8(ss2), 0);
memcpy(out + x * sizeof(v), &v, sizeof(v)); memcpy(out + x * sizeof(v), &v, sizeof(v));
} }
} else if (im->bands == 4) { } else if (im->bands == 4) {
for (x = 2; x < im->xsize-2; x++) { for (x = 2; x < im->xsize - 2; x++) {
float ss0 = offset; float ss0 = offset;
float ss1 = offset; float ss1 = offset;
float ss2 = offset; float ss2 = offset;
float ss3 = offset; float ss3 = offset;
UINT32 v; UINT32 v;
ss0 += KERNEL1x5(in2, x*4+0, &kernel[0], 4); ss0 += KERNEL1x5(in2, x * 4 + 0, &kernel[0], 4);
ss1 += KERNEL1x5(in2, x*4+1, &kernel[0], 4); ss1 += KERNEL1x5(in2, x * 4 + 1, &kernel[0], 4);
ss2 += KERNEL1x5(in2, x*4+2, &kernel[0], 4); ss2 += KERNEL1x5(in2, x * 4 + 2, &kernel[0], 4);
ss3 += KERNEL1x5(in2, x*4+3, &kernel[0], 4); ss3 += KERNEL1x5(in2, x * 4 + 3, &kernel[0], 4);
ss0 += KERNEL1x5(in1, x*4+0, &kernel[5], 4); ss0 += KERNEL1x5(in1, x * 4 + 0, &kernel[5], 4);
ss1 += KERNEL1x5(in1, x*4+1, &kernel[5], 4); ss1 += KERNEL1x5(in1, x * 4 + 1, &kernel[5], 4);
ss2 += KERNEL1x5(in1, x*4+2, &kernel[5], 4); ss2 += KERNEL1x5(in1, x * 4 + 2, &kernel[5], 4);
ss3 += KERNEL1x5(in1, x*4+3, &kernel[5], 4); ss3 += KERNEL1x5(in1, x * 4 + 3, &kernel[5], 4);
ss0 += KERNEL1x5(in0, x*4+0, &kernel[10], 4); ss0 += KERNEL1x5(in0, x * 4 + 0, &kernel[10], 4);
ss1 += KERNEL1x5(in0, x*4+1, &kernel[10], 4); ss1 += KERNEL1x5(in0, x * 4 + 1, &kernel[10], 4);
ss2 += KERNEL1x5(in0, x*4+2, &kernel[10], 4); ss2 += KERNEL1x5(in0, x * 4 + 2, &kernel[10], 4);
ss3 += KERNEL1x5(in0, x*4+3, &kernel[10], 4); ss3 += KERNEL1x5(in0, x * 4 + 3, &kernel[10], 4);
ss0 += KERNEL1x5(in_1, x*4+0, &kernel[15], 4); ss0 += KERNEL1x5(in_1, x * 4 + 0, &kernel[15], 4);
ss1 += KERNEL1x5(in_1, x*4+1, &kernel[15], 4); ss1 += KERNEL1x5(in_1, x * 4 + 1, &kernel[15], 4);
ss2 += KERNEL1x5(in_1, x*4+2, &kernel[15], 4); ss2 += KERNEL1x5(in_1, x * 4 + 2, &kernel[15], 4);
ss3 += KERNEL1x5(in_1, x*4+3, &kernel[15], 4); ss3 += KERNEL1x5(in_1, x * 4 + 3, &kernel[15], 4);
ss0 += KERNEL1x5(in_2, x*4+0, &kernel[20], 4); ss0 += KERNEL1x5(in_2, x * 4 + 0, &kernel[20], 4);
ss1 += KERNEL1x5(in_2, x*4+1, &kernel[20], 4); ss1 += KERNEL1x5(in_2, x * 4 + 1, &kernel[20], 4);
ss2 += KERNEL1x5(in_2, x*4+2, &kernel[20], 4); ss2 += KERNEL1x5(in_2, x * 4 + 2, &kernel[20], 4);
ss3 += KERNEL1x5(in_2, x*4+3, &kernel[20], 4); ss3 += KERNEL1x5(in_2, x * 4 + 3, &kernel[20], 4);
v = MAKE_UINT32( v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3));
clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3));
memcpy(out + x * sizeof(v), &v, sizeof(v)); memcpy(out + x * sizeof(v), &v, sizeof(v));
} }
} }
memcpy(out + x * sizeof(UINT32), in0 + x * sizeof(UINT32), sizeof(UINT32) * 2); memcpy(
out + x * sizeof(UINT32), in0 + x * sizeof(UINT32), sizeof(UINT32) * 2);
} }
} }
memcpy(imOut->image[y], im->image[y], im->linesize); memcpy(imOut->image[y], im->image[y], im->linesize);
memcpy(imOut->image[y+1], im->image[y+1], im->linesize); memcpy(imOut->image[y + 1], im->image[y + 1], im->linesize);
} }
Imaging Imaging
ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32* kernel, ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32 *kernel, FLOAT32 offset) {
FLOAT32 offset)
{
Imaging imOut; Imaging imOut;
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
if ( ! im || im->type != IMAGING_TYPE_UINT8) { if (!im || im->type != IMAGING_TYPE_UINT8) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
if (im->xsize < xsize || im->ysize < ysize) { if (im->xsize < xsize || im->ysize < ysize) {
@ -349,7 +336,7 @@ ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32* kernel,
} }
if ((xsize != 3 && xsize != 5) || xsize != ysize) { if ((xsize != 3 && xsize != 5) || xsize != ysize) {
return (Imaging) ImagingError_ValueError("bad kernel size"); return (Imaging)ImagingError_ValueError("bad kernel size");
} }
imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize);
@ -368,4 +355,3 @@ ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32* kernel,
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
return imOut; return imOut;
} }

View File

@ -14,26 +14,21 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#define I16(ptr) ((ptr)[0] + ((ptr)[1] << 8))
#define I16(ptr)\ #define I32(ptr) ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24))
((ptr)[0] + ((ptr)[1] << 8))
#define I32(ptr)\ #define ERR_IF_DATA_OOB(offset) \
((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24)) if ((data + (offset)) > ptr + bytes) { \
state->errcode = IMAGING_CODEC_OVERRUN; \
#define ERR_IF_DATA_OOB(offset) \ return -1; \
if ((data + (offset)) > ptr + bytes) {\ }
state->errcode = IMAGING_CODEC_OVERRUN; \
return -1; \
}
int int
ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes) ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
{ UINT8 *ptr;
UINT8* ptr;
int framesize; int framesize;
int c, chunks, advance; int c, chunks, advance;
int l, lines; int l, lines;
@ -62,36 +57,39 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
state->errcode = IMAGING_CODEC_OVERRUN; state->errcode = IMAGING_CODEC_OVERRUN;
return -1; return -1;
} }
if (I16(ptr+4) != 0xF1FA) { if (I16(ptr + 4) != 0xF1FA) {
state->errcode = IMAGING_CODEC_UNKNOWN; state->errcode = IMAGING_CODEC_UNKNOWN;
return -1; return -1;
} }
chunks = I16(ptr+6); chunks = I16(ptr + 6);
ptr += 16; ptr += 16;
bytes -= 16; bytes -= 16;
/* Process subchunks */ /* Process subchunks */
for (c = 0; c < chunks; c++) { for (c = 0; c < chunks; c++) {
UINT8* data; UINT8 *data;
if (bytes < 10) { if (bytes < 10) {
state->errcode = IMAGING_CODEC_OVERRUN; state->errcode = IMAGING_CODEC_OVERRUN;
return -1; return -1;
} }
data = ptr + 6; data = ptr + 6;
switch (I16(ptr+4)) { switch (I16(ptr + 4)) {
case 4: case 11: case 4:
case 11:
/* FLI COLOR chunk */ /* FLI COLOR chunk */
break; /* ignored; handled by Python code */ break; /* ignored; handled by Python code */
case 7: case 7:
/* FLI SS2 chunk (word delta) */ /* FLI SS2 chunk (word delta) */
/* OOB ok, we've got 4 bytes min on entry */ /* OOB ok, we've got 4 bytes min on entry */
lines = I16(data); data += 2; lines = I16(data);
data += 2;
for (l = y = 0; l < lines && y < state->ysize; l++, y++) { for (l = y = 0; l < lines && y < state->ysize; l++, y++) {
UINT8* local_buf = (UINT8*) im->image[y]; UINT8 *local_buf = (UINT8 *)im->image[y];
int p, packets; int p, packets;
ERR_IF_DATA_OOB(2) ERR_IF_DATA_OOB(2)
packets = I16(data); data += 2; packets = I16(data);
data += 2;
while (packets & 0x8000) { while (packets & 0x8000) {
/* flag word */ /* flag word */
if (packets & 0x4000) { if (packets & 0x4000) {
@ -100,20 +98,21 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
state->errcode = IMAGING_CODEC_OVERRUN; state->errcode = IMAGING_CODEC_OVERRUN;
return -1; return -1;
} }
local_buf = (UINT8*) im->image[y]; local_buf = (UINT8 *)im->image[y];
} else { } else {
/* store last byte (used if line width is odd) */ /* store last byte (used if line width is odd) */
local_buf[state->xsize-1] = (UINT8) packets; local_buf[state->xsize - 1] = (UINT8)packets;
} }
ERR_IF_DATA_OOB(2) ERR_IF_DATA_OOB(2)
packets = I16(data); data += 2; packets = I16(data);
data += 2;
} }
for (p = x = 0; p < packets; p++) { for (p = x = 0; p < packets; p++) {
ERR_IF_DATA_OOB(2) ERR_IF_DATA_OOB(2)
x += data[0]; /* pixel skip */ x += data[0]; /* pixel skip */
if (data[1] >= 128) { if (data[1] >= 128) {
ERR_IF_DATA_OOB(4) ERR_IF_DATA_OOB(4)
i = 256-data[1]; /* run */ i = 256 - data[1]; /* run */
if (x + i + i > state->xsize) { if (x + i + i > state->xsize) {
break; break;
} }
@ -123,11 +122,11 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
} }
data += 2 + 2; data += 2 + 2;
} else { } else {
i = 2 * (int) data[1]; /* chunk */ i = 2 * (int)data[1]; /* chunk */
if (x + i > state->xsize) { if (x + i > state->xsize) {
break; break;
} }
ERR_IF_DATA_OOB(2+i) ERR_IF_DATA_OOB(2 + i)
memcpy(local_buf + x, data + 2, i); memcpy(local_buf + x, data + 2, i);
data += 2 + i; data += 2 + i;
x += i; x += i;
@ -146,16 +145,18 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
case 12: case 12:
/* FLI LC chunk (byte delta) */ /* FLI LC chunk (byte delta) */
/* OOB Check ok, we have 4 bytes min here */ /* OOB Check ok, we have 4 bytes min here */
y = I16(data); ymax = y + I16(data+2); data += 4; y = I16(data);
ymax = y + I16(data + 2);
data += 4;
for (; y < ymax && y < state->ysize; y++) { for (; y < ymax && y < state->ysize; y++) {
UINT8* out = (UINT8*) im->image[y]; UINT8 *out = (UINT8 *)im->image[y];
ERR_IF_DATA_OOB(1) ERR_IF_DATA_OOB(1)
int p, packets = *data++; int p, packets = *data++;
for (p = x = 0; p < packets; p++, x += i) { for (p = x = 0; p < packets; p++, x += i) {
ERR_IF_DATA_OOB(2) ERR_IF_DATA_OOB(2)
x += data[0]; /* skip pixels */ x += data[0]; /* skip pixels */
if (data[1] & 0x80) { if (data[1] & 0x80) {
i = 256-data[1]; /* run */ i = 256 - data[1]; /* run */
if (x + i > state->xsize) { if (x + i > state->xsize) {
break; break;
} }
@ -167,7 +168,7 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
if (x + i > state->xsize) { if (x + i > state->xsize) {
break; break;
} }
ERR_IF_DATA_OOB(2+i) ERR_IF_DATA_OOB(2 + i)
memcpy(out + x, data + 2, i); memcpy(out + x, data + 2, i);
data += i + 2; data += i + 2;
} }
@ -192,7 +193,7 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
/* FLI BRUN chunk */ /* FLI BRUN chunk */
/* OOB, ok, we've got 4 bytes min on entry */ /* OOB, ok, we've got 4 bytes min on entry */
for (y = 0; y < state->ysize; y++) { for (y = 0; y < state->ysize; y++) {
UINT8* out = (UINT8*) im->image[y]; UINT8 *out = (UINT8 *)im->image[y];
data += 1; /* ignore packetcount byte */ data += 1; /* ignore packetcount byte */
for (x = 0; x < state->xsize; x += i) { for (x = 0; x < state->xsize; x += i) {
ERR_IF_DATA_OOB(2) ERR_IF_DATA_OOB(2)
@ -201,7 +202,7 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
if (x + i > state->xsize) { if (x + i > state->xsize) {
break; /* safety first */ break; /* safety first */
} }
ERR_IF_DATA_OOB(i+1) ERR_IF_DATA_OOB(i + 1)
memcpy(out + x, data + 1, i); memcpy(out + x, data + 1, i);
data += i + 1; data += i + 1;
} else { } else {
@ -222,12 +223,12 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
break; break;
case 16: case 16:
/* COPY chunk */ /* COPY chunk */
if (state->xsize > bytes/state->ysize) { if (state->xsize > bytes / state->ysize) {
/* not enough data for frame */ /* not enough data for frame */
return ptr - buf; /* bytes consumed */ return ptr - buf; /* bytes consumed */
} }
for (y = 0; y < state->ysize; y++) { for (y = 0; y < state->ysize; y++) {
UINT8* local_buf = (UINT8*) im->image[y]; UINT8 *local_buf = (UINT8 *)im->image[y];
memcpy(local_buf, data, state->xsize); memcpy(local_buf, data, state->xsize);
data += state->xsize; data += state->xsize;
} }

File diff suppressed because it is too large Load Diff

View File

@ -16,13 +16,10 @@
* See the README file for details on usage and redistribution. * See the README file for details on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
int int
ImagingGetBBox(Imaging im, int bbox[4]) ImagingGetBBox(Imaging im, int bbox[4]) {
{
/* Get the bounding box for any non-zero data in the image.*/ /* Get the bounding box for any non-zero data in the image.*/
int x, y; int x, y;
@ -33,26 +30,26 @@ ImagingGetBBox(Imaging im, int bbox[4])
bbox[1] = -1; bbox[1] = -1;
bbox[2] = bbox[3] = 0; bbox[2] = bbox[3] = 0;
#define GETBBOX(image, mask)\ #define GETBBOX(image, mask) \
for (y = 0; y < im->ysize; y++) {\ for (y = 0; y < im->ysize; y++) { \
has_data = 0;\ has_data = 0; \
for (x = 0; x < im->xsize; x++) {\ for (x = 0; x < im->xsize; x++) { \
if (im->image[y][x] & mask) {\ if (im->image[y][x] & mask) { \
has_data = 1;\ has_data = 1; \
if (x < bbox[0]) {\ if (x < bbox[0]) { \
bbox[0] = x;\ bbox[0] = x; \
}\ } \
if (x >= bbox[2]) {\ if (x >= bbox[2]) { \
bbox[2] = x+1;\ bbox[2] = x + 1; \
}\ } \
}\ } \
}\ } \
if (has_data) {\ if (has_data) { \
if (bbox[1] < 0) {\ if (bbox[1] < 0) { \
bbox[1] = y;\ bbox[1] = y; \
}\ } \
bbox[3] = y+1;\ bbox[3] = y + 1; \
}\ } \
} }
if (im->image8) { if (im->image8) {
@ -60,16 +57,15 @@ ImagingGetBBox(Imaging im, int bbox[4])
} else { } else {
INT32 mask = 0xffffffff; INT32 mask = 0xffffffff;
if (im->bands == 3) { if (im->bands == 3) {
((UINT8*) &mask)[3] = 0; ((UINT8 *)&mask)[3] = 0;
} else if (strcmp(im->mode, "RGBa") == 0 || } else if (
strcmp(im->mode, "RGBA") == 0 || strcmp(im->mode, "RGBa") == 0 || strcmp(im->mode, "RGBA") == 0 ||
strcmp(im->mode, "La") == 0 || strcmp(im->mode, "La") == 0 || strcmp(im->mode, "LA") == 0 ||
strcmp(im->mode, "LA") == 0 || strcmp(im->mode, "PA") == 0) {
strcmp(im->mode, "PA") == 0) {
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
mask = 0x000000ff; mask = 0x000000ff;
#else #else
mask = 0xff000000; mask = 0xff000000;
#endif #endif
} }
GETBBOX(image32, mask); GETBBOX(image32, mask);
@ -83,10 +79,8 @@ ImagingGetBBox(Imaging im, int bbox[4])
return 1; /* ok */ return 1; /* ok */
} }
int int
ImagingGetProjection(Imaging im, UINT8* xproj, UINT8* yproj) ImagingGetProjection(Imaging im, UINT8 *xproj, UINT8 *yproj) {
{
/* Get projection arrays for non-zero data in the image.*/ /* Get projection arrays for non-zero data in the image.*/
int x, y; int x, y;
@ -96,26 +90,26 @@ ImagingGetProjection(Imaging im, UINT8* xproj, UINT8* yproj)
memset(xproj, 0, im->xsize); memset(xproj, 0, im->xsize);
memset(yproj, 0, im->ysize); memset(yproj, 0, im->ysize);
#define GETPROJ(image, mask)\ #define GETPROJ(image, mask) \
for (y = 0; y < im->ysize; y++) {\ for (y = 0; y < im->ysize; y++) { \
has_data = 0;\ has_data = 0; \
for (x = 0; x < im->xsize; x++) {\ for (x = 0; x < im->xsize; x++) { \
if (im->image[y][x] & mask) {\ if (im->image[y][x] & mask) { \
has_data = 1;\ has_data = 1; \
xproj[x] = 1;\ xproj[x] = 1; \
}\ } \
}\ } \
if (has_data) {\ if (has_data) { \
yproj[y] = 1;\ yproj[y] = 1; \
}\ } \
} }
if (im->image8) { if (im->image8) {
GETPROJ(image8, 0xff); GETPROJ(image8, 0xff);
} else { } else {
INT32 mask = 0xffffffff; INT32 mask = 0xffffffff;
if (im->bands == 3) { if (im->bands == 3) {
((UINT8*) &mask)[3] = 0; ((UINT8 *)&mask)[3] = 0;
} }
GETPROJ(image32, mask); GETPROJ(image32, mask);
} }
@ -123,16 +117,14 @@ ImagingGetProjection(Imaging im, UINT8* xproj, UINT8* yproj)
return 1; /* ok */ return 1; /* ok */
} }
int int
ImagingGetExtrema(Imaging im, void *extrema) ImagingGetExtrema(Imaging im, void *extrema) {
{
int x, y; int x, y;
INT32 imin, imax; INT32 imin, imax;
FLOAT32 fmin, fmax; FLOAT32 fmin, fmax;
if (im->bands != 1) { if (im->bands != 1) {
(void) ImagingError_ModeError(); (void)ImagingError_ModeError();
return -1; /* mismatch */ return -1; /* mismatch */
} }
@ -141,111 +133,109 @@ ImagingGetExtrema(Imaging im, void *extrema)
} }
switch (im->type) { switch (im->type) {
case IMAGING_TYPE_UINT8: case IMAGING_TYPE_UINT8:
imin = imax = im->image8[0][0]; imin = imax = im->image8[0][0];
for (y = 0; y < im->ysize; y++) { for (y = 0; y < im->ysize; y++) {
UINT8* in = im->image8[y]; UINT8 *in = im->image8[y];
for (x = 0; x < im->xsize; x++) { for (x = 0; x < im->xsize; x++) {
if (imin > in[x]) { if (imin > in[x]) {
imin = in[x]; imin = in[x];
} else if (imax < in[x]) { } else if (imax < in[x]) {
imax = in[x]; imax = in[x];
}
} }
} }
} ((UINT8 *)extrema)[0] = (UINT8)imin;
((UINT8*) extrema)[0] = (UINT8) imin; ((UINT8 *)extrema)[1] = (UINT8)imax;
((UINT8*) extrema)[1] = (UINT8) imax; break;
break; case IMAGING_TYPE_INT32:
case IMAGING_TYPE_INT32: imin = imax = im->image32[0][0];
imin = imax = im->image32[0][0]; for (y = 0; y < im->ysize; y++) {
for (y = 0; y < im->ysize; y++) { INT32 *in = im->image32[y];
INT32* in = im->image32[y]; for (x = 0; x < im->xsize; x++) {
for (x = 0; x < im->xsize; x++) { if (imin > in[x]) {
if (imin > in[x]) { imin = in[x];
imin = in[x]; } else if (imax < in[x]) {
} else if (imax < in[x]) { imax = in[x];
imax = in[x]; }
} }
} }
} memcpy(extrema, &imin, sizeof(imin));
memcpy(extrema, &imin, sizeof(imin)); memcpy(((char *)extrema) + sizeof(imin), &imax, sizeof(imax));
memcpy(((char*)extrema) + sizeof(imin), &imax, sizeof(imax)); break;
break; case IMAGING_TYPE_FLOAT32:
case IMAGING_TYPE_FLOAT32: fmin = fmax = ((FLOAT32 *)im->image32[0])[0];
fmin = fmax = ((FLOAT32*) im->image32[0])[0]; for (y = 0; y < im->ysize; y++) {
for (y = 0; y < im->ysize; y++) { FLOAT32 *in = (FLOAT32 *)im->image32[y];
FLOAT32* in = (FLOAT32*) im->image32[y]; for (x = 0; x < im->xsize; x++) {
for (x = 0; x < im->xsize; x++) { if (fmin > in[x]) {
if (fmin > in[x]) { fmin = in[x];
fmin = in[x]; } else if (fmax < in[x]) {
} else if (fmax < in[x]) { fmax = in[x];
fmax = in[x]; }
} }
} }
} memcpy(extrema, &fmin, sizeof(fmin));
memcpy(extrema, &fmin, sizeof(fmin)); memcpy(((char *)extrema) + sizeof(fmin), &fmax, sizeof(fmax));
memcpy(((char*)extrema) + sizeof(fmin), &fmax, sizeof(fmax)); break;
break; case IMAGING_TYPE_SPECIAL:
case IMAGING_TYPE_SPECIAL: if (strcmp(im->mode, "I;16") == 0) {
if (strcmp(im->mode, "I;16") == 0) { UINT16 v;
UINT16 v; UINT8 *pixel = *im->image8;
UINT8* pixel = *im->image8;
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
v = pixel[0] + (pixel[1] << 8); v = pixel[0] + (pixel[1] << 8);
#else #else
memcpy(&v, pixel, sizeof(v)); memcpy(&v, pixel, sizeof(v));
#endif #endif
imin = imax = v; imin = imax = v;
for (y = 0; y < im->ysize; y++) { for (y = 0; y < im->ysize; y++) {
for (x = 0; x < im->xsize; x++) { for (x = 0; x < im->xsize; x++) {
pixel = (UINT8*)im->image[y] + x * sizeof(v); pixel = (UINT8 *)im->image[y] + x * sizeof(v);
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
v = pixel[0] + (pixel[1] << 8); v = pixel[0] + (pixel[1] << 8);
#else #else
memcpy(&v, pixel, sizeof(v)); memcpy(&v, pixel, sizeof(v));
#endif #endif
if (imin > v) { if (imin > v) {
imin = v; imin = v;
} else if (imax < v) { } else if (imax < v) {
imax = v; imax = v;
} }
} }
} }
v = (UINT16) imin; v = (UINT16)imin;
memcpy(extrema, &v, sizeof(v)); memcpy(extrema, &v, sizeof(v));
v = (UINT16) imax; v = (UINT16)imax;
memcpy(((char*)extrema) + sizeof(v), &v, sizeof(v)); memcpy(((char *)extrema) + sizeof(v), &v, sizeof(v));
break; break;
} }
/* FALL THROUGH */ /* FALL THROUGH */
default: default:
(void) ImagingError_ModeError(); (void)ImagingError_ModeError();
return -1; return -1;
} }
return 1; /* ok */ return 1; /* ok */
} }
/* static ImagingColorItem* getcolors8(Imaging im, int maxcolors, int* size);*/ /* static ImagingColorItem* getcolors8(Imaging im, int maxcolors, int* size);*/
static ImagingColorItem* getcolors32(Imaging im, int maxcolors, int* size); static ImagingColorItem *
getcolors32(Imaging im, int maxcolors, int *size);
ImagingColorItem* ImagingColorItem *
ImagingGetColors(Imaging im, int maxcolors, int* size) ImagingGetColors(Imaging im, int maxcolors, int *size) {
{
/* FIXME: add support for 8-bit images */ /* FIXME: add support for 8-bit images */
return getcolors32(im, maxcolors, size); return getcolors32(im, maxcolors, size);
} }
static ImagingColorItem* static ImagingColorItem *
getcolors32(Imaging im, int maxcolors, int* size) getcolors32(Imaging im, int maxcolors, int *size) {
{
unsigned int h; unsigned int h;
unsigned int i, incr; unsigned int i, incr;
int colors; int colors;
INT32 pixel_mask; INT32 pixel_mask;
int x, y; int x, y;
ImagingColorItem* table; ImagingColorItem *table;
ImagingColorItem* v; ImagingColorItem *v;
unsigned int code_size; unsigned int code_size;
unsigned int code_poly; unsigned int code_poly;
@ -256,19 +246,19 @@ getcolors32(Imaging im, int maxcolors, int* size)
Python's Unicode property database (written by yours truly) /F */ Python's Unicode property database (written by yours truly) /F */
static int SIZES[] = { static int SIZES[] = {
4,3, 8,3, 16,3, 32,5, 64,3, 128,3, 256,29, 512,17, 1024,9, 2048,5, 4, 3, 8, 3, 16, 3, 32, 5, 64, 3,
4096,83, 8192,27, 16384,43, 32768,3, 65536,45, 131072,9, 262144,39, 128, 3, 256, 29, 512, 17, 1024, 9, 2048, 5,
524288,39, 1048576,9, 2097152,5, 4194304,3, 8388608,33, 16777216,27, 4096, 83, 8192, 27, 16384, 43, 32768, 3, 65536, 45,
33554432,9, 67108864,71, 134217728,39, 268435456,9, 536870912,5, 131072, 9, 262144, 39, 524288, 39, 1048576, 9, 2097152, 5,
1073741824,83, 0 4194304, 3, 8388608, 33, 16777216, 27, 33554432, 9, 67108864, 71,
}; 134217728, 39, 268435456, 9, 536870912, 5, 1073741824, 83, 0};
code_size = code_poly = code_mask = 0; code_size = code_poly = code_mask = 0;
for (i = 0; SIZES[i]; i += 2) { for (i = 0; SIZES[i]; i += 2) {
if (SIZES[i] > maxcolors) { if (SIZES[i] > maxcolors) {
code_size = SIZES[i]; code_size = SIZES[i];
code_poly = SIZES[i+1]; code_poly = SIZES[i + 1];
code_mask = code_size - 1; code_mask = code_size - 1;
break; break;
} }
@ -292,13 +282,13 @@ getcolors32(Imaging im, int maxcolors, int* size)
pixel_mask = 0xffffffff; pixel_mask = 0xffffffff;
if (im->bands == 3) { if (im->bands == 3) {
((UINT8*) &pixel_mask)[3] = 0; ((UINT8 *)&pixel_mask)[3] = 0;
} }
colors = 0; colors = 0;
for (y = 0; y < im->ysize; y++) { for (y = 0; y < im->ysize; y++) {
INT32* p = im->image32[y]; INT32 *p = im->image32[y];
for (x = 0; x < im->xsize; x++) { for (x = 0; x < im->xsize; x++) {
INT32 pixel = p[x] & pixel_mask; INT32 pixel = p[x] & pixel_mask;
h = (pixel); /* null hashing */ h = (pixel); /* null hashing */
@ -309,7 +299,8 @@ getcolors32(Imaging im, int maxcolors, int* size)
if (colors++ == maxcolors) { if (colors++ == maxcolors) {
goto overflow; goto overflow;
} }
v->x = x; v->y = y; v->x = x;
v->y = y;
v->pixel = pixel; v->pixel = pixel;
v->count = 1; v->count = 1;
continue; continue;
@ -329,7 +320,8 @@ getcolors32(Imaging im, int maxcolors, int* size)
if (colors++ == maxcolors) { if (colors++ == maxcolors) {
goto overflow; goto overflow;
} }
v->x = x; v->y = y; v->x = x;
v->y = y;
v->pixel = pixel; v->pixel = pixel;
v->count = 1; v->count = 1;
break; break;
@ -348,7 +340,7 @@ getcolors32(Imaging im, int maxcolors, int* size)
overflow: overflow:
/* pack the table */ /* pack the table */
for (x = y = 0; x < (int) code_size; x++) for (x = y = 0; x < (int)code_size; x++)
if (table[x].count) { if (table[x].count) {
if (x != y) { if (x != y) {
table[y] = table[x]; table[y] = table[x];

View File

@ -7,17 +7,14 @@
* Copyright (c) Fredrik Lundh 1995-96. * Copyright (c) Fredrik Lundh 1995-96.
*/ */
/* Max size for a LZW code word. */ /* Max size for a LZW code word. */
#define GIFBITS 12 #define GIFBITS 12
#define GIFTABLE (1<<GIFBITS)
#define GIFBUFFER (1<<GIFBITS)
#define GIFTABLE (1 << GIFBITS)
#define GIFBUFFER (1 << GIFBITS)
typedef struct { typedef struct {
/* CONFIGURATION */ /* CONFIGURATION */
/* Initial number of bits. The caller should clear all fields in /* Initial number of bits. The caller should clear all fields in
@ -65,15 +62,13 @@ typedef struct {
} GIFDECODERSTATE; } GIFDECODERSTATE;
typedef struct GIFENCODERBLOCK_T typedef struct GIFENCODERBLOCK_T {
{
struct GIFENCODERBLOCK_T *next; struct GIFENCODERBLOCK_T *next;
int size; int size;
UINT8 data[255]; UINT8 data[255];
} GIFENCODERBLOCK; } GIFENCODERBLOCK;
typedef struct { typedef struct {
/* CONFIGURATION */ /* CONFIGURATION */
/* Initial number of bits. The caller should clear all fields in /* Initial number of bits. The caller should clear all fields in
@ -96,13 +91,13 @@ typedef struct {
int bitcount; int bitcount;
/* Output buffer list (linked list) */ /* Output buffer list (linked list) */
GIFENCODERBLOCK* block; /* current block */ GIFENCODERBLOCK *block; /* current block */
GIFENCODERBLOCK* flush; /* output queue */ GIFENCODERBLOCK *flush; /* output queue */
GIFENCODERBLOCK* free; /* if not null, use this */ GIFENCODERBLOCK *free; /* if not null, use this */
/* Fields used for run-length encoding */ /* Fields used for run-length encoding */
int first; /* true if we haven't read the first pixel */ int first; /* true if we haven't read the first pixel */
int last; /* last byte value seen */ int last; /* last byte value seen */
int count; /* how many bytes with that value we've seen */ int count; /* how many bytes with that value we've seen */
int lastcode; int lastcode;

View File

@ -21,7 +21,6 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#include <stdio.h> #include <stdio.h>
@ -29,48 +28,44 @@
#include "Gif.h" #include "Gif.h"
#define NEWLINE(state, context) \
#define NEWLINE(state, context) {\ { \
state->x = 0;\ state->x = 0; \
state->y += context->step;\ state->y += context->step; \
while (state->y >= state->ysize)\ while (state->y >= state->ysize) switch (context->interlace) { \
switch (context->interlace) {\ case 1: \
case 1:\ context->repeat = state->y = 4; \
context->repeat = state->y = 4;\ context->interlace = 2; \
context->interlace = 2;\ break; \
break;\ case 2: \
case 2:\ context->step = 4; \
context->step = 4;\ context->repeat = state->y = 2; \
context->repeat = state->y = 2;\ context->interlace = 3; \
context->interlace = 3;\ break; \
break;\ case 3: \
case 3:\ context->step = 2; \
context->step = 2;\ context->repeat = state->y = 1; \
context->repeat = state->y = 1;\ context->interlace = 0; \
context->interlace = 0;\ break; \
break;\ default: \
default:\ return -1; \
return -1;\ } \
}\ if (state->y < state->ysize) { \
if (state->y < state->ysize) {\ out = im->image8[state->y + state->yoff] + state->xoff; \
out = im->image8[state->y + state->yoff] + state->xoff;\ } \
}\ }
}
int int
ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t bytes) ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes) {
{ UINT8 *p;
UINT8* p; UINT8 *out;
UINT8* out;
int c, i; int c, i;
int thiscode; int thiscode;
GIFDECODERSTATE *context = (GIFDECODERSTATE*) state->context; GIFDECODERSTATE *context = (GIFDECODERSTATE *)state->context;
UINT8 *ptr = buffer; UINT8 *ptr = buffer;
if (!state->state) { if (!state->state) {
/* Initialise state */ /* Initialise state */
if (context->bits < 0 || context->bits > 12) { if (context->bits < 0 || context->bits > 12) {
state->errcode = IMAGING_CODEC_CONFIG; state->errcode = IMAGING_CODEC_CONFIG;
@ -97,9 +92,7 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
out = im->image8[state->y + state->yoff] + state->xoff + state->x; out = im->image8[state->y + state->yoff] + state->xoff + state->x;
for (;;) { for (;;) {
if (state->state == 1) { if (state->state == 1) {
/* First free entry in table */ /* First free entry in table */
context->next = context->clear + 2; context->next = context->clear + 2;
@ -115,7 +108,6 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
} }
if (context->bufferindex < GIFBUFFER) { if (context->bufferindex < GIFBUFFER) {
/* Return whole buffer in one chunk */ /* Return whole buffer in one chunk */
i = GIFBUFFER - context->bufferindex; i = GIFBUFFER - context->bufferindex;
p = &context->buffer[context->bufferindex]; p = &context->buffer[context->bufferindex];
@ -123,24 +115,21 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
context->bufferindex = GIFBUFFER; context->bufferindex = GIFBUFFER;
} else { } else {
/* Get current symbol */ /* Get current symbol */
while (context->bitcount < context->codesize) { while (context->bitcount < context->codesize) {
if (context->blocksize > 0) { if (context->blocksize > 0) {
/* Read next byte */ /* Read next byte */
c = *ptr++; bytes--; c = *ptr++;
bytes--;
context->blocksize--; context->blocksize--;
/* New bits are shifted in from from the left. */ /* New bits are shifted in from from the left. */
context->bitbuffer |= (INT32) c << context->bitcount; context->bitbuffer |= (INT32)c << context->bitcount;
context->bitcount += 8; context->bitcount += 8;
} else { } else {
/* New GIF block */ /* New GIF block */
/* We don't start decoding unless we have a full block */ /* We don't start decoding unless we have a full block */
@ -148,19 +137,19 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
return ptr - buffer; return ptr - buffer;
} }
c = *ptr; c = *ptr;
if (bytes < c+1) { if (bytes < c + 1) {
return ptr - buffer; return ptr - buffer;
} }
context->blocksize = c; context->blocksize = c;
ptr++; bytes--; ptr++;
bytes--;
} }
} }
/* Extract current symbol from bit buffer. */ /* Extract current symbol from bit buffer. */
c = (int) context->bitbuffer & context->codemask; c = (int)context->bitbuffer & context->codemask;
/* Adjust buffer */ /* Adjust buffer */
context->bitbuffer >>= context->codesize; context->bitbuffer >>= context->codesize;
@ -185,7 +174,6 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
p = &context->lastdata; p = &context->lastdata;
if (state->state == 2) { if (state->state == 2) {
/* First valid symbol after clear; use as is */ /* First valid symbol after clear; use as is */
if (c > context->clear) { if (c > context->clear) {
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
@ -196,7 +184,6 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
state->state = 3; state->state = 3;
} else { } else {
thiscode = c; thiscode = c;
if (c > context->next) { if (c > context->next) {
@ -205,7 +192,6 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
} }
if (c == context->next) { if (c == context->next) {
/* c == next is allowed. not sure why. */ /* c == next is allowed. not sure why. */
if (context->bufferindex <= 0) { if (context->bufferindex <= 0) {
@ -213,15 +199,12 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
return -1; return -1;
} }
context->buffer[--context->bufferindex] = context->buffer[--context->bufferindex] = context->lastdata;
context->lastdata;
c = context->lastcode; c = context->lastcode;
} }
while (c >= context->clear) { while (c >= context->clear) {
/* Copy data string to buffer (beginning from right) */ /* Copy data string to buffer (beginning from right) */
if (context->bufferindex <= 0 || c >= GIFTABLE) { if (context->bufferindex <= 0 || c >= GIFTABLE) {
@ -229,8 +212,7 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
return -1; return -1;
} }
context->buffer[--context->bufferindex] = context->buffer[--context->bufferindex] = context->data[c];
context->data[c];
c = context->link[c]; c = context->link[c];
} }
@ -238,26 +220,22 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
context->lastdata = c; context->lastdata = c;
if (context->next < GIFTABLE) { if (context->next < GIFTABLE) {
/* We'll only add this symbol if we have room /* We'll only add this symbol if we have room
for it (take advise, Netscape!) */ for it (take advise, Netscape!) */
context->data[context->next] = c; context->data[context->next] = c;
context->link[context->next] = context->lastcode; context->link[context->next] = context->lastcode;
if (context->next == context->codemask && if (context->next == context->codemask &&
context->codesize < GIFBITS) { context->codesize < GIFBITS) {
/* Expand code size */ /* Expand code size */
context->codesize++; context->codesize++;
context->codemask = (1 << context->codesize) - 1; context->codemask = (1 << context->codesize) - 1;
} }
context->next++; context->next++;
} }
context->lastcode = thiscode; context->lastcode = thiscode;
} }
} }
@ -273,7 +251,7 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
/* FIXME: should we handle the transparency index in here??? */ /* FIXME: should we handle the transparency index in here??? */
if (i == 1) { if (i == 1) {
if (state->x < state->xsize-1) { if (state->x < state->xsize - 1) {
/* Single pixel, not at the end of the line. */ /* Single pixel, not at the end of the line. */
*out++ = p[0]; *out++ = p[0];
state->x++; state->x++;
@ -282,7 +260,7 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
} else if (state->x + i <= state->xsize) { } else if (state->x + i <= state->xsize) {
/* This string fits into current line. */ /* This string fits into current line. */
memcpy(out, p, i); memcpy(out, p, i);
out += i; out += i;
state->x += i; state->x += i;
if (state->x == state->xsize) { if (state->x == state->xsize) {
NEWLINE(state, context); NEWLINE(state, context);

View File

@ -35,12 +35,11 @@ enum { INIT, ENCODE, ENCODE_EOF, FLUSH, EXIT };
necessary. */ necessary. */
static inline int static inline int
emit(GIFENCODERSTATE *context, int byte) emit(GIFENCODERSTATE *context, int byte) {
{
/* write a byte to the output buffer */ /* write a byte to the output buffer */
if (!context->block || context->block->size == 255) { if (!context->block || context->block->size == 255) {
GIFENCODERBLOCK* block; GIFENCODERBLOCK *block;
/* no room in the current block (or no current block); /* no room in the current block (or no current block);
allocate a new one */ allocate a new one */
@ -74,7 +73,6 @@ emit(GIFENCODERSTATE *context, int byte)
block->next = NULL; block->next = NULL;
context->block = block; context->block = block;
} }
/* write new byte to block */ /* write new byte to block */
@ -86,68 +84,68 @@ emit(GIFENCODERSTATE *context, int byte)
/* write a code word to the current block. this is a macro to make /* write a code word to the current block. this is a macro to make
sure it's inlined on all platforms */ sure it's inlined on all platforms */
#define EMIT(code) {\ #define EMIT(code) \
context->bitbuffer |= ((INT32) (code)) << context->bitcount;\ { \
context->bitcount += 9;\ context->bitbuffer |= ((INT32)(code)) << context->bitcount; \
while (context->bitcount >= 8) {\ context->bitcount += 9; \
if (!emit(context, (UINT8) context->bitbuffer)) {\ while (context->bitcount >= 8) { \
state->errcode = IMAGING_CODEC_MEMORY;\ if (!emit(context, (UINT8)context->bitbuffer)) { \
return 0;\ state->errcode = IMAGING_CODEC_MEMORY; \
}\ return 0; \
context->bitbuffer >>= 8;\ } \
context->bitcount -= 8;\ context->bitbuffer >>= 8; \
}\ context->bitcount -= 8; \
} } \
}
/* write a run. we use a combination of literals and combinations of /* write a run. we use a combination of literals and combinations of
literals. this can give quite decent compression for images with literals. this can give quite decent compression for images with
long stretches of identical pixels. but remember: if you want long stretches of identical pixels. but remember: if you want
really good compression, use another file format. */ really good compression, use another file format. */
#define EMIT_RUN(label) {\ #define EMIT_RUN(label) \
label:\ { \
while (context->count > 0) {\ label: \
int run = 2;\ while (context->count > 0) { \
EMIT(context->last);\ int run = 2; \
context->count--;\ EMIT(context->last); \
if (state->count++ == LAST_CODE) {\ context->count--; \
EMIT(CLEAR_CODE);\ if (state->count++ == LAST_CODE) { \
state->count = FIRST_CODE;\ EMIT(CLEAR_CODE); \
goto label;\ state->count = FIRST_CODE; \
}\ goto label; \
while (context->count >= run) {\ } \
EMIT(state->count - 1);\ while (context->count >= run) { \
context->count -= run;\ EMIT(state->count - 1); \
run++;\ context->count -= run; \
if (state->count++ == LAST_CODE) {\ run++; \
EMIT(CLEAR_CODE);\ if (state->count++ == LAST_CODE) { \
state->count = FIRST_CODE;\ EMIT(CLEAR_CODE); \
goto label;\ state->count = FIRST_CODE; \
}\ goto label; \
}\ } \
if (context->count > 1) {\ } \
EMIT(state->count - 1 - (run - context->count));\ if (context->count > 1) { \
context->count = 0;\ EMIT(state->count - 1 - (run - context->count)); \
if (state->count++ == LAST_CODE) {\ context->count = 0; \
EMIT(CLEAR_CODE);\ if (state->count++ == LAST_CODE) { \
state->count = FIRST_CODE;\ EMIT(CLEAR_CODE); \
}\ state->count = FIRST_CODE; \
break;\ } \
}\ break; \
}\ } \
} } \
}
int int
ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
{ UINT8 *ptr;
UINT8* ptr;
int this; int this;
GIFENCODERBLOCK* block; GIFENCODERBLOCK *block;
GIFENCODERSTATE *context = (GIFENCODERSTATE*) state->context; GIFENCODERSTATE *context = (GIFENCODERSTATE *)state->context;
if (!state->state) { if (!state->state) {
/* place a clear code in the output buffer */ /* place a clear code in the output buffer */
context->bitbuffer = CLEAR_CODE; context->bitbuffer = CLEAR_CODE;
context->bitcount = 9; context->bitcount = 9;
@ -167,22 +165,17 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
if (state->xsize <= 0 || state->ysize <= 0) { if (state->xsize <= 0 || state->ysize <= 0) {
state->state = ENCODE_EOF; state->state = ENCODE_EOF;
} }
} }
ptr = buf; ptr = buf;
for (;;) for (;;) switch (state->state) {
switch (state->state) {
case INIT: case INIT:
case ENCODE: case ENCODE:
/* identify and store a run of pixels */ /* identify and store a run of pixels */
if (state->x == 0 || state->x >= state->xsize) { if (state->x == 0 || state->x >= state->xsize) {
if (!context->interlace && state->y >= state->ysize) { if (!context->interlace && state->y >= state->ysize) {
state->state = ENCODE_EOF; state->state = ENCODE_EOF;
break; break;
@ -196,9 +189,9 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
/* get another line of data */ /* get another line of data */
state->shuffle( state->shuffle(
state->buffer, state->buffer,
(UINT8*) im->image[state->y + state->yoff] + (UINT8 *)im->image[state->y + state->yoff] +
state->xoff * im->pixelsize, state->xsize state->xoff * im->pixelsize,
); state->xsize);
state->x = 0; state->x = 0;
@ -231,7 +224,6 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
/* just make sure we don't loop forever */ /* just make sure we don't loop forever */
context->interlace = 0; context->interlace = 0;
} }
} }
/* Potential special case for xsize==1 */ /* Potential special case for xsize==1 */
if (state->x < state->xsize) { if (state->x < state->xsize) {
@ -250,7 +242,6 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
} }
break; break;
case ENCODE_EOF: case ENCODE_EOF:
/* write the final run */ /* write the final run */
@ -261,7 +252,7 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
/* empty the bit buffer */ /* empty the bit buffer */
while (context->bitcount > 0) { while (context->bitcount > 0) {
if (!emit(context, (UINT8) context->bitbuffer)) { if (!emit(context, (UINT8)context->bitbuffer)) {
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
return 0; return 0;
} }
@ -271,7 +262,7 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
/* flush the last block, and exit */ /* flush the last block, and exit */
if (context->block) { if (context->block) {
GIFENCODERBLOCK* block; GIFENCODERBLOCK *block;
block = context->flush; block = context->flush;
while (block && block->next) { while (block && block->next) {
block = block->next; block = block->next;
@ -291,45 +282,41 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
case EXIT: case EXIT:
case FLUSH: case FLUSH:
while (context->flush) { while (context->flush) {
/* get a block from the flush queue */
/* get a block from the flush queue */ block = context->flush;
block = context->flush;
if (block->size > 0) {
/* make sure it fits into the output buffer */
if (bytes < block->size+1) {
return ptr - buf;
}
ptr[0] = block->size;
memcpy(ptr+1, block->data, block->size);
ptr += block->size+1;
bytes -= block->size+1;
if (block->size > 0) {
/* make sure it fits into the output buffer */
if (bytes < block->size + 1) {
return ptr - buf;
} }
context->flush = block->next; ptr[0] = block->size;
memcpy(ptr + 1, block->data, block->size);
if (context->free) {
free(context->free);
}
context->free = block;
ptr += block->size + 1;
bytes -= block->size + 1;
} }
if (state->state == EXIT) { context->flush = block->next;
/* this was the last block! */
if (context->free) {
free(context->free);
}
state->errcode = IMAGING_CODEC_END;
return ptr - buf;
}
state->state = ENCODE; if (context->free) {
break; free(context->free);
} }
context->free = block;
}
if (state->state == EXIT) {
/* this was the last block! */
if (context->free) {
free(context->free);
}
state->errcode = IMAGING_CODEC_END;
return ptr - buf;
}
state->state = ENCODE;
break;
}
} }

View File

@ -13,23 +13,22 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#define HEX(v) ((v >= '0' && v <= '9') ? v - '0' :\ #define HEX(v) \
(v >= 'a' && v <= 'f') ? v - 'a' + 10 :\ ((v >= '0' && v <= '9') ? v - '0' \
(v >= 'A' && v <= 'F') ? v - 'A' + 10 : -1) : (v >= 'a' && v <= 'f') ? v - 'a' + 10 \
: (v >= 'A' && v <= 'F') ? v - 'A' + 10 \
: -1)
int int
ImagingHexDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes) ImagingHexDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
{ UINT8 *ptr;
UINT8* ptr;
int a, b; int a, b;
ptr = buf; ptr = buf;
for (;;) { for (;;) {
if (bytes < 2) { if (bytes < 2) {
return ptr - buf; return ptr - buf;
} }
@ -38,22 +37,19 @@ ImagingHexDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
b = HEX(ptr[1]); b = HEX(ptr[1]);
if (a < 0 || b < 0) { if (a < 0 || b < 0) {
ptr++; ptr++;
bytes--; bytes--;
} else { } else {
ptr += 2; ptr += 2;
bytes -= 2; bytes -= 2;
state->buffer[state->x] = (a<<4) + b; state->buffer[state->x] = (a << 4) + b;
if (++state->x >= state->bytes) { if (++state->x >= state->bytes) {
/* Got a full line, unpack it */ /* Got a full line, unpack it */
state->shuffle((UINT8*) im->image[state->y], state->buffer, state->shuffle(
state->xsize); (UINT8 *)im->image[state->y], state->buffer, state->xsize);
state->x = 0; state->x = 0;
@ -62,7 +58,6 @@ ImagingHexDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
return -1; return -1;
} }
} }
} }
} }
} }

View File

@ -16,10 +16,8 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
/* HISTOGRAM */ /* HISTOGRAM */
/* -------------------------------------------------------------------- /* --------------------------------------------------------------------
* Take a histogram of an image. Returns a histogram object containing * Take a histogram of an image. Returns a histogram object containing
@ -27,8 +25,7 @@
*/ */
void void
ImagingHistogramDelete(ImagingHistogram h) ImagingHistogramDelete(ImagingHistogram h) {
{
if (h) { if (h) {
if (h->histogram) { if (h->histogram) {
free(h->histogram); free(h->histogram);
@ -38,31 +35,29 @@ ImagingHistogramDelete(ImagingHistogram h)
} }
ImagingHistogram ImagingHistogram
ImagingHistogramNew(Imaging im) ImagingHistogramNew(Imaging im) {
{
ImagingHistogram h; ImagingHistogram h;
/* Create histogram descriptor */ /* Create histogram descriptor */
h = calloc(1, sizeof(struct ImagingHistogramInstance)); h = calloc(1, sizeof(struct ImagingHistogramInstance));
if (!h) { if (!h) {
return (ImagingHistogram) ImagingError_MemoryError(); return (ImagingHistogram)ImagingError_MemoryError();
} }
strncpy(h->mode, im->mode, IMAGING_MODE_LENGTH-1); strncpy(h->mode, im->mode, IMAGING_MODE_LENGTH - 1);
h->mode[IMAGING_MODE_LENGTH-1] = 0; h->mode[IMAGING_MODE_LENGTH - 1] = 0;
h->bands = im->bands; h->bands = im->bands;
h->histogram = calloc(im->pixelsize, 256 * sizeof(long)); h->histogram = calloc(im->pixelsize, 256 * sizeof(long));
if (!h->histogram) { if (!h->histogram) {
free(h); free(h);
return (ImagingHistogram) ImagingError_MemoryError(); return (ImagingHistogram)ImagingError_MemoryError();
} }
return h; return h;
} }
ImagingHistogram ImagingHistogram
ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax) ImagingGetHistogram(Imaging im, Imaging imMask, void *minmax) {
{
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
int x, y, i; int x, y, i;
ImagingHistogram h; ImagingHistogram h;
@ -107,13 +102,13 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax)
} }
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
for (y = 0; y < im->ysize; y++) { for (y = 0; y < im->ysize; y++) {
UINT8* in = (UINT8*) im->image32[y]; UINT8 *in = (UINT8 *)im->image32[y];
for (x = 0; x < im->xsize; x++) { for (x = 0; x < im->xsize; x++) {
if (imMask->image8[y][x] != 0) { if (imMask->image8[y][x] != 0) {
h->histogram[(*in++)]++; h->histogram[(*in++)]++;
h->histogram[(*in++)+256]++; h->histogram[(*in++) + 256]++;
h->histogram[(*in++)+512]++; h->histogram[(*in++) + 512]++;
h->histogram[(*in++)+768]++; h->histogram[(*in++) + 768]++;
} else { } else {
in += 4; in += 4;
} }
@ -136,12 +131,12 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax)
case IMAGING_TYPE_UINT8: case IMAGING_TYPE_UINT8:
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
for (y = 0; y < im->ysize; y++) { for (y = 0; y < im->ysize; y++) {
UINT8* in = (UINT8*) im->image[y]; UINT8 *in = (UINT8 *)im->image[y];
for (x = 0; x < im->xsize; x++) { for (x = 0; x < im->xsize; x++) {
h->histogram[(*in++)]++; h->histogram[(*in++)]++;
h->histogram[(*in++)+256]++; h->histogram[(*in++) + 256]++;
h->histogram[(*in++)+512]++; h->histogram[(*in++) + 512]++;
h->histogram[(*in++)+768]++; h->histogram[(*in++) + 768]++;
} }
} }
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
@ -155,16 +150,16 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax)
break; break;
} }
memcpy(&imin, minmax, sizeof(imin)); memcpy(&imin, minmax, sizeof(imin));
memcpy(&imax, ((char*)minmax) + sizeof(imin), sizeof(imax)); memcpy(&imax, ((char *)minmax) + sizeof(imin), sizeof(imax));
if (imin >= imax) { if (imin >= imax) {
break; break;
} }
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
scale = 255.0F / (imax - imin); scale = 255.0F / (imax - imin);
for (y = 0; y < im->ysize; y++) { for (y = 0; y < im->ysize; y++) {
INT32* in = im->image32[y]; INT32 *in = im->image32[y];
for (x = 0; x < im->xsize; x++) { for (x = 0; x < im->xsize; x++) {
i = (int) (((*in++)-imin)*scale); i = (int)(((*in++) - imin) * scale);
if (i >= 0 && i < 256) { if (i >= 0 && i < 256) {
h->histogram[i]++; h->histogram[i]++;
} }
@ -181,16 +176,16 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax)
break; break;
} }
memcpy(&fmin, minmax, sizeof(fmin)); memcpy(&fmin, minmax, sizeof(fmin));
memcpy(&fmax, ((char*)minmax) + sizeof(fmin), sizeof(fmax)); memcpy(&fmax, ((char *)minmax) + sizeof(fmin), sizeof(fmax));
if (fmin >= fmax) { if (fmin >= fmax) {
break; break;
} }
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
scale = 255.0F / (fmax - fmin); scale = 255.0F / (fmax - fmin);
for (y = 0; y < im->ysize; y++) { for (y = 0; y < im->ysize; y++) {
FLOAT32* in = (FLOAT32*) im->image32[y]; FLOAT32 *in = (FLOAT32 *)im->image32[y];
for (x = 0; x < im->xsize; x++) { for (x = 0; x < im->xsize; x++) {
i = (int) (((*in++)-fmin)*scale); i = (int)(((*in++) - fmin) * scale);
if (i >= 0 && i < 256) { if (i >= 0 && i < 256) {
h->histogram[i]++; h->histogram[i]++;
} }

View File

@ -35,20 +35,27 @@ struct ImagingDIBInstance {
ImagingShuffler unpack; ImagingShuffler unpack;
}; };
typedef struct ImagingDIBInstance* ImagingDIB; typedef struct ImagingDIBInstance *ImagingDIB;
extern char* ImagingGetModeDIB(int size_out[2]); extern char *
ImagingGetModeDIB(int size_out[2]);
extern ImagingDIB ImagingNewDIB(const char *mode, int xsize, int ysize); extern ImagingDIB
ImagingNewDIB(const char *mode, int xsize, int ysize);
extern void ImagingDeleteDIB(ImagingDIB im); extern void
ImagingDeleteDIB(ImagingDIB im);
extern void ImagingDrawDIB(ImagingDIB dib, void *dc, int dst[4], int src[4]); extern void
extern void ImagingExposeDIB(ImagingDIB dib, void *dc); ImagingDrawDIB(ImagingDIB dib, void *dc, int dst[4], int src[4]);
extern void
ImagingExposeDIB(ImagingDIB dib, void *dc);
extern int ImagingQueryPaletteDIB(ImagingDIB dib, void *dc); extern int
ImagingQueryPaletteDIB(ImagingDIB dib, void *dc);
extern void ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4]); extern void
ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4]);
#if defined(__cplusplus) #if defined(__cplusplus)
} }

View File

@ -10,7 +10,8 @@
#include "Python.h" #include "Python.h"
/* Workaround issue #2479 */ /* Workaround issue #2479 */
#if PY_VERSION_HEX < 0x03070000 && defined(PySlice_GetIndicesEx) && !defined(PYPY_VERSION) #if PY_VERSION_HEX < 0x03070000 && defined(PySlice_GetIndicesEx) && \
!defined(PYPY_VERSION)
#undef PySlice_GetIndicesEx #undef PySlice_GetIndicesEx
#endif #endif
@ -62,7 +63,7 @@
#define INT64 long #define INT64 long
#endif #endif
#define INT8 signed char #define INT8 signed char
#define UINT8 unsigned char #define UINT8 unsigned char
#define UINT16 unsigned INT16 #define UINT16 unsigned INT16
@ -76,11 +77,9 @@
#define FLOAT64 double #define FLOAT64 double
#ifdef _MSC_VER #ifdef _MSC_VER
typedef signed __int64 int64_t; typedef signed __int64 int64_t;
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
#define GCC_VERSION (__GNUC__ * 10000 \ #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
#endif #endif

View File

@ -10,20 +10,16 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "ImPlatform.h" #include "ImPlatform.h"
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
#ifndef M_PI #ifndef M_PI
#define M_PI 3.1415926535897932384626433832795 #define M_PI 3.1415926535897932384626433832795
#endif #endif
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* /*
@ -57,12 +53,12 @@ extern "C" {
/* Handles */ /* Handles */
typedef struct ImagingMemoryInstance* Imaging; typedef struct ImagingMemoryInstance *Imaging;
typedef struct ImagingAccessInstance* ImagingAccess; typedef struct ImagingAccessInstance *ImagingAccess;
typedef struct ImagingHistogramInstance* ImagingHistogram; typedef struct ImagingHistogramInstance *ImagingHistogram;
typedef struct ImagingOutlineInstance* ImagingOutline; typedef struct ImagingOutlineInstance *ImagingOutline;
typedef struct ImagingPaletteInstance* ImagingPalette; typedef struct ImagingPaletteInstance *ImagingPalette;
/* handle magics (used with PyCObject). */ /* handle magics (used with PyCObject). */
#define IMAGING_MAGIC "PIL Imaging" #define IMAGING_MAGIC "PIL Imaging"
@ -73,7 +69,8 @@ typedef struct ImagingPaletteInstance* ImagingPalette;
#define IMAGING_TYPE_FLOAT32 2 #define IMAGING_TYPE_FLOAT32 2
#define IMAGING_TYPE_SPECIAL 3 /* check mode for details */ #define IMAGING_TYPE_SPECIAL 3 /* check mode for details */
#define IMAGING_MODE_LENGTH 6+1 /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "BGR;xy") */ #define IMAGING_MODE_LENGTH \
6 + 1 /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "BGR;xy") */
typedef struct { typedef struct {
char *ptr; char *ptr;
@ -81,158 +78,178 @@ typedef struct {
} ImagingMemoryBlock; } ImagingMemoryBlock;
struct ImagingMemoryInstance { struct ImagingMemoryInstance {
/* Format */ /* Format */
char mode[IMAGING_MODE_LENGTH]; /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "BGR;xy") */ char mode[IMAGING_MODE_LENGTH]; /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK",
int type; /* Data type (IMAGING_TYPE_*) */ "YCbCr", "BGR;xy") */
int depth; /* Depth (ignored in this version) */ int type; /* Data type (IMAGING_TYPE_*) */
int bands; /* Number of bands (1, 2, 3, or 4) */ int depth; /* Depth (ignored in this version) */
int xsize; /* Image dimension. */ int bands; /* Number of bands (1, 2, 3, or 4) */
int xsize; /* Image dimension. */
int ysize; int ysize;
/* Colour palette (for "P" images only) */ /* Colour palette (for "P" images only) */
ImagingPalette palette; ImagingPalette palette;
/* Data pointers */ /* Data pointers */
UINT8 **image8; /* Set for 8-bit images (pixelsize=1). */ UINT8 **image8; /* Set for 8-bit images (pixelsize=1). */
INT32 **image32; /* Set for 32-bit images (pixelsize=4). */ INT32 **image32; /* Set for 32-bit images (pixelsize=4). */
/* Internals */ /* Internals */
char **image; /* Actual raster data. */ char **image; /* Actual raster data. */
char *block; /* Set if data is allocated in a single block. */ char *block; /* Set if data is allocated in a single block. */
ImagingMemoryBlock *blocks; /* Memory blocks for pixel storage */ ImagingMemoryBlock *blocks; /* Memory blocks for pixel storage */
int pixelsize; /* Size of a pixel, in bytes (1, 2 or 4) */ int pixelsize; /* Size of a pixel, in bytes (1, 2 or 4) */
int linesize; /* Size of a line, in bytes (xsize * pixelsize) */ int linesize; /* Size of a line, in bytes (xsize * pixelsize) */
/* Virtual methods */ /* Virtual methods */
void (*destroy)(Imaging im); void (*destroy)(Imaging im);
}; };
#define IMAGING_PIXEL_1(im, x, y) ((im)->image8[(y)][(x)])
#define IMAGING_PIXEL_L(im, x, y) ((im)->image8[(y)][(x)])
#define IMAGING_PIXEL_LA(im, x, y) ((im)->image[(y)][(x)*4])
#define IMAGING_PIXEL_P(im, x, y) ((im)->image8[(y)][(x)])
#define IMAGING_PIXEL_PA(im, x, y) ((im)->image[(y)][(x)*4])
#define IMAGING_PIXEL_I(im, x, y) ((im)->image32[(y)][(x)])
#define IMAGING_PIXEL_F(im, x, y) (((FLOAT32 *)(im)->image32[y])[x])
#define IMAGING_PIXEL_RGB(im, x, y) ((im)->image[(y)][(x)*4])
#define IMAGING_PIXEL_RGBA(im, x, y) ((im)->image[(y)][(x)*4])
#define IMAGING_PIXEL_CMYK(im, x, y) ((im)->image[(y)][(x)*4])
#define IMAGING_PIXEL_YCbCr(im, x, y) ((im)->image[(y)][(x)*4])
#define IMAGING_PIXEL_1(im,x,y) ((im)->image8[(y)][(x)]) #define IMAGING_PIXEL_UINT8(im, x, y) ((im)->image8[(y)][(x)])
#define IMAGING_PIXEL_L(im,x,y) ((im)->image8[(y)][(x)]) #define IMAGING_PIXEL_INT32(im, x, y) ((im)->image32[(y)][(x)])
#define IMAGING_PIXEL_LA(im,x,y) ((im)->image[(y)][(x)*4]) #define IMAGING_PIXEL_FLOAT32(im, x, y) (((FLOAT32 *)(im)->image32[y])[x])
#define IMAGING_PIXEL_P(im,x,y) ((im)->image8[(y)][(x)])
#define IMAGING_PIXEL_PA(im,x,y) ((im)->image[(y)][(x)*4])
#define IMAGING_PIXEL_I(im,x,y) ((im)->image32[(y)][(x)])
#define IMAGING_PIXEL_F(im,x,y) (((FLOAT32*)(im)->image32[y])[x])
#define IMAGING_PIXEL_RGB(im,x,y) ((im)->image[(y)][(x)*4])
#define IMAGING_PIXEL_RGBA(im,x,y) ((im)->image[(y)][(x)*4])
#define IMAGING_PIXEL_CMYK(im,x,y) ((im)->image[(y)][(x)*4])
#define IMAGING_PIXEL_YCbCr(im,x,y) ((im)->image[(y)][(x)*4])
#define IMAGING_PIXEL_UINT8(im,x,y) ((im)->image8[(y)][(x)])
#define IMAGING_PIXEL_INT32(im,x,y) ((im)->image32[(y)][(x)])
#define IMAGING_PIXEL_FLOAT32(im,x,y) (((FLOAT32*)(im)->image32[y])[x])
struct ImagingAccessInstance { struct ImagingAccessInstance {
const char* mode; const char *mode;
void* (*line)(Imaging im, int x, int y); void *(*line)(Imaging im, int x, int y);
void (*get_pixel)(Imaging im, int x, int y, void* pixel); void (*get_pixel)(Imaging im, int x, int y, void *pixel);
void (*put_pixel)(Imaging im, int x, int y, const void* pixel); void (*put_pixel)(Imaging im, int x, int y, const void *pixel);
}; };
struct ImagingHistogramInstance { struct ImagingHistogramInstance {
/* Format */ /* Format */
char mode[IMAGING_MODE_LENGTH]; /* Band names (of corresponding source image) */ char mode[IMAGING_MODE_LENGTH]; /* Band names (of corresponding source image) */
int bands; /* Number of bands (1, 3, or 4) */ int bands; /* Number of bands (1, 3, or 4) */
/* Data */ /* Data */
long *histogram; /* Histogram (bands*256 longs) */ long *histogram; /* Histogram (bands*256 longs) */
}; };
struct ImagingPaletteInstance { struct ImagingPaletteInstance {
/* Format */ /* Format */
char mode[IMAGING_MODE_LENGTH]; /* Band names */ char mode[IMAGING_MODE_LENGTH]; /* Band names */
/* Data */ /* Data */
UINT8 palette[1024];/* Palette data (same format as image data) */ UINT8 palette[1024]; /* Palette data (same format as image data) */
INT16* cache; /* Palette cache (used for predefined palettes) */
int keep_cache; /* This palette will be reused; keep cache */
INT16 *cache; /* Palette cache (used for predefined palettes) */
int keep_cache; /* This palette will be reused; keep cache */
}; };
typedef struct ImagingMemoryArena { typedef struct ImagingMemoryArena {
int alignment; /* Alignment in memory of each line of an image */ int alignment; /* Alignment in memory of each line of an image */
int block_size; /* Preferred block size, bytes */ int block_size; /* Preferred block size, bytes */
int blocks_max; /* Maximum number of cached blocks */ int blocks_max; /* Maximum number of cached blocks */
int blocks_cached; /* Current number of blocks not associated with images */ int blocks_cached; /* Current number of blocks not associated with images */
ImagingMemoryBlock *blocks_pool; ImagingMemoryBlock *blocks_pool;
int stats_new_count; /* Number of new allocated images */ int stats_new_count; /* Number of new allocated images */
int stats_allocated_blocks; /* Number of allocated blocks */ int stats_allocated_blocks; /* Number of allocated blocks */
int stats_reused_blocks; /* Number of blocks which were retrieved from a pool */ int stats_reused_blocks; /* Number of blocks which were retrieved from a pool */
int stats_reallocated_blocks; /* Number of blocks which were actually reallocated after retrieving */ int stats_reallocated_blocks; /* Number of blocks which were actually reallocated
int stats_freed_blocks; /* Number of freed blocks */ after retrieving */
} *ImagingMemoryArena; int stats_freed_blocks; /* Number of freed blocks */
} * ImagingMemoryArena;
/* Objects */ /* Objects */
/* ------- */ /* ------- */
extern struct ImagingMemoryArena ImagingDefaultArena; extern struct ImagingMemoryArena ImagingDefaultArena;
extern int ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max); extern int
extern void ImagingMemoryClearCache(ImagingMemoryArena arena, int new_size); ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max);
extern void
ImagingMemoryClearCache(ImagingMemoryArena arena, int new_size);
extern Imaging ImagingNew(const char* mode, int xsize, int ysize); extern Imaging
extern Imaging ImagingNewDirty(const char* mode, int xsize, int ysize); ImagingNew(const char *mode, int xsize, int ysize);
extern Imaging ImagingNew2Dirty(const char* mode, Imaging imOut, Imaging imIn); extern Imaging
extern void ImagingDelete(Imaging im); ImagingNewDirty(const char *mode, int xsize, int ysize);
extern Imaging
ImagingNew2Dirty(const char *mode, Imaging imOut, Imaging imIn);
extern void
ImagingDelete(Imaging im);
extern Imaging ImagingNewBlock(const char* mode, int xsize, int ysize); extern Imaging
ImagingNewBlock(const char *mode, int xsize, int ysize);
extern Imaging ImagingNewPrologue(const char *mode, extern Imaging
int xsize, int ysize); ImagingNewPrologue(const char *mode, int xsize, int ysize);
extern Imaging ImagingNewPrologueSubtype(const char *mode, extern Imaging
int xsize, int ysize, ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int structure_size);
int structure_size);
extern void ImagingCopyPalette(Imaging destination, Imaging source); extern void
ImagingCopyPalette(Imaging destination, Imaging source);
extern void ImagingHistogramDelete(ImagingHistogram histogram); extern void
ImagingHistogramDelete(ImagingHistogram histogram);
extern void ImagingAccessInit(void); extern void
extern ImagingAccess ImagingAccessNew(Imaging im); ImagingAccessInit(void);
extern void _ImagingAccessDelete(Imaging im, ImagingAccess access); extern ImagingAccess
ImagingAccessNew(Imaging im);
extern void
_ImagingAccessDelete(Imaging im, ImagingAccess access);
#define ImagingAccessDelete(im, access) /* nop, for now */ #define ImagingAccessDelete(im, access) /* nop, for now */
extern ImagingPalette ImagingPaletteNew(const char *mode); extern ImagingPalette
extern ImagingPalette ImagingPaletteNewBrowser(void); ImagingPaletteNew(const char *mode);
extern ImagingPalette ImagingPaletteDuplicate(ImagingPalette palette); extern ImagingPalette
extern void ImagingPaletteDelete(ImagingPalette palette); ImagingPaletteNewBrowser(void);
extern ImagingPalette
ImagingPaletteDuplicate(ImagingPalette palette);
extern void
ImagingPaletteDelete(ImagingPalette palette);
extern int ImagingPaletteCachePrepare(ImagingPalette palette); extern int
extern void ImagingPaletteCacheUpdate(ImagingPalette palette, ImagingPaletteCachePrepare(ImagingPalette palette);
int r, int g, int b); extern void
extern void ImagingPaletteCacheDelete(ImagingPalette palette); ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b);
extern void
ImagingPaletteCacheDelete(ImagingPalette palette);
#define ImagingPaletteCache(p, r, g, b)\ #define ImagingPaletteCache(p, r, g, b) \
p->cache[(r>>2) + (g>>2)*64 + (b>>2)*64*64] p->cache[(r >> 2) + (g >> 2) * 64 + (b >> 2) * 64 * 64]
extern Imaging ImagingQuantize(Imaging im, int colours, int mode, int kmeans); extern Imaging
ImagingQuantize(Imaging im, int colours, int mode, int kmeans);
/* Threading */ /* Threading */
/* --------- */ /* --------- */
typedef void* ImagingSectionCookie; typedef void *ImagingSectionCookie;
extern void ImagingSectionEnter(ImagingSectionCookie* cookie); extern void
extern void ImagingSectionLeave(ImagingSectionCookie* cookie); ImagingSectionEnter(ImagingSectionCookie *cookie);
extern void
ImagingSectionLeave(ImagingSectionCookie *cookie);
/* Exceptions */ /* Exceptions */
/* ---------- */ /* ---------- */
extern void* ImagingError_OSError(void); extern void *
extern void* ImagingError_MemoryError(void); ImagingError_OSError(void);
extern void* ImagingError_ModeError(void); /* maps to ValueError by default */ extern void *
extern void* ImagingError_Mismatch(void); /* maps to ValueError by default */ ImagingError_MemoryError(void);
extern void* ImagingError_ValueError(const char* message); extern void *
extern void ImagingError_Clear(void); ImagingError_ModeError(void); /* maps to ValueError by default */
extern void *
ImagingError_Mismatch(void); /* maps to ValueError by default */
extern void *
ImagingError_ValueError(const char *message);
extern void
ImagingError_Clear(void);
/* Transform callbacks */ /* Transform callbacks */
/* ------------------- */ /* ------------------- */
@ -242,7 +259,6 @@ extern void ImagingError_Clear(void);
#define IMAGING_TRANSFORM_PERSPECTIVE 2 #define IMAGING_TRANSFORM_PERSPECTIVE 2
#define IMAGING_TRANSFORM_QUAD 3 #define IMAGING_TRANSFORM_QUAD 3
/* standard filters */ /* standard filters */
#define IMAGING_TRANSFORM_NEAREST 0 #define IMAGING_TRANSFORM_NEAREST 0
#define IMAGING_TRANSFORM_BOX 4 #define IMAGING_TRANSFORM_BOX 4
@ -251,249 +267,391 @@ extern void ImagingError_Clear(void);
#define IMAGING_TRANSFORM_BICUBIC 3 #define IMAGING_TRANSFORM_BICUBIC 3
#define IMAGING_TRANSFORM_LANCZOS 1 #define IMAGING_TRANSFORM_LANCZOS 1
typedef int (*ImagingTransformMap)(double* X, double* Y, typedef int (*ImagingTransformMap)(double *X, double *Y, int x, int y, void *data);
int x, int y, void* data); typedef int (*ImagingTransformFilter)(void *out, Imaging im, double x, double y);
typedef int (*ImagingTransformFilter)(void* out, Imaging im,
double x, double y);
/* Image Manipulation Methods */ /* Image Manipulation Methods */
/* -------------------------- */ /* -------------------------- */
extern Imaging ImagingAlphaComposite(Imaging imIn1, Imaging imIn2); extern Imaging
extern Imaging ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha); ImagingAlphaComposite(Imaging imIn1, Imaging imIn2);
extern Imaging ImagingCopy(Imaging im); extern Imaging
extern Imaging ImagingConvert(Imaging im, const char* mode, ImagingPalette palette, int dither); ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha);
extern Imaging ImagingConvertInPlace(Imaging im, const char* mode); extern Imaging
extern Imaging ImagingConvertMatrix(Imaging im, const char *mode, float m[]); ImagingCopy(Imaging im);
extern Imaging ImagingConvertTransparent(Imaging im, const char *mode, int r, int g, int b); extern Imaging
extern Imaging ImagingCrop(Imaging im, int x0, int y0, int x1, int y1); ImagingConvert(Imaging im, const char *mode, ImagingPalette palette, int dither);
extern Imaging ImagingExpand(Imaging im, int x, int y, int mode); extern Imaging
extern Imaging ImagingFill(Imaging im, const void* ink); ImagingConvertInPlace(Imaging im, const char *mode);
extern int ImagingFill2( extern Imaging
Imaging into, const void* ink, Imaging mask, ImagingConvertMatrix(Imaging im, const char *mode, float m[]);
int x0, int y0, int x1, int y1); extern Imaging
extern Imaging ImagingFillBand(Imaging im, int band, int color); ImagingConvertTransparent(Imaging im, const char *mode, int r, int g, int b);
extern Imaging ImagingFillLinearGradient(const char* mode); extern Imaging
extern Imaging ImagingFillRadialGradient(const char* mode); ImagingCrop(Imaging im, int x0, int y0, int x1, int y1);
extern Imaging ImagingFilter( extern Imaging
Imaging im, int xsize, int ysize, const FLOAT32* kernel, ImagingExpand(Imaging im, int x, int y, int mode);
FLOAT32 offset); extern Imaging
extern Imaging ImagingFlipLeftRight(Imaging imOut, Imaging imIn); ImagingFill(Imaging im, const void *ink);
extern Imaging ImagingFlipTopBottom(Imaging imOut, Imaging imIn); extern int
extern Imaging ImagingGaussianBlur(Imaging imOut, Imaging imIn, float radius, ImagingFill2(
int passes); Imaging into, const void *ink, Imaging mask, int x0, int y0, int x1, int y1);
extern Imaging ImagingGetBand(Imaging im, int band); extern Imaging
extern Imaging ImagingMerge(const char* mode, Imaging bands[4]); ImagingFillBand(Imaging im, int band, int color);
extern int ImagingSplit(Imaging im, Imaging bands[4]); extern Imaging
extern int ImagingGetBBox(Imaging im, int bbox[4]); ImagingFillLinearGradient(const char *mode);
typedef struct { int x, y; INT32 count; INT32 pixel; } ImagingColorItem; extern Imaging
extern ImagingColorItem* ImagingGetColors(Imaging im, int maxcolors, ImagingFillRadialGradient(const char *mode);
int *colors); extern Imaging
extern int ImagingGetExtrema(Imaging im, void *extrema); ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32 *kernel, FLOAT32 offset);
extern int ImagingGetProjection(Imaging im, UINT8* xproj, UINT8* yproj); extern Imaging
extern ImagingHistogram ImagingGetHistogram( ImagingFlipLeftRight(Imaging imOut, Imaging imIn);
Imaging im, Imaging mask, void *extrema); extern Imaging
extern Imaging ImagingModeFilter(Imaging im, int size); ImagingFlipTopBottom(Imaging imOut, Imaging imIn);
extern Imaging ImagingNegative(Imaging im); extern Imaging
extern Imaging ImagingOffset(Imaging im, int xoffset, int yoffset); ImagingGaussianBlur(Imaging imOut, Imaging imIn, float radius, int passes);
extern int ImagingPaste( extern Imaging
Imaging into, Imaging im, Imaging mask, ImagingGetBand(Imaging im, int band);
int x0, int y0, int x1, int y1); extern Imaging
extern Imaging ImagingPoint( ImagingMerge(const char *mode, Imaging bands[4]);
Imaging im, const char* tablemode, const void* table); extern int
extern Imaging ImagingPointTransform( ImagingSplit(Imaging im, Imaging bands[4]);
Imaging imIn, double scale, double offset); extern int
extern Imaging ImagingPutBand(Imaging im, Imaging imIn, int band); ImagingGetBBox(Imaging im, int bbox[4]);
extern Imaging ImagingRankFilter(Imaging im, int size, int rank); typedef struct {
extern Imaging ImagingRotate90(Imaging imOut, Imaging imIn); int x, y;
extern Imaging ImagingRotate180(Imaging imOut, Imaging imIn); INT32 count;
extern Imaging ImagingRotate270(Imaging imOut, Imaging imIn); INT32 pixel;
extern Imaging ImagingTranspose(Imaging imOut, Imaging imIn); } ImagingColorItem;
extern Imaging ImagingTransverse(Imaging imOut, Imaging imIn); extern ImagingColorItem *
extern Imaging ImagingResample(Imaging imIn, int xsize, int ysize, int filter, float box[4]); ImagingGetColors(Imaging im, int maxcolors, int *colors);
extern Imaging ImagingReduce(Imaging imIn, int xscale, int yscale, int box[4]); extern int
extern Imaging ImagingTransform( ImagingGetExtrema(Imaging im, void *extrema);
Imaging imOut, Imaging imIn, int method, int x0, int y0, int x1, int y1, extern int
double *a, int filter, int fill); ImagingGetProjection(Imaging im, UINT8 *xproj, UINT8 *yproj);
extern Imaging ImagingUnsharpMask( extern ImagingHistogram
Imaging imOut, Imaging im, float radius, int percent, int threshold); ImagingGetHistogram(Imaging im, Imaging mask, void *extrema);
extern Imaging ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n); extern Imaging
extern Imaging ImagingColorLUT3D_linear(Imaging imOut, Imaging imIn, ImagingModeFilter(Imaging im, int size);
int table_channels, int size1D, int size2D, int size3D, INT16* table); extern Imaging
ImagingNegative(Imaging im);
extern Imaging
ImagingOffset(Imaging im, int xoffset, int yoffset);
extern int
ImagingPaste(Imaging into, Imaging im, Imaging mask, int x0, int y0, int x1, int y1);
extern Imaging
ImagingPoint(Imaging im, const char *tablemode, const void *table);
extern Imaging
ImagingPointTransform(Imaging imIn, double scale, double offset);
extern Imaging
ImagingPutBand(Imaging im, Imaging imIn, int band);
extern Imaging
ImagingRankFilter(Imaging im, int size, int rank);
extern Imaging
ImagingRotate90(Imaging imOut, Imaging imIn);
extern Imaging
ImagingRotate180(Imaging imOut, Imaging imIn);
extern Imaging
ImagingRotate270(Imaging imOut, Imaging imIn);
extern Imaging
ImagingTranspose(Imaging imOut, Imaging imIn);
extern Imaging
ImagingTransverse(Imaging imOut, Imaging imIn);
extern Imaging
ImagingResample(Imaging imIn, int xsize, int ysize, int filter, float box[4]);
extern Imaging
ImagingReduce(Imaging imIn, int xscale, int yscale, int box[4]);
extern Imaging
ImagingTransform(
Imaging imOut,
Imaging imIn,
int method,
int x0,
int y0,
int x1,
int y1,
double *a,
int filter,
int fill);
extern Imaging
ImagingUnsharpMask(Imaging imOut, Imaging im, float radius, int percent, int threshold);
extern Imaging
ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n);
extern Imaging
ImagingColorLUT3D_linear(
Imaging imOut,
Imaging imIn,
int table_channels,
int size1D,
int size2D,
int size3D,
INT16 *table);
extern Imaging ImagingCopy2(Imaging imOut, Imaging imIn); extern Imaging
extern Imaging ImagingConvert2(Imaging imOut, Imaging imIn); ImagingCopy2(Imaging imOut, Imaging imIn);
extern Imaging
ImagingConvert2(Imaging imOut, Imaging imIn);
/* Channel operations */ /* Channel operations */
/* any mode, except "F" */ /* any mode, except "F" */
extern Imaging ImagingChopLighter(Imaging imIn1, Imaging imIn2); extern Imaging
extern Imaging ImagingChopDarker(Imaging imIn1, Imaging imIn2); ImagingChopLighter(Imaging imIn1, Imaging imIn2);
extern Imaging ImagingChopDifference(Imaging imIn1, Imaging imIn2); extern Imaging
extern Imaging ImagingChopMultiply(Imaging imIn1, Imaging imIn2); ImagingChopDarker(Imaging imIn1, Imaging imIn2);
extern Imaging ImagingChopScreen(Imaging imIn1, Imaging imIn2); extern Imaging
extern Imaging ImagingChopAdd( ImagingChopDifference(Imaging imIn1, Imaging imIn2);
Imaging imIn1, Imaging imIn2, float scale, int offset); extern Imaging
extern Imaging ImagingChopSubtract( ImagingChopMultiply(Imaging imIn1, Imaging imIn2);
Imaging imIn1, Imaging imIn2, float scale, int offset); extern Imaging
extern Imaging ImagingChopAddModulo(Imaging imIn1, Imaging imIn2); ImagingChopScreen(Imaging imIn1, Imaging imIn2);
extern Imaging ImagingChopSubtractModulo(Imaging imIn1, Imaging imIn2); extern Imaging
extern Imaging ImagingChopSoftLight(Imaging imIn1, Imaging imIn2); ImagingChopAdd(Imaging imIn1, Imaging imIn2, float scale, int offset);
extern Imaging ImagingChopHardLight(Imaging imIn1, Imaging imIn2); extern Imaging
extern Imaging ImagingOverlay(Imaging imIn1, Imaging imIn2); ImagingChopSubtract(Imaging imIn1, Imaging imIn2, float scale, int offset);
extern Imaging
ImagingChopAddModulo(Imaging imIn1, Imaging imIn2);
extern Imaging
ImagingChopSubtractModulo(Imaging imIn1, Imaging imIn2);
extern Imaging
ImagingChopSoftLight(Imaging imIn1, Imaging imIn2);
extern Imaging
ImagingChopHardLight(Imaging imIn1, Imaging imIn2);
extern Imaging
ImagingOverlay(Imaging imIn1, Imaging imIn2);
/* "1" images only */ /* "1" images only */
extern Imaging ImagingChopAnd(Imaging imIn1, Imaging imIn2); extern Imaging
extern Imaging ImagingChopOr(Imaging imIn1, Imaging imIn2); ImagingChopAnd(Imaging imIn1, Imaging imIn2);
extern Imaging ImagingChopXor(Imaging imIn1, Imaging imIn2); extern Imaging
ImagingChopOr(Imaging imIn1, Imaging imIn2);
extern Imaging
ImagingChopXor(Imaging imIn1, Imaging imIn2);
/* Graphics */ /* Graphics */
extern int ImagingDrawArc(Imaging im, int x0, int y0, int x1, int y1, extern int
float start, float end, const void* ink, int width, ImagingDrawArc(
int op); Imaging im,
extern int ImagingDrawBitmap(Imaging im, int x0, int y0, Imaging bitmap, int x0,
const void* ink, int op); int y0,
extern int ImagingDrawChord(Imaging im, int x0, int y0, int x1, int y1, int x1,
float start, float end, const void* ink, int fill, int y1,
int width, int op); float start,
extern int ImagingDrawEllipse(Imaging im, int x0, int y0, int x1, int y1, float end,
const void* ink, int fill, int width, int op); const void *ink,
extern int ImagingDrawLine(Imaging im, int x0, int y0, int x1, int y1, int width,
const void* ink, int op); int op);
extern int ImagingDrawWideLine(Imaging im, int x0, int y0, int x1, int y1, extern int
const void* ink, int width, int op); ImagingDrawBitmap(Imaging im, int x0, int y0, Imaging bitmap, const void *ink, int op);
extern int ImagingDrawPieslice(Imaging im, int x0, int y0, int x1, int y1, extern int
float start, float end, const void* ink, int fill, ImagingDrawChord(
int width, int op); Imaging im,
extern int ImagingDrawPoint(Imaging im, int x, int y, const void* ink, int op); int x0,
extern int ImagingDrawPolygon(Imaging im, int points, int *xy, int y0,
const void* ink, int fill, int op); int x1,
extern int ImagingDrawRectangle(Imaging im, int x0, int y0, int x1, int y1, int y1,
const void* ink, int fill, int width, int op); float start,
float end,
const void *ink,
int fill,
int width,
int op);
extern int
ImagingDrawEllipse(
Imaging im,
int x0,
int y0,
int x1,
int y1,
const void *ink,
int fill,
int width,
int op);
extern int
ImagingDrawLine(Imaging im, int x0, int y0, int x1, int y1, const void *ink, int op);
extern int
ImagingDrawWideLine(
Imaging im, int x0, int y0, int x1, int y1, const void *ink, int width, int op);
extern int
ImagingDrawPieslice(
Imaging im,
int x0,
int y0,
int x1,
int y1,
float start,
float end,
const void *ink,
int fill,
int width,
int op);
extern int
ImagingDrawPoint(Imaging im, int x, int y, const void *ink, int op);
extern int
ImagingDrawPolygon(Imaging im, int points, int *xy, const void *ink, int fill, int op);
extern int
ImagingDrawRectangle(
Imaging im,
int x0,
int y0,
int x1,
int y1,
const void *ink,
int fill,
int width,
int op);
/* Level 2 graphics (WORK IN PROGRESS) */ /* Level 2 graphics (WORK IN PROGRESS) */
extern ImagingOutline ImagingOutlineNew(void); extern ImagingOutline
extern void ImagingOutlineDelete(ImagingOutline outline); ImagingOutlineNew(void);
extern void
ImagingOutlineDelete(ImagingOutline outline);
extern int ImagingDrawOutline(Imaging im, ImagingOutline outline, extern int
const void* ink, int fill, int op); ImagingDrawOutline(
Imaging im, ImagingOutline outline, const void *ink, int fill, int op);
extern int ImagingOutlineMove(ImagingOutline outline, float x, float y); extern int
extern int ImagingOutlineLine(ImagingOutline outline, float x, float y); ImagingOutlineMove(ImagingOutline outline, float x, float y);
extern int ImagingOutlineCurve(ImagingOutline outline, float x1, float y1, extern int
float x2, float y2, float x3, float y3); ImagingOutlineLine(ImagingOutline outline, float x, float y);
extern int ImagingOutlineTransform(ImagingOutline outline, double a[6]); extern int
ImagingOutlineCurve(
ImagingOutline outline, float x1, float y1, float x2, float y2, float x3, float y3);
extern int
ImagingOutlineTransform(ImagingOutline outline, double a[6]);
extern int ImagingOutlineClose(ImagingOutline outline); extern int
ImagingOutlineClose(ImagingOutline outline);
/* Special effects */ /* Special effects */
extern Imaging ImagingEffectSpread(Imaging imIn, int distance); extern Imaging
extern Imaging ImagingEffectNoise(int xsize, int ysize, float sigma); ImagingEffectSpread(Imaging imIn, int distance);
extern Imaging ImagingEffectMandelbrot(int xsize, int ysize, extern Imaging
double extent[4], int quality); ImagingEffectNoise(int xsize, int ysize, float sigma);
extern Imaging
ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality);
/* File I/O */ /* File I/O */
/* -------- */ /* -------- */
/* Built-in drivers */ /* Built-in drivers */
extern Imaging ImagingOpenPPM(const char* filename); extern Imaging
extern int ImagingSavePPM(Imaging im, const char* filename); ImagingOpenPPM(const char *filename);
extern int
ImagingSavePPM(Imaging im, const char *filename);
/* Codecs */ /* Codecs */
typedef struct ImagingCodecStateInstance *ImagingCodecState; typedef struct ImagingCodecStateInstance *ImagingCodecState;
typedef int (*ImagingCodec)(Imaging im, ImagingCodecState state, typedef int (*ImagingCodec)(
UINT8* buffer, int bytes); Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
extern int ImagingBcnDecode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, Py_ssize_t bytes); ImagingBcnDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
extern int ImagingBitDecode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, Py_ssize_t bytes); ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
extern int ImagingEpsEncode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, int bytes); ImagingEpsEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
extern int ImagingFliDecode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, Py_ssize_t bytes); ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
extern int ImagingGifDecode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, Py_ssize_t bytes); ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
extern int ImagingGifEncode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, int bytes); ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
extern int ImagingHexDecode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, Py_ssize_t bytes); ImagingHexDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
#ifdef HAVE_LIBJPEG #ifdef HAVE_LIBJPEG
extern int ImagingJpegDecode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, Py_ssize_t bytes); ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
extern int ImagingJpegDecodeCleanup(ImagingCodecState state); extern int
extern int ImagingJpegUseJCSExtensions(void); ImagingJpegDecodeCleanup(ImagingCodecState state);
extern int
ImagingJpegUseJCSExtensions(void);
extern int ImagingJpegEncode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, int bytes); ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
#endif #endif
#ifdef HAVE_OPENJPEG #ifdef HAVE_OPENJPEG
extern int ImagingJpeg2KDecode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, Py_ssize_t bytes); ImagingJpeg2KDecode(
extern int ImagingJpeg2KDecodeCleanup(ImagingCodecState state); Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
extern int ImagingJpeg2KEncode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, int bytes); ImagingJpeg2KDecodeCleanup(ImagingCodecState state);
extern int ImagingJpeg2KEncodeCleanup(ImagingCodecState state); extern int
ImagingJpeg2KEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
extern int
ImagingJpeg2KEncodeCleanup(ImagingCodecState state);
#endif #endif
#ifdef HAVE_LIBTIFF #ifdef HAVE_LIBTIFF
extern int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, Py_ssize_t bytes); ImagingLibTiffDecode(
extern int ImagingLibTiffEncode(Imaging im, ImagingCodecState state, Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
UINT8* buffer, int bytes); extern int
ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
#endif #endif
#ifdef HAVE_LIBMPEG #ifdef HAVE_LIBMPEG
extern int ImagingMpegDecode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, Py_ssize_t bytes); ImagingMpegDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
#endif #endif
extern int ImagingMspDecode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, Py_ssize_t bytes); ImagingMspDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
extern int ImagingPackbitsDecode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, Py_ssize_t bytes); ImagingPackbitsDecode(
extern int ImagingPcdDecode(Imaging im, ImagingCodecState state, Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
UINT8* buffer, Py_ssize_t bytes); extern int
extern int ImagingPcxDecode(Imaging im, ImagingCodecState state, ImagingPcdDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
UINT8* buffer, Py_ssize_t bytes); extern int
extern int ImagingPcxEncode(Imaging im, ImagingCodecState state, ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
UINT8* buffer, int bytes); extern int
extern int ImagingRawDecode(Imaging im, ImagingCodecState state, ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
UINT8* buffer, Py_ssize_t bytes); extern int
extern int ImagingRawEncode(Imaging im, ImagingCodecState state, ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
UINT8* buffer, int bytes); extern int
extern int ImagingSgiRleDecode(Imaging im, ImagingCodecState state, ImagingRawEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
UINT8* buffer, Py_ssize_t bytes); extern int
extern int ImagingSunRleDecode(Imaging im, ImagingCodecState state, ImagingSgiRleDecode(
UINT8* buffer, Py_ssize_t bytes); Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
extern int ImagingTgaRleDecode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, Py_ssize_t bytes); ImagingSunRleDecode(
extern int ImagingTgaRleEncode(Imaging im, ImagingCodecState state, Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
UINT8* buffer, int bytes); extern int
extern int ImagingXbmDecode(Imaging im, ImagingCodecState state, ImagingTgaRleDecode(
UINT8* buffer, Py_ssize_t bytes); Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
extern int ImagingXbmEncode(Imaging im, ImagingCodecState state, extern int
UINT8* buffer, int bytes); ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
#ifdef HAVE_LIBZ extern int
extern int ImagingZipDecode(Imaging im, ImagingCodecState state, ImagingXbmDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
UINT8* buffer, Py_ssize_t bytes); extern int
extern int ImagingZipDecodeCleanup(ImagingCodecState state); ImagingXbmEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
extern int ImagingZipEncode(Imaging im, ImagingCodecState state, #ifdef HAVE_LIBZ
UINT8* buffer, int bytes); extern int
extern int ImagingZipEncodeCleanup(ImagingCodecState state); ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
extern int
ImagingZipDecodeCleanup(ImagingCodecState state);
extern int
ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
extern int
ImagingZipEncodeCleanup(ImagingCodecState state);
#endif #endif
typedef void (*ImagingShuffler)(UINT8* out, const UINT8* in, int pixels); typedef void (*ImagingShuffler)(UINT8 *out, const UINT8 *in, int pixels);
/* Public shufflers */ /* Public shufflers */
extern void ImagingPackBGR(UINT8* out, const UINT8* in, int pixels); extern void
extern void ImagingUnpackYCC(UINT8* out, const UINT8* in, int pixels); ImagingPackBGR(UINT8 *out, const UINT8 *in, int pixels);
extern void ImagingUnpackYCCA(UINT8* out, const UINT8* in, int pixels); extern void
ImagingUnpackYCC(UINT8 *out, const UINT8 *in, int pixels);
extern void
ImagingUnpackYCCA(UINT8 *out, const UINT8 *in, int pixels);
extern void ImagingConvertRGB2YCbCr(UINT8* out, const UINT8* in, int pixels); extern void
extern void ImagingConvertYCbCr2RGB(UINT8* out, const UINT8* in, int pixels); ImagingConvertRGB2YCbCr(UINT8 *out, const UINT8 *in, int pixels);
extern void
ImagingConvertYCbCr2RGB(UINT8 *out, const UINT8 *in, int pixels);
extern ImagingShuffler ImagingFindUnpacker(const char* mode, extern ImagingShuffler
const char* rawmode, int* bits_out); ImagingFindUnpacker(const char *mode, const char *rawmode, int *bits_out);
extern ImagingShuffler ImagingFindPacker(const char* mode, extern ImagingShuffler
const char* rawmode, int* bits_out); ImagingFindPacker(const char *mode, const char *rawmode, int *bits_out);
struct ImagingCodecStateInstance { struct ImagingCodecStateInstance {
int count; int count;
@ -509,30 +667,27 @@ struct ImagingCodecStateInstance {
PyObject *fd; PyObject *fd;
}; };
/* Codec read/write python fd */ /* Codec read/write python fd */
extern Py_ssize_t _imaging_read_pyFd(PyObject *fd, char* dest, Py_ssize_t bytes); extern Py_ssize_t
extern Py_ssize_t _imaging_write_pyFd(PyObject *fd, char* src, Py_ssize_t bytes); _imaging_read_pyFd(PyObject *fd, char *dest, Py_ssize_t bytes);
extern int _imaging_seek_pyFd(PyObject *fd, Py_ssize_t offset, int whence); extern Py_ssize_t
extern Py_ssize_t _imaging_tell_pyFd(PyObject *fd); _imaging_write_pyFd(PyObject *fd, char *src, Py_ssize_t bytes);
extern int
_imaging_seek_pyFd(PyObject *fd, Py_ssize_t offset, int whence);
extern Py_ssize_t
_imaging_tell_pyFd(PyObject *fd);
/* Errcodes */ /* Errcodes */
#define IMAGING_CODEC_END 1 #define IMAGING_CODEC_END 1
#define IMAGING_CODEC_OVERRUN -1 #define IMAGING_CODEC_OVERRUN -1
#define IMAGING_CODEC_BROKEN -2 #define IMAGING_CODEC_BROKEN -2
#define IMAGING_CODEC_UNKNOWN -3 #define IMAGING_CODEC_UNKNOWN -3
#define IMAGING_CODEC_CONFIG -8 #define IMAGING_CODEC_CONFIG -8
#define IMAGING_CODEC_MEMORY -9 #define IMAGING_CODEC_MEMORY -9
#include "ImagingUtils.h" #include "ImagingUtils.h"
extern UINT8 *clip8_lookups; extern UINT8 *clip8_lookups;
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif

View File

@ -1,47 +1,42 @@
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
#define MAKE_UINT32(u0, u1, u2, u3) ((UINT32)(u3) | ((UINT32)(u2)<<8) | ((UINT32)(u1)<<16) | ((UINT32)(u0)<<24)) #define MAKE_UINT32(u0, u1, u2, u3) \
#define MASK_UINT32_CHANNEL_0 0xff000000 ((UINT32)(u3) | ((UINT32)(u2) << 8) | ((UINT32)(u1) << 16) | ((UINT32)(u0) << 24))
#define MASK_UINT32_CHANNEL_1 0x00ff0000 #define MASK_UINT32_CHANNEL_0 0xff000000
#define MASK_UINT32_CHANNEL_2 0x0000ff00 #define MASK_UINT32_CHANNEL_1 0x00ff0000
#define MASK_UINT32_CHANNEL_3 0x000000ff #define MASK_UINT32_CHANNEL_2 0x0000ff00
#define MASK_UINT32_CHANNEL_3 0x000000ff
#else #else
#define MAKE_UINT32(u0, u1, u2, u3) ((UINT32)(u0) | ((UINT32)(u1)<<8) | ((UINT32)(u2)<<16) | ((UINT32)(u3)<<24)) #define MAKE_UINT32(u0, u1, u2, u3) \
#define MASK_UINT32_CHANNEL_0 0x000000ff ((UINT32)(u0) | ((UINT32)(u1) << 8) | ((UINT32)(u2) << 16) | ((UINT32)(u3) << 24))
#define MASK_UINT32_CHANNEL_1 0x0000ff00 #define MASK_UINT32_CHANNEL_0 0x000000ff
#define MASK_UINT32_CHANNEL_2 0x00ff0000 #define MASK_UINT32_CHANNEL_1 0x0000ff00
#define MASK_UINT32_CHANNEL_3 0xff000000 #define MASK_UINT32_CHANNEL_2 0x00ff0000
#define MASK_UINT32_CHANNEL_3 0xff000000
#endif #endif
#define SHIFTFORDIV255(a) ((((a) >> 8) + a) >> 8)
#define SHIFTFORDIV255(a)\
((((a) >> 8) + a) >> 8)
/* like (a * b + 127) / 255), but much faster on most platforms */ /* like (a * b + 127) / 255), but much faster on most platforms */
#define MULDIV255(a, b, tmp)\ #define MULDIV255(a, b, tmp) (tmp = (a) * (b) + 128, SHIFTFORDIV255(tmp))
(tmp = (a) * (b) + 128, SHIFTFORDIV255(tmp))
#define DIV255(a, tmp)\ #define DIV255(a, tmp) (tmp = (a) + 128, SHIFTFORDIV255(tmp))
(tmp = (a) + 128, SHIFTFORDIV255(tmp))
#define BLEND(mask, in1, in2, tmp1)\ #define BLEND(mask, in1, in2, tmp1) DIV255(in1 *(255 - mask) + in2 * mask, tmp1)
DIV255(in1 * (255 - mask) + in2 * mask, tmp1)
#define PREBLEND(mask, in1, in2, tmp1)\
(MULDIV255(in1, (255 - mask), tmp1) + in2)
#define PREBLEND(mask, in1, in2, tmp1) (MULDIV255(in1, (255 - mask), tmp1) + in2)
#define CLIP8(v) ((v) <= 0 ? 0 : (v) < 256 ? (v) : 255) #define CLIP8(v) ((v) <= 0 ? 0 : (v) < 256 ? (v) : 255)
/* This is to work around a bug in GCC prior 4.9 in 64 bit mode. /* This is to work around a bug in GCC prior 4.9 in 64 bit mode.
GCC generates code with partial dependency which is 3 times slower. GCC generates code with partial dependency which is 3 times slower.
See: http://stackoverflow.com/a/26588074/253146 */ See: http://stackoverflow.com/a/26588074/253146 */
#if defined(__x86_64__) && defined(__SSE__) && ! defined(__NO_INLINE__) && \ #if defined(__x86_64__) && defined(__SSE__) && !defined(__NO_INLINE__) && \
! defined(__clang__) && defined(GCC_VERSION) && (GCC_VERSION < 40900) !defined(__clang__) && defined(GCC_VERSION) && (GCC_VERSION < 40900)
static float __attribute__((always_inline)) inline _i2f(int v) { static float __attribute__((always_inline)) inline _i2f(int v) {
float x; float x;
__asm__("xorps %0, %0; cvtsi2ss %1, %0" : "=x"(x) : "r"(v) ); __asm__("xorps %0, %0; cvtsi2ss %1, %0" : "=x"(x) : "r"(v));
return x; return x;
} }
#else #else
static float inline _i2f(int v) { return (float) v; } static float inline _i2f(int v) { return (float)v; }
#endif #endif

View File

@ -12,13 +12,11 @@
#include <setjmp.h> #include <setjmp.h>
typedef struct { typedef struct {
struct jpeg_error_mgr pub; /* "public" fields */ struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */ jmp_buf setjmp_buffer; /* for return to caller */
} JPEGERROR; } JPEGERROR;
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Decoder */ /* Decoder */
@ -28,15 +26,14 @@ typedef struct {
} JPEGSOURCE; } JPEGSOURCE;
typedef struct { typedef struct {
/* CONFIGURATION */ /* CONFIGURATION */
/* Jpeg file mode (empty if not known) */ /* Jpeg file mode (empty if not known) */
char jpegmode[8+1]; char jpegmode[8 + 1];
/* Converter output mode (input to the shuffler). If empty, /* Converter output mode (input to the shuffler). If empty,
convert conversions are disabled */ convert conversions are disabled */
char rawmode[8+1]; char rawmode[8 + 1];
/* If set, trade quality for speed */ /* If set, trade quality for speed */
int draft; int draft;
@ -54,7 +51,6 @@ typedef struct {
} JPEGSTATE; } JPEGSTATE;
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Encoder */ /* Encoder */
@ -64,7 +60,6 @@ typedef struct {
} JPEGDESTINATION; } JPEGDESTINATION;
typedef struct { typedef struct {
/* CONFIGURATION */ /* CONFIGURATION */
/* Quality (0-100, -1 means default) */ /* Quality (0-100, -1 means default) */
@ -89,7 +84,7 @@ typedef struct {
int subsampling; int subsampling;
/* Converter input mode (input to the shuffler) */ /* Converter input mode (input to the shuffler) */
char rawmode[8+1]; char rawmode[8 + 1];
/* Custom quantization tables () */ /* Custom quantization tables () */
unsigned int *qtables; unsigned int *qtables;
@ -98,7 +93,8 @@ typedef struct {
int qtablesLen; int qtablesLen;
/* Extra data (to be injected after header) */ /* Extra data (to be injected after header) */
char* extra; int extra_size; char *extra;
int extra_size;
/* PRIVATE CONTEXT (set by encoder) */ /* PRIVATE CONTEXT (set by encoder) */
@ -110,7 +106,7 @@ typedef struct {
int extra_offset; int extra_offset;
size_t rawExifLen; /* EXIF data length */ size_t rawExifLen; /* EXIF data length */
char* rawExif; /* EXIF buffer pointer */ char *rawExif; /* EXIF buffer pointer */
} JPEGENCODERSTATE; } JPEGENCODERSTATE;

View File

@ -24,7 +24,7 @@ typedef struct {
int fd; int fd;
/* File pointer, when opened */ /* File pointer, when opened */
FILE * pfile; FILE *pfile;
/* Length of data, if available; otherwise, -1 */ /* Length of data, if available; otherwise, -1 */
off_t length; off_t length;
@ -33,13 +33,13 @@ typedef struct {
OPJ_CODEC_FORMAT format; OPJ_CODEC_FORMAT format;
/* Set to divide image resolution by 2**reduce. */ /* Set to divide image resolution by 2**reduce. */
int reduce; int reduce;
/* Set to limit the number of quality layers to decode (0 = all layers) */ /* Set to limit the number of quality layers to decode (0 = all layers) */
int layers; int layers;
/* PRIVATE CONTEXT (set by decoder) */ /* PRIVATE CONTEXT (set by decoder) */
const char *error_msg; const char *error_msg;
} JPEG2KDECODESTATE; } JPEG2KDECODESTATE;
@ -51,36 +51,36 @@ typedef struct {
/* CONFIGURATION */ /* CONFIGURATION */
/* File descriptor, if available; otherwise, -1 */ /* File descriptor, if available; otherwise, -1 */
int fd; int fd;
/* File pointer, when opened */ /* File pointer, when opened */
FILE * pfile; FILE *pfile;
/* Specify the desired format */ /* Specify the desired format */
OPJ_CODEC_FORMAT format; OPJ_CODEC_FORMAT format;
/* Image offset */ /* Image offset */
int offset_x, offset_y; int offset_x, offset_y;
/* Tile information */ /* Tile information */
int tile_offset_x, tile_offset_y; int tile_offset_x, tile_offset_y;
int tile_size_x, tile_size_y; int tile_size_x, tile_size_y;
/* Quality layers (a sequence of numbers giving *either* rates or dB) */ /* Quality layers (a sequence of numbers giving *either* rates or dB) */
int quality_is_in_db; int quality_is_in_db;
PyObject *quality_layers; PyObject *quality_layers;
/* Number of resolutions (DWT decompositions + 1 */ /* Number of resolutions (DWT decompositions + 1 */
int num_resolutions; int num_resolutions;
/* Code block size */ /* Code block size */
int cblk_width, cblk_height; int cblk_width, cblk_height;
/* Precinct size */ /* Precinct size */
int precinct_width, precinct_height; int precinct_width, precinct_height;
/* Compression style */ /* Compression style */
int irreversible; int irreversible;
/* Progression order (LRCP/RLCP/RPCL/PCRL/CPRL) */ /* Progression order (LRCP/RLCP/RPCL/PCRL/CPRL) */
OPJ_PROG_ORDER progression; OPJ_PROG_ORDER progression;
@ -89,8 +89,7 @@ typedef struct {
OPJ_CINEMA_MODE cinema_mode; OPJ_CINEMA_MODE cinema_mode;
/* PRIVATE CONTEXT (set by decoder) */ /* PRIVATE CONTEXT (set by decoder) */
const char *error_msg; const char *error_msg;
} JPEG2KENCODESTATE; } JPEG2KENCODESTATE;

View File

@ -23,7 +23,7 @@
typedef struct { typedef struct {
OPJ_UINT32 tile_index; OPJ_UINT32 tile_index;
OPJ_UINT32 data_size; OPJ_UINT32 data_size;
OPJ_INT32 x0, y0, x1, y1; OPJ_INT32 x0, y0, x1, y1;
OPJ_UINT32 nb_comps; OPJ_UINT32 nb_comps;
} JPEG2KTILEINFO; } JPEG2KTILEINFO;
@ -32,9 +32,8 @@ typedef struct {
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
static void static void
j2k_error(const char *msg, void *client_data) j2k_error(const char *msg, void *client_data) {
{ JPEG2KDECODESTATE *state = (JPEG2KDECODESTATE *)client_data;
JPEG2KDECODESTATE *state = (JPEG2KDECODESTATE *) client_data;
free((void *)state->error_msg); free((void *)state->error_msg);
state->error_msg = strdup(msg); state->error_msg = strdup(msg);
} }
@ -44,8 +43,7 @@ j2k_error(const char *msg, void *client_data)
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
static OPJ_SIZE_T static OPJ_SIZE_T
j2k_read(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) j2k_read(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) {
{
ImagingCodecState state = (ImagingCodecState)p_user_data; ImagingCodecState state = (ImagingCodecState)p_user_data;
size_t len = _imaging_read_pyFd(state->fd, p_buffer, p_nb_bytes); size_t len = _imaging_read_pyFd(state->fd, p_buffer, p_nb_bytes);
@ -54,8 +52,7 @@ j2k_read(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data)
} }
static OPJ_OFF_T static OPJ_OFF_T
j2k_skip(OPJ_OFF_T p_nb_bytes, void *p_user_data) j2k_skip(OPJ_OFF_T p_nb_bytes, void *p_user_data) {
{
off_t pos; off_t pos;
ImagingCodecState state = (ImagingCodecState)p_user_data; ImagingCodecState state = (ImagingCodecState)p_user_data;
@ -69,21 +66,18 @@ j2k_skip(OPJ_OFF_T p_nb_bytes, void *p_user_data)
/* Unpackers */ /* Unpackers */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
typedef void (*j2k_unpacker_t)(opj_image_t *in, typedef void (*j2k_unpacker_t)(
const JPEG2KTILEINFO *tileInfo, opj_image_t *in, const JPEG2KTILEINFO *tileInfo, const UINT8 *data, Imaging im);
const UINT8 *data,
Imaging im);
struct j2k_decode_unpacker { struct j2k_decode_unpacker {
const char *mode; const char *mode;
OPJ_COLOR_SPACE color_space; OPJ_COLOR_SPACE color_space;
unsigned components; unsigned components;
j2k_unpacker_t unpacker; j2k_unpacker_t unpacker;
}; };
static inline static inline unsigned
unsigned j2ku_shift(unsigned x, int n) j2ku_shift(unsigned x, int n) {
{
if (n < 0) { if (n < 0) {
return x >> -n; return x >> -n;
} else { } else {
@ -92,9 +86,11 @@ unsigned j2ku_shift(unsigned x, int n)
} }
static void static void
j2ku_gray_l(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, j2ku_gray_l(
const UINT8 *tiledata, Imaging im) opj_image_t *in,
{ const JPEG2KTILEINFO *tileinfo,
const UINT8 *tiledata,
Imaging im) {
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0; unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
unsigned w = tileinfo->x1 - tileinfo->x0; unsigned w = tileinfo->x1 - tileinfo->x0;
unsigned h = tileinfo->y1 - tileinfo->y0; unsigned h = tileinfo->y1 - tileinfo->y0;
@ -115,41 +111,42 @@ j2ku_gray_l(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
/* csiz*h*w + offset = tileinfo.datasize */ /* csiz*h*w + offset = tileinfo.datasize */
switch (csiz) { switch (csiz) {
case 1: case 1:
for (y = 0; y < h; ++y) { for (y = 0; y < h; ++y) {
const UINT8 *data = &tiledata[y * w]; const UINT8 *data = &tiledata[y * w];
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0; UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
for (x = 0; x < w; ++x) { for (x = 0; x < w; ++x) {
*row++ = j2ku_shift(offset + *data++, shift); *row++ = j2ku_shift(offset + *data++, shift);
}
} }
} break;
break; case 2:
case 2: for (y = 0; y < h; ++y) {
for (y = 0; y < h; ++y) { const UINT16 *data = (const UINT16 *)&tiledata[2 * y * w];
const UINT16 *data = (const UINT16 *)&tiledata[2 * y * w]; UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0; for (x = 0; x < w; ++x) {
for (x = 0; x < w; ++x) { *row++ = j2ku_shift(offset + *data++, shift);
*row++ = j2ku_shift(offset + *data++, shift); }
} }
} break;
break; case 4:
case 4: for (y = 0; y < h; ++y) {
for (y = 0; y < h; ++y) { const UINT32 *data = (const UINT32 *)&tiledata[4 * y * w];
const UINT32 *data = (const UINT32 *)&tiledata[4 * y * w]; UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0; for (x = 0; x < w; ++x) {
for (x = 0; x < w; ++x) { *row++ = j2ku_shift(offset + *data++, shift);
*row++ = j2ku_shift(offset + *data++, shift); }
} }
} break;
break;
} }
} }
static void static void
j2ku_gray_i(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, j2ku_gray_i(
const UINT8 *tiledata, Imaging im) opj_image_t *in,
{ const JPEG2KTILEINFO *tileinfo,
const UINT8 *tiledata,
Imaging im) {
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0; unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
unsigned w = tileinfo->x1 - tileinfo->x0; unsigned w = tileinfo->x1 - tileinfo->x0;
unsigned h = tileinfo->y1 - tileinfo->y0; unsigned h = tileinfo->y1 - tileinfo->y0;
@ -169,41 +166,42 @@ j2ku_gray_i(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
} }
switch (csiz) { switch (csiz) {
case 1: case 1:
for (y = 0; y < h; ++y) { for (y = 0; y < h; ++y) {
const UINT8 *data = &tiledata[y * w]; const UINT8 *data = &tiledata[y * w];
UINT16 *row = (UINT16 *)im->image[y0 + y] + x0; UINT16 *row = (UINT16 *)im->image[y0 + y] + x0;
for (x = 0; x < w; ++x) { for (x = 0; x < w; ++x) {
*row++ = j2ku_shift(offset + *data++, shift); *row++ = j2ku_shift(offset + *data++, shift);
}
} }
} break;
break; case 2:
case 2: for (y = 0; y < h; ++y) {
for (y = 0; y < h; ++y) { const UINT16 *data = (const UINT16 *)&tiledata[2 * y * w];
const UINT16 *data = (const UINT16 *)&tiledata[2 * y * w]; UINT16 *row = (UINT16 *)im->image[y0 + y] + x0;
UINT16 *row = (UINT16 *)im->image[y0 + y] + x0; for (x = 0; x < w; ++x) {
for (x = 0; x < w; ++x) { *row++ = j2ku_shift(offset + *data++, shift);
*row++ = j2ku_shift(offset + *data++, shift); }
} }
} break;
break; case 4:
case 4: for (y = 0; y < h; ++y) {
for (y = 0; y < h; ++y) { const UINT32 *data = (const UINT32 *)&tiledata[4 * y * w];
const UINT32 *data = (const UINT32 *)&tiledata[4 * y * w]; UINT16 *row = (UINT16 *)im->image[y0 + y] + x0;
UINT16 *row = (UINT16 *)im->image[y0 + y] + x0; for (x = 0; x < w; ++x) {
for (x = 0; x < w; ++x) { *row++ = j2ku_shift(offset + *data++, shift);
*row++ = j2ku_shift(offset + *data++, shift); }
} }
} break;
break;
} }
} }
static void static void
j2ku_gray_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, j2ku_gray_rgb(
const UINT8 *tiledata, Imaging im) opj_image_t *in,
{ const JPEG2KTILEINFO *tileinfo,
const UINT8 *tiledata,
Imaging im) {
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0; unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
unsigned w = tileinfo->x1 - tileinfo->x0; unsigned w = tileinfo->x1 - tileinfo->x0;
unsigned h = tileinfo->y1 - tileinfo->y0; unsigned h = tileinfo->y1 - tileinfo->y0;
@ -223,49 +221,51 @@ j2ku_gray_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
} }
switch (csiz) { switch (csiz) {
case 1: case 1:
for (y = 0; y < h; ++y) { for (y = 0; y < h; ++y) {
const UINT8 *data = &tiledata[y * w]; const UINT8 *data = &tiledata[y * w];
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0; UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
for (x = 0; x < w; ++x) { for (x = 0; x < w; ++x) {
UINT8 byte = j2ku_shift(offset + *data++, shift); UINT8 byte = j2ku_shift(offset + *data++, shift);
row[0] = row[1] = row[2] = byte; row[0] = row[1] = row[2] = byte;
row[3] = 0xff; row[3] = 0xff;
row += 4; row += 4;
}
} }
} break;
break; case 2:
case 2: for (y = 0; y < h; ++y) {
for (y = 0; y < h; ++y) { const UINT16 *data = (UINT16 *)&tiledata[2 * y * w];
const UINT16 *data = (UINT16 *)&tiledata[2 * y * w]; UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0; for (x = 0; x < w; ++x) {
for (x = 0; x < w; ++x) { UINT8 byte = j2ku_shift(offset + *data++, shift);
UINT8 byte = j2ku_shift(offset + *data++, shift); row[0] = row[1] = row[2] = byte;
row[0] = row[1] = row[2] = byte; row[3] = 0xff;
row[3] = 0xff; row += 4;
row += 4; }
} }
} break;
break; case 4:
case 4: for (y = 0; y < h; ++y) {
for (y = 0; y < h; ++y) { const UINT32 *data = (UINT32 *)&tiledata[4 * y * w];
const UINT32 *data = (UINT32 *)&tiledata[4 * y * w]; UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0; for (x = 0; x < w; ++x) {
for (x = 0; x < w; ++x) { UINT8 byte = j2ku_shift(offset + *data++, shift);
UINT8 byte = j2ku_shift(offset + *data++, shift); row[0] = row[1] = row[2] = byte;
row[0] = row[1] = row[2] = byte; row[3] = 0xff;
row[3] = 0xff; row += 4;
row += 4; }
} }
} break;
break;
} }
} }
static void static void
j2ku_graya_la(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, j2ku_graya_la(
const UINT8 *tiledata, Imaging im) opj_image_t *in,
{ const JPEG2KTILEINFO *tileinfo,
const UINT8 *tiledata,
Imaging im) {
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0; unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
unsigned w = tileinfo->x1 - tileinfo->x0; unsigned w = tileinfo->x1 - tileinfo->x0;
unsigned h = tileinfo->y1 - tileinfo->y0; unsigned h = tileinfo->y1 - tileinfo->y0;
@ -304,15 +304,31 @@ j2ku_graya_la(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
UINT32 word = 0, aword = 0, byte; UINT32 word = 0, aword = 0, byte;
switch (csiz) { switch (csiz) {
case 1: word = *data++; break; case 1:
case 2: word = *(const UINT16 *)data; data += 2; break; word = *data++;
case 4: word = *(const UINT32 *)data; data += 4; break; break;
case 2:
word = *(const UINT16 *)data;
data += 2;
break;
case 4:
word = *(const UINT32 *)data;
data += 4;
break;
} }
switch (acsiz) { switch (acsiz) {
case 1: aword = *adata++; break; case 1:
case 2: aword = *(const UINT16 *)adata; adata += 2; break; aword = *adata++;
case 4: aword = *(const UINT32 *)adata; adata += 4; break; break;
case 2:
aword = *(const UINT16 *)adata;
adata += 2;
break;
case 4:
aword = *(const UINT32 *)adata;
adata += 4;
break;
} }
byte = j2ku_shift(offset + word, shift); byte = j2ku_shift(offset + word, shift);
@ -324,9 +340,11 @@ j2ku_graya_la(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
} }
static void static void
j2ku_srgb_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, j2ku_srgb_rgb(
const UINT8 *tiledata, Imaging im) opj_image_t *in,
{ const JPEG2KTILEINFO *tileinfo,
const UINT8 *tiledata,
Imaging im) {
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0; unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
unsigned w = tileinfo->x1 - tileinfo->x0; unsigned w = tileinfo->x1 - tileinfo->x0;
unsigned h = tileinfo->y1 - tileinfo->y0; unsigned h = tileinfo->y1 - tileinfo->y0;
@ -365,9 +383,17 @@ j2ku_srgb_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
UINT32 word = 0; UINT32 word = 0;
switch (csiz[n]) { switch (csiz[n]) {
case 1: word = *data[n]++; break; case 1:
case 2: word = *(const UINT16 *)data[n]; data[n] += 2; break; word = *data[n]++;
case 4: word = *(const UINT32 *)data[n]; data[n] += 4; break; break;
case 2:
word = *(const UINT16 *)data[n];
data[n] += 2;
break;
case 4:
word = *(const UINT32 *)data[n];
data[n] += 4;
break;
} }
row[n] = j2ku_shift(offsets[n] + word, shifts[n]); row[n] = j2ku_shift(offsets[n] + word, shifts[n]);
@ -379,9 +405,11 @@ j2ku_srgb_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
} }
static void static void
j2ku_sycc_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, j2ku_sycc_rgb(
const UINT8 *tiledata, Imaging im) opj_image_t *in,
{ const JPEG2KTILEINFO *tileinfo,
const UINT8 *tiledata,
Imaging im) {
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0; unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
unsigned w = tileinfo->x1 - tileinfo->x0; unsigned w = tileinfo->x1 - tileinfo->x0;
unsigned h = tileinfo->y1 - tileinfo->y0; unsigned h = tileinfo->y1 - tileinfo->y0;
@ -421,9 +449,17 @@ j2ku_sycc_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
UINT32 word = 0; UINT32 word = 0;
switch (csiz[n]) { switch (csiz[n]) {
case 1: word = *data[n]++; break; case 1:
case 2: word = *(const UINT16 *)data[n]; data[n] += 2; break; word = *data[n]++;
case 4: word = *(const UINT32 *)data[n]; data[n] += 4; break; break;
case 2:
word = *(const UINT16 *)data[n];
data[n] += 2;
break;
case 4:
word = *(const UINT32 *)data[n];
data[n] += 4;
break;
} }
row[n] = j2ku_shift(offsets[n] + word, shifts[n]); row[n] = j2ku_shift(offsets[n] + word, shifts[n]);
@ -437,9 +473,11 @@ j2ku_sycc_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
} }
static void static void
j2ku_srgba_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, j2ku_srgba_rgba(
const UINT8 *tiledata, Imaging im) opj_image_t *in,
{ const JPEG2KTILEINFO *tileinfo,
const UINT8 *tiledata,
Imaging im) {
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0; unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
unsigned w = tileinfo->x1 - tileinfo->x0; unsigned w = tileinfo->x1 - tileinfo->x0;
unsigned h = tileinfo->y1 - tileinfo->y0; unsigned h = tileinfo->y1 - tileinfo->y0;
@ -478,9 +516,17 @@ j2ku_srgba_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
UINT32 word = 0; UINT32 word = 0;
switch (csiz[n]) { switch (csiz[n]) {
case 1: word = *data[n]++; break; case 1:
case 2: word = *(const UINT16 *)data[n]; data[n] += 2; break; word = *data[n]++;
case 4: word = *(const UINT32 *)data[n]; data[n] += 4; break; break;
case 2:
word = *(const UINT16 *)data[n];
data[n] += 2;
break;
case 4:
word = *(const UINT32 *)data[n];
data[n] += 4;
break;
} }
row[n] = j2ku_shift(offsets[n] + word, shifts[n]); row[n] = j2ku_shift(offsets[n] + word, shifts[n]);
@ -491,9 +537,11 @@ j2ku_srgba_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
} }
static void static void
j2ku_sycca_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, j2ku_sycca_rgba(
const UINT8 *tiledata, Imaging im) opj_image_t *in,
{ const JPEG2KTILEINFO *tileinfo,
const UINT8 *tiledata,
Imaging im) {
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0; unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
unsigned w = tileinfo->x1 - tileinfo->x0; unsigned w = tileinfo->x1 - tileinfo->x0;
unsigned h = tileinfo->y1 - tileinfo->y0; unsigned h = tileinfo->y1 - tileinfo->y0;
@ -533,9 +581,17 @@ j2ku_sycca_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
UINT32 word = 0; UINT32 word = 0;
switch (csiz[n]) { switch (csiz[n]) {
case 1: word = *data[n]++; break; case 1:
case 2: word = *(const UINT16 *)data[n]; data[n] += 2; break; word = *data[n]++;
case 4: word = *(const UINT32 *)data[n]; data[n] += 4; break; break;
case 2:
word = *(const UINT16 *)data[n];
data[n] += 2;
break;
case 4:
word = *(const UINT32 *)data[n];
data[n] += 4;
break;
} }
row[n] = j2ku_shift(offsets[n] + word, shifts[n]); row[n] = j2ku_shift(offsets[n] + word, shifts[n]);
@ -548,22 +604,22 @@ j2ku_sycca_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
} }
static const struct j2k_decode_unpacker j2k_unpackers[] = { static const struct j2k_decode_unpacker j2k_unpackers[] = {
{ "L", OPJ_CLRSPC_GRAY, 1, j2ku_gray_l }, {"L", OPJ_CLRSPC_GRAY, 1, j2ku_gray_l},
{ "I;16", OPJ_CLRSPC_GRAY, 1, j2ku_gray_i }, {"I;16", OPJ_CLRSPC_GRAY, 1, j2ku_gray_i},
{ "I;16B", OPJ_CLRSPC_GRAY, 1, j2ku_gray_i }, {"I;16B", OPJ_CLRSPC_GRAY, 1, j2ku_gray_i},
{ "LA", OPJ_CLRSPC_GRAY, 2, j2ku_graya_la }, {"LA", OPJ_CLRSPC_GRAY, 2, j2ku_graya_la},
{ "RGB", OPJ_CLRSPC_GRAY, 1, j2ku_gray_rgb }, {"RGB", OPJ_CLRSPC_GRAY, 1, j2ku_gray_rgb},
{ "RGB", OPJ_CLRSPC_GRAY, 2, j2ku_gray_rgb }, {"RGB", OPJ_CLRSPC_GRAY, 2, j2ku_gray_rgb},
{ "RGB", OPJ_CLRSPC_SRGB, 3, j2ku_srgb_rgb }, {"RGB", OPJ_CLRSPC_SRGB, 3, j2ku_srgb_rgb},
{ "RGB", OPJ_CLRSPC_SYCC, 3, j2ku_sycc_rgb }, {"RGB", OPJ_CLRSPC_SYCC, 3, j2ku_sycc_rgb},
{ "RGB", OPJ_CLRSPC_SRGB, 4, j2ku_srgb_rgb }, {"RGB", OPJ_CLRSPC_SRGB, 4, j2ku_srgb_rgb},
{ "RGB", OPJ_CLRSPC_SYCC, 4, j2ku_sycc_rgb }, {"RGB", OPJ_CLRSPC_SYCC, 4, j2ku_sycc_rgb},
{ "RGBA", OPJ_CLRSPC_GRAY, 1, j2ku_gray_rgb }, {"RGBA", OPJ_CLRSPC_GRAY, 1, j2ku_gray_rgb},
{ "RGBA", OPJ_CLRSPC_GRAY, 2, j2ku_graya_la }, {"RGBA", OPJ_CLRSPC_GRAY, 2, j2ku_graya_la},
{ "RGBA", OPJ_CLRSPC_SRGB, 3, j2ku_srgb_rgb }, {"RGBA", OPJ_CLRSPC_SRGB, 3, j2ku_srgb_rgb},
{ "RGBA", OPJ_CLRSPC_SYCC, 3, j2ku_sycc_rgb }, {"RGBA", OPJ_CLRSPC_SYCC, 3, j2ku_sycc_rgb},
{ "RGBA", OPJ_CLRSPC_SRGB, 4, j2ku_srgba_rgba }, {"RGBA", OPJ_CLRSPC_SRGB, 4, j2ku_srgba_rgba},
{ "RGBA", OPJ_CLRSPC_SYCC, 4, j2ku_sycca_rgba }, {"RGBA", OPJ_CLRSPC_SYCC, 4, j2ku_sycca_rgba},
}; };
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
@ -578,9 +634,8 @@ enum {
}; };
static int static int
j2k_decode_entry(Imaging im, ImagingCodecState state) j2k_decode_entry(Imaging im, ImagingCodecState state) {
{ JPEG2KDECODESTATE *context = (JPEG2KDECODESTATE *)state->context;
JPEG2KDECODESTATE *context = (JPEG2KDECODESTATE *) state->context;
opj_stream_t *stream = NULL; opj_stream_t *stream = NULL;
opj_image_t *image = NULL; opj_image_t *image = NULL;
opj_codec_t *codec = NULL; opj_codec_t *codec = NULL;
@ -591,7 +646,6 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
unsigned n, tile_height, tile_width; unsigned n, tile_height, tile_width;
int components; int components;
stream = opj_stream_create(BUFFER_SIZE, OPJ_TRUE); stream = opj_stream_create(BUFFER_SIZE, OPJ_TRUE);
if (!stream) { if (!stream) {
@ -645,8 +699,8 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
} }
/* Check that this image is something we can handle */ /* Check that this image is something we can handle */
if (image->numcomps < 1 || image->numcomps > 4 if (image->numcomps < 1 || image->numcomps > 4 ||
|| image->color_space == OPJ_CLRSPC_UNKNOWN) { image->color_space == OPJ_CLRSPC_UNKNOWN) {
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
state->state = J2K_STATE_FAILED; state->state = J2K_STATE_FAILED;
goto quick_exit; goto quick_exit;
@ -686,15 +740,21 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
if (color_space == OPJ_CLRSPC_UNSPECIFIED) { if (color_space == OPJ_CLRSPC_UNSPECIFIED) {
switch (image->numcomps) { switch (image->numcomps) {
case 1: case 2: color_space = OPJ_CLRSPC_GRAY; break; case 1:
case 3: case 4: color_space = OPJ_CLRSPC_SRGB; break; case 2:
color_space = OPJ_CLRSPC_GRAY;
break;
case 3:
case 4:
color_space = OPJ_CLRSPC_SRGB;
break;
} }
} }
for (n = 0; n < sizeof(j2k_unpackers) / sizeof (j2k_unpackers[0]); ++n) { for (n = 0; n < sizeof(j2k_unpackers) / sizeof(j2k_unpackers[0]); ++n) {
if (color_space == j2k_unpackers[n].color_space if (color_space == j2k_unpackers[n].color_space &&
&& image->numcomps == j2k_unpackers[n].components image->numcomps == j2k_unpackers[n].components &&
&& strcmp (im->mode, j2k_unpackers[n].mode) == 0) { strcmp(im->mode, j2k_unpackers[n].mode) == 0) {
unpack = j2k_unpackers[n].unpacker; unpack = j2k_unpackers[n].unpacker;
break; break;
} }
@ -713,14 +773,17 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
OPJ_BOOL should_continue; OPJ_BOOL should_continue;
unsigned correction = (1 << params.cp_reduce) - 1; unsigned correction = (1 << params.cp_reduce) - 1;
if (!opj_read_tile_header(codec, if (!opj_read_tile_header(
stream, codec,
&tile_info.tile_index, stream,
&tile_info.data_size, &tile_info.tile_index,
&tile_info.x0, &tile_info.y0, &tile_info.data_size,
&tile_info.x1, &tile_info.y1, &tile_info.x0,
&tile_info.nb_comps, &tile_info.y0,
&should_continue)) { &tile_info.x1,
&tile_info.y1,
&tile_info.nb_comps,
&should_continue)) {
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
state->state = J2K_STATE_FAILED; state->state = J2K_STATE_FAILED;
goto quick_exit; goto quick_exit;
@ -740,14 +803,12 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
/* Check the tile bounds; if the tile is outside the image area, /* Check the tile bounds; if the tile is outside the image area,
or if it has a negative width or height (i.e. the coordinates are or if it has a negative width or height (i.e. the coordinates are
swapped), bail. */ swapped), bail. */
if (tile_info.x0 >= tile_info.x1 if (tile_info.x0 >= tile_info.x1 || tile_info.y0 >= tile_info.y1 ||
|| tile_info.y0 >= tile_info.y1 tile_info.x0 < 0 || tile_info.y0 < 0 ||
|| tile_info.x0 < 0 (OPJ_UINT32)tile_info.x0 < image->x0 ||
|| tile_info.y0 < 0 (OPJ_UINT32)tile_info.y0 < image->y0 ||
|| (OPJ_UINT32)tile_info.x0 < image->x0 (OPJ_INT32)(tile_info.x1 - image->x0) > im->xsize ||
|| (OPJ_UINT32)tile_info.y0 < image->y0 (OPJ_INT32)(tile_info.y1 - image->y0) > im->ysize) {
|| (OPJ_INT32)(tile_info.x1 - image->x0) > im->xsize
|| (OPJ_INT32)(tile_info.y1 - image->y0) > im->ysize) {
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
state->state = J2K_STATE_FAILED; state->state = J2K_STATE_FAILED;
goto quick_exit; goto quick_exit;
@ -760,10 +821,10 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
tile_width = tile_info.x1 - tile_info.x0; tile_width = tile_info.x1 - tile_info.x0;
tile_height = tile_info.y1 - tile_info.y0; tile_height = tile_info.y1 - tile_info.y0;
components = tile_info.nb_comps == 3 ? 4 : tile_info.nb_comps; components = tile_info.nb_comps == 3 ? 4 : tile_info.nb_comps;
if (( tile_width > UINT_MAX / components ) || if ((tile_width > UINT_MAX / components) ||
( tile_height > UINT_MAX / components ) || (tile_height > UINT_MAX / components) ||
( tile_width > UINT_MAX / (tile_height * components )) || (tile_width > UINT_MAX / (tile_height * components)) ||
( tile_height > UINT_MAX / (tile_width * components ))) { (tile_height > UINT_MAX / (tile_width * components))) {
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
state->state = J2K_STATE_FAILED; state->state = J2K_STATE_FAILED;
goto quick_exit; goto quick_exit;
@ -777,7 +838,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
if (buffer_size < tile_info.data_size) { if (buffer_size < tile_info.data_size) {
/* malloc check ok, overflow and tile size sanity check above */ /* malloc check ok, overflow and tile size sanity check above */
UINT8 *new = realloc (state->buffer, tile_info.data_size); UINT8 *new = realloc(state->buffer, tile_info.data_size);
if (!new) { if (!new) {
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
state->state = J2K_STATE_FAILED; state->state = J2K_STATE_FAILED;
@ -787,12 +848,12 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
buffer_size = tile_info.data_size; buffer_size = tile_info.data_size;
} }
if (!opj_decode_tile_data(
if (!opj_decode_tile_data(codec, codec,
tile_info.tile_index, tile_info.tile_index,
(OPJ_BYTE *)state->buffer, (OPJ_BYTE *)state->buffer,
tile_info.data_size, tile_info.data_size,
stream)) { stream)) {
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
state->state = J2K_STATE_FAILED; state->state = J2K_STATE_FAILED;
goto quick_exit; goto quick_exit;
@ -811,12 +872,12 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
state->errcode = IMAGING_CODEC_END; state->errcode = IMAGING_CODEC_END;
if (context->pfile) { if (context->pfile) {
if(fclose(context->pfile)){ if (fclose(context->pfile)) {
context->pfile = NULL; context->pfile = NULL;
} }
} }
quick_exit: quick_exit:
if (codec) { if (codec) {
opj_destroy_codec(codec); opj_destroy_codec(codec);
} }
@ -831,10 +892,8 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
} }
int int
ImagingJpeg2KDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes) ImagingJpeg2KDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
{ if (bytes) {
if (bytes){
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
state->state = J2K_STATE_FAILED; state->state = J2K_STATE_FAILED;
return -1; return -1;
@ -867,7 +926,7 @@ ImagingJpeg2KDecodeCleanup(ImagingCodecState state) {
JPEG2KDECODESTATE *context = (JPEG2KDECODESTATE *)state->context; JPEG2KDECODESTATE *context = (JPEG2KDECODESTATE *)state->context;
if (context->error_msg) { if (context->error_msg) {
free ((void *)context->error_msg); free((void *)context->error_msg);
} }
context->error_msg = NULL; context->error_msg = NULL;
@ -876,8 +935,7 @@ ImagingJpeg2KDecodeCleanup(ImagingCodecState state) {
} }
const char * const char *
ImagingJpeg2KVersion(void) ImagingJpeg2KVersion(void) {
{
return opj_version(); return opj_version();
} }

View File

@ -19,26 +19,24 @@
#include "Jpeg2K.h" #include "Jpeg2K.h"
#define CINEMA_24_CS_LENGTH 1302083 #define CINEMA_24_CS_LENGTH 1302083
#define CINEMA_48_CS_LENGTH 651041 #define CINEMA_48_CS_LENGTH 651041
#define COMP_24_CS_MAX_LENGTH 1041666 #define COMP_24_CS_MAX_LENGTH 1041666
#define COMP_48_CS_MAX_LENGTH 520833 #define COMP_48_CS_MAX_LENGTH 520833
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Error handler */ /* Error handler */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
static void static void
j2k_error(const char *msg, void *client_data) j2k_error(const char *msg, void *client_data) {
{ JPEG2KENCODESTATE *state = (JPEG2KENCODESTATE *)client_data;
JPEG2KENCODESTATE *state = (JPEG2KENCODESTATE *) client_data;
free((void *)state->error_msg); free((void *)state->error_msg);
state->error_msg = strdup(msg); state->error_msg = strdup(msg);
} }
static void static void
j2k_warn(const char *msg, void *client_data) j2k_warn(const char *msg, void *client_data) {
{
// Null handler // Null handler
} }
@ -47,8 +45,7 @@ j2k_warn(const char *msg, void *client_data)
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
static OPJ_SIZE_T static OPJ_SIZE_T
j2k_write(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) j2k_write(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) {
{
ImagingCodecState state = (ImagingCodecState)p_user_data; ImagingCodecState state = (ImagingCodecState)p_user_data;
unsigned int result; unsigned int result;
@ -57,16 +54,14 @@ j2k_write(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data)
return result ? result : (OPJ_SIZE_T)-1; return result ? result : (OPJ_SIZE_T)-1;
} }
static OPJ_OFF_T static OPJ_OFF_T
j2k_skip(OPJ_OFF_T p_nb_bytes, void *p_user_data) j2k_skip(OPJ_OFF_T p_nb_bytes, void *p_user_data) {
{
ImagingCodecState state = (ImagingCodecState)p_user_data; ImagingCodecState state = (ImagingCodecState)p_user_data;
char *buffer; char *buffer;
int result; int result;
/* Explicitly write zeros */ /* Explicitly write zeros */
buffer = calloc(p_nb_bytes,1); buffer = calloc(p_nb_bytes, 1);
if (!buffer) { if (!buffer) {
return (OPJ_OFF_T)-1; return (OPJ_OFF_T)-1;
} }
@ -79,8 +74,7 @@ j2k_skip(OPJ_OFF_T p_nb_bytes, void *p_user_data)
} }
static OPJ_BOOL static OPJ_BOOL
j2k_seek(OPJ_OFF_T p_nb_bytes, void *p_user_data) j2k_seek(OPJ_OFF_T p_nb_bytes, void *p_user_data) {
{
ImagingCodecState state = (ImagingCodecState)p_user_data; ImagingCodecState state = (ImagingCodecState)p_user_data;
off_t pos = 0; off_t pos = 0;
@ -94,16 +88,13 @@ j2k_seek(OPJ_OFF_T p_nb_bytes, void *p_user_data)
/* Encoder */ /* Encoder */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
typedef void (*j2k_pack_tile_t)(Imaging im, UINT8 *buf, typedef void (*j2k_pack_tile_t)(
unsigned x0, unsigned y0, Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h);
unsigned w, unsigned h);
static void static void
j2k_pack_l(Imaging im, UINT8 *buf, j2k_pack_l(Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h) {
unsigned x0, unsigned y0, unsigned w, unsigned h)
{
UINT8 *ptr = buf; UINT8 *ptr = buf;
unsigned x,y; unsigned x, y;
for (y = 0; y < h; ++y) { for (y = 0; y < h; ++y) {
UINT8 *data = (UINT8 *)(im->image[y + y0] + x0); UINT8 *data = (UINT8 *)(im->image[y + y0] + x0);
for (x = 0; x < w; ++x) { for (x = 0; x < w; ++x) {
@ -113,11 +104,9 @@ j2k_pack_l(Imaging im, UINT8 *buf,
} }
static void static void
j2k_pack_i16(Imaging im, UINT8 *buf, j2k_pack_i16(Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h) {
unsigned x0, unsigned y0, unsigned w, unsigned h)
{
UINT8 *ptr = buf; UINT8 *ptr = buf;
unsigned x,y; unsigned x, y;
for (y = 0; y < h; ++y) { for (y = 0; y < h; ++y) {
UINT8 *data = (UINT8 *)(im->image[y + y0] + x0); UINT8 *data = (UINT8 *)(im->image[y + y0] + x0);
for (x = 0; x < w; ++x) { for (x = 0; x < w; ++x) {
@ -127,14 +116,11 @@ j2k_pack_i16(Imaging im, UINT8 *buf,
} }
} }
static void static void
j2k_pack_la(Imaging im, UINT8 *buf, j2k_pack_la(Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h) {
unsigned x0, unsigned y0, unsigned w, unsigned h)
{
UINT8 *ptr = buf; UINT8 *ptr = buf;
UINT8 *ptra = buf + w * h; UINT8 *ptra = buf + w * h;
unsigned x,y; unsigned x, y;
for (y = 0; y < h; ++y) { for (y = 0; y < h; ++y) {
UINT8 *data = (UINT8 *)(im->image[y + y0] + 4 * x0); UINT8 *data = (UINT8 *)(im->image[y + y0] + 4 * x0);
for (x = 0; x < w; ++x) { for (x = 0; x < w; ++x) {
@ -146,13 +132,11 @@ j2k_pack_la(Imaging im, UINT8 *buf,
} }
static void static void
j2k_pack_rgb(Imaging im, UINT8 *buf, j2k_pack_rgb(Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h) {
unsigned x0, unsigned y0, unsigned w, unsigned h)
{
UINT8 *pr = buf; UINT8 *pr = buf;
UINT8 *pg = pr + w * h; UINT8 *pg = pr + w * h;
UINT8 *pb = pg + w * h; UINT8 *pb = pg + w * h;
unsigned x,y; unsigned x, y;
for (y = 0; y < h; ++y) { for (y = 0; y < h; ++y) {
UINT8 *data = (UINT8 *)(im->image[y + y0] + 4 * x0); UINT8 *data = (UINT8 *)(im->image[y + y0] + 4 * x0);
for (x = 0; x < w; ++x) { for (x = 0; x < w; ++x) {
@ -165,14 +149,13 @@ j2k_pack_rgb(Imaging im, UINT8 *buf,
} }
static void static void
j2k_pack_rgba(Imaging im, UINT8 *buf, j2k_pack_rgba(
unsigned x0, unsigned y0, unsigned w, unsigned h) Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h) {
{
UINT8 *pr = buf; UINT8 *pr = buf;
UINT8 *pg = pr + w * h; UINT8 *pg = pr + w * h;
UINT8 *pb = pg + w * h; UINT8 *pb = pg + w * h;
UINT8 *pa = pb + w * h; UINT8 *pa = pb + w * h;
unsigned x,y; unsigned x, y;
for (y = 0; y < h; ++y) { for (y = 0; y < h; ++y) {
UINT8 *data = (UINT8 *)(im->image[y + y0] + 4 * x0); UINT8 *data = (UINT8 *)(im->image[y + y0] + 4 * x0);
for (x = 0; x < w; ++x) { for (x = 0; x < w; ++x) {
@ -192,8 +175,7 @@ enum {
}; };
static void static void
j2k_set_cinema_params(Imaging im, int components, opj_cparameters_t *params) j2k_set_cinema_params(Imaging im, int components, opj_cparameters_t *params) {
{
float rate; float rate;
int n; int n;
@ -215,8 +197,9 @@ j2k_set_cinema_params(Imaging im, int components, opj_cparameters_t *params)
params->irreversible = 1; params->irreversible = 1;
if (params->cp_cinema == OPJ_CINEMA4K_24) { if (params->cp_cinema == OPJ_CINEMA4K_24) {
float max_rate = ((float)(components * im->xsize * im->ysize * 8) float max_rate =
/ (CINEMA_24_CS_LENGTH * 8)); ((float)(components * im->xsize * im->ysize * 8) /
(CINEMA_24_CS_LENGTH * 8));
params->POC[0].tile = 1; params->POC[0].tile = 1;
params->POC[0].resno0 = 0; params->POC[0].resno0 = 0;
@ -239,8 +222,9 @@ j2k_set_cinema_params(Imaging im, int components, opj_cparameters_t *params)
if (params->tcp_rates[0] == 0) { if (params->tcp_rates[0] == 0) {
params->tcp_rates[n] = max_rate; params->tcp_rates[n] = max_rate;
} else { } else {
rate = ((float)(components * im->xsize * im->ysize * 8) rate =
/ (params->tcp_rates[n] * 8)); ((float)(components * im->xsize * im->ysize * 8) /
(params->tcp_rates[n] * 8));
if (rate > CINEMA_24_CS_LENGTH) { if (rate > CINEMA_24_CS_LENGTH) {
params->tcp_rates[n] = max_rate; params->tcp_rates[n] = max_rate;
} }
@ -249,16 +233,18 @@ j2k_set_cinema_params(Imaging im, int components, opj_cparameters_t *params)
params->max_comp_size = COMP_24_CS_MAX_LENGTH; params->max_comp_size = COMP_24_CS_MAX_LENGTH;
} else { } else {
float max_rate = ((float)(components * im->xsize * im->ysize * 8) float max_rate =
/ (CINEMA_48_CS_LENGTH * 8)); ((float)(components * im->xsize * im->ysize * 8) /
(CINEMA_48_CS_LENGTH * 8));
for (n = 0; n < params->tcp_numlayers; ++n) { for (n = 0; n < params->tcp_numlayers; ++n) {
rate = 0; rate = 0;
if (params->tcp_rates[0] == 0) { if (params->tcp_rates[0] == 0) {
params->tcp_rates[n] = max_rate; params->tcp_rates[n] = max_rate;
} else { } else {
rate = ((float)(components * im->xsize * im->ysize * 8) rate =
/ (params->tcp_rates[n] * 8)); ((float)(components * im->xsize * im->ysize * 8) /
(params->tcp_rates[n] * 8));
if (rate > CINEMA_48_CS_LENGTH) { if (rate > CINEMA_48_CS_LENGTH) {
params->tcp_rates[n] = max_rate; params->tcp_rates[n] = max_rate;
} }
@ -270,8 +256,7 @@ j2k_set_cinema_params(Imaging im, int components, opj_cparameters_t *params)
} }
static int static int
j2k_encode_entry(Imaging im, ImagingCodecState state) j2k_encode_entry(Imaging im, ImagingCodecState state) {
{
JPEG2KENCODESTATE *context = (JPEG2KENCODESTATE *)state->context; JPEG2KENCODESTATE *context = (JPEG2KENCODESTATE *)state->context;
opj_stream_t *stream = NULL; opj_stream_t *stream = NULL;
opj_image_t *image = NULL; opj_image_t *image = NULL;
@ -312,35 +297,35 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
#endif #endif
/* Setup an opj_image */ /* Setup an opj_image */
if (strcmp (im->mode, "L") == 0) { if (strcmp(im->mode, "L") == 0) {
components = 1; components = 1;
color_space = OPJ_CLRSPC_GRAY; color_space = OPJ_CLRSPC_GRAY;
pack = j2k_pack_l; pack = j2k_pack_l;
} else if (strcmp (im->mode, "I;16") == 0){ } else if (strcmp(im->mode, "I;16") == 0) {
components = 1; components = 1;
color_space = OPJ_CLRSPC_GRAY; color_space = OPJ_CLRSPC_GRAY;
pack = j2k_pack_i16; pack = j2k_pack_i16;
prec = 16; prec = 16;
bpp = 12; bpp = 12;
} else if (strcmp (im->mode, "I;16B") == 0){ } else if (strcmp(im->mode, "I;16B") == 0) {
components = 1; components = 1;
color_space = OPJ_CLRSPC_GRAY; color_space = OPJ_CLRSPC_GRAY;
pack = j2k_pack_i16; pack = j2k_pack_i16;
prec = 16; prec = 16;
bpp = 12; bpp = 12;
} else if (strcmp (im->mode, "LA") == 0) { } else if (strcmp(im->mode, "LA") == 0) {
components = 2; components = 2;
color_space = OPJ_CLRSPC_GRAY; color_space = OPJ_CLRSPC_GRAY;
pack = j2k_pack_la; pack = j2k_pack_la;
} else if (strcmp (im->mode, "RGB") == 0) { } else if (strcmp(im->mode, "RGB") == 0) {
components = 3; components = 3;
color_space = OPJ_CLRSPC_SRGB; color_space = OPJ_CLRSPC_SRGB;
pack = j2k_pack_rgb; pack = j2k_pack_rgb;
} else if (strcmp (im->mode, "YCbCr") == 0) { } else if (strcmp(im->mode, "YCbCr") == 0) {
components = 3; components = 3;
color_space = OPJ_CLRSPC_SYCC; color_space = OPJ_CLRSPC_SYCC;
pack = j2k_pack_rgb; pack = j2k_pack_rgb;
} else if (strcmp (im->mode, "RGBA") == 0) { } else if (strcmp(im->mode, "RGBA") == 0) {
components = 4; components = 4;
color_space = OPJ_CLRSPC_SRGB; color_space = OPJ_CLRSPC_SRGB;
pack = j2k_pack_rgba; pack = j2k_pack_rgba;
@ -400,8 +385,9 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
float *pq; float *pq;
if (len > 0) { if (len > 0) {
if ((unsigned)len > sizeof(params.tcp_rates) / sizeof(params.tcp_rates[0])) { if ((unsigned)len >
len = sizeof(params.tcp_rates)/sizeof(params.tcp_rates[0]); sizeof(params.tcp_rates) / sizeof(params.tcp_rates[0])) {
len = sizeof(params.tcp_rates) / sizeof(params.tcp_rates[0]);
} }
params.tcp_numlayers = (int)len; params.tcp_numlayers = (int)len;
@ -431,16 +417,16 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
params.numresolution = context->num_resolutions; params.numresolution = context->num_resolutions;
} }
if (context->cblk_width >= 4 && context->cblk_width <= 1024 if (context->cblk_width >= 4 && context->cblk_width <= 1024 &&
&& context->cblk_height >= 4 && context->cblk_height <= 1024 context->cblk_height >= 4 && context->cblk_height <= 1024 &&
&& context->cblk_width * context->cblk_height <= 4096) { context->cblk_width * context->cblk_height <= 4096) {
params.cblockw_init = context->cblk_width; params.cblockw_init = context->cblk_width;
params.cblockh_init = context->cblk_height; params.cblockh_init = context->cblk_height;
} }
if (context->precinct_width >= 4 && context->precinct_height >= 4 if (context->precinct_width >= 4 && context->precinct_height >= 4 &&
&& context->precinct_width >= context->cblk_width context->precinct_width >= context->cblk_width &&
&& context->precinct_height > context->cblk_height) { context->precinct_height > context->cblk_height) {
params.prcw_init[0] = context->precinct_width; params.prcw_init[0] = context->precinct_width;
params.prch_init[0] = context->precinct_height; params.prch_init[0] = context->precinct_height;
params.res_spec = 1; params.res_spec = 1;
@ -454,22 +440,22 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
params.cp_cinema = context->cinema_mode; params.cp_cinema = context->cinema_mode;
switch (params.cp_cinema) { switch (params.cp_cinema) {
case OPJ_OFF: case OPJ_OFF:
params.cp_rsiz = OPJ_STD_RSIZ; params.cp_rsiz = OPJ_STD_RSIZ;
break; break;
case OPJ_CINEMA2K_24: case OPJ_CINEMA2K_24:
case OPJ_CINEMA2K_48: case OPJ_CINEMA2K_48:
params.cp_rsiz = OPJ_CINEMA2K; params.cp_rsiz = OPJ_CINEMA2K;
if (params.numresolution > 6) { if (params.numresolution > 6) {
params.numresolution = 6; params.numresolution = 6;
} }
break; break;
case OPJ_CINEMA4K_24: case OPJ_CINEMA4K_24:
params.cp_rsiz = OPJ_CINEMA4K; params.cp_rsiz = OPJ_CINEMA4K;
if (params.numresolution > 7) { if (params.numresolution > 7) {
params.numresolution = 7; params.numresolution = 7;
} }
break; break;
} }
if (context->cinema_mode != OPJ_OFF) { if (context->cinema_mode != OPJ_OFF) {
@ -504,24 +490,24 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
} }
/* Write each tile */ /* Write each tile */
tiles_x = (im->xsize + (params.image_offset_x0 - params.cp_tx0) tiles_x = (im->xsize + (params.image_offset_x0 - params.cp_tx0) + tile_width - 1) /
+ tile_width - 1) / tile_width; tile_width;
tiles_y = (im->ysize + (params.image_offset_y0 - params.cp_ty0) tiles_y = (im->ysize + (params.image_offset_y0 - params.cp_ty0) + tile_height - 1) /
+ tile_height - 1) / tile_height; tile_height;
/* check for integer overflow for the malloc line, checking any expression /* check for integer overflow for the malloc line, checking any expression
that may multiply either tile_width or tile_height */ that may multiply either tile_width or tile_height */
_overflow_scale_factor = components * prec; _overflow_scale_factor = components * prec;
if (( tile_width > UINT_MAX / _overflow_scale_factor ) || if ((tile_width > UINT_MAX / _overflow_scale_factor) ||
( tile_height > UINT_MAX / _overflow_scale_factor ) || (tile_height > UINT_MAX / _overflow_scale_factor) ||
( tile_width > UINT_MAX / (tile_height * _overflow_scale_factor )) || (tile_width > UINT_MAX / (tile_height * _overflow_scale_factor)) ||
( tile_height > UINT_MAX / (tile_width * _overflow_scale_factor ))) { (tile_height > UINT_MAX / (tile_width * _overflow_scale_factor))) {
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
state->state = J2K_STATE_FAILED; state->state = J2K_STATE_FAILED;
goto quick_exit; goto quick_exit;
} }
/* malloc check ok, checked for overflow above */ /* malloc check ok, checked for overflow above */
state->buffer = malloc (tile_width * tile_height * components * prec / 8); state->buffer = malloc(tile_width * tile_height * components * prec / 8);
if (!state->buffer) { if (!state->buffer) {
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
state->state = J2K_STATE_FAILED; state->state = J2K_STATE_FAILED;
@ -564,8 +550,7 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
data_size = pixw * pixh * components * prec / 8; data_size = pixw * pixh * components * prec / 8;
if (!opj_write_tile(codec, tile_ndx++, state->buffer, if (!opj_write_tile(codec, tile_ndx++, state->buffer, data_size, stream)) {
data_size, stream)) {
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
state->state = J2K_STATE_FAILED; state->state = J2K_STATE_FAILED;
goto quick_exit; goto quick_exit;
@ -583,7 +568,7 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
state->state = J2K_STATE_DONE; state->state = J2K_STATE_DONE;
ret = -1; ret = -1;
quick_exit: quick_exit:
if (codec) { if (codec) {
opj_destroy_codec(codec); opj_destroy_codec(codec);
} }
@ -598,14 +583,12 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
} }
int int
ImagingJpeg2KEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) ImagingJpeg2KEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
{
if (state->state == J2K_STATE_FAILED) { if (state->state == J2K_STATE_FAILED) {
return -1; return -1;
} }
if (state->state == J2K_STATE_START) { if (state->state == J2K_STATE_START) {
state->state = J2K_STATE_ENCODING; state->state = J2K_STATE_ENCODING;
return j2k_encode_entry(im, state); return j2k_encode_entry(im, state);
@ -628,12 +611,11 @@ ImagingJpeg2KEncodeCleanup(ImagingCodecState state) {
} }
if (context->error_msg) { if (context->error_msg) {
free ((void *)context->error_msg); free((void *)context->error_msg);
} }
context->error_msg = NULL; context->error_msg = NULL;
return -1; return -1;
} }

View File

@ -21,10 +21,9 @@
* See the README file for details on usage and redistribution. * See the README file for details on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#ifdef HAVE_LIBJPEG #ifdef HAVE_LIBJPEG
#undef HAVE_PROTOTYPES #undef HAVE_PROTOTYPES
#undef HAVE_STDLIB_H #undef HAVE_STDLIB_H
@ -37,7 +36,6 @@
#include "Jpeg.h" #include "Jpeg.h"
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x) #define TOSTRING(x) STRINGIFY(x)
@ -50,20 +48,19 @@ char *libjpeg_turbo_version = NULL;
#endif #endif
int int
ImagingJpegUseJCSExtensions() ImagingJpegUseJCSExtensions() {
{
int use_jcs_extensions = 0; int use_jcs_extensions = 0;
#ifdef JCS_EXTENSIONS #ifdef JCS_EXTENSIONS
#if defined(LIBJPEG_TURBO_VERSION_NUMBER) #if defined(LIBJPEG_TURBO_VERSION_NUMBER)
#if LIBJPEG_TURBO_VERSION_NUMBER >= 1002010 #if LIBJPEG_TURBO_VERSION_NUMBER >= 1002010
use_jcs_extensions = 1; use_jcs_extensions = 1;
#endif #endif
#else #else
if (libjpeg_turbo_version) { if (libjpeg_turbo_version) {
use_jcs_extensions = strcmp(libjpeg_turbo_version, "1.2.1") >= 0; use_jcs_extensions = strcmp(libjpeg_turbo_version, "1.2.1") >= 0;
} }
#endif #endif
#endif #endif
return use_jcs_extensions; return use_jcs_extensions;
} }
@ -72,24 +69,19 @@ ImagingJpegUseJCSExtensions()
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
METHODDEF(void) METHODDEF(void)
stub(j_decompress_ptr cinfo) stub(j_decompress_ptr cinfo) { /* empty */ }
{
/* empty */
}
METHODDEF(boolean) METHODDEF(boolean)
fill_input_buffer(j_decompress_ptr cinfo) fill_input_buffer(j_decompress_ptr cinfo) {
{
/* Suspension */ /* Suspension */
return FALSE; return FALSE;
} }
METHODDEF(void) METHODDEF(void)
skip_input_data(j_decompress_ptr cinfo, long num_bytes) skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
{ JPEGSOURCE *source = (JPEGSOURCE *)cinfo->src;
JPEGSOURCE* source = (JPEGSOURCE*) cinfo->src;
if (num_bytes > (long) source->pub.bytes_in_buffer) { if (num_bytes > (long)source->pub.bytes_in_buffer) {
/* We need to skip more data than we have in the buffer. /* We need to skip more data than we have in the buffer.
This will force the JPEG library to suspend decoding. */ This will force the JPEG library to suspend decoding. */
source->skip = num_bytes - source->pub.bytes_in_buffer; source->skip = num_bytes - source->pub.bytes_in_buffer;
@ -103,50 +95,42 @@ skip_input_data(j_decompress_ptr cinfo, long num_bytes)
} }
} }
GLOBAL(void) GLOBAL(void)
jpeg_buffer_src(j_decompress_ptr cinfo, JPEGSOURCE* source) jpeg_buffer_src(j_decompress_ptr cinfo, JPEGSOURCE *source) {
{ cinfo->src = (void *)source;
cinfo->src = (void*) source;
/* Prepare for suspending reader */ /* Prepare for suspending reader */
source->pub.init_source = stub; source->pub.init_source = stub;
source->pub.fill_input_buffer = fill_input_buffer; source->pub.fill_input_buffer = fill_input_buffer;
source->pub.skip_input_data = skip_input_data; source->pub.skip_input_data = skip_input_data;
source->pub.resync_to_restart = jpeg_resync_to_restart; source->pub.resync_to_restart = jpeg_resync_to_restart;
source->pub.term_source = stub; source->pub.term_source = stub;
source->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ source->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
source->skip = 0; source->skip = 0;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Error handler */ /* Error handler */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
METHODDEF(void) METHODDEF(void)
error(j_common_ptr cinfo) error(j_common_ptr cinfo) {
{ JPEGERROR *error;
JPEGERROR* error; error = (JPEGERROR *)cinfo->err;
error = (JPEGERROR*) cinfo->err; longjmp(error->setjmp_buffer, 1);
longjmp(error->setjmp_buffer, 1);
} }
METHODDEF(void) METHODDEF(void)
output(j_common_ptr cinfo) output(j_common_ptr cinfo) { /* nothing */ }
{
/* nothing */
}
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Decoder */ /* Decoder */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
int int
ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes) ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
{ JPEGSTATE *context = (JPEGSTATE *)state->context;
JPEGSTATE* context = (JPEGSTATE*) state->context;
int ok; int ok;
if (setjmp(context->error.setjmp_buffer)) { if (setjmp(context->error.setjmp_buffer)) {
@ -157,7 +141,6 @@ ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t by
} }
if (!state->state) { if (!state->state) {
/* Setup decompression context */ /* Setup decompression context */
context->cinfo.err = jpeg_std_error(&context->error.pub); context->cinfo.err = jpeg_std_error(&context->error.pub);
context->error.pub.error_exit = error; context->error.pub.error_exit = error;
@ -167,7 +150,6 @@ ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t by
/* Ready to decode */ /* Ready to decode */
state->state = 1; state->state = 1;
} }
/* Load the source buffer */ /* Load the source buffer */
@ -182,137 +164,137 @@ ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t by
} }
switch (state->state) { switch (state->state) {
case 1:
case 1: /* Read JPEG header, until we find an image body. */
do {
/* Note that we cannot return unless we have decoded
as much data as possible. */
ok = jpeg_read_header(&context->cinfo, FALSE);
/* Read JPEG header, until we find an image body. */ } while (ok == JPEG_HEADER_TABLES_ONLY);
do {
/* Note that we cannot return unless we have decoded if (ok == JPEG_SUSPENDED) {
as much data as possible. */ break;
ok = jpeg_read_header(&context->cinfo, FALSE); }
} while (ok == JPEG_HEADER_TABLES_ONLY); /* Decoder settings */
if (ok == JPEG_SUSPENDED) { /* jpegmode indicates whats in the file; if not set, we'll
break; trust the decoder */
} if (strcmp(context->jpegmode, "L") == 0) {
context->cinfo.jpeg_color_space = JCS_GRAYSCALE;
} else if (strcmp(context->jpegmode, "RGB") == 0) {
context->cinfo.jpeg_color_space = JCS_RGB;
} else if (strcmp(context->jpegmode, "CMYK") == 0) {
context->cinfo.jpeg_color_space = JCS_CMYK;
} else if (strcmp(context->jpegmode, "YCbCr") == 0) {
context->cinfo.jpeg_color_space = JCS_YCbCr;
} else if (strcmp(context->jpegmode, "YCbCrK") == 0) {
context->cinfo.jpeg_color_space = JCS_YCCK;
}
/* Decoder settings */ /* rawmode indicates what we want from the decoder. if not
set, conversions are disabled */
/* jpegmode indicates whats in the file; if not set, we'll if (strcmp(context->rawmode, "L") == 0) {
trust the decoder */ context->cinfo.out_color_space = JCS_GRAYSCALE;
if (strcmp(context->jpegmode, "L") == 0) { } else if (strcmp(context->rawmode, "RGB") == 0) {
context->cinfo.jpeg_color_space = JCS_GRAYSCALE; context->cinfo.out_color_space = JCS_RGB;
} else if (strcmp(context->jpegmode, "RGB") == 0) { }
context->cinfo.jpeg_color_space = JCS_RGB; #ifdef JCS_EXTENSIONS
} else if (strcmp(context->jpegmode, "CMYK") == 0) { else if (strcmp(context->rawmode, "RGBX") == 0) {
context->cinfo.jpeg_color_space = JCS_CMYK;
} else if (strcmp(context->jpegmode, "YCbCr") == 0) {
context->cinfo.jpeg_color_space = JCS_YCbCr;
} else if (strcmp(context->jpegmode, "YCbCrK") == 0) {
context->cinfo.jpeg_color_space = JCS_YCCK;
}
/* rawmode indicates what we want from the decoder. if not
set, conversions are disabled */
if (strcmp(context->rawmode, "L") == 0) {
context->cinfo.out_color_space = JCS_GRAYSCALE;
} else if (strcmp(context->rawmode, "RGB") == 0) {
context->cinfo.out_color_space = JCS_RGB;
}
#ifdef JCS_EXTENSIONS
else if (strcmp(context->rawmode, "RGBX") == 0) {
context->cinfo.out_color_space = JCS_EXT_RGBX; context->cinfo.out_color_space = JCS_EXT_RGBX;
} }
#endif #endif
else if (strcmp(context->rawmode, "CMYK") == 0 || else if (
strcmp(context->rawmode, "CMYK;I") == 0) { strcmp(context->rawmode, "CMYK") == 0 ||
context->cinfo.out_color_space = JCS_CMYK; strcmp(context->rawmode, "CMYK;I") == 0) {
} else if (strcmp(context->rawmode, "YCbCr") == 0) { context->cinfo.out_color_space = JCS_CMYK;
context->cinfo.out_color_space = JCS_YCbCr; } else if (strcmp(context->rawmode, "YCbCr") == 0) {
} else if (strcmp(context->rawmode, "YCbCrK") == 0) { context->cinfo.out_color_space = JCS_YCbCr;
context->cinfo.out_color_space = JCS_YCCK; } else if (strcmp(context->rawmode, "YCbCrK") == 0) {
} else { context->cinfo.out_color_space = JCS_YCCK;
/* Disable decoder conversions */ } else {
context->cinfo.jpeg_color_space = JCS_UNKNOWN; /* Disable decoder conversions */
context->cinfo.out_color_space = JCS_UNKNOWN; context->cinfo.jpeg_color_space = JCS_UNKNOWN;
} context->cinfo.out_color_space = JCS_UNKNOWN;
}
if (context->scale > 1) { if (context->scale > 1) {
context->cinfo.scale_num = 1; context->cinfo.scale_num = 1;
context->cinfo.scale_denom = context->scale; context->cinfo.scale_denom = context->scale;
} }
if (context->draft) { if (context->draft) {
context->cinfo.do_fancy_upsampling = FALSE; context->cinfo.do_fancy_upsampling = FALSE;
context->cinfo.dct_method = JDCT_FASTEST; context->cinfo.dct_method = JDCT_FASTEST;
} }
state->state++; state->state++;
/* fall through */ /* fall through */
case 2: case 2:
/* Set things up for decompression (this processes the entire /* Set things up for decompression (this processes the entire
file if necessary to return data line by line) */ file if necessary to return data line by line) */
if (!jpeg_start_decompress(&context->cinfo)) { if (!jpeg_start_decompress(&context->cinfo)) {
break; break;
} }
state->state++; state->state++;
/* fall through */ /* fall through */
case 3: case 3:
/* Decompress a single line of data */ /* Decompress a single line of data */
ok = 1; ok = 1;
while (state->y < state->ysize) { while (state->y < state->ysize) {
ok = jpeg_read_scanlines(&context->cinfo, &state->buffer, 1); ok = jpeg_read_scanlines(&context->cinfo, &state->buffer, 1);
if (ok != 1) {
break;
}
state->shuffle(
(UINT8 *)im->image[state->y + state->yoff] +
state->xoff * im->pixelsize,
state->buffer,
state->xsize);
state->y++;
}
if (ok != 1) { if (ok != 1) {
break; break;
} }
state->shuffle((UINT8*) im->image[state->y + state->yoff] + state->state++;
state->xoff * im->pixelsize, state->buffer, /* fall through */
state->xsize);
state->y++;
}
if (ok != 1) {
break;
}
state->state++;
/* fall through */
case 4: case 4:
/* Finish decompression */ /* Finish decompression */
if (!jpeg_finish_decompress(&context->cinfo)) { if (!jpeg_finish_decompress(&context->cinfo)) {
/* FIXME: add strictness mode test */ /* FIXME: add strictness mode test */
if (state->y < state->ysize) { if (state->y < state->ysize) {
break; break;
}
} }
}
/* Clean up */
jpeg_destroy_decompress(&context->cinfo);
/* if (jerr.pub.num_warnings) return BROKEN; */
return -1;
/* Clean up */
jpeg_destroy_decompress(&context->cinfo);
/* if (jerr.pub.num_warnings) return BROKEN; */
return -1;
} }
/* Return number of bytes consumed */ /* Return number of bytes consumed */
return context->source.pub.next_input_byte - buf; return context->source.pub.next_input_byte - buf;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Cleanup */ /* Cleanup */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
int ImagingJpegDecodeCleanup(ImagingCodecState state){ int
ImagingJpegDecodeCleanup(ImagingCodecState state) {
/* called to free the decompression engine when the decode terminates /* called to free the decompression engine when the decode terminates
due to a corrupt or truncated image due to a corrupt or truncated image
*/ */
JPEGSTATE* context = (JPEGSTATE*) state->context; JPEGSTATE *context = (JPEGSTATE *)state->context;
/* Clean up */ /* Clean up */
jpeg_destroy_decompress(&context->cinfo); jpeg_destroy_decompress(&context->cinfo);
@ -320,4 +302,3 @@ int ImagingJpegDecodeCleanup(ImagingCodecState state){
} }
#endif #endif

View File

@ -19,10 +19,9 @@
* See the README file for details on usage and redistribution. * See the README file for details on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#ifdef HAVE_LIBJPEG #ifdef HAVE_LIBJPEG
#undef HAVE_PROTOTYPES #undef HAVE_PROTOTYPES
#undef HAVE_STDLIB_H #undef HAVE_STDLIB_H
@ -40,51 +39,42 @@
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
METHODDEF(void) METHODDEF(void)
stub(j_compress_ptr cinfo) stub(j_compress_ptr cinfo) { /* empty */ }
{
/* empty */
}
METHODDEF(boolean) METHODDEF(boolean)
empty_output_buffer (j_compress_ptr cinfo) empty_output_buffer(j_compress_ptr cinfo) {
{
/* Suspension */ /* Suspension */
return FALSE; return FALSE;
} }
GLOBAL(void) GLOBAL(void)
jpeg_buffer_dest(j_compress_ptr cinfo, JPEGDESTINATION* destination) jpeg_buffer_dest(j_compress_ptr cinfo, JPEGDESTINATION *destination) {
{ cinfo->dest = (void *)destination;
cinfo->dest = (void*) destination;
destination->pub.init_destination = stub; destination->pub.init_destination = stub;
destination->pub.empty_output_buffer = empty_output_buffer; destination->pub.empty_output_buffer = empty_output_buffer;
destination->pub.term_destination = stub; destination->pub.term_destination = stub;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Error handler */ /* Error handler */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
METHODDEF(void) METHODDEF(void)
error(j_common_ptr cinfo) error(j_common_ptr cinfo) {
{ JPEGERROR *error;
JPEGERROR* error; error = (JPEGERROR *)cinfo->err;
error = (JPEGERROR*) cinfo->err; (*cinfo->err->output_message)(cinfo);
(*cinfo->err->output_message) (cinfo);
longjmp(error->setjmp_buffer, 1); longjmp(error->setjmp_buffer, 1);
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Encoder */ /* Encoder */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
int int
ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
{ JPEGENCODERSTATE *context = (JPEGENCODERSTATE *)state->context;
JPEGENCODERSTATE* context = (JPEGENCODERSTATE*) state->context;
int ok; int ok;
if (setjmp(context->error.setjmp_buffer)) { if (setjmp(context->error.setjmp_buffer)) {
@ -95,7 +85,6 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
} }
if (!state->state) { if (!state->state) {
/* Setup compression context (very similar to the decoder) */ /* Setup compression context (very similar to the decoder) */
context->cinfo.err = jpeg_std_error(&context->error.pub); context->cinfo.err = jpeg_std_error(&context->error.pub);
context->error.pub.error_exit = error; context->error.pub.error_exit = error;
@ -106,7 +95,6 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
/* Ready to encode */ /* Ready to encode */
state->state = 1; state->state = 1;
} }
/* Load the destination buffer */ /* Load the destination buffer */
@ -114,7 +102,6 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
context->destination.pub.free_in_buffer = bytes; context->destination.pub.free_in_buffer = bytes;
switch (state->state) { switch (state->state) {
case 1: case 1:
context->cinfo.image_width = state->xsize; context->cinfo.image_width = state->xsize;
@ -136,11 +123,11 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
case 32: case 32:
context->cinfo.input_components = 4; context->cinfo.input_components = 4;
context->cinfo.in_color_space = JCS_CMYK; context->cinfo.in_color_space = JCS_CMYK;
#ifdef JCS_EXTENSIONS #ifdef JCS_EXTENSIONS
if (strcmp(context->rawmode, "RGBX") == 0) { if (strcmp(context->rawmode, "RGBX") == 0) {
context->cinfo.in_color_space = JCS_EXT_RGBX; context->cinfo.in_color_space = JCS_EXT_RGBX;
} }
#endif #endif
break; break;
default: default:
state->errcode = IMAGING_CODEC_CONFIG; state->errcode = IMAGING_CODEC_CONFIG;
@ -159,15 +146,20 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
quality = context->quality; quality = context->quality;
} }
for (i = 0; i < context->qtablesLen; i++) { for (i = 0; i < context->qtablesLen; i++) {
jpeg_add_quant_table(&context->cinfo, i, &context->qtables[i * DCTSIZE2], jpeg_add_quant_table(
quality, FALSE); &context->cinfo,
i,
&context->qtables[i * DCTSIZE2],
quality,
FALSE);
context->cinfo.comp_info[i].quant_tbl_no = i; context->cinfo.comp_info[i].quant_tbl_no = i;
last_q = i; last_q = i;
} }
if (context->qtablesLen == 1) { if (context->qtablesLen == 1) {
// jpeg_set_defaults created two qtables internally, but we only wanted one. // jpeg_set_defaults created two qtables internally, but we only
jpeg_add_quant_table(&context->cinfo, 1, &context->qtables[0], // wanted one.
quality, FALSE); jpeg_add_quant_table(
&context->cinfo, 1, &context->qtables[0], quality, FALSE);
} }
for (i = last_q; i < context->cinfo.num_components; i++) { for (i = last_q; i < context->cinfo.num_components; i++) {
context->cinfo.comp_info[i].quant_tbl_no = last_q; context->cinfo.comp_info[i].quant_tbl_no = last_q;
@ -177,9 +169,8 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
} }
/* Set subsampling options */ /* Set subsampling options */
switch (context->subsampling) switch (context->subsampling) {
{ case 0: /* 1x1 1x1 1x1 (4:4:4) : None */
case 0: /* 1x1 1x1 1x1 (4:4:4) : None */
{ {
context->cinfo.comp_info[0].h_samp_factor = 1; context->cinfo.comp_info[0].h_samp_factor = 1;
context->cinfo.comp_info[0].v_samp_factor = 1; context->cinfo.comp_info[0].v_samp_factor = 1;
@ -189,7 +180,7 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
context->cinfo.comp_info[2].v_samp_factor = 1; context->cinfo.comp_info[2].v_samp_factor = 1;
break; break;
} }
case 1: /* 2x1, 1x1, 1x1 (4:2:2) : Medium */ case 1: /* 2x1, 1x1, 1x1 (4:2:2) : Medium */
{ {
context->cinfo.comp_info[0].h_samp_factor = 2; context->cinfo.comp_info[0].h_samp_factor = 2;
context->cinfo.comp_info[0].v_samp_factor = 1; context->cinfo.comp_info[0].v_samp_factor = 1;
@ -199,7 +190,7 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
context->cinfo.comp_info[2].v_samp_factor = 1; context->cinfo.comp_info[2].v_samp_factor = 1;
break; break;
} }
case 2: /* 2x2, 1x1, 1x1 (4:2:0) : High */ case 2: /* 2x2, 1x1, 1x1 (4:2:0) : High */
{ {
context->cinfo.comp_info[0].h_samp_factor = 2; context->cinfo.comp_info[0].h_samp_factor = 2;
context->cinfo.comp_info[0].v_samp_factor = 2; context->cinfo.comp_info[0].v_samp_factor = 2;
@ -209,23 +200,22 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
context->cinfo.comp_info[2].v_samp_factor = 1; context->cinfo.comp_info[2].v_samp_factor = 1;
break; break;
} }
default: default: {
{
/* Use the lib's default */ /* Use the lib's default */
break; break;
} }
} }
if (context->progressive) { if (context->progressive) {
jpeg_simple_progression(&context->cinfo); jpeg_simple_progression(&context->cinfo);
} }
context->cinfo.smoothing_factor = context->smooth; context->cinfo.smoothing_factor = context->smooth;
context->cinfo.optimize_coding = (boolean) context->optimize; context->cinfo.optimize_coding = (boolean)context->optimize;
if (context->xdpi > 0 && context->ydpi > 0) { if (context->xdpi > 0 && context->ydpi > 0) {
context->cinfo.write_JFIF_header = TRUE; context->cinfo.write_JFIF_header = TRUE;
context->cinfo.density_unit = 1; /* dots per inch */ context->cinfo.density_unit = 1; /* dots per inch */
context->cinfo.X_density = context->xdpi; context->cinfo.X_density = context->xdpi;
context->cinfo.Y_density = context->ydpi; context->cinfo.Y_density = context->ydpi;
} }
switch (context->streamtype) { switch (context->streamtype) {
case 1: case 1:
/* tables only -- not yet implemented */ /* tables only -- not yet implemented */
@ -248,13 +238,16 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
case 2: case 2:
// check for exif len + 'APP1' header bytes // check for exif len + 'APP1' header bytes
if (context->rawExifLen + 5 > context->destination.pub.free_in_buffer){ if (context->rawExifLen + 5 > context->destination.pub.free_in_buffer) {
break; break;
} }
//add exif header // add exif header
if (context->rawExifLen > 0){ if (context->rawExifLen > 0) {
jpeg_write_marker(&context->cinfo, JPEG_APP0+1, jpeg_write_marker(
(unsigned char*)context->rawExif, context->rawExifLen); &context->cinfo,
JPEG_APP0 + 1,
(unsigned char *)context->rawExif,
context->rawExifLen);
} }
state->state++; state->state++;
@ -267,8 +260,10 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
if (n > context->destination.pub.free_in_buffer) { if (n > context->destination.pub.free_in_buffer) {
n = context->destination.pub.free_in_buffer; n = context->destination.pub.free_in_buffer;
} }
memcpy(context->destination.pub.next_output_byte, memcpy(
context->extra + context->extra_offset, n); context->destination.pub.next_output_byte,
context->extra + context->extra_offset,
n);
context->destination.pub.next_output_byte += n; context->destination.pub.next_output_byte += n;
context->destination.pub.free_in_buffer -= n; context->destination.pub.free_in_buffer -= n;
context->extra_offset += n; context->extra_offset += n;
@ -282,15 +277,17 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
} }
case 4: case 4:
if (1024 > context->destination.pub.free_in_buffer){ if (1024 > context->destination.pub.free_in_buffer) {
break; break;
} }
ok = 1; ok = 1;
while (state->y < state->ysize) { while (state->y < state->ysize) {
state->shuffle(state->buffer, state->shuffle(
(UINT8*) im->image[state->y + state->yoff] + state->buffer,
state->xoff * im->pixelsize, state->xsize); (UINT8 *)im->image[state->y + state->yoff] +
state->xoff * im->pixelsize,
state->xsize);
ok = jpeg_write_scanlines(&context->cinfo, &state->buffer, 1); ok = jpeg_write_scanlines(&context->cinfo, &state->buffer, 1);
if (ok != 1) { if (ok != 1) {
break; break;
@ -330,17 +327,14 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
/* if (jerr.pub.num_warnings) return BROKEN; */ /* if (jerr.pub.num_warnings) return BROKEN; */
state->errcode = IMAGING_CODEC_END; state->errcode = IMAGING_CODEC_END;
break; break;
} }
/* Return number of bytes in output buffer */ /* Return number of bytes in output buffer */
return context->destination.pub.next_output_byte - buf; return context->destination.pub.next_output_byte - buf;
} }
const char* const char *
ImagingJpegVersion(void) ImagingJpegVersion(void) {
{
static char version[20]; static char version[20];
sprintf(version, "%d.%d", JPEG_LIB_VERSION / 10, JPEG_LIB_VERSION % 10); sprintf(version, "%d.%d", JPEG_LIB_VERSION / 10, JPEG_LIB_VERSION % 10);
return version; return version;

View File

@ -13,65 +13,60 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#define CLIPF(v) ((v <= 0.0) ? 0 : (v >= 255.0F) ? 255 : (UINT8)v)
#define CLIPF(v) ((v <= 0.0) ? 0 : (v >= 255.0F) ? 255 : (UINT8) v)
Imaging Imaging
ImagingConvertMatrix(Imaging im, const char *mode, float m[]) ImagingConvertMatrix(Imaging im, const char *mode, float m[]) {
{
Imaging imOut; Imaging imOut;
int x, y; int x, y;
/* Assume there's enough data in the buffer */ /* Assume there's enough data in the buffer */
if (!im) { if (!im) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
if (strcmp(mode, "L") == 0 && im->bands == 3) { if (strcmp(mode, "L") == 0 && im->bands == 3) {
imOut = ImagingNewDirty("L", im->xsize, im->ysize); imOut = ImagingNewDirty("L", im->xsize, im->ysize);
if (!imOut) { if (!imOut) {
return NULL; return NULL;
} }
for (y = 0; y < im->ysize; y++) { for (y = 0; y < im->ysize; y++) {
UINT8* in = (UINT8*) im->image[y]; UINT8 *in = (UINT8 *)im->image[y];
UINT8* out = (UINT8*) imOut->image[y]; UINT8 *out = (UINT8 *)imOut->image[y];
for (x = 0; x < im->xsize; x++) { for (x = 0; x < im->xsize; x++) {
float v = m[0]*in[0] + m[1]*in[1] + m[2]*in[2] + m[3] + 0.5; float v = m[0] * in[0] + m[1] * in[1] + m[2] * in[2] + m[3] + 0.5;
out[x] = CLIPF(v); out[x] = CLIPF(v);
in += 4; in += 4;
} }
} }
} else if (strlen(mode) == 3 && im->bands == 3) { } else if (strlen(mode) == 3 && im->bands == 3) {
imOut = ImagingNewDirty(mode, im->xsize, im->ysize); imOut = ImagingNewDirty(mode, im->xsize, im->ysize);
if (!imOut) { if (!imOut) {
return NULL; return NULL;
} }
for (y = 0; y < im->ysize; y++) { for (y = 0; y < im->ysize; y++) {
UINT8* in = (UINT8*) im->image[y]; UINT8 *in = (UINT8 *)im->image[y];
UINT8* out = (UINT8*) imOut->image[y]; UINT8 *out = (UINT8 *)imOut->image[y];
for (x = 0; x < im->xsize; x++) { for (x = 0; x < im->xsize; x++) {
float v0 = m[0]*in[0] + m[1]*in[1] + m[2]*in[2] + m[3] + 0.5; float v0 = m[0] * in[0] + m[1] * in[1] + m[2] * in[2] + m[3] + 0.5;
float v1 = m[4]*in[0] + m[5]*in[1] + m[6]*in[2] + m[7] + 0.5; float v1 = m[4] * in[0] + m[5] * in[1] + m[6] * in[2] + m[7] + 0.5;
float v2 = m[8]*in[0] + m[9]*in[1] + m[10]*in[2] + m[11] + 0.5; float v2 = m[8] * in[0] + m[9] * in[1] + m[10] * in[2] + m[11] + 0.5;
out[0] = CLIPF(v0); out[0] = CLIPF(v0);
out[1] = CLIPF(v1); out[1] = CLIPF(v1);
out[2] = CLIPF(v2); out[2] = CLIPF(v2);
in += 4; out += 4; in += 4;
out += 4;
} }
} }
} else { } else {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
return imOut; return imOut;

View File

@ -16,8 +16,7 @@
#include "Imaging.h" #include "Imaging.h"
Imaging Imaging
ImagingModeFilter(Imaging im, int size) ImagingModeFilter(Imaging im, int size) {
{
Imaging imOut; Imaging imOut;
int x, y, i; int x, y, i;
int xx, yy; int xx, yy;
@ -26,7 +25,7 @@ ImagingModeFilter(Imaging im, int size)
int histogram[256]; int histogram[256];
if (!im || im->bands != 1 || im->type != IMAGING_TYPE_UINT8) { if (!im || im->bands != 1 || im->type != IMAGING_TYPE_UINT8) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize);
@ -37,9 +36,8 @@ ImagingModeFilter(Imaging im, int size)
size = size / 2; size = size / 2;
for (y = 0; y < imOut->ysize; y++) { for (y = 0; y < imOut->ysize; y++) {
UINT8* out = &IMAGING_PIXEL_L(imOut, 0, y); UINT8 *out = &IMAGING_PIXEL_L(imOut, 0, y);
for (x = 0; x < imOut->xsize; x++) { for (x = 0; x < imOut->xsize; x++) {
/* calculate histogram over current area */ /* calculate histogram over current area */
/* FIXME: brute force! to improve, update the histogram /* FIXME: brute force! to improve, update the histogram
@ -50,7 +48,7 @@ ImagingModeFilter(Imaging im, int size)
memset(histogram, 0, sizeof(histogram)); memset(histogram, 0, sizeof(histogram));
for (yy = y - size; yy <= y + size; yy++) { for (yy = y - size; yy <= y + size; yy++) {
if (yy >= 0 && yy < imOut->ysize) { if (yy >= 0 && yy < imOut->ysize) {
UINT8* in = &IMAGING_PIXEL_L(im, 0, yy); UINT8 *in = &IMAGING_PIXEL_L(im, 0, yy);
for (xx = x - size; xx <= x + size; xx++) { for (xx = x - size; xx <= x + size; xx++) {
if (xx >= 0 && xx < imOut->xsize) { if (xx >= 0 && xx < imOut->xsize) {
histogram[in[xx]]++; histogram[in[xx]]++;
@ -65,7 +63,7 @@ ImagingModeFilter(Imaging im, int size)
for (i = 1; i < 256; i++) { for (i = 1; i < 256; i++) {
if (histogram[i] > maxcount) { if (histogram[i] > maxcount) {
maxcount = histogram[i]; maxcount = histogram[i];
maxpixel = (UINT8) i; maxpixel = (UINT8)i;
} }
} }
@ -74,9 +72,7 @@ ImagingModeFilter(Imaging im, int size)
} else { } else {
out[x] = IMAGING_PIXEL_L(im, x, y); out[x] = IMAGING_PIXEL_L(im, x, y);
} }
} }
} }
ImagingCopyPalette(imOut, im); ImagingCopyPalette(imOut, im);

View File

@ -16,18 +16,15 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
Imaging Imaging
ImagingNegative(Imaging im) ImagingNegative(Imaging im) {
{
Imaging imOut; Imaging imOut;
int x, y; int x, y;
if (!im) { if (!im) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize);
@ -43,4 +40,3 @@ ImagingNegative(Imaging im)
return imOut; return imOut;
} }

View File

@ -14,18 +14,15 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
Imaging Imaging
ImagingOffset(Imaging im, int xoffset, int yoffset) ImagingOffset(Imaging im, int xoffset, int yoffset) {
{
int x, y; int x, y;
Imaging imOut; Imaging imOut;
if (!im) { if (!im) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize); imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize);
@ -48,13 +45,13 @@ ImagingOffset(Imaging im, int xoffset, int yoffset)
yoffset += im->ysize; yoffset += im->ysize;
} }
#define OFFSET(image)\ #define OFFSET(image) \
for (y = 0; y < im->ysize; y++) {\ for (y = 0; y < im->ysize; y++) { \
for (x = 0; x < im->xsize; x++) {\ for (x = 0; x < im->xsize; x++) { \
int yi = (y + yoffset) % im->ysize;\ int yi = (y + yoffset) % im->ysize; \
int xi = (x + xoffset) % im->xsize;\ int xi = (x + xoffset) % im->xsize; \
imOut->image[y][x] = im->image[yi][xi];\ imOut->image[y][x] = im->image[yi][xi]; \
}\ } \
} }
if (im->image8) { if (im->image8) {

View File

@ -1,4 +1,4 @@
/* /*
* The Python Imaging Library. * The Python Imaging Library.
* $Id$ * $Id$
* *
@ -25,7 +25,6 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#define R 0 #define R 0
@ -41,20 +40,28 @@
/* byte swapping macros */ /* byte swapping macros */
#define C16N\ #define C16N (out[0] = tmp[0], out[1] = tmp[1]);
(out[0]=tmp[0], out[1]=tmp[1]); #define C16S (out[1] = tmp[0], out[0] = tmp[1]);
#define C16S\ #define C32N (out[0] = tmp[0], out[1] = tmp[1], out[2] = tmp[2], out[3] = tmp[3]);
(out[1]=tmp[0], out[0]=tmp[1]); #define C32S (out[3] = tmp[0], out[2] = tmp[1], out[1] = tmp[2], out[0] = tmp[3]);
#define C32N\ #define C64N \
(out[0]=tmp[0], out[1]=tmp[1], out[2]=tmp[2], out[3]=tmp[3]); (out[0] = tmp[0], \
#define C32S\ out[1] = tmp[1], \
(out[3]=tmp[0], out[2]=tmp[1], out[1]=tmp[2], out[0]=tmp[3]); out[2] = tmp[2], \
#define C64N\ out[3] = tmp[3], \
(out[0]=tmp[0], out[1]=tmp[1], out[2]=tmp[2], out[3]=tmp[3],\ out[4] = tmp[4], \
out[4]=tmp[4], out[5]=tmp[5], out[6]=tmp[6], out[7]=tmp[7]); out[5] = tmp[5], \
#define C64S\ out[6] = tmp[6], \
(out[7]=tmp[0], out[6]=tmp[1], out[5]=tmp[2], out[4]=tmp[3],\ out[7] = tmp[7]);
out[3]=tmp[4], out[2]=tmp[5], out[1]=tmp[6], out[0]=tmp[7]); #define C64S \
(out[7] = tmp[0], \
out[6] = tmp[1], \
out[5] = tmp[2], \
out[4] = tmp[3], \
out[3] = tmp[4], \
out[2] = tmp[5], \
out[1] = tmp[6], \
out[0] = tmp[7]);
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
#define C16B C16N #define C16B C16N
@ -72,13 +79,12 @@
#define C64L C64N #define C64L C64N
#endif #endif
static void static void
pack1(UINT8* out, const UINT8* in, int pixels) pack1(UINT8 *out, const UINT8 *in, int pixels) {
{
int i, m, b; int i, m, b;
/* bilevel (black is 0) */ /* bilevel (black is 0) */
b = 0; m = 128; b = 0;
m = 128;
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
if (in[i] != 0) { if (in[i] != 0) {
b |= m; b |= m;
@ -86,7 +92,8 @@ pack1(UINT8* out, const UINT8* in, int pixels)
m >>= 1; m >>= 1;
if (m == 0) { if (m == 0) {
*out++ = b; *out++ = b;
b = 0; m = 128; b = 0;
m = 128;
} }
} }
if (m != 128) { if (m != 128) {
@ -95,11 +102,11 @@ pack1(UINT8* out, const UINT8* in, int pixels)
} }
static void static void
pack1I(UINT8* out, const UINT8* in, int pixels) pack1I(UINT8 *out, const UINT8 *in, int pixels) {
{
int i, m, b; int i, m, b;
/* bilevel (black is 1) */ /* bilevel (black is 1) */
b = 0; m = 128; b = 0;
m = 128;
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
if (in[i] == 0) { if (in[i] == 0) {
b |= m; b |= m;
@ -107,7 +114,8 @@ pack1I(UINT8* out, const UINT8* in, int pixels)
m >>= 1; m >>= 1;
if (m == 0) { if (m == 0) {
*out++ = b; *out++ = b;
b = 0; m = 128; b = 0;
m = 128;
} }
} }
if (m != 128) { if (m != 128) {
@ -116,19 +124,20 @@ pack1I(UINT8* out, const UINT8* in, int pixels)
} }
static void static void
pack1R(UINT8* out, const UINT8* in, int pixels) pack1R(UINT8 *out, const UINT8 *in, int pixels) {
{
int i, m, b; int i, m, b;
/* bilevel, lsb first (black is 0) */ /* bilevel, lsb first (black is 0) */
b = 0; m = 1; b = 0;
m = 1;
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
if (in[i] != 0) { if (in[i] != 0) {
b |= m; b |= m;
} }
m <<= 1; m <<= 1;
if (m == 256){ if (m == 256) {
*out++ = b; *out++ = b;
b = 0; m = 1; b = 0;
m = 1;
} }
} }
if (m != 1) { if (m != 1) {
@ -137,19 +146,20 @@ pack1R(UINT8* out, const UINT8* in, int pixels)
} }
static void static void
pack1IR(UINT8* out, const UINT8* in, int pixels) pack1IR(UINT8 *out, const UINT8 *in, int pixels) {
{
int i, m, b; int i, m, b;
/* bilevel, lsb first (black is 1) */ /* bilevel, lsb first (black is 1) */
b = 0; m = 1; b = 0;
m = 1;
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
if (in[i] == 0) { if (in[i] == 0) {
b |= m; b |= m;
} }
m <<= 1; m <<= 1;
if (m == 256){ if (m == 256) {
*out++ = b; *out++ = b;
b = 0; m = 1; b = 0;
m = 1;
} }
} }
if (m != 1) { if (m != 1) {
@ -158,8 +168,7 @@ pack1IR(UINT8* out, const UINT8* in, int pixels)
} }
static void static void
pack1L(UINT8* out, const UINT8* in, int pixels) pack1L(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* bilevel, stored as bytes */ /* bilevel, stored as bytes */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
@ -168,12 +177,11 @@ pack1L(UINT8* out, const UINT8* in, int pixels)
} }
static void static void
packP4(UINT8* out, const UINT8* in, int pixels) packP4(UINT8 *out, const UINT8 *in, int pixels) {
{
while (pixels >= 2) { while (pixels >= 2) {
*out++ = (in[0] << 4) | *out++ = (in[0] << 4) | (in[1] & 15);
(in[1] & 15); in += 2;
in += 2; pixels -= 2; pixels -= 2;
} }
if (pixels) { if (pixels) {
@ -182,34 +190,27 @@ packP4(UINT8* out, const UINT8* in, int pixels)
} }
static void static void
packP2(UINT8* out, const UINT8* in, int pixels) packP2(UINT8 *out, const UINT8 *in, int pixels) {
{
while (pixels >= 4) { while (pixels >= 4) {
*out++ = (in[0] << 6) | *out++ = (in[0] << 6) | ((in[1] & 3) << 4) | ((in[2] & 3) << 2) | (in[3] & 3);
((in[1] & 3) << 4) | in += 4;
((in[2] & 3) << 2) | pixels -= 4;
(in[3] & 3);
in += 4; pixels -= 4;
} }
switch (pixels) { switch (pixels) {
case 3: case 3:
out[0] = (in[0] << 6) | out[0] = (in[0] << 6) | ((in[1] & 3) << 4) | ((in[2] & 3) << 2);
((in[1] & 3) << 4) | break;
((in[2] & 3) << 2); case 2:
break; out[0] = (in[0] << 6) | ((in[1] & 3) << 4);
case 2: break;
out[0] = (in[0] << 6) | case 1:
((in[1] & 3) << 4); out[0] = (in[0] << 6);
break;
case 1:
out[0] = (in[0] << 6);
} }
} }
static void static void
packL16(UINT8* out, const UINT8* in, int pixels) packL16(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* L -> L;16, e.g: \xff77 -> \x00\xff\x00\x77 */ /* L -> L;16, e.g: \xff77 -> \x00\xff\x00\x77 */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
@ -220,8 +221,7 @@ packL16(UINT8* out, const UINT8* in, int pixels)
} }
static void static void
packL16B(UINT8* out, const UINT8* in, int pixels) packL16B(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* L -> L;16B, e.g: \xff77 -> \xff\x00\x77\x00 */ /* L -> L;16B, e.g: \xff77 -> \xff\x00\x77\x00 */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
@ -231,34 +231,31 @@ packL16B(UINT8* out, const UINT8* in, int pixels)
} }
} }
static void static void
packLA(UINT8* out, const UINT8* in, int pixels) packLA(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* LA, pixel interleaved */ /* LA, pixel interleaved */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[0] = in[R]; out[0] = in[R];
out[1] = in[A]; out[1] = in[A];
out += 2; in += 4; out += 2;
in += 4;
} }
} }
static void static void
packLAL(UINT8* out, const UINT8* in, int pixels) packLAL(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* LA, line interleaved */ /* LA, line interleaved */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[i] = in[R]; out[i] = in[R];
out[i+pixels] = in[A]; out[i + pixels] = in[A];
in += 4; in += 4;
} }
} }
void void
ImagingPackRGB(UINT8* out, const UINT8* in, int pixels) ImagingPackRGB(UINT8 *out, const UINT8 *in, int pixels) {
{
int i = 0; int i = 0;
/* RGB triplets */ /* RGB triplets */
#ifdef __sparc #ifdef __sparc
@ -267,25 +264,25 @@ ImagingPackRGB(UINT8* out, const UINT8* in, int pixels)
out[0] = in[R]; out[0] = in[R];
out[1] = in[G]; out[1] = in[G];
out[2] = in[B]; out[2] = in[B];
out += 3; in += 4; out += 3;
in += 4;
} }
#else #else
for (; i < pixels-1; i++) { for (; i < pixels - 1; i++) {
memcpy(out, in + i * 4, 4); memcpy(out, in + i * 4, 4);
out += 3; out += 3;
} }
for (; i < pixels; i++) { for (; i < pixels; i++) {
out[0] = in[i*4+R]; out[0] = in[i * 4 + R];
out[1] = in[i*4+G]; out[1] = in[i * 4 + G];
out[2] = in[i*4+B]; out[2] = in[i * 4 + B];
out += 3; out += 3;
} }
#endif #endif
} }
void void
ImagingPackXRGB(UINT8* out, const UINT8* in, int pixels) ImagingPackXRGB(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* XRGB, triplets with left padding */ /* XRGB, triplets with left padding */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
@ -293,26 +290,26 @@ ImagingPackXRGB(UINT8* out, const UINT8* in, int pixels)
out[1] = in[R]; out[1] = in[R];
out[2] = in[G]; out[2] = in[G];
out[3] = in[B]; out[3] = in[B];
out += 4; in += 4; out += 4;
in += 4;
} }
} }
void void
ImagingPackBGR(UINT8* out, const UINT8* in, int pixels) ImagingPackBGR(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* RGB, reversed bytes */ /* RGB, reversed bytes */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[0] = in[B]; out[0] = in[B];
out[1] = in[G]; out[1] = in[G];
out[2] = in[R]; out[2] = in[R];
out += 3; in += 4; out += 3;
in += 4;
} }
} }
void void
ImagingPackBGRX(UINT8* out, const UINT8* in, int pixels) ImagingPackBGRX(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* BGRX, reversed bytes with right padding */ /* BGRX, reversed bytes with right padding */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
@ -320,13 +317,13 @@ ImagingPackBGRX(UINT8* out, const UINT8* in, int pixels)
out[1] = in[G]; out[1] = in[G];
out[2] = in[R]; out[2] = in[R];
out[3] = 0; out[3] = 0;
out += 4; in += 4; out += 4;
in += 4;
} }
} }
void void
ImagingPackXBGR(UINT8* out, const UINT8* in, int pixels) ImagingPackXBGR(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* XBGR, reversed bytes with left padding */ /* XBGR, reversed bytes with left padding */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
@ -334,13 +331,13 @@ ImagingPackXBGR(UINT8* out, const UINT8* in, int pixels)
out[1] = in[B]; out[1] = in[B];
out[2] = in[G]; out[2] = in[G];
out[3] = in[R]; out[3] = in[R];
out += 4; in += 4; out += 4;
in += 4;
} }
} }
void void
ImagingPackBGRA(UINT8* out, const UINT8* in, int pixels) ImagingPackBGRA(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* BGRX, reversed bytes with right padding */ /* BGRX, reversed bytes with right padding */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
@ -348,13 +345,13 @@ ImagingPackBGRA(UINT8* out, const UINT8* in, int pixels)
out[1] = in[G]; out[1] = in[G];
out[2] = in[R]; out[2] = in[R];
out[3] = in[A]; out[3] = in[A];
out += 4; in += 4; out += 4;
in += 4;
} }
} }
void void
ImagingPackABGR(UINT8* out, const UINT8* in, int pixels) ImagingPackABGR(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* XBGR, reversed bytes with left padding */ /* XBGR, reversed bytes with left padding */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
@ -362,13 +359,13 @@ ImagingPackABGR(UINT8* out, const UINT8* in, int pixels)
out[1] = in[B]; out[1] = in[B];
out[2] = in[G]; out[2] = in[G];
out[3] = in[R]; out[3] = in[R];
out += 4; in += 4; out += 4;
in += 4;
} }
} }
void void
ImagingPackBGRa(UINT8* out, const UINT8* in, int pixels) ImagingPackBGRa(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* BGRa, reversed bytes with premultiplied alpha */ /* BGRa, reversed bytes with premultiplied alpha */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
@ -377,43 +374,41 @@ ImagingPackBGRa(UINT8* out, const UINT8* in, int pixels)
out[0] = MULDIV255(in[B], alpha, tmp); out[0] = MULDIV255(in[B], alpha, tmp);
out[1] = MULDIV255(in[G], alpha, tmp); out[1] = MULDIV255(in[G], alpha, tmp);
out[2] = MULDIV255(in[R], alpha, tmp); out[2] = MULDIV255(in[R], alpha, tmp);
out += 4; in += 4; out += 4;
in += 4;
} }
} }
static void static void
packRGBL(UINT8* out, const UINT8* in, int pixels) packRGBL(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* RGB, line interleaved */ /* RGB, line interleaved */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[i] = in[R]; out[i] = in[R];
out[i+pixels] = in[G]; out[i + pixels] = in[G];
out[i+pixels+pixels] = in[B]; out[i + pixels + pixels] = in[B];
in += 4; in += 4;
} }
} }
static void static void
packRGBXL(UINT8* out, const UINT8* in, int pixels) packRGBXL(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* RGBX, line interleaved */ /* RGBX, line interleaved */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[i] = in[R]; out[i] = in[R];
out[i+pixels] = in[G]; out[i + pixels] = in[G];
out[i+pixels+pixels] = in[B]; out[i + pixels + pixels] = in[B];
out[i+pixels+pixels+pixels] = in[X]; out[i + pixels + pixels + pixels] = in[X];
in += 4; in += 4;
} }
} }
static void static void
packI16B(UINT8* out, const UINT8* in_, int pixels) packI16B(UINT8 *out, const UINT8 *in_, int pixels) {
{
int i; int i;
UINT16 tmp_; UINT16 tmp_;
UINT8* tmp = (UINT8*) &tmp_; UINT8 *tmp = (UINT8 *)&tmp_;
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
INT32 in; INT32 in;
memcpy(&in, in_, sizeof(in)); memcpy(&in, in_, sizeof(in));
@ -425,96 +420,91 @@ packI16B(UINT8* out, const UINT8* in_, int pixels)
tmp_ = in; tmp_ = in;
} }
C16B; C16B;
out += 2; in_ += sizeof(in); out += 2;
in_ += sizeof(in);
} }
} }
static void static void
packI16N_I16B(UINT8* out, const UINT8* in, int pixels){ packI16N_I16B(UINT8 *out, const UINT8 *in, int pixels) {
int i; int i;
UINT8* tmp = (UINT8*) in; UINT8 *tmp = (UINT8 *)in;
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
C16B; C16B;
out += 2; tmp += 2; out += 2;
tmp += 2;
} }
} }
static void static void
packI16N_I16(UINT8* out, const UINT8* in, int pixels){ packI16N_I16(UINT8 *out, const UINT8 *in, int pixels) {
int i; int i;
UINT8* tmp = (UINT8*) in; UINT8 *tmp = (UINT8 *)in;
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
C16L; C16L;
out += 2; tmp += 2; out += 2;
tmp += 2;
} }
} }
static void static void
packI32S(UINT8* out, const UINT8* in, int pixels) packI32S(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
UINT8* tmp = (UINT8*) in; UINT8 *tmp = (UINT8 *)in;
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
C32L; C32L;
out += 4; tmp += 4; out += 4;
tmp += 4;
} }
} }
void void
ImagingPackLAB(UINT8* out, const UINT8* in, int pixels) ImagingPackLAB(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* LAB triplets */ /* LAB triplets */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
out[0] = in[0]; out[0] = in[0];
out[1] = in[1] ^ 128; /* signed in outside world */ out[1] = in[1] ^ 128; /* signed in outside world */
out[2] = in[2] ^ 128; out[2] = in[2] ^ 128;
out += 3; in += 4; out += 3;
in += 4;
} }
} }
static void static void
copy1(UINT8* out, const UINT8* in, int pixels) copy1(UINT8 *out, const UINT8 *in, int pixels) {
{
/* L, P */ /* L, P */
memcpy(out, in, pixels); memcpy(out, in, pixels);
} }
static void static void
copy2(UINT8* out, const UINT8* in, int pixels) copy2(UINT8 *out, const UINT8 *in, int pixels) {
{
/* I;16, etc */ /* I;16, etc */
memcpy(out, in, pixels*2); memcpy(out, in, pixels * 2);
} }
static void static void
copy3(UINT8* out, const UINT8* in, int pixels) copy3(UINT8 *out, const UINT8 *in, int pixels) {
{
/* BGR;24, etc */ /* BGR;24, etc */
memcpy(out, in, pixels*3); memcpy(out, in, pixels * 3);
} }
static void static void
copy4(UINT8* out, const UINT8* in, int pixels) copy4(UINT8 *out, const UINT8 *in, int pixels) {
{
/* RGBA, CMYK quadruples */ /* RGBA, CMYK quadruples */
memcpy(out, in, 4*pixels); memcpy(out, in, 4 * pixels);
} }
static void static void
copy4I(UINT8* out, const UINT8* in, int pixels) copy4I(UINT8 *out, const UINT8 *in, int pixels) {
{
/* RGBA, CMYK quadruples, inverted */ /* RGBA, CMYK quadruples, inverted */
int i; int i;
for (i = 0; i < pixels*4; i++) { for (i = 0; i < pixels * 4; i++) {
out[i] = ~in[i]; out[i] = ~in[i];
} }
} }
static void static void
band0(UINT8* out, const UINT8* in, int pixels) band0(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
for (i = 0; i < pixels; i++, in += 4) { for (i = 0; i < pixels; i++, in += 4) {
out[i] = in[0]; out[i] = in[0];
@ -522,8 +512,7 @@ band0(UINT8* out, const UINT8* in, int pixels)
} }
static void static void
band1(UINT8* out, const UINT8* in, int pixels) band1(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
for (i = 0; i < pixels; i++, in += 4) { for (i = 0; i < pixels; i++, in += 4) {
out[i] = in[1]; out[i] = in[1];
@ -531,8 +520,7 @@ band1(UINT8* out, const UINT8* in, int pixels)
} }
static void static void
band2(UINT8* out, const UINT8* in, int pixels) band2(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
for (i = 0; i < pixels; i++, in += 4) { for (i = 0; i < pixels; i++, in += 4) {
out[i] = in[2]; out[i] = in[2];
@ -540,8 +528,7 @@ band2(UINT8* out, const UINT8* in, int pixels)
} }
static void static void
band3(UINT8* out, const UINT8* in, int pixels) band3(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
for (i = 0; i < pixels; i++, in += 4) { for (i = 0; i < pixels; i++, in += 4) {
out[i] = in[3]; out[i] = in[3];
@ -549,143 +536,141 @@ band3(UINT8* out, const UINT8* in, int pixels)
} }
static struct { static struct {
const char* mode; const char *mode;
const char* rawmode; const char *rawmode;
int bits; int bits;
ImagingShuffler pack; ImagingShuffler pack;
} packers[] = { } packers[] = {
/* bilevel */ /* bilevel */
{"1", "1", 1, pack1}, {"1", "1", 1, pack1},
{"1", "1;I", 1, pack1I}, {"1", "1;I", 1, pack1I},
{"1", "1;R", 1, pack1R}, {"1", "1;R", 1, pack1R},
{"1", "1;IR", 1, pack1IR}, {"1", "1;IR", 1, pack1IR},
{"1", "L", 8, pack1L}, {"1", "L", 8, pack1L},
/* greyscale */ /* greyscale */
{"L", "L", 8, copy1}, {"L", "L", 8, copy1},
{"L", "L;16", 16, packL16}, {"L", "L;16", 16, packL16},
{"L", "L;16B", 16, packL16B}, {"L", "L;16B", 16, packL16B},
/* greyscale w. alpha */ /* greyscale w. alpha */
{"LA", "LA", 16, packLA}, {"LA", "LA", 16, packLA},
{"LA", "LA;L", 16, packLAL}, {"LA", "LA;L", 16, packLAL},
/* greyscale w. alpha premultiplied */ /* greyscale w. alpha premultiplied */
{"La", "La", 16, packLA}, {"La", "La", 16, packLA},
/* palette */ /* palette */
{"P", "P;1", 1, pack1}, {"P", "P;1", 1, pack1},
{"P", "P;2", 2, packP2}, {"P", "P;2", 2, packP2},
{"P", "P;4", 4, packP4}, {"P", "P;4", 4, packP4},
{"P", "P", 8, copy1}, {"P", "P", 8, copy1},
/* palette w. alpha */ /* palette w. alpha */
{"PA", "PA", 16, packLA}, {"PA", "PA", 16, packLA},
{"PA", "PA;L", 16, packLAL}, {"PA", "PA;L", 16, packLAL},
/* true colour */ /* true colour */
{"RGB", "RGB", 24, ImagingPackRGB}, {"RGB", "RGB", 24, ImagingPackRGB},
{"RGB", "RGBX", 32, copy4}, {"RGB", "RGBX", 32, copy4},
{"RGB", "XRGB", 32, ImagingPackXRGB}, {"RGB", "XRGB", 32, ImagingPackXRGB},
{"RGB", "BGR", 24, ImagingPackBGR}, {"RGB", "BGR", 24, ImagingPackBGR},
{"RGB", "BGRX", 32, ImagingPackBGRX}, {"RGB", "BGRX", 32, ImagingPackBGRX},
{"RGB", "XBGR", 32, ImagingPackXBGR}, {"RGB", "XBGR", 32, ImagingPackXBGR},
{"RGB", "RGB;L", 24, packRGBL}, {"RGB", "RGB;L", 24, packRGBL},
{"RGB", "R", 8, band0}, {"RGB", "R", 8, band0},
{"RGB", "G", 8, band1}, {"RGB", "G", 8, band1},
{"RGB", "B", 8, band2}, {"RGB", "B", 8, band2},
/* true colour w. alpha */ /* true colour w. alpha */
{"RGBA", "RGBA", 32, copy4}, {"RGBA", "RGBA", 32, copy4},
{"RGBA", "RGBA;L", 32, packRGBXL}, {"RGBA", "RGBA;L", 32, packRGBXL},
{"RGBA", "RGB", 24, ImagingPackRGB}, {"RGBA", "RGB", 24, ImagingPackRGB},
{"RGBA", "BGR", 24, ImagingPackBGR}, {"RGBA", "BGR", 24, ImagingPackBGR},
{"RGBA", "BGRA", 32, ImagingPackBGRA}, {"RGBA", "BGRA", 32, ImagingPackBGRA},
{"RGBA", "ABGR", 32, ImagingPackABGR}, {"RGBA", "ABGR", 32, ImagingPackABGR},
{"RGBA", "BGRa", 32, ImagingPackBGRa}, {"RGBA", "BGRa", 32, ImagingPackBGRa},
{"RGBA", "R", 8, band0}, {"RGBA", "R", 8, band0},
{"RGBA", "G", 8, band1}, {"RGBA", "G", 8, band1},
{"RGBA", "B", 8, band2}, {"RGBA", "B", 8, band2},
{"RGBA", "A", 8, band3}, {"RGBA", "A", 8, band3},
/* true colour w. alpha premultiplied */ /* true colour w. alpha premultiplied */
{"RGBa", "RGBa", 32, copy4}, {"RGBa", "RGBa", 32, copy4},
{"RGBa", "BGRa", 32, ImagingPackBGRA}, {"RGBa", "BGRa", 32, ImagingPackBGRA},
{"RGBa", "aBGR", 32, ImagingPackABGR}, {"RGBa", "aBGR", 32, ImagingPackABGR},
/* true colour w. padding */ /* true colour w. padding */
{"RGBX", "RGBX", 32, copy4}, {"RGBX", "RGBX", 32, copy4},
{"RGBX", "RGBX;L", 32, packRGBXL}, {"RGBX", "RGBX;L", 32, packRGBXL},
{"RGBX", "RGB", 24, ImagingPackRGB}, {"RGBX", "RGB", 24, ImagingPackRGB},
{"RGBX", "BGR", 24, ImagingPackBGR}, {"RGBX", "BGR", 24, ImagingPackBGR},
{"RGBX", "BGRX", 32, ImagingPackBGRX}, {"RGBX", "BGRX", 32, ImagingPackBGRX},
{"RGBX", "XBGR", 32, ImagingPackXBGR}, {"RGBX", "XBGR", 32, ImagingPackXBGR},
{"RGBX", "R", 8, band0}, {"RGBX", "R", 8, band0},
{"RGBX", "G", 8, band1}, {"RGBX", "G", 8, band1},
{"RGBX", "B", 8, band2}, {"RGBX", "B", 8, band2},
{"RGBX", "X", 8, band3}, {"RGBX", "X", 8, band3},
/* colour separation */ /* colour separation */
{"CMYK", "CMYK", 32, copy4}, {"CMYK", "CMYK", 32, copy4},
{"CMYK", "CMYK;I", 32, copy4I}, {"CMYK", "CMYK;I", 32, copy4I},
{"CMYK", "CMYK;L", 32, packRGBXL}, {"CMYK", "CMYK;L", 32, packRGBXL},
{"CMYK", "C", 8, band0}, {"CMYK", "C", 8, band0},
{"CMYK", "M", 8, band1}, {"CMYK", "M", 8, band1},
{"CMYK", "Y", 8, band2}, {"CMYK", "Y", 8, band2},
{"CMYK", "K", 8, band3}, {"CMYK", "K", 8, band3},
/* video (YCbCr) */ /* video (YCbCr) */
{"YCbCr", "YCbCr", 24, ImagingPackRGB}, {"YCbCr", "YCbCr", 24, ImagingPackRGB},
{"YCbCr", "YCbCr;L", 24, packRGBL}, {"YCbCr", "YCbCr;L", 24, packRGBL},
{"YCbCr", "YCbCrX", 32, copy4}, {"YCbCr", "YCbCrX", 32, copy4},
{"YCbCr", "YCbCrK", 32, copy4}, {"YCbCr", "YCbCrK", 32, copy4},
{"YCbCr", "Y", 8, band0}, {"YCbCr", "Y", 8, band0},
{"YCbCr", "Cb", 8, band1}, {"YCbCr", "Cb", 8, band1},
{"YCbCr", "Cr", 8, band2}, {"YCbCr", "Cr", 8, band2},
/* LAB Color */ /* LAB Color */
{"LAB", "LAB", 24, ImagingPackLAB}, {"LAB", "LAB", 24, ImagingPackLAB},
{"LAB", "L", 8, band0}, {"LAB", "L", 8, band0},
{"LAB", "A", 8, band1}, {"LAB", "A", 8, band1},
{"LAB", "B", 8, band2}, {"LAB", "B", 8, band2},
/* HSV */ /* HSV */
{"HSV", "HSV", 24, ImagingPackRGB}, {"HSV", "HSV", 24, ImagingPackRGB},
{"HSV", "H", 8, band0}, {"HSV", "H", 8, band0},
{"HSV", "S", 8, band1}, {"HSV", "S", 8, band1},
{"HSV", "V", 8, band2}, {"HSV", "V", 8, band2},
/* integer */ /* integer */
{"I", "I", 32, copy4}, {"I", "I", 32, copy4},
{"I", "I;16B", 16, packI16B}, {"I", "I;16B", 16, packI16B},
{"I", "I;32S", 32, packI32S}, {"I", "I;32S", 32, packI32S},
{"I", "I;32NS", 32, copy4}, {"I", "I;32NS", 32, copy4},
/* floating point */ /* floating point */
{"F", "F", 32, copy4}, {"F", "F", 32, copy4},
{"F", "F;32F", 32, packI32S}, {"F", "F;32F", 32, packI32S},
{"F", "F;32NF", 32, copy4}, {"F", "F;32NF", 32, copy4},
/* storage modes */ /* storage modes */
{"I;16", "I;16", 16, copy2}, {"I;16", "I;16", 16, copy2},
{"I;16", "I;16B", 16, packI16N_I16B}, {"I;16", "I;16B", 16, packI16N_I16B},
{"I;16B", "I;16B", 16, copy2}, {"I;16B", "I;16B", 16, copy2},
{"I;16L", "I;16L", 16, copy2}, {"I;16L", "I;16L", 16, copy2},
{"I;16", "I;16N", 16, packI16N_I16}, // LibTiff native->image endian. {"I;16", "I;16N", 16, packI16N_I16}, // LibTiff native->image endian.
{"I;16L", "I;16N", 16, packI16N_I16}, {"I;16L", "I;16N", 16, packI16N_I16},
{"I;16B", "I;16N", 16, packI16N_I16B}, {"I;16B", "I;16N", 16, packI16N_I16B},
{"BGR;15", "BGR;15", 16, copy2}, {"BGR;15", "BGR;15", 16, copy2},
{"BGR;16", "BGR;16", 16, copy2}, {"BGR;16", "BGR;16", 16, copy2},
{"BGR;24", "BGR;24", 24, copy3}, {"BGR;24", "BGR;24", 24, copy3},
{NULL} /* sentinel */ {NULL} /* sentinel */
}; };
ImagingShuffler ImagingShuffler
ImagingFindPacker(const char* mode, const char* rawmode, int* bits_out) ImagingFindPacker(const char *mode, const char *rawmode, int *bits_out) {
{
int i; int i;
/* find a suitable pixel packer */ /* find a suitable pixel packer */

View File

@ -13,30 +13,27 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
int int
ImagingPackbitsDecode(Imaging im, ImagingCodecState state, ImagingPackbitsDecode(
UINT8* buf, Py_ssize_t bytes) Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
{
UINT8 n; UINT8 n;
UINT8* ptr; UINT8 *ptr;
int i; int i;
ptr = buf; ptr = buf;
for (;;) { for (;;) {
if (bytes < 1) { if (bytes < 1) {
return ptr - buf; return ptr - buf;
} }
if (ptr[0] & 0x80) { if (ptr[0] & 0x80) {
if (ptr[0] == 0x80) { if (ptr[0] == 0x80) {
/* Nop */ /* Nop */
ptr++; bytes--; ptr++;
bytes--;
continue; continue;
} }
@ -53,12 +50,12 @@ ImagingPackbitsDecode(Imaging im, ImagingCodecState state,
state->buffer[state->x++] = ptr[1]; state->buffer[state->x++] = ptr[1];
} }
ptr += 2; bytes -= 2; ptr += 2;
bytes -= 2;
} else { } else {
/* Literal */ /* Literal */
n = ptr[0]+2; n = ptr[0] + 2;
if (bytes < n) { if (bytes < n) {
return ptr - buf; return ptr - buf;
@ -72,16 +69,17 @@ ImagingPackbitsDecode(Imaging im, ImagingCodecState state,
state->buffer[state->x++] = ptr[i]; state->buffer[state->x++] = ptr[i];
} }
ptr += n; bytes -= n; ptr += n;
bytes -= n;
} }
if (state->x >= state->bytes) { if (state->x >= state->bytes) {
/* Got a full line, unpack it */ /* Got a full line, unpack it */
state->shuffle((UINT8*) im->image[state->y + state->yoff] + state->shuffle(
state->xoff * im->pixelsize, state->buffer, (UINT8 *)im->image[state->y + state->yoff] +
state->xsize); state->xoff * im->pixelsize,
state->buffer,
state->xsize);
state->x = 0; state->x = 0;
@ -90,6 +88,5 @@ ImagingPackbitsDecode(Imaging im, ImagingCodecState state,
return -1; return -1;
} }
} }
} }
} }

View File

@ -16,46 +16,41 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#include <math.h> #include <math.h>
ImagingPalette ImagingPalette
ImagingPaletteNew(const char* mode) ImagingPaletteNew(const char *mode) {
{
/* Create a palette object */ /* Create a palette object */
int i; int i;
ImagingPalette palette; ImagingPalette palette;
if (strcmp(mode, "RGB") && strcmp(mode, "RGBA")) { if (strcmp(mode, "RGB") && strcmp(mode, "RGBA")) {
return (ImagingPalette) ImagingError_ModeError(); return (ImagingPalette)ImagingError_ModeError();
} }
palette = calloc(1, sizeof(struct ImagingPaletteInstance)); palette = calloc(1, sizeof(struct ImagingPaletteInstance));
if (!palette) { if (!palette) {
return (ImagingPalette) ImagingError_MemoryError(); return (ImagingPalette)ImagingError_MemoryError();
} }
strncpy(palette->mode, mode, IMAGING_MODE_LENGTH-1); strncpy(palette->mode, mode, IMAGING_MODE_LENGTH - 1);
palette->mode[IMAGING_MODE_LENGTH-1] = 0; palette->mode[IMAGING_MODE_LENGTH - 1] = 0;
/* Initialize to ramp */ /* Initialize to ramp */
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
palette->palette[i*4+0] = palette->palette[i * 4 + 0] = palette->palette[i * 4 + 1] =
palette->palette[i*4+1] = palette->palette[i * 4 + 2] = (UINT8)i;
palette->palette[i*4+2] = (UINT8) i; palette->palette[i * 4 + 3] = 255; /* opaque */
palette->palette[i*4+3] = 255; /* opaque */
} }
return palette; return palette;
} }
ImagingPalette ImagingPalette
ImagingPaletteNewBrowser(void) ImagingPaletteNewBrowser(void) {
{
/* Create a standard "browser" palette object */ /* Create a standard "browser" palette object */
int i, r, g, b; int i, r, g, b;
@ -70,9 +65,8 @@ ImagingPaletteNewBrowser(void)
/* FIXME: Add 10-level windows palette here? */ /* FIXME: Add 10-level windows palette here? */
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
palette->palette[i*4+0] = palette->palette[i * 4 + 0] = palette->palette[i * 4 + 1] =
palette->palette[i*4+1] = palette->palette[i * 4 + 2] = 0;
palette->palette[i*4+2] = 0;
} }
/* Simple 6x6x6 colour cube */ /* Simple 6x6x6 colour cube */
@ -80,9 +74,9 @@ ImagingPaletteNewBrowser(void)
for (b = 0; b < 256; b += 51) { for (b = 0; b < 256; b += 51) {
for (g = 0; g < 256; g += 51) { for (g = 0; g < 256; g += 51) {
for (r = 0; r < 256; r += 51) { for (r = 0; r < 256; r += 51) {
palette->palette[i*4+0] = r; palette->palette[i * 4 + 0] = r;
palette->palette[i*4+1] = g; palette->palette[i * 4 + 1] = g;
palette->palette[i*4+2] = b; palette->palette[i * 4 + 2] = b;
i++; i++;
} }
} }
@ -92,17 +86,15 @@ ImagingPaletteNewBrowser(void)
/* FIXME: add 30-level greyscale wedge here? */ /* FIXME: add 30-level greyscale wedge here? */
for (; i < 256; i++) { for (; i < 256; i++) {
palette->palette[i*4+0] = palette->palette[i * 4 + 0] = palette->palette[i * 4 + 1] =
palette->palette[i*4+1] = palette->palette[i * 4 + 2] = 0;
palette->palette[i*4+2] = 0;
} }
return palette; return palette;
} }
ImagingPalette ImagingPalette
ImagingPaletteDuplicate(ImagingPalette palette) ImagingPaletteDuplicate(ImagingPalette palette) {
{
/* Duplicate palette descriptor */ /* Duplicate palette descriptor */
ImagingPalette new_palette; ImagingPalette new_palette;
@ -113,7 +105,7 @@ ImagingPaletteDuplicate(ImagingPalette palette)
/* malloc check ok, small constant allocation */ /* malloc check ok, small constant allocation */
new_palette = malloc(sizeof(struct ImagingPaletteInstance)); new_palette = malloc(sizeof(struct ImagingPaletteInstance));
if (!new_palette) { if (!new_palette) {
return (ImagingPalette) ImagingError_MemoryError(); return (ImagingPalette)ImagingError_MemoryError();
} }
memcpy(new_palette, palette, sizeof(struct ImagingPaletteInstance)); memcpy(new_palette, palette, sizeof(struct ImagingPaletteInstance));
@ -125,8 +117,7 @@ ImagingPaletteDuplicate(ImagingPalette palette)
} }
void void
ImagingPaletteDelete(ImagingPalette palette) ImagingPaletteDelete(ImagingPalette palette) {
{
/* Destroy palette object */ /* Destroy palette object */
if (palette) { if (palette) {
@ -137,7 +128,6 @@ ImagingPaletteDelete(ImagingPalette palette)
} }
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Colour mapping */ /* Colour mapping */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
@ -155,27 +145,26 @@ ImagingPaletteDelete(ImagingPalette palette)
#define DIST(a, b, s) (a - b) * (a - b) * s #define DIST(a, b, s) (a - b) * (a - b) * s
/* Colour weights (no scaling, for now) */ /* Colour weights (no scaling, for now) */
#define RSCALE 1 #define RSCALE 1
#define GSCALE 1 #define GSCALE 1
#define BSCALE 1 #define BSCALE 1
/* Calculated scaled distances */ /* Calculated scaled distances */
#define RDIST(a, b) DIST(a, b, RSCALE*RSCALE) #define RDIST(a, b) DIST(a, b, RSCALE *RSCALE)
#define GDIST(a, b) DIST(a, b, GSCALE*GSCALE) #define GDIST(a, b) DIST(a, b, GSCALE *GSCALE)
#define BDIST(a, b) DIST(a, b, BSCALE*BSCALE) #define BDIST(a, b) DIST(a, b, BSCALE *BSCALE)
/* Incremental steps */ /* Incremental steps */
#define RSTEP (4 * RSCALE) #define RSTEP (4 * RSCALE)
#define GSTEP (4 * GSCALE) #define GSTEP (4 * GSCALE)
#define BSTEP (4 * BSCALE) #define BSTEP (4 * BSCALE)
#define BOX 8 #define BOX 8
#define BOXVOLUME BOX*BOX*BOX #define BOXVOLUME BOX *BOX *BOX
void void
ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b) ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b) {
{
int i, j; int i, j;
unsigned int dmin[256], dmax; unsigned int dmin[256], dmax;
int r0, g0, b0; int r0, g0, b0;
@ -187,32 +176,37 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
/* Get box boundaries for the given (r,g,b)-triplet. Each box /* Get box boundaries for the given (r,g,b)-triplet. Each box
covers eight cache slots (32 colour values, that is). */ covers eight cache slots (32 colour values, that is). */
r0 = r & 0xe0; r1 = r0 + 0x1f; rc = (r0 + r1) / 2; r0 = r & 0xe0;
g0 = g & 0xe0; g1 = g0 + 0x1f; gc = (g0 + g1) / 2; r1 = r0 + 0x1f;
b0 = b & 0xe0; b1 = b0 + 0x1f; bc = (b0 + b1) / 2; rc = (r0 + r1) / 2;
g0 = g & 0xe0;
g1 = g0 + 0x1f;
gc = (g0 + g1) / 2;
b0 = b & 0xe0;
b1 = b0 + 0x1f;
bc = (b0 + b1) / 2;
/* Step 1 -- Select relevant palette entries (after Heckbert) */ /* Step 1 -- Select relevant palette entries (after Heckbert) */
/* For each palette entry, calculate the min and max distances to /* For each palette entry, calculate the min and max distances to
* any position in the box given by the colour we're looking for. */ * any position in the box given by the colour we're looking for. */
dmax = (unsigned int) ~0; dmax = (unsigned int)~0;
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
int r, g, b; int r, g, b;
unsigned int tmin, tmax; unsigned int tmin, tmax;
/* Find min and max distances to any point in the box */ /* Find min and max distances to any point in the box */
r = palette->palette[i*4+0]; r = palette->palette[i * 4 + 0];
tmin = (r < r0) ? RDIST(r, r1) : (r > r1) ? RDIST(r, r0) : 0; tmin = (r < r0) ? RDIST(r, r1) : (r > r1) ? RDIST(r, r0) : 0;
tmax = (r <= rc) ? RDIST(r, r1) : RDIST(r, r0); tmax = (r <= rc) ? RDIST(r, r1) : RDIST(r, r0);
g = palette->palette[i*4+1]; g = palette->palette[i * 4 + 1];
tmin += (g < g0) ? GDIST(g, g1) : (g > g1) ? GDIST(g, g0) : 0; tmin += (g < g0) ? GDIST(g, g1) : (g > g1) ? GDIST(g, g0) : 0;
tmax += (g <= gc) ? GDIST(g, g1) : GDIST(g, g0); tmax += (g <= gc) ? GDIST(g, g1) : GDIST(g, g0);
b = palette->palette[i*4+2]; b = palette->palette[i * 4 + 2];
tmin += (b < b0) ? BDIST(b, b1) : (b > b1) ? BDIST(b, b0) : 0; tmin += (b < b0) ? BDIST(b, b1) : (b > b1) ? BDIST(b, b0) : 0;
tmax += (b <= bc) ? BDIST(b, b1) : BDIST(b, b0); tmax += (b <= bc) ? BDIST(b, b1) : BDIST(b, b0);
@ -220,7 +214,6 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
if (tmax < dmax) { if (tmax < dmax) {
dmax = tmax; /* keep the smallest max distance only */ dmax = tmax; /* keep the smallest max distance only */
} }
} }
/* Step 2 -- Incrementally update cache slot (after Thomas) */ /* Step 2 -- Incrementally update cache slot (after Thomas) */
@ -230,22 +223,20 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
* distance is less than or equal the smallest max distance */ * distance is less than or equal the smallest max distance */
for (i = 0; i < BOXVOLUME; i++) { for (i = 0; i < BOXVOLUME; i++) {
d[i] = (unsigned int) ~0; d[i] = (unsigned int)~0;
} }
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
if (dmin[i] <= dmax) { if (dmin[i] <= dmax) {
int rd, gd, bd; int rd, gd, bd;
int ri, gi, bi; int ri, gi, bi;
int rx, gx, bx; int rx, gx, bx;
ri = (r0 - palette->palette[i*4+0]) * RSCALE; ri = (r0 - palette->palette[i * 4 + 0]) * RSCALE;
gi = (g0 - palette->palette[i*4+1]) * GSCALE; gi = (g0 - palette->palette[i * 4 + 1]) * GSCALE;
bi = (b0 - palette->palette[i*4+2]) * BSCALE; bi = (b0 - palette->palette[i * 4 + 2]) * BSCALE;
rd = ri*ri + gi*gi + bi*bi; rd = ri * ri + gi * gi + bi * bi;
ri = ri * (2 * RSTEP) + RSTEP * RSTEP; ri = ri * (2 * RSTEP) + RSTEP * RSTEP;
gi = gi * (2 * GSTEP) + GSTEP * GSTEP; gi = gi * (2 * GSTEP) + GSTEP * GSTEP;
@ -253,13 +244,15 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
rx = ri; rx = ri;
for (r = j = 0; r < BOX; r++) { for (r = j = 0; r < BOX; r++) {
gd = rd; gx = gi; gd = rd;
gx = gi;
for (g = 0; g < BOX; g++) { for (g = 0; g < BOX; g++) {
bd = gd; bx = bi; bd = gd;
bx = bi;
for (b = 0; b < BOX; b++) { for (b = 0; b < BOX; b++) {
if ((unsigned int) bd < d[j]) { if ((unsigned int)bd < d[j]) {
d[j] = bd; d[j] = bd;
c[j] = (UINT8) i; c[j] = (UINT8)i;
} }
bd += bx; bd += bx;
bx += 2 * BSTEP * BSTEP; bx += 2 * BSTEP * BSTEP;
@ -280,33 +273,30 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
* cache slot in the box. Update the cache. */ * cache slot in the box. Update the cache. */
j = 0; j = 0;
for (r = r0; r < r1; r+=4) { for (r = r0; r < r1; r += 4) {
for (g = g0; g < g1; g+=4) { for (g = g0; g < g1; g += 4) {
for (b = b0; b < b1; b+=4) { for (b = b0; b < b1; b += 4) {
ImagingPaletteCache(palette, r, g, b) = c[j++]; ImagingPaletteCache(palette, r, g, b) = c[j++];
} }
} }
} }
} }
int int
ImagingPaletteCachePrepare(ImagingPalette palette) ImagingPaletteCachePrepare(ImagingPalette palette) {
{
/* Add a colour cache to a palette */ /* Add a colour cache to a palette */
int i; int i;
int entries = 64*64*64; int entries = 64 * 64 * 64;
if (palette->cache == NULL) { if (palette->cache == NULL) {
/* The cache is 512k. It might be a good idea to break it /* The cache is 512k. It might be a good idea to break it
up into a pointer array (e.g. an 8-bit image?) */ up into a pointer array (e.g. an 8-bit image?) */
/* malloc check ok, small constant allocation */ /* malloc check ok, small constant allocation */
palette->cache = (INT16*) malloc(entries * sizeof(INT16)); palette->cache = (INT16 *)malloc(entries * sizeof(INT16));
if (!palette->cache) { if (!palette->cache) {
(void) ImagingError_MemoryError(); (void)ImagingError_MemoryError();
return -1; return -1;
} }
@ -314,16 +304,13 @@ ImagingPaletteCachePrepare(ImagingPalette palette)
for (i = 0; i < entries; i++) { for (i = 0; i < entries; i++) {
palette->cache[i] = 0x100; palette->cache[i] = 0x100;
} }
} }
return 0; return 0;
} }
void void
ImagingPaletteCacheDelete(ImagingPalette palette) ImagingPaletteCacheDelete(ImagingPalette palette) {
{
/* Release the colour cache, if any */ /* Release the colour cache, if any */
if (palette && palette->cache) { if (palette && palette->cache) {

View File

@ -23,11 +23,17 @@
#include "Imaging.h" #include "Imaging.h"
static inline void static inline void
paste(Imaging imOut, Imaging imIn, int dx, int dy, int sx, int sy, paste(
int xsize, int ysize, int pixelsize) Imaging imOut,
{ Imaging imIn,
int dx,
int dy,
int sx,
int sy,
int xsize,
int ysize,
int pixelsize) {
/* paste opaque region */ /* paste opaque region */
int y; int y;
@ -38,25 +44,31 @@ paste(Imaging imOut, Imaging imIn, int dx, int dy, int sx, int sy,
xsize *= pixelsize; xsize *= pixelsize;
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
memcpy(imOut->image[y+dy]+dx, imIn->image[y+sy]+sx, xsize); memcpy(imOut->image[y + dy] + dx, imIn->image[y + sy] + sx, xsize);
} }
} }
static inline void static inline void
paste_mask_1(Imaging imOut, Imaging imIn, Imaging imMask, paste_mask_1(
int dx, int dy, int sx, int sy, Imaging imOut,
int xsize, int ysize, int pixelsize) Imaging imIn,
{ Imaging imMask,
int dx,
int dy,
int sx,
int sy,
int xsize,
int ysize,
int pixelsize) {
/* paste with mode "1" mask */ /* paste with mode "1" mask */
int x, y; int x, y;
if (imOut->image8) { if (imOut->image8) {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
UINT8* out = imOut->image8[y+dy]+dx; UINT8 *out = imOut->image8[y + dy] + dx;
UINT8* in = imIn->image8[y+sy]+sx; UINT8 *in = imIn->image8[y + sy] + sx;
UINT8* mask = imMask->image8[y+sy]+sx; UINT8 *mask = imMask->image8[y + sy] + sx;
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
if (*mask++) { if (*mask++) {
*out = *in; *out = *in;
@ -66,11 +78,10 @@ paste_mask_1(Imaging imOut, Imaging imIn, Imaging imMask,
} }
} else { } else {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
INT32* out = imOut->image32[y+dy]+dx; INT32 *out = imOut->image32[y + dy] + dx;
INT32* in = imIn->image32[y+sy]+sx; INT32 *in = imIn->image32[y + sy] + sx;
UINT8* mask = imMask->image8[y+sy]+sx; UINT8 *mask = imMask->image8[y + sy] + sx;
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
if (*mask++) { if (*mask++) {
*out = *in; *out = *in;
@ -82,21 +93,27 @@ paste_mask_1(Imaging imOut, Imaging imIn, Imaging imMask,
} }
static inline void static inline void
paste_mask_L(Imaging imOut, Imaging imIn, Imaging imMask, paste_mask_L(
int dx, int dy, int sx, int sy, Imaging imOut,
int xsize, int ysize, int pixelsize) Imaging imIn,
{ Imaging imMask,
int dx,
int dy,
int sx,
int sy,
int xsize,
int ysize,
int pixelsize) {
/* paste with mode "L" matte */ /* paste with mode "L" matte */
int x, y; int x, y;
unsigned int tmp1; unsigned int tmp1;
if (imOut->image8) { if (imOut->image8) {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
UINT8* out = imOut->image8[y+dy]+dx; UINT8 *out = imOut->image8[y + dy] + dx;
UINT8* in = imIn->image8[y+sy]+sx; UINT8 *in = imIn->image8[y + sy] + sx;
UINT8* mask = imMask->image8[y+sy]+sx; UINT8 *mask = imMask->image8[y + sy] + sx;
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
*out = BLEND(*mask, *out, *in, tmp1); *out = BLEND(*mask, *out, *in, tmp1);
out++, in++, mask++; out++, in++, mask++;
@ -104,39 +121,46 @@ paste_mask_L(Imaging imOut, Imaging imIn, Imaging imMask,
} }
} else { } else {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
UINT8* out = (UINT8*) (imOut->image32[y + dy] + dx); UINT8 *out = (UINT8 *)(imOut->image32[y + dy] + dx);
UINT8* in = (UINT8*) (imIn->image32[y + sy] + sx); UINT8 *in = (UINT8 *)(imIn->image32[y + sy] + sx);
UINT8* mask = (UINT8*) (imMask->image8[y+sy] + sx); UINT8 *mask = (UINT8 *)(imMask->image8[y + sy] + sx);
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
UINT8 a = mask[0]; UINT8 a = mask[0];
out[0] = BLEND(a, out[0], in[0], tmp1); out[0] = BLEND(a, out[0], in[0], tmp1);
out[1] = BLEND(a, out[1], in[1], tmp1); out[1] = BLEND(a, out[1], in[1], tmp1);
out[2] = BLEND(a, out[2], in[2], tmp1); out[2] = BLEND(a, out[2], in[2], tmp1);
out[3] = BLEND(a, out[3], in[3], tmp1); out[3] = BLEND(a, out[3], in[3], tmp1);
out += 4; in += 4; mask ++; out += 4;
in += 4;
mask++;
} }
} }
} }
} }
static inline void static inline void
paste_mask_RGBA(Imaging imOut, Imaging imIn, Imaging imMask, paste_mask_RGBA(
int dx, int dy, int sx, int sy, Imaging imOut,
int xsize, int ysize, int pixelsize) Imaging imIn,
{ Imaging imMask,
int dx,
int dy,
int sx,
int sy,
int xsize,
int ysize,
int pixelsize) {
/* paste with mode "RGBA" matte */ /* paste with mode "RGBA" matte */
int x, y; int x, y;
unsigned int tmp1; unsigned int tmp1;
if (imOut->image8) { if (imOut->image8) {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
UINT8* out = imOut->image8[y+dy]+dx; UINT8 *out = imOut->image8[y + dy] + dx;
UINT8* in = imIn->image8[y+sy]+sx; UINT8 *in = imIn->image8[y + sy] + sx;
UINT8* mask = (UINT8*) imMask->image[y+sy]+sx*4+3; UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx * 4 + 3;
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
*out = BLEND(*mask, *out, *in, tmp1); *out = BLEND(*mask, *out, *in, tmp1);
out++, in++, mask += 4; out++, in++, mask += 4;
@ -144,40 +168,46 @@ paste_mask_RGBA(Imaging imOut, Imaging imIn, Imaging imMask,
} }
} else { } else {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
UINT8* out = (UINT8*) (imOut->image32[y + dy] + dx); UINT8 *out = (UINT8 *)(imOut->image32[y + dy] + dx);
UINT8* in = (UINT8*) (imIn->image32[y + sy] + sx); UINT8 *in = (UINT8 *)(imIn->image32[y + sy] + sx);
UINT8* mask = (UINT8*) (imMask->image32[y+sy] + sx); UINT8 *mask = (UINT8 *)(imMask->image32[y + sy] + sx);
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
UINT8 a = mask[3]; UINT8 a = mask[3];
out[0] = BLEND(a, out[0], in[0], tmp1); out[0] = BLEND(a, out[0], in[0], tmp1);
out[1] = BLEND(a, out[1], in[1], tmp1); out[1] = BLEND(a, out[1], in[1], tmp1);
out[2] = BLEND(a, out[2], in[2], tmp1); out[2] = BLEND(a, out[2], in[2], tmp1);
out[3] = BLEND(a, out[3], in[3], tmp1); out[3] = BLEND(a, out[3], in[3], tmp1);
out += 4; in += 4; mask += 4; out += 4;
in += 4;
mask += 4;
} }
} }
} }
} }
static inline void static inline void
paste_mask_RGBa(Imaging imOut, Imaging imIn, Imaging imMask, paste_mask_RGBa(
int dx, int dy, int sx, int sy, Imaging imOut,
int xsize, int ysize, int pixelsize) Imaging imIn,
{ Imaging imMask,
int dx,
int dy,
int sx,
int sy,
int xsize,
int ysize,
int pixelsize) {
/* paste with mode "RGBa" matte */ /* paste with mode "RGBa" matte */
int x, y; int x, y;
unsigned int tmp1; unsigned int tmp1;
if (imOut->image8) { if (imOut->image8) {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
UINT8* out = imOut->image8[y+dy]+dx; UINT8 *out = imOut->image8[y + dy] + dx;
UINT8* in = imIn->image8[y+sy]+sx; UINT8 *in = imIn->image8[y + sy] + sx;
UINT8* mask = (UINT8*) imMask->image[y+sy]+sx*4+3; UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx * 4 + 3;
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
*out = PREBLEND(*mask, *out, *in, tmp1); *out = PREBLEND(*mask, *out, *in, tmp1);
out++, in++, mask += 4; out++, in++, mask += 4;
@ -185,34 +215,34 @@ paste_mask_RGBa(Imaging imOut, Imaging imIn, Imaging imMask,
} }
} else { } else {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
UINT8* out = (UINT8*) (imOut->image32[y + dy] + dx); UINT8 *out = (UINT8 *)(imOut->image32[y + dy] + dx);
UINT8* in = (UINT8*) (imIn->image32[y + sy] + sx); UINT8 *in = (UINT8 *)(imIn->image32[y + sy] + sx);
UINT8* mask = (UINT8*) (imMask->image32[y+sy] + sx); UINT8 *mask = (UINT8 *)(imMask->image32[y + sy] + sx);
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
UINT8 a = mask[3]; UINT8 a = mask[3];
out[0] = PREBLEND(a, out[0], in[0], tmp1); out[0] = PREBLEND(a, out[0], in[0], tmp1);
out[1] = PREBLEND(a, out[1], in[1], tmp1); out[1] = PREBLEND(a, out[1], in[1], tmp1);
out[2] = PREBLEND(a, out[2], in[2], tmp1); out[2] = PREBLEND(a, out[2], in[2], tmp1);
out[3] = PREBLEND(a, out[3], in[3], tmp1); out[3] = PREBLEND(a, out[3], in[3], tmp1);
out += 4; in += 4; mask += 4; out += 4;
in += 4;
mask += 4;
} }
} }
} }
} }
int int
ImagingPaste(Imaging imOut, Imaging imIn, Imaging imMask, ImagingPaste(
int dx0, int dy0, int dx1, int dy1) Imaging imOut, Imaging imIn, Imaging imMask, int dx0, int dy0, int dx1, int dy1) {
{
int xsize, ysize; int xsize, ysize;
int pixelsize; int pixelsize;
int sx0, sy0; int sx0, sy0;
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
if (!imOut || !imIn) { if (!imOut || !imIn) {
(void) ImagingError_ModeError(); (void)ImagingError_ModeError();
return -1; return -1;
} }
@ -221,14 +251,13 @@ ImagingPaste(Imaging imOut, Imaging imIn, Imaging imMask,
xsize = dx1 - dx0; xsize = dx1 - dx0;
ysize = dy1 - dy0; ysize = dy1 - dy0;
if (xsize != imIn->xsize || ysize != imIn->ysize || if (xsize != imIn->xsize || ysize != imIn->ysize || pixelsize != imIn->pixelsize) {
pixelsize != imIn->pixelsize) { (void)ImagingError_Mismatch();
(void) ImagingError_Mismatch();
return -1; return -1;
} }
if (imMask && (xsize != imMask->xsize || ysize != imMask->ysize)) { if (imMask && (xsize != imMask->xsize || ysize != imMask->ysize)) {
(void) ImagingError_Mismatch(); (void)ImagingError_Mismatch();
return -1; return -1;
} }
@ -258,30 +287,28 @@ ImagingPaste(Imaging imOut, Imaging imIn, Imaging imMask,
} else if (strcmp(imMask->mode, "1") == 0) { } else if (strcmp(imMask->mode, "1") == 0) {
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
paste_mask_1(imOut, imIn, imMask, dx0, dy0, sx0, sy0, paste_mask_1(imOut, imIn, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
xsize, ysize, pixelsize);
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
} else if (strcmp(imMask->mode, "L") == 0) { } else if (strcmp(imMask->mode, "L") == 0) {
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
paste_mask_L(imOut, imIn, imMask, dx0, dy0, sx0, sy0, paste_mask_L(imOut, imIn, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
xsize, ysize, pixelsize);
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
} else if (strcmp(imMask->mode, "RGBA") == 0) { } else if (strcmp(imMask->mode, "RGBA") == 0) {
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
paste_mask_RGBA(imOut, imIn, imMask, dx0, dy0, sx0, sy0, paste_mask_RGBA(
xsize, ysize, pixelsize); imOut, imIn, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
} else if (strcmp(imMask->mode, "RGBa") == 0) { } else if (strcmp(imMask->mode, "RGBa") == 0) {
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
paste_mask_RGBa(imOut, imIn, imMask, dx0, dy0, sx0, sy0, paste_mask_RGBa(
xsize, ysize, pixelsize); imOut, imIn, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
} else { } else {
(void) ImagingError_ValueError("bad transparency mask"); (void)ImagingError_ValueError("bad transparency mask");
return -1; return -1;
} }
@ -289,9 +316,14 @@ ImagingPaste(Imaging imOut, Imaging imIn, Imaging imMask,
} }
static inline void static inline void
fill(Imaging imOut, const void* ink_, int dx, int dy, fill(
int xsize, int ysize, int pixelsize) Imaging imOut,
{ const void *ink_,
int dx,
int dy,
int xsize,
int ysize,
int pixelsize) {
/* fill opaque region */ /* fill opaque region */
int x, y; int x, y;
@ -302,30 +334,34 @@ fill(Imaging imOut, const void* ink_, int dx, int dy,
memcpy(&ink8, ink_, sizeof(ink8)); memcpy(&ink8, ink_, sizeof(ink8));
if (imOut->image8 || ink32 == 0L) { if (imOut->image8 || ink32 == 0L) {
dx *= pixelsize; dx *= pixelsize;
xsize *= pixelsize; xsize *= pixelsize;
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
memset(imOut->image[y+dy]+dx, ink8, xsize); memset(imOut->image[y + dy] + dx, ink8, xsize);
} }
} else { } else {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
INT32* out = imOut->image32[y+dy]+dx; INT32 *out = imOut->image32[y + dy] + dx;
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
out[x] = ink32; out[x] = ink32;
} }
} }
} }
} }
static inline void static inline void
fill_mask_1(Imaging imOut, const void* ink_, Imaging imMask, fill_mask_1(
int dx, int dy, int sx, int sy, Imaging imOut,
int xsize, int ysize, int pixelsize) const void *ink_,
{ Imaging imMask,
int dx,
int dy,
int sx,
int sy,
int xsize,
int ysize,
int pixelsize) {
/* fill with mode "1" mask */ /* fill with mode "1" mask */
int x, y; int x, y;
@ -336,10 +372,9 @@ fill_mask_1(Imaging imOut, const void* ink_, Imaging imMask,
memcpy(&ink8, ink_, sizeof(ink8)); memcpy(&ink8, ink_, sizeof(ink8));
if (imOut->image8) { if (imOut->image8) {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
UINT8* out = imOut->image8[y+dy]+dx; UINT8 *out = imOut->image8[y + dy] + dx;
UINT8* mask = imMask->image8[y+sy]+sx; UINT8 *mask = imMask->image8[y + sy] + sx;
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
if (*mask++) { if (*mask++) {
*out = ink8; *out = ink8;
@ -349,10 +384,9 @@ fill_mask_1(Imaging imOut, const void* ink_, Imaging imMask,
} }
} else { } else {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
INT32* out = imOut->image32[y+dy]+dx; INT32 *out = imOut->image32[y + dy] + dx;
UINT8* mask = imMask->image8[y+sy]+sx; UINT8 *mask = imMask->image8[y + sy] + sx;
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
if (*mask++) { if (*mask++) {
*out = ink32; *out = ink32;
@ -364,20 +398,26 @@ fill_mask_1(Imaging imOut, const void* ink_, Imaging imMask,
} }
static inline void static inline void
fill_mask_L(Imaging imOut, const UINT8* ink, Imaging imMask, fill_mask_L(
int dx, int dy, int sx, int sy, Imaging imOut,
int xsize, int ysize, int pixelsize) const UINT8 *ink,
{ Imaging imMask,
int dx,
int dy,
int sx,
int sy,
int xsize,
int ysize,
int pixelsize) {
/* fill with mode "L" matte */ /* fill with mode "L" matte */
int x, y, i; int x, y, i;
unsigned int tmp1; unsigned int tmp1;
if (imOut->image8) { if (imOut->image8) {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
UINT8* out = imOut->image8[y+dy]+dx; UINT8 *out = imOut->image8[y + dy] + dx;
UINT8* mask = imMask->image8[y+sy]+sx; UINT8 *mask = imMask->image8[y + sy] + sx;
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
*out = BLEND(*mask, *out, ink[0], tmp1); *out = BLEND(*mask, *out, ink[0], tmp1);
out++, mask++; out++, mask++;
@ -385,21 +425,20 @@ fill_mask_L(Imaging imOut, const UINT8* ink, Imaging imMask,
} }
} else { } else {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
UINT8* out = (UINT8*) imOut->image[y+dy]+dx*pixelsize; UINT8 *out = (UINT8 *)imOut->image[y + dy] + dx * pixelsize;
UINT8* mask = (UINT8*) imMask->image[y+sy]+sx; UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
for (i = 0; i < pixelsize; i++) { for (i = 0; i < pixelsize; i++) {
UINT8 channel_mask = *mask; UINT8 channel_mask = *mask;
if (( if ((strcmp(imOut->mode, "RGBa") == 0 ||
strcmp(imOut->mode, "RGBa") == 0 || strcmp(imOut->mode, "RGBA") == 0 ||
strcmp(imOut->mode, "RGBA") == 0 || strcmp(imOut->mode, "La") == 0 ||
strcmp(imOut->mode, "La") == 0 || strcmp(imOut->mode, "LA") == 0 ||
strcmp(imOut->mode, "LA") == 0 || strcmp(imOut->mode, "PA") == 0) &&
strcmp(imOut->mode, "PA") == 0 i != 3) {
) && i != 3) { channel_mask =
channel_mask = 255 - (255 - channel_mask) * (1 - (255 - out[3]) / 255); 255 - (255 - channel_mask) * (1 - (255 - out[3]) / 255);
} }
out[i] = BLEND(channel_mask, out[i], ink[i], tmp1); out[i] = BLEND(channel_mask, out[i], ink[i], tmp1);
} }
@ -411,21 +450,27 @@ fill_mask_L(Imaging imOut, const UINT8* ink, Imaging imMask,
} }
static inline void static inline void
fill_mask_RGBA(Imaging imOut, const UINT8* ink, Imaging imMask, fill_mask_RGBA(
int dx, int dy, int sx, int sy, Imaging imOut,
int xsize, int ysize, int pixelsize) const UINT8 *ink,
{ Imaging imMask,
int dx,
int dy,
int sx,
int sy,
int xsize,
int ysize,
int pixelsize) {
/* fill with mode "RGBA" matte */ /* fill with mode "RGBA" matte */
int x, y, i; int x, y, i;
unsigned int tmp1; unsigned int tmp1;
if (imOut->image8) { if (imOut->image8) {
sx = sx * 4 + 3;
sx = sx*4+3;
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
UINT8* out = imOut->image8[y+dy]+dx; UINT8 *out = imOut->image8[y + dy] + dx;
UINT8* mask = (UINT8*) imMask->image[y+sy]+sx; UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
*out = BLEND(*mask, *out, ink[0], tmp1); *out = BLEND(*mask, *out, ink[0], tmp1);
out++, mask += 4; out++, mask += 4;
@ -433,12 +478,11 @@ fill_mask_RGBA(Imaging imOut, const UINT8* ink, Imaging imMask,
} }
} else { } else {
dx *= pixelsize; dx *= pixelsize;
sx = sx*4 + 3; sx = sx * 4 + 3;
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
UINT8* out = (UINT8*) imOut->image[y+dy]+dx; UINT8 *out = (UINT8 *)imOut->image[y + dy] + dx;
UINT8* mask = (UINT8*) imMask->image[y+sy]+sx; UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
for (i = 0; i < pixelsize; i++) { for (i = 0; i < pixelsize; i++) {
*out = BLEND(*mask, *out, ink[i], tmp1); *out = BLEND(*mask, *out, ink[i], tmp1);
@ -451,21 +495,27 @@ fill_mask_RGBA(Imaging imOut, const UINT8* ink, Imaging imMask,
} }
static inline void static inline void
fill_mask_RGBa(Imaging imOut, const UINT8* ink, Imaging imMask, fill_mask_RGBa(
int dx, int dy, int sx, int sy, Imaging imOut,
int xsize, int ysize, int pixelsize) const UINT8 *ink,
{ Imaging imMask,
int dx,
int dy,
int sx,
int sy,
int xsize,
int ysize,
int pixelsize) {
/* fill with mode "RGBa" matte */ /* fill with mode "RGBa" matte */
int x, y, i; int x, y, i;
unsigned int tmp1; unsigned int tmp1;
if (imOut->image8) { if (imOut->image8) {
sx = sx * 4 + 3;
sx = sx*4 + 3;
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
UINT8* out = imOut->image8[y+dy]+dx; UINT8 *out = imOut->image8[y + dy] + dx;
UINT8* mask = (UINT8*) imMask->image[y+sy]+sx; UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
*out = PREBLEND(*mask, *out, ink[0], tmp1); *out = PREBLEND(*mask, *out, ink[0], tmp1);
out++, mask += 4; out++, mask += 4;
@ -473,12 +523,11 @@ fill_mask_RGBa(Imaging imOut, const UINT8* ink, Imaging imMask,
} }
} else { } else {
dx *= pixelsize; dx *= pixelsize;
sx = sx*4 + 3; sx = sx * 4 + 3;
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
UINT8* out = (UINT8*) imOut->image[y+dy]+dx; UINT8 *out = (UINT8 *)imOut->image[y + dy] + dx;
UINT8* mask = (UINT8*) imMask->image[y+sy]+sx; UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
for (x = 0; x < xsize; x++) { for (x = 0; x < xsize; x++) {
for (i = 0; i < pixelsize; i++) { for (i = 0; i < pixelsize; i++) {
*out = PREBLEND(*mask, *out, ink[i], tmp1); *out = PREBLEND(*mask, *out, ink[i], tmp1);
@ -491,16 +540,21 @@ fill_mask_RGBa(Imaging imOut, const UINT8* ink, Imaging imMask,
} }
int int
ImagingFill2(Imaging imOut, const void* ink, Imaging imMask, ImagingFill2(
int dx0, int dy0, int dx1, int dy1) Imaging imOut,
{ const void *ink,
Imaging imMask,
int dx0,
int dy0,
int dx1,
int dy1) {
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
int xsize, ysize; int xsize, ysize;
int pixelsize; int pixelsize;
int sx0, sy0; int sx0, sy0;
if (!imOut || !ink) { if (!imOut || !ink) {
(void) ImagingError_ModeError(); (void)ImagingError_ModeError();
return -1; return -1;
} }
@ -510,7 +564,7 @@ ImagingFill2(Imaging imOut, const void* ink, Imaging imMask,
ysize = dy1 - dy0; ysize = dy1 - dy0;
if (imMask && (xsize != imMask->xsize || ysize != imMask->ysize)) { if (imMask && (xsize != imMask->xsize || ysize != imMask->ysize)) {
(void) ImagingError_Mismatch(); (void)ImagingError_Mismatch();
return -1; return -1;
} }
@ -540,30 +594,26 @@ ImagingFill2(Imaging imOut, const void* ink, Imaging imMask,
} else if (strcmp(imMask->mode, "1") == 0) { } else if (strcmp(imMask->mode, "1") == 0) {
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
fill_mask_1(imOut, ink, imMask, dx0, dy0, sx0, sy0, fill_mask_1(imOut, ink, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
xsize, ysize, pixelsize);
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
} else if (strcmp(imMask->mode, "L") == 0) { } else if (strcmp(imMask->mode, "L") == 0) {
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
fill_mask_L(imOut, ink, imMask, dx0, dy0, sx0, sy0, fill_mask_L(imOut, ink, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
xsize, ysize, pixelsize);
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
} else if (strcmp(imMask->mode, "RGBA") == 0) { } else if (strcmp(imMask->mode, "RGBA") == 0) {
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
fill_mask_RGBA(imOut, ink, imMask, dx0, dy0, sx0, sy0, fill_mask_RGBA(imOut, ink, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
xsize, ysize, pixelsize);
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
} else if (strcmp(imMask->mode, "RGBa") == 0) { } else if (strcmp(imMask->mode, "RGBa") == 0) {
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
fill_mask_RGBa(imOut, ink, imMask, dx0, dy0, sx0, sy0, fill_mask_RGBa(imOut, ink, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
xsize, ysize, pixelsize);
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
} else { } else {
(void) ImagingError_ValueError("bad transparency mask"); (void)ImagingError_ValueError("bad transparency mask");
return -1; return -1;
} }

View File

@ -19,24 +19,20 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
int int
ImagingPcdDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes) ImagingPcdDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
{
int x; int x;
int chunk; int chunk;
UINT8* out; UINT8 *out;
UINT8* ptr; UINT8 *ptr;
ptr = buf; ptr = buf;
chunk = 3 * state->xsize; chunk = 3 * state->xsize;
for (;;) { for (;;) {
/* We need data for two full lines before we can do anything */ /* We need data for two full lines before we can do anything */
if (bytes < chunk) { if (bytes < chunk) {
return ptr - buf; return ptr - buf;
@ -46,13 +42,12 @@ ImagingPcdDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
out = state->buffer; out = state->buffer;
for (x = 0; x < state->xsize; x++) { for (x = 0; x < state->xsize; x++) {
out[0] = ptr[x]; out[0] = ptr[x];
out[1] = ptr[(x+4*state->xsize)/2]; out[1] = ptr[(x + 4 * state->xsize) / 2];
out[2] = ptr[(x+5*state->xsize)/2]; out[2] = ptr[(x + 5 * state->xsize) / 2];
out += 3; out += 3;
} }
state->shuffle((UINT8*) im->image[state->y], state->shuffle((UINT8 *)im->image[state->y], state->buffer, state->xsize);
state->buffer, state->xsize);
if (++state->y >= state->ysize) { if (++state->y >= state->ysize) {
return -1; /* This can hardly happen */ return -1; /* This can hardly happen */
@ -61,14 +56,13 @@ ImagingPcdDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
/* Unpack second line */ /* Unpack second line */
out = state->buffer; out = state->buffer;
for (x = 0; x < state->xsize; x++) { for (x = 0; x < state->xsize; x++) {
out[0] = ptr[x+state->xsize]; out[0] = ptr[x + state->xsize];
out[1] = ptr[(x+4*state->xsize)/2]; out[1] = ptr[(x + 4 * state->xsize) / 2];
out[2] = ptr[(x+5*state->xsize)/2]; out[2] = ptr[(x + 5 * state->xsize) / 2];
out += 3; out += 3;
} }
state->shuffle((UINT8*) im->image[state->y], state->shuffle((UINT8 *)im->image[state->y], state->buffer, state->xsize);
state->buffer, state->xsize);
if (++state->y >= state->ysize) { if (++state->y >= state->ysize) {
return -1; return -1;
@ -76,6 +70,5 @@ ImagingPcdDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
ptr += chunk; ptr += chunk;
bytes -= chunk; bytes -= chunk;
} }
} }

View File

@ -13,14 +13,12 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
int int
ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes) ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
{
UINT8 n; UINT8 n;
UINT8* ptr; UINT8 *ptr;
if ((state->xsize * state->bits + 7) / 8 > state->bytes) { if ((state->xsize * state->bits + 7) / 8 > state->bytes) {
state->errcode = IMAGING_CODEC_OVERRUN; state->errcode = IMAGING_CODEC_OVERRUN;
@ -30,13 +28,11 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
ptr = buf; ptr = buf;
for (;;) { for (;;) {
if (bytes < 1) { if (bytes < 1) {
return ptr - buf; return ptr - buf;
} }
if ((*ptr & 0xC0) == 0xC0) { if ((*ptr & 0xC0) == 0xC0) {
/* Run */ /* Run */
if (bytes < 2) { if (bytes < 2) {
return ptr - buf; return ptr - buf;
@ -53,14 +49,14 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
n--; n--;
} }
ptr += 2; bytes -= 2; ptr += 2;
bytes -= 2;
} else { } else {
/* Literal */ /* Literal */
state->buffer[state->x++] = ptr[0]; state->buffer[state->x++] = ptr[0];
ptr++; bytes--; ptr++;
bytes--;
} }
if (state->x >= state->bytes) { if (state->x >= state->bytes) {
@ -68,16 +64,19 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
int bands = state->bytes / state->xsize; int bands = state->bytes / state->xsize;
int stride = state->bytes / bands; int stride = state->bytes / bands;
int i; int i;
for (i=1; i< bands; i++) { // note -- skipping first band for (i = 1; i < bands; i++) { // note -- skipping first band
memmove(&state->buffer[i*state->xsize], memmove(
&state->buffer[i*stride], &state->buffer[i * state->xsize],
state->xsize); &state->buffer[i * stride],
state->xsize);
} }
} }
/* Got a full line, unpack it */ /* Got a full line, unpack it */
state->shuffle((UINT8*) im->image[state->y + state->yoff] + state->shuffle(
state->xoff * im->pixelsize, state->buffer, (UINT8 *)im->image[state->y + state->yoff] +
state->xsize); state->xoff * im->pixelsize,
state->buffer,
state->xsize);
state->x = 0; state->x = 0;
@ -86,6 +85,5 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
return -1; return -1;
} }
} }
} }
} }

View File

@ -13,7 +13,6 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
enum { INIT, FETCH, ENCODE }; enum { INIT, FETCH, ENCODE };
@ -22,9 +21,8 @@ enum { INIT, FETCH, ENCODE };
#define LAST ystep #define LAST ystep
int int
ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
{ UINT8 *ptr;
UINT8* ptr;
int this; int this;
int bytes_per_line = 0; int bytes_per_line = 0;
int padding = 0; int padding = 0;
@ -45,12 +43,12 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
} }
bpp = state->bits; bpp = state->bits;
if (state->bits == 24){ if (state->bits == 24) {
planes = 3; planes = 3;
bpp = 8; bpp = 8;
} }
bytes_per_line = (state->xsize*bpp + 7) / 8; bytes_per_line = (state->xsize * bpp + 7) / 8;
/* The stride here needs to be kept in sync with the version in /* The stride here needs to be kept in sync with the version in
PcxImagePlugin.py. If it's not, the header and the body of the PcxImagePlugin.py. If it's not, the header and the body of the
image will be out of sync and bad things will happen on decode. image will be out of sync and bad things will happen on decode.
@ -59,133 +57,131 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
padding = stride - bytes_per_line; padding = stride - bytes_per_line;
for (;;) { for (;;) {
switch (state->state) { switch (state->state) {
case FETCH: case FETCH:
/* get a line of data */ /* get a line of data */
if (state->y >= state->ysize) { if (state->y >= state->ysize) {
state->errcode = IMAGING_CODEC_END; state->errcode = IMAGING_CODEC_END;
return ptr - buf; return ptr - buf;
} }
state->shuffle(state->buffer, state->shuffle(
(UINT8*) im->image[state->y + state->yoff] + state->buffer,
state->xoff * im->pixelsize, state->xsize); (UINT8 *)im->image[state->y + state->yoff] +
state->xoff * im->pixelsize,
state->xsize);
state->y += 1; state->y += 1;
state->count = 1; state->count = 1;
state->LAST = state->buffer[0]; state->LAST = state->buffer[0];
state->x = 1; state->x = 1;
state->state = ENCODE; state->state = ENCODE;
/* fall through */ /* fall through */
case ENCODE: case ENCODE:
/* compress this line */ /* compress this line */
/* when we arrive here, "count" contains the number of /* when we arrive here, "count" contains the number of
bytes having the value of "LAST" that we've already bytes having the value of "LAST" that we've already
seen */ seen */
do { do {
/* If we're encoding an odd width file, and we've /* If we're encoding an odd width file, and we've
got more than one plane, we need to pad each got more than one plane, we need to pad each
color row with padding bytes at the end. Since color row with padding bytes at the end. Since
The pixels are stored RRRRRGGGGGBBBBB, so we need The pixels are stored RRRRRGGGGGBBBBB, so we need
to have the padding be RRRRRPGGGGGPBBBBBP. Hence to have the padding be RRRRRPGGGGGPBBBBBP. Hence
the double loop the double loop
*/ */
while (state->x % bytes_per_line) { while (state->x % bytes_per_line) {
if (state->count == 63) {
if (state->count == 63) { /* this run is full; flush it */
/* this run is full; flush it */ if (bytes < 2) {
if (bytes < 2) {
return ptr - buf;
}
ptr[0] = 0xff;
ptr[1] = state->LAST;
ptr += 2;
bytes -= 2;
state->count = 0;
}
this = state->buffer[state->x];
if (this == state->LAST) {
/* extend the current run */
state->x += 1;
state->count += 1;
} else {
/* start a new run */
if (state->count == 1 && (state->LAST < 0xc0)) {
if (bytes < 1) {
return ptr - buf; return ptr - buf;
} }
ptr[0] = state->LAST; ptr[0] = 0xff;
ptr += 1; ptr[1] = state->LAST;
bytes -= 1; ptr += 2;
bytes -= 2;
state->count = 0;
}
this = state->buffer[state->x];
if (this == state->LAST) {
/* extend the current run */
state->x += 1;
state->count += 1;
} else { } else {
if (state->count > 0) { /* start a new run */
if (bytes < 2) { if (state->count == 1 && (state->LAST < 0xc0)) {
if (bytes < 1) {
return ptr - buf; return ptr - buf;
} }
ptr[0] = 0xc0 | state->count; ptr[0] = state->LAST;
ptr[1] = state->LAST; ptr += 1;
ptr += 2; bytes -= 1;
bytes -= 2; } else {
if (state->count > 0) {
if (bytes < 2) {
return ptr - buf;
}
ptr[0] = 0xc0 | state->count;
ptr[1] = state->LAST;
ptr += 2;
bytes -= 2;
}
} }
state->LAST = this;
state->count = 1;
state->x += 1;
} }
state->LAST = this;
state->count = 1;
state->x += 1;
} }
}
/* end of line; flush the current run */ /* end of line; flush the current run */
if (state->count == 1 && (state->LAST < 0xc0)) { if (state->count == 1 && (state->LAST < 0xc0)) {
if (bytes < 1 + padding) { if (bytes < 1 + padding) {
return ptr - buf;
}
ptr[0] = state->LAST;
ptr += 1;
bytes -= 1;
} else {
if (state->count > 0) {
if (bytes < 2 + padding) {
return ptr - buf; return ptr - buf;
} }
ptr[0] = 0xc0 | state->count; ptr[0] = state->LAST;
ptr[1] = state->LAST; ptr += 1;
ptr += 2; bytes -= 1;
bytes -= 2; } else {
if (state->count > 0) {
if (bytes < 2 + padding) {
return ptr - buf;
}
ptr[0] = 0xc0 | state->count;
ptr[1] = state->LAST;
ptr += 2;
bytes -= 2;
}
} }
} /* add the padding */
/* add the padding */ for (i = 0; i < padding; i++) {
for (i = 0; i < padding; i++) { ptr[0] = 0;
ptr[0] = 0; ptr += 1;
ptr += 1; bytes -= 1;
bytes -= 1; }
} /* reset for the next color plane. */
/* reset for the next color plane. */ if (state->x < planes * bytes_per_line) {
if (state->x < planes * bytes_per_line) { state->count = 1;
state->count = 1; state->LAST = state->buffer[state->x];
state->LAST = state->buffer[state->x]; state->x += 1;
state->x += 1; }
} } while (state->x < planes * bytes_per_line);
} while (state->x < planes * bytes_per_line);
/* read next line */ /* read next line */
state->state = FETCH; state->state = FETCH;
break; break;
} }
} }
} }

View File

@ -19,22 +19,20 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
typedef struct { typedef struct {
const void* table; const void *table;
} im_point_context; } im_point_context;
static void static void
im_point_8_8(Imaging imOut, Imaging imIn, im_point_context* context) im_point_8_8(Imaging imOut, Imaging imIn, im_point_context *context) {
{
int x, y; int x, y;
/* 8-bit source, 8-bit destination */ /* 8-bit source, 8-bit destination */
UINT8* table = (UINT8*) context->table; UINT8 *table = (UINT8 *)context->table;
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
UINT8* in = imIn->image8[y]; UINT8 *in = imIn->image8[y];
UINT8* out = imOut->image8[y]; UINT8 *out = imOut->image8[y];
for (x = 0; x < imIn->xsize; x++) { for (x = 0; x < imIn->xsize; x++) {
out[x] = table[in[x]]; out[x] = table[in[x]];
} }
@ -42,68 +40,67 @@ im_point_8_8(Imaging imOut, Imaging imIn, im_point_context* context)
} }
static void static void
im_point_2x8_2x8(Imaging imOut, Imaging imIn, im_point_context* context) im_point_2x8_2x8(Imaging imOut, Imaging imIn, im_point_context *context) {
{
int x, y; int x, y;
/* 2x8-bit source, 2x8-bit destination */ /* 2x8-bit source, 2x8-bit destination */
UINT8* table = (UINT8*) context->table; UINT8 *table = (UINT8 *)context->table;
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
UINT8* in = (UINT8*) imIn->image[y]; UINT8 *in = (UINT8 *)imIn->image[y];
UINT8* out = (UINT8*) imOut->image[y]; UINT8 *out = (UINT8 *)imOut->image[y];
for (x = 0; x < imIn->xsize; x++) { for (x = 0; x < imIn->xsize; x++) {
out[0] = table[in[0]]; out[0] = table[in[0]];
out[3] = table[in[3]+256]; out[3] = table[in[3] + 256];
in += 4; out += 4; in += 4;
out += 4;
} }
} }
} }
static void static void
im_point_3x8_3x8(Imaging imOut, Imaging imIn, im_point_context* context) im_point_3x8_3x8(Imaging imOut, Imaging imIn, im_point_context *context) {
{
int x, y; int x, y;
/* 3x8-bit source, 3x8-bit destination */ /* 3x8-bit source, 3x8-bit destination */
UINT8* table = (UINT8*) context->table; UINT8 *table = (UINT8 *)context->table;
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
UINT8* in = (UINT8*) imIn->image[y]; UINT8 *in = (UINT8 *)imIn->image[y];
UINT8* out = (UINT8*) imOut->image[y]; UINT8 *out = (UINT8 *)imOut->image[y];
for (x = 0; x < imIn->xsize; x++) { for (x = 0; x < imIn->xsize; x++) {
out[0] = table[in[0]]; out[0] = table[in[0]];
out[1] = table[in[1]+256]; out[1] = table[in[1] + 256];
out[2] = table[in[2]+512]; out[2] = table[in[2] + 512];
in += 4; out += 4; in += 4;
out += 4;
} }
} }
} }
static void static void
im_point_4x8_4x8(Imaging imOut, Imaging imIn, im_point_context* context) im_point_4x8_4x8(Imaging imOut, Imaging imIn, im_point_context *context) {
{
int x, y; int x, y;
/* 4x8-bit source, 4x8-bit destination */ /* 4x8-bit source, 4x8-bit destination */
UINT8* table = (UINT8*) context->table; UINT8 *table = (UINT8 *)context->table;
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
UINT8* in = (UINT8*) imIn->image[y]; UINT8 *in = (UINT8 *)imIn->image[y];
UINT8* out = (UINT8*) imOut->image[y]; UINT8 *out = (UINT8 *)imOut->image[y];
for (x = 0; x < imIn->xsize; x++) { for (x = 0; x < imIn->xsize; x++) {
out[0] = table[in[0]]; out[0] = table[in[0]];
out[1] = table[in[1]+256]; out[1] = table[in[1] + 256];
out[2] = table[in[2]+512]; out[2] = table[in[2] + 512];
out[3] = table[in[3]+768]; out[3] = table[in[3] + 768];
in += 4; out += 4; in += 4;
out += 4;
} }
} }
} }
static void static void
im_point_8_32(Imaging imOut, Imaging imIn, im_point_context* context) im_point_8_32(Imaging imOut, Imaging imIn, im_point_context *context) {
{
int x, y; int x, y;
/* 8-bit source, 32-bit destination */ /* 8-bit source, 32-bit destination */
char* table = (char*) context->table; char *table = (char *)context->table;
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
UINT8* in = imIn->image8[y]; UINT8 *in = imIn->image8[y];
INT32* out = imOut->image32[y]; INT32 *out = imOut->image32[y];
for (x = 0; x < imIn->xsize; x++) { for (x = 0; x < imIn->xsize; x++) {
memcpy(out + x, table + in[x] * sizeof(INT32), sizeof(INT32)); memcpy(out + x, table + in[x] * sizeof(INT32), sizeof(INT32));
} }
@ -111,14 +108,13 @@ im_point_8_32(Imaging imOut, Imaging imIn, im_point_context* context)
} }
static void static void
im_point_32_8(Imaging imOut, Imaging imIn, im_point_context* context) im_point_32_8(Imaging imOut, Imaging imIn, im_point_context *context) {
{
int x, y; int x, y;
/* 32-bit source, 8-bit destination */ /* 32-bit source, 8-bit destination */
UINT8* table = (UINT8*) context->table; UINT8 *table = (UINT8 *)context->table;
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
INT32* in = imIn->image32[y]; INT32 *in = imIn->image32[y];
UINT8* out = imOut->image8[y]; UINT8 *out = imOut->image8[y];
for (x = 0; x < imIn->xsize; x++) { for (x = 0; x < imIn->xsize; x++) {
int v = in[x]; int v = in[x];
if (v < 0) { if (v < 0) {
@ -132,17 +128,16 @@ im_point_32_8(Imaging imOut, Imaging imIn, im_point_context* context)
} }
Imaging Imaging
ImagingPoint(Imaging imIn, const char* mode, const void* table) ImagingPoint(Imaging imIn, const char *mode, const void *table) {
{
/* lookup table transform */ /* lookup table transform */
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
Imaging imOut; Imaging imOut;
im_point_context context; im_point_context context;
void (*point)(Imaging imIn, Imaging imOut, im_point_context* context); void (*point)(Imaging imIn, Imaging imOut, im_point_context * context);
if (!imIn) { if (!imIn) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
if (!mode) { if (!mode) {
@ -166,22 +161,22 @@ ImagingPoint(Imaging imIn, const char* mode, const void* table)
if (imIn->type == IMAGING_TYPE_UINT8) { if (imIn->type == IMAGING_TYPE_UINT8) {
if (imIn->bands == imOut->bands && imIn->type == imOut->type) { if (imIn->bands == imOut->bands && imIn->type == imOut->type) {
switch (imIn->bands) { switch (imIn->bands) {
case 1: case 1:
point = im_point_8_8; point = im_point_8_8;
break; break;
case 2: case 2:
point = im_point_2x8_2x8; point = im_point_2x8_2x8;
break; break;
case 3: case 3:
point = im_point_3x8_3x8; point = im_point_3x8_3x8;
break; break;
case 4: case 4:
point = im_point_4x8_4x8; point = im_point_4x8_4x8;
break; break;
default: default:
/* this cannot really happen */ /* this cannot really happen */
point = im_point_8_8; point = im_point_8_8;
break; break;
} }
} else { } else {
point = im_point_8_32; point = im_point_8_32;
@ -201,26 +196,22 @@ ImagingPoint(Imaging imIn, const char* mode, const void* table)
return imOut; return imOut;
mode_mismatch: mode_mismatch:
return (Imaging) ImagingError_ValueError( return (Imaging)ImagingError_ValueError(
"point operation not supported for this mode" "point operation not supported for this mode");
);
} }
Imaging Imaging
ImagingPointTransform(Imaging imIn, double scale, double offset) ImagingPointTransform(Imaging imIn, double scale, double offset) {
{
/* scale/offset transform */ /* scale/offset transform */
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
Imaging imOut; Imaging imOut;
int x, y; int x, y;
if (!imIn || (strcmp(imIn->mode, "I") != 0 && if (!imIn || (strcmp(imIn->mode, "I") != 0 && strcmp(imIn->mode, "I;16") != 0 &&
strcmp(imIn->mode, "I;16") != 0 &&
strcmp(imIn->mode, "F") != 0)) { strcmp(imIn->mode, "F") != 0)) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize); imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize);
@ -229,50 +220,50 @@ ImagingPointTransform(Imaging imIn, double scale, double offset)
} }
switch (imIn->type) { switch (imIn->type) {
case IMAGING_TYPE_INT32: case IMAGING_TYPE_INT32:
ImagingSectionEnter(&cookie);
for (y = 0; y < imIn->ysize; y++) {
INT32* in = imIn->image32[y];
INT32* out = imOut->image32[y];
/* FIXME: add clipping? */
for (x = 0; x < imIn->xsize; x++) {
out[x] = in[x] * scale + offset;
}
}
ImagingSectionLeave(&cookie);
break;
case IMAGING_TYPE_FLOAT32:
ImagingSectionEnter(&cookie);
for (y = 0; y < imIn->ysize; y++) {
FLOAT32* in = (FLOAT32*) imIn->image32[y];
FLOAT32* out = (FLOAT32*) imOut->image32[y];
for (x = 0; x < imIn->xsize; x++) {
out[x] = in[x] * scale + offset;
}
}
ImagingSectionLeave(&cookie);
break;
case IMAGING_TYPE_SPECIAL:
if (strcmp(imIn->mode,"I;16") == 0) {
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
char* in = (char*)imIn->image[y]; INT32 *in = imIn->image32[y];
char* out = (char*)imOut->image[y]; INT32 *out = imOut->image32[y];
/* FIXME: add clipping? */ /* FIXME: add clipping? */
for (x = 0; x < imIn->xsize; x++) { for (x = 0; x < imIn->xsize; x++) {
UINT16 v; out[x] = in[x] * scale + offset;
memcpy(&v, in + x * sizeof(v), sizeof(v));
v = v * scale + offset;
memcpy(out + x * sizeof(UINT16), &v, sizeof(v));
} }
} }
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
break; break;
} case IMAGING_TYPE_FLOAT32:
/* FALL THROUGH */ ImagingSectionEnter(&cookie);
default: for (y = 0; y < imIn->ysize; y++) {
ImagingDelete(imOut); FLOAT32 *in = (FLOAT32 *)imIn->image32[y];
return (Imaging) ImagingError_ValueError("internal error"); FLOAT32 *out = (FLOAT32 *)imOut->image32[y];
for (x = 0; x < imIn->xsize; x++) {
out[x] = in[x] * scale + offset;
}
}
ImagingSectionLeave(&cookie);
break;
case IMAGING_TYPE_SPECIAL:
if (strcmp(imIn->mode, "I;16") == 0) {
ImagingSectionEnter(&cookie);
for (y = 0; y < imIn->ysize; y++) {
char *in = (char *)imIn->image[y];
char *out = (char *)imOut->image[y];
/* FIXME: add clipping? */
for (x = 0; x < imIn->xsize; x++) {
UINT16 v;
memcpy(&v, in + x * sizeof(v), sizeof(v));
v = v * scale + offset;
memcpy(out + x * sizeof(UINT16), &v, sizeof(v));
}
}
ImagingSectionLeave(&cookie);
break;
}
/* FALL THROUGH */
default:
ImagingDelete(imOut);
return (Imaging)ImagingError_ValueError("internal error");
} }
return imOut; return imOut;

File diff suppressed because it is too large Load Diff

View File

@ -24,290 +24,313 @@
#include "QuantHash.h" #include "QuantHash.h"
typedef struct _HashNode { typedef struct _HashNode {
struct _HashNode *next; struct _HashNode *next;
HashKey_t key; HashKey_t key;
HashVal_t value; HashVal_t value;
} HashNode; } HashNode;
struct _HashTable { struct _HashTable {
HashNode **table; HashNode **table;
uint32_t length; uint32_t length;
uint32_t count; uint32_t count;
HashFunc hashFunc; HashFunc hashFunc;
HashCmpFunc cmpFunc; HashCmpFunc cmpFunc;
void *userData; void *userData;
}; };
#define MIN_LENGTH 11 #define MIN_LENGTH 11
#define RESIZE_FACTOR 3 #define RESIZE_FACTOR 3
static int _hashtable_insert_node(HashTable *,HashNode *,int,int,CollisionFunc); static int
_hashtable_insert_node(HashTable *, HashNode *, int, int, CollisionFunc);
HashTable *hashtable_new(HashFunc hf,HashCmpFunc cf) { HashTable *
HashTable *h; hashtable_new(HashFunc hf, HashCmpFunc cf) {
h=malloc(sizeof(HashTable)); HashTable *h;
if (!h) { return NULL; } h = malloc(sizeof(HashTable));
h->hashFunc=hf; if (!h) {
h->cmpFunc=cf; return NULL;
h->length=MIN_LENGTH; }
h->count=0; h->hashFunc = hf;
h->userData=NULL; h->cmpFunc = cf;
h->table=malloc(sizeof(HashNode *)*h->length); h->length = MIN_LENGTH;
if (!h->table) { free(h); return NULL; } h->count = 0;
memset (h->table,0,sizeof(HashNode *)*h->length); h->userData = NULL;
return h; h->table = malloc(sizeof(HashNode *) * h->length);
if (!h->table) {
free(h);
return NULL;
}
memset(h->table, 0, sizeof(HashNode *) * h->length);
return h;
} }
static uint32_t _findPrime(uint32_t start,int dir) { static uint32_t
static int unit[]={0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0}; _findPrime(uint32_t start, int dir) {
uint32_t t; static int unit[] = {0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0};
while (start>1) { uint32_t t;
if (!unit[start&0x0f]) { while (start > 1) {
start+=dir; if (!unit[start & 0x0f]) {
continue; start += dir;
} continue;
for (t=2;t<sqrt((double)start);t++) { }
if (!start%t) { for (t = 2; t < sqrt((double)start); t++) {
break; if (!start % t) {
} break;
} }
if (t>=sqrt((double)start)) { }
break; if (t >= sqrt((double)start)) {
} break;
start+=dir; }
} start += dir;
return start; }
return start;
} }
static void _hashtable_rehash(HashTable *h,CollisionFunc cf,uint32_t newSize) { static void
HashNode **oldTable=h->table; _hashtable_rehash(HashTable *h, CollisionFunc cf, uint32_t newSize) {
uint32_t i; HashNode **oldTable = h->table;
HashNode *n,*nn; uint32_t i;
uint32_t oldSize; HashNode *n, *nn;
oldSize=h->length; uint32_t oldSize;
h->table=malloc(sizeof(HashNode *)*newSize); oldSize = h->length;
if (!h->table) { h->table = malloc(sizeof(HashNode *) * newSize);
h->table=oldTable; if (!h->table) {
return; h->table = oldTable;
} return;
h->length=newSize; }
h->count=0; h->length = newSize;
memset (h->table,0,sizeof(HashNode *)*h->length); h->count = 0;
for (i=0;i<oldSize;i++) { memset(h->table, 0, sizeof(HashNode *) * h->length);
for (n=oldTable[i];n;n=nn) { for (i = 0; i < oldSize; i++) {
nn=n->next; for (n = oldTable[i]; n; n = nn) {
_hashtable_insert_node(h,n,0,0,cf); nn = n->next;
} _hashtable_insert_node(h, n, 0, 0, cf);
} }
free(oldTable); }
free(oldTable);
} }
static void _hashtable_resize(HashTable *h) { static void
uint32_t newSize; _hashtable_resize(HashTable *h) {
uint32_t oldSize; uint32_t newSize;
oldSize=h->length; uint32_t oldSize;
newSize=oldSize; oldSize = h->length;
if (h->count*RESIZE_FACTOR<h->length) { newSize = oldSize;
newSize=_findPrime(h->length/2-1,-1); if (h->count * RESIZE_FACTOR < h->length) {
} else if (h->length*RESIZE_FACTOR<h->count) { newSize = _findPrime(h->length / 2 - 1, -1);
newSize=_findPrime(h->length*2+1,+1); } else if (h->length * RESIZE_FACTOR < h->count) {
} newSize = _findPrime(h->length * 2 + 1, +1);
if (newSize<MIN_LENGTH) { newSize=oldSize; } }
if (newSize!=oldSize) { if (newSize < MIN_LENGTH) {
_hashtable_rehash(h,NULL,newSize); newSize = oldSize;
} }
if (newSize != oldSize) {
_hashtable_rehash(h, NULL, newSize);
}
} }
static int _hashtable_insert_node(HashTable *h,HashNode *node,int resize,int update,CollisionFunc cf) { static int
uint32_t hash=h->hashFunc(h,node->key)%h->length; _hashtable_insert_node(
HashNode **n,*nv; HashTable *h, HashNode *node, int resize, int update, CollisionFunc cf) {
int i; uint32_t hash = h->hashFunc(h, node->key) % h->length;
HashNode **n, *nv;
int i;
for (n=&(h->table[hash]);*n;n=&((*n)->next)) { for (n = &(h->table[hash]); *n; n = &((*n)->next)) {
nv=*n; nv = *n;
i=h->cmpFunc(h,nv->key,node->key); i = h->cmpFunc(h, nv->key, node->key);
if (!i) { if (!i) {
if (cf) { if (cf) {
nv->key=node->key; nv->key = node->key;
cf(h,&(nv->key),&(nv->value),node->key,node->value); cf(h, &(nv->key), &(nv->value), node->key, node->value);
free(node); free(node);
return 1;
} else {
nv->key = node->key;
nv->value = node->value;
free(node);
return 1;
}
} else if (i > 0) {
break;
}
}
if (!update) {
node->next = *n;
*n = node;
h->count++;
if (resize) {
_hashtable_resize(h);
}
return 1;
} else {
return 0;
}
}
static int
_hashtable_insert(HashTable *h, HashKey_t key, HashVal_t val, int resize, int update) {
HashNode **n, *nv;
HashNode *t;
int i;
uint32_t hash = h->hashFunc(h, key) % h->length;
for (n = &(h->table[hash]); *n; n = &((*n)->next)) {
nv = *n;
i = h->cmpFunc(h, nv->key, key);
if (!i) {
nv->value = val;
return 1; return 1;
} else { } else if (i > 0) {
nv->key=node->key; break;
nv->value=node->value; }
free(node); }
return 1; if (!update) {
} t = malloc(sizeof(HashNode));
} else if (i>0) { if (!t) {
break;
}
}
if (!update) {
node->next=*n;
*n=node;
h->count++;
if (resize) {
_hashtable_resize(h);
}
return 1;
} else {
return 0;
}
}
static int _hashtable_insert(HashTable *h,HashKey_t key,HashVal_t val,int resize,int update) {
HashNode **n,*nv;
HashNode *t;
int i;
uint32_t hash=h->hashFunc(h,key)%h->length;
for (n=&(h->table[hash]);*n;n=&((*n)->next)) {
nv=*n;
i=h->cmpFunc(h,nv->key,key);
if (!i) {
nv->value=val;
return 1;
} else if (i>0) {
break;
}
}
if (!update) {
t=malloc(sizeof(HashNode));
if (!t) {
return 0;
}
t->next=*n;
*n=t;
t->key=key;
t->value=val;
h->count++;
if (resize) {
_hashtable_resize(h);
}
return 1;
} else {
return 0;
}
}
int hashtable_insert_or_update_computed(HashTable *h,
HashKey_t key,
ComputeFunc newFunc,
ComputeFunc existsFunc) {
HashNode **n,*nv;
HashNode *t;
int i;
uint32_t hash=h->hashFunc(h,key)%h->length;
for (n=&(h->table[hash]);*n;n=&((*n)->next)) {
nv=*n;
i=h->cmpFunc(h,nv->key,key);
if (!i) {
if (existsFunc) {
existsFunc(h,nv->key,&(nv->value));
} else {
return 0; return 0;
} }
return 1; t->next = *n;
} else if (i>0) { *n = t;
break; t->key = key;
} t->value = val;
} h->count++;
t=malloc(sizeof(HashNode)); if (resize) {
if (!t) { _hashtable_resize(h);
return 0; }
} return 1;
t->key=key; } else {
t->next=*n; return 0;
*n=t; }
if (newFunc) {
newFunc(h,t->key,&(t->value));
} else {
free(t);
return 0;
}
h->count++;
_hashtable_resize(h);
return 1;
} }
int hashtable_insert(HashTable *h,HashKey_t key,HashVal_t val) { int
return _hashtable_insert(h,key,val,1,0); hashtable_insert_or_update_computed(
HashTable *h, HashKey_t key, ComputeFunc newFunc, ComputeFunc existsFunc) {
HashNode **n, *nv;
HashNode *t;
int i;
uint32_t hash = h->hashFunc(h, key) % h->length;
for (n = &(h->table[hash]); *n; n = &((*n)->next)) {
nv = *n;
i = h->cmpFunc(h, nv->key, key);
if (!i) {
if (existsFunc) {
existsFunc(h, nv->key, &(nv->value));
} else {
return 0;
}
return 1;
} else if (i > 0) {
break;
}
}
t = malloc(sizeof(HashNode));
if (!t) {
return 0;
}
t->key = key;
t->next = *n;
*n = t;
if (newFunc) {
newFunc(h, t->key, &(t->value));
} else {
free(t);
return 0;
}
h->count++;
_hashtable_resize(h);
return 1;
} }
void hashtable_foreach_update(HashTable *h,IteratorUpdateFunc i,void *u) { int
HashNode *n; hashtable_insert(HashTable *h, HashKey_t key, HashVal_t val) {
uint32_t x; return _hashtable_insert(h, key, val, 1, 0);
if (h->table) {
for (x=0;x<h->length;x++) {
for (n=h->table[x];n;n=n->next) {
i(h,n->key,&(n->value),u);
}
}
}
} }
void hashtable_foreach(HashTable *h,IteratorFunc i,void *u) { void
HashNode *n; hashtable_foreach_update(HashTable *h, IteratorUpdateFunc i, void *u) {
uint32_t x; HashNode *n;
uint32_t x;
if (h->table) { if (h->table) {
for (x=0;x<h->length;x++) { for (x = 0; x < h->length; x++) {
for (n=h->table[x];n;n=n->next) { for (n = h->table[x]; n; n = n->next) {
i(h,n->key,n->value,u); i(h, n->key, &(n->value), u);
} }
} }
} }
} }
void hashtable_free(HashTable *h) { void
HashNode *n,*nn; hashtable_foreach(HashTable *h, IteratorFunc i, void *u) {
uint32_t i; HashNode *n;
uint32_t x;
if (h->table) { if (h->table) {
for (i=0;i<h->length;i++) { for (x = 0; x < h->length; x++) {
for (n=h->table[i];n;n=nn) { for (n = h->table[x]; n; n = n->next) {
nn=n->next; i(h, n->key, n->value, u);
free(n); }
} }
} }
free(h->table);
}
free(h);
} }
void hashtable_rehash_compute(HashTable *h,CollisionFunc cf) { void
_hashtable_rehash(h,cf,h->length); hashtable_free(HashTable *h) {
HashNode *n, *nn;
uint32_t i;
if (h->table) {
for (i = 0; i < h->length; i++) {
for (n = h->table[i]; n; n = nn) {
nn = n->next;
free(n);
}
}
free(h->table);
}
free(h);
} }
int hashtable_lookup(const HashTable *h,const HashKey_t key,HashVal_t *valp) { void
uint32_t hash=h->hashFunc(h,key)%h->length; hashtable_rehash_compute(HashTable *h, CollisionFunc cf) {
HashNode *n; _hashtable_rehash(h, cf, h->length);
int i;
for (n=h->table[hash];n;n=n->next) {
i=h->cmpFunc(h,n->key,key);
if (!i) {
*valp=n->value;
return 1;
} else if (i>0) {
break;
}
}
return 0;
} }
uint32_t hashtable_get_count(const HashTable *h) { int
return h->count; hashtable_lookup(const HashTable *h, const HashKey_t key, HashVal_t *valp) {
uint32_t hash = h->hashFunc(h, key) % h->length;
HashNode *n;
int i;
for (n = h->table[hash]; n; n = n->next) {
i = h->cmpFunc(h, n->key, key);
if (!i) {
*valp = n->value;
return 1;
} else if (i > 0) {
break;
}
}
return 0;
} }
void *hashtable_get_user_data(const HashTable *h) { uint32_t
return h->userData; hashtable_get_count(const HashTable *h) {
return h->count;
} }
void *hashtable_set_user_data(HashTable *h,void *data) { void *
void *r=h->userData; hashtable_get_user_data(const HashTable *h) {
h->userData=data; return h->userData;
return r; }
void *
hashtable_set_user_data(HashTable *h, void *data) {
void *r = h->userData;
h->userData = data;
return r;
} }

View File

@ -18,23 +18,38 @@ typedef struct _HashTable HashTable;
typedef Pixel HashKey_t; typedef Pixel HashKey_t;
typedef uint32_t HashVal_t; typedef uint32_t HashVal_t;
typedef uint32_t (*HashFunc)(const HashTable *,const HashKey_t); typedef uint32_t (*HashFunc)(const HashTable *, const HashKey_t);
typedef int (*HashCmpFunc)(const HashTable *,const HashKey_t,const HashKey_t); typedef int (*HashCmpFunc)(const HashTable *, const HashKey_t, const HashKey_t);
typedef void (*IteratorFunc)(const HashTable *,const HashKey_t,const HashVal_t,void *); typedef void (*IteratorFunc)(
typedef void (*IteratorUpdateFunc)(const HashTable *,const HashKey_t,HashVal_t *,void *); const HashTable *, const HashKey_t, const HashVal_t, void *);
typedef void (*ComputeFunc)(const HashTable *,const HashKey_t,HashVal_t *); typedef void (*IteratorUpdateFunc)(
typedef void (*CollisionFunc)(const HashTable *,HashKey_t *,HashVal_t *,HashKey_t,HashVal_t); const HashTable *, const HashKey_t, HashVal_t *, void *);
typedef void (*ComputeFunc)(const HashTable *, const HashKey_t, HashVal_t *);
typedef void (*CollisionFunc)(
const HashTable *, HashKey_t *, HashVal_t *, HashKey_t, HashVal_t);
HashTable * hashtable_new(HashFunc hf,HashCmpFunc cf); HashTable *
void hashtable_free(HashTable *h); hashtable_new(HashFunc hf, HashCmpFunc cf);
void hashtable_foreach(HashTable *h,IteratorFunc i,void *u); void
void hashtable_foreach_update(HashTable *h,IteratorUpdateFunc i,void *u); hashtable_free(HashTable *h);
int hashtable_insert(HashTable *h,HashKey_t key,HashVal_t val); void
int hashtable_lookup(const HashTable *h,const HashKey_t key,HashVal_t *valp); hashtable_foreach(HashTable *h, IteratorFunc i, void *u);
int hashtable_insert_or_update_computed(HashTable *h,HashKey_t key,ComputeFunc newFunc,ComputeFunc existsFunc); void
void *hashtable_set_user_data(HashTable *h,void *data); hashtable_foreach_update(HashTable *h, IteratorUpdateFunc i, void *u);
void *hashtable_get_user_data(const HashTable *h); int
uint32_t hashtable_get_count(const HashTable *h); hashtable_insert(HashTable *h, HashKey_t key, HashVal_t val);
void hashtable_rehash_compute(HashTable *h,CollisionFunc cf); int
hashtable_lookup(const HashTable *h, const HashKey_t key, HashVal_t *valp);
int
hashtable_insert_or_update_computed(
HashTable *h, HashKey_t key, ComputeFunc newFunc, ComputeFunc existsFunc);
void *
hashtable_set_user_data(HashTable *h, void *data);
void *
hashtable_get_user_data(const HashTable *h);
uint32_t
hashtable_get_count(const HashTable *h);
void
hashtable_rehash_compute(HashTable *h, CollisionFunc cf);
#endif // __QUANTHASH_H__ #endif // __QUANTHASH_H__

View File

@ -25,10 +25,10 @@
#include "QuantHeap.h" #include "QuantHeap.h"
struct _Heap { struct _Heap {
void **heap; void **heap;
unsigned int heapsize; unsigned int heapsize;
unsigned int heapcount; unsigned int heapcount;
HeapCmpFunc cf; HeapCmpFunc cf;
}; };
#define INITIAL_SIZE 256 #define INITIAL_SIZE 256
@ -36,127 +36,141 @@ struct _Heap {
// #define DEBUG // #define DEBUG
#ifdef DEBUG #ifdef DEBUG
static int _heap_test(Heap *); static int
_heap_test(Heap *);
#endif #endif
void ImagingQuantHeapFree(Heap *h) { void
free(h->heap); ImagingQuantHeapFree(Heap *h) {
free(h); free(h->heap);
free(h);
} }
static int _heap_grow(Heap *h,unsigned int newsize) { static int
void *newheap; _heap_grow(Heap *h, unsigned int newsize) {
if (!newsize) { void *newheap;
newsize=h->heapsize<<1; if (!newsize) {
} newsize = h->heapsize << 1;
if (newsize<h->heapsize) { }
return 0; if (newsize < h->heapsize) {
} return 0;
if (newsize > INT_MAX / sizeof(void *)){ }
return 0; if (newsize > INT_MAX / sizeof(void *)) {
} return 0;
/* malloc check ok, using calloc for overflow, also checking }
above due to memcpy below*/ /* malloc check ok, using calloc for overflow, also checking
newheap=calloc(newsize, sizeof(void *)); above due to memcpy below*/
if (!newheap) { newheap = calloc(newsize, sizeof(void *));
return 0; if (!newheap) {
} return 0;
memcpy(newheap,h->heap,sizeof(void *)*h->heapsize); }
free(h->heap); memcpy(newheap, h->heap, sizeof(void *) * h->heapsize);
h->heap=newheap; free(h->heap);
h->heapsize=newsize; h->heap = newheap;
return 1; h->heapsize = newsize;
return 1;
} }
#ifdef DEBUG #ifdef DEBUG
static int _heap_test(Heap *h) { static int
unsigned int k; _heap_test(Heap *h) {
for (k=1;k*2<=h->heapcount;k++) { unsigned int k;
if (h->cf(h,h->heap[k],h->heap[k*2])<0) { for (k = 1; k * 2 <= h->heapcount; k++) {
printf ("heap is bad\n"); if (h->cf(h, h->heap[k], h->heap[k * 2]) < 0) {
return 0; printf("heap is bad\n");
} return 0;
if (k*2+1<=h->heapcount && h->cf(h,h->heap[k],h->heap[k*2+1])<0) { }
printf ("heap is bad\n"); if (k * 2 + 1 <= h->heapcount && h->cf(h, h->heap[k], h->heap[k * 2 + 1]) < 0) {
return 0; printf("heap is bad\n");
} return 0;
} }
return 1; }
return 1;
} }
#endif #endif
int ImagingQuantHeapRemove(Heap* h,void **r) { int
unsigned int k,l; ImagingQuantHeapRemove(Heap *h, void **r) {
void *v; unsigned int k, l;
void *v;
if (!h->heapcount) { if (!h->heapcount) {
return 0; return 0;
} }
*r=h->heap[1]; *r = h->heap[1];
v=h->heap[h->heapcount--]; v = h->heap[h->heapcount--];
for (k=1;k*2<=h->heapcount;k=l) { for (k = 1; k * 2 <= h->heapcount; k = l) {
l=k*2; l = k * 2;
if (l<h->heapcount) { if (l < h->heapcount) {
if (h->cf(h,h->heap[l],h->heap[l+1])<0) { if (h->cf(h, h->heap[l], h->heap[l + 1]) < 0) {
l++; l++;
} }
} }
if (h->cf(h,v,h->heap[l])>0) { if (h->cf(h, v, h->heap[l]) > 0) {
break; break;
} }
h->heap[k]=h->heap[l]; h->heap[k] = h->heap[l];
} }
h->heap[k]=v; h->heap[k] = v;
#ifdef DEBUG #ifdef DEBUG
if (!_heap_test(h)) { printf ("oops - heap_remove messed up the heap\n"); exit(1); } if (!_heap_test(h)) {
printf("oops - heap_remove messed up the heap\n");
exit(1);
}
#endif #endif
return 1; return 1;
} }
int ImagingQuantHeapAdd(Heap *h,void *val) { int
int k; ImagingQuantHeapAdd(Heap *h, void *val) {
if (h->heapcount==h->heapsize-1) { int k;
_heap_grow(h,0); if (h->heapcount == h->heapsize - 1) {
} _heap_grow(h, 0);
k=++h->heapcount; }
while (k!=1) { k = ++h->heapcount;
if (h->cf(h,val,h->heap[k/2])<=0) { while (k != 1) {
break; if (h->cf(h, val, h->heap[k / 2]) <= 0) {
} break;
h->heap[k]=h->heap[k/2]; }
k>>=1; h->heap[k] = h->heap[k / 2];
} k >>= 1;
h->heap[k]=val; }
h->heap[k] = val;
#ifdef DEBUG #ifdef DEBUG
if (!_heap_test(h)) { printf ("oops - heap_add messed up the heap\n"); exit(1); } if (!_heap_test(h)) {
printf("oops - heap_add messed up the heap\n");
exit(1);
}
#endif #endif
return 1; return 1;
} }
int ImagingQuantHeapTop(Heap *h,void **r) { int
if (!h->heapcount) { ImagingQuantHeapTop(Heap *h, void **r) {
return 0; if (!h->heapcount) {
} return 0;
*r=h->heap[1]; }
return 1; *r = h->heap[1];
return 1;
} }
Heap *ImagingQuantHeapNew(HeapCmpFunc cf) { Heap *
Heap *h; ImagingQuantHeapNew(HeapCmpFunc cf) {
Heap *h;
/* malloc check ok, small constant allocation */ /* malloc check ok, small constant allocation */
h=malloc(sizeof(Heap)); h = malloc(sizeof(Heap));
if (!h) { if (!h) {
return NULL; return NULL;
} }
h->heapsize=INITIAL_SIZE; h->heapsize = INITIAL_SIZE;
/* malloc check ok, using calloc for overflow */ /* malloc check ok, using calloc for overflow */
h->heap=calloc(h->heapsize, sizeof(void *)); h->heap = calloc(h->heapsize, sizeof(void *));
if (!h->heap) { if (!h->heap) {
free(h); free(h);
return NULL; return NULL;
} }
h->heapcount=0; h->heapcount = 0;
h->cf=cf; h->cf = cf;
return h; return h;
} }

View File

@ -16,12 +16,16 @@
typedef struct _Heap Heap; typedef struct _Heap Heap;
typedef int (*HeapCmpFunc)(const Heap *,const void *,const void *); typedef int (*HeapCmpFunc)(const Heap *, const void *, const void *);
void ImagingQuantHeapFree(Heap *); void
int ImagingQuantHeapRemove(Heap *,void **); ImagingQuantHeapFree(Heap *);
int ImagingQuantHeapAdd(Heap *,void *); int
int ImagingQuantHeapTop(Heap *,void **); ImagingQuantHeapRemove(Heap *, void **);
int
ImagingQuantHeapAdd(Heap *, void *);
int
ImagingQuantHeapTop(Heap *, void **);
Heap *ImagingQuantHeapNew(HeapCmpFunc); Heap *ImagingQuantHeapNew(HeapCmpFunc);
#endif // __QUANTHEAP_H__ #endif // __QUANTHEAP_H__

View File

@ -31,490 +31,508 @@
#include "ImagingUtils.h" #include "ImagingUtils.h"
#include "QuantOctree.h" #include "QuantOctree.h"
typedef struct _ColorBucket{ typedef struct _ColorBucket {
/* contains palette index when used for look up cube */ /* contains palette index when used for look up cube */
uint32_t count; uint32_t count;
uint64_t r; uint64_t r;
uint64_t g; uint64_t g;
uint64_t b; uint64_t b;
uint64_t a; uint64_t a;
} *ColorBucket; } * ColorBucket;
typedef struct _ColorCube{ typedef struct _ColorCube {
unsigned int rBits, gBits, bBits, aBits; unsigned int rBits, gBits, bBits, aBits;
unsigned int rWidth, gWidth, bWidth, aWidth; unsigned int rWidth, gWidth, bWidth, aWidth;
unsigned int rOffset, gOffset, bOffset, aOffset; unsigned int rOffset, gOffset, bOffset, aOffset;
unsigned long size; unsigned long size;
ColorBucket buckets; ColorBucket buckets;
} *ColorCube; } * ColorCube;
#define MAX(a, b) (a)>(b) ? (a) : (b) #define MAX(a, b) (a) > (b) ? (a) : (b)
static ColorCube static ColorCube
new_color_cube(int r, int g, int b, int a) { new_color_cube(int r, int g, int b, int a) {
ColorCube cube; ColorCube cube;
/* malloc check ok, small constant allocation */ /* malloc check ok, small constant allocation */
cube = malloc(sizeof(struct _ColorCube)); cube = malloc(sizeof(struct _ColorCube));
if (!cube) { if (!cube) {
return NULL; return NULL;
} }
cube->rBits = MAX(r, 0); cube->rBits = MAX(r, 0);
cube->gBits = MAX(g, 0); cube->gBits = MAX(g, 0);
cube->bBits = MAX(b, 0); cube->bBits = MAX(b, 0);
cube->aBits = MAX(a, 0); cube->aBits = MAX(a, 0);
/* overflow check for size multiplication below */ /* overflow check for size multiplication below */
if (cube->rBits + cube->gBits + cube->bBits + cube->aBits > 31) { if (cube->rBits + cube->gBits + cube->bBits + cube->aBits > 31) {
free(cube); free(cube);
return NULL; return NULL;
} }
/* the width of the cube for each dimension */ /* the width of the cube for each dimension */
cube->rWidth = 1<<cube->rBits; cube->rWidth = 1 << cube->rBits;
cube->gWidth = 1<<cube->gBits; cube->gWidth = 1 << cube->gBits;
cube->bWidth = 1<<cube->bBits; cube->bWidth = 1 << cube->bBits;
cube->aWidth = 1<<cube->aBits; cube->aWidth = 1 << cube->aBits;
/* the offsets of each color */ /* the offsets of each color */
cube->rOffset = cube->gBits + cube->bBits + cube->aBits; cube->rOffset = cube->gBits + cube->bBits + cube->aBits;
cube->gOffset = cube->bBits + cube->aBits; cube->gOffset = cube->bBits + cube->aBits;
cube->bOffset = cube->aBits; cube->bOffset = cube->aBits;
cube->aOffset = 0; cube->aOffset = 0;
/* the number of color buckets */ /* the number of color buckets */
cube->size = cube->rWidth * cube->gWidth * cube->bWidth * cube->aWidth; cube->size = cube->rWidth * cube->gWidth * cube->bWidth * cube->aWidth;
/* malloc check ok, overflow checked above */ /* malloc check ok, overflow checked above */
cube->buckets = calloc(cube->size, sizeof(struct _ColorBucket)); cube->buckets = calloc(cube->size, sizeof(struct _ColorBucket));
if (!cube->buckets) { if (!cube->buckets) {
free(cube); free(cube);
return NULL; return NULL;
} }
return cube; return cube;
} }
static void static void
free_color_cube(ColorCube cube) { free_color_cube(ColorCube cube) {
if (cube != NULL) { if (cube != NULL) {
free(cube->buckets); free(cube->buckets);
free(cube); free(cube);
} }
} }
static long static long
color_bucket_offset_pos(const ColorCube cube, color_bucket_offset_pos(
unsigned int r, unsigned int g, unsigned int b, unsigned int a) const ColorCube cube,
{ unsigned int r,
return r<<cube->rOffset | g<<cube->gOffset | b<<cube->bOffset | a<<cube->aOffset; unsigned int g,
unsigned int b,
unsigned int a) {
return r << cube->rOffset | g << cube->gOffset | b << cube->bOffset |
a << cube->aOffset;
} }
static long static long
color_bucket_offset(const ColorCube cube, const Pixel *p) { color_bucket_offset(const ColorCube cube, const Pixel *p) {
unsigned int r = p->c.r>>(8-cube->rBits); unsigned int r = p->c.r >> (8 - cube->rBits);
unsigned int g = p->c.g>>(8-cube->gBits); unsigned int g = p->c.g >> (8 - cube->gBits);
unsigned int b = p->c.b>>(8-cube->bBits); unsigned int b = p->c.b >> (8 - cube->bBits);
unsigned int a = p->c.a>>(8-cube->aBits); unsigned int a = p->c.a >> (8 - cube->aBits);
return color_bucket_offset_pos(cube, r, g, b, a); return color_bucket_offset_pos(cube, r, g, b, a);
} }
static ColorBucket static ColorBucket
color_bucket_from_cube(const ColorCube cube, const Pixel *p) { color_bucket_from_cube(const ColorCube cube, const Pixel *p) {
unsigned int offset = color_bucket_offset(cube, p); unsigned int offset = color_bucket_offset(cube, p);
return &cube->buckets[offset]; return &cube->buckets[offset];
} }
static void static void
add_color_to_color_cube(const ColorCube cube, const Pixel *p) { add_color_to_color_cube(const ColorCube cube, const Pixel *p) {
ColorBucket bucket = color_bucket_from_cube(cube, p); ColorBucket bucket = color_bucket_from_cube(cube, p);
bucket->count += 1; bucket->count += 1;
bucket->r += p->c.r; bucket->r += p->c.r;
bucket->g += p->c.g; bucket->g += p->c.g;
bucket->b += p->c.b; bucket->b += p->c.b;
bucket->a += p->c.a; bucket->a += p->c.a;
} }
static unsigned long static unsigned long
count_used_color_buckets(const ColorCube cube) { count_used_color_buckets(const ColorCube cube) {
unsigned long usedBuckets = 0; unsigned long usedBuckets = 0;
unsigned long i; unsigned long i;
for (i=0; i < cube->size; i++) { for (i = 0; i < cube->size; i++) {
if (cube->buckets[i].count > 0) { if (cube->buckets[i].count > 0) {
usedBuckets += 1; usedBuckets += 1;
} }
} }
return usedBuckets; return usedBuckets;
} }
static void static void
avg_color_from_color_bucket(const ColorBucket bucket, Pixel *dst) { avg_color_from_color_bucket(const ColorBucket bucket, Pixel *dst) {
float count = bucket->count; float count = bucket->count;
if (count != 0) { if (count != 0) {
dst->c.r = CLIP8((int)(bucket->r / count)); dst->c.r = CLIP8((int)(bucket->r / count));
dst->c.g = CLIP8((int)(bucket->g / count)); dst->c.g = CLIP8((int)(bucket->g / count));
dst->c.b = CLIP8((int)(bucket->b / count)); dst->c.b = CLIP8((int)(bucket->b / count));
dst->c.a = CLIP8((int)(bucket->a / count)); dst->c.a = CLIP8((int)(bucket->a / count));
} else { } else {
dst->c.r = 0; dst->c.r = 0;
dst->c.g = 0; dst->c.g = 0;
dst->c.b = 0; dst->c.b = 0;
dst->c.a = 0; dst->c.a = 0;
} }
} }
static int static int
compare_bucket_count(const ColorBucket a, const ColorBucket b) { compare_bucket_count(const ColorBucket a, const ColorBucket b) {
return b->count - a->count; return b->count - a->count;
} }
static ColorBucket static ColorBucket
create_sorted_color_palette(const ColorCube cube) { create_sorted_color_palette(const ColorCube cube) {
ColorBucket buckets; ColorBucket buckets;
if (cube->size > LONG_MAX / sizeof(struct _ColorBucket)) { if (cube->size > LONG_MAX / sizeof(struct _ColorBucket)) {
return NULL; return NULL;
} }
/* malloc check ok, calloc + overflow check above for memcpy */ /* malloc check ok, calloc + overflow check above for memcpy */
buckets = calloc(cube->size, sizeof(struct _ColorBucket)); buckets = calloc(cube->size, sizeof(struct _ColorBucket));
if (!buckets) { if (!buckets) {
return NULL; return NULL;
} }
memcpy(buckets, cube->buckets, sizeof(struct _ColorBucket)*cube->size); memcpy(buckets, cube->buckets, sizeof(struct _ColorBucket) * cube->size);
qsort(buckets, cube->size, sizeof(struct _ColorBucket), qsort(
(int (*)(void const *, void const *))&compare_bucket_count); buckets,
cube->size,
sizeof(struct _ColorBucket),
(int (*)(void const *, void const *)) & compare_bucket_count);
return buckets; return buckets;
} }
void add_bucket_values(ColorBucket src, ColorBucket dst) { void
dst->count += src->count; add_bucket_values(ColorBucket src, ColorBucket dst) {
dst->r += src->r; dst->count += src->count;
dst->g += src->g; dst->r += src->r;
dst->b += src->b; dst->g += src->g;
dst->a += src->a; dst->b += src->b;
dst->a += src->a;
} }
/* expand or shrink a given cube to level */ /* expand or shrink a given cube to level */
static ColorCube copy_color_cube(const ColorCube cube, static ColorCube
unsigned int rBits, unsigned int gBits, unsigned int bBits, unsigned int aBits) copy_color_cube(
{ const ColorCube cube,
unsigned int r, g, b, a; unsigned int rBits,
long src_pos, dst_pos; unsigned int gBits,
unsigned int src_reduce[4] = {0}, dst_reduce[4] = {0}; unsigned int bBits,
unsigned int width[4]; unsigned int aBits) {
ColorCube result; unsigned int r, g, b, a;
long src_pos, dst_pos;
unsigned int src_reduce[4] = {0}, dst_reduce[4] = {0};
unsigned int width[4];
ColorCube result;
result = new_color_cube(rBits, gBits, bBits, aBits); result = new_color_cube(rBits, gBits, bBits, aBits);
if (!result) { if (!result) {
return NULL; return NULL;
} }
if (cube->rBits > rBits) { if (cube->rBits > rBits) {
dst_reduce[0] = cube->rBits - result->rBits; dst_reduce[0] = cube->rBits - result->rBits;
width[0] = cube->rWidth; width[0] = cube->rWidth;
} else { } else {
src_reduce[0] = result->rBits - cube->rBits; src_reduce[0] = result->rBits - cube->rBits;
width[0] = result->rWidth; width[0] = result->rWidth;
} }
if (cube->gBits > gBits) { if (cube->gBits > gBits) {
dst_reduce[1] = cube->gBits - result->gBits; dst_reduce[1] = cube->gBits - result->gBits;
width[1] = cube->gWidth; width[1] = cube->gWidth;
} else { } else {
src_reduce[1] = result->gBits - cube->gBits; src_reduce[1] = result->gBits - cube->gBits;
width[1] = result->gWidth; width[1] = result->gWidth;
} }
if (cube->bBits > bBits) { if (cube->bBits > bBits) {
dst_reduce[2] = cube->bBits - result->bBits; dst_reduce[2] = cube->bBits - result->bBits;
width[2] = cube->bWidth; width[2] = cube->bWidth;
} else { } else {
src_reduce[2] = result->bBits - cube->bBits; src_reduce[2] = result->bBits - cube->bBits;
width[2] = result->bWidth; width[2] = result->bWidth;
} }
if (cube->aBits > aBits) { if (cube->aBits > aBits) {
dst_reduce[3] = cube->aBits - result->aBits; dst_reduce[3] = cube->aBits - result->aBits;
width[3] = cube->aWidth; width[3] = cube->aWidth;
} else { } else {
src_reduce[3] = result->aBits - cube->aBits; src_reduce[3] = result->aBits - cube->aBits;
width[3] = result->aWidth; width[3] = result->aWidth;
} }
for (r=0; r<width[0]; r++) { for (r = 0; r < width[0]; r++) {
for (g=0; g<width[1]; g++) { for (g = 0; g < width[1]; g++) {
for (b=0; b<width[2]; b++) { for (b = 0; b < width[2]; b++) {
for (a=0; a<width[3]; a++) { for (a = 0; a < width[3]; a++) {
src_pos = color_bucket_offset_pos(cube, src_pos = color_bucket_offset_pos(
r>>src_reduce[0], cube,
g>>src_reduce[1], r >> src_reduce[0],
b>>src_reduce[2], g >> src_reduce[1],
a>>src_reduce[3]); b >> src_reduce[2],
dst_pos = color_bucket_offset_pos(result, a >> src_reduce[3]);
r>>dst_reduce[0], dst_pos = color_bucket_offset_pos(
g>>dst_reduce[1], result,
b>>dst_reduce[2], r >> dst_reduce[0],
a>>dst_reduce[3]); g >> dst_reduce[1],
add_bucket_values( b >> dst_reduce[2],
&cube->buckets[src_pos], a >> dst_reduce[3]);
&result->buckets[dst_pos] add_bucket_values(
); &cube->buckets[src_pos], &result->buckets[dst_pos]);
}
} }
} }
} }
} return result;
return result;
} }
void void
subtract_color_buckets(ColorCube cube, ColorBucket buckets, long nBuckets) { subtract_color_buckets(ColorCube cube, ColorBucket buckets, long nBuckets) {
ColorBucket minuend, subtrahend; ColorBucket minuend, subtrahend;
long i; long i;
Pixel p; Pixel p;
for (i=0; i<nBuckets; i++) { for (i = 0; i < nBuckets; i++) {
subtrahend = &buckets[i]; subtrahend = &buckets[i];
// If the subtrahend contains no buckets, there is nothing to subtract. // If the subtrahend contains no buckets, there is nothing to subtract.
if (subtrahend->count == 0) { if (subtrahend->count == 0) {
continue; continue;
} }
avg_color_from_color_bucket(subtrahend, &p); avg_color_from_color_bucket(subtrahend, &p);
minuend = color_bucket_from_cube(cube, &p); minuend = color_bucket_from_cube(cube, &p);
minuend->count -= subtrahend->count; minuend->count -= subtrahend->count;
minuend->r -= subtrahend->r; minuend->r -= subtrahend->r;
minuend->g -= subtrahend->g; minuend->g -= subtrahend->g;
minuend->b -= subtrahend->b; minuend->b -= subtrahend->b;
minuend->a -= subtrahend->a; minuend->a -= subtrahend->a;
} }
} }
static void static void
set_lookup_value(const ColorCube cube, const Pixel *p, long value) { set_lookup_value(const ColorCube cube, const Pixel *p, long value) {
ColorBucket bucket = color_bucket_from_cube(cube, p); ColorBucket bucket = color_bucket_from_cube(cube, p);
bucket->count = value; bucket->count = value;
} }
uint64_t uint64_t
lookup_color(const ColorCube cube, const Pixel *p) { lookup_color(const ColorCube cube, const Pixel *p) {
ColorBucket bucket = color_bucket_from_cube(cube, p); ColorBucket bucket = color_bucket_from_cube(cube, p);
return bucket->count; return bucket->count;
} }
void add_lookup_buckets(ColorCube cube, ColorBucket palette, long nColors, long offset) { void
long i; add_lookup_buckets(ColorCube cube, ColorBucket palette, long nColors, long offset) {
Pixel p; long i;
for (i=offset; i<offset+nColors; i++) { Pixel p;
avg_color_from_color_bucket(&palette[i], &p); for (i = offset; i < offset + nColors; i++) {
set_lookup_value(cube, &p, i); avg_color_from_color_bucket(&palette[i], &p);
} set_lookup_value(cube, &p, i);
}
} }
ColorBucket ColorBucket
combined_palette(ColorBucket bucketsA, unsigned long nBucketsA, ColorBucket bucketsB, unsigned long nBucketsB) { combined_palette(
ColorBucket result; ColorBucket bucketsA,
if (nBucketsA > LONG_MAX - nBucketsB || unsigned long nBucketsA,
(nBucketsA+nBucketsB) > LONG_MAX / sizeof(struct _ColorBucket)) { ColorBucket bucketsB,
return NULL; unsigned long nBucketsB) {
} ColorBucket result;
/* malloc check ok, overflow check above */ if (nBucketsA > LONG_MAX - nBucketsB ||
result = calloc(nBucketsA + nBucketsB, sizeof(struct _ColorBucket)); (nBucketsA + nBucketsB) > LONG_MAX / sizeof(struct _ColorBucket)) {
if (!result) { return NULL;
return NULL; }
} /* malloc check ok, overflow check above */
memcpy(result, bucketsA, sizeof(struct _ColorBucket) * nBucketsA); result = calloc(nBucketsA + nBucketsB, sizeof(struct _ColorBucket));
memcpy(&result[nBucketsA], bucketsB, sizeof(struct _ColorBucket) * nBucketsB); if (!result) {
return result; return NULL;
}
memcpy(result, bucketsA, sizeof(struct _ColorBucket) * nBucketsA);
memcpy(&result[nBucketsA], bucketsB, sizeof(struct _ColorBucket) * nBucketsB);
return result;
} }
static Pixel * static Pixel *
create_palette_array(const ColorBucket palette, unsigned int paletteLength) { create_palette_array(const ColorBucket palette, unsigned int paletteLength) {
Pixel *paletteArray; Pixel *paletteArray;
unsigned int i; unsigned int i;
/* malloc check ok, calloc for overflow */ /* malloc check ok, calloc for overflow */
paletteArray = calloc(paletteLength, sizeof(Pixel)); paletteArray = calloc(paletteLength, sizeof(Pixel));
if (!paletteArray) { if (!paletteArray) {
return NULL; return NULL;
} }
for (i=0; i<paletteLength; i++) { for (i = 0; i < paletteLength; i++) {
avg_color_from_color_bucket(&palette[i], &paletteArray[i]); avg_color_from_color_bucket(&palette[i], &paletteArray[i]);
} }
return paletteArray; return paletteArray;
} }
static void static void
map_image_pixels(const Pixel *pixelData, map_image_pixels(
uint32_t nPixels, const Pixel *pixelData,
const ColorCube lookupCube, uint32_t nPixels,
uint32_t *pixelArray) const ColorCube lookupCube,
{ uint32_t *pixelArray) {
long i; long i;
for (i=0; i<nPixels; i++) { for (i = 0; i < nPixels; i++) {
pixelArray[i] = lookup_color(lookupCube, &pixelData[i]); pixelArray[i] = lookup_color(lookupCube, &pixelData[i]);
} }
} }
const unsigned int CUBE_LEVELS[8] = {4, 4, 4, 0, 2, 2, 2, 0}; const unsigned int CUBE_LEVELS[8] = {4, 4, 4, 0, 2, 2, 2, 0};
const unsigned int CUBE_LEVELS_ALPHA[8] = {3, 4, 3, 3, 2, 2, 2, 2}; const unsigned int CUBE_LEVELS_ALPHA[8] = {3, 4, 3, 3, 2, 2, 2, 2};
int quantize_octree(Pixel *pixelData, int
uint32_t nPixels, quantize_octree(
uint32_t nQuantPixels, Pixel *pixelData,
Pixel **palette, uint32_t nPixels,
uint32_t *paletteLength, uint32_t nQuantPixels,
uint32_t **quantizedPixels, Pixel **palette,
int withAlpha) uint32_t *paletteLength,
{ uint32_t **quantizedPixels,
ColorCube fineCube = NULL; int withAlpha) {
ColorCube coarseCube = NULL; ColorCube fineCube = NULL;
ColorCube lookupCube = NULL; ColorCube coarseCube = NULL;
ColorCube coarseLookupCube = NULL; ColorCube lookupCube = NULL;
ColorBucket paletteBucketsCoarse = NULL; ColorCube coarseLookupCube = NULL;
ColorBucket paletteBucketsFine = NULL; ColorBucket paletteBucketsCoarse = NULL;
ColorBucket paletteBuckets = NULL; ColorBucket paletteBucketsFine = NULL;
uint32_t *qp = NULL; ColorBucket paletteBuckets = NULL;
long i; uint32_t *qp = NULL;
unsigned long nCoarseColors, nFineColors, nAlreadySubtracted; long i;
const unsigned int *cubeBits; unsigned long nCoarseColors, nFineColors, nAlreadySubtracted;
const unsigned int *cubeBits;
if (withAlpha) { if (withAlpha) {
cubeBits = CUBE_LEVELS_ALPHA; cubeBits = CUBE_LEVELS_ALPHA;
} } else {
else { cubeBits = CUBE_LEVELS;
cubeBits = CUBE_LEVELS; }
}
/* /*
Create two color cubes, one fine grained with 8x16x8=1024 Create two color cubes, one fine grained with 8x16x8=1024
colors buckets and a coarse with 4x4x4=64 color buckets. colors buckets and a coarse with 4x4x4=64 color buckets.
The coarse one guarantees that there are color buckets available for The coarse one guarantees that there are color buckets available for
the whole color range (assuming nQuantPixels > 64). the whole color range (assuming nQuantPixels > 64).
For a quantization to 256 colors all 64 coarse colors will be used For a quantization to 256 colors all 64 coarse colors will be used
plus the 192 most used color buckets from the fine color cube. plus the 192 most used color buckets from the fine color cube.
The average of all colors within one bucket is used as the actual The average of all colors within one bucket is used as the actual
color for that bucket. color for that bucket.
For images with alpha the cubes gets a forth dimension, For images with alpha the cubes gets a forth dimension,
8x16x8x8 and 4x4x4x4. 8x16x8x8 and 4x4x4x4.
*/ */
/* create fine cube */ /* create fine cube */
fineCube = new_color_cube(cubeBits[0], cubeBits[1], fineCube = new_color_cube(cubeBits[0], cubeBits[1], cubeBits[2], cubeBits[3]);
cubeBits[2], cubeBits[3]); if (!fineCube) {
if (!fineCube) { goto error;
goto error; }
} for (i = 0; i < nPixels; i++) {
for (i=0; i<nPixels; i++) { add_color_to_color_cube(fineCube, &pixelData[i]);
add_color_to_color_cube(fineCube, &pixelData[i]); }
}
/* create coarse cube */ /* create coarse cube */
coarseCube = copy_color_cube(fineCube, cubeBits[4], cubeBits[5], coarseCube =
cubeBits[6], cubeBits[7]); copy_color_cube(fineCube, cubeBits[4], cubeBits[5], cubeBits[6], cubeBits[7]);
if (!coarseCube) { if (!coarseCube) {
goto error; goto error;
} }
nCoarseColors = count_used_color_buckets(coarseCube); nCoarseColors = count_used_color_buckets(coarseCube);
/* limit to nQuantPixels */ /* limit to nQuantPixels */
if (nCoarseColors > nQuantPixels) { if (nCoarseColors > nQuantPixels) {
nCoarseColors = nQuantPixels; nCoarseColors = nQuantPixels;
} }
/* how many space do we have in our palette for fine colors? */ /* how many space do we have in our palette for fine colors? */
nFineColors = nQuantPixels - nCoarseColors; nFineColors = nQuantPixels - nCoarseColors;
/* create fine color palette */ /* create fine color palette */
paletteBucketsFine = create_sorted_color_palette(fineCube); paletteBucketsFine = create_sorted_color_palette(fineCube);
if (!paletteBucketsFine) { if (!paletteBucketsFine) {
goto error; goto error;
} }
/* remove the used fine colors from the coarse cube */ /* remove the used fine colors from the coarse cube */
subtract_color_buckets(coarseCube, paletteBucketsFine, nFineColors); subtract_color_buckets(coarseCube, paletteBucketsFine, nFineColors);
/* did the subtraction cleared one or more coarse bucket? */ /* did the subtraction cleared one or more coarse bucket? */
while (nCoarseColors > count_used_color_buckets(coarseCube)) { while (nCoarseColors > count_used_color_buckets(coarseCube)) {
/* then we can use the free buckets for fine colors */ /* then we can use the free buckets for fine colors */
nAlreadySubtracted = nFineColors; nAlreadySubtracted = nFineColors;
nCoarseColors = count_used_color_buckets(coarseCube); nCoarseColors = count_used_color_buckets(coarseCube);
nFineColors = nQuantPixels - nCoarseColors; nFineColors = nQuantPixels - nCoarseColors;
subtract_color_buckets(coarseCube, &paletteBucketsFine[nAlreadySubtracted], subtract_color_buckets(
nFineColors-nAlreadySubtracted); coarseCube,
} &paletteBucketsFine[nAlreadySubtracted],
nFineColors - nAlreadySubtracted);
}
/* create our palette buckets with fine and coarse combined */ /* create our palette buckets with fine and coarse combined */
paletteBucketsCoarse = create_sorted_color_palette(coarseCube); paletteBucketsCoarse = create_sorted_color_palette(coarseCube);
if (!paletteBucketsCoarse) { if (!paletteBucketsCoarse) {
goto error; goto error;
} }
paletteBuckets = combined_palette(paletteBucketsCoarse, nCoarseColors, paletteBuckets = combined_palette(
paletteBucketsFine, nFineColors); paletteBucketsCoarse, nCoarseColors, paletteBucketsFine, nFineColors);
free(paletteBucketsFine); free(paletteBucketsFine);
paletteBucketsFine = NULL; paletteBucketsFine = NULL;
free(paletteBucketsCoarse); free(paletteBucketsCoarse);
paletteBucketsCoarse = NULL; paletteBucketsCoarse = NULL;
if (!paletteBuckets) { if (!paletteBuckets) {
goto error; goto error;
} }
/* add all coarse colors to our coarse lookup cube. */ /* add all coarse colors to our coarse lookup cube. */
coarseLookupCube = new_color_cube(cubeBits[4], cubeBits[5], coarseLookupCube =
cubeBits[6], cubeBits[7]); new_color_cube(cubeBits[4], cubeBits[5], cubeBits[6], cubeBits[7]);
if (!coarseLookupCube) { if (!coarseLookupCube) {
goto error; goto error;
} }
add_lookup_buckets(coarseLookupCube, paletteBuckets, nCoarseColors, 0); add_lookup_buckets(coarseLookupCube, paletteBuckets, nCoarseColors, 0);
/* expand coarse cube (64) to larger fine cube (4k). the value of each /* expand coarse cube (64) to larger fine cube (4k). the value of each
coarse bucket is then present in the according 64 fine buckets. */ coarse bucket is then present in the according 64 fine buckets. */
lookupCube = copy_color_cube(coarseLookupCube, cubeBits[0], cubeBits[1], lookupCube = copy_color_cube(
cubeBits[2], cubeBits[3]); coarseLookupCube, cubeBits[0], cubeBits[1], cubeBits[2], cubeBits[3]);
if (!lookupCube) { if (!lookupCube) {
goto error; goto error;
} }
/* add fine colors to the lookup cube */ /* add fine colors to the lookup cube */
add_lookup_buckets(lookupCube, paletteBuckets, nFineColors, nCoarseColors); add_lookup_buckets(lookupCube, paletteBuckets, nFineColors, nCoarseColors);
/* create result pixels and map palette indices */ /* create result pixels and map palette indices */
/* malloc check ok, calloc for overflow */ /* malloc check ok, calloc for overflow */
qp = calloc(nPixels, sizeof(Pixel)); qp = calloc(nPixels, sizeof(Pixel));
if (!qp) { if (!qp) {
goto error; goto error;
} }
map_image_pixels(pixelData, nPixels, lookupCube, qp); map_image_pixels(pixelData, nPixels, lookupCube, qp);
/* convert palette buckets to RGB pixel palette */ /* convert palette buckets to RGB pixel palette */
*palette = create_palette_array(paletteBuckets, nQuantPixels); *palette = create_palette_array(paletteBuckets, nQuantPixels);
if (!(*palette)) { if (!(*palette)) {
goto error; goto error;
} }
*quantizedPixels = qp; *quantizedPixels = qp;
*paletteLength = nQuantPixels; *paletteLength = nQuantPixels;
free_color_cube(coarseCube); free_color_cube(coarseCube);
free_color_cube(fineCube); free_color_cube(fineCube);
free_color_cube(lookupCube); free_color_cube(lookupCube);
free_color_cube(coarseLookupCube); free_color_cube(coarseLookupCube);
free(paletteBuckets); free(paletteBuckets);
return 1; return 1;
error: error:
/* everything is initialized to NULL /* everything is initialized to NULL
so we are safe to call free */ so we are safe to call free */
free(qp); free(qp);
free_color_cube(lookupCube); free_color_cube(lookupCube);
free_color_cube(coarseLookupCube); free_color_cube(coarseLookupCube);
free(paletteBuckets); free(paletteBuckets);
free(paletteBucketsCoarse); free(paletteBucketsCoarse);
free(paletteBucketsFine); free(paletteBucketsFine);
free_color_cube(coarseCube); free_color_cube(coarseCube);
free_color_cube(fineCube); free_color_cube(fineCube);
return 0; return 0;
} }

View File

@ -3,12 +3,7 @@
#include "QuantTypes.h" #include "QuantTypes.h"
int quantize_octree(Pixel *, int
uint32_t, quantize_octree(Pixel *, uint32_t, uint32_t, Pixel **, uint32_t *, uint32_t **, int);
uint32_t,
Pixel **,
uint32_t *,
uint32_t **,
int);
#endif #endif

View File

@ -26,8 +26,7 @@ quantize_pngquant(
Pixel **palette, Pixel **palette,
uint32_t *paletteLength, uint32_t *paletteLength,
uint32_t **quantizedPixels, uint32_t **quantizedPixels,
int withAlpha) int withAlpha) {
{
int result = 0; int result = 0;
liq_image *image = NULL; liq_image *image = NULL;
liq_attr *attr = NULL; liq_attr *attr = NULL;
@ -41,23 +40,24 @@ quantize_pngquant(
/* configure pngquant */ /* configure pngquant */
attr = liq_attr_create(); attr = liq_attr_create();
if (!attr) { goto err; } if (!attr) {
goto err;
}
if (quantPixels) { if (quantPixels) {
liq_set_max_colors(attr, quantPixels); liq_set_max_colors(attr, quantPixels);
} }
/* prepare input image */ /* prepare input image */
image = liq_image_create_rgba( image = liq_image_create_rgba(attr, pixelData, width, height, 0.45455 /* gamma */);
attr, if (!image) {
pixelData, goto err;
width, }
height,
0.45455 /* gamma */);
if (!image) { goto err; }
/* quantize the image */ /* quantize the image */
remap = liq_quantize_image(attr, image); remap = liq_quantize_image(attr, image);
if (!remap) { goto err; } if (!remap) {
goto err;
}
liq_set_output_gamma(remap, 0.45455); liq_set_output_gamma(remap, 0.45455);
liq_set_dithering_level(remap, 1); liq_set_dithering_level(remap, 1);
@ -65,7 +65,9 @@ quantize_pngquant(
const liq_palette *l_palette = liq_get_palette(remap); const liq_palette *l_palette = liq_get_palette(remap);
*paletteLength = l_palette->count; *paletteLength = l_palette->count;
*palette = malloc(sizeof(Pixel) * l_palette->count); *palette = malloc(sizeof(Pixel) * l_palette->count);
if (!*palette) { goto err; } if (!*palette) {
goto err;
}
for (i = 0; i < l_palette->count; i++) { for (i = 0; i < l_palette->count; i++) {
(*palette)[i].c.b = l_palette->entries[i].b; (*palette)[i].c.b = l_palette->entries[i].b;
(*palette)[i].c.g = l_palette->entries[i].g; (*palette)[i].c.g = l_palette->entries[i].g;
@ -75,9 +77,13 @@ quantize_pngquant(
/* write output pixels (pngquant uses char array) */ /* write output pixels (pngquant uses char array) */
charMatrix = malloc(width * height); charMatrix = malloc(width * height);
if (!charMatrix) { goto err; } if (!charMatrix) {
charMatrixRows = malloc(height * sizeof(unsigned char*)); goto err;
if (!charMatrixRows) { goto err; } }
charMatrixRows = malloc(height * sizeof(unsigned char *));
if (!charMatrixRows) {
goto err;
}
for (y = 0; y < height; y++) { for (y = 0; y < height; y++) {
charMatrixRows[y] = &charMatrix[y * width]; charMatrixRows[y] = &charMatrix[y * width];
} }
@ -87,7 +93,9 @@ quantize_pngquant(
/* transcribe output pixels (pillow uses uint32_t array) */ /* transcribe output pixels (pillow uses uint32_t array) */
*quantizedPixels = malloc(sizeof(uint32_t) * width * height); *quantizedPixels = malloc(sizeof(uint32_t) * width * height);
if (!*quantizedPixels) { goto err; } if (!*quantizedPixels) {
goto err;
}
for (i = 0; i < width * height; i++) { for (i = 0; i < width * height; i++) {
(*quantizedPixels)[i] = charMatrix[i]; (*quantizedPixels)[i] = charMatrix[i];
} }
@ -106,16 +114,15 @@ err:
} }
free(charMatrix); free(charMatrix);
free(charMatrixRows); free(charMatrixRows);
if (!result) { if (!result) {
free(*quantizedPixels); free(*quantizedPixels);
free(*palette); free(*palette);
} }
return result; return result;
} }
const char* const char *
ImagingImageQuantVersion(void) ImagingImageQuantVersion(void) {
{
static char version[20]; static char version[20];
int number = liq_version(); int number = liq_version();
sprintf(version, "%d.%d.%d", number / 10000, (number / 100) % 100, number % 100); sprintf(version, "%d.%d.%d", number / 10000, (number / 100) % 100, number % 100);

View File

@ -3,7 +3,9 @@
#include "QuantTypes.h" #include "QuantTypes.h"
int quantize_pngquant(Pixel *, int
quantize_pngquant(
Pixel *,
unsigned int, unsigned int,
unsigned int, unsigned int,
uint32_t, uint32_t,

View File

@ -20,13 +20,13 @@ typedef unsigned __int64 uint64_t;
#endif #endif
typedef union { typedef union {
struct { struct {
unsigned char r,g,b,a; unsigned char r, g, b, a;
} c; } c;
struct { struct {
unsigned char v[4]; unsigned char v[4];
} a; } a;
uint32_t v; uint32_t v;
} Pixel; } Pixel;
#endif #endif

View File

@ -17,94 +17,98 @@
/* Fast rank algorithm (due to Wirth), based on public domain code /* Fast rank algorithm (due to Wirth), based on public domain code
by Nicolas Devillard, available at http://ndevilla.free.fr */ by Nicolas Devillard, available at http://ndevilla.free.fr */
#define SWAP(type,a,b) { register type t=(a);(a)=(b);(b)=t; } #define SWAP(type, a, b) \
{ \
register type t = (a); \
(a) = (b); \
(b) = t; \
}
#define MakeRankFunction(type)\ #define MakeRankFunction(type) \
static type Rank##type(type a[], int n, int k)\ static type Rank##type(type a[], int n, int k) { \
{\ register int i, j, l, m; \
register int i, j, l, m;\ register type x; \
register type x;\ l = 0; \
l = 0; m = n-1;\ m = n - 1; \
while (l < m) {\ while (l < m) { \
x = a[k];\ x = a[k]; \
i = l;\ i = l; \
j = m;\ j = m; \
do {\ do { \
while (a[i] < x) {\ while (a[i] < x) { \
i++;\ i++; \
}\ } \
while (x < a[j]) {\ while (x < a[j]) { \
j--;\ j--; \
}\ } \
if (i <= j) {\ if (i <= j) { \
SWAP(type, a[i], a[j]);\ SWAP(type, a[i], a[j]); \
i++; j--;\ i++; \
}\ j--; \
} while (i <= j);\ } \
if (j < k) {\ } while (i <= j); \
l = i;\ if (j < k) { \
}\ l = i; \
if (k < i) {\ } \
m = j;\ if (k < i) { \
}\ m = j; \
}\ } \
return a[k];\ } \
} return a[k]; \
}
MakeRankFunction(UINT8) MakeRankFunction(UINT8) MakeRankFunction(INT32) MakeRankFunction(FLOAT32)
MakeRankFunction(INT32)
MakeRankFunction(FLOAT32)
Imaging Imaging ImagingRankFilter(Imaging im, int size, int rank) {
ImagingRankFilter(Imaging im, int size, int rank)
{
Imaging imOut = NULL; Imaging imOut = NULL;
int x, y; int x, y;
int i, margin, size2; int i, margin, size2;
if (!im || im->bands != 1 || im->type == IMAGING_TYPE_SPECIAL) { if (!im || im->bands != 1 || im->type == IMAGING_TYPE_SPECIAL) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
if (!(size & 1)) { if (!(size & 1)) {
return (Imaging) ImagingError_ValueError("bad filter size"); return (Imaging)ImagingError_ValueError("bad filter size");
} }
/* malloc check ok, for overflow in the define below */ /* malloc check ok, for overflow in the define below */
if (size > INT_MAX / size || if (size > INT_MAX / size || size > INT_MAX / (size * (int)sizeof(FLOAT32))) {
size > INT_MAX / (size * (int)sizeof(FLOAT32))) { return (Imaging)ImagingError_ValueError("filter size too large");
return (Imaging) ImagingError_ValueError("filter size too large");
} }
size2 = size * size; size2 = size * size;
margin = (size-1) / 2; margin = (size - 1) / 2;
if (rank < 0 || rank >= size2) { if (rank < 0 || rank >= size2) {
return (Imaging) ImagingError_ValueError("bad rank value"); return (Imaging)ImagingError_ValueError("bad rank value");
} }
imOut = ImagingNew(im->mode, im->xsize - 2*margin, im->ysize - 2*margin); imOut = ImagingNew(im->mode, im->xsize - 2 * margin, im->ysize - 2 * margin);
if (!imOut) { if (!imOut) {
return NULL; return NULL;
} }
/* malloc check ok, checked above */ /* malloc check ok, checked above */
#define RANK_BODY(type) do {\ #define RANK_BODY(type) \
type* buf = malloc(size2 * sizeof(type));\ do { \
if (!buf) {\ type *buf = malloc(size2 * sizeof(type)); \
goto nomemory;\ if (!buf) { \
}\ goto nomemory; \
for (y = 0; y < imOut->ysize; y++) {\ } \
for (x = 0; x < imOut->xsize; x++) {\ for (y = 0; y < imOut->ysize; y++) { \
for (i = 0; i < size; i++) {\ for (x = 0; x < imOut->xsize; x++) { \
memcpy(buf + i*size, &IMAGING_PIXEL_##type(im, x, y+i),\ for (i = 0; i < size; i++) { \
size * sizeof(type));\ memcpy( \
}\ buf + i * size, \
IMAGING_PIXEL_##type(imOut, x, y) = Rank##type(buf, size2, rank);\ &IMAGING_PIXEL_##type(im, x, y + i), \
}\ size * sizeof(type)); \
}\ } \
free(buf); \ IMAGING_PIXEL_##type(imOut, x, y) = Rank##type(buf, size2, rank); \
} while (0) } \
} \
free(buf); \
} while (0)
if (im->image8) { if (im->image8) {
RANK_BODY(UINT8); RANK_BODY(UINT8);
@ -115,7 +119,7 @@ ImagingRankFilter(Imaging im, int size, int rank)
} else { } else {
/* safety net (we shouldn't end up here) */ /* safety net (we shouldn't end up here) */
ImagingDelete(imOut); ImagingDelete(imOut);
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
ImagingCopyPalette(imOut, im); ImagingCopyPalette(imOut, im);
@ -124,5 +128,5 @@ ImagingRankFilter(Imaging im, int size, int rank)
nomemory: nomemory:
ImagingDelete(imOut); ImagingDelete(imOut);
return (Imaging) ImagingError_MemoryError(); return (Imaging)ImagingError_MemoryError();
} }

View File

@ -1,7 +1,6 @@
/* Raw.h */ /* Raw.h */
typedef struct { typedef struct {
/* CONFIGURATION */ /* CONFIGURATION */
/* Distance between lines (0=no padding) */ /* Distance between lines (0=no padding) */

View File

@ -13,22 +13,18 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#include "Raw.h" #include "Raw.h"
int int
ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes) ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
{
enum { LINE = 1, SKIP }; enum { LINE = 1, SKIP };
RAWSTATE* rawstate = state->context; RAWSTATE *rawstate = state->context;
UINT8* ptr; UINT8 *ptr;
if (state->state == 0) { if (state->state == 0) {
/* Initialize context variables */ /* Initialize context variables */
/* get size of image data and padding */ /* get size of image data and padding */
@ -45,22 +41,19 @@ ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
/* check image orientation */ /* check image orientation */
if (state->ystep < 0) { if (state->ystep < 0) {
state->y = state->ysize-1; state->y = state->ysize - 1;
state->ystep = -1; state->ystep = -1;
} else { } else {
state->ystep = 1; state->ystep = 1;
} }
state->state = LINE; state->state = LINE;
} }
ptr = buf; ptr = buf;
for (;;) { for (;;) {
if (state->state == SKIP) { if (state->state == SKIP) {
/* Skip padding between lines */ /* Skip padding between lines */
if (bytes < rawstate->skip) { if (bytes < rawstate->skip) {
@ -71,7 +64,6 @@ ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
bytes -= rawstate->skip; bytes -= rawstate->skip;
state->state = LINE; state->state = LINE;
} }
if (bytes < state->bytes) { if (bytes < state->bytes) {
@ -79,8 +71,10 @@ ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
} }
/* Unpack data */ /* Unpack data */
state->shuffle((UINT8*) im->image[state->y + state->yoff] + state->shuffle(
state->xoff * im->pixelsize, ptr, state->xsize); (UINT8 *)im->image[state->y + state->yoff] + state->xoff * im->pixelsize,
ptr,
state->xsize);
ptr += state->bytes; ptr += state->bytes;
bytes -= state->bytes; bytes -= state->bytes;
@ -93,7 +87,5 @@ ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
} }
state->state = SKIP; state->state = SKIP;
} }
} }

View File

@ -17,16 +17,13 @@
* *
* See the README file for information on usage and redistribution. */ * See the README file for information on usage and redistribution. */
#include "Imaging.h" #include "Imaging.h"
int int
ImagingRawEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) ImagingRawEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
{ UINT8 *ptr;
UINT8* ptr;
if (!state->state) { if (!state->state) {
/* The "count" field holds the stride, if specified. Fix /* The "count" field holds the stride, if specified. Fix
things up so "bytes" is the full size, and "count" the things up so "bytes" is the full size, and "count" the
packed size */ packed size */
@ -48,14 +45,13 @@ ImagingRawEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
/* The "ystep" field specifies the orientation */ /* The "ystep" field specifies the orientation */
if (state->ystep < 0) { if (state->ystep < 0) {
state->y = state->ysize-1; state->y = state->ysize - 1;
state->ystep = -1; state->ystep = -1;
} else { } else {
state->ystep = 1; state->ystep = 1;
} }
state->state = 1; state->state = 1;
} }
if (bytes < state->bytes) { if (bytes < state->bytes) {
@ -66,9 +62,10 @@ ImagingRawEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
ptr = buf; ptr = buf;
while (bytes >= state->bytes) { while (bytes >= state->bytes) {
state->shuffle(
state->shuffle(ptr, (UINT8*) im->image[state->y + state->yoff] + ptr,
state->xoff * im->pixelsize, state->xsize); (UINT8 *)im->image[state->y + state->yoff] + state->xoff * im->pixelsize,
state->xsize);
if (state->bytes > state->count) { if (state->bytes > state->count) {
/* zero-pad the buffer, if necessary */ /* zero-pad the buffer, if necessary */
@ -84,9 +81,7 @@ ImagingRawEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
state->errcode = IMAGING_CODEC_END; state->errcode = IMAGING_CODEC_END;
break; break;
} }
} }
return ptr - buf; return ptr - buf;
} }

File diff suppressed because it is too large Load Diff

View File

@ -2,36 +2,34 @@
#include <math.h> #include <math.h>
#define ROUND_UP(f) ((int)((f) >= 0.0 ? (f) + 0.5F : (f)-0.5F))
#define ROUND_UP(f) ((int) ((f) >= 0.0 ? (f) + 0.5F : (f) - 0.5F))
struct filter { struct filter {
double (*filter)(double x); double (*filter)(double x);
double support; double support;
}; };
static inline double box_filter(double x) static inline double
{ box_filter(double x) {
if (x > -0.5 && x <= 0.5) { if (x > -0.5 && x <= 0.5) {
return 1.0; return 1.0;
} }
return 0.0; return 0.0;
} }
static inline double bilinear_filter(double x) static inline double
{ bilinear_filter(double x) {
if (x < 0.0) { if (x < 0.0) {
x = -x; x = -x;
} }
if (x < 1.0) { if (x < 1.0) {
return 1.0-x; return 1.0 - x;
} }
return 0.0; return 0.0;
} }
static inline double hamming_filter(double x) static inline double
{ hamming_filter(double x) {
if (x < 0.0) { if (x < 0.0) {
x = -x; x = -x;
} }
@ -45,15 +43,16 @@ static inline double hamming_filter(double x)
return sin(x) / x * (0.54f + 0.46f * cos(x)); return sin(x) / x * (0.54f + 0.46f * cos(x));
} }
static inline double bicubic_filter(double x) static inline double
{ bicubic_filter(double x) {
/* https://en.wikipedia.org/wiki/Bicubic_interpolation#Bicubic_convolution_algorithm */ /* https://en.wikipedia.org/wiki/Bicubic_interpolation#Bicubic_convolution_algorithm
*/
#define a -0.5 #define a -0.5
if (x < 0.0) { if (x < 0.0) {
x = -x; x = -x;
} }
if (x < 1.0) { if (x < 1.0) {
return ((a + 2.0) * x - (a + 3.0)) * x*x + 1; return ((a + 2.0) * x - (a + 3.0)) * x * x + 1;
} }
if (x < 2.0) { if (x < 2.0) {
return (((x - 5) * x + 8) * x - 4) * a; return (((x - 5) * x + 8) * x - 4) * a;
@ -62,8 +61,8 @@ static inline double bicubic_filter(double x)
#undef a #undef a
} }
static inline double sinc_filter(double x) static inline double
{ sinc_filter(double x) {
if (x == 0.0) { if (x == 0.0) {
return 1.0; return 1.0;
} }
@ -71,21 +70,20 @@ static inline double sinc_filter(double x)
return sin(x) / x; return sin(x) / x;
} }
static inline double lanczos_filter(double x) static inline double
{ lanczos_filter(double x) {
/* truncated sinc */ /* truncated sinc */
if (-3.0 <= x && x < 3.0) { if (-3.0 <= x && x < 3.0) {
return sinc_filter(x) * sinc_filter(x/3); return sinc_filter(x) * sinc_filter(x / 3);
} }
return 0.0; return 0.0;
} }
static struct filter BOX = { box_filter, 0.5 }; static struct filter BOX = {box_filter, 0.5};
static struct filter BILINEAR = { bilinear_filter, 1.0 }; static struct filter BILINEAR = {bilinear_filter, 1.0};
static struct filter HAMMING = { hamming_filter, 1.0 }; static struct filter HAMMING = {hamming_filter, 1.0};
static struct filter BICUBIC = { bicubic_filter, 2.0 }; static struct filter BICUBIC = {bicubic_filter, 2.0};
static struct filter LANCZOS = { lanczos_filter, 3.0 }; static struct filter LANCZOS = {lanczos_filter, 3.0};
/* 8 bits for result. Filter can have negative areas. /* 8 bits for result. Filter can have negative areas.
In one cases the sum of the coefficients will be negative, In one cases the sum of the coefficients will be negative,
@ -93,102 +91,102 @@ static struct filter LANCZOS = { lanczos_filter, 3.0 };
two extra bits for overflow and int type. */ two extra bits for overflow and int type. */
#define PRECISION_BITS (32 - 8 - 2) #define PRECISION_BITS (32 - 8 - 2)
/* Handles values form -640 to 639. */ /* Handles values form -640 to 639. */
UINT8 _clip8_lookups[1280] = { UINT8 _clip8_lookups[1280] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 255, 255, 255, 255, 255,
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
}; };
UINT8 *clip8_lookups = &_clip8_lookups[640]; UINT8 *clip8_lookups = &_clip8_lookups[640];
static inline UINT8 clip8(int in) static inline UINT8
{ clip8(int in) {
return clip8_lookups[in >> PRECISION_BITS]; return clip8_lookups[in >> PRECISION_BITS];
} }
int int
precompute_coeffs(int inSize, float in0, float in1, int outSize, precompute_coeffs(
struct filter *filterp, int **boundsp, double **kkp) { int inSize,
float in0,
float in1,
int outSize,
struct filter *filterp,
int **boundsp,
double **kkp) {
double support, scale, filterscale; double support, scale, filterscale;
double center, ww, ss; double center, ww, ss;
int xx, x, ksize, xmin, xmax; int xx, x, ksize, xmin, xmax;
@ -196,7 +194,7 @@ precompute_coeffs(int inSize, float in0, float in1, int outSize,
double *kk, *k; double *kk, *k;
/* prepare for horizontal stretch */ /* prepare for horizontal stretch */
filterscale = scale = (double) (in1 - in0) / outSize; filterscale = scale = (double)(in1 - in0) / outSize;
if (filterscale < 1.0) { if (filterscale < 1.0) {
filterscale = 1.0; filterscale = 1.0;
} }
@ -205,7 +203,7 @@ precompute_coeffs(int inSize, float in0, float in1, int outSize,
support = filterp->support * filterscale; support = filterp->support * filterscale;
/* maximum number of coeffs */ /* maximum number of coeffs */
ksize = (int) ceil(support) * 2 + 1; ksize = (int)ceil(support) * 2 + 1;
// check for overflow // check for overflow
if (outSize > INT_MAX / (ksize * (int)sizeof(double))) { if (outSize > INT_MAX / (ksize * (int)sizeof(double))) {
@ -216,14 +214,14 @@ precompute_coeffs(int inSize, float in0, float in1, int outSize,
/* coefficient buffer */ /* coefficient buffer */
/* malloc check ok, overflow checked above */ /* malloc check ok, overflow checked above */
kk = malloc(outSize * ksize * sizeof(double)); kk = malloc(outSize * ksize * sizeof(double));
if ( ! kk) { if (!kk) {
ImagingError_MemoryError(); ImagingError_MemoryError();
return 0; return 0;
} }
/* malloc check ok, ksize*sizeof(double) > 2*sizeof(int) */ /* malloc check ok, ksize*sizeof(double) > 2*sizeof(int) */
bounds = malloc(outSize * 2 * sizeof(int)); bounds = malloc(outSize * 2 * sizeof(int));
if ( ! bounds) { if (!bounds) {
free(kk); free(kk);
ImagingError_MemoryError(); ImagingError_MemoryError();
return 0; return 0;
@ -234,12 +232,12 @@ precompute_coeffs(int inSize, float in0, float in1, int outSize,
ww = 0.0; ww = 0.0;
ss = 1.0 / filterscale; ss = 1.0 / filterscale;
// Round the value // Round the value
xmin = (int) (center - support + 0.5); xmin = (int)(center - support + 0.5);
if (xmin < 0) { if (xmin < 0) {
xmin = 0; xmin = 0;
} }
// Round the value // Round the value
xmax = (int) (center + support + 0.5); xmax = (int)(center + support + 0.5);
if (xmax > inSize) { if (xmax > inSize) {
xmax = inSize; xmax = inSize;
} }
@ -267,38 +265,33 @@ precompute_coeffs(int inSize, float in0, float in1, int outSize,
return ksize; return ksize;
} }
void void
normalize_coeffs_8bpc(int outSize, int ksize, double *prekk) normalize_coeffs_8bpc(int outSize, int ksize, double *prekk) {
{
int x; int x;
INT32 *kk; INT32 *kk;
// use the same buffer for normalized coefficients // use the same buffer for normalized coefficients
kk = (INT32 *) prekk; kk = (INT32 *)prekk;
for (x = 0; x < outSize * ksize; x++) { for (x = 0; x < outSize * ksize; x++) {
if (prekk[x] < 0) { if (prekk[x] < 0) {
kk[x] = (int) (-0.5 + prekk[x] * (1 << PRECISION_BITS)); kk[x] = (int)(-0.5 + prekk[x] * (1 << PRECISION_BITS));
} else { } else {
kk[x] = (int) (0.5 + prekk[x] * (1 << PRECISION_BITS)); kk[x] = (int)(0.5 + prekk[x] * (1 << PRECISION_BITS));
} }
} }
} }
void void
ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset, ImagingResampleHorizontal_8bpc(
int ksize, int *bounds, double *prekk) Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *prekk) {
{
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
int ss0, ss1, ss2, ss3; int ss0, ss1, ss2, ss3;
int xx, yy, x, xmin, xmax; int xx, yy, x, xmin, xmax;
INT32 *k, *kk; INT32 *k, *kk;
// use the same buffer for normalized coefficients // use the same buffer for normalized coefficients
kk = (INT32 *) prekk; kk = (INT32 *)prekk;
normalize_coeffs_8bpc(imOut->xsize, ksize, prekk); normalize_coeffs_8bpc(imOut->xsize, ksize, prekk);
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
@ -308,9 +301,9 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset,
xmin = bounds[xx * 2 + 0]; xmin = bounds[xx * 2 + 0];
xmax = bounds[xx * 2 + 1]; xmax = bounds[xx * 2 + 1];
k = &kk[xx * ksize]; k = &kk[xx * ksize];
ss0 = 1 << (PRECISION_BITS -1); ss0 = 1 << (PRECISION_BITS - 1);
for (x = 0; x < xmax; x++) { for (x = 0; x < xmax; x++) {
ss0 += ((UINT8) imIn->image8[yy + offset][x + xmin]) * k[x]; ss0 += ((UINT8)imIn->image8[yy + offset][x + xmin]) * k[x];
} }
imOut->image8[yy][xx] = clip8(ss0); imOut->image8[yy][xx] = clip8(ss0);
} }
@ -323,10 +316,12 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset,
xmin = bounds[xx * 2 + 0]; xmin = bounds[xx * 2 + 0];
xmax = bounds[xx * 2 + 1]; xmax = bounds[xx * 2 + 1];
k = &kk[xx * ksize]; k = &kk[xx * ksize];
ss0 = ss3 = 1 << (PRECISION_BITS -1); ss0 = ss3 = 1 << (PRECISION_BITS - 1);
for (x = 0; x < xmax; x++) { for (x = 0; x < xmax; x++) {
ss0 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 0]) * k[x]; ss0 += ((UINT8)imIn->image[yy + offset][(x + xmin) * 4 + 0]) *
ss3 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 3]) * k[x]; k[x];
ss3 += ((UINT8)imIn->image[yy + offset][(x + xmin) * 4 + 3]) *
k[x];
} }
v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3)); v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3));
memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v)); memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v));
@ -339,11 +334,14 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset,
xmin = bounds[xx * 2 + 0]; xmin = bounds[xx * 2 + 0];
xmax = bounds[xx * 2 + 1]; xmax = bounds[xx * 2 + 1];
k = &kk[xx * ksize]; k = &kk[xx * ksize];
ss0 = ss1 = ss2 = 1 << (PRECISION_BITS -1); ss0 = ss1 = ss2 = 1 << (PRECISION_BITS - 1);
for (x = 0; x < xmax; x++) { for (x = 0; x < xmax; x++) {
ss0 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 0]) * k[x]; ss0 += ((UINT8)imIn->image[yy + offset][(x + xmin) * 4 + 0]) *
ss1 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 1]) * k[x]; k[x];
ss2 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 2]) * k[x]; ss1 += ((UINT8)imIn->image[yy + offset][(x + xmin) * 4 + 1]) *
k[x];
ss2 += ((UINT8)imIn->image[yy + offset][(x + xmin) * 4 + 2]) *
k[x];
} }
v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), 0); v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), 0);
memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v)); memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v));
@ -356,12 +354,16 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset,
xmin = bounds[xx * 2 + 0]; xmin = bounds[xx * 2 + 0];
xmax = bounds[xx * 2 + 1]; xmax = bounds[xx * 2 + 1];
k = &kk[xx * ksize]; k = &kk[xx * ksize];
ss0 = ss1 = ss2 = ss3 = 1 << (PRECISION_BITS -1); ss0 = ss1 = ss2 = ss3 = 1 << (PRECISION_BITS - 1);
for (x = 0; x < xmax; x++) { for (x = 0; x < xmax; x++) {
ss0 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 0]) * k[x]; ss0 += ((UINT8)imIn->image[yy + offset][(x + xmin) * 4 + 0]) *
ss1 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 1]) * k[x]; k[x];
ss2 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 2]) * k[x]; ss1 += ((UINT8)imIn->image[yy + offset][(x + xmin) * 4 + 1]) *
ss3 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 3]) * k[x]; k[x];
ss2 += ((UINT8)imIn->image[yy + offset][(x + xmin) * 4 + 2]) *
k[x];
ss3 += ((UINT8)imIn->image[yy + offset][(x + xmin) * 4 + 3]) *
k[x];
} }
v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3)); v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3));
memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v)); memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v));
@ -372,18 +374,16 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset,
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
} }
void void
ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset, ImagingResampleVertical_8bpc(
int ksize, int *bounds, double *prekk) Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *prekk) {
{
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
int ss0, ss1, ss2, ss3; int ss0, ss1, ss2, ss3;
int xx, yy, y, ymin, ymax; int xx, yy, y, ymin, ymax;
INT32 *k, *kk; INT32 *k, *kk;
// use the same buffer for normalized coefficients // use the same buffer for normalized coefficients
kk = (INT32 *) prekk; kk = (INT32 *)prekk;
normalize_coeffs_8bpc(imOut->ysize, ksize, prekk); normalize_coeffs_8bpc(imOut->ysize, ksize, prekk);
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
@ -393,9 +393,9 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset,
ymin = bounds[yy * 2 + 0]; ymin = bounds[yy * 2 + 0];
ymax = bounds[yy * 2 + 1]; ymax = bounds[yy * 2 + 1];
for (xx = 0; xx < imOut->xsize; xx++) { for (xx = 0; xx < imOut->xsize; xx++) {
ss0 = 1 << (PRECISION_BITS -1); ss0 = 1 << (PRECISION_BITS - 1);
for (y = 0; y < ymax; y++) { for (y = 0; y < ymax; y++) {
ss0 += ((UINT8) imIn->image8[y + ymin][xx]) * k[y]; ss0 += ((UINT8)imIn->image8[y + ymin][xx]) * k[y];
} }
imOut->image8[yy][xx] = clip8(ss0); imOut->image8[yy][xx] = clip8(ss0);
} }
@ -408,10 +408,10 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset,
ymax = bounds[yy * 2 + 1]; ymax = bounds[yy * 2 + 1];
for (xx = 0; xx < imOut->xsize; xx++) { for (xx = 0; xx < imOut->xsize; xx++) {
UINT32 v; UINT32 v;
ss0 = ss3 = 1 << (PRECISION_BITS -1); ss0 = ss3 = 1 << (PRECISION_BITS - 1);
for (y = 0; y < ymax; y++) { for (y = 0; y < ymax; y++) {
ss0 += ((UINT8) imIn->image[y + ymin][xx*4 + 0]) * k[y]; ss0 += ((UINT8)imIn->image[y + ymin][xx * 4 + 0]) * k[y];
ss3 += ((UINT8) imIn->image[y + ymin][xx*4 + 3]) * k[y]; ss3 += ((UINT8)imIn->image[y + ymin][xx * 4 + 3]) * k[y];
} }
v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3)); v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3));
memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v)); memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v));
@ -424,11 +424,11 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset,
ymax = bounds[yy * 2 + 1]; ymax = bounds[yy * 2 + 1];
for (xx = 0; xx < imOut->xsize; xx++) { for (xx = 0; xx < imOut->xsize; xx++) {
UINT32 v; UINT32 v;
ss0 = ss1 = ss2 = 1 << (PRECISION_BITS -1); ss0 = ss1 = ss2 = 1 << (PRECISION_BITS - 1);
for (y = 0; y < ymax; y++) { for (y = 0; y < ymax; y++) {
ss0 += ((UINT8) imIn->image[y + ymin][xx*4 + 0]) * k[y]; ss0 += ((UINT8)imIn->image[y + ymin][xx * 4 + 0]) * k[y];
ss1 += ((UINT8) imIn->image[y + ymin][xx*4 + 1]) * k[y]; ss1 += ((UINT8)imIn->image[y + ymin][xx * 4 + 1]) * k[y];
ss2 += ((UINT8) imIn->image[y + ymin][xx*4 + 2]) * k[y]; ss2 += ((UINT8)imIn->image[y + ymin][xx * 4 + 2]) * k[y];
} }
v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), 0); v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), 0);
memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v)); memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v));
@ -441,12 +441,12 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset,
ymax = bounds[yy * 2 + 1]; ymax = bounds[yy * 2 + 1];
for (xx = 0; xx < imOut->xsize; xx++) { for (xx = 0; xx < imOut->xsize; xx++) {
UINT32 v; UINT32 v;
ss0 = ss1 = ss2 = ss3 = 1 << (PRECISION_BITS -1); ss0 = ss1 = ss2 = ss3 = 1 << (PRECISION_BITS - 1);
for (y = 0; y < ymax; y++) { for (y = 0; y < ymax; y++) {
ss0 += ((UINT8) imIn->image[y + ymin][xx*4 + 0]) * k[y]; ss0 += ((UINT8)imIn->image[y + ymin][xx * 4 + 0]) * k[y];
ss1 += ((UINT8) imIn->image[y + ymin][xx*4 + 1]) * k[y]; ss1 += ((UINT8)imIn->image[y + ymin][xx * 4 + 1]) * k[y];
ss2 += ((UINT8) imIn->image[y + ymin][xx*4 + 2]) * k[y]; ss2 += ((UINT8)imIn->image[y + ymin][xx * 4 + 2]) * k[y];
ss3 += ((UINT8) imIn->image[y + ymin][xx*4 + 3]) * k[y]; ss3 += ((UINT8)imIn->image[y + ymin][xx * 4 + 3]) * k[y];
} }
v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3)); v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3));
memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v)); memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v));
@ -457,18 +457,16 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset,
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
} }
void void
ImagingResampleHorizontal_32bpc(Imaging imOut, Imaging imIn, int offset, ImagingResampleHorizontal_32bpc(
int ksize, int *bounds, double *kk) Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *kk) {
{
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
double ss; double ss;
int xx, yy, x, xmin, xmax; int xx, yy, x, xmin, xmax;
double *k; double *k;
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
switch(imIn->type) { switch (imIn->type) {
case IMAGING_TYPE_INT32: case IMAGING_TYPE_INT32:
for (yy = 0; yy < imOut->ysize; yy++) { for (yy = 0; yy < imOut->ysize; yy++) {
for (xx = 0; xx < imOut->xsize; xx++) { for (xx = 0; xx < imOut->xsize; xx++) {
@ -502,18 +500,16 @@ ImagingResampleHorizontal_32bpc(Imaging imOut, Imaging imIn, int offset,
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
} }
void void
ImagingResampleVertical_32bpc(Imaging imOut, Imaging imIn, int offset, ImagingResampleVertical_32bpc(
int ksize, int *bounds, double *kk) Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *kk) {
{
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
double ss; double ss;
int xx, yy, y, ymin, ymax; int xx, yy, y, ymin, ymax;
double *k; double *k;
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
switch(imIn->type) { switch (imIn->type) {
case IMAGING_TYPE_INT32: case IMAGING_TYPE_INT32:
for (yy = 0; yy < imOut->ysize; yy++) { for (yy = 0; yy < imOut->ysize; yy++) {
ymin = bounds[yy * 2 + 0]; ymin = bounds[yy * 2 + 0];
@ -547,36 +543,36 @@ ImagingResampleVertical_32bpc(Imaging imOut, Imaging imIn, int offset,
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
} }
typedef void (*ResampleFunction)(
typedef void (*ResampleFunction)(Imaging imOut, Imaging imIn, int offset, Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *kk);
int ksize, int *bounds, double *kk);
Imaging Imaging
ImagingResampleInner(Imaging imIn, int xsize, int ysize, ImagingResampleInner(
struct filter *filterp, float box[4], Imaging imIn,
ResampleFunction ResampleHorizontal, int xsize,
ResampleFunction ResampleVertical); int ysize,
struct filter *filterp,
float box[4],
ResampleFunction ResampleHorizontal,
ResampleFunction ResampleVertical);
Imaging Imaging
ImagingResample(Imaging imIn, int xsize, int ysize, int filter, float box[4]) ImagingResample(Imaging imIn, int xsize, int ysize, int filter, float box[4]) {
{
struct filter *filterp; struct filter *filterp;
ResampleFunction ResampleHorizontal; ResampleFunction ResampleHorizontal;
ResampleFunction ResampleVertical; ResampleFunction ResampleVertical;
if (strcmp(imIn->mode, "P") == 0 || strcmp(imIn->mode, "1") == 0) { if (strcmp(imIn->mode, "P") == 0 || strcmp(imIn->mode, "1") == 0) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
if (imIn->type == IMAGING_TYPE_SPECIAL) { if (imIn->type == IMAGING_TYPE_SPECIAL) {
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} else if (imIn->image8) { } else if (imIn->image8) {
ResampleHorizontal = ImagingResampleHorizontal_8bpc; ResampleHorizontal = ImagingResampleHorizontal_8bpc;
ResampleVertical = ImagingResampleVertical_8bpc; ResampleVertical = ImagingResampleVertical_8bpc;
} else { } else {
switch(imIn->type) { switch (imIn->type) {
case IMAGING_TYPE_UINT8: case IMAGING_TYPE_UINT8:
ResampleHorizontal = ImagingResampleHorizontal_8bpc; ResampleHorizontal = ImagingResampleHorizontal_8bpc;
ResampleVertical = ImagingResampleVertical_8bpc; ResampleVertical = ImagingResampleVertical_8bpc;
@ -587,44 +583,44 @@ ImagingResample(Imaging imIn, int xsize, int ysize, int filter, float box[4])
ResampleVertical = ImagingResampleVertical_32bpc; ResampleVertical = ImagingResampleVertical_32bpc;
break; break;
default: default:
return (Imaging) ImagingError_ModeError(); return (Imaging)ImagingError_ModeError();
} }
} }
/* check filter */ /* check filter */
switch (filter) { switch (filter) {
case IMAGING_TRANSFORM_BOX: case IMAGING_TRANSFORM_BOX:
filterp = &BOX; filterp = &BOX;
break; break;
case IMAGING_TRANSFORM_BILINEAR: case IMAGING_TRANSFORM_BILINEAR:
filterp = &BILINEAR; filterp = &BILINEAR;
break; break;
case IMAGING_TRANSFORM_HAMMING: case IMAGING_TRANSFORM_HAMMING:
filterp = &HAMMING; filterp = &HAMMING;
break; break;
case IMAGING_TRANSFORM_BICUBIC: case IMAGING_TRANSFORM_BICUBIC:
filterp = &BICUBIC; filterp = &BICUBIC;
break; break;
case IMAGING_TRANSFORM_LANCZOS: case IMAGING_TRANSFORM_LANCZOS:
filterp = &LANCZOS; filterp = &LANCZOS;
break; break;
default: default:
return (Imaging) ImagingError_ValueError( return (Imaging)ImagingError_ValueError("unsupported resampling filter");
"unsupported resampling filter"
);
} }
return ImagingResampleInner(imIn, xsize, ysize, filterp, box, return ImagingResampleInner(
ResampleHorizontal, ResampleVertical); imIn, xsize, ysize, filterp, box, ResampleHorizontal, ResampleVertical);
} }
Imaging Imaging
ImagingResampleInner(Imaging imIn, int xsize, int ysize, ImagingResampleInner(
struct filter *filterp, float box[4], Imaging imIn,
ResampleFunction ResampleHorizontal, int xsize,
ResampleFunction ResampleVertical) int ysize,
{ struct filter *filterp,
float box[4],
ResampleFunction ResampleHorizontal,
ResampleFunction ResampleVertical) {
Imaging imTemp = NULL; Imaging imTemp = NULL;
Imaging imOut = NULL; Imaging imOut = NULL;
@ -637,15 +633,15 @@ ImagingResampleInner(Imaging imIn, int xsize, int ysize,
need_horizontal = xsize != imIn->xsize || box[0] || box[2] != xsize; need_horizontal = xsize != imIn->xsize || box[0] || box[2] != xsize;
need_vertical = ysize != imIn->ysize || box[1] || box[3] != ysize; need_vertical = ysize != imIn->ysize || box[1] || box[3] != ysize;
ksize_horiz = precompute_coeffs(imIn->xsize, box[0], box[2], xsize, ksize_horiz = precompute_coeffs(
filterp, &bounds_horiz, &kk_horiz); imIn->xsize, box[0], box[2], xsize, filterp, &bounds_horiz, &kk_horiz);
if ( ! ksize_horiz) { if (!ksize_horiz) {
return NULL; return NULL;
} }
ksize_vert = precompute_coeffs(imIn->ysize, box[1], box[3], ysize, ksize_vert = precompute_coeffs(
filterp, &bounds_vert, &kk_vert); imIn->ysize, box[1], box[3], ysize, filterp, &bounds_vert, &kk_vert);
if ( ! ksize_vert) { if (!ksize_vert) {
free(bounds_horiz); free(bounds_horiz);
free(kk_horiz); free(kk_horiz);
return NULL; return NULL;
@ -654,8 +650,7 @@ ImagingResampleInner(Imaging imIn, int xsize, int ysize,
// First used row in the source image // First used row in the source image
ybox_first = bounds_vert[0]; ybox_first = bounds_vert[0];
// Last used row in the source image // Last used row in the source image
ybox_last = bounds_vert[ysize*2 - 2] + bounds_vert[ysize*2 - 1]; ybox_last = bounds_vert[ysize * 2 - 2] + bounds_vert[ysize * 2 - 1];
/* two-pass resize, horizontal pass */ /* two-pass resize, horizontal pass */
if (need_horizontal) { if (need_horizontal) {
@ -666,12 +661,12 @@ ImagingResampleInner(Imaging imIn, int xsize, int ysize,
imTemp = ImagingNewDirty(imIn->mode, xsize, ybox_last - ybox_first); imTemp = ImagingNewDirty(imIn->mode, xsize, ybox_last - ybox_first);
if (imTemp) { if (imTemp) {
ResampleHorizontal(imTemp, imIn, ybox_first, ResampleHorizontal(
ksize_horiz, bounds_horiz, kk_horiz); imTemp, imIn, ybox_first, ksize_horiz, bounds_horiz, kk_horiz);
} }
free(bounds_horiz); free(bounds_horiz);
free(kk_horiz); free(kk_horiz);
if ( ! imTemp) { if (!imTemp) {
free(bounds_vert); free(bounds_vert);
free(kk_vert); free(kk_vert);
return NULL; return NULL;
@ -688,15 +683,14 @@ ImagingResampleInner(Imaging imIn, int xsize, int ysize,
imOut = ImagingNewDirty(imIn->mode, imIn->xsize, ysize); imOut = ImagingNewDirty(imIn->mode, imIn->xsize, ysize);
if (imOut) { if (imOut) {
/* imIn can be the original image or horizontally resampled one */ /* imIn can be the original image or horizontally resampled one */
ResampleVertical(imOut, imIn, 0, ResampleVertical(imOut, imIn, 0, ksize_vert, bounds_vert, kk_vert);
ksize_vert, bounds_vert, kk_vert);
} }
/* it's safe to call ImagingDelete with empty value /* it's safe to call ImagingDelete with empty value
if previous step was not performed. */ if previous step was not performed. */
ImagingDelete(imTemp); ImagingDelete(imTemp);
free(bounds_vert); free(bounds_vert);
free(kk_vert); free(kk_vert);
if ( ! imOut) { if (!imOut) {
return NULL; return NULL;
} }
} else { } else {
@ -706,7 +700,7 @@ ImagingResampleInner(Imaging imIn, int xsize, int ysize,
} }
/* none of the previous steps are performed, copying */ /* none of the previous steps are performed, copying */
if ( ! imOut) { if (!imOut) {
imOut = ImagingCopy(imIn); imOut = ImagingCopy(imIn);
} }

View File

@ -1,7 +1,6 @@
/* Sgi.h */ /* Sgi.h */
typedef struct { typedef struct {
/* CONFIGURATION */ /* CONFIGURATION */
/* Number of bytes per channel per pixel */ /* Number of bytes per channel per pixel */

View File

@ -20,18 +20,17 @@
#define RLE_COPY_FLAG 0x80 #define RLE_COPY_FLAG 0x80
#define RLE_MAX_RUN 0x7f #define RLE_MAX_RUN 0x7f
static void read4B(UINT32* dest, UINT8* buf) static void
{ read4B(UINT32 *dest, UINT8 *buf) {
*dest = (UINT32)((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); *dest = (UINT32)((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
} }
static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize) static int
{ expandrow(UINT8 *dest, UINT8 *src, int n, int z, int xsize) {
UINT8 pixel, count; UINT8 pixel, count;
int x = 0; int x = 0;
for (;n > 0; n--) for (; n > 0; n--) {
{
pixel = *src++; pixel = *src++;
if (n == 1 && pixel != 0) { if (n == 1 && pixel != 0) {
return n; return n;
@ -45,34 +44,31 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize)
} }
x += count; x += count;
if (pixel & RLE_COPY_FLAG) { if (pixel & RLE_COPY_FLAG) {
while(count--) { while (count--) {
*dest = *src++; *dest = *src++;
dest += z; dest += z;
} }
} } else {
else {
pixel = *src++; pixel = *src++;
while (count--) { while (count--) {
*dest = pixel; *dest = pixel;
dest += z; dest += z;
} }
} }
} }
return 0; return 0;
} }
static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize) static int
{ expandrow2(UINT8 *dest, const UINT8 *src, int n, int z, int xsize) {
UINT8 pixel, count; UINT8 pixel, count;
int x = 0; int x = 0;
for (;n > 0; n--) for (; n > 0; n--) {
{
pixel = src[1]; pixel = src[1];
src+=2; src += 2;
if (n == 1 && pixel != 0) { if (n == 1 && pixel != 0) {
return n; return n;
} }
@ -85,42 +81,37 @@ static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize)
} }
x += count; x += count;
if (pixel & RLE_COPY_FLAG) { if (pixel & RLE_COPY_FLAG) {
while(count--) { while (count--) {
memcpy(dest, src, 2); memcpy(dest, src, 2);
src += 2; src += 2;
dest += z * 2; dest += z * 2;
} }
} } else {
else {
while (count--) { while (count--) {
memcpy(dest, src, 2); memcpy(dest, src, 2);
dest += z * 2; dest += z * 2;
} }
src+=2; src += 2;
} }
} }
return 0; return 0;
} }
int int
ImagingSgiRleDecode(Imaging im, ImagingCodecState state, ImagingSgiRleDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
UINT8* buf, Py_ssize_t bytes)
{
UINT8 *ptr; UINT8 *ptr;
SGISTATE *c; SGISTATE *c;
int err = 0; int err = 0;
int status; int status;
/* size check */ /* size check */
if (im->xsize > INT_MAX / im->bands || if (im->xsize > INT_MAX / im->bands || im->ysize > INT_MAX / im->bands) {
im->ysize > INT_MAX / im->bands) {
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
return -1; return -1;
} }
/* Get all data from File descriptor */ /* Get all data from File descriptor */
c = (SGISTATE*)state->context; c = (SGISTATE *)state->context;
_imaging_seek_pyFd(state->fd, 0L, SEEK_END); _imaging_seek_pyFd(state->fd, 0L, SEEK_END);
c->bufsize = _imaging_tell_pyFd(state->fd); c->bufsize = _imaging_tell_pyFd(state->fd);
c->bufsize -= SGI_HEADER_SIZE; c->bufsize -= SGI_HEADER_SIZE;
@ -130,7 +121,7 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
each with 4 bytes per element of tablen each with 4 bytes per element of tablen
Check here before we allocate any memory Check here before we allocate any memory
*/ */
if (c->bufsize < 8*c->tablen) { if (c->bufsize < 8 * c->tablen) {
state->errcode = IMAGING_CODEC_OVERRUN; state->errcode = IMAGING_CODEC_OVERRUN;
return -1; return -1;
} }
@ -141,8 +132,7 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
return -1; return -1;
} }
_imaging_seek_pyFd(state->fd, SGI_HEADER_SIZE, SEEK_SET); _imaging_seek_pyFd(state->fd, SGI_HEADER_SIZE, SEEK_SET);
_imaging_read_pyFd(state->fd, (char*)ptr, c->bufsize); _imaging_read_pyFd(state->fd, (char *)ptr, c->bufsize);
/* decoder initialization */ /* decoder initialization */
state->count = 0; state->count = 0;
@ -160,28 +150,27 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
state->buffer = calloc(im->xsize * im->bands, sizeof(UINT8) * 2); state->buffer = calloc(im->xsize * im->bands, sizeof(UINT8) * 2);
c->starttab = calloc(c->tablen, sizeof(UINT32)); c->starttab = calloc(c->tablen, sizeof(UINT32));
c->lengthtab = calloc(c->tablen, sizeof(UINT32)); c->lengthtab = calloc(c->tablen, sizeof(UINT32));
if (!state->buffer || if (!state->buffer || !c->starttab || !c->lengthtab) {
!c->starttab ||
!c->lengthtab) {
err = IMAGING_CODEC_MEMORY; err = IMAGING_CODEC_MEMORY;
goto sgi_finish_decode; goto sgi_finish_decode;
} }
/* populate offsets table */ /* populate offsets table */
for (c->tabindex = 0, c->bufindex = 0; c->tabindex < c->tablen; c->tabindex++, c->bufindex+=4) { for (c->tabindex = 0, c->bufindex = 0; c->tabindex < c->tablen;
c->tabindex++, c->bufindex += 4) {
read4B(&c->starttab[c->tabindex], &ptr[c->bufindex]); read4B(&c->starttab[c->tabindex], &ptr[c->bufindex]);
} }
/* populate lengths table */ /* populate lengths table */
for (c->tabindex = 0, c->bufindex = c->tablen * sizeof(UINT32); c->tabindex < c->tablen; c->tabindex++, c->bufindex+=4) { for (c->tabindex = 0, c->bufindex = c->tablen * sizeof(UINT32);
c->tabindex < c->tablen;
c->tabindex++, c->bufindex += 4) {
read4B(&c->lengthtab[c->tabindex], &ptr[c->bufindex]); read4B(&c->lengthtab[c->tabindex], &ptr[c->bufindex]);
} }
state->count += c->tablen * sizeof(UINT32) * 2; state->count += c->tablen * sizeof(UINT32) * 2;
/* read compressed rows */ /* read compressed rows */
for (c->rowno = 0; c->rowno < im->ysize; c->rowno++, state->y += state->ystep) for (c->rowno = 0; c->rowno < im->ysize; c->rowno++, state->y += state->ystep) {
{ for (c->channo = 0; c->channo < im->bands; c->channo++) {
for (c->channo = 0; c->channo < im->bands; c->channo++)
{
c->rleoffset = c->starttab[c->rowno + c->channo * im->ysize]; c->rleoffset = c->starttab[c->rowno + c->channo * im->ysize];
c->rlelength = c->lengthtab[c->rowno + c->channo * im->ysize]; c->rlelength = c->lengthtab[c->rowno + c->channo * im->ysize];
c->rleoffset -= SGI_HEADER_SIZE; c->rleoffset -= SGI_HEADER_SIZE;
@ -192,11 +181,20 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
} }
/* row decompression */ /* row decompression */
if (c->bpc ==1) { if (c->bpc == 1) {
status = expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize); status = expandrow(
} &state->buffer[c->channo],
else { &ptr[c->rleoffset],
status = expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize); c->rlelength,
im->bands,
im->xsize);
} else {
status = expandrow2(
&state->buffer[c->channo * 2],
&ptr[c->rleoffset],
c->rlelength,
im->bands,
im->xsize);
} }
if (status == -1) { if (status == -1) {
state->errcode = IMAGING_CODEC_OVERRUN; state->errcode = IMAGING_CODEC_OVERRUN;
@ -209,19 +207,18 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
} }
/* store decompressed data in image */ /* store decompressed data in image */
state->shuffle((UINT8*)im->image[state->y], state->buffer, im->xsize); state->shuffle((UINT8 *)im->image[state->y], state->buffer, im->xsize);
} }
c->bufsize++; c->bufsize++;
sgi_finish_decode: ; sgi_finish_decode:;
free(c->starttab); free(c->starttab);
free(c->lengthtab); free(c->lengthtab);
free(ptr); free(ptr);
if (err != 0){ if (err != 0) {
state->errcode=err; state->errcode = err;
return -1; return -1;
} }
return state->count - c->bufsize; return state->count - c->bufsize;

View File

@ -34,11 +34,9 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#include <string.h> #include <string.h>
int ImagingNewCount = 0; int ImagingNewCount = 0;
/* -------------------------------------------------------------------- /* --------------------------------------------------------------------
@ -46,18 +44,17 @@ int ImagingNewCount = 0;
*/ */
Imaging Imaging
ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size) ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size) {
{
Imaging im; Imaging im;
/* linesize overflow check, roughly the current largest space req'd */ /* linesize overflow check, roughly the current largest space req'd */
if (xsize > (INT_MAX / 4) - 1) { if (xsize > (INT_MAX / 4) - 1) {
return (Imaging) ImagingError_MemoryError(); return (Imaging)ImagingError_MemoryError();
} }
im = (Imaging) calloc(1, size); im = (Imaging)calloc(1, size);
if (!im) { if (!im) {
return (Imaging) ImagingError_MemoryError(); return (Imaging)ImagingError_MemoryError();
} }
/* Setup image descriptor */ /* Setup image descriptor */
@ -115,8 +112,9 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size)
im->linesize = xsize * 4; im->linesize = xsize * 4;
im->type = IMAGING_TYPE_INT32; im->type = IMAGING_TYPE_INT32;
} else if (strcmp(mode, "I;16") == 0 || strcmp(mode, "I;16L") == 0 \ } else if (
|| strcmp(mode, "I;16B") == 0 || strcmp(mode, "I;16N") == 0) { strcmp(mode, "I;16") == 0 || strcmp(mode, "I;16L") == 0 ||
strcmp(mode, "I;16B") == 0 || strcmp(mode, "I;16N") == 0) {
/* EXPERIMENTAL */ /* EXPERIMENTAL */
/* 16-bit raw integer images */ /* 16-bit raw integer images */
im->bands = 1; im->bands = 1;
@ -135,7 +133,7 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size)
/* 15-bit reversed true colour */ /* 15-bit reversed true colour */
im->bands = 1; im->bands = 1;
im->pixelsize = 2; im->pixelsize = 2;
im->linesize = (xsize*2 + 3) & -4; im->linesize = (xsize * 2 + 3) & -4;
im->type = IMAGING_TYPE_SPECIAL; im->type = IMAGING_TYPE_SPECIAL;
} else if (strcmp(mode, "BGR;16") == 0) { } else if (strcmp(mode, "BGR;16") == 0) {
@ -143,7 +141,7 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size)
/* 16-bit reversed true colour */ /* 16-bit reversed true colour */
im->bands = 1; im->bands = 1;
im->pixelsize = 2; im->pixelsize = 2;
im->linesize = (xsize*2 + 3) & -4; im->linesize = (xsize * 2 + 3) & -4;
im->type = IMAGING_TYPE_SPECIAL; im->type = IMAGING_TYPE_SPECIAL;
} else if (strcmp(mode, "BGR;24") == 0) { } else if (strcmp(mode, "BGR;24") == 0) {
@ -151,7 +149,7 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size)
/* 24-bit reversed true colour */ /* 24-bit reversed true colour */
im->bands = 1; im->bands = 1;
im->pixelsize = 3; im->pixelsize = 3;
im->linesize = (xsize*3 + 3) & -4; im->linesize = (xsize * 3 + 3) & -4;
im->type = IMAGING_TYPE_SPECIAL; im->type = IMAGING_TYPE_SPECIAL;
} else if (strcmp(mode, "BGR;32") == 0) { } else if (strcmp(mode, "BGR;32") == 0) {
@ -159,7 +157,7 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size)
/* 32-bit reversed true colour */ /* 32-bit reversed true colour */
im->bands = 1; im->bands = 1;
im->pixelsize = 4; im->pixelsize = 4;
im->linesize = (xsize*4 + 3) & -4; im->linesize = (xsize * 4 + 3) & -4;
im->type = IMAGING_TYPE_SPECIAL; im->type = IMAGING_TYPE_SPECIAL;
} else if (strcmp(mode, "RGBX") == 0) { } else if (strcmp(mode, "RGBX") == 0) {
@ -204,7 +202,7 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size)
} else { } else {
free(im); free(im);
return (Imaging) ImagingError_ValueError("unrecognized image mode"); return (Imaging)ImagingError_ValueError("unrecognized image mode");
} }
/* Setup image descriptor */ /* Setup image descriptor */
@ -212,21 +210,23 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size)
/* Pointer array (allocate at least one line, to avoid MemoryError /* Pointer array (allocate at least one line, to avoid MemoryError
exceptions on platforms where calloc(0, x) returns NULL) */ exceptions on platforms where calloc(0, x) returns NULL) */
im->image = (char **) calloc((ysize > 0) ? ysize : 1, sizeof(void *)); im->image = (char **)calloc((ysize > 0) ? ysize : 1, sizeof(void *));
if ( ! im->image) { if (!im->image) {
free(im); free(im);
return (Imaging) ImagingError_MemoryError(); return (Imaging)ImagingError_MemoryError();
} }
/* Initialize alias pointers to pixel data. */ /* Initialize alias pointers to pixel data. */
switch (im->pixelsize) { switch (im->pixelsize) {
case 1: case 2: case 3: case 1:
im->image8 = (UINT8 **) im->image; case 2:
break; case 3:
case 4: im->image8 = (UINT8 **)im->image;
im->image32 = (INT32 **) im->image; break;
break; case 4:
im->image32 = (INT32 **)im->image;
break;
} }
ImagingDefaultArena.stats_new_count += 1; ImagingDefaultArena.stats_new_count += 1;
@ -235,15 +235,13 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size)
} }
Imaging Imaging
ImagingNewPrologue(const char *mode, int xsize, int ysize) ImagingNewPrologue(const char *mode, int xsize, int ysize) {
{
return ImagingNewPrologueSubtype( return ImagingNewPrologueSubtype(
mode, xsize, ysize, sizeof(struct ImagingMemoryInstance)); mode, xsize, ysize, sizeof(struct ImagingMemoryInstance));
} }
void void
ImagingDelete(Imaging im) ImagingDelete(Imaging im) {
{
if (!im) { if (!im) {
return; return;
} }
@ -263,7 +261,6 @@ ImagingDelete(Imaging im)
free(im); free(im);
} }
/* Array Storage Type */ /* Array Storage Type */
/* ------------------ */ /* ------------------ */
/* Allocate image as an array of line buffers. */ /* Allocate image as an array of line buffers. */
@ -271,17 +268,20 @@ ImagingDelete(Imaging im)
#define IMAGING_PAGE_SIZE (4096) #define IMAGING_PAGE_SIZE (4096)
struct ImagingMemoryArena ImagingDefaultArena = { struct ImagingMemoryArena ImagingDefaultArena = {
1, // alignment 1, // alignment
16*1024*1024, // block_size 16 * 1024 * 1024, // block_size
0, // blocks_max 0, // blocks_max
0, // blocks_cached 0, // blocks_cached
NULL, // blocks_pool NULL, // blocks_pool
0, 0, 0, 0, 0 // Stats 0,
0,
0,
0,
0 // Stats
}; };
int int
ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max) ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max) {
{
void *p; void *p;
/* Free already cached blocks */ /* Free already cached blocks */
ImagingMemoryClearCache(arena, blocks_max); ImagingMemoryClearCache(arena, blocks_max);
@ -291,14 +291,14 @@ ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max)
arena->blocks_pool = NULL; arena->blocks_pool = NULL;
} else if (arena->blocks_pool != NULL) { } else if (arena->blocks_pool != NULL) {
p = realloc(arena->blocks_pool, sizeof(*arena->blocks_pool) * blocks_max); p = realloc(arena->blocks_pool, sizeof(*arena->blocks_pool) * blocks_max);
if ( ! p) { if (!p) {
// Leave previous blocks_max value // Leave previous blocks_max value
return 0; return 0;
} }
arena->blocks_pool = p; arena->blocks_pool = p;
} else { } else {
arena->blocks_pool = calloc(sizeof(*arena->blocks_pool), blocks_max); arena->blocks_pool = calloc(sizeof(*arena->blocks_pool), blocks_max);
if ( ! arena->blocks_pool) { if (!arena->blocks_pool) {
return 0; return 0;
} }
} }
@ -308,8 +308,7 @@ ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max)
} }
void void
ImagingMemoryClearCache(ImagingMemoryArena arena, int new_size) ImagingMemoryClearCache(ImagingMemoryArena arena, int new_size) {
{
while (arena->blocks_cached > new_size) { while (arena->blocks_cached > new_size) {
arena->blocks_cached -= 1; arena->blocks_cached -= 1;
free(arena->blocks_pool[arena->blocks_cached].ptr); free(arena->blocks_pool[arena->blocks_cached].ptr);
@ -318,8 +317,7 @@ ImagingMemoryClearCache(ImagingMemoryArena arena, int new_size)
} }
ImagingMemoryBlock ImagingMemoryBlock
memory_get_block(ImagingMemoryArena arena, int requested_size, int dirty) memory_get_block(ImagingMemoryArena arena, int requested_size, int dirty) {
{
ImagingMemoryBlock block = {NULL, 0}; ImagingMemoryBlock block = {NULL, 0};
if (arena->blocks_cached > 0) { if (arena->blocks_cached > 0) {
@ -327,16 +325,16 @@ memory_get_block(ImagingMemoryArena arena, int requested_size, int dirty)
arena->blocks_cached -= 1; arena->blocks_cached -= 1;
block = arena->blocks_pool[arena->blocks_cached]; block = arena->blocks_pool[arena->blocks_cached];
// Reallocate if needed // Reallocate if needed
if (block.size != requested_size){ if (block.size != requested_size) {
block.ptr = realloc(block.ptr, requested_size); block.ptr = realloc(block.ptr, requested_size);
} }
if ( ! block.ptr) { if (!block.ptr) {
// Can't allocate, free previous pointer (it is still valid) // Can't allocate, free previous pointer (it is still valid)
free(arena->blocks_pool[arena->blocks_cached].ptr); free(arena->blocks_pool[arena->blocks_cached].ptr);
arena->stats_freed_blocks += 1; arena->stats_freed_blocks += 1;
return block; return block;
} }
if ( ! dirty) { if (!dirty) {
memset(block.ptr, 0, requested_size); memset(block.ptr, 0, requested_size);
} }
arena->stats_reused_blocks += 1; arena->stats_reused_blocks += 1;
@ -356,9 +354,8 @@ memory_get_block(ImagingMemoryArena arena, int requested_size, int dirty)
} }
void void
memory_return_block(ImagingMemoryArena arena, ImagingMemoryBlock block) memory_return_block(ImagingMemoryArena arena, ImagingMemoryBlock block) {
{ if (arena->blocks_cached < arena->blocks_max) {
if (arena->blocks_cached < arena->blocks_max) {
// Reduce block size // Reduce block size
if (block.size > arena->block_size) { if (block.size > arena->block_size) {
block.size = arena->block_size; block.size = arena->block_size;
@ -372,15 +369,13 @@ memory_return_block(ImagingMemoryArena arena, ImagingMemoryBlock block)
} }
} }
static void static void
ImagingDestroyArray(Imaging im) ImagingDestroyArray(Imaging im) {
{
int y = 0; int y = 0;
if (im->blocks) { if (im->blocks) {
while (im->blocks[y].ptr) { while (im->blocks[y].ptr) {
memory_return_block(&ImagingDefaultArena, im->blocks[y]); memory_return_block(&ImagingDefaultArena, im->blocks[y]);
y += 1; y += 1;
} }
free(im->blocks); free(im->blocks);
@ -388,8 +383,7 @@ ImagingDestroyArray(Imaging im)
} }
Imaging Imaging
ImagingAllocateArray(Imaging im, int dirty, int block_size) ImagingAllocateArray(Imaging im, int dirty, int block_size) {
{
int y, line_in_block, current_block; int y, line_in_block, current_block;
ImagingMemoryArena arena = &ImagingDefaultArena; ImagingMemoryArena arena = &ImagingDefaultArena;
ImagingMemoryBlock block = {NULL, 0}; ImagingMemoryBlock block = {NULL, 0};
@ -397,7 +391,7 @@ ImagingAllocateArray(Imaging im, int dirty, int block_size)
char *aligned_ptr = NULL; char *aligned_ptr = NULL;
/* 0-width or 0-height image. No need to do anything */ /* 0-width or 0-height image. No need to do anything */
if ( ! im->linesize || ! im->ysize) { if (!im->linesize || !im->ysize) {
return im; return im;
} }
@ -412,8 +406,8 @@ ImagingAllocateArray(Imaging im, int dirty, int block_size)
/* One extra pointer is always NULL */ /* One extra pointer is always NULL */
im->blocks = calloc(sizeof(*im->blocks), blocks_count + 1); im->blocks = calloc(sizeof(*im->blocks), blocks_count + 1);
if ( ! im->blocks) { if (!im->blocks) {
return (Imaging) ImagingError_MemoryError(); return (Imaging)ImagingError_MemoryError();
} }
/* Allocate image as an array of lines */ /* Allocate image as an array of lines */
@ -428,9 +422,9 @@ ImagingAllocateArray(Imaging im, int dirty, int block_size)
} }
required = lines_remaining * aligned_linesize + arena->alignment - 1; required = lines_remaining * aligned_linesize + arena->alignment - 1;
block = memory_get_block(arena, required, dirty); block = memory_get_block(arena, required, dirty);
if ( ! block.ptr) { if (!block.ptr) {
ImagingDestroyArray(im); ImagingDestroyArray(im);
return (Imaging) ImagingError_MemoryError(); return (Imaging)ImagingError_MemoryError();
} }
im->blocks[current_block] = block; im->blocks[current_block] = block;
/* Bulletproof code from libc _int_memalign */ /* Bulletproof code from libc _int_memalign */
@ -454,42 +448,38 @@ ImagingAllocateArray(Imaging im, int dirty, int block_size)
return im; return im;
} }
/* Block Storage Type */ /* Block Storage Type */
/* ------------------ */ /* ------------------ */
/* Allocate image as a single block. */ /* Allocate image as a single block. */
static void static void
ImagingDestroyBlock(Imaging im) ImagingDestroyBlock(Imaging im) {
{
if (im->block) { if (im->block) {
free(im->block); free(im->block);
} }
} }
Imaging Imaging
ImagingAllocateBlock(Imaging im) ImagingAllocateBlock(Imaging im) {
{
Py_ssize_t y, i; Py_ssize_t y, i;
/* overflow check for malloc */ /* overflow check for malloc */
if (im->linesize && if (im->linesize && im->ysize > INT_MAX / im->linesize) {
im->ysize > INT_MAX / im->linesize) { return (Imaging)ImagingError_MemoryError();
return (Imaging) ImagingError_MemoryError();
} }
if (im->ysize * im->linesize <= 0) { if (im->ysize * im->linesize <= 0) {
/* some platforms return NULL for malloc(0); this fix /* some platforms return NULL for malloc(0); this fix
prevents MemoryError on zero-sized images on such prevents MemoryError on zero-sized images on such
platforms */ platforms */
im->block = (char *) malloc(1); im->block = (char *)malloc(1);
} else { } else {
/* malloc check ok, overflow check above */ /* malloc check ok, overflow check above */
im->block = (char *) calloc(im->ysize, im->linesize); im->block = (char *)calloc(im->ysize, im->linesize);
} }
if ( ! im->block) { if (!im->block) {
return (Imaging) ImagingError_MemoryError(); return (Imaging)ImagingError_MemoryError();
} }
for (y = i = 0; y < im->ysize; y++) { for (y = i = 0; y < im->ysize; y++) {
@ -507,16 +497,15 @@ ImagingAllocateBlock(Imaging im)
*/ */
Imaging Imaging
ImagingNewInternal(const char* mode, int xsize, int ysize, int dirty) ImagingNewInternal(const char *mode, int xsize, int ysize, int dirty) {
{
Imaging im; Imaging im;
if (xsize < 0 || ysize < 0) { if (xsize < 0 || ysize < 0) {
return (Imaging) ImagingError_ValueError("bad image size"); return (Imaging)ImagingError_ValueError("bad image size");
} }
im = ImagingNewPrologue(mode, xsize, ysize); im = ImagingNewPrologue(mode, xsize, ysize);
if ( ! im) { if (!im) {
return NULL; return NULL;
} }
@ -536,28 +525,25 @@ ImagingNewInternal(const char* mode, int xsize, int ysize, int dirty)
} }
Imaging Imaging
ImagingNew(const char* mode, int xsize, int ysize) ImagingNew(const char *mode, int xsize, int ysize) {
{
return ImagingNewInternal(mode, xsize, ysize, 0); return ImagingNewInternal(mode, xsize, ysize, 0);
} }
Imaging Imaging
ImagingNewDirty(const char* mode, int xsize, int ysize) ImagingNewDirty(const char *mode, int xsize, int ysize) {
{
return ImagingNewInternal(mode, xsize, ysize, 1); return ImagingNewInternal(mode, xsize, ysize, 1);
} }
Imaging Imaging
ImagingNewBlock(const char* mode, int xsize, int ysize) ImagingNewBlock(const char *mode, int xsize, int ysize) {
{
Imaging im; Imaging im;
if (xsize < 0 || ysize < 0) { if (xsize < 0 || ysize < 0) {
return (Imaging) ImagingError_ValueError("bad image size"); return (Imaging)ImagingError_ValueError("bad image size");
} }
im = ImagingNewPrologue(mode, xsize, ysize); im = ImagingNewPrologue(mode, xsize, ysize);
if ( ! im) { if (!im) {
return NULL; return NULL;
} }
@ -570,15 +556,13 @@ ImagingNewBlock(const char* mode, int xsize, int ysize)
} }
Imaging Imaging
ImagingNew2Dirty(const char* mode, Imaging imOut, Imaging imIn) ImagingNew2Dirty(const char *mode, Imaging imOut, Imaging imIn) {
{
/* allocate or validate output image */ /* allocate or validate output image */
if (imOut) { if (imOut) {
/* make sure images match */ /* make sure images match */
if (strcmp(imOut->mode, mode) != 0 if (strcmp(imOut->mode, mode) != 0 || imOut->xsize != imIn->xsize ||
|| imOut->xsize != imIn->xsize imOut->ysize != imIn->ysize) {
|| imOut->ysize != imIn->ysize) {
return ImagingError_Mismatch(); return ImagingError_Mismatch();
} }
} else { } else {
@ -593,8 +577,7 @@ ImagingNew2Dirty(const char* mode, Imaging imOut, Imaging imIn)
} }
void void
ImagingCopyPalette(Imaging destination, Imaging source) ImagingCopyPalette(Imaging destination, Imaging source) {
{
if (source->palette) { if (source->palette) {
if (destination->palette) { if (destination->palette) {
ImagingPaletteDelete(destination->palette); ImagingPaletteDelete(destination->palette);

View File

@ -15,37 +15,30 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
int int
ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes) ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
{
int n; int n;
UINT8* ptr; UINT8 *ptr;
UINT8 extra_data = 0; UINT8 extra_data = 0;
UINT8 extra_bytes = 0; UINT8 extra_bytes = 0;
ptr = buf; ptr = buf;
for (;;) { for (;;) {
if (bytes < 1) { if (bytes < 1) {
return ptr - buf; return ptr - buf;
} }
if (ptr[0] == 0x80) { if (ptr[0] == 0x80) {
if (bytes < 2) { if (bytes < 2) {
break; break;
} }
n = ptr[1]; n = ptr[1];
if (n == 0) { if (n == 0) {
/* Literal 0x80 (2 bytes) */ /* Literal 0x80 (2 bytes) */
n = 1; n = 1;
@ -55,7 +48,6 @@ ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t
bytes -= 2; bytes -= 2;
} else { } else {
/* Run (3 bytes) */ /* Run (3 bytes) */
if (bytes < 3) { if (bytes < 3) {
break; break;
@ -84,7 +76,7 @@ ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t
n += 1; n += 1;
if (state->x + n > state->bytes) { if (state->x + n > state->bytes) {
extra_bytes = n; /* full value */ extra_bytes = n; /* full value */
n = state->bytes - state->x; n = state->bytes - state->x;
extra_bytes -= n; extra_bytes -= n;
extra_data = ptr[2]; extra_data = ptr[2];
@ -94,11 +86,9 @@ ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t
ptr += 3; ptr += 3;
bytes -= 3; bytes -= 3;
} }
} else { } else {
/* Literal byte */ /* Literal byte */
n = 1; n = 1;
@ -106,18 +96,18 @@ ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t
ptr += 1; ptr += 1;
bytes -= 1; bytes -= 1;
} }
for (;;) { for (;;) {
state->x += n; state->x += n;
if (state->x >= state->bytes) { if (state->x >= state->bytes) {
/* Got a full line, unpack it */ /* Got a full line, unpack it */
state->shuffle((UINT8*) im->image[state->y + state->yoff] + state->shuffle(
state->xoff * im->pixelsize, state->buffer, (UINT8 *)im->image[state->y + state->yoff] +
state->xsize); state->xoff * im->pixelsize,
state->buffer,
state->xsize);
state->x = 0; state->x = 0;
@ -132,7 +122,7 @@ ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t
} }
if (state->x > 0) { if (state->x > 0) {
break; // assert break; // assert
} }
if (extra_bytes >= state->bytes) { if (extra_bytes >= state->bytes) {

View File

@ -14,43 +14,35 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
int int
ImagingTgaRleDecode(Imaging im, ImagingCodecState state, ImagingTgaRleDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
UINT8* buf, Py_ssize_t bytes)
{
int n, depth; int n, depth;
UINT8* ptr; UINT8 *ptr;
ptr = buf; ptr = buf;
if (state->state == 0) { if (state->state == 0) {
/* check image orientation */ /* check image orientation */
if (state->ystep < 0) { if (state->ystep < 0) {
state->y = state->ysize-1; state->y = state->ysize - 1;
state->ystep = -1; state->ystep = -1;
} else { } else {
state->ystep = 1; state->ystep = 1;
} }
state->state = 1; state->state = 1;
} }
depth = state->count; depth = state->count;
for (;;) { for (;;) {
if (bytes < 1) { if (bytes < 1) {
return ptr - buf; return ptr - buf;
} }
if (ptr[0] & 0x80) { if (ptr[0] & 0x80) {
/* Run (1 + pixelsize bytes) */ /* Run (1 + pixelsize bytes) */
if (bytes < 1 + depth) { if (bytes < 1 + depth) {
@ -69,7 +61,7 @@ ImagingTgaRleDecode(Imaging im, ImagingCodecState state,
} else { } else {
int i; int i;
for (i = 0; i < n; i += depth) { for (i = 0; i < n; i += depth) {
memcpy(state->buffer + state->x + i, ptr+1, depth); memcpy(state->buffer + state->x + i, ptr + 1, depth);
} }
} }
@ -77,7 +69,6 @@ ImagingTgaRleDecode(Imaging im, ImagingCodecState state,
bytes -= 1 + depth; bytes -= 1 + depth;
} else { } else {
/* Literal (1+n+1 bytes block) */ /* Literal (1+n+1 bytes block) */
n = depth * (ptr[0] + 1); n = depth * (ptr[0] + 1);
@ -94,17 +85,17 @@ ImagingTgaRleDecode(Imaging im, ImagingCodecState state,
ptr += 1 + n; ptr += 1 + n;
bytes -= 1 + n; bytes -= 1 + n;
} }
state->x += n; state->x += n;
if (state->x >= state->bytes) { if (state->x >= state->bytes) {
/* Got a full line, unpack it */ /* Got a full line, unpack it */
state->shuffle((UINT8*) im->image[state->y + state->yoff] + state->shuffle(
state->xoff * im->pixelsize, state->buffer, (UINT8 *)im->image[state->y + state->yoff] +
state->xsize); state->xoff * im->pixelsize,
state->buffer,
state->xsize);
state->x = 0; state->x = 0;
@ -114,9 +105,7 @@ ImagingTgaRleDecode(Imaging im, ImagingCodecState state,
/* End of file (errcode = 0) */ /* End of file (errcode = 0) */
return -1; return -1;
} }
} }
} }
return ptr - buf; return ptr - buf;

View File

@ -4,18 +4,15 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
static int
static int comparePixels(const UINT8* buf, int x, int bytesPerPixel) comparePixels(const UINT8 *buf, int x, int bytesPerPixel) {
{
buf += x * bytesPerPixel; buf += x * bytesPerPixel;
return memcmp(buf, buf + bytesPerPixel, bytesPerPixel) == 0; return memcmp(buf, buf + bytesPerPixel, bytesPerPixel) == 0;
} }
int int
ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
{ UINT8 *dst;
UINT8* dst;
int bytesPerPixel; int bytesPerPixel;
if (state->state == 0) { if (state->state == 0) {
@ -40,7 +37,7 @@ ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
* excluding the 1-byte descriptor. * excluding the 1-byte descriptor.
*/ */
if (state->count == 0) { if (state->count == 0) {
UINT8* row; UINT8 *row;
UINT8 descriptor; UINT8 descriptor;
int startX; int startX;
@ -64,8 +61,8 @@ ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
if (state->x == 0) { if (state->x == 0) {
state->shuffle( state->shuffle(
state->buffer, state->buffer,
(UINT8*)im->image[state->y + state->yoff] (UINT8 *)im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize, state->xoff * im->pixelsize,
state->xsize); state->xsize);
} }
@ -149,9 +146,7 @@ ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
} }
memcpy( memcpy(
dst, dst, state->buffer + (state->x * bytesPerPixel - state->count), flushCount);
state->buffer + (state->x * bytesPerPixel - state->count),
flushCount);
dst += flushCount; dst += flushCount;
bytes -= flushCount; bytes -= flushCount;

View File

@ -23,7 +23,8 @@
/* Convert C file descriptor to WinApi HFILE if LibTiff was compiled with tif_win32.c /* Convert C file descriptor to WinApi HFILE if LibTiff was compiled with tif_win32.c
* *
* This cast is safe, as the top 32-bits of HFILE are guaranteed to be zero, * This cast is safe, as the top 32-bits of HFILE are guaranteed to be zero,
* see https://docs.microsoft.com/en-us/windows/win32/winprog64/interprocess-communication * see
* https://docs.microsoft.com/en-us/windows/win32/winprog64/interprocess-communication
*/ */
#ifndef USE_WIN32_FILEIO #ifndef USE_WIN32_FILEIO
#define fd_to_tiff_fd(fd) (fd) #define fd_to_tiff_fd(fd) (fd)
@ -31,16 +32,23 @@
#define fd_to_tiff_fd(fd) ((int)_get_osfhandle(fd)) #define fd_to_tiff_fd(fd) ((int)_get_osfhandle(fd))
#endif #endif
void dump_state(const TIFFSTATE *state){ void
TRACE(("State: Location %u size %d eof %d data: %p ifd: %d\n", (uint)state->loc, dump_state(const TIFFSTATE *state) {
(int)state->size, (uint)state->eof, state->data, state->ifd)); TRACE(
("State: Location %u size %d eof %d data: %p ifd: %d\n",
(uint)state->loc,
(int)state->size,
(uint)state->eof,
state->data,
state->ifd));
} }
/* /*
procs for TIFFOpenClient procs for TIFFOpenClient
*/ */
tsize_t _tiffReadProc(thandle_t hdata, tdata_t buf, tsize_t size) { tsize_t
_tiffReadProc(thandle_t hdata, tdata_t buf, tsize_t size) {
TIFFSTATE *state = (TIFFSTATE *)hdata; TIFFSTATE *state = (TIFFSTATE *)hdata;
tsize_t to_read; tsize_t to_read;
@ -53,11 +61,12 @@ tsize_t _tiffReadProc(thandle_t hdata, tdata_t buf, tsize_t size) {
_TIFFmemcpy(buf, (UINT8 *)state->data + state->loc, to_read); _TIFFmemcpy(buf, (UINT8 *)state->data + state->loc, to_read);
state->loc += (toff_t)to_read; state->loc += (toff_t)to_read;
TRACE( ("location: %u\n", (uint)state->loc)); TRACE(("location: %u\n", (uint)state->loc));
return to_read; return to_read;
} }
tsize_t _tiffWriteProc(thandle_t hdata, tdata_t buf, tsize_t size) { tsize_t
_tiffWriteProc(thandle_t hdata, tdata_t buf, tsize_t size) {
TIFFSTATE *state = (TIFFSTATE *)hdata; TIFFSTATE *state = (TIFFSTATE *)hdata;
tsize_t to_write; tsize_t to_write;
@ -65,14 +74,14 @@ tsize_t _tiffWriteProc(thandle_t hdata, tdata_t buf, tsize_t size) {
dump_state(state); dump_state(state);
to_write = min(size, state->size - (tsize_t)state->loc); to_write = min(size, state->size - (tsize_t)state->loc);
if (state->flrealloc && size>to_write) { if (state->flrealloc && size > to_write) {
tdata_t new_data; tdata_t new_data;
tsize_t newsize=state->size; tsize_t newsize = state->size;
while (newsize < (size + state->size)) { while (newsize < (size + state->size)) {
if (newsize > INT_MAX - 64*1024){ if (newsize > INT_MAX - 64 * 1024) {
return 0; return 0;
} }
newsize += 64*1024; newsize += 64 * 1024;
// newsize*=2; // UNDONE, by 64k chunks? // newsize*=2; // UNDONE, by 64k chunks?
} }
TRACE(("Reallocing in write to %d bytes\n", (int)newsize)); TRACE(("Reallocing in write to %d bytes\n", (int)newsize));
@ -97,27 +106,29 @@ tsize_t _tiffWriteProc(thandle_t hdata, tdata_t buf, tsize_t size) {
return to_write; return to_write;
} }
toff_t _tiffSeekProc(thandle_t hdata, toff_t off, int whence) { toff_t
_tiffSeekProc(thandle_t hdata, toff_t off, int whence) {
TIFFSTATE *state = (TIFFSTATE *)hdata; TIFFSTATE *state = (TIFFSTATE *)hdata;
TRACE(("_tiffSeekProc: off: %u whence: %d \n", (uint)off, whence)); TRACE(("_tiffSeekProc: off: %u whence: %d \n", (uint)off, whence));
dump_state(state); dump_state(state);
switch (whence) { switch (whence) {
case 0: case 0:
state->loc = off; state->loc = off;
break; break;
case 1: case 1:
state->loc += off; state->loc += off;
break; break;
case 2: case 2:
state->loc = state->eof + off; state->loc = state->eof + off;
break; break;
} }
dump_state(state); dump_state(state);
return state->loc; return state->loc;
} }
int _tiffCloseProc(thandle_t hdata) { int
_tiffCloseProc(thandle_t hdata) {
TIFFSTATE *state = (TIFFSTATE *)hdata; TIFFSTATE *state = (TIFFSTATE *)hdata;
TRACE(("_tiffCloseProc \n")); TRACE(("_tiffCloseProc \n"));
@ -126,8 +137,8 @@ int _tiffCloseProc(thandle_t hdata) {
return 0; return 0;
} }
toff_t
toff_t _tiffSizeProc(thandle_t hdata) { _tiffSizeProc(thandle_t hdata) {
TIFFSTATE *state = (TIFFSTATE *)hdata; TIFFSTATE *state = (TIFFSTATE *)hdata;
TRACE(("_tiffSizeProc \n")); TRACE(("_tiffSizeProc \n"));
@ -136,7 +147,8 @@ toff_t _tiffSizeProc(thandle_t hdata) {
return (toff_t)state->size; return (toff_t)state->size;
} }
int _tiffMapProc(thandle_t hdata, tdata_t* pbase, toff_t* psize) { int
_tiffMapProc(thandle_t hdata, tdata_t *pbase, toff_t *psize) {
TIFFSTATE *state = (TIFFSTATE *)hdata; TIFFSTATE *state = (TIFFSTATE *)hdata;
TRACE(("_tiffMapProc input size: %u, data: %p\n", (uint)*psize, *pbase)); TRACE(("_tiffMapProc input size: %u, data: %p\n", (uint)*psize, *pbase));
@ -148,25 +160,41 @@ int _tiffMapProc(thandle_t hdata, tdata_t* pbase, toff_t* psize) {
return (1); return (1);
} }
int _tiffNullMapProc(thandle_t hdata, tdata_t* pbase, toff_t* psize) { int
(void) hdata; (void) pbase; (void) psize; _tiffNullMapProc(thandle_t hdata, tdata_t *pbase, toff_t *psize) {
(void)hdata;
(void)pbase;
(void)psize;
return (0); return (0);
} }
void _tiffUnmapProc(thandle_t hdata, tdata_t base, toff_t size) { void
_tiffUnmapProc(thandle_t hdata, tdata_t base, toff_t size) {
TRACE(("_tiffUnMapProc\n")); TRACE(("_tiffUnMapProc\n"));
(void) hdata; (void) base; (void) size; (void)hdata;
(void)base;
(void)size;
} }
int ImagingLibTiffInit(ImagingCodecState state, int fp, uint32 offset) { int
ImagingLibTiffInit(ImagingCodecState state, int fp, uint32 offset) {
TIFFSTATE *clientstate = (TIFFSTATE *)state->context; TIFFSTATE *clientstate = (TIFFSTATE *)state->context;
TRACE(("initing libtiff\n")); TRACE(("initing libtiff\n"));
TRACE(("filepointer: %d \n", fp)); TRACE(("filepointer: %d \n", fp));
TRACE(("State: count %d, state %d, x %d, y %d, ystep %d\n", state->count, state->state, TRACE(
state->x, state->y, state->ystep)); ("State: count %d, state %d, x %d, y %d, ystep %d\n",
TRACE(("State: xsize %d, ysize %d, xoff %d, yoff %d \n", state->xsize, state->ysize, state->count,
state->xoff, state->yoff)); state->state,
state->x,
state->y,
state->ystep));
TRACE(
("State: xsize %d, ysize %d, xoff %d, yoff %d \n",
state->xsize,
state->ysize,
state->xoff,
state->yoff));
TRACE(("State: bits %d, bytes %d \n", state->bits, state->bytes)); TRACE(("State: bits %d, bytes %d \n", state->bits, state->bytes));
TRACE(("State: context %p \n", state->context)); TRACE(("State: context %p \n", state->context));
@ -180,12 +208,12 @@ int ImagingLibTiffInit(ImagingCodecState state, int fp, uint32 offset) {
return 1; return 1;
} }
int
int _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) { _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
// To avoid dealing with YCbCr subsampling, let libtiff handle it // To avoid dealing with YCbCr subsampling, let libtiff handle it
// Use a TIFFRGBAImage wrapping the tiff image, and let libtiff handle // Use a TIFFRGBAImage wrapping the tiff image, and let libtiff handle
// all of the conversion. Metadata read from the TIFFRGBAImage could // all of the conversion. Metadata read from the TIFFRGBAImage could
// be different from the metadata that the base tiff returns. // be different from the metadata that the base tiff returns.
INT32 strip_row; INT32 strip_row;
UINT8 *new_data; UINT8 *new_data;
@ -211,8 +239,12 @@ int _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
img.col_offset = 0; img.col_offset = 0;
if (state->xsize != img.width || state->ysize != img.height) { if (state->xsize != img.width || state->ysize != img.height) {
TRACE(("Inconsistent Image Error: %d =? %d, %d =? %d", TRACE(
state->xsize, img.width, state->ysize, img.height)); ("Inconsistent Image Error: %d =? %d, %d =? %d",
state->xsize,
img.width,
state->ysize,
img.height));
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
goto decodeycbcr_err; goto decodeycbcr_err;
} }
@ -221,9 +253,9 @@ int _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
if (INT_MAX / 4 < img.width) { if (INT_MAX / 4 < img.width) {
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
goto decodeycbcr_err; goto decodeycbcr_err;
} }
// TiffRGBAImages are 32bits/pixel. // TiffRGBAImages are 32bits/pixel.
row_byte_size = img.width * 4; row_byte_size = img.width * 4;
/* overflow check for realloc */ /* overflow check for realloc */
@ -238,7 +270,7 @@ int _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
/* realloc to fit whole strip */ /* realloc to fit whole strip */
/* malloc check above */ /* malloc check above */
new_data = realloc (state->buffer, state->bytes); new_data = realloc(state->buffer, state->bytes);
if (!new_data) { if (!new_data) {
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
goto decodeycbcr_err; goto decodeycbcr_err;
@ -247,11 +279,12 @@ int _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
state->buffer = new_data; state->buffer = new_data;
for (; state->y < state->ysize; state->y += rows_per_strip) { for (; state->y < state->ysize; state->y += rows_per_strip) {
img.row_offset = state->y; img.row_offset = state->y;
rows_to_read = min(rows_per_strip, img.height - state->y); rows_to_read = min(rows_per_strip, img.height - state->y);
if (TIFFRGBAImageGet(&img, (UINT32 *)state->buffer, img.width, rows_to_read) == -1) { if (TIFFRGBAImageGet(&img, (UINT32 *)state->buffer, img.width, rows_to_read) ==
TRACE(("Decode Error, y: %d\n", state->y )); -1) {
TRACE(("Decode Error, y: %d\n", state->y));
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
goto decodeycbcr_err; goto decodeycbcr_err;
} }
@ -259,20 +292,24 @@ int _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
TRACE(("Decoded strip for row %d \n", state->y)); TRACE(("Decoded strip for row %d \n", state->y));
// iterate over each row in the strip and stuff data into image // iterate over each row in the strip and stuff data into image
for (strip_row = 0; strip_row < min((INT32) rows_per_strip, state->ysize - state->y); strip_row++) { for (strip_row = 0;
strip_row < min((INT32)rows_per_strip, state->ysize - state->y);
strip_row++) {
TRACE(("Writing data into line %d ; \n", state->y + strip_row)); TRACE(("Writing data into line %d ; \n", state->y + strip_row));
// UINT8 * bbb = state->buffer + strip_row * (state->bytes / rows_per_strip); // UINT8 * bbb = state->buffer + strip_row * (state->bytes /
// TRACE(("chars: %x %x %x %x\n", ((UINT8 *)bbb)[0], ((UINT8 *)bbb)[1], ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3])); // rows_per_strip); TRACE(("chars: %x %x %x %x\n", ((UINT8 *)bbb)[0],
// ((UINT8 *)bbb)[1], ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3]));
state->shuffle((UINT8*) im->image[state->y + state->yoff + strip_row] + state->shuffle(
state->xoff * im->pixelsize, (UINT8 *)im->image[state->y + state->yoff + strip_row] +
state->buffer + strip_row * row_byte_size, state->xoff * im->pixelsize,
state->xsize); state->buffer + strip_row * row_byte_size,
state->xsize);
} }
} }
decodeycbcr_err: decodeycbcr_err:
TIFFRGBAImageEnd(&img); TIFFRGBAImageEnd(&img);
if (state->errcode != 0) { if (state->errcode != 0) {
return -1; return -1;
@ -280,7 +317,8 @@ int _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
return 0; return 0;
} }
int _decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff) { int
_decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff) {
INT32 strip_row; INT32 strip_row;
UINT8 *new_data; UINT8 *new_data;
UINT32 rows_per_strip, row_byte_size; UINT32 rows_per_strip, row_byte_size;
@ -307,7 +345,8 @@ int _decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff) {
if (TIFFStripSize(tiff) > state->bytes) { if (TIFFStripSize(tiff) > state->bytes) {
// If the strip size as expected by LibTiff isn't what we're expecting, abort. // If the strip size as expected by LibTiff isn't what we're expecting, abort.
// man: TIFFStripSize returns the equivalent size for a strip of data as it would be returned in a // man: TIFFStripSize returns the equivalent size for a strip of data as it
// would be returned in a
// call to TIFFReadEncodedStrip ... // call to TIFFReadEncodedStrip ...
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
@ -316,7 +355,7 @@ int _decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff) {
/* realloc to fit whole strip */ /* realloc to fit whole strip */
/* malloc check above */ /* malloc check above */
new_data = realloc (state->buffer, state->bytes); new_data = realloc(state->buffer, state->bytes);
if (!new_data) { if (!new_data) {
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
return -1; return -1;
@ -325,7 +364,11 @@ int _decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff) {
state->buffer = new_data; state->buffer = new_data;
for (; state->y < state->ysize; state->y += rows_per_strip) { for (; state->y < state->ysize; state->y += rows_per_strip) {
if (TIFFReadEncodedStrip(tiff, TIFFComputeStrip(tiff, state->y, 0), (tdata_t)state->buffer, -1) == -1) { if (TIFFReadEncodedStrip(
tiff,
TIFFComputeStrip(tiff, state->y, 0),
(tdata_t)state->buffer,
-1) == -1) {
TRACE(("Decode Error, strip %d\n", TIFFComputeStrip(tiff, state->y, 0))); TRACE(("Decode Error, strip %d\n", TIFFComputeStrip(tiff, state->y, 0)));
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
return -1; return -1;
@ -334,46 +377,80 @@ int _decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff) {
TRACE(("Decoded strip for row %d \n", state->y)); TRACE(("Decoded strip for row %d \n", state->y));
// iterate over each row in the strip and stuff data into image // iterate over each row in the strip and stuff data into image
for (strip_row = 0; strip_row < min((INT32) rows_per_strip, state->ysize - state->y); strip_row++) { for (strip_row = 0;
strip_row < min((INT32)rows_per_strip, state->ysize - state->y);
strip_row++) {
TRACE(("Writing data into line %d ; \n", state->y + strip_row)); TRACE(("Writing data into line %d ; \n", state->y + strip_row));
// UINT8 * bbb = state->buffer + strip_row * (state->bytes / rows_per_strip); // UINT8 * bbb = state->buffer + strip_row * (state->bytes /
// TRACE(("chars: %x %x %x %x\n", ((UINT8 *)bbb)[0], ((UINT8 *)bbb)[1], ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3])); // rows_per_strip); TRACE(("chars: %x %x %x %x\n", ((UINT8 *)bbb)[0],
// ((UINT8 *)bbb)[1], ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3]));
state->shuffle((UINT8*) im->image[state->y + state->yoff + strip_row] + state->shuffle(
state->xoff * im->pixelsize, (UINT8 *)im->image[state->y + state->yoff + strip_row] +
state->buffer + strip_row * row_byte_size, state->xoff * im->pixelsize,
state->xsize); state->buffer + strip_row * row_byte_size,
state->xsize);
} }
} }
return 0; return 0;
} }
int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t bytes) { int
ImagingLibTiffDecode(
Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes) {
TIFFSTATE *clientstate = (TIFFSTATE *)state->context; TIFFSTATE *clientstate = (TIFFSTATE *)state->context;
char *filename = "tempfile.tif"; char *filename = "tempfile.tif";
char *mode = "r"; char *mode = "r";
TIFF *tiff; TIFF *tiff;
uint16 photometric = 0; // init to not PHOTOMETRIC_YCBCR uint16 photometric = 0; // init to not PHOTOMETRIC_YCBCR
int isYCbCr = 0; int isYCbCr = 0;
/* buffer is the encoded file, bytes is the length of the encoded file */ /* buffer is the encoded file, bytes is the length of the encoded file */
/* it all ends up in state->buffer, which is a uint8* from Imaging.h */ /* it all ends up in state->buffer, which is a uint8* from Imaging.h */
TRACE(("in decoder: bytes %d\n", bytes)); TRACE(("in decoder: bytes %d\n", bytes));
TRACE(("State: count %d, state %d, x %d, y %d, ystep %d\n", state->count, state->state, TRACE(
state->x, state->y, state->ystep)); ("State: count %d, state %d, x %d, y %d, ystep %d\n",
TRACE(("State: xsize %d, ysize %d, xoff %d, yoff %d \n", state->xsize, state->ysize, state->count,
state->xoff, state->yoff)); state->state,
state->x,
state->y,
state->ystep));
TRACE(
("State: xsize %d, ysize %d, xoff %d, yoff %d \n",
state->xsize,
state->ysize,
state->xoff,
state->yoff));
TRACE(("State: bits %d, bytes %d \n", state->bits, state->bytes)); TRACE(("State: bits %d, bytes %d \n", state->bits, state->bytes));
TRACE(("Buffer: %p: %c%c%c%c\n", buffer, (char)buffer[0], (char)buffer[1],(char)buffer[2], (char)buffer[3])); TRACE(
TRACE(("State->Buffer: %c%c%c%c\n", (char)state->buffer[0], (char)state->buffer[1],(char)state->buffer[2], (char)state->buffer[3])); ("Buffer: %p: %c%c%c%c\n",
TRACE(("Image: mode %s, type %d, bands: %d, xsize %d, ysize %d \n", buffer,
im->mode, im->type, im->bands, im->xsize, im->ysize)); (char)buffer[0],
TRACE(("Image: image8 %p, image32 %p, image %p, block %p \n", (char)buffer[1],
im->image8, im->image32, im->image, im->block)); (char)buffer[2],
TRACE(("Image: pixelsize: %d, linesize %d \n", (char)buffer[3]));
im->pixelsize, im->linesize)); TRACE(
("State->Buffer: %c%c%c%c\n",
(char)state->buffer[0],
(char)state->buffer[1],
(char)state->buffer[2],
(char)state->buffer[3]));
TRACE(
("Image: mode %s, type %d, bands: %d, xsize %d, ysize %d \n",
im->mode,
im->type,
im->bands,
im->xsize,
im->ysize));
TRACE(
("Image: image8 %p, image32 %p, image %p, block %p \n",
im->image8,
im->image32,
im->image,
im->block));
TRACE(("Image: pixelsize: %d, linesize %d \n", im->pixelsize, im->linesize));
dump_state(clientstate); dump_state(clientstate);
clientstate->size = bytes; clientstate->size = bytes;
@ -387,54 +464,59 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_
TIFFSetWarningHandlerExt(NULL); TIFFSetWarningHandlerExt(NULL);
if (clientstate->fp) { if (clientstate->fp) {
TRACE(("Opening using fd: %d\n",clientstate->fp)); TRACE(("Opening using fd: %d\n", clientstate->fp));
lseek(clientstate->fp,0,SEEK_SET); // Sometimes, I get it set to the end. lseek(clientstate->fp, 0, SEEK_SET); // Sometimes, I get it set to the end.
tiff = TIFFFdOpen(fd_to_tiff_fd(clientstate->fp), filename, mode); tiff = TIFFFdOpen(fd_to_tiff_fd(clientstate->fp), filename, mode);
} else { } else {
TRACE(("Opening from string\n")); TRACE(("Opening from string\n"));
tiff = TIFFClientOpen(filename, mode, tiff = TIFFClientOpen(
(thandle_t) clientstate, filename,
_tiffReadProc, _tiffWriteProc, mode,
_tiffSeekProc, _tiffCloseProc, _tiffSizeProc, (thandle_t)clientstate,
_tiffMapProc, _tiffUnmapProc); _tiffReadProc,
_tiffWriteProc,
_tiffSeekProc,
_tiffCloseProc,
_tiffSizeProc,
_tiffMapProc,
_tiffUnmapProc);
} }
if (!tiff){ if (!tiff) {
TRACE(("Error, didn't get the tiff\n")); TRACE(("Error, didn't get the tiff\n"));
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
return -1; return -1;
} }
if (clientstate->ifd){ if (clientstate->ifd) {
int rv; int rv;
uint32 ifdoffset = clientstate->ifd; uint32 ifdoffset = clientstate->ifd;
TRACE(("reading tiff ifd %u\n", ifdoffset)); TRACE(("reading tiff ifd %u\n", ifdoffset));
rv = TIFFSetSubDirectory(tiff, ifdoffset); rv = TIFFSetSubDirectory(tiff, ifdoffset);
if (!rv){ if (!rv) {
TRACE(("error in TIFFSetSubDirectory")); TRACE(("error in TIFFSetSubDirectory"));
goto decode_err; goto decode_err;
} }
} }
TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric); TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);
isYCbCr = photometric == PHOTOMETRIC_YCBCR; isYCbCr = photometric == PHOTOMETRIC_YCBCR;
if (TIFFIsTiled(tiff)) { if (TIFFIsTiled(tiff)) {
INT32 x, y, tile_y; INT32 x, y, tile_y;
UINT32 tile_width, tile_length, current_tile_length, current_line, current_tile_width, row_byte_size; UINT32 tile_width, tile_length, current_tile_length, current_line,
current_tile_width, row_byte_size;
UINT8 *new_data; UINT8 *new_data;
TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tile_width); TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tile_width);
TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tile_length); TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tile_length);
/* overflow check for row_byte_size calculation */ /* overflow check for row_byte_size calculation */
if ((UINT32) INT_MAX / state->bits < tile_width) { if ((UINT32)INT_MAX / state->bits < tile_width) {
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
goto decode_err; goto decode_err;
} }
if (isYCbCr) { if (isYCbCr) {
row_byte_size = tile_width * 4; row_byte_size = tile_width * 4;
/* sanity check, we use this value in shuffle below */ /* sanity check, we use this value in shuffle below */
@ -443,7 +525,8 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_
goto decode_err; goto decode_err;
} }
} else { } else {
// We could use TIFFTileSize, but for YCbCr data it returns subsampled data size // We could use TIFFTileSize, but for YCbCr data it returns subsampled data
// size
row_byte_size = (tile_width * state->bits + 7) / 8; row_byte_size = (tile_width * state->bits + 7) / 8;
} }
@ -456,14 +539,15 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_
state->bytes = row_byte_size * tile_length; state->bytes = row_byte_size * tile_length;
if (TIFFTileSize(tiff) > state->bytes) { if (TIFFTileSize(tiff) > state->bytes) {
// If the strip size as expected by LibTiff isn't what we're expecting, abort. // If the strip size as expected by LibTiff isn't what we're expecting,
// abort.
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
goto decode_err; goto decode_err;
} }
/* realloc to fit whole tile */ /* realloc to fit whole tile */
/* malloc check above */ /* malloc check above */
new_data = realloc (state->buffer, state->bytes); new_data = realloc(state->buffer, state->bytes);
if (!new_data) { if (!new_data) {
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
goto decode_err; goto decode_err;
@ -492,14 +576,19 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_
TRACE(("Read tile at %dx%d; \n\n", x, y)); TRACE(("Read tile at %dx%d; \n\n", x, y));
current_tile_width = min((INT32) tile_width, state->xsize - x); current_tile_width = min((INT32)tile_width, state->xsize - x);
current_tile_length = min((INT32) tile_length, state->ysize - y); current_tile_length = min((INT32)tile_length, state->ysize - y);
// iterate over each line in the tile and stuff data into image // iterate over each line in the tile and stuff data into image
for (tile_y = 0; tile_y < current_tile_length; tile_y++) { for (tile_y = 0; tile_y < current_tile_length; tile_y++) {
TRACE(("Writing tile data at %dx%d using tile_width: %d; \n", tile_y + y, x, current_tile_width)); TRACE(
("Writing tile data at %dx%d using tile_width: %d; \n",
tile_y + y,
x,
current_tile_width));
// UINT8 * bbb = state->buffer + tile_y * row_byte_size; // UINT8 * bbb = state->buffer + tile_y * row_byte_size;
// TRACE(("chars: %x%x%x%x\n", ((UINT8 *)bbb)[0], ((UINT8 *)bbb)[1], ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3])); // TRACE(("chars: %x%x%x%x\n", ((UINT8 *)bbb)[0], ((UINT8 *)bbb)[1],
// ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3]));
/* /*
* For some reason the TIFFReadRGBATile() function * For some reason the TIFFReadRGBATile() function
* chooses the lower left corner as the origin. * chooses the lower left corner as the origin.
@ -512,24 +601,23 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_
} else { } else {
current_line = tile_y; current_line = tile_y;
} }
state->shuffle((UINT8*) im->image[tile_y + y] + x * im->pixelsize, state->shuffle(
state->buffer + current_line * row_byte_size, (UINT8 *)im->image[tile_y + y] + x * im->pixelsize,
current_tile_width state->buffer + current_line * row_byte_size,
); current_tile_width);
} }
} }
} }
} else { } else {
if (!isYCbCr) { if (!isYCbCr) {
_decodeStrip(im, state, tiff); _decodeStrip(im, state, tiff);
} } else {
else {
_decodeStripYCbCr(im, state, tiff); _decodeStripYCbCr(im, state, tiff);
} }
} }
decode_err: decode_err:
TIFFClose(tiff); TIFFClose(tiff);
TRACE(("Done Decoding, Returning \n")); TRACE(("Done Decoding, Returning \n"));
// Returning -1 here to force ImageFile.load to break, rather than // Returning -1 here to force ImageFile.load to break, rather than
@ -537,7 +625,8 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_
return -1; return -1;
} }
int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp) { int
ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp) {
// Open the FD or the pointer as a tiff file, for writing. // Open the FD or the pointer as a tiff file, for writing.
// We may have to do some monkeying around to make this really work. // We may have to do some monkeying around to make this really work.
// If we have a fp, then we're good. // If we have a fp, then we're good.
@ -546,21 +635,30 @@ int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp) {
// Going to have to deal with the directory as well. // Going to have to deal with the directory as well.
TIFFSTATE *clientstate = (TIFFSTATE *)state->context; TIFFSTATE *clientstate = (TIFFSTATE *)state->context;
int bufsize = 64*1024; int bufsize = 64 * 1024;
char *mode = "w"; char *mode = "w";
TRACE(("initing libtiff\n")); TRACE(("initing libtiff\n"));
TRACE(("Filename %s, filepointer: %d \n", filename, fp)); TRACE(("Filename %s, filepointer: %d \n", filename, fp));
TRACE(("State: count %d, state %d, x %d, y %d, ystep %d\n", state->count, state->state, TRACE(
state->x, state->y, state->ystep)); ("State: count %d, state %d, x %d, y %d, ystep %d\n",
TRACE(("State: xsize %d, ysize %d, xoff %d, yoff %d \n", state->xsize, state->ysize, state->count,
state->xoff, state->yoff)); state->state,
state->x,
state->y,
state->ystep));
TRACE(
("State: xsize %d, ysize %d, xoff %d, yoff %d \n",
state->xsize,
state->ysize,
state->xoff,
state->yoff));
TRACE(("State: bits %d, bytes %d \n", state->bits, state->bytes)); TRACE(("State: bits %d, bytes %d \n", state->bits, state->bytes));
TRACE(("State: context %p \n", state->context)); TRACE(("State: context %p \n", state->context));
clientstate->loc = 0; clientstate->loc = 0;
clientstate->size = 0; clientstate->size = 0;
clientstate->eof =0; clientstate->eof = 0;
clientstate->data = 0; clientstate->data = 0;
clientstate->flrealloc = 0; clientstate->flrealloc = 0;
clientstate->fp = fp; clientstate->fp = fp;
@ -568,27 +666,33 @@ int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp) {
state->state = 0; state->state = 0;
if (fp) { if (fp) {
TRACE(("Opening using fd: %d for writing \n",clientstate->fp)); TRACE(("Opening using fd: %d for writing \n", clientstate->fp));
clientstate->tiff = TIFFFdOpen(fd_to_tiff_fd(clientstate->fp), filename, mode); clientstate->tiff = TIFFFdOpen(fd_to_tiff_fd(clientstate->fp), filename, mode);
} else { } else {
// malloc a buffer to write the tif, we're going to need to realloc or something if we need bigger. // malloc a buffer to write the tif, we're going to need to realloc or something
// if we need bigger.
TRACE(("Opening a buffer for writing \n")); TRACE(("Opening a buffer for writing \n"));
/* malloc check ok, small constant allocation */ /* malloc check ok, small constant allocation */
clientstate->data = malloc(bufsize); clientstate->data = malloc(bufsize);
clientstate->size = bufsize; clientstate->size = bufsize;
clientstate->flrealloc=1; clientstate->flrealloc = 1;
if (!clientstate->data) { if (!clientstate->data) {
TRACE(("Error, couldn't allocate a buffer of size %d\n", bufsize)); TRACE(("Error, couldn't allocate a buffer of size %d\n", bufsize));
return 0; return 0;
} }
clientstate->tiff = TIFFClientOpen(filename, mode, clientstate->tiff = TIFFClientOpen(
(thandle_t) clientstate, filename,
_tiffReadProc, _tiffWriteProc, mode,
_tiffSeekProc, _tiffCloseProc, _tiffSizeProc, (thandle_t)clientstate,
_tiffNullMapProc, _tiffUnmapProc); /*force no mmap*/ _tiffReadProc,
_tiffWriteProc,
_tiffSeekProc,
_tiffCloseProc,
_tiffSizeProc,
_tiffNullMapProc,
_tiffUnmapProc); /*force no mmap*/
} }
if (!clientstate->tiff) { if (!clientstate->tiff) {
@ -597,10 +701,11 @@ int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp) {
} }
return 1; return 1;
} }
int ImagingLibTiffMergeFieldInfo(ImagingCodecState state, TIFFDataType field_type, int key, int is_var_length){ int
ImagingLibTiffMergeFieldInfo(
ImagingCodecState state, TIFFDataType field_type, int key, int is_var_length) {
// Refer to libtiff docs (http://www.simplesystems.org/libtiff/addingtags.html) // Refer to libtiff docs (http://www.simplesystems.org/libtiff/addingtags.html)
TIFFSTATE *clientstate = (TIFFSTATE *)state->context; TIFFSTATE *clientstate = (TIFFSTATE *)state->context;
uint32 n; uint32 n;
@ -615,8 +720,14 @@ int ImagingLibTiffMergeFieldInfo(ImagingCodecState state, TIFFDataType field_typ
int passcount = 0; int passcount = 0;
TIFFFieldInfo info[] = { TIFFFieldInfo info[] = {
{ key, readcount, writecount, field_type, FIELD_CUSTOM, 1, passcount, "CustomField" } {key,
}; readcount,
writecount,
field_type,
FIELD_CUSTOM,
1,
passcount,
"CustomField"}};
if (is_var_length) { if (is_var_length) {
info[0].field_writecount = -1; info[0].field_writecount = -1;
@ -629,7 +740,8 @@ int ImagingLibTiffMergeFieldInfo(ImagingCodecState state, TIFFDataType field_typ
n = sizeof(info) / sizeof(info[0]); n = sizeof(info) / sizeof(info[0]);
// Test for libtiff 4.0 or later, excluding libtiff 3.9.6 and 3.9.7 // Test for libtiff 4.0 or later, excluding libtiff 3.9.6 and 3.9.7
#if TIFFLIB_VERSION >= 20111221 && TIFFLIB_VERSION != 20120218 && TIFFLIB_VERSION != 20120922 #if TIFFLIB_VERSION >= 20111221 && TIFFLIB_VERSION != 20120218 && \
TIFFLIB_VERSION != 20120922
status = TIFFMergeFieldInfo(clientstate->tiff, info, n); status = TIFFMergeFieldInfo(clientstate->tiff, info, n);
#else #else
TIFFMergeFieldInfo(clientstate->tiff, info, n); TIFFMergeFieldInfo(clientstate->tiff, info, n);
@ -637,7 +749,8 @@ int ImagingLibTiffMergeFieldInfo(ImagingCodecState state, TIFFDataType field_typ
return status; return status;
} }
int ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...){ int
ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...) {
// after tif_dir.c->TIFFSetField. // after tif_dir.c->TIFFSetField.
TIFFSTATE *clientstate = (TIFFSTATE *)state->context; TIFFSTATE *clientstate = (TIFFSTATE *)state->context;
va_list ap; va_list ap;
@ -649,8 +762,8 @@ int ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...){
return status; return status;
} }
int
int ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8* buffer, int bytes) { ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes) {
/* One shot encoder. Encode everything to the tiff in the clientstate. /* One shot encoder. Encode everything to the tiff in the clientstate.
If we're running off of a FD, then run once, we're good, everything If we're running off of a FD, then run once, we're good, everything
ends up in the file, we close and we're done. ends up in the file, we close and we're done.
@ -664,35 +777,65 @@ int ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8* buffer, int
TIFF *tiff = clientstate->tiff; TIFF *tiff = clientstate->tiff;
TRACE(("in encoder: bytes %d\n", bytes)); TRACE(("in encoder: bytes %d\n", bytes));
TRACE(("State: count %d, state %d, x %d, y %d, ystep %d\n", state->count, state->state, TRACE(
state->x, state->y, state->ystep)); ("State: count %d, state %d, x %d, y %d, ystep %d\n",
TRACE(("State: xsize %d, ysize %d, xoff %d, yoff %d \n", state->xsize, state->ysize, state->count,
state->xoff, state->yoff)); state->state,
state->x,
state->y,
state->ystep));
TRACE(
("State: xsize %d, ysize %d, xoff %d, yoff %d \n",
state->xsize,
state->ysize,
state->xoff,
state->yoff));
TRACE(("State: bits %d, bytes %d \n", state->bits, state->bytes)); TRACE(("State: bits %d, bytes %d \n", state->bits, state->bytes));
TRACE(("Buffer: %p: %c%c%c%c\n", buffer, (char)buffer[0], (char)buffer[1],(char)buffer[2], (char)buffer[3])); TRACE(
TRACE(("State->Buffer: %c%c%c%c\n", (char)state->buffer[0], (char)state->buffer[1],(char)state->buffer[2], (char)state->buffer[3])); ("Buffer: %p: %c%c%c%c\n",
TRACE(("Image: mode %s, type %d, bands: %d, xsize %d, ysize %d \n", buffer,
im->mode, im->type, im->bands, im->xsize, im->ysize)); (char)buffer[0],
TRACE(("Image: image8 %p, image32 %p, image %p, block %p \n", (char)buffer[1],
im->image8, im->image32, im->image, im->block)); (char)buffer[2],
TRACE(("Image: pixelsize: %d, linesize %d \n", (char)buffer[3]));
im->pixelsize, im->linesize)); TRACE(
("State->Buffer: %c%c%c%c\n",
(char)state->buffer[0],
(char)state->buffer[1],
(char)state->buffer[2],
(char)state->buffer[3]));
TRACE(
("Image: mode %s, type %d, bands: %d, xsize %d, ysize %d \n",
im->mode,
im->type,
im->bands,
im->xsize,
im->ysize));
TRACE(
("Image: image8 %p, image32 %p, image %p, block %p \n",
im->image8,
im->image32,
im->image,
im->block));
TRACE(("Image: pixelsize: %d, linesize %d \n", im->pixelsize, im->linesize));
dump_state(clientstate); dump_state(clientstate);
if (state->state == 0) { if (state->state == 0) {
TRACE(("Encoding line bt line")); TRACE(("Encoding line bt line"));
while(state->y < state->ysize){ while (state->y < state->ysize) {
state->shuffle(state->buffer, state->shuffle(
(UINT8*) im->image[state->y + state->yoff] + state->buffer,
state->xoff * im->pixelsize, (UINT8 *)im->image[state->y + state->yoff] +
state->xsize); state->xoff * im->pixelsize,
state->xsize);
if (TIFFWriteScanline(tiff, (tdata_t)(state->buffer), (uint32)state->y, 0) == -1) { if (TIFFWriteScanline(
tiff, (tdata_t)(state->buffer), (uint32)state->y, 0) == -1) {
TRACE(("Encode Error, row %d\n", state->y)); TRACE(("Encode Error, row %d\n", state->y));
state->errcode = IMAGING_CODEC_BROKEN; state->errcode = IMAGING_CODEC_BROKEN;
TIFFClose(tiff); TIFFClose(tiff);
if (!clientstate->fp){ if (!clientstate->fp) {
free(clientstate->data); free(clientstate->data);
} }
return -1; return -1;
@ -701,7 +844,7 @@ int ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8* buffer, int
} }
if (state->y == state->ysize) { if (state->y == state->ysize) {
state->state=1; state->state = 1;
TRACE(("Flushing \n")); TRACE(("Flushing \n"));
if (!TIFFFlush(tiff)) { if (!TIFFFlush(tiff)) {
@ -709,7 +852,7 @@ int ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8* buffer, int
// likely reason is memory. // likely reason is memory.
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
TIFFClose(tiff); TIFFClose(tiff);
if (!clientstate->fp){ if (!clientstate->fp) {
free(clientstate->data); free(clientstate->data);
} }
return -1; return -1;
@ -718,13 +861,19 @@ int ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8* buffer, int
TIFFClose(tiff); TIFFClose(tiff);
// reset the clientstate metadata to use it to read out the buffer. // reset the clientstate metadata to use it to read out the buffer.
clientstate->loc = 0; clientstate->loc = 0;
clientstate->size = clientstate->eof; // redundant? clientstate->size = clientstate->eof; // redundant?
} }
} }
if (state->state == 1 && !clientstate->fp) { if (state->state == 1 && !clientstate->fp) {
int read = (int)_tiffReadProc(clientstate, (tdata_t)buffer, (tsize_t)bytes); int read = (int)_tiffReadProc(clientstate, (tdata_t)buffer, (tsize_t)bytes);
TRACE(("Buffer: %p: %c%c%c%c\n", buffer, (char)buffer[0], (char)buffer[1],(char)buffer[2], (char)buffer[3])); TRACE(
("Buffer: %p: %c%c%c%c\n",
buffer,
(char)buffer[0],
(char)buffer[1],
(char)buffer[2],
(char)buffer[3]));
if (clientstate->loc == clientstate->eof) { if (clientstate->loc == clientstate->eof) {
TRACE(("Hit EOF, calling an end, freeing data")); TRACE(("Hit EOF, calling an end, freeing data"));
state->errcode = IMAGING_CODEC_END; state->errcode = IMAGING_CODEC_END;
@ -737,9 +886,8 @@ int ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8* buffer, int
return 0; return 0;
} }
const char* const char *
ImagingTiffVersion(void) ImagingTiffVersion(void) {
{
return TIFFGetVersion(); return TIFFGetVersion();
} }

View File

@ -20,8 +20,8 @@
*/ */
#ifndef min #ifndef min
#define min(x,y) (( x > y ) ? y : x ) #define min(x, y) ((x > y) ? y : x)
#define max(x,y) (( x < y ) ? y : x ) #define max(x, y) ((x < y) ? y : x)
#endif #endif
#ifndef _PIL_LIBTIFF_ #ifndef _PIL_LIBTIFF_
@ -32,22 +32,24 @@ typedef struct {
toff_t loc; /* toff_t == uint32 */ toff_t loc; /* toff_t == uint32 */
tsize_t size; /* tsize_t == int32 */ tsize_t size; /* tsize_t == int32 */
int fp; int fp;
uint32 ifd; /* offset of the ifd, used for multipage uint32 ifd; /* offset of the ifd, used for multipage
* Should be uint32 for libtiff 3.9.x * Should be uint32 for libtiff 3.9.x
* uint64 for libtiff 4.0.x * uint64 for libtiff 4.0.x
*/ */
TIFF *tiff; /* Used in write */ TIFF *tiff; /* Used in write */
toff_t eof; toff_t eof;
int flrealloc;/* may we realloc */ int flrealloc; /* may we realloc */
} TIFFSTATE; } TIFFSTATE;
extern int
ImagingLibTiffInit(ImagingCodecState state, int fp, uint32 offset);
extern int ImagingLibTiffInit(ImagingCodecState state, int fp, uint32 offset); extern int
extern int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp); ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp);
extern int ImagingLibTiffMergeFieldInfo(ImagingCodecState state, TIFFDataType field_type, int key, int is_var_length); extern int
extern int ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...); ImagingLibTiffMergeFieldInfo(
ImagingCodecState state, TIFFDataType field_type, int key, int is_var_length);
extern int
ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...);
/* /*
Trace debugging Trace debugging

File diff suppressed because it is too large Load Diff

View File

@ -13,150 +13,151 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
/* Tables generated by pcdtables.py, based on transforms taken from /* Tables generated by pcdtables.py, based on transforms taken from
the "Colour Space Conversions FAQ" by Roberts/Ford. */ the "Colour Space Conversions FAQ" by Roberts/Ford. */
static INT16 L[] = { 0, 1, 3, 4, 5, 7, 8, 10, 11, 12, 14, 15, 16, 18, static INT16 L[] = {
19, 20, 22, 23, 24, 26, 27, 29, 30, 31, 33, 34, 35, 37, 38, 39, 41, 0, 1, 3, 4, 5, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 20,
42, 43, 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 60, 61, 62, 64, 22, 23, 24, 26, 27, 29, 30, 31, 33, 34, 35, 37, 38, 39, 41, 42,
65, 67, 68, 69, 71, 72, 73, 75, 76, 77, 79, 80, 82, 83, 84, 86, 87, 43, 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 60, 61, 62, 64,
88, 90, 91, 92, 94, 95, 96, 98, 99, 101, 102, 103, 105, 106, 107, 109, 65, 67, 68, 69, 71, 72, 73, 75, 76, 77, 79, 80, 82, 83, 84, 86,
110, 111, 113, 114, 115, 117, 118, 120, 121, 122, 124, 125, 126, 128, 87, 88, 90, 91, 92, 94, 95, 96, 98, 99, 101, 102, 103, 105, 106, 107,
129, 130, 132, 133, 134, 136, 137, 139, 140, 141, 143, 144, 145, 147, 109, 110, 111, 113, 114, 115, 117, 118, 120, 121, 122, 124, 125, 126, 128, 129,
148, 149, 151, 152, 153, 155, 156, 158, 159, 160, 162, 163, 164, 166, 130, 132, 133, 134, 136, 137, 139, 140, 141, 143, 144, 145, 147, 148, 149, 151,
167, 168, 170, 171, 173, 174, 175, 177, 178, 179, 181, 182, 183, 185, 152, 153, 155, 156, 158, 159, 160, 162, 163, 164, 166, 167, 168, 170, 171, 173,
186, 187, 189, 190, 192, 193, 194, 196, 197, 198, 200, 201, 202, 204, 174, 175, 177, 178, 179, 181, 182, 183, 185, 186, 187, 189, 190, 192, 193, 194,
205, 206, 208, 209, 211, 212, 213, 215, 216, 217, 219, 220, 221, 223, 196, 197, 198, 200, 201, 202, 204, 205, 206, 208, 209, 211, 212, 213, 215, 216,
224, 225, 227, 228, 230, 231, 232, 234, 235, 236, 238, 239, 240, 242, 217, 219, 220, 221, 223, 224, 225, 227, 228, 230, 231, 232, 234, 235, 236, 238,
243, 245, 246, 247, 249, 250, 251, 253, 254, 255, 257, 258, 259, 261, 239, 240, 242, 243, 245, 246, 247, 249, 250, 251, 253, 254, 255, 257, 258, 259,
262, 264, 265, 266, 268, 269, 270, 272, 273, 274, 276, 277, 278, 280, 261, 262, 264, 265, 266, 268, 269, 270, 272, 273, 274, 276, 277, 278, 280, 281,
281, 283, 284, 285, 287, 288, 289, 291, 292, 293, 295, 296, 297, 299, 283, 284, 285, 287, 288, 289, 291, 292, 293, 295, 296, 297, 299, 300, 302, 303,
300, 302, 303, 304, 306, 307, 308, 310, 311, 312, 314, 315, 317, 318, 304, 306, 307, 308, 310, 311, 312, 314, 315, 317, 318, 319, 321, 322, 323, 325,
319, 321, 322, 323, 325, 326, 327, 329, 330, 331, 333, 334, 336, 337, 326, 327, 329, 330, 331, 333, 334, 336, 337, 338, 340, 341, 342, 344, 345, 346};
338, 340, 341, 342, 344, 345, 346 };
static INT16 CB[] = { -345, -343, -341, -338, -336, -334, -332, -329, static INT16 CB[] = {
-327, -325, -323, -321, -318, -316, -314, -312, -310, -307, -305, -345, -343, -341, -338, -336, -334, -332, -329, -327, -325, -323, -321, -318, -316,
-303, -301, -298, -296, -294, -292, -290, -287, -285, -283, -281, -314, -312, -310, -307, -305, -303, -301, -298, -296, -294, -292, -290, -287, -285,
-278, -276, -274, -272, -270, -267, -265, -263, -261, -258, -256, -283, -281, -278, -276, -274, -272, -270, -267, -265, -263, -261, -258, -256, -254,
-254, -252, -250, -247, -245, -243, -241, -239, -236, -234, -232, -252, -250, -247, -245, -243, -241, -239, -236, -234, -232, -230, -227, -225, -223,
-230, -227, -225, -223, -221, -219, -216, -214, -212, -210, -207, -221, -219, -216, -214, -212, -210, -207, -205, -203, -201, -199, -196, -194, -192,
-205, -203, -201, -199, -196, -194, -192, -190, -188, -185, -183, -190, -188, -185, -183, -181, -179, -176, -174, -172, -170, -168, -165, -163, -161,
-181, -179, -176, -174, -172, -170, -168, -165, -163, -161, -159, -159, -156, -154, -152, -150, -148, -145, -143, -141, -139, -137, -134, -132, -130,
-156, -154, -152, -150, -148, -145, -143, -141, -139, -137, -134, -128, -125, -123, -121, -119, -117, -114, -112, -110, -108, -105, -103, -101, -99,
-132, -130, -128, -125, -123, -121, -119, -117, -114, -112, -110, -97, -94, -92, -90, -88, -85, -83, -81, -79, -77, -74, -72, -70, -68,
-108, -105, -103, -101, -99, -97, -94, -92, -90, -88, -85, -83, -81, -66, -63, -61, -59, -57, -54, -52, -50, -48, -46, -43, -41, -39, -37,
-79, -77, -74, -72, -70, -68, -66, -63, -61, -59, -57, -54, -52, -50, -34, -32, -30, -28, -26, -23, -21, -19, -17, -15, -12, -10, -8, -6,
-48, -46, -43, -41, -39, -37, -34, -32, -30, -28, -26, -23, -21, -19, -3, -1, 0, 2, 4, 7, 9, 11, 13, 16, 18, 20, 22, 24,
-17, -15, -12, -10, -8, -6, -3, -1, 0, 2, 4, 7, 9, 11, 13, 16, 18, 20, 27, 29, 31, 33, 35, 38, 40, 42, 44, 47, 49, 51, 53, 55,
22, 24, 27, 29, 31, 33, 35, 38, 40, 42, 44, 47, 49, 51, 53, 55, 58, 58, 60, 62, 64, 67, 69, 71, 73, 75, 78, 80, 82, 84, 86,
60, 62, 64, 67, 69, 71, 73, 75, 78, 80, 82, 84, 86, 89, 91, 93, 95, 89, 91, 93, 95, 98, 100, 102, 104, 106, 109, 111, 113, 115, 118,
98, 100, 102, 104, 106, 109, 111, 113, 115, 118, 120, 122, 124, 126, 120, 122, 124, 126, 129, 131, 133, 135, 138, 140, 142, 144, 146, 149,
129, 131, 133, 135, 138, 140, 142, 144, 146, 149, 151, 153, 155, 157, 151, 153, 155, 157, 160, 162, 164, 166, 169, 171, 173, 175, 177, 180,
160, 162, 164, 166, 169, 171, 173, 175, 177, 180, 182, 184, 186, 189, 182, 184, 186, 189, 191, 193, 195, 197, 200, 202, 204, 206, 208, 211,
191, 193, 195, 197, 200, 202, 204, 206, 208, 211, 213, 215, 217, 220 }; 213, 215, 217, 220};
static INT16 GB[] = { 67, 67, 66, 66, 65, 65, 65, 64, 64, 63, 63, 62, static INT16 GB[] = {
62, 62, 61, 61, 60, 60, 59, 59, 59, 58, 58, 57, 57, 56, 56, 56, 55, 67, 67, 66, 66, 65, 65, 65, 64, 64, 63, 63, 62, 62, 62, 61, 61,
55, 54, 54, 53, 53, 52, 52, 52, 51, 51, 50, 50, 49, 49, 49, 48, 48, 60, 60, 59, 59, 59, 58, 58, 57, 57, 56, 56, 56, 55, 55, 54, 54,
47, 47, 46, 46, 46, 45, 45, 44, 44, 43, 43, 43, 42, 42, 41, 41, 40, 53, 53, 52, 52, 52, 51, 51, 50, 50, 49, 49, 49, 48, 48, 47, 47,
40, 40, 39, 39, 38, 38, 37, 37, 37, 36, 36, 35, 35, 34, 34, 34, 33, 46, 46, 46, 45, 45, 44, 44, 43, 43, 43, 42, 42, 41, 41, 40, 40,
33, 32, 32, 31, 31, 31, 30, 30, 29, 29, 28, 28, 28, 27, 27, 26, 26, 40, 39, 39, 38, 38, 37, 37, 37, 36, 36, 35, 35, 34, 34, 34, 33,
25, 25, 25, 24, 24, 23, 23, 22, 22, 22, 21, 21, 20, 20, 19, 19, 19, 33, 32, 32, 31, 31, 31, 30, 30, 29, 29, 28, 28, 28, 27, 27, 26,
18, 18, 17, 17, 16, 16, 15, 15, 15, 14, 14, 13, 13, 12, 12, 12, 11, 26, 25, 25, 25, 24, 24, 23, 23, 22, 22, 22, 21, 21, 20, 20, 19,
11, 10, 10, 9, 9, 9, 8, 8, 7, 7, 6, 6, 6, 5, 5, 4, 4, 3, 3, 3, 2, 2, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 15, 14, 14, 13, 13, 12,
1, 1, 0, 0, 0, 0, 0, -1, -1, -2, -2, -2, -3, -3, -4, -4, -5, -5, -5, 12, 12, 11, 11, 10, 10, 9, 9, 9, 8, 8, 7, 7, 6, 6, 6,
-6, -6, -7, -7, -8, -8, -8, -9, -9, -10, -10, -11, -11, -11, -12, -12, 5, 5, 4, 4, 3, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0,
-13, -13, -14, -14, -14, -15, -15, -16, -16, -17, -17, -18, -18, -18, -1, -1, -2, -2, -2, -3, -3, -4, -4, -5, -5, -5, -6, -6, -7, -7,
-19, -19, -20, -20, -21, -21, -21, -22, -22, -23, -23, -24, -24, -24, -8, -8, -8, -9, -9, -10, -10, -11, -11, -11, -12, -12, -13, -13, -14, -14,
-25, -25, -26, -26, -27, -27, -27, -28, -28, -29, -29, -30, -30, -30, -14, -15, -15, -16, -16, -17, -17, -18, -18, -18, -19, -19, -20, -20, -21, -21,
-31, -31, -32, -32, -33, -33, -33, -34, -34, -35, -35, -36, -36, -36, -21, -22, -22, -23, -23, -24, -24, -24, -25, -25, -26, -26, -27, -27, -27, -28,
-37, -37, -38, -38, -39, -39, -39, -40, -40, -41, -41, -42 }; -28, -29, -29, -30, -30, -30, -31, -31, -32, -32, -33, -33, -33, -34, -34, -35,
-35, -36, -36, -36, -37, -37, -38, -38, -39, -39, -39, -40, -40, -41, -41, -42};
static INT16 CR[] = { -249, -247, -245, -243, -241, -239, -238, -236, static INT16 CR[] = {
-234, -232, -230, -229, -227, -225, -223, -221, -219, -218, -216, -249, -247, -245, -243, -241, -239, -238, -236, -234, -232, -230, -229, -227, -225,
-214, -212, -210, -208, -207, -205, -203, -201, -199, -198, -196, -223, -221, -219, -218, -216, -214, -212, -210, -208, -207, -205, -203, -201, -199,
-194, -192, -190, -188, -187, -185, -183, -181, -179, -178, -176, -198, -196, -194, -192, -190, -188, -187, -185, -183, -181, -179, -178, -176, -174,
-174, -172, -170, -168, -167, -165, -163, -161, -159, -157, -156, -172, -170, -168, -167, -165, -163, -161, -159, -157, -156, -154, -152, -150, -148,
-154, -152, -150, -148, -147, -145, -143, -141, -139, -137, -136, -147, -145, -143, -141, -139, -137, -136, -134, -132, -130, -128, -127, -125, -123,
-134, -132, -130, -128, -127, -125, -123, -121, -119, -117, -116, -121, -119, -117, -116, -114, -112, -110, -108, -106, -105, -103, -101, -99, -97,
-114, -112, -110, -108, -106, -105, -103, -101, -99, -97, -96, -94, -96, -94, -92, -90, -88, -86, -85, -83, -81, -79, -77, -76, -74, -72,
-92, -90, -88, -86, -85, -83, -81, -79, -77, -76, -74, -72, -70, -68, -70, -68, -66, -65, -63, -61, -59, -57, -55, -54, -52, -50, -48, -46,
-66, -65, -63, -61, -59, -57, -55, -54, -52, -50, -48, -46, -45, -43, -45, -43, -41, -39, -37, -35, -34, -32, -30, -28, -26, -25, -23, -21,
-41, -39, -37, -35, -34, -32, -30, -28, -26, -25, -23, -21, -19, -17, -19, -17, -15, -14, -12, -10, -8, -6, -4, -3, -1, 0, 2, 4,
-15, -14, -12, -10, -8, -6, -4, -3, -1, 0, 2, 4, 5, 7, 9, 11, 13, 15, 5, 7, 9, 11, 13, 15, 16, 18, 20, 22, 24, 26, 27, 29,
16, 18, 20, 22, 24, 26, 27, 29, 31, 33, 35, 36, 38, 40, 42, 44, 46, 31, 33, 35, 36, 38, 40, 42, 44, 46, 47, 49, 51, 53, 55,
47, 49, 51, 53, 55, 56, 58, 60, 62, 64, 66, 67, 69, 71, 73, 75, 77, 56, 58, 60, 62, 64, 66, 67, 69, 71, 73, 75, 77, 78, 80,
78, 80, 82, 84, 86, 87, 89, 91, 93, 95, 97, 98, 100, 102, 104, 106, 82, 84, 86, 87, 89, 91, 93, 95, 97, 98, 100, 102, 104, 106,
107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 129, 131, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 129, 131,
133, 135, 137, 138, 140, 142, 144, 146, 148, 149, 151, 153, 155, 157, 133, 135, 137, 138, 140, 142, 144, 146, 148, 149, 151, 153, 155, 157,
158, 160, 162, 164, 166, 168, 169, 171, 173, 175, 177, 179, 180, 182, 158, 160, 162, 164, 166, 168, 169, 171, 173, 175, 177, 179, 180, 182,
184, 186, 188, 189, 191, 193, 195, 197, 199, 200, 202, 204, 206, 208, 184, 186, 188, 189, 191, 193, 195, 197, 199, 200, 202, 204, 206, 208,
209, 211, 213, 215 }; 209, 211, 213, 215};
static INT16 GR[] = { 127, 126, 125, 124, 123, 122, 121, 121, 120, 119, static INT16 GR[] = {
118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 108, 107, 106, 127, 126, 125, 124, 123, 122, 121, 121, 120, 119, 118, 117, 116, 115, 114,
105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 95, 94, 93, 92, 91, 113, 112, 111, 110, 109, 108, 108, 107, 106, 105, 104, 103, 102, 101, 100,
90, 89, 88, 87, 86, 85, 84, 83, 83, 82, 81, 80, 79, 78, 77, 76, 75, 99, 98, 97, 96, 95, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86,
74, 73, 72, 71, 70, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 85, 84, 83, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72,
58, 57, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 45, 44, 71, 70, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58,
43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 32, 31, 30, 29, 28, 57, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 45,
27, 26, 25, 24, 23, 22, 21, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 32, 31,
11, 10, 9, 8, 7, 6, 6, 5, 4, 3, 2, 1, 0, 0, -1, -2, -3, -4, -5, -5, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 19, 18, 17,
-6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -18, -19, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 6, 5, 4, 3,
-20, -21, -22, -23, -24, -25, -26, -27, -28, -29, -30, -31, -31, -32, 2, 1, 0, 0, -1, -2, -3, -4, -5, -5, -6, -7, -8, -9, -10,
-33, -34, -35, -36, -37, -38, -39, -40, -41, -42, -43, -44, -44, -45, -11, -12, -13, -14, -15, -16, -17, -18, -18, -19, -20, -21, -22, -23, -24,
-46, -47, -48, -49, -50, -51, -52, -53, -54, -55, -56, -56, -57, -58, -25, -26, -27, -28, -29, -30, -31, -31, -32, -33, -34, -35, -36, -37, -38,
-59, -60, -61, -62, -63, -64, -65, -66, -67, -68, -69, -69, -70, -71, -39, -40, -41, -42, -43, -44, -44, -45, -46, -47, -48, -49, -50, -51, -52,
-72, -73, -74, -75, -76, -77, -78, -79, -80, -81, -82, -82, -83, -84, -53, -54, -55, -56, -56, -57, -58, -59, -60, -61, -62, -63, -64, -65, -66,
-85, -86, -87, -88, -89, -90, -91, -92, -93, -94, -94, -95, -96, -97, -67, -68, -69, -69, -70, -71, -72, -73, -74, -75, -76, -77, -78, -79, -80,
-98, -99, -100, -101, -102, -103, -104, -105, -106, -107, -107, -108 }; -81, -82, -82, -83, -84, -85, -86, -87, -88, -89, -90, -91, -92, -93, -94,
-94, -95, -96, -97, -98, -99, -100, -101, -102, -103, -104, -105, -106, -107, -107,
-108};
#define R 0 #define R 0
#define G 1 #define G 1
#define B 2 #define B 2
#define A 3 #define A 3
#define YCC2RGB(rgb, y, cb, cr) {\ #define YCC2RGB(rgb, y, cb, cr) \
int l = L[y];\ { \
int r = l + CR[cr];\ int l = L[y]; \
int g = l + GR[cr] + GB[cb];\ int r = l + CR[cr]; \
int b = l + CB[cb];\ int g = l + GR[cr] + GB[cb]; \
rgb[0] = (r <= 0) ? 0 : (r >= 255) ? 255 : r;\ int b = l + CB[cb]; \
rgb[1] = (g <= 0) ? 0 : (g >= 255) ? 255 : g;\ rgb[0] = (r <= 0) ? 0 : (r >= 255) ? 255 : r; \
rgb[2] = (b <= 0) ? 0 : (b >= 255) ? 255 : b;\ rgb[1] = (g <= 0) ? 0 : (g >= 255) ? 255 : g; \
} rgb[2] = (b <= 0) ? 0 : (b >= 255) ? 255 : b; \
}
void void
ImagingUnpackYCC(UINT8* out, const UINT8* in, int pixels) ImagingUnpackYCC(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* PhotoYCC triplets */ /* PhotoYCC triplets */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
YCC2RGB(out, in[0], in[1], in[2]); YCC2RGB(out, in[0], in[1], in[2]);
out[A] = 255; out[A] = 255;
out += 4; in += 3; out += 4;
in += 3;
} }
} }
void void
ImagingUnpackYCCA(UINT8* out, const UINT8* in, int pixels) ImagingUnpackYCCA(UINT8 *out, const UINT8 *in, int pixels) {
{
int i; int i;
/* PhotoYCC triplets plus premultiplied alpha */ /* PhotoYCC triplets plus premultiplied alpha */
for (i = 0; i < pixels; i++) { for (i = 0; i < pixels; i++) {
/* Divide by alpha */ /* Divide by alpha */
UINT8 rgb[3]; UINT8 rgb[3];
rgb[0] = (in[3] == 0) ? 0 : (((int) in[0] * 255) / in[3]); rgb[0] = (in[3] == 0) ? 0 : (((int)in[0] * 255) / in[3]);
rgb[1] = (in[3] == 0) ? 0 : (((int) in[1] * 255) / in[3]); rgb[1] = (in[3] == 0) ? 0 : (((int)in[1] * 255) / in[3]);
rgb[2] = (in[3] == 0) ? 0 : (((int) in[2] * 255) / in[3]); rgb[2] = (in[3] == 0) ? 0 : (((int)in[2] * 255) / in[3]);
/* Convert non-multiplied data to RGB */ /* Convert non-multiplied data to RGB */
YCC2RGB(out, rgb[0], rgb[1], rgb[2]); YCC2RGB(out, rgb[0], rgb[1], rgb[2]);
out[A] = in[3]; out[A] = in[3];
out += 4; in += 4; out += 4;
in += 4;
} }
} }

View File

@ -8,26 +8,22 @@
#include "Imaging.h" #include "Imaging.h"
typedef UINT8 pixel[4]; typedef UINT8 pixel[4];
static inline UINT8
static inline UINT8 clip8(int in) clip8(int in) {
{
if (in >= 255) { if (in >= 255) {
return 255; return 255;
} }
if (in <= 0) { if (in <= 0) {
return 0; return 0;
} }
return (UINT8) in; return (UINT8)in;
} }
Imaging Imaging
ImagingUnsharpMask(Imaging imOut, Imaging imIn, float radius, int percent, ImagingUnsharpMask(
int threshold) Imaging imOut, Imaging imIn, float radius, int percent, int threshold) {
{
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
Imaging result; Imaging result;
@ -53,8 +49,7 @@ ImagingUnsharpMask(Imaging imOut, Imaging imIn, float radius, int percent,
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
for (y = 0; y < imIn->ysize; y++) { for (y = 0; y < imIn->ysize; y++) {
if (imIn->image8) if (imIn->image8) {
{
lineIn8 = imIn->image8[y]; lineIn8 = imIn->image8[y];
lineOut8 = imOut->image8[y]; lineOut8 = imOut->image8[y];
for (x = 0; x < imIn->xsize; x++) { for (x = 0; x < imIn->xsize; x++) {
@ -74,20 +69,24 @@ ImagingUnsharpMask(Imaging imOut, Imaging imIn, float radius, int percent,
for (x = 0; x < imIn->xsize; x++) { for (x = 0; x < imIn->xsize; x++) {
/* compare in/out pixels, apply sharpening */ /* compare in/out pixels, apply sharpening */
diff = lineIn[x][0] - lineOut[x][0]; diff = lineIn[x][0] - lineOut[x][0];
lineOut[x][0] = abs(diff) > threshold ? lineOut[x][0] = abs(diff) > threshold
clip8(lineIn[x][0] + diff * percent / 100) : lineIn[x][0]; ? clip8(lineIn[x][0] + diff * percent / 100)
: lineIn[x][0];
diff = lineIn[x][1] - lineOut[x][1]; diff = lineIn[x][1] - lineOut[x][1];
lineOut[x][1] = abs(diff) > threshold ? lineOut[x][1] = abs(diff) > threshold
clip8(lineIn[x][1] + diff * percent / 100) : lineIn[x][1]; ? clip8(lineIn[x][1] + diff * percent / 100)
: lineIn[x][1];
diff = lineIn[x][2] - lineOut[x][2]; diff = lineIn[x][2] - lineOut[x][2];
lineOut[x][2] = abs(diff) > threshold ? lineOut[x][2] = abs(diff) > threshold
clip8(lineIn[x][2] + diff * percent / 100) : lineIn[x][2]; ? clip8(lineIn[x][2] + diff * percent / 100)
: lineIn[x][2];
diff = lineIn[x][3] - lineOut[x][3]; diff = lineIn[x][3] - lineOut[x][3];
lineOut[x][3] = abs(diff) > threshold ? lineOut[x][3] = abs(diff) > threshold
clip8(lineIn[x][3] + diff * percent / 100) : lineIn[x][3]; ? clip8(lineIn[x][3] + diff * percent / 100)
: lineIn[x][3];
} }
} }
} }

View File

@ -13,19 +13,19 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#define HEX(v) ((v >= '0' && v <= '9') ? v - '0' :\ #define HEX(v) \
(v >= 'a' && v <= 'f') ? v - 'a' + 10 :\ ((v >= '0' && v <= '9') ? v - '0' \
(v >= 'A' && v <= 'F') ? v - 'A' + 10 : 0) : (v >= 'a' && v <= 'f') ? v - 'a' + 10 \
: (v >= 'A' && v <= 'F') ? v - 'A' + 10 \
: 0)
int int
ImagingXbmDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes) ImagingXbmDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
{
enum { BYTE = 1, SKIP }; enum { BYTE = 1, SKIP };
UINT8* ptr; UINT8 *ptr;
if (!state->state) { if (!state->state) {
state->state = SKIP; state->state = SKIP;
@ -34,9 +34,7 @@ ImagingXbmDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
ptr = buf; ptr = buf;
for (;;) { for (;;) {
if (state->state == SKIP) { if (state->state == SKIP) {
/* Skip forward until next 'x' */ /* Skip forward until next 'x' */
while (bytes > 0) { while (bytes > 0) {
@ -52,20 +50,17 @@ ImagingXbmDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
} }
state->state = BYTE; state->state = BYTE;
} }
if (bytes < 3) { if (bytes < 3) {
return ptr - buf; return ptr - buf;
} }
state->buffer[state->x] = (HEX(ptr[1])<<4) + HEX(ptr[2]); state->buffer[state->x] = (HEX(ptr[1]) << 4) + HEX(ptr[2]);
if (++state->x >= state->bytes) { if (++state->x >= state->bytes) {
/* Got a full line, unpack it */ /* Got a full line, unpack it */
state->shuffle((UINT8*) im->image[state->y], state->buffer, state->shuffle((UINT8 *)im->image[state->y], state->buffer, state->xsize);
state->xsize);
state->x = 0; state->x = 0;
@ -79,7 +74,5 @@ ImagingXbmDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
bytes -= 3; bytes -= 3;
state->state = SKIP; state->state = SKIP;
} }
} }

View File

@ -13,25 +13,20 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
int int
ImagingXbmEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) ImagingXbmEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
{
const char *hex = "0123456789abcdef"; const char *hex = "0123456789abcdef";
UINT8* ptr = buf; UINT8 *ptr = buf;
int i, n; int i, n;
if (!state->state) { if (!state->state) {
/* 8 pixels are stored in no more than 6 bytes */ /* 8 pixels are stored in no more than 6 bytes */
state->bytes = 6*(state->xsize+7)/8; state->bytes = 6 * (state->xsize + 7) / 8;
state->state = 1; state->state = 1;
} }
if (bytes < state->bytes) { if (bytes < state->bytes) {
@ -42,60 +37,54 @@ ImagingXbmEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
ptr = buf; ptr = buf;
while (bytes >= state->bytes) { while (bytes >= state->bytes) {
state->shuffle(
state->buffer,
(UINT8 *)im->image[state->y + state->yoff] + state->xoff * im->pixelsize,
state->xsize);
state->shuffle(state->buffer, if (state->y < state->ysize - 1) {
(UINT8*) im->image[state->y + state->yoff] +
state->xoff * im->pixelsize, state->xsize);
if (state->y < state->ysize-1) {
/* any line but the last */ /* any line but the last */
for (n = 0; n < state->xsize; n += 8) { for (n = 0; n < state->xsize; n += 8) {
i = state->buffer[n / 8];
i = state->buffer[n/8];
*ptr++ = '0'; *ptr++ = '0';
*ptr++ = 'x'; *ptr++ = 'x';
*ptr++ = hex[(i>>4)&15]; *ptr++ = hex[(i >> 4) & 15];
*ptr++ = hex[i&15]; *ptr++ = hex[i & 15];
*ptr++ = ','; *ptr++ = ',';
bytes -= 5; bytes -= 5;
if (++state->count >= 79/5) { if (++state->count >= 79 / 5) {
*ptr++ = '\n'; *ptr++ = '\n';
bytes--; bytes--;
state->count = 0; state->count = 0;
} }
} }
state->y++; state->y++;
} else { } else {
/* last line */ /* last line */
for (n = 0; n < state->xsize; n += 8) { for (n = 0; n < state->xsize; n += 8) {
i = state->buffer[n / 8];
i = state->buffer[n/8];
*ptr++ = '0'; *ptr++ = '0';
*ptr++ = 'x'; *ptr++ = 'x';
*ptr++ = hex[(i>>4)&15]; *ptr++ = hex[(i >> 4) & 15];
*ptr++ = hex[i&15]; *ptr++ = hex[i & 15];
if (n < state->xsize-8) { if (n < state->xsize - 8) {
*ptr++ = ','; *ptr++ = ',';
if (++state->count >= 79/5) { if (++state->count >= 79 / 5) {
*ptr++ = '\n'; *ptr++ = '\n';
bytes--; bytes--;
state->count = 0; state->count = 0;
} }
} else { } else {
*ptr++ = '\n'; *ptr++ = '\n';
} }
bytes -= 5; bytes -= 5;
} }
state->errcode = IMAGING_CODEC_END; state->errcode = IMAGING_CODEC_END;

View File

@ -7,19 +7,15 @@
* Copyright (c) Fredrik Lundh 1996. * Copyright (c) Fredrik Lundh 1996.
*/ */
#include "zlib.h" #include "zlib.h"
/* modes */ /* modes */
#define ZIP_PNG 0 /* continuous, filtered image data */ #define ZIP_PNG 0 /* continuous, filtered image data */
#define ZIP_PNG_PALETTE 1 /* non-continuous data, disable filtering */ #define ZIP_PNG_PALETTE 1 /* non-continuous data, disable filtering */
#define ZIP_TIFF_PREDICTOR 2 /* TIFF, with predictor */ #define ZIP_TIFF_PREDICTOR 2 /* TIFF, with predictor */
#define ZIP_TIFF 3 /* TIFF, without predictor */ #define ZIP_TIFF 3 /* TIFF, without predictor */
typedef struct { typedef struct {
/* CONFIGURATION */ /* CONFIGURATION */
/* Codec mode */ /* Codec mode */
@ -34,29 +30,29 @@ typedef struct {
int compress_type; int compress_type;
/* Predefined dictionary (experimental) */ /* Predefined dictionary (experimental) */
char* dictionary; char *dictionary;
int dictionary_size; int dictionary_size;
/* PRIVATE CONTEXT (set by decoder/encoder) */ /* PRIVATE CONTEXT (set by decoder/encoder) */
z_stream z_stream; /* (de)compression stream */ z_stream z_stream; /* (de)compression stream */
UINT8* previous; /* previous line (allocated) */ UINT8 *previous; /* previous line (allocated) */
int last_output; /* # bytes last output by inflate */ int last_output; /* # bytes last output by inflate */
/* Compressor specific stuff */ /* Compressor specific stuff */
UINT8* prior; /* filter storage (allocated) */ UINT8 *prior; /* filter storage (allocated) */
UINT8* up; UINT8 *up;
UINT8* average; UINT8 *average;
UINT8* paeth; UINT8 *paeth;
UINT8* output; /* output data */ UINT8 *output; /* output data */
int prefix; /* size of filter prefix (0 for TIFF data) */ int prefix; /* size of filter prefix (0 for TIFF data) */
int interlaced; /* is the image interlaced? (PNG) */ int interlaced; /* is the image interlaced? (PNG) */
int pass; /* current pass of the interlaced image (PNG) */ int pass; /* current pass of the interlaced image (PNG) */
} ZIPSTATE; } ZIPSTATE;

View File

@ -15,23 +15,22 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ
#include "ZipCodecs.h" #include "ZipCodecs.h"
static const int OFFSET[] = { 7, 3, 3, 1, 1, 0, 0 }; static const int OFFSET[] = {7, 3, 3, 1, 1, 0, 0};
static const int STARTING_COL[] = { 0, 4, 0, 2, 0, 1, 0 }; static const int STARTING_COL[] = {0, 4, 0, 2, 0, 1, 0};
static const int STARTING_ROW[] = { 0, 0, 4, 0, 2, 0, 1 }; static const int STARTING_ROW[] = {0, 0, 4, 0, 2, 0, 1};
static const int COL_INCREMENT[] = { 8, 8, 4, 4, 2, 2, 1 }; static const int COL_INCREMENT[] = {8, 8, 4, 4, 2, 2, 1};
static const int ROW_INCREMENT[] = { 8, 8, 8, 4, 4, 2, 2 }; static const int ROW_INCREMENT[] = {8, 8, 8, 4, 4, 2, 2};
/* Get the length in bytes of a scanline in the pass specified, /* Get the length in bytes of a scanline in the pass specified,
* for interlaced images */ * for interlaced images */
static int get_row_len(ImagingCodecState state, int pass) static int
{ get_row_len(ImagingCodecState state, int pass) {
int row_len = (state->xsize + OFFSET[pass]) / COL_INCREMENT[pass]; int row_len = (state->xsize + OFFSET[pass]) / COL_INCREMENT[pass];
return ((row_len * state->bits) + 7) / 8; return ((row_len * state->bits) + 7) / 8;
} }
@ -41,17 +40,15 @@ static int get_row_len(ImagingCodecState state, int pass)
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
int int
ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes) ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
{ ZIPSTATE *context = (ZIPSTATE *)state->context;
ZIPSTATE* context = (ZIPSTATE*) state->context;
int err; int err;
int n; int n;
UINT8* ptr; UINT8 *ptr;
int i, bpp; int i, bpp;
int row_len; int row_len;
if (!state->state) { if (!state->state) {
/* Initialization */ /* Initialization */
if (context->mode == ZIP_PNG || context->mode == ZIP_PNG_PALETTE) { if (context->mode == ZIP_PNG || context->mode == ZIP_PNG_PALETTE) {
context->prefix = 1; /* PNG */ context->prefix = 1; /* PNG */
@ -66,8 +63,8 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
prefix, and allocate a buffer to hold the previous line */ prefix, and allocate a buffer to hold the previous line */
free(state->buffer); free(state->buffer);
/* malloc check ok, overflow checked above */ /* malloc check ok, overflow checked above */
state->buffer = (UINT8*) malloc(state->bytes+1); state->buffer = (UINT8 *)malloc(state->bytes + 1);
context->previous = (UINT8*) malloc(state->bytes+1); context->previous = (UINT8 *)malloc(state->bytes + 1);
if (!state->buffer || !context->previous) { if (!state->buffer || !context->previous) {
state->errcode = IMAGING_CODEC_MEMORY; state->errcode = IMAGING_CODEC_MEMORY;
return -1; return -1;
@ -76,12 +73,12 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
context->last_output = 0; context->last_output = 0;
/* Initialize to black */ /* Initialize to black */
memset(context->previous, 0, state->bytes+1); memset(context->previous, 0, state->bytes + 1);
/* Setup decompression context */ /* Setup decompression context */
context->z_stream.zalloc = (alloc_func) NULL; context->z_stream.zalloc = (alloc_func)NULL;
context->z_stream.zfree = (free_func) NULL; context->z_stream.zfree = (free_func)NULL;
context->z_stream.opaque = (voidpf) NULL; context->z_stream.opaque = (voidpf)NULL;
err = inflateInit(&context->z_stream); err = inflateInit(&context->z_stream);
if (err < 0) { if (err < 0) {
@ -98,7 +95,6 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
/* Ready to decode */ /* Ready to decode */
state->state = 1; state->state = 1;
} }
if (context->interlaced) { if (context->interlaced) {
@ -113,10 +109,8 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
/* Decompress what we've got this far */ /* Decompress what we've got this far */
while (context->z_stream.avail_in > 0) { while (context->z_stream.avail_in > 0) {
context->z_stream.next_out = state->buffer + context->last_output; context->z_stream.next_out = state->buffer + context->last_output;
context->z_stream.avail_out = context->z_stream.avail_out = row_len + context->prefix - context->last_output;
row_len + context->prefix - context->last_output;
err = inflate(&context->z_stream, Z_NO_FLUSH); err = inflate(&context->z_stream, Z_NO_FLUSH);
@ -144,74 +138,74 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
/* Apply predictor */ /* Apply predictor */
switch (context->mode) { switch (context->mode) {
case ZIP_PNG: case ZIP_PNG:
switch (state->buffer[0]) { switch (state->buffer[0]) {
case 0: case 0:
break;
case 1:
/* prior */
bpp = (state->bits + 7) / 8;
for (i = bpp + 1; i <= row_len; i++) {
state->buffer[i] += state->buffer[i - bpp];
}
break;
case 2:
/* up */
for (i = 1; i <= row_len; i++) {
state->buffer[i] += context->previous[i];
}
break;
case 3:
/* average */
bpp = (state->bits + 7) / 8;
for (i = 1; i <= bpp; i++) {
state->buffer[i] += context->previous[i] / 2;
}
for (; i <= row_len; i++) {
state->buffer[i] +=
(state->buffer[i - bpp] + context->previous[i]) / 2;
}
break;
case 4:
/* paeth filtering */
bpp = (state->bits + 7) / 8;
for (i = 1; i <= bpp; i++) {
state->buffer[i] += context->previous[i];
}
for (; i <= row_len; i++) {
int a, b, c;
int pa, pb, pc;
/* fetch pixels */
a = state->buffer[i - bpp];
b = context->previous[i];
c = context->previous[i - bpp];
/* distances to surrounding pixels */
pa = abs(b - c);
pb = abs(a - c);
pc = abs(a + b - 2 * c);
/* pick predictor with the shortest distance */
state->buffer[i] += (pa <= pb && pa <= pc) ? a
: (pb <= pc) ? b
: c;
}
break;
default:
state->errcode = IMAGING_CODEC_UNKNOWN;
free(context->previous);
context->previous = NULL;
inflateEnd(&context->z_stream);
return -1;
}
break; break;
case 1: case ZIP_TIFF_PREDICTOR:
/* prior */
bpp = (state->bits + 7) / 8; bpp = (state->bits + 7) / 8;
for (i = bpp+1; i <= row_len; i++) { for (i = bpp + 1; i <= row_len; i++) {
state->buffer[i] += state->buffer[i-bpp]; state->buffer[i] += state->buffer[i - bpp];
} }
break; break;
case 2:
/* up */
for (i = 1; i <= row_len; i++) {
state->buffer[i] += context->previous[i];
}
break;
case 3:
/* average */
bpp = (state->bits + 7) / 8;
for (i = 1; i <= bpp; i++) {
state->buffer[i] += context->previous[i]/2;
}
for (; i <= row_len; i++) {
state->buffer[i] +=
(state->buffer[i-bpp] + context->previous[i])/2;
}
break;
case 4:
/* paeth filtering */
bpp = (state->bits + 7) / 8;
for (i = 1; i <= bpp; i++) {
state->buffer[i] += context->previous[i];
}
for (; i <= row_len; i++) {
int a, b, c;
int pa, pb, pc;
/* fetch pixels */
a = state->buffer[i-bpp];
b = context->previous[i];
c = context->previous[i-bpp];
/* distances to surrounding pixels */
pa = abs(b - c);
pb = abs(a - c);
pc = abs(a + b - 2*c);
/* pick predictor with the shortest distance */
state->buffer[i] +=
(pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
}
break;
default:
state->errcode = IMAGING_CODEC_UNKNOWN;
free(context->previous);
context->previous = NULL;
inflateEnd(&context->z_stream);
return -1;
}
break;
case ZIP_TIFF_PREDICTOR:
bpp = (state->bits + 7) / 8;
for (i = bpp+1; i <= row_len; i++) {
state->buffer[i] += state->buffer[i-bpp];
}
break;
} }
/* Stuff data into the image */ /* Stuff data into the image */
@ -220,20 +214,22 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
if (state->bits >= 8) { if (state->bits >= 8) {
/* Stuff pixels in their correct location, one by one */ /* Stuff pixels in their correct location, one by one */
for (i = 0; i < row_len; i += ((state->bits + 7) / 8)) { for (i = 0; i < row_len; i += ((state->bits + 7) / 8)) {
state->shuffle((UINT8*) im->image[state->y] + state->shuffle(
col * im->pixelsize, (UINT8 *)im->image[state->y] + col * im->pixelsize,
state->buffer + context->prefix + i, 1); state->buffer + context->prefix + i,
1);
col += COL_INCREMENT[context->pass]; col += COL_INCREMENT[context->pass];
} }
} else { } else {
/* Handle case with more than a pixel in each byte */ /* Handle case with more than a pixel in each byte */
int row_bits = ((state->xsize + OFFSET[context->pass]) int row_bits = ((state->xsize + OFFSET[context->pass]) /
/ COL_INCREMENT[context->pass]) * state->bits; COL_INCREMENT[context->pass]) *
state->bits;
for (i = 0; i < row_bits; i += state->bits) { for (i = 0; i < row_bits; i += state->bits) {
UINT8 byte = *(state->buffer + context->prefix + (i / 8)); UINT8 byte = *(state->buffer + context->prefix + (i / 8));
byte <<= (i % 8); byte <<= (i % 8);
state->shuffle((UINT8*) im->image[state->y] + state->shuffle(
col * im->pixelsize, &byte, 1); (UINT8 *)im->image[state->y] + col * im->pixelsize, &byte, 1);
col += COL_INCREMENT[context->pass]; col += COL_INCREMENT[context->pass];
} }
} }
@ -250,13 +246,14 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
row_len = get_row_len(state, context->pass); row_len = get_row_len(state, context->pass);
/* Since we're moving to the "first" line, the previous line /* Since we're moving to the "first" line, the previous line
* should be black to make filters work correctly */ * should be black to make filters work correctly */
memset(state->buffer, 0, state->bytes+1); memset(state->buffer, 0, state->bytes + 1);
} }
} else { } else {
state->shuffle((UINT8*) im->image[state->y + state->yoff] + state->shuffle(
state->xoff * im->pixelsize, (UINT8 *)im->image[state->y + state->yoff] +
state->buffer + context->prefix, state->xoff * im->pixelsize,
state->xsize); state->buffer + context->prefix,
state->xsize);
state->y++; state->y++;
} }
@ -264,7 +261,6 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
context->last_output = 0; context->last_output = 0;
if (state->y >= state->ysize || err == Z_STREAM_END) { if (state->y >= state->ysize || err == Z_STREAM_END) {
/* The image and the data should end simultaneously */ /* The image and the data should end simultaneously */
/* if (state->y < state->ysize || err != Z_STREAM_END) /* if (state->y < state->ysize || err != Z_STREAM_END)
state->errcode = IMAGING_CODEC_BROKEN; */ state->errcode = IMAGING_CODEC_BROKEN; */
@ -273,26 +269,23 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
context->previous = NULL; context->previous = NULL;
inflateEnd(&context->z_stream); inflateEnd(&context->z_stream);
return -1; /* end of file (errcode=0) */ return -1; /* end of file (errcode=0) */
} }
/* Swap buffer pointers */ /* Swap buffer pointers */
ptr = state->buffer; ptr = state->buffer;
state->buffer = context->previous; state->buffer = context->previous;
context->previous = ptr; context->previous = ptr;
} }
return bytes; /* consumed all of it */ return bytes; /* consumed all of it */
} }
int
int ImagingZipDecodeCleanup(ImagingCodecState state){ ImagingZipDecodeCleanup(ImagingCodecState state) {
/* called to free the decompression engine when the decode terminates /* called to free the decompression engine when the decode terminates
due to a corrupt or truncated image due to a corrupt or truncated image
*/ */
ZIPSTATE* context = (ZIPSTATE*) state->context; ZIPSTATE *context = (ZIPSTATE *)state->context;
/* Clean up */ /* Clean up */
if (context->previous) { if (context->previous) {

View File

@ -14,25 +14,22 @@
* See the README file for information on usage and redistribution. * See the README file for information on usage and redistribution.
*/ */
#include "Imaging.h" #include "Imaging.h"
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ
#include "ZipCodecs.h" #include "ZipCodecs.h"
int int
ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
{ ZIPSTATE *context = (ZIPSTATE *)state->context;
ZIPSTATE* context = (ZIPSTATE*) state->context;
int err; int err;
int compress_level, compress_type; int compress_level, compress_type;
UINT8* ptr; UINT8 *ptr;
int i, bpp, s, sum; int i, bpp, s, sum;
ImagingSectionCookie cookie; ImagingSectionCookie cookie;
if (!state->state) { if (!state->state) {
/* Initialization */ /* Initialization */
/* Valid modes are ZIP_PNG, ZIP_PNG_PALETTE, and ZIP_TIFF */ /* Valid modes are ZIP_PNG, ZIP_PNG_PALETTE, and ZIP_TIFF */
@ -47,14 +44,14 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
and allocate filter buffers */ and allocate filter buffers */
free(state->buffer); free(state->buffer);
/* malloc check ok, overflow checked above */ /* malloc check ok, overflow checked above */
state->buffer = (UINT8*) malloc(state->bytes+1); state->buffer = (UINT8 *)malloc(state->bytes + 1);
context->previous = (UINT8*) malloc(state->bytes+1); context->previous = (UINT8 *)malloc(state->bytes + 1);
context->prior = (UINT8*) malloc(state->bytes+1); context->prior = (UINT8 *)malloc(state->bytes + 1);
context->up = (UINT8*) malloc(state->bytes+1); context->up = (UINT8 *)malloc(state->bytes + 1);
context->average = (UINT8*) malloc(state->bytes+1); context->average = (UINT8 *)malloc(state->bytes + 1);
context->paeth = (UINT8*) malloc(state->bytes+1); context->paeth = (UINT8 *)malloc(state->bytes + 1);
if (!state->buffer || !context->previous || !context->prior || if (!state->buffer || !context->previous || !context->prior || !context->up ||
!context->up || !context->average || !context->paeth) { !context->average || !context->paeth) {
free(context->paeth); free(context->paeth);
free(context->average); free(context->average);
free(context->up); free(context->up);
@ -72,7 +69,7 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
context->paeth[0] = 4; context->paeth[0] = 4;
/* Initialise previous buffer to black */ /* Initialise previous buffer to black */
memset(context->previous, 0, state->bytes+1); memset(context->previous, 0, state->bytes + 1);
/* Setup compression context */ /* Setup compression context */
context->z_stream.zalloc = (alloc_func)0; context->z_stream.zalloc = (alloc_func)0;
@ -81,33 +78,37 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
context->z_stream.next_in = 0; context->z_stream.next_in = 0;
context->z_stream.avail_in = 0; context->z_stream.avail_in = 0;
compress_level = (context->optimize) ? Z_BEST_COMPRESSION compress_level =
: context->compress_level; (context->optimize) ? Z_BEST_COMPRESSION : context->compress_level;
if (context->compress_type == -1) { if (context->compress_type == -1) {
compress_type = (context->mode == ZIP_PNG) ? Z_FILTERED compress_type =
: Z_DEFAULT_STRATEGY; (context->mode == ZIP_PNG) ? Z_FILTERED : Z_DEFAULT_STRATEGY;
} else { } else {
compress_type = context->compress_type; compress_type = context->compress_type;
} }
err = deflateInit2(&context->z_stream, err = deflateInit2(
/* compression level */ &context->z_stream,
compress_level, /* compression level */
/* compression method */ compress_level,
Z_DEFLATED, /* compression method */
/* compression memory resources */ Z_DEFLATED,
15, 9, /* compression memory resources */
/* compression strategy (image data are filtered)*/ 15,
compress_type); 9,
/* compression strategy (image data are filtered)*/
compress_type);
if (err < 0) { if (err < 0) {
state->errcode = IMAGING_CODEC_CONFIG; state->errcode = IMAGING_CODEC_CONFIG;
return -1; return -1;
} }
if (context->dictionary && context->dictionary_size > 0) { if (context->dictionary && context->dictionary_size > 0) {
err = deflateSetDictionary(&context->z_stream, (unsigned char *)context->dictionary, err = deflateSetDictionary(
context->dictionary_size); &context->z_stream,
(unsigned char *)context->dictionary,
context->dictionary_size);
if (err < 0) { if (err < 0) {
state->errcode = IMAGING_CODEC_CONFIG; state->errcode = IMAGING_CODEC_CONFIG;
return -1; return -1;
@ -116,7 +117,6 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
/* Ready to decode */ /* Ready to decode */
state->state = 1; state->state = 1;
} }
/* Setup the destination buffer */ /* Setup the destination buffer */
@ -147,203 +147,194 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
ImagingSectionEnter(&cookie); ImagingSectionEnter(&cookie);
for (;;) { for (;;) {
switch (state->state) { switch (state->state) {
case 1:
case 1: /* Compress image data */
while (context->z_stream.avail_out > 0) {
/* Compress image data */ if (state->y >= state->ysize) {
while (context->z_stream.avail_out > 0) { /* End of image; now flush compressor buffers */
state->state = 2;
if (state->y >= state->ysize) { break;
/* End of image; now flush compressor buffers */
state->state = 2;
break;
}
/* Stuff image data into the compressor */
state->shuffle(state->buffer+1,
(UINT8*) im->image[state->y + state->yoff] +
state->xoff * im->pixelsize,
state->xsize);
state->y++;
context->output = state->buffer;
if (context->mode == ZIP_PNG) {
/* Filter the image data. For each line, select
the filter that gives the least total distance
from zero for the filtered data (taken from
LIBPNG) */
bpp = (state->bits + 7) / 8;
/* 0. No filter */
for (i = 1, sum = 0; i <= state->bytes; i++) {
UINT8 v = state->buffer[i];
sum += (v < 128) ? v : 256 - v;
} }
/* 2. Up. We'll test this first to save time when /* Stuff image data into the compressor */
an image line is identical to the one above. */ state->shuffle(
if (sum > 0) { state->buffer + 1,
for (i = 1, s = 0; i <= state->bytes; i++) { (UINT8 *)im->image[state->y + state->yoff] +
UINT8 v = state->buffer[i] - context->previous[i]; state->xoff * im->pixelsize,
context->up[i] = v; state->xsize);
s += (v < 128) ? v : 256 - v;
}
if (s < sum) {
context->output = context->up;
sum = s; /* 0 if line was duplicated */
}
}
/* 1. Prior */ state->y++;
if (sum > 0) {
for (i = 1, s = 0; i <= bpp; i++) { context->output = state->buffer;
if (context->mode == ZIP_PNG) {
/* Filter the image data. For each line, select
the filter that gives the least total distance
from zero for the filtered data (taken from
LIBPNG) */
bpp = (state->bits + 7) / 8;
/* 0. No filter */
for (i = 1, sum = 0; i <= state->bytes; i++) {
UINT8 v = state->buffer[i]; UINT8 v = state->buffer[i];
context->prior[i] = v; sum += (v < 128) ? v : 256 - v;
s += (v < 128) ? v : 256 - v;
} }
for (; i <= state->bytes; i++) {
UINT8 v = state->buffer[i] - state->buffer[i-bpp]; /* 2. Up. We'll test this first to save time when
context->prior[i] = v; an image line is identical to the one above. */
s += (v < 128) ? v : 256 - v; if (sum > 0) {
for (i = 1, s = 0; i <= state->bytes; i++) {
UINT8 v = state->buffer[i] - context->previous[i];
context->up[i] = v;
s += (v < 128) ? v : 256 - v;
}
if (s < sum) {
context->output = context->up;
sum = s; /* 0 if line was duplicated */
}
} }
if (s < sum) {
context->output = context->prior; /* 1. Prior */
sum = s; /* 0 if line is solid */ if (sum > 0) {
for (i = 1, s = 0; i <= bpp; i++) {
UINT8 v = state->buffer[i];
context->prior[i] = v;
s += (v < 128) ? v : 256 - v;
}
for (; i <= state->bytes; i++) {
UINT8 v = state->buffer[i] - state->buffer[i - bpp];
context->prior[i] = v;
s += (v < 128) ? v : 256 - v;
}
if (s < sum) {
context->output = context->prior;
sum = s; /* 0 if line is solid */
}
}
/* 3. Average (not very common in real-life images,
so its only used with the optimize option) */
if (context->optimize && sum > 0) {
for (i = 1, s = 0; i <= bpp; i++) {
UINT8 v = state->buffer[i] - context->previous[i] / 2;
context->average[i] = v;
s += (v < 128) ? v : 256 - v;
}
for (; i <= state->bytes; i++) {
UINT8 v =
state->buffer[i] -
(state->buffer[i - bpp] + context->previous[i]) / 2;
context->average[i] = v;
s += (v < 128) ? v : 256 - v;
}
if (s < sum) {
context->output = context->average;
sum = s;
}
}
/* 4. Paeth */
if (sum > 0) {
for (i = 1, s = 0; i <= bpp; i++) {
UINT8 v = state->buffer[i] - context->previous[i];
context->paeth[i] = v;
s += (v < 128) ? v : 256 - v;
}
for (; i <= state->bytes; i++) {
UINT8 v;
int a, b, c;
int pa, pb, pc;
/* fetch pixels */
a = state->buffer[i - bpp];
b = context->previous[i];
c = context->previous[i - bpp];
/* distances to surrounding pixels */
pa = abs(b - c);
pb = abs(a - c);
pc = abs(a + b - 2 * c);
/* pick predictor with the shortest distance */
v = state->buffer[i] - ((pa <= pb && pa <= pc) ? a
: (pb <= pc) ? b
: c);
context->paeth[i] = v;
s += (v < 128) ? v : 256 - v;
}
if (s < sum) {
context->output = context->paeth;
sum = s;
}
} }
} }
/* 3. Average (not very common in real-life images, /* Compress this line */
so its only used with the optimize option) */ context->z_stream.next_in = context->output;
if (context->optimize && sum > 0) { context->z_stream.avail_in = state->bytes + 1;
for (i = 1, s = 0; i <= bpp; i++) {
UINT8 v = state->buffer[i] - context->previous[i]/2; err = deflate(&context->z_stream, Z_NO_FLUSH);
context->average[i] = v;
s += (v < 128) ? v : 256 - v; if (err < 0) {
} /* Something went wrong inside the compression library */
for (; i <= state->bytes; i++) { if (err == Z_DATA_ERROR) {
UINT8 v = state->buffer[i] - state->errcode = IMAGING_CODEC_BROKEN;
(state->buffer[i-bpp] + context->previous[i])/2; } else if (err == Z_MEM_ERROR) {
context->average[i] = v; state->errcode = IMAGING_CODEC_MEMORY;
s += (v < 128) ? v : 256 - v; } else {
} state->errcode = IMAGING_CODEC_CONFIG;
if (s < sum) {
context->output = context->average;
sum = s;
} }
free(context->paeth);
free(context->average);
free(context->up);
free(context->prior);
free(context->previous);
deflateEnd(&context->z_stream);
ImagingSectionLeave(&cookie);
return -1;
} }
/* 4. Paeth */ /* Swap buffer pointers */
if (sum > 0) { ptr = state->buffer;
for (i = 1, s = 0; i <= bpp; i++) { state->buffer = context->previous;
UINT8 v = state->buffer[i] - context->previous[i]; context->previous = ptr;
context->paeth[i] = v;
s += (v < 128) ? v : 256 - v;
}
for (; i <= state->bytes; i++) {
UINT8 v;
int a, b, c;
int pa, pb, pc;
/* fetch pixels */
a = state->buffer[i-bpp];
b = context->previous[i];
c = context->previous[i-bpp];
/* distances to surrounding pixels */
pa = abs(b - c);
pb = abs(a - c);
pc = abs(a + b - 2*c);
/* pick predictor with the shortest distance */
v = state->buffer[i] -
((pa <= pb && pa <= pc) ? a :
(pb <= pc) ? b : c);
context->paeth[i] = v;
s += (v < 128) ? v : 256 - v;
}
if (s < sum) {
context->output = context->paeth;
sum = s;
}
}
}
/* Compress this line */
context->z_stream.next_in = context->output;
context->z_stream.avail_in = state->bytes+1;
err = deflate(&context->z_stream, Z_NO_FLUSH);
if (err < 0) {
/* Something went wrong inside the compression library */
if (err == Z_DATA_ERROR) {
state->errcode = IMAGING_CODEC_BROKEN;
} else if (err == Z_MEM_ERROR) {
state->errcode = IMAGING_CODEC_MEMORY;
} else {
state->errcode = IMAGING_CODEC_CONFIG;
}
free(context->paeth);
free(context->average);
free(context->up);
free(context->prior);
free(context->previous);
deflateEnd(&context->z_stream);
ImagingSectionLeave(&cookie);
return -1;
}
/* Swap buffer pointers */
ptr = state->buffer;
state->buffer = context->previous;
context->previous = ptr;
}
if (context->z_stream.avail_out == 0) {
break; /* Buffer full */
}
case 2:
/* End of image data; flush compressor buffers */
while (context->z_stream.avail_out > 0) {
err = deflate(&context->z_stream, Z_FINISH);
if (err == Z_STREAM_END) {
free(context->paeth);
free(context->average);
free(context->up);
free(context->prior);
free(context->previous);
deflateEnd(&context->z_stream);
state->errcode = IMAGING_CODEC_END;
break;
} }
if (context->z_stream.avail_out == 0) { if (context->z_stream.avail_out == 0) {
break; /* Buffer full */ break; /* Buffer full */
} }
} case 2:
/* End of image data; flush compressor buffers */
while (context->z_stream.avail_out > 0) {
err = deflate(&context->z_stream, Z_FINISH);
if (err == Z_STREAM_END) {
free(context->paeth);
free(context->average);
free(context->up);
free(context->prior);
free(context->previous);
deflateEnd(&context->z_stream);
state->errcode = IMAGING_CODEC_END;
break;
}
if (context->z_stream.avail_out == 0) {
break; /* Buffer full */
}
}
} }
ImagingSectionLeave(&cookie); ImagingSectionLeave(&cookie);
return bytes - context->z_stream.avail_out; return bytes - context->z_stream.avail_out;
} }
/* Should never ever arrive here... */ /* Should never ever arrive here... */
@ -358,21 +349,18 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
int int
ImagingZipEncodeCleanup(ImagingCodecState state) { ImagingZipEncodeCleanup(ImagingCodecState state) {
ZIPSTATE* context = (ZIPSTATE*) state->context; ZIPSTATE *context = (ZIPSTATE *)state->context;
if (context->dictionary) { if (context->dictionary) {
free (context->dictionary); free(context->dictionary);
context->dictionary = NULL; context->dictionary = NULL;
} }
return -1; return -1;
} }
const char *
ImagingZipVersion(void) {
const char*
ImagingZipVersion(void)
{
return zlibVersion(); return zlibVersion();
} }

View File

@ -1,10 +1,8 @@
#include "Python.h" #include "Python.h"
#include "Imaging.h" #include "Imaging.h"
Py_ssize_t Py_ssize_t
_imaging_read_pyFd(PyObject *fd, char* dest, Py_ssize_t bytes) _imaging_read_pyFd(PyObject *fd, char *dest, Py_ssize_t bytes) {
{
/* dest should be a buffer bytes long, returns length of read /* dest should be a buffer bytes long, returns length of read
-1 on error */ -1 on error */
@ -29,16 +27,13 @@ _imaging_read_pyFd(PyObject *fd, char* dest, Py_ssize_t bytes)
Py_DECREF(result); Py_DECREF(result);
return length; return length;
err: err:
Py_DECREF(result); Py_DECREF(result);
return -1; return -1;
} }
Py_ssize_t Py_ssize_t
_imaging_write_pyFd(PyObject *fd, char* src, Py_ssize_t bytes) _imaging_write_pyFd(PyObject *fd, char *src, Py_ssize_t bytes) {
{
PyObject *result; PyObject *result;
PyObject *byteObj; PyObject *byteObj;
@ -49,24 +44,20 @@ _imaging_write_pyFd(PyObject *fd, char* src, Py_ssize_t bytes)
Py_DECREF(result); Py_DECREF(result);
return bytes; return bytes;
} }
int int
_imaging_seek_pyFd(PyObject *fd, Py_ssize_t offset, int whence) _imaging_seek_pyFd(PyObject *fd, Py_ssize_t offset, int whence) {
{
PyObject *result; PyObject *result;
result = PyObject_CallMethod(fd, "seek", "ni", offset, whence); result = PyObject_CallMethod(fd, "seek", "ni", offset, whence);
Py_DECREF(result); Py_DECREF(result);
return 0; return 0;
} }
Py_ssize_t Py_ssize_t
_imaging_tell_pyFd(PyObject *fd) _imaging_tell_pyFd(PyObject *fd) {
{
PyObject *result; PyObject *result;
Py_ssize_t location; Py_ssize_t location;

View File

@ -63,8 +63,7 @@ typedef struct _raqm raqm_t;
* *
* Since: 0.1 * Since: 0.1
*/ */
typedef enum typedef enum {
{
RAQM_DIRECTION_DEFAULT, RAQM_DIRECTION_DEFAULT,
RAQM_DIRECTION_RTL, RAQM_DIRECTION_RTL,
RAQM_DIRECTION_LTR, RAQM_DIRECTION_LTR,
@ -106,73 +105,50 @@ typedef struct raqm_glyph_t_01 {
uint32_t cluster; uint32_t cluster;
} raqm_glyph_t_01; } raqm_glyph_t_01;
raqm_t *
raqm_create(void);
raqm_t * raqm_t *
raqm_create (void); raqm_reference(raqm_t *rq);
raqm_t *
raqm_reference (raqm_t *rq);
void void
raqm_destroy (raqm_t *rq); raqm_destroy(raqm_t *rq);
bool bool
raqm_set_text (raqm_t *rq, raqm_set_text(raqm_t *rq, const uint32_t *text, size_t len);
const uint32_t *text,
size_t len);
bool bool
raqm_set_text_utf8 (raqm_t *rq, raqm_set_text_utf8(raqm_t *rq, const char *text, size_t len);
const char *text,
size_t len);
bool bool
raqm_set_par_direction (raqm_t *rq, raqm_set_par_direction(raqm_t *rq, raqm_direction_t dir);
raqm_direction_t dir);
bool bool
raqm_set_language (raqm_t *rq, raqm_set_language(raqm_t *rq, const char *lang, size_t start, size_t len);
const char *lang,
size_t start,
size_t len);
bool bool
raqm_add_font_feature (raqm_t *rq, raqm_add_font_feature(raqm_t *rq, const char *feature, int len);
const char *feature,
int len);
bool bool
raqm_set_freetype_face (raqm_t *rq, raqm_set_freetype_face(raqm_t *rq, FT_Face face);
FT_Face face);
bool bool
raqm_set_freetype_face_range (raqm_t *rq, raqm_set_freetype_face_range(raqm_t *rq, FT_Face face, size_t start, size_t len);
FT_Face face,
size_t start,
size_t len);
bool bool
raqm_set_freetype_load_flags (raqm_t *rq, raqm_set_freetype_load_flags(raqm_t *rq, int flags);
int flags);
bool bool
raqm_layout (raqm_t *rq); raqm_layout(raqm_t *rq);
raqm_glyph_t * raqm_glyph_t *
raqm_get_glyphs (raqm_t *rq, raqm_get_glyphs(raqm_t *rq, size_t *length);
size_t *length);
bool bool
raqm_index_to_position (raqm_t *rq, raqm_index_to_position(raqm_t *rq, size_t *index, int *x, int *y);
size_t *index,
int *x,
int *y);
bool bool
raqm_position_to_index (raqm_t *rq, raqm_position_to_index(raqm_t *rq, int x, int y, size_t *index);
int x,
int y,
size_t *index);
#ifdef __cplusplus #ifdef __cplusplus
} }

182
src/map.c
View File

@ -23,17 +23,18 @@
#include "libImaging/Imaging.h" #include "libImaging/Imaging.h"
/* compatibility wrappers (defined in _imaging.c) */ /* compatibility wrappers (defined in _imaging.c) */
extern int PyImaging_CheckBuffer(PyObject* buffer); extern int
extern int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view); PyImaging_CheckBuffer(PyObject *buffer);
extern int
PyImaging_GetBuffer(PyObject *buffer, Py_buffer *view);
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Standard mapper */ /* Standard mapper */
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD char *base;
char* base; int size;
int size; int offset;
int offset;
#ifdef _WIN32 #ifdef _WIN32
HANDLE hFile; HANDLE hFile;
HANDLE hMap; HANDLE hMap;
@ -42,9 +43,8 @@ typedef struct {
static PyTypeObject ImagingMapperType; static PyTypeObject ImagingMapperType;
ImagingMapperObject* ImagingMapperObject *
PyImaging_MapperNew(const char* filename, int readonly) PyImaging_MapperNew(const char *filename, int readonly) {
{
ImagingMapperObject *mapper; ImagingMapperObject *mapper;
if (PyType_Ready(&ImagingMapperType) < 0) { if (PyType_Ready(&ImagingMapperType) < 0) {
@ -61,14 +61,15 @@ PyImaging_MapperNew(const char* filename, int readonly)
#ifdef _WIN32 #ifdef _WIN32
mapper->hFile = (HANDLE)-1; mapper->hFile = (HANDLE)-1;
mapper->hMap = (HANDLE)-1; mapper->hMap = (HANDLE)-1;
/* FIXME: currently supports readonly mappings only */ /* FIXME: currently supports readonly mappings only */
mapper->hFile = CreateFile( mapper->hFile = CreateFile(
filename, filename,
GENERIC_READ, GENERIC_READ,
FILE_SHARE_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL,
NULL); NULL);
if (mapper->hFile == (HANDLE)-1) { if (mapper->hFile == (HANDLE)-1) {
@ -77,10 +78,7 @@ PyImaging_MapperNew(const char* filename, int readonly)
return NULL; return NULL;
} }
mapper->hMap = CreateFileMapping( mapper->hMap = CreateFileMapping(mapper->hFile, NULL, PAGE_READONLY, 0, 0, NULL);
mapper->hFile, NULL,
PAGE_READONLY,
0, 0, NULL);
if (mapper->hMap == (HANDLE)-1) { if (mapper->hMap == (HANDLE)-1) {
CloseHandle(mapper->hFile); CloseHandle(mapper->hFile);
PyErr_SetString(PyExc_OSError, "cannot map file"); PyErr_SetString(PyExc_OSError, "cannot map file");
@ -88,10 +86,7 @@ PyImaging_MapperNew(const char* filename, int readonly)
return NULL; return NULL;
} }
mapper->base = (char*) MapViewOfFile( mapper->base = (char *)MapViewOfFile(mapper->hMap, FILE_MAP_READ, 0, 0, 0);
mapper->hMap,
FILE_MAP_READ,
0, 0, 0);
mapper->size = GetFileSize(mapper->hFile, 0); mapper->size = GetFileSize(mapper->hFile, 0);
#endif #endif
@ -100,8 +95,7 @@ PyImaging_MapperNew(const char* filename, int readonly)
} }
static void static void
mapping_dealloc(ImagingMapperObject* mapper) mapping_dealloc(ImagingMapperObject *mapper) {
{
#ifdef _WIN32 #ifdef _WIN32
if (mapper->base != 0) { if (mapper->base != 0) {
UnmapViewOfFile(mapper->base); UnmapViewOfFile(mapper->base);
@ -121,10 +115,9 @@ mapping_dealloc(ImagingMapperObject* mapper)
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* standard file operations */ /* standard file operations */
static PyObject* static PyObject *
mapping_read(ImagingMapperObject* mapper, PyObject* args) mapping_read(ImagingMapperObject *mapper, PyObject *args) {
{ PyObject *buf;
PyObject* buf;
int size = -1; int size = -1;
if (!PyArg_ParseTuple(args, "|i", &size)) { if (!PyArg_ParseTuple(args, "|i", &size)) {
@ -152,9 +145,8 @@ mapping_read(ImagingMapperObject* mapper, PyObject* args)
return buf; return buf;
} }
static PyObject* static PyObject *
mapping_seek(ImagingMapperObject* mapper, PyObject* args) mapping_seek(ImagingMapperObject *mapper, PyObject *args) {
{
int offset; int offset;
int whence = 0; int whence = 0;
if (!PyArg_ParseTuple(args, "i|i", &offset, &whence)) { if (!PyArg_ParseTuple(args, "i|i", &offset, &whence)) {
@ -183,27 +175,26 @@ mapping_seek(ImagingMapperObject* mapper, PyObject* args)
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* map entire image */ /* map entire image */
extern PyObject*PyImagingNew(Imaging im); extern PyObject *
PyImagingNew(Imaging im);
static void static void
ImagingDestroyMap(Imaging im) ImagingDestroyMap(Imaging im) {
{
return; /* nothing to do! */ return; /* nothing to do! */
} }
static PyObject* static PyObject *
mapping_readimage(ImagingMapperObject* mapper, PyObject* args) mapping_readimage(ImagingMapperObject *mapper, PyObject *args) {
{
int y, size; int y, size;
Imaging im; Imaging im;
char* mode; char *mode;
int xsize; int xsize;
int ysize; int ysize;
int stride; int stride;
int orientation; int orientation;
if (!PyArg_ParseTuple(args, "s(ii)ii", &mode, &xsize, &ysize, if (!PyArg_ParseTuple(
&stride, &orientation)) { args, "s(ii)ii", &mode, &xsize, &ysize, &stride, &orientation)) {
return NULL; return NULL;
} }
@ -237,7 +228,7 @@ mapping_readimage(ImagingMapperObject* mapper, PyObject* args)
} }
} else { } else {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
im->image[ysize-y-1] = mapper->base + mapper->offset + y * stride; im->image[ysize - y - 1] = mapper->base + mapper->offset + y * stride;
} }
} }
@ -258,48 +249,46 @@ static struct PyMethodDef methods[] = {
}; };
static PyTypeObject ImagingMapperType = { static PyTypeObject ImagingMapperType = {
PyVarObject_HEAD_INIT(NULL, 0) PyVarObject_HEAD_INIT(NULL, 0) "ImagingMapper", /*tp_name*/
"ImagingMapper", /*tp_name*/ sizeof(ImagingMapperObject), /*tp_size*/
sizeof(ImagingMapperObject), /*tp_size*/ 0, /*tp_itemsize*/
0, /*tp_itemsize*/ /* methods */
/* methods */ (destructor)mapping_dealloc, /*tp_dealloc*/
(destructor)mapping_dealloc, /*tp_dealloc*/ 0, /*tp_print*/
0, /*tp_print*/ 0, /*tp_getattr*/
0, /*tp_getattr*/ 0, /*tp_setattr*/
0, /*tp_setattr*/ 0, /*tp_compare*/
0, /*tp_compare*/ 0, /*tp_repr*/
0, /*tp_repr*/ 0, /*tp_as_number */
0, /*tp_as_number */ 0, /*tp_as_sequence */
0, /*tp_as_sequence */ 0, /*tp_as_mapping */
0, /*tp_as_mapping */ 0, /*tp_hash*/
0, /*tp_hash*/ 0, /*tp_call*/
0, /*tp_call*/ 0, /*tp_str*/
0, /*tp_str*/ 0, /*tp_getattro*/
0, /*tp_getattro*/ 0, /*tp_setattro*/
0, /*tp_setattro*/ 0, /*tp_as_buffer*/
0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/ 0, /*tp_doc*/
0, /*tp_doc*/ 0, /*tp_traverse*/
0, /*tp_traverse*/ 0, /*tp_clear*/
0, /*tp_clear*/ 0, /*tp_richcompare*/
0, /*tp_richcompare*/ 0, /*tp_weaklistoffset*/
0, /*tp_weaklistoffset*/ 0, /*tp_iter*/
0, /*tp_iter*/ 0, /*tp_iternext*/
0, /*tp_iternext*/ methods, /*tp_methods*/
methods, /*tp_methods*/ 0, /*tp_members*/
0, /*tp_members*/ 0, /*tp_getset*/
0, /*tp_getset*/
}; };
PyObject* PyObject *
PyImaging_Mapper(PyObject* self, PyObject* args) PyImaging_Mapper(PyObject *self, PyObject *args) {
{ char *filename;
char* filename;
if (!PyArg_ParseTuple(args, "s", &filename)) { if (!PyArg_ParseTuple(args, "s", &filename)) {
return NULL; return NULL;
} }
return (PyObject*) PyImaging_MapperNew(filename, 1); return (PyObject *)PyImaging_MapperNew(filename, 1);
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
@ -307,36 +296,43 @@ PyImaging_Mapper(PyObject* self, PyObject* args)
typedef struct ImagingBufferInstance { typedef struct ImagingBufferInstance {
struct ImagingMemoryInstance im; struct ImagingMemoryInstance im;
PyObject* target; PyObject *target;
Py_buffer view; Py_buffer view;
} ImagingBufferInstance; } ImagingBufferInstance;
static void static void
mapping_destroy_buffer(Imaging im) mapping_destroy_buffer(Imaging im) {
{ ImagingBufferInstance *buffer = (ImagingBufferInstance *)im;
ImagingBufferInstance* buffer = (ImagingBufferInstance*) im;
PyBuffer_Release(&buffer->view); PyBuffer_Release(&buffer->view);
Py_XDECREF(buffer->target); Py_XDECREF(buffer->target);
} }
PyObject* PyObject *
PyImaging_MapBuffer(PyObject* self, PyObject* args) PyImaging_MapBuffer(PyObject *self, PyObject *args) {
{
Py_ssize_t y, size; Py_ssize_t y, size;
Imaging im; Imaging im;
PyObject* target; PyObject *target;
Py_buffer view; Py_buffer view;
char* mode; char *mode;
char* codec; char *codec;
Py_ssize_t offset; Py_ssize_t offset;
int xsize, ysize; int xsize, ysize;
int stride; int stride;
int ystep; int ystep;
if (!PyArg_ParseTuple(args, "O(ii)sn(sii)", &target, &xsize, &ysize, if (!PyArg_ParseTuple(
&codec, &offset, &mode, &stride, &ystep)) { args,
"O(ii)sn(sii)",
&target,
&xsize,
&ysize,
&codec,
&offset,
&mode,
&stride,
&ystep)) {
return NULL; return NULL;
} }
@ -360,7 +356,7 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
return NULL; return NULL;
} }
size = (Py_ssize_t) ysize * stride; size = (Py_ssize_t)ysize * stride;
if (offset > PY_SSIZE_T_MAX - size) { if (offset > PY_SSIZE_T_MAX - size) {
PyErr_SetString(PyExc_MemoryError, "Integer overflow in offset"); PyErr_SetString(PyExc_MemoryError, "Integer overflow in offset");
@ -383,8 +379,7 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
return NULL; return NULL;
} }
im = ImagingNewPrologueSubtype( im = ImagingNewPrologueSubtype(mode, xsize, ysize, sizeof(ImagingBufferInstance));
mode, xsize, ysize, sizeof(ImagingBufferInstance));
if (!im) { if (!im) {
PyBuffer_Release(&view); PyBuffer_Release(&view);
return NULL; return NULL;
@ -393,20 +388,19 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
/* setup file pointers */ /* setup file pointers */
if (ystep > 0) { if (ystep > 0) {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
im->image[y] = (char*)view.buf + offset + y * stride; im->image[y] = (char *)view.buf + offset + y * stride;
} }
} else { } else {
for (y = 0; y < ysize; y++) { for (y = 0; y < ysize; y++) {
im->image[ysize-y-1] = (char*)view.buf + offset + y * stride; im->image[ysize - y - 1] = (char *)view.buf + offset + y * stride;
} }
} }
im->destroy = mapping_destroy_buffer; im->destroy = mapping_destroy_buffer;
Py_INCREF(target); Py_INCREF(target);
((ImagingBufferInstance*) im)->target = target; ((ImagingBufferInstance *)im)->target = target;
((ImagingBufferInstance*) im)->view = view; ((ImagingBufferInstance *)im)->view = view;
return PyImagingNew(im); return PyImagingNew(im);
} }

View File

@ -21,22 +21,19 @@
#include "libImaging/Imaging.h" #include "libImaging/Imaging.h"
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Class */ /* Class */
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD ImagingOutline outline;
ImagingOutline outline;
} OutlineObject; } OutlineObject;
static PyTypeObject OutlineType; static PyTypeObject OutlineType;
#define PyOutline_Check(op) (Py_TYPE(op) == &OutlineType) #define PyOutline_Check(op) (Py_TYPE(op) == &OutlineType)
static OutlineObject* static OutlineObject *
_outline_new(void) _outline_new(void) {
{
OutlineObject *self; OutlineObject *self;
if (PyType_Ready(&OutlineType) < 0) { if (PyType_Ready(&OutlineType) < 0) {
@ -54,43 +51,37 @@ _outline_new(void)
} }
static void static void
_outline_dealloc(OutlineObject* self) _outline_dealloc(OutlineObject *self) {
{
ImagingOutlineDelete(self->outline); ImagingOutlineDelete(self->outline);
PyObject_Del(self); PyObject_Del(self);
} }
ImagingOutline ImagingOutline
PyOutline_AsOutline(PyObject* outline) PyOutline_AsOutline(PyObject *outline) {
{
if (PyOutline_Check(outline)) { if (PyOutline_Check(outline)) {
return ((OutlineObject*) outline)->outline; return ((OutlineObject *)outline)->outline;
} }
return NULL; return NULL;
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Factories */ /* Factories */
PyObject* PyObject *
PyOutline_Create(PyObject* self, PyObject* args) PyOutline_Create(PyObject *self, PyObject *args) {
{
if (!PyArg_ParseTuple(args, ":outline")) { if (!PyArg_ParseTuple(args, ":outline")) {
return NULL; return NULL;
} }
return (PyObject*) _outline_new(); return (PyObject *)_outline_new();
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Methods */ /* Methods */
static PyObject* static PyObject *
_outline_move(OutlineObject* self, PyObject* args) _outline_move(OutlineObject *self, PyObject *args) {
{
float x0, y0; float x0, y0;
if (!PyArg_ParseTuple(args, "ff", &x0, &y0)) { if (!PyArg_ParseTuple(args, "ff", &x0, &y0)) {
return NULL; return NULL;
@ -102,9 +93,8 @@ _outline_move(OutlineObject* self, PyObject* args)
return Py_None; return Py_None;
} }
static PyObject* static PyObject *
_outline_line(OutlineObject* self, PyObject* args) _outline_line(OutlineObject *self, PyObject *args) {
{
float x1, y1; float x1, y1;
if (!PyArg_ParseTuple(args, "ff", &x1, &y1)) { if (!PyArg_ParseTuple(args, "ff", &x1, &y1)) {
return NULL; return NULL;
@ -116,9 +106,8 @@ _outline_line(OutlineObject* self, PyObject* args)
return Py_None; return Py_None;
} }
static PyObject* static PyObject *
_outline_curve(OutlineObject* self, PyObject* args) _outline_curve(OutlineObject *self, PyObject *args) {
{
float x1, y1, x2, y2, x3, y3; float x1, y1, x2, y2, x3, y3;
if (!PyArg_ParseTuple(args, "ffffff", &x1, &y1, &x2, &y2, &x3, &y3)) { if (!PyArg_ParseTuple(args, "ffffff", &x1, &y1, &x2, &y2, &x3, &y3)) {
return NULL; return NULL;
@ -130,9 +119,8 @@ _outline_curve(OutlineObject* self, PyObject* args)
return Py_None; return Py_None;
} }
static PyObject* static PyObject *
_outline_close(OutlineObject* self, PyObject* args) _outline_close(OutlineObject *self, PyObject *args) {
{
if (!PyArg_ParseTuple(args, ":close")) { if (!PyArg_ParseTuple(args, ":close")) {
return NULL; return NULL;
} }
@ -143,11 +131,10 @@ _outline_close(OutlineObject* self, PyObject* args)
return Py_None; return Py_None;
} }
static PyObject* static PyObject *
_outline_transform(OutlineObject* self, PyObject* args) _outline_transform(OutlineObject *self, PyObject *args) {
{
double a[6]; double a[6];
if (!PyArg_ParseTuple(args, "(dddddd)", a+0, a+1, a+2, a+3, a+4, a+5)) { if (!PyArg_ParseTuple(args, "(dddddd)", a + 0, a + 1, a + 2, a + 3, a + 4, a + 5)) {
return NULL; return NULL;
} }
@ -167,35 +154,34 @@ static struct PyMethodDef _outline_methods[] = {
}; };
static PyTypeObject OutlineType = { static PyTypeObject OutlineType = {
PyVarObject_HEAD_INIT(NULL, 0) PyVarObject_HEAD_INIT(NULL, 0) "Outline", /*tp_name*/
"Outline", /*tp_name*/ sizeof(OutlineObject), /*tp_size*/
sizeof(OutlineObject), /*tp_size*/ 0, /*tp_itemsize*/
0, /*tp_itemsize*/
/* methods */ /* methods */
(destructor)_outline_dealloc,/*tp_dealloc*/ (destructor)_outline_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
0, /*tp_repr*/ 0, /*tp_repr*/
0, /*tp_as_number */ 0, /*tp_as_number */
0, /*tp_as_sequence */ 0, /*tp_as_sequence */
0, /*tp_as_mapping */ 0, /*tp_as_mapping */
0, /*tp_hash*/ 0, /*tp_hash*/
0, /*tp_call*/ 0, /*tp_call*/
0, /*tp_str*/ 0, /*tp_str*/
0, /*tp_getattro*/ 0, /*tp_getattro*/
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/ 0, /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
0, /*tp_richcompare*/ 0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/ 0, /*tp_weaklistoffset*/
0, /*tp_iter*/ 0, /*tp_iter*/
0, /*tp_iternext*/ 0, /*tp_iternext*/
_outline_methods, /*tp_methods*/ _outline_methods, /*tp_methods*/
0, /*tp_members*/ 0, /*tp_members*/
0, /*tp_getset*/ 0, /*tp_getset*/
}; };

Some files were not shown because too many files have changed in this diff Show More