mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-24 00:04:09 +03:00
Format with ClangFormat
This commit is contained in:
parent
e2d00f8cf8
commit
46b7e86bab
|
@ -79,18 +79,20 @@ typedef struct Tcl_Interp Tcl_Interp;
|
|||
typedef struct Tcl_Command_ *Tcl_Command;
|
||||
typedef void *ClientData;
|
||||
|
||||
typedef int (Tcl_CmdProc) (ClientData clientData, Tcl_Interp
|
||||
*interp, int argc, const char *argv[]);
|
||||
typedef void (Tcl_CmdDeleteProc) (ClientData clientData);
|
||||
typedef int(Tcl_CmdProc)(
|
||||
ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[]);
|
||||
typedef void(Tcl_CmdDeleteProc)(ClientData clientData);
|
||||
|
||||
/* Typedefs derived from function signatures in Tcl header */
|
||||
/* Tcl_CreateCommand */
|
||||
typedef Tcl_Command (*Tcl_CreateCommand_t)(Tcl_Interp *interp,
|
||||
const char *cmdName, Tcl_CmdProc *proc,
|
||||
ClientData clientData,
|
||||
Tcl_CmdDeleteProc *deleteProc);
|
||||
typedef Tcl_Command (*Tcl_CreateCommand_t)(
|
||||
Tcl_Interp *interp,
|
||||
const char *cmdName,
|
||||
Tcl_CmdProc *proc,
|
||||
ClientData clientData,
|
||||
Tcl_CmdDeleteProc *deleteProc);
|
||||
/* Tcl_AppendResult */
|
||||
typedef void (*Tcl_AppendResult_t) (Tcl_Interp *interp, ...);
|
||||
typedef void (*Tcl_AppendResult_t)(Tcl_Interp *interp, ...);
|
||||
|
||||
/* Tk header excerpts */
|
||||
|
||||
|
@ -107,8 +109,7 @@ typedef struct Tk_Window_ *Tk_Window;
|
|||
|
||||
typedef void *Tk_PhotoHandle;
|
||||
|
||||
typedef struct Tk_PhotoImageBlock
|
||||
{
|
||||
typedef struct Tk_PhotoImageBlock {
|
||||
unsigned char *pixelPtr;
|
||||
int width;
|
||||
int height;
|
||||
|
@ -119,23 +120,30 @@ typedef struct Tk_PhotoImageBlock
|
|||
|
||||
/* Typedefs derived from function signatures in Tk header */
|
||||
/* Tk_PhotoPutBlock for Tk <= 8.4 */
|
||||
typedef void (*Tk_PhotoPutBlock_84_t) (Tk_PhotoHandle handle,
|
||||
Tk_PhotoImageBlock *blockPtr, int x, int y,
|
||||
int width, int height, int compRule);
|
||||
typedef void (*Tk_PhotoPutBlock_84_t)(
|
||||
Tk_PhotoHandle handle,
|
||||
Tk_PhotoImageBlock *blockPtr,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int compRule);
|
||||
/* Tk_PhotoPutBlock for Tk >= 8.5 */
|
||||
typedef int (*Tk_PhotoPutBlock_85_t) (Tcl_Interp * interp,
|
||||
Tk_PhotoHandle handle,
|
||||
Tk_PhotoImageBlock * blockPtr, int x, int y,
|
||||
int width, int height, int compRule);
|
||||
typedef int (*Tk_PhotoPutBlock_85_t)(
|
||||
Tcl_Interp *interp,
|
||||
Tk_PhotoHandle handle,
|
||||
Tk_PhotoImageBlock *blockPtr,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int compRule);
|
||||
/* Tk_PhotoSetSize for Tk <= 8.4 */
|
||||
typedef void (*Tk_PhotoSetSize_84_t) (Tk_PhotoHandle handle,
|
||||
int width, int height);
|
||||
typedef void (*Tk_PhotoSetSize_84_t)(Tk_PhotoHandle handle, int width, int height);
|
||||
/* Tk_FindPhoto */
|
||||
typedef Tk_PhotoHandle (*Tk_FindPhoto_t) (Tcl_Interp *interp,
|
||||
const char *imageName);
|
||||
typedef Tk_PhotoHandle (*Tk_FindPhoto_t)(Tcl_Interp *interp, const char *imageName);
|
||||
/* Tk_PhotoGetImage */
|
||||
typedef int (*Tk_PhotoGetImage_t) (Tk_PhotoHandle handle,
|
||||
Tk_PhotoImageBlock * blockPtr);
|
||||
typedef int (*Tk_PhotoGetImage_t)(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr);
|
||||
|
||||
/*
|
||||
* end block for C++
|
||||
|
|
|
@ -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 Imaging
|
||||
ImagingFind(const char* name)
|
||||
{
|
||||
ImagingFind(const char *name) {
|
||||
Py_ssize_t id;
|
||||
|
||||
/* FIXME: use CObject instead? */
|
||||
|
@ -72,41 +71,37 @@ ImagingFind(const char* name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return (Imaging) id;
|
||||
return (Imaging)id;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
PyImagingPhotoPut(ClientData clientdata, Tcl_Interp* interp,
|
||||
int argc, const char **argv)
|
||||
{
|
||||
PyImagingPhotoPut(
|
||||
ClientData clientdata, Tcl_Interp *interp, int argc, const char **argv) {
|
||||
Imaging im;
|
||||
Tk_PhotoHandle photo;
|
||||
Tk_PhotoImageBlock block;
|
||||
|
||||
if (argc != 3) {
|
||||
TCL_APPEND_RESULT(interp, "usage: ", argv[0],
|
||||
" destPhoto srcImage", (char *) NULL);
|
||||
TCL_APPEND_RESULT(
|
||||
interp, "usage: ", argv[0], " destPhoto srcImage", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* get Tcl PhotoImage handle */
|
||||
photo = TK_FIND_PHOTO(interp, argv[1]);
|
||||
if (photo == NULL) {
|
||||
TCL_APPEND_RESULT(
|
||||
interp, "destination photo must exist", (char *) NULL
|
||||
);
|
||||
TCL_APPEND_RESULT(interp, "destination photo must exist", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* get PIL Image handle */
|
||||
im = ImagingFind(argv[2]);
|
||||
if (!im) {
|
||||
TCL_APPEND_RESULT(interp, "bad name", (char*) NULL);
|
||||
TCL_APPEND_RESULT(interp, "bad name", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (!im->block) {
|
||||
TCL_APPEND_RESULT(interp, "bad display memory", (char*) NULL);
|
||||
TCL_APPEND_RESULT(interp, "bad display memory", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
@ -126,18 +121,18 @@ PyImagingPhotoPut(ClientData clientdata, Tcl_Interp* interp,
|
|||
block.offset[3] = 0; /* no alpha */
|
||||
}
|
||||
} else {
|
||||
TCL_APPEND_RESULT(interp, "Bad mode", (char*) NULL);
|
||||
TCL_APPEND_RESULT(interp, "Bad mode", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
block.width = im->xsize;
|
||||
block.height = im->ysize;
|
||||
block.pitch = im->linesize;
|
||||
block.pixelPtr = (unsigned char*) im->block;
|
||||
block.pixelPtr = (unsigned char *)im->block;
|
||||
|
||||
if (TK_LT_85) { /* Tk 8.4 */
|
||||
TK_PHOTO_PUT_BLOCK_84(photo, &block, 0, 0, block.width, block.height,
|
||||
TK_PHOTO_COMPOSITE_SET);
|
||||
TK_PHOTO_PUT_BLOCK_84(
|
||||
photo, &block, 0, 0, block.width, block.height, TK_PHOTO_COMPOSITE_SET);
|
||||
if (strcmp(im->mode, "RGBA") == 0) {
|
||||
/* Tk workaround: we need apply ToggleComplexAlphaIfNeeded */
|
||||
/* (fixed in Tk 8.5a3) */
|
||||
|
@ -145,50 +140,54 @@ PyImagingPhotoPut(ClientData clientdata, Tcl_Interp* interp,
|
|||
}
|
||||
} else {
|
||||
/* Tk >=8.5 */
|
||||
TK_PHOTO_PUT_BLOCK_85(interp, photo, &block, 0, 0, block.width,
|
||||
block.height, TK_PHOTO_COMPOSITE_SET);
|
||||
TK_PHOTO_PUT_BLOCK_85(
|
||||
interp,
|
||||
photo,
|
||||
&block,
|
||||
0,
|
||||
0,
|
||||
block.width,
|
||||
block.height,
|
||||
TK_PHOTO_COMPOSITE_SET);
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
PyImagingPhotoGet(ClientData clientdata, Tcl_Interp* interp,
|
||||
int argc, const char **argv)
|
||||
{
|
||||
PyImagingPhotoGet(
|
||||
ClientData clientdata, Tcl_Interp *interp, int argc, const char **argv) {
|
||||
Imaging im;
|
||||
Tk_PhotoHandle photo;
|
||||
Tk_PhotoImageBlock block;
|
||||
int x, y, z;
|
||||
|
||||
if (argc != 3) {
|
||||
TCL_APPEND_RESULT(interp, "usage: ", argv[0],
|
||||
" srcPhoto destImage", (char *) NULL);
|
||||
TCL_APPEND_RESULT(
|
||||
interp, "usage: ", argv[0], " srcPhoto destImage", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* get Tcl PhotoImage handle */
|
||||
photo = TK_FIND_PHOTO(interp, argv[1]);
|
||||
if (photo == NULL) {
|
||||
TCL_APPEND_RESULT(
|
||||
interp, "source photo must exist", (char *) NULL
|
||||
);
|
||||
TCL_APPEND_RESULT(interp, "source photo must exist", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* get PIL Image handle */
|
||||
im = ImagingFind(argv[2]);
|
||||
if (!im) {
|
||||
TCL_APPEND_RESULT(interp, "bad name", (char*) NULL);
|
||||
TCL_APPEND_RESULT(interp, "bad name", (char *)NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
TK_PHOTO_GET_IMAGE(photo, &block);
|
||||
|
||||
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 (z=0; z < block.pixelSize; z++) {
|
||||
for (z = 0; z < block.pixelSize; z++) {
|
||||
int offset = block.offset[z];
|
||||
out[x + offset] = block.pixelPtr[y * block.pitch + x + offset];
|
||||
}
|
||||
|
@ -198,14 +197,20 @@ PyImagingPhotoGet(ClientData clientdata, Tcl_Interp* interp,
|
|||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TkImaging_Init(Tcl_Interp* interp)
|
||||
{
|
||||
TCL_CREATE_COMMAND(interp, "PyImagingPhoto", PyImagingPhotoPut,
|
||||
(ClientData) 0, (Tcl_CmdDeleteProc*) NULL);
|
||||
TCL_CREATE_COMMAND(interp, "PyImagingPhotoGet", PyImagingPhotoGet,
|
||||
(ClientData) 0, (Tcl_CmdDeleteProc*) NULL);
|
||||
TkImaging_Init(Tcl_Interp *interp) {
|
||||
TCL_CREATE_COMMAND(
|
||||
interp,
|
||||
"PyImagingPhoto",
|
||||
PyImagingPhotoPut,
|
||||
(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"
|
||||
|
||||
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`.
|
||||
* Set Python exception if we can't find `func_name` in `lib_handle`.
|
||||
* Returns function pointer or NULL if not present.
|
||||
*/
|
||||
*/
|
||||
|
||||
char message[100];
|
||||
|
||||
|
@ -248,24 +253,26 @@ FARPROC _dfunc(HMODULE lib_handle, const char *func_name)
|
|||
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
|
||||
* functions found, 1 for all functions found, -1 for some but not all
|
||||
* functions found.
|
||||
*/
|
||||
|
||||
if ((TCL_CREATE_COMMAND = (Tcl_CreateCommand_t)
|
||||
GetProcAddress(hMod, "Tcl_CreateCommand")) == NULL) {
|
||||
if ((TCL_CREATE_COMMAND =
|
||||
(Tcl_CreateCommand_t)GetProcAddress(hMod, "Tcl_CreateCommand")) == NULL) {
|
||||
return 0; /* Maybe not Tcl module */
|
||||
}
|
||||
return ((TCL_APPEND_RESULT = (Tcl_AppendResult_t) _dfunc(hMod,
|
||||
"Tcl_AppendResult")) == NULL) ? -1 : 1;
|
||||
return ((TCL_APPEND_RESULT =
|
||||
(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
|
||||
* 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");
|
||||
if (func == NULL) { /* Maybe not Tk module */
|
||||
if (func == NULL) { /* Maybe not Tk module */
|
||||
return 0;
|
||||
}
|
||||
if ((TK_PHOTO_GET_IMAGE = (Tk_PhotoGetImage_t)
|
||||
_dfunc(hMod, "Tk_PhotoGetImage")) == NULL) { return -1; };
|
||||
if ((TK_FIND_PHOTO = (Tk_FindPhoto_t)
|
||||
_dfunc(hMod, "Tk_FindPhoto")) == NULL) { return -1; };
|
||||
if ((TK_PHOTO_GET_IMAGE = (Tk_PhotoGetImage_t)_dfunc(hMod, "Tk_PhotoGetImage")) ==
|
||||
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_PhotoPutBlock_Panic defined as of 8.5.0 */
|
||||
if (TK_LT_85) {
|
||||
TK_PHOTO_PUT_BLOCK_84 = (Tk_PhotoPutBlock_84_t) func;
|
||||
return ((TK_PHOTO_SET_SIZE_84 = (Tk_PhotoSetSize_84_t)
|
||||
_dfunc(hMod, "Tk_PhotoSetSize")) == NULL) ? -1 : 1;
|
||||
TK_PHOTO_PUT_BLOCK_84 = (Tk_PhotoPutBlock_84_t)func;
|
||||
return ((TK_PHOTO_SET_SIZE_84 =
|
||||
(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;
|
||||
}
|
||||
|
||||
int load_tkinter_funcs(void)
|
||||
{
|
||||
int
|
||||
load_tkinter_funcs(void) {
|
||||
/*
|
||||
* Load Tcl and Tk functions by searching all modules in current process.
|
||||
* Return 0 for success, non-zero for failure.
|
||||
|
@ -344,7 +356,7 @@ int load_tkinter_funcs(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
#else /* not Windows */
|
||||
#else /* not Windows */
|
||||
|
||||
/*
|
||||
* 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. */
|
||||
char *fname2char(PyObject *fname)
|
||||
{
|
||||
PyObject* bytes;
|
||||
char *
|
||||
fname2char(PyObject *fname) {
|
||||
PyObject *bytes;
|
||||
bytes = PyUnicode_EncodeFSDefault(fname);
|
||||
if (bytes == NULL) {
|
||||
return NULL;
|
||||
|
@ -365,15 +377,15 @@ char *fname2char(PyObject *fname)
|
|||
|
||||
#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`.
|
||||
* Set Python exception if we can't find `func_name` in `lib_handle`.
|
||||
* Returns function pointer or NULL if not present.
|
||||
*/
|
||||
|
||||
void* func;
|
||||
void *func;
|
||||
/* Reset errors. */
|
||||
dlerror();
|
||||
func = dlsym(lib_handle, func_name);
|
||||
|
@ -384,35 +396,44 @@ void *_dfunc(void *lib_handle, const char *func_name)
|
|||
return func;
|
||||
}
|
||||
|
||||
int _func_loader(void *lib)
|
||||
{
|
||||
int
|
||||
_func_loader(void *lib) {
|
||||
/*
|
||||
* Fill global function pointers from dynamic lib.
|
||||
* Return 1 if any pointer is NULL, 0 otherwise.
|
||||
*/
|
||||
|
||||
if ((TCL_CREATE_COMMAND = (Tcl_CreateCommand_t)
|
||||
_dfunc(lib, "Tcl_CreateCommand")) == NULL) { return 1; }
|
||||
if ((TCL_APPEND_RESULT = (Tcl_AppendResult_t) _dfunc(lib,
|
||||
"Tcl_AppendResult")) == 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; }
|
||||
if ((TCL_CREATE_COMMAND = (Tcl_CreateCommand_t)_dfunc(lib, "Tcl_CreateCommand")) ==
|
||||
NULL) {
|
||||
return 1;
|
||||
}
|
||||
if ((TCL_APPEND_RESULT = (Tcl_AppendResult_t)_dfunc(lib, "Tcl_AppendResult")) ==
|
||||
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_LT_85 = (dlsym(lib, "Tk_PhotoPutBlock_Panic") == NULL);
|
||||
if (TK_LT_85) {
|
||||
return (((TK_PHOTO_PUT_BLOCK_84 = (Tk_PhotoPutBlock_84_t)
|
||||
_dfunc(lib, "Tk_PhotoPutBlock")) == NULL) ||
|
||||
((TK_PHOTO_SET_SIZE_84 = (Tk_PhotoSetSize_84_t)
|
||||
_dfunc(lib, "Tk_PhotoSetSize")) == NULL));
|
||||
return (
|
||||
((TK_PHOTO_PUT_BLOCK_84 =
|
||||
(Tk_PhotoPutBlock_84_t)_dfunc(lib, "Tk_PhotoPutBlock")) == 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)
|
||||
_dfunc(lib, "Tk_PhotoPutBlock")) == NULL);
|
||||
return (
|
||||
(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.
|
||||
* Return 0 for success, non-zero for failure.
|
||||
|
@ -447,8 +468,7 @@ int load_tkinter_funcs(void)
|
|||
}
|
||||
tkinter_lib = dlopen(tkinter_libname, RTLD_LAZY);
|
||||
if (tkinter_lib == NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"Cannot dlopen tkinter module file");
|
||||
PyErr_SetString(PyExc_RuntimeError, "Cannot dlopen tkinter module file");
|
||||
goto exit;
|
||||
}
|
||||
ret = _func_loader(tkinter_lib);
|
||||
|
|
2949
src/_imaging.c
2949
src/_imaging.c
File diff suppressed because it is too large
Load Diff
1065
src/_imagingcms.c
1065
src/_imagingcms.c
File diff suppressed because it is too large
Load Diff
985
src/_imagingft.c
985
src/_imagingft.c
File diff suppressed because it is too large
Load Diff
|
@ -23,50 +23,51 @@
|
|||
#define MAX_INT32 2147483647.0
|
||||
#define MIN_INT32 -2147483648.0
|
||||
|
||||
#define UNOP(name, op, type)\
|
||||
void name(Imaging out, Imaging im1)\
|
||||
{\
|
||||
int x, y;\
|
||||
for (y = 0; y < out->ysize; y++) {\
|
||||
type* p0 = (type*) out->image[y];\
|
||||
type* p1 = (type*) im1->image[y];\
|
||||
for (x = 0; x < out->xsize; x++) {\
|
||||
*p0 = op(type, *p1);\
|
||||
p0++; p1++;\
|
||||
}\
|
||||
}\
|
||||
}
|
||||
#define UNOP(name, op, type) \
|
||||
void name(Imaging out, Imaging im1) { \
|
||||
int x, y; \
|
||||
for (y = 0; y < out->ysize; y++) { \
|
||||
type *p0 = (type *)out->image[y]; \
|
||||
type *p1 = (type *)im1->image[y]; \
|
||||
for (x = 0; x < out->xsize; x++) { \
|
||||
*p0 = op(type, *p1); \
|
||||
p0++; \
|
||||
p1++; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define BINOP(name, op, type)\
|
||||
void name(Imaging out, Imaging im1, Imaging im2)\
|
||||
{\
|
||||
int x, y;\
|
||||
for (y = 0; y < out->ysize; y++) {\
|
||||
type* p0 = (type*) out->image[y];\
|
||||
type* p1 = (type*) im1->image[y];\
|
||||
type* p2 = (type*) im2->image[y];\
|
||||
for (x = 0; x < out->xsize; x++) {\
|
||||
*p0 = op(type, *p1, *p2);\
|
||||
p0++; p1++; p2++;\
|
||||
}\
|
||||
}\
|
||||
}
|
||||
#define BINOP(name, op, type) \
|
||||
void name(Imaging out, Imaging im1, Imaging im2) { \
|
||||
int x, y; \
|
||||
for (y = 0; y < out->ysize; y++) { \
|
||||
type *p0 = (type *)out->image[y]; \
|
||||
type *p1 = (type *)im1->image[y]; \
|
||||
type *p2 = (type *)im2->image[y]; \
|
||||
for (x = 0; x < out->xsize; x++) { \
|
||||
*p0 = op(type, *p1, *p2); \
|
||||
p0++; \
|
||||
p1++; \
|
||||
p2++; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define NEG(type, v1) -(v1)
|
||||
#define INVERT(type, v1) ~(v1)
|
||||
|
||||
#define ADD(type, v1, v2) (v1)+(v2)
|
||||
#define SUB(type, v1, v2) (v1)-(v2)
|
||||
#define MUL(type, v1, v2) (v1)*(v2)
|
||||
#define ADD(type, v1, v2) (v1) + (v2)
|
||||
#define SUB(type, v1, v2) (v1) - (v2)
|
||||
#define MUL(type, v1, v2) (v1) * (v2)
|
||||
|
||||
#define MIN(type, v1, v2) ((v1)<(v2))?(v1):(v2)
|
||||
#define MAX(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 AND(type, v1, v2) (v1)&(v2)
|
||||
#define OR(type, v1, v2) (v1)|(v2)
|
||||
#define XOR(type, v1, v2) (v1)^(v2)
|
||||
#define LSHIFT(type, v1, v2) (v1)<<(v2)
|
||||
#define RSHIFT(type, v1, v2) (v1)>>(v2)
|
||||
#define AND(type, v1, v2) (v1) & (v2)
|
||||
#define OR(type, v1, v2) (v1) | (v2)
|
||||
#define XOR(type, v1, v2) (v1) ^ (v2)
|
||||
#define LSHIFT(type, v1, v2) (v1) << (v2)
|
||||
#define RSHIFT(type, v1, v2) (v1) >> (v2)
|
||||
|
||||
#define ABS_I(type, v1) abs((v1))
|
||||
#define ABS_F(type, v1) fabs((v1))
|
||||
|
@ -79,14 +80,14 @@ void name(Imaging out, Imaging im1, Imaging im2)\
|
|||
* PyFPE_END_PROTECT(result)
|
||||
*/
|
||||
|
||||
#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_I(type, v1, v2) ((v2) != 0) ? (v1) / (v2) : 0
|
||||
#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_F(type, v1, v2) ((v2)!=0.0F)?fmod((v1),(v2)):0.0F
|
||||
#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
|
||||
|
||||
static int powi(int x, int y)
|
||||
{
|
||||
static int
|
||||
powi(int x, int y) {
|
||||
double v = pow(x, y) + 0.5;
|
||||
if (errno == EDOM) {
|
||||
return 0;
|
||||
|
@ -96,21 +97,21 @@ static int powi(int x, int y)
|
|||
} else if (v > MAX_INT32) {
|
||||
v = MAX_INT32;
|
||||
}
|
||||
return (int) v;
|
||||
return (int)v;
|
||||
}
|
||||
|
||||
#define POW_I(type, v1, v2) powi(v1, v2)
|
||||
#define POW_F(type, v1, v2) powf(v1, v2) /* FIXME: EDOM handling */
|
||||
|
||||
#define DIFF_I(type, v1, v2) abs((v1)-(v2))
|
||||
#define DIFF_F(type, v1, v2) fabs((v1)-(v2))
|
||||
#define DIFF_I(type, v1, v2) abs((v1) - (v2))
|
||||
#define DIFF_F(type, v1, v2) fabs((v1) - (v2))
|
||||
|
||||
#define EQ(type, v1, v2) (v1)==(v2)
|
||||
#define NE(type, v1, v2) (v1)!=(v2)
|
||||
#define LT(type, v1, v2) (v1)<(v2)
|
||||
#define LE(type, v1, v2) (v1)<=(v2)
|
||||
#define GT(type, v1, v2) (v1)>(v2)
|
||||
#define GE(type, v1, v2) (v1)>=(v2)
|
||||
#define EQ(type, v1, v2) (v1) == (v2)
|
||||
#define NE(type, v1, v2) (v1) != (v2)
|
||||
#define LT(type, v1, v2) (v1) < (v2)
|
||||
#define LE(type, v1, v2) (v1) <= (v2)
|
||||
#define GT(type, v1, v2) (v1) > (v2)
|
||||
#define GE(type, v1, v2) (v1) >= (v2)
|
||||
|
||||
UNOP(abs_I, ABS_I, INT32)
|
||||
UNOP(neg_I, NEG, INT32)
|
||||
|
@ -162,8 +163,7 @@ BINOP(gt_F, GT, FLOAT32)
|
|||
BINOP(ge_F, GE, FLOAT32)
|
||||
|
||||
static PyObject *
|
||||
_unop(PyObject* self, PyObject* args)
|
||||
{
|
||||
_unop(PyObject *self, PyObject *args) {
|
||||
Imaging out;
|
||||
Imaging im1;
|
||||
void (*unop)(Imaging, Imaging);
|
||||
|
@ -173,10 +173,10 @@ _unop(PyObject* self, PyObject* args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
out = (Imaging) i0;
|
||||
im1 = (Imaging) i1;
|
||||
out = (Imaging)i0;
|
||||
im1 = (Imaging)i1;
|
||||
|
||||
unop = (void*) op;
|
||||
unop = (void *)op;
|
||||
|
||||
unop(out, im1);
|
||||
|
||||
|
@ -185,8 +185,7 @@ _unop(PyObject* self, PyObject* args)
|
|||
}
|
||||
|
||||
static PyObject *
|
||||
_binop(PyObject* self, PyObject* args)
|
||||
{
|
||||
_binop(PyObject *self, PyObject *args) {
|
||||
Imaging out;
|
||||
Imaging im1;
|
||||
Imaging im2;
|
||||
|
@ -197,11 +196,11 @@ _binop(PyObject* self, PyObject* args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
out = (Imaging) i0;
|
||||
im1 = (Imaging) i1;
|
||||
im2 = (Imaging) i2;
|
||||
out = (Imaging)i0;
|
||||
im1 = (Imaging)i1;
|
||||
im2 = (Imaging)i2;
|
||||
|
||||
binop = (void*) op;
|
||||
binop = (void *)op;
|
||||
|
||||
binop(out, im1, im2);
|
||||
|
||||
|
@ -210,15 +209,11 @@ _binop(PyObject* self, PyObject* args)
|
|||
}
|
||||
|
||||
static PyMethodDef _functions[] = {
|
||||
{"unop", _unop, 1},
|
||||
{"binop", _binop, 1},
|
||||
{NULL, NULL}
|
||||
};
|
||||
{"unop", _unop, 1}, {"binop", _binop, 1}, {NULL, NULL}};
|
||||
|
||||
static void
|
||||
install(PyObject *d, char* name, void* value)
|
||||
{
|
||||
PyObject *v = PyLong_FromSsize_t((Py_ssize_t) value);
|
||||
install(PyObject *d, char *name, void *value) {
|
||||
PyObject *v = PyLong_FromSsize_t((Py_ssize_t)value);
|
||||
if (!v || PyDict_SetItemString(d, name, v)) {
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
@ -226,8 +221,8 @@ install(PyObject *d, char* name, void* value)
|
|||
}
|
||||
|
||||
static int
|
||||
setup_module(PyObject* m) {
|
||||
PyObject* d = PyModule_GetDict(m);
|
||||
setup_module(PyObject *m) {
|
||||
PyObject *d = PyModule_GetDict(m);
|
||||
|
||||
install(d, "abs_I", abs_I);
|
||||
install(d, "neg_I", neg_I);
|
||||
|
@ -279,14 +274,14 @@ setup_module(PyObject* m) {
|
|||
|
||||
PyMODINIT_FUNC
|
||||
PyInit__imagingmath(void) {
|
||||
PyObject* m;
|
||||
PyObject *m;
|
||||
|
||||
static PyModuleDef module_def = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_imagingmath", /* m_name */
|
||||
NULL, /* m_doc */
|
||||
-1, /* m_size */
|
||||
_functions, /* m_methods */
|
||||
"_imagingmath", /* m_name */
|
||||
NULL, /* m_doc */
|
||||
-1, /* m_size */
|
||||
_functions, /* m_methods */
|
||||
};
|
||||
|
||||
m = PyModule_Create(&module_def);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "Python.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
|
||||
a new binary image.
|
||||
|
@ -27,9 +27,8 @@
|
|||
|
||||
Returns number of changed pixels.
|
||||
*/
|
||||
static PyObject*
|
||||
apply(PyObject *self, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
apply(PyObject *self, PyObject *args) {
|
||||
const char *lut;
|
||||
PyObject *py_lut;
|
||||
Py_ssize_t lut_len, i0, i1;
|
||||
|
@ -58,18 +57,16 @@ apply(PyObject *self, PyObject* args)
|
|||
|
||||
lut = PyBytes_AsString(py_lut);
|
||||
|
||||
imgin = (Imaging) i0;
|
||||
imgout = (Imaging) i1;
|
||||
imgin = (Imaging)i0;
|
||||
imgout = (Imaging)i1;
|
||||
width = imgin->xsize;
|
||||
height = imgin->ysize;
|
||||
|
||||
if (imgin->type != IMAGING_TYPE_UINT8 ||
|
||||
imgin->bands != 1) {
|
||||
if (imgin->type != IMAGING_TYPE_UINT8 || imgin->bands != 1) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Unsupported image type");
|
||||
return NULL;
|
||||
}
|
||||
if (imgout->type != IMAGING_TYPE_UINT8 ||
|
||||
imgout->bands != 1) {
|
||||
if (imgout->type != IMAGING_TYPE_UINT8 || imgout->bands != 1) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Unsupported image type");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -77,52 +74,46 @@ apply(PyObject *self, PyObject* args)
|
|||
inrows = imgin->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 *inrow = inrows[row_idx];
|
||||
UINT8 *prow, *nrow; /* Previous and next row */
|
||||
|
||||
/* zero boundary conditions. TBD support other modes */
|
||||
outrow[0] = outrow[width-1] = 0;
|
||||
if (row_idx==0 || row_idx == height-1) {
|
||||
for(col_idx=0; col_idx<width; col_idx++) {
|
||||
outrow[0] = outrow[width - 1] = 0;
|
||||
if (row_idx == 0 || row_idx == height - 1) {
|
||||
for (col_idx = 0; col_idx < width; col_idx++) {
|
||||
outrow[col_idx] = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
prow = inrows[row_idx-1];
|
||||
nrow = inrows[row_idx+1];
|
||||
prow = inrows[row_idx - 1];
|
||||
nrow = inrows[row_idx + 1];
|
||||
|
||||
for (col_idx=1; col_idx<width-1; col_idx++) {
|
||||
int cim = col_idx-1;
|
||||
int cip = col_idx+1;
|
||||
unsigned char b0 = prow[cim] &1;
|
||||
unsigned char b1 = prow[col_idx]&1;
|
||||
unsigned char b2 = prow[cip]&1;
|
||||
for (col_idx = 1; col_idx < width - 1; col_idx++) {
|
||||
int cim = col_idx - 1;
|
||||
int cip = col_idx + 1;
|
||||
unsigned char b0 = prow[cim] & 1;
|
||||
unsigned char b1 = prow[col_idx] & 1;
|
||||
unsigned char b2 = prow[cip] & 1;
|
||||
|
||||
unsigned char b3 = inrow[cim]&1;
|
||||
unsigned char b4 = inrow[col_idx]&1;
|
||||
unsigned char b5 = inrow[cip]&1;
|
||||
unsigned char b3 = inrow[cim] & 1;
|
||||
unsigned char b4 = inrow[col_idx] & 1;
|
||||
unsigned char b5 = inrow[cip] & 1;
|
||||
|
||||
unsigned char b6 = nrow[cim]&1;
|
||||
unsigned char b7 = nrow[col_idx]&1;
|
||||
unsigned char b8 = nrow[cip]&1;
|
||||
unsigned char b6 = nrow[cim] & 1;
|
||||
unsigned char b7 = nrow[col_idx] & 1;
|
||||
unsigned char b8 = nrow[cip] & 1;
|
||||
|
||||
int lut_idx = (b0
|
||||
|(b1 << 1)
|
||||
|(b2 << 2)
|
||||
|(b3 << 3)
|
||||
|(b4 << 4)
|
||||
|(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));
|
||||
int lut_idx =
|
||||
(b0 | (b1 << 1) | (b2 << 2) | (b3 << 3) | (b4 << 4) | (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
|
||||
|
@ -135,9 +126,8 @@ apply(PyObject *self, PyObject* args)
|
|||
|
||||
Returns list of matching pixels.
|
||||
*/
|
||||
static PyObject*
|
||||
match(PyObject *self, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
match(PyObject *self, PyObject *args) {
|
||||
const char *lut;
|
||||
PyObject *py_lut;
|
||||
Py_ssize_t lut_len, i0;
|
||||
|
@ -165,10 +155,9 @@ match(PyObject *self, PyObject* args)
|
|||
}
|
||||
|
||||
lut = PyBytes_AsString(py_lut);
|
||||
imgin = (Imaging) i0;
|
||||
imgin = (Imaging)i0;
|
||||
|
||||
if (imgin->type != IMAGING_TYPE_UINT8 ||
|
||||
imgin->bands != 1) {
|
||||
if (imgin->type != IMAGING_TYPE_UINT8 || imgin->bands != 1) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Unsupported image type");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -177,39 +166,33 @@ match(PyObject *self, PyObject* args)
|
|||
width = imgin->xsize;
|
||||
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 *prow, *nrow;
|
||||
|
||||
prow = inrows[row_idx-1];
|
||||
nrow = inrows[row_idx+1];
|
||||
prow = inrows[row_idx - 1];
|
||||
nrow = inrows[row_idx + 1];
|
||||
|
||||
for (col_idx=1; col_idx<width-1; col_idx++) {
|
||||
int cim = col_idx-1;
|
||||
int cip = col_idx+1;
|
||||
unsigned char b0 = prow[cim] &1;
|
||||
unsigned char b1 = prow[col_idx]&1;
|
||||
unsigned char b2 = prow[cip]&1;
|
||||
for (col_idx = 1; col_idx < width - 1; col_idx++) {
|
||||
int cim = col_idx - 1;
|
||||
int cip = col_idx + 1;
|
||||
unsigned char b0 = prow[cim] & 1;
|
||||
unsigned char b1 = prow[col_idx] & 1;
|
||||
unsigned char b2 = prow[cip] & 1;
|
||||
|
||||
unsigned char b3 = inrow[cim]&1;
|
||||
unsigned char b4 = inrow[col_idx]&1;
|
||||
unsigned char b5 = inrow[cip]&1;
|
||||
unsigned char b3 = inrow[cim] & 1;
|
||||
unsigned char b4 = inrow[col_idx] & 1;
|
||||
unsigned char b5 = inrow[cip] & 1;
|
||||
|
||||
unsigned char b6 = nrow[cim]&1;
|
||||
unsigned char b7 = nrow[col_idx]&1;
|
||||
unsigned char b8 = nrow[cip]&1;
|
||||
unsigned char b6 = nrow[cim] & 1;
|
||||
unsigned char b7 = nrow[col_idx] & 1;
|
||||
unsigned char b8 = nrow[cip] & 1;
|
||||
|
||||
int lut_idx = (b0
|
||||
|(b1 << 1)
|
||||
|(b2 << 2)
|
||||
|(b3 << 3)
|
||||
|(b4 << 4)
|
||||
|(b5 << 5)
|
||||
|(b6 << 6)
|
||||
|(b7 << 7)
|
||||
|(b8 << 8));
|
||||
int lut_idx =
|
||||
(b0 | (b1 << 1) | (b2 << 2) | (b3 << 3) | (b4 << 4) | (b5 << 5) |
|
||||
(b6 << 6) | (b7 << 7) | (b8 << 8));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -222,9 +205,8 @@ match(PyObject *self, PyObject* args)
|
|||
May be used to extract features after a sequence of MorphOps were applied.
|
||||
This is faster than match as only 1x1 lookup is made.
|
||||
*/
|
||||
static PyObject*
|
||||
get_on_pixels(PyObject *self, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
get_on_pixels(PyObject *self, PyObject *args) {
|
||||
Py_ssize_t i0;
|
||||
Imaging img;
|
||||
UINT8 **rows;
|
||||
|
@ -237,16 +219,16 @@ get_on_pixels(PyObject *self, PyObject* args)
|
|||
|
||||
return NULL;
|
||||
}
|
||||
img = (Imaging) i0;
|
||||
img = (Imaging)i0;
|
||||
rows = img->image8;
|
||||
width = img->xsize;
|
||||
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];
|
||||
for (col_idx=0; col_idx<width; col_idx++) {
|
||||
for (col_idx = 0; col_idx < width; 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);
|
||||
}
|
||||
}
|
||||
|
@ -254,11 +236,9 @@ get_on_pixels(PyObject *self, PyObject* args)
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
setup_module(PyObject* m)
|
||||
{
|
||||
PyObject* d = PyModule_GetDict(m);
|
||||
setup_module(PyObject *m) {
|
||||
PyObject *d = PyModule_GetDict(m);
|
||||
|
||||
PyDict_SetItemString(d, "__version", PyUnicode_FromString("0.1"));
|
||||
|
||||
|
@ -270,19 +250,18 @@ static PyMethodDef functions[] = {
|
|||
{"apply", (PyCFunction)apply, METH_VARARGS, NULL},
|
||||
{"get_on_pixels", (PyCFunction)get_on_pixels, METH_VARARGS, NULL},
|
||||
{"match", (PyCFunction)match, METH_VARARGS, NULL},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
{NULL, NULL, 0, NULL}};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
PyInit__imagingmorph(void) {
|
||||
PyObject* m;
|
||||
PyObject *m;
|
||||
|
||||
static PyModuleDef module_def = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_imagingmorph", /* m_name */
|
||||
"A module for doing image morphology", /* m_doc */
|
||||
-1, /* m_size */
|
||||
functions, /* m_methods */
|
||||
"_imagingmorph", /* m_name */
|
||||
"A module for doing image morphology", /* m_doc */
|
||||
-1, /* m_size */
|
||||
functions, /* m_methods */
|
||||
};
|
||||
|
||||
m = PyModule_Create(&module_def);
|
||||
|
|
|
@ -12,43 +12,42 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Python.h"
|
||||
#include "libImaging/Imaging.h"
|
||||
|
||||
#include "Tk/_tkmini.h"
|
||||
|
||||
/* must link with Tk/tkImaging.c */
|
||||
extern void TkImaging_Init(Tcl_Interp* interp);
|
||||
extern int load_tkinter_funcs(void);
|
||||
extern 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
|
||||
versions, we use _tkinter's interpaddr hook instead, and all older
|
||||
versions use this structure layout) */
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
Tcl_Interp* interp;
|
||||
PyObject_HEAD Tcl_Interp *interp;
|
||||
} TkappObject;
|
||||
|
||||
static PyObject*
|
||||
_tkinit(PyObject* self, PyObject* args)
|
||||
{
|
||||
Tcl_Interp* interp;
|
||||
static PyObject *
|
||||
_tkinit(PyObject *self, PyObject *args) {
|
||||
Tcl_Interp *interp;
|
||||
|
||||
PyObject* arg;
|
||||
PyObject *arg;
|
||||
int is_interp;
|
||||
if (!PyArg_ParseTuple(args, "Oi", &arg, &is_interp)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (is_interp) {
|
||||
interp = (Tcl_Interp*)PyLong_AsVoidPtr(arg);
|
||||
interp = (Tcl_Interp *)PyLong_AsVoidPtr(arg);
|
||||
} else {
|
||||
TkappObject* app;
|
||||
TkappObject *app;
|
||||
/* Do it the hard way. This will break if the TkappObject
|
||||
layout changes */
|
||||
app = (TkappObject*)PyLong_AsVoidPtr(arg);
|
||||
app = (TkappObject *)PyLong_AsVoidPtr(arg);
|
||||
interp = app->interp;
|
||||
}
|
||||
|
||||
|
@ -69,10 +68,10 @@ PyMODINIT_FUNC
|
|||
PyInit__imagingtk(void) {
|
||||
static PyModuleDef module_def = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_imagingtk", /* m_name */
|
||||
NULL, /* m_doc */
|
||||
-1, /* m_size */
|
||||
functions, /* m_methods */
|
||||
"_imagingtk", /* m_name */
|
||||
NULL, /* m_doc */
|
||||
-1, /* m_size */
|
||||
functions, /* m_methods */
|
||||
};
|
||||
PyObject *m;
|
||||
m = PyModule_Create(&module_def);
|
||||
|
|
645
src/_webp.c
645
src/_webp.c
|
@ -21,12 +21,14 @@
|
|||
|
||||
#endif
|
||||
|
||||
void ImagingSectionEnter(ImagingSectionCookie* cookie) {
|
||||
*cookie = (PyThreadState *) PyEval_SaveThread();
|
||||
void
|
||||
ImagingSectionEnter(ImagingSectionCookie *cookie) {
|
||||
*cookie = (PyThreadState *)PyEval_SaveThread();
|
||||
}
|
||||
|
||||
void ImagingSectionLeave(ImagingSectionCookie* cookie) {
|
||||
PyEval_RestoreThread((PyThreadState*) *cookie);
|
||||
void
|
||||
ImagingSectionLeave(ImagingSectionCookie *cookie) {
|
||||
PyEval_RestoreThread((PyThreadState *)*cookie);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -35,12 +37,15 @@ void ImagingSectionLeave(ImagingSectionCookie* cookie) {
|
|||
|
||||
#ifdef HAVE_WEBPMUX
|
||||
|
||||
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_MEMORY_ERROR", "WEBP_MUX_NOT_ENOUGH_DATA"
|
||||
};
|
||||
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_MEMORY_ERROR",
|
||||
"WEBP_MUX_NOT_ENOUGH_DATA"};
|
||||
|
||||
PyObject* HandleMuxError(WebPMuxError err, char* chunk) {
|
||||
PyObject *
|
||||
HandleMuxError(WebPMuxError err, char *chunk) {
|
||||
char message[100];
|
||||
int message_len;
|
||||
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
|
||||
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 {
|
||||
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) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "failed to construct error message");
|
||||
|
@ -90,8 +97,7 @@ PyObject* HandleMuxError(WebPMuxError err, char* chunk) {
|
|||
|
||||
// Encoder type
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
WebPAnimEncoder* enc;
|
||||
PyObject_HEAD WebPAnimEncoder *enc;
|
||||
WebPPicture frame;
|
||||
} WebPAnimEncoderObject;
|
||||
|
||||
|
@ -99,18 +105,17 @@ static PyTypeObject WebPAnimEncoder_Type;
|
|||
|
||||
// Decoder type
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
WebPAnimDecoder* dec;
|
||||
PyObject_HEAD WebPAnimDecoder *dec;
|
||||
WebPAnimInfo info;
|
||||
WebPData data;
|
||||
char* mode;
|
||||
char *mode;
|
||||
} WebPAnimDecoderObject;
|
||||
|
||||
static PyTypeObject WebPAnimDecoder_Type;
|
||||
|
||||
// Encoder functions
|
||||
PyObject* _anim_encoder_new(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject *
|
||||
_anim_encoder_new(PyObject *self, PyObject *args) {
|
||||
int width, height;
|
||||
uint32_t bgcolor;
|
||||
int loop_count;
|
||||
|
@ -119,12 +124,21 @@ PyObject* _anim_encoder_new(PyObject* self, PyObject* args)
|
|||
int allow_mixed;
|
||||
int verbose;
|
||||
WebPAnimEncoderOptions enc_options;
|
||||
WebPAnimEncoderObject* encp = NULL;
|
||||
WebPAnimEncoder* enc = NULL;
|
||||
WebPAnimEncoderObject *encp = NULL;
|
||||
WebPAnimEncoder *enc = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iiIiiiiii",
|
||||
&width, &height, &bgcolor, &loop_count, &minimize_size,
|
||||
&kmin, &kmax, &allow_mixed, &verbose)) {
|
||||
if (!PyArg_ParseTuple(
|
||||
args,
|
||||
"iiIiiiiii",
|
||||
&width,
|
||||
&height,
|
||||
&bgcolor,
|
||||
&loop_count,
|
||||
&minimize_size,
|
||||
&kmin,
|
||||
&kmax,
|
||||
&allow_mixed,
|
||||
&verbose)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -154,7 +168,7 @@ PyObject* _anim_encoder_new(PyObject* self, PyObject* args)
|
|||
enc = WebPAnimEncoderNew(width, height, &enc_options);
|
||||
if (enc) {
|
||||
encp->enc = enc;
|
||||
return (PyObject*) encp;
|
||||
return (PyObject *)encp;
|
||||
}
|
||||
WebPPictureFree(&(encp->frame));
|
||||
}
|
||||
|
@ -164,33 +178,42 @@ PyObject* _anim_encoder_new(PyObject* self, PyObject* args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
PyObject* _anim_encoder_dealloc(PyObject* self)
|
||||
{
|
||||
WebPAnimEncoderObject* encp = (WebPAnimEncoderObject*)self;
|
||||
PyObject *
|
||||
_anim_encoder_dealloc(PyObject *self) {
|
||||
WebPAnimEncoderObject *encp = (WebPAnimEncoderObject *)self;
|
||||
WebPPictureFree(&(encp->frame));
|
||||
WebPAnimEncoderDelete(encp->enc);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyObject* _anim_encoder_add(PyObject* self, PyObject* args)
|
||||
{
|
||||
uint8_t* rgb;
|
||||
PyObject *
|
||||
_anim_encoder_add(PyObject *self, PyObject *args) {
|
||||
uint8_t *rgb;
|
||||
Py_ssize_t size;
|
||||
int timestamp;
|
||||
int width;
|
||||
int height;
|
||||
char* mode;
|
||||
char *mode;
|
||||
int lossless;
|
||||
float quality_factor;
|
||||
int method;
|
||||
WebPConfig config;
|
||||
WebPAnimEncoderObject* encp = (WebPAnimEncoderObject*)self;
|
||||
WebPAnimEncoder* enc = encp->enc;
|
||||
WebPPicture* frame = &(encp->frame);
|
||||
WebPAnimEncoderObject *encp = (WebPAnimEncoderObject *)self;
|
||||
WebPAnimEncoder *enc = encp->enc;
|
||||
WebPPicture *frame = &(encp->frame);
|
||||
|
||||
if (!PyArg_ParseTuple(args, "z#iiisifi",
|
||||
(char**)&rgb, &size, ×tamp, &width, &height, &mode,
|
||||
&lossless, &quality_factor, &method)) {
|
||||
if (!PyArg_ParseTuple(
|
||||
args,
|
||||
"z#iiisifi",
|
||||
(char **)&rgb,
|
||||
&size,
|
||||
×tamp,
|
||||
&width,
|
||||
&height,
|
||||
&mode,
|
||||
&lossless,
|
||||
&quality_factor,
|
||||
&method)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -218,10 +241,10 @@ PyObject* _anim_encoder_add(PyObject* self, PyObject* args)
|
|||
// Populate the frame with raw bytes passed to us
|
||||
frame->width = width;
|
||||
frame->height = height;
|
||||
frame->use_argb = 1; // Don't convert RGB pixels to YUV
|
||||
if (strcmp(mode, "RGBA")==0) {
|
||||
frame->use_argb = 1; // Don't convert RGB pixels to YUV
|
||||
if (strcmp(mode, "RGBA") == 0) {
|
||||
WebPPictureImportRGBA(frame, rgb, 4 * width);
|
||||
} else if (strcmp(mode, "RGBX")==0) {
|
||||
} else if (strcmp(mode, "RGBX") == 0) {
|
||||
WebPPictureImportRGBX(frame, rgb, 4 * width);
|
||||
} else {
|
||||
WebPPictureImportRGB(frame, rgb, 3 * width);
|
||||
|
@ -236,22 +259,29 @@ PyObject* _anim_encoder_add(PyObject* self, PyObject* args)
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyObject* _anim_encoder_assemble(PyObject* self, PyObject* args)
|
||||
{
|
||||
uint8_t* icc_bytes;
|
||||
uint8_t* exif_bytes;
|
||||
uint8_t* xmp_bytes;
|
||||
PyObject *
|
||||
_anim_encoder_assemble(PyObject *self, PyObject *args) {
|
||||
uint8_t *icc_bytes;
|
||||
uint8_t *exif_bytes;
|
||||
uint8_t *xmp_bytes;
|
||||
Py_ssize_t icc_size;
|
||||
Py_ssize_t exif_size;
|
||||
Py_ssize_t xmp_size;
|
||||
WebPData webp_data;
|
||||
WebPAnimEncoderObject* encp = (WebPAnimEncoderObject*)self;
|
||||
WebPAnimEncoder* enc = encp->enc;
|
||||
WebPMux* mux = NULL;
|
||||
PyObject* ret = NULL;
|
||||
WebPAnimEncoderObject *encp = (WebPAnimEncoderObject *)self;
|
||||
WebPAnimEncoder *enc = encp->enc;
|
||||
WebPMux *mux = NULL;
|
||||
PyObject *ret = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s#s#s#",
|
||||
&icc_bytes, &icc_size, &exif_bytes, &exif_size, &xmp_bytes, &xmp_size)) {
|
||||
if (!PyArg_ParseTuple(
|
||||
args,
|
||||
"s#s#s#",
|
||||
&icc_bytes,
|
||||
&icc_size,
|
||||
&exif_bytes,
|
||||
&exif_size,
|
||||
&xmp_bytes,
|
||||
&xmp_size)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -270,9 +300,9 @@ PyObject* _anim_encoder_assemble(PyObject* self, PyObject* args)
|
|||
int i_icc_size = (int)icc_size;
|
||||
int i_exif_size = (int)exif_size;
|
||||
int i_xmp_size = (int)xmp_size;
|
||||
WebPData icc_profile = { icc_bytes, i_icc_size };
|
||||
WebPData exif = { exif_bytes, i_exif_size };
|
||||
WebPData xmp = { xmp_bytes, i_xmp_size };
|
||||
WebPData icc_profile = {icc_bytes, i_icc_size};
|
||||
WebPData exif = {exif_bytes, i_exif_size};
|
||||
WebPData xmp = {xmp_bytes, i_xmp_size};
|
||||
|
||||
mux = WebPMuxCreate(&webp_data, 1);
|
||||
if (mux == NULL) {
|
||||
|
@ -312,7 +342,7 @@ PyObject* _anim_encoder_assemble(PyObject* self, PyObject* args)
|
|||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// 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
|
||||
PyObject* _anim_decoder_new(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject *
|
||||
_anim_decoder_new(PyObject *self, PyObject *args) {
|
||||
PyBytesObject *webp_string;
|
||||
const uint8_t *webp;
|
||||
Py_ssize_t size;
|
||||
WebPData webp_src;
|
||||
char* mode;
|
||||
char *mode;
|
||||
WebPDecoderConfig config;
|
||||
WebPAnimDecoderObject* decp = NULL;
|
||||
WebPAnimDecoder* dec = NULL;
|
||||
WebPAnimDecoderObject *decp = NULL;
|
||||
WebPAnimDecoder *dec = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "S", &webp_string)) {
|
||||
return NULL;
|
||||
}
|
||||
PyBytes_AsStringAndSize((PyObject *)webp_string, (char**)&webp, &size);
|
||||
PyBytes_AsStringAndSize((PyObject *)webp_string, (char **)&webp, &size);
|
||||
webp_src.bytes = webp;
|
||||
webp_src.size = size;
|
||||
|
||||
|
@ -359,7 +389,7 @@ PyObject* _anim_decoder_new(PyObject* self, PyObject* args)
|
|||
if (dec) {
|
||||
if (WebPAnimDecoderGetInfo(dec, &(decp->info))) {
|
||||
decp->dec = dec;
|
||||
return (PyObject*)decp;
|
||||
return (PyObject *)decp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -369,33 +399,34 @@ PyObject* _anim_decoder_new(PyObject* self, PyObject* args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
PyObject* _anim_decoder_dealloc(PyObject* self)
|
||||
{
|
||||
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject *)self;
|
||||
PyObject *
|
||||
_anim_decoder_dealloc(PyObject *self) {
|
||||
WebPAnimDecoderObject *decp = (WebPAnimDecoderObject *)self;
|
||||
WebPDataClear(&(decp->data));
|
||||
WebPAnimDecoderDelete(decp->dec);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyObject* _anim_decoder_get_info(PyObject* self)
|
||||
{
|
||||
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject *)self;
|
||||
WebPAnimInfo* info = &(decp->info);
|
||||
PyObject *
|
||||
_anim_decoder_get_info(PyObject *self) {
|
||||
WebPAnimDecoderObject *decp = (WebPAnimDecoderObject *)self;
|
||||
WebPAnimInfo *info = &(decp->info);
|
||||
|
||||
return Py_BuildValue("IIIIIs",
|
||||
info->canvas_width, info->canvas_height,
|
||||
return Py_BuildValue(
|
||||
"IIIIIs",
|
||||
info->canvas_width,
|
||||
info->canvas_height,
|
||||
info->loop_count,
|
||||
info->bgcolor,
|
||||
info->frame_count,
|
||||
decp->mode
|
||||
);
|
||||
decp->mode);
|
||||
}
|
||||
|
||||
PyObject* _anim_decoder_get_chunk(PyObject* self, PyObject* args)
|
||||
{
|
||||
char* mode;
|
||||
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject *)self;
|
||||
const WebPDemuxer* demux;
|
||||
PyObject *
|
||||
_anim_decoder_get_chunk(PyObject *self, PyObject *args) {
|
||||
char *mode;
|
||||
WebPAnimDecoderObject *decp = (WebPAnimDecoderObject *)self;
|
||||
const WebPDemuxer *demux;
|
||||
WebPChunkIterator iter;
|
||||
PyObject *ret;
|
||||
|
||||
|
@ -408,27 +439,27 @@ PyObject* _anim_decoder_get_chunk(PyObject* self, PyObject* args)
|
|||
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);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject* _anim_decoder_get_next(PyObject* self)
|
||||
{
|
||||
uint8_t* buf;
|
||||
PyObject *
|
||||
_anim_decoder_get_next(PyObject *self) {
|
||||
uint8_t *buf;
|
||||
int timestamp;
|
||||
PyObject* bytes;
|
||||
PyObject* ret;
|
||||
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject*)self;
|
||||
PyObject *bytes;
|
||||
PyObject *ret;
|
||||
WebPAnimDecoderObject *decp = (WebPAnimDecoderObject *)self;
|
||||
|
||||
if (!WebPAnimDecoderGetNext(decp->dec, &buf, ×tamp)) {
|
||||
PyErr_SetString(PyExc_OSError, "failed to read next frame");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bytes = PyBytes_FromStringAndSize((char *)buf,
|
||||
decp->info.canvas_width * 4 * decp->info.canvas_height);
|
||||
bytes = PyBytes_FromStringAndSize(
|
||||
(char *)buf, decp->info.canvas_width * 4 * decp->info.canvas_height);
|
||||
|
||||
ret = Py_BuildValue("Si", bytes, timestamp);
|
||||
|
||||
|
@ -436,9 +467,9 @@ PyObject* _anim_decoder_get_next(PyObject* self)
|
|||
return ret;
|
||||
}
|
||||
|
||||
PyObject* _anim_decoder_reset(PyObject* self)
|
||||
{
|
||||
WebPAnimDecoderObject* decp = (WebPAnimDecoderObject *)self;
|
||||
PyObject *
|
||||
_anim_decoder_reset(PyObject *self) {
|
||||
WebPAnimDecoderObject *decp = (WebPAnimDecoderObject *)self;
|
||||
WebPAnimDecoderReset(decp->dec);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
@ -456,37 +487,36 @@ static struct PyMethodDef _anim_encoder_methods[] = {
|
|||
|
||||
// WebPAnimDecoder type definition
|
||||
static PyTypeObject WebPAnimEncoder_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"WebPAnimEncoder", /*tp_name */
|
||||
sizeof(WebPAnimEncoderObject), /*tp_size */
|
||||
0, /*tp_itemsize */
|
||||
PyVarObject_HEAD_INIT(NULL, 0) "WebPAnimEncoder", /*tp_name */
|
||||
sizeof(WebPAnimEncoderObject), /*tp_size */
|
||||
0, /*tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)_anim_encoder_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number */
|
||||
0, /*tp_as_sequence */
|
||||
0, /*tp_as_mapping */
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
_anim_encoder_methods, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
0, /*tp_getset*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number */
|
||||
0, /*tp_as_sequence */
|
||||
0, /*tp_as_mapping */
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
_anim_encoder_methods, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
0, /*tp_getset*/
|
||||
};
|
||||
|
||||
// WebPAnimDecoder methods
|
||||
|
@ -500,37 +530,36 @@ static struct PyMethodDef _anim_decoder_methods[] = {
|
|||
|
||||
// WebPAnimDecoder type definition
|
||||
static PyTypeObject WebPAnimDecoder_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"WebPAnimDecoder", /*tp_name */
|
||||
sizeof(WebPAnimDecoderObject), /*tp_size */
|
||||
0, /*tp_itemsize */
|
||||
PyVarObject_HEAD_INIT(NULL, 0) "WebPAnimDecoder", /*tp_name */
|
||||
sizeof(WebPAnimDecoderObject), /*tp_size */
|
||||
0, /*tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)_anim_decoder_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number */
|
||||
0, /*tp_as_sequence */
|
||||
0, /*tp_as_mapping */
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
_anim_decoder_methods, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
0, /*tp_getset*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number */
|
||||
0, /*tp_as_sequence */
|
||||
0, /*tp_as_mapping */
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
_anim_decoder_methods, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
0, /*tp_getset*/
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -539,19 +568,19 @@ static PyTypeObject WebPAnimDecoder_Type = {
|
|||
/* Legacy WebP Support */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject *
|
||||
WebPEncode_wrapper(PyObject *self, PyObject *args) {
|
||||
int width;
|
||||
int height;
|
||||
int lossless;
|
||||
float quality_factor;
|
||||
int method;
|
||||
uint8_t* rgb;
|
||||
uint8_t* icc_bytes;
|
||||
uint8_t* exif_bytes;
|
||||
uint8_t* xmp_bytes;
|
||||
uint8_t* output;
|
||||
char* mode;
|
||||
uint8_t *rgb;
|
||||
uint8_t *icc_bytes;
|
||||
uint8_t *exif_bytes;
|
||||
uint8_t *xmp_bytes;
|
||||
uint8_t *output;
|
||||
char *mode;
|
||||
Py_ssize_t size;
|
||||
Py_ssize_t icc_size;
|
||||
Py_ssize_t exif_size;
|
||||
|
@ -565,9 +594,23 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args)
|
|||
WebPMemoryWriter writer;
|
||||
WebPPicture pic;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "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)) {
|
||||
if (!PyArg_ParseTuple(
|
||||
args,
|
||||
"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;
|
||||
}
|
||||
|
||||
|
@ -602,7 +645,7 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args)
|
|||
}
|
||||
pic.width = width;
|
||||
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) {
|
||||
WebPPictureImportRGBA(&pic, rgb, channels * width);
|
||||
|
@ -628,98 +671,100 @@ PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args)
|
|||
|
||||
#ifndef HAVE_WEBPMUX
|
||||
if (ret_size > 0) {
|
||||
PyObject *ret = PyBytes_FromStringAndSize((char*)output, ret_size);
|
||||
PyObject *ret = PyBytes_FromStringAndSize((char *)output, ret_size);
|
||||
free(output);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* 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 in the upper byte. (Not sure why, it shouldn't have been there)
|
||||
*/
|
||||
int i_icc_size = (int)icc_size;
|
||||
int i_exif_size = (int)exif_size;
|
||||
int i_xmp_size = (int)xmp_size;
|
||||
WebPData output_data = {0};
|
||||
WebPData image = { output, ret_size };
|
||||
WebPData icc_profile = { icc_bytes, i_icc_size };
|
||||
WebPData exif = { exif_bytes, i_exif_size };
|
||||
WebPData xmp = { xmp_bytes, i_xmp_size };
|
||||
WebPMuxError err;
|
||||
int dbg = 0;
|
||||
/* 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 in the upper byte. (Not sure why, it shouldn't have been there)
|
||||
*/
|
||||
int i_icc_size = (int)icc_size;
|
||||
int i_exif_size = (int)exif_size;
|
||||
int i_xmp_size = (int)xmp_size;
|
||||
WebPData output_data = {0};
|
||||
WebPData image = {output, ret_size};
|
||||
WebPData icc_profile = {icc_bytes, i_icc_size};
|
||||
WebPData exif = {exif_bytes, i_exif_size};
|
||||
WebPData xmp = {xmp_bytes, i_xmp_size};
|
||||
WebPMuxError err;
|
||||
int dbg = 0;
|
||||
|
||||
int copy_data = 0; // value 1 indicates given data WILL be copied to the mux
|
||||
// and value 0 indicates data will NOT be copied.
|
||||
int copy_data = 0; // value 1 indicates given data WILL be copied to the mux
|
||||
// and value 0 indicates data will NOT be copied.
|
||||
|
||||
WebPMux* mux = WebPMuxNew();
|
||||
WebPMuxSetImage(mux, &image, copy_data);
|
||||
WebPMux *mux = WebPMuxNew();
|
||||
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) {
|
||||
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) {
|
||||
fprintf(stderr, "Adding Exif Data\n");
|
||||
fprintf(stderr, "exif size %d \n", i_exif_size);
|
||||
}
|
||||
err = WebPMuxSetChunk(mux, "EXIF", &exif, copy_data);
|
||||
if (err != WEBP_MUX_OK) {
|
||||
return HandleMuxError(err, "EXIF");
|
||||
if (i_exif_size > 0) {
|
||||
if (dbg) {
|
||||
fprintf(stderr, "Adding Exif Data\n");
|
||||
}
|
||||
err = WebPMuxSetChunk(mux, "EXIF", &exif, copy_data);
|
||||
if (err != WEBP_MUX_OK) {
|
||||
return HandleMuxError(err, "EXIF");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dbg) {
|
||||
fprintf(stderr, "xmp size %d \n", i_xmp_size);
|
||||
}
|
||||
if (i_xmp_size > 0) {
|
||||
if (dbg){
|
||||
fprintf(stderr, "Adding XMP Data\n");
|
||||
if (dbg) {
|
||||
fprintf(stderr, "xmp size %d \n", i_xmp_size);
|
||||
}
|
||||
err = WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data);
|
||||
if (err != WEBP_MUX_OK) {
|
||||
return HandleMuxError(err, "XMP ");
|
||||
if (i_xmp_size > 0) {
|
||||
if (dbg) {
|
||||
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);
|
||||
WebPMuxDelete(mux);
|
||||
free(output);
|
||||
WebPMuxAssemble(mux, &output_data);
|
||||
WebPMuxDelete(mux);
|
||||
free(output);
|
||||
|
||||
ret_size = output_data.size;
|
||||
if (ret_size > 0) {
|
||||
PyObject *ret = PyBytes_FromStringAndSize((char*)output_data.bytes, ret_size);
|
||||
WebPDataClear(&output_data);
|
||||
return ret;
|
||||
}
|
||||
ret_size = output_data.size;
|
||||
if (ret_size > 0) {
|
||||
PyObject *ret =
|
||||
PyBytes_FromStringAndSize((char *)output_data.bytes, ret_size);
|
||||
WebPDataClear(&output_data);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyBytesObject* webp_string;
|
||||
const uint8_t* webp;
|
||||
PyObject *
|
||||
WebPDecode_wrapper(PyObject *self, PyObject *args) {
|
||||
PyBytesObject *webp_string;
|
||||
const uint8_t *webp;
|
||||
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;
|
||||
VP8StatusCode vp8_status_code = VP8_STATUS_OK;
|
||||
char* mode = "RGB";
|
||||
char *mode = "RGB";
|
||||
|
||||
if (!PyArg_ParseTuple(args, "S", &webp_string)) {
|
||||
return NULL;
|
||||
|
@ -729,7 +774,7 @@ PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args)
|
|||
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);
|
||||
if (vp8_status_code == VP8_STATUS_OK) {
|
||||
|
@ -743,39 +788,40 @@ PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args)
|
|||
#ifndef HAVE_WEBPMUX
|
||||
vp8_status_code = WebPDecode(webp, size, &config);
|
||||
#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);
|
||||
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
|
||||
}
|
||||
|
@ -785,20 +831,24 @@ PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args)
|
|||
}
|
||||
|
||||
if (config.output.colorspace < MODE_YUV) {
|
||||
bytes = PyBytes_FromStringAndSize((char*)config.output.u.RGBA.rgba,
|
||||
config.output.u.RGBA.size);
|
||||
bytes = PyBytes_FromStringAndSize(
|
||||
(char *)config.output.u.RGBA.rgba, config.output.u.RGBA.size);
|
||||
} else {
|
||||
// Skipping YUV for now. Need Test Images.
|
||||
// UNDONE -- unclear if we'll ever get here if we set mode_rgb*
|
||||
bytes = PyBytes_FromStringAndSize((char*)config.output.u.YUVA.y,
|
||||
config.output.u.YUVA.y_size);
|
||||
bytes = PyBytes_FromStringAndSize(
|
||||
(char *)config.output.u.YUVA.y, config.output.u.YUVA.y_size);
|
||||
}
|
||||
|
||||
pymode = PyUnicode_FromString(mode);
|
||||
ret = Py_BuildValue("SiiSSS", bytes, config.output.width,
|
||||
config.output.height, pymode,
|
||||
NULL == icc_profile ? Py_None : icc_profile,
|
||||
NULL == exif ? Py_None : exif);
|
||||
ret = Py_BuildValue(
|
||||
"SiiSSS",
|
||||
bytes,
|
||||
config.output.width,
|
||||
config.output.height,
|
||||
pymode,
|
||||
NULL == icc_profile ? Py_None : icc_profile,
|
||||
NULL == exif ? Py_None : exif);
|
||||
|
||||
end:
|
||||
WebPFreeDecBuffer(&config.output);
|
||||
|
@ -817,17 +867,22 @@ end:
|
|||
|
||||
// Return the decoder's version number, packed in hexadecimal using 8bits for
|
||||
// each of major/minor/revision. E.g: v2.5.7 is 0x020507.
|
||||
PyObject* WebPDecoderVersion_wrapper() {
|
||||
PyObject *
|
||||
WebPDecoderVersion_wrapper() {
|
||||
return Py_BuildValue("i", WebPGetDecoderVersion());
|
||||
}
|
||||
|
||||
// Version as string
|
||||
const char*
|
||||
WebPDecoderVersion_str(void)
|
||||
{
|
||||
const char *
|
||||
WebPDecoderVersion_str(void) {
|
||||
static char version[20];
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
* Files that are valid with 0.3 are reported as being invalid.
|
||||
*/
|
||||
int WebPDecoderBuggyAlpha(void) {
|
||||
return WebPGetDecoderVersion()==0x0103;
|
||||
int
|
||||
WebPDecoderBuggyAlpha(void) {
|
||||
return WebPGetDecoderVersion() == 0x0103;
|
||||
}
|
||||
|
||||
PyObject* WebPDecoderBuggyAlpha_wrapper() {
|
||||
PyObject *
|
||||
WebPDecoderBuggyAlpha_wrapper() {
|
||||
return Py_BuildValue("i", WebPDecoderBuggyAlpha());
|
||||
}
|
||||
|
||||
|
@ -847,8 +904,7 @@ PyObject* WebPDecoderBuggyAlpha_wrapper() {
|
|||
/* Module Setup */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static PyMethodDef webpMethods[] =
|
||||
{
|
||||
static PyMethodDef webpMethods[] = {
|
||||
#ifdef HAVE_WEBPANIM
|
||||
{"WebPAnimDecoder", _anim_decoder_new, METH_VARARGS, "WebPAnimDecoder"},
|
||||
{"WebPAnimEncoder", _anim_encoder_new, METH_VARARGS, "WebPAnimEncoder"},
|
||||
|
@ -856,11 +912,14 @@ static PyMethodDef webpMethods[] =
|
|||
{"WebPEncode", WebPEncode_wrapper, METH_VARARGS, "WebPEncode"},
|
||||
{"WebPDecode", WebPDecode_wrapper, METH_VARARGS, "WebPDecode"},
|
||||
{"WebPDecoderVersion", WebPDecoderVersion_wrapper, METH_NOARGS, "WebPVersion"},
|
||||
{"WebPDecoderBuggyAlpha", WebPDecoderBuggyAlpha_wrapper, METH_NOARGS, "WebPDecoderBuggyAlpha"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
{"WebPDecoderBuggyAlpha",
|
||||
WebPDecoderBuggyAlpha_wrapper,
|
||||
METH_NOARGS,
|
||||
"WebPDecoderBuggyAlpha"},
|
||||
{NULL, NULL}};
|
||||
|
||||
void addMuxFlagToModule(PyObject* m) {
|
||||
void
|
||||
addMuxFlagToModule(PyObject *m) {
|
||||
#ifdef HAVE_WEBPMUX
|
||||
PyModule_AddObject(m, "HAVE_WEBPMUX", Py_True);
|
||||
#else
|
||||
|
@ -868,7 +927,8 @@ void addMuxFlagToModule(PyObject* m) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void addAnimFlagToModule(PyObject* m) {
|
||||
void
|
||||
addAnimFlagToModule(PyObject *m) {
|
||||
#ifdef HAVE_WEBPANIM
|
||||
PyModule_AddObject(m, "HAVE_WEBPANIM", Py_True);
|
||||
#else
|
||||
|
@ -876,18 +936,21 @@ void addAnimFlagToModule(PyObject* m) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void addTransparencyFlagToModule(PyObject* m) {
|
||||
PyModule_AddObject(m, "HAVE_TRANSPARENCY",
|
||||
PyBool_FromLong(!WebPDecoderBuggyAlpha()));
|
||||
void
|
||||
addTransparencyFlagToModule(PyObject *m) {
|
||||
PyModule_AddObject(
|
||||
m, "HAVE_TRANSPARENCY", PyBool_FromLong(!WebPDecoderBuggyAlpha()));
|
||||
}
|
||||
|
||||
static int setup_module(PyObject* m) {
|
||||
PyObject* d = PyModule_GetDict(m);
|
||||
static int
|
||||
setup_module(PyObject *m) {
|
||||
PyObject *d = PyModule_GetDict(m);
|
||||
addMuxFlagToModule(m);
|
||||
addAnimFlagToModule(m);
|
||||
addTransparencyFlagToModule(m);
|
||||
|
||||
PyDict_SetItemString(d, "webpdecoder_version", PyUnicode_FromString(WebPDecoderVersion_str()));
|
||||
PyDict_SetItemString(
|
||||
d, "webpdecoder_version", PyUnicode_FromString(WebPDecoderVersion_str()));
|
||||
|
||||
#ifdef HAVE_WEBPANIM
|
||||
/* Ready object types */
|
||||
|
@ -901,14 +964,14 @@ static int setup_module(PyObject* m) {
|
|||
|
||||
PyMODINIT_FUNC
|
||||
PyInit__webp(void) {
|
||||
PyObject* m;
|
||||
PyObject *m;
|
||||
|
||||
static PyModuleDef module_def = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_webp", /* m_name */
|
||||
NULL, /* m_doc */
|
||||
-1, /* m_size */
|
||||
webpMethods, /* m_methods */
|
||||
"_webp", /* m_name */
|
||||
NULL, /* m_doc */
|
||||
-1, /* m_size */
|
||||
webpMethods, /* m_methods */
|
||||
};
|
||||
|
||||
m = PyModule_Create(&module_def);
|
||||
|
|
465
src/decode.c
465
src/decode.c
|
@ -39,31 +39,28 @@
|
|||
#include "libImaging/Bit.h"
|
||||
#include "libImaging/Sgi.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Common */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
int (*decode)(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
PyObject_HEAD int (*decode)(
|
||||
Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
int (*cleanup)(ImagingCodecState state);
|
||||
struct ImagingCodecStateInstance state;
|
||||
Imaging im;
|
||||
PyObject* lock;
|
||||
PyObject *lock;
|
||||
int pulls_fd;
|
||||
} ImagingDecoderObject;
|
||||
|
||||
static PyTypeObject ImagingDecoderType;
|
||||
|
||||
static ImagingDecoderObject*
|
||||
PyImaging_DecoderNew(int contextsize)
|
||||
{
|
||||
static ImagingDecoderObject *
|
||||
PyImaging_DecoderNew(int contextsize) {
|
||||
ImagingDecoderObject *decoder;
|
||||
void *context;
|
||||
|
||||
if(PyType_Ready(&ImagingDecoderType) < 0) {
|
||||
if (PyType_Ready(&ImagingDecoderType) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -77,10 +74,10 @@ PyImaging_DecoderNew(int contextsize)
|
|||
|
||||
/* Allocate decoder context */
|
||||
if (contextsize > 0) {
|
||||
context = (void*) calloc(1, contextsize);
|
||||
context = (void *)calloc(1, contextsize);
|
||||
if (!context) {
|
||||
Py_DECREF(decoder);
|
||||
(void) ImagingError_MemoryError();
|
||||
(void)ImagingError_MemoryError();
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
|
@ -105,8 +102,7 @@ PyImaging_DecoderNew(int contextsize)
|
|||
}
|
||||
|
||||
static void
|
||||
_dealloc(ImagingDecoderObject* decoder)
|
||||
{
|
||||
_dealloc(ImagingDecoderObject *decoder) {
|
||||
if (decoder->cleanup) {
|
||||
decoder->cleanup(&decoder->state);
|
||||
}
|
||||
|
@ -117,10 +113,9 @@ _dealloc(ImagingDecoderObject* decoder)
|
|||
PyObject_Del(decoder);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_decode(ImagingDecoderObject* decoder, PyObject* args)
|
||||
{
|
||||
UINT8* buffer;
|
||||
static PyObject *
|
||||
_decode(ImagingDecoderObject *decoder, PyObject *args) {
|
||||
UINT8 *buffer;
|
||||
Py_ssize_t bufsize;
|
||||
int status;
|
||||
ImagingSectionCookie cookie;
|
||||
|
@ -142,26 +137,23 @@ _decode(ImagingDecoderObject* decoder, PyObject* args)
|
|||
return Py_BuildValue("ii", status, decoder->state.errcode);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_decode_cleanup(ImagingDecoderObject* decoder, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
_decode_cleanup(ImagingDecoderObject *decoder, PyObject *args) {
|
||||
int status = 0;
|
||||
|
||||
if (decoder->cleanup){
|
||||
if (decoder->cleanup) {
|
||||
status = decoder->cleanup(&decoder->state);
|
||||
}
|
||||
|
||||
return Py_BuildValue("i", status);
|
||||
}
|
||||
|
||||
extern Imaging
|
||||
PyImaging_AsImaging(PyObject *op);
|
||||
|
||||
|
||||
extern Imaging PyImaging_AsImaging(PyObject *op);
|
||||
|
||||
static PyObject*
|
||||
_setimage(ImagingDecoderObject* decoder, PyObject* args)
|
||||
{
|
||||
PyObject* op;
|
||||
static PyObject *
|
||||
_setimage(ImagingDecoderObject *decoder, PyObject *args) {
|
||||
PyObject *op;
|
||||
Imaging im;
|
||||
ImagingCodecState state;
|
||||
int x0, y0, x1, y1;
|
||||
|
@ -192,10 +184,8 @@ _setimage(ImagingDecoderObject* decoder, PyObject* args)
|
|||
state->ysize = y1 - y0;
|
||||
}
|
||||
|
||||
if (state->xsize <= 0 ||
|
||||
state->xsize + state->xoff > (int) im->xsize ||
|
||||
state->ysize <= 0 ||
|
||||
state->ysize + state->yoff > (int) im->ysize) {
|
||||
if (state->xsize <= 0 || state->xsize + state->xoff > (int)im->xsize ||
|
||||
state->ysize <= 0 || state->ysize + state->yoff > (int)im->ysize) {
|
||||
PyErr_SetString(PyExc_ValueError, "tile cannot extend outside image");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -203,13 +193,13 @@ _setimage(ImagingDecoderObject* decoder, PyObject* args)
|
|||
/* Allocate memory buffer (if bits field is set) */
|
||||
if (state->bits > 0) {
|
||||
if (!state->bytes) {
|
||||
if (state->xsize > ((INT_MAX / state->bits)-7)){
|
||||
if (state->xsize > ((INT_MAX / state->bits) - 7)) {
|
||||
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 */
|
||||
state->buffer = (UINT8*) malloc(state->bytes);
|
||||
state->buffer = (UINT8 *)malloc(state->bytes);
|
||||
if (!state->buffer) {
|
||||
return ImagingError_MemoryError();
|
||||
}
|
||||
|
@ -225,10 +215,9 @@ _setimage(ImagingDecoderObject* decoder, PyObject* args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_setfd(ImagingDecoderObject* decoder, PyObject* args)
|
||||
{
|
||||
PyObject* fd;
|
||||
static PyObject *
|
||||
_setfd(ImagingDecoderObject *decoder, PyObject *args) {
|
||||
PyObject *fd;
|
||||
ImagingCodecState state;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O", &fd)) {
|
||||
|
@ -244,10 +233,8 @@ _setfd(ImagingDecoderObject* decoder, PyObject* args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
_get_pulls_fd(ImagingDecoderObject *decoder)
|
||||
{
|
||||
_get_pulls_fd(ImagingDecoderObject *decoder) {
|
||||
return PyBool_FromLong(decoder->pulls_fd);
|
||||
}
|
||||
|
||||
|
@ -260,52 +247,51 @@ static struct PyMethodDef methods[] = {
|
|||
};
|
||||
|
||||
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.",
|
||||
NULL},
|
||||
{NULL, NULL, NULL, NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
static PyTypeObject ImagingDecoderType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"ImagingDecoder", /*tp_name*/
|
||||
sizeof(ImagingDecoderObject), /*tp_size*/
|
||||
0, /*tp_itemsize*/
|
||||
PyVarObject_HEAD_INIT(NULL, 0) "ImagingDecoder", /*tp_name*/
|
||||
sizeof(ImagingDecoderObject), /*tp_size*/
|
||||
0, /*tp_itemsize*/
|
||||
/* methods */
|
||||
(destructor)_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number */
|
||||
0, /*tp_as_sequence */
|
||||
0, /*tp_as_mapping */
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
methods, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
getseters, /*tp_getset*/
|
||||
(destructor)_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number */
|
||||
0, /*tp_as_sequence */
|
||||
0, /*tp_as_mapping */
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
methods, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
getseters, /*tp_getset*/
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
get_unpacker(ImagingDecoderObject* decoder, const char* mode,
|
||||
const char* rawmode)
|
||||
{
|
||||
get_unpacker(ImagingDecoderObject *decoder, const char *mode, const char *rawmode) {
|
||||
int bits;
|
||||
ImagingShuffler unpack;
|
||||
|
||||
|
@ -322,24 +308,21 @@ get_unpacker(ImagingDecoderObject* decoder, const char* mode,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* BIT (packed fields) */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
PyImaging_BitDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_BitDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
|
||||
char* mode;
|
||||
int bits = 8;
|
||||
int pad = 8;
|
||||
int fill = 0;
|
||||
int sign = 0;
|
||||
char *mode;
|
||||
int bits = 8;
|
||||
int pad = 8;
|
||||
int fill = 0;
|
||||
int sign = 0;
|
||||
int ystep = 1;
|
||||
if (!PyArg_ParseTuple(args, "s|iiiii", &mode, &bits, &pad, &fill,
|
||||
&sign, &ystep)) {
|
||||
if (!PyArg_ParseTuple(args, "s|iiiii", &mode, &bits, &pad, &fill, &sign, &ystep)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -357,26 +340,24 @@ PyImaging_BitDecoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
decoder->state.ystep = ystep;
|
||||
|
||||
((BITSTATE*)decoder->state.context)->bits = bits;
|
||||
((BITSTATE*)decoder->state.context)->pad = pad;
|
||||
((BITSTATE*)decoder->state.context)->fill = fill;
|
||||
((BITSTATE*)decoder->state.context)->sign = sign;
|
||||
((BITSTATE *)decoder->state.context)->bits = bits;
|
||||
((BITSTATE *)decoder->state.context)->pad = pad;
|
||||
((BITSTATE *)decoder->state.context)->fill = fill;
|
||||
((BITSTATE *)decoder->state.context)->sign = sign;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* BCn: GPU block-compressed texture formats */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
PyImaging_BcnDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_BcnDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
|
||||
char* mode;
|
||||
char* actual;
|
||||
char *mode;
|
||||
char *actual;
|
||||
int n = 0;
|
||||
int ystep = 1;
|
||||
if (!PyArg_ParseTuple(args, "s|ii", &mode, &n, &ystep)) {
|
||||
|
@ -384,20 +365,23 @@ PyImaging_BcnDecoderNew(PyObject* self, PyObject* args)
|
|||
}
|
||||
|
||||
switch (n) {
|
||||
case 1: /* BC1: 565 color, 1-bit alpha */
|
||||
case 2: /* BC2: 565 color, 4-bit 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 7: /* BC7: 4-channel 8-bit via everything */
|
||||
actual = "RGBA"; break;
|
||||
case 4: /* BC4: 1-channel 8-bit via 1 BC3 alpha block */
|
||||
actual = "L"; break;
|
||||
case 6: /* BC6: 3-channel 16-bit float */
|
||||
/* TODO: support 4-channel floating point images */
|
||||
actual = "RGBAF"; break;
|
||||
default:
|
||||
PyErr_SetString(PyExc_ValueError, "block compression type unknown");
|
||||
return NULL;
|
||||
case 1: /* BC1: 565 color, 1-bit alpha */
|
||||
case 2: /* BC2: 565 color, 4-bit 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 7: /* BC7: 4-channel 8-bit via everything */
|
||||
actual = "RGBA";
|
||||
break;
|
||||
case 4: /* BC4: 1-channel 8-bit via 1 BC3 alpha block */
|
||||
actual = "L";
|
||||
break;
|
||||
case 6: /* BC6: 3-channel 16-bit float */
|
||||
/* TODO: support 4-channel floating point images */
|
||||
actual = "RGBAF";
|
||||
break;
|
||||
default:
|
||||
PyErr_SetString(PyExc_ValueError, "block compression type unknown");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strcmp(mode, actual) != 0) {
|
||||
|
@ -414,18 +398,16 @@ PyImaging_BcnDecoderNew(PyObject* self, PyObject* args)
|
|||
decoder->state.state = n;
|
||||
decoder->state.ystep = ystep;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* FLI */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
PyImaging_FliDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_FliDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
|
||||
decoder = PyImaging_DecoderNew(0);
|
||||
if (decoder == NULL) {
|
||||
|
@ -434,20 +416,18 @@ PyImaging_FliDecoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
decoder->decode = ImagingFliDecode;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* GIF */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
PyImaging_GifDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_GifDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
|
||||
char* mode;
|
||||
char *mode;
|
||||
int bits = 8;
|
||||
int interlace = 0;
|
||||
if (!PyArg_ParseTuple(args, "s|ii", &mode, &bits, &interlace)) {
|
||||
|
@ -466,24 +446,22 @@ PyImaging_GifDecoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
decoder->decode = ImagingGifDecode;
|
||||
|
||||
((GIFDECODERSTATE*)decoder->state.context)->bits = bits;
|
||||
((GIFDECODERSTATE*)decoder->state.context)->interlace = interlace;
|
||||
((GIFDECODERSTATE *)decoder->state.context)->bits = bits;
|
||||
((GIFDECODERSTATE *)decoder->state.context)->interlace = interlace;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* HEX */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
PyImaging_HexDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_HexDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
|
||||
char* mode;
|
||||
char* rawmode;
|
||||
char *mode;
|
||||
char *rawmode;
|
||||
if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -499,10 +477,9 @@ PyImaging_HexDecoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
decoder->decode = ImagingHexDecode;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* LibTiff */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -513,17 +490,16 @@ PyImaging_HexDecoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
#include <string.h>
|
||||
|
||||
PyObject*
|
||||
PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
char* mode;
|
||||
char* rawmode;
|
||||
char* compname;
|
||||
PyObject *
|
||||
PyImaging_LibTiffDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
char *mode;
|
||||
char *rawmode;
|
||||
char *compname;
|
||||
int fp;
|
||||
uint32 ifdoffset;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "sssiI", &mode, &rawmode, &compname, &fp, &ifdoffset)) {
|
||||
if (!PyArg_ParseTuple(args, "sssiI", &mode, &rawmode, &compname, &fp, &ifdoffset)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -538,31 +514,29 @@ PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (! ImagingLibTiffInit(&decoder->state, fp, ifdoffset)) {
|
||||
if (!ImagingLibTiffInit(&decoder->state, fp, ifdoffset)) {
|
||||
Py_DECREF(decoder);
|
||||
PyErr_SetString(PyExc_RuntimeError, "tiff codec initialization failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
decoder->decode = ImagingLibTiffDecode;
|
||||
decoder->decode = ImagingLibTiffDecode;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* PackBits */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
PyImaging_PackbitsDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_PackbitsDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
|
||||
char* mode;
|
||||
char* rawmode;
|
||||
char *mode;
|
||||
char *rawmode;
|
||||
if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -578,18 +552,16 @@ PyImaging_PackbitsDecoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
decoder->decode = ImagingPackbitsDecode;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* PCD */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
PyImaging_PcdDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_PcdDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
|
||||
decoder = PyImaging_DecoderNew(0);
|
||||
if (decoder == NULL) {
|
||||
|
@ -603,21 +575,19 @@ PyImaging_PcdDecoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
decoder->decode = ImagingPcdDecode;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* PCX */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
PyImaging_PcxDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_PcxDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
|
||||
char* mode;
|
||||
char* rawmode;
|
||||
char *mode;
|
||||
char *rawmode;
|
||||
int stride;
|
||||
if (!PyArg_ParseTuple(args, "ssi", &mode, &rawmode, &stride)) {
|
||||
return NULL;
|
||||
|
@ -636,23 +606,21 @@ PyImaging_PcxDecoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
decoder->decode = ImagingPcxDecode;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* RAW */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
PyImaging_RawDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_RawDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
|
||||
char* mode;
|
||||
char* rawmode;
|
||||
char *mode;
|
||||
char *rawmode;
|
||||
int stride = 0;
|
||||
int ystep = 1;
|
||||
int ystep = 1;
|
||||
if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &stride, &ystep)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -670,23 +638,21 @@ PyImaging_RawDecoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
decoder->state.ystep = ystep;
|
||||
|
||||
((RAWSTATE*)decoder->state.context)->stride = stride;
|
||||
((RAWSTATE *)decoder->state.context)->stride = stride;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* SGI RLE */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
PyImaging_SgiRleDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_SgiRleDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
|
||||
char* mode;
|
||||
char* rawmode;
|
||||
char *mode;
|
||||
char *rawmode;
|
||||
int ystep = 1;
|
||||
int bpc = 1;
|
||||
if (!PyArg_ParseTuple(args, "ss|ii", &mode, &rawmode, &ystep, &bpc)) {
|
||||
|
@ -706,23 +672,21 @@ PyImaging_SgiRleDecoderNew(PyObject* self, PyObject* args)
|
|||
decoder->decode = ImagingSgiRleDecode;
|
||||
decoder->state.ystep = ystep;
|
||||
|
||||
((SGISTATE*)decoder->state.context)->bpc = bpc;
|
||||
((SGISTATE *)decoder->state.context)->bpc = bpc;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* SUN RLE */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
PyImaging_SunRleDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_SunRleDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
|
||||
char* mode;
|
||||
char* rawmode;
|
||||
char *mode;
|
||||
char *rawmode;
|
||||
if (!PyArg_ParseTuple(args, "ss", &mode, &rawmode)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -738,21 +702,19 @@ PyImaging_SunRleDecoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
decoder->decode = ImagingSunRleDecode;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* TGA RLE */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
PyImaging_TgaRleDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_TgaRleDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
|
||||
char* mode;
|
||||
char* rawmode;
|
||||
char *mode;
|
||||
char *rawmode;
|
||||
int ystep = 1;
|
||||
int depth = 8;
|
||||
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.count = depth / 8;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* XBM */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
PyImaging_XbmDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_XbmDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
|
||||
decoder = PyImaging_DecoderNew(0);
|
||||
if (decoder == NULL) {
|
||||
|
@ -797,10 +757,9 @@ PyImaging_XbmDecoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
decoder->decode = ImagingXbmDecode;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* ZIP */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -809,13 +768,12 @@ PyImaging_XbmDecoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
#include "libImaging/ZipCodecs.h"
|
||||
|
||||
PyObject*
|
||||
PyImaging_ZipDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_ZipDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
|
||||
char* mode;
|
||||
char* rawmode;
|
||||
char *mode;
|
||||
char *rawmode;
|
||||
int interlaced = 0;
|
||||
if (!PyArg_ParseTuple(args, "ss|i", &mode, &rawmode, &interlaced)) {
|
||||
return NULL;
|
||||
|
@ -833,13 +791,12 @@ PyImaging_ZipDecoderNew(PyObject* self, PyObject* args)
|
|||
decoder->decode = ImagingZipDecode;
|
||||
decoder->cleanup = ImagingZipDecodeCleanup;
|
||||
|
||||
((ZIPSTATE*)decoder->state.context)->interlaced = interlaced;
|
||||
((ZIPSTATE *)decoder->state.context)->interlaced = interlaced;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* JPEG */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -849,31 +806,29 @@ PyImaging_ZipDecoderNew(PyObject* self, PyObject* args)
|
|||
/* 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 HAVE_PROTOTYPES
|
||||
#undef HAVE_STDDEF_H
|
||||
#undef HAVE_STDLIB_H
|
||||
#undef UINT8
|
||||
#undef UINT16
|
||||
#undef UINT32
|
||||
#undef INT8
|
||||
#undef INT16
|
||||
#undef INT32
|
||||
#undef HAVE_PROTOTYPES
|
||||
#undef HAVE_STDDEF_H
|
||||
#undef HAVE_STDLIB_H
|
||||
#undef UINT8
|
||||
#undef UINT16
|
||||
#undef UINT32
|
||||
#undef INT8
|
||||
#undef INT16
|
||||
#undef INT32
|
||||
|
||||
#include "libImaging/Jpeg.h"
|
||||
|
||||
PyObject*
|
||||
PyImaging_JpegDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_JpegDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
|
||||
char* mode;
|
||||
char* rawmode; /* what we want from the decoder */
|
||||
char* jpegmode; /* what's in the file */
|
||||
char *mode;
|
||||
char *rawmode; /* what we want from the decoder */
|
||||
char *jpegmode; /* what's in the file */
|
||||
int scale = 1;
|
||||
int draft = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ssz|ii", &mode, &rawmode, &jpegmode,
|
||||
&scale, &draft)) {
|
||||
if (!PyArg_ParseTuple(args, "ssz|ii", &mode, &rawmode, &jpegmode, &scale, &draft)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -900,13 +855,13 @@ PyImaging_JpegDecoderNew(PyObject* self, PyObject* args)
|
|||
decoder->decode = ImagingJpegDecode;
|
||||
decoder->cleanup = ImagingJpegDecodeCleanup;
|
||||
|
||||
strncpy(((JPEGSTATE*)decoder->state.context)->rawmode, rawmode, 8);
|
||||
strncpy(((JPEGSTATE*)decoder->state.context)->jpegmode, jpegmode, 8);
|
||||
strncpy(((JPEGSTATE *)decoder->state.context)->rawmode, rawmode, 8);
|
||||
strncpy(((JPEGSTATE *)decoder->state.context)->jpegmode, jpegmode, 8);
|
||||
|
||||
((JPEGSTATE*)decoder->state.context)->scale = scale;
|
||||
((JPEGSTATE*)decoder->state.context)->draft = draft;
|
||||
((JPEGSTATE *)decoder->state.context)->scale = scale;
|
||||
((JPEGSTATE *)decoder->state.context)->draft = draft;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -918,22 +873,21 @@ PyImaging_JpegDecoderNew(PyObject* self, PyObject* args)
|
|||
|
||||
#include "libImaging/Jpeg2K.h"
|
||||
|
||||
PyObject*
|
||||
PyImaging_Jpeg2KDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
PyObject *
|
||||
PyImaging_Jpeg2KDecoderNew(PyObject *self, PyObject *args) {
|
||||
ImagingDecoderObject *decoder;
|
||||
JPEG2KDECODESTATE *context;
|
||||
|
||||
char* mode;
|
||||
char* format;
|
||||
char *mode;
|
||||
char *format;
|
||||
OPJ_CODEC_FORMAT codec_format;
|
||||
int reduce = 0;
|
||||
int layers = 0;
|
||||
int fd = -1;
|
||||
PY_LONG_LONG length = -1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ss|iiiL", &mode, &format,
|
||||
&reduce, &layers, &fd, &length)) {
|
||||
if (!PyArg_ParseTuple(
|
||||
args, "ss|iiiL", &mode, &format, &reduce, &layers, &fd, &length)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -964,7 +918,6 @@ PyImaging_Jpeg2KDecoderNew(PyObject* self, PyObject* args)
|
|||
context->reduce = reduce;
|
||||
context->layers = layers;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
return (PyObject *)decoder;
|
||||
}
|
||||
#endif /* HAVE_OPENJPEG */
|
||||
|
||||
|
|
564
src/display.c
564
src/display.c
|
@ -41,15 +41,13 @@
|
|||
#endif
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
ImagingDIB dib;
|
||||
PyObject_HEAD ImagingDIB dib;
|
||||
} ImagingDisplayObject;
|
||||
|
||||
static PyTypeObject ImagingDisplayType;
|
||||
|
||||
static ImagingDisplayObject*
|
||||
_new(const char* mode, int xsize, int ysize)
|
||||
{
|
||||
static ImagingDisplayObject *
|
||||
_new(const char *mode, int xsize, int ysize) {
|
||||
ImagingDisplayObject *display;
|
||||
|
||||
if (PyType_Ready(&ImagingDisplayType) < 0) {
|
||||
|
@ -71,17 +69,15 @@ _new(const char* mode, int xsize, int ysize)
|
|||
}
|
||||
|
||||
static void
|
||||
_delete(ImagingDisplayObject* display)
|
||||
{
|
||||
_delete(ImagingDisplayObject *display) {
|
||||
if (display->dib) {
|
||||
ImagingDeleteDIB(display->dib);
|
||||
}
|
||||
PyObject_Del(display);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_expose(ImagingDisplayObject* display, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
_expose(ImagingDisplayObject *display, PyObject *args) {
|
||||
HDC hdc;
|
||||
if (!PyArg_ParseTuple(args, F_HANDLE, &hdc)) {
|
||||
return NULL;
|
||||
|
@ -93,15 +89,23 @@ _expose(ImagingDisplayObject* display, PyObject* args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_draw(ImagingDisplayObject* display, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
_draw(ImagingDisplayObject *display, PyObject *args) {
|
||||
HDC hdc;
|
||||
int dst[4];
|
||||
int src[4];
|
||||
if (!PyArg_ParseTuple(args, F_HANDLE "(iiii)(iiii)", &hdc,
|
||||
dst+0, dst+1, dst+2, dst+3,
|
||||
src+0, src+1, src+2, src+3)) {
|
||||
if (!PyArg_ParseTuple(
|
||||
args,
|
||||
F_HANDLE "(iiii)(iiii)",
|
||||
&hdc,
|
||||
dst + 0,
|
||||
dst + 1,
|
||||
dst + 2,
|
||||
dst + 3,
|
||||
src + 0,
|
||||
src + 1,
|
||||
src + 2,
|
||||
src + 3)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -111,17 +115,17 @@ _draw(ImagingDisplayObject* display, PyObject* args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
extern Imaging PyImaging_AsImaging(PyObject *op);
|
||||
extern Imaging
|
||||
PyImaging_AsImaging(PyObject *op);
|
||||
|
||||
static PyObject*
|
||||
_paste(ImagingDisplayObject* display, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
_paste(ImagingDisplayObject *display, PyObject *args) {
|
||||
Imaging im;
|
||||
|
||||
PyObject* op;
|
||||
PyObject *op;
|
||||
int xy[4];
|
||||
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;
|
||||
}
|
||||
im = PyImaging_AsImaging(op);
|
||||
|
@ -142,9 +146,8 @@ _paste(ImagingDisplayObject* display, PyObject* args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_query_palette(ImagingDisplayObject* display, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
_query_palette(ImagingDisplayObject *display, PyObject *args) {
|
||||
HDC hdc;
|
||||
int status;
|
||||
|
||||
|
@ -157,9 +160,8 @@ _query_palette(ImagingDisplayObject* display, PyObject* args)
|
|||
return Py_BuildValue("i", status);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_getdc(ImagingDisplayObject* display, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
_getdc(ImagingDisplayObject *display, PyObject *args) {
|
||||
HWND window;
|
||||
HDC dc;
|
||||
|
||||
|
@ -176,9 +178,8 @@ _getdc(ImagingDisplayObject* display, PyObject* args)
|
|||
return Py_BuildValue(F_HANDLE, dc);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_releasedc(ImagingDisplayObject* display, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
_releasedc(ImagingDisplayObject *display, PyObject *args) {
|
||||
HWND window;
|
||||
HDC dc;
|
||||
|
||||
|
@ -192,10 +193,9 @@ _releasedc(ImagingDisplayObject* display, PyObject* args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_frombytes(ImagingDisplayObject* display, PyObject* args)
|
||||
{
|
||||
char* ptr;
|
||||
static PyObject *
|
||||
_frombytes(ImagingDisplayObject *display, PyObject *args) {
|
||||
char *ptr;
|
||||
Py_ssize_t bytes;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "y#:frombytes", &ptr, &bytes)) {
|
||||
|
@ -213,16 +213,14 @@ _frombytes(ImagingDisplayObject* display, PyObject* args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_tobytes(ImagingDisplayObject* display, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
_tobytes(ImagingDisplayObject *display, PyObject *args) {
|
||||
if (!PyArg_ParseTuple(args, ":tobytes")) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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[] = {
|
||||
|
@ -237,62 +235,55 @@ static struct PyMethodDef methods[] = {
|
|||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
static PyObject*
|
||||
_getattr_mode(ImagingDisplayObject* self, void* closure)
|
||||
{
|
||||
static PyObject *
|
||||
_getattr_mode(ImagingDisplayObject *self, void *closure) {
|
||||
return Py_BuildValue("s", self->dib->mode);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_getattr_size(ImagingDisplayObject* self, void* closure)
|
||||
{
|
||||
static PyObject *
|
||||
_getattr_size(ImagingDisplayObject *self, void *closure) {
|
||||
return Py_BuildValue("ii", self->dib->xsize, self->dib->ysize);
|
||||
}
|
||||
|
||||
static struct PyGetSetDef getsetters[] = {
|
||||
{ "mode", (getter) _getattr_mode },
|
||||
{ "size", (getter) _getattr_size },
|
||||
{ NULL }
|
||||
};
|
||||
{"mode", (getter)_getattr_mode}, {"size", (getter)_getattr_size}, {NULL}};
|
||||
|
||||
static PyTypeObject ImagingDisplayType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"ImagingDisplay", /*tp_name*/
|
||||
sizeof(ImagingDisplayObject),/*tp_size*/
|
||||
0, /*tp_itemsize*/
|
||||
PyVarObject_HEAD_INIT(NULL, 0) "ImagingDisplay", /*tp_name*/
|
||||
sizeof(ImagingDisplayObject), /*tp_size*/
|
||||
0, /*tp_itemsize*/
|
||||
/* methods */
|
||||
(destructor)_delete, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number */
|
||||
0, /*tp_as_sequence */
|
||||
0, /*tp_as_mapping */
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
methods, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
getsetters, /*tp_getset*/
|
||||
(destructor)_delete, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number */
|
||||
0, /*tp_as_sequence */
|
||||
0, /*tp_as_mapping */
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
methods, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
getsetters, /*tp_getset*/
|
||||
};
|
||||
|
||||
PyObject*
|
||||
PyImaging_DisplayWin32(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDisplayObject* display;
|
||||
PyObject *
|
||||
PyImaging_DisplayWin32(PyObject *self, PyObject *args) {
|
||||
ImagingDisplayObject *display;
|
||||
char *mode;
|
||||
int xsize, ysize;
|
||||
|
||||
|
@ -305,12 +296,11 @@ PyImaging_DisplayWin32(PyObject* self, PyObject* args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return (PyObject*) display;
|
||||
return (PyObject *)display;
|
||||
}
|
||||
|
||||
PyObject*
|
||||
PyImaging_DisplayModeWin32(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject *
|
||||
PyImaging_DisplayModeWin32(PyObject *self, PyObject *args) {
|
||||
char *mode;
|
||||
int size[2];
|
||||
|
||||
|
@ -322,18 +312,17 @@ PyImaging_DisplayModeWin32(PyObject* self, PyObject* args)
|
|||
/* -------------------------------------------------------------------- */
|
||||
/* Windows screen grabber */
|
||||
|
||||
typedef HANDLE(__stdcall* Func_SetThreadDpiAwarenessContext)(HANDLE);
|
||||
typedef HANDLE(__stdcall *Func_SetThreadDpiAwarenessContext)(HANDLE);
|
||||
|
||||
PyObject*
|
||||
PyImaging_GrabScreenWin32(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject *
|
||||
PyImaging_GrabScreenWin32(PyObject *self, PyObject *args) {
|
||||
int x = 0, y = 0, width, height;
|
||||
int includeLayeredWindows = 0, all_screens = 0;
|
||||
HBITMAP bitmap;
|
||||
BITMAPCOREHEADER core;
|
||||
HDC screen, screen_copy;
|
||||
DWORD rop;
|
||||
PyObject* buffer;
|
||||
PyObject *buffer;
|
||||
HANDLE dpiAwareness;
|
||||
HMODULE user32;
|
||||
Func_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContext_function;
|
||||
|
@ -352,11 +341,11 @@ PyImaging_GrabScreenWin32(PyObject* self, PyObject* args)
|
|||
// loaded dynamically to avoid link errors
|
||||
user32 = LoadLibraryA("User32.dll");
|
||||
SetThreadDpiAwarenessContext_function =
|
||||
(Func_SetThreadDpiAwarenessContext)
|
||||
GetProcAddress(user32, "SetThreadDpiAwarenessContext");
|
||||
(Func_SetThreadDpiAwarenessContext)GetProcAddress(
|
||||
user32, "SetThreadDpiAwarenessContext");
|
||||
if (SetThreadDpiAwarenessContext_function != NULL) {
|
||||
// DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = ((DPI_CONTEXT_HANDLE)-3)
|
||||
dpiAwareness = SetThreadDpiAwarenessContext_function((HANDLE) -3);
|
||||
dpiAwareness = SetThreadDpiAwarenessContext_function((HANDLE)-3);
|
||||
}
|
||||
|
||||
if (all_screens) {
|
||||
|
@ -396,7 +385,7 @@ PyImaging_GrabScreenWin32(PyObject* self, PyObject* args)
|
|||
|
||||
/* 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) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -406,8 +395,14 @@ PyImaging_GrabScreenWin32(PyObject* self, PyObject* args)
|
|||
core.bcHeight = height;
|
||||
core.bcPlanes = 1;
|
||||
core.bcBitCount = 24;
|
||||
if (!GetDIBits(screen_copy, bitmap, 0, height, PyBytes_AS_STRING(buffer),
|
||||
(BITMAPINFO*) &core, DIB_RGB_COLORS)) {
|
||||
if (!GetDIBits(
|
||||
screen_copy,
|
||||
bitmap,
|
||||
0,
|
||||
height,
|
||||
PyBytes_AS_STRING(buffer),
|
||||
(BITMAPINFO *)&core,
|
||||
DIB_RGB_COLORS)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -426,11 +421,11 @@ error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK list_windows_callback(HWND hwnd, LPARAM lParam)
|
||||
{
|
||||
PyObject* window_list = (PyObject*) lParam;
|
||||
PyObject* item;
|
||||
PyObject* title;
|
||||
static BOOL CALLBACK
|
||||
list_windows_callback(HWND hwnd, LPARAM lParam) {
|
||||
PyObject *window_list = (PyObject *)lParam;
|
||||
PyObject *item;
|
||||
PyObject *title;
|
||||
RECT inner, outer;
|
||||
int title_size;
|
||||
int status;
|
||||
|
@ -440,7 +435,7 @@ static BOOL CALLBACK list_windows_callback(HWND hwnd, LPARAM lParam)
|
|||
if (title_size > 0) {
|
||||
title = PyUnicode_FromStringAndSize(NULL, title_size);
|
||||
if (title) {
|
||||
GetWindowTextW(hwnd, PyUnicode_AS_UNICODE(title), title_size+1);
|
||||
GetWindowTextW(hwnd, PyUnicode_AS_UNICODE(title), title_size + 1);
|
||||
}
|
||||
} else {
|
||||
title = PyUnicode_FromString("");
|
||||
|
@ -454,10 +449,17 @@ static BOOL CALLBACK list_windows_callback(HWND hwnd, LPARAM lParam)
|
|||
GetWindowRect(hwnd, &outer);
|
||||
|
||||
item = Py_BuildValue(
|
||||
F_HANDLE "N(iiii)(iiii)", hwnd, title,
|
||||
inner.left, inner.top, inner.right, inner.bottom,
|
||||
outer.left, outer.top, outer.right, outer.bottom
|
||||
);
|
||||
F_HANDLE "N(iiii)(iiii)",
|
||||
hwnd,
|
||||
title,
|
||||
inner.left,
|
||||
inner.top,
|
||||
inner.right,
|
||||
inner.bottom,
|
||||
outer.left,
|
||||
outer.top,
|
||||
outer.right,
|
||||
outer.bottom);
|
||||
if (!item) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -473,17 +475,16 @@ static BOOL CALLBACK list_windows_callback(HWND hwnd, LPARAM lParam)
|
|||
return 1;
|
||||
}
|
||||
|
||||
PyObject*
|
||||
PyImaging_ListWindowsWin32(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject* window_list;
|
||||
PyObject *
|
||||
PyImaging_ListWindowsWin32(PyObject *self, PyObject *args) {
|
||||
PyObject *window_list;
|
||||
|
||||
window_list = PyList_New(0);
|
||||
if (!window_list) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EnumWindows(list_windows_callback, (LPARAM) window_list);
|
||||
EnumWindows(list_windows_callback, (LPARAM)window_list);
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
Py_DECREF(window_list);
|
||||
|
@ -496,17 +497,16 @@ PyImaging_ListWindowsWin32(PyObject* self, PyObject* args)
|
|||
/* -------------------------------------------------------------------- */
|
||||
/* Windows clipboard grabber */
|
||||
|
||||
PyObject*
|
||||
PyImaging_GrabClipboardWin32(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject *
|
||||
PyImaging_GrabClipboardWin32(PyObject *self, PyObject *args) {
|
||||
int clip;
|
||||
HANDLE handle = NULL;
|
||||
int size;
|
||||
void* data;
|
||||
PyObject* result;
|
||||
void *data;
|
||||
PyObject *result;
|
||||
UINT format;
|
||||
UINT formats[] = { CF_DIB, CF_DIBV5, CF_HDROP, RegisterClipboardFormatA("PNG"), 0 };
|
||||
LPCSTR format_names[] = { "DIB", "DIB", "file", "png", NULL };
|
||||
UINT formats[] = {CF_DIB, CF_DIBV5, CF_HDROP, RegisterClipboardFormatA("PNG"), 0};
|
||||
LPCSTR format_names[] = {"DIB", "DIB", "file", "png", NULL};
|
||||
|
||||
if (!OpenClipboard(NULL)) {
|
||||
PyErr_SetString(PyExc_OSError, "failed to open clipboard");
|
||||
|
@ -551,15 +551,14 @@ PyImaging_GrabClipboardWin32(PyObject* self, PyObject* args)
|
|||
static int mainloop = 0;
|
||||
|
||||
static void
|
||||
callback_error(const char* handler)
|
||||
{
|
||||
PyObject* sys_stderr;
|
||||
callback_error(const char *handler) {
|
||||
PyObject *sys_stderr;
|
||||
|
||||
sys_stderr = PySys_GetObject("stderr");
|
||||
|
||||
if (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);
|
||||
}
|
||||
|
||||
|
@ -568,109 +567,119 @@ callback_error(const char* handler)
|
|||
}
|
||||
|
||||
static LRESULT CALLBACK
|
||||
windowCallback(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
windowCallback(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
PAINTSTRUCT ps;
|
||||
PyObject* callback = NULL;
|
||||
PyObject* result;
|
||||
PyThreadState* threadstate;
|
||||
PyThreadState* current_threadstate;
|
||||
PyObject *callback = NULL;
|
||||
PyObject *result;
|
||||
PyThreadState *threadstate;
|
||||
PyThreadState *current_threadstate;
|
||||
HDC dc;
|
||||
RECT rect;
|
||||
LRESULT status = 0;
|
||||
|
||||
/* set up threadstate for messages that calls back into python */
|
||||
switch (message) {
|
||||
case WM_CREATE:
|
||||
mainloop++;
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
mainloop--;
|
||||
/* fall through... */
|
||||
case WM_PAINT:
|
||||
case WM_SIZE:
|
||||
callback = (PyObject*) GetWindowLongPtr(wnd, 0);
|
||||
if (callback) {
|
||||
threadstate = (PyThreadState*)
|
||||
GetWindowLongPtr(wnd, sizeof(PyObject*));
|
||||
current_threadstate = PyThreadState_Swap(NULL);
|
||||
PyEval_RestoreThread(threadstate);
|
||||
} else {
|
||||
return DefWindowProc(wnd, message, wParam, lParam);
|
||||
}
|
||||
case WM_CREATE:
|
||||
mainloop++;
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
mainloop--;
|
||||
/* fall through... */
|
||||
case WM_PAINT:
|
||||
case WM_SIZE:
|
||||
callback = (PyObject *)GetWindowLongPtr(wnd, 0);
|
||||
if (callback) {
|
||||
threadstate =
|
||||
(PyThreadState *)GetWindowLongPtr(wnd, sizeof(PyObject *));
|
||||
current_threadstate = PyThreadState_Swap(NULL);
|
||||
PyEval_RestoreThread(threadstate);
|
||||
} else {
|
||||
return DefWindowProc(wnd, message, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
/* process 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:
|
||||
/* 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 */
|
||||
result = PyObject_CallFunction(
|
||||
callback,
|
||||
"siiii",
|
||||
"damage",
|
||||
ps.rcPaint.left,
|
||||
ps.rcPaint.top,
|
||||
ps.rcPaint.right,
|
||||
ps.rcPaint.bottom);
|
||||
if (result) {
|
||||
Py_DECREF(result);
|
||||
} else {
|
||||
callback_error("window damage callback");
|
||||
}
|
||||
|
||||
result = PyObject_CallFunction(
|
||||
callback, "siiii", "damage",
|
||||
ps.rcPaint.left, ps.rcPaint.top,
|
||||
ps.rcPaint.right, ps.rcPaint.bottom
|
||||
);
|
||||
if (result) {
|
||||
Py_DECREF(result);
|
||||
} else {
|
||||
callback_error("window damage callback");
|
||||
}
|
||||
result = PyObject_CallFunction(
|
||||
callback,
|
||||
"s" F_HANDLE "iiii",
|
||||
"clear",
|
||||
dc,
|
||||
0,
|
||||
0,
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top);
|
||||
if (result) {
|
||||
Py_DECREF(result);
|
||||
} else {
|
||||
callback_error("window clear callback");
|
||||
}
|
||||
|
||||
result = PyObject_CallFunction(
|
||||
callback, "s" F_HANDLE "iiii", "clear", dc,
|
||||
0, 0, rect.right-rect.left, rect.bottom-rect.top
|
||||
);
|
||||
if (result) {
|
||||
Py_DECREF(result);
|
||||
} else {
|
||||
callback_error("window clear callback");
|
||||
}
|
||||
result = PyObject_CallFunction(
|
||||
callback,
|
||||
"s" F_HANDLE "iiii",
|
||||
"repair",
|
||||
dc,
|
||||
0,
|
||||
0,
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top);
|
||||
if (result) {
|
||||
Py_DECREF(result);
|
||||
} else {
|
||||
callback_error("window repair callback");
|
||||
}
|
||||
|
||||
result = PyObject_CallFunction(
|
||||
callback, "s" F_HANDLE "iiii", "repair", dc,
|
||||
0, 0, rect.right-rect.left, rect.bottom-rect.top
|
||||
);
|
||||
if (result) {
|
||||
Py_DECREF(result);
|
||||
} else {
|
||||
callback_error("window repair callback");
|
||||
}
|
||||
ReleaseDC(wnd, dc);
|
||||
EndPaint(wnd, &ps);
|
||||
break;
|
||||
|
||||
ReleaseDC(wnd, dc);
|
||||
EndPaint(wnd, &ps);
|
||||
break;
|
||||
case WM_SIZE:
|
||||
/* resize window */
|
||||
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:
|
||||
/* resize window */
|
||||
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_DESTROY:
|
||||
/* destroy window */
|
||||
result = PyObject_CallFunction(callback, "s", "destroy");
|
||||
if (result) {
|
||||
Py_DECREF(result);
|
||||
} else {
|
||||
callback_error("window destroy callback");
|
||||
}
|
||||
Py_DECREF(callback);
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
/* destroy window */
|
||||
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);
|
||||
default:
|
||||
status = DefWindowProc(wnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
|
@ -682,14 +691,13 @@ windowCallback(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
return status;
|
||||
}
|
||||
|
||||
PyObject*
|
||||
PyImaging_CreateWindowWin32(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject *
|
||||
PyImaging_CreateWindowWin32(PyObject *self, PyObject *args) {
|
||||
HWND wnd;
|
||||
WNDCLASS windowClass;
|
||||
|
||||
char* title;
|
||||
PyObject* callback;
|
||||
char *title;
|
||||
PyObject *callback;
|
||||
int width = 0, height = 0;
|
||||
if (!PyArg_ParseTuple(args, "sO|ii", &title, &callback, &width, &height)) {
|
||||
return NULL;
|
||||
|
@ -705,7 +713,7 @@ PyImaging_CreateWindowWin32(PyObject* self, PyObject* args)
|
|||
/* register toplevel window class */
|
||||
windowClass.style = CS_CLASSDC;
|
||||
windowClass.cbClsExtra = 0;
|
||||
windowClass.cbWndExtra = sizeof(PyObject*) + sizeof(PyThreadState*);
|
||||
windowClass.cbWndExtra = sizeof(PyObject *) + sizeof(PyThreadState *);
|
||||
windowClass.hInstance = GetModuleHandle(NULL);
|
||||
/* windowClass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); */
|
||||
windowClass.hbrBackground = NULL;
|
||||
|
@ -718,11 +726,18 @@ PyImaging_CreateWindowWin32(PyObject* self, PyObject* args)
|
|||
RegisterClass(&windowClass); /* FIXME: check return status */
|
||||
|
||||
wnd = CreateWindowEx(
|
||||
0, windowClass.lpszClassName, title,
|
||||
0,
|
||||
windowClass.lpszClassName,
|
||||
title,
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, width, height,
|
||||
HWND_DESKTOP, NULL, NULL, NULL
|
||||
);
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
width,
|
||||
height,
|
||||
HWND_DESKTOP,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (!wnd) {
|
||||
PyErr_SetString(PyExc_OSError, "failed to create window");
|
||||
|
@ -731,76 +746,76 @@ PyImaging_CreateWindowWin32(PyObject* self, PyObject* args)
|
|||
|
||||
/* register window callback */
|
||||
Py_INCREF(callback);
|
||||
SetWindowLongPtr(wnd, 0, (LONG_PTR) callback);
|
||||
SetWindowLongPtr(wnd, sizeof(callback), (LONG_PTR) PyThreadState_Get());
|
||||
SetWindowLongPtr(wnd, 0, (LONG_PTR)callback);
|
||||
SetWindowLongPtr(wnd, sizeof(callback), (LONG_PTR)PyThreadState_Get());
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
ShowWindow(wnd, SW_SHOWNORMAL);
|
||||
Py_BEGIN_ALLOW_THREADS ShowWindow(wnd, SW_SHOWNORMAL);
|
||||
SetForegroundWindow(wnd); /* to make sure it's visible */
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
return Py_BuildValue(F_HANDLE, wnd);
|
||||
return Py_BuildValue(F_HANDLE, wnd);
|
||||
}
|
||||
|
||||
PyObject*
|
||||
PyImaging_EventLoopWin32(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject *
|
||||
PyImaging_EventLoopWin32(PyObject *self, PyObject *args) {
|
||||
MSG msg;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
while (mainloop && GetMessage(&msg, NULL, 0, 0)) {
|
||||
Py_BEGIN_ALLOW_THREADS while (mainloop && GetMessage(&msg, NULL, 0, 0)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* windows WMF renderer */
|
||||
|
||||
#define GET32(p,o) ((DWORD*)(p+o))[0]
|
||||
#define GET32(p, o) ((DWORD *)(p + o))[0]
|
||||
|
||||
PyObject *
|
||||
PyImaging_DrawWmf(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyImaging_DrawWmf(PyObject *self, PyObject *args) {
|
||||
HBITMAP bitmap;
|
||||
HENHMETAFILE meta;
|
||||
BITMAPCOREHEADER core;
|
||||
HDC dc;
|
||||
RECT rect;
|
||||
PyObject* buffer = NULL;
|
||||
char* ptr;
|
||||
PyObject *buffer = NULL;
|
||||
char *ptr;
|
||||
|
||||
char* data;
|
||||
char *data;
|
||||
Py_ssize_t datasize;
|
||||
int width, height;
|
||||
int x0, y0, x1, y1;
|
||||
if (!PyArg_ParseTuple(args, "y#(ii)(iiii):_load", &data, &datasize,
|
||||
&width, &height, &x0, &x1, &y0, &y1)) {
|
||||
if (!PyArg_ParseTuple(
|
||||
args,
|
||||
"y#(ii)(iiii):_load",
|
||||
&data,
|
||||
&datasize,
|
||||
&width,
|
||||
&height,
|
||||
&x0,
|
||||
&x1,
|
||||
&y0,
|
||||
&y1)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* step 1: copy metafile contents into METAFILE object */
|
||||
|
||||
if (datasize > 22 && GET32(data, 0) == 0x9ac6cdd7) {
|
||||
|
||||
/* placeable windows metafile (22-byte aldus header) */
|
||||
meta = SetWinMetaFileBits(datasize-22, data+22, NULL, NULL);
|
||||
|
||||
} else if (datasize > 80 && GET32(data, 0) == 1 &&
|
||||
GET32(data, 40) == 0x464d4520) {
|
||||
meta = SetWinMetaFileBits(datasize - 22, data + 22, NULL, NULL);
|
||||
|
||||
} else if (datasize > 80 && GET32(data, 0) == 1 && GET32(data, 40) == 0x464d4520) {
|
||||
/* enhanced metafile */
|
||||
meta = SetEnhMetaFileBits(datasize, data);
|
||||
|
||||
} else {
|
||||
|
||||
/* unknown meta format */
|
||||
meta = NULL;
|
||||
|
||||
}
|
||||
|
||||
if (!meta) {
|
||||
|
@ -818,9 +833,7 @@ PyImaging_DrawWmf(PyObject* self, PyObject* args)
|
|||
|
||||
dc = CreateCompatibleDC(NULL);
|
||||
|
||||
bitmap = CreateDIBSection(
|
||||
dc, (BITMAPINFO*) &core, DIB_RGB_COLORS, &ptr, NULL, 0
|
||||
);
|
||||
bitmap = CreateDIBSection(dc, (BITMAPINFO *)&core, DIB_RGB_COLORS, &ptr, NULL, 0);
|
||||
|
||||
if (!bitmap) {
|
||||
PyErr_SetString(PyExc_OSError, "cannot create bitmap");
|
||||
|
@ -850,7 +863,7 @@ PyImaging_DrawWmf(PyObject* self, PyObject* args)
|
|||
|
||||
GdiFlush();
|
||||
|
||||
buffer = PyBytes_FromStringAndSize(ptr, height * ((width*3 + 3) & -4));
|
||||
buffer = PyBytes_FromStringAndSize(ptr, height * ((width * 3 + 3) & -4));
|
||||
|
||||
error:
|
||||
DeleteEnhMetaFile(meta);
|
||||
|
@ -875,18 +888,17 @@ error:
|
|||
/* -------------------------------------------------------------------- */
|
||||
/* X11 screen grabber */
|
||||
|
||||
PyObject*
|
||||
PyImaging_GrabScreenX11(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject *
|
||||
PyImaging_GrabScreenX11(PyObject *self, PyObject *args) {
|
||||
int width, height;
|
||||
char* display_name;
|
||||
xcb_connection_t* connection;
|
||||
char *display_name;
|
||||
xcb_connection_t *connection;
|
||||
int screen_number;
|
||||
xcb_screen_iterator_t iter;
|
||||
xcb_screen_t* screen = NULL;
|
||||
xcb_get_image_reply_t* reply;
|
||||
xcb_generic_error_t* error;
|
||||
PyObject* buffer = NULL;
|
||||
xcb_screen_t *screen = NULL;
|
||||
xcb_get_image_reply_t *reply;
|
||||
xcb_generic_error_t *error;
|
||||
PyObject *buffer = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|z", &display_name)) {
|
||||
return NULL;
|
||||
|
@ -896,7 +908,10 @@ PyImaging_GrabScreenX11(PyObject* self, PyObject* args)
|
|||
|
||||
connection = xcb_connect(display_name, &screen_number);
|
||||
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);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -920,13 +935,26 @@ PyImaging_GrabScreenX11(PyObject* self, PyObject* args)
|
|||
|
||||
/* get image data */
|
||||
|
||||
reply = xcb_get_image_reply(connection,
|
||||
xcb_get_image(connection, XCB_IMAGE_FORMAT_Z_PIXMAP, screen->root,
|
||||
0, 0, width, height, 0x00ffffff),
|
||||
&error);
|
||||
reply = xcb_get_image_reply(
|
||||
connection,
|
||||
xcb_get_image(
|
||||
connection,
|
||||
XCB_IMAGE_FORMAT_Z_PIXMAP,
|
||||
screen->root,
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
height,
|
||||
0x00ffffff),
|
||||
&error);
|
||||
if (reply == NULL) {
|
||||
PyErr_Format(PyExc_OSError, "X get_image failed: error %i (%i, %i, %i)",
|
||||
error->error_code, error->major_code, error->minor_code, error->resource_id);
|
||||
PyErr_Format(
|
||||
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);
|
||||
xcb_disconnect(connection);
|
||||
return NULL;
|
||||
|
@ -935,8 +963,8 @@ PyImaging_GrabScreenX11(PyObject* self, PyObject* args)
|
|||
/* store data in Python buffer */
|
||||
|
||||
if (reply->depth == 24) {
|
||||
buffer = PyBytes_FromStringAndSize((char*)xcb_get_image_data(reply),
|
||||
xcb_get_image_data_length(reply));
|
||||
buffer = PyBytes_FromStringAndSize(
|
||||
(char *)xcb_get_image_data(reply), xcb_get_image_data_length(reply));
|
||||
} else {
|
||||
PyErr_Format(PyExc_OSError, "unsupported bit depth: %i", reply->depth);
|
||||
}
|
||||
|
|
645
src/encode.c
645
src/encode.c
File diff suppressed because it is too large
Load Diff
|
@ -9,7 +9,6 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
/* use Tests/make_hash.py to calculate these values */
|
||||
|
@ -19,23 +18,25 @@
|
|||
static struct ImagingAccessInstance access_table[ACCESS_TABLE_SIZE];
|
||||
|
||||
static inline UINT32
|
||||
hash(const char* mode)
|
||||
{
|
||||
hash(const char *mode) {
|
||||
UINT32 i = ACCESS_TABLE_HASH;
|
||||
while (*mode) {
|
||||
i = ((i<<5) + i) ^ (UINT8) *mode++;
|
||||
i = ((i << 5) + i) ^ (UINT8)*mode++;
|
||||
}
|
||||
return i % ACCESS_TABLE_SIZE;
|
||||
}
|
||||
|
||||
static ImagingAccess
|
||||
add_item(const char* mode)
|
||||
{
|
||||
add_item(const char *mode) {
|
||||
UINT32 i = hash(mode);
|
||||
/* printf("hash %s => %d\n", mode, i); */
|
||||
if (access_table[i].mode && strcmp(access_table[i].mode, mode) != 0) {
|
||||
fprintf(stderr, "AccessInit: hash collision: %d for both %s and %s\n",
|
||||
i, mode, access_table[i].mode);
|
||||
fprintf(
|
||||
stderr,
|
||||
"AccessInit: hash collision: %d for both %s and %s\n",
|
||||
i,
|
||||
mode,
|
||||
access_table[i].mode);
|
||||
exit(1);
|
||||
}
|
||||
access_table[i].mode = mode;
|
||||
|
@ -44,37 +45,33 @@ add_item(const char* mode)
|
|||
|
||||
/* fetch pointer to pixel line */
|
||||
|
||||
static void*
|
||||
line_8(Imaging im, int x, int y)
|
||||
{
|
||||
static void *
|
||||
line_8(Imaging im, int x, int y) {
|
||||
return &im->image8[y][x];
|
||||
}
|
||||
|
||||
static void*
|
||||
line_16(Imaging im, int x, int y)
|
||||
{
|
||||
return &im->image8[y][x+x];
|
||||
static void *
|
||||
line_16(Imaging im, int x, int y) {
|
||||
return &im->image8[y][x + x];
|
||||
}
|
||||
|
||||
static void*
|
||||
line_32(Imaging im, int x, int y)
|
||||
{
|
||||
static void *
|
||||
line_32(Imaging im, int x, int y) {
|
||||
return &im->image32[y][x];
|
||||
}
|
||||
|
||||
/* fetch individual pixel */
|
||||
|
||||
static void
|
||||
get_pixel(Imaging im, int x, int y, void* color)
|
||||
{
|
||||
char* out = color;
|
||||
get_pixel(Imaging im, int x, int y, void *color) {
|
||||
char *out = color;
|
||||
|
||||
/* generic pixel access*/
|
||||
|
||||
if (im->image8) {
|
||||
out[0] = im->image8[y][x];
|
||||
} else {
|
||||
UINT8* p = (UINT8*) &im->image32[y][x];
|
||||
UINT8 *p = (UINT8 *)&im->image32[y][x];
|
||||
if (im->type == IMAGING_TYPE_UINT8 && im->bands == 2) {
|
||||
out[0] = p[0];
|
||||
out[1] = p[3];
|
||||
|
@ -85,18 +82,16 @@ get_pixel(Imaging im, int x, int y, void* color)
|
|||
}
|
||||
|
||||
static void
|
||||
get_pixel_8(Imaging im, int x, int y, void* color)
|
||||
{
|
||||
char* out = color;
|
||||
get_pixel_8(Imaging im, int x, int y, void *color) {
|
||||
char *out = color;
|
||||
out[0] = im->image8[y][x];
|
||||
}
|
||||
|
||||
static void
|
||||
get_pixel_16L(Imaging im, int x, int y, void* color)
|
||||
{
|
||||
UINT8* in = (UINT8*) &im->image[y][x+x];
|
||||
get_pixel_16L(Imaging im, int x, int y, void *color) {
|
||||
UINT8 *in = (UINT8 *)&im->image[y][x + x];
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
UINT16 out = in[0] + (in[1]<<8);
|
||||
UINT16 out = in[0] + (in[1] << 8);
|
||||
memcpy(color, &out, sizeof(out));
|
||||
#else
|
||||
memcpy(color, in, sizeof(UINT16));
|
||||
|
@ -104,29 +99,26 @@ get_pixel_16L(Imaging im, int x, int y, void* color)
|
|||
}
|
||||
|
||||
static void
|
||||
get_pixel_16B(Imaging im, int x, int y, void* color)
|
||||
{
|
||||
UINT8* in = (UINT8*) &im->image[y][x+x];
|
||||
get_pixel_16B(Imaging im, int x, int y, void *color) {
|
||||
UINT8 *in = (UINT8 *)&im->image[y][x + x];
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
memcpy(color, in, sizeof(UINT16));
|
||||
#else
|
||||
UINT16 out = in[1] + (in[0]<<8);
|
||||
UINT16 out = in[1] + (in[0] << 8);
|
||||
memcpy(color, &out, sizeof(out));
|
||||
#endif
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
static void
|
||||
get_pixel_32L(Imaging im, int x, int y, void* color)
|
||||
{
|
||||
UINT8* in = (UINT8*) &im->image[y][x*4];
|
||||
get_pixel_32L(Imaging im, int x, int y, void *color) {
|
||||
UINT8 *in = (UINT8 *)&im->image[y][x * 4];
|
||||
#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));
|
||||
#else
|
||||
memcpy(color, in, sizeof(INT32));
|
||||
|
@ -134,13 +126,12 @@ get_pixel_32L(Imaging im, int x, int y, void* color)
|
|||
}
|
||||
|
||||
static void
|
||||
get_pixel_32B(Imaging im, int x, int y, void* color)
|
||||
{
|
||||
UINT8* in = (UINT8*) &im->image[y][x*4];
|
||||
get_pixel_32B(Imaging im, int x, int y, void *color) {
|
||||
UINT8 *in = (UINT8 *)&im->image[y][x * 4];
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
memcpy(color, in, sizeof(INT32));
|
||||
#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));
|
||||
#endif
|
||||
}
|
||||
|
@ -148,47 +139,41 @@ get_pixel_32B(Imaging im, int x, int y, void* color)
|
|||
/* store individual pixel */
|
||||
|
||||
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) {
|
||||
im->image8[y][x] = *((UINT8*) color);
|
||||
im->image8[y][x] = *((UINT8 *)color);
|
||||
} else {
|
||||
memcpy(&im->image32[y][x], color, sizeof(INT32));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
put_pixel_8(Imaging im, int x, int y, const void* color)
|
||||
{
|
||||
im->image8[y][x] = *((UINT8*) color);
|
||||
put_pixel_8(Imaging im, int x, int y, const void *color) {
|
||||
im->image8[y][x] = *((UINT8 *)color);
|
||||
}
|
||||
|
||||
static void
|
||||
put_pixel_16L(Imaging im, int x, int y, const void* color)
|
||||
{
|
||||
memcpy(&im->image8[y][x+x], color, 2);
|
||||
put_pixel_16L(Imaging im, int x, int y, const void *color) {
|
||||
memcpy(&im->image8[y][x + x], color, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
put_pixel_16B(Imaging im, int x, int y, const void* color)
|
||||
{
|
||||
const char* in = color;
|
||||
UINT8* out = (UINT8*) &im->image8[y][x+x];
|
||||
put_pixel_16B(Imaging im, int x, int y, const void *color) {
|
||||
const char *in = color;
|
||||
UINT8 *out = (UINT8 *)&im->image8[y][x + x];
|
||||
out[0] = in[1];
|
||||
out[1] = in[0];
|
||||
}
|
||||
|
||||
static void
|
||||
put_pixel_32L(Imaging im, int x, int y, const void* color)
|
||||
{
|
||||
memcpy(&im->image8[y][x*4], color, 4);
|
||||
put_pixel_32L(Imaging im, int x, int y, const void *color) {
|
||||
memcpy(&im->image8[y][x * 4], color, 4);
|
||||
}
|
||||
|
||||
static void
|
||||
put_pixel_32B(Imaging im, int x, int y, const void* color)
|
||||
{
|
||||
const char* in = color;
|
||||
UINT8* out = (UINT8*) &im->image8[y][x*4];
|
||||
put_pixel_32B(Imaging im, int x, int y, const void *color) {
|
||||
const char *in = color;
|
||||
UINT8 *out = (UINT8 *)&im->image8[y][x * 4];
|
||||
out[0] = in[3];
|
||||
out[1] = in[2];
|
||||
out[2] = in[1];
|
||||
|
@ -196,19 +181,18 @@ put_pixel_32B(Imaging im, int x, int y, const void* color)
|
|||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void
|
||||
ImagingAccessInit()
|
||||
{
|
||||
#define ADD(mode_, line_, get_pixel_, put_pixel_) \
|
||||
{ ImagingAccess access = add_item(mode_); \
|
||||
access->line = line_; \
|
||||
access->get_pixel = get_pixel_; \
|
||||
access->put_pixel = put_pixel_; \
|
||||
ImagingAccessInit() {
|
||||
#define ADD(mode_, line_, get_pixel_, put_pixel_) \
|
||||
{ \
|
||||
ImagingAccess access = add_item(mode_); \
|
||||
access->line = line_; \
|
||||
access->get_pixel = get_pixel_; \
|
||||
access->put_pixel = put_pixel_; \
|
||||
}
|
||||
|
||||
/* populate access table */
|
||||
|
@ -236,8 +220,7 @@ ImagingAccessInit()
|
|||
}
|
||||
|
||||
ImagingAccess
|
||||
ImagingAccessNew(Imaging im)
|
||||
{
|
||||
ImagingAccessNew(Imaging im) {
|
||||
ImagingAccess access = &access_table[hash(im->mode)];
|
||||
if (im->mode[0] != access->mode[0] || strcmp(im->mode, access->mode) != 0) {
|
||||
return NULL;
|
||||
|
@ -246,7 +229,4 @@ ImagingAccessNew(Imaging im)
|
|||
}
|
||||
|
||||
void
|
||||
_ImagingAccessDelete(Imaging im, ImagingAccess access)
|
||||
{
|
||||
|
||||
}
|
||||
_ImagingAccessDelete(Imaging im, ImagingAccess access) {}
|
||||
|
|
|
@ -8,39 +8,30 @@
|
|||
* See the README file for details on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#define PRECISION_BITS 7
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
UINT8 r;
|
||||
UINT8 g;
|
||||
UINT8 b;
|
||||
UINT8 a;
|
||||
} rgba8;
|
||||
|
||||
|
||||
|
||||
Imaging
|
||||
ImagingAlphaComposite(Imaging imDst, Imaging imSrc)
|
||||
{
|
||||
ImagingAlphaComposite(Imaging imDst, Imaging imSrc) {
|
||||
Imaging imOut;
|
||||
int x, y;
|
||||
|
||||
/* Check arguments */
|
||||
if (!imDst || !imSrc ||
|
||||
strcmp(imDst->mode, "RGBA") ||
|
||||
imDst->type != IMAGING_TYPE_UINT8 ||
|
||||
imDst->bands != 4) {
|
||||
if (!imDst || !imSrc || strcmp(imDst->mode, "RGBA") ||
|
||||
imDst->type != IMAGING_TYPE_UINT8 || imDst->bands != 4) {
|
||||
return ImagingError_ModeError();
|
||||
}
|
||||
|
||||
if (strcmp(imDst->mode, imSrc->mode) ||
|
||||
imDst->type != imSrc->type ||
|
||||
imDst->bands != imSrc->bands ||
|
||||
imDst->xsize != imSrc->xsize ||
|
||||
if (strcmp(imDst->mode, imSrc->mode) || imDst->type != imSrc->type ||
|
||||
imDst->bands != imSrc->bands || imDst->xsize != imSrc->xsize ||
|
||||
imDst->ysize != imSrc->ysize) {
|
||||
return ImagingError_Mismatch();
|
||||
}
|
||||
|
@ -51,11 +42,11 @@ ImagingAlphaComposite(Imaging imDst, Imaging imSrc)
|
|||
}
|
||||
|
||||
for (y = 0; y < imDst->ysize; y++) {
|
||||
rgba8* dst = (rgba8*) imDst->image[y];
|
||||
rgba8* src = (rgba8*) imSrc->image[y];
|
||||
rgba8* out = (rgba8*) imOut->image[y];
|
||||
rgba8 *dst = (rgba8 *)imDst->image[y];
|
||||
rgba8 *src = (rgba8 *)imSrc->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) {
|
||||
// Copy 4 bytes at once.
|
||||
*out = *dst;
|
||||
|
@ -69,21 +60,25 @@ ImagingAlphaComposite(Imaging imDst, Imaging imSrc)
|
|||
UINT32 outa255 = src->a * 255 + blend;
|
||||
// There we use 7 bits for precision.
|
||||
// We could use more, but we go beyond 32 bits.
|
||||
UINT32 coef1 = src->a * 255 * 255 * (1<<PRECISION_BITS) / outa255;
|
||||
UINT32 coef2 = 255 * (1<<PRECISION_BITS) - coef1;
|
||||
UINT32 coef1 = src->a * 255 * 255 * (1 << PRECISION_BITS) / outa255;
|
||||
UINT32 coef2 = 255 * (1 << PRECISION_BITS) - coef1;
|
||||
|
||||
tmpr = src->r * coef1 + dst->r * coef2;
|
||||
tmpg = src->g * coef1 + dst->g * coef2;
|
||||
tmpb = src->b * coef1 + dst->b * coef2;
|
||||
out->r = SHIFTFORDIV255(tmpr + (0x80<<PRECISION_BITS)) >> PRECISION_BITS;
|
||||
out->g = SHIFTFORDIV255(tmpg + (0x80<<PRECISION_BITS)) >> PRECISION_BITS;
|
||||
out->b = SHIFTFORDIV255(tmpb + (0x80<<PRECISION_BITS)) >> PRECISION_BITS;
|
||||
out->r =
|
||||
SHIFTFORDIV255(tmpr + (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);
|
||||
}
|
||||
|
||||
dst++; src++; out++;
|
||||
dst++;
|
||||
src++;
|
||||
out++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return imOut;
|
||||
|
|
|
@ -15,23 +15,20 @@
|
|||
* See the README file for details on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
Imaging
|
||||
ImagingGetBand(Imaging imIn, int band)
|
||||
{
|
||||
ImagingGetBand(Imaging imIn, int band) {
|
||||
Imaging imOut;
|
||||
int x, y;
|
||||
|
||||
/* Check arguments */
|
||||
if (!imIn || imIn->type != IMAGING_TYPE_UINT8) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
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 */
|
||||
|
@ -51,8 +48,8 @@ ImagingGetBand(Imaging imIn, int band)
|
|||
|
||||
/* Extract band from image */
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
UINT8* in = (UINT8*) imIn->image[y] + band;
|
||||
UINT8* out = imOut->image8[y];
|
||||
UINT8 *in = (UINT8 *)imIn->image[y] + band;
|
||||
UINT8 *out = imOut->image8[y];
|
||||
x = 0;
|
||||
for (; x < imIn->xsize - 3; x += 4) {
|
||||
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
|
||||
|
@ -68,15 +65,13 @@ ImagingGetBand(Imaging imIn, int band)
|
|||
return imOut;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ImagingSplit(Imaging imIn, Imaging bands[4])
|
||||
{
|
||||
ImagingSplit(Imaging imIn, Imaging bands[4]) {
|
||||
int i, j, x, y;
|
||||
|
||||
/* Check arguments */
|
||||
if (!imIn || imIn->type != IMAGING_TYPE_UINT8) {
|
||||
(void) ImagingError_ModeError();
|
||||
(void)ImagingError_ModeError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -88,7 +83,7 @@ ImagingSplit(Imaging imIn, Imaging bands[4])
|
|||
|
||||
for (i = 0; i < imIn->bands; i++) {
|
||||
bands[i] = ImagingNewDirty("L", imIn->xsize, imIn->ysize);
|
||||
if ( ! bands[i]) {
|
||||
if (!bands[i]) {
|
||||
for (j = 0; j < i; ++j) {
|
||||
ImagingDelete(bands[j]);
|
||||
}
|
||||
|
@ -99,14 +94,14 @@ ImagingSplit(Imaging imIn, Imaging bands[4])
|
|||
/* Extract bands from image */
|
||||
if (imIn->bands == 2) {
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
UINT8* in = (UINT8*) imIn->image[y];
|
||||
UINT8* out0 = bands[0]->image8[y];
|
||||
UINT8* out1 = bands[1]->image8[y];
|
||||
UINT8 *in = (UINT8 *)imIn->image[y];
|
||||
UINT8 *out0 = bands[0]->image8[y];
|
||||
UINT8 *out1 = bands[1]->image8[y];
|
||||
x = 0;
|
||||
for (; x < imIn->xsize - 3; x += 4) {
|
||||
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
|
||||
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));
|
||||
in += 16;
|
||||
}
|
||||
|
@ -118,17 +113,17 @@ ImagingSplit(Imaging imIn, Imaging bands[4])
|
|||
}
|
||||
} else if (imIn->bands == 3) {
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
UINT8* in = (UINT8*) imIn->image[y];
|
||||
UINT8* out0 = bands[0]->image8[y];
|
||||
UINT8* out1 = bands[1]->image8[y];
|
||||
UINT8* out2 = bands[2]->image8[y];
|
||||
UINT8 *in = (UINT8 *)imIn->image[y];
|
||||
UINT8 *out0 = bands[0]->image8[y];
|
||||
UINT8 *out1 = bands[1]->image8[y];
|
||||
UINT8 *out2 = bands[2]->image8[y];
|
||||
x = 0;
|
||||
for (; x < imIn->xsize - 3; x += 4) {
|
||||
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
|
||||
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));
|
||||
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));
|
||||
in += 16;
|
||||
}
|
||||
|
@ -141,20 +136,20 @@ ImagingSplit(Imaging imIn, Imaging bands[4])
|
|||
}
|
||||
} else {
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
UINT8* in = (UINT8*) imIn->image[y];
|
||||
UINT8* out0 = bands[0]->image8[y];
|
||||
UINT8* out1 = bands[1]->image8[y];
|
||||
UINT8* out2 = bands[2]->image8[y];
|
||||
UINT8* out3 = bands[3]->image8[y];
|
||||
UINT8 *in = (UINT8 *)imIn->image[y];
|
||||
UINT8 *out0 = bands[0]->image8[y];
|
||||
UINT8 *out1 = bands[1]->image8[y];
|
||||
UINT8 *out2 = bands[2]->image8[y];
|
||||
UINT8 *out3 = bands[3]->image8[y];
|
||||
x = 0;
|
||||
for (; x < imIn->xsize - 3; x += 4) {
|
||||
UINT32 v = MAKE_UINT32(in[0], in[4], in[8], in[12]);
|
||||
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));
|
||||
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));
|
||||
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));
|
||||
in += 16;
|
||||
}
|
||||
|
@ -171,25 +166,22 @@ ImagingSplit(Imaging imIn, Imaging bands[4])
|
|||
return imIn->bands;
|
||||
}
|
||||
|
||||
|
||||
Imaging
|
||||
ImagingPutBand(Imaging imOut, Imaging imIn, int band)
|
||||
{
|
||||
ImagingPutBand(Imaging imOut, Imaging imIn, int band) {
|
||||
int x, y;
|
||||
|
||||
/* Check arguments */
|
||||
if (!imIn || imIn->bands != 1 || !imOut) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
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 ||
|
||||
imIn->xsize != imOut->xsize ||
|
||||
if (imIn->type != imOut->type || imIn->xsize != imOut->xsize ||
|
||||
imIn->ysize != imOut->ysize) {
|
||||
return (Imaging) ImagingError_Mismatch();
|
||||
return (Imaging)ImagingError_Mismatch();
|
||||
}
|
||||
|
||||
/* Shortcuts */
|
||||
|
@ -204,8 +196,8 @@ ImagingPutBand(Imaging imOut, Imaging imIn, int band)
|
|||
|
||||
/* Insert band into image */
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
UINT8* in = imIn->image8[y];
|
||||
UINT8* out = (UINT8*) imOut->image[y] + band;
|
||||
UINT8 *in = imIn->image8[y];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y] + band;
|
||||
for (x = 0; x < imIn->xsize; x++) {
|
||||
*out = in[x];
|
||||
out += 4;
|
||||
|
@ -216,17 +208,16 @@ ImagingPutBand(Imaging imOut, Imaging imIn, int band)
|
|||
}
|
||||
|
||||
Imaging
|
||||
ImagingFillBand(Imaging imOut, int band, int color)
|
||||
{
|
||||
ImagingFillBand(Imaging imOut, int band, int color) {
|
||||
int x, y;
|
||||
|
||||
/* Check arguments */
|
||||
if (!imOut || imOut->type != IMAGING_TYPE_UINT8) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
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 */
|
||||
|
@ -238,9 +229,9 @@ ImagingFillBand(Imaging imOut, int band, int color)
|
|||
|
||||
/* Insert color into image */
|
||||
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++) {
|
||||
*out = (UINT8) color;
|
||||
*out = (UINT8)color;
|
||||
out += 4;
|
||||
}
|
||||
}
|
||||
|
@ -249,40 +240,39 @@ ImagingFillBand(Imaging imOut, int band, int color)
|
|||
}
|
||||
|
||||
Imaging
|
||||
ImagingMerge(const char* mode, Imaging bands[4])
|
||||
{
|
||||
ImagingMerge(const char *mode, Imaging bands[4]) {
|
||||
int i, x, y;
|
||||
int bandsCount = 0;
|
||||
Imaging imOut;
|
||||
Imaging firstBand;
|
||||
|
||||
firstBand = bands[0];
|
||||
if ( ! firstBand) {
|
||||
return (Imaging) ImagingError_ValueError("wrong number of bands");
|
||||
if (!firstBand) {
|
||||
return (Imaging)ImagingError_ValueError("wrong number of bands");
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if ( ! bands[i]) {
|
||||
if (!bands[i]) {
|
||||
break;
|
||||
}
|
||||
if (bands[i]->bands != 1) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
if (bands[i]->xsize != firstBand->xsize
|
||||
|| bands[i]->ysize != firstBand->ysize) {
|
||||
return (Imaging) ImagingError_Mismatch();
|
||||
if (bands[i]->xsize != firstBand->xsize ||
|
||||
bands[i]->ysize != firstBand->ysize) {
|
||||
return (Imaging)ImagingError_Mismatch();
|
||||
}
|
||||
}
|
||||
bandsCount = i;
|
||||
|
||||
imOut = ImagingNewDirty(mode, firstBand->xsize, firstBand->ysize);
|
||||
if ( ! imOut) {
|
||||
if (!imOut) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (imOut->bands != bandsCount) {
|
||||
ImagingDelete(imOut);
|
||||
return (Imaging) ImagingError_ValueError("wrong number of bands");
|
||||
return (Imaging)ImagingError_ValueError("wrong number of bands");
|
||||
}
|
||||
|
||||
if (imOut->bands == 1) {
|
||||
|
@ -291,30 +281,30 @@ ImagingMerge(const char* mode, Imaging bands[4])
|
|||
|
||||
if (imOut->bands == 2) {
|
||||
for (y = 0; y < imOut->ysize; y++) {
|
||||
UINT8* in0 = bands[0]->image8[y];
|
||||
UINT8* in1 = bands[1]->image8[y];
|
||||
UINT32* out = (UINT32*) imOut->image32[y];
|
||||
UINT8 *in0 = bands[0]->image8[y];
|
||||
UINT8 *in1 = bands[1]->image8[y];
|
||||
UINT32 *out = (UINT32 *)imOut->image32[y];
|
||||
for (x = 0; x < imOut->xsize; x++) {
|
||||
out[x] = MAKE_UINT32(in0[x], 0, 0, in1[x]);
|
||||
}
|
||||
}
|
||||
} else if (imOut->bands == 3) {
|
||||
for (y = 0; y < imOut->ysize; y++) {
|
||||
UINT8* in0 = bands[0]->image8[y];
|
||||
UINT8* in1 = bands[1]->image8[y];
|
||||
UINT8* in2 = bands[2]->image8[y];
|
||||
UINT32* out = (UINT32*) imOut->image32[y];
|
||||
UINT8 *in0 = bands[0]->image8[y];
|
||||
UINT8 *in1 = bands[1]->image8[y];
|
||||
UINT8 *in2 = bands[2]->image8[y];
|
||||
UINT32 *out = (UINT32 *)imOut->image32[y];
|
||||
for (x = 0; x < imOut->xsize; x++) {
|
||||
out[x] = MAKE_UINT32(in0[x], in1[x], in2[x], 0);
|
||||
}
|
||||
}
|
||||
} else if (imOut->bands == 4) {
|
||||
for (y = 0; y < imOut->ysize; y++) {
|
||||
UINT8* in0 = bands[0]->image8[y];
|
||||
UINT8* in1 = bands[1]->image8[y];
|
||||
UINT8* in2 = bands[2]->image8[y];
|
||||
UINT8* in3 = bands[3]->image8[y];
|
||||
UINT32* out = (UINT32*) imOut->image32[y];
|
||||
UINT8 *in0 = bands[0]->image8[y];
|
||||
UINT8 *in1 = bands[1]->image8[y];
|
||||
UINT8 *in2 = bands[2]->image8[y];
|
||||
UINT8 *in3 = bands[3]->image8[y];
|
||||
UINT32 *out = (UINT32 *)imOut->image32[y];
|
||||
for (x = 0; x < imOut->xsize; x++) {
|
||||
out[x] = MAKE_UINT32(in0[x], in1[x], in2[x], in3[x]);
|
||||
}
|
||||
|
|
|
@ -11,10 +11,8 @@
|
|||
* https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
UINT8 r, g, b, a;
|
||||
} rgba;
|
||||
|
@ -37,23 +35,24 @@ typedef struct {
|
|||
UINT8 lut[6];
|
||||
} bc3_alpha;
|
||||
|
||||
#define LOAD16(p) \
|
||||
(p)[0] | ((p)[1] << 8)
|
||||
#define LOAD16(p) (p)[0] | ((p)[1] << 8)
|
||||
|
||||
#define LOAD32(p) \
|
||||
(p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24)
|
||||
#define LOAD32(p) (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->c1 = LOAD16(src + 2);
|
||||
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));
|
||||
}
|
||||
|
||||
static rgba decode_565(UINT16 x) {
|
||||
static rgba
|
||||
decode_565(UINT16 x) {
|
||||
rgba c;
|
||||
int r, g, b;
|
||||
r = (x & 0xf800) >> 8;
|
||||
|
@ -69,7 +68,8 @@ static rgba decode_565(UINT16 x) {
|
|||
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;
|
||||
rgba p[4];
|
||||
int n, cw;
|
||||
|
@ -85,13 +85,13 @@ static void decode_bc1_color(rgba *dst, const UINT8 *src) {
|
|||
g1 = p[1].g;
|
||||
b1 = p[1].b;
|
||||
if (col.c0 > col.c1) {
|
||||
p[2].r = (2*r0 + 1*r1) / 3;
|
||||
p[2].g = (2*g0 + 1*g1) / 3;
|
||||
p[2].b = (2*b0 + 1*b1) / 3;
|
||||
p[2].r = (2 * r0 + 1 * r1) / 3;
|
||||
p[2].g = (2 * g0 + 1 * g1) / 3;
|
||||
p[2].b = (2 * b0 + 1 * b1) / 3;
|
||||
p[2].a = 0xff;
|
||||
p[3].r = (1*r0 + 2*r1) / 3;
|
||||
p[3].g = (1*g0 + 2*g1) / 3;
|
||||
p[3].b = (1*b0 + 2*b1) / 3;
|
||||
p[3].r = (1 * r0 + 2 * r1) / 3;
|
||||
p[3].g = (1 * g0 + 2 * g1) / 3;
|
||||
p[3].b = (1 * b0 + 2 * b1) / 3;
|
||||
p[3].a = 0xff;
|
||||
} else {
|
||||
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;
|
||||
UINT16 a0, a1;
|
||||
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[1] = (UINT8)a1;
|
||||
if (a0 > a1) {
|
||||
a[2] = (6*a0 + 1*a1) / 7;
|
||||
a[3] = (5*a0 + 2*a1) / 7;
|
||||
a[4] = (4*a0 + 3*a1) / 7;
|
||||
a[5] = (3*a0 + 4*a1) / 7;
|
||||
a[6] = (2*a0 + 5*a1) / 7;
|
||||
a[7] = (1*a0 + 6*a1) / 7;
|
||||
a[2] = (6 * a0 + 1 * a1) / 7;
|
||||
a[3] = (5 * a0 + 2 * a1) / 7;
|
||||
a[4] = (4 * a0 + 3 * a1) / 7;
|
||||
a[5] = (3 * a0 + 4 * a1) / 7;
|
||||
a[6] = (2 * a0 + 5 * a1) / 7;
|
||||
a[7] = (1 * a0 + 6 * a1) / 7;
|
||||
} else {
|
||||
a[2] = (4*a0 + 1*a1) / 5;
|
||||
a[3] = (3*a0 + 2*a1) / 5;
|
||||
a[4] = (2*a0 + 3*a1) / 5;
|
||||
a[5] = (1*a0 + 4*a1) / 5;
|
||||
a[2] = (4 * a0 + 1 * a1) / 5;
|
||||
a[3] = (3 * a0 + 2 * a1) / 5;
|
||||
a[4] = (2 * a0 + 3 * a1) / 5;
|
||||
a[5] = (1 * a0 + 4 * a1) / 5;
|
||||
a[6] = 0;
|
||||
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);
|
||||
for (n = 0; n < 8; 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);
|
||||
}
|
||||
|
||||
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;
|
||||
decode_bc1_color(col, src + 8);
|
||||
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_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);
|
||||
}
|
||||
|
||||
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 + 8, sizeof(col[0]), 1);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
bit &= 7;
|
||||
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;
|
||||
int x;
|
||||
int by = bit >> 3;
|
||||
|
@ -197,7 +206,7 @@ static UINT8 get_bits(const UINT8* src, int bit, int count) {
|
|||
if (bit + count <= 8) {
|
||||
v = (src[by] >> bit) & ((1 << count) - 1);
|
||||
} else {
|
||||
x = src[by] | (src[by+1] << 8);
|
||||
x = src[by] | (src[by + 1] << 8);
|
||||
v = (x >> bit) & ((1 << count) - 1);
|
||||
}
|
||||
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, 0, 7, 8, 0, 0, 2, 2},
|
||||
{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:
|
||||
Table.P2, 1 bit per index */
|
||||
static const UINT16 bc7_si2[] = {
|
||||
0xcccc, 0x8888, 0xeeee, 0xecc8, 0xc880, 0xfeec, 0xfec8, 0xec80,
|
||||
0xc800, 0xffec, 0xfe80, 0xe800, 0xffe8, 0xff00, 0xfff0, 0xf000,
|
||||
0xf710, 0x008e, 0x7100, 0x08ce, 0x008c, 0x7310, 0x3100, 0x8cce,
|
||||
0x088c, 0x3110, 0x6666, 0x366c, 0x17e8, 0x0ff0, 0x718e, 0x399c,
|
||||
0xaaaa, 0xf0f0, 0x5a5a, 0x33cc, 0x3c3c, 0x55aa, 0x9696, 0xa55a,
|
||||
0x73ce, 0x13c8, 0x324c, 0x3bdc, 0x6996, 0xc33c, 0x9966, 0x0660,
|
||||
0x0272, 0x04e4, 0x4e40, 0x2720, 0xc936, 0x936c, 0x39c6, 0x639c,
|
||||
0x9336, 0x9cc6, 0x817e, 0xe718, 0xccf0, 0x0fcc, 0x7744, 0xee22};
|
||||
0xcccc, 0x8888, 0xeeee, 0xecc8, 0xc880, 0xfeec, 0xfec8, 0xec80, 0xc800, 0xffec,
|
||||
0xfe80, 0xe800, 0xffe8, 0xff00, 0xfff0, 0xf000, 0xf710, 0x008e, 0x7100, 0x08ce,
|
||||
0x008c, 0x7310, 0x3100, 0x8cce, 0x088c, 0x3110, 0x6666, 0x366c, 0x17e8, 0x0ff0,
|
||||
0x718e, 0x399c, 0xaaaa, 0xf0f0, 0x5a5a, 0x33cc, 0x3c3c, 0x55aa, 0x9696, 0xa55a,
|
||||
0x73ce, 0x13c8, 0x324c, 0x3bdc, 0x6996, 0xc33c, 0x9966, 0x0660, 0x0272, 0x04e4,
|
||||
0x4e40, 0x2720, 0xc936, 0x936c, 0x39c6, 0x639c, 0x9336, 0x9cc6, 0x817e, 0xe718,
|
||||
0xccf0, 0x0fcc, 0x7744, 0xee22};
|
||||
|
||||
/* Table.P3, 2 bits per index */
|
||||
static const UINT32 bc7_si3[] = {
|
||||
0xaa685050, 0x6a5a5040, 0x5a5a4200, 0x5450a0a8,
|
||||
0xa5a50000, 0xa0a05050, 0x5555a0a0, 0x5a5a5050,
|
||||
0xaa550000, 0xaa555500, 0xaaaa5500, 0x90909090,
|
||||
0x94949494, 0xa4a4a4a4, 0xa9a59450, 0x2a0a4250,
|
||||
0xa5945040, 0x0a425054, 0xa5a5a500, 0x55a0a0a0,
|
||||
0xa8a85454, 0x6a6a4040, 0xa4a45000, 0x1a1a0500,
|
||||
0x0050a4a4, 0xaaa59090, 0x14696914, 0x69691400,
|
||||
0xa08585a0, 0xaa821414, 0x50a4a450, 0x6a5a0200,
|
||||
0xa9a58000, 0x5090a0a8, 0xa8a09050, 0x24242424,
|
||||
0x00aa5500, 0x24924924, 0x24499224, 0x50a50a50,
|
||||
0x500aa550, 0xaaaa4444, 0x66660000, 0xa5a0a5a0,
|
||||
0x50a050a0, 0x69286928, 0x44aaaa44, 0x66666600,
|
||||
0xaa444444, 0x54a854a8, 0x95809580, 0x96969600,
|
||||
0xa85454a8, 0x80959580, 0xaa141414, 0x96960000,
|
||||
0xaaaa1414, 0xa05050a0, 0xa0a5a5a0, 0x96000000,
|
||||
0x40804080, 0xa9a8a9a8, 0xaaaaaa44, 0x2a4a5254};
|
||||
0xaa685050, 0x6a5a5040, 0x5a5a4200, 0x5450a0a8, 0xa5a50000, 0xa0a05050, 0x5555a0a0,
|
||||
0x5a5a5050, 0xaa550000, 0xaa555500, 0xaaaa5500, 0x90909090, 0x94949494, 0xa4a4a4a4,
|
||||
0xa9a59450, 0x2a0a4250, 0xa5945040, 0x0a425054, 0xa5a5a500, 0x55a0a0a0, 0xa8a85454,
|
||||
0x6a6a4040, 0xa4a45000, 0x1a1a0500, 0x0050a4a4, 0xaaa59090, 0x14696914, 0x69691400,
|
||||
0xa08585a0, 0xaa821414, 0x50a4a450, 0x6a5a0200, 0xa9a58000, 0x5090a0a8, 0xa8a09050,
|
||||
0x24242424, 0x00aa5500, 0x24924924, 0x24499224, 0x50a50a50, 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:
|
||||
Table.A2 */
|
||||
static const char bc7_ai0[] = {
|
||||
15,15,15,15,15,15,15,15,
|
||||
15,15,15,15,15,15,15,15,
|
||||
15, 2, 8, 2, 2, 8, 8,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};
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 8, 2, 2, 8,
|
||||
8, 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 */
|
||||
static const char bc7_ai1[] = {
|
||||
3, 3,15,15, 8, 3,15,15,
|
||||
8, 8, 6, 6, 6, 5, 3, 3,
|
||||
3, 3, 8,15, 3, 3, 6,10,
|
||||
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};
|
||||
3, 3, 15, 15, 8, 3, 15, 15, 8, 8, 6, 6, 6, 5, 3, 3, 3, 3, 8, 15, 3, 3,
|
||||
6, 10, 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 */
|
||||
static const char bc7_ai2[] = {
|
||||
15, 8, 8, 3,15,15, 3, 8,
|
||||
15,15,15,15,15,15,15, 8,
|
||||
15, 8,15, 3,15, 8,15, 8,
|
||||
3,15, 6,10,15,15,10, 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};
|
||||
static const char bc7_ai2[] = {15, 8, 8, 3, 15, 15, 3, 8, 15, 15, 15, 15, 15,
|
||||
15, 15, 8, 15, 8, 15, 3, 15, 8, 15, 8, 3, 15,
|
||||
6, 10, 15, 15, 10, 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 */
|
||||
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[] = {
|
||||
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) {
|
||||
return bc7_weights2;
|
||||
}
|
||||
|
@ -309,7 +297,8 @@ static const char *bc7_get_weights(int n) {
|
|||
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) {
|
||||
return 1 & (bc7_si2[partition] >> n);
|
||||
}
|
||||
|
@ -319,12 +308,14 @@ static int bc7_get_subset(int ns, int partition, int n) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static UINT8 expand_quantized(UINT8 v, int bits) {
|
||||
static UINT8
|
||||
expand_quantized(UINT8 v, int bits) {
|
||||
v = v << (8 - 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 t1 = 64 - s1;
|
||||
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);
|
||||
}
|
||||
|
||||
static void decode_bc7_block(rgba *col, const UINT8* src) {
|
||||
static void
|
||||
decode_bc7_block(rgba *col, const UINT8 *src) {
|
||||
rgba endpoints[6];
|
||||
int bit = 0, cibit, aibit;
|
||||
int mode = src[0];
|
||||
|
@ -352,7 +344,8 @@ static void decode_bc7_block(rgba *col, const UINT8* src) {
|
|||
}
|
||||
return;
|
||||
}
|
||||
while (!(mode & (1 << bit++))) ;
|
||||
while (!(mode & (1 << bit++)))
|
||||
;
|
||||
mode = bit - 1;
|
||||
info = &bc7_modes[mode];
|
||||
/* 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);
|
||||
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); \
|
||||
bit += N;
|
||||
LOAD(partition, info->pb);
|
||||
|
@ -421,14 +414,14 @@ static void decode_bc7_block(rgba *col, const UINT8* src) {
|
|||
if (ab) {
|
||||
ab++;
|
||||
}
|
||||
for (i = 0; i < numep; i+=2) {
|
||||
for (i = 0; i < numep; i += 2) {
|
||||
LOAD(val, 1);
|
||||
for (j = 0; j < 2; j++) {
|
||||
ASSIGN_P(endpoints[i+j].r);
|
||||
ASSIGN_P(endpoints[i+j].g);
|
||||
ASSIGN_P(endpoints[i+j].b);
|
||||
ASSIGN_P(endpoints[i + j].r);
|
||||
ASSIGN_P(endpoints[i + j].g);
|
||||
ASSIGN_P(endpoints[i + j].b);
|
||||
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]);
|
||||
}
|
||||
#define ROTATE(x, y) \
|
||||
val = x; \
|
||||
x = y; \
|
||||
y = val
|
||||
val = x; \
|
||||
x = y; \
|
||||
y = val
|
||||
if (rotation == 1) {
|
||||
ROTATE(col[i].r, col[i].a);
|
||||
} else if (rotation == 2) {
|
||||
|
@ -498,106 +491,102 @@ static void decode_bc7_block(rgba *col, const UINT8* src) {
|
|||
|
||||
/* BC6 */
|
||||
typedef struct {
|
||||
char ns; /* number of subsets (also called regions) */
|
||||
char tr; /* whether endpoints are delta-compressed */
|
||||
char pb; /* partition bits */
|
||||
char ns; /* number of subsets (also called regions) */
|
||||
char tr; /* whether endpoints are delta-compressed */
|
||||
char pb; /* partition bits */
|
||||
char epb; /* endpoint bits */
|
||||
char rb; /* red bits (delta) */
|
||||
char gb; /* green bits (delta) */
|
||||
char bb; /* blue bits (delta) */
|
||||
char rb; /* red bits (delta) */
|
||||
char gb; /* green bits (delta) */
|
||||
char bb; /* blue bits (delta) */
|
||||
} bc6_mode_info;
|
||||
|
||||
static const bc6_mode_info bc6_modes[] = {
|
||||
// 00
|
||||
{2, 1, 5, 10, 5, 5, 5},
|
||||
// 01
|
||||
{2, 1, 5, 7, 6, 6, 6},
|
||||
{2, 1, 5, 7, 6, 6, 6},
|
||||
// 10
|
||||
{2, 1, 5, 11, 5, 4, 4},
|
||||
{2, 1, 5, 11, 4, 5, 4},
|
||||
{2, 1, 5, 11, 4, 4, 5},
|
||||
{2, 1, 5, 9, 5, 5, 5},
|
||||
{2, 1, 5, 8, 6, 5, 5},
|
||||
{2, 1, 5, 8, 5, 6, 5},
|
||||
{2, 1, 5, 8, 5, 5, 6},
|
||||
{2, 0, 5, 6, 6, 6, 6},
|
||||
{2, 1, 5, 9, 5, 5, 5},
|
||||
{2, 1, 5, 8, 6, 5, 5},
|
||||
{2, 1, 5, 8, 5, 6, 5},
|
||||
{2, 1, 5, 8, 5, 5, 6},
|
||||
{2, 0, 5, 6, 6, 6, 6},
|
||||
// 11
|
||||
{1, 0, 0, 10, 10, 10, 10},
|
||||
{1, 1, 0, 11, 9, 9, 9},
|
||||
{1, 1, 0, 12, 8, 8, 8},
|
||||
{1, 1, 0, 16, 4, 4, 4}
|
||||
};
|
||||
{1, 1, 0, 11, 9, 9, 9},
|
||||
{1, 1, 0, 12, 8, 8, 8},
|
||||
{1, 1, 0, 16, 4, 4, 4}};
|
||||
|
||||
/* Table.F, encoded as a sequence of bit indices */
|
||||
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,
|
||||
23, 24, 25, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 52,
|
||||
164, 112, 113, 114, 115, 64, 65, 66, 67, 68, 172, 160, 161, 162, 163, 80,
|
||||
81, 82, 83, 84, 173, 128, 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,
|
||||
22, 133, 174, 116, 32, 33, 34, 35, 36, 37, 38, 175, 177, 176, 48, 49, 50,
|
||||
51, 52, 53, 112, 113, 114, 115, 64, 65, 66, 67, 68, 69, 160, 161, 162, 163,
|
||||
80, 81, 82, 83, 84, 85, 128, 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,
|
||||
33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 52, 10, 112, 113, 114,
|
||||
115, 64, 65, 66, 67, 26, 172, 160, 161, 162, 163, 80, 81, 82, 83, 42, 173,
|
||||
128, 129, 130, 131, 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,
|
||||
33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 10, 164, 112, 113, 114,
|
||||
115, 64, 65, 66, 67, 68, 26, 160, 161, 162, 163, 80, 81, 82, 83, 42, 173,
|
||||
128, 129, 130, 131, 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,
|
||||
33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 10, 132, 112, 113, 114,
|
||||
115, 64, 65, 66, 67, 26, 172, 160, 161, 162, 163, 80, 81, 82, 83, 84, 42,
|
||||
128, 129, 130, 131, 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,
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 176, 48, 49, 50, 51, 52, 164, 112, 113,
|
||||
114, 115, 64, 65, 66, 67, 68, 172, 160, 161, 162, 163, 80, 81, 82, 83, 84,
|
||||
173, 128, 129, 130, 131, 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,
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 175, 176, 48, 49, 50, 51, 52, 53, 112, 113,
|
||||
114, 115, 64, 65, 66, 67, 68, 172, 160, 161, 162, 163, 80, 81, 82, 83, 84,
|
||||
173, 128, 129, 130, 131, 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,
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 165, 176, 48, 49, 50, 51, 52, 164, 112,
|
||||
113, 114, 115, 64, 65, 66, 67, 68, 69, 160, 161, 162, 163, 80, 81, 82, 83,
|
||||
84, 173, 128, 129, 130, 131, 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,
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 177, 176, 48, 49, 50, 51, 52, 164, 112,
|
||||
113, 114, 115, 64, 65, 66, 67, 68, 172, 160, 161, 162, 163, 80, 81, 82, 83,
|
||||
84, 85, 128, 129, 130, 131, 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,
|
||||
174, 116, 32, 33, 34, 35, 36, 37, 165, 175, 177, 176, 48, 49, 50, 51, 52,
|
||||
53, 112, 113, 114, 115, 64, 65, 66, 67, 68, 69, 160, 161, 162, 163, 80, 81,
|
||||
82, 83, 84, 85, 128, 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,
|
||||
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,
|
||||
89},
|
||||
{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, 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},
|
||||
{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, 52, 53, 54, 55, 11, 10,
|
||||
64, 65, 66, 67, 68, 69, 70, 71, 27, 26, 80, 81, 82, 83, 84, 85, 86, 87, 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}};
|
||||
{116, 132, 176, 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, 52, 164, 112, 113, 114, 115, 64, 65,
|
||||
66, 67, 68, 172, 160, 161, 162, 163, 80, 81, 82, 83, 84, 173, 128,
|
||||
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, 22, 133, 174, 116, 32, 33, 34, 35, 36, 37, 38,
|
||||
175, 177, 176, 48, 49, 50, 51, 52, 53, 112, 113, 114, 115, 64, 65,
|
||||
66, 67, 68, 69, 160, 161, 162, 163, 80, 81, 82, 83, 84, 85, 128,
|
||||
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, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
||||
48, 49, 50, 51, 52, 10, 112, 113, 114, 115, 64, 65, 66, 67, 26,
|
||||
172, 160, 161, 162, 163, 80, 81, 82, 83, 42, 173, 128, 129, 130, 131,
|
||||
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, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
||||
48, 49, 50, 51, 10, 164, 112, 113, 114, 115, 64, 65, 66, 67, 68,
|
||||
26, 160, 161, 162, 163, 80, 81, 82, 83, 42, 173, 128, 129, 130, 131,
|
||||
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, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
||||
48, 49, 50, 51, 10, 132, 112, 113, 114, 115, 64, 65, 66, 67, 26,
|
||||
172, 160, 161, 162, 163, 80, 81, 82, 83, 84, 42, 128, 129, 130, 131,
|
||||
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, 32, 33, 34, 35, 36, 37, 38, 39, 40, 176,
|
||||
48, 49, 50, 51, 52, 164, 112, 113, 114, 115, 64, 65, 66, 67, 68,
|
||||
172, 160, 161, 162, 163, 80, 81, 82, 83, 84, 173, 128, 129, 130, 131,
|
||||
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, 32, 33, 34, 35, 36, 37, 38, 39, 175, 176,
|
||||
48, 49, 50, 51, 52, 53, 112, 113, 114, 115, 64, 65, 66, 67, 68,
|
||||
172, 160, 161, 162, 163, 80, 81, 82, 83, 84, 173, 128, 129, 130, 131,
|
||||
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, 32, 33, 34, 35, 36, 37, 38, 39, 165, 176,
|
||||
48, 49, 50, 51, 52, 164, 112, 113, 114, 115, 64, 65, 66, 67, 68,
|
||||
69, 160, 161, 162, 163, 80, 81, 82, 83, 84, 173, 128, 129, 130, 131,
|
||||
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, 32, 33, 34, 35, 36, 37, 38, 39, 177, 176,
|
||||
48, 49, 50, 51, 52, 164, 112, 113, 114, 115, 64, 65, 66, 67, 68,
|
||||
172, 160, 161, 162, 163, 80, 81, 82, 83, 84, 85, 128, 129, 130, 131,
|
||||
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, 174, 116, 32, 33, 34, 35, 36, 37, 165, 175, 177, 176,
|
||||
48, 49, 50, 51, 52, 53, 112, 113, 114, 115, 64, 65, 66, 67, 68,
|
||||
69, 160, 161, 162, 163, 80, 81, 82, 83, 84, 85, 128, 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, 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, 89},
|
||||
{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, 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},
|
||||
{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, 52, 53, 54, 55, 11, 10,
|
||||
64, 65, 66, 67, 68, 69, 70, 71, 27, 26, 80, 81, 82, 83, 84, 85, 86, 87, 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;
|
||||
if (x & (1 << (prec - 1))) {
|
||||
x |= -1 << prec;
|
||||
|
@ -605,7 +594,8 @@ static void bc6_sign_extend(UINT16 *v, int prec) {
|
|||
*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 x;
|
||||
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 */
|
||||
union {
|
||||
UINT32 u;
|
||||
|
@ -662,7 +653,8 @@ static float half_to_float(UINT16 h) {
|
|||
return o.f;
|
||||
}
|
||||
|
||||
static float bc6_finalize(int v, int sign) {
|
||||
static float
|
||||
bc6_finalize(int v, int sign) {
|
||||
if (sign) {
|
||||
if (v < 0) {
|
||||
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 t = 64 - s;
|
||||
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);
|
||||
}
|
||||
|
||||
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, ... */
|
||||
int ueps[12];
|
||||
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 */
|
||||
for (i = 3; i < numep; i += 3) {
|
||||
bc6_sign_extend(&endpoints[i+0], info->rb);
|
||||
bc6_sign_extend(&endpoints[i+1], info->gb);
|
||||
bc6_sign_extend(&endpoints[i+2], info->bb);
|
||||
bc6_sign_extend(&endpoints[i + 0], info->rb);
|
||||
bc6_sign_extend(&endpoints[i + 1], info->gb);
|
||||
bc6_sign_extend(&endpoints[i + 2], info->bb);
|
||||
}
|
||||
}
|
||||
if (info->tr) { /* apply deltas */
|
||||
|
@ -747,9 +741,9 @@ static void decode_bc6_block(rgb32f *col, const UINT8* src, int sign) {
|
|||
}
|
||||
if (sign) {
|
||||
for (i = 3; i < numep; i += 3) {
|
||||
bc6_sign_extend(&endpoints[i+0], info->rb);
|
||||
bc6_sign_extend(&endpoints[i+1], info->gb);
|
||||
bc6_sign_extend(&endpoints[i+2], info->bb);
|
||||
bc6_sign_extend(&endpoints[i + 0], info->rb);
|
||||
bc6_sign_extend(&endpoints[i + 1], info->gb);
|
||||
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);
|
||||
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 height = state->ysize;
|
||||
int xmax = width + state->xoff;
|
||||
|
@ -795,15 +790,15 @@ static void put_block(Imaging im, ImagingCodecState state, const char *col, int
|
|||
if (x >= width) {
|
||||
continue;
|
||||
}
|
||||
memcpy(dst + sz*x, col + sz*(j*4 + i), sz);
|
||||
memcpy(dst + sz * x, col + sz * (j * 4 + i), sz);
|
||||
}
|
||||
} else {
|
||||
if (state->ystep < 0) {
|
||||
y = state->yoff + ymax - y - 1;
|
||||
}
|
||||
x = state->x;
|
||||
dst = im->image[y] + sz*x;
|
||||
memcpy(dst, col + sz*(j*4), 4 * sz);
|
||||
dst = im->image[y] + sz * x;
|
||||
memcpy(dst, col + sz * (j * 4), 4 * sz);
|
||||
}
|
||||
}
|
||||
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;
|
||||
const UINT8 *ptr = src;
|
||||
switch (N) {
|
||||
#define DECODE_LOOP(NN, SZ, TY, ...) \
|
||||
case NN: \
|
||||
while (bytes >= SZ) { \
|
||||
TY col[16]; \
|
||||
memset(col, 0, 16 * sizeof(col[0])); \
|
||||
decode_bc##NN##_block(col, ptr); \
|
||||
#define DECODE_LOOP(NN, SZ, TY, ...) \
|
||||
case NN: \
|
||||
while (bytes >= SZ) { \
|
||||
TY col[16]; \
|
||||
memset(col, 0, 16 * sizeof(col[0])); \
|
||||
decode_bc##NN##_block(col, ptr); \
|
||||
put_block(im, state, (const char *)col, sizeof(col[0]), C); \
|
||||
ptr += SZ; \
|
||||
bytes -= SZ; \
|
||||
if (state->y >= ymax) {\
|
||||
return -1; \
|
||||
}\
|
||||
} \
|
||||
ptr += SZ; \
|
||||
bytes -= SZ; \
|
||||
if (state->y >= ymax) { \
|
||||
return -1; \
|
||||
} \
|
||||
} \
|
||||
break
|
||||
|
||||
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);
|
||||
ptr += 16;
|
||||
bytes -= 16;
|
||||
if (state->y >= ymax) {\
|
||||
return -1; \
|
||||
}\
|
||||
if (state->y >= ymax) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
DECODE_LOOP(7, 16, rgba);
|
||||
DECODE_LOOP(7, 16, rgba);
|
||||
#undef DECODE_LOOP
|
||||
}
|
||||
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 width = state->xsize;
|
||||
int height = state->ysize;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* Bit.h */
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* CONFIGURATION */
|
||||
|
||||
/* Number of bits per pixel */
|
||||
|
@ -19,7 +18,7 @@ typedef struct {
|
|||
|
||||
/* Lookup table (not implemented) */
|
||||
unsigned long lutsize;
|
||||
FLOAT32* lut;
|
||||
FLOAT32 *lut;
|
||||
|
||||
/* INTERNAL */
|
||||
unsigned long mask;
|
||||
|
|
|
@ -13,20 +13,16 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#include "Bit.h"
|
||||
|
||||
|
||||
int
|
||||
ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes)
|
||||
{
|
||||
BITSTATE* bitstate = state->context;
|
||||
UINT8* ptr;
|
||||
ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
|
||||
BITSTATE *bitstate = state->context;
|
||||
UINT8 *ptr;
|
||||
|
||||
if (state->state == 0) {
|
||||
|
||||
/* Initialize context variables */
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
bitstate->mask = (1<<bitstate->bits)-1;
|
||||
bitstate->mask = (1 << bitstate->bits) - 1;
|
||||
|
||||
if (bitstate->sign) {
|
||||
bitstate->signmask = (1<<(bitstate->bits-1));
|
||||
bitstate->signmask = (1 << (bitstate->bits - 1));
|
||||
}
|
||||
|
||||
/* check image orientation */
|
||||
if (state->ystep < 0) {
|
||||
state->y = state->ysize-1;
|
||||
state->y = state->ysize - 1;
|
||||
state->ystep = -1;
|
||||
} else {
|
||||
state->ystep = 1;
|
||||
}
|
||||
|
||||
state->state = 1;
|
||||
|
||||
}
|
||||
|
||||
ptr = buf;
|
||||
|
||||
while (bytes > 0) {
|
||||
|
||||
UINT8 byte = *ptr;
|
||||
|
||||
ptr++;
|
||||
bytes--;
|
||||
|
||||
/* get a byte from the input stream and insert in the bit buffer */
|
||||
if (bitstate->fill&1) {
|
||||
if (bitstate->fill & 1) {
|
||||
/* fill MSB first */
|
||||
bitstate->bitbuffer |= (unsigned long) byte << bitstate->bitcount;
|
||||
bitstate->bitbuffer |= (unsigned long)byte << bitstate->bitcount;
|
||||
} else {
|
||||
/* fill LSB first */
|
||||
bitstate->bitbuffer = (bitstate->bitbuffer << 8) | byte;
|
||||
|
@ -80,26 +74,24 @@ ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
bitstate->bitcount += 8;
|
||||
|
||||
while (bitstate->bitcount >= bitstate->bits) {
|
||||
|
||||
/* get a pixel from the bit buffer */
|
||||
unsigned long data;
|
||||
FLOAT32 pixel;
|
||||
|
||||
if (bitstate->fill&2) {
|
||||
if (bitstate->fill & 2) {
|
||||
/* store LSB first */
|
||||
data = bitstate->bitbuffer & bitstate->mask;
|
||||
if (bitstate->bitcount > 32) {
|
||||
/* bitbuffer overflow; restore it from last input byte */
|
||||
bitstate->bitbuffer = byte >> (8 - (bitstate->bitcount -
|
||||
bitstate->bits));
|
||||
bitstate->bitbuffer =
|
||||
byte >> (8 - (bitstate->bitcount - bitstate->bits));
|
||||
} else {
|
||||
bitstate->bitbuffer >>= bitstate->bits;
|
||||
}
|
||||
} else {
|
||||
/* store MSB first */
|
||||
data = (bitstate->bitbuffer >> (bitstate->bitcount -
|
||||
bitstate->bits))
|
||||
& bitstate->mask;
|
||||
data = (bitstate->bitbuffer >> (bitstate->bitcount - bitstate->bits)) &
|
||||
bitstate->mask;
|
||||
}
|
||||
|
||||
bitstate->bitcount -= bitstate->bits;
|
||||
|
@ -109,7 +101,7 @@ ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
if (data <= 0) {
|
||||
pixel = bitstate->lut[0];
|
||||
} else if (data >= bitstate->lutsize) {
|
||||
pixel = bitstate->lut[bitstate->lutsize-1];
|
||||
pixel = bitstate->lut[bitstate->lutsize - 1];
|
||||
} else {
|
||||
pixel = bitstate->lut[data];
|
||||
}
|
||||
|
@ -117,13 +109,13 @@ ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
/* convert */
|
||||
if (data & bitstate->signmask) {
|
||||
/* image memory contains signed data */
|
||||
pixel = (FLOAT32) (INT32) (data | ~bitstate->mask);
|
||||
pixel = (FLOAT32)(INT32)(data | ~bitstate->mask);
|
||||
} 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 */
|
||||
if (++state->x >= state->xsize) {
|
||||
|
|
|
@ -15,27 +15,22 @@
|
|||
* See the README file for details on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
Imaging
|
||||
ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha)
|
||||
{
|
||||
ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha) {
|
||||
Imaging imOut;
|
||||
int x, y;
|
||||
|
||||
/* Check arguments */
|
||||
if (!imIn1 || !imIn2 || imIn1->type != IMAGING_TYPE_UINT8
|
||||
|| imIn1->palette || strcmp(imIn1->mode, "1") == 0
|
||||
|| imIn2->palette || strcmp(imIn2->mode, "1") == 0) {
|
||||
if (!imIn1 || !imIn2 || imIn1->type != IMAGING_TYPE_UINT8 || imIn1->palette ||
|
||||
strcmp(imIn1->mode, "1") == 0 || imIn2->palette ||
|
||||
strcmp(imIn2->mode, "1") == 0) {
|
||||
return ImagingError_ModeError();
|
||||
}
|
||||
|
||||
if (imIn1->type != imIn2->type ||
|
||||
imIn1->bands != imIn2->bands ||
|
||||
imIn1->xsize != imIn2->xsize ||
|
||||
imIn1->ysize != imIn2->ysize) {
|
||||
if (imIn1->type != imIn2->type || imIn1->bands != imIn2->bands ||
|
||||
imIn1->xsize != imIn2->xsize || imIn1->ysize != imIn2->ysize) {
|
||||
return ImagingError_Mismatch();
|
||||
}
|
||||
|
||||
|
@ -54,29 +49,27 @@ ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha)
|
|||
if (alpha >= 0 && alpha <= 1.0) {
|
||||
/* Interpolate between bands */
|
||||
for (y = 0; y < imIn1->ysize; y++) {
|
||||
UINT8* in1 = (UINT8*) imIn1->image[y];
|
||||
UINT8* in2 = (UINT8*) imIn2->image[y];
|
||||
UINT8* out = (UINT8*) imOut->image[y];
|
||||
UINT8 *in1 = (UINT8 *)imIn1->image[y];
|
||||
UINT8 *in2 = (UINT8 *)imIn2->image[y];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y];
|
||||
for (x = 0; x < imIn1->linesize; x++) {
|
||||
out[x] = (UINT8)
|
||||
((int) in1[x] + alpha * ((int) in2[x] - (int) in1[x]));
|
||||
out[x] = (UINT8)((int)in1[x] + alpha * ((int)in2[x] - (int)in1[x]));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Extrapolation; must make sure to clip resulting values */
|
||||
for (y = 0; y < imIn1->ysize; y++) {
|
||||
UINT8* in1 = (UINT8*) imIn1->image[y];
|
||||
UINT8* in2 = (UINT8*) imIn2->image[y];
|
||||
UINT8* out = (UINT8*) imOut->image[y];
|
||||
UINT8 *in1 = (UINT8 *)imIn1->image[y];
|
||||
UINT8 *in2 = (UINT8 *)imIn2->image[y];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y];
|
||||
for (x = 0; x < imIn1->linesize; x++) {
|
||||
float temp = (float)
|
||||
((int) in1[x] + alpha * ((int) in2[x] - (int) in1[x]));
|
||||
float temp = (float)((int)in1[x] + alpha * ((int)in2[x] - (int)in1[x]));
|
||||
if (temp <= 0.0) {
|
||||
out[x] = 0;
|
||||
} else if (temp >= 255.0) {
|
||||
out[x] = 255;
|
||||
} else {
|
||||
out[x] = (UINT8) temp;
|
||||
out[x] = (UINT8)temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,37 +1,40 @@
|
|||
#include "Imaging.h"
|
||||
|
||||
|
||||
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
|
||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
|
||||
|
||||
typedef UINT8 pixel[4];
|
||||
|
||||
void static inline
|
||||
ImagingLineBoxBlur32(pixel *lineOut, pixel *lineIn, int lastx, int radius, int edgeA,
|
||||
int edgeB, UINT32 ww, UINT32 fw)
|
||||
{
|
||||
void static inline ImagingLineBoxBlur32(
|
||||
pixel *lineOut,
|
||||
pixel *lineIn,
|
||||
int lastx,
|
||||
int radius,
|
||||
int edgeA,
|
||||
int edgeB,
|
||||
UINT32 ww,
|
||||
UINT32 fw) {
|
||||
int x;
|
||||
UINT32 acc[4];
|
||||
UINT32 bulk[4];
|
||||
|
||||
#define MOVE_ACC(acc, subtract, add) \
|
||||
acc[0] += lineIn[add][0] - lineIn[subtract][0]; \
|
||||
acc[1] += lineIn[add][1] - lineIn[subtract][1]; \
|
||||
acc[2] += lineIn[add][2] - lineIn[subtract][2]; \
|
||||
acc[3] += lineIn[add][3] - lineIn[subtract][3];
|
||||
#define MOVE_ACC(acc, subtract, add) \
|
||||
acc[0] += lineIn[add][0] - lineIn[subtract][0]; \
|
||||
acc[1] += lineIn[add][1] - lineIn[subtract][1]; \
|
||||
acc[2] += lineIn[add][2] - lineIn[subtract][2]; \
|
||||
acc[3] += lineIn[add][3] - lineIn[subtract][3];
|
||||
|
||||
#define ADD_FAR(bulk, acc, left, right) \
|
||||
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[2] = (acc[2] * ww) + (lineIn[left][2] + lineIn[right][2]) * fw; \
|
||||
bulk[3] = (acc[3] * ww) + (lineIn[left][3] + lineIn[right][3]) * fw;
|
||||
#define ADD_FAR(bulk, acc, left, right) \
|
||||
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[2] = (acc[2] * ww) + (lineIn[left][2] + lineIn[right][2]) * fw; \
|
||||
bulk[3] = (acc[3] * ww) + (lineIn[left][3] + lineIn[right][3]) * fw;
|
||||
|
||||
#define SAVE(x, bulk) \
|
||||
lineOut[x][0] = (UINT8)((bulk[0] + (1 << 23)) >> 24); \
|
||||
lineOut[x][1] = (UINT8)((bulk[1] + (1 << 23)) >> 24); \
|
||||
lineOut[x][2] = (UINT8)((bulk[2] + (1 << 23)) >> 24); \
|
||||
lineOut[x][3] = (UINT8)((bulk[3] + (1 << 23)) >> 24);
|
||||
#define SAVE(x, bulk) \
|
||||
lineOut[x][0] = (UINT8)((bulk[0] + (1 << 23)) >> 24); \
|
||||
lineOut[x][1] = (UINT8)((bulk[1] + (1 << 23)) >> 24); \
|
||||
lineOut[x][2] = (UINT8)((bulk[2] + (1 << 23)) >> 24); \
|
||||
lineOut[x][3] = (UINT8)((bulk[3] + (1 << 23)) >> 24);
|
||||
|
||||
/* Compute acc for -1 pixel (outside of image):
|
||||
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[3] += lineIn[lastx][3] * (radius - edgeA + 1);
|
||||
|
||||
if (edgeA <= edgeB)
|
||||
{
|
||||
if (edgeA <= edgeB) {
|
||||
/* Subtract pixel from left ("0").
|
||||
Add pixels from radius. */
|
||||
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);
|
||||
SAVE(x, bulk);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
for (x = 0; x < edgeB; x++) {
|
||||
MOVE_ACC(acc, 0, x + radius);
|
||||
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 ADD_FAR
|
||||
#undef SAVE
|
||||
#undef MOVE_ACC
|
||||
#undef ADD_FAR
|
||||
#undef SAVE
|
||||
}
|
||||
|
||||
|
||||
void static inline
|
||||
ImagingLineBoxBlur8(UINT8 *lineOut, UINT8 *lineIn, int lastx, int radius, int edgeA,
|
||||
int edgeB, UINT32 ww, UINT32 fw)
|
||||
{
|
||||
void static inline ImagingLineBoxBlur8(
|
||||
UINT8 *lineOut,
|
||||
UINT8 *lineIn,
|
||||
int lastx,
|
||||
int radius,
|
||||
int edgeA,
|
||||
int edgeB,
|
||||
UINT32 ww,
|
||||
UINT32 fw) {
|
||||
int x;
|
||||
UINT32 acc;
|
||||
UINT32 bulk;
|
||||
|
||||
#define MOVE_ACC(acc, subtract, add) \
|
||||
acc += lineIn[add] - lineIn[subtract];
|
||||
#define MOVE_ACC(acc, subtract, add) acc += lineIn[add] - lineIn[subtract];
|
||||
|
||||
#define ADD_FAR(bulk, acc, left, right) \
|
||||
bulk = (acc * ww) + (lineIn[left] + lineIn[right]) * fw;
|
||||
#define ADD_FAR(bulk, acc, left, right) \
|
||||
bulk = (acc * ww) + (lineIn[left] + lineIn[right]) * fw;
|
||||
|
||||
#define SAVE(x, bulk) \
|
||||
lineOut[x] = (UINT8)((bulk + (1 << 23)) >> 24)
|
||||
#define SAVE(x, bulk) lineOut[x] = (UINT8)((bulk + (1 << 23)) >> 24)
|
||||
|
||||
acc = lineIn[0] * (radius + 1);
|
||||
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);
|
||||
|
||||
if (edgeA <= edgeB)
|
||||
{
|
||||
if (edgeA <= edgeB) {
|
||||
for (x = 0; x < edgeA; x++) {
|
||||
MOVE_ACC(acc, 0, x + radius);
|
||||
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);
|
||||
SAVE(x, bulk);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
for (x = 0; x < edgeB; x++) {
|
||||
MOVE_ACC(acc, 0, x + radius);
|
||||
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 ADD_FAR
|
||||
#undef SAVE
|
||||
#undef MOVE_ACC
|
||||
#undef ADD_FAR
|
||||
#undef SAVE
|
||||
}
|
||||
|
||||
|
||||
|
||||
Imaging
|
||||
ImagingHorizontalBoxBlur(Imaging imOut, Imaging imIn, float floatRadius)
|
||||
{
|
||||
ImagingHorizontalBoxBlur(Imaging imOut, Imaging imIn, float floatRadius) {
|
||||
ImagingSectionCookie cookie;
|
||||
|
||||
int y;
|
||||
|
||||
int radius = (int) floatRadius;
|
||||
UINT32 ww = (UINT32) (1 << 24) / (floatRadius * 2 + 1);
|
||||
int radius = (int)floatRadius;
|
||||
UINT32 ww = (UINT32)(1 << 24) / (floatRadius * 2 + 1);
|
||||
UINT32 fw = ((1 << 24) - (radius * 2 + 1) * ww) / 2;
|
||||
|
||||
int edgeA = MIN(radius + 1, imIn->xsize);
|
||||
|
@ -192,32 +188,33 @@ ImagingHorizontalBoxBlur(Imaging imOut, Imaging imIn, float floatRadius)
|
|||
|
||||
ImagingSectionEnter(&cookie);
|
||||
|
||||
if (imIn->image8)
|
||||
{
|
||||
if (imIn->image8) {
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
ImagingLineBoxBlur8(
|
||||
(imIn == imOut ? (UINT8 *) lineOut : imOut->image8[y]),
|
||||
(imIn == imOut ? (UINT8 *)lineOut : imOut->image8[y]),
|
||||
imIn->image8[y],
|
||||
imIn->xsize - 1,
|
||||
radius, edgeA, edgeB,
|
||||
ww, fw
|
||||
);
|
||||
radius,
|
||||
edgeA,
|
||||
edgeB,
|
||||
ww,
|
||||
fw);
|
||||
if (imIn == imOut) {
|
||||
// Commit.
|
||||
memcpy(imOut->image8[y], lineOut, imIn->xsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
ImagingLineBoxBlur32(
|
||||
imIn == imOut ? (pixel *) lineOut : (pixel *) imOut->image32[y],
|
||||
(pixel *) imIn->image32[y],
|
||||
imIn == imOut ? (pixel *)lineOut : (pixel *)imOut->image32[y],
|
||||
(pixel *)imIn->image32[y],
|
||||
imIn->xsize - 1,
|
||||
radius, edgeA, edgeB,
|
||||
ww, fw
|
||||
);
|
||||
radius,
|
||||
edgeA,
|
||||
edgeB,
|
||||
ww,
|
||||
fw);
|
||||
if (imIn == imOut) {
|
||||
// Commit.
|
||||
memcpy(imOut->image32[y], lineOut, imIn->xsize * 4);
|
||||
|
@ -232,23 +229,17 @@ ImagingHorizontalBoxBlur(Imaging imOut, Imaging imIn, float floatRadius)
|
|||
return imOut;
|
||||
}
|
||||
|
||||
|
||||
Imaging
|
||||
ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n)
|
||||
{
|
||||
ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n) {
|
||||
int i;
|
||||
Imaging imTransposed;
|
||||
|
||||
if (n < 1) {
|
||||
return ImagingError_ValueError(
|
||||
"number of passes must be greater than zero"
|
||||
);
|
||||
return ImagingError_ValueError("number of passes must be greater than zero");
|
||||
}
|
||||
|
||||
if (strcmp(imIn->mode, imOut->mode) ||
|
||||
imIn->type != imOut->type ||
|
||||
imIn->bands != imOut->bands ||
|
||||
imIn->xsize != imOut->xsize ||
|
||||
if (strcmp(imIn->mode, imOut->mode) || imIn->type != imOut->type ||
|
||||
imIn->bands != imOut->bands || imIn->xsize != imOut->xsize ||
|
||||
imIn->ysize != imOut->ysize) {
|
||||
return ImagingError_Mismatch();
|
||||
}
|
||||
|
@ -257,14 +248,10 @@ ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n)
|
|||
return ImagingError_ModeError();
|
||||
}
|
||||
|
||||
if (!(strcmp(imIn->mode, "RGB") == 0 ||
|
||||
strcmp(imIn->mode, "RGBA") == 0 ||
|
||||
strcmp(imIn->mode, "RGBa") == 0 ||
|
||||
strcmp(imIn->mode, "RGBX") == 0 ||
|
||||
strcmp(imIn->mode, "CMYK") == 0 ||
|
||||
strcmp(imIn->mode, "L") == 0 ||
|
||||
strcmp(imIn->mode, "LA") == 0 ||
|
||||
strcmp(imIn->mode, "La") == 0)) {
|
||||
if (!(strcmp(imIn->mode, "RGB") == 0 || strcmp(imIn->mode, "RGBA") == 0 ||
|
||||
strcmp(imIn->mode, "RGBa") == 0 || strcmp(imIn->mode, "RGBX") == 0 ||
|
||||
strcmp(imIn->mode, "CMYK") == 0 || strcmp(imIn->mode, "L") == 0 ||
|
||||
strcmp(imIn->mode, "LA") == 0 || strcmp(imIn->mode, "La") == 0)) {
|
||||
return ImagingError_ModeError();
|
||||
}
|
||||
|
||||
|
@ -277,14 +264,14 @@ ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n)
|
|||
Use imOut as a destination at first pass,
|
||||
then use imOut as a source too. */
|
||||
ImagingHorizontalBoxBlur(imOut, imIn, radius);
|
||||
for (i = 1; i < n; i ++) {
|
||||
for (i = 1; i < n; i++) {
|
||||
ImagingHorizontalBoxBlur(imOut, imOut, radius);
|
||||
}
|
||||
/* Transpose result for blur in another direction. */
|
||||
ImagingTranspose(imTransposed, imOut);
|
||||
|
||||
/* Reuse imTransposed as a source and destination there. */
|
||||
for (i = 0; i < n; i ++) {
|
||||
for (i = 0; i < n; i++) {
|
||||
ImagingHorizontalBoxBlur(imTransposed, imTransposed, radius);
|
||||
}
|
||||
/* Restore original orientation. */
|
||||
|
@ -295,10 +282,8 @@ ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n)
|
|||
return imOut;
|
||||
}
|
||||
|
||||
|
||||
Imaging ImagingGaussianBlur(Imaging imOut, Imaging imIn, float radius,
|
||||
int passes)
|
||||
{
|
||||
Imaging
|
||||
ImagingGaussianBlur(Imaging imOut, Imaging imIn, float radius, int passes) {
|
||||
float sigma2, L, l, a;
|
||||
|
||||
sigma2 = radius * radius / passes;
|
||||
|
|
|
@ -16,62 +16,59 @@
|
|||
* See the README file for details on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#define CHOP(operation)\
|
||||
int x, y;\
|
||||
Imaging imOut;\
|
||||
imOut = create(imIn1, imIn2, NULL);\
|
||||
if (!imOut) {\
|
||||
return NULL;\
|
||||
}\
|
||||
for (y = 0; y < imOut->ysize; y++) {\
|
||||
UINT8* out = (UINT8*) imOut->image[y];\
|
||||
UINT8* in1 = (UINT8*) imIn1->image[y];\
|
||||
UINT8* in2 = (UINT8*) imIn2->image[y];\
|
||||
for (x = 0; x < imOut->linesize; x++) {\
|
||||
int temp = operation;\
|
||||
if (temp <= 0) {\
|
||||
out[x] = 0;\
|
||||
} else if (temp >= 255) {\
|
||||
out[x] = 255;\
|
||||
} else {\
|
||||
out[x] = temp;\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
#define CHOP(operation) \
|
||||
int x, y; \
|
||||
Imaging imOut; \
|
||||
imOut = create(imIn1, imIn2, NULL); \
|
||||
if (!imOut) { \
|
||||
return NULL; \
|
||||
} \
|
||||
for (y = 0; y < imOut->ysize; y++) { \
|
||||
UINT8 *out = (UINT8 *)imOut->image[y]; \
|
||||
UINT8 *in1 = (UINT8 *)imIn1->image[y]; \
|
||||
UINT8 *in2 = (UINT8 *)imIn2->image[y]; \
|
||||
for (x = 0; x < imOut->linesize; x++) { \
|
||||
int temp = operation; \
|
||||
if (temp <= 0) { \
|
||||
out[x] = 0; \
|
||||
} else if (temp >= 255) { \
|
||||
out[x] = 255; \
|
||||
} else { \
|
||||
out[x] = temp; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
return imOut;
|
||||
|
||||
#define CHOP2(operation, mode)\
|
||||
int x, y;\
|
||||
Imaging imOut;\
|
||||
imOut = create(imIn1, imIn2, mode);\
|
||||
if (!imOut) {\
|
||||
return NULL;\
|
||||
}\
|
||||
for (y = 0; y < imOut->ysize; y++) {\
|
||||
UINT8* out = (UINT8*) imOut->image[y];\
|
||||
UINT8* in1 = (UINT8*) imIn1->image[y];\
|
||||
UINT8* in2 = (UINT8*) imIn2->image[y];\
|
||||
for (x = 0; x < imOut->linesize; x++) {\
|
||||
out[x] = operation;\
|
||||
}\
|
||||
}\
|
||||
#define CHOP2(operation, mode) \
|
||||
int x, y; \
|
||||
Imaging imOut; \
|
||||
imOut = create(imIn1, imIn2, mode); \
|
||||
if (!imOut) { \
|
||||
return NULL; \
|
||||
} \
|
||||
for (y = 0; y < imOut->ysize; y++) { \
|
||||
UINT8 *out = (UINT8 *)imOut->image[y]; \
|
||||
UINT8 *in1 = (UINT8 *)imIn1->image[y]; \
|
||||
UINT8 *in2 = (UINT8 *)imIn2->image[y]; \
|
||||
for (x = 0; x < imOut->linesize; x++) { \
|
||||
out[x] = operation; \
|
||||
} \
|
||||
} \
|
||||
return imOut;
|
||||
|
||||
static Imaging
|
||||
create(Imaging im1, Imaging im2, char* mode)
|
||||
{
|
||||
create(Imaging im1, Imaging im2, char *mode) {
|
||||
int xsize, ysize;
|
||||
|
||||
if (!im1 || !im2 || im1->type != IMAGING_TYPE_UINT8 ||
|
||||
(mode != NULL && (strcmp(im1->mode, "1") || strcmp(im2->mode, "1")))) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
if (im1->type != im2->type ||
|
||||
im1->bands != im2->bands) {
|
||||
return (Imaging) ImagingError_Mismatch();
|
||||
if (im1->type != im2->type || im1->bands != im2->bands) {
|
||||
return (Imaging)ImagingError_Mismatch();
|
||||
}
|
||||
|
||||
xsize = (im1->xsize < im2->xsize) ? im1->xsize : im2->xsize;
|
||||
|
@ -81,97 +78,85 @@ create(Imaging im1, Imaging im2, char* mode)
|
|||
}
|
||||
|
||||
Imaging
|
||||
ImagingChopLighter(Imaging imIn1, Imaging imIn2)
|
||||
{
|
||||
ImagingChopLighter(Imaging imIn1, Imaging imIn2) {
|
||||
CHOP((in1[x] > in2[x]) ? in1[x] : in2[x]);
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingChopDarker(Imaging imIn1, Imaging imIn2)
|
||||
{
|
||||
ImagingChopDarker(Imaging imIn1, Imaging imIn2) {
|
||||
CHOP((in1[x] < in2[x]) ? in1[x] : in2[x]);
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingChopDifference(Imaging imIn1, Imaging imIn2)
|
||||
{
|
||||
CHOP(abs((int) in1[x] - (int) in2[x]));
|
||||
ImagingChopDifference(Imaging imIn1, Imaging imIn2) {
|
||||
CHOP(abs((int)in1[x] - (int)in2[x]));
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingChopMultiply(Imaging imIn1, Imaging imIn2)
|
||||
{
|
||||
CHOP((int) in1[x] * (int) in2[x] / 255);
|
||||
ImagingChopMultiply(Imaging imIn1, Imaging imIn2) {
|
||||
CHOP((int)in1[x] * (int)in2[x] / 255);
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingChopScreen(Imaging imIn1, Imaging imIn2)
|
||||
{
|
||||
CHOP(255 - ((int) (255 - in1[x]) * (int) (255 - in2[x])) / 255);
|
||||
ImagingChopScreen(Imaging imIn1, Imaging imIn2) {
|
||||
CHOP(255 - ((int)(255 - in1[x]) * (int)(255 - in2[x])) / 255);
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingChopAdd(Imaging imIn1, Imaging imIn2, float scale, int offset)
|
||||
{
|
||||
CHOP(((int) in1[x] + (int) in2[x]) / scale + offset);
|
||||
ImagingChopAdd(Imaging imIn1, Imaging imIn2, float scale, int offset) {
|
||||
CHOP(((int)in1[x] + (int)in2[x]) / scale + offset);
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingChopSubtract(Imaging imIn1, Imaging imIn2, float scale, int offset)
|
||||
{
|
||||
CHOP(((int) in1[x] - (int) in2[x]) / scale + offset);
|
||||
ImagingChopSubtract(Imaging imIn1, Imaging imIn2, float scale, int offset) {
|
||||
CHOP(((int)in1[x] - (int)in2[x]) / scale + offset);
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingChopAnd(Imaging imIn1, Imaging imIn2)
|
||||
{
|
||||
ImagingChopAnd(Imaging imIn1, Imaging imIn2) {
|
||||
CHOP2((in1[x] && in2[x]) ? 255 : 0, "1");
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingChopOr(Imaging imIn1, Imaging imIn2)
|
||||
{
|
||||
ImagingChopOr(Imaging imIn1, Imaging imIn2) {
|
||||
CHOP2((in1[x] || in2[x]) ? 255 : 0, "1");
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingChopXor(Imaging imIn1, Imaging imIn2)
|
||||
{
|
||||
ImagingChopXor(Imaging imIn1, Imaging imIn2) {
|
||||
CHOP2(((in1[x] != 0) ^ (in2[x] != 0)) ? 255 : 0, "1");
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingChopAddModulo(Imaging imIn1, Imaging imIn2)
|
||||
{
|
||||
ImagingChopAddModulo(Imaging imIn1, Imaging imIn2) {
|
||||
CHOP2(in1[x] + in2[x], NULL);
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingChopSubtractModulo(Imaging imIn1, Imaging imIn2)
|
||||
{
|
||||
ImagingChopSubtractModulo(Imaging imIn1, Imaging imIn2) {
|
||||
CHOP2(in1[x] - in2[x], NULL);
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingChopSoftLight(Imaging imIn1, Imaging imIn2)
|
||||
{
|
||||
CHOP2( (((255-in1[x]) * (in1[x]*in2[x]) ) / 65536) +
|
||||
(in1[x] * ( 255 - ( (255 - in1[x]) * (255 - in2[x] ) / 255) )) / 255
|
||||
, NULL );
|
||||
ImagingChopSoftLight(Imaging imIn1, Imaging imIn2) {
|
||||
CHOP2(
|
||||
(((255 - in1[x]) * (in1[x] * in2[x])) / 65536) +
|
||||
(in1[x] * (255 - ((255 - in1[x]) * (255 - in2[x]) / 255))) / 255,
|
||||
NULL);
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingChopHardLight(Imaging imIn1, Imaging imIn2)
|
||||
{
|
||||
CHOP2( (in2[x]<128) ? ( (in1[x]*in2[x])/127)
|
||||
: 255 - ( ((255-in2[x]) * (255-in1[x])) / 127)
|
||||
, NULL);
|
||||
ImagingChopHardLight(Imaging imIn1, Imaging imIn2) {
|
||||
CHOP2(
|
||||
(in2[x] < 128) ? ((in1[x] * in2[x]) / 127)
|
||||
: 255 - (((255 - in2[x]) * (255 - in1[x])) / 127),
|
||||
NULL);
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingOverlay(Imaging imIn1, Imaging imIn2)
|
||||
{
|
||||
CHOP2( (in1[x]<128) ? ( (in1[x]*in2[x])/127)
|
||||
: 255 - ( ((255-in1[x]) * (255-in2[x])) / 127)
|
||||
, NULL);
|
||||
ImagingOverlay(Imaging imIn1, Imaging imIn2) {
|
||||
CHOP2(
|
||||
(in1[x] < 128) ? ((in1[x] * in2[x]) / 127)
|
||||
: 255 - (((255 - in1[x]) * (255 - in2[x])) / 127),
|
||||
NULL);
|
||||
}
|
||||
|
|
|
@ -1,52 +1,45 @@
|
|||
#include "Imaging.h"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
/* 8 bits for result. Table can overflow [0, 1.0] range,
|
||||
so we need extra bits for overflow and negative values.
|
||||
NOTE: This value should be the same as in _imaging/_prepare_lut_table() */
|
||||
#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.
|
||||
6 — max index in the table
|
||||
(max size is 65, but index 64 is not reachable) */
|
||||
#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)
|
||||
|
||||
|
||||
static inline UINT8 clip8(int in)
|
||||
{
|
||||
static inline UINT8
|
||||
clip8(int in) {
|
||||
return clip8_lookups[(in + PRECISION_ROUNDING) >> PRECISION_BITS];
|
||||
}
|
||||
|
||||
static inline void
|
||||
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[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;
|
||||
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[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;
|
||||
}
|
||||
|
||||
static inline void
|
||||
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[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[3] = (a[3] * ((1<<SHIFT_BITS)-shift) + b[3] * shift) >> SHIFT_BITS;
|
||||
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[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[3] = (a[3] * ((1 << SHIFT_BITS) - shift) + b[3] * shift) >> SHIFT_BITS;
|
||||
}
|
||||
|
||||
static inline int
|
||||
table_index3D(int index1D, int index2D, int index3D,
|
||||
int size1D, int size1D_2D)
|
||||
{
|
||||
table_index3D(int index1D, int index2D, int index3D, int size1D, int size1D_2D) {
|
||||
return index1D + index2D * size1D + index3D * size1D_2D;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Transforms colors of imIn using provided 3D lookup table
|
||||
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.
|
||||
*/
|
||||
Imaging
|
||||
ImagingColorLUT3D_linear(Imaging imOut, Imaging imIn, int table_channels,
|
||||
int size1D, int size2D, int size3D,
|
||||
INT16* table)
|
||||
{
|
||||
ImagingColorLUT3D_linear(
|
||||
Imaging imOut,
|
||||
Imaging imIn,
|
||||
int table_channels,
|
||||
int size1D,
|
||||
int size2D,
|
||||
int size3D,
|
||||
INT16 *table) {
|
||||
/* This float to int conversion doesn't have rounding
|
||||
error compensation (+0.5) for two reasons:
|
||||
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.
|
||||
With this compensation we never hit the upper cells
|
||||
but this also doesn't introduce any noticeable difference. */
|
||||
UINT32 scale1D = (size1D - 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 scale1D = (size1D - 1) / 255.0 * (1 << SCALE_BITS);
|
||||
UINT32 scale2D = (size2D - 1) / 255.0 * (1 << SCALE_BITS);
|
||||
UINT32 scale3D = (size3D - 1) / 255.0 * (1 << SCALE_BITS);
|
||||
int size1D_2D = size1D * size2D;
|
||||
int x, y;
|
||||
ImagingSectionCookie cookie;
|
||||
|
@ -89,75 +86,97 @@ ImagingColorLUT3D_linear(Imaging imOut, Imaging imIn, int table_channels,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (imIn->type != IMAGING_TYPE_UINT8 ||
|
||||
imOut->type != IMAGING_TYPE_UINT8 ||
|
||||
imIn->bands < 3 ||
|
||||
imOut->bands < table_channels
|
||||
) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
if (imIn->type != IMAGING_TYPE_UINT8 || imOut->type != IMAGING_TYPE_UINT8 ||
|
||||
imIn->bands < 3 || imOut->bands < table_channels) {
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
/* In case we have one extra band in imOut and don't have in imIn.*/
|
||||
if (imOut->bands > table_channels && imOut->bands > imIn->bands) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
ImagingSectionEnter(&cookie);
|
||||
for (y = 0; y < imOut->ysize; y++) {
|
||||
UINT8* rowIn = (UINT8 *)imIn->image[y];
|
||||
char* rowOut = (char *)imOut->image[y];
|
||||
UINT8 *rowIn = (UINT8 *)imIn->image[y];
|
||||
char *rowOut = (char *)imOut->image[y];
|
||||
for (x = 0; x < imOut->xsize; x++) {
|
||||
UINT32 index1D = rowIn[x*4 + 0] * scale1D;
|
||||
UINT32 index2D = rowIn[x*4 + 1] * scale2D;
|
||||
UINT32 index3D = rowIn[x*4 + 2] * scale3D;
|
||||
UINT32 index1D = rowIn[x * 4 + 0] * scale1D;
|
||||
UINT32 index2D = rowIn[x * 4 + 1] * scale2D;
|
||||
UINT32 index3D = rowIn[x * 4 + 2] * scale3D;
|
||||
INT16 shift1D = (SCALE_MASK & index1D) >> (SCALE_BITS - SHIFT_BITS);
|
||||
INT16 shift2D = (SCALE_MASK & index2D) >> (SCALE_BITS - SHIFT_BITS);
|
||||
INT16 shift3D = (SCALE_MASK & index3D) >> (SCALE_BITS - SHIFT_BITS);
|
||||
int idx = table_channels * table_index3D(
|
||||
index1D >> SCALE_BITS, index2D >> SCALE_BITS,
|
||||
index3D >> SCALE_BITS, size1D, size1D_2D);
|
||||
index1D >> SCALE_BITS,
|
||||
index2D >> SCALE_BITS,
|
||||
index3D >> SCALE_BITS,
|
||||
size1D,
|
||||
size1D_2D);
|
||||
INT16 result[4], left[4], right[4];
|
||||
INT16 leftleft[4], leftright[4], rightleft[4], rightright[4];
|
||||
|
||||
if (table_channels == 3) {
|
||||
UINT32 v;
|
||||
interpolate3(leftleft, &table[idx + 0], &table[idx + 3], shift1D);
|
||||
interpolate3(leftright, &table[idx + size1D*3],
|
||||
&table[idx + size1D*3 + 3], shift1D);
|
||||
interpolate3(
|
||||
leftright,
|
||||
&table[idx + size1D * 3],
|
||||
&table[idx + size1D * 3 + 3],
|
||||
shift1D);
|
||||
interpolate3(left, leftleft, leftright, shift2D);
|
||||
|
||||
interpolate3(rightleft, &table[idx + size1D_2D*3],
|
||||
&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(
|
||||
rightleft,
|
||||
&table[idx + size1D_2D * 3],
|
||||
&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(result, left, right, shift3D);
|
||||
|
||||
v = MAKE_UINT32(
|
||||
clip8(result[0]), clip8(result[1]),
|
||||
clip8(result[2]), rowIn[x*4 + 3]);
|
||||
clip8(result[0]),
|
||||
clip8(result[1]),
|
||||
clip8(result[2]),
|
||||
rowIn[x * 4 + 3]);
|
||||
memcpy(rowOut + x * sizeof(v), &v, sizeof(v));
|
||||
}
|
||||
|
||||
if (table_channels == 4) {
|
||||
UINT32 v;
|
||||
interpolate4(leftleft, &table[idx + 0], &table[idx + 4], shift1D);
|
||||
interpolate4(leftright, &table[idx + size1D*4],
|
||||
&table[idx + size1D*4 + 4], shift1D);
|
||||
interpolate4(
|
||||
leftright,
|
||||
&table[idx + size1D * 4],
|
||||
&table[idx + size1D * 4 + 4],
|
||||
shift1D);
|
||||
interpolate4(left, leftleft, leftright, shift2D);
|
||||
|
||||
interpolate4(rightleft, &table[idx + size1D_2D*4],
|
||||
&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(
|
||||
rightleft,
|
||||
&table[idx + size1D_2D * 4],
|
||||
&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(result, left, right, shift3D);
|
||||
|
||||
v = MAKE_UINT32(
|
||||
clip8(result[0]), clip8(result[1]),
|
||||
clip8(result[2]), clip8(result[3]));
|
||||
clip8(result[0]),
|
||||
clip8(result[1]),
|
||||
clip8(result[2]),
|
||||
clip8(result[3]));
|
||||
memcpy(rowOut + x * sizeof(v), &v, sizeof(v));
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -28,356 +28,332 @@
|
|||
|
||||
#define SCALE 6 /* bits */
|
||||
|
||||
static INT16 Y_R[] = { 0, 19, 38, 57, 77, 96, 115, 134, 153, 172, 191,
|
||||
210, 230, 249, 268, 287, 306, 325, 344, 364, 383, 402, 421, 440, 459,
|
||||
478, 498, 517, 536, 555, 574, 593, 612, 631, 651, 670, 689, 708, 727,
|
||||
746, 765, 785, 804, 823, 842, 861, 880, 899, 919, 938, 957, 976, 995,
|
||||
1014, 1033, 1052, 1072, 1091, 1110, 1129, 1148, 1167, 1186, 1206,
|
||||
1225, 1244, 1263, 1282, 1301, 1320, 1340, 1359, 1378, 1397, 1416,
|
||||
1435, 1454, 1473, 1493, 1512, 1531, 1550, 1569, 1588, 1607, 1627,
|
||||
1646, 1665, 1684, 1703, 1722, 1741, 1761, 1780, 1799, 1818, 1837,
|
||||
1856, 1875, 1894, 1914, 1933, 1952, 1971, 1990, 2009, 2028, 2048,
|
||||
2067, 2086, 2105, 2124, 2143, 2162, 2182, 2201, 2220, 2239, 2258,
|
||||
2277, 2296, 2315, 2335, 2354, 2373, 2392, 2411, 2430, 2449, 2469,
|
||||
2488, 2507, 2526, 2545, 2564, 2583, 2602, 2622, 2641, 2660, 2679,
|
||||
2698, 2717, 2736, 2756, 2775, 2794, 2813, 2832, 2851, 2870, 2890,
|
||||
2909, 2928, 2947, 2966, 2985, 3004, 3023, 3043, 3062, 3081, 3100,
|
||||
3119, 3138, 3157, 3177, 3196, 3215, 3234, 3253, 3272, 3291, 3311,
|
||||
3330, 3349, 3368, 3387, 3406, 3425, 3444, 3464, 3483, 3502, 3521,
|
||||
3540, 3559, 3578, 3598, 3617, 3636, 3655, 3674, 3693, 3712, 3732,
|
||||
3751, 3770, 3789, 3808, 3827, 3846, 3865, 3885, 3904, 3923, 3942,
|
||||
3961, 3980, 3999, 4019, 4038, 4057, 4076, 4095, 4114, 4133, 4153,
|
||||
4172, 4191, 4210, 4229, 4248, 4267, 4286, 4306, 4325, 4344, 4363,
|
||||
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_R[] = {
|
||||
0, 19, 38, 57, 77, 96, 115, 134, 153, 172, 191, 210, 230, 249,
|
||||
268, 287, 306, 325, 344, 364, 383, 402, 421, 440, 459, 478, 498, 517,
|
||||
536, 555, 574, 593, 612, 631, 651, 670, 689, 708, 727, 746, 765, 785,
|
||||
804, 823, 842, 861, 880, 899, 919, 938, 957, 976, 995, 1014, 1033, 1052,
|
||||
1072, 1091, 1110, 1129, 1148, 1167, 1186, 1206, 1225, 1244, 1263, 1282, 1301, 1320,
|
||||
1340, 1359, 1378, 1397, 1416, 1435, 1454, 1473, 1493, 1512, 1531, 1550, 1569, 1588,
|
||||
1607, 1627, 1646, 1665, 1684, 1703, 1722, 1741, 1761, 1780, 1799, 1818, 1837, 1856,
|
||||
1875, 1894, 1914, 1933, 1952, 1971, 1990, 2009, 2028, 2048, 2067, 2086, 2105, 2124,
|
||||
2143, 2162, 2182, 2201, 2220, 2239, 2258, 2277, 2296, 2315, 2335, 2354, 2373, 2392,
|
||||
2411, 2430, 2449, 2469, 2488, 2507, 2526, 2545, 2564, 2583, 2602, 2622, 2641, 2660,
|
||||
2679, 2698, 2717, 2736, 2756, 2775, 2794, 2813, 2832, 2851, 2870, 2890, 2909, 2928,
|
||||
2947, 2966, 2985, 3004, 3023, 3043, 3062, 3081, 3100, 3119, 3138, 3157, 3177, 3196,
|
||||
3215, 3234, 3253, 3272, 3291, 3311, 3330, 3349, 3368, 3387, 3406, 3425, 3444, 3464,
|
||||
3483, 3502, 3521, 3540, 3559, 3578, 3598, 3617, 3636, 3655, 3674, 3693, 3712, 3732,
|
||||
3751, 3770, 3789, 3808, 3827, 3846, 3865, 3885, 3904, 3923, 3942, 3961, 3980, 3999,
|
||||
4019, 4038, 4057, 4076, 4095, 4114, 4133, 4153, 4172, 4191, 4210, 4229, 4248, 4267,
|
||||
4286, 4306, 4325, 4344, 4363, 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,
|
||||
376, 413, 451, 488, 526, 564, 601, 639, 676, 714, 751, 789, 826, 864,
|
||||
902, 939, 977, 1014, 1052, 1089, 1127, 1165, 1202, 1240, 1277, 1315,
|
||||
1352, 1390, 1428, 1465, 1503, 1540, 1578, 1615, 1653, 1691, 1728,
|
||||
1766, 1803, 1841, 1878, 1916, 1954, 1991, 2029, 2066, 2104, 2141,
|
||||
2179, 2217, 2254, 2292, 2329, 2367, 2404, 2442, 2479, 2517, 2555,
|
||||
2592, 2630, 2667, 2705, 2742, 2780, 2818, 2855, 2893, 2930, 2968,
|
||||
3005, 3043, 3081, 3118, 3156, 3193, 3231, 3268, 3306, 3344, 3381,
|
||||
3419, 3456, 3494, 3531, 3569, 3607, 3644, 3682, 3719, 3757, 3794,
|
||||
3832, 3870, 3907, 3945, 3982, 4020, 4057, 4095, 4132, 4170, 4208,
|
||||
4245, 4283, 4320, 4358, 4395, 4433, 4471, 4508, 4546, 4583, 4621,
|
||||
4658, 4696, 4734, 4771, 4809, 4846, 4884, 4921, 4959, 4997, 5034,
|
||||
5072, 5109, 5147, 5184, 5222, 5260, 5297, 5335, 5372, 5410, 5447,
|
||||
5485, 5522, 5560, 5598, 5635, 5673, 5710, 5748, 5785, 5823, 5861,
|
||||
5898, 5936, 5973, 6011, 6048, 6086, 6124, 6161, 6199, 6236, 6274,
|
||||
6311, 6349, 6387, 6424, 6462, 6499, 6537, 6574, 6612, 6650, 6687,
|
||||
6725, 6762, 6800, 6837, 6875, 6913, 6950, 6988, 7025, 7063, 7100,
|
||||
7138, 7175, 7213, 7251, 7288, 7326, 7363, 7401, 7438, 7476, 7514,
|
||||
7551, 7589, 7626, 7664, 7701, 7739, 7777, 7814, 7852, 7889, 7927,
|
||||
7964, 8002, 8040, 8077, 8115, 8152, 8190, 8227, 8265, 8303, 8340,
|
||||
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_G[] = {
|
||||
0, 38, 75, 113, 150, 188, 225, 263, 301, 338, 376, 413, 451, 488,
|
||||
526, 564, 601, 639, 676, 714, 751, 789, 826, 864, 902, 939, 977, 1014,
|
||||
1052, 1089, 1127, 1165, 1202, 1240, 1277, 1315, 1352, 1390, 1428, 1465, 1503, 1540,
|
||||
1578, 1615, 1653, 1691, 1728, 1766, 1803, 1841, 1878, 1916, 1954, 1991, 2029, 2066,
|
||||
2104, 2141, 2179, 2217, 2254, 2292, 2329, 2367, 2404, 2442, 2479, 2517, 2555, 2592,
|
||||
2630, 2667, 2705, 2742, 2780, 2818, 2855, 2893, 2930, 2968, 3005, 3043, 3081, 3118,
|
||||
3156, 3193, 3231, 3268, 3306, 3344, 3381, 3419, 3456, 3494, 3531, 3569, 3607, 3644,
|
||||
3682, 3719, 3757, 3794, 3832, 3870, 3907, 3945, 3982, 4020, 4057, 4095, 4132, 4170,
|
||||
4208, 4245, 4283, 4320, 4358, 4395, 4433, 4471, 4508, 4546, 4583, 4621, 4658, 4696,
|
||||
4734, 4771, 4809, 4846, 4884, 4921, 4959, 4997, 5034, 5072, 5109, 5147, 5184, 5222,
|
||||
5260, 5297, 5335, 5372, 5410, 5447, 5485, 5522, 5560, 5598, 5635, 5673, 5710, 5748,
|
||||
5785, 5823, 5861, 5898, 5936, 5973, 6011, 6048, 6086, 6124, 6161, 6199, 6236, 6274,
|
||||
6311, 6349, 6387, 6424, 6462, 6499, 6537, 6574, 6612, 6650, 6687, 6725, 6762, 6800,
|
||||
6837, 6875, 6913, 6950, 6988, 7025, 7063, 7100, 7138, 7175, 7213, 7251, 7288, 7326,
|
||||
7363, 7401, 7438, 7476, 7514, 7551, 7589, 7626, 7664, 7701, 7739, 7777, 7814, 7852,
|
||||
7889, 7927, 7964, 8002, 8040, 8077, 8115, 8152, 8190, 8227, 8265, 8303, 8340, 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,
|
||||
88, 95, 102, 109, 117, 124, 131, 139, 146, 153, 161, 168, 175, 182,
|
||||
190, 197, 204, 212, 219, 226, 233, 241, 248, 255, 263, 270, 277, 285,
|
||||
292, 299, 306, 314, 321, 328, 336, 343, 350, 358, 365, 372, 379, 387,
|
||||
394, 401, 409, 416, 423, 430, 438, 445, 452, 460, 467, 474, 482, 489,
|
||||
496, 503, 511, 518, 525, 533, 540, 547, 554, 562, 569, 576, 584, 591,
|
||||
598, 606, 613, 620, 627, 635, 642, 649, 657, 664, 671, 679, 686, 693,
|
||||
700, 708, 715, 722, 730, 737, 744, 751, 759, 766, 773, 781, 788, 795,
|
||||
803, 810, 817, 824, 832, 839, 846, 854, 861, 868, 876, 883, 890, 897,
|
||||
905, 912, 919, 927, 934, 941, 948, 956, 963, 970, 978, 985, 992, 1000,
|
||||
1007, 1014, 1021, 1029, 1036, 1043, 1051, 1058, 1065, 1073, 1080,
|
||||
1087, 1094, 1102, 1109, 1116, 1124, 1131, 1138, 1145, 1153, 1160,
|
||||
1167, 1175, 1182, 1189, 1197, 1204, 1211, 1218, 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,
|
||||
1408, 1415, 1423, 1430, 1437, 1445, 1452, 1459, 1466, 1474, 1481,
|
||||
1488, 1496, 1503, 1510, 1518, 1525, 1532, 1539, 1547, 1554, 1561,
|
||||
1569, 1576, 1583, 1591, 1598, 1605, 1612, 1620, 1627, 1634, 1642,
|
||||
1649, 1656, 1663, 1671, 1678, 1685, 1693, 1700, 1707, 1715, 1722,
|
||||
1729, 1736, 1744, 1751, 1758, 1766, 1773, 1780, 1788, 1795, 1802,
|
||||
1809, 1817, 1824, 1831, 1839, 1846, 1853, 1860 };
|
||||
static INT16 Y_B[] = {
|
||||
0, 7, 15, 22, 29, 36, 44, 51, 58, 66, 73, 80, 88, 95,
|
||||
102, 109, 117, 124, 131, 139, 146, 153, 161, 168, 175, 182, 190, 197,
|
||||
204, 212, 219, 226, 233, 241, 248, 255, 263, 270, 277, 285, 292, 299,
|
||||
306, 314, 321, 328, 336, 343, 350, 358, 365, 372, 379, 387, 394, 401,
|
||||
409, 416, 423, 430, 438, 445, 452, 460, 467, 474, 482, 489, 496, 503,
|
||||
511, 518, 525, 533, 540, 547, 554, 562, 569, 576, 584, 591, 598, 606,
|
||||
613, 620, 627, 635, 642, 649, 657, 664, 671, 679, 686, 693, 700, 708,
|
||||
715, 722, 730, 737, 744, 751, 759, 766, 773, 781, 788, 795, 803, 810,
|
||||
817, 824, 832, 839, 846, 854, 861, 868, 876, 883, 890, 897, 905, 912,
|
||||
919, 927, 934, 941, 948, 956, 963, 970, 978, 985, 992, 1000, 1007, 1014,
|
||||
1021, 1029, 1036, 1043, 1051, 1058, 1065, 1073, 1080, 1087, 1094, 1102, 1109, 1116,
|
||||
1124, 1131, 1138, 1145, 1153, 1160, 1167, 1175, 1182, 1189, 1197, 1204, 1211, 1218,
|
||||
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, 1408, 1415, 1423,
|
||||
1430, 1437, 1445, 1452, 1459, 1466, 1474, 1481, 1488, 1496, 1503, 1510, 1518, 1525,
|
||||
1532, 1539, 1547, 1554, 1561, 1569, 1576, 1583, 1591, 1598, 1605, 1612, 1620, 1627,
|
||||
1634, 1642, 1649, 1656, 1663, 1671, 1678, 1685, 1693, 1700, 1707, 1715, 1722, 1729,
|
||||
1736, 1744, 1751, 1758, 1766, 1773, 1780, 1788, 1795, 1802, 1809, 1817, 1824, 1831,
|
||||
1839, 1846, 1853, 1860};
|
||||
|
||||
static INT16 Cb_R[] = { 0, -10, -21, -31, -42, -53, -64, -75, -85,
|
||||
-96, -107, -118, -129, -139, -150, -161, -172, -183, -193, -204, -215,
|
||||
-226, -237, -247, -258, -269, -280, -291, -301, -312, -323, -334,
|
||||
-345, -355, -366, -377, -388, -399, -409, -420, -431, -442, -453,
|
||||
-463, -474, -485, -496, -507, -517, -528, -539, -550, -561, -571,
|
||||
-582, -593, -604, -615, -625, -636, -647, -658, -669, -679, -690,
|
||||
-701, -712, -723, -733, -744, -755, -766, -777, -787, -798, -809,
|
||||
-820, -831, -841, -852, -863, -874, -885, -895, -906, -917, -928,
|
||||
-939, -949, -960, -971, -982, -993, -1003, -1014, -1025, -1036, -1047,
|
||||
-1057, -1068, -1079, -1090, -1101, -1111, -1122, -1133, -1144, -1155,
|
||||
-1165, -1176, -1187, -1198, -1209, -1219, -1230, -1241, -1252, -1263,
|
||||
-1273, -1284, -1295, -1306, -1317, -1327, -1338, -1349, -1360, -1371,
|
||||
-1381, -1392, -1403, -1414, -1425, -1435, -1446, -1457, -1468, -1479,
|
||||
-1489, -1500, -1511, -1522, -1533, -1543, -1554, -1565, -1576, -1587,
|
||||
-1597, -1608, -1619, -1630, -1641, -1651, -1662, -1673, -1684, -1694,
|
||||
-1705, -1716, -1727, -1738, -1748, -1759, -1770, -1781, -1792, -1802,
|
||||
-1813, -1824, -1835, -1846, -1856, -1867, -1878, -1889, -1900, -1910,
|
||||
-1921, -1932, -1943, -1954, -1964, -1975, -1986, -1997, -2008, -2018,
|
||||
-2029, -2040, -2051, -2062, -2072, -2083, -2094, -2105, -2116, -2126,
|
||||
-2137, -2148, -2159, -2170, -2180, -2191, -2202, -2213, -2224, -2234,
|
||||
-2245, -2256, -2267, -2278, -2288, -2299, -2310, -2321, -2332, -2342,
|
||||
-2353, -2364, -2375, -2386, -2396, -2407, -2418, -2429, -2440, -2450,
|
||||
-2461, -2472, -2483, -2494, -2504, -2515, -2526, -2537, -2548, -2558,
|
||||
-2569, -2580, -2591, -2602, -2612, -2623, -2634, -2645, -2656, -2666,
|
||||
-2677, -2688, -2699, -2710, -2720, -2731, -2742, -2753 };
|
||||
static INT16 Cb_R[] = {
|
||||
0, -10, -21, -31, -42, -53, -64, -75, -85, -96, -107, -118,
|
||||
-129, -139, -150, -161, -172, -183, -193, -204, -215, -226, -237, -247,
|
||||
-258, -269, -280, -291, -301, -312, -323, -334, -345, -355, -366, -377,
|
||||
-388, -399, -409, -420, -431, -442, -453, -463, -474, -485, -496, -507,
|
||||
-517, -528, -539, -550, -561, -571, -582, -593, -604, -615, -625, -636,
|
||||
-647, -658, -669, -679, -690, -701, -712, -723, -733, -744, -755, -766,
|
||||
-777, -787, -798, -809, -820, -831, -841, -852, -863, -874, -885, -895,
|
||||
-906, -917, -928, -939, -949, -960, -971, -982, -993, -1003, -1014, -1025,
|
||||
-1036, -1047, -1057, -1068, -1079, -1090, -1101, -1111, -1122, -1133, -1144, -1155,
|
||||
-1165, -1176, -1187, -1198, -1209, -1219, -1230, -1241, -1252, -1263, -1273, -1284,
|
||||
-1295, -1306, -1317, -1327, -1338, -1349, -1360, -1371, -1381, -1392, -1403, -1414,
|
||||
-1425, -1435, -1446, -1457, -1468, -1479, -1489, -1500, -1511, -1522, -1533, -1543,
|
||||
-1554, -1565, -1576, -1587, -1597, -1608, -1619, -1630, -1641, -1651, -1662, -1673,
|
||||
-1684, -1694, -1705, -1716, -1727, -1738, -1748, -1759, -1770, -1781, -1792, -1802,
|
||||
-1813, -1824, -1835, -1846, -1856, -1867, -1878, -1889, -1900, -1910, -1921, -1932,
|
||||
-1943, -1954, -1964, -1975, -1986, -1997, -2008, -2018, -2029, -2040, -2051, -2062,
|
||||
-2072, -2083, -2094, -2105, -2116, -2126, -2137, -2148, -2159, -2170, -2180, -2191,
|
||||
-2202, -2213, -2224, -2234, -2245, -2256, -2267, -2278, -2288, -2299, -2310, -2321,
|
||||
-2332, -2342, -2353, -2364, -2375, -2386, -2396, -2407, -2418, -2429, -2440, -2450,
|
||||
-2461, -2472, -2483, -2494, -2504, -2515, -2526, -2537, -2548, -2558, -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,
|
||||
-190, -211, -232, -253, -275, -296, -317, -338, -359, -381, -402,
|
||||
-423, -444, -465, -487, -508, -529, -550, -571, -593, -614, -635,
|
||||
-656, -677, -699, -720, -741, -762, -783, -805, -826, -847, -868,
|
||||
-889, -911, -932, -953, -974, -995, -1017, -1038, -1059, -1080, -1101,
|
||||
-1123, -1144, -1165, -1186, -1207, -1229, -1250, -1271, -1292, -1313,
|
||||
-1335, -1356, -1377, -1398, -1419, -1441, -1462, -1483, -1504, -1525,
|
||||
-1547, -1568, -1589, -1610, -1631, -1653, -1674, -1695, -1716, -1737,
|
||||
-1759, -1780, -1801, -1822, -1843, -1865, -1886, -1907, -1928, -1949,
|
||||
-1971, -1992, -2013, -2034, -2055, -2077, -2098, -2119, -2140, -2161,
|
||||
-2183, -2204, -2225, -2246, -2267, -2289, -2310, -2331, -2352, -2373,
|
||||
-2395, -2416, -2437, -2458, -2479, -2501, -2522, -2543, -2564, -2585,
|
||||
-2607, -2628, -2649, -2670, -2691, -2713, -2734, -2755, -2776, -2797,
|
||||
-2819, -2840, -2861, -2882, -2903, -2925, -2946, -2967, -2988, -3009,
|
||||
-3031, -3052, -3073, -3094, -3115, -3137, -3158, -3179, -3200, -3221,
|
||||
-3243, -3264, -3285, -3306, -3328, -3349, -3370, -3391, -3412, -3434,
|
||||
-3455, -3476, -3497, -3518, -3540, -3561, -3582, -3603, -3624, -3646,
|
||||
-3667, -3688, -3709, -3730, -3752, -3773, -3794, -3815, -3836, -3858,
|
||||
-3879, -3900, -3921, -3942, -3964, -3985, -4006, -4027, -4048, -4070,
|
||||
-4091, -4112, -4133, -4154, -4176, -4197, -4218, -4239, -4260, -4282,
|
||||
-4303, -4324, -4345, -4366, -4388, -4409, -4430, -4451, -4472, -4494,
|
||||
-4515, -4536, -4557, -4578, -4600, -4621, -4642, -4663, -4684, -4706,
|
||||
-4727, -4748, -4769, -4790, -4812, -4833, -4854, -4875, -4896, -4918,
|
||||
-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_G[] = {
|
||||
0, -20, -41, -63, -84, -105, -126, -147, -169, -190, -211, -232,
|
||||
-253, -275, -296, -317, -338, -359, -381, -402, -423, -444, -465, -487,
|
||||
-508, -529, -550, -571, -593, -614, -635, -656, -677, -699, -720, -741,
|
||||
-762, -783, -805, -826, -847, -868, -889, -911, -932, -953, -974, -995,
|
||||
-1017, -1038, -1059, -1080, -1101, -1123, -1144, -1165, -1186, -1207, -1229, -1250,
|
||||
-1271, -1292, -1313, -1335, -1356, -1377, -1398, -1419, -1441, -1462, -1483, -1504,
|
||||
-1525, -1547, -1568, -1589, -1610, -1631, -1653, -1674, -1695, -1716, -1737, -1759,
|
||||
-1780, -1801, -1822, -1843, -1865, -1886, -1907, -1928, -1949, -1971, -1992, -2013,
|
||||
-2034, -2055, -2077, -2098, -2119, -2140, -2161, -2183, -2204, -2225, -2246, -2267,
|
||||
-2289, -2310, -2331, -2352, -2373, -2395, -2416, -2437, -2458, -2479, -2501, -2522,
|
||||
-2543, -2564, -2585, -2607, -2628, -2649, -2670, -2691, -2713, -2734, -2755, -2776,
|
||||
-2797, -2819, -2840, -2861, -2882, -2903, -2925, -2946, -2967, -2988, -3009, -3031,
|
||||
-3052, -3073, -3094, -3115, -3137, -3158, -3179, -3200, -3221, -3243, -3264, -3285,
|
||||
-3306, -3328, -3349, -3370, -3391, -3412, -3434, -3455, -3476, -3497, -3518, -3540,
|
||||
-3561, -3582, -3603, -3624, -3646, -3667, -3688, -3709, -3730, -3752, -3773, -3794,
|
||||
-3815, -3836, -3858, -3879, -3900, -3921, -3942, -3964, -3985, -4006, -4027, -4048,
|
||||
-4070, -4091, -4112, -4133, -4154, -4176, -4197, -4218, -4239, -4260, -4282, -4303,
|
||||
-4324, -4345, -4366, -4388, -4409, -4430, -4451, -4472, -4494, -4515, -4536, -4557,
|
||||
-4578, -4600, -4621, -4642, -4663, -4684, -4706, -4727, -4748, -4769, -4790, -4812,
|
||||
-4833, -4854, -4875, -4896, -4918, -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,
|
||||
320, 352, 384, 416, 448, 480, 512, 544, 576, 608, 640, 672, 704, 736,
|
||||
768, 800, 832, 864, 896, 928, 960, 992, 1024, 1056, 1088, 1120, 1152,
|
||||
1184, 1216, 1248, 1280, 1312, 1344, 1376, 1408, 1440, 1472, 1504,
|
||||
1536, 1568, 1600, 1632, 1664, 1696, 1728, 1760, 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,
|
||||
2592, 2624, 2656, 2688, 2720, 2752, 2784, 2816, 2848, 2880, 2912,
|
||||
2944, 2976, 3008, 3040, 3072, 3104, 3136, 3168, 3200, 3232, 3264,
|
||||
3296, 3328, 3360, 3392, 3424, 3456, 3488, 3520, 3552, 3584, 3616,
|
||||
3648, 3680, 3712, 3744, 3776, 3808, 3840, 3872, 3904, 3936, 3968,
|
||||
4000, 4032, 4064, 4096, 4128, 4160, 4192, 4224, 4256, 4288, 4320,
|
||||
4352, 4384, 4416, 4448, 4480, 4512, 4544, 4576, 4608, 4640, 4672,
|
||||
4704, 4736, 4768, 4800, 4832, 4864, 4896, 4928, 4960, 4992, 5024,
|
||||
5056, 5088, 5120, 5152, 5184, 5216, 5248, 5280, 5312, 5344, 5376,
|
||||
5408, 5440, 5472, 5504, 5536, 5568, 5600, 5632, 5664, 5696, 5728,
|
||||
5760, 5792, 5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080,
|
||||
6112, 6144, 6176, 6208, 6240, 6272, 6304, 6336, 6368, 6400, 6432,
|
||||
6464, 6496, 6528, 6560, 6592, 6624, 6656, 6688, 6720, 6752, 6784,
|
||||
6816, 6848, 6880, 6912, 6944, 6976, 7008, 7040, 7072, 7104, 7136,
|
||||
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 };
|
||||
static INT16 Cb_B[] = {
|
||||
0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416,
|
||||
448, 480, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864,
|
||||
896, 928, 960, 992, 1024, 1056, 1088, 1120, 1152, 1184, 1216, 1248, 1280, 1312,
|
||||
1344, 1376, 1408, 1440, 1472, 1504, 1536, 1568, 1600, 1632, 1664, 1696, 1728, 1760,
|
||||
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, 2592, 2624, 2656,
|
||||
2688, 2720, 2752, 2784, 2816, 2848, 2880, 2912, 2944, 2976, 3008, 3040, 3072, 3104,
|
||||
3136, 3168, 3200, 3232, 3264, 3296, 3328, 3360, 3392, 3424, 3456, 3488, 3520, 3552,
|
||||
3584, 3616, 3648, 3680, 3712, 3744, 3776, 3808, 3840, 3872, 3904, 3936, 3968, 4000,
|
||||
4032, 4064, 4096, 4128, 4160, 4192, 4224, 4256, 4288, 4320, 4352, 4384, 4416, 4448,
|
||||
4480, 4512, 4544, 4576, 4608, 4640, 4672, 4704, 4736, 4768, 4800, 4832, 4864, 4896,
|
||||
4928, 4960, 4992, 5024, 5056, 5088, 5120, 5152, 5184, 5216, 5248, 5280, 5312, 5344,
|
||||
5376, 5408, 5440, 5472, 5504, 5536, 5568, 5600, 5632, 5664, 5696, 5728, 5760, 5792,
|
||||
5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080, 6112, 6144, 6176, 6208, 6240,
|
||||
6272, 6304, 6336, 6368, 6400, 6432, 6464, 6496, 6528, 6560, 6592, 6624, 6656, 6688,
|
||||
6720, 6752, 6784, 6816, 6848, 6880, 6912, 6944, 6976, 7008, 7040, 7072, 7104, 7136,
|
||||
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
|
||||
|
||||
static INT16 Cr_G[] = { 0, -26, -53, -79, -106, -133, -160, -187,
|
||||
-213, -240, -267, -294, -321, -347, -374, -401, -428, -455, -481,
|
||||
-508, -535, -562, -589, -615, -642, -669, -696, -722, -749, -776,
|
||||
-803, -830, -856, -883, -910, -937, -964, -990, -1017, -1044, -1071,
|
||||
-1098, -1124, -1151, -1178, -1205, -1232, -1258, -1285, -1312, -1339,
|
||||
-1366, -1392, -1419, -1446, -1473, -1500, -1526, -1553, -1580, -1607,
|
||||
-1634, -1660, -1687, -1714, -1741, -1768, -1794, -1821, -1848, -1875,
|
||||
-1902, -1928, -1955, -1982, -2009, -2036, -2062, -2089, -2116, -2143,
|
||||
-2169, -2196, -2223, -2250, -2277, -2303, -2330, -2357, -2384, -2411,
|
||||
-2437, -2464, -2491, -2518, -2545, -2571, -2598, -2625, -2652, -2679,
|
||||
-2705, -2732, -2759, -2786, -2813, -2839, -2866, -2893, -2920, -2947,
|
||||
-2973, -3000, -3027, -3054, -3081, -3107, -3134, -3161, -3188, -3215,
|
||||
-3241, -3268, -3295, -3322, -3349, -3375, -3402, -3429, -3456, -3483,
|
||||
-3509, -3536, -3563, -3590, -3616, -3643, -3670, -3697, -3724, -3750,
|
||||
-3777, -3804, -3831, -3858, -3884, -3911, -3938, -3965, -3992, -4018,
|
||||
-4045, -4072, -4099, -4126, -4152, -4179, -4206, -4233, -4260, -4286,
|
||||
-4313, -4340, -4367, -4394, -4420, -4447, -4474, -4501, -4528, -4554,
|
||||
-4581, -4608, -4635, -4662, -4688, -4715, -4742, -4769, -4796, -4822,
|
||||
-4849, -4876, -4903, -4929, -4956, -4983, -5010, -5037, -5063, -5090,
|
||||
-5117, -5144, -5171, -5197, -5224, -5251, -5278, -5305, -5331, -5358,
|
||||
-5385, -5412, -5439, -5465, -5492, -5519, -5546, -5573, -5599, -5626,
|
||||
-5653, -5680, -5707, -5733, -5760, -5787, -5814, -5841, -5867, -5894,
|
||||
-5921, -5948, -5975, -6001, -6028, -6055, -6082, -6109, -6135, -6162,
|
||||
-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_G[] = {
|
||||
0, -26, -53, -79, -106, -133, -160, -187, -213, -240, -267, -294,
|
||||
-321, -347, -374, -401, -428, -455, -481, -508, -535, -562, -589, -615,
|
||||
-642, -669, -696, -722, -749, -776, -803, -830, -856, -883, -910, -937,
|
||||
-964, -990, -1017, -1044, -1071, -1098, -1124, -1151, -1178, -1205, -1232, -1258,
|
||||
-1285, -1312, -1339, -1366, -1392, -1419, -1446, -1473, -1500, -1526, -1553, -1580,
|
||||
-1607, -1634, -1660, -1687, -1714, -1741, -1768, -1794, -1821, -1848, -1875, -1902,
|
||||
-1928, -1955, -1982, -2009, -2036, -2062, -2089, -2116, -2143, -2169, -2196, -2223,
|
||||
-2250, -2277, -2303, -2330, -2357, -2384, -2411, -2437, -2464, -2491, -2518, -2545,
|
||||
-2571, -2598, -2625, -2652, -2679, -2705, -2732, -2759, -2786, -2813, -2839, -2866,
|
||||
-2893, -2920, -2947, -2973, -3000, -3027, -3054, -3081, -3107, -3134, -3161, -3188,
|
||||
-3215, -3241, -3268, -3295, -3322, -3349, -3375, -3402, -3429, -3456, -3483, -3509,
|
||||
-3536, -3563, -3590, -3616, -3643, -3670, -3697, -3724, -3750, -3777, -3804, -3831,
|
||||
-3858, -3884, -3911, -3938, -3965, -3992, -4018, -4045, -4072, -4099, -4126, -4152,
|
||||
-4179, -4206, -4233, -4260, -4286, -4313, -4340, -4367, -4394, -4420, -4447, -4474,
|
||||
-4501, -4528, -4554, -4581, -4608, -4635, -4662, -4688, -4715, -4742, -4769, -4796,
|
||||
-4822, -4849, -4876, -4903, -4929, -4956, -4983, -5010, -5037, -5063, -5090, -5117,
|
||||
-5144, -5171, -5197, -5224, -5251, -5278, -5305, -5331, -5358, -5385, -5412, -5439,
|
||||
-5465, -5492, -5519, -5546, -5573, -5599, -5626, -5653, -5680, -5707, -5733, -5760,
|
||||
-5787, -5814, -5841, -5867, -5894, -5921, -5948, -5975, -6001, -6028, -6055, -6082,
|
||||
-6109, -6135, -6162, -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,
|
||||
-51, -56, -61, -67, -72, -77, -82, -87, -93, -98, -103, -108, -113,
|
||||
-119, -124, -129, -134, -140, -145, -150, -155, -160, -166, -171,
|
||||
-176, -181, -186, -192, -197, -202, -207, -212, -218, -223, -228,
|
||||
-233, -238, -244, -249, -254, -259, -264, -270, -275, -280, -285,
|
||||
-290, -296, -301, -306, -311, -316, -322, -327, -332, -337, -342,
|
||||
-348, -353, -358, -363, -368, -374, -379, -384, -389, -394, -400,
|
||||
-405, -410, -415, -421, -426, -431, -436, -441, -447, -452, -457,
|
||||
-462, -467, -473, -478, -483, -488, -493, -499, -504, -509, -514,
|
||||
-519, -525, -530, -535, -540, -545, -551, -556, -561, -566, -571,
|
||||
-577, -582, -587, -592, -597, -603, -608, -613, -618, -623, -629,
|
||||
-634, -639, -644, -649, -655, -660, -665, -670, -675, -681, -686,
|
||||
-691, -696, -702, -707, -712, -717, -722, -728, -733, -738, -743,
|
||||
-748, -754, -759, -764, -769, -774, -780, -785, -790, -795, -800,
|
||||
-806, -811, -816, -821, -826, -832, -837, -842, -847, -852, -858,
|
||||
-863, -868, -873, -878, -884, -889, -894, -899, -904, -910, -915,
|
||||
-920, -925, -930, -936, -941, -946, -951, -957, -962, -967, -972,
|
||||
-977, -983, -988, -993, -998, -1003, -1009, -1014, -1019, -1024,
|
||||
-1029, -1035, -1040, -1045, -1050, -1055, -1061, -1066, -1071, -1076,
|
||||
-1081, -1087, -1092, -1097, -1102, -1107, -1113, -1118, -1123, -1128,
|
||||
-1133, -1139, -1144, -1149, -1154, -1159, -1165, -1170, -1175, -1180,
|
||||
-1185, -1191, -1196, -1201, -1206, -1211, -1217, -1222, -1227, -1232,
|
||||
-1238, -1243, -1248, -1253, -1258, -1264, -1269, -1274, -1279, -1284,
|
||||
-1290, -1295, -1300, -1305, -1310, -1316, -1321, -1326 };
|
||||
static INT16 Cr_B[] = {
|
||||
0, -4, -9, -15, -20, -25, -30, -35, -41, -46, -51, -56,
|
||||
-61, -67, -72, -77, -82, -87, -93, -98, -103, -108, -113, -119,
|
||||
-124, -129, -134, -140, -145, -150, -155, -160, -166, -171, -176, -181,
|
||||
-186, -192, -197, -202, -207, -212, -218, -223, -228, -233, -238, -244,
|
||||
-249, -254, -259, -264, -270, -275, -280, -285, -290, -296, -301, -306,
|
||||
-311, -316, -322, -327, -332, -337, -342, -348, -353, -358, -363, -368,
|
||||
-374, -379, -384, -389, -394, -400, -405, -410, -415, -421, -426, -431,
|
||||
-436, -441, -447, -452, -457, -462, -467, -473, -478, -483, -488, -493,
|
||||
-499, -504, -509, -514, -519, -525, -530, -535, -540, -545, -551, -556,
|
||||
-561, -566, -571, -577, -582, -587, -592, -597, -603, -608, -613, -618,
|
||||
-623, -629, -634, -639, -644, -649, -655, -660, -665, -670, -675, -681,
|
||||
-686, -691, -696, -702, -707, -712, -717, -722, -728, -733, -738, -743,
|
||||
-748, -754, -759, -764, -769, -774, -780, -785, -790, -795, -800, -806,
|
||||
-811, -816, -821, -826, -832, -837, -842, -847, -852, -858, -863, -868,
|
||||
-873, -878, -884, -889, -894, -899, -904, -910, -915, -920, -925, -930,
|
||||
-936, -941, -946, -951, -957, -962, -967, -972, -977, -983, -988, -993,
|
||||
-998, -1003, -1009, -1014, -1019, -1024, -1029, -1035, -1040, -1045, -1050, -1055,
|
||||
-1061, -1066, -1071, -1076, -1081, -1087, -1092, -1097, -1102, -1107, -1113, -1118,
|
||||
-1123, -1128, -1133, -1139, -1144, -1149, -1154, -1159, -1165, -1170, -1175, -1180,
|
||||
-1185, -1191, -1196, -1201, -1206, -1211, -1217, -1222, -1227, -1232, -1238, -1243,
|
||||
-1248, -1253, -1258, -1264, -1269, -1274, -1279, -1284, -1290, -1295, -1300, -1305,
|
||||
-1310, -1316, -1321, -1326};
|
||||
|
||||
static INT16 R_Cr[] = { -11484, -11394, -11305, -11215, -11125,
|
||||
-11036, -10946, -10856, -10766, -10677, -10587, -10497, -10407,
|
||||
-10318, -10228, -10138, -10049, -9959, -9869, -9779, -9690, -9600,
|
||||
-9510, -9420, -9331, -9241, -9151, -9062, -8972, -8882, -8792, -8703,
|
||||
-8613, -8523, -8433, -8344, -8254, -8164, -8075, -7985, -7895, -7805,
|
||||
-7716, -7626, -7536, -7446, -7357, -7267, -7177, -7088, -6998, -6908,
|
||||
-6818, -6729, -6639, -6549, -6459, -6370, -6280, -6190, -6101, -6011,
|
||||
-5921, -5831, -5742, -5652, -5562, -5472, -5383, -5293, -5203, -5113,
|
||||
-5024, -4934, -4844, -4755, -4665, -4575, -4485, -4396, -4306, -4216,
|
||||
-4126, -4037, -3947, -3857, -3768, -3678, -3588, -3498, -3409, -3319,
|
||||
-3229, -3139, -3050, -2960, -2870, -2781, -2691, -2601, -2511, -2422,
|
||||
-2332, -2242, -2152, -2063, -1973, -1883, -1794, -1704, -1614, -1524,
|
||||
-1435, -1345, -1255, -1165, -1076, -986, -896, -807, -717, -627, -537,
|
||||
-448, -358, -268, -178, -89, 0, 90, 179, 269, 359, 449, 538, 628, 718,
|
||||
808, 897, 987, 1077, 1166, 1256, 1346, 1436, 1525, 1615, 1705, 1795,
|
||||
1884, 1974, 2064, 2153, 2243, 2333, 2423, 2512, 2602, 2692, 2782,
|
||||
2871, 2961, 3051, 3140, 3230, 3320, 3410, 3499, 3589, 3679, 3769,
|
||||
3858, 3948, 4038, 4127, 4217, 4307, 4397, 4486, 4576, 4666, 4756,
|
||||
4845, 4935, 5025, 5114, 5204, 5294, 5384, 5473, 5563, 5653, 5743,
|
||||
5832, 5922, 6012, 6102, 6191, 6281, 6371, 6460, 6550, 6640, 6730,
|
||||
6819, 6909, 6999, 7089, 7178, 7268, 7358, 7447, 7537, 7627, 7717,
|
||||
7806, 7896, 7986, 8076, 8165, 8255, 8345, 8434, 8524, 8614, 8704,
|
||||
8793, 8883, 8973, 9063, 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 R_Cr[] = {
|
||||
-11484, -11394, -11305, -11215, -11125, -11036, -10946, -10856, -10766, -10677,
|
||||
-10587, -10497, -10407, -10318, -10228, -10138, -10049, -9959, -9869, -9779,
|
||||
-9690, -9600, -9510, -9420, -9331, -9241, -9151, -9062, -8972, -8882,
|
||||
-8792, -8703, -8613, -8523, -8433, -8344, -8254, -8164, -8075, -7985,
|
||||
-7895, -7805, -7716, -7626, -7536, -7446, -7357, -7267, -7177, -7088,
|
||||
-6998, -6908, -6818, -6729, -6639, -6549, -6459, -6370, -6280, -6190,
|
||||
-6101, -6011, -5921, -5831, -5742, -5652, -5562, -5472, -5383, -5293,
|
||||
-5203, -5113, -5024, -4934, -4844, -4755, -4665, -4575, -4485, -4396,
|
||||
-4306, -4216, -4126, -4037, -3947, -3857, -3768, -3678, -3588, -3498,
|
||||
-3409, -3319, -3229, -3139, -3050, -2960, -2870, -2781, -2691, -2601,
|
||||
-2511, -2422, -2332, -2242, -2152, -2063, -1973, -1883, -1794, -1704,
|
||||
-1614, -1524, -1435, -1345, -1255, -1165, -1076, -986, -896, -807,
|
||||
-717, -627, -537, -448, -358, -268, -178, -89, 0, 90,
|
||||
179, 269, 359, 449, 538, 628, 718, 808, 897, 987,
|
||||
1077, 1166, 1256, 1346, 1436, 1525, 1615, 1705, 1795, 1884,
|
||||
1974, 2064, 2153, 2243, 2333, 2423, 2512, 2602, 2692, 2782,
|
||||
2871, 2961, 3051, 3140, 3230, 3320, 3410, 3499, 3589, 3679,
|
||||
3769, 3858, 3948, 4038, 4127, 4217, 4307, 4397, 4486, 4576,
|
||||
4666, 4756, 4845, 4935, 5025, 5114, 5204, 5294, 5384, 5473,
|
||||
5563, 5653, 5743, 5832, 5922, 6012, 6102, 6191, 6281, 6371,
|
||||
6460, 6550, 6640, 6730, 6819, 6909, 6999, 7089, 7178, 7268,
|
||||
7358, 7447, 7537, 7627, 7717, 7806, 7896, 7986, 8076, 8165,
|
||||
8255, 8345, 8434, 8524, 8614, 8704, 8793, 8883, 8973, 9063,
|
||||
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,
|
||||
2665, 2643, 2621, 2599, 2577, 2555, 2533, 2511, 2489, 2467, 2445,
|
||||
2423, 2401, 2379, 2357, 2335, 2313, 2291, 2269, 2247, 2225, 2202,
|
||||
2180, 2158, 2136, 2114, 2092, 2070, 2048, 2026, 2004, 1982, 1960,
|
||||
1938, 1916, 1894, 1872, 1850, 1828, 1806, 1784, 1762, 1740, 1718,
|
||||
1696, 1674, 1652, 1630, 1608, 1586, 1564, 1542, 1520, 1498, 1476,
|
||||
1454, 1432, 1410, 1388, 1366, 1344, 1321, 1299, 1277, 1255, 1233,
|
||||
1211, 1189, 1167, 1145, 1123, 1101, 1079, 1057, 1035, 1013, 991, 969,
|
||||
947, 925, 903, 881, 859, 837, 815, 793, 771, 749, 727, 705, 683, 661,
|
||||
639, 617, 595, 573, 551, 529, 507, 485, 463, 440, 418, 396, 374, 352,
|
||||
330, 308, 286, 264, 242, 220, 198, 176, 154, 132, 110, 88, 66, 44, 22,
|
||||
0, -21, -43, -65, -87, -109, -131, -153, -175, -197, -219, -241, -263,
|
||||
-285, -307, -329, -351, -373, -395, -417, -439, -462, -484, -506,
|
||||
-528, -550, -572, -594, -616, -638, -660, -682, -704, -726, -748,
|
||||
-770, -792, -814, -836, -858, -880, -902, -924, -946, -968, -990,
|
||||
-1012, -1034, -1056, -1078, -1100, -1122, -1144, -1166, -1188, -1210,
|
||||
-1232, -1254, -1276, -1298, -1320, -1343, -1365, -1387, -1409, -1431,
|
||||
-1453, -1475, -1497, -1519, -1541, -1563, -1585, -1607, -1629, -1651,
|
||||
-1673, -1695, -1717, -1739, -1761, -1783, -1805, -1827, -1849, -1871,
|
||||
-1893, -1915, -1937, -1959, -1981, -2003, -2025, -2047, -2069, -2091,
|
||||
-2113, -2135, -2157, -2179, -2201, -2224, -2246, -2268, -2290, -2312,
|
||||
-2334, -2356, -2378, -2400, -2422, -2444, -2466, -2488, -2510, -2532,
|
||||
-2554, -2576, -2598, -2620, -2642, -2664, -2686, -2708, -2730, -2752,
|
||||
-2774, -2796 };
|
||||
static INT16 G_Cb[] = {
|
||||
2819, 2797, 2775, 2753, 2731, 2709, 2687, 2665, 2643, 2621, 2599, 2577,
|
||||
2555, 2533, 2511, 2489, 2467, 2445, 2423, 2401, 2379, 2357, 2335, 2313,
|
||||
2291, 2269, 2247, 2225, 2202, 2180, 2158, 2136, 2114, 2092, 2070, 2048,
|
||||
2026, 2004, 1982, 1960, 1938, 1916, 1894, 1872, 1850, 1828, 1806, 1784,
|
||||
1762, 1740, 1718, 1696, 1674, 1652, 1630, 1608, 1586, 1564, 1542, 1520,
|
||||
1498, 1476, 1454, 1432, 1410, 1388, 1366, 1344, 1321, 1299, 1277, 1255,
|
||||
1233, 1211, 1189, 1167, 1145, 1123, 1101, 1079, 1057, 1035, 1013, 991,
|
||||
969, 947, 925, 903, 881, 859, 837, 815, 793, 771, 749, 727,
|
||||
705, 683, 661, 639, 617, 595, 573, 551, 529, 507, 485, 463,
|
||||
440, 418, 396, 374, 352, 330, 308, 286, 264, 242, 220, 198,
|
||||
176, 154, 132, 110, 88, 66, 44, 22, 0, -21, -43, -65,
|
||||
-87, -109, -131, -153, -175, -197, -219, -241, -263, -285, -307, -329,
|
||||
-351, -373, -395, -417, -439, -462, -484, -506, -528, -550, -572, -594,
|
||||
-616, -638, -660, -682, -704, -726, -748, -770, -792, -814, -836, -858,
|
||||
-880, -902, -924, -946, -968, -990, -1012, -1034, -1056, -1078, -1100, -1122,
|
||||
-1144, -1166, -1188, -1210, -1232, -1254, -1276, -1298, -1320, -1343, -1365, -1387,
|
||||
-1409, -1431, -1453, -1475, -1497, -1519, -1541, -1563, -1585, -1607, -1629, -1651,
|
||||
-1673, -1695, -1717, -1739, -1761, -1783, -1805, -1827, -1849, -1871, -1893, -1915,
|
||||
-1937, -1959, -1981, -2003, -2025, -2047, -2069, -2091, -2113, -2135, -2157, -2179,
|
||||
-2201, -2224, -2246, -2268, -2290, -2312, -2334, -2356, -2378, -2400, -2422, -2444,
|
||||
-2466, -2488, -2510, -2532, -2554, -2576, -2598, -2620, -2642, -2664, -2686, -2708,
|
||||
-2730, -2752, -2774, -2796};
|
||||
|
||||
static INT16 G_Cr[] = { 5850, 5805, 5759, 5713, 5667, 5622, 5576,
|
||||
5530, 5485, 5439, 5393, 5347, 5302, 5256, 5210, 5165, 5119, 5073,
|
||||
5028, 4982, 4936, 4890, 4845, 4799, 4753, 4708, 4662, 4616, 4570,
|
||||
4525, 4479, 4433, 4388, 4342, 4296, 4251, 4205, 4159, 4113, 4068,
|
||||
4022, 3976, 3931, 3885, 3839, 3794, 3748, 3702, 3656, 3611, 3565,
|
||||
3519, 3474, 3428, 3382, 3336, 3291, 3245, 3199, 3154, 3108, 3062,
|
||||
3017, 2971, 2925, 2879, 2834, 2788, 2742, 2697, 2651, 2605, 2559,
|
||||
2514, 2468, 2422, 2377, 2331, 2285, 2240, 2194, 2148, 2102, 2057,
|
||||
2011, 1965, 1920, 1874, 1828, 1782, 1737, 1691, 1645, 1600, 1554,
|
||||
1508, 1463, 1417, 1371, 1325, 1280, 1234, 1188, 1143, 1097, 1051,
|
||||
1006, 960, 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,
|
||||
-273, -319, -365, -410, -456, -502, -547, -593, -639, -685, -730,
|
||||
-776, -822, -867, -913, -959, -1005, -1050, -1096, -1142, -1187,
|
||||
-1233, -1279, -1324, -1370, -1416, -1462, -1507, -1553, -1599, -1644,
|
||||
-1690, -1736, -1781, -1827, -1873, -1919, -1964, -2010, -2056, -2101,
|
||||
-2147, -2193, -2239, -2284, -2330, -2376, -2421, -2467, -2513, -2558,
|
||||
-2604, -2650, -2696, -2741, -2787, -2833, -2878, -2924, -2970, -3016,
|
||||
-3061, -3107, -3153, -3198, -3244, -3290, -3335, -3381, -3427, -3473,
|
||||
-3518, -3564, -3610, -3655, -3701, -3747, -3793, -3838, -3884, -3930,
|
||||
-3975, -4021, -4067, -4112, -4158, -4204, -4250, -4295, -4341, -4387,
|
||||
-4432, -4478, -4524, -4569, -4615, -4661, -4707, -4752, -4798, -4844,
|
||||
-4889, -4935, -4981, -5027, -5072, -5118, -5164, -5209, -5255, -5301,
|
||||
-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 G_Cr[] = {
|
||||
5850, 5805, 5759, 5713, 5667, 5622, 5576, 5530, 5485, 5439, 5393, 5347,
|
||||
5302, 5256, 5210, 5165, 5119, 5073, 5028, 4982, 4936, 4890, 4845, 4799,
|
||||
4753, 4708, 4662, 4616, 4570, 4525, 4479, 4433, 4388, 4342, 4296, 4251,
|
||||
4205, 4159, 4113, 4068, 4022, 3976, 3931, 3885, 3839, 3794, 3748, 3702,
|
||||
3656, 3611, 3565, 3519, 3474, 3428, 3382, 3336, 3291, 3245, 3199, 3154,
|
||||
3108, 3062, 3017, 2971, 2925, 2879, 2834, 2788, 2742, 2697, 2651, 2605,
|
||||
2559, 2514, 2468, 2422, 2377, 2331, 2285, 2240, 2194, 2148, 2102, 2057,
|
||||
2011, 1965, 1920, 1874, 1828, 1782, 1737, 1691, 1645, 1600, 1554, 1508,
|
||||
1463, 1417, 1371, 1325, 1280, 1234, 1188, 1143, 1097, 1051, 1006, 960,
|
||||
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, -273, -319, -365, -410, -456, -502, -547, -593, -639, -685,
|
||||
-730, -776, -822, -867, -913, -959, -1005, -1050, -1096, -1142, -1187, -1233,
|
||||
-1279, -1324, -1370, -1416, -1462, -1507, -1553, -1599, -1644, -1690, -1736, -1781,
|
||||
-1827, -1873, -1919, -1964, -2010, -2056, -2101, -2147, -2193, -2239, -2284, -2330,
|
||||
-2376, -2421, -2467, -2513, -2558, -2604, -2650, -2696, -2741, -2787, -2833, -2878,
|
||||
-2924, -2970, -3016, -3061, -3107, -3153, -3198, -3244, -3290, -3335, -3381, -3427,
|
||||
-3473, -3518, -3564, -3610, -3655, -3701, -3747, -3793, -3838, -3884, -3930, -3975,
|
||||
-4021, -4067, -4112, -4158, -4204, -4250, -4295, -4341, -4387, -4432, -4478, -4524,
|
||||
-4569, -4615, -4661, -4707, -4752, -4798, -4844, -4889, -4935, -4981, -5027, -5072,
|
||||
-5118, -5164, -5209, -5255, -5301, -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};
|
||||
|
||||
void
|
||||
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)
|
||||
{
|
||||
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;
|
||||
UINT8 a;
|
||||
int r, g, b;
|
||||
int y, cr, cb;
|
||||
|
||||
for (x = 0; x < pixels; x++, in += 4, out += 4) {
|
||||
y = in[0];
|
||||
cb = in[1];
|
||||
cr = in[2];
|
||||
a = in[3];
|
||||
|
||||
r = y + (( R_Cr[cr]) >> SCALE);
|
||||
r = y + ((R_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[1] = (g <= 0) ? 0 : (g >= 255) ? 255 : g;
|
||||
|
|
|
@ -15,18 +15,15 @@
|
|||
* See the README file for details on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
static Imaging
|
||||
_copy(Imaging imOut, Imaging imIn)
|
||||
{
|
||||
_copy(Imaging imOut, Imaging imIn) {
|
||||
ImagingSectionCookie cookie;
|
||||
int y;
|
||||
|
||||
if (!imIn) {
|
||||
return (Imaging) ImagingError_ValueError(NULL);
|
||||
return (Imaging)ImagingError_ValueError(NULL);
|
||||
}
|
||||
|
||||
imOut = ImagingNew2Dirty(imIn->mode, imOut, imIn);
|
||||
|
@ -50,13 +47,11 @@ _copy(Imaging imOut, Imaging imIn)
|
|||
}
|
||||
|
||||
Imaging
|
||||
ImagingCopy(Imaging imIn)
|
||||
{
|
||||
ImagingCopy(Imaging imIn) {
|
||||
return _copy(NULL, imIn);
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingCopy2(Imaging imOut, Imaging imIn)
|
||||
{
|
||||
ImagingCopy2(Imaging imOut, Imaging imIn) {
|
||||
return _copy(imOut, imIn);
|
||||
}
|
||||
|
|
|
@ -15,20 +15,17 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
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;
|
||||
int xsize, ysize;
|
||||
int dx0, dy0, dx1, dy1;
|
||||
INT32 zero = 0;
|
||||
|
||||
if (!imIn) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
xsize = sx1 - sx0;
|
||||
|
@ -48,7 +45,7 @@ ImagingCrop(Imaging imIn, int sx0, int sy0, int sx1, int sy1)
|
|||
ImagingCopyPalette(imOut, imIn);
|
||||
|
||||
if (sx0 < 0 || sy0 < 0 || sx1 > imIn->xsize || sy1 > imIn->ysize) {
|
||||
(void) ImagingFill(imOut, &zero);
|
||||
(void)ImagingFill(imOut, &zero);
|
||||
}
|
||||
|
||||
dx0 = -sx0;
|
||||
|
|
|
@ -19,21 +19,18 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "ImDib.h"
|
||||
|
||||
|
||||
char*
|
||||
ImagingGetModeDIB(int size_out[2])
|
||||
{
|
||||
char *
|
||||
ImagingGetModeDIB(int size_out[2]) {
|
||||
/* Get device characteristics */
|
||||
|
||||
HDC dc;
|
||||
char* mode;
|
||||
char *mode;
|
||||
|
||||
dc = CreateCompatibleDC(NULL);
|
||||
|
||||
|
@ -55,10 +52,8 @@ ImagingGetModeDIB(int size_out[2])
|
|||
return mode;
|
||||
}
|
||||
|
||||
|
||||
ImagingDIB
|
||||
ImagingNewDIB(const char *mode, int xsize, int ysize)
|
||||
{
|
||||
ImagingNewDIB(const char *mode, int xsize, int ysize) {
|
||||
/* Create a Windows bitmap */
|
||||
|
||||
ImagingDIB dib;
|
||||
|
@ -66,23 +61,21 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
|
|||
int i;
|
||||
|
||||
/* Check mode */
|
||||
if (strcmp(mode, "1") != 0 && strcmp(mode, "L") != 0 &&
|
||||
strcmp(mode, "RGB") != 0) {
|
||||
return (ImagingDIB) ImagingError_ModeError();
|
||||
if (strcmp(mode, "1") != 0 && strcmp(mode, "L") != 0 && strcmp(mode, "RGB") != 0) {
|
||||
return (ImagingDIB)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
/* Create DIB context and info header */
|
||||
/* malloc check ok, small constant allocation */
|
||||
dib = (ImagingDIB) malloc(sizeof(*dib));
|
||||
dib = (ImagingDIB)malloc(sizeof(*dib));
|
||||
if (!dib) {
|
||||
return (ImagingDIB) ImagingError_MemoryError();
|
||||
return (ImagingDIB)ImagingError_MemoryError();
|
||||
}
|
||||
/* malloc check ok, small constant allocation */
|
||||
dib->info = (BITMAPINFO*) malloc(sizeof(BITMAPINFOHEADER) +
|
||||
256 * sizeof(RGBQUAD));
|
||||
dib->info = (BITMAPINFO *)malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
|
||||
if (!dib->info) {
|
||||
free(dib);
|
||||
return (ImagingDIB) ImagingError_MemoryError();
|
||||
return (ImagingDIB)ImagingError_MemoryError();
|
||||
}
|
||||
|
||||
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.biHeight = ysize;
|
||||
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;
|
||||
|
||||
/* Create DIB */
|
||||
|
@ -98,15 +91,15 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
|
|||
if (!dib->dc) {
|
||||
free(dib->info);
|
||||
free(dib);
|
||||
return (ImagingDIB) ImagingError_MemoryError();
|
||||
return (ImagingDIB)ImagingError_MemoryError();
|
||||
}
|
||||
|
||||
dib->bitmap = CreateDIBSection(dib->dc, dib->info, DIB_RGB_COLORS,
|
||||
&dib->bits, NULL, 0);
|
||||
dib->bitmap =
|
||||
CreateDIBSection(dib->dc, dib->info, DIB_RGB_COLORS, &dib->bits, NULL, 0);
|
||||
if (!dib->bitmap) {
|
||||
free(dib->info);
|
||||
free(dib);
|
||||
return (ImagingDIB) ImagingError_MemoryError();
|
||||
return (ImagingDIB)ImagingError_MemoryError();
|
||||
}
|
||||
|
||||
strcpy(dib->mode, mode);
|
||||
|
@ -117,7 +110,7 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
|
|||
dib->linesize = (xsize * dib->pixelsize + 3) & -4;
|
||||
|
||||
if (dib->pixelsize == 1) {
|
||||
dib->pack = dib->unpack = (ImagingShuffler) memcpy;
|
||||
dib->pack = dib->unpack = (ImagingShuffler)memcpy;
|
||||
} else {
|
||||
dib->pack = 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) */
|
||||
if (dib->pixelsize == 1) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
palette[i].rgbRed =
|
||||
palette[i].rgbGreen =
|
||||
palette[i].rgbBlue = i;
|
||||
palette[i].rgbRed = palette[i].rgbGreen = palette[i].rgbBlue = i;
|
||||
palette[i].rgbReserved = 0;
|
||||
}
|
||||
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) */
|
||||
if (strcmp(ImagingGetModeDIB(NULL), "P") == 0) {
|
||||
|
||||
char palbuf[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)];
|
||||
LPLOGPALETTE pal = (LPLOGPALETTE) palbuf;
|
||||
char palbuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];
|
||||
LPLOGPALETTE pal = (LPLOGPALETTE)palbuf;
|
||||
int i, r, g, b;
|
||||
|
||||
/* Load system palette */
|
||||
|
@ -152,7 +142,6 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
|
|||
GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry);
|
||||
|
||||
if (strcmp(mode, "L") == 0) {
|
||||
|
||||
/* Greyscale DIB. Fill all 236 slots with a greyscale ramp
|
||||
* (this is usually overkill on Windows since VGA only offers
|
||||
* 6 bits greyscale resolution). Ignore the slots already
|
||||
|
@ -160,16 +149,14 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
|
|||
|
||||
i = 10;
|
||||
for (r = 0; r < 236; r++) {
|
||||
pal->palPalEntry[i].peRed =
|
||||
pal->palPalEntry[i].peGreen =
|
||||
pal->palPalEntry[i].peBlue = i;
|
||||
pal->palPalEntry[i].peRed = pal->palPalEntry[i].peGreen =
|
||||
pal->palPalEntry[i].peBlue = i;
|
||||
i++;
|
||||
}
|
||||
|
||||
dib->palette = CreatePalette(pal);
|
||||
|
||||
} else if (strcmp(mode, "RGB") == 0) {
|
||||
|
||||
#ifdef CUBE216
|
||||
|
||||
/* 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. */
|
||||
pal->palPalEntry[i].peRed =
|
||||
pal->palPalEntry[i].peGreen =
|
||||
pal->palPalEntry[i].peBlue = r * 255 / (22-1);
|
||||
pal->palPalEntry[i].peRed = pal->palPalEntry[i].peGreen =
|
||||
pal->palPalEntry[i].peBlue = r * 255 / (22 - 1);
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -214,76 +200,91 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
|
|||
#endif
|
||||
|
||||
dib->palette = CreatePalette(pal);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return dib;
|
||||
}
|
||||
|
||||
void
|
||||
ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4])
|
||||
{
|
||||
ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4]) {
|
||||
/* Paste image data into a bitmap */
|
||||
|
||||
/* FIXME: check size! */
|
||||
|
||||
int y;
|
||||
for (y = 0; y < im->ysize; y++) {
|
||||
dib->pack(dib->bits + dib->linesize*(dib->ysize-(xy[1]+y)-1) +
|
||||
xy[0]*dib->pixelsize, im->image[y], im->xsize);
|
||||
dib->pack(
|
||||
dib->bits + dib->linesize * (dib->ysize - (xy[1] + y) - 1) +
|
||||
xy[0] * dib->pixelsize,
|
||||
im->image[y],
|
||||
im->xsize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ImagingExposeDIB(ImagingDIB dib, void *dc)
|
||||
{
|
||||
ImagingExposeDIB(ImagingDIB dib, void *dc) {
|
||||
/* Copy bitmap to display */
|
||||
|
||||
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
|
||||
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 */
|
||||
|
||||
if (GetDeviceCaps((HDC) dc, RASTERCAPS) & RC_STRETCHDIB) {
|
||||
if (GetDeviceCaps((HDC)dc, RASTERCAPS) & RC_STRETCHDIB) {
|
||||
/* stretchdib (printers) */
|
||||
StretchDIBits((HDC) dc, 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);
|
||||
StretchDIBits(
|
||||
(HDC)dc,
|
||||
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 {
|
||||
/* stretchblt (displays) */
|
||||
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],
|
||||
dib->dc, src[0], src[1], src[2]-src[0], src[3]-src[1],
|
||||
SRCCOPY);
|
||||
StretchBlt(
|
||||
(HDC)dc,
|
||||
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
|
||||
ImagingQueryPaletteDIB(ImagingDIB dib, void *dc)
|
||||
{
|
||||
ImagingQueryPaletteDIB(ImagingDIB dib, void *dc) {
|
||||
/* Install bitmap palette */
|
||||
|
||||
int n;
|
||||
|
||||
if (dib->palette != 0) {
|
||||
|
||||
/* Realize associated palette */
|
||||
HPALETTE now = SelectPalette((HDC) dc, dib->palette, FALSE);
|
||||
n = RealizePalette((HDC) dc);
|
||||
HPALETTE now = SelectPalette((HDC)dc, dib->palette, FALSE);
|
||||
n = RealizePalette((HDC)dc);
|
||||
|
||||
/* Restore palette */
|
||||
SelectPalette((HDC) dc, now, FALSE);
|
||||
SelectPalette((HDC)dc, now, FALSE);
|
||||
|
||||
} else {
|
||||
n = 0;
|
||||
|
@ -293,8 +294,7 @@ ImagingQueryPaletteDIB(ImagingDIB dib, void *dc)
|
|||
}
|
||||
|
||||
void
|
||||
ImagingDeleteDIB(ImagingDIB dib)
|
||||
{
|
||||
ImagingDeleteDIB(ImagingDIB dib) {
|
||||
/* Clean up */
|
||||
|
||||
if (dib->palette) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -15,14 +15,12 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
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 */
|
||||
|
||||
Imaging im;
|
||||
|
@ -32,10 +30,10 @@ ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality)
|
|||
double dr, di;
|
||||
|
||||
/* Check arguments */
|
||||
width = extent[2] - extent[0];
|
||||
width = extent[2] - extent[0];
|
||||
height = extent[3] - extent[1];
|
||||
if (width < 0.0 || height < 0.0 || quality < 2) {
|
||||
return (Imaging) ImagingError_ValueError(NULL);
|
||||
return (Imaging)ImagingError_ValueError(NULL);
|
||||
}
|
||||
|
||||
im = ImagingNewDirty("L", xsize, ysize);
|
||||
|
@ -43,24 +41,24 @@ ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
dr = width/(xsize-1);
|
||||
di = height/(ysize-1);
|
||||
dr = width / (xsize - 1);
|
||||
di = height / (ysize - 1);
|
||||
|
||||
radius = 100.0;
|
||||
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8* buf = im->image8[y];
|
||||
UINT8 *buf = im->image8[y];
|
||||
for (x = 0; x < xsize; x++) {
|
||||
x1 = y1 = xi2 = yi2 = 0.0;
|
||||
cr = x*dr + extent[0];
|
||||
ci = y*di + extent[1];
|
||||
cr = x * dr + extent[0];
|
||||
ci = y * di + extent[1];
|
||||
for (k = 1;; k++) {
|
||||
y1 = 2*x1*y1 + ci;
|
||||
y1 = 2 * x1 * y1 + ci;
|
||||
x1 = xi2 - yi2 + cr;
|
||||
xi2 = x1*x1;
|
||||
yi2 = y1*y1;
|
||||
xi2 = x1 * x1;
|
||||
yi2 = y1 * y1;
|
||||
if ((xi2 + yi2) > radius) {
|
||||
buf[x] = k*255/quality;
|
||||
buf[x] = k * 255 / quality;
|
||||
break;
|
||||
}
|
||||
if (k > quality) {
|
||||
|
@ -74,8 +72,7 @@ ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality)
|
|||
}
|
||||
|
||||
Imaging
|
||||
ImagingEffectNoise(int xsize, int ysize, float sigma)
|
||||
{
|
||||
ImagingEffectNoise(int xsize, int ysize, float sigma) {
|
||||
/* Generate Gaussian noise centered around 128 */
|
||||
|
||||
Imaging imOut;
|
||||
|
@ -92,7 +89,7 @@ ImagingEffectNoise(int xsize, int ysize, float sigma)
|
|||
nextok = 0;
|
||||
|
||||
for (y = 0; y < imOut->ysize; y++) {
|
||||
UINT8* out = imOut->image8[y];
|
||||
UINT8 *out = imOut->image8[y];
|
||||
for (x = 0; x < imOut->xsize; x++) {
|
||||
if (nextok) {
|
||||
this = next;
|
||||
|
@ -101,11 +98,11 @@ ImagingEffectNoise(int xsize, int ysize, float sigma)
|
|||
/* after numerical recipes */
|
||||
double v1, v2, radius, factor;
|
||||
do {
|
||||
v1 = rand()*(2.0/RAND_MAX) - 1.0;
|
||||
v2 = rand()*(2.0/RAND_MAX) - 1.0;
|
||||
radius= v1*v1 + v2*v2;
|
||||
v1 = rand() * (2.0 / RAND_MAX) - 1.0;
|
||||
v2 = rand() * (2.0 / RAND_MAX) - 1.0;
|
||||
radius = v1 * v1 + v2 * v2;
|
||||
} while (radius >= 1.0);
|
||||
factor = sqrt(-2.0*log(radius)/radius);
|
||||
factor = sqrt(-2.0 * log(radius) / radius);
|
||||
this = factor * v1;
|
||||
next = factor * v2;
|
||||
}
|
||||
|
@ -117,8 +114,7 @@ ImagingEffectNoise(int xsize, int ysize, float sigma)
|
|||
}
|
||||
|
||||
Imaging
|
||||
ImagingEffectSpread(Imaging imIn, int distance)
|
||||
{
|
||||
ImagingEffectSpread(Imaging imIn, int distance) {
|
||||
/* Randomly spread pixels in an image */
|
||||
|
||||
Imaging imOut;
|
||||
|
@ -130,26 +126,26 @@ ImagingEffectSpread(Imaging imIn, int distance)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#define SPREAD(type, image)\
|
||||
if (distance == 0) {\
|
||||
for (y = 0; y < imOut->ysize; y++) {\
|
||||
for (x = 0; x < imOut->xsize; x++) {\
|
||||
imOut->image[y][x] = imIn->image[y][x];\
|
||||
}\
|
||||
}\
|
||||
} else {\
|
||||
for (y = 0; y < imOut->ysize; y++) {\
|
||||
for (x = 0; x < imOut->xsize; x++) {\
|
||||
int xx = x + (rand() % distance) - distance/2;\
|
||||
int yy = y + (rand() % distance) - distance/2;\
|
||||
if (xx >= 0 && xx < imIn->xsize && yy >= 0 && yy < imIn->ysize) {\
|
||||
imOut->image[yy][xx] = imIn->image[y][x];\
|
||||
imOut->image[y][x] = imIn->image[yy][xx];\
|
||||
} else {\
|
||||
imOut->image[y][x] = imIn->image[y][x];\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
#define SPREAD(type, image) \
|
||||
if (distance == 0) { \
|
||||
for (y = 0; y < imOut->ysize; y++) { \
|
||||
for (x = 0; x < imOut->xsize; x++) { \
|
||||
imOut->image[y][x] = imIn->image[y][x]; \
|
||||
} \
|
||||
} \
|
||||
} else { \
|
||||
for (y = 0; y < imOut->ysize; y++) { \
|
||||
for (x = 0; x < imOut->xsize; x++) { \
|
||||
int xx = x + (rand() % distance) - distance / 2; \
|
||||
int yy = y + (rand() % distance) - distance / 2; \
|
||||
if (xx >= 0 && xx < imIn->xsize && yy >= 0 && yy < imIn->ysize) { \
|
||||
imOut->image[yy][xx] = imIn->image[y][x]; \
|
||||
imOut->image[y][x] = imIn->image[yy][xx]; \
|
||||
} else { \
|
||||
imOut->image[y][x] = imIn->image[y][x]; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
if (imIn->image8) {
|
||||
|
|
|
@ -17,28 +17,24 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
int
|
||||
ImagingEpsEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||
{
|
||||
enum { HEXBYTE=1, NEWLINE };
|
||||
ImagingEpsEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
|
||||
enum { HEXBYTE = 1, NEWLINE };
|
||||
const char *hex = "0123456789abcdef";
|
||||
|
||||
UINT8* ptr = buf;
|
||||
UINT8* in, i;
|
||||
UINT8 *ptr = buf;
|
||||
UINT8 *in, i;
|
||||
|
||||
if (!state->state) {
|
||||
state->state = HEXBYTE;
|
||||
state->xsize *= im->pixelsize; /* Hack! */
|
||||
}
|
||||
|
||||
in = (UINT8*) im->image[state->y];
|
||||
in = (UINT8 *)im->image[state->y];
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (state->state == NEWLINE) {
|
||||
if (bytes < 1) {
|
||||
break;
|
||||
|
@ -53,8 +49,8 @@ ImagingEpsEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
}
|
||||
|
||||
i = in[state->x++];
|
||||
*ptr++ = hex[(i>>4)&15];
|
||||
*ptr++ = hex[i&15];
|
||||
*ptr++ = hex[(i >> 4) & 15];
|
||||
*ptr++ = hex[i & 15];
|
||||
bytes -= 2;
|
||||
|
||||
/* Skip junk bytes */
|
||||
|
@ -62,7 +58,7 @@ ImagingEpsEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
state->x++;
|
||||
}
|
||||
|
||||
if (++state->count >= 79/2) {
|
||||
if (++state->count >= 79 / 2) {
|
||||
state->state = NEWLINE;
|
||||
state->count = 0;
|
||||
}
|
||||
|
@ -73,11 +69,9 @@ ImagingEpsEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
state->errcode = IMAGING_CODEC_END;
|
||||
break;
|
||||
}
|
||||
in = (UINT8*) im->image[state->y];
|
||||
in = (UINT8 *)im->image[state->y];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ptr - buf;
|
||||
|
||||
}
|
||||
|
|
|
@ -19,41 +19,34 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
/* exception state */
|
||||
|
||||
void *
|
||||
ImagingError_OSError(void)
|
||||
{
|
||||
ImagingError_OSError(void) {
|
||||
fprintf(stderr, "*** exception: file access error\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
ImagingError_MemoryError(void)
|
||||
{
|
||||
ImagingError_MemoryError(void) {
|
||||
fprintf(stderr, "*** exception: out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
ImagingError_ModeError(void)
|
||||
{
|
||||
ImagingError_ModeError(void) {
|
||||
return ImagingError_ValueError("bad image mode");
|
||||
}
|
||||
|
||||
void *
|
||||
ImagingError_Mismatch(void)
|
||||
{
|
||||
ImagingError_Mismatch(void) {
|
||||
return ImagingError_ValueError("images don't match");
|
||||
}
|
||||
|
||||
void *
|
||||
ImagingError_ValueError(const char *message)
|
||||
{
|
||||
ImagingError_ValueError(const char *message) {
|
||||
if (!message) {
|
||||
message = "exception: bad argument to function";
|
||||
}
|
||||
|
@ -62,21 +55,18 @@ ImagingError_ValueError(const char *message)
|
|||
}
|
||||
|
||||
void
|
||||
ImagingError_Clear(void)
|
||||
{
|
||||
ImagingError_Clear(void) {
|
||||
/* nop */;
|
||||
}
|
||||
|
||||
/* thread state */
|
||||
|
||||
void
|
||||
ImagingSectionEnter(ImagingSectionCookie* cookie)
|
||||
{
|
||||
ImagingSectionEnter(ImagingSectionCookie *cookie) {
|
||||
/* pass */
|
||||
}
|
||||
|
||||
void
|
||||
ImagingSectionLeave(ImagingSectionCookie* cookie)
|
||||
{
|
||||
ImagingSectionLeave(ImagingSectionCookie *cookie) {
|
||||
/* pass */
|
||||
}
|
||||
|
|
|
@ -15,19 +15,15 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
int
|
||||
ImagingSaveRaw(Imaging im, FILE* fp)
|
||||
{
|
||||
ImagingSaveRaw(Imaging im, FILE *fp) {
|
||||
int x, y, i;
|
||||
|
||||
if (strcmp(im->mode, "1") == 0 || strcmp(im->mode, "L") == 0) {
|
||||
|
||||
/* @PIL227: FIXME: for mode "1", map != 0 to 255 */
|
||||
|
||||
/* PGM "L" */
|
||||
|
@ -36,33 +32,29 @@ ImagingSaveRaw(Imaging im, FILE* fp)
|
|||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* PPM "RGB" or other internal format */
|
||||
for (y = 0; y < im->ysize; y++) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ImagingSavePPM(Imaging im, const char* outfile)
|
||||
{
|
||||
FILE* fp;
|
||||
ImagingSavePPM(Imaging im, const char *outfile) {
|
||||
FILE *fp;
|
||||
|
||||
if (!im) {
|
||||
(void) ImagingError_ValueError(NULL);
|
||||
(void)ImagingError_ValueError(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fp = fopen(outfile, "wb");
|
||||
if (!fp) {
|
||||
(void) ImagingError_OSError();
|
||||
(void)ImagingError_OSError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -74,7 +66,7 @@ ImagingSavePPM(Imaging im, const char* outfile)
|
|||
fprintf(fp, "P6\n%d %d\n255\n", im->xsize, im->ysize);
|
||||
} else {
|
||||
fclose(fp);
|
||||
(void) ImagingError_ModeError();
|
||||
(void)ImagingError_ModeError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -84,4 +76,3 @@ ImagingSavePPM(Imaging im, const char* outfile)
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,14 +15,12 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#include "math.h"
|
||||
|
||||
Imaging
|
||||
ImagingFill(Imaging im, const void* colour)
|
||||
{
|
||||
ImagingFill(Imaging im, const void *colour) {
|
||||
int x, y;
|
||||
ImagingSectionCookie cookie;
|
||||
|
||||
|
@ -53,7 +51,7 @@ ImagingFill(Imaging im, const void* colour)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
unsigned char cc = (unsigned char) *(UINT8*) colour;
|
||||
unsigned char cc = (unsigned char)*(UINT8 *)colour;
|
||||
for (y = 0; y < im->ysize; y++) {
|
||||
memset(im->image[y], cc, im->linesize);
|
||||
}
|
||||
|
@ -65,13 +63,12 @@ ImagingFill(Imaging im, const void* colour)
|
|||
}
|
||||
|
||||
Imaging
|
||||
ImagingFillLinearGradient(const char *mode)
|
||||
{
|
||||
ImagingFillLinearGradient(const char *mode) {
|
||||
Imaging im;
|
||||
int y;
|
||||
|
||||
if (strlen(mode) != 1) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
im = ImagingNewDirty(mode, 256, 256);
|
||||
|
@ -80,21 +77,20 @@ ImagingFillLinearGradient(const char *mode)
|
|||
}
|
||||
|
||||
for (y = 0; y < 256; y++) {
|
||||
memset(im->image8[y], (unsigned char) y, 256);
|
||||
memset(im->image8[y], (unsigned char)y, 256);
|
||||
}
|
||||
|
||||
return im;
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingFillRadialGradient(const char *mode)
|
||||
{
|
||||
ImagingFillRadialGradient(const char *mode) {
|
||||
Imaging im;
|
||||
int x, y;
|
||||
int d;
|
||||
|
||||
if (strlen(mode) != 1) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
im = ImagingNewDirty(mode, 256, 256);
|
||||
|
@ -104,7 +100,8 @@ ImagingFillRadialGradient(const char *mode)
|
|||
|
||||
for (y = 0; y < 256; y++) {
|
||||
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) {
|
||||
im->image8[y][x] = 255;
|
||||
} else {
|
||||
|
|
|
@ -26,59 +26,59 @@
|
|||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
static inline UINT8 clip8(float in)
|
||||
{
|
||||
static inline UINT8
|
||||
clip8(float in) {
|
||||
if (in <= 0.0) {
|
||||
return 0;
|
||||
}
|
||||
if (in >= 255.0) {
|
||||
return 255;
|
||||
}
|
||||
return (UINT8) in;
|
||||
return (UINT8)in;
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingExpand(Imaging imIn, int xmargin, int ymargin, int mode)
|
||||
{
|
||||
ImagingExpand(Imaging imIn, int xmargin, int ymargin, int mode) {
|
||||
Imaging imOut;
|
||||
int x, y;
|
||||
ImagingSectionCookie cookie;
|
||||
|
||||
if (xmargin < 0 && ymargin < 0) {
|
||||
return (Imaging) ImagingError_ValueError("bad kernel size");
|
||||
return (Imaging)ImagingError_ValueError("bad kernel size");
|
||||
}
|
||||
|
||||
imOut = ImagingNewDirty(
|
||||
imIn->mode, imIn->xsize+2*xmargin, imIn->ysize+2*ymargin);
|
||||
imIn->mode, imIn->xsize + 2 * xmargin, imIn->ysize + 2 * ymargin);
|
||||
if (!imOut) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#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 < 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] =\
|
||||
imIn->image[yin][imIn->xsize-1];\
|
||||
}\
|
||||
}
|
||||
#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 < 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] = \
|
||||
imIn->image[yin][imIn->xsize - 1]; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define EXPAND(type, image) {\
|
||||
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 < ymargin; y++) {\
|
||||
EXPAND_LINE(type, image, imIn->ysize-1, ymargin+imIn->ysize+y);\
|
||||
}\
|
||||
}
|
||||
#define EXPAND(type, image) \
|
||||
{ \
|
||||
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 < ymargin; y++) { \
|
||||
EXPAND_LINE(type, image, imIn->ysize - 1, ymargin + imIn->ysize + y); \
|
||||
} \
|
||||
}
|
||||
|
||||
ImagingSectionEnter(&cookie);
|
||||
if (imIn->image8) {
|
||||
|
@ -93,15 +93,11 @@ ImagingExpand(Imaging imIn, int xmargin, int ymargin, int mode)
|
|||
return imOut;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ImagingFilter3x3(Imaging imOut, Imaging im, const float* kernel,
|
||||
float offset)
|
||||
{
|
||||
#define KERNEL1x3(in0, x, kernel, d) ( \
|
||||
_i2f((UINT8) in0[x-d]) * (kernel)[0] + \
|
||||
_i2f((UINT8) in0[x]) * (kernel)[1] + \
|
||||
_i2f((UINT8) in0[x+d]) * (kernel)[2])
|
||||
ImagingFilter3x3(Imaging imOut, Imaging im, const float *kernel, float offset) {
|
||||
#define KERNEL1x3(in0, x, kernel, d) \
|
||||
(_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;
|
||||
|
||||
|
@ -109,86 +105,84 @@ ImagingFilter3x3(Imaging imOut, Imaging im, const float* kernel,
|
|||
if (im->bands == 1) {
|
||||
// Add one time for rounding
|
||||
offset += 0.5;
|
||||
for (y = 1; y < im->ysize-1; y++) {
|
||||
UINT8* in_1 = (UINT8*) im->image[y-1];
|
||||
UINT8* in0 = (UINT8*) im->image[y];
|
||||
UINT8* in1 = (UINT8*) im->image[y+1];
|
||||
UINT8* out = (UINT8*) imOut->image[y];
|
||||
for (y = 1; y < im->ysize - 1; y++) {
|
||||
UINT8 *in_1 = (UINT8 *)im->image[y - 1];
|
||||
UINT8 *in0 = (UINT8 *)im->image[y];
|
||||
UINT8 *in1 = (UINT8 *)im->image[y + 1];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y];
|
||||
|
||||
out[0] = in0[0];
|
||||
for (x = 1; x < im->xsize-1; x++) {
|
||||
for (x = 1; x < im->xsize - 1; x++) {
|
||||
float ss = offset;
|
||||
ss += KERNEL1x3(in1, x, &kernel[0], 1);
|
||||
ss += KERNEL1x3(in0, x, &kernel[3], 1);
|
||||
ss += KERNEL1x3(in_1, x, &kernel[6], 1);
|
||||
out[x] = clip8(ss);
|
||||
}
|
||||
}
|
||||
out[x] = in0[x];
|
||||
}
|
||||
} else {
|
||||
// Add one time for rounding
|
||||
offset += 0.5;
|
||||
for (y = 1; y < im->ysize-1; y++) {
|
||||
UINT8* in_1 = (UINT8*) im->image[y-1];
|
||||
UINT8* in0 = (UINT8*) im->image[y];
|
||||
UINT8* in1 = (UINT8*) im->image[y+1];
|
||||
UINT8* out = (UINT8*) imOut->image[y];
|
||||
for (y = 1; y < im->ysize - 1; y++) {
|
||||
UINT8 *in_1 = (UINT8 *)im->image[y - 1];
|
||||
UINT8 *in0 = (UINT8 *)im->image[y];
|
||||
UINT8 *in1 = (UINT8 *)im->image[y + 1];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y];
|
||||
|
||||
memcpy(out, in0, sizeof(UINT32));
|
||||
if (im->bands == 2) {
|
||||
for (x = 1; x < im->xsize-1; x++) {
|
||||
for (x = 1; x < im->xsize - 1; x++) {
|
||||
float ss0 = offset;
|
||||
float ss3 = offset;
|
||||
UINT32 v;
|
||||
ss0 += KERNEL1x3(in1, x*4+0, &kernel[0], 4);
|
||||
ss3 += KERNEL1x3(in1, x*4+3, &kernel[0], 4);
|
||||
ss0 += KERNEL1x3(in0, x*4+0, &kernel[3], 4);
|
||||
ss3 += KERNEL1x3(in0, x*4+3, &kernel[3], 4);
|
||||
ss0 += KERNEL1x3(in_1, x*4+0, &kernel[6], 4);
|
||||
ss3 += KERNEL1x3(in_1, x*4+3, &kernel[6], 4);
|
||||
ss0 += KERNEL1x3(in1, x * 4 + 0, &kernel[0], 4);
|
||||
ss3 += KERNEL1x3(in1, x * 4 + 3, &kernel[0], 4);
|
||||
ss0 += KERNEL1x3(in0, x * 4 + 0, &kernel[3], 4);
|
||||
ss3 += KERNEL1x3(in0, x * 4 + 3, &kernel[3], 4);
|
||||
ss0 += KERNEL1x3(in_1, x * 4 + 0, &kernel[6], 4);
|
||||
ss3 += KERNEL1x3(in_1, x * 4 + 3, &kernel[6], 4);
|
||||
v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3));
|
||||
memcpy(out + x * sizeof(v), &v, sizeof(v));
|
||||
}
|
||||
} 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 ss1 = offset;
|
||||
float ss2 = offset;
|
||||
UINT32 v;
|
||||
ss0 += KERNEL1x3(in1, x*4+0, &kernel[0], 4);
|
||||
ss1 += KERNEL1x3(in1, x*4+1, &kernel[0], 4);
|
||||
ss2 += KERNEL1x3(in1, x*4+2, &kernel[0], 4);
|
||||
ss0 += KERNEL1x3(in0, x*4+0, &kernel[3], 4);
|
||||
ss1 += KERNEL1x3(in0, x*4+1, &kernel[3], 4);
|
||||
ss2 += KERNEL1x3(in0, x*4+2, &kernel[3], 4);
|
||||
ss0 += KERNEL1x3(in_1, x*4+0, &kernel[6], 4);
|
||||
ss1 += KERNEL1x3(in_1, x*4+1, &kernel[6], 4);
|
||||
ss2 += KERNEL1x3(in_1, x*4+2, &kernel[6], 4);
|
||||
v = MAKE_UINT32(
|
||||
clip8(ss0), clip8(ss1), clip8(ss2), 0);
|
||||
ss0 += KERNEL1x3(in1, x * 4 + 0, &kernel[0], 4);
|
||||
ss1 += KERNEL1x3(in1, x * 4 + 1, &kernel[0], 4);
|
||||
ss2 += KERNEL1x3(in1, x * 4 + 2, &kernel[0], 4);
|
||||
ss0 += KERNEL1x3(in0, x * 4 + 0, &kernel[3], 4);
|
||||
ss1 += KERNEL1x3(in0, x * 4 + 1, &kernel[3], 4);
|
||||
ss2 += KERNEL1x3(in0, x * 4 + 2, &kernel[3], 4);
|
||||
ss0 += KERNEL1x3(in_1, x * 4 + 0, &kernel[6], 4);
|
||||
ss1 += KERNEL1x3(in_1, x * 4 + 1, &kernel[6], 4);
|
||||
ss2 += KERNEL1x3(in_1, x * 4 + 2, &kernel[6], 4);
|
||||
v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), 0);
|
||||
memcpy(out + x * sizeof(v), &v, sizeof(v));
|
||||
}
|
||||
} 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 ss1 = offset;
|
||||
float ss2 = offset;
|
||||
float ss3 = offset;
|
||||
UINT32 v;
|
||||
ss0 += KERNEL1x3(in1, x*4+0, &kernel[0], 4);
|
||||
ss1 += KERNEL1x3(in1, x*4+1, &kernel[0], 4);
|
||||
ss2 += KERNEL1x3(in1, x*4+2, &kernel[0], 4);
|
||||
ss3 += KERNEL1x3(in1, x*4+3, &kernel[0], 4);
|
||||
ss0 += KERNEL1x3(in0, x*4+0, &kernel[3], 4);
|
||||
ss1 += KERNEL1x3(in0, x*4+1, &kernel[3], 4);
|
||||
ss2 += KERNEL1x3(in0, x*4+2, &kernel[3], 4);
|
||||
ss3 += KERNEL1x3(in0, x*4+3, &kernel[3], 4);
|
||||
ss0 += KERNEL1x3(in_1, x*4+0, &kernel[6], 4);
|
||||
ss1 += KERNEL1x3(in_1, x*4+1, &kernel[6], 4);
|
||||
ss2 += KERNEL1x3(in_1, x*4+2, &kernel[6], 4);
|
||||
ss3 += KERNEL1x3(in_1, x*4+3, &kernel[6], 4);
|
||||
v = MAKE_UINT32(
|
||||
clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3));
|
||||
ss0 += KERNEL1x3(in1, x * 4 + 0, &kernel[0], 4);
|
||||
ss1 += KERNEL1x3(in1, x * 4 + 1, &kernel[0], 4);
|
||||
ss2 += KERNEL1x3(in1, x * 4 + 2, &kernel[0], 4);
|
||||
ss3 += KERNEL1x3(in1, x * 4 + 3, &kernel[0], 4);
|
||||
ss0 += KERNEL1x3(in0, x * 4 + 0, &kernel[3], 4);
|
||||
ss1 += KERNEL1x3(in0, x * 4 + 1, &kernel[3], 4);
|
||||
ss2 += KERNEL1x3(in0, x * 4 + 2, &kernel[3], 4);
|
||||
ss3 += KERNEL1x3(in0, x * 4 + 3, &kernel[3], 4);
|
||||
ss0 += KERNEL1x3(in_1, x * 4 + 0, &kernel[6], 4);
|
||||
ss1 += KERNEL1x3(in_1, x * 4 + 1, &kernel[6], 4);
|
||||
ss2 += KERNEL1x3(in_1, x * 4 + 2, &kernel[6], 4);
|
||||
ss3 += KERNEL1x3(in_1, x * 4 + 3, &kernel[6], 4);
|
||||
v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3));
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ImagingFilter5x5(Imaging imOut, Imaging im, const float* kernel,
|
||||
float offset)
|
||||
{
|
||||
#define KERNEL1x5(in0, x, kernel, d) ( \
|
||||
_i2f((UINT8) in0[x-d-d]) * (kernel)[0] + \
|
||||
_i2f((UINT8) in0[x-d]) * (kernel)[1] + \
|
||||
_i2f((UINT8) in0[x]) * (kernel)[2] + \
|
||||
_i2f((UINT8) in0[x+d]) * (kernel)[3] + \
|
||||
_i2f((UINT8) in0[x+d+d]) * (kernel)[4])
|
||||
ImagingFilter5x5(Imaging imOut, Imaging im, const float *kernel, float offset) {
|
||||
#define KERNEL1x5(in0, x, kernel, d) \
|
||||
(_i2f((UINT8)in0[x - d - d]) * (kernel)[0] + \
|
||||
_i2f((UINT8)in0[x - d]) * (kernel)[1] + _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;
|
||||
|
||||
|
@ -217,17 +207,17 @@ ImagingFilter5x5(Imaging imOut, Imaging im, const float* kernel,
|
|||
if (im->bands == 1) {
|
||||
// Add one time for rounding
|
||||
offset += 0.5;
|
||||
for (y = 2; y < im->ysize-2; y++) {
|
||||
UINT8* in_2 = (UINT8*) im->image[y-2];
|
||||
UINT8* in_1 = (UINT8*) im->image[y-1];
|
||||
UINT8* in0 = (UINT8*) im->image[y];
|
||||
UINT8* in1 = (UINT8*) im->image[y+1];
|
||||
UINT8* in2 = (UINT8*) im->image[y+2];
|
||||
UINT8* out = (UINT8*) imOut->image[y];
|
||||
for (y = 2; y < im->ysize - 2; y++) {
|
||||
UINT8 *in_2 = (UINT8 *)im->image[y - 2];
|
||||
UINT8 *in_1 = (UINT8 *)im->image[y - 1];
|
||||
UINT8 *in0 = (UINT8 *)im->image[y];
|
||||
UINT8 *in1 = (UINT8 *)im->image[y + 1];
|
||||
UINT8 *in2 = (UINT8 *)im->image[y + 2];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y];
|
||||
|
||||
out[0] = in0[0];
|
||||
out[1] = in0[1];
|
||||
for (x = 2; x < im->xsize-2; x++) {
|
||||
for (x = 2; x < im->xsize - 2; x++) {
|
||||
float ss = offset;
|
||||
ss += KERNEL1x5(in2, x, &kernel[0], 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);
|
||||
out[x] = clip8(ss);
|
||||
}
|
||||
out[x+0] = in0[x+0];
|
||||
out[x+1] = in0[x+1];
|
||||
out[x + 0] = in0[x + 0];
|
||||
out[x + 1] = in0[x + 1];
|
||||
}
|
||||
} else {
|
||||
// Add one time for rounding
|
||||
offset += 0.5;
|
||||
for (y = 2; y < im->ysize-2; y++) {
|
||||
UINT8* in_2 = (UINT8*) im->image[y-2];
|
||||
UINT8* in_1 = (UINT8*) im->image[y-1];
|
||||
UINT8* in0 = (UINT8*) im->image[y];
|
||||
UINT8* in1 = (UINT8*) im->image[y+1];
|
||||
UINT8* in2 = (UINT8*) im->image[y+2];
|
||||
UINT8* out = (UINT8*) imOut->image[y];
|
||||
for (y = 2; y < im->ysize - 2; y++) {
|
||||
UINT8 *in_2 = (UINT8 *)im->image[y - 2];
|
||||
UINT8 *in_1 = (UINT8 *)im->image[y - 1];
|
||||
UINT8 *in0 = (UINT8 *)im->image[y];
|
||||
UINT8 *in1 = (UINT8 *)im->image[y + 1];
|
||||
UINT8 *in2 = (UINT8 *)im->image[y + 2];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y];
|
||||
|
||||
memcpy(out, in0, sizeof(UINT32) * 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 ss3 = offset;
|
||||
UINT32 v;
|
||||
ss0 += KERNEL1x5(in2, x*4+0, &kernel[0], 4);
|
||||
ss3 += KERNEL1x5(in2, x*4+3, &kernel[0], 4);
|
||||
ss0 += KERNEL1x5(in1, x*4+0, &kernel[5], 4);
|
||||
ss3 += KERNEL1x5(in1, x*4+3, &kernel[5], 4);
|
||||
ss0 += KERNEL1x5(in0, x*4+0, &kernel[10], 4);
|
||||
ss3 += KERNEL1x5(in0, x*4+3, &kernel[10], 4);
|
||||
ss0 += KERNEL1x5(in_1, x*4+0, &kernel[15], 4);
|
||||
ss3 += KERNEL1x5(in_1, x*4+3, &kernel[15], 4);
|
||||
ss0 += KERNEL1x5(in_2, x*4+0, &kernel[20], 4);
|
||||
ss3 += KERNEL1x5(in_2, x*4+3, &kernel[20], 4);
|
||||
ss0 += KERNEL1x5(in2, x * 4 + 0, &kernel[0], 4);
|
||||
ss3 += KERNEL1x5(in2, x * 4 + 3, &kernel[0], 4);
|
||||
ss0 += KERNEL1x5(in1, x * 4 + 0, &kernel[5], 4);
|
||||
ss3 += KERNEL1x5(in1, x * 4 + 3, &kernel[5], 4);
|
||||
ss0 += KERNEL1x5(in0, x * 4 + 0, &kernel[10], 4);
|
||||
ss3 += KERNEL1x5(in0, x * 4 + 3, &kernel[10], 4);
|
||||
ss0 += KERNEL1x5(in_1, x * 4 + 0, &kernel[15], 4);
|
||||
ss3 += KERNEL1x5(in_1, x * 4 + 3, &kernel[15], 4);
|
||||
ss0 += KERNEL1x5(in_2, x * 4 + 0, &kernel[20], 4);
|
||||
ss3 += KERNEL1x5(in_2, x * 4 + 3, &kernel[20], 4);
|
||||
v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3));
|
||||
memcpy(out + x * sizeof(v), &v, sizeof(v));
|
||||
}
|
||||
} 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 ss1 = offset;
|
||||
float ss2 = offset;
|
||||
UINT32 v;
|
||||
ss0 += KERNEL1x5(in2, x*4+0, &kernel[0], 4);
|
||||
ss1 += KERNEL1x5(in2, x*4+1, &kernel[0], 4);
|
||||
ss2 += KERNEL1x5(in2, x*4+2, &kernel[0], 4);
|
||||
ss0 += KERNEL1x5(in1, x*4+0, &kernel[5], 4);
|
||||
ss1 += KERNEL1x5(in1, x*4+1, &kernel[5], 4);
|
||||
ss2 += KERNEL1x5(in1, x*4+2, &kernel[5], 4);
|
||||
ss0 += KERNEL1x5(in0, x*4+0, &kernel[10], 4);
|
||||
ss1 += KERNEL1x5(in0, x*4+1, &kernel[10], 4);
|
||||
ss2 += KERNEL1x5(in0, x*4+2, &kernel[10], 4);
|
||||
ss0 += KERNEL1x5(in_1, x*4+0, &kernel[15], 4);
|
||||
ss1 += KERNEL1x5(in_1, x*4+1, &kernel[15], 4);
|
||||
ss2 += KERNEL1x5(in_1, x*4+2, &kernel[15], 4);
|
||||
ss0 += KERNEL1x5(in_2, x*4+0, &kernel[20], 4);
|
||||
ss1 += KERNEL1x5(in_2, x*4+1, &kernel[20], 4);
|
||||
ss2 += KERNEL1x5(in_2, x*4+2, &kernel[20], 4);
|
||||
v = MAKE_UINT32(
|
||||
clip8(ss0), clip8(ss1), clip8(ss2), 0);
|
||||
ss0 += KERNEL1x5(in2, x * 4 + 0, &kernel[0], 4);
|
||||
ss1 += KERNEL1x5(in2, x * 4 + 1, &kernel[0], 4);
|
||||
ss2 += KERNEL1x5(in2, x * 4 + 2, &kernel[0], 4);
|
||||
ss0 += KERNEL1x5(in1, x * 4 + 0, &kernel[5], 4);
|
||||
ss1 += KERNEL1x5(in1, x * 4 + 1, &kernel[5], 4);
|
||||
ss2 += KERNEL1x5(in1, x * 4 + 2, &kernel[5], 4);
|
||||
ss0 += KERNEL1x5(in0, x * 4 + 0, &kernel[10], 4);
|
||||
ss1 += KERNEL1x5(in0, x * 4 + 1, &kernel[10], 4);
|
||||
ss2 += KERNEL1x5(in0, x * 4 + 2, &kernel[10], 4);
|
||||
ss0 += KERNEL1x5(in_1, x * 4 + 0, &kernel[15], 4);
|
||||
ss1 += KERNEL1x5(in_1, x * 4 + 1, &kernel[15], 4);
|
||||
ss2 += KERNEL1x5(in_1, x * 4 + 2, &kernel[15], 4);
|
||||
ss0 += KERNEL1x5(in_2, x * 4 + 0, &kernel[20], 4);
|
||||
ss1 += KERNEL1x5(in_2, x * 4 + 1, &kernel[20], 4);
|
||||
ss2 += KERNEL1x5(in_2, x * 4 + 2, &kernel[20], 4);
|
||||
v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), 0);
|
||||
memcpy(out + x * sizeof(v), &v, sizeof(v));
|
||||
}
|
||||
} 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 ss1 = offset;
|
||||
float ss2 = offset;
|
||||
float ss3 = offset;
|
||||
UINT32 v;
|
||||
ss0 += KERNEL1x5(in2, x*4+0, &kernel[0], 4);
|
||||
ss1 += KERNEL1x5(in2, x*4+1, &kernel[0], 4);
|
||||
ss2 += KERNEL1x5(in2, x*4+2, &kernel[0], 4);
|
||||
ss3 += KERNEL1x5(in2, x*4+3, &kernel[0], 4);
|
||||
ss0 += KERNEL1x5(in1, x*4+0, &kernel[5], 4);
|
||||
ss1 += KERNEL1x5(in1, x*4+1, &kernel[5], 4);
|
||||
ss2 += KERNEL1x5(in1, x*4+2, &kernel[5], 4);
|
||||
ss3 += KERNEL1x5(in1, x*4+3, &kernel[5], 4);
|
||||
ss0 += KERNEL1x5(in0, x*4+0, &kernel[10], 4);
|
||||
ss1 += KERNEL1x5(in0, x*4+1, &kernel[10], 4);
|
||||
ss2 += KERNEL1x5(in0, x*4+2, &kernel[10], 4);
|
||||
ss3 += KERNEL1x5(in0, x*4+3, &kernel[10], 4);
|
||||
ss0 += KERNEL1x5(in_1, x*4+0, &kernel[15], 4);
|
||||
ss1 += KERNEL1x5(in_1, x*4+1, &kernel[15], 4);
|
||||
ss2 += KERNEL1x5(in_1, x*4+2, &kernel[15], 4);
|
||||
ss3 += KERNEL1x5(in_1, x*4+3, &kernel[15], 4);
|
||||
ss0 += KERNEL1x5(in_2, x*4+0, &kernel[20], 4);
|
||||
ss1 += KERNEL1x5(in_2, x*4+1, &kernel[20], 4);
|
||||
ss2 += KERNEL1x5(in_2, x*4+2, &kernel[20], 4);
|
||||
ss3 += KERNEL1x5(in_2, x*4+3, &kernel[20], 4);
|
||||
v = MAKE_UINT32(
|
||||
clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3));
|
||||
ss0 += KERNEL1x5(in2, x * 4 + 0, &kernel[0], 4);
|
||||
ss1 += KERNEL1x5(in2, x * 4 + 1, &kernel[0], 4);
|
||||
ss2 += KERNEL1x5(in2, x * 4 + 2, &kernel[0], 4);
|
||||
ss3 += KERNEL1x5(in2, x * 4 + 3, &kernel[0], 4);
|
||||
ss0 += KERNEL1x5(in1, x * 4 + 0, &kernel[5], 4);
|
||||
ss1 += KERNEL1x5(in1, x * 4 + 1, &kernel[5], 4);
|
||||
ss2 += KERNEL1x5(in1, x * 4 + 2, &kernel[5], 4);
|
||||
ss3 += KERNEL1x5(in1, x * 4 + 3, &kernel[5], 4);
|
||||
ss0 += KERNEL1x5(in0, x * 4 + 0, &kernel[10], 4);
|
||||
ss1 += KERNEL1x5(in0, x * 4 + 1, &kernel[10], 4);
|
||||
ss2 += KERNEL1x5(in0, x * 4 + 2, &kernel[10], 4);
|
||||
ss3 += KERNEL1x5(in0, x * 4 + 3, &kernel[10], 4);
|
||||
ss0 += KERNEL1x5(in_1, x * 4 + 0, &kernel[15], 4);
|
||||
ss1 += KERNEL1x5(in_1, x * 4 + 1, &kernel[15], 4);
|
||||
ss2 += KERNEL1x5(in_1, x * 4 + 2, &kernel[15], 4);
|
||||
ss3 += KERNEL1x5(in_1, x * 4 + 3, &kernel[15], 4);
|
||||
ss0 += KERNEL1x5(in_2, x * 4 + 0, &kernel[20], 4);
|
||||
ss1 += KERNEL1x5(in_2, x * 4 + 1, &kernel[20], 4);
|
||||
ss2 += KERNEL1x5(in_2, x * 4 + 2, &kernel[20], 4);
|
||||
ss3 += KERNEL1x5(in_2, x * 4 + 3, &kernel[20], 4);
|
||||
v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3));
|
||||
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+1], im->image[y+1], im->linesize);
|
||||
memcpy(imOut->image[y + 1], im->image[y + 1], im->linesize);
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32* kernel,
|
||||
FLOAT32 offset)
|
||||
{
|
||||
ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32 *kernel, FLOAT32 offset) {
|
||||
Imaging imOut;
|
||||
ImagingSectionCookie cookie;
|
||||
|
||||
if ( ! im || im->type != IMAGING_TYPE_UINT8) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
if (!im || im->type != IMAGING_TYPE_UINT8) {
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
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) {
|
||||
return (Imaging) ImagingError_ValueError("bad kernel size");
|
||||
return (Imaging)ImagingError_ValueError("bad kernel size");
|
||||
}
|
||||
|
||||
imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize);
|
||||
|
@ -368,4 +355,3 @@ ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32* kernel,
|
|||
ImagingSectionLeave(&cookie);
|
||||
return imOut;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,26 +14,21 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#define I16(ptr) ((ptr)[0] + ((ptr)[1] << 8))
|
||||
|
||||
#define I16(ptr)\
|
||||
((ptr)[0] + ((ptr)[1] << 8))
|
||||
#define I32(ptr) ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24))
|
||||
|
||||
#define I32(ptr)\
|
||||
((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24))
|
||||
|
||||
#define ERR_IF_DATA_OOB(offset) \
|
||||
if ((data + (offset)) > ptr + bytes) {\
|
||||
state->errcode = IMAGING_CODEC_OVERRUN; \
|
||||
return -1; \
|
||||
}
|
||||
#define ERR_IF_DATA_OOB(offset) \
|
||||
if ((data + (offset)) > ptr + bytes) { \
|
||||
state->errcode = IMAGING_CODEC_OVERRUN; \
|
||||
return -1; \
|
||||
}
|
||||
|
||||
int
|
||||
ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes)
|
||||
{
|
||||
UINT8* ptr;
|
||||
ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
|
||||
UINT8 *ptr;
|
||||
int framesize;
|
||||
int c, chunks, advance;
|
||||
int l, lines;
|
||||
|
@ -62,36 +57,39 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
state->errcode = IMAGING_CODEC_OVERRUN;
|
||||
return -1;
|
||||
}
|
||||
if (I16(ptr+4) != 0xF1FA) {
|
||||
if (I16(ptr + 4) != 0xF1FA) {
|
||||
state->errcode = IMAGING_CODEC_UNKNOWN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
chunks = I16(ptr+6);
|
||||
chunks = I16(ptr + 6);
|
||||
ptr += 16;
|
||||
bytes -= 16;
|
||||
|
||||
/* Process subchunks */
|
||||
for (c = 0; c < chunks; c++) {
|
||||
UINT8* data;
|
||||
UINT8 *data;
|
||||
if (bytes < 10) {
|
||||
state->errcode = IMAGING_CODEC_OVERRUN;
|
||||
return -1;
|
||||
}
|
||||
data = ptr + 6;
|
||||
switch (I16(ptr+4)) {
|
||||
case 4: case 11:
|
||||
switch (I16(ptr + 4)) {
|
||||
case 4:
|
||||
case 11:
|
||||
/* FLI COLOR chunk */
|
||||
break; /* ignored; handled by Python code */
|
||||
case 7:
|
||||
/* FLI SS2 chunk (word delta) */
|
||||
/* 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++) {
|
||||
UINT8* local_buf = (UINT8*) im->image[y];
|
||||
UINT8 *local_buf = (UINT8 *)im->image[y];
|
||||
int p, packets;
|
||||
ERR_IF_DATA_OOB(2)
|
||||
packets = I16(data); data += 2;
|
||||
packets = I16(data);
|
||||
data += 2;
|
||||
while (packets & 0x8000) {
|
||||
/* flag word */
|
||||
if (packets & 0x4000) {
|
||||
|
@ -100,20 +98,21 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
state->errcode = IMAGING_CODEC_OVERRUN;
|
||||
return -1;
|
||||
}
|
||||
local_buf = (UINT8*) im->image[y];
|
||||
local_buf = (UINT8 *)im->image[y];
|
||||
} else {
|
||||
/* 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)
|
||||
packets = I16(data); data += 2;
|
||||
packets = I16(data);
|
||||
data += 2;
|
||||
}
|
||||
for (p = x = 0; p < packets; p++) {
|
||||
ERR_IF_DATA_OOB(2)
|
||||
x += data[0]; /* pixel skip */
|
||||
if (data[1] >= 128) {
|
||||
ERR_IF_DATA_OOB(4)
|
||||
i = 256-data[1]; /* run */
|
||||
i = 256 - data[1]; /* run */
|
||||
if (x + i + i > state->xsize) {
|
||||
break;
|
||||
}
|
||||
|
@ -123,11 +122,11 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
}
|
||||
data += 2 + 2;
|
||||
} else {
|
||||
i = 2 * (int) data[1]; /* chunk */
|
||||
i = 2 * (int)data[1]; /* chunk */
|
||||
if (x + i > state->xsize) {
|
||||
break;
|
||||
}
|
||||
ERR_IF_DATA_OOB(2+i)
|
||||
ERR_IF_DATA_OOB(2 + i)
|
||||
memcpy(local_buf + x, data + 2, i);
|
||||
data += 2 + i;
|
||||
x += i;
|
||||
|
@ -146,16 +145,18 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
case 12:
|
||||
/* FLI LC chunk (byte delta) */
|
||||
/* 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++) {
|
||||
UINT8* out = (UINT8*) im->image[y];
|
||||
ERR_IF_DATA_OOB(1)
|
||||
UINT8 *out = (UINT8 *)im->image[y];
|
||||
ERR_IF_DATA_OOB(1)
|
||||
int p, packets = *data++;
|
||||
for (p = x = 0; p < packets; p++, x += i) {
|
||||
ERR_IF_DATA_OOB(2)
|
||||
x += data[0]; /* skip pixels */
|
||||
if (data[1] & 0x80) {
|
||||
i = 256-data[1]; /* run */
|
||||
i = 256 - data[1]; /* run */
|
||||
if (x + i > state->xsize) {
|
||||
break;
|
||||
}
|
||||
|
@ -167,7 +168,7 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
if (x + i > state->xsize) {
|
||||
break;
|
||||
}
|
||||
ERR_IF_DATA_OOB(2+i)
|
||||
ERR_IF_DATA_OOB(2 + i)
|
||||
memcpy(out + x, data + 2, i);
|
||||
data += i + 2;
|
||||
}
|
||||
|
@ -192,7 +193,7 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
/* FLI BRUN chunk */
|
||||
/* OOB, ok, we've got 4 bytes min on entry */
|
||||
for (y = 0; y < state->ysize; y++) {
|
||||
UINT8* out = (UINT8*) im->image[y];
|
||||
UINT8 *out = (UINT8 *)im->image[y];
|
||||
data += 1; /* ignore packetcount byte */
|
||||
for (x = 0; x < state->xsize; x += i) {
|
||||
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) {
|
||||
break; /* safety first */
|
||||
}
|
||||
ERR_IF_DATA_OOB(i+1)
|
||||
ERR_IF_DATA_OOB(i + 1)
|
||||
memcpy(out + x, data + 1, i);
|
||||
data += i + 1;
|
||||
} else {
|
||||
|
@ -222,12 +223,12 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
break;
|
||||
case 16:
|
||||
/* COPY chunk */
|
||||
if (state->xsize > bytes/state->ysize) {
|
||||
if (state->xsize > bytes / state->ysize) {
|
||||
/* not enough data for frame */
|
||||
return ptr - buf; /* bytes consumed */
|
||||
}
|
||||
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);
|
||||
data += state->xsize;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -16,13 +16,10 @@
|
|||
* See the README file for details on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
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.*/
|
||||
|
||||
int x, y;
|
||||
|
@ -33,26 +30,26 @@ ImagingGetBBox(Imaging im, int bbox[4])
|
|||
bbox[1] = -1;
|
||||
bbox[2] = bbox[3] = 0;
|
||||
|
||||
#define GETBBOX(image, mask)\
|
||||
for (y = 0; y < im->ysize; y++) {\
|
||||
has_data = 0;\
|
||||
for (x = 0; x < im->xsize; x++) {\
|
||||
if (im->image[y][x] & mask) {\
|
||||
has_data = 1;\
|
||||
if (x < bbox[0]) {\
|
||||
bbox[0] = x;\
|
||||
}\
|
||||
if (x >= bbox[2]) {\
|
||||
bbox[2] = x+1;\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
if (has_data) {\
|
||||
if (bbox[1] < 0) {\
|
||||
bbox[1] = y;\
|
||||
}\
|
||||
bbox[3] = y+1;\
|
||||
}\
|
||||
#define GETBBOX(image, mask) \
|
||||
for (y = 0; y < im->ysize; y++) { \
|
||||
has_data = 0; \
|
||||
for (x = 0; x < im->xsize; x++) { \
|
||||
if (im->image[y][x] & mask) { \
|
||||
has_data = 1; \
|
||||
if (x < bbox[0]) { \
|
||||
bbox[0] = x; \
|
||||
} \
|
||||
if (x >= bbox[2]) { \
|
||||
bbox[2] = x + 1; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (has_data) { \
|
||||
if (bbox[1] < 0) { \
|
||||
bbox[1] = y; \
|
||||
} \
|
||||
bbox[3] = y + 1; \
|
||||
} \
|
||||
}
|
||||
|
||||
if (im->image8) {
|
||||
|
@ -60,16 +57,15 @@ ImagingGetBBox(Imaging im, int bbox[4])
|
|||
} else {
|
||||
INT32 mask = 0xffffffff;
|
||||
if (im->bands == 3) {
|
||||
((UINT8*) &mask)[3] = 0;
|
||||
} else if (strcmp(im->mode, "RGBa") == 0 ||
|
||||
strcmp(im->mode, "RGBA") == 0 ||
|
||||
strcmp(im->mode, "La") == 0 ||
|
||||
strcmp(im->mode, "LA") == 0 ||
|
||||
strcmp(im->mode, "PA") == 0) {
|
||||
((UINT8 *)&mask)[3] = 0;
|
||||
} else if (
|
||||
strcmp(im->mode, "RGBa") == 0 || strcmp(im->mode, "RGBA") == 0 ||
|
||||
strcmp(im->mode, "La") == 0 || strcmp(im->mode, "LA") == 0 ||
|
||||
strcmp(im->mode, "PA") == 0) {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
mask = 0x000000ff;
|
||||
mask = 0x000000ff;
|
||||
#else
|
||||
mask = 0xff000000;
|
||||
mask = 0xff000000;
|
||||
#endif
|
||||
}
|
||||
GETBBOX(image32, mask);
|
||||
|
@ -83,10 +79,8 @@ ImagingGetBBox(Imaging im, int bbox[4])
|
|||
return 1; /* ok */
|
||||
}
|
||||
|
||||
|
||||
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.*/
|
||||
|
||||
int x, y;
|
||||
|
@ -96,26 +90,26 @@ ImagingGetProjection(Imaging im, UINT8* xproj, UINT8* yproj)
|
|||
memset(xproj, 0, im->xsize);
|
||||
memset(yproj, 0, im->ysize);
|
||||
|
||||
#define GETPROJ(image, mask)\
|
||||
for (y = 0; y < im->ysize; y++) {\
|
||||
has_data = 0;\
|
||||
for (x = 0; x < im->xsize; x++) {\
|
||||
if (im->image[y][x] & mask) {\
|
||||
has_data = 1;\
|
||||
xproj[x] = 1;\
|
||||
}\
|
||||
}\
|
||||
if (has_data) {\
|
||||
yproj[y] = 1;\
|
||||
}\
|
||||
}
|
||||
#define GETPROJ(image, mask) \
|
||||
for (y = 0; y < im->ysize; y++) { \
|
||||
has_data = 0; \
|
||||
for (x = 0; x < im->xsize; x++) { \
|
||||
if (im->image[y][x] & mask) { \
|
||||
has_data = 1; \
|
||||
xproj[x] = 1; \
|
||||
} \
|
||||
} \
|
||||
if (has_data) { \
|
||||
yproj[y] = 1; \
|
||||
} \
|
||||
}
|
||||
|
||||
if (im->image8) {
|
||||
GETPROJ(image8, 0xff);
|
||||
} else {
|
||||
INT32 mask = 0xffffffff;
|
||||
if (im->bands == 3) {
|
||||
((UINT8*) &mask)[3] = 0;
|
||||
((UINT8 *)&mask)[3] = 0;
|
||||
}
|
||||
GETPROJ(image32, mask);
|
||||
}
|
||||
|
@ -123,16 +117,14 @@ ImagingGetProjection(Imaging im, UINT8* xproj, UINT8* yproj)
|
|||
return 1; /* ok */
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ImagingGetExtrema(Imaging im, void *extrema)
|
||||
{
|
||||
ImagingGetExtrema(Imaging im, void *extrema) {
|
||||
int x, y;
|
||||
INT32 imin, imax;
|
||||
FLOAT32 fmin, fmax;
|
||||
|
||||
if (im->bands != 1) {
|
||||
(void) ImagingError_ModeError();
|
||||
(void)ImagingError_ModeError();
|
||||
return -1; /* mismatch */
|
||||
}
|
||||
|
||||
|
@ -141,111 +133,109 @@ ImagingGetExtrema(Imaging im, void *extrema)
|
|||
}
|
||||
|
||||
switch (im->type) {
|
||||
case IMAGING_TYPE_UINT8:
|
||||
imin = imax = im->image8[0][0];
|
||||
for (y = 0; y < im->ysize; y++) {
|
||||
UINT8* in = im->image8[y];
|
||||
for (x = 0; x < im->xsize; x++) {
|
||||
if (imin > in[x]) {
|
||||
imin = in[x];
|
||||
} else if (imax < in[x]) {
|
||||
imax = in[x];
|
||||
case IMAGING_TYPE_UINT8:
|
||||
imin = imax = im->image8[0][0];
|
||||
for (y = 0; y < im->ysize; y++) {
|
||||
UINT8 *in = im->image8[y];
|
||||
for (x = 0; x < im->xsize; x++) {
|
||||
if (imin > in[x]) {
|
||||
imin = in[x];
|
||||
} else if (imax < in[x]) {
|
||||
imax = in[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
((UINT8*) extrema)[0] = (UINT8) imin;
|
||||
((UINT8*) extrema)[1] = (UINT8) imax;
|
||||
break;
|
||||
case IMAGING_TYPE_INT32:
|
||||
imin = imax = im->image32[0][0];
|
||||
for (y = 0; y < im->ysize; y++) {
|
||||
INT32* in = im->image32[y];
|
||||
for (x = 0; x < im->xsize; x++) {
|
||||
if (imin > in[x]) {
|
||||
imin = in[x];
|
||||
} else if (imax < in[x]) {
|
||||
imax = in[x];
|
||||
((UINT8 *)extrema)[0] = (UINT8)imin;
|
||||
((UINT8 *)extrema)[1] = (UINT8)imax;
|
||||
break;
|
||||
case IMAGING_TYPE_INT32:
|
||||
imin = imax = im->image32[0][0];
|
||||
for (y = 0; y < im->ysize; y++) {
|
||||
INT32 *in = im->image32[y];
|
||||
for (x = 0; x < im->xsize; x++) {
|
||||
if (imin > in[x]) {
|
||||
imin = in[x];
|
||||
} else if (imax < in[x]) {
|
||||
imax = in[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(extrema, &imin, sizeof(imin));
|
||||
memcpy(((char*)extrema) + sizeof(imin), &imax, sizeof(imax));
|
||||
break;
|
||||
case IMAGING_TYPE_FLOAT32:
|
||||
fmin = fmax = ((FLOAT32*) im->image32[0])[0];
|
||||
for (y = 0; y < im->ysize; y++) {
|
||||
FLOAT32* in = (FLOAT32*) im->image32[y];
|
||||
for (x = 0; x < im->xsize; x++) {
|
||||
if (fmin > in[x]) {
|
||||
fmin = in[x];
|
||||
} else if (fmax < in[x]) {
|
||||
fmax = in[x];
|
||||
memcpy(extrema, &imin, sizeof(imin));
|
||||
memcpy(((char *)extrema) + sizeof(imin), &imax, sizeof(imax));
|
||||
break;
|
||||
case IMAGING_TYPE_FLOAT32:
|
||||
fmin = fmax = ((FLOAT32 *)im->image32[0])[0];
|
||||
for (y = 0; y < im->ysize; y++) {
|
||||
FLOAT32 *in = (FLOAT32 *)im->image32[y];
|
||||
for (x = 0; x < im->xsize; x++) {
|
||||
if (fmin > in[x]) {
|
||||
fmin = in[x];
|
||||
} else if (fmax < in[x]) {
|
||||
fmax = in[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(extrema, &fmin, sizeof(fmin));
|
||||
memcpy(((char*)extrema) + sizeof(fmin), &fmax, sizeof(fmax));
|
||||
break;
|
||||
case IMAGING_TYPE_SPECIAL:
|
||||
if (strcmp(im->mode, "I;16") == 0) {
|
||||
UINT16 v;
|
||||
UINT8* pixel = *im->image8;
|
||||
memcpy(extrema, &fmin, sizeof(fmin));
|
||||
memcpy(((char *)extrema) + sizeof(fmin), &fmax, sizeof(fmax));
|
||||
break;
|
||||
case IMAGING_TYPE_SPECIAL:
|
||||
if (strcmp(im->mode, "I;16") == 0) {
|
||||
UINT16 v;
|
||||
UINT8 *pixel = *im->image8;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
v = pixel[0] + (pixel[1] << 8);
|
||||
v = pixel[0] + (pixel[1] << 8);
|
||||
#else
|
||||
memcpy(&v, pixel, sizeof(v));
|
||||
memcpy(&v, pixel, sizeof(v));
|
||||
#endif
|
||||
imin = imax = v;
|
||||
for (y = 0; y < im->ysize; y++) {
|
||||
for (x = 0; x < im->xsize; x++) {
|
||||
pixel = (UINT8*)im->image[y] + x * sizeof(v);
|
||||
imin = imax = v;
|
||||
for (y = 0; y < im->ysize; y++) {
|
||||
for (x = 0; x < im->xsize; x++) {
|
||||
pixel = (UINT8 *)im->image[y] + x * sizeof(v);
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
v = pixel[0] + (pixel[1] << 8);
|
||||
v = pixel[0] + (pixel[1] << 8);
|
||||
#else
|
||||
memcpy(&v, pixel, sizeof(v));
|
||||
memcpy(&v, pixel, sizeof(v));
|
||||
#endif
|
||||
if (imin > v) {
|
||||
imin = v;
|
||||
} else if (imax < v) {
|
||||
imax = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
v = (UINT16) imin;
|
||||
memcpy(extrema, &v, sizeof(v));
|
||||
v = (UINT16) imax;
|
||||
memcpy(((char*)extrema) + sizeof(v), &v, sizeof(v));
|
||||
break;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
default:
|
||||
(void) ImagingError_ModeError();
|
||||
return -1;
|
||||
if (imin > v) {
|
||||
imin = v;
|
||||
} else if (imax < v) {
|
||||
imax = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
v = (UINT16)imin;
|
||||
memcpy(extrema, &v, sizeof(v));
|
||||
v = (UINT16)imax;
|
||||
memcpy(((char *)extrema) + sizeof(v), &v, sizeof(v));
|
||||
break;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
default:
|
||||
(void)ImagingError_ModeError();
|
||||
return -1;
|
||||
}
|
||||
return 1; /* ok */
|
||||
}
|
||||
|
||||
|
||||
/* 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*
|
||||
ImagingGetColors(Imaging im, int maxcolors, int* size)
|
||||
{
|
||||
ImagingColorItem *
|
||||
ImagingGetColors(Imaging im, int maxcolors, int *size) {
|
||||
/* FIXME: add support for 8-bit images */
|
||||
return getcolors32(im, maxcolors, size);
|
||||
}
|
||||
|
||||
static ImagingColorItem*
|
||||
getcolors32(Imaging im, int maxcolors, int* size)
|
||||
{
|
||||
static ImagingColorItem *
|
||||
getcolors32(Imaging im, int maxcolors, int *size) {
|
||||
unsigned int h;
|
||||
unsigned int i, incr;
|
||||
int colors;
|
||||
INT32 pixel_mask;
|
||||
int x, y;
|
||||
ImagingColorItem* table;
|
||||
ImagingColorItem* v;
|
||||
ImagingColorItem *table;
|
||||
ImagingColorItem *v;
|
||||
|
||||
unsigned int code_size;
|
||||
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 */
|
||||
|
||||
static int SIZES[] = {
|
||||
4,3, 8,3, 16,3, 32,5, 64,3, 128,3, 256,29, 512,17, 1024,9, 2048,5,
|
||||
4096,83, 8192,27, 16384,43, 32768,3, 65536,45, 131072,9, 262144,39,
|
||||
524288,39, 1048576,9, 2097152,5, 4194304,3, 8388608,33, 16777216,27,
|
||||
33554432,9, 67108864,71, 134217728,39, 268435456,9, 536870912,5,
|
||||
1073741824,83, 0
|
||||
};
|
||||
4, 3, 8, 3, 16, 3, 32, 5, 64, 3,
|
||||
128, 3, 256, 29, 512, 17, 1024, 9, 2048, 5,
|
||||
4096, 83, 8192, 27, 16384, 43, 32768, 3, 65536, 45,
|
||||
131072, 9, 262144, 39, 524288, 39, 1048576, 9, 2097152, 5,
|
||||
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;
|
||||
|
||||
for (i = 0; SIZES[i]; i += 2) {
|
||||
if (SIZES[i] > maxcolors) {
|
||||
code_size = SIZES[i];
|
||||
code_poly = SIZES[i+1];
|
||||
code_poly = SIZES[i + 1];
|
||||
code_mask = code_size - 1;
|
||||
break;
|
||||
}
|
||||
|
@ -292,13 +282,13 @@ getcolors32(Imaging im, int maxcolors, int* size)
|
|||
|
||||
pixel_mask = 0xffffffff;
|
||||
if (im->bands == 3) {
|
||||
((UINT8*) &pixel_mask)[3] = 0;
|
||||
((UINT8 *)&pixel_mask)[3] = 0;
|
||||
}
|
||||
|
||||
colors = 0;
|
||||
|
||||
for (y = 0; y < im->ysize; y++) {
|
||||
INT32* p = im->image32[y];
|
||||
INT32 *p = im->image32[y];
|
||||
for (x = 0; x < im->xsize; x++) {
|
||||
INT32 pixel = p[x] & pixel_mask;
|
||||
h = (pixel); /* null hashing */
|
||||
|
@ -309,7 +299,8 @@ getcolors32(Imaging im, int maxcolors, int* size)
|
|||
if (colors++ == maxcolors) {
|
||||
goto overflow;
|
||||
}
|
||||
v->x = x; v->y = y;
|
||||
v->x = x;
|
||||
v->y = y;
|
||||
v->pixel = pixel;
|
||||
v->count = 1;
|
||||
continue;
|
||||
|
@ -329,7 +320,8 @@ getcolors32(Imaging im, int maxcolors, int* size)
|
|||
if (colors++ == maxcolors) {
|
||||
goto overflow;
|
||||
}
|
||||
v->x = x; v->y = y;
|
||||
v->x = x;
|
||||
v->y = y;
|
||||
v->pixel = pixel;
|
||||
v->count = 1;
|
||||
break;
|
||||
|
@ -348,7 +340,7 @@ getcolors32(Imaging im, int maxcolors, int* size)
|
|||
overflow:
|
||||
|
||||
/* 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 (x != y) {
|
||||
table[y] = table[x];
|
||||
|
|
|
@ -7,17 +7,14 @@
|
|||
* Copyright (c) Fredrik Lundh 1995-96.
|
||||
*/
|
||||
|
||||
|
||||
/* Max size for a LZW code word. */
|
||||
|
||||
#define GIFBITS 12
|
||||
|
||||
#define GIFTABLE (1<<GIFBITS)
|
||||
#define GIFBUFFER (1<<GIFBITS)
|
||||
#define GIFBITS 12
|
||||
|
||||
#define GIFTABLE (1 << GIFBITS)
|
||||
#define GIFBUFFER (1 << GIFBITS)
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* CONFIGURATION */
|
||||
|
||||
/* Initial number of bits. The caller should clear all fields in
|
||||
|
@ -65,15 +62,13 @@ typedef struct {
|
|||
|
||||
} GIFDECODERSTATE;
|
||||
|
||||
typedef struct GIFENCODERBLOCK_T
|
||||
{
|
||||
typedef struct GIFENCODERBLOCK_T {
|
||||
struct GIFENCODERBLOCK_T *next;
|
||||
int size;
|
||||
UINT8 data[255];
|
||||
} GIFENCODERBLOCK;
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* CONFIGURATION */
|
||||
|
||||
/* Initial number of bits. The caller should clear all fields in
|
||||
|
@ -96,13 +91,13 @@ typedef struct {
|
|||
int bitcount;
|
||||
|
||||
/* Output buffer list (linked list) */
|
||||
GIFENCODERBLOCK* block; /* current block */
|
||||
GIFENCODERBLOCK* flush; /* output queue */
|
||||
GIFENCODERBLOCK* free; /* if not null, use this */
|
||||
GIFENCODERBLOCK *block; /* current block */
|
||||
GIFENCODERBLOCK *flush; /* output queue */
|
||||
GIFENCODERBLOCK *free; /* if not null, use this */
|
||||
|
||||
/* Fields used for run-length encoding */
|
||||
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 lastcode;
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -29,48 +28,44 @@
|
|||
|
||||
#include "Gif.h"
|
||||
|
||||
|
||||
#define NEWLINE(state, context) {\
|
||||
state->x = 0;\
|
||||
state->y += context->step;\
|
||||
while (state->y >= state->ysize)\
|
||||
switch (context->interlace) {\
|
||||
case 1:\
|
||||
context->repeat = state->y = 4;\
|
||||
context->interlace = 2;\
|
||||
break;\
|
||||
case 2:\
|
||||
context->step = 4;\
|
||||
context->repeat = state->y = 2;\
|
||||
context->interlace = 3;\
|
||||
break;\
|
||||
case 3:\
|
||||
context->step = 2;\
|
||||
context->repeat = state->y = 1;\
|
||||
context->interlace = 0;\
|
||||
break;\
|
||||
default:\
|
||||
return -1;\
|
||||
}\
|
||||
if (state->y < state->ysize) {\
|
||||
out = im->image8[state->y + state->yoff] + state->xoff;\
|
||||
}\
|
||||
}
|
||||
|
||||
#define NEWLINE(state, context) \
|
||||
{ \
|
||||
state->x = 0; \
|
||||
state->y += context->step; \
|
||||
while (state->y >= state->ysize) switch (context->interlace) { \
|
||||
case 1: \
|
||||
context->repeat = state->y = 4; \
|
||||
context->interlace = 2; \
|
||||
break; \
|
||||
case 2: \
|
||||
context->step = 4; \
|
||||
context->repeat = state->y = 2; \
|
||||
context->interlace = 3; \
|
||||
break; \
|
||||
case 3: \
|
||||
context->step = 2; \
|
||||
context->repeat = state->y = 1; \
|
||||
context->interlace = 0; \
|
||||
break; \
|
||||
default: \
|
||||
return -1; \
|
||||
} \
|
||||
if (state->y < state->ysize) { \
|
||||
out = im->image8[state->y + state->yoff] + state->xoff; \
|
||||
} \
|
||||
}
|
||||
|
||||
int
|
||||
ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t bytes)
|
||||
{
|
||||
UINT8* p;
|
||||
UINT8* out;
|
||||
ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes) {
|
||||
UINT8 *p;
|
||||
UINT8 *out;
|
||||
int c, i;
|
||||
int thiscode;
|
||||
GIFDECODERSTATE *context = (GIFDECODERSTATE*) state->context;
|
||||
GIFDECODERSTATE *context = (GIFDECODERSTATE *)state->context;
|
||||
|
||||
UINT8 *ptr = buffer;
|
||||
|
||||
if (!state->state) {
|
||||
|
||||
/* Initialise state */
|
||||
if (context->bits < 0 || context->bits > 12) {
|
||||
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;
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (state->state == 1) {
|
||||
|
||||
/* First free entry in table */
|
||||
context->next = context->clear + 2;
|
||||
|
||||
|
@ -115,7 +108,6 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
|
|||
}
|
||||
|
||||
if (context->bufferindex < GIFBUFFER) {
|
||||
|
||||
/* Return whole buffer in one chunk */
|
||||
i = GIFBUFFER - context->bufferindex;
|
||||
p = &context->buffer[context->bufferindex];
|
||||
|
@ -123,24 +115,21 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
|
|||
context->bufferindex = GIFBUFFER;
|
||||
|
||||
} else {
|
||||
|
||||
/* Get current symbol */
|
||||
|
||||
while (context->bitcount < context->codesize) {
|
||||
|
||||
if (context->blocksize > 0) {
|
||||
|
||||
/* Read next byte */
|
||||
c = *ptr++; bytes--;
|
||||
c = *ptr++;
|
||||
bytes--;
|
||||
|
||||
context->blocksize--;
|
||||
|
||||
/* New bits are shifted in from from the left. */
|
||||
context->bitbuffer |= (INT32) c << context->bitcount;
|
||||
context->bitbuffer |= (INT32)c << context->bitcount;
|
||||
context->bitcount += 8;
|
||||
|
||||
} else {
|
||||
|
||||
/* New GIF 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;
|
||||
}
|
||||
c = *ptr;
|
||||
if (bytes < c+1) {
|
||||
if (bytes < c + 1) {
|
||||
return ptr - buffer;
|
||||
}
|
||||
|
||||
context->blocksize = c;
|
||||
|
||||
ptr++; bytes--;
|
||||
|
||||
ptr++;
|
||||
bytes--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract current symbol from bit buffer. */
|
||||
c = (int) context->bitbuffer & context->codemask;
|
||||
c = (int)context->bitbuffer & context->codemask;
|
||||
|
||||
/* Adjust buffer */
|
||||
context->bitbuffer >>= context->codesize;
|
||||
|
@ -185,7 +174,6 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
|
|||
p = &context->lastdata;
|
||||
|
||||
if (state->state == 2) {
|
||||
|
||||
/* First valid symbol after clear; use as is */
|
||||
if (c > context->clear) {
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
|
@ -196,7 +184,6 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
|
|||
state->state = 3;
|
||||
|
||||
} else {
|
||||
|
||||
thiscode = c;
|
||||
|
||||
if (c > context->next) {
|
||||
|
@ -205,7 +192,6 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
|
|||
}
|
||||
|
||||
if (c == context->next) {
|
||||
|
||||
/* c == next is allowed. not sure why. */
|
||||
|
||||
if (context->bufferindex <= 0) {
|
||||
|
@ -213,15 +199,12 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
|
|||
return -1;
|
||||
}
|
||||
|
||||
context->buffer[--context->bufferindex] =
|
||||
context->lastdata;
|
||||
context->buffer[--context->bufferindex] = context->lastdata;
|
||||
|
||||
c = context->lastcode;
|
||||
|
||||
}
|
||||
|
||||
while (c >= context->clear) {
|
||||
|
||||
/* Copy data string to buffer (beginning from right) */
|
||||
|
||||
if (context->bufferindex <= 0 || c >= GIFTABLE) {
|
||||
|
@ -229,8 +212,7 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
|
|||
return -1;
|
||||
}
|
||||
|
||||
context->buffer[--context->bufferindex] =
|
||||
context->data[c];
|
||||
context->buffer[--context->bufferindex] = context->data[c];
|
||||
|
||||
c = context->link[c];
|
||||
}
|
||||
|
@ -238,26 +220,22 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
|
|||
context->lastdata = c;
|
||||
|
||||
if (context->next < GIFTABLE) {
|
||||
|
||||
/* We'll only add this symbol if we have room
|
||||
for it (take advise, Netscape!) */
|
||||
context->data[context->next] = c;
|
||||
context->link[context->next] = context->lastcode;
|
||||
|
||||
if (context->next == context->codemask &&
|
||||
context->codesize < GIFBITS) {
|
||||
|
||||
context->codesize < GIFBITS) {
|
||||
/* Expand code size */
|
||||
context->codesize++;
|
||||
context->codemask = (1 << context->codesize) - 1;
|
||||
}
|
||||
|
||||
context->next++;
|
||||
|
||||
}
|
||||
|
||||
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??? */
|
||||
|
||||
if (i == 1) {
|
||||
if (state->x < state->xsize-1) {
|
||||
if (state->x < state->xsize - 1) {
|
||||
/* Single pixel, not at the end of the line. */
|
||||
*out++ = p[0];
|
||||
state->x++;
|
||||
|
@ -282,7 +260,7 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t
|
|||
} else if (state->x + i <= state->xsize) {
|
||||
/* This string fits into current line. */
|
||||
memcpy(out, p, i);
|
||||
out += i;
|
||||
out += i;
|
||||
state->x += i;
|
||||
if (state->x == state->xsize) {
|
||||
NEWLINE(state, context);
|
||||
|
|
|
@ -35,12 +35,11 @@ enum { INIT, ENCODE, ENCODE_EOF, FLUSH, EXIT };
|
|||
necessary. */
|
||||
|
||||
static inline int
|
||||
emit(GIFENCODERSTATE *context, int byte)
|
||||
{
|
||||
emit(GIFENCODERSTATE *context, int byte) {
|
||||
/* write a byte to the output buffer */
|
||||
|
||||
if (!context->block || context->block->size == 255) {
|
||||
GIFENCODERBLOCK* block;
|
||||
GIFENCODERBLOCK *block;
|
||||
|
||||
/* no room in the current block (or no current block);
|
||||
allocate a new one */
|
||||
|
@ -74,7 +73,6 @@ emit(GIFENCODERSTATE *context, int byte)
|
|||
block->next = NULL;
|
||||
|
||||
context->block = 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
|
||||
sure it's inlined on all platforms */
|
||||
|
||||
#define EMIT(code) {\
|
||||
context->bitbuffer |= ((INT32) (code)) << context->bitcount;\
|
||||
context->bitcount += 9;\
|
||||
while (context->bitcount >= 8) {\
|
||||
if (!emit(context, (UINT8) context->bitbuffer)) {\
|
||||
state->errcode = IMAGING_CODEC_MEMORY;\
|
||||
return 0;\
|
||||
}\
|
||||
context->bitbuffer >>= 8;\
|
||||
context->bitcount -= 8;\
|
||||
}\
|
||||
}
|
||||
#define EMIT(code) \
|
||||
{ \
|
||||
context->bitbuffer |= ((INT32)(code)) << context->bitcount; \
|
||||
context->bitcount += 9; \
|
||||
while (context->bitcount >= 8) { \
|
||||
if (!emit(context, (UINT8)context->bitbuffer)) { \
|
||||
state->errcode = IMAGING_CODEC_MEMORY; \
|
||||
return 0; \
|
||||
} \
|
||||
context->bitbuffer >>= 8; \
|
||||
context->bitcount -= 8; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* write a run. we use a combination of literals and combinations of
|
||||
literals. this can give quite decent compression for images with
|
||||
long stretches of identical pixels. but remember: if you want
|
||||
really good compression, use another file format. */
|
||||
|
||||
#define EMIT_RUN(label) {\
|
||||
label:\
|
||||
while (context->count > 0) {\
|
||||
int run = 2;\
|
||||
EMIT(context->last);\
|
||||
context->count--;\
|
||||
if (state->count++ == LAST_CODE) {\
|
||||
EMIT(CLEAR_CODE);\
|
||||
state->count = FIRST_CODE;\
|
||||
goto label;\
|
||||
}\
|
||||
while (context->count >= run) {\
|
||||
EMIT(state->count - 1);\
|
||||
context->count -= run;\
|
||||
run++;\
|
||||
if (state->count++ == LAST_CODE) {\
|
||||
EMIT(CLEAR_CODE);\
|
||||
state->count = FIRST_CODE;\
|
||||
goto label;\
|
||||
}\
|
||||
}\
|
||||
if (context->count > 1) {\
|
||||
EMIT(state->count - 1 - (run - context->count));\
|
||||
context->count = 0;\
|
||||
if (state->count++ == LAST_CODE) {\
|
||||
EMIT(CLEAR_CODE);\
|
||||
state->count = FIRST_CODE;\
|
||||
}\
|
||||
break;\
|
||||
}\
|
||||
}\
|
||||
}
|
||||
#define EMIT_RUN(label) \
|
||||
{ \
|
||||
label: \
|
||||
while (context->count > 0) { \
|
||||
int run = 2; \
|
||||
EMIT(context->last); \
|
||||
context->count--; \
|
||||
if (state->count++ == LAST_CODE) { \
|
||||
EMIT(CLEAR_CODE); \
|
||||
state->count = FIRST_CODE; \
|
||||
goto label; \
|
||||
} \
|
||||
while (context->count >= run) { \
|
||||
EMIT(state->count - 1); \
|
||||
context->count -= run; \
|
||||
run++; \
|
||||
if (state->count++ == LAST_CODE) { \
|
||||
EMIT(CLEAR_CODE); \
|
||||
state->count = FIRST_CODE; \
|
||||
goto label; \
|
||||
} \
|
||||
} \
|
||||
if (context->count > 1) { \
|
||||
EMIT(state->count - 1 - (run - context->count)); \
|
||||
context->count = 0; \
|
||||
if (state->count++ == LAST_CODE) { \
|
||||
EMIT(CLEAR_CODE); \
|
||||
state->count = FIRST_CODE; \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
int
|
||||
ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||
{
|
||||
UINT8* ptr;
|
||||
ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
|
||||
UINT8 *ptr;
|
||||
int this;
|
||||
|
||||
GIFENCODERBLOCK* block;
|
||||
GIFENCODERSTATE *context = (GIFENCODERSTATE*) state->context;
|
||||
GIFENCODERBLOCK *block;
|
||||
GIFENCODERSTATE *context = (GIFENCODERSTATE *)state->context;
|
||||
|
||||
if (!state->state) {
|
||||
|
||||
/* place a clear code in the output buffer */
|
||||
context->bitbuffer = CLEAR_CODE;
|
||||
context->bitcount = 9;
|
||||
|
@ -167,22 +165,17 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
if (state->xsize <= 0 || state->ysize <= 0) {
|
||||
state->state = ENCODE_EOF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ptr = buf;
|
||||
|
||||
for (;;)
|
||||
|
||||
switch (state->state) {
|
||||
|
||||
for (;;) switch (state->state) {
|
||||
case INIT:
|
||||
case ENCODE:
|
||||
|
||||
/* identify and store a run of pixels */
|
||||
|
||||
if (state->x == 0 || state->x >= state->xsize) {
|
||||
|
||||
if (!context->interlace && state->y >= state->ysize) {
|
||||
state->state = ENCODE_EOF;
|
||||
break;
|
||||
|
@ -196,9 +189,9 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
/* get another line of data */
|
||||
state->shuffle(
|
||||
state->buffer,
|
||||
(UINT8*) im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize, state->xsize
|
||||
);
|
||||
(UINT8 *)im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize,
|
||||
state->xsize);
|
||||
|
||||
state->x = 0;
|
||||
|
||||
|
@ -231,7 +224,6 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
/* just make sure we don't loop forever */
|
||||
context->interlace = 0;
|
||||
}
|
||||
|
||||
}
|
||||
/* Potential special case for xsize==1 */
|
||||
if (state->x < state->xsize) {
|
||||
|
@ -250,7 +242,6 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
}
|
||||
break;
|
||||
|
||||
|
||||
case ENCODE_EOF:
|
||||
|
||||
/* write the final run */
|
||||
|
@ -261,7 +252,7 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
|
||||
/* empty the bit buffer */
|
||||
while (context->bitcount > 0) {
|
||||
if (!emit(context, (UINT8) context->bitbuffer)) {
|
||||
if (!emit(context, (UINT8)context->bitbuffer)) {
|
||||
state->errcode = IMAGING_CODEC_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
|
@ -271,7 +262,7 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
|
||||
/* flush the last block, and exit */
|
||||
if (context->block) {
|
||||
GIFENCODERBLOCK* block;
|
||||
GIFENCODERBLOCK *block;
|
||||
block = context->flush;
|
||||
while (block && block->next) {
|
||||
block = block->next;
|
||||
|
@ -291,45 +282,41 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
case EXIT:
|
||||
case FLUSH:
|
||||
|
||||
while (context->flush) {
|
||||
|
||||
/* get a block from the flush queue */
|
||||
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;
|
||||
while (context->flush) {
|
||||
/* get a block from the flush queue */
|
||||
block = context->flush;
|
||||
|
||||
if (block->size > 0) {
|
||||
/* make sure it fits into the output buffer */
|
||||
if (bytes < block->size + 1) {
|
||||
return ptr - buf;
|
||||
}
|
||||
|
||||
context->flush = block->next;
|
||||
|
||||
if (context->free) {
|
||||
free(context->free);
|
||||
}
|
||||
context->free = block;
|
||||
ptr[0] = block->size;
|
||||
memcpy(ptr + 1, block->data, block->size);
|
||||
|
||||
ptr += block->size + 1;
|
||||
bytes -= block->size + 1;
|
||||
}
|
||||
|
||||
if (state->state == EXIT) {
|
||||
/* this was the last block! */
|
||||
if (context->free) {
|
||||
free(context->free);
|
||||
}
|
||||
state->errcode = IMAGING_CODEC_END;
|
||||
return ptr - buf;
|
||||
}
|
||||
context->flush = block->next;
|
||||
|
||||
state->state = ENCODE;
|
||||
break;
|
||||
}
|
||||
if (context->free) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,23 +13,22 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#define HEX(v) ((v >= '0' && v <= '9') ? v - '0' :\
|
||||
(v >= 'a' && v <= 'f') ? v - 'a' + 10 :\
|
||||
(v >= 'A' && v <= 'F') ? v - 'A' + 10 : -1)
|
||||
#define HEX(v) \
|
||||
((v >= '0' && v <= '9') ? v - '0' \
|
||||
: (v >= 'a' && v <= 'f') ? v - 'a' + 10 \
|
||||
: (v >= 'A' && v <= 'F') ? v - 'A' + 10 \
|
||||
: -1)
|
||||
|
||||
int
|
||||
ImagingHexDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes)
|
||||
{
|
||||
UINT8* ptr;
|
||||
ImagingHexDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
|
||||
UINT8 *ptr;
|
||||
int a, b;
|
||||
|
||||
ptr = buf;
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (bytes < 2) {
|
||||
return ptr - buf;
|
||||
}
|
||||
|
@ -38,22 +37,19 @@ ImagingHexDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
b = HEX(ptr[1]);
|
||||
|
||||
if (a < 0 || b < 0) {
|
||||
|
||||
ptr++;
|
||||
bytes--;
|
||||
|
||||
} else {
|
||||
|
||||
ptr += 2;
|
||||
bytes -= 2;
|
||||
|
||||
state->buffer[state->x] = (a<<4) + b;
|
||||
state->buffer[state->x] = (a << 4) + b;
|
||||
|
||||
if (++state->x >= state->bytes) {
|
||||
|
||||
/* Got a full line, unpack it */
|
||||
state->shuffle((UINT8*) im->image[state->y], state->buffer,
|
||||
state->xsize);
|
||||
state->shuffle(
|
||||
(UINT8 *)im->image[state->y], state->buffer, state->xsize);
|
||||
|
||||
state->x = 0;
|
||||
|
||||
|
@ -62,7 +58,6 @@ ImagingHexDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,8 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
/* HISTOGRAM */
|
||||
/* --------------------------------------------------------------------
|
||||
* Take a histogram of an image. Returns a histogram object containing
|
||||
|
@ -27,8 +25,7 @@
|
|||
*/
|
||||
|
||||
void
|
||||
ImagingHistogramDelete(ImagingHistogram h)
|
||||
{
|
||||
ImagingHistogramDelete(ImagingHistogram h) {
|
||||
if (h) {
|
||||
if (h->histogram) {
|
||||
free(h->histogram);
|
||||
|
@ -38,31 +35,29 @@ ImagingHistogramDelete(ImagingHistogram h)
|
|||
}
|
||||
|
||||
ImagingHistogram
|
||||
ImagingHistogramNew(Imaging im)
|
||||
{
|
||||
ImagingHistogramNew(Imaging im) {
|
||||
ImagingHistogram h;
|
||||
|
||||
/* Create histogram descriptor */
|
||||
h = calloc(1, sizeof(struct ImagingHistogramInstance));
|
||||
if (!h) {
|
||||
return (ImagingHistogram) ImagingError_MemoryError();
|
||||
return (ImagingHistogram)ImagingError_MemoryError();
|
||||
}
|
||||
strncpy(h->mode, im->mode, IMAGING_MODE_LENGTH-1);
|
||||
h->mode[IMAGING_MODE_LENGTH-1] = 0;
|
||||
strncpy(h->mode, im->mode, IMAGING_MODE_LENGTH - 1);
|
||||
h->mode[IMAGING_MODE_LENGTH - 1] = 0;
|
||||
|
||||
h->bands = im->bands;
|
||||
h->histogram = calloc(im->pixelsize, 256 * sizeof(long));
|
||||
if (!h->histogram) {
|
||||
free(h);
|
||||
return (ImagingHistogram) ImagingError_MemoryError();
|
||||
return (ImagingHistogram)ImagingError_MemoryError();
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
ImagingHistogram
|
||||
ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax)
|
||||
{
|
||||
ImagingGetHistogram(Imaging im, Imaging imMask, void *minmax) {
|
||||
ImagingSectionCookie cookie;
|
||||
int x, y, i;
|
||||
ImagingHistogram h;
|
||||
|
@ -107,13 +102,13 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax)
|
|||
}
|
||||
ImagingSectionEnter(&cookie);
|
||||
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++) {
|
||||
if (imMask->image8[y][x] != 0) {
|
||||
h->histogram[(*in++)]++;
|
||||
h->histogram[(*in++)+256]++;
|
||||
h->histogram[(*in++)+512]++;
|
||||
h->histogram[(*in++)+768]++;
|
||||
h->histogram[(*in++) + 256]++;
|
||||
h->histogram[(*in++) + 512]++;
|
||||
h->histogram[(*in++) + 768]++;
|
||||
} else {
|
||||
in += 4;
|
||||
}
|
||||
|
@ -136,12 +131,12 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax)
|
|||
case IMAGING_TYPE_UINT8:
|
||||
ImagingSectionEnter(&cookie);
|
||||
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++) {
|
||||
h->histogram[(*in++)]++;
|
||||
h->histogram[(*in++)+256]++;
|
||||
h->histogram[(*in++)+512]++;
|
||||
h->histogram[(*in++)+768]++;
|
||||
h->histogram[(*in++) + 256]++;
|
||||
h->histogram[(*in++) + 512]++;
|
||||
h->histogram[(*in++) + 768]++;
|
||||
}
|
||||
}
|
||||
ImagingSectionLeave(&cookie);
|
||||
|
@ -155,16 +150,16 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax)
|
|||
break;
|
||||
}
|
||||
memcpy(&imin, minmax, sizeof(imin));
|
||||
memcpy(&imax, ((char*)minmax) + sizeof(imin), sizeof(imax));
|
||||
memcpy(&imax, ((char *)minmax) + sizeof(imin), sizeof(imax));
|
||||
if (imin >= imax) {
|
||||
break;
|
||||
}
|
||||
ImagingSectionEnter(&cookie);
|
||||
scale = 255.0F / (imax - imin);
|
||||
for (y = 0; y < im->ysize; y++) {
|
||||
INT32* in = im->image32[y];
|
||||
INT32 *in = im->image32[y];
|
||||
for (x = 0; x < im->xsize; x++) {
|
||||
i = (int) (((*in++)-imin)*scale);
|
||||
i = (int)(((*in++) - imin) * scale);
|
||||
if (i >= 0 && i < 256) {
|
||||
h->histogram[i]++;
|
||||
}
|
||||
|
@ -181,16 +176,16 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax)
|
|||
break;
|
||||
}
|
||||
memcpy(&fmin, minmax, sizeof(fmin));
|
||||
memcpy(&fmax, ((char*)minmax) + sizeof(fmin), sizeof(fmax));
|
||||
memcpy(&fmax, ((char *)minmax) + sizeof(fmin), sizeof(fmax));
|
||||
if (fmin >= fmax) {
|
||||
break;
|
||||
}
|
||||
ImagingSectionEnter(&cookie);
|
||||
scale = 255.0F / (fmax - fmin);
|
||||
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++) {
|
||||
i = (int) (((*in++)-fmin)*scale);
|
||||
i = (int)(((*in++) - fmin) * scale);
|
||||
if (i >= 0 && i < 256) {
|
||||
h->histogram[i]++;
|
||||
}
|
||||
|
|
|
@ -35,20 +35,27 @@ struct ImagingDIBInstance {
|
|||
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 ImagingExposeDIB(ImagingDIB dib, void *dc);
|
||||
extern void
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
#include "Python.h"
|
||||
|
||||
/* 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
|
||||
#endif
|
||||
|
||||
|
@ -62,7 +63,7 @@
|
|||
#define INT64 long
|
||||
#endif
|
||||
|
||||
#define INT8 signed char
|
||||
#define INT8 signed char
|
||||
#define UINT8 unsigned char
|
||||
|
||||
#define UINT16 unsigned INT16
|
||||
|
@ -76,11 +77,9 @@
|
|||
#define FLOAT64 double
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef signed __int64 int64_t;
|
||||
typedef signed __int64 int64_t;
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define GCC_VERSION (__GNUC__ * 10000 \
|
||||
+ __GNUC_MINOR__ * 100 \
|
||||
+ __GNUC_PATCHLEVEL__)
|
||||
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||
#endif
|
||||
|
|
|
@ -10,20 +10,16 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "ImPlatform.h"
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
|
@ -57,12 +53,12 @@ extern "C" {
|
|||
|
||||
/* Handles */
|
||||
|
||||
typedef struct ImagingMemoryInstance* Imaging;
|
||||
typedef struct ImagingMemoryInstance *Imaging;
|
||||
|
||||
typedef struct ImagingAccessInstance* ImagingAccess;
|
||||
typedef struct ImagingHistogramInstance* ImagingHistogram;
|
||||
typedef struct ImagingOutlineInstance* ImagingOutline;
|
||||
typedef struct ImagingPaletteInstance* ImagingPalette;
|
||||
typedef struct ImagingAccessInstance *ImagingAccess;
|
||||
typedef struct ImagingHistogramInstance *ImagingHistogram;
|
||||
typedef struct ImagingOutlineInstance *ImagingOutline;
|
||||
typedef struct ImagingPaletteInstance *ImagingPalette;
|
||||
|
||||
/* handle magics (used with PyCObject). */
|
||||
#define IMAGING_MAGIC "PIL Imaging"
|
||||
|
@ -73,7 +69,8 @@ typedef struct ImagingPaletteInstance* ImagingPalette;
|
|||
#define IMAGING_TYPE_FLOAT32 2
|
||||
#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 {
|
||||
char *ptr;
|
||||
|
@ -81,158 +78,178 @@ typedef struct {
|
|||
} ImagingMemoryBlock;
|
||||
|
||||
struct ImagingMemoryInstance {
|
||||
|
||||
/* Format */
|
||||
char mode[IMAGING_MODE_LENGTH]; /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "BGR;xy") */
|
||||
int type; /* Data type (IMAGING_TYPE_*) */
|
||||
int depth; /* Depth (ignored in this version) */
|
||||
int bands; /* Number of bands (1, 2, 3, or 4) */
|
||||
int xsize; /* Image dimension. */
|
||||
char mode[IMAGING_MODE_LENGTH]; /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK",
|
||||
"YCbCr", "BGR;xy") */
|
||||
int type; /* Data type (IMAGING_TYPE_*) */
|
||||
int depth; /* Depth (ignored in this version) */
|
||||
int bands; /* Number of bands (1, 2, 3, or 4) */
|
||||
int xsize; /* Image dimension. */
|
||||
int ysize;
|
||||
|
||||
/* Colour palette (for "P" images only) */
|
||||
ImagingPalette palette;
|
||||
|
||||
/* Data pointers */
|
||||
UINT8 **image8; /* Set for 8-bit images (pixelsize=1). */
|
||||
INT32 **image32; /* Set for 32-bit images (pixelsize=4). */
|
||||
UINT8 **image8; /* Set for 8-bit images (pixelsize=1). */
|
||||
INT32 **image32; /* Set for 32-bit images (pixelsize=4). */
|
||||
|
||||
/* Internals */
|
||||
char **image; /* Actual raster data. */
|
||||
char *block; /* Set if data is allocated in a single block. */
|
||||
ImagingMemoryBlock *blocks; /* Memory blocks for pixel storage */
|
||||
char **image; /* Actual raster data. */
|
||||
char *block; /* Set if data is allocated in a single block. */
|
||||
ImagingMemoryBlock *blocks; /* Memory blocks for pixel storage */
|
||||
|
||||
int pixelsize; /* Size of a pixel, in bytes (1, 2 or 4) */
|
||||
int linesize; /* Size of a line, in bytes (xsize * pixelsize) */
|
||||
int pixelsize; /* Size of a pixel, in bytes (1, 2 or 4) */
|
||||
int linesize; /* Size of a line, in bytes (xsize * pixelsize) */
|
||||
|
||||
/* Virtual methods */
|
||||
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_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_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])
|
||||
#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 {
|
||||
const char* mode;
|
||||
void* (*line)(Imaging im, int x, int y);
|
||||
void (*get_pixel)(Imaging im, int x, int y, void* pixel);
|
||||
void (*put_pixel)(Imaging im, int x, int y, const void* pixel);
|
||||
const char *mode;
|
||||
void *(*line)(Imaging im, int x, int y);
|
||||
void (*get_pixel)(Imaging im, int x, int y, void *pixel);
|
||||
void (*put_pixel)(Imaging im, int x, int y, const void *pixel);
|
||||
};
|
||||
|
||||
struct ImagingHistogramInstance {
|
||||
|
||||
/* Format */
|
||||
char mode[IMAGING_MODE_LENGTH]; /* Band names (of corresponding source image) */
|
||||
int bands; /* Number of bands (1, 3, or 4) */
|
||||
char mode[IMAGING_MODE_LENGTH]; /* Band names (of corresponding source image) */
|
||||
int bands; /* Number of bands (1, 3, or 4) */
|
||||
|
||||
/* Data */
|
||||
long *histogram; /* Histogram (bands*256 longs) */
|
||||
|
||||
long *histogram; /* Histogram (bands*256 longs) */
|
||||
};
|
||||
|
||||
|
||||
struct ImagingPaletteInstance {
|
||||
|
||||
/* Format */
|
||||
char mode[IMAGING_MODE_LENGTH]; /* Band names */
|
||||
char mode[IMAGING_MODE_LENGTH]; /* Band names */
|
||||
|
||||
/* 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 */
|
||||
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 */
|
||||
};
|
||||
|
||||
typedef struct ImagingMemoryArena {
|
||||
int alignment; /* Alignment in memory of each line of an image */
|
||||
int block_size; /* Preferred block size, bytes */
|
||||
int blocks_max; /* Maximum number of cached blocks */
|
||||
int blocks_cached; /* Current number of blocks not associated with images */
|
||||
int alignment; /* Alignment in memory of each line of an image */
|
||||
int block_size; /* Preferred block size, bytes */
|
||||
int blocks_max; /* Maximum number of cached blocks */
|
||||
int blocks_cached; /* Current number of blocks not associated with images */
|
||||
ImagingMemoryBlock *blocks_pool;
|
||||
int stats_new_count; /* Number of new allocated images */
|
||||
int stats_allocated_blocks; /* Number of allocated blocks */
|
||||
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_freed_blocks; /* Number of freed blocks */
|
||||
} *ImagingMemoryArena;
|
||||
|
||||
int stats_new_count; /* Number of new allocated images */
|
||||
int stats_allocated_blocks; /* Number of allocated blocks */
|
||||
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_freed_blocks; /* Number of freed blocks */
|
||||
} * ImagingMemoryArena;
|
||||
|
||||
/* Objects */
|
||||
/* ------- */
|
||||
|
||||
extern struct ImagingMemoryArena ImagingDefaultArena;
|
||||
extern int ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max);
|
||||
extern void ImagingMemoryClearCache(ImagingMemoryArena arena, int new_size);
|
||||
extern int
|
||||
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 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
|
||||
ImagingNew(const char *mode, int xsize, int ysize);
|
||||
extern Imaging
|
||||
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,
|
||||
int xsize, int ysize);
|
||||
extern Imaging ImagingNewPrologueSubtype(const char *mode,
|
||||
int xsize, int ysize,
|
||||
int structure_size);
|
||||
extern Imaging
|
||||
ImagingNewPrologue(const char *mode, int xsize, int ysize);
|
||||
extern Imaging
|
||||
ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, 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 ImagingAccess ImagingAccessNew(Imaging im);
|
||||
extern void _ImagingAccessDelete(Imaging im, ImagingAccess access);
|
||||
extern void
|
||||
ImagingAccessInit(void);
|
||||
extern ImagingAccess
|
||||
ImagingAccessNew(Imaging im);
|
||||
extern void
|
||||
_ImagingAccessDelete(Imaging im, ImagingAccess access);
|
||||
#define ImagingAccessDelete(im, access) /* nop, for now */
|
||||
|
||||
extern ImagingPalette ImagingPaletteNew(const char *mode);
|
||||
extern ImagingPalette ImagingPaletteNewBrowser(void);
|
||||
extern ImagingPalette ImagingPaletteDuplicate(ImagingPalette palette);
|
||||
extern void ImagingPaletteDelete(ImagingPalette palette);
|
||||
extern ImagingPalette
|
||||
ImagingPaletteNew(const char *mode);
|
||||
extern ImagingPalette
|
||||
ImagingPaletteNewBrowser(void);
|
||||
extern ImagingPalette
|
||||
ImagingPaletteDuplicate(ImagingPalette palette);
|
||||
extern void
|
||||
ImagingPaletteDelete(ImagingPalette palette);
|
||||
|
||||
extern int ImagingPaletteCachePrepare(ImagingPalette palette);
|
||||
extern void ImagingPaletteCacheUpdate(ImagingPalette palette,
|
||||
int r, int g, int b);
|
||||
extern void ImagingPaletteCacheDelete(ImagingPalette palette);
|
||||
extern int
|
||||
ImagingPaletteCachePrepare(ImagingPalette palette);
|
||||
extern void
|
||||
ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b);
|
||||
extern void
|
||||
ImagingPaletteCacheDelete(ImagingPalette palette);
|
||||
|
||||
#define ImagingPaletteCache(p, r, g, b)\
|
||||
p->cache[(r>>2) + (g>>2)*64 + (b>>2)*64*64]
|
||||
#define ImagingPaletteCache(p, r, g, b) \
|
||||
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 */
|
||||
/* --------- */
|
||||
|
||||
typedef void* ImagingSectionCookie;
|
||||
typedef void *ImagingSectionCookie;
|
||||
|
||||
extern void ImagingSectionEnter(ImagingSectionCookie* cookie);
|
||||
extern void ImagingSectionLeave(ImagingSectionCookie* cookie);
|
||||
extern void
|
||||
ImagingSectionEnter(ImagingSectionCookie *cookie);
|
||||
extern void
|
||||
ImagingSectionLeave(ImagingSectionCookie *cookie);
|
||||
|
||||
/* Exceptions */
|
||||
/* ---------- */
|
||||
|
||||
extern void* ImagingError_OSError(void);
|
||||
extern void* ImagingError_MemoryError(void);
|
||||
extern 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);
|
||||
extern void *
|
||||
ImagingError_OSError(void);
|
||||
extern void *
|
||||
ImagingError_MemoryError(void);
|
||||
extern 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 */
|
||||
/* ------------------- */
|
||||
|
@ -242,7 +259,6 @@ extern void ImagingError_Clear(void);
|
|||
#define IMAGING_TRANSFORM_PERSPECTIVE 2
|
||||
#define IMAGING_TRANSFORM_QUAD 3
|
||||
|
||||
|
||||
/* standard filters */
|
||||
#define IMAGING_TRANSFORM_NEAREST 0
|
||||
#define IMAGING_TRANSFORM_BOX 4
|
||||
|
@ -251,249 +267,391 @@ extern void ImagingError_Clear(void);
|
|||
#define IMAGING_TRANSFORM_BICUBIC 3
|
||||
#define IMAGING_TRANSFORM_LANCZOS 1
|
||||
|
||||
typedef int (*ImagingTransformMap)(double* X, double* Y,
|
||||
int x, int y, void* data);
|
||||
typedef int (*ImagingTransformFilter)(void* out, Imaging im,
|
||||
double x, double y);
|
||||
typedef int (*ImagingTransformMap)(double *X, double *Y, int x, int y, void *data);
|
||||
typedef int (*ImagingTransformFilter)(void *out, Imaging im, double x, double y);
|
||||
|
||||
/* Image Manipulation Methods */
|
||||
/* -------------------------- */
|
||||
|
||||
extern Imaging ImagingAlphaComposite(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha);
|
||||
extern Imaging ImagingCopy(Imaging im);
|
||||
extern Imaging ImagingConvert(Imaging im, const char* mode, ImagingPalette palette, int dither);
|
||||
extern Imaging ImagingConvertInPlace(Imaging im, const char* mode);
|
||||
extern Imaging ImagingConvertMatrix(Imaging im, const char *mode, float m[]);
|
||||
extern Imaging ImagingConvertTransparent(Imaging im, const char *mode, int r, int g, int b);
|
||||
extern Imaging ImagingCrop(Imaging im, int x0, int y0, int x1, int y1);
|
||||
extern Imaging ImagingExpand(Imaging im, int x, int y, int mode);
|
||||
extern Imaging ImagingFill(Imaging im, const void* ink);
|
||||
extern int ImagingFill2(
|
||||
Imaging into, const void* ink, Imaging mask,
|
||||
int x0, int y0, int x1, int y1);
|
||||
extern Imaging ImagingFillBand(Imaging im, int band, int color);
|
||||
extern Imaging ImagingFillLinearGradient(const char* mode);
|
||||
extern Imaging ImagingFillRadialGradient(const char* mode);
|
||||
extern Imaging ImagingFilter(
|
||||
Imaging im, int xsize, int ysize, const FLOAT32* kernel,
|
||||
FLOAT32 offset);
|
||||
extern Imaging ImagingFlipLeftRight(Imaging imOut, Imaging imIn);
|
||||
extern Imaging ImagingFlipTopBottom(Imaging imOut, Imaging imIn);
|
||||
extern Imaging ImagingGaussianBlur(Imaging imOut, Imaging imIn, float radius,
|
||||
int passes);
|
||||
extern Imaging ImagingGetBand(Imaging im, int band);
|
||||
extern Imaging ImagingMerge(const char* mode, Imaging bands[4]);
|
||||
extern int ImagingSplit(Imaging im, Imaging bands[4]);
|
||||
extern int ImagingGetBBox(Imaging im, int bbox[4]);
|
||||
typedef struct { int x, y; INT32 count; INT32 pixel; } ImagingColorItem;
|
||||
extern ImagingColorItem* ImagingGetColors(Imaging im, int maxcolors,
|
||||
int *colors);
|
||||
extern int ImagingGetExtrema(Imaging im, void *extrema);
|
||||
extern int ImagingGetProjection(Imaging im, UINT8* xproj, UINT8* yproj);
|
||||
extern ImagingHistogram ImagingGetHistogram(
|
||||
Imaging im, Imaging mask, void *extrema);
|
||||
extern Imaging ImagingModeFilter(Imaging im, int size);
|
||||
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
|
||||
ImagingAlphaComposite(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging
|
||||
ImagingBlend(Imaging imIn1, Imaging imIn2, float alpha);
|
||||
extern Imaging
|
||||
ImagingCopy(Imaging im);
|
||||
extern Imaging
|
||||
ImagingConvert(Imaging im, const char *mode, ImagingPalette palette, int dither);
|
||||
extern Imaging
|
||||
ImagingConvertInPlace(Imaging im, const char *mode);
|
||||
extern Imaging
|
||||
ImagingConvertMatrix(Imaging im, const char *mode, float m[]);
|
||||
extern Imaging
|
||||
ImagingConvertTransparent(Imaging im, const char *mode, int r, int g, int b);
|
||||
extern Imaging
|
||||
ImagingCrop(Imaging im, int x0, int y0, int x1, int y1);
|
||||
extern Imaging
|
||||
ImagingExpand(Imaging im, int x, int y, int mode);
|
||||
extern Imaging
|
||||
ImagingFill(Imaging im, const void *ink);
|
||||
extern int
|
||||
ImagingFill2(
|
||||
Imaging into, const void *ink, Imaging mask, int x0, int y0, int x1, int y1);
|
||||
extern Imaging
|
||||
ImagingFillBand(Imaging im, int band, int color);
|
||||
extern Imaging
|
||||
ImagingFillLinearGradient(const char *mode);
|
||||
extern Imaging
|
||||
ImagingFillRadialGradient(const char *mode);
|
||||
extern Imaging
|
||||
ImagingFilter(Imaging im, int xsize, int ysize, const FLOAT32 *kernel, FLOAT32 offset);
|
||||
extern Imaging
|
||||
ImagingFlipLeftRight(Imaging imOut, Imaging imIn);
|
||||
extern Imaging
|
||||
ImagingFlipTopBottom(Imaging imOut, Imaging imIn);
|
||||
extern Imaging
|
||||
ImagingGaussianBlur(Imaging imOut, Imaging imIn, float radius, int passes);
|
||||
extern Imaging
|
||||
ImagingGetBand(Imaging im, int band);
|
||||
extern Imaging
|
||||
ImagingMerge(const char *mode, Imaging bands[4]);
|
||||
extern int
|
||||
ImagingSplit(Imaging im, Imaging bands[4]);
|
||||
extern int
|
||||
ImagingGetBBox(Imaging im, int bbox[4]);
|
||||
typedef struct {
|
||||
int x, y;
|
||||
INT32 count;
|
||||
INT32 pixel;
|
||||
} ImagingColorItem;
|
||||
extern ImagingColorItem *
|
||||
ImagingGetColors(Imaging im, int maxcolors, int *colors);
|
||||
extern int
|
||||
ImagingGetExtrema(Imaging im, void *extrema);
|
||||
extern int
|
||||
ImagingGetProjection(Imaging im, UINT8 *xproj, UINT8 *yproj);
|
||||
extern ImagingHistogram
|
||||
ImagingGetHistogram(Imaging im, Imaging mask, void *extrema);
|
||||
extern Imaging
|
||||
ImagingModeFilter(Imaging im, int size);
|
||||
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 ImagingConvert2(Imaging imOut, Imaging imIn);
|
||||
extern Imaging
|
||||
ImagingCopy2(Imaging imOut, Imaging imIn);
|
||||
extern Imaging
|
||||
ImagingConvert2(Imaging imOut, Imaging imIn);
|
||||
|
||||
/* Channel operations */
|
||||
/* any mode, except "F" */
|
||||
extern Imaging ImagingChopLighter(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging ImagingChopDarker(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging ImagingChopDifference(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging ImagingChopMultiply(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging ImagingChopScreen(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging ImagingChopAdd(
|
||||
Imaging imIn1, Imaging imIn2, float scale, int offset);
|
||||
extern Imaging 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);
|
||||
extern Imaging
|
||||
ImagingChopLighter(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging
|
||||
ImagingChopDarker(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging
|
||||
ImagingChopDifference(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging
|
||||
ImagingChopMultiply(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging
|
||||
ImagingChopScreen(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging
|
||||
ImagingChopAdd(Imaging imIn1, Imaging imIn2, float scale, int offset);
|
||||
extern Imaging
|
||||
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 */
|
||||
extern Imaging ImagingChopAnd(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging ImagingChopOr(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging ImagingChopXor(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging
|
||||
ImagingChopAnd(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging
|
||||
ImagingChopOr(Imaging imIn1, Imaging imIn2);
|
||||
extern Imaging
|
||||
ImagingChopXor(Imaging imIn1, Imaging imIn2);
|
||||
|
||||
/* Graphics */
|
||||
extern int ImagingDrawArc(Imaging im, int x0, int y0, int x1, int y1,
|
||||
float start, float end, const void* ink, int width,
|
||||
int op);
|
||||
extern int ImagingDrawBitmap(Imaging im, int x0, int y0, Imaging bitmap,
|
||||
const void* ink, int op);
|
||||
extern int ImagingDrawChord(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 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);
|
||||
extern int
|
||||
ImagingDrawArc(
|
||||
Imaging im,
|
||||
int x0,
|
||||
int y0,
|
||||
int x1,
|
||||
int y1,
|
||||
float start,
|
||||
float end,
|
||||
const void *ink,
|
||||
int width,
|
||||
int op);
|
||||
extern int
|
||||
ImagingDrawBitmap(Imaging im, int x0, int y0, Imaging bitmap, const void *ink, int op);
|
||||
extern int
|
||||
ImagingDrawChord(
|
||||
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
|
||||
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) */
|
||||
extern ImagingOutline ImagingOutlineNew(void);
|
||||
extern void ImagingOutlineDelete(ImagingOutline outline);
|
||||
extern ImagingOutline
|
||||
ImagingOutlineNew(void);
|
||||
extern void
|
||||
ImagingOutlineDelete(ImagingOutline outline);
|
||||
|
||||
extern int ImagingDrawOutline(Imaging im, ImagingOutline outline,
|
||||
const void* ink, int fill, int op);
|
||||
extern int
|
||||
ImagingDrawOutline(
|
||||
Imaging im, ImagingOutline outline, const void *ink, int fill, int op);
|
||||
|
||||
extern int ImagingOutlineMove(ImagingOutline outline, float x, float y);
|
||||
extern int ImagingOutlineLine(ImagingOutline outline, float x, float y);
|
||||
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
|
||||
ImagingOutlineMove(ImagingOutline outline, float x, float y);
|
||||
extern int
|
||||
ImagingOutlineLine(ImagingOutline outline, float x, float y);
|
||||
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 */
|
||||
extern Imaging ImagingEffectSpread(Imaging imIn, int distance);
|
||||
extern Imaging ImagingEffectNoise(int xsize, int ysize, float sigma);
|
||||
extern Imaging ImagingEffectMandelbrot(int xsize, int ysize,
|
||||
double extent[4], int quality);
|
||||
|
||||
extern Imaging
|
||||
ImagingEffectSpread(Imaging imIn, int distance);
|
||||
extern Imaging
|
||||
ImagingEffectNoise(int xsize, int ysize, float sigma);
|
||||
extern Imaging
|
||||
ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality);
|
||||
|
||||
/* File I/O */
|
||||
/* -------- */
|
||||
|
||||
/* Built-in drivers */
|
||||
extern Imaging ImagingOpenPPM(const char* filename);
|
||||
extern int ImagingSavePPM(Imaging im, const char* filename);
|
||||
extern Imaging
|
||||
ImagingOpenPPM(const char *filename);
|
||||
extern int
|
||||
ImagingSavePPM(Imaging im, const char *filename);
|
||||
|
||||
/* Codecs */
|
||||
typedef struct ImagingCodecStateInstance *ImagingCodecState;
|
||||
typedef int (*ImagingCodec)(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
typedef int (*ImagingCodec)(
|
||||
Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
|
||||
|
||||
extern int ImagingBcnDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingBitDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingEpsEncode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
extern int ImagingFliDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingGifDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingGifEncode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
extern int ImagingHexDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
#ifdef HAVE_LIBJPEG
|
||||
extern int ImagingJpegDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingJpegDecodeCleanup(ImagingCodecState state);
|
||||
extern int ImagingJpegUseJCSExtensions(void);
|
||||
extern int
|
||||
ImagingBcnDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingBitDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingEpsEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
|
||||
extern int
|
||||
ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
|
||||
extern int
|
||||
ImagingHexDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
#ifdef HAVE_LIBJPEG
|
||||
extern int
|
||||
ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingJpegDecodeCleanup(ImagingCodecState state);
|
||||
extern int
|
||||
ImagingJpegUseJCSExtensions(void);
|
||||
|
||||
extern int ImagingJpegEncode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
extern int
|
||||
ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
|
||||
#endif
|
||||
#ifdef HAVE_OPENJPEG
|
||||
extern int ImagingJpeg2KDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingJpeg2KDecodeCleanup(ImagingCodecState state);
|
||||
extern int ImagingJpeg2KEncode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
extern int ImagingJpeg2KEncodeCleanup(ImagingCodecState state);
|
||||
extern int
|
||||
ImagingJpeg2KDecode(
|
||||
Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingJpeg2KDecodeCleanup(ImagingCodecState state);
|
||||
extern int
|
||||
ImagingJpeg2KEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
|
||||
extern int
|
||||
ImagingJpeg2KEncodeCleanup(ImagingCodecState state);
|
||||
#endif
|
||||
#ifdef HAVE_LIBTIFF
|
||||
extern int ImagingLibTiffDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingLibTiffEncode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
#ifdef HAVE_LIBTIFF
|
||||
extern int
|
||||
ImagingLibTiffDecode(
|
||||
Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
|
||||
#endif
|
||||
#ifdef HAVE_LIBMPEG
|
||||
extern int ImagingMpegDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
#ifdef HAVE_LIBMPEG
|
||||
extern int
|
||||
ImagingMpegDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
#endif
|
||||
extern int ImagingMspDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingPackbitsDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingPcdDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingPcxDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingPcxEncode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
extern int ImagingRawDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingRawEncode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
extern int ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingSunRleDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingTgaRleDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingTgaRleEncode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
extern int ImagingXbmDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, Py_ssize_t bytes);
|
||||
extern int ImagingXbmEncode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
#ifdef HAVE_LIBZ
|
||||
extern int 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);
|
||||
extern int
|
||||
ImagingMspDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingPackbitsDecode(
|
||||
Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingPcdDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
|
||||
extern int
|
||||
ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingRawEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
|
||||
extern int
|
||||
ImagingSgiRleDecode(
|
||||
Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingSunRleDecode(
|
||||
Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingTgaRleDecode(
|
||||
Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
|
||||
extern int
|
||||
ImagingXbmDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t bytes);
|
||||
extern int
|
||||
ImagingXbmEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes);
|
||||
#ifdef HAVE_LIBZ
|
||||
extern int
|
||||
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
|
||||
|
||||
typedef void (*ImagingShuffler)(UINT8* out, const UINT8* in, int pixels);
|
||||
typedef void (*ImagingShuffler)(UINT8 *out, const UINT8 *in, int pixels);
|
||||
|
||||
/* Public shufflers */
|
||||
extern void ImagingPackBGR(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
|
||||
ImagingPackBGR(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 ImagingConvertYCbCr2RGB(UINT8* out, const UINT8* in, int pixels);
|
||||
extern void
|
||||
ImagingConvertRGB2YCbCr(UINT8 *out, const UINT8 *in, int pixels);
|
||||
extern void
|
||||
ImagingConvertYCbCr2RGB(UINT8 *out, const UINT8 *in, int pixels);
|
||||
|
||||
extern ImagingShuffler ImagingFindUnpacker(const char* mode,
|
||||
const char* rawmode, int* bits_out);
|
||||
extern ImagingShuffler ImagingFindPacker(const char* mode,
|
||||
const char* rawmode, int* bits_out);
|
||||
extern ImagingShuffler
|
||||
ImagingFindUnpacker(const char *mode, const char *rawmode, int *bits_out);
|
||||
extern ImagingShuffler
|
||||
ImagingFindPacker(const char *mode, const char *rawmode, int *bits_out);
|
||||
|
||||
struct ImagingCodecStateInstance {
|
||||
int count;
|
||||
|
@ -509,30 +667,27 @@ struct ImagingCodecStateInstance {
|
|||
PyObject *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 _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);
|
||||
|
||||
|
||||
extern Py_ssize_t
|
||||
_imaging_read_pyFd(PyObject *fd, char *dest, Py_ssize_t bytes);
|
||||
extern Py_ssize_t
|
||||
_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 */
|
||||
#define IMAGING_CODEC_END 1
|
||||
#define IMAGING_CODEC_OVERRUN -1
|
||||
#define IMAGING_CODEC_BROKEN -2
|
||||
#define IMAGING_CODEC_UNKNOWN -3
|
||||
#define IMAGING_CODEC_CONFIG -8
|
||||
#define IMAGING_CODEC_MEMORY -9
|
||||
|
||||
|
||||
#define IMAGING_CODEC_END 1
|
||||
#define IMAGING_CODEC_OVERRUN -1
|
||||
#define IMAGING_CODEC_BROKEN -2
|
||||
#define IMAGING_CODEC_UNKNOWN -3
|
||||
#define IMAGING_CODEC_CONFIG -8
|
||||
#define IMAGING_CODEC_MEMORY -9
|
||||
|
||||
#include "ImagingUtils.h"
|
||||
extern UINT8 *clip8_lookups;
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,47 +1,42 @@
|
|||
#ifdef WORDS_BIGENDIAN
|
||||
#define MAKE_UINT32(u0, u1, u2, u3) ((UINT32)(u3) | ((UINT32)(u2)<<8) | ((UINT32)(u1)<<16) | ((UINT32)(u0)<<24))
|
||||
#define MASK_UINT32_CHANNEL_0 0xff000000
|
||||
#define MASK_UINT32_CHANNEL_1 0x00ff0000
|
||||
#define MASK_UINT32_CHANNEL_2 0x0000ff00
|
||||
#define MASK_UINT32_CHANNEL_3 0x000000ff
|
||||
#define MAKE_UINT32(u0, u1, u2, u3) \
|
||||
((UINT32)(u3) | ((UINT32)(u2) << 8) | ((UINT32)(u1) << 16) | ((UINT32)(u0) << 24))
|
||||
#define MASK_UINT32_CHANNEL_0 0xff000000
|
||||
#define MASK_UINT32_CHANNEL_1 0x00ff0000
|
||||
#define MASK_UINT32_CHANNEL_2 0x0000ff00
|
||||
#define MASK_UINT32_CHANNEL_3 0x000000ff
|
||||
#else
|
||||
#define MAKE_UINT32(u0, u1, u2, u3) ((UINT32)(u0) | ((UINT32)(u1)<<8) | ((UINT32)(u2)<<16) | ((UINT32)(u3)<<24))
|
||||
#define MASK_UINT32_CHANNEL_0 0x000000ff
|
||||
#define MASK_UINT32_CHANNEL_1 0x0000ff00
|
||||
#define MASK_UINT32_CHANNEL_2 0x00ff0000
|
||||
#define MASK_UINT32_CHANNEL_3 0xff000000
|
||||
#define MAKE_UINT32(u0, u1, u2, u3) \
|
||||
((UINT32)(u0) | ((UINT32)(u1) << 8) | ((UINT32)(u2) << 16) | ((UINT32)(u3) << 24))
|
||||
#define MASK_UINT32_CHANNEL_0 0x000000ff
|
||||
#define MASK_UINT32_CHANNEL_1 0x0000ff00
|
||||
#define MASK_UINT32_CHANNEL_2 0x00ff0000
|
||||
#define MASK_UINT32_CHANNEL_3 0xff000000
|
||||
#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 */
|
||||
#define MULDIV255(a, b, tmp)\
|
||||
(tmp = (a) * (b) + 128, SHIFTFORDIV255(tmp))
|
||||
#define MULDIV255(a, b, tmp) (tmp = (a) * (b) + 128, SHIFTFORDIV255(tmp))
|
||||
|
||||
#define DIV255(a, tmp)\
|
||||
(tmp = (a) + 128, SHIFTFORDIV255(tmp))
|
||||
#define DIV255(a, tmp) (tmp = (a) + 128, SHIFTFORDIV255(tmp))
|
||||
|
||||
#define BLEND(mask, in1, in2, tmp1)\
|
||||
DIV255(in1 * (255 - mask) + in2 * mask, tmp1)
|
||||
|
||||
#define PREBLEND(mask, in1, in2, tmp1)\
|
||||
(MULDIV255(in1, (255 - mask), tmp1) + in2)
|
||||
#define BLEND(mask, in1, in2, tmp1) DIV255(in1 *(255 - mask) + in2 * mask, tmp1)
|
||||
|
||||
#define PREBLEND(mask, in1, in2, tmp1) (MULDIV255(in1, (255 - mask), tmp1) + in2)
|
||||
|
||||
#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.
|
||||
GCC generates code with partial dependency which is 3 times slower.
|
||||
See: http://stackoverflow.com/a/26588074/253146 */
|
||||
#if defined(__x86_64__) && defined(__SSE__) && ! defined(__NO_INLINE__) && \
|
||||
! defined(__clang__) && defined(GCC_VERSION) && (GCC_VERSION < 40900)
|
||||
#if defined(__x86_64__) && defined(__SSE__) && !defined(__NO_INLINE__) && \
|
||||
!defined(__clang__) && defined(GCC_VERSION) && (GCC_VERSION < 40900)
|
||||
static float __attribute__((always_inline)) inline _i2f(int v) {
|
||||
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;
|
||||
}
|
||||
#else
|
||||
static float inline _i2f(int v) { return (float) v; }
|
||||
static float inline _i2f(int v) { return (float)v; }
|
||||
#endif
|
||||
|
|
|
@ -12,13 +12,11 @@
|
|||
|
||||
#include <setjmp.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
} JPEGERROR;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Decoder */
|
||||
|
||||
|
@ -28,15 +26,14 @@ typedef struct {
|
|||
} JPEGSOURCE;
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* CONFIGURATION */
|
||||
|
||||
/* Jpeg file mode (empty if not known) */
|
||||
char jpegmode[8+1];
|
||||
char jpegmode[8 + 1];
|
||||
|
||||
/* Converter output mode (input to the shuffler). If empty,
|
||||
convert conversions are disabled */
|
||||
char rawmode[8+1];
|
||||
char rawmode[8 + 1];
|
||||
|
||||
/* If set, trade quality for speed */
|
||||
int draft;
|
||||
|
@ -54,7 +51,6 @@ typedef struct {
|
|||
|
||||
} JPEGSTATE;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Encoder */
|
||||
|
||||
|
@ -64,7 +60,6 @@ typedef struct {
|
|||
} JPEGDESTINATION;
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* CONFIGURATION */
|
||||
|
||||
/* Quality (0-100, -1 means default) */
|
||||
|
@ -89,7 +84,7 @@ typedef struct {
|
|||
int subsampling;
|
||||
|
||||
/* Converter input mode (input to the shuffler) */
|
||||
char rawmode[8+1];
|
||||
char rawmode[8 + 1];
|
||||
|
||||
/* Custom quantization tables () */
|
||||
unsigned int *qtables;
|
||||
|
@ -98,7 +93,8 @@ typedef struct {
|
|||
int qtablesLen;
|
||||
|
||||
/* Extra data (to be injected after header) */
|
||||
char* extra; int extra_size;
|
||||
char *extra;
|
||||
int extra_size;
|
||||
|
||||
/* PRIVATE CONTEXT (set by encoder) */
|
||||
|
||||
|
@ -110,7 +106,7 @@ typedef struct {
|
|||
|
||||
int extra_offset;
|
||||
|
||||
size_t rawExifLen; /* EXIF data length */
|
||||
char* rawExif; /* EXIF buffer pointer */
|
||||
size_t rawExifLen; /* EXIF data length */
|
||||
char *rawExif; /* EXIF buffer pointer */
|
||||
|
||||
} JPEGENCODERSTATE;
|
||||
|
|
|
@ -24,7 +24,7 @@ typedef struct {
|
|||
int fd;
|
||||
|
||||
/* File pointer, when opened */
|
||||
FILE * pfile;
|
||||
FILE *pfile;
|
||||
|
||||
/* Length of data, if available; otherwise, -1 */
|
||||
off_t length;
|
||||
|
@ -33,13 +33,13 @@ typedef struct {
|
|||
OPJ_CODEC_FORMAT format;
|
||||
|
||||
/* 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) */
|
||||
int layers;
|
||||
int layers;
|
||||
|
||||
/* PRIVATE CONTEXT (set by decoder) */
|
||||
const char *error_msg;
|
||||
const char *error_msg;
|
||||
|
||||
} JPEG2KDECODESTATE;
|
||||
|
||||
|
@ -51,36 +51,36 @@ typedef struct {
|
|||
/* CONFIGURATION */
|
||||
|
||||
/* File descriptor, if available; otherwise, -1 */
|
||||
int fd;
|
||||
int fd;
|
||||
|
||||
/* File pointer, when opened */
|
||||
FILE * pfile;
|
||||
FILE *pfile;
|
||||
|
||||
/* Specify the desired format */
|
||||
OPJ_CODEC_FORMAT format;
|
||||
|
||||
/* Image offset */
|
||||
int offset_x, offset_y;
|
||||
int offset_x, offset_y;
|
||||
|
||||
/* Tile information */
|
||||
int tile_offset_x, tile_offset_y;
|
||||
int tile_size_x, tile_size_y;
|
||||
int tile_offset_x, tile_offset_y;
|
||||
int tile_size_x, tile_size_y;
|
||||
|
||||
/* Quality layers (a sequence of numbers giving *either* rates or dB) */
|
||||
int quality_is_in_db;
|
||||
PyObject *quality_layers;
|
||||
int quality_is_in_db;
|
||||
PyObject *quality_layers;
|
||||
|
||||
/* Number of resolutions (DWT decompositions + 1 */
|
||||
int num_resolutions;
|
||||
int num_resolutions;
|
||||
|
||||
/* Code block size */
|
||||
int cblk_width, cblk_height;
|
||||
int cblk_width, cblk_height;
|
||||
|
||||
/* Precinct size */
|
||||
int precinct_width, precinct_height;
|
||||
int precinct_width, precinct_height;
|
||||
|
||||
/* Compression style */
|
||||
int irreversible;
|
||||
int irreversible;
|
||||
|
||||
/* Progression order (LRCP/RLCP/RPCL/PCRL/CPRL) */
|
||||
OPJ_PROG_ORDER progression;
|
||||
|
@ -89,8 +89,7 @@ typedef struct {
|
|||
OPJ_CINEMA_MODE cinema_mode;
|
||||
|
||||
/* PRIVATE CONTEXT (set by decoder) */
|
||||
const char *error_msg;
|
||||
|
||||
const char *error_msg;
|
||||
|
||||
} JPEG2KENCODESTATE;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
typedef struct {
|
||||
OPJ_UINT32 tile_index;
|
||||
OPJ_UINT32 data_size;
|
||||
OPJ_INT32 x0, y0, x1, y1;
|
||||
OPJ_INT32 x0, y0, x1, y1;
|
||||
OPJ_UINT32 nb_comps;
|
||||
} JPEG2KTILEINFO;
|
||||
|
||||
|
@ -32,9 +32,8 @@ typedef struct {
|
|||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
j2k_error(const char *msg, void *client_data)
|
||||
{
|
||||
JPEG2KDECODESTATE *state = (JPEG2KDECODESTATE *) client_data;
|
||||
j2k_error(const char *msg, void *client_data) {
|
||||
JPEG2KDECODESTATE *state = (JPEG2KDECODESTATE *)client_data;
|
||||
free((void *)state->error_msg);
|
||||
state->error_msg = strdup(msg);
|
||||
}
|
||||
|
@ -44,8 +43,7 @@ j2k_error(const char *msg, void *client_data)
|
|||
/* -------------------------------------------------------------------- */
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
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;
|
||||
ImagingCodecState state = (ImagingCodecState)p_user_data;
|
||||
|
||||
|
@ -69,21 +66,18 @@ j2k_skip(OPJ_OFF_T p_nb_bytes, void *p_user_data)
|
|||
/* Unpackers */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
typedef void (*j2k_unpacker_t)(opj_image_t *in,
|
||||
const JPEG2KTILEINFO *tileInfo,
|
||||
const UINT8 *data,
|
||||
Imaging im);
|
||||
typedef void (*j2k_unpacker_t)(
|
||||
opj_image_t *in, const JPEG2KTILEINFO *tileInfo, const UINT8 *data, Imaging im);
|
||||
|
||||
struct j2k_decode_unpacker {
|
||||
const char *mode;
|
||||
OPJ_COLOR_SPACE color_space;
|
||||
unsigned components;
|
||||
j2k_unpacker_t unpacker;
|
||||
const char *mode;
|
||||
OPJ_COLOR_SPACE color_space;
|
||||
unsigned components;
|
||||
j2k_unpacker_t unpacker;
|
||||
};
|
||||
|
||||
static inline
|
||||
unsigned j2ku_shift(unsigned x, int n)
|
||||
{
|
||||
static inline unsigned
|
||||
j2ku_shift(unsigned x, int n) {
|
||||
if (n < 0) {
|
||||
return x >> -n;
|
||||
} else {
|
||||
|
@ -92,9 +86,11 @@ unsigned j2ku_shift(unsigned x, int n)
|
|||
}
|
||||
|
||||
static void
|
||||
j2ku_gray_l(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata, Imaging im)
|
||||
{
|
||||
j2ku_gray_l(
|
||||
opj_image_t *in,
|
||||
const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata,
|
||||
Imaging im) {
|
||||
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
|
||||
unsigned w = tileinfo->x1 - tileinfo->x0;
|
||||
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 */
|
||||
switch (csiz) {
|
||||
case 1:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT8 *data = &tiledata[y * w];
|
||||
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
*row++ = j2ku_shift(offset + *data++, shift);
|
||||
case 1:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT8 *data = &tiledata[y * w];
|
||||
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
*row++ = j2ku_shift(offset + *data++, shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT16 *data = (const UINT16 *)&tiledata[2 * y * w];
|
||||
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
*row++ = j2ku_shift(offset + *data++, shift);
|
||||
break;
|
||||
case 2:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT16 *data = (const UINT16 *)&tiledata[2 * y * w];
|
||||
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
*row++ = j2ku_shift(offset + *data++, shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT32 *data = (const UINT32 *)&tiledata[4 * y * w];
|
||||
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
*row++ = j2ku_shift(offset + *data++, shift);
|
||||
break;
|
||||
case 4:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT32 *data = (const UINT32 *)&tiledata[4 * y * w];
|
||||
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
*row++ = j2ku_shift(offset + *data++, shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
j2ku_gray_i(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata, Imaging im)
|
||||
{
|
||||
j2ku_gray_i(
|
||||
opj_image_t *in,
|
||||
const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata,
|
||||
Imaging im) {
|
||||
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
|
||||
unsigned w = tileinfo->x1 - tileinfo->x0;
|
||||
unsigned h = tileinfo->y1 - tileinfo->y0;
|
||||
|
@ -169,41 +166,42 @@ j2ku_gray_i(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
|||
}
|
||||
|
||||
switch (csiz) {
|
||||
case 1:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT8 *data = &tiledata[y * w];
|
||||
UINT16 *row = (UINT16 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
*row++ = j2ku_shift(offset + *data++, shift);
|
||||
case 1:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT8 *data = &tiledata[y * w];
|
||||
UINT16 *row = (UINT16 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
*row++ = j2ku_shift(offset + *data++, shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT16 *data = (const UINT16 *)&tiledata[2 * y * w];
|
||||
UINT16 *row = (UINT16 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
*row++ = j2ku_shift(offset + *data++, shift);
|
||||
break;
|
||||
case 2:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT16 *data = (const UINT16 *)&tiledata[2 * y * w];
|
||||
UINT16 *row = (UINT16 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
*row++ = j2ku_shift(offset + *data++, shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT32 *data = (const UINT32 *)&tiledata[4 * y * w];
|
||||
UINT16 *row = (UINT16 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
*row++ = j2ku_shift(offset + *data++, shift);
|
||||
break;
|
||||
case 4:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT32 *data = (const UINT32 *)&tiledata[4 * y * w];
|
||||
UINT16 *row = (UINT16 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
*row++ = j2ku_shift(offset + *data++, shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
j2ku_gray_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata, Imaging im)
|
||||
{
|
||||
j2ku_gray_rgb(
|
||||
opj_image_t *in,
|
||||
const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata,
|
||||
Imaging im) {
|
||||
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
|
||||
unsigned w = tileinfo->x1 - tileinfo->x0;
|
||||
unsigned h = tileinfo->y1 - tileinfo->y0;
|
||||
|
@ -223,49 +221,51 @@ j2ku_gray_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
|||
}
|
||||
|
||||
switch (csiz) {
|
||||
case 1:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT8 *data = &tiledata[y * w];
|
||||
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
UINT8 byte = j2ku_shift(offset + *data++, shift);
|
||||
row[0] = row[1] = row[2] = byte;
|
||||
row[3] = 0xff;
|
||||
row += 4;
|
||||
case 1:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT8 *data = &tiledata[y * w];
|
||||
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
UINT8 byte = j2ku_shift(offset + *data++, shift);
|
||||
row[0] = row[1] = row[2] = byte;
|
||||
row[3] = 0xff;
|
||||
row += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT16 *data = (UINT16 *)&tiledata[2 * y * w];
|
||||
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
UINT8 byte = j2ku_shift(offset + *data++, shift);
|
||||
row[0] = row[1] = row[2] = byte;
|
||||
row[3] = 0xff;
|
||||
row += 4;
|
||||
break;
|
||||
case 2:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT16 *data = (UINT16 *)&tiledata[2 * y * w];
|
||||
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
UINT8 byte = j2ku_shift(offset + *data++, shift);
|
||||
row[0] = row[1] = row[2] = byte;
|
||||
row[3] = 0xff;
|
||||
row += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT32 *data = (UINT32 *)&tiledata[4 * y * w];
|
||||
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
UINT8 byte = j2ku_shift(offset + *data++, shift);
|
||||
row[0] = row[1] = row[2] = byte;
|
||||
row[3] = 0xff;
|
||||
row += 4;
|
||||
break;
|
||||
case 4:
|
||||
for (y = 0; y < h; ++y) {
|
||||
const UINT32 *data = (UINT32 *)&tiledata[4 * y * w];
|
||||
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0;
|
||||
for (x = 0; x < w; ++x) {
|
||||
UINT8 byte = j2ku_shift(offset + *data++, shift);
|
||||
row[0] = row[1] = row[2] = byte;
|
||||
row[3] = 0xff;
|
||||
row += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
j2ku_graya_la(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata, Imaging im)
|
||||
{
|
||||
j2ku_graya_la(
|
||||
opj_image_t *in,
|
||||
const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata,
|
||||
Imaging im) {
|
||||
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
|
||||
unsigned w = tileinfo->x1 - tileinfo->x0;
|
||||
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;
|
||||
|
||||
switch (csiz) {
|
||||
case 1: word = *data++; break;
|
||||
case 2: word = *(const UINT16 *)data; data += 2; break;
|
||||
case 4: word = *(const UINT32 *)data; data += 4; break;
|
||||
case 1:
|
||||
word = *data++;
|
||||
break;
|
||||
case 2:
|
||||
word = *(const UINT16 *)data;
|
||||
data += 2;
|
||||
break;
|
||||
case 4:
|
||||
word = *(const UINT32 *)data;
|
||||
data += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (acsiz) {
|
||||
case 1: aword = *adata++; break;
|
||||
case 2: aword = *(const UINT16 *)adata; adata += 2; break;
|
||||
case 4: aword = *(const UINT32 *)adata; adata += 4; break;
|
||||
case 1:
|
||||
aword = *adata++;
|
||||
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);
|
||||
|
@ -324,9 +340,11 @@ j2ku_graya_la(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
|||
}
|
||||
|
||||
static void
|
||||
j2ku_srgb_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata, Imaging im)
|
||||
{
|
||||
j2ku_srgb_rgb(
|
||||
opj_image_t *in,
|
||||
const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata,
|
||||
Imaging im) {
|
||||
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
|
||||
unsigned w = tileinfo->x1 - tileinfo->x0;
|
||||
unsigned h = tileinfo->y1 - tileinfo->y0;
|
||||
|
@ -365,9 +383,17 @@ j2ku_srgb_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
|||
UINT32 word = 0;
|
||||
|
||||
switch (csiz[n]) {
|
||||
case 1: word = *data[n]++; break;
|
||||
case 2: word = *(const UINT16 *)data[n]; data[n] += 2; break;
|
||||
case 4: word = *(const UINT32 *)data[n]; data[n] += 4; break;
|
||||
case 1:
|
||||
word = *data[n]++;
|
||||
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]);
|
||||
|
@ -379,9 +405,11 @@ j2ku_srgb_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
|||
}
|
||||
|
||||
static void
|
||||
j2ku_sycc_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata, Imaging im)
|
||||
{
|
||||
j2ku_sycc_rgb(
|
||||
opj_image_t *in,
|
||||
const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata,
|
||||
Imaging im) {
|
||||
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
|
||||
unsigned w = tileinfo->x1 - tileinfo->x0;
|
||||
unsigned h = tileinfo->y1 - tileinfo->y0;
|
||||
|
@ -421,9 +449,17 @@ j2ku_sycc_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
|||
UINT32 word = 0;
|
||||
|
||||
switch (csiz[n]) {
|
||||
case 1: word = *data[n]++; break;
|
||||
case 2: word = *(const UINT16 *)data[n]; data[n] += 2; break;
|
||||
case 4: word = *(const UINT32 *)data[n]; data[n] += 4; break;
|
||||
case 1:
|
||||
word = *data[n]++;
|
||||
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]);
|
||||
|
@ -437,9 +473,11 @@ j2ku_sycc_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
|||
}
|
||||
|
||||
static void
|
||||
j2ku_srgba_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata, Imaging im)
|
||||
{
|
||||
j2ku_srgba_rgba(
|
||||
opj_image_t *in,
|
||||
const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata,
|
||||
Imaging im) {
|
||||
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
|
||||
unsigned w = tileinfo->x1 - tileinfo->x0;
|
||||
unsigned h = tileinfo->y1 - tileinfo->y0;
|
||||
|
@ -478,9 +516,17 @@ j2ku_srgba_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
|||
UINT32 word = 0;
|
||||
|
||||
switch (csiz[n]) {
|
||||
case 1: word = *data[n]++; break;
|
||||
case 2: word = *(const UINT16 *)data[n]; data[n] += 2; break;
|
||||
case 4: word = *(const UINT32 *)data[n]; data[n] += 4; break;
|
||||
case 1:
|
||||
word = *data[n]++;
|
||||
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]);
|
||||
|
@ -491,9 +537,11 @@ j2ku_srgba_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
|||
}
|
||||
|
||||
static void
|
||||
j2ku_sycca_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata, Imaging im)
|
||||
{
|
||||
j2ku_sycca_rgba(
|
||||
opj_image_t *in,
|
||||
const JPEG2KTILEINFO *tileinfo,
|
||||
const UINT8 *tiledata,
|
||||
Imaging im) {
|
||||
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
|
||||
unsigned w = tileinfo->x1 - tileinfo->x0;
|
||||
unsigned h = tileinfo->y1 - tileinfo->y0;
|
||||
|
@ -533,9 +581,17 @@ j2ku_sycca_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
|||
UINT32 word = 0;
|
||||
|
||||
switch (csiz[n]) {
|
||||
case 1: word = *data[n]++; break;
|
||||
case 2: word = *(const UINT16 *)data[n]; data[n] += 2; break;
|
||||
case 4: word = *(const UINT32 *)data[n]; data[n] += 4; break;
|
||||
case 1:
|
||||
word = *data[n]++;
|
||||
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]);
|
||||
|
@ -548,22 +604,22 @@ j2ku_sycca_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
|
|||
}
|
||||
|
||||
static const struct j2k_decode_unpacker j2k_unpackers[] = {
|
||||
{ "L", OPJ_CLRSPC_GRAY, 1, j2ku_gray_l },
|
||||
{ "I;16", OPJ_CLRSPC_GRAY, 1, j2ku_gray_i },
|
||||
{ "I;16B", OPJ_CLRSPC_GRAY, 1, j2ku_gray_i },
|
||||
{ "LA", OPJ_CLRSPC_GRAY, 2, j2ku_graya_la },
|
||||
{ "RGB", OPJ_CLRSPC_GRAY, 1, j2ku_gray_rgb },
|
||||
{ "RGB", OPJ_CLRSPC_GRAY, 2, j2ku_gray_rgb },
|
||||
{ "RGB", OPJ_CLRSPC_SRGB, 3, j2ku_srgb_rgb },
|
||||
{ "RGB", OPJ_CLRSPC_SYCC, 3, j2ku_sycc_rgb },
|
||||
{ "RGB", OPJ_CLRSPC_SRGB, 4, j2ku_srgb_rgb },
|
||||
{ "RGB", OPJ_CLRSPC_SYCC, 4, j2ku_sycc_rgb },
|
||||
{ "RGBA", OPJ_CLRSPC_GRAY, 1, j2ku_gray_rgb },
|
||||
{ "RGBA", OPJ_CLRSPC_GRAY, 2, j2ku_graya_la },
|
||||
{ "RGBA", OPJ_CLRSPC_SRGB, 3, j2ku_srgb_rgb },
|
||||
{ "RGBA", OPJ_CLRSPC_SYCC, 3, j2ku_sycc_rgb },
|
||||
{ "RGBA", OPJ_CLRSPC_SRGB, 4, j2ku_srgba_rgba },
|
||||
{ "RGBA", OPJ_CLRSPC_SYCC, 4, j2ku_sycca_rgba },
|
||||
{"L", OPJ_CLRSPC_GRAY, 1, j2ku_gray_l},
|
||||
{"I;16", OPJ_CLRSPC_GRAY, 1, j2ku_gray_i},
|
||||
{"I;16B", OPJ_CLRSPC_GRAY, 1, j2ku_gray_i},
|
||||
{"LA", OPJ_CLRSPC_GRAY, 2, j2ku_graya_la},
|
||||
{"RGB", OPJ_CLRSPC_GRAY, 1, j2ku_gray_rgb},
|
||||
{"RGB", OPJ_CLRSPC_GRAY, 2, j2ku_gray_rgb},
|
||||
{"RGB", OPJ_CLRSPC_SRGB, 3, j2ku_srgb_rgb},
|
||||
{"RGB", OPJ_CLRSPC_SYCC, 3, j2ku_sycc_rgb},
|
||||
{"RGB", OPJ_CLRSPC_SRGB, 4, j2ku_srgb_rgb},
|
||||
{"RGB", OPJ_CLRSPC_SYCC, 4, j2ku_sycc_rgb},
|
||||
{"RGBA", OPJ_CLRSPC_GRAY, 1, j2ku_gray_rgb},
|
||||
{"RGBA", OPJ_CLRSPC_GRAY, 2, j2ku_graya_la},
|
||||
{"RGBA", OPJ_CLRSPC_SRGB, 3, j2ku_srgb_rgb},
|
||||
{"RGBA", OPJ_CLRSPC_SYCC, 3, j2ku_sycc_rgb},
|
||||
{"RGBA", OPJ_CLRSPC_SRGB, 4, j2ku_srgba_rgba},
|
||||
{"RGBA", OPJ_CLRSPC_SYCC, 4, j2ku_sycca_rgba},
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -578,9 +634,8 @@ enum {
|
|||
};
|
||||
|
||||
static int
|
||||
j2k_decode_entry(Imaging im, ImagingCodecState state)
|
||||
{
|
||||
JPEG2KDECODESTATE *context = (JPEG2KDECODESTATE *) state->context;
|
||||
j2k_decode_entry(Imaging im, ImagingCodecState state) {
|
||||
JPEG2KDECODESTATE *context = (JPEG2KDECODESTATE *)state->context;
|
||||
opj_stream_t *stream = NULL;
|
||||
opj_image_t *image = NULL;
|
||||
opj_codec_t *codec = NULL;
|
||||
|
@ -591,7 +646,6 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
|
|||
unsigned n, tile_height, tile_width;
|
||||
int components;
|
||||
|
||||
|
||||
stream = opj_stream_create(BUFFER_SIZE, OPJ_TRUE);
|
||||
|
||||
if (!stream) {
|
||||
|
@ -645,8 +699,8 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
|
|||
}
|
||||
|
||||
/* Check that this image is something we can handle */
|
||||
if (image->numcomps < 1 || image->numcomps > 4
|
||||
|| image->color_space == OPJ_CLRSPC_UNKNOWN) {
|
||||
if (image->numcomps < 1 || image->numcomps > 4 ||
|
||||
image->color_space == OPJ_CLRSPC_UNKNOWN) {
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
state->state = J2K_STATE_FAILED;
|
||||
goto quick_exit;
|
||||
|
@ -686,15 +740,21 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
|
|||
|
||||
if (color_space == OPJ_CLRSPC_UNSPECIFIED) {
|
||||
switch (image->numcomps) {
|
||||
case 1: case 2: color_space = OPJ_CLRSPC_GRAY; break;
|
||||
case 3: case 4: color_space = OPJ_CLRSPC_SRGB; break;
|
||||
case 1:
|
||||
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) {
|
||||
if (color_space == j2k_unpackers[n].color_space
|
||||
&& image->numcomps == j2k_unpackers[n].components
|
||||
&& strcmp (im->mode, j2k_unpackers[n].mode) == 0) {
|
||||
for (n = 0; n < sizeof(j2k_unpackers) / sizeof(j2k_unpackers[0]); ++n) {
|
||||
if (color_space == j2k_unpackers[n].color_space &&
|
||||
image->numcomps == j2k_unpackers[n].components &&
|
||||
strcmp(im->mode, j2k_unpackers[n].mode) == 0) {
|
||||
unpack = j2k_unpackers[n].unpacker;
|
||||
break;
|
||||
}
|
||||
|
@ -713,14 +773,17 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
|
|||
OPJ_BOOL should_continue;
|
||||
unsigned correction = (1 << params.cp_reduce) - 1;
|
||||
|
||||
if (!opj_read_tile_header(codec,
|
||||
stream,
|
||||
&tile_info.tile_index,
|
||||
&tile_info.data_size,
|
||||
&tile_info.x0, &tile_info.y0,
|
||||
&tile_info.x1, &tile_info.y1,
|
||||
&tile_info.nb_comps,
|
||||
&should_continue)) {
|
||||
if (!opj_read_tile_header(
|
||||
codec,
|
||||
stream,
|
||||
&tile_info.tile_index,
|
||||
&tile_info.data_size,
|
||||
&tile_info.x0,
|
||||
&tile_info.y0,
|
||||
&tile_info.x1,
|
||||
&tile_info.y1,
|
||||
&tile_info.nb_comps,
|
||||
&should_continue)) {
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
state->state = J2K_STATE_FAILED;
|
||||
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,
|
||||
or if it has a negative width or height (i.e. the coordinates are
|
||||
swapped), bail. */
|
||||
if (tile_info.x0 >= tile_info.x1
|
||||
|| tile_info.y0 >= tile_info.y1
|
||||
|| tile_info.x0 < 0
|
||||
|| tile_info.y0 < 0
|
||||
|| (OPJ_UINT32)tile_info.x0 < image->x0
|
||||
|| (OPJ_UINT32)tile_info.y0 < image->y0
|
||||
|| (OPJ_INT32)(tile_info.x1 - image->x0) > im->xsize
|
||||
|| (OPJ_INT32)(tile_info.y1 - image->y0) > im->ysize) {
|
||||
if (tile_info.x0 >= tile_info.x1 || tile_info.y0 >= tile_info.y1 ||
|
||||
tile_info.x0 < 0 || tile_info.y0 < 0 ||
|
||||
(OPJ_UINT32)tile_info.x0 < image->x0 ||
|
||||
(OPJ_UINT32)tile_info.y0 < image->y0 ||
|
||||
(OPJ_INT32)(tile_info.x1 - image->x0) > im->xsize ||
|
||||
(OPJ_INT32)(tile_info.y1 - image->y0) > im->ysize) {
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
state->state = J2K_STATE_FAILED;
|
||||
goto quick_exit;
|
||||
|
@ -760,10 +821,10 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
|
|||
tile_width = tile_info.x1 - tile_info.x0;
|
||||
tile_height = tile_info.y1 - tile_info.y0;
|
||||
components = tile_info.nb_comps == 3 ? 4 : tile_info.nb_comps;
|
||||
if (( tile_width > UINT_MAX / components ) ||
|
||||
( tile_height > UINT_MAX / components ) ||
|
||||
( tile_width > UINT_MAX / (tile_height * components )) ||
|
||||
( tile_height > UINT_MAX / (tile_width * components ))) {
|
||||
if ((tile_width > UINT_MAX / components) ||
|
||||
(tile_height > UINT_MAX / components) ||
|
||||
(tile_width > UINT_MAX / (tile_height * components)) ||
|
||||
(tile_height > UINT_MAX / (tile_width * components))) {
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
state->state = J2K_STATE_FAILED;
|
||||
goto quick_exit;
|
||||
|
@ -777,7 +838,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
|
|||
|
||||
if (buffer_size < tile_info.data_size) {
|
||||
/* 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) {
|
||||
state->errcode = IMAGING_CODEC_MEMORY;
|
||||
state->state = J2K_STATE_FAILED;
|
||||
|
@ -787,12 +848,12 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
|
|||
buffer_size = tile_info.data_size;
|
||||
}
|
||||
|
||||
|
||||
if (!opj_decode_tile_data(codec,
|
||||
tile_info.tile_index,
|
||||
(OPJ_BYTE *)state->buffer,
|
||||
tile_info.data_size,
|
||||
stream)) {
|
||||
if (!opj_decode_tile_data(
|
||||
codec,
|
||||
tile_info.tile_index,
|
||||
(OPJ_BYTE *)state->buffer,
|
||||
tile_info.data_size,
|
||||
stream)) {
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
state->state = J2K_STATE_FAILED;
|
||||
goto quick_exit;
|
||||
|
@ -811,12 +872,12 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
|
|||
state->errcode = IMAGING_CODEC_END;
|
||||
|
||||
if (context->pfile) {
|
||||
if(fclose(context->pfile)){
|
||||
if (fclose(context->pfile)) {
|
||||
context->pfile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
quick_exit:
|
||||
quick_exit:
|
||||
if (codec) {
|
||||
opj_destroy_codec(codec);
|
||||
}
|
||||
|
@ -831,10 +892,8 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
|
|||
}
|
||||
|
||||
int
|
||||
ImagingJpeg2KDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes)
|
||||
{
|
||||
|
||||
if (bytes){
|
||||
ImagingJpeg2KDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
|
||||
if (bytes) {
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
state->state = J2K_STATE_FAILED;
|
||||
return -1;
|
||||
|
@ -867,7 +926,7 @@ ImagingJpeg2KDecodeCleanup(ImagingCodecState state) {
|
|||
JPEG2KDECODESTATE *context = (JPEG2KDECODESTATE *)state->context;
|
||||
|
||||
if (context->error_msg) {
|
||||
free ((void *)context->error_msg);
|
||||
free((void *)context->error_msg);
|
||||
}
|
||||
|
||||
context->error_msg = NULL;
|
||||
|
@ -876,8 +935,7 @@ ImagingJpeg2KDecodeCleanup(ImagingCodecState state) {
|
|||
}
|
||||
|
||||
const char *
|
||||
ImagingJpeg2KVersion(void)
|
||||
{
|
||||
ImagingJpeg2KVersion(void) {
|
||||
return opj_version();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,26 +19,24 @@
|
|||
|
||||
#include "Jpeg2K.h"
|
||||
|
||||
#define CINEMA_24_CS_LENGTH 1302083
|
||||
#define CINEMA_48_CS_LENGTH 651041
|
||||
#define CINEMA_24_CS_LENGTH 1302083
|
||||
#define CINEMA_48_CS_LENGTH 651041
|
||||
#define COMP_24_CS_MAX_LENGTH 1041666
|
||||
#define COMP_48_CS_MAX_LENGTH 520833
|
||||
#define COMP_48_CS_MAX_LENGTH 520833
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Error handler */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
j2k_error(const char *msg, void *client_data)
|
||||
{
|
||||
JPEG2KENCODESTATE *state = (JPEG2KENCODESTATE *) client_data;
|
||||
j2k_error(const char *msg, void *client_data) {
|
||||
JPEG2KENCODESTATE *state = (JPEG2KENCODESTATE *)client_data;
|
||||
free((void *)state->error_msg);
|
||||
state->error_msg = strdup(msg);
|
||||
}
|
||||
|
||||
static void
|
||||
j2k_warn(const char *msg, void *client_data)
|
||||
{
|
||||
j2k_warn(const char *msg, void *client_data) {
|
||||
// Null handler
|
||||
}
|
||||
|
||||
|
@ -47,8 +45,7 @@ j2k_warn(const char *msg, void *client_data)
|
|||
/* -------------------------------------------------------------------- */
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
char *buffer;
|
||||
int result;
|
||||
|
||||
/* Explicitly write zeros */
|
||||
buffer = calloc(p_nb_bytes,1);
|
||||
buffer = calloc(p_nb_bytes, 1);
|
||||
if (!buffer) {
|
||||
return (OPJ_OFF_T)-1;
|
||||
}
|
||||
|
@ -79,8 +74,7 @@ j2k_skip(OPJ_OFF_T p_nb_bytes, void *p_user_data)
|
|||
}
|
||||
|
||||
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;
|
||||
off_t pos = 0;
|
||||
|
||||
|
@ -94,16 +88,13 @@ j2k_seek(OPJ_OFF_T p_nb_bytes, void *p_user_data)
|
|||
/* Encoder */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
typedef void (*j2k_pack_tile_t)(Imaging im, UINT8 *buf,
|
||||
unsigned x0, unsigned y0,
|
||||
unsigned w, unsigned h);
|
||||
typedef void (*j2k_pack_tile_t)(
|
||||
Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h);
|
||||
|
||||
static void
|
||||
j2k_pack_l(Imaging im, UINT8 *buf,
|
||||
unsigned x0, unsigned y0, unsigned w, unsigned h)
|
||||
{
|
||||
j2k_pack_l(Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h) {
|
||||
UINT8 *ptr = buf;
|
||||
unsigned x,y;
|
||||
unsigned x, y;
|
||||
for (y = 0; y < h; ++y) {
|
||||
UINT8 *data = (UINT8 *)(im->image[y + y0] + x0);
|
||||
for (x = 0; x < w; ++x) {
|
||||
|
@ -113,11 +104,9 @@ j2k_pack_l(Imaging im, UINT8 *buf,
|
|||
}
|
||||
|
||||
static void
|
||||
j2k_pack_i16(Imaging im, UINT8 *buf,
|
||||
unsigned x0, unsigned y0, unsigned w, unsigned h)
|
||||
{
|
||||
j2k_pack_i16(Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h) {
|
||||
UINT8 *ptr = buf;
|
||||
unsigned x,y;
|
||||
unsigned x, y;
|
||||
for (y = 0; y < h; ++y) {
|
||||
UINT8 *data = (UINT8 *)(im->image[y + y0] + x0);
|
||||
for (x = 0; x < w; ++x) {
|
||||
|
@ -127,14 +116,11 @@ j2k_pack_i16(Imaging im, UINT8 *buf,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
j2k_pack_la(Imaging im, UINT8 *buf,
|
||||
unsigned x0, unsigned y0, unsigned w, unsigned h)
|
||||
{
|
||||
j2k_pack_la(Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h) {
|
||||
UINT8 *ptr = buf;
|
||||
UINT8 *ptra = buf + w * h;
|
||||
unsigned x,y;
|
||||
unsigned x, y;
|
||||
for (y = 0; y < h; ++y) {
|
||||
UINT8 *data = (UINT8 *)(im->image[y + y0] + 4 * x0);
|
||||
for (x = 0; x < w; ++x) {
|
||||
|
@ -146,13 +132,11 @@ j2k_pack_la(Imaging im, UINT8 *buf,
|
|||
}
|
||||
|
||||
static void
|
||||
j2k_pack_rgb(Imaging im, UINT8 *buf,
|
||||
unsigned x0, unsigned y0, unsigned w, unsigned h)
|
||||
{
|
||||
j2k_pack_rgb(Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h) {
|
||||
UINT8 *pr = buf;
|
||||
UINT8 *pg = pr + w * h;
|
||||
UINT8 *pb = pg + w * h;
|
||||
unsigned x,y;
|
||||
unsigned x, y;
|
||||
for (y = 0; y < h; ++y) {
|
||||
UINT8 *data = (UINT8 *)(im->image[y + y0] + 4 * x0);
|
||||
for (x = 0; x < w; ++x) {
|
||||
|
@ -165,14 +149,13 @@ j2k_pack_rgb(Imaging im, UINT8 *buf,
|
|||
}
|
||||
|
||||
static void
|
||||
j2k_pack_rgba(Imaging im, UINT8 *buf,
|
||||
unsigned x0, unsigned y0, unsigned w, unsigned h)
|
||||
{
|
||||
j2k_pack_rgba(
|
||||
Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h) {
|
||||
UINT8 *pr = buf;
|
||||
UINT8 *pg = pr + w * h;
|
||||
UINT8 *pb = pg + w * h;
|
||||
UINT8 *pa = pb + w * h;
|
||||
unsigned x,y;
|
||||
unsigned x, y;
|
||||
for (y = 0; y < h; ++y) {
|
||||
UINT8 *data = (UINT8 *)(im->image[y + y0] + 4 * x0);
|
||||
for (x = 0; x < w; ++x) {
|
||||
|
@ -192,8 +175,7 @@ enum {
|
|||
};
|
||||
|
||||
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;
|
||||
int n;
|
||||
|
||||
|
@ -215,8 +197,9 @@ j2k_set_cinema_params(Imaging im, int components, opj_cparameters_t *params)
|
|||
params->irreversible = 1;
|
||||
|
||||
if (params->cp_cinema == OPJ_CINEMA4K_24) {
|
||||
float max_rate = ((float)(components * im->xsize * im->ysize * 8)
|
||||
/ (CINEMA_24_CS_LENGTH * 8));
|
||||
float max_rate =
|
||||
((float)(components * im->xsize * im->ysize * 8) /
|
||||
(CINEMA_24_CS_LENGTH * 8));
|
||||
|
||||
params->POC[0].tile = 1;
|
||||
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) {
|
||||
params->tcp_rates[n] = max_rate;
|
||||
} else {
|
||||
rate = ((float)(components * im->xsize * im->ysize * 8)
|
||||
/ (params->tcp_rates[n] * 8));
|
||||
rate =
|
||||
((float)(components * im->xsize * im->ysize * 8) /
|
||||
(params->tcp_rates[n] * 8));
|
||||
if (rate > CINEMA_24_CS_LENGTH) {
|
||||
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;
|
||||
} else {
|
||||
float max_rate = ((float)(components * im->xsize * im->ysize * 8)
|
||||
/ (CINEMA_48_CS_LENGTH * 8));
|
||||
float max_rate =
|
||||
((float)(components * im->xsize * im->ysize * 8) /
|
||||
(CINEMA_48_CS_LENGTH * 8));
|
||||
|
||||
for (n = 0; n < params->tcp_numlayers; ++n) {
|
||||
rate = 0;
|
||||
if (params->tcp_rates[0] == 0) {
|
||||
params->tcp_rates[n] = max_rate;
|
||||
} else {
|
||||
rate = ((float)(components * im->xsize * im->ysize * 8)
|
||||
/ (params->tcp_rates[n] * 8));
|
||||
rate =
|
||||
((float)(components * im->xsize * im->ysize * 8) /
|
||||
(params->tcp_rates[n] * 8));
|
||||
if (rate > CINEMA_48_CS_LENGTH) {
|
||||
params->tcp_rates[n] = max_rate;
|
||||
}
|
||||
|
@ -270,8 +256,7 @@ j2k_set_cinema_params(Imaging im, int components, opj_cparameters_t *params)
|
|||
}
|
||||
|
||||
static int
|
||||
j2k_encode_entry(Imaging im, ImagingCodecState state)
|
||||
{
|
||||
j2k_encode_entry(Imaging im, ImagingCodecState state) {
|
||||
JPEG2KENCODESTATE *context = (JPEG2KENCODESTATE *)state->context;
|
||||
opj_stream_t *stream = NULL;
|
||||
opj_image_t *image = NULL;
|
||||
|
@ -312,35 +297,35 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
|
|||
#endif
|
||||
|
||||
/* Setup an opj_image */
|
||||
if (strcmp (im->mode, "L") == 0) {
|
||||
if (strcmp(im->mode, "L") == 0) {
|
||||
components = 1;
|
||||
color_space = OPJ_CLRSPC_GRAY;
|
||||
pack = j2k_pack_l;
|
||||
} else if (strcmp (im->mode, "I;16") == 0){
|
||||
} else if (strcmp(im->mode, "I;16") == 0) {
|
||||
components = 1;
|
||||
color_space = OPJ_CLRSPC_GRAY;
|
||||
pack = j2k_pack_i16;
|
||||
prec = 16;
|
||||
bpp = 12;
|
||||
} else if (strcmp (im->mode, "I;16B") == 0){
|
||||
} else if (strcmp(im->mode, "I;16B") == 0) {
|
||||
components = 1;
|
||||
color_space = OPJ_CLRSPC_GRAY;
|
||||
pack = j2k_pack_i16;
|
||||
prec = 16;
|
||||
bpp = 12;
|
||||
} else if (strcmp (im->mode, "LA") == 0) {
|
||||
} else if (strcmp(im->mode, "LA") == 0) {
|
||||
components = 2;
|
||||
color_space = OPJ_CLRSPC_GRAY;
|
||||
pack = j2k_pack_la;
|
||||
} else if (strcmp (im->mode, "RGB") == 0) {
|
||||
} else if (strcmp(im->mode, "RGB") == 0) {
|
||||
components = 3;
|
||||
color_space = OPJ_CLRSPC_SRGB;
|
||||
pack = j2k_pack_rgb;
|
||||
} else if (strcmp (im->mode, "YCbCr") == 0) {
|
||||
} else if (strcmp(im->mode, "YCbCr") == 0) {
|
||||
components = 3;
|
||||
color_space = OPJ_CLRSPC_SYCC;
|
||||
pack = j2k_pack_rgb;
|
||||
} else if (strcmp (im->mode, "RGBA") == 0) {
|
||||
} else if (strcmp(im->mode, "RGBA") == 0) {
|
||||
components = 4;
|
||||
color_space = OPJ_CLRSPC_SRGB;
|
||||
pack = j2k_pack_rgba;
|
||||
|
@ -400,8 +385,9 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
|
|||
float *pq;
|
||||
|
||||
if (len > 0) {
|
||||
if ((unsigned)len > sizeof(params.tcp_rates) / sizeof(params.tcp_rates[0])) {
|
||||
len = sizeof(params.tcp_rates)/sizeof(params.tcp_rates[0]);
|
||||
if ((unsigned)len >
|
||||
sizeof(params.tcp_rates) / sizeof(params.tcp_rates[0])) {
|
||||
len = sizeof(params.tcp_rates) / sizeof(params.tcp_rates[0]);
|
||||
}
|
||||
|
||||
params.tcp_numlayers = (int)len;
|
||||
|
@ -431,16 +417,16 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
|
|||
params.numresolution = context->num_resolutions;
|
||||
}
|
||||
|
||||
if (context->cblk_width >= 4 && context->cblk_width <= 1024
|
||||
&& context->cblk_height >= 4 && context->cblk_height <= 1024
|
||||
&& context->cblk_width * context->cblk_height <= 4096) {
|
||||
if (context->cblk_width >= 4 && context->cblk_width <= 1024 &&
|
||||
context->cblk_height >= 4 && context->cblk_height <= 1024 &&
|
||||
context->cblk_width * context->cblk_height <= 4096) {
|
||||
params.cblockw_init = context->cblk_width;
|
||||
params.cblockh_init = context->cblk_height;
|
||||
}
|
||||
|
||||
if (context->precinct_width >= 4 && context->precinct_height >= 4
|
||||
&& context->precinct_width >= context->cblk_width
|
||||
&& context->precinct_height > context->cblk_height) {
|
||||
if (context->precinct_width >= 4 && context->precinct_height >= 4 &&
|
||||
context->precinct_width >= context->cblk_width &&
|
||||
context->precinct_height > context->cblk_height) {
|
||||
params.prcw_init[0] = context->precinct_width;
|
||||
params.prch_init[0] = context->precinct_height;
|
||||
params.res_spec = 1;
|
||||
|
@ -454,22 +440,22 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
|
|||
params.cp_cinema = context->cinema_mode;
|
||||
|
||||
switch (params.cp_cinema) {
|
||||
case OPJ_OFF:
|
||||
params.cp_rsiz = OPJ_STD_RSIZ;
|
||||
break;
|
||||
case OPJ_CINEMA2K_24:
|
||||
case OPJ_CINEMA2K_48:
|
||||
params.cp_rsiz = OPJ_CINEMA2K;
|
||||
if (params.numresolution > 6) {
|
||||
params.numresolution = 6;
|
||||
}
|
||||
break;
|
||||
case OPJ_CINEMA4K_24:
|
||||
params.cp_rsiz = OPJ_CINEMA4K;
|
||||
if (params.numresolution > 7) {
|
||||
params.numresolution = 7;
|
||||
}
|
||||
break;
|
||||
case OPJ_OFF:
|
||||
params.cp_rsiz = OPJ_STD_RSIZ;
|
||||
break;
|
||||
case OPJ_CINEMA2K_24:
|
||||
case OPJ_CINEMA2K_48:
|
||||
params.cp_rsiz = OPJ_CINEMA2K;
|
||||
if (params.numresolution > 6) {
|
||||
params.numresolution = 6;
|
||||
}
|
||||
break;
|
||||
case OPJ_CINEMA4K_24:
|
||||
params.cp_rsiz = OPJ_CINEMA4K;
|
||||
if (params.numresolution > 7) {
|
||||
params.numresolution = 7;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (context->cinema_mode != OPJ_OFF) {
|
||||
|
@ -504,24 +490,24 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
|
|||
}
|
||||
|
||||
/* Write each tile */
|
||||
tiles_x = (im->xsize + (params.image_offset_x0 - params.cp_tx0)
|
||||
+ tile_width - 1) / tile_width;
|
||||
tiles_y = (im->ysize + (params.image_offset_y0 - params.cp_ty0)
|
||||
+ tile_height - 1) / tile_height;
|
||||
tiles_x = (im->xsize + (params.image_offset_x0 - params.cp_tx0) + tile_width - 1) /
|
||||
tile_width;
|
||||
tiles_y = (im->ysize + (params.image_offset_y0 - params.cp_ty0) + tile_height - 1) /
|
||||
tile_height;
|
||||
|
||||
/* check for integer overflow for the malloc line, checking any expression
|
||||
that may multiply either tile_width or tile_height */
|
||||
_overflow_scale_factor = components * prec;
|
||||
if (( tile_width > UINT_MAX / _overflow_scale_factor ) ||
|
||||
( tile_height > UINT_MAX / _overflow_scale_factor ) ||
|
||||
( tile_width > UINT_MAX / (tile_height * _overflow_scale_factor )) ||
|
||||
( tile_height > UINT_MAX / (tile_width * _overflow_scale_factor ))) {
|
||||
if ((tile_width > UINT_MAX / _overflow_scale_factor) ||
|
||||
(tile_height > UINT_MAX / _overflow_scale_factor) ||
|
||||
(tile_width > UINT_MAX / (tile_height * _overflow_scale_factor)) ||
|
||||
(tile_height > UINT_MAX / (tile_width * _overflow_scale_factor))) {
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
state->state = J2K_STATE_FAILED;
|
||||
goto quick_exit;
|
||||
}
|
||||
/* 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) {
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
state->state = J2K_STATE_FAILED;
|
||||
|
@ -564,8 +550,7 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
|
|||
|
||||
data_size = pixw * pixh * components * prec / 8;
|
||||
|
||||
if (!opj_write_tile(codec, tile_ndx++, state->buffer,
|
||||
data_size, stream)) {
|
||||
if (!opj_write_tile(codec, tile_ndx++, state->buffer, data_size, stream)) {
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
state->state = J2K_STATE_FAILED;
|
||||
goto quick_exit;
|
||||
|
@ -583,7 +568,7 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
|
|||
state->state = J2K_STATE_DONE;
|
||||
ret = -1;
|
||||
|
||||
quick_exit:
|
||||
quick_exit:
|
||||
if (codec) {
|
||||
opj_destroy_codec(codec);
|
||||
}
|
||||
|
@ -598,14 +583,12 @@ j2k_encode_entry(Imaging im, ImagingCodecState state)
|
|||
}
|
||||
|
||||
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) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (state->state == J2K_STATE_START) {
|
||||
|
||||
state->state = J2K_STATE_ENCODING;
|
||||
|
||||
return j2k_encode_entry(im, state);
|
||||
|
@ -628,12 +611,11 @@ ImagingJpeg2KEncodeCleanup(ImagingCodecState state) {
|
|||
}
|
||||
|
||||
if (context->error_msg) {
|
||||
free ((void *)context->error_msg);
|
||||
free((void *)context->error_msg);
|
||||
}
|
||||
|
||||
context->error_msg = NULL;
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,10 +21,9 @@
|
|||
* See the README file for details on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#ifdef HAVE_LIBJPEG
|
||||
#ifdef HAVE_LIBJPEG
|
||||
|
||||
#undef HAVE_PROTOTYPES
|
||||
#undef HAVE_STDLIB_H
|
||||
|
@ -37,7 +36,6 @@
|
|||
|
||||
#include "Jpeg.h"
|
||||
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
|
||||
|
@ -50,20 +48,19 @@ char *libjpeg_turbo_version = NULL;
|
|||
#endif
|
||||
|
||||
int
|
||||
ImagingJpegUseJCSExtensions()
|
||||
{
|
||||
ImagingJpegUseJCSExtensions() {
|
||||
int use_jcs_extensions = 0;
|
||||
#ifdef JCS_EXTENSIONS
|
||||
#if defined(LIBJPEG_TURBO_VERSION_NUMBER)
|
||||
#if LIBJPEG_TURBO_VERSION_NUMBER >= 1002010
|
||||
use_jcs_extensions = 1;
|
||||
#endif
|
||||
#else
|
||||
if (libjpeg_turbo_version) {
|
||||
use_jcs_extensions = strcmp(libjpeg_turbo_version, "1.2.1") >= 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#ifdef JCS_EXTENSIONS
|
||||
#if defined(LIBJPEG_TURBO_VERSION_NUMBER)
|
||||
#if LIBJPEG_TURBO_VERSION_NUMBER >= 1002010
|
||||
use_jcs_extensions = 1;
|
||||
#endif
|
||||
#else
|
||||
if (libjpeg_turbo_version) {
|
||||
use_jcs_extensions = strcmp(libjpeg_turbo_version, "1.2.1") >= 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return use_jcs_extensions;
|
||||
}
|
||||
|
||||
|
@ -72,24 +69,19 @@ ImagingJpegUseJCSExtensions()
|
|||
/* -------------------------------------------------------------------- */
|
||||
|
||||
METHODDEF(void)
|
||||
stub(j_decompress_ptr cinfo)
|
||||
{
|
||||
/* empty */
|
||||
}
|
||||
stub(j_decompress_ptr cinfo) { /* empty */ }
|
||||
|
||||
METHODDEF(boolean)
|
||||
fill_input_buffer(j_decompress_ptr cinfo)
|
||||
{
|
||||
fill_input_buffer(j_decompress_ptr cinfo) {
|
||||
/* Suspension */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
||||
{
|
||||
JPEGSOURCE* source = (JPEGSOURCE*) cinfo->src;
|
||||
skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
|
||||
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.
|
||||
This will force the JPEG library to suspend decoding. */
|
||||
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)
|
||||
jpeg_buffer_src(j_decompress_ptr cinfo, JPEGSOURCE* source)
|
||||
{
|
||||
cinfo->src = (void*) source;
|
||||
jpeg_buffer_src(j_decompress_ptr cinfo, JPEGSOURCE *source) {
|
||||
cinfo->src = (void *)source;
|
||||
|
||||
/* Prepare for suspending reader */
|
||||
source->pub.init_source = stub;
|
||||
source->pub.fill_input_buffer = fill_input_buffer;
|
||||
source->pub.skip_input_data = skip_input_data;
|
||||
source->pub.resync_to_restart = jpeg_resync_to_restart;
|
||||
source->pub.term_source = stub;
|
||||
source->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
|
||||
/* Prepare for suspending reader */
|
||||
source->pub.init_source = stub;
|
||||
source->pub.fill_input_buffer = fill_input_buffer;
|
||||
source->pub.skip_input_data = skip_input_data;
|
||||
source->pub.resync_to_restart = jpeg_resync_to_restart;
|
||||
source->pub.term_source = stub;
|
||||
source->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
|
||||
|
||||
source->skip = 0;
|
||||
source->skip = 0;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Error handler */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
METHODDEF(void)
|
||||
error(j_common_ptr cinfo)
|
||||
{
|
||||
JPEGERROR* error;
|
||||
error = (JPEGERROR*) cinfo->err;
|
||||
longjmp(error->setjmp_buffer, 1);
|
||||
error(j_common_ptr cinfo) {
|
||||
JPEGERROR *error;
|
||||
error = (JPEGERROR *)cinfo->err;
|
||||
longjmp(error->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
output(j_common_ptr cinfo)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
output(j_common_ptr cinfo) { /* nothing */ }
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Decoder */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes)
|
||||
{
|
||||
JPEGSTATE* context = (JPEGSTATE*) state->context;
|
||||
ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
|
||||
JPEGSTATE *context = (JPEGSTATE *)state->context;
|
||||
int ok;
|
||||
|
||||
if (setjmp(context->error.setjmp_buffer)) {
|
||||
|
@ -157,7 +141,6 @@ ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t by
|
|||
}
|
||||
|
||||
if (!state->state) {
|
||||
|
||||
/* Setup decompression context */
|
||||
context->cinfo.err = jpeg_std_error(&context->error.pub);
|
||||
context->error.pub.error_exit = error;
|
||||
|
@ -167,7 +150,6 @@ ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t by
|
|||
|
||||
/* Ready to decode */
|
||||
state->state = 1;
|
||||
|
||||
}
|
||||
|
||||
/* Load the source buffer */
|
||||
|
@ -182,137 +164,137 @@ ImagingJpegDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t by
|
|||
}
|
||||
|
||||
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. */
|
||||
do {
|
||||
} while (ok == JPEG_HEADER_TABLES_ONLY);
|
||||
|
||||
/* Note that we cannot return unless we have decoded
|
||||
as much data as possible. */
|
||||
ok = jpeg_read_header(&context->cinfo, FALSE);
|
||||
if (ok == JPEG_SUSPENDED) {
|
||||
break;
|
||||
}
|
||||
|
||||
} while (ok == JPEG_HEADER_TABLES_ONLY);
|
||||
/* Decoder settings */
|
||||
|
||||
if (ok == JPEG_SUSPENDED) {
|
||||
break;
|
||||
}
|
||||
/* jpegmode indicates whats in the file; if not set, we'll
|
||||
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 */
|
||||
|
||||
/* jpegmode indicates whats in the file; if not set, we'll
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
/* 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;
|
||||
}
|
||||
#endif
|
||||
else if (strcmp(context->rawmode, "CMYK") == 0 ||
|
||||
strcmp(context->rawmode, "CMYK;I") == 0) {
|
||||
context->cinfo.out_color_space = JCS_CMYK;
|
||||
} else if (strcmp(context->rawmode, "YCbCr") == 0) {
|
||||
context->cinfo.out_color_space = JCS_YCbCr;
|
||||
} else if (strcmp(context->rawmode, "YCbCrK") == 0) {
|
||||
context->cinfo.out_color_space = JCS_YCCK;
|
||||
} else {
|
||||
/* Disable decoder conversions */
|
||||
context->cinfo.jpeg_color_space = JCS_UNKNOWN;
|
||||
context->cinfo.out_color_space = JCS_UNKNOWN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (
|
||||
strcmp(context->rawmode, "CMYK") == 0 ||
|
||||
strcmp(context->rawmode, "CMYK;I") == 0) {
|
||||
context->cinfo.out_color_space = JCS_CMYK;
|
||||
} else if (strcmp(context->rawmode, "YCbCr") == 0) {
|
||||
context->cinfo.out_color_space = JCS_YCbCr;
|
||||
} else if (strcmp(context->rawmode, "YCbCrK") == 0) {
|
||||
context->cinfo.out_color_space = JCS_YCCK;
|
||||
} else {
|
||||
/* Disable decoder conversions */
|
||||
context->cinfo.jpeg_color_space = JCS_UNKNOWN;
|
||||
context->cinfo.out_color_space = JCS_UNKNOWN;
|
||||
}
|
||||
|
||||
if (context->scale > 1) {
|
||||
context->cinfo.scale_num = 1;
|
||||
context->cinfo.scale_denom = context->scale;
|
||||
}
|
||||
if (context->draft) {
|
||||
context->cinfo.do_fancy_upsampling = FALSE;
|
||||
context->cinfo.dct_method = JDCT_FASTEST;
|
||||
}
|
||||
if (context->scale > 1) {
|
||||
context->cinfo.scale_num = 1;
|
||||
context->cinfo.scale_denom = context->scale;
|
||||
}
|
||||
if (context->draft) {
|
||||
context->cinfo.do_fancy_upsampling = FALSE;
|
||||
context->cinfo.dct_method = JDCT_FASTEST;
|
||||
}
|
||||
|
||||
state->state++;
|
||||
/* fall through */
|
||||
state->state++;
|
||||
/* fall through */
|
||||
|
||||
case 2:
|
||||
case 2:
|
||||
|
||||
/* Set things up for decompression (this processes the entire
|
||||
file if necessary to return data line by line) */
|
||||
if (!jpeg_start_decompress(&context->cinfo)) {
|
||||
break;
|
||||
}
|
||||
/* Set things up for decompression (this processes the entire
|
||||
file if necessary to return data line by line) */
|
||||
if (!jpeg_start_decompress(&context->cinfo)) {
|
||||
break;
|
||||
}
|
||||
|
||||
state->state++;
|
||||
/* fall through */
|
||||
state->state++;
|
||||
/* fall through */
|
||||
|
||||
case 3:
|
||||
case 3:
|
||||
|
||||
/* Decompress a single line of data */
|
||||
ok = 1;
|
||||
while (state->y < state->ysize) {
|
||||
ok = jpeg_read_scanlines(&context->cinfo, &state->buffer, 1);
|
||||
/* Decompress a single line of data */
|
||||
ok = 1;
|
||||
while (state->y < state->ysize) {
|
||||
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) {
|
||||
break;
|
||||
}
|
||||
state->shuffle((UINT8*) im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize, state->buffer,
|
||||
state->xsize);
|
||||
state->y++;
|
||||
}
|
||||
if (ok != 1) {
|
||||
break;
|
||||
}
|
||||
state->state++;
|
||||
/* fall through */
|
||||
state->state++;
|
||||
/* fall through */
|
||||
|
||||
case 4:
|
||||
case 4:
|
||||
|
||||
/* Finish decompression */
|
||||
if (!jpeg_finish_decompress(&context->cinfo)) {
|
||||
/* FIXME: add strictness mode test */
|
||||
if (state->y < state->ysize) {
|
||||
break;
|
||||
/* Finish decompression */
|
||||
if (!jpeg_finish_decompress(&context->cinfo)) {
|
||||
/* FIXME: add strictness mode test */
|
||||
if (state->y < state->ysize) {
|
||||
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 context->source.pub.next_input_byte - buf;
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Cleanup */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
int ImagingJpegDecodeCleanup(ImagingCodecState state){
|
||||
int
|
||||
ImagingJpegDecodeCleanup(ImagingCodecState state) {
|
||||
/* called to free the decompression engine when the decode terminates
|
||||
due to a corrupt or truncated image
|
||||
*/
|
||||
JPEGSTATE* context = (JPEGSTATE*) state->context;
|
||||
JPEGSTATE *context = (JPEGSTATE *)state->context;
|
||||
|
||||
/* Clean up */
|
||||
jpeg_destroy_decompress(&context->cinfo);
|
||||
|
@ -320,4 +302,3 @@ int ImagingJpegDecodeCleanup(ImagingCodecState state){
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -19,10 +19,9 @@
|
|||
* See the README file for details on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#ifdef HAVE_LIBJPEG
|
||||
#ifdef HAVE_LIBJPEG
|
||||
|
||||
#undef HAVE_PROTOTYPES
|
||||
#undef HAVE_STDLIB_H
|
||||
|
@ -40,51 +39,42 @@
|
|||
/* -------------------------------------------------------------------- */
|
||||
|
||||
METHODDEF(void)
|
||||
stub(j_compress_ptr cinfo)
|
||||
{
|
||||
/* empty */
|
||||
}
|
||||
stub(j_compress_ptr cinfo) { /* empty */ }
|
||||
|
||||
METHODDEF(boolean)
|
||||
empty_output_buffer (j_compress_ptr cinfo)
|
||||
{
|
||||
empty_output_buffer(j_compress_ptr cinfo) {
|
||||
/* Suspension */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_buffer_dest(j_compress_ptr cinfo, JPEGDESTINATION* destination)
|
||||
{
|
||||
cinfo->dest = (void*) destination;
|
||||
jpeg_buffer_dest(j_compress_ptr cinfo, JPEGDESTINATION *destination) {
|
||||
cinfo->dest = (void *)destination;
|
||||
|
||||
destination->pub.init_destination = stub;
|
||||
destination->pub.empty_output_buffer = empty_output_buffer;
|
||||
destination->pub.term_destination = stub;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Error handler */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
METHODDEF(void)
|
||||
error(j_common_ptr cinfo)
|
||||
{
|
||||
JPEGERROR* error;
|
||||
error = (JPEGERROR*) cinfo->err;
|
||||
(*cinfo->err->output_message) (cinfo);
|
||||
error(j_common_ptr cinfo) {
|
||||
JPEGERROR *error;
|
||||
error = (JPEGERROR *)cinfo->err;
|
||||
(*cinfo->err->output_message)(cinfo);
|
||||
longjmp(error->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Encoder */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||
{
|
||||
JPEGENCODERSTATE* context = (JPEGENCODERSTATE*) state->context;
|
||||
ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
|
||||
JPEGENCODERSTATE *context = (JPEGENCODERSTATE *)state->context;
|
||||
int ok;
|
||||
|
||||
if (setjmp(context->error.setjmp_buffer)) {
|
||||
|
@ -95,7 +85,6 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
}
|
||||
|
||||
if (!state->state) {
|
||||
|
||||
/* Setup compression context (very similar to the decoder) */
|
||||
context->cinfo.err = jpeg_std_error(&context->error.pub);
|
||||
context->error.pub.error_exit = error;
|
||||
|
@ -106,7 +95,6 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
|
||||
/* Ready to encode */
|
||||
state->state = 1;
|
||||
|
||||
}
|
||||
|
||||
/* Load the destination buffer */
|
||||
|
@ -114,7 +102,6 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
context->destination.pub.free_in_buffer = bytes;
|
||||
|
||||
switch (state->state) {
|
||||
|
||||
case 1:
|
||||
|
||||
context->cinfo.image_width = state->xsize;
|
||||
|
@ -136,11 +123,11 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
case 32:
|
||||
context->cinfo.input_components = 4;
|
||||
context->cinfo.in_color_space = JCS_CMYK;
|
||||
#ifdef JCS_EXTENSIONS
|
||||
#ifdef JCS_EXTENSIONS
|
||||
if (strcmp(context->rawmode, "RGBX") == 0) {
|
||||
context->cinfo.in_color_space = JCS_EXT_RGBX;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
state->errcode = IMAGING_CODEC_CONFIG;
|
||||
|
@ -159,15 +146,20 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
quality = context->quality;
|
||||
}
|
||||
for (i = 0; i < context->qtablesLen; i++) {
|
||||
jpeg_add_quant_table(&context->cinfo, i, &context->qtables[i * DCTSIZE2],
|
||||
quality, FALSE);
|
||||
jpeg_add_quant_table(
|
||||
&context->cinfo,
|
||||
i,
|
||||
&context->qtables[i * DCTSIZE2],
|
||||
quality,
|
||||
FALSE);
|
||||
context->cinfo.comp_info[i].quant_tbl_no = i;
|
||||
last_q = i;
|
||||
}
|
||||
if (context->qtablesLen == 1) {
|
||||
// jpeg_set_defaults created two qtables internally, but we only wanted one.
|
||||
jpeg_add_quant_table(&context->cinfo, 1, &context->qtables[0],
|
||||
quality, FALSE);
|
||||
// jpeg_set_defaults created two qtables internally, but we only
|
||||
// wanted one.
|
||||
jpeg_add_quant_table(
|
||||
&context->cinfo, 1, &context->qtables[0], quality, FALSE);
|
||||
}
|
||||
for (i = last_q; i < context->cinfo.num_components; i++) {
|
||||
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 */
|
||||
switch (context->subsampling)
|
||||
{
|
||||
case 0: /* 1x1 1x1 1x1 (4:4:4) : None */
|
||||
switch (context->subsampling) {
|
||||
case 0: /* 1x1 1x1 1x1 (4:4:4) : None */
|
||||
{
|
||||
context->cinfo.comp_info[0].h_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;
|
||||
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].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;
|
||||
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].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;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
/* Use the lib's default */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (context->progressive) {
|
||||
jpeg_simple_progression(&context->cinfo);
|
||||
}
|
||||
context->cinfo.smoothing_factor = context->smooth;
|
||||
context->cinfo.optimize_coding = (boolean) context->optimize;
|
||||
if (context->xdpi > 0 && context->ydpi > 0) {
|
||||
context->cinfo.write_JFIF_header = TRUE;
|
||||
context->cinfo.density_unit = 1; /* dots per inch */
|
||||
context->cinfo.X_density = context->xdpi;
|
||||
context->cinfo.Y_density = context->ydpi;
|
||||
}
|
||||
}
|
||||
if (context->progressive) {
|
||||
jpeg_simple_progression(&context->cinfo);
|
||||
}
|
||||
context->cinfo.smoothing_factor = context->smooth;
|
||||
context->cinfo.optimize_coding = (boolean)context->optimize;
|
||||
if (context->xdpi > 0 && context->ydpi > 0) {
|
||||
context->cinfo.write_JFIF_header = TRUE;
|
||||
context->cinfo.density_unit = 1; /* dots per inch */
|
||||
context->cinfo.X_density = context->xdpi;
|
||||
context->cinfo.Y_density = context->ydpi;
|
||||
}
|
||||
switch (context->streamtype) {
|
||||
case 1:
|
||||
/* tables only -- not yet implemented */
|
||||
|
@ -248,13 +238,16 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
|
||||
case 2:
|
||||
// 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;
|
||||
}
|
||||
//add exif header
|
||||
if (context->rawExifLen > 0){
|
||||
jpeg_write_marker(&context->cinfo, JPEG_APP0+1,
|
||||
(unsigned char*)context->rawExif, context->rawExifLen);
|
||||
// add exif header
|
||||
if (context->rawExifLen > 0) {
|
||||
jpeg_write_marker(
|
||||
&context->cinfo,
|
||||
JPEG_APP0 + 1,
|
||||
(unsigned char *)context->rawExif,
|
||||
context->rawExifLen);
|
||||
}
|
||||
|
||||
state->state++;
|
||||
|
@ -267,8 +260,10 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
if (n > context->destination.pub.free_in_buffer) {
|
||||
n = context->destination.pub.free_in_buffer;
|
||||
}
|
||||
memcpy(context->destination.pub.next_output_byte,
|
||||
context->extra + context->extra_offset, n);
|
||||
memcpy(
|
||||
context->destination.pub.next_output_byte,
|
||||
context->extra + context->extra_offset,
|
||||
n);
|
||||
context->destination.pub.next_output_byte += n;
|
||||
context->destination.pub.free_in_buffer -= n;
|
||||
context->extra_offset += n;
|
||||
|
@ -282,15 +277,17 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
}
|
||||
|
||||
case 4:
|
||||
if (1024 > context->destination.pub.free_in_buffer){
|
||||
if (1024 > context->destination.pub.free_in_buffer) {
|
||||
break;
|
||||
}
|
||||
|
||||
ok = 1;
|
||||
while (state->y < state->ysize) {
|
||||
state->shuffle(state->buffer,
|
||||
(UINT8*) im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize, state->xsize);
|
||||
state->shuffle(
|
||||
state->buffer,
|
||||
(UINT8 *)im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize,
|
||||
state->xsize);
|
||||
ok = jpeg_write_scanlines(&context->cinfo, &state->buffer, 1);
|
||||
if (ok != 1) {
|
||||
break;
|
||||
|
@ -330,17 +327,14 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
/* if (jerr.pub.num_warnings) return BROKEN; */
|
||||
state->errcode = IMAGING_CODEC_END;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* Return number of bytes in output buffer */
|
||||
return context->destination.pub.next_output_byte - buf;
|
||||
|
||||
}
|
||||
|
||||
const char*
|
||||
ImagingJpegVersion(void)
|
||||
{
|
||||
const char *
|
||||
ImagingJpegVersion(void) {
|
||||
static char version[20];
|
||||
sprintf(version, "%d.%d", JPEG_LIB_VERSION / 10, JPEG_LIB_VERSION % 10);
|
||||
return version;
|
||||
|
|
|
@ -13,65 +13,60 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#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
|
||||
ImagingConvertMatrix(Imaging im, const char *mode, float m[])
|
||||
{
|
||||
ImagingConvertMatrix(Imaging im, const char *mode, float m[]) {
|
||||
Imaging imOut;
|
||||
int x, y;
|
||||
|
||||
/* Assume there's enough data in the buffer */
|
||||
if (!im) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
if (strcmp(mode, "L") == 0 && im->bands == 3) {
|
||||
|
||||
imOut = ImagingNewDirty("L", im->xsize, im->ysize);
|
||||
if (!imOut) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (y = 0; y < im->ysize; y++) {
|
||||
UINT8* in = (UINT8*) im->image[y];
|
||||
UINT8* out = (UINT8*) imOut->image[y];
|
||||
UINT8 *in = (UINT8 *)im->image[y];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y];
|
||||
|
||||
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);
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (strlen(mode) == 3 && im->bands == 3) {
|
||||
|
||||
imOut = ImagingNewDirty(mode, im->xsize, im->ysize);
|
||||
if (!imOut) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (y = 0; y < im->ysize; y++) {
|
||||
UINT8* in = (UINT8*) im->image[y];
|
||||
UINT8* out = (UINT8*) imOut->image[y];
|
||||
UINT8 *in = (UINT8 *)im->image[y];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y];
|
||||
|
||||
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 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 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 v2 = m[8] * in[0] + m[9] * in[1] + m[10] * in[2] + m[11] + 0.5;
|
||||
out[0] = CLIPF(v0);
|
||||
out[1] = CLIPF(v1);
|
||||
out[2] = CLIPF(v2);
|
||||
in += 4; out += 4;
|
||||
in += 4;
|
||||
out += 4;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
return imOut;
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
#include "Imaging.h"
|
||||
|
||||
Imaging
|
||||
ImagingModeFilter(Imaging im, int size)
|
||||
{
|
||||
ImagingModeFilter(Imaging im, int size) {
|
||||
Imaging imOut;
|
||||
int x, y, i;
|
||||
int xx, yy;
|
||||
|
@ -26,7 +25,7 @@ ImagingModeFilter(Imaging im, int size)
|
|||
int histogram[256];
|
||||
|
||||
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);
|
||||
|
@ -37,9 +36,8 @@ ImagingModeFilter(Imaging im, int size)
|
|||
size = size / 2;
|
||||
|
||||
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++) {
|
||||
|
||||
/* calculate histogram over current area */
|
||||
|
||||
/* FIXME: brute force! to improve, update the histogram
|
||||
|
@ -50,7 +48,7 @@ ImagingModeFilter(Imaging im, int size)
|
|||
memset(histogram, 0, sizeof(histogram));
|
||||
for (yy = y - size; yy <= y + size; yy++) {
|
||||
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++) {
|
||||
if (xx >= 0 && xx < imOut->xsize) {
|
||||
histogram[in[xx]]++;
|
||||
|
@ -65,7 +63,7 @@ ImagingModeFilter(Imaging im, int size)
|
|||
for (i = 1; i < 256; i++) {
|
||||
if (histogram[i] > maxcount) {
|
||||
maxcount = histogram[i];
|
||||
maxpixel = (UINT8) i;
|
||||
maxpixel = (UINT8)i;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,9 +72,7 @@ ImagingModeFilter(Imaging im, int size)
|
|||
} else {
|
||||
out[x] = IMAGING_PIXEL_L(im, x, y);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ImagingCopyPalette(imOut, im);
|
||||
|
|
|
@ -16,18 +16,15 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
Imaging
|
||||
ImagingNegative(Imaging im)
|
||||
{
|
||||
ImagingNegative(Imaging im) {
|
||||
Imaging imOut;
|
||||
int x, y;
|
||||
|
||||
if (!im) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize);
|
||||
|
@ -43,4 +40,3 @@ ImagingNegative(Imaging im)
|
|||
|
||||
return imOut;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,18 +14,15 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
Imaging
|
||||
ImagingOffset(Imaging im, int xoffset, int yoffset)
|
||||
{
|
||||
ImagingOffset(Imaging im, int xoffset, int yoffset) {
|
||||
int x, y;
|
||||
Imaging imOut;
|
||||
|
||||
if (!im) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
imOut = ImagingNewDirty(im->mode, im->xsize, im->ysize);
|
||||
|
@ -48,13 +45,13 @@ ImagingOffset(Imaging im, int xoffset, int yoffset)
|
|||
yoffset += im->ysize;
|
||||
}
|
||||
|
||||
#define OFFSET(image)\
|
||||
for (y = 0; y < im->ysize; y++) {\
|
||||
for (x = 0; x < im->xsize; x++) {\
|
||||
int yi = (y + yoffset) % im->ysize;\
|
||||
int xi = (x + xoffset) % im->xsize;\
|
||||
imOut->image[y][x] = im->image[yi][xi];\
|
||||
}\
|
||||
#define OFFSET(image) \
|
||||
for (y = 0; y < im->ysize; y++) { \
|
||||
for (x = 0; x < im->xsize; x++) { \
|
||||
int yi = (y + yoffset) % im->ysize; \
|
||||
int xi = (x + xoffset) % im->xsize; \
|
||||
imOut->image[y][x] = im->image[yi][xi]; \
|
||||
} \
|
||||
}
|
||||
|
||||
if (im->image8) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* The Python Imaging Library.
|
||||
* $Id$
|
||||
*
|
||||
|
@ -25,7 +25,6 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#define R 0
|
||||
|
@ -41,20 +40,28 @@
|
|||
|
||||
/* byte swapping macros */
|
||||
|
||||
#define C16N\
|
||||
(out[0]=tmp[0], out[1]=tmp[1]);
|
||||
#define C16S\
|
||||
(out[1]=tmp[0], out[0]=tmp[1]);
|
||||
#define C32N\
|
||||
(out[0]=tmp[0], out[1]=tmp[1], out[2]=tmp[2], out[3]=tmp[3]);
|
||||
#define C32S\
|
||||
(out[3]=tmp[0], out[2]=tmp[1], out[1]=tmp[2], out[0]=tmp[3]);
|
||||
#define C64N\
|
||||
(out[0]=tmp[0], out[1]=tmp[1], out[2]=tmp[2], out[3]=tmp[3],\
|
||||
out[4]=tmp[4], out[5]=tmp[5], out[6]=tmp[6], out[7]=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]);
|
||||
#define C16N (out[0] = tmp[0], out[1] = tmp[1]);
|
||||
#define C16S (out[1] = tmp[0], out[0] = tmp[1]);
|
||||
#define C32N (out[0] = tmp[0], out[1] = tmp[1], out[2] = tmp[2], out[3] = tmp[3]);
|
||||
#define C32S (out[3] = tmp[0], out[2] = tmp[1], out[1] = tmp[2], out[0] = tmp[3]);
|
||||
#define C64N \
|
||||
(out[0] = tmp[0], \
|
||||
out[1] = tmp[1], \
|
||||
out[2] = tmp[2], \
|
||||
out[3] = tmp[3], \
|
||||
out[4] = tmp[4], \
|
||||
out[5] = tmp[5], \
|
||||
out[6] = tmp[6], \
|
||||
out[7] = 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
|
||||
#define C16B C16N
|
||||
|
@ -72,13 +79,12 @@
|
|||
#define C64L C64N
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
pack1(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
pack1(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i, m, b;
|
||||
/* bilevel (black is 0) */
|
||||
b = 0; m = 128;
|
||||
b = 0;
|
||||
m = 128;
|
||||
for (i = 0; i < pixels; i++) {
|
||||
if (in[i] != 0) {
|
||||
b |= m;
|
||||
|
@ -86,7 +92,8 @@ pack1(UINT8* out, const UINT8* in, int pixels)
|
|||
m >>= 1;
|
||||
if (m == 0) {
|
||||
*out++ = b;
|
||||
b = 0; m = 128;
|
||||
b = 0;
|
||||
m = 128;
|
||||
}
|
||||
}
|
||||
if (m != 128) {
|
||||
|
@ -95,11 +102,11 @@ pack1(UINT8* out, const UINT8* in, int pixels)
|
|||
}
|
||||
|
||||
static void
|
||||
pack1I(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
pack1I(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i, m, b;
|
||||
/* bilevel (black is 1) */
|
||||
b = 0; m = 128;
|
||||
b = 0;
|
||||
m = 128;
|
||||
for (i = 0; i < pixels; i++) {
|
||||
if (in[i] == 0) {
|
||||
b |= m;
|
||||
|
@ -107,7 +114,8 @@ pack1I(UINT8* out, const UINT8* in, int pixels)
|
|||
m >>= 1;
|
||||
if (m == 0) {
|
||||
*out++ = b;
|
||||
b = 0; m = 128;
|
||||
b = 0;
|
||||
m = 128;
|
||||
}
|
||||
}
|
||||
if (m != 128) {
|
||||
|
@ -116,19 +124,20 @@ pack1I(UINT8* out, const UINT8* in, int pixels)
|
|||
}
|
||||
|
||||
static void
|
||||
pack1R(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
pack1R(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i, m, b;
|
||||
/* bilevel, lsb first (black is 0) */
|
||||
b = 0; m = 1;
|
||||
b = 0;
|
||||
m = 1;
|
||||
for (i = 0; i < pixels; i++) {
|
||||
if (in[i] != 0) {
|
||||
b |= m;
|
||||
}
|
||||
m <<= 1;
|
||||
if (m == 256){
|
||||
if (m == 256) {
|
||||
*out++ = b;
|
||||
b = 0; m = 1;
|
||||
b = 0;
|
||||
m = 1;
|
||||
}
|
||||
}
|
||||
if (m != 1) {
|
||||
|
@ -137,19 +146,20 @@ pack1R(UINT8* out, const UINT8* in, int pixels)
|
|||
}
|
||||
|
||||
static void
|
||||
pack1IR(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
pack1IR(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i, m, b;
|
||||
/* bilevel, lsb first (black is 1) */
|
||||
b = 0; m = 1;
|
||||
b = 0;
|
||||
m = 1;
|
||||
for (i = 0; i < pixels; i++) {
|
||||
if (in[i] == 0) {
|
||||
b |= m;
|
||||
}
|
||||
m <<= 1;
|
||||
if (m == 256){
|
||||
if (m == 256) {
|
||||
*out++ = b;
|
||||
b = 0; m = 1;
|
||||
b = 0;
|
||||
m = 1;
|
||||
}
|
||||
}
|
||||
if (m != 1) {
|
||||
|
@ -158,8 +168,7 @@ pack1IR(UINT8* out, const UINT8* in, int pixels)
|
|||
}
|
||||
|
||||
static void
|
||||
pack1L(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
pack1L(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* bilevel, stored as bytes */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
|
@ -168,12 +177,11 @@ pack1L(UINT8* out, const UINT8* in, int pixels)
|
|||
}
|
||||
|
||||
static void
|
||||
packP4(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
packP4(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
while (pixels >= 2) {
|
||||
*out++ = (in[0] << 4) |
|
||||
(in[1] & 15);
|
||||
in += 2; pixels -= 2;
|
||||
*out++ = (in[0] << 4) | (in[1] & 15);
|
||||
in += 2;
|
||||
pixels -= 2;
|
||||
}
|
||||
|
||||
if (pixels) {
|
||||
|
@ -182,34 +190,27 @@ packP4(UINT8* out, const UINT8* in, int pixels)
|
|||
}
|
||||
|
||||
static void
|
||||
packP2(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
packP2(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
while (pixels >= 4) {
|
||||
*out++ = (in[0] << 6) |
|
||||
((in[1] & 3) << 4) |
|
||||
((in[2] & 3) << 2) |
|
||||
(in[3] & 3);
|
||||
in += 4; pixels -= 4;
|
||||
*out++ = (in[0] << 6) | ((in[1] & 3) << 4) | ((in[2] & 3) << 2) | (in[3] & 3);
|
||||
in += 4;
|
||||
pixels -= 4;
|
||||
}
|
||||
|
||||
switch (pixels) {
|
||||
case 3:
|
||||
out[0] = (in[0] << 6) |
|
||||
((in[1] & 3) << 4) |
|
||||
((in[2] & 3) << 2);
|
||||
break;
|
||||
case 2:
|
||||
out[0] = (in[0] << 6) |
|
||||
((in[1] & 3) << 4);
|
||||
break;
|
||||
case 1:
|
||||
out[0] = (in[0] << 6);
|
||||
case 3:
|
||||
out[0] = (in[0] << 6) | ((in[1] & 3) << 4) | ((in[2] & 3) << 2);
|
||||
break;
|
||||
case 2:
|
||||
out[0] = (in[0] << 6) | ((in[1] & 3) << 4);
|
||||
break;
|
||||
case 1:
|
||||
out[0] = (in[0] << 6);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
packL16(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
packL16(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* L -> L;16, e.g: \xff77 -> \x00\xff\x00\x77 */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
|
@ -220,8 +221,7 @@ packL16(UINT8* out, const UINT8* in, int pixels)
|
|||
}
|
||||
|
||||
static void
|
||||
packL16B(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
packL16B(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* L -> L;16B, e.g: \xff77 -> \xff\x00\x77\x00 */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
|
@ -231,34 +231,31 @@ packL16B(UINT8* out, const UINT8* in, int pixels)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
packLA(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
packLA(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* LA, pixel interleaved */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
out[0] = in[R];
|
||||
out[1] = in[A];
|
||||
out += 2; in += 4;
|
||||
out += 2;
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
packLAL(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
packLAL(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* LA, line interleaved */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
out[i] = in[R];
|
||||
out[i+pixels] = in[A];
|
||||
out[i + pixels] = in[A];
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ImagingPackRGB(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
ImagingPackRGB(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i = 0;
|
||||
/* RGB triplets */
|
||||
#ifdef __sparc
|
||||
|
@ -267,25 +264,25 @@ ImagingPackRGB(UINT8* out, const UINT8* in, int pixels)
|
|||
out[0] = in[R];
|
||||
out[1] = in[G];
|
||||
out[2] = in[B];
|
||||
out += 3; in += 4;
|
||||
out += 3;
|
||||
in += 4;
|
||||
}
|
||||
#else
|
||||
for (; i < pixels-1; i++) {
|
||||
for (; i < pixels - 1; i++) {
|
||||
memcpy(out, in + i * 4, 4);
|
||||
out += 3;
|
||||
}
|
||||
for (; i < pixels; i++) {
|
||||
out[0] = in[i*4+R];
|
||||
out[1] = in[i*4+G];
|
||||
out[2] = in[i*4+B];
|
||||
out[0] = in[i * 4 + R];
|
||||
out[1] = in[i * 4 + G];
|
||||
out[2] = in[i * 4 + B];
|
||||
out += 3;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ImagingPackXRGB(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
ImagingPackXRGB(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* XRGB, triplets with left padding */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
|
@ -293,26 +290,26 @@ ImagingPackXRGB(UINT8* out, const UINT8* in, int pixels)
|
|||
out[1] = in[R];
|
||||
out[2] = in[G];
|
||||
out[3] = in[B];
|
||||
out += 4; in += 4;
|
||||
out += 4;
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ImagingPackBGR(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
ImagingPackBGR(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* RGB, reversed bytes */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
out[0] = in[B];
|
||||
out[1] = in[G];
|
||||
out[2] = in[R];
|
||||
out += 3; in += 4;
|
||||
out += 3;
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ImagingPackBGRX(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
ImagingPackBGRX(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* BGRX, reversed bytes with right padding */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
|
@ -320,13 +317,13 @@ ImagingPackBGRX(UINT8* out, const UINT8* in, int pixels)
|
|||
out[1] = in[G];
|
||||
out[2] = in[R];
|
||||
out[3] = 0;
|
||||
out += 4; in += 4;
|
||||
out += 4;
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ImagingPackXBGR(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
ImagingPackXBGR(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* XBGR, reversed bytes with left padding */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
|
@ -334,13 +331,13 @@ ImagingPackXBGR(UINT8* out, const UINT8* in, int pixels)
|
|||
out[1] = in[B];
|
||||
out[2] = in[G];
|
||||
out[3] = in[R];
|
||||
out += 4; in += 4;
|
||||
out += 4;
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ImagingPackBGRA(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
ImagingPackBGRA(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* BGRX, reversed bytes with right padding */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
|
@ -348,13 +345,13 @@ ImagingPackBGRA(UINT8* out, const UINT8* in, int pixels)
|
|||
out[1] = in[G];
|
||||
out[2] = in[R];
|
||||
out[3] = in[A];
|
||||
out += 4; in += 4;
|
||||
out += 4;
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ImagingPackABGR(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
ImagingPackABGR(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* XBGR, reversed bytes with left padding */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
|
@ -362,13 +359,13 @@ ImagingPackABGR(UINT8* out, const UINT8* in, int pixels)
|
|||
out[1] = in[B];
|
||||
out[2] = in[G];
|
||||
out[3] = in[R];
|
||||
out += 4; in += 4;
|
||||
out += 4;
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ImagingPackBGRa(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
ImagingPackBGRa(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* BGRa, reversed bytes with premultiplied alpha */
|
||||
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[1] = MULDIV255(in[G], alpha, tmp);
|
||||
out[2] = MULDIV255(in[R], alpha, tmp);
|
||||
out += 4; in += 4;
|
||||
out += 4;
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
packRGBL(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
packRGBL(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* RGB, line interleaved */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
out[i] = in[R];
|
||||
out[i+pixels] = in[G];
|
||||
out[i+pixels+pixels] = in[B];
|
||||
out[i + pixels] = in[G];
|
||||
out[i + pixels + pixels] = in[B];
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
packRGBXL(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
packRGBXL(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* RGBX, line interleaved */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
out[i] = in[R];
|
||||
out[i+pixels] = in[G];
|
||||
out[i+pixels+pixels] = in[B];
|
||||
out[i+pixels+pixels+pixels] = in[X];
|
||||
out[i + pixels] = in[G];
|
||||
out[i + pixels + pixels] = in[B];
|
||||
out[i + pixels + pixels + pixels] = in[X];
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
packI16B(UINT8* out, const UINT8* in_, int pixels)
|
||||
{
|
||||
packI16B(UINT8 *out, const UINT8 *in_, int pixels) {
|
||||
int i;
|
||||
UINT16 tmp_;
|
||||
UINT8* tmp = (UINT8*) &tmp_;
|
||||
UINT8 *tmp = (UINT8 *)&tmp_;
|
||||
for (i = 0; i < pixels; i++) {
|
||||
INT32 in;
|
||||
memcpy(&in, in_, sizeof(in));
|
||||
|
@ -425,96 +420,91 @@ packI16B(UINT8* out, const UINT8* in_, int pixels)
|
|||
tmp_ = in;
|
||||
}
|
||||
C16B;
|
||||
out += 2; in_ += sizeof(in);
|
||||
out += 2;
|
||||
in_ += sizeof(in);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
packI16N_I16B(UINT8* out, const UINT8* in, int pixels){
|
||||
packI16N_I16B(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
UINT8* tmp = (UINT8*) in;
|
||||
UINT8 *tmp = (UINT8 *)in;
|
||||
for (i = 0; i < pixels; i++) {
|
||||
C16B;
|
||||
out += 2; tmp += 2;
|
||||
out += 2;
|
||||
tmp += 2;
|
||||
}
|
||||
|
||||
}
|
||||
static void
|
||||
packI16N_I16(UINT8* out, const UINT8* in, int pixels){
|
||||
packI16N_I16(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
UINT8* tmp = (UINT8*) in;
|
||||
UINT8 *tmp = (UINT8 *)in;
|
||||
for (i = 0; i < pixels; i++) {
|
||||
C16L;
|
||||
out += 2; tmp += 2;
|
||||
out += 2;
|
||||
tmp += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
packI32S(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
packI32S(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
UINT8* tmp = (UINT8*) in;
|
||||
UINT8 *tmp = (UINT8 *)in;
|
||||
for (i = 0; i < pixels; i++) {
|
||||
C32L;
|
||||
out += 4; tmp += 4;
|
||||
out += 4;
|
||||
tmp += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ImagingPackLAB(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
ImagingPackLAB(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* LAB triplets */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
out[0] = in[0];
|
||||
out[1] = in[1] ^ 128; /* signed in outside world */
|
||||
out[2] = in[2] ^ 128;
|
||||
out += 3; in += 4;
|
||||
out += 3;
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
copy1(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
copy1(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
/* L, P */
|
||||
memcpy(out, in, pixels);
|
||||
}
|
||||
|
||||
static void
|
||||
copy2(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
copy2(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
/* I;16, etc */
|
||||
memcpy(out, in, pixels*2);
|
||||
memcpy(out, in, pixels * 2);
|
||||
}
|
||||
|
||||
static void
|
||||
copy3(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
copy3(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
/* BGR;24, etc */
|
||||
memcpy(out, in, pixels*3);
|
||||
memcpy(out, in, pixels * 3);
|
||||
}
|
||||
|
||||
static void
|
||||
copy4(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
copy4(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
/* RGBA, CMYK quadruples */
|
||||
memcpy(out, in, 4*pixels);
|
||||
memcpy(out, in, 4 * pixels);
|
||||
}
|
||||
|
||||
static void
|
||||
copy4I(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
copy4I(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
/* RGBA, CMYK quadruples, inverted */
|
||||
int i;
|
||||
for (i = 0; i < pixels*4; i++) {
|
||||
for (i = 0; i < pixels * 4; i++) {
|
||||
out[i] = ~in[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
band0(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
band0(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
for (i = 0; i < pixels; i++, in += 4) {
|
||||
out[i] = in[0];
|
||||
|
@ -522,8 +512,7 @@ band0(UINT8* out, const UINT8* in, int pixels)
|
|||
}
|
||||
|
||||
static void
|
||||
band1(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
band1(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
for (i = 0; i < pixels; i++, in += 4) {
|
||||
out[i] = in[1];
|
||||
|
@ -531,8 +520,7 @@ band1(UINT8* out, const UINT8* in, int pixels)
|
|||
}
|
||||
|
||||
static void
|
||||
band2(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
band2(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
for (i = 0; i < pixels; i++, in += 4) {
|
||||
out[i] = in[2];
|
||||
|
@ -540,8 +528,7 @@ band2(UINT8* out, const UINT8* in, int pixels)
|
|||
}
|
||||
|
||||
static void
|
||||
band3(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
band3(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
for (i = 0; i < pixels; i++, in += 4) {
|
||||
out[i] = in[3];
|
||||
|
@ -549,143 +536,141 @@ band3(UINT8* out, const UINT8* in, int pixels)
|
|||
}
|
||||
|
||||
static struct {
|
||||
const char* mode;
|
||||
const char* rawmode;
|
||||
const char *mode;
|
||||
const char *rawmode;
|
||||
int bits;
|
||||
ImagingShuffler pack;
|
||||
} packers[] = {
|
||||
|
||||
/* bilevel */
|
||||
{"1", "1", 1, pack1},
|
||||
{"1", "1;I", 1, pack1I},
|
||||
{"1", "1;R", 1, pack1R},
|
||||
{"1", "1;IR", 1, pack1IR},
|
||||
{"1", "L", 8, pack1L},
|
||||
{"1", "1", 1, pack1},
|
||||
{"1", "1;I", 1, pack1I},
|
||||
{"1", "1;R", 1, pack1R},
|
||||
{"1", "1;IR", 1, pack1IR},
|
||||
{"1", "L", 8, pack1L},
|
||||
|
||||
/* greyscale */
|
||||
{"L", "L", 8, copy1},
|
||||
{"L", "L;16", 16, packL16},
|
||||
{"L", "L;16B", 16, packL16B},
|
||||
{"L", "L", 8, copy1},
|
||||
{"L", "L;16", 16, packL16},
|
||||
{"L", "L;16B", 16, packL16B},
|
||||
|
||||
/* greyscale w. alpha */
|
||||
{"LA", "LA", 16, packLA},
|
||||
{"LA", "LA;L", 16, packLAL},
|
||||
{"LA", "LA", 16, packLA},
|
||||
{"LA", "LA;L", 16, packLAL},
|
||||
|
||||
/* greyscale w. alpha premultiplied */
|
||||
{"La", "La", 16, packLA},
|
||||
{"La", "La", 16, packLA},
|
||||
|
||||
/* palette */
|
||||
{"P", "P;1", 1, pack1},
|
||||
{"P", "P;2", 2, packP2},
|
||||
{"P", "P;4", 4, packP4},
|
||||
{"P", "P", 8, copy1},
|
||||
{"P", "P;1", 1, pack1},
|
||||
{"P", "P;2", 2, packP2},
|
||||
{"P", "P;4", 4, packP4},
|
||||
{"P", "P", 8, copy1},
|
||||
|
||||
/* palette w. alpha */
|
||||
{"PA", "PA", 16, packLA},
|
||||
{"PA", "PA;L", 16, packLAL},
|
||||
{"PA", "PA", 16, packLA},
|
||||
{"PA", "PA;L", 16, packLAL},
|
||||
|
||||
/* true colour */
|
||||
{"RGB", "RGB", 24, ImagingPackRGB},
|
||||
{"RGB", "RGBX", 32, copy4},
|
||||
{"RGB", "XRGB", 32, ImagingPackXRGB},
|
||||
{"RGB", "BGR", 24, ImagingPackBGR},
|
||||
{"RGB", "BGRX", 32, ImagingPackBGRX},
|
||||
{"RGB", "XBGR", 32, ImagingPackXBGR},
|
||||
{"RGB", "RGB;L", 24, packRGBL},
|
||||
{"RGB", "R", 8, band0},
|
||||
{"RGB", "G", 8, band1},
|
||||
{"RGB", "B", 8, band2},
|
||||
{"RGB", "RGB", 24, ImagingPackRGB},
|
||||
{"RGB", "RGBX", 32, copy4},
|
||||
{"RGB", "XRGB", 32, ImagingPackXRGB},
|
||||
{"RGB", "BGR", 24, ImagingPackBGR},
|
||||
{"RGB", "BGRX", 32, ImagingPackBGRX},
|
||||
{"RGB", "XBGR", 32, ImagingPackXBGR},
|
||||
{"RGB", "RGB;L", 24, packRGBL},
|
||||
{"RGB", "R", 8, band0},
|
||||
{"RGB", "G", 8, band1},
|
||||
{"RGB", "B", 8, band2},
|
||||
|
||||
/* true colour w. alpha */
|
||||
{"RGBA", "RGBA", 32, copy4},
|
||||
{"RGBA", "RGBA;L", 32, packRGBXL},
|
||||
{"RGBA", "RGB", 24, ImagingPackRGB},
|
||||
{"RGBA", "BGR", 24, ImagingPackBGR},
|
||||
{"RGBA", "BGRA", 32, ImagingPackBGRA},
|
||||
{"RGBA", "ABGR", 32, ImagingPackABGR},
|
||||
{"RGBA", "BGRa", 32, ImagingPackBGRa},
|
||||
{"RGBA", "R", 8, band0},
|
||||
{"RGBA", "G", 8, band1},
|
||||
{"RGBA", "B", 8, band2},
|
||||
{"RGBA", "A", 8, band3},
|
||||
{"RGBA", "RGBA", 32, copy4},
|
||||
{"RGBA", "RGBA;L", 32, packRGBXL},
|
||||
{"RGBA", "RGB", 24, ImagingPackRGB},
|
||||
{"RGBA", "BGR", 24, ImagingPackBGR},
|
||||
{"RGBA", "BGRA", 32, ImagingPackBGRA},
|
||||
{"RGBA", "ABGR", 32, ImagingPackABGR},
|
||||
{"RGBA", "BGRa", 32, ImagingPackBGRa},
|
||||
{"RGBA", "R", 8, band0},
|
||||
{"RGBA", "G", 8, band1},
|
||||
{"RGBA", "B", 8, band2},
|
||||
{"RGBA", "A", 8, band3},
|
||||
|
||||
/* true colour w. alpha premultiplied */
|
||||
{"RGBa", "RGBa", 32, copy4},
|
||||
{"RGBa", "BGRa", 32, ImagingPackBGRA},
|
||||
{"RGBa", "aBGR", 32, ImagingPackABGR},
|
||||
{"RGBa", "RGBa", 32, copy4},
|
||||
{"RGBa", "BGRa", 32, ImagingPackBGRA},
|
||||
{"RGBa", "aBGR", 32, ImagingPackABGR},
|
||||
|
||||
/* true colour w. padding */
|
||||
{"RGBX", "RGBX", 32, copy4},
|
||||
{"RGBX", "RGBX;L", 32, packRGBXL},
|
||||
{"RGBX", "RGB", 24, ImagingPackRGB},
|
||||
{"RGBX", "BGR", 24, ImagingPackBGR},
|
||||
{"RGBX", "BGRX", 32, ImagingPackBGRX},
|
||||
{"RGBX", "XBGR", 32, ImagingPackXBGR},
|
||||
{"RGBX", "R", 8, band0},
|
||||
{"RGBX", "G", 8, band1},
|
||||
{"RGBX", "B", 8, band2},
|
||||
{"RGBX", "X", 8, band3},
|
||||
{"RGBX", "RGBX", 32, copy4},
|
||||
{"RGBX", "RGBX;L", 32, packRGBXL},
|
||||
{"RGBX", "RGB", 24, ImagingPackRGB},
|
||||
{"RGBX", "BGR", 24, ImagingPackBGR},
|
||||
{"RGBX", "BGRX", 32, ImagingPackBGRX},
|
||||
{"RGBX", "XBGR", 32, ImagingPackXBGR},
|
||||
{"RGBX", "R", 8, band0},
|
||||
{"RGBX", "G", 8, band1},
|
||||
{"RGBX", "B", 8, band2},
|
||||
{"RGBX", "X", 8, band3},
|
||||
|
||||
/* colour separation */
|
||||
{"CMYK", "CMYK", 32, copy4},
|
||||
{"CMYK", "CMYK;I", 32, copy4I},
|
||||
{"CMYK", "CMYK;L", 32, packRGBXL},
|
||||
{"CMYK", "C", 8, band0},
|
||||
{"CMYK", "M", 8, band1},
|
||||
{"CMYK", "Y", 8, band2},
|
||||
{"CMYK", "K", 8, band3},
|
||||
{"CMYK", "CMYK", 32, copy4},
|
||||
{"CMYK", "CMYK;I", 32, copy4I},
|
||||
{"CMYK", "CMYK;L", 32, packRGBXL},
|
||||
{"CMYK", "C", 8, band0},
|
||||
{"CMYK", "M", 8, band1},
|
||||
{"CMYK", "Y", 8, band2},
|
||||
{"CMYK", "K", 8, band3},
|
||||
|
||||
/* video (YCbCr) */
|
||||
{"YCbCr", "YCbCr", 24, ImagingPackRGB},
|
||||
{"YCbCr", "YCbCr;L", 24, packRGBL},
|
||||
{"YCbCr", "YCbCrX", 32, copy4},
|
||||
{"YCbCr", "YCbCrK", 32, copy4},
|
||||
{"YCbCr", "Y", 8, band0},
|
||||
{"YCbCr", "Cb", 8, band1},
|
||||
{"YCbCr", "Cr", 8, band2},
|
||||
{"YCbCr", "YCbCr", 24, ImagingPackRGB},
|
||||
{"YCbCr", "YCbCr;L", 24, packRGBL},
|
||||
{"YCbCr", "YCbCrX", 32, copy4},
|
||||
{"YCbCr", "YCbCrK", 32, copy4},
|
||||
{"YCbCr", "Y", 8, band0},
|
||||
{"YCbCr", "Cb", 8, band1},
|
||||
{"YCbCr", "Cr", 8, band2},
|
||||
|
||||
/* LAB Color */
|
||||
{"LAB", "LAB", 24, ImagingPackLAB},
|
||||
{"LAB", "L", 8, band0},
|
||||
{"LAB", "A", 8, band1},
|
||||
{"LAB", "B", 8, band2},
|
||||
{"LAB", "LAB", 24, ImagingPackLAB},
|
||||
{"LAB", "L", 8, band0},
|
||||
{"LAB", "A", 8, band1},
|
||||
{"LAB", "B", 8, band2},
|
||||
|
||||
/* HSV */
|
||||
{"HSV", "HSV", 24, ImagingPackRGB},
|
||||
{"HSV", "H", 8, band0},
|
||||
{"HSV", "S", 8, band1},
|
||||
{"HSV", "V", 8, band2},
|
||||
{"HSV", "HSV", 24, ImagingPackRGB},
|
||||
{"HSV", "H", 8, band0},
|
||||
{"HSV", "S", 8, band1},
|
||||
{"HSV", "V", 8, band2},
|
||||
|
||||
/* integer */
|
||||
{"I", "I", 32, copy4},
|
||||
{"I", "I;16B", 16, packI16B},
|
||||
{"I", "I;32S", 32, packI32S},
|
||||
{"I", "I;32NS", 32, copy4},
|
||||
{"I", "I", 32, copy4},
|
||||
{"I", "I;16B", 16, packI16B},
|
||||
{"I", "I;32S", 32, packI32S},
|
||||
{"I", "I;32NS", 32, copy4},
|
||||
|
||||
/* floating point */
|
||||
{"F", "F", 32, copy4},
|
||||
{"F", "F;32F", 32, packI32S},
|
||||
{"F", "F;32NF", 32, copy4},
|
||||
{"F", "F", 32, copy4},
|
||||
{"F", "F;32F", 32, packI32S},
|
||||
{"F", "F;32NF", 32, copy4},
|
||||
|
||||
/* storage modes */
|
||||
{"I;16", "I;16", 16, copy2},
|
||||
{"I;16", "I;16B", 16, packI16N_I16B},
|
||||
{"I;16B", "I;16B", 16, copy2},
|
||||
{"I;16L", "I;16L", 16, copy2},
|
||||
{"I;16", "I;16N", 16, packI16N_I16}, // LibTiff native->image endian.
|
||||
{"I;16L", "I;16N", 16, packI16N_I16},
|
||||
{"I;16B", "I;16N", 16, packI16N_I16B},
|
||||
{"BGR;15", "BGR;15", 16, copy2},
|
||||
{"BGR;16", "BGR;16", 16, copy2},
|
||||
{"BGR;24", "BGR;24", 24, copy3},
|
||||
{"I;16", "I;16", 16, copy2},
|
||||
{"I;16", "I;16B", 16, packI16N_I16B},
|
||||
{"I;16B", "I;16B", 16, copy2},
|
||||
{"I;16L", "I;16L", 16, copy2},
|
||||
{"I;16", "I;16N", 16, packI16N_I16}, // LibTiff native->image endian.
|
||||
{"I;16L", "I;16N", 16, packI16N_I16},
|
||||
{"I;16B", "I;16N", 16, packI16N_I16B},
|
||||
{"BGR;15", "BGR;15", 16, copy2},
|
||||
{"BGR;16", "BGR;16", 16, copy2},
|
||||
{"BGR;24", "BGR;24", 24, copy3},
|
||||
|
||||
{NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
||||
ImagingShuffler
|
||||
ImagingFindPacker(const char* mode, const char* rawmode, int* bits_out)
|
||||
{
|
||||
ImagingFindPacker(const char *mode, const char *rawmode, int *bits_out) {
|
||||
int i;
|
||||
|
||||
/* find a suitable pixel packer */
|
||||
|
|
|
@ -13,30 +13,27 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
int
|
||||
ImagingPackbitsDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buf, Py_ssize_t bytes)
|
||||
{
|
||||
ImagingPackbitsDecode(
|
||||
Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
|
||||
UINT8 n;
|
||||
UINT8* ptr;
|
||||
UINT8 *ptr;
|
||||
int i;
|
||||
|
||||
ptr = buf;
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (bytes < 1) {
|
||||
return ptr - buf;
|
||||
}
|
||||
|
||||
if (ptr[0] & 0x80) {
|
||||
|
||||
if (ptr[0] == 0x80) {
|
||||
/* Nop */
|
||||
ptr++; bytes--;
|
||||
ptr++;
|
||||
bytes--;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -53,12 +50,12 @@ ImagingPackbitsDecode(Imaging im, ImagingCodecState state,
|
|||
state->buffer[state->x++] = ptr[1];
|
||||
}
|
||||
|
||||
ptr += 2; bytes -= 2;
|
||||
ptr += 2;
|
||||
bytes -= 2;
|
||||
|
||||
} else {
|
||||
|
||||
/* Literal */
|
||||
n = ptr[0]+2;
|
||||
n = ptr[0] + 2;
|
||||
|
||||
if (bytes < n) {
|
||||
return ptr - buf;
|
||||
|
@ -72,16 +69,17 @@ ImagingPackbitsDecode(Imaging im, ImagingCodecState state,
|
|||
state->buffer[state->x++] = ptr[i];
|
||||
}
|
||||
|
||||
ptr += n; bytes -= n;
|
||||
|
||||
ptr += n;
|
||||
bytes -= n;
|
||||
}
|
||||
|
||||
if (state->x >= state->bytes) {
|
||||
|
||||
/* Got a full line, unpack it */
|
||||
state->shuffle((UINT8*) im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize, state->buffer,
|
||||
state->xsize);
|
||||
state->shuffle(
|
||||
(UINT8 *)im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize,
|
||||
state->buffer,
|
||||
state->xsize);
|
||||
|
||||
state->x = 0;
|
||||
|
||||
|
@ -90,6 +88,5 @@ ImagingPackbitsDecode(Imaging im, ImagingCodecState state,
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,46 +16,41 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
ImagingPalette
|
||||
ImagingPaletteNew(const char* mode)
|
||||
{
|
||||
ImagingPaletteNew(const char *mode) {
|
||||
/* Create a palette object */
|
||||
|
||||
int i;
|
||||
ImagingPalette palette;
|
||||
|
||||
if (strcmp(mode, "RGB") && strcmp(mode, "RGBA")) {
|
||||
return (ImagingPalette) ImagingError_ModeError();
|
||||
return (ImagingPalette)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
palette = calloc(1, sizeof(struct ImagingPaletteInstance));
|
||||
if (!palette) {
|
||||
return (ImagingPalette) ImagingError_MemoryError();
|
||||
return (ImagingPalette)ImagingError_MemoryError();
|
||||
}
|
||||
|
||||
strncpy(palette->mode, mode, IMAGING_MODE_LENGTH-1);
|
||||
palette->mode[IMAGING_MODE_LENGTH-1] = 0;
|
||||
strncpy(palette->mode, mode, IMAGING_MODE_LENGTH - 1);
|
||||
palette->mode[IMAGING_MODE_LENGTH - 1] = 0;
|
||||
|
||||
/* Initialize to ramp */
|
||||
for (i = 0; i < 256; i++) {
|
||||
palette->palette[i*4+0] =
|
||||
palette->palette[i*4+1] =
|
||||
palette->palette[i*4+2] = (UINT8) i;
|
||||
palette->palette[i*4+3] = 255; /* opaque */
|
||||
palette->palette[i * 4 + 0] = palette->palette[i * 4 + 1] =
|
||||
palette->palette[i * 4 + 2] = (UINT8)i;
|
||||
palette->palette[i * 4 + 3] = 255; /* opaque */
|
||||
}
|
||||
|
||||
return palette;
|
||||
}
|
||||
|
||||
ImagingPalette
|
||||
ImagingPaletteNewBrowser(void)
|
||||
{
|
||||
ImagingPaletteNewBrowser(void) {
|
||||
/* Create a standard "browser" palette object */
|
||||
|
||||
int i, r, g, b;
|
||||
|
@ -70,9 +65,8 @@ ImagingPaletteNewBrowser(void)
|
|||
/* FIXME: Add 10-level windows palette here? */
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
palette->palette[i*4+0] =
|
||||
palette->palette[i*4+1] =
|
||||
palette->palette[i*4+2] = 0;
|
||||
palette->palette[i * 4 + 0] = palette->palette[i * 4 + 1] =
|
||||
palette->palette[i * 4 + 2] = 0;
|
||||
}
|
||||
|
||||
/* Simple 6x6x6 colour cube */
|
||||
|
@ -80,9 +74,9 @@ ImagingPaletteNewBrowser(void)
|
|||
for (b = 0; b < 256; b += 51) {
|
||||
for (g = 0; g < 256; g += 51) {
|
||||
for (r = 0; r < 256; r += 51) {
|
||||
palette->palette[i*4+0] = r;
|
||||
palette->palette[i*4+1] = g;
|
||||
palette->palette[i*4+2] = b;
|
||||
palette->palette[i * 4 + 0] = r;
|
||||
palette->palette[i * 4 + 1] = g;
|
||||
palette->palette[i * 4 + 2] = b;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -92,17 +86,15 @@ ImagingPaletteNewBrowser(void)
|
|||
/* FIXME: add 30-level greyscale wedge here? */
|
||||
|
||||
for (; i < 256; i++) {
|
||||
palette->palette[i*4+0] =
|
||||
palette->palette[i*4+1] =
|
||||
palette->palette[i*4+2] = 0;
|
||||
palette->palette[i * 4 + 0] = palette->palette[i * 4 + 1] =
|
||||
palette->palette[i * 4 + 2] = 0;
|
||||
}
|
||||
|
||||
return palette;
|
||||
}
|
||||
|
||||
ImagingPalette
|
||||
ImagingPaletteDuplicate(ImagingPalette palette)
|
||||
{
|
||||
ImagingPaletteDuplicate(ImagingPalette palette) {
|
||||
/* Duplicate palette descriptor */
|
||||
|
||||
ImagingPalette new_palette;
|
||||
|
@ -113,7 +105,7 @@ ImagingPaletteDuplicate(ImagingPalette palette)
|
|||
/* malloc check ok, small constant allocation */
|
||||
new_palette = malloc(sizeof(struct ImagingPaletteInstance));
|
||||
if (!new_palette) {
|
||||
return (ImagingPalette) ImagingError_MemoryError();
|
||||
return (ImagingPalette)ImagingError_MemoryError();
|
||||
}
|
||||
|
||||
memcpy(new_palette, palette, sizeof(struct ImagingPaletteInstance));
|
||||
|
@ -125,8 +117,7 @@ ImagingPaletteDuplicate(ImagingPalette palette)
|
|||
}
|
||||
|
||||
void
|
||||
ImagingPaletteDelete(ImagingPalette palette)
|
||||
{
|
||||
ImagingPaletteDelete(ImagingPalette palette) {
|
||||
/* Destroy palette object */
|
||||
|
||||
if (palette) {
|
||||
|
@ -137,7 +128,6 @@ ImagingPaletteDelete(ImagingPalette palette)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Colour mapping */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -155,27 +145,26 @@ ImagingPaletteDelete(ImagingPalette palette)
|
|||
#define DIST(a, b, s) (a - b) * (a - b) * s
|
||||
|
||||
/* Colour weights (no scaling, for now) */
|
||||
#define RSCALE 1
|
||||
#define GSCALE 1
|
||||
#define BSCALE 1
|
||||
#define RSCALE 1
|
||||
#define GSCALE 1
|
||||
#define BSCALE 1
|
||||
|
||||
/* Calculated scaled distances */
|
||||
#define RDIST(a, b) DIST(a, b, RSCALE*RSCALE)
|
||||
#define GDIST(a, b) DIST(a, b, GSCALE*GSCALE)
|
||||
#define BDIST(a, b) DIST(a, b, BSCALE*BSCALE)
|
||||
#define RDIST(a, b) DIST(a, b, RSCALE *RSCALE)
|
||||
#define GDIST(a, b) DIST(a, b, GSCALE *GSCALE)
|
||||
#define BDIST(a, b) DIST(a, b, BSCALE *BSCALE)
|
||||
|
||||
/* Incremental steps */
|
||||
#define RSTEP (4 * RSCALE)
|
||||
#define GSTEP (4 * GSCALE)
|
||||
#define BSTEP (4 * BSCALE)
|
||||
#define RSTEP (4 * RSCALE)
|
||||
#define GSTEP (4 * GSCALE)
|
||||
#define BSTEP (4 * BSCALE)
|
||||
|
||||
#define BOX 8
|
||||
#define BOX 8
|
||||
|
||||
#define BOXVOLUME BOX*BOX*BOX
|
||||
#define BOXVOLUME BOX *BOX *BOX
|
||||
|
||||
void
|
||||
ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
|
||||
{
|
||||
ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b) {
|
||||
int i, j;
|
||||
unsigned int dmin[256], dmax;
|
||||
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
|
||||
covers eight cache slots (32 colour values, that is). */
|
||||
|
||||
r0 = r & 0xe0; r1 = r0 + 0x1f; rc = (r0 + r1) / 2;
|
||||
g0 = g & 0xe0; g1 = g0 + 0x1f; gc = (g0 + g1) / 2;
|
||||
b0 = b & 0xe0; b1 = b0 + 0x1f; bc = (b0 + b1) / 2;
|
||||
r0 = r & 0xe0;
|
||||
r1 = r0 + 0x1f;
|
||||
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) */
|
||||
|
||||
/* For each palette entry, calculate the min and max distances to
|
||||
* 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++) {
|
||||
|
||||
int r, g, b;
|
||||
unsigned int tmin, tmax;
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
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;
|
||||
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) {
|
||||
dmax = tmax; /* keep the smallest max distance only */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
||||
for (i = 0; i < BOXVOLUME; i++) {
|
||||
d[i] = (unsigned int) ~0;
|
||||
d[i] = (unsigned int)~0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
|
||||
if (dmin[i] <= dmax) {
|
||||
|
||||
int rd, gd, bd;
|
||||
int ri, gi, bi;
|
||||
int rx, gx, bx;
|
||||
|
||||
ri = (r0 - palette->palette[i*4+0]) * RSCALE;
|
||||
gi = (g0 - palette->palette[i*4+1]) * GSCALE;
|
||||
bi = (b0 - palette->palette[i*4+2]) * BSCALE;
|
||||
ri = (r0 - palette->palette[i * 4 + 0]) * RSCALE;
|
||||
gi = (g0 - palette->palette[i * 4 + 1]) * GSCALE;
|
||||
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;
|
||||
gi = gi * (2 * GSTEP) + GSTEP * GSTEP;
|
||||
|
@ -253,13 +244,15 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
|
|||
|
||||
rx = ri;
|
||||
for (r = j = 0; r < BOX; r++) {
|
||||
gd = rd; gx = gi;
|
||||
gd = rd;
|
||||
gx = gi;
|
||||
for (g = 0; g < BOX; g++) {
|
||||
bd = gd; bx = bi;
|
||||
bd = gd;
|
||||
bx = bi;
|
||||
for (b = 0; b < BOX; b++) {
|
||||
if ((unsigned int) bd < d[j]) {
|
||||
if ((unsigned int)bd < d[j]) {
|
||||
d[j] = bd;
|
||||
c[j] = (UINT8) i;
|
||||
c[j] = (UINT8)i;
|
||||
}
|
||||
bd += bx;
|
||||
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. */
|
||||
|
||||
j = 0;
|
||||
for (r = r0; r < r1; r+=4) {
|
||||
for (g = g0; g < g1; g+=4) {
|
||||
for (b = b0; b < b1; b+=4) {
|
||||
for (r = r0; r < r1; r += 4) {
|
||||
for (g = g0; g < g1; g += 4) {
|
||||
for (b = b0; b < b1; b += 4) {
|
||||
ImagingPaletteCache(palette, r, g, b) = c[j++];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ImagingPaletteCachePrepare(ImagingPalette palette)
|
||||
{
|
||||
ImagingPaletteCachePrepare(ImagingPalette palette) {
|
||||
/* Add a colour cache to a palette */
|
||||
|
||||
int i;
|
||||
int entries = 64*64*64;
|
||||
int entries = 64 * 64 * 64;
|
||||
|
||||
if (palette->cache == NULL) {
|
||||
|
||||
/* The cache is 512k. It might be a good idea to break it
|
||||
up into a pointer array (e.g. an 8-bit image?) */
|
||||
|
||||
/* malloc check ok, small constant allocation */
|
||||
palette->cache = (INT16*) malloc(entries * sizeof(INT16));
|
||||
palette->cache = (INT16 *)malloc(entries * sizeof(INT16));
|
||||
if (!palette->cache) {
|
||||
(void) ImagingError_MemoryError();
|
||||
(void)ImagingError_MemoryError();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -314,16 +304,13 @@ ImagingPaletteCachePrepare(ImagingPalette palette)
|
|||
for (i = 0; i < entries; i++) {
|
||||
palette->cache[i] = 0x100;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ImagingPaletteCacheDelete(ImagingPalette palette)
|
||||
{
|
||||
ImagingPaletteCacheDelete(ImagingPalette palette) {
|
||||
/* Release the colour cache, if any */
|
||||
|
||||
if (palette && palette->cache) {
|
||||
|
|
|
@ -23,11 +23,17 @@
|
|||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
static inline void
|
||||
paste(Imaging imOut, Imaging imIn, int dx, int dy, int sx, int sy,
|
||||
int xsize, int ysize, int pixelsize)
|
||||
{
|
||||
paste(
|
||||
Imaging imOut,
|
||||
Imaging imIn,
|
||||
int dx,
|
||||
int dy,
|
||||
int sx,
|
||||
int sy,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int pixelsize) {
|
||||
/* paste opaque region */
|
||||
|
||||
int y;
|
||||
|
@ -38,25 +44,31 @@ paste(Imaging imOut, Imaging imIn, int dx, int dy, int sx, int sy,
|
|||
xsize *= pixelsize;
|
||||
|
||||
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
|
||||
paste_mask_1(Imaging imOut, Imaging imIn, Imaging imMask,
|
||||
int dx, int dy, int sx, int sy,
|
||||
int xsize, int ysize, int pixelsize)
|
||||
{
|
||||
paste_mask_1(
|
||||
Imaging imOut,
|
||||
Imaging imIn,
|
||||
Imaging imMask,
|
||||
int dx,
|
||||
int dy,
|
||||
int sx,
|
||||
int sy,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int pixelsize) {
|
||||
/* paste with mode "1" mask */
|
||||
|
||||
int x, y;
|
||||
|
||||
if (imOut->image8) {
|
||||
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8* out = imOut->image8[y+dy]+dx;
|
||||
UINT8* in = imIn->image8[y+sy]+sx;
|
||||
UINT8* mask = imMask->image8[y+sy]+sx;
|
||||
UINT8 *out = imOut->image8[y + dy] + dx;
|
||||
UINT8 *in = imIn->image8[y + sy] + sx;
|
||||
UINT8 *mask = imMask->image8[y + sy] + sx;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
if (*mask++) {
|
||||
*out = *in;
|
||||
|
@ -66,11 +78,10 @@ paste_mask_1(Imaging imOut, Imaging imIn, Imaging imMask,
|
|||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (y = 0; y < ysize; y++) {
|
||||
INT32* out = imOut->image32[y+dy]+dx;
|
||||
INT32* in = imIn->image32[y+sy]+sx;
|
||||
UINT8* mask = imMask->image8[y+sy]+sx;
|
||||
INT32 *out = imOut->image32[y + dy] + dx;
|
||||
INT32 *in = imIn->image32[y + sy] + sx;
|
||||
UINT8 *mask = imMask->image8[y + sy] + sx;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
if (*mask++) {
|
||||
*out = *in;
|
||||
|
@ -82,21 +93,27 @@ paste_mask_1(Imaging imOut, Imaging imIn, Imaging imMask,
|
|||
}
|
||||
|
||||
static inline void
|
||||
paste_mask_L(Imaging imOut, Imaging imIn, Imaging imMask,
|
||||
int dx, int dy, int sx, int sy,
|
||||
int xsize, int ysize, int pixelsize)
|
||||
{
|
||||
paste_mask_L(
|
||||
Imaging imOut,
|
||||
Imaging imIn,
|
||||
Imaging imMask,
|
||||
int dx,
|
||||
int dy,
|
||||
int sx,
|
||||
int sy,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int pixelsize) {
|
||||
/* paste with mode "L" matte */
|
||||
|
||||
int x, y;
|
||||
unsigned int tmp1;
|
||||
|
||||
if (imOut->image8) {
|
||||
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8* out = imOut->image8[y+dy]+dx;
|
||||
UINT8* in = imIn->image8[y+sy]+sx;
|
||||
UINT8* mask = imMask->image8[y+sy]+sx;
|
||||
UINT8 *out = imOut->image8[y + dy] + dx;
|
||||
UINT8 *in = imIn->image8[y + sy] + sx;
|
||||
UINT8 *mask = imMask->image8[y + sy] + sx;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
*out = BLEND(*mask, *out, *in, tmp1);
|
||||
out++, in++, mask++;
|
||||
|
@ -104,39 +121,46 @@ paste_mask_L(Imaging imOut, Imaging imIn, Imaging imMask,
|
|||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8* out = (UINT8*) (imOut->image32[y + dy] + dx);
|
||||
UINT8* in = (UINT8*) (imIn->image32[y + sy] + sx);
|
||||
UINT8* mask = (UINT8*) (imMask->image8[y+sy] + sx);
|
||||
UINT8 *out = (UINT8 *)(imOut->image32[y + dy] + dx);
|
||||
UINT8 *in = (UINT8 *)(imIn->image32[y + sy] + sx);
|
||||
UINT8 *mask = (UINT8 *)(imMask->image8[y + sy] + sx);
|
||||
for (x = 0; x < xsize; x++) {
|
||||
UINT8 a = mask[0];
|
||||
out[0] = BLEND(a, out[0], in[0], tmp1);
|
||||
out[1] = BLEND(a, out[1], in[1], tmp1);
|
||||
out[2] = BLEND(a, out[2], in[2], tmp1);
|
||||
out[3] = BLEND(a, out[3], in[3], tmp1);
|
||||
out += 4; in += 4; mask ++;
|
||||
out += 4;
|
||||
in += 4;
|
||||
mask++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
paste_mask_RGBA(Imaging imOut, Imaging imIn, Imaging imMask,
|
||||
int dx, int dy, int sx, int sy,
|
||||
int xsize, int ysize, int pixelsize)
|
||||
{
|
||||
paste_mask_RGBA(
|
||||
Imaging imOut,
|
||||
Imaging imIn,
|
||||
Imaging imMask,
|
||||
int dx,
|
||||
int dy,
|
||||
int sx,
|
||||
int sy,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int pixelsize) {
|
||||
/* paste with mode "RGBA" matte */
|
||||
|
||||
int x, y;
|
||||
unsigned int tmp1;
|
||||
|
||||
if (imOut->image8) {
|
||||
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8* out = imOut->image8[y+dy]+dx;
|
||||
UINT8* in = imIn->image8[y+sy]+sx;
|
||||
UINT8* mask = (UINT8*) imMask->image[y+sy]+sx*4+3;
|
||||
UINT8 *out = imOut->image8[y + dy] + dx;
|
||||
UINT8 *in = imIn->image8[y + sy] + sx;
|
||||
UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx * 4 + 3;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
*out = BLEND(*mask, *out, *in, tmp1);
|
||||
out++, in++, mask += 4;
|
||||
|
@ -144,40 +168,46 @@ paste_mask_RGBA(Imaging imOut, Imaging imIn, Imaging imMask,
|
|||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8* out = (UINT8*) (imOut->image32[y + dy] + dx);
|
||||
UINT8* in = (UINT8*) (imIn->image32[y + sy] + sx);
|
||||
UINT8* mask = (UINT8*) (imMask->image32[y+sy] + sx);
|
||||
UINT8 *out = (UINT8 *)(imOut->image32[y + dy] + dx);
|
||||
UINT8 *in = (UINT8 *)(imIn->image32[y + sy] + sx);
|
||||
UINT8 *mask = (UINT8 *)(imMask->image32[y + sy] + sx);
|
||||
for (x = 0; x < xsize; x++) {
|
||||
UINT8 a = mask[3];
|
||||
out[0] = BLEND(a, out[0], in[0], tmp1);
|
||||
out[1] = BLEND(a, out[1], in[1], tmp1);
|
||||
out[2] = BLEND(a, out[2], in[2], 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
|
||||
paste_mask_RGBa(Imaging imOut, Imaging imIn, Imaging imMask,
|
||||
int dx, int dy, int sx, int sy,
|
||||
int xsize, int ysize, int pixelsize)
|
||||
{
|
||||
paste_mask_RGBa(
|
||||
Imaging imOut,
|
||||
Imaging imIn,
|
||||
Imaging imMask,
|
||||
int dx,
|
||||
int dy,
|
||||
int sx,
|
||||
int sy,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int pixelsize) {
|
||||
/* paste with mode "RGBa" matte */
|
||||
|
||||
int x, y;
|
||||
unsigned int tmp1;
|
||||
|
||||
if (imOut->image8) {
|
||||
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8* out = imOut->image8[y+dy]+dx;
|
||||
UINT8* in = imIn->image8[y+sy]+sx;
|
||||
UINT8* mask = (UINT8*) imMask->image[y+sy]+sx*4+3;
|
||||
UINT8 *out = imOut->image8[y + dy] + dx;
|
||||
UINT8 *in = imIn->image8[y + sy] + sx;
|
||||
UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx * 4 + 3;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
*out = PREBLEND(*mask, *out, *in, tmp1);
|
||||
out++, in++, mask += 4;
|
||||
|
@ -185,34 +215,34 @@ paste_mask_RGBa(Imaging imOut, Imaging imIn, Imaging imMask,
|
|||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8* out = (UINT8*) (imOut->image32[y + dy] + dx);
|
||||
UINT8* in = (UINT8*) (imIn->image32[y + sy] + sx);
|
||||
UINT8* mask = (UINT8*) (imMask->image32[y+sy] + sx);
|
||||
UINT8 *out = (UINT8 *)(imOut->image32[y + dy] + dx);
|
||||
UINT8 *in = (UINT8 *)(imIn->image32[y + sy] + sx);
|
||||
UINT8 *mask = (UINT8 *)(imMask->image32[y + sy] + sx);
|
||||
for (x = 0; x < xsize; x++) {
|
||||
UINT8 a = mask[3];
|
||||
out[0] = PREBLEND(a, out[0], in[0], tmp1);
|
||||
out[1] = PREBLEND(a, out[1], in[1], tmp1);
|
||||
out[2] = PREBLEND(a, out[2], in[2], tmp1);
|
||||
out[3] = PREBLEND(a, out[3], in[3], tmp1);
|
||||
out += 4; in += 4; mask += 4;
|
||||
out += 4;
|
||||
in += 4;
|
||||
mask += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ImagingPaste(Imaging imOut, Imaging imIn, Imaging imMask,
|
||||
int dx0, int dy0, int dx1, int dy1)
|
||||
{
|
||||
ImagingPaste(
|
||||
Imaging imOut, Imaging imIn, Imaging imMask, int dx0, int dy0, int dx1, int dy1) {
|
||||
int xsize, ysize;
|
||||
int pixelsize;
|
||||
int sx0, sy0;
|
||||
ImagingSectionCookie cookie;
|
||||
|
||||
if (!imOut || !imIn) {
|
||||
(void) ImagingError_ModeError();
|
||||
(void)ImagingError_ModeError();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -221,14 +251,13 @@ ImagingPaste(Imaging imOut, Imaging imIn, Imaging imMask,
|
|||
xsize = dx1 - dx0;
|
||||
ysize = dy1 - dy0;
|
||||
|
||||
if (xsize != imIn->xsize || ysize != imIn->ysize ||
|
||||
pixelsize != imIn->pixelsize) {
|
||||
(void) ImagingError_Mismatch();
|
||||
if (xsize != imIn->xsize || ysize != imIn->ysize || pixelsize != imIn->pixelsize) {
|
||||
(void)ImagingError_Mismatch();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (imMask && (xsize != imMask->xsize || ysize != imMask->ysize)) {
|
||||
(void) ImagingError_Mismatch();
|
||||
(void)ImagingError_Mismatch();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -258,30 +287,28 @@ ImagingPaste(Imaging imOut, Imaging imIn, Imaging imMask,
|
|||
|
||||
} else if (strcmp(imMask->mode, "1") == 0) {
|
||||
ImagingSectionEnter(&cookie);
|
||||
paste_mask_1(imOut, imIn, imMask, dx0, dy0, sx0, sy0,
|
||||
xsize, ysize, pixelsize);
|
||||
paste_mask_1(imOut, imIn, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
|
||||
ImagingSectionLeave(&cookie);
|
||||
|
||||
} else if (strcmp(imMask->mode, "L") == 0) {
|
||||
ImagingSectionEnter(&cookie);
|
||||
paste_mask_L(imOut, imIn, imMask, dx0, dy0, sx0, sy0,
|
||||
xsize, ysize, pixelsize);
|
||||
paste_mask_L(imOut, imIn, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
|
||||
ImagingSectionLeave(&cookie);
|
||||
|
||||
} else if (strcmp(imMask->mode, "RGBA") == 0) {
|
||||
ImagingSectionEnter(&cookie);
|
||||
paste_mask_RGBA(imOut, imIn, imMask, dx0, dy0, sx0, sy0,
|
||||
xsize, ysize, pixelsize);
|
||||
paste_mask_RGBA(
|
||||
imOut, imIn, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
|
||||
ImagingSectionLeave(&cookie);
|
||||
|
||||
} else if (strcmp(imMask->mode, "RGBa") == 0) {
|
||||
ImagingSectionEnter(&cookie);
|
||||
paste_mask_RGBa(imOut, imIn, imMask, dx0, dy0, sx0, sy0,
|
||||
xsize, ysize, pixelsize);
|
||||
paste_mask_RGBa(
|
||||
imOut, imIn, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
|
||||
ImagingSectionLeave(&cookie);
|
||||
|
||||
} else {
|
||||
(void) ImagingError_ValueError("bad transparency mask");
|
||||
(void)ImagingError_ValueError("bad transparency mask");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -289,9 +316,14 @@ ImagingPaste(Imaging imOut, Imaging imIn, Imaging imMask,
|
|||
}
|
||||
|
||||
static inline void
|
||||
fill(Imaging imOut, const void* ink_, int dx, int dy,
|
||||
int xsize, int ysize, int pixelsize)
|
||||
{
|
||||
fill(
|
||||
Imaging imOut,
|
||||
const void *ink_,
|
||||
int dx,
|
||||
int dy,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int pixelsize) {
|
||||
/* fill opaque region */
|
||||
|
||||
int x, y;
|
||||
|
@ -302,30 +334,34 @@ fill(Imaging imOut, const void* ink_, int dx, int dy,
|
|||
memcpy(&ink8, ink_, sizeof(ink8));
|
||||
|
||||
if (imOut->image8 || ink32 == 0L) {
|
||||
|
||||
dx *= pixelsize;
|
||||
xsize *= pixelsize;
|
||||
for (y = 0; y < ysize; y++) {
|
||||
memset(imOut->image[y+dy]+dx, ink8, xsize);
|
||||
memset(imOut->image[y + dy] + dx, ink8, xsize);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
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++) {
|
||||
out[x] = ink32;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
fill_mask_1(Imaging imOut, const void* ink_, Imaging imMask,
|
||||
int dx, int dy, int sx, int sy,
|
||||
int xsize, int ysize, int pixelsize)
|
||||
{
|
||||
fill_mask_1(
|
||||
Imaging imOut,
|
||||
const void *ink_,
|
||||
Imaging imMask,
|
||||
int dx,
|
||||
int dy,
|
||||
int sx,
|
||||
int sy,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int pixelsize) {
|
||||
/* fill with mode "1" mask */
|
||||
|
||||
int x, y;
|
||||
|
@ -336,10 +372,9 @@ fill_mask_1(Imaging imOut, const void* ink_, Imaging imMask,
|
|||
memcpy(&ink8, ink_, sizeof(ink8));
|
||||
|
||||
if (imOut->image8) {
|
||||
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8* out = imOut->image8[y+dy]+dx;
|
||||
UINT8* mask = imMask->image8[y+sy]+sx;
|
||||
UINT8 *out = imOut->image8[y + dy] + dx;
|
||||
UINT8 *mask = imMask->image8[y + sy] + sx;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
if (*mask++) {
|
||||
*out = ink8;
|
||||
|
@ -349,10 +384,9 @@ fill_mask_1(Imaging imOut, const void* ink_, Imaging imMask,
|
|||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (y = 0; y < ysize; y++) {
|
||||
INT32* out = imOut->image32[y+dy]+dx;
|
||||
UINT8* mask = imMask->image8[y+sy]+sx;
|
||||
INT32 *out = imOut->image32[y + dy] + dx;
|
||||
UINT8 *mask = imMask->image8[y + sy] + sx;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
if (*mask++) {
|
||||
*out = ink32;
|
||||
|
@ -364,20 +398,26 @@ fill_mask_1(Imaging imOut, const void* ink_, Imaging imMask,
|
|||
}
|
||||
|
||||
static inline void
|
||||
fill_mask_L(Imaging imOut, const UINT8* ink, Imaging imMask,
|
||||
int dx, int dy, int sx, int sy,
|
||||
int xsize, int ysize, int pixelsize)
|
||||
{
|
||||
fill_mask_L(
|
||||
Imaging imOut,
|
||||
const UINT8 *ink,
|
||||
Imaging imMask,
|
||||
int dx,
|
||||
int dy,
|
||||
int sx,
|
||||
int sy,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int pixelsize) {
|
||||
/* fill with mode "L" matte */
|
||||
|
||||
int x, y, i;
|
||||
unsigned int tmp1;
|
||||
|
||||
if (imOut->image8) {
|
||||
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8* out = imOut->image8[y+dy]+dx;
|
||||
UINT8* mask = imMask->image8[y+sy]+sx;
|
||||
UINT8 *out = imOut->image8[y + dy] + dx;
|
||||
UINT8 *mask = imMask->image8[y + sy] + sx;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
*out = BLEND(*mask, *out, ink[0], tmp1);
|
||||
out++, mask++;
|
||||
|
@ -385,21 +425,20 @@ fill_mask_L(Imaging imOut, const UINT8* ink, Imaging imMask,
|
|||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8* out = (UINT8*) imOut->image[y+dy]+dx*pixelsize;
|
||||
UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
|
||||
UINT8 *out = (UINT8 *)imOut->image[y + dy] + dx * pixelsize;
|
||||
UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
for (i = 0; i < pixelsize; i++) {
|
||||
UINT8 channel_mask = *mask;
|
||||
if ((
|
||||
strcmp(imOut->mode, "RGBa") == 0 ||
|
||||
strcmp(imOut->mode, "RGBA") == 0 ||
|
||||
strcmp(imOut->mode, "La") == 0 ||
|
||||
strcmp(imOut->mode, "LA") == 0 ||
|
||||
strcmp(imOut->mode, "PA") == 0
|
||||
) && i != 3) {
|
||||
channel_mask = 255 - (255 - channel_mask) * (1 - (255 - out[3]) / 255);
|
||||
if ((strcmp(imOut->mode, "RGBa") == 0 ||
|
||||
strcmp(imOut->mode, "RGBA") == 0 ||
|
||||
strcmp(imOut->mode, "La") == 0 ||
|
||||
strcmp(imOut->mode, "LA") == 0 ||
|
||||
strcmp(imOut->mode, "PA") == 0) &&
|
||||
i != 3) {
|
||||
channel_mask =
|
||||
255 - (255 - channel_mask) * (1 - (255 - out[3]) / 255);
|
||||
}
|
||||
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
|
||||
fill_mask_RGBA(Imaging imOut, const UINT8* ink, Imaging imMask,
|
||||
int dx, int dy, int sx, int sy,
|
||||
int xsize, int ysize, int pixelsize)
|
||||
{
|
||||
fill_mask_RGBA(
|
||||
Imaging imOut,
|
||||
const UINT8 *ink,
|
||||
Imaging imMask,
|
||||
int dx,
|
||||
int dy,
|
||||
int sx,
|
||||
int sy,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int pixelsize) {
|
||||
/* fill with mode "RGBA" matte */
|
||||
|
||||
int x, y, i;
|
||||
unsigned int tmp1;
|
||||
|
||||
if (imOut->image8) {
|
||||
|
||||
sx = sx*4+3;
|
||||
sx = sx * 4 + 3;
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8* out = imOut->image8[y+dy]+dx;
|
||||
UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
|
||||
UINT8 *out = imOut->image8[y + dy] + dx;
|
||||
UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
*out = BLEND(*mask, *out, ink[0], tmp1);
|
||||
out++, mask += 4;
|
||||
|
@ -433,12 +478,11 @@ fill_mask_RGBA(Imaging imOut, const UINT8* ink, Imaging imMask,
|
|||
}
|
||||
|
||||
} else {
|
||||
|
||||
dx *= pixelsize;
|
||||
sx = sx*4 + 3;
|
||||
sx = sx * 4 + 3;
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8* out = (UINT8*) imOut->image[y+dy]+dx;
|
||||
UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
|
||||
UINT8 *out = (UINT8 *)imOut->image[y + dy] + dx;
|
||||
UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
for (i = 0; i < pixelsize; i++) {
|
||||
*out = BLEND(*mask, *out, ink[i], tmp1);
|
||||
|
@ -451,21 +495,27 @@ fill_mask_RGBA(Imaging imOut, const UINT8* ink, Imaging imMask,
|
|||
}
|
||||
|
||||
static inline void
|
||||
fill_mask_RGBa(Imaging imOut, const UINT8* ink, Imaging imMask,
|
||||
int dx, int dy, int sx, int sy,
|
||||
int xsize, int ysize, int pixelsize)
|
||||
{
|
||||
fill_mask_RGBa(
|
||||
Imaging imOut,
|
||||
const UINT8 *ink,
|
||||
Imaging imMask,
|
||||
int dx,
|
||||
int dy,
|
||||
int sx,
|
||||
int sy,
|
||||
int xsize,
|
||||
int ysize,
|
||||
int pixelsize) {
|
||||
/* fill with mode "RGBa" matte */
|
||||
|
||||
int x, y, i;
|
||||
unsigned int tmp1;
|
||||
|
||||
if (imOut->image8) {
|
||||
|
||||
sx = sx*4 + 3;
|
||||
sx = sx * 4 + 3;
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8* out = imOut->image8[y+dy]+dx;
|
||||
UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
|
||||
UINT8 *out = imOut->image8[y + dy] + dx;
|
||||
UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
*out = PREBLEND(*mask, *out, ink[0], tmp1);
|
||||
out++, mask += 4;
|
||||
|
@ -473,12 +523,11 @@ fill_mask_RGBa(Imaging imOut, const UINT8* ink, Imaging imMask,
|
|||
}
|
||||
|
||||
} else {
|
||||
|
||||
dx *= pixelsize;
|
||||
sx = sx*4 + 3;
|
||||
sx = sx * 4 + 3;
|
||||
for (y = 0; y < ysize; y++) {
|
||||
UINT8* out = (UINT8*) imOut->image[y+dy]+dx;
|
||||
UINT8* mask = (UINT8*) imMask->image[y+sy]+sx;
|
||||
UINT8 *out = (UINT8 *)imOut->image[y + dy] + dx;
|
||||
UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx;
|
||||
for (x = 0; x < xsize; x++) {
|
||||
for (i = 0; i < pixelsize; i++) {
|
||||
*out = PREBLEND(*mask, *out, ink[i], tmp1);
|
||||
|
@ -491,16 +540,21 @@ fill_mask_RGBa(Imaging imOut, const UINT8* ink, Imaging imMask,
|
|||
}
|
||||
|
||||
int
|
||||
ImagingFill2(Imaging imOut, const void* ink, Imaging imMask,
|
||||
int dx0, int dy0, int dx1, int dy1)
|
||||
{
|
||||
ImagingFill2(
|
||||
Imaging imOut,
|
||||
const void *ink,
|
||||
Imaging imMask,
|
||||
int dx0,
|
||||
int dy0,
|
||||
int dx1,
|
||||
int dy1) {
|
||||
ImagingSectionCookie cookie;
|
||||
int xsize, ysize;
|
||||
int pixelsize;
|
||||
int sx0, sy0;
|
||||
|
||||
if (!imOut || !ink) {
|
||||
(void) ImagingError_ModeError();
|
||||
(void)ImagingError_ModeError();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -510,7 +564,7 @@ ImagingFill2(Imaging imOut, const void* ink, Imaging imMask,
|
|||
ysize = dy1 - dy0;
|
||||
|
||||
if (imMask && (xsize != imMask->xsize || ysize != imMask->ysize)) {
|
||||
(void) ImagingError_Mismatch();
|
||||
(void)ImagingError_Mismatch();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -540,30 +594,26 @@ ImagingFill2(Imaging imOut, const void* ink, Imaging imMask,
|
|||
|
||||
} else if (strcmp(imMask->mode, "1") == 0) {
|
||||
ImagingSectionEnter(&cookie);
|
||||
fill_mask_1(imOut, ink, imMask, dx0, dy0, sx0, sy0,
|
||||
xsize, ysize, pixelsize);
|
||||
fill_mask_1(imOut, ink, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
|
||||
ImagingSectionLeave(&cookie);
|
||||
|
||||
} else if (strcmp(imMask->mode, "L") == 0) {
|
||||
ImagingSectionEnter(&cookie);
|
||||
fill_mask_L(imOut, ink, imMask, dx0, dy0, sx0, sy0,
|
||||
xsize, ysize, pixelsize);
|
||||
fill_mask_L(imOut, ink, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
|
||||
ImagingSectionLeave(&cookie);
|
||||
|
||||
} else if (strcmp(imMask->mode, "RGBA") == 0) {
|
||||
ImagingSectionEnter(&cookie);
|
||||
fill_mask_RGBA(imOut, ink, imMask, dx0, dy0, sx0, sy0,
|
||||
xsize, ysize, pixelsize);
|
||||
fill_mask_RGBA(imOut, ink, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
|
||||
ImagingSectionLeave(&cookie);
|
||||
|
||||
} else if (strcmp(imMask->mode, "RGBa") == 0) {
|
||||
ImagingSectionEnter(&cookie);
|
||||
fill_mask_RGBa(imOut, ink, imMask, dx0, dy0, sx0, sy0,
|
||||
xsize, ysize, pixelsize);
|
||||
fill_mask_RGBa(imOut, ink, imMask, dx0, dy0, sx0, sy0, xsize, ysize, pixelsize);
|
||||
ImagingSectionLeave(&cookie);
|
||||
|
||||
} else {
|
||||
(void) ImagingError_ValueError("bad transparency mask");
|
||||
(void)ImagingError_ValueError("bad transparency mask");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,24 +19,20 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
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 chunk;
|
||||
UINT8* out;
|
||||
UINT8* ptr;
|
||||
UINT8 *out;
|
||||
UINT8 *ptr;
|
||||
|
||||
ptr = buf;
|
||||
|
||||
chunk = 3 * state->xsize;
|
||||
|
||||
for (;;) {
|
||||
|
||||
/* We need data for two full lines before we can do anything */
|
||||
if (bytes < chunk) {
|
||||
return ptr - buf;
|
||||
|
@ -46,13 +42,12 @@ ImagingPcdDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
out = state->buffer;
|
||||
for (x = 0; x < state->xsize; x++) {
|
||||
out[0] = ptr[x];
|
||||
out[1] = ptr[(x+4*state->xsize)/2];
|
||||
out[2] = ptr[(x+5*state->xsize)/2];
|
||||
out[1] = ptr[(x + 4 * state->xsize) / 2];
|
||||
out[2] = ptr[(x + 5 * state->xsize) / 2];
|
||||
out += 3;
|
||||
}
|
||||
|
||||
state->shuffle((UINT8*) im->image[state->y],
|
||||
state->buffer, state->xsize);
|
||||
state->shuffle((UINT8 *)im->image[state->y], state->buffer, state->xsize);
|
||||
|
||||
if (++state->y >= state->ysize) {
|
||||
return -1; /* This can hardly happen */
|
||||
|
@ -61,14 +56,13 @@ ImagingPcdDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
/* Unpack second line */
|
||||
out = state->buffer;
|
||||
for (x = 0; x < state->xsize; x++) {
|
||||
out[0] = ptr[x+state->xsize];
|
||||
out[1] = ptr[(x+4*state->xsize)/2];
|
||||
out[2] = ptr[(x+5*state->xsize)/2];
|
||||
out[0] = ptr[x + state->xsize];
|
||||
out[1] = ptr[(x + 4 * state->xsize) / 2];
|
||||
out[2] = ptr[(x + 5 * state->xsize) / 2];
|
||||
out += 3;
|
||||
}
|
||||
|
||||
state->shuffle((UINT8*) im->image[state->y],
|
||||
state->buffer, state->xsize);
|
||||
state->shuffle((UINT8 *)im->image[state->y], state->buffer, state->xsize);
|
||||
|
||||
if (++state->y >= state->ysize) {
|
||||
return -1;
|
||||
|
@ -76,6 +70,5 @@ ImagingPcdDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
|
||||
ptr += chunk;
|
||||
bytes -= chunk;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,14 +13,12 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
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* ptr;
|
||||
UINT8 *ptr;
|
||||
|
||||
if ((state->xsize * state->bits + 7) / 8 > state->bytes) {
|
||||
state->errcode = IMAGING_CODEC_OVERRUN;
|
||||
|
@ -30,13 +28,11 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
ptr = buf;
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (bytes < 1) {
|
||||
return ptr - buf;
|
||||
}
|
||||
|
||||
if ((*ptr & 0xC0) == 0xC0) {
|
||||
|
||||
/* Run */
|
||||
if (bytes < 2) {
|
||||
return ptr - buf;
|
||||
|
@ -53,14 +49,14 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
n--;
|
||||
}
|
||||
|
||||
ptr += 2; bytes -= 2;
|
||||
ptr += 2;
|
||||
bytes -= 2;
|
||||
|
||||
} else {
|
||||
|
||||
/* Literal */
|
||||
state->buffer[state->x++] = ptr[0];
|
||||
ptr++; bytes--;
|
||||
|
||||
ptr++;
|
||||
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 stride = state->bytes / bands;
|
||||
int i;
|
||||
for (i=1; i< bands; i++) { // note -- skipping first band
|
||||
memmove(&state->buffer[i*state->xsize],
|
||||
&state->buffer[i*stride],
|
||||
state->xsize);
|
||||
for (i = 1; i < bands; i++) { // note -- skipping first band
|
||||
memmove(
|
||||
&state->buffer[i * state->xsize],
|
||||
&state->buffer[i * stride],
|
||||
state->xsize);
|
||||
}
|
||||
}
|
||||
/* Got a full line, unpack it */
|
||||
state->shuffle((UINT8*) im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize, state->buffer,
|
||||
state->xsize);
|
||||
state->shuffle(
|
||||
(UINT8 *)im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize,
|
||||
state->buffer,
|
||||
state->xsize);
|
||||
|
||||
state->x = 0;
|
||||
|
||||
|
@ -86,6 +85,5 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
enum { INIT, FETCH, ENCODE };
|
||||
|
@ -22,9 +21,8 @@ enum { INIT, FETCH, ENCODE };
|
|||
#define LAST ystep
|
||||
|
||||
int
|
||||
ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||
{
|
||||
UINT8* ptr;
|
||||
ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
|
||||
UINT8 *ptr;
|
||||
int this;
|
||||
int bytes_per_line = 0;
|
||||
int padding = 0;
|
||||
|
@ -45,12 +43,12 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
}
|
||||
|
||||
bpp = state->bits;
|
||||
if (state->bits == 24){
|
||||
if (state->bits == 24) {
|
||||
planes = 3;
|
||||
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
|
||||
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.
|
||||
|
@ -59,133 +57,131 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
|
||||
padding = stride - bytes_per_line;
|
||||
|
||||
|
||||
for (;;) {
|
||||
|
||||
switch (state->state) {
|
||||
case FETCH:
|
||||
case FETCH:
|
||||
|
||||
/* get a line of data */
|
||||
if (state->y >= state->ysize) {
|
||||
state->errcode = IMAGING_CODEC_END;
|
||||
return ptr - buf;
|
||||
}
|
||||
/* get a line of data */
|
||||
if (state->y >= state->ysize) {
|
||||
state->errcode = IMAGING_CODEC_END;
|
||||
return ptr - buf;
|
||||
}
|
||||
|
||||
state->shuffle(state->buffer,
|
||||
(UINT8*) im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize, state->xsize);
|
||||
state->shuffle(
|
||||
state->buffer,
|
||||
(UINT8 *)im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize,
|
||||
state->xsize);
|
||||
|
||||
state->y += 1;
|
||||
state->y += 1;
|
||||
|
||||
state->count = 1;
|
||||
state->LAST = state->buffer[0];
|
||||
state->count = 1;
|
||||
state->LAST = state->buffer[0];
|
||||
|
||||
state->x = 1;
|
||||
state->x = 1;
|
||||
|
||||
state->state = ENCODE;
|
||||
/* fall through */
|
||||
state->state = ENCODE;
|
||||
/* fall through */
|
||||
|
||||
case ENCODE:
|
||||
/* compress this line */
|
||||
case ENCODE:
|
||||
/* compress this line */
|
||||
|
||||
/* when we arrive here, "count" contains the number of
|
||||
bytes having the value of "LAST" that we've already
|
||||
seen */
|
||||
do {
|
||||
/* If we're encoding an odd width file, and we've
|
||||
got more than one plane, we need to pad each
|
||||
color row with padding bytes at the end. Since
|
||||
The pixels are stored RRRRRGGGGGBBBBB, so we need
|
||||
to have the padding be RRRRRPGGGGGPBBBBBP. Hence
|
||||
the double loop
|
||||
*/
|
||||
while (state->x % bytes_per_line) {
|
||||
|
||||
if (state->count == 63) {
|
||||
/* this run is full; flush it */
|
||||
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) {
|
||||
/* when we arrive here, "count" contains the number of
|
||||
bytes having the value of "LAST" that we've already
|
||||
seen */
|
||||
do {
|
||||
/* If we're encoding an odd width file, and we've
|
||||
got more than one plane, we need to pad each
|
||||
color row with padding bytes at the end. Since
|
||||
The pixels are stored RRRRRGGGGGBBBBB, so we need
|
||||
to have the padding be RRRRRPGGGGGPBBBBBP. Hence
|
||||
the double loop
|
||||
*/
|
||||
while (state->x % bytes_per_line) {
|
||||
if (state->count == 63) {
|
||||
/* this run is full; flush it */
|
||||
if (bytes < 2) {
|
||||
return ptr - buf;
|
||||
}
|
||||
ptr[0] = state->LAST;
|
||||
ptr += 1;
|
||||
bytes -= 1;
|
||||
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 {
|
||||
if (state->count > 0) {
|
||||
if (bytes < 2) {
|
||||
/* start a new run */
|
||||
if (state->count == 1 && (state->LAST < 0xc0)) {
|
||||
if (bytes < 1) {
|
||||
return ptr - buf;
|
||||
}
|
||||
ptr[0] = 0xc0 | state->count;
|
||||
ptr[1] = state->LAST;
|
||||
ptr += 2;
|
||||
bytes -= 2;
|
||||
ptr[0] = state->LAST;
|
||||
ptr += 1;
|
||||
bytes -= 1;
|
||||
} 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 */
|
||||
if (state->count == 1 && (state->LAST < 0xc0)) {
|
||||
if (bytes < 1 + padding) {
|
||||
return ptr - buf;
|
||||
}
|
||||
ptr[0] = state->LAST;
|
||||
ptr += 1;
|
||||
bytes -= 1;
|
||||
} else {
|
||||
if (state->count > 0) {
|
||||
if (bytes < 2 + padding) {
|
||||
/* end of line; flush the current run */
|
||||
if (state->count == 1 && (state->LAST < 0xc0)) {
|
||||
if (bytes < 1 + padding) {
|
||||
return ptr - buf;
|
||||
}
|
||||
ptr[0] = 0xc0 | state->count;
|
||||
ptr[1] = state->LAST;
|
||||
ptr += 2;
|
||||
bytes -= 2;
|
||||
ptr[0] = state->LAST;
|
||||
ptr += 1;
|
||||
bytes -= 1;
|
||||
} 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 */
|
||||
for (i = 0; i < padding; i++) {
|
||||
ptr[0] = 0;
|
||||
ptr += 1;
|
||||
bytes -= 1;
|
||||
}
|
||||
/* reset for the next color plane. */
|
||||
if (state->x < planes * bytes_per_line) {
|
||||
state->count = 1;
|
||||
state->LAST = state->buffer[state->x];
|
||||
state->x += 1;
|
||||
}
|
||||
} while (state->x < planes * bytes_per_line);
|
||||
/* add the padding */
|
||||
for (i = 0; i < padding; i++) {
|
||||
ptr[0] = 0;
|
||||
ptr += 1;
|
||||
bytes -= 1;
|
||||
}
|
||||
/* reset for the next color plane. */
|
||||
if (state->x < planes * bytes_per_line) {
|
||||
state->count = 1;
|
||||
state->LAST = state->buffer[state->x];
|
||||
state->x += 1;
|
||||
}
|
||||
} while (state->x < planes * bytes_per_line);
|
||||
|
||||
/* read next line */
|
||||
state->state = FETCH;
|
||||
break;
|
||||
/* read next line */
|
||||
state->state = FETCH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,22 +19,20 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
typedef struct {
|
||||
const void* table;
|
||||
const void *table;
|
||||
} im_point_context;
|
||||
|
||||
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;
|
||||
/* 8-bit source, 8-bit destination */
|
||||
UINT8* table = (UINT8*) context->table;
|
||||
UINT8 *table = (UINT8 *)context->table;
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
UINT8* in = imIn->image8[y];
|
||||
UINT8* out = imOut->image8[y];
|
||||
UINT8 *in = imIn->image8[y];
|
||||
UINT8 *out = imOut->image8[y];
|
||||
for (x = 0; x < imIn->xsize; x++) {
|
||||
out[x] = table[in[x]];
|
||||
}
|
||||
|
@ -42,68 +40,67 @@ im_point_8_8(Imaging imOut, Imaging imIn, im_point_context* context)
|
|||
}
|
||||
|
||||
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;
|
||||
/* 2x8-bit source, 2x8-bit destination */
|
||||
UINT8* table = (UINT8*) context->table;
|
||||
UINT8 *table = (UINT8 *)context->table;
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
UINT8* in = (UINT8*) imIn->image[y];
|
||||
UINT8* out = (UINT8*) imOut->image[y];
|
||||
UINT8 *in = (UINT8 *)imIn->image[y];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y];
|
||||
for (x = 0; x < imIn->xsize; x++) {
|
||||
out[0] = table[in[0]];
|
||||
out[3] = table[in[3]+256];
|
||||
in += 4; out += 4;
|
||||
out[3] = table[in[3] + 256];
|
||||
in += 4;
|
||||
out += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
/* 3x8-bit source, 3x8-bit destination */
|
||||
UINT8* table = (UINT8*) context->table;
|
||||
UINT8 *table = (UINT8 *)context->table;
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
UINT8* in = (UINT8*) imIn->image[y];
|
||||
UINT8* out = (UINT8*) imOut->image[y];
|
||||
UINT8 *in = (UINT8 *)imIn->image[y];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y];
|
||||
for (x = 0; x < imIn->xsize; x++) {
|
||||
out[0] = table[in[0]];
|
||||
out[1] = table[in[1]+256];
|
||||
out[2] = table[in[2]+512];
|
||||
in += 4; out += 4;
|
||||
out[1] = table[in[1] + 256];
|
||||
out[2] = table[in[2] + 512];
|
||||
in += 4;
|
||||
out += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
/* 4x8-bit source, 4x8-bit destination */
|
||||
UINT8* table = (UINT8*) context->table;
|
||||
UINT8 *table = (UINT8 *)context->table;
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
UINT8* in = (UINT8*) imIn->image[y];
|
||||
UINT8* out = (UINT8*) imOut->image[y];
|
||||
UINT8 *in = (UINT8 *)imIn->image[y];
|
||||
UINT8 *out = (UINT8 *)imOut->image[y];
|
||||
for (x = 0; x < imIn->xsize; x++) {
|
||||
out[0] = table[in[0]];
|
||||
out[1] = table[in[1]+256];
|
||||
out[2] = table[in[2]+512];
|
||||
out[3] = table[in[3]+768];
|
||||
in += 4; out += 4;
|
||||
out[1] = table[in[1] + 256];
|
||||
out[2] = table[in[2] + 512];
|
||||
out[3] = table[in[3] + 768];
|
||||
in += 4;
|
||||
out += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
/* 8-bit source, 32-bit destination */
|
||||
char* table = (char*) context->table;
|
||||
char *table = (char *)context->table;
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
UINT8* in = imIn->image8[y];
|
||||
INT32* out = imOut->image32[y];
|
||||
UINT8 *in = imIn->image8[y];
|
||||
INT32 *out = imOut->image32[y];
|
||||
for (x = 0; x < imIn->xsize; x++) {
|
||||
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
|
||||
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;
|
||||
/* 32-bit source, 8-bit destination */
|
||||
UINT8* table = (UINT8*) context->table;
|
||||
UINT8 *table = (UINT8 *)context->table;
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
INT32* in = imIn->image32[y];
|
||||
UINT8* out = imOut->image8[y];
|
||||
INT32 *in = imIn->image32[y];
|
||||
UINT8 *out = imOut->image8[y];
|
||||
for (x = 0; x < imIn->xsize; x++) {
|
||||
int v = in[x];
|
||||
if (v < 0) {
|
||||
|
@ -132,17 +128,16 @@ im_point_32_8(Imaging imOut, Imaging imIn, im_point_context* context)
|
|||
}
|
||||
|
||||
Imaging
|
||||
ImagingPoint(Imaging imIn, const char* mode, const void* table)
|
||||
{
|
||||
ImagingPoint(Imaging imIn, const char *mode, const void *table) {
|
||||
/* lookup table transform */
|
||||
|
||||
ImagingSectionCookie cookie;
|
||||
Imaging imOut;
|
||||
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) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
if (!mode) {
|
||||
|
@ -166,22 +161,22 @@ ImagingPoint(Imaging imIn, const char* mode, const void* table)
|
|||
if (imIn->type == IMAGING_TYPE_UINT8) {
|
||||
if (imIn->bands == imOut->bands && imIn->type == imOut->type) {
|
||||
switch (imIn->bands) {
|
||||
case 1:
|
||||
point = im_point_8_8;
|
||||
break;
|
||||
case 2:
|
||||
point = im_point_2x8_2x8;
|
||||
break;
|
||||
case 3:
|
||||
point = im_point_3x8_3x8;
|
||||
break;
|
||||
case 4:
|
||||
point = im_point_4x8_4x8;
|
||||
break;
|
||||
default:
|
||||
/* this cannot really happen */
|
||||
point = im_point_8_8;
|
||||
break;
|
||||
case 1:
|
||||
point = im_point_8_8;
|
||||
break;
|
||||
case 2:
|
||||
point = im_point_2x8_2x8;
|
||||
break;
|
||||
case 3:
|
||||
point = im_point_3x8_3x8;
|
||||
break;
|
||||
case 4:
|
||||
point = im_point_4x8_4x8;
|
||||
break;
|
||||
default:
|
||||
/* this cannot really happen */
|
||||
point = im_point_8_8;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
point = im_point_8_32;
|
||||
|
@ -201,26 +196,22 @@ ImagingPoint(Imaging imIn, const char* mode, const void* table)
|
|||
|
||||
return imOut;
|
||||
|
||||
mode_mismatch:
|
||||
return (Imaging) ImagingError_ValueError(
|
||||
"point operation not supported for this mode"
|
||||
);
|
||||
mode_mismatch:
|
||||
return (Imaging)ImagingError_ValueError(
|
||||
"point operation not supported for this mode");
|
||||
}
|
||||
|
||||
|
||||
Imaging
|
||||
ImagingPointTransform(Imaging imIn, double scale, double offset)
|
||||
{
|
||||
ImagingPointTransform(Imaging imIn, double scale, double offset) {
|
||||
/* scale/offset transform */
|
||||
|
||||
ImagingSectionCookie cookie;
|
||||
Imaging imOut;
|
||||
int x, y;
|
||||
|
||||
if (!imIn || (strcmp(imIn->mode, "I") != 0 &&
|
||||
strcmp(imIn->mode, "I;16") != 0 &&
|
||||
if (!imIn || (strcmp(imIn->mode, "I") != 0 && strcmp(imIn->mode, "I;16") != 0 &&
|
||||
strcmp(imIn->mode, "F") != 0)) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize);
|
||||
|
@ -229,50 +220,50 @@ ImagingPointTransform(Imaging imIn, double scale, double offset)
|
|||
}
|
||||
|
||||
switch (imIn->type) {
|
||||
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) {
|
||||
case IMAGING_TYPE_INT32:
|
||||
ImagingSectionEnter(&cookie);
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
char* in = (char*)imIn->image[y];
|
||||
char* out = (char*)imOut->image[y];
|
||||
INT32 *in = imIn->image32[y];
|
||||
INT32 *out = imOut->image32[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));
|
||||
out[x] = in[x] * scale + offset;
|
||||
}
|
||||
}
|
||||
ImagingSectionLeave(&cookie);
|
||||
break;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
default:
|
||||
ImagingDelete(imOut);
|
||||
return (Imaging) ImagingError_ValueError("internal error");
|
||||
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);
|
||||
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;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -24,290 +24,313 @@
|
|||
#include "QuantHash.h"
|
||||
|
||||
typedef struct _HashNode {
|
||||
struct _HashNode *next;
|
||||
HashKey_t key;
|
||||
HashVal_t value;
|
||||
struct _HashNode *next;
|
||||
HashKey_t key;
|
||||
HashVal_t value;
|
||||
} HashNode;
|
||||
|
||||
struct _HashTable {
|
||||
HashNode **table;
|
||||
uint32_t length;
|
||||
uint32_t count;
|
||||
HashFunc hashFunc;
|
||||
HashCmpFunc cmpFunc;
|
||||
void *userData;
|
||||
HashNode **table;
|
||||
uint32_t length;
|
||||
uint32_t count;
|
||||
HashFunc hashFunc;
|
||||
HashCmpFunc cmpFunc;
|
||||
void *userData;
|
||||
};
|
||||
|
||||
#define MIN_LENGTH 11
|
||||
#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 *h;
|
||||
h=malloc(sizeof(HashTable));
|
||||
if (!h) { return NULL; }
|
||||
h->hashFunc=hf;
|
||||
h->cmpFunc=cf;
|
||||
h->length=MIN_LENGTH;
|
||||
h->count=0;
|
||||
h->userData=NULL;
|
||||
h->table=malloc(sizeof(HashNode *)*h->length);
|
||||
if (!h->table) { free(h); return NULL; }
|
||||
memset (h->table,0,sizeof(HashNode *)*h->length);
|
||||
return h;
|
||||
HashTable *
|
||||
hashtable_new(HashFunc hf, HashCmpFunc cf) {
|
||||
HashTable *h;
|
||||
h = malloc(sizeof(HashTable));
|
||||
if (!h) {
|
||||
return NULL;
|
||||
}
|
||||
h->hashFunc = hf;
|
||||
h->cmpFunc = cf;
|
||||
h->length = MIN_LENGTH;
|
||||
h->count = 0;
|
||||
h->userData = NULL;
|
||||
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 int unit[]={0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0};
|
||||
uint32_t t;
|
||||
while (start>1) {
|
||||
if (!unit[start&0x0f]) {
|
||||
start+=dir;
|
||||
continue;
|
||||
}
|
||||
for (t=2;t<sqrt((double)start);t++) {
|
||||
if (!start%t) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (t>=sqrt((double)start)) {
|
||||
break;
|
||||
}
|
||||
start+=dir;
|
||||
}
|
||||
return start;
|
||||
static uint32_t
|
||||
_findPrime(uint32_t start, int dir) {
|
||||
static int unit[] = {0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0};
|
||||
uint32_t t;
|
||||
while (start > 1) {
|
||||
if (!unit[start & 0x0f]) {
|
||||
start += dir;
|
||||
continue;
|
||||
}
|
||||
for (t = 2; t < sqrt((double)start); t++) {
|
||||
if (!start % t) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (t >= sqrt((double)start)) {
|
||||
break;
|
||||
}
|
||||
start += dir;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
static void _hashtable_rehash(HashTable *h,CollisionFunc cf,uint32_t newSize) {
|
||||
HashNode **oldTable=h->table;
|
||||
uint32_t i;
|
||||
HashNode *n,*nn;
|
||||
uint32_t oldSize;
|
||||
oldSize=h->length;
|
||||
h->table=malloc(sizeof(HashNode *)*newSize);
|
||||
if (!h->table) {
|
||||
h->table=oldTable;
|
||||
return;
|
||||
}
|
||||
h->length=newSize;
|
||||
h->count=0;
|
||||
memset (h->table,0,sizeof(HashNode *)*h->length);
|
||||
for (i=0;i<oldSize;i++) {
|
||||
for (n=oldTable[i];n;n=nn) {
|
||||
nn=n->next;
|
||||
_hashtable_insert_node(h,n,0,0,cf);
|
||||
}
|
||||
}
|
||||
free(oldTable);
|
||||
static void
|
||||
_hashtable_rehash(HashTable *h, CollisionFunc cf, uint32_t newSize) {
|
||||
HashNode **oldTable = h->table;
|
||||
uint32_t i;
|
||||
HashNode *n, *nn;
|
||||
uint32_t oldSize;
|
||||
oldSize = h->length;
|
||||
h->table = malloc(sizeof(HashNode *) * newSize);
|
||||
if (!h->table) {
|
||||
h->table = oldTable;
|
||||
return;
|
||||
}
|
||||
h->length = newSize;
|
||||
h->count = 0;
|
||||
memset(h->table, 0, sizeof(HashNode *) * h->length);
|
||||
for (i = 0; i < oldSize; i++) {
|
||||
for (n = oldTable[i]; n; n = nn) {
|
||||
nn = n->next;
|
||||
_hashtable_insert_node(h, n, 0, 0, cf);
|
||||
}
|
||||
}
|
||||
free(oldTable);
|
||||
}
|
||||
|
||||
static void _hashtable_resize(HashTable *h) {
|
||||
uint32_t newSize;
|
||||
uint32_t oldSize;
|
||||
oldSize=h->length;
|
||||
newSize=oldSize;
|
||||
if (h->count*RESIZE_FACTOR<h->length) {
|
||||
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) {
|
||||
_hashtable_rehash(h,NULL,newSize);
|
||||
}
|
||||
static void
|
||||
_hashtable_resize(HashTable *h) {
|
||||
uint32_t newSize;
|
||||
uint32_t oldSize;
|
||||
oldSize = h->length;
|
||||
newSize = oldSize;
|
||||
if (h->count * RESIZE_FACTOR < h->length) {
|
||||
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) {
|
||||
_hashtable_rehash(h, NULL, newSize);
|
||||
}
|
||||
}
|
||||
|
||||
static int _hashtable_insert_node(HashTable *h,HashNode *node,int resize,int update,CollisionFunc cf) {
|
||||
uint32_t hash=h->hashFunc(h,node->key)%h->length;
|
||||
HashNode **n,*nv;
|
||||
int i;
|
||||
static int
|
||||
_hashtable_insert_node(
|
||||
HashTable *h, HashNode *node, int resize, int update, CollisionFunc cf) {
|
||||
uint32_t hash = h->hashFunc(h, node->key) % h->length;
|
||||
HashNode **n, *nv;
|
||||
int i;
|
||||
|
||||
for (n=&(h->table[hash]);*n;n=&((*n)->next)) {
|
||||
nv=*n;
|
||||
i=h->cmpFunc(h,nv->key,node->key);
|
||||
if (!i) {
|
||||
if (cf) {
|
||||
nv->key=node->key;
|
||||
cf(h,&(nv->key),&(nv->value),node->key,node->value);
|
||||
free(node);
|
||||
for (n = &(h->table[hash]); *n; n = &((*n)->next)) {
|
||||
nv = *n;
|
||||
i = h->cmpFunc(h, nv->key, node->key);
|
||||
if (!i) {
|
||||
if (cf) {
|
||||
nv->key = node->key;
|
||||
cf(h, &(nv->key), &(nv->value), node->key, node->value);
|
||||
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;
|
||||
} 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;
|
||||
} 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 {
|
||||
} else if (i > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!update) {
|
||||
t = malloc(sizeof(HashNode));
|
||||
if (!t) {
|
||||
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;
|
||||
}
|
||||
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(HashTable *h,HashKey_t key,HashVal_t val) {
|
||||
return _hashtable_insert(h,key,val,1,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 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) {
|
||||
HashNode *n;
|
||||
uint32_t x;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
int
|
||||
hashtable_insert(HashTable *h, HashKey_t key, HashVal_t val) {
|
||||
return _hashtable_insert(h, key, val, 1, 0);
|
||||
}
|
||||
|
||||
void hashtable_foreach(HashTable *h,IteratorFunc i,void *u) {
|
||||
HashNode *n;
|
||||
uint32_t x;
|
||||
void
|
||||
hashtable_foreach_update(HashTable *h, IteratorUpdateFunc i, void *u) {
|
||||
HashNode *n;
|
||||
uint32_t x;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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_free(HashTable *h) {
|
||||
HashNode *n,*nn;
|
||||
uint32_t i;
|
||||
void
|
||||
hashtable_foreach(HashTable *h, IteratorFunc i, void *u) {
|
||||
HashNode *n;
|
||||
uint32_t x;
|
||||
|
||||
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);
|
||||
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_rehash_compute(HashTable *h,CollisionFunc cf) {
|
||||
_hashtable_rehash(h,cf,h->length);
|
||||
void
|
||||
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) {
|
||||
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_rehash_compute(HashTable *h, CollisionFunc cf) {
|
||||
_hashtable_rehash(h, cf, h->length);
|
||||
}
|
||||
|
||||
uint32_t hashtable_get_count(const HashTable *h) {
|
||||
return h->count;
|
||||
int
|
||||
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) {
|
||||
return h->userData;
|
||||
uint32_t
|
||||
hashtable_get_count(const HashTable *h) {
|
||||
return h->count;
|
||||
}
|
||||
|
||||
void *hashtable_set_user_data(HashTable *h,void *data) {
|
||||
void *r=h->userData;
|
||||
h->userData=data;
|
||||
return r;
|
||||
void *
|
||||
hashtable_get_user_data(const HashTable *h) {
|
||||
return h->userData;
|
||||
}
|
||||
|
||||
void *
|
||||
hashtable_set_user_data(HashTable *h, void *data) {
|
||||
void *r = h->userData;
|
||||
h->userData = data;
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -18,23 +18,38 @@ typedef struct _HashTable HashTable;
|
|||
typedef Pixel HashKey_t;
|
||||
typedef uint32_t HashVal_t;
|
||||
|
||||
typedef uint32_t (*HashFunc)(const HashTable *,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 (*IteratorUpdateFunc)(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);
|
||||
typedef uint32_t (*HashFunc)(const HashTable *, 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 (*IteratorUpdateFunc)(
|
||||
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);
|
||||
void hashtable_free(HashTable *h);
|
||||
void hashtable_foreach(HashTable *h,IteratorFunc i,void *u);
|
||||
void hashtable_foreach_update(HashTable *h,IteratorUpdateFunc i,void *u);
|
||||
int hashtable_insert(HashTable *h,HashKey_t key,HashVal_t val);
|
||||
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);
|
||||
HashTable *
|
||||
hashtable_new(HashFunc hf, HashCmpFunc cf);
|
||||
void
|
||||
hashtable_free(HashTable *h);
|
||||
void
|
||||
hashtable_foreach(HashTable *h, IteratorFunc i, void *u);
|
||||
void
|
||||
hashtable_foreach_update(HashTable *h, IteratorUpdateFunc i, void *u);
|
||||
int
|
||||
hashtable_insert(HashTable *h, HashKey_t key, HashVal_t val);
|
||||
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__
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
#include "QuantHeap.h"
|
||||
|
||||
struct _Heap {
|
||||
void **heap;
|
||||
unsigned int heapsize;
|
||||
unsigned int heapcount;
|
||||
HeapCmpFunc cf;
|
||||
void **heap;
|
||||
unsigned int heapsize;
|
||||
unsigned int heapcount;
|
||||
HeapCmpFunc cf;
|
||||
};
|
||||
|
||||
#define INITIAL_SIZE 256
|
||||
|
@ -36,127 +36,141 @@ struct _Heap {
|
|||
// #define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
static int _heap_test(Heap *);
|
||||
static int
|
||||
_heap_test(Heap *);
|
||||
#endif
|
||||
|
||||
void ImagingQuantHeapFree(Heap *h) {
|
||||
free(h->heap);
|
||||
free(h);
|
||||
void
|
||||
ImagingQuantHeapFree(Heap *h) {
|
||||
free(h->heap);
|
||||
free(h);
|
||||
}
|
||||
|
||||
static int _heap_grow(Heap *h,unsigned int newsize) {
|
||||
void *newheap;
|
||||
if (!newsize) {
|
||||
newsize=h->heapsize<<1;
|
||||
}
|
||||
if (newsize<h->heapsize) {
|
||||
return 0;
|
||||
}
|
||||
if (newsize > INT_MAX / sizeof(void *)){
|
||||
return 0;
|
||||
}
|
||||
/* malloc check ok, using calloc for overflow, also checking
|
||||
above due to memcpy below*/
|
||||
newheap=calloc(newsize, sizeof(void *));
|
||||
if (!newheap) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(newheap,h->heap,sizeof(void *)*h->heapsize);
|
||||
free(h->heap);
|
||||
h->heap=newheap;
|
||||
h->heapsize=newsize;
|
||||
return 1;
|
||||
static int
|
||||
_heap_grow(Heap *h, unsigned int newsize) {
|
||||
void *newheap;
|
||||
if (!newsize) {
|
||||
newsize = h->heapsize << 1;
|
||||
}
|
||||
if (newsize < h->heapsize) {
|
||||
return 0;
|
||||
}
|
||||
if (newsize > INT_MAX / sizeof(void *)) {
|
||||
return 0;
|
||||
}
|
||||
/* malloc check ok, using calloc for overflow, also checking
|
||||
above due to memcpy below*/
|
||||
newheap = calloc(newsize, sizeof(void *));
|
||||
if (!newheap) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(newheap, h->heap, sizeof(void *) * h->heapsize);
|
||||
free(h->heap);
|
||||
h->heap = newheap;
|
||||
h->heapsize = newsize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static int _heap_test(Heap *h) {
|
||||
unsigned int k;
|
||||
for (k=1;k*2<=h->heapcount;k++) {
|
||||
if (h->cf(h,h->heap[k],h->heap[k*2])<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");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
static int
|
||||
_heap_test(Heap *h) {
|
||||
unsigned int k;
|
||||
for (k = 1; k * 2 <= h->heapcount; k++) {
|
||||
if (h->cf(h, h->heap[k], h->heap[k * 2]) < 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");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int ImagingQuantHeapRemove(Heap* h,void **r) {
|
||||
unsigned int k,l;
|
||||
void *v;
|
||||
int
|
||||
ImagingQuantHeapRemove(Heap *h, void **r) {
|
||||
unsigned int k, l;
|
||||
void *v;
|
||||
|
||||
if (!h->heapcount) {
|
||||
return 0;
|
||||
}
|
||||
*r=h->heap[1];
|
||||
v=h->heap[h->heapcount--];
|
||||
for (k=1;k*2<=h->heapcount;k=l) {
|
||||
l=k*2;
|
||||
if (l<h->heapcount) {
|
||||
if (h->cf(h,h->heap[l],h->heap[l+1])<0) {
|
||||
l++;
|
||||
}
|
||||
}
|
||||
if (h->cf(h,v,h->heap[l])>0) {
|
||||
break;
|
||||
}
|
||||
h->heap[k]=h->heap[l];
|
||||
}
|
||||
h->heap[k]=v;
|
||||
if (!h->heapcount) {
|
||||
return 0;
|
||||
}
|
||||
*r = h->heap[1];
|
||||
v = h->heap[h->heapcount--];
|
||||
for (k = 1; k * 2 <= h->heapcount; k = l) {
|
||||
l = k * 2;
|
||||
if (l < h->heapcount) {
|
||||
if (h->cf(h, h->heap[l], h->heap[l + 1]) < 0) {
|
||||
l++;
|
||||
}
|
||||
}
|
||||
if (h->cf(h, v, h->heap[l]) > 0) {
|
||||
break;
|
||||
}
|
||||
h->heap[k] = h->heap[l];
|
||||
}
|
||||
h->heap[k] = v;
|
||||
#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
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ImagingQuantHeapAdd(Heap *h,void *val) {
|
||||
int k;
|
||||
if (h->heapcount==h->heapsize-1) {
|
||||
_heap_grow(h,0);
|
||||
}
|
||||
k=++h->heapcount;
|
||||
while (k!=1) {
|
||||
if (h->cf(h,val,h->heap[k/2])<=0) {
|
||||
break;
|
||||
}
|
||||
h->heap[k]=h->heap[k/2];
|
||||
k>>=1;
|
||||
}
|
||||
h->heap[k]=val;
|
||||
int
|
||||
ImagingQuantHeapAdd(Heap *h, void *val) {
|
||||
int k;
|
||||
if (h->heapcount == h->heapsize - 1) {
|
||||
_heap_grow(h, 0);
|
||||
}
|
||||
k = ++h->heapcount;
|
||||
while (k != 1) {
|
||||
if (h->cf(h, val, h->heap[k / 2]) <= 0) {
|
||||
break;
|
||||
}
|
||||
h->heap[k] = h->heap[k / 2];
|
||||
k >>= 1;
|
||||
}
|
||||
h->heap[k] = val;
|
||||
#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
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ImagingQuantHeapTop(Heap *h,void **r) {
|
||||
if (!h->heapcount) {
|
||||
return 0;
|
||||
}
|
||||
*r=h->heap[1];
|
||||
return 1;
|
||||
int
|
||||
ImagingQuantHeapTop(Heap *h, void **r) {
|
||||
if (!h->heapcount) {
|
||||
return 0;
|
||||
}
|
||||
*r = h->heap[1];
|
||||
return 1;
|
||||
}
|
||||
|
||||
Heap *ImagingQuantHeapNew(HeapCmpFunc cf) {
|
||||
Heap *h;
|
||||
Heap *
|
||||
ImagingQuantHeapNew(HeapCmpFunc cf) {
|
||||
Heap *h;
|
||||
|
||||
/* malloc check ok, small constant allocation */
|
||||
h=malloc(sizeof(Heap));
|
||||
if (!h) {
|
||||
return NULL;
|
||||
}
|
||||
h->heapsize=INITIAL_SIZE;
|
||||
/* malloc check ok, using calloc for overflow */
|
||||
h->heap=calloc(h->heapsize, sizeof(void *));
|
||||
if (!h->heap) {
|
||||
free(h);
|
||||
return NULL;
|
||||
}
|
||||
h->heapcount=0;
|
||||
h->cf=cf;
|
||||
return h;
|
||||
/* malloc check ok, small constant allocation */
|
||||
h = malloc(sizeof(Heap));
|
||||
if (!h) {
|
||||
return NULL;
|
||||
}
|
||||
h->heapsize = INITIAL_SIZE;
|
||||
/* malloc check ok, using calloc for overflow */
|
||||
h->heap = calloc(h->heapsize, sizeof(void *));
|
||||
if (!h->heap) {
|
||||
free(h);
|
||||
return NULL;
|
||||
}
|
||||
h->heapcount = 0;
|
||||
h->cf = cf;
|
||||
return h;
|
||||
}
|
||||
|
|
|
@ -16,12 +16,16 @@
|
|||
|
||||
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 *);
|
||||
int ImagingQuantHeapRemove(Heap *,void **);
|
||||
int ImagingQuantHeapAdd(Heap *,void *);
|
||||
int ImagingQuantHeapTop(Heap *,void **);
|
||||
void
|
||||
ImagingQuantHeapFree(Heap *);
|
||||
int
|
||||
ImagingQuantHeapRemove(Heap *, void **);
|
||||
int
|
||||
ImagingQuantHeapAdd(Heap *, void *);
|
||||
int
|
||||
ImagingQuantHeapTop(Heap *, void **);
|
||||
Heap *ImagingQuantHeapNew(HeapCmpFunc);
|
||||
|
||||
#endif // __QUANTHEAP_H__
|
||||
#endif // __QUANTHEAP_H__
|
||||
|
|
|
@ -31,490 +31,508 @@
|
|||
#include "ImagingUtils.h"
|
||||
#include "QuantOctree.h"
|
||||
|
||||
typedef struct _ColorBucket{
|
||||
/* contains palette index when used for look up cube */
|
||||
uint32_t count;
|
||||
uint64_t r;
|
||||
uint64_t g;
|
||||
uint64_t b;
|
||||
uint64_t a;
|
||||
} *ColorBucket;
|
||||
typedef struct _ColorBucket {
|
||||
/* contains palette index when used for look up cube */
|
||||
uint32_t count;
|
||||
uint64_t r;
|
||||
uint64_t g;
|
||||
uint64_t b;
|
||||
uint64_t a;
|
||||
} * ColorBucket;
|
||||
|
||||
typedef struct _ColorCube{
|
||||
unsigned int rBits, gBits, bBits, aBits;
|
||||
unsigned int rWidth, gWidth, bWidth, aWidth;
|
||||
unsigned int rOffset, gOffset, bOffset, aOffset;
|
||||
typedef struct _ColorCube {
|
||||
unsigned int rBits, gBits, bBits, aBits;
|
||||
unsigned int rWidth, gWidth, bWidth, aWidth;
|
||||
unsigned int rOffset, gOffset, bOffset, aOffset;
|
||||
|
||||
unsigned long size;
|
||||
ColorBucket buckets;
|
||||
} *ColorCube;
|
||||
unsigned long size;
|
||||
ColorBucket buckets;
|
||||
} * ColorCube;
|
||||
|
||||
#define MAX(a, b) (a)>(b) ? (a) : (b)
|
||||
#define MAX(a, b) (a) > (b) ? (a) : (b)
|
||||
|
||||
static ColorCube
|
||||
new_color_cube(int r, int g, int b, int a) {
|
||||
ColorCube cube;
|
||||
ColorCube cube;
|
||||
|
||||
/* malloc check ok, small constant allocation */
|
||||
cube = malloc(sizeof(struct _ColorCube));
|
||||
if (!cube) {
|
||||
return NULL;
|
||||
/* malloc check ok, small constant allocation */
|
||||
cube = malloc(sizeof(struct _ColorCube));
|
||||
if (!cube) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cube->rBits = MAX(r, 0);
|
||||
cube->gBits = MAX(g, 0);
|
||||
cube->bBits = MAX(b, 0);
|
||||
cube->aBits = MAX(a, 0);
|
||||
cube->rBits = MAX(r, 0);
|
||||
cube->gBits = MAX(g, 0);
|
||||
cube->bBits = MAX(b, 0);
|
||||
cube->aBits = MAX(a, 0);
|
||||
|
||||
/* overflow check for size multiplication below */
|
||||
if (cube->rBits + cube->gBits + cube->bBits + cube->aBits > 31) {
|
||||
free(cube);
|
||||
return NULL;
|
||||
}
|
||||
/* overflow check for size multiplication below */
|
||||
if (cube->rBits + cube->gBits + cube->bBits + cube->aBits > 31) {
|
||||
free(cube);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* the width of the cube for each dimension */
|
||||
cube->rWidth = 1<<cube->rBits;
|
||||
cube->gWidth = 1<<cube->gBits;
|
||||
cube->bWidth = 1<<cube->bBits;
|
||||
cube->aWidth = 1<<cube->aBits;
|
||||
/* the width of the cube for each dimension */
|
||||
cube->rWidth = 1 << cube->rBits;
|
||||
cube->gWidth = 1 << cube->gBits;
|
||||
cube->bWidth = 1 << cube->bBits;
|
||||
cube->aWidth = 1 << cube->aBits;
|
||||
|
||||
/* the offsets of each color */
|
||||
/* the offsets of each color */
|
||||
|
||||
cube->rOffset = cube->gBits + cube->bBits + cube->aBits;
|
||||
cube->gOffset = cube->bBits + cube->aBits;
|
||||
cube->bOffset = cube->aBits;
|
||||
cube->aOffset = 0;
|
||||
cube->rOffset = cube->gBits + cube->bBits + cube->aBits;
|
||||
cube->gOffset = cube->bBits + cube->aBits;
|
||||
cube->bOffset = cube->aBits;
|
||||
cube->aOffset = 0;
|
||||
|
||||
/* the number of color buckets */
|
||||
cube->size = cube->rWidth * cube->gWidth * cube->bWidth * cube->aWidth;
|
||||
/* malloc check ok, overflow checked above */
|
||||
cube->buckets = calloc(cube->size, sizeof(struct _ColorBucket));
|
||||
/* the number of color buckets */
|
||||
cube->size = cube->rWidth * cube->gWidth * cube->bWidth * cube->aWidth;
|
||||
/* malloc check ok, overflow checked above */
|
||||
cube->buckets = calloc(cube->size, sizeof(struct _ColorBucket));
|
||||
|
||||
if (!cube->buckets) {
|
||||
free(cube);
|
||||
return NULL;
|
||||
}
|
||||
return cube;
|
||||
if (!cube->buckets) {
|
||||
free(cube);
|
||||
return NULL;
|
||||
}
|
||||
return cube;
|
||||
}
|
||||
|
||||
static void
|
||||
free_color_cube(ColorCube cube) {
|
||||
if (cube != NULL) {
|
||||
free(cube->buckets);
|
||||
free(cube);
|
||||
}
|
||||
if (cube != NULL) {
|
||||
free(cube->buckets);
|
||||
free(cube);
|
||||
}
|
||||
}
|
||||
|
||||
static long
|
||||
color_bucket_offset_pos(const ColorCube cube,
|
||||
unsigned int r, unsigned int g, unsigned int b, unsigned int a)
|
||||
{
|
||||
return r<<cube->rOffset | g<<cube->gOffset | b<<cube->bOffset | a<<cube->aOffset;
|
||||
color_bucket_offset_pos(
|
||||
const ColorCube cube,
|
||||
unsigned int r,
|
||||
unsigned int g,
|
||||
unsigned int b,
|
||||
unsigned int a) {
|
||||
return r << cube->rOffset | g << cube->gOffset | b << cube->bOffset |
|
||||
a << cube->aOffset;
|
||||
}
|
||||
|
||||
static long
|
||||
color_bucket_offset(const ColorCube cube, const Pixel *p) {
|
||||
unsigned int r = p->c.r>>(8-cube->rBits);
|
||||
unsigned int g = p->c.g>>(8-cube->gBits);
|
||||
unsigned int b = p->c.b>>(8-cube->bBits);
|
||||
unsigned int a = p->c.a>>(8-cube->aBits);
|
||||
return color_bucket_offset_pos(cube, r, g, b, a);
|
||||
unsigned int r = p->c.r >> (8 - cube->rBits);
|
||||
unsigned int g = p->c.g >> (8 - cube->gBits);
|
||||
unsigned int b = p->c.b >> (8 - cube->bBits);
|
||||
unsigned int a = p->c.a >> (8 - cube->aBits);
|
||||
return color_bucket_offset_pos(cube, r, g, b, a);
|
||||
}
|
||||
|
||||
static ColorBucket
|
||||
color_bucket_from_cube(const ColorCube cube, const Pixel *p) {
|
||||
unsigned int offset = color_bucket_offset(cube, p);
|
||||
return &cube->buckets[offset];
|
||||
unsigned int offset = color_bucket_offset(cube, p);
|
||||
return &cube->buckets[offset];
|
||||
}
|
||||
|
||||
static void
|
||||
add_color_to_color_cube(const ColorCube cube, const Pixel *p) {
|
||||
ColorBucket bucket = color_bucket_from_cube(cube, p);
|
||||
bucket->count += 1;
|
||||
bucket->r += p->c.r;
|
||||
bucket->g += p->c.g;
|
||||
bucket->b += p->c.b;
|
||||
bucket->a += p->c.a;
|
||||
ColorBucket bucket = color_bucket_from_cube(cube, p);
|
||||
bucket->count += 1;
|
||||
bucket->r += p->c.r;
|
||||
bucket->g += p->c.g;
|
||||
bucket->b += p->c.b;
|
||||
bucket->a += p->c.a;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
count_used_color_buckets(const ColorCube cube) {
|
||||
unsigned long usedBuckets = 0;
|
||||
unsigned long i;
|
||||
for (i=0; i < cube->size; i++) {
|
||||
if (cube->buckets[i].count > 0) {
|
||||
usedBuckets += 1;
|
||||
}
|
||||
}
|
||||
return usedBuckets;
|
||||
unsigned long usedBuckets = 0;
|
||||
unsigned long i;
|
||||
for (i = 0; i < cube->size; i++) {
|
||||
if (cube->buckets[i].count > 0) {
|
||||
usedBuckets += 1;
|
||||
}
|
||||
}
|
||||
return usedBuckets;
|
||||
}
|
||||
|
||||
static void
|
||||
avg_color_from_color_bucket(const ColorBucket bucket, Pixel *dst) {
|
||||
float count = bucket->count;
|
||||
if (count != 0) {
|
||||
dst->c.r = CLIP8((int)(bucket->r / count));
|
||||
dst->c.g = CLIP8((int)(bucket->g / count));
|
||||
dst->c.b = CLIP8((int)(bucket->b / count));
|
||||
dst->c.a = CLIP8((int)(bucket->a / count));
|
||||
} else {
|
||||
dst->c.r = 0;
|
||||
dst->c.g = 0;
|
||||
dst->c.b = 0;
|
||||
dst->c.a = 0;
|
||||
}
|
||||
float count = bucket->count;
|
||||
if (count != 0) {
|
||||
dst->c.r = CLIP8((int)(bucket->r / count));
|
||||
dst->c.g = CLIP8((int)(bucket->g / count));
|
||||
dst->c.b = CLIP8((int)(bucket->b / count));
|
||||
dst->c.a = CLIP8((int)(bucket->a / count));
|
||||
} else {
|
||||
dst->c.r = 0;
|
||||
dst->c.g = 0;
|
||||
dst->c.b = 0;
|
||||
dst->c.a = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
compare_bucket_count(const ColorBucket a, const ColorBucket b) {
|
||||
return b->count - a->count;
|
||||
return b->count - a->count;
|
||||
}
|
||||
|
||||
static ColorBucket
|
||||
create_sorted_color_palette(const ColorCube cube) {
|
||||
ColorBucket buckets;
|
||||
if (cube->size > LONG_MAX / sizeof(struct _ColorBucket)) {
|
||||
return NULL;
|
||||
}
|
||||
/* malloc check ok, calloc + overflow check above for memcpy */
|
||||
buckets = calloc(cube->size, sizeof(struct _ColorBucket));
|
||||
if (!buckets) {
|
||||
return NULL;
|
||||
}
|
||||
memcpy(buckets, cube->buckets, sizeof(struct _ColorBucket)*cube->size);
|
||||
ColorBucket buckets;
|
||||
if (cube->size > LONG_MAX / sizeof(struct _ColorBucket)) {
|
||||
return NULL;
|
||||
}
|
||||
/* malloc check ok, calloc + overflow check above for memcpy */
|
||||
buckets = calloc(cube->size, sizeof(struct _ColorBucket));
|
||||
if (!buckets) {
|
||||
return NULL;
|
||||
}
|
||||
memcpy(buckets, cube->buckets, sizeof(struct _ColorBucket) * cube->size);
|
||||
|
||||
qsort(buckets, cube->size, sizeof(struct _ColorBucket),
|
||||
(int (*)(void const *, void const *))&compare_bucket_count);
|
||||
qsort(
|
||||
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) {
|
||||
dst->count += src->count;
|
||||
dst->r += src->r;
|
||||
dst->g += src->g;
|
||||
dst->b += src->b;
|
||||
dst->a += src->a;
|
||||
void
|
||||
add_bucket_values(ColorBucket src, ColorBucket dst) {
|
||||
dst->count += src->count;
|
||||
dst->r += src->r;
|
||||
dst->g += src->g;
|
||||
dst->b += src->b;
|
||||
dst->a += src->a;
|
||||
}
|
||||
|
||||
/* expand or shrink a given cube to level */
|
||||
static ColorCube copy_color_cube(const ColorCube cube,
|
||||
unsigned int rBits, unsigned int gBits, unsigned int bBits, unsigned int aBits)
|
||||
{
|
||||
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;
|
||||
static ColorCube
|
||||
copy_color_cube(
|
||||
const ColorCube cube,
|
||||
unsigned int rBits,
|
||||
unsigned int gBits,
|
||||
unsigned int bBits,
|
||||
unsigned int aBits) {
|
||||
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);
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
result = new_color_cube(rBits, gBits, bBits, aBits);
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cube->rBits > rBits) {
|
||||
dst_reduce[0] = cube->rBits - result->rBits;
|
||||
width[0] = cube->rWidth;
|
||||
} else {
|
||||
src_reduce[0] = result->rBits - cube->rBits;
|
||||
width[0] = result->rWidth;
|
||||
}
|
||||
if (cube->gBits > gBits) {
|
||||
dst_reduce[1] = cube->gBits - result->gBits;
|
||||
width[1] = cube->gWidth;
|
||||
} else {
|
||||
src_reduce[1] = result->gBits - cube->gBits;
|
||||
width[1] = result->gWidth;
|
||||
}
|
||||
if (cube->bBits > bBits) {
|
||||
dst_reduce[2] = cube->bBits - result->bBits;
|
||||
width[2] = cube->bWidth;
|
||||
} else {
|
||||
src_reduce[2] = result->bBits - cube->bBits;
|
||||
width[2] = result->bWidth;
|
||||
}
|
||||
if (cube->aBits > aBits) {
|
||||
dst_reduce[3] = cube->aBits - result->aBits;
|
||||
width[3] = cube->aWidth;
|
||||
} else {
|
||||
src_reduce[3] = result->aBits - cube->aBits;
|
||||
width[3] = result->aWidth;
|
||||
}
|
||||
if (cube->rBits > rBits) {
|
||||
dst_reduce[0] = cube->rBits - result->rBits;
|
||||
width[0] = cube->rWidth;
|
||||
} else {
|
||||
src_reduce[0] = result->rBits - cube->rBits;
|
||||
width[0] = result->rWidth;
|
||||
}
|
||||
if (cube->gBits > gBits) {
|
||||
dst_reduce[1] = cube->gBits - result->gBits;
|
||||
width[1] = cube->gWidth;
|
||||
} else {
|
||||
src_reduce[1] = result->gBits - cube->gBits;
|
||||
width[1] = result->gWidth;
|
||||
}
|
||||
if (cube->bBits > bBits) {
|
||||
dst_reduce[2] = cube->bBits - result->bBits;
|
||||
width[2] = cube->bWidth;
|
||||
} else {
|
||||
src_reduce[2] = result->bBits - cube->bBits;
|
||||
width[2] = result->bWidth;
|
||||
}
|
||||
if (cube->aBits > aBits) {
|
||||
dst_reduce[3] = cube->aBits - result->aBits;
|
||||
width[3] = cube->aWidth;
|
||||
} else {
|
||||
src_reduce[3] = result->aBits - cube->aBits;
|
||||
width[3] = result->aWidth;
|
||||
}
|
||||
|
||||
for (r=0; r<width[0]; r++) {
|
||||
for (g=0; g<width[1]; g++) {
|
||||
for (b=0; b<width[2]; b++) {
|
||||
for (a=0; a<width[3]; a++) {
|
||||
src_pos = color_bucket_offset_pos(cube,
|
||||
r>>src_reduce[0],
|
||||
g>>src_reduce[1],
|
||||
b>>src_reduce[2],
|
||||
a>>src_reduce[3]);
|
||||
dst_pos = color_bucket_offset_pos(result,
|
||||
r>>dst_reduce[0],
|
||||
g>>dst_reduce[1],
|
||||
b>>dst_reduce[2],
|
||||
a>>dst_reduce[3]);
|
||||
add_bucket_values(
|
||||
&cube->buckets[src_pos],
|
||||
&result->buckets[dst_pos]
|
||||
);
|
||||
for (r = 0; r < width[0]; r++) {
|
||||
for (g = 0; g < width[1]; g++) {
|
||||
for (b = 0; b < width[2]; b++) {
|
||||
for (a = 0; a < width[3]; a++) {
|
||||
src_pos = color_bucket_offset_pos(
|
||||
cube,
|
||||
r >> src_reduce[0],
|
||||
g >> src_reduce[1],
|
||||
b >> src_reduce[2],
|
||||
a >> src_reduce[3]);
|
||||
dst_pos = color_bucket_offset_pos(
|
||||
result,
|
||||
r >> dst_reduce[0],
|
||||
g >> dst_reduce[1],
|
||||
b >> dst_reduce[2],
|
||||
a >> dst_reduce[3]);
|
||||
add_bucket_values(
|
||||
&cube->buckets[src_pos], &result->buckets[dst_pos]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
subtract_color_buckets(ColorCube cube, ColorBucket buckets, long nBuckets) {
|
||||
ColorBucket minuend, subtrahend;
|
||||
long i;
|
||||
Pixel p;
|
||||
for (i=0; i<nBuckets; i++) {
|
||||
subtrahend = &buckets[i];
|
||||
ColorBucket minuend, subtrahend;
|
||||
long i;
|
||||
Pixel p;
|
||||
for (i = 0; i < nBuckets; i++) {
|
||||
subtrahend = &buckets[i];
|
||||
|
||||
// If the subtrahend contains no buckets, there is nothing to subtract.
|
||||
if (subtrahend->count == 0) {
|
||||
continue;
|
||||
}
|
||||
// If the subtrahend contains no buckets, there is nothing to subtract.
|
||||
if (subtrahend->count == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
avg_color_from_color_bucket(subtrahend, &p);
|
||||
minuend = color_bucket_from_cube(cube, &p);
|
||||
minuend->count -= subtrahend->count;
|
||||
minuend->r -= subtrahend->r;
|
||||
minuend->g -= subtrahend->g;
|
||||
minuend->b -= subtrahend->b;
|
||||
minuend->a -= subtrahend->a;
|
||||
}
|
||||
avg_color_from_color_bucket(subtrahend, &p);
|
||||
minuend = color_bucket_from_cube(cube, &p);
|
||||
minuend->count -= subtrahend->count;
|
||||
minuend->r -= subtrahend->r;
|
||||
minuend->g -= subtrahend->g;
|
||||
minuend->b -= subtrahend->b;
|
||||
minuend->a -= subtrahend->a;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_lookup_value(const ColorCube cube, const Pixel *p, long value) {
|
||||
ColorBucket bucket = color_bucket_from_cube(cube, p);
|
||||
bucket->count = value;
|
||||
ColorBucket bucket = color_bucket_from_cube(cube, p);
|
||||
bucket->count = value;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
lookup_color(const ColorCube cube, const Pixel *p) {
|
||||
ColorBucket bucket = color_bucket_from_cube(cube, p);
|
||||
return bucket->count;
|
||||
ColorBucket bucket = color_bucket_from_cube(cube, p);
|
||||
return bucket->count;
|
||||
}
|
||||
|
||||
void add_lookup_buckets(ColorCube cube, ColorBucket palette, long nColors, long offset) {
|
||||
long i;
|
||||
Pixel p;
|
||||
for (i=offset; i<offset+nColors; i++) {
|
||||
avg_color_from_color_bucket(&palette[i], &p);
|
||||
set_lookup_value(cube, &p, i);
|
||||
}
|
||||
void
|
||||
add_lookup_buckets(ColorCube cube, ColorBucket palette, long nColors, long offset) {
|
||||
long i;
|
||||
Pixel p;
|
||||
for (i = offset; i < offset + nColors; i++) {
|
||||
avg_color_from_color_bucket(&palette[i], &p);
|
||||
set_lookup_value(cube, &p, i);
|
||||
}
|
||||
}
|
||||
|
||||
ColorBucket
|
||||
combined_palette(ColorBucket bucketsA, unsigned long nBucketsA, ColorBucket bucketsB, unsigned long nBucketsB) {
|
||||
ColorBucket result;
|
||||
if (nBucketsA > LONG_MAX - nBucketsB ||
|
||||
(nBucketsA+nBucketsB) > LONG_MAX / sizeof(struct _ColorBucket)) {
|
||||
return NULL;
|
||||
}
|
||||
/* malloc check ok, overflow check above */
|
||||
result = calloc(nBucketsA + nBucketsB, sizeof(struct _ColorBucket));
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
memcpy(result, bucketsA, sizeof(struct _ColorBucket) * nBucketsA);
|
||||
memcpy(&result[nBucketsA], bucketsB, sizeof(struct _ColorBucket) * nBucketsB);
|
||||
return result;
|
||||
combined_palette(
|
||||
ColorBucket bucketsA,
|
||||
unsigned long nBucketsA,
|
||||
ColorBucket bucketsB,
|
||||
unsigned long nBucketsB) {
|
||||
ColorBucket result;
|
||||
if (nBucketsA > LONG_MAX - nBucketsB ||
|
||||
(nBucketsA + nBucketsB) > LONG_MAX / sizeof(struct _ColorBucket)) {
|
||||
return NULL;
|
||||
}
|
||||
/* malloc check ok, overflow check above */
|
||||
result = calloc(nBucketsA + nBucketsB, sizeof(struct _ColorBucket));
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
memcpy(result, bucketsA, sizeof(struct _ColorBucket) * nBucketsA);
|
||||
memcpy(&result[nBucketsA], bucketsB, sizeof(struct _ColorBucket) * nBucketsB);
|
||||
return result;
|
||||
}
|
||||
|
||||
static Pixel *
|
||||
create_palette_array(const ColorBucket palette, unsigned int paletteLength) {
|
||||
Pixel *paletteArray;
|
||||
unsigned int i;
|
||||
Pixel *paletteArray;
|
||||
unsigned int i;
|
||||
|
||||
/* malloc check ok, calloc for overflow */
|
||||
paletteArray = calloc(paletteLength, sizeof(Pixel));
|
||||
if (!paletteArray) {
|
||||
return NULL;
|
||||
}
|
||||
/* malloc check ok, calloc for overflow */
|
||||
paletteArray = calloc(paletteLength, sizeof(Pixel));
|
||||
if (!paletteArray) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i=0; i<paletteLength; i++) {
|
||||
avg_color_from_color_bucket(&palette[i], &paletteArray[i]);
|
||||
}
|
||||
return paletteArray;
|
||||
for (i = 0; i < paletteLength; i++) {
|
||||
avg_color_from_color_bucket(&palette[i], &paletteArray[i]);
|
||||
}
|
||||
return paletteArray;
|
||||
}
|
||||
|
||||
static void
|
||||
map_image_pixels(const Pixel *pixelData,
|
||||
uint32_t nPixels,
|
||||
const ColorCube lookupCube,
|
||||
uint32_t *pixelArray)
|
||||
{
|
||||
long i;
|
||||
for (i=0; i<nPixels; i++) {
|
||||
pixelArray[i] = lookup_color(lookupCube, &pixelData[i]);
|
||||
}
|
||||
map_image_pixels(
|
||||
const Pixel *pixelData,
|
||||
uint32_t nPixels,
|
||||
const ColorCube lookupCube,
|
||||
uint32_t *pixelArray) {
|
||||
long i;
|
||||
for (i = 0; i < nPixels; 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};
|
||||
|
||||
int quantize_octree(Pixel *pixelData,
|
||||
uint32_t nPixels,
|
||||
uint32_t nQuantPixels,
|
||||
Pixel **palette,
|
||||
uint32_t *paletteLength,
|
||||
uint32_t **quantizedPixels,
|
||||
int withAlpha)
|
||||
{
|
||||
ColorCube fineCube = NULL;
|
||||
ColorCube coarseCube = NULL;
|
||||
ColorCube lookupCube = NULL;
|
||||
ColorCube coarseLookupCube = NULL;
|
||||
ColorBucket paletteBucketsCoarse = NULL;
|
||||
ColorBucket paletteBucketsFine = NULL;
|
||||
ColorBucket paletteBuckets = NULL;
|
||||
uint32_t *qp = NULL;
|
||||
long i;
|
||||
unsigned long nCoarseColors, nFineColors, nAlreadySubtracted;
|
||||
const unsigned int *cubeBits;
|
||||
int
|
||||
quantize_octree(
|
||||
Pixel *pixelData,
|
||||
uint32_t nPixels,
|
||||
uint32_t nQuantPixels,
|
||||
Pixel **palette,
|
||||
uint32_t *paletteLength,
|
||||
uint32_t **quantizedPixels,
|
||||
int withAlpha) {
|
||||
ColorCube fineCube = NULL;
|
||||
ColorCube coarseCube = NULL;
|
||||
ColorCube lookupCube = NULL;
|
||||
ColorCube coarseLookupCube = NULL;
|
||||
ColorBucket paletteBucketsCoarse = NULL;
|
||||
ColorBucket paletteBucketsFine = NULL;
|
||||
ColorBucket paletteBuckets = NULL;
|
||||
uint32_t *qp = NULL;
|
||||
long i;
|
||||
unsigned long nCoarseColors, nFineColors, nAlreadySubtracted;
|
||||
const unsigned int *cubeBits;
|
||||
|
||||
if (withAlpha) {
|
||||
cubeBits = CUBE_LEVELS_ALPHA;
|
||||
}
|
||||
else {
|
||||
cubeBits = CUBE_LEVELS;
|
||||
}
|
||||
if (withAlpha) {
|
||||
cubeBits = CUBE_LEVELS_ALPHA;
|
||||
} else {
|
||||
cubeBits = CUBE_LEVELS;
|
||||
}
|
||||
|
||||
/*
|
||||
Create two color cubes, one fine grained with 8x16x8=1024
|
||||
colors buckets and a coarse with 4x4x4=64 color buckets.
|
||||
The coarse one guarantees that there are color buckets available for
|
||||
the whole color range (assuming nQuantPixels > 64).
|
||||
/*
|
||||
Create two color cubes, one fine grained with 8x16x8=1024
|
||||
colors buckets and a coarse with 4x4x4=64 color buckets.
|
||||
The coarse one guarantees that there are color buckets available for
|
||||
the whole color range (assuming nQuantPixels > 64).
|
||||
|
||||
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.
|
||||
The average of all colors within one bucket is used as the actual
|
||||
color for that bucket.
|
||||
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.
|
||||
The average of all colors within one bucket is used as the actual
|
||||
color for that bucket.
|
||||
|
||||
For images with alpha the cubes gets a forth dimension,
|
||||
8x16x8x8 and 4x4x4x4.
|
||||
*/
|
||||
For images with alpha the cubes gets a forth dimension,
|
||||
8x16x8x8 and 4x4x4x4.
|
||||
*/
|
||||
|
||||
/* create fine cube */
|
||||
fineCube = new_color_cube(cubeBits[0], cubeBits[1],
|
||||
cubeBits[2], cubeBits[3]);
|
||||
if (!fineCube) {
|
||||
goto error;
|
||||
}
|
||||
for (i=0; i<nPixels; i++) {
|
||||
add_color_to_color_cube(fineCube, &pixelData[i]);
|
||||
}
|
||||
/* create fine cube */
|
||||
fineCube = new_color_cube(cubeBits[0], cubeBits[1], cubeBits[2], cubeBits[3]);
|
||||
if (!fineCube) {
|
||||
goto error;
|
||||
}
|
||||
for (i = 0; i < nPixels; i++) {
|
||||
add_color_to_color_cube(fineCube, &pixelData[i]);
|
||||
}
|
||||
|
||||
/* create coarse cube */
|
||||
coarseCube = copy_color_cube(fineCube, cubeBits[4], cubeBits[5],
|
||||
cubeBits[6], cubeBits[7]);
|
||||
if (!coarseCube) {
|
||||
goto error;
|
||||
}
|
||||
nCoarseColors = count_used_color_buckets(coarseCube);
|
||||
/* create coarse cube */
|
||||
coarseCube =
|
||||
copy_color_cube(fineCube, cubeBits[4], cubeBits[5], cubeBits[6], cubeBits[7]);
|
||||
if (!coarseCube) {
|
||||
goto error;
|
||||
}
|
||||
nCoarseColors = count_used_color_buckets(coarseCube);
|
||||
|
||||
/* limit to nQuantPixels */
|
||||
if (nCoarseColors > nQuantPixels) {
|
||||
nCoarseColors = nQuantPixels;
|
||||
}
|
||||
/* limit to nQuantPixels */
|
||||
if (nCoarseColors > nQuantPixels) {
|
||||
nCoarseColors = nQuantPixels;
|
||||
}
|
||||
|
||||
/* how many space do we have in our palette for fine colors? */
|
||||
nFineColors = nQuantPixels - nCoarseColors;
|
||||
/* how many space do we have in our palette for fine colors? */
|
||||
nFineColors = nQuantPixels - nCoarseColors;
|
||||
|
||||
/* create fine color palette */
|
||||
paletteBucketsFine = create_sorted_color_palette(fineCube);
|
||||
if (!paletteBucketsFine) {
|
||||
goto error;
|
||||
}
|
||||
/* create fine color palette */
|
||||
paletteBucketsFine = create_sorted_color_palette(fineCube);
|
||||
if (!paletteBucketsFine) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* remove the used fine colors from the coarse cube */
|
||||
subtract_color_buckets(coarseCube, paletteBucketsFine, nFineColors);
|
||||
/* remove the used fine colors from the coarse cube */
|
||||
subtract_color_buckets(coarseCube, paletteBucketsFine, nFineColors);
|
||||
|
||||
/* did the subtraction cleared one or more coarse bucket? */
|
||||
while (nCoarseColors > count_used_color_buckets(coarseCube)) {
|
||||
/* then we can use the free buckets for fine colors */
|
||||
nAlreadySubtracted = nFineColors;
|
||||
nCoarseColors = count_used_color_buckets(coarseCube);
|
||||
nFineColors = nQuantPixels - nCoarseColors;
|
||||
subtract_color_buckets(coarseCube, &paletteBucketsFine[nAlreadySubtracted],
|
||||
nFineColors-nAlreadySubtracted);
|
||||
}
|
||||
/* did the subtraction cleared one or more coarse bucket? */
|
||||
while (nCoarseColors > count_used_color_buckets(coarseCube)) {
|
||||
/* then we can use the free buckets for fine colors */
|
||||
nAlreadySubtracted = nFineColors;
|
||||
nCoarseColors = count_used_color_buckets(coarseCube);
|
||||
nFineColors = nQuantPixels - nCoarseColors;
|
||||
subtract_color_buckets(
|
||||
coarseCube,
|
||||
&paletteBucketsFine[nAlreadySubtracted],
|
||||
nFineColors - nAlreadySubtracted);
|
||||
}
|
||||
|
||||
/* create our palette buckets with fine and coarse combined */
|
||||
paletteBucketsCoarse = create_sorted_color_palette(coarseCube);
|
||||
if (!paletteBucketsCoarse) {
|
||||
goto error;
|
||||
}
|
||||
paletteBuckets = combined_palette(paletteBucketsCoarse, nCoarseColors,
|
||||
paletteBucketsFine, nFineColors);
|
||||
/* create our palette buckets with fine and coarse combined */
|
||||
paletteBucketsCoarse = create_sorted_color_palette(coarseCube);
|
||||
if (!paletteBucketsCoarse) {
|
||||
goto error;
|
||||
}
|
||||
paletteBuckets = combined_palette(
|
||||
paletteBucketsCoarse, nCoarseColors, paletteBucketsFine, nFineColors);
|
||||
|
||||
free(paletteBucketsFine);
|
||||
paletteBucketsFine = NULL;
|
||||
free(paletteBucketsCoarse);
|
||||
paletteBucketsCoarse = NULL;
|
||||
if (!paletteBuckets) {
|
||||
goto error;
|
||||
}
|
||||
free(paletteBucketsFine);
|
||||
paletteBucketsFine = NULL;
|
||||
free(paletteBucketsCoarse);
|
||||
paletteBucketsCoarse = NULL;
|
||||
if (!paletteBuckets) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* add all coarse colors to our coarse lookup cube. */
|
||||
coarseLookupCube = new_color_cube(cubeBits[4], cubeBits[5],
|
||||
cubeBits[6], cubeBits[7]);
|
||||
if (!coarseLookupCube) {
|
||||
goto error;
|
||||
}
|
||||
add_lookup_buckets(coarseLookupCube, paletteBuckets, nCoarseColors, 0);
|
||||
/* add all coarse colors to our coarse lookup cube. */
|
||||
coarseLookupCube =
|
||||
new_color_cube(cubeBits[4], cubeBits[5], cubeBits[6], cubeBits[7]);
|
||||
if (!coarseLookupCube) {
|
||||
goto error;
|
||||
}
|
||||
add_lookup_buckets(coarseLookupCube, paletteBuckets, nCoarseColors, 0);
|
||||
|
||||
/* expand coarse cube (64) to larger fine cube (4k). the value of each
|
||||
coarse bucket is then present in the according 64 fine buckets. */
|
||||
lookupCube = copy_color_cube(coarseLookupCube, cubeBits[0], cubeBits[1],
|
||||
cubeBits[2], cubeBits[3]);
|
||||
if (!lookupCube) {
|
||||
goto error;
|
||||
}
|
||||
/* expand coarse cube (64) to larger fine cube (4k). the value of each
|
||||
coarse bucket is then present in the according 64 fine buckets. */
|
||||
lookupCube = copy_color_cube(
|
||||
coarseLookupCube, cubeBits[0], cubeBits[1], cubeBits[2], cubeBits[3]);
|
||||
if (!lookupCube) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* add fine colors to the lookup cube */
|
||||
add_lookup_buckets(lookupCube, paletteBuckets, nFineColors, nCoarseColors);
|
||||
/* add fine colors to the lookup cube */
|
||||
add_lookup_buckets(lookupCube, paletteBuckets, nFineColors, nCoarseColors);
|
||||
|
||||
/* create result pixels and map palette indices */
|
||||
/* malloc check ok, calloc for overflow */
|
||||
qp = calloc(nPixels, sizeof(Pixel));
|
||||
if (!qp) {
|
||||
goto error;
|
||||
}
|
||||
map_image_pixels(pixelData, nPixels, lookupCube, qp);
|
||||
/* create result pixels and map palette indices */
|
||||
/* malloc check ok, calloc for overflow */
|
||||
qp = calloc(nPixels, sizeof(Pixel));
|
||||
if (!qp) {
|
||||
goto error;
|
||||
}
|
||||
map_image_pixels(pixelData, nPixels, lookupCube, qp);
|
||||
|
||||
/* convert palette buckets to RGB pixel palette */
|
||||
*palette = create_palette_array(paletteBuckets, nQuantPixels);
|
||||
if (!(*palette)) {
|
||||
goto error;
|
||||
}
|
||||
/* convert palette buckets to RGB pixel palette */
|
||||
*palette = create_palette_array(paletteBuckets, nQuantPixels);
|
||||
if (!(*palette)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
*quantizedPixels = qp;
|
||||
*paletteLength = nQuantPixels;
|
||||
*quantizedPixels = qp;
|
||||
*paletteLength = nQuantPixels;
|
||||
|
||||
free_color_cube(coarseCube);
|
||||
free_color_cube(fineCube);
|
||||
free_color_cube(lookupCube);
|
||||
free_color_cube(coarseLookupCube);
|
||||
free(paletteBuckets);
|
||||
return 1;
|
||||
free_color_cube(coarseCube);
|
||||
free_color_cube(fineCube);
|
||||
free_color_cube(lookupCube);
|
||||
free_color_cube(coarseLookupCube);
|
||||
free(paletteBuckets);
|
||||
return 1;
|
||||
|
||||
error:
|
||||
/* everything is initialized to NULL
|
||||
so we are safe to call free */
|
||||
free(qp);
|
||||
free_color_cube(lookupCube);
|
||||
free_color_cube(coarseLookupCube);
|
||||
free(paletteBuckets);
|
||||
free(paletteBucketsCoarse);
|
||||
free(paletteBucketsFine);
|
||||
free_color_cube(coarseCube);
|
||||
free_color_cube(fineCube);
|
||||
return 0;
|
||||
/* everything is initialized to NULL
|
||||
so we are safe to call free */
|
||||
free(qp);
|
||||
free_color_cube(lookupCube);
|
||||
free_color_cube(coarseLookupCube);
|
||||
free(paletteBuckets);
|
||||
free(paletteBucketsCoarse);
|
||||
free(paletteBucketsFine);
|
||||
free_color_cube(coarseCube);
|
||||
free_color_cube(fineCube);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3,12 +3,7 @@
|
|||
|
||||
#include "QuantTypes.h"
|
||||
|
||||
int quantize_octree(Pixel *,
|
||||
uint32_t,
|
||||
uint32_t,
|
||||
Pixel **,
|
||||
uint32_t *,
|
||||
uint32_t **,
|
||||
int);
|
||||
int
|
||||
quantize_octree(Pixel *, uint32_t, uint32_t, Pixel **, uint32_t *, uint32_t **, int);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -26,8 +26,7 @@ quantize_pngquant(
|
|||
Pixel **palette,
|
||||
uint32_t *paletteLength,
|
||||
uint32_t **quantizedPixels,
|
||||
int withAlpha)
|
||||
{
|
||||
int withAlpha) {
|
||||
int result = 0;
|
||||
liq_image *image = NULL;
|
||||
liq_attr *attr = NULL;
|
||||
|
@ -41,23 +40,24 @@ quantize_pngquant(
|
|||
|
||||
/* configure pngquant */
|
||||
attr = liq_attr_create();
|
||||
if (!attr) { goto err; }
|
||||
if (!attr) {
|
||||
goto err;
|
||||
}
|
||||
if (quantPixels) {
|
||||
liq_set_max_colors(attr, quantPixels);
|
||||
}
|
||||
|
||||
/* prepare input image */
|
||||
image = liq_image_create_rgba(
|
||||
attr,
|
||||
pixelData,
|
||||
width,
|
||||
height,
|
||||
0.45455 /* gamma */);
|
||||
if (!image) { goto err; }
|
||||
image = liq_image_create_rgba(attr, pixelData, width, height, 0.45455 /* gamma */);
|
||||
if (!image) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* quantize the image */
|
||||
remap = liq_quantize_image(attr, image);
|
||||
if (!remap) { goto err; }
|
||||
if (!remap) {
|
||||
goto err;
|
||||
}
|
||||
liq_set_output_gamma(remap, 0.45455);
|
||||
liq_set_dithering_level(remap, 1);
|
||||
|
||||
|
@ -65,7 +65,9 @@ quantize_pngquant(
|
|||
const liq_palette *l_palette = liq_get_palette(remap);
|
||||
*paletteLength = 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++) {
|
||||
(*palette)[i].c.b = l_palette->entries[i].b;
|
||||
(*palette)[i].c.g = l_palette->entries[i].g;
|
||||
|
@ -75,9 +77,13 @@ quantize_pngquant(
|
|||
|
||||
/* write output pixels (pngquant uses char array) */
|
||||
charMatrix = malloc(width * height);
|
||||
if (!charMatrix) { goto err; }
|
||||
charMatrixRows = malloc(height * sizeof(unsigned char*));
|
||||
if (!charMatrixRows) { goto err; }
|
||||
if (!charMatrix) {
|
||||
goto err;
|
||||
}
|
||||
charMatrixRows = malloc(height * sizeof(unsigned char *));
|
||||
if (!charMatrixRows) {
|
||||
goto err;
|
||||
}
|
||||
for (y = 0; y < height; y++) {
|
||||
charMatrixRows[y] = &charMatrix[y * width];
|
||||
}
|
||||
|
@ -87,7 +93,9 @@ quantize_pngquant(
|
|||
|
||||
/* transcribe output pixels (pillow uses uint32_t array) */
|
||||
*quantizedPixels = malloc(sizeof(uint32_t) * width * height);
|
||||
if (!*quantizedPixels) { goto err; }
|
||||
if (!*quantizedPixels) {
|
||||
goto err;
|
||||
}
|
||||
for (i = 0; i < width * height; i++) {
|
||||
(*quantizedPixels)[i] = charMatrix[i];
|
||||
}
|
||||
|
@ -106,16 +114,15 @@ err:
|
|||
}
|
||||
free(charMatrix);
|
||||
free(charMatrixRows);
|
||||
if (!result) {
|
||||
if (!result) {
|
||||
free(*quantizedPixels);
|
||||
free(*palette);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const char*
|
||||
ImagingImageQuantVersion(void)
|
||||
{
|
||||
const char *
|
||||
ImagingImageQuantVersion(void) {
|
||||
static char version[20];
|
||||
int number = liq_version();
|
||||
sprintf(version, "%d.%d.%d", number / 10000, (number / 100) % 100, number % 100);
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
#include "QuantTypes.h"
|
||||
|
||||
int quantize_pngquant(Pixel *,
|
||||
int
|
||||
quantize_pngquant(
|
||||
Pixel *,
|
||||
unsigned int,
|
||||
unsigned int,
|
||||
uint32_t,
|
||||
|
|
|
@ -20,13 +20,13 @@ typedef unsigned __int64 uint64_t;
|
|||
#endif
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
unsigned char r,g,b,a;
|
||||
} c;
|
||||
struct {
|
||||
unsigned char v[4];
|
||||
} a;
|
||||
uint32_t v;
|
||||
struct {
|
||||
unsigned char r, g, b, a;
|
||||
} c;
|
||||
struct {
|
||||
unsigned char v[4];
|
||||
} a;
|
||||
uint32_t v;
|
||||
} Pixel;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,94 +17,98 @@
|
|||
/* Fast rank algorithm (due to Wirth), based on public domain code
|
||||
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)\
|
||||
static type Rank##type(type a[], int n, int k)\
|
||||
{\
|
||||
register int i, j, l, m;\
|
||||
register type x;\
|
||||
l = 0; m = n-1;\
|
||||
while (l < m) {\
|
||||
x = a[k];\
|
||||
i = l;\
|
||||
j = m;\
|
||||
do {\
|
||||
while (a[i] < x) {\
|
||||
i++;\
|
||||
}\
|
||||
while (x < a[j]) {\
|
||||
j--;\
|
||||
}\
|
||||
if (i <= j) {\
|
||||
SWAP(type, a[i], a[j]);\
|
||||
i++; j--;\
|
||||
}\
|
||||
} while (i <= j);\
|
||||
if (j < k) {\
|
||||
l = i;\
|
||||
}\
|
||||
if (k < i) {\
|
||||
m = j;\
|
||||
}\
|
||||
}\
|
||||
return a[k];\
|
||||
}
|
||||
#define MakeRankFunction(type) \
|
||||
static type Rank##type(type a[], int n, int k) { \
|
||||
register int i, j, l, m; \
|
||||
register type x; \
|
||||
l = 0; \
|
||||
m = n - 1; \
|
||||
while (l < m) { \
|
||||
x = a[k]; \
|
||||
i = l; \
|
||||
j = m; \
|
||||
do { \
|
||||
while (a[i] < x) { \
|
||||
i++; \
|
||||
} \
|
||||
while (x < a[j]) { \
|
||||
j--; \
|
||||
} \
|
||||
if (i <= j) { \
|
||||
SWAP(type, a[i], a[j]); \
|
||||
i++; \
|
||||
j--; \
|
||||
} \
|
||||
} while (i <= j); \
|
||||
if (j < k) { \
|
||||
l = i; \
|
||||
} \
|
||||
if (k < i) { \
|
||||
m = j; \
|
||||
} \
|
||||
} \
|
||||
return a[k]; \
|
||||
}
|
||||
|
||||
MakeRankFunction(UINT8)
|
||||
MakeRankFunction(INT32)
|
||||
MakeRankFunction(FLOAT32)
|
||||
MakeRankFunction(UINT8) MakeRankFunction(INT32) MakeRankFunction(FLOAT32)
|
||||
|
||||
Imaging
|
||||
ImagingRankFilter(Imaging im, int size, int rank)
|
||||
{
|
||||
Imaging ImagingRankFilter(Imaging im, int size, int rank) {
|
||||
Imaging imOut = NULL;
|
||||
int x, y;
|
||||
int i, margin, size2;
|
||||
|
||||
if (!im || im->bands != 1 || im->type == IMAGING_TYPE_SPECIAL) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
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 */
|
||||
if (size > INT_MAX / size ||
|
||||
size > INT_MAX / (size * (int)sizeof(FLOAT32))) {
|
||||
return (Imaging) ImagingError_ValueError("filter size too large");
|
||||
if (size > INT_MAX / size || size > INT_MAX / (size * (int)sizeof(FLOAT32))) {
|
||||
return (Imaging)ImagingError_ValueError("filter size too large");
|
||||
}
|
||||
|
||||
size2 = size * size;
|
||||
margin = (size-1) / 2;
|
||||
margin = (size - 1) / 2;
|
||||
|
||||
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) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* malloc check ok, checked above */
|
||||
#define RANK_BODY(type) do {\
|
||||
type* buf = malloc(size2 * sizeof(type));\
|
||||
if (!buf) {\
|
||||
goto nomemory;\
|
||||
}\
|
||||
for (y = 0; y < imOut->ysize; y++) {\
|
||||
for (x = 0; x < imOut->xsize; x++) {\
|
||||
for (i = 0; i < size; i++) {\
|
||||
memcpy(buf + i*size, &IMAGING_PIXEL_##type(im, x, y+i),\
|
||||
size * sizeof(type));\
|
||||
}\
|
||||
IMAGING_PIXEL_##type(imOut, x, y) = Rank##type(buf, size2, rank);\
|
||||
}\
|
||||
}\
|
||||
free(buf); \
|
||||
} while (0)
|
||||
#define RANK_BODY(type) \
|
||||
do { \
|
||||
type *buf = malloc(size2 * sizeof(type)); \
|
||||
if (!buf) { \
|
||||
goto nomemory; \
|
||||
} \
|
||||
for (y = 0; y < imOut->ysize; y++) { \
|
||||
for (x = 0; x < imOut->xsize; x++) { \
|
||||
for (i = 0; i < size; i++) { \
|
||||
memcpy( \
|
||||
buf + i * size, \
|
||||
&IMAGING_PIXEL_##type(im, x, y + i), \
|
||||
size * sizeof(type)); \
|
||||
} \
|
||||
IMAGING_PIXEL_##type(imOut, x, y) = Rank##type(buf, size2, rank); \
|
||||
} \
|
||||
} \
|
||||
free(buf); \
|
||||
} while (0)
|
||||
|
||||
if (im->image8) {
|
||||
RANK_BODY(UINT8);
|
||||
|
@ -115,7 +119,7 @@ ImagingRankFilter(Imaging im, int size, int rank)
|
|||
} else {
|
||||
/* safety net (we shouldn't end up here) */
|
||||
ImagingDelete(imOut);
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
|
||||
ImagingCopyPalette(imOut, im);
|
||||
|
@ -124,5 +128,5 @@ ImagingRankFilter(Imaging im, int size, int rank)
|
|||
|
||||
nomemory:
|
||||
ImagingDelete(imOut);
|
||||
return (Imaging) ImagingError_MemoryError();
|
||||
return (Imaging)ImagingError_MemoryError();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* Raw.h */
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* CONFIGURATION */
|
||||
|
||||
/* Distance between lines (0=no padding) */
|
||||
|
|
|
@ -13,22 +13,18 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#include "Raw.h"
|
||||
|
||||
|
||||
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 };
|
||||
RAWSTATE* rawstate = state->context;
|
||||
RAWSTATE *rawstate = state->context;
|
||||
|
||||
UINT8* ptr;
|
||||
UINT8 *ptr;
|
||||
|
||||
if (state->state == 0) {
|
||||
|
||||
/* Initialize context variables */
|
||||
|
||||
/* 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 */
|
||||
if (state->ystep < 0) {
|
||||
state->y = state->ysize-1;
|
||||
state->y = state->ysize - 1;
|
||||
state->ystep = -1;
|
||||
} else {
|
||||
state->ystep = 1;
|
||||
}
|
||||
|
||||
state->state = LINE;
|
||||
|
||||
}
|
||||
|
||||
ptr = buf;
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (state->state == SKIP) {
|
||||
|
||||
/* Skip padding between lines */
|
||||
|
||||
if (bytes < rawstate->skip) {
|
||||
|
@ -71,7 +64,6 @@ ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
bytes -= rawstate->skip;
|
||||
|
||||
state->state = LINE;
|
||||
|
||||
}
|
||||
|
||||
if (bytes < state->bytes) {
|
||||
|
@ -79,8 +71,10 @@ ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
}
|
||||
|
||||
/* Unpack data */
|
||||
state->shuffle((UINT8*) im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize, ptr, state->xsize);
|
||||
state->shuffle(
|
||||
(UINT8 *)im->image[state->y + state->yoff] + state->xoff * im->pixelsize,
|
||||
ptr,
|
||||
state->xsize);
|
||||
|
||||
ptr += state->bytes;
|
||||
bytes -= state->bytes;
|
||||
|
@ -93,7 +87,5 @@ ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
}
|
||||
|
||||
state->state = SKIP;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,16 +17,13 @@
|
|||
*
|
||||
* See the README file for information on usage and redistribution. */
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
int
|
||||
ImagingRawEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||
{
|
||||
UINT8* ptr;
|
||||
ImagingRawEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
|
||||
UINT8 *ptr;
|
||||
|
||||
if (!state->state) {
|
||||
|
||||
/* The "count" field holds the stride, if specified. Fix
|
||||
things up so "bytes" is the full size, and "count" the
|
||||
packed size */
|
||||
|
@ -48,14 +45,13 @@ ImagingRawEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
/* The "ystep" field specifies the orientation */
|
||||
|
||||
if (state->ystep < 0) {
|
||||
state->y = state->ysize-1;
|
||||
state->y = state->ysize - 1;
|
||||
state->ystep = -1;
|
||||
} else {
|
||||
state->ystep = 1;
|
||||
}
|
||||
|
||||
state->state = 1;
|
||||
|
||||
}
|
||||
|
||||
if (bytes < state->bytes) {
|
||||
|
@ -66,9 +62,10 @@ ImagingRawEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
ptr = buf;
|
||||
|
||||
while (bytes >= state->bytes) {
|
||||
|
||||
state->shuffle(ptr, (UINT8*) im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize, state->xsize);
|
||||
state->shuffle(
|
||||
ptr,
|
||||
(UINT8 *)im->image[state->y + state->yoff] + state->xoff * im->pixelsize,
|
||||
state->xsize);
|
||||
|
||||
if (state->bytes > state->count) {
|
||||
/* zero-pad the buffer, if necessary */
|
||||
|
@ -84,9 +81,7 @@ ImagingRawEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
state->errcode = IMAGING_CODEC_END;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ptr - buf;
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,36 +2,34 @@
|
|||
|
||||
#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 {
|
||||
double (*filter)(double x);
|
||||
double support;
|
||||
};
|
||||
|
||||
static inline double box_filter(double x)
|
||||
{
|
||||
static inline double
|
||||
box_filter(double x) {
|
||||
if (x > -0.5 && x <= 0.5) {
|
||||
return 1.0;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
static inline double bilinear_filter(double x)
|
||||
{
|
||||
static inline double
|
||||
bilinear_filter(double x) {
|
||||
if (x < 0.0) {
|
||||
x = -x;
|
||||
}
|
||||
if (x < 1.0) {
|
||||
return 1.0-x;
|
||||
return 1.0 - x;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
static inline double hamming_filter(double x)
|
||||
{
|
||||
static inline double
|
||||
hamming_filter(double x) {
|
||||
if (x < 0.0) {
|
||||
x = -x;
|
||||
}
|
||||
|
@ -45,15 +43,16 @@ static inline double hamming_filter(double x)
|
|||
return sin(x) / x * (0.54f + 0.46f * cos(x));
|
||||
}
|
||||
|
||||
static inline double bicubic_filter(double x)
|
||||
{
|
||||
/* https://en.wikipedia.org/wiki/Bicubic_interpolation#Bicubic_convolution_algorithm */
|
||||
static inline double
|
||||
bicubic_filter(double x) {
|
||||
/* https://en.wikipedia.org/wiki/Bicubic_interpolation#Bicubic_convolution_algorithm
|
||||
*/
|
||||
#define a -0.5
|
||||
if (x < 0.0) {
|
||||
x = -x;
|
||||
}
|
||||
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) {
|
||||
return (((x - 5) * x + 8) * x - 4) * a;
|
||||
|
@ -62,8 +61,8 @@ static inline double bicubic_filter(double x)
|
|||
#undef a
|
||||
}
|
||||
|
||||
static inline double sinc_filter(double x)
|
||||
{
|
||||
static inline double
|
||||
sinc_filter(double x) {
|
||||
if (x == 0.0) {
|
||||
return 1.0;
|
||||
}
|
||||
|
@ -71,21 +70,20 @@ static inline double sinc_filter(double x)
|
|||
return sin(x) / x;
|
||||
}
|
||||
|
||||
static inline double lanczos_filter(double x)
|
||||
{
|
||||
static inline double
|
||||
lanczos_filter(double x) {
|
||||
/* truncated sinc */
|
||||
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;
|
||||
}
|
||||
|
||||
static struct filter BOX = { box_filter, 0.5 };
|
||||
static struct filter BILINEAR = { bilinear_filter, 1.0 };
|
||||
static struct filter HAMMING = { hamming_filter, 1.0 };
|
||||
static struct filter BICUBIC = { bicubic_filter, 2.0 };
|
||||
static struct filter LANCZOS = { lanczos_filter, 3.0 };
|
||||
|
||||
static struct filter BOX = {box_filter, 0.5};
|
||||
static struct filter BILINEAR = {bilinear_filter, 1.0};
|
||||
static struct filter HAMMING = {hamming_filter, 1.0};
|
||||
static struct filter BICUBIC = {bicubic_filter, 2.0};
|
||||
static struct filter LANCZOS = {lanczos_filter, 3.0};
|
||||
|
||||
/* 8 bits for result. Filter can have negative areas.
|
||||
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. */
|
||||
#define PRECISION_BITS (32 - 8 - 2)
|
||||
|
||||
|
||||
/* Handles values form -640 to 639. */
|
||||
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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
||||
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
|
||||
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
|
||||
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
|
||||
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
|
||||
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
|
||||
160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
|
||||
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
|
||||
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
|
||||
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
|
||||
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
|
||||
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,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 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,
|
||||
6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
|
||||
23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
|
||||
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
|
||||
57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
|
||||
74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
|
||||
91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
|
||||
108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
|
||||
125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
|
||||
142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
|
||||
159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
|
||||
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
|
||||
193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
|
||||
210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
|
||||
227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 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,
|
||||
};
|
||||
|
||||
UINT8 *clip8_lookups = &_clip8_lookups[640];
|
||||
|
||||
static inline UINT8 clip8(int in)
|
||||
{
|
||||
static inline UINT8
|
||||
clip8(int in) {
|
||||
return clip8_lookups[in >> PRECISION_BITS];
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
precompute_coeffs(int inSize, float in0, float in1, int outSize,
|
||||
struct filter *filterp, int **boundsp, double **kkp) {
|
||||
precompute_coeffs(
|
||||
int inSize,
|
||||
float in0,
|
||||
float in1,
|
||||
int outSize,
|
||||
struct filter *filterp,
|
||||
int **boundsp,
|
||||
double **kkp) {
|
||||
double support, scale, filterscale;
|
||||
double center, ww, ss;
|
||||
int xx, x, ksize, xmin, xmax;
|
||||
|
@ -196,7 +194,7 @@ precompute_coeffs(int inSize, float in0, float in1, int outSize,
|
|||
double *kk, *k;
|
||||
|
||||
/* prepare for horizontal stretch */
|
||||
filterscale = scale = (double) (in1 - in0) / outSize;
|
||||
filterscale = scale = (double)(in1 - in0) / outSize;
|
||||
if (filterscale < 1.0) {
|
||||
filterscale = 1.0;
|
||||
}
|
||||
|
@ -205,7 +203,7 @@ precompute_coeffs(int inSize, float in0, float in1, int outSize,
|
|||
support = filterp->support * filterscale;
|
||||
|
||||
/* maximum number of coeffs */
|
||||
ksize = (int) ceil(support) * 2 + 1;
|
||||
ksize = (int)ceil(support) * 2 + 1;
|
||||
|
||||
// check for overflow
|
||||
if (outSize > INT_MAX / (ksize * (int)sizeof(double))) {
|
||||
|
@ -216,14 +214,14 @@ precompute_coeffs(int inSize, float in0, float in1, int outSize,
|
|||
/* coefficient buffer */
|
||||
/* malloc check ok, overflow checked above */
|
||||
kk = malloc(outSize * ksize * sizeof(double));
|
||||
if ( ! kk) {
|
||||
if (!kk) {
|
||||
ImagingError_MemoryError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* malloc check ok, ksize*sizeof(double) > 2*sizeof(int) */
|
||||
bounds = malloc(outSize * 2 * sizeof(int));
|
||||
if ( ! bounds) {
|
||||
if (!bounds) {
|
||||
free(kk);
|
||||
ImagingError_MemoryError();
|
||||
return 0;
|
||||
|
@ -234,12 +232,12 @@ precompute_coeffs(int inSize, float in0, float in1, int outSize,
|
|||
ww = 0.0;
|
||||
ss = 1.0 / filterscale;
|
||||
// Round the value
|
||||
xmin = (int) (center - support + 0.5);
|
||||
xmin = (int)(center - support + 0.5);
|
||||
if (xmin < 0) {
|
||||
xmin = 0;
|
||||
}
|
||||
// Round the value
|
||||
xmax = (int) (center + support + 0.5);
|
||||
xmax = (int)(center + support + 0.5);
|
||||
if (xmax > inSize) {
|
||||
xmax = inSize;
|
||||
}
|
||||
|
@ -267,38 +265,33 @@ precompute_coeffs(int inSize, float in0, float in1, int outSize,
|
|||
return ksize;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
normalize_coeffs_8bpc(int outSize, int ksize, double *prekk)
|
||||
{
|
||||
normalize_coeffs_8bpc(int outSize, int ksize, double *prekk) {
|
||||
int x;
|
||||
INT32 *kk;
|
||||
|
||||
// use the same buffer for normalized coefficients
|
||||
kk = (INT32 *) prekk;
|
||||
kk = (INT32 *)prekk;
|
||||
|
||||
for (x = 0; x < outSize * ksize; x++) {
|
||||
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 {
|
||||
kk[x] = (int) (0.5 + prekk[x] * (1 << PRECISION_BITS));
|
||||
kk[x] = (int)(0.5 + prekk[x] * (1 << PRECISION_BITS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset,
|
||||
int ksize, int *bounds, double *prekk)
|
||||
{
|
||||
ImagingResampleHorizontal_8bpc(
|
||||
Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *prekk) {
|
||||
ImagingSectionCookie cookie;
|
||||
int ss0, ss1, ss2, ss3;
|
||||
int xx, yy, x, xmin, xmax;
|
||||
INT32 *k, *kk;
|
||||
|
||||
// use the same buffer for normalized coefficients
|
||||
kk = (INT32 *) prekk;
|
||||
kk = (INT32 *)prekk;
|
||||
normalize_coeffs_8bpc(imOut->xsize, ksize, prekk);
|
||||
|
||||
ImagingSectionEnter(&cookie);
|
||||
|
@ -308,9 +301,9 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
xmin = bounds[xx * 2 + 0];
|
||||
xmax = bounds[xx * 2 + 1];
|
||||
k = &kk[xx * ksize];
|
||||
ss0 = 1 << (PRECISION_BITS -1);
|
||||
ss0 = 1 << (PRECISION_BITS - 1);
|
||||
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);
|
||||
}
|
||||
|
@ -323,10 +316,12 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
xmin = bounds[xx * 2 + 0];
|
||||
xmax = bounds[xx * 2 + 1];
|
||||
k = &kk[xx * ksize];
|
||||
ss0 = ss3 = 1 << (PRECISION_BITS -1);
|
||||
ss0 = ss3 = 1 << (PRECISION_BITS - 1);
|
||||
for (x = 0; x < xmax; x++) {
|
||||
ss0 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 0]) * k[x];
|
||||
ss3 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 3]) * k[x];
|
||||
ss0 += ((UINT8)imIn->image[yy + offset][(x + xmin) * 4 + 0]) *
|
||||
k[x];
|
||||
ss3 += ((UINT8)imIn->image[yy + offset][(x + xmin) * 4 + 3]) *
|
||||
k[x];
|
||||
}
|
||||
v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3));
|
||||
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];
|
||||
xmax = bounds[xx * 2 + 1];
|
||||
k = &kk[xx * ksize];
|
||||
ss0 = ss1 = ss2 = 1 << (PRECISION_BITS -1);
|
||||
ss0 = ss1 = ss2 = 1 << (PRECISION_BITS - 1);
|
||||
for (x = 0; x < xmax; x++) {
|
||||
ss0 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 0]) * 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];
|
||||
ss0 += ((UINT8)imIn->image[yy + offset][(x + xmin) * 4 + 0]) *
|
||||
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);
|
||||
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];
|
||||
xmax = bounds[xx * 2 + 1];
|
||||
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++) {
|
||||
ss0 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 0]) * 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];
|
||||
ss3 += ((UINT8) imIn->image[yy + offset][(x + xmin)*4 + 3]) * k[x];
|
||||
ss0 += ((UINT8)imIn->image[yy + offset][(x + xmin) * 4 + 0]) *
|
||||
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];
|
||||
ss3 += ((UINT8)imIn->image[yy + offset][(x + xmin) * 4 + 3]) *
|
||||
k[x];
|
||||
}
|
||||
v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3));
|
||||
memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v));
|
||||
|
@ -372,18 +374,16 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
ImagingSectionLeave(&cookie);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset,
|
||||
int ksize, int *bounds, double *prekk)
|
||||
{
|
||||
ImagingResampleVertical_8bpc(
|
||||
Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *prekk) {
|
||||
ImagingSectionCookie cookie;
|
||||
int ss0, ss1, ss2, ss3;
|
||||
int xx, yy, y, ymin, ymax;
|
||||
INT32 *k, *kk;
|
||||
|
||||
// use the same buffer for normalized coefficients
|
||||
kk = (INT32 *) prekk;
|
||||
kk = (INT32 *)prekk;
|
||||
normalize_coeffs_8bpc(imOut->ysize, ksize, prekk);
|
||||
|
||||
ImagingSectionEnter(&cookie);
|
||||
|
@ -393,9 +393,9 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
ymin = bounds[yy * 2 + 0];
|
||||
ymax = bounds[yy * 2 + 1];
|
||||
for (xx = 0; xx < imOut->xsize; xx++) {
|
||||
ss0 = 1 << (PRECISION_BITS -1);
|
||||
ss0 = 1 << (PRECISION_BITS - 1);
|
||||
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);
|
||||
}
|
||||
|
@ -408,10 +408,10 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
ymax = bounds[yy * 2 + 1];
|
||||
for (xx = 0; xx < imOut->xsize; xx++) {
|
||||
UINT32 v;
|
||||
ss0 = ss3 = 1 << (PRECISION_BITS -1);
|
||||
ss0 = ss3 = 1 << (PRECISION_BITS - 1);
|
||||
for (y = 0; y < ymax; y++) {
|
||||
ss0 += ((UINT8) imIn->image[y + ymin][xx*4 + 0]) * k[y];
|
||||
ss3 += ((UINT8) imIn->image[y + ymin][xx*4 + 3]) * k[y];
|
||||
ss0 += ((UINT8)imIn->image[y + ymin][xx * 4 + 0]) * k[y];
|
||||
ss3 += ((UINT8)imIn->image[y + ymin][xx * 4 + 3]) * k[y];
|
||||
}
|
||||
v = MAKE_UINT32(clip8(ss0), 0, 0, clip8(ss3));
|
||||
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];
|
||||
for (xx = 0; xx < imOut->xsize; xx++) {
|
||||
UINT32 v;
|
||||
ss0 = ss1 = ss2 = 1 << (PRECISION_BITS -1);
|
||||
ss0 = ss1 = ss2 = 1 << (PRECISION_BITS - 1);
|
||||
for (y = 0; y < ymax; y++) {
|
||||
ss0 += ((UINT8) imIn->image[y + ymin][xx*4 + 0]) * k[y];
|
||||
ss1 += ((UINT8) imIn->image[y + ymin][xx*4 + 1]) * k[y];
|
||||
ss2 += ((UINT8) imIn->image[y + ymin][xx*4 + 2]) * k[y];
|
||||
ss0 += ((UINT8)imIn->image[y + ymin][xx * 4 + 0]) * k[y];
|
||||
ss1 += ((UINT8)imIn->image[y + ymin][xx * 4 + 1]) * k[y];
|
||||
ss2 += ((UINT8)imIn->image[y + ymin][xx * 4 + 2]) * k[y];
|
||||
}
|
||||
v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), 0);
|
||||
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];
|
||||
for (xx = 0; xx < imOut->xsize; xx++) {
|
||||
UINT32 v;
|
||||
ss0 = ss1 = ss2 = ss3 = 1 << (PRECISION_BITS -1);
|
||||
ss0 = ss1 = ss2 = ss3 = 1 << (PRECISION_BITS - 1);
|
||||
for (y = 0; y < ymax; y++) {
|
||||
ss0 += ((UINT8) imIn->image[y + ymin][xx*4 + 0]) * k[y];
|
||||
ss1 += ((UINT8) imIn->image[y + ymin][xx*4 + 1]) * k[y];
|
||||
ss2 += ((UINT8) imIn->image[y + ymin][xx*4 + 2]) * k[y];
|
||||
ss3 += ((UINT8) imIn->image[y + ymin][xx*4 + 3]) * k[y];
|
||||
ss0 += ((UINT8)imIn->image[y + ymin][xx * 4 + 0]) * k[y];
|
||||
ss1 += ((UINT8)imIn->image[y + ymin][xx * 4 + 1]) * k[y];
|
||||
ss2 += ((UINT8)imIn->image[y + ymin][xx * 4 + 2]) * k[y];
|
||||
ss3 += ((UINT8)imIn->image[y + ymin][xx * 4 + 3]) * k[y];
|
||||
}
|
||||
v = MAKE_UINT32(clip8(ss0), clip8(ss1), clip8(ss2), clip8(ss3));
|
||||
memcpy(imOut->image[yy] + xx * sizeof(v), &v, sizeof(v));
|
||||
|
@ -457,18 +457,16 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
ImagingSectionLeave(&cookie);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ImagingResampleHorizontal_32bpc(Imaging imOut, Imaging imIn, int offset,
|
||||
int ksize, int *bounds, double *kk)
|
||||
{
|
||||
ImagingResampleHorizontal_32bpc(
|
||||
Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *kk) {
|
||||
ImagingSectionCookie cookie;
|
||||
double ss;
|
||||
int xx, yy, x, xmin, xmax;
|
||||
double *k;
|
||||
|
||||
ImagingSectionEnter(&cookie);
|
||||
switch(imIn->type) {
|
||||
switch (imIn->type) {
|
||||
case IMAGING_TYPE_INT32:
|
||||
for (yy = 0; yy < imOut->ysize; yy++) {
|
||||
for (xx = 0; xx < imOut->xsize; xx++) {
|
||||
|
@ -502,18 +500,16 @@ ImagingResampleHorizontal_32bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
ImagingSectionLeave(&cookie);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ImagingResampleVertical_32bpc(Imaging imOut, Imaging imIn, int offset,
|
||||
int ksize, int *bounds, double *kk)
|
||||
{
|
||||
ImagingResampleVertical_32bpc(
|
||||
Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *kk) {
|
||||
ImagingSectionCookie cookie;
|
||||
double ss;
|
||||
int xx, yy, y, ymin, ymax;
|
||||
double *k;
|
||||
|
||||
ImagingSectionEnter(&cookie);
|
||||
switch(imIn->type) {
|
||||
switch (imIn->type) {
|
||||
case IMAGING_TYPE_INT32:
|
||||
for (yy = 0; yy < imOut->ysize; yy++) {
|
||||
ymin = bounds[yy * 2 + 0];
|
||||
|
@ -547,36 +543,36 @@ ImagingResampleVertical_32bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
ImagingSectionLeave(&cookie);
|
||||
}
|
||||
|
||||
|
||||
typedef void (*ResampleFunction)(Imaging imOut, Imaging imIn, int offset,
|
||||
int ksize, int *bounds, double *kk);
|
||||
|
||||
typedef void (*ResampleFunction)(
|
||||
Imaging imOut, Imaging imIn, int offset, int ksize, int *bounds, double *kk);
|
||||
|
||||
Imaging
|
||||
ImagingResampleInner(Imaging imIn, int xsize, int ysize,
|
||||
struct filter *filterp, float box[4],
|
||||
ResampleFunction ResampleHorizontal,
|
||||
ResampleFunction ResampleVertical);
|
||||
|
||||
ImagingResampleInner(
|
||||
Imaging imIn,
|
||||
int xsize,
|
||||
int ysize,
|
||||
struct filter *filterp,
|
||||
float box[4],
|
||||
ResampleFunction ResampleHorizontal,
|
||||
ResampleFunction ResampleVertical);
|
||||
|
||||
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;
|
||||
ResampleFunction ResampleHorizontal;
|
||||
ResampleFunction ResampleVertical;
|
||||
|
||||
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) {
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
} else if (imIn->image8) {
|
||||
ResampleHorizontal = ImagingResampleHorizontal_8bpc;
|
||||
ResampleVertical = ImagingResampleVertical_8bpc;
|
||||
} else {
|
||||
switch(imIn->type) {
|
||||
switch (imIn->type) {
|
||||
case IMAGING_TYPE_UINT8:
|
||||
ResampleHorizontal = ImagingResampleHorizontal_8bpc;
|
||||
ResampleVertical = ImagingResampleVertical_8bpc;
|
||||
|
@ -587,44 +583,44 @@ ImagingResample(Imaging imIn, int xsize, int ysize, int filter, float box[4])
|
|||
ResampleVertical = ImagingResampleVertical_32bpc;
|
||||
break;
|
||||
default:
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
return (Imaging)ImagingError_ModeError();
|
||||
}
|
||||
}
|
||||
|
||||
/* check filter */
|
||||
switch (filter) {
|
||||
case IMAGING_TRANSFORM_BOX:
|
||||
filterp = &BOX;
|
||||
break;
|
||||
case IMAGING_TRANSFORM_BILINEAR:
|
||||
filterp = &BILINEAR;
|
||||
break;
|
||||
case IMAGING_TRANSFORM_HAMMING:
|
||||
filterp = &HAMMING;
|
||||
break;
|
||||
case IMAGING_TRANSFORM_BICUBIC:
|
||||
filterp = &BICUBIC;
|
||||
break;
|
||||
case IMAGING_TRANSFORM_LANCZOS:
|
||||
filterp = &LANCZOS;
|
||||
break;
|
||||
default:
|
||||
return (Imaging) ImagingError_ValueError(
|
||||
"unsupported resampling filter"
|
||||
);
|
||||
case IMAGING_TRANSFORM_BOX:
|
||||
filterp = &BOX;
|
||||
break;
|
||||
case IMAGING_TRANSFORM_BILINEAR:
|
||||
filterp = &BILINEAR;
|
||||
break;
|
||||
case IMAGING_TRANSFORM_HAMMING:
|
||||
filterp = &HAMMING;
|
||||
break;
|
||||
case IMAGING_TRANSFORM_BICUBIC:
|
||||
filterp = &BICUBIC;
|
||||
break;
|
||||
case IMAGING_TRANSFORM_LANCZOS:
|
||||
filterp = &LANCZOS;
|
||||
break;
|
||||
default:
|
||||
return (Imaging)ImagingError_ValueError("unsupported resampling filter");
|
||||
}
|
||||
|
||||
return ImagingResampleInner(imIn, xsize, ysize, filterp, box,
|
||||
ResampleHorizontal, ResampleVertical);
|
||||
return ImagingResampleInner(
|
||||
imIn, xsize, ysize, filterp, box, ResampleHorizontal, ResampleVertical);
|
||||
}
|
||||
|
||||
|
||||
Imaging
|
||||
ImagingResampleInner(Imaging imIn, int xsize, int ysize,
|
||||
struct filter *filterp, float box[4],
|
||||
ResampleFunction ResampleHorizontal,
|
||||
ResampleFunction ResampleVertical)
|
||||
{
|
||||
ImagingResampleInner(
|
||||
Imaging imIn,
|
||||
int xsize,
|
||||
int ysize,
|
||||
struct filter *filterp,
|
||||
float box[4],
|
||||
ResampleFunction ResampleHorizontal,
|
||||
ResampleFunction ResampleVertical) {
|
||||
Imaging imTemp = 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_vertical = ysize != imIn->ysize || box[1] || box[3] != ysize;
|
||||
|
||||
ksize_horiz = precompute_coeffs(imIn->xsize, box[0], box[2], xsize,
|
||||
filterp, &bounds_horiz, &kk_horiz);
|
||||
if ( ! ksize_horiz) {
|
||||
ksize_horiz = precompute_coeffs(
|
||||
imIn->xsize, box[0], box[2], xsize, filterp, &bounds_horiz, &kk_horiz);
|
||||
if (!ksize_horiz) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ksize_vert = precompute_coeffs(imIn->ysize, box[1], box[3], ysize,
|
||||
filterp, &bounds_vert, &kk_vert);
|
||||
if ( ! ksize_vert) {
|
||||
ksize_vert = precompute_coeffs(
|
||||
imIn->ysize, box[1], box[3], ysize, filterp, &bounds_vert, &kk_vert);
|
||||
if (!ksize_vert) {
|
||||
free(bounds_horiz);
|
||||
free(kk_horiz);
|
||||
return NULL;
|
||||
|
@ -654,8 +650,7 @@ ImagingResampleInner(Imaging imIn, int xsize, int ysize,
|
|||
// First used row in the source image
|
||||
ybox_first = bounds_vert[0];
|
||||
// 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 */
|
||||
if (need_horizontal) {
|
||||
|
@ -666,12 +661,12 @@ ImagingResampleInner(Imaging imIn, int xsize, int ysize,
|
|||
|
||||
imTemp = ImagingNewDirty(imIn->mode, xsize, ybox_last - ybox_first);
|
||||
if (imTemp) {
|
||||
ResampleHorizontal(imTemp, imIn, ybox_first,
|
||||
ksize_horiz, bounds_horiz, kk_horiz);
|
||||
ResampleHorizontal(
|
||||
imTemp, imIn, ybox_first, ksize_horiz, bounds_horiz, kk_horiz);
|
||||
}
|
||||
free(bounds_horiz);
|
||||
free(kk_horiz);
|
||||
if ( ! imTemp) {
|
||||
if (!imTemp) {
|
||||
free(bounds_vert);
|
||||
free(kk_vert);
|
||||
return NULL;
|
||||
|
@ -688,15 +683,14 @@ ImagingResampleInner(Imaging imIn, int xsize, int ysize,
|
|||
imOut = ImagingNewDirty(imIn->mode, imIn->xsize, ysize);
|
||||
if (imOut) {
|
||||
/* imIn can be the original image or horizontally resampled one */
|
||||
ResampleVertical(imOut, imIn, 0,
|
||||
ksize_vert, bounds_vert, kk_vert);
|
||||
ResampleVertical(imOut, imIn, 0, ksize_vert, bounds_vert, kk_vert);
|
||||
}
|
||||
/* it's safe to call ImagingDelete with empty value
|
||||
if previous step was not performed. */
|
||||
ImagingDelete(imTemp);
|
||||
free(bounds_vert);
|
||||
free(kk_vert);
|
||||
if ( ! imOut) {
|
||||
if (!imOut) {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
|
@ -706,7 +700,7 @@ ImagingResampleInner(Imaging imIn, int xsize, int ysize,
|
|||
}
|
||||
|
||||
/* none of the previous steps are performed, copying */
|
||||
if ( ! imOut) {
|
||||
if (!imOut) {
|
||||
imOut = ImagingCopy(imIn);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* Sgi.h */
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* CONFIGURATION */
|
||||
|
||||
/* Number of bytes per channel per pixel */
|
||||
|
|
|
@ -20,18 +20,17 @@
|
|||
#define RLE_COPY_FLAG 0x80
|
||||
#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]);
|
||||
}
|
||||
|
||||
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;
|
||||
int x = 0;
|
||||
|
||||
for (;n > 0; n--)
|
||||
{
|
||||
for (; n > 0; n--) {
|
||||
pixel = *src++;
|
||||
if (n == 1 && pixel != 0) {
|
||||
return n;
|
||||
|
@ -45,34 +44,31 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize)
|
|||
}
|
||||
x += count;
|
||||
if (pixel & RLE_COPY_FLAG) {
|
||||
while(count--) {
|
||||
while (count--) {
|
||||
*dest = *src++;
|
||||
dest += z;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
pixel = *src++;
|
||||
while (count--) {
|
||||
*dest = pixel;
|
||||
dest += z;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
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;
|
||||
|
||||
int x = 0;
|
||||
|
||||
for (;n > 0; n--)
|
||||
{
|
||||
for (; n > 0; n--) {
|
||||
pixel = src[1];
|
||||
src+=2;
|
||||
src += 2;
|
||||
if (n == 1 && pixel != 0) {
|
||||
return n;
|
||||
}
|
||||
|
@ -85,42 +81,37 @@ static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize)
|
|||
}
|
||||
x += count;
|
||||
if (pixel & RLE_COPY_FLAG) {
|
||||
while(count--) {
|
||||
while (count--) {
|
||||
memcpy(dest, src, 2);
|
||||
src += 2;
|
||||
dest += z * 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
while (count--) {
|
||||
memcpy(dest, src, 2);
|
||||
dest += z * 2;
|
||||
}
|
||||
src+=2;
|
||||
src += 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buf, Py_ssize_t bytes)
|
||||
{
|
||||
ImagingSgiRleDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
|
||||
UINT8 *ptr;
|
||||
SGISTATE *c;
|
||||
int err = 0;
|
||||
int status;
|
||||
|
||||
/* size check */
|
||||
if (im->xsize > INT_MAX / im->bands ||
|
||||
im->ysize > INT_MAX / im->bands) {
|
||||
if (im->xsize > INT_MAX / im->bands || im->ysize > INT_MAX / im->bands) {
|
||||
state->errcode = IMAGING_CODEC_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get all data from File descriptor */
|
||||
c = (SGISTATE*)state->context;
|
||||
c = (SGISTATE *)state->context;
|
||||
_imaging_seek_pyFd(state->fd, 0L, SEEK_END);
|
||||
c->bufsize = _imaging_tell_pyFd(state->fd);
|
||||
c->bufsize -= SGI_HEADER_SIZE;
|
||||
|
@ -130,7 +121,7 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
|||
each with 4 bytes per element of tablen
|
||||
Check here before we allocate any memory
|
||||
*/
|
||||
if (c->bufsize < 8*c->tablen) {
|
||||
if (c->bufsize < 8 * c->tablen) {
|
||||
state->errcode = IMAGING_CODEC_OVERRUN;
|
||||
return -1;
|
||||
}
|
||||
|
@ -141,8 +132,7 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
|||
return -1;
|
||||
}
|
||||
_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 */
|
||||
state->count = 0;
|
||||
|
@ -160,28 +150,27 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
|||
state->buffer = calloc(im->xsize * im->bands, sizeof(UINT8) * 2);
|
||||
c->starttab = calloc(c->tablen, sizeof(UINT32));
|
||||
c->lengthtab = calloc(c->tablen, sizeof(UINT32));
|
||||
if (!state->buffer ||
|
||||
!c->starttab ||
|
||||
!c->lengthtab) {
|
||||
if (!state->buffer || !c->starttab || !c->lengthtab) {
|
||||
err = IMAGING_CODEC_MEMORY;
|
||||
goto sgi_finish_decode;
|
||||
}
|
||||
/* 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]);
|
||||
}
|
||||
/* 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]);
|
||||
}
|
||||
|
||||
state->count += c->tablen * sizeof(UINT32) * 2;
|
||||
|
||||
/* read compressed rows */
|
||||
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->rowno = 0; c->rowno < im->ysize; c->rowno++, state->y += state->ystep) {
|
||||
for (c->channo = 0; c->channo < im->bands; c->channo++) {
|
||||
c->rleoffset = c->starttab[c->rowno + c->channo * im->ysize];
|
||||
c->rlelength = c->lengthtab[c->rowno + c->channo * im->ysize];
|
||||
c->rleoffset -= SGI_HEADER_SIZE;
|
||||
|
@ -192,11 +181,20 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
|||
}
|
||||
|
||||
/* row decompression */
|
||||
if (c->bpc ==1) {
|
||||
status = expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize);
|
||||
}
|
||||
else {
|
||||
status = expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize);
|
||||
if (c->bpc == 1) {
|
||||
status = expandrow(
|
||||
&state->buffer[c->channo],
|
||||
&ptr[c->rleoffset],
|
||||
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) {
|
||||
state->errcode = IMAGING_CODEC_OVERRUN;
|
||||
|
@ -209,19 +207,18 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
|||
}
|
||||
|
||||
/* 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++;
|
||||
|
||||
sgi_finish_decode: ;
|
||||
sgi_finish_decode:;
|
||||
|
||||
free(c->starttab);
|
||||
free(c->lengthtab);
|
||||
free(ptr);
|
||||
if (err != 0){
|
||||
state->errcode=err;
|
||||
if (err != 0) {
|
||||
state->errcode = err;
|
||||
return -1;
|
||||
}
|
||||
return state->count - c->bufsize;
|
||||
|
|
|
@ -34,11 +34,9 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
int ImagingNewCount = 0;
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
|
@ -46,18 +44,17 @@ int ImagingNewCount = 0;
|
|||
*/
|
||||
|
||||
Imaging
|
||||
ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size)
|
||||
{
|
||||
ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size) {
|
||||
Imaging im;
|
||||
|
||||
/* linesize overflow check, roughly the current largest space req'd */
|
||||
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) {
|
||||
return (Imaging) ImagingError_MemoryError();
|
||||
return (Imaging)ImagingError_MemoryError();
|
||||
}
|
||||
|
||||
/* Setup image descriptor */
|
||||
|
@ -115,8 +112,9 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size)
|
|||
im->linesize = xsize * 4;
|
||||
im->type = IMAGING_TYPE_INT32;
|
||||
|
||||
} else if (strcmp(mode, "I;16") == 0 || strcmp(mode, "I;16L") == 0 \
|
||||
|| strcmp(mode, "I;16B") == 0 || strcmp(mode, "I;16N") == 0) {
|
||||
} else if (
|
||||
strcmp(mode, "I;16") == 0 || strcmp(mode, "I;16L") == 0 ||
|
||||
strcmp(mode, "I;16B") == 0 || strcmp(mode, "I;16N") == 0) {
|
||||
/* EXPERIMENTAL */
|
||||
/* 16-bit raw integer images */
|
||||
im->bands = 1;
|
||||
|
@ -135,7 +133,7 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size)
|
|||
/* 15-bit reversed true colour */
|
||||
im->bands = 1;
|
||||
im->pixelsize = 2;
|
||||
im->linesize = (xsize*2 + 3) & -4;
|
||||
im->linesize = (xsize * 2 + 3) & -4;
|
||||
im->type = IMAGING_TYPE_SPECIAL;
|
||||
|
||||
} 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 */
|
||||
im->bands = 1;
|
||||
im->pixelsize = 2;
|
||||
im->linesize = (xsize*2 + 3) & -4;
|
||||
im->linesize = (xsize * 2 + 3) & -4;
|
||||
im->type = IMAGING_TYPE_SPECIAL;
|
||||
|
||||
} 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 */
|
||||
im->bands = 1;
|
||||
im->pixelsize = 3;
|
||||
im->linesize = (xsize*3 + 3) & -4;
|
||||
im->linesize = (xsize * 3 + 3) & -4;
|
||||
im->type = IMAGING_TYPE_SPECIAL;
|
||||
|
||||
} 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 */
|
||||
im->bands = 1;
|
||||
im->pixelsize = 4;
|
||||
im->linesize = (xsize*4 + 3) & -4;
|
||||
im->linesize = (xsize * 4 + 3) & -4;
|
||||
im->type = IMAGING_TYPE_SPECIAL;
|
||||
|
||||
} else if (strcmp(mode, "RGBX") == 0) {
|
||||
|
@ -204,7 +202,7 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size)
|
|||
|
||||
} else {
|
||||
free(im);
|
||||
return (Imaging) ImagingError_ValueError("unrecognized image mode");
|
||||
return (Imaging)ImagingError_ValueError("unrecognized image mode");
|
||||
}
|
||||
|
||||
/* 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
|
||||
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);
|
||||
return (Imaging) ImagingError_MemoryError();
|
||||
return (Imaging)ImagingError_MemoryError();
|
||||
}
|
||||
|
||||
/* Initialize alias pointers to pixel data. */
|
||||
switch (im->pixelsize) {
|
||||
case 1: case 2: case 3:
|
||||
im->image8 = (UINT8 **) im->image;
|
||||
break;
|
||||
case 4:
|
||||
im->image32 = (INT32 **) im->image;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
im->image8 = (UINT8 **)im->image;
|
||||
break;
|
||||
case 4:
|
||||
im->image32 = (INT32 **)im->image;
|
||||
break;
|
||||
}
|
||||
|
||||
ImagingDefaultArena.stats_new_count += 1;
|
||||
|
@ -235,15 +235,13 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size)
|
|||
}
|
||||
|
||||
Imaging
|
||||
ImagingNewPrologue(const char *mode, int xsize, int ysize)
|
||||
{
|
||||
ImagingNewPrologue(const char *mode, int xsize, int ysize) {
|
||||
return ImagingNewPrologueSubtype(
|
||||
mode, xsize, ysize, sizeof(struct ImagingMemoryInstance));
|
||||
}
|
||||
|
||||
void
|
||||
ImagingDelete(Imaging im)
|
||||
{
|
||||
ImagingDelete(Imaging im) {
|
||||
if (!im) {
|
||||
return;
|
||||
}
|
||||
|
@ -263,7 +261,6 @@ ImagingDelete(Imaging im)
|
|||
free(im);
|
||||
}
|
||||
|
||||
|
||||
/* Array Storage Type */
|
||||
/* ------------------ */
|
||||
/* Allocate image as an array of line buffers. */
|
||||
|
@ -271,17 +268,20 @@ ImagingDelete(Imaging im)
|
|||
#define IMAGING_PAGE_SIZE (4096)
|
||||
|
||||
struct ImagingMemoryArena ImagingDefaultArena = {
|
||||
1, // alignment
|
||||
16*1024*1024, // block_size
|
||||
0, // blocks_max
|
||||
0, // blocks_cached
|
||||
NULL, // blocks_pool
|
||||
0, 0, 0, 0, 0 // Stats
|
||||
1, // alignment
|
||||
16 * 1024 * 1024, // block_size
|
||||
0, // blocks_max
|
||||
0, // blocks_cached
|
||||
NULL, // blocks_pool
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0 // Stats
|
||||
};
|
||||
|
||||
int
|
||||
ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max)
|
||||
{
|
||||
ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max) {
|
||||
void *p;
|
||||
/* Free already cached blocks */
|
||||
ImagingMemoryClearCache(arena, blocks_max);
|
||||
|
@ -291,14 +291,14 @@ ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max)
|
|||
arena->blocks_pool = NULL;
|
||||
} else if (arena->blocks_pool != NULL) {
|
||||
p = realloc(arena->blocks_pool, sizeof(*arena->blocks_pool) * blocks_max);
|
||||
if ( ! p) {
|
||||
if (!p) {
|
||||
// Leave previous blocks_max value
|
||||
return 0;
|
||||
}
|
||||
arena->blocks_pool = p;
|
||||
} else {
|
||||
arena->blocks_pool = calloc(sizeof(*arena->blocks_pool), blocks_max);
|
||||
if ( ! arena->blocks_pool) {
|
||||
if (!arena->blocks_pool) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -308,8 +308,7 @@ ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max)
|
|||
}
|
||||
|
||||
void
|
||||
ImagingMemoryClearCache(ImagingMemoryArena arena, int new_size)
|
||||
{
|
||||
ImagingMemoryClearCache(ImagingMemoryArena arena, int new_size) {
|
||||
while (arena->blocks_cached > new_size) {
|
||||
arena->blocks_cached -= 1;
|
||||
free(arena->blocks_pool[arena->blocks_cached].ptr);
|
||||
|
@ -318,8 +317,7 @@ ImagingMemoryClearCache(ImagingMemoryArena arena, int new_size)
|
|||
}
|
||||
|
||||
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};
|
||||
|
||||
if (arena->blocks_cached > 0) {
|
||||
|
@ -327,16 +325,16 @@ memory_get_block(ImagingMemoryArena arena, int requested_size, int dirty)
|
|||
arena->blocks_cached -= 1;
|
||||
block = arena->blocks_pool[arena->blocks_cached];
|
||||
// Reallocate if needed
|
||||
if (block.size != requested_size){
|
||||
if (block.size != 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)
|
||||
free(arena->blocks_pool[arena->blocks_cached].ptr);
|
||||
arena->stats_freed_blocks += 1;
|
||||
return block;
|
||||
}
|
||||
if ( ! dirty) {
|
||||
if (!dirty) {
|
||||
memset(block.ptr, 0, requested_size);
|
||||
}
|
||||
arena->stats_reused_blocks += 1;
|
||||
|
@ -356,9 +354,8 @@ memory_get_block(ImagingMemoryArena arena, int requested_size, int dirty)
|
|||
}
|
||||
|
||||
void
|
||||
memory_return_block(ImagingMemoryArena arena, ImagingMemoryBlock block)
|
||||
{
|
||||
if (arena->blocks_cached < arena->blocks_max) {
|
||||
memory_return_block(ImagingMemoryArena arena, ImagingMemoryBlock block) {
|
||||
if (arena->blocks_cached < arena->blocks_max) {
|
||||
// Reduce block size
|
||||
if (block.size > arena->block_size) {
|
||||
block.size = arena->block_size;
|
||||
|
@ -372,15 +369,13 @@ memory_return_block(ImagingMemoryArena arena, ImagingMemoryBlock block)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ImagingDestroyArray(Imaging im)
|
||||
{
|
||||
ImagingDestroyArray(Imaging im) {
|
||||
int y = 0;
|
||||
|
||||
if (im->blocks) {
|
||||
while (im->blocks[y].ptr) {
|
||||
memory_return_block(&ImagingDefaultArena, im->blocks[y]);
|
||||
memory_return_block(&ImagingDefaultArena, im->blocks[y]);
|
||||
y += 1;
|
||||
}
|
||||
free(im->blocks);
|
||||
|
@ -388,8 +383,7 @@ ImagingDestroyArray(Imaging im)
|
|||
}
|
||||
|
||||
Imaging
|
||||
ImagingAllocateArray(Imaging im, int dirty, int block_size)
|
||||
{
|
||||
ImagingAllocateArray(Imaging im, int dirty, int block_size) {
|
||||
int y, line_in_block, current_block;
|
||||
ImagingMemoryArena arena = &ImagingDefaultArena;
|
||||
ImagingMemoryBlock block = {NULL, 0};
|
||||
|
@ -397,7 +391,7 @@ ImagingAllocateArray(Imaging im, int dirty, int block_size)
|
|||
char *aligned_ptr = NULL;
|
||||
|
||||
/* 0-width or 0-height image. No need to do anything */
|
||||
if ( ! im->linesize || ! im->ysize) {
|
||||
if (!im->linesize || !im->ysize) {
|
||||
return im;
|
||||
}
|
||||
|
||||
|
@ -412,8 +406,8 @@ ImagingAllocateArray(Imaging im, int dirty, int block_size)
|
|||
|
||||
/* One extra pointer is always NULL */
|
||||
im->blocks = calloc(sizeof(*im->blocks), blocks_count + 1);
|
||||
if ( ! im->blocks) {
|
||||
return (Imaging) ImagingError_MemoryError();
|
||||
if (!im->blocks) {
|
||||
return (Imaging)ImagingError_MemoryError();
|
||||
}
|
||||
|
||||
/* 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;
|
||||
block = memory_get_block(arena, required, dirty);
|
||||
if ( ! block.ptr) {
|
||||
if (!block.ptr) {
|
||||
ImagingDestroyArray(im);
|
||||
return (Imaging) ImagingError_MemoryError();
|
||||
return (Imaging)ImagingError_MemoryError();
|
||||
}
|
||||
im->blocks[current_block] = block;
|
||||
/* Bulletproof code from libc _int_memalign */
|
||||
|
@ -454,42 +448,38 @@ ImagingAllocateArray(Imaging im, int dirty, int block_size)
|
|||
return im;
|
||||
}
|
||||
|
||||
|
||||
/* Block Storage Type */
|
||||
/* ------------------ */
|
||||
/* Allocate image as a single block. */
|
||||
|
||||
static void
|
||||
ImagingDestroyBlock(Imaging im)
|
||||
{
|
||||
ImagingDestroyBlock(Imaging im) {
|
||||
if (im->block) {
|
||||
free(im->block);
|
||||
}
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingAllocateBlock(Imaging im)
|
||||
{
|
||||
ImagingAllocateBlock(Imaging im) {
|
||||
Py_ssize_t y, i;
|
||||
|
||||
/* overflow check for malloc */
|
||||
if (im->linesize &&
|
||||
im->ysize > INT_MAX / im->linesize) {
|
||||
return (Imaging) ImagingError_MemoryError();
|
||||
if (im->linesize && im->ysize > INT_MAX / im->linesize) {
|
||||
return (Imaging)ImagingError_MemoryError();
|
||||
}
|
||||
|
||||
if (im->ysize * im->linesize <= 0) {
|
||||
/* some platforms return NULL for malloc(0); this fix
|
||||
prevents MemoryError on zero-sized images on such
|
||||
platforms */
|
||||
im->block = (char *) malloc(1);
|
||||
im->block = (char *)malloc(1);
|
||||
} else {
|
||||
/* 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) {
|
||||
return (Imaging) ImagingError_MemoryError();
|
||||
if (!im->block) {
|
||||
return (Imaging)ImagingError_MemoryError();
|
||||
}
|
||||
|
||||
for (y = i = 0; y < im->ysize; y++) {
|
||||
|
@ -507,16 +497,15 @@ ImagingAllocateBlock(Imaging im)
|
|||
*/
|
||||
|
||||
Imaging
|
||||
ImagingNewInternal(const char* mode, int xsize, int ysize, int dirty)
|
||||
{
|
||||
ImagingNewInternal(const char *mode, int xsize, int ysize, int dirty) {
|
||||
Imaging im;
|
||||
|
||||
if (xsize < 0 || ysize < 0) {
|
||||
return (Imaging) ImagingError_ValueError("bad image size");
|
||||
return (Imaging)ImagingError_ValueError("bad image size");
|
||||
}
|
||||
|
||||
im = ImagingNewPrologue(mode, xsize, ysize);
|
||||
if ( ! im) {
|
||||
if (!im) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -536,28 +525,25 @@ ImagingNewInternal(const char* mode, int xsize, int ysize, int dirty)
|
|||
}
|
||||
|
||||
Imaging
|
||||
ImagingNew(const char* mode, int xsize, int ysize)
|
||||
{
|
||||
ImagingNew(const char *mode, int xsize, int ysize) {
|
||||
return ImagingNewInternal(mode, xsize, ysize, 0);
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingNewDirty(const char* mode, int xsize, int ysize)
|
||||
{
|
||||
ImagingNewDirty(const char *mode, int xsize, int ysize) {
|
||||
return ImagingNewInternal(mode, xsize, ysize, 1);
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingNewBlock(const char* mode, int xsize, int ysize)
|
||||
{
|
||||
ImagingNewBlock(const char *mode, int xsize, int ysize) {
|
||||
Imaging im;
|
||||
|
||||
if (xsize < 0 || ysize < 0) {
|
||||
return (Imaging) ImagingError_ValueError("bad image size");
|
||||
return (Imaging)ImagingError_ValueError("bad image size");
|
||||
}
|
||||
|
||||
im = ImagingNewPrologue(mode, xsize, ysize);
|
||||
if ( ! im) {
|
||||
if (!im) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -570,15 +556,13 @@ ImagingNewBlock(const char* mode, int xsize, int ysize)
|
|||
}
|
||||
|
||||
Imaging
|
||||
ImagingNew2Dirty(const char* mode, Imaging imOut, Imaging imIn)
|
||||
{
|
||||
ImagingNew2Dirty(const char *mode, Imaging imOut, Imaging imIn) {
|
||||
/* allocate or validate output image */
|
||||
|
||||
if (imOut) {
|
||||
/* make sure images match */
|
||||
if (strcmp(imOut->mode, mode) != 0
|
||||
|| imOut->xsize != imIn->xsize
|
||||
|| imOut->ysize != imIn->ysize) {
|
||||
if (strcmp(imOut->mode, mode) != 0 || imOut->xsize != imIn->xsize ||
|
||||
imOut->ysize != imIn->ysize) {
|
||||
return ImagingError_Mismatch();
|
||||
}
|
||||
} else {
|
||||
|
@ -593,8 +577,7 @@ ImagingNew2Dirty(const char* mode, Imaging imOut, Imaging imIn)
|
|||
}
|
||||
|
||||
void
|
||||
ImagingCopyPalette(Imaging destination, Imaging source)
|
||||
{
|
||||
ImagingCopyPalette(Imaging destination, Imaging source) {
|
||||
if (source->palette) {
|
||||
if (destination->palette) {
|
||||
ImagingPaletteDelete(destination->palette);
|
||||
|
|
|
@ -15,37 +15,30 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
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;
|
||||
UINT8* ptr;
|
||||
UINT8 *ptr;
|
||||
UINT8 extra_data = 0;
|
||||
UINT8 extra_bytes = 0;
|
||||
|
||||
ptr = buf;
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (bytes < 1) {
|
||||
return ptr - buf;
|
||||
}
|
||||
|
||||
if (ptr[0] == 0x80) {
|
||||
|
||||
if (bytes < 2) {
|
||||
break;
|
||||
}
|
||||
|
||||
n = ptr[1];
|
||||
|
||||
|
||||
if (n == 0) {
|
||||
|
||||
/* Literal 0x80 (2 bytes) */
|
||||
n = 1;
|
||||
|
||||
|
@ -55,7 +48,6 @@ ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t
|
|||
bytes -= 2;
|
||||
|
||||
} else {
|
||||
|
||||
/* Run (3 bytes) */
|
||||
if (bytes < 3) {
|
||||
break;
|
||||
|
@ -84,7 +76,7 @@ ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t
|
|||
n += 1;
|
||||
|
||||
if (state->x + n > state->bytes) {
|
||||
extra_bytes = n; /* full value */
|
||||
extra_bytes = n; /* full value */
|
||||
n = state->bytes - state->x;
|
||||
extra_bytes -= n;
|
||||
extra_data = ptr[2];
|
||||
|
@ -94,11 +86,9 @@ ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t
|
|||
|
||||
ptr += 3;
|
||||
bytes -= 3;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Literal byte */
|
||||
n = 1;
|
||||
|
||||
|
@ -106,18 +96,18 @@ ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t
|
|||
|
||||
ptr += 1;
|
||||
bytes -= 1;
|
||||
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
state->x += n;
|
||||
|
||||
if (state->x >= state->bytes) {
|
||||
|
||||
/* Got a full line, unpack it */
|
||||
state->shuffle((UINT8*) im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize, state->buffer,
|
||||
state->xsize);
|
||||
state->shuffle(
|
||||
(UINT8 *)im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize,
|
||||
state->buffer,
|
||||
state->xsize);
|
||||
|
||||
state->x = 0;
|
||||
|
||||
|
@ -132,7 +122,7 @@ ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t
|
|||
}
|
||||
|
||||
if (state->x > 0) {
|
||||
break; // assert
|
||||
break; // assert
|
||||
}
|
||||
|
||||
if (extra_bytes >= state->bytes) {
|
||||
|
|
|
@ -14,43 +14,35 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
int
|
||||
ImagingTgaRleDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buf, Py_ssize_t bytes)
|
||||
{
|
||||
ImagingTgaRleDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
|
||||
int n, depth;
|
||||
UINT8* ptr;
|
||||
UINT8 *ptr;
|
||||
|
||||
ptr = buf;
|
||||
|
||||
if (state->state == 0) {
|
||||
|
||||
/* check image orientation */
|
||||
if (state->ystep < 0) {
|
||||
state->y = state->ysize-1;
|
||||
state->y = state->ysize - 1;
|
||||
state->ystep = -1;
|
||||
} else {
|
||||
state->ystep = 1;
|
||||
}
|
||||
|
||||
state->state = 1;
|
||||
|
||||
}
|
||||
|
||||
depth = state->count;
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (bytes < 1) {
|
||||
return ptr - buf;
|
||||
}
|
||||
|
||||
if (ptr[0] & 0x80) {
|
||||
|
||||
/* Run (1 + pixelsize bytes) */
|
||||
|
||||
if (bytes < 1 + depth) {
|
||||
|
@ -69,7 +61,7 @@ ImagingTgaRleDecode(Imaging im, ImagingCodecState state,
|
|||
} else {
|
||||
int i;
|
||||
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;
|
||||
|
||||
} else {
|
||||
|
||||
/* Literal (1+n+1 bytes block) */
|
||||
n = depth * (ptr[0] + 1);
|
||||
|
||||
|
@ -94,17 +85,17 @@ ImagingTgaRleDecode(Imaging im, ImagingCodecState state,
|
|||
|
||||
ptr += 1 + n;
|
||||
bytes -= 1 + n;
|
||||
|
||||
}
|
||||
|
||||
state->x += n;
|
||||
|
||||
if (state->x >= state->bytes) {
|
||||
|
||||
/* Got a full line, unpack it */
|
||||
state->shuffle((UINT8*) im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize, state->buffer,
|
||||
state->xsize);
|
||||
state->shuffle(
|
||||
(UINT8 *)im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize,
|
||||
state->buffer,
|
||||
state->xsize);
|
||||
|
||||
state->x = 0;
|
||||
|
||||
|
@ -114,9 +105,7 @@ ImagingTgaRleDecode(Imaging im, ImagingCodecState state,
|
|||
/* End of file (errcode = 0) */
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ptr - buf;
|
||||
|
|
|
@ -4,18 +4,15 @@
|
|||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static int comparePixels(const UINT8* buf, int x, int bytesPerPixel)
|
||||
{
|
||||
static int
|
||||
comparePixels(const UINT8 *buf, int x, int bytesPerPixel) {
|
||||
buf += x * bytesPerPixel;
|
||||
return memcmp(buf, buf + bytesPerPixel, bytesPerPixel) == 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||
{
|
||||
UINT8* dst;
|
||||
ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
|
||||
UINT8 *dst;
|
||||
int bytesPerPixel;
|
||||
|
||||
if (state->state == 0) {
|
||||
|
@ -40,7 +37,7 @@ ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
* excluding the 1-byte descriptor.
|
||||
*/
|
||||
if (state->count == 0) {
|
||||
UINT8* row;
|
||||
UINT8 *row;
|
||||
UINT8 descriptor;
|
||||
int startX;
|
||||
|
||||
|
@ -64,8 +61,8 @@ ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
if (state->x == 0) {
|
||||
state->shuffle(
|
||||
state->buffer,
|
||||
(UINT8*)im->image[state->y + state->yoff]
|
||||
+ state->xoff * im->pixelsize,
|
||||
(UINT8 *)im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize,
|
||||
state->xsize);
|
||||
}
|
||||
|
||||
|
@ -149,9 +146,7 @@ ImagingTgaRleEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
}
|
||||
|
||||
memcpy(
|
||||
dst,
|
||||
state->buffer + (state->x * bytesPerPixel - state->count),
|
||||
flushCount);
|
||||
dst, state->buffer + (state->x * bytesPerPixel - state->count), flushCount);
|
||||
dst += flushCount;
|
||||
bytes -= flushCount;
|
||||
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
/* 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,
|
||||
* 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
|
||||
#define fd_to_tiff_fd(fd) (fd)
|
||||
|
@ -31,16 +32,23 @@
|
|||
#define fd_to_tiff_fd(fd) ((int)_get_osfhandle(fd))
|
||||
#endif
|
||||
|
||||
void dump_state(const TIFFSTATE *state){
|
||||
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));
|
||||
void
|
||||
dump_state(const TIFFSTATE *state) {
|
||||
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
|
||||
*/
|
||||
|
||||
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;
|
||||
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);
|
||||
state->loc += (toff_t)to_read;
|
||||
|
||||
TRACE( ("location: %u\n", (uint)state->loc));
|
||||
TRACE(("location: %u\n", (uint)state->loc));
|
||||
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;
|
||||
tsize_t to_write;
|
||||
|
||||
|
@ -65,14 +74,14 @@ tsize_t _tiffWriteProc(thandle_t hdata, tdata_t buf, tsize_t size) {
|
|||
dump_state(state);
|
||||
|
||||
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;
|
||||
tsize_t newsize=state->size;
|
||||
tsize_t newsize = state->size;
|
||||
while (newsize < (size + state->size)) {
|
||||
if (newsize > INT_MAX - 64*1024){
|
||||
if (newsize > INT_MAX - 64 * 1024) {
|
||||
return 0;
|
||||
}
|
||||
newsize += 64*1024;
|
||||
newsize += 64 * 1024;
|
||||
// newsize*=2; // UNDONE, by 64k chunks?
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
TRACE(("_tiffSeekProc: off: %u whence: %d \n", (uint)off, whence));
|
||||
dump_state(state);
|
||||
switch (whence) {
|
||||
case 0:
|
||||
state->loc = off;
|
||||
break;
|
||||
case 1:
|
||||
state->loc += off;
|
||||
break;
|
||||
case 2:
|
||||
state->loc = state->eof + off;
|
||||
break;
|
||||
case 0:
|
||||
state->loc = off;
|
||||
break;
|
||||
case 1:
|
||||
state->loc += off;
|
||||
break;
|
||||
case 2:
|
||||
state->loc = state->eof + off;
|
||||
break;
|
||||
}
|
||||
dump_state(state);
|
||||
return state->loc;
|
||||
}
|
||||
|
||||
int _tiffCloseProc(thandle_t hdata) {
|
||||
int
|
||||
_tiffCloseProc(thandle_t hdata) {
|
||||
TIFFSTATE *state = (TIFFSTATE *)hdata;
|
||||
|
||||
TRACE(("_tiffCloseProc \n"));
|
||||
|
@ -126,8 +137,8 @@ int _tiffCloseProc(thandle_t hdata) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
toff_t _tiffSizeProc(thandle_t hdata) {
|
||||
toff_t
|
||||
_tiffSizeProc(thandle_t hdata) {
|
||||
TIFFSTATE *state = (TIFFSTATE *)hdata;
|
||||
|
||||
TRACE(("_tiffSizeProc \n"));
|
||||
|
@ -136,7 +147,8 @@ toff_t _tiffSizeProc(thandle_t hdata) {
|
|||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int _tiffNullMapProc(thandle_t hdata, tdata_t* pbase, toff_t* psize) {
|
||||
(void) hdata; (void) pbase; (void) psize;
|
||||
int
|
||||
_tiffNullMapProc(thandle_t hdata, tdata_t *pbase, toff_t *psize) {
|
||||
(void)hdata;
|
||||
(void)pbase;
|
||||
(void)psize;
|
||||
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"));
|
||||
(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;
|
||||
|
||||
TRACE(("initing libtiff\n"));
|
||||
TRACE(("filepointer: %d \n", fp));
|
||||
TRACE(("State: count %d, state %d, x %d, y %d, ystep %d\n", state->count, 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(("filepointer: %d \n", fp));
|
||||
TRACE(
|
||||
("State: count %d, state %d, x %d, y %d, ystep %d\n",
|
||||
state->count,
|
||||
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: context %p \n", state->context));
|
||||
|
||||
|
@ -180,12 +208,12 @@ int ImagingLibTiffInit(ImagingCodecState state, int fp, uint32 offset) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
|
||||
int
|
||||
_decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
|
||||
// To avoid dealing with YCbCr subsampling, let libtiff handle it
|
||||
// Use a TIFFRGBAImage wrapping the tiff image, and let libtiff handle
|
||||
// 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;
|
||||
UINT8 *new_data;
|
||||
|
@ -211,8 +239,12 @@ int _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
|
|||
img.col_offset = 0;
|
||||
|
||||
if (state->xsize != img.width || state->ysize != img.height) {
|
||||
TRACE(("Inconsistent Image Error: %d =? %d, %d =? %d",
|
||||
state->xsize, img.width, state->ysize, img.height));
|
||||
TRACE(
|
||||
("Inconsistent Image Error: %d =? %d, %d =? %d",
|
||||
state->xsize,
|
||||
img.width,
|
||||
state->ysize,
|
||||
img.height));
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
goto decodeycbcr_err;
|
||||
}
|
||||
|
@ -221,9 +253,9 @@ int _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
|
|||
if (INT_MAX / 4 < img.width) {
|
||||
state->errcode = IMAGING_CODEC_MEMORY;
|
||||
goto decodeycbcr_err;
|
||||
}
|
||||
|
||||
// TiffRGBAImages are 32bits/pixel.
|
||||
}
|
||||
|
||||
// TiffRGBAImages are 32bits/pixel.
|
||||
row_byte_size = img.width * 4;
|
||||
|
||||
/* overflow check for realloc */
|
||||
|
@ -238,7 +270,7 @@ int _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
|
|||
|
||||
/* realloc to fit whole strip */
|
||||
/* malloc check above */
|
||||
new_data = realloc (state->buffer, state->bytes);
|
||||
new_data = realloc(state->buffer, state->bytes);
|
||||
if (!new_data) {
|
||||
state->errcode = IMAGING_CODEC_MEMORY;
|
||||
goto decodeycbcr_err;
|
||||
|
@ -247,11 +279,12 @@ int _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
|
|||
state->buffer = new_data;
|
||||
|
||||
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);
|
||||
|
||||
if (TIFFRGBAImageGet(&img, (UINT32 *)state->buffer, img.width, rows_to_read) == -1) {
|
||||
TRACE(("Decode Error, y: %d\n", state->y ));
|
||||
if (TIFFRGBAImageGet(&img, (UINT32 *)state->buffer, img.width, rows_to_read) ==
|
||||
-1) {
|
||||
TRACE(("Decode Error, y: %d\n", state->y));
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
goto decodeycbcr_err;
|
||||
}
|
||||
|
@ -259,20 +292,24 @@ int _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
|
|||
TRACE(("Decoded strip for row %d \n", state->y));
|
||||
|
||||
// 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));
|
||||
|
||||
// UINT8 * bbb = state->buffer + strip_row * (state->bytes / rows_per_strip);
|
||||
// TRACE(("chars: %x %x %x %x\n", ((UINT8 *)bbb)[0], ((UINT8 *)bbb)[1], ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3]));
|
||||
// UINT8 * bbb = state->buffer + strip_row * (state->bytes /
|
||||
// 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->xoff * im->pixelsize,
|
||||
state->buffer + strip_row * row_byte_size,
|
||||
state->xsize);
|
||||
state->shuffle(
|
||||
(UINT8 *)im->image[state->y + state->yoff + strip_row] +
|
||||
state->xoff * im->pixelsize,
|
||||
state->buffer + strip_row * row_byte_size,
|
||||
state->xsize);
|
||||
}
|
||||
}
|
||||
|
||||
decodeycbcr_err:
|
||||
decodeycbcr_err:
|
||||
TIFFRGBAImageEnd(&img);
|
||||
if (state->errcode != 0) {
|
||||
return -1;
|
||||
|
@ -280,7 +317,8 @@ int _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int _decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff) {
|
||||
int
|
||||
_decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff) {
|
||||
INT32 strip_row;
|
||||
UINT8 *new_data;
|
||||
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 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 ...
|
||||
|
||||
state->errcode = IMAGING_CODEC_MEMORY;
|
||||
|
@ -316,7 +355,7 @@ int _decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff) {
|
|||
|
||||
/* realloc to fit whole strip */
|
||||
/* malloc check above */
|
||||
new_data = realloc (state->buffer, state->bytes);
|
||||
new_data = realloc(state->buffer, state->bytes);
|
||||
if (!new_data) {
|
||||
state->errcode = IMAGING_CODEC_MEMORY;
|
||||
return -1;
|
||||
|
@ -325,7 +364,11 @@ int _decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff) {
|
|||
state->buffer = new_data;
|
||||
|
||||
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)));
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
return -1;
|
||||
|
@ -334,46 +377,80 @@ int _decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff) {
|
|||
TRACE(("Decoded strip for row %d \n", state->y));
|
||||
|
||||
// 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));
|
||||
|
||||
// UINT8 * bbb = state->buffer + strip_row * (state->bytes / rows_per_strip);
|
||||
// TRACE(("chars: %x %x %x %x\n", ((UINT8 *)bbb)[0], ((UINT8 *)bbb)[1], ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3]));
|
||||
// UINT8 * bbb = state->buffer + strip_row * (state->bytes /
|
||||
// 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->xoff * im->pixelsize,
|
||||
state->buffer + strip_row * row_byte_size,
|
||||
state->xsize);
|
||||
state->shuffle(
|
||||
(UINT8 *)im->image[state->y + state->yoff + strip_row] +
|
||||
state->xoff * im->pixelsize,
|
||||
state->buffer + strip_row * row_byte_size,
|
||||
state->xsize);
|
||||
}
|
||||
}
|
||||
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;
|
||||
char *filename = "tempfile.tif";
|
||||
char *mode = "r";
|
||||
TIFF *tiff;
|
||||
uint16 photometric = 0; // init to not PHOTOMETRIC_YCBCR
|
||||
uint16 photometric = 0; // init to not PHOTOMETRIC_YCBCR
|
||||
int isYCbCr = 0;
|
||||
|
||||
/* 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 */
|
||||
|
||||
TRACE(("in decoder: bytes %d\n", bytes));
|
||||
TRACE(("State: count %d, state %d, x %d, y %d, ystep %d\n", state->count, 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: count %d, state %d, x %d, y %d, ystep %d\n",
|
||||
state->count,
|
||||
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(("Buffer: %p: %c%c%c%c\n", buffer, (char)buffer[0], (char)buffer[1],(char)buffer[2], (char)buffer[3]));
|
||||
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));
|
||||
TRACE(
|
||||
("Buffer: %p: %c%c%c%c\n",
|
||||
buffer,
|
||||
(char)buffer[0],
|
||||
(char)buffer[1],
|
||||
(char)buffer[2],
|
||||
(char)buffer[3]));
|
||||
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);
|
||||
clientstate->size = bytes;
|
||||
|
@ -387,54 +464,59 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_
|
|||
TIFFSetWarningHandlerExt(NULL);
|
||||
|
||||
if (clientstate->fp) {
|
||||
TRACE(("Opening using fd: %d\n",clientstate->fp));
|
||||
lseek(clientstate->fp,0,SEEK_SET); // Sometimes, I get it set to the end.
|
||||
TRACE(("Opening using fd: %d\n", clientstate->fp));
|
||||
lseek(clientstate->fp, 0, SEEK_SET); // Sometimes, I get it set to the end.
|
||||
tiff = TIFFFdOpen(fd_to_tiff_fd(clientstate->fp), filename, mode);
|
||||
} else {
|
||||
TRACE(("Opening from string\n"));
|
||||
tiff = TIFFClientOpen(filename, mode,
|
||||
(thandle_t) clientstate,
|
||||
_tiffReadProc, _tiffWriteProc,
|
||||
_tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
|
||||
_tiffMapProc, _tiffUnmapProc);
|
||||
tiff = TIFFClientOpen(
|
||||
filename,
|
||||
mode,
|
||||
(thandle_t)clientstate,
|
||||
_tiffReadProc,
|
||||
_tiffWriteProc,
|
||||
_tiffSeekProc,
|
||||
_tiffCloseProc,
|
||||
_tiffSizeProc,
|
||||
_tiffMapProc,
|
||||
_tiffUnmapProc);
|
||||
}
|
||||
|
||||
if (!tiff){
|
||||
if (!tiff) {
|
||||
TRACE(("Error, didn't get the tiff\n"));
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (clientstate->ifd){
|
||||
if (clientstate->ifd) {
|
||||
int rv;
|
||||
uint32 ifdoffset = clientstate->ifd;
|
||||
TRACE(("reading tiff ifd %u\n", ifdoffset));
|
||||
rv = TIFFSetSubDirectory(tiff, ifdoffset);
|
||||
if (!rv){
|
||||
if (!rv) {
|
||||
TRACE(("error in TIFFSetSubDirectory"));
|
||||
goto decode_err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);
|
||||
isYCbCr = photometric == PHOTOMETRIC_YCBCR;
|
||||
|
||||
|
||||
if (TIFFIsTiled(tiff)) {
|
||||
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;
|
||||
|
||||
TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tile_width);
|
||||
TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tile_length);
|
||||
|
||||
/* 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;
|
||||
goto decode_err;
|
||||
}
|
||||
|
||||
|
||||
if (isYCbCr) {
|
||||
row_byte_size = tile_width * 4;
|
||||
/* 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;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
@ -456,14 +539,15 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_
|
|||
state->bytes = row_byte_size * tile_length;
|
||||
|
||||
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;
|
||||
goto decode_err;
|
||||
}
|
||||
|
||||
/* realloc to fit whole tile */
|
||||
/* malloc check above */
|
||||
new_data = realloc (state->buffer, state->bytes);
|
||||
new_data = realloc(state->buffer, state->bytes);
|
||||
if (!new_data) {
|
||||
state->errcode = IMAGING_CODEC_MEMORY;
|
||||
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));
|
||||
|
||||
current_tile_width = min((INT32) tile_width, state->xsize - x);
|
||||
current_tile_length = min((INT32) tile_length, state->ysize - y);
|
||||
current_tile_width = min((INT32)tile_width, state->xsize - x);
|
||||
current_tile_length = min((INT32)tile_length, state->ysize - y);
|
||||
// iterate over each line in the tile and stuff data into image
|
||||
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;
|
||||
// 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
|
||||
* chooses the lower left corner as the origin.
|
||||
|
@ -512,24 +601,23 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_
|
|||
} else {
|
||||
current_line = tile_y;
|
||||
}
|
||||
|
||||
state->shuffle((UINT8*) im->image[tile_y + y] + x * im->pixelsize,
|
||||
state->buffer + current_line * row_byte_size,
|
||||
current_tile_width
|
||||
);
|
||||
|
||||
state->shuffle(
|
||||
(UINT8 *)im->image[tile_y + y] + x * im->pixelsize,
|
||||
state->buffer + current_line * row_byte_size,
|
||||
current_tile_width);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!isYCbCr) {
|
||||
_decodeStrip(im, state, tiff);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_decodeStripYCbCr(im, state, tiff);
|
||||
}
|
||||
}
|
||||
|
||||
decode_err:
|
||||
decode_err:
|
||||
TIFFClose(tiff);
|
||||
TRACE(("Done Decoding, Returning \n"));
|
||||
// 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;
|
||||
}
|
||||
|
||||
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.
|
||||
// We may have to do some monkeying around to make this really work.
|
||||
// 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.
|
||||
|
||||
TIFFSTATE *clientstate = (TIFFSTATE *)state->context;
|
||||
int bufsize = 64*1024;
|
||||
int bufsize = 64 * 1024;
|
||||
char *mode = "w";
|
||||
|
||||
TRACE(("initing libtiff\n"));
|
||||
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,
|
||||
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(("Filename %s, filepointer: %d \n", filename, fp));
|
||||
TRACE(
|
||||
("State: count %d, state %d, x %d, y %d, ystep %d\n",
|
||||
state->count,
|
||||
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: context %p \n", state->context));
|
||||
|
||||
clientstate->loc = 0;
|
||||
clientstate->size = 0;
|
||||
clientstate->eof =0;
|
||||
clientstate->eof = 0;
|
||||
clientstate->data = 0;
|
||||
clientstate->flrealloc = 0;
|
||||
clientstate->fp = fp;
|
||||
|
@ -568,27 +666,33 @@ int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp) {
|
|||
state->state = 0;
|
||||
|
||||
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);
|
||||
} 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"));
|
||||
/* malloc check ok, small constant allocation */
|
||||
clientstate->data = malloc(bufsize);
|
||||
clientstate->size = bufsize;
|
||||
clientstate->flrealloc=1;
|
||||
clientstate->flrealloc = 1;
|
||||
|
||||
if (!clientstate->data) {
|
||||
TRACE(("Error, couldn't allocate a buffer of size %d\n", bufsize));
|
||||
return 0;
|
||||
}
|
||||
|
||||
clientstate->tiff = TIFFClientOpen(filename, mode,
|
||||
(thandle_t) clientstate,
|
||||
_tiffReadProc, _tiffWriteProc,
|
||||
_tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
|
||||
_tiffNullMapProc, _tiffUnmapProc); /*force no mmap*/
|
||||
|
||||
clientstate->tiff = TIFFClientOpen(
|
||||
filename,
|
||||
mode,
|
||||
(thandle_t)clientstate,
|
||||
_tiffReadProc,
|
||||
_tiffWriteProc,
|
||||
_tiffSeekProc,
|
||||
_tiffCloseProc,
|
||||
_tiffSizeProc,
|
||||
_tiffNullMapProc,
|
||||
_tiffUnmapProc); /*force no mmap*/
|
||||
}
|
||||
|
||||
if (!clientstate->tiff) {
|
||||
|
@ -597,10 +701,11 @@ int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp) {
|
|||
}
|
||||
|
||||
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)
|
||||
TIFFSTATE *clientstate = (TIFFSTATE *)state->context;
|
||||
uint32 n;
|
||||
|
@ -615,8 +720,14 @@ int ImagingLibTiffMergeFieldInfo(ImagingCodecState state, TIFFDataType field_typ
|
|||
int passcount = 0;
|
||||
|
||||
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) {
|
||||
info[0].field_writecount = -1;
|
||||
|
@ -629,7 +740,8 @@ int ImagingLibTiffMergeFieldInfo(ImagingCodecState state, TIFFDataType field_typ
|
|||
n = sizeof(info) / sizeof(info[0]);
|
||||
|
||||
// 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);
|
||||
#else
|
||||
TIFFMergeFieldInfo(clientstate->tiff, info, n);
|
||||
|
@ -637,7 +749,8 @@ int ImagingLibTiffMergeFieldInfo(ImagingCodecState state, TIFFDataType field_typ
|
|||
return status;
|
||||
}
|
||||
|
||||
int ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...){
|
||||
int
|
||||
ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...) {
|
||||
// after tif_dir.c->TIFFSetField.
|
||||
TIFFSTATE *clientstate = (TIFFSTATE *)state->context;
|
||||
va_list ap;
|
||||
|
@ -649,8 +762,8 @@ int ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...){
|
|||
return status;
|
||||
}
|
||||
|
||||
|
||||
int ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8* buffer, int bytes) {
|
||||
int
|
||||
ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int bytes) {
|
||||
/* 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
|
||||
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;
|
||||
|
||||
TRACE(("in encoder: bytes %d\n", bytes));
|
||||
TRACE(("State: count %d, state %d, x %d, y %d, ystep %d\n", state->count, 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: count %d, state %d, x %d, y %d, ystep %d\n",
|
||||
state->count,
|
||||
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(("Buffer: %p: %c%c%c%c\n", buffer, (char)buffer[0], (char)buffer[1],(char)buffer[2], (char)buffer[3]));
|
||||
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));
|
||||
TRACE(
|
||||
("Buffer: %p: %c%c%c%c\n",
|
||||
buffer,
|
||||
(char)buffer[0],
|
||||
(char)buffer[1],
|
||||
(char)buffer[2],
|
||||
(char)buffer[3]));
|
||||
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);
|
||||
|
||||
if (state->state == 0) {
|
||||
TRACE(("Encoding line bt line"));
|
||||
while(state->y < state->ysize){
|
||||
state->shuffle(state->buffer,
|
||||
(UINT8*) im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize,
|
||||
state->xsize);
|
||||
while (state->y < state->ysize) {
|
||||
state->shuffle(
|
||||
state->buffer,
|
||||
(UINT8 *)im->image[state->y + state->yoff] +
|
||||
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));
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
TIFFClose(tiff);
|
||||
if (!clientstate->fp){
|
||||
if (!clientstate->fp) {
|
||||
free(clientstate->data);
|
||||
}
|
||||
return -1;
|
||||
|
@ -701,7 +844,7 @@ int ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8* buffer, int
|
|||
}
|
||||
|
||||
if (state->y == state->ysize) {
|
||||
state->state=1;
|
||||
state->state = 1;
|
||||
|
||||
TRACE(("Flushing \n"));
|
||||
if (!TIFFFlush(tiff)) {
|
||||
|
@ -709,7 +852,7 @@ int ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8* buffer, int
|
|||
// likely reason is memory.
|
||||
state->errcode = IMAGING_CODEC_MEMORY;
|
||||
TIFFClose(tiff);
|
||||
if (!clientstate->fp){
|
||||
if (!clientstate->fp) {
|
||||
free(clientstate->data);
|
||||
}
|
||||
return -1;
|
||||
|
@ -718,13 +861,19 @@ int ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8* buffer, int
|
|||
TIFFClose(tiff);
|
||||
// reset the clientstate metadata to use it to read out the buffer.
|
||||
clientstate->loc = 0;
|
||||
clientstate->size = clientstate->eof; // redundant?
|
||||
clientstate->size = clientstate->eof; // redundant?
|
||||
}
|
||||
}
|
||||
|
||||
if (state->state == 1 && !clientstate->fp) {
|
||||
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) {
|
||||
TRACE(("Hit EOF, calling an end, freeing data"));
|
||||
state->errcode = IMAGING_CODEC_END;
|
||||
|
@ -737,9 +886,8 @@ int ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8* buffer, int
|
|||
return 0;
|
||||
}
|
||||
|
||||
const char*
|
||||
ImagingTiffVersion(void)
|
||||
{
|
||||
const char *
|
||||
ImagingTiffVersion(void) {
|
||||
return TIFFGetVersion();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
*/
|
||||
|
||||
#ifndef min
|
||||
#define min(x,y) (( x > y ) ? y : x )
|
||||
#define max(x,y) (( x < y ) ? y : x )
|
||||
#define min(x, y) ((x > y) ? y : x)
|
||||
#define max(x, y) ((x < y) ? y : x)
|
||||
#endif
|
||||
|
||||
#ifndef _PIL_LIBTIFF_
|
||||
|
@ -32,22 +32,24 @@ typedef struct {
|
|||
toff_t loc; /* toff_t == uint32 */
|
||||
tsize_t size; /* tsize_t == int32 */
|
||||
int fp;
|
||||
uint32 ifd; /* offset of the ifd, used for multipage
|
||||
* Should be uint32 for libtiff 3.9.x
|
||||
* uint64 for libtiff 4.0.x
|
||||
*/
|
||||
TIFF *tiff; /* Used in write */
|
||||
uint32 ifd; /* offset of the ifd, used for multipage
|
||||
* Should be uint32 for libtiff 3.9.x
|
||||
* uint64 for libtiff 4.0.x
|
||||
*/
|
||||
TIFF *tiff; /* Used in write */
|
||||
toff_t eof;
|
||||
int flrealloc;/* may we realloc */
|
||||
int flrealloc; /* may we realloc */
|
||||
} TIFFSTATE;
|
||||
|
||||
|
||||
|
||||
extern int ImagingLibTiffInit(ImagingCodecState state, int fp, uint32 offset);
|
||||
extern int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp);
|
||||
extern int ImagingLibTiffMergeFieldInfo(ImagingCodecState state, TIFFDataType field_type, int key, int is_var_length);
|
||||
extern int ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...);
|
||||
|
||||
extern int
|
||||
ImagingLibTiffInit(ImagingCodecState state, int fp, uint32 offset);
|
||||
extern int
|
||||
ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp);
|
||||
extern int
|
||||
ImagingLibTiffMergeFieldInfo(
|
||||
ImagingCodecState state, TIFFDataType field_type, int key, int is_var_length);
|
||||
extern int
|
||||
ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...);
|
||||
|
||||
/*
|
||||
Trace debugging
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -13,150 +13,151 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
/* Tables generated by pcdtables.py, based on transforms taken from
|
||||
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,
|
||||
19, 20, 22, 23, 24, 26, 27, 29, 30, 31, 33, 34, 35, 37, 38, 39, 41,
|
||||
42, 43, 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 60, 61, 62, 64,
|
||||
65, 67, 68, 69, 71, 72, 73, 75, 76, 77, 79, 80, 82, 83, 84, 86, 87,
|
||||
88, 90, 91, 92, 94, 95, 96, 98, 99, 101, 102, 103, 105, 106, 107, 109,
|
||||
110, 111, 113, 114, 115, 117, 118, 120, 121, 122, 124, 125, 126, 128,
|
||||
129, 130, 132, 133, 134, 136, 137, 139, 140, 141, 143, 144, 145, 147,
|
||||
148, 149, 151, 152, 153, 155, 156, 158, 159, 160, 162, 163, 164, 166,
|
||||
167, 168, 170, 171, 173, 174, 175, 177, 178, 179, 181, 182, 183, 185,
|
||||
186, 187, 189, 190, 192, 193, 194, 196, 197, 198, 200, 201, 202, 204,
|
||||
205, 206, 208, 209, 211, 212, 213, 215, 216, 217, 219, 220, 221, 223,
|
||||
224, 225, 227, 228, 230, 231, 232, 234, 235, 236, 238, 239, 240, 242,
|
||||
243, 245, 246, 247, 249, 250, 251, 253, 254, 255, 257, 258, 259, 261,
|
||||
262, 264, 265, 266, 268, 269, 270, 272, 273, 274, 276, 277, 278, 280,
|
||||
281, 283, 284, 285, 287, 288, 289, 291, 292, 293, 295, 296, 297, 299,
|
||||
300, 302, 303, 304, 306, 307, 308, 310, 311, 312, 314, 315, 317, 318,
|
||||
319, 321, 322, 323, 325, 326, 327, 329, 330, 331, 333, 334, 336, 337,
|
||||
338, 340, 341, 342, 344, 345, 346 };
|
||||
static INT16 L[] = {
|
||||
0, 1, 3, 4, 5, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 20,
|
||||
22, 23, 24, 26, 27, 29, 30, 31, 33, 34, 35, 37, 38, 39, 41, 42,
|
||||
43, 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 60, 61, 62, 64,
|
||||
65, 67, 68, 69, 71, 72, 73, 75, 76, 77, 79, 80, 82, 83, 84, 86,
|
||||
87, 88, 90, 91, 92, 94, 95, 96, 98, 99, 101, 102, 103, 105, 106, 107,
|
||||
109, 110, 111, 113, 114, 115, 117, 118, 120, 121, 122, 124, 125, 126, 128, 129,
|
||||
130, 132, 133, 134, 136, 137, 139, 140, 141, 143, 144, 145, 147, 148, 149, 151,
|
||||
152, 153, 155, 156, 158, 159, 160, 162, 163, 164, 166, 167, 168, 170, 171, 173,
|
||||
174, 175, 177, 178, 179, 181, 182, 183, 185, 186, 187, 189, 190, 192, 193, 194,
|
||||
196, 197, 198, 200, 201, 202, 204, 205, 206, 208, 209, 211, 212, 213, 215, 216,
|
||||
217, 219, 220, 221, 223, 224, 225, 227, 228, 230, 231, 232, 234, 235, 236, 238,
|
||||
239, 240, 242, 243, 245, 246, 247, 249, 250, 251, 253, 254, 255, 257, 258, 259,
|
||||
261, 262, 264, 265, 266, 268, 269, 270, 272, 273, 274, 276, 277, 278, 280, 281,
|
||||
283, 284, 285, 287, 288, 289, 291, 292, 293, 295, 296, 297, 299, 300, 302, 303,
|
||||
304, 306, 307, 308, 310, 311, 312, 314, 315, 317, 318, 319, 321, 322, 323, 325,
|
||||
326, 327, 329, 330, 331, 333, 334, 336, 337, 338, 340, 341, 342, 344, 345, 346};
|
||||
|
||||
static INT16 CB[] = { -345, -343, -341, -338, -336, -334, -332, -329,
|
||||
-327, -325, -323, -321, -318, -316, -314, -312, -310, -307, -305,
|
||||
-303, -301, -298, -296, -294, -292, -290, -287, -285, -283, -281,
|
||||
-278, -276, -274, -272, -270, -267, -265, -263, -261, -258, -256,
|
||||
-254, -252, -250, -247, -245, -243, -241, -239, -236, -234, -232,
|
||||
-230, -227, -225, -223, -221, -219, -216, -214, -212, -210, -207,
|
||||
-205, -203, -201, -199, -196, -194, -192, -190, -188, -185, -183,
|
||||
-181, -179, -176, -174, -172, -170, -168, -165, -163, -161, -159,
|
||||
-156, -154, -152, -150, -148, -145, -143, -141, -139, -137, -134,
|
||||
-132, -130, -128, -125, -123, -121, -119, -117, -114, -112, -110,
|
||||
-108, -105, -103, -101, -99, -97, -94, -92, -90, -88, -85, -83, -81,
|
||||
-79, -77, -74, -72, -70, -68, -66, -63, -61, -59, -57, -54, -52, -50,
|
||||
-48, -46, -43, -41, -39, -37, -34, -32, -30, -28, -26, -23, -21, -19,
|
||||
-17, -15, -12, -10, -8, -6, -3, -1, 0, 2, 4, 7, 9, 11, 13, 16, 18, 20,
|
||||
22, 24, 27, 29, 31, 33, 35, 38, 40, 42, 44, 47, 49, 51, 53, 55, 58,
|
||||
60, 62, 64, 67, 69, 71, 73, 75, 78, 80, 82, 84, 86, 89, 91, 93, 95,
|
||||
98, 100, 102, 104, 106, 109, 111, 113, 115, 118, 120, 122, 124, 126,
|
||||
129, 131, 133, 135, 138, 140, 142, 144, 146, 149, 151, 153, 155, 157,
|
||||
160, 162, 164, 166, 169, 171, 173, 175, 177, 180, 182, 184, 186, 189,
|
||||
191, 193, 195, 197, 200, 202, 204, 206, 208, 211, 213, 215, 217, 220 };
|
||||
static INT16 CB[] = {
|
||||
-345, -343, -341, -338, -336, -334, -332, -329, -327, -325, -323, -321, -318, -316,
|
||||
-314, -312, -310, -307, -305, -303, -301, -298, -296, -294, -292, -290, -287, -285,
|
||||
-283, -281, -278, -276, -274, -272, -270, -267, -265, -263, -261, -258, -256, -254,
|
||||
-252, -250, -247, -245, -243, -241, -239, -236, -234, -232, -230, -227, -225, -223,
|
||||
-221, -219, -216, -214, -212, -210, -207, -205, -203, -201, -199, -196, -194, -192,
|
||||
-190, -188, -185, -183, -181, -179, -176, -174, -172, -170, -168, -165, -163, -161,
|
||||
-159, -156, -154, -152, -150, -148, -145, -143, -141, -139, -137, -134, -132, -130,
|
||||
-128, -125, -123, -121, -119, -117, -114, -112, -110, -108, -105, -103, -101, -99,
|
||||
-97, -94, -92, -90, -88, -85, -83, -81, -79, -77, -74, -72, -70, -68,
|
||||
-66, -63, -61, -59, -57, -54, -52, -50, -48, -46, -43, -41, -39, -37,
|
||||
-34, -32, -30, -28, -26, -23, -21, -19, -17, -15, -12, -10, -8, -6,
|
||||
-3, -1, 0, 2, 4, 7, 9, 11, 13, 16, 18, 20, 22, 24,
|
||||
27, 29, 31, 33, 35, 38, 40, 42, 44, 47, 49, 51, 53, 55,
|
||||
58, 60, 62, 64, 67, 69, 71, 73, 75, 78, 80, 82, 84, 86,
|
||||
89, 91, 93, 95, 98, 100, 102, 104, 106, 109, 111, 113, 115, 118,
|
||||
120, 122, 124, 126, 129, 131, 133, 135, 138, 140, 142, 144, 146, 149,
|
||||
151, 153, 155, 157, 160, 162, 164, 166, 169, 171, 173, 175, 177, 180,
|
||||
182, 184, 186, 189, 191, 193, 195, 197, 200, 202, 204, 206, 208, 211,
|
||||
213, 215, 217, 220};
|
||||
|
||||
static INT16 GB[] = { 67, 67, 66, 66, 65, 65, 65, 64, 64, 63, 63, 62,
|
||||
62, 62, 61, 61, 60, 60, 59, 59, 59, 58, 58, 57, 57, 56, 56, 56, 55,
|
||||
55, 54, 54, 53, 53, 52, 52, 52, 51, 51, 50, 50, 49, 49, 49, 48, 48,
|
||||
47, 47, 46, 46, 46, 45, 45, 44, 44, 43, 43, 43, 42, 42, 41, 41, 40,
|
||||
40, 40, 39, 39, 38, 38, 37, 37, 37, 36, 36, 35, 35, 34, 34, 34, 33,
|
||||
33, 32, 32, 31, 31, 31, 30, 30, 29, 29, 28, 28, 28, 27, 27, 26, 26,
|
||||
25, 25, 25, 24, 24, 23, 23, 22, 22, 22, 21, 21, 20, 20, 19, 19, 19,
|
||||
18, 18, 17, 17, 16, 16, 15, 15, 15, 14, 14, 13, 13, 12, 12, 12, 11,
|
||||
11, 10, 10, 9, 9, 9, 8, 8, 7, 7, 6, 6, 6, 5, 5, 4, 4, 3, 3, 3, 2, 2,
|
||||
1, 1, 0, 0, 0, 0, 0, -1, -1, -2, -2, -2, -3, -3, -4, -4, -5, -5, -5,
|
||||
-6, -6, -7, -7, -8, -8, -8, -9, -9, -10, -10, -11, -11, -11, -12, -12,
|
||||
-13, -13, -14, -14, -14, -15, -15, -16, -16, -17, -17, -18, -18, -18,
|
||||
-19, -19, -20, -20, -21, -21, -21, -22, -22, -23, -23, -24, -24, -24,
|
||||
-25, -25, -26, -26, -27, -27, -27, -28, -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 GB[] = {
|
||||
67, 67, 66, 66, 65, 65, 65, 64, 64, 63, 63, 62, 62, 62, 61, 61,
|
||||
60, 60, 59, 59, 59, 58, 58, 57, 57, 56, 56, 56, 55, 55, 54, 54,
|
||||
53, 53, 52, 52, 52, 51, 51, 50, 50, 49, 49, 49, 48, 48, 47, 47,
|
||||
46, 46, 46, 45, 45, 44, 44, 43, 43, 43, 42, 42, 41, 41, 40, 40,
|
||||
40, 39, 39, 38, 38, 37, 37, 37, 36, 36, 35, 35, 34, 34, 34, 33,
|
||||
33, 32, 32, 31, 31, 31, 30, 30, 29, 29, 28, 28, 28, 27, 27, 26,
|
||||
26, 25, 25, 25, 24, 24, 23, 23, 22, 22, 22, 21, 21, 20, 20, 19,
|
||||
19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 15, 14, 14, 13, 13, 12,
|
||||
12, 12, 11, 11, 10, 10, 9, 9, 9, 8, 8, 7, 7, 6, 6, 6,
|
||||
5, 5, 4, 4, 3, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0,
|
||||
-1, -1, -2, -2, -2, -3, -3, -4, -4, -5, -5, -5, -6, -6, -7, -7,
|
||||
-8, -8, -8, -9, -9, -10, -10, -11, -11, -11, -12, -12, -13, -13, -14, -14,
|
||||
-14, -15, -15, -16, -16, -17, -17, -18, -18, -18, -19, -19, -20, -20, -21, -21,
|
||||
-21, -22, -22, -23, -23, -24, -24, -24, -25, -25, -26, -26, -27, -27, -27, -28,
|
||||
-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,
|
||||
-234, -232, -230, -229, -227, -225, -223, -221, -219, -218, -216,
|
||||
-214, -212, -210, -208, -207, -205, -203, -201, -199, -198, -196,
|
||||
-194, -192, -190, -188, -187, -185, -183, -181, -179, -178, -176,
|
||||
-174, -172, -170, -168, -167, -165, -163, -161, -159, -157, -156,
|
||||
-154, -152, -150, -148, -147, -145, -143, -141, -139, -137, -136,
|
||||
-134, -132, -130, -128, -127, -125, -123, -121, -119, -117, -116,
|
||||
-114, -112, -110, -108, -106, -105, -103, -101, -99, -97, -96, -94,
|
||||
-92, -90, -88, -86, -85, -83, -81, -79, -77, -76, -74, -72, -70, -68,
|
||||
-66, -65, -63, -61, -59, -57, -55, -54, -52, -50, -48, -46, -45, -43,
|
||||
-41, -39, -37, -35, -34, -32, -30, -28, -26, -25, -23, -21, -19, -17,
|
||||
-15, -14, -12, -10, -8, -6, -4, -3, -1, 0, 2, 4, 5, 7, 9, 11, 13, 15,
|
||||
16, 18, 20, 22, 24, 26, 27, 29, 31, 33, 35, 36, 38, 40, 42, 44, 46,
|
||||
47, 49, 51, 53, 55, 56, 58, 60, 62, 64, 66, 67, 69, 71, 73, 75, 77,
|
||||
78, 80, 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,
|
||||
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,
|
||||
184, 186, 188, 189, 191, 193, 195, 197, 199, 200, 202, 204, 206, 208,
|
||||
209, 211, 213, 215 };
|
||||
static INT16 CR[] = {
|
||||
-249, -247, -245, -243, -241, -239, -238, -236, -234, -232, -230, -229, -227, -225,
|
||||
-223, -221, -219, -218, -216, -214, -212, -210, -208, -207, -205, -203, -201, -199,
|
||||
-198, -196, -194, -192, -190, -188, -187, -185, -183, -181, -179, -178, -176, -174,
|
||||
-172, -170, -168, -167, -165, -163, -161, -159, -157, -156, -154, -152, -150, -148,
|
||||
-147, -145, -143, -141, -139, -137, -136, -134, -132, -130, -128, -127, -125, -123,
|
||||
-121, -119, -117, -116, -114, -112, -110, -108, -106, -105, -103, -101, -99, -97,
|
||||
-96, -94, -92, -90, -88, -86, -85, -83, -81, -79, -77, -76, -74, -72,
|
||||
-70, -68, -66, -65, -63, -61, -59, -57, -55, -54, -52, -50, -48, -46,
|
||||
-45, -43, -41, -39, -37, -35, -34, -32, -30, -28, -26, -25, -23, -21,
|
||||
-19, -17, -15, -14, -12, -10, -8, -6, -4, -3, -1, 0, 2, 4,
|
||||
5, 7, 9, 11, 13, 15, 16, 18, 20, 22, 24, 26, 27, 29,
|
||||
31, 33, 35, 36, 38, 40, 42, 44, 46, 47, 49, 51, 53, 55,
|
||||
56, 58, 60, 62, 64, 66, 67, 69, 71, 73, 75, 77, 78, 80,
|
||||
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,
|
||||
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,
|
||||
184, 186, 188, 189, 191, 193, 195, 197, 199, 200, 202, 204, 206, 208,
|
||||
209, 211, 213, 215};
|
||||
|
||||
static INT16 GR[] = { 127, 126, 125, 124, 123, 122, 121, 121, 120, 119,
|
||||
118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 108, 107, 106,
|
||||
105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 95, 94, 93, 92, 91,
|
||||
90, 89, 88, 87, 86, 85, 84, 83, 83, 82, 81, 80, 79, 78, 77, 76, 75,
|
||||
74, 73, 72, 71, 70, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59,
|
||||
58, 57, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 45, 44,
|
||||
43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 32, 31, 30, 29, 28,
|
||||
27, 26, 25, 24, 23, 22, 21, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12,
|
||||
11, 10, 9, 8, 7, 6, 6, 5, 4, 3, 2, 1, 0, 0, -1, -2, -3, -4, -5, -5,
|
||||
-6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -18, -19,
|
||||
-20, -21, -22, -23, -24, -25, -26, -27, -28, -29, -30, -31, -31, -32,
|
||||
-33, -34, -35, -36, -37, -38, -39, -40, -41, -42, -43, -44, -44, -45,
|
||||
-46, -47, -48, -49, -50, -51, -52, -53, -54, -55, -56, -56, -57, -58,
|
||||
-59, -60, -61, -62, -63, -64, -65, -66, -67, -68, -69, -69, -70, -71,
|
||||
-72, -73, -74, -75, -76, -77, -78, -79, -80, -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 };
|
||||
static INT16 GR[] = {
|
||||
127, 126, 125, 124, 123, 122, 121, 121, 120, 119, 118, 117, 116, 115, 114,
|
||||
113, 112, 111, 110, 109, 108, 108, 107, 106, 105, 104, 103, 102, 101, 100,
|
||||
99, 98, 97, 96, 95, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86,
|
||||
85, 84, 83, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72,
|
||||
71, 70, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58,
|
||||
57, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 45,
|
||||
44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 32, 31,
|
||||
30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 19, 18, 17,
|
||||
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 6, 5, 4, 3,
|
||||
2, 1, 0, 0, -1, -2, -3, -4, -5, -5, -6, -7, -8, -9, -10,
|
||||
-11, -12, -13, -14, -15, -16, -17, -18, -18, -19, -20, -21, -22, -23, -24,
|
||||
-25, -26, -27, -28, -29, -30, -31, -31, -32, -33, -34, -35, -36, -37, -38,
|
||||
-39, -40, -41, -42, -43, -44, -44, -45, -46, -47, -48, -49, -50, -51, -52,
|
||||
-53, -54, -55, -56, -56, -57, -58, -59, -60, -61, -62, -63, -64, -65, -66,
|
||||
-67, -68, -69, -69, -70, -71, -72, -73, -74, -75, -76, -77, -78, -79, -80,
|
||||
-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 G 1
|
||||
#define B 2
|
||||
#define A 3
|
||||
|
||||
#define YCC2RGB(rgb, y, cb, cr) {\
|
||||
int l = L[y];\
|
||||
int r = l + CR[cr];\
|
||||
int g = l + GR[cr] + GB[cb];\
|
||||
int b = l + CB[cb];\
|
||||
rgb[0] = (r <= 0) ? 0 : (r >= 255) ? 255 : r;\
|
||||
rgb[1] = (g <= 0) ? 0 : (g >= 255) ? 255 : g;\
|
||||
rgb[2] = (b <= 0) ? 0 : (b >= 255) ? 255 : b;\
|
||||
}
|
||||
#define YCC2RGB(rgb, y, cb, cr) \
|
||||
{ \
|
||||
int l = L[y]; \
|
||||
int r = l + CR[cr]; \
|
||||
int g = l + GR[cr] + GB[cb]; \
|
||||
int b = l + CB[cb]; \
|
||||
rgb[0] = (r <= 0) ? 0 : (r >= 255) ? 255 : r; \
|
||||
rgb[1] = (g <= 0) ? 0 : (g >= 255) ? 255 : g; \
|
||||
rgb[2] = (b <= 0) ? 0 : (b >= 255) ? 255 : b; \
|
||||
}
|
||||
|
||||
void
|
||||
ImagingUnpackYCC(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
ImagingUnpackYCC(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* PhotoYCC triplets */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
YCC2RGB(out, in[0], in[1], in[2]);
|
||||
out[A] = 255;
|
||||
out += 4; in += 3;
|
||||
out += 4;
|
||||
in += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ImagingUnpackYCCA(UINT8* out, const UINT8* in, int pixels)
|
||||
{
|
||||
ImagingUnpackYCCA(UINT8 *out, const UINT8 *in, int pixels) {
|
||||
int i;
|
||||
/* PhotoYCC triplets plus premultiplied alpha */
|
||||
for (i = 0; i < pixels; i++) {
|
||||
/* Divide by alpha */
|
||||
UINT8 rgb[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[2] = (in[3] == 0) ? 0 : (((int) in[2] * 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[2] = (in[3] == 0) ? 0 : (((int)in[2] * 255) / in[3]);
|
||||
/* Convert non-multiplied data to RGB */
|
||||
YCC2RGB(out, rgb[0], rgb[1], rgb[2]);
|
||||
out[A] = in[3];
|
||||
out += 4; in += 4;
|
||||
out += 4;
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,26 +8,22 @@
|
|||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
typedef UINT8 pixel[4];
|
||||
|
||||
|
||||
static inline UINT8 clip8(int in)
|
||||
{
|
||||
static inline UINT8
|
||||
clip8(int in) {
|
||||
if (in >= 255) {
|
||||
return 255;
|
||||
return 255;
|
||||
}
|
||||
if (in <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return (UINT8) in;
|
||||
return (UINT8)in;
|
||||
}
|
||||
|
||||
|
||||
Imaging
|
||||
ImagingUnsharpMask(Imaging imOut, Imaging imIn, float radius, int percent,
|
||||
int threshold)
|
||||
{
|
||||
ImagingUnsharpMask(
|
||||
Imaging imOut, Imaging imIn, float radius, int percent, int threshold) {
|
||||
ImagingSectionCookie cookie;
|
||||
Imaging result;
|
||||
|
||||
|
@ -53,8 +49,7 @@ ImagingUnsharpMask(Imaging imOut, Imaging imIn, float radius, int percent,
|
|||
ImagingSectionEnter(&cookie);
|
||||
|
||||
for (y = 0; y < imIn->ysize; y++) {
|
||||
if (imIn->image8)
|
||||
{
|
||||
if (imIn->image8) {
|
||||
lineIn8 = imIn->image8[y];
|
||||
lineOut8 = imOut->image8[y];
|
||||
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++) {
|
||||
/* compare in/out pixels, apply sharpening */
|
||||
diff = lineIn[x][0] - lineOut[x][0];
|
||||
lineOut[x][0] = abs(diff) > threshold ?
|
||||
clip8(lineIn[x][0] + diff * percent / 100) : lineIn[x][0];
|
||||
lineOut[x][0] = abs(diff) > threshold
|
||||
? clip8(lineIn[x][0] + diff * percent / 100)
|
||||
: lineIn[x][0];
|
||||
|
||||
diff = lineIn[x][1] - lineOut[x][1];
|
||||
lineOut[x][1] = abs(diff) > threshold ?
|
||||
clip8(lineIn[x][1] + diff * percent / 100) : lineIn[x][1];
|
||||
lineOut[x][1] = abs(diff) > threshold
|
||||
? clip8(lineIn[x][1] + diff * percent / 100)
|
||||
: lineIn[x][1];
|
||||
|
||||
diff = lineIn[x][2] - lineOut[x][2];
|
||||
lineOut[x][2] = abs(diff) > threshold ?
|
||||
clip8(lineIn[x][2] + diff * percent / 100) : lineIn[x][2];
|
||||
lineOut[x][2] = abs(diff) > threshold
|
||||
? clip8(lineIn[x][2] + diff * percent / 100)
|
||||
: lineIn[x][2];
|
||||
|
||||
diff = lineIn[x][3] - lineOut[x][3];
|
||||
lineOut[x][3] = abs(diff) > threshold ?
|
||||
clip8(lineIn[x][3] + diff * percent / 100) : lineIn[x][3];
|
||||
lineOut[x][3] = abs(diff) > threshold
|
||||
? clip8(lineIn[x][3] + diff * percent / 100)
|
||||
: lineIn[x][3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,19 +13,19 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#define HEX(v) ((v >= '0' && v <= '9') ? v - '0' :\
|
||||
(v >= 'a' && v <= 'f') ? v - 'a' + 10 :\
|
||||
(v >= 'A' && v <= 'F') ? v - 'A' + 10 : 0)
|
||||
#define HEX(v) \
|
||||
((v >= '0' && v <= '9') ? v - '0' \
|
||||
: (v >= 'a' && v <= 'f') ? v - 'a' + 10 \
|
||||
: (v >= 'A' && v <= 'F') ? v - 'A' + 10 \
|
||||
: 0)
|
||||
|
||||
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 };
|
||||
|
||||
UINT8* ptr;
|
||||
UINT8 *ptr;
|
||||
|
||||
if (!state->state) {
|
||||
state->state = SKIP;
|
||||
|
@ -34,9 +34,7 @@ ImagingXbmDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
ptr = buf;
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (state->state == SKIP) {
|
||||
|
||||
/* Skip forward until next 'x' */
|
||||
|
||||
while (bytes > 0) {
|
||||
|
@ -52,20 +50,17 @@ ImagingXbmDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
}
|
||||
|
||||
state->state = BYTE;
|
||||
|
||||
}
|
||||
|
||||
if (bytes < 3) {
|
||||
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) {
|
||||
|
||||
/* Got a full line, unpack it */
|
||||
state->shuffle((UINT8*) im->image[state->y], state->buffer,
|
||||
state->xsize);
|
||||
state->shuffle((UINT8 *)im->image[state->y], state->buffer, state->xsize);
|
||||
|
||||
state->x = 0;
|
||||
|
||||
|
@ -79,7 +74,5 @@ ImagingXbmDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
bytes -= 3;
|
||||
|
||||
state->state = SKIP;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,25 +13,20 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
int
|
||||
ImagingXbmEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||
{
|
||||
ImagingXbmEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
|
||||
const char *hex = "0123456789abcdef";
|
||||
|
||||
UINT8* ptr = buf;
|
||||
UINT8 *ptr = buf;
|
||||
int i, n;
|
||||
|
||||
if (!state->state) {
|
||||
|
||||
/* 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;
|
||||
|
||||
}
|
||||
|
||||
if (bytes < state->bytes) {
|
||||
|
@ -42,60 +37,54 @@ ImagingXbmEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
ptr = buf;
|
||||
|
||||
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,
|
||||
(UINT8*) im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize, state->xsize);
|
||||
|
||||
if (state->y < state->ysize-1) {
|
||||
|
||||
if (state->y < state->ysize - 1) {
|
||||
/* any line but the last */
|
||||
for (n = 0; n < state->xsize; n += 8) {
|
||||
|
||||
i = state->buffer[n/8];
|
||||
i = state->buffer[n / 8];
|
||||
|
||||
*ptr++ = '0';
|
||||
*ptr++ = 'x';
|
||||
*ptr++ = hex[(i>>4)&15];
|
||||
*ptr++ = hex[i&15];
|
||||
*ptr++ = hex[(i >> 4) & 15];
|
||||
*ptr++ = hex[i & 15];
|
||||
*ptr++ = ',';
|
||||
bytes -= 5;
|
||||
|
||||
if (++state->count >= 79/5) {
|
||||
if (++state->count >= 79 / 5) {
|
||||
*ptr++ = '\n';
|
||||
bytes--;
|
||||
state->count = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
state->y++;
|
||||
|
||||
} else {
|
||||
|
||||
/* last line */
|
||||
for (n = 0; n < state->xsize; n += 8) {
|
||||
|
||||
i = state->buffer[n/8];
|
||||
i = state->buffer[n / 8];
|
||||
|
||||
*ptr++ = '0';
|
||||
*ptr++ = 'x';
|
||||
*ptr++ = hex[(i>>4)&15];
|
||||
*ptr++ = hex[i&15];
|
||||
*ptr++ = hex[(i >> 4) & 15];
|
||||
*ptr++ = hex[i & 15];
|
||||
|
||||
if (n < state->xsize-8) {
|
||||
if (n < state->xsize - 8) {
|
||||
*ptr++ = ',';
|
||||
if (++state->count >= 79/5) {
|
||||
*ptr++ = '\n';
|
||||
bytes--;
|
||||
state->count = 0;
|
||||
if (++state->count >= 79 / 5) {
|
||||
*ptr++ = '\n';
|
||||
bytes--;
|
||||
state->count = 0;
|
||||
}
|
||||
} else {
|
||||
*ptr++ = '\n';
|
||||
}
|
||||
|
||||
bytes -= 5;
|
||||
|
||||
}
|
||||
|
||||
state->errcode = IMAGING_CODEC_END;
|
||||
|
|
|
@ -7,19 +7,15 @@
|
|||
* Copyright (c) Fredrik Lundh 1996.
|
||||
*/
|
||||
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
|
||||
/* modes */
|
||||
#define ZIP_PNG 0 /* continuous, filtered image data */
|
||||
#define ZIP_PNG_PALETTE 1 /* non-continuous data, disable filtering */
|
||||
#define ZIP_TIFF_PREDICTOR 2 /* TIFF, with predictor */
|
||||
#define ZIP_TIFF 3 /* TIFF, without predictor */
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* CONFIGURATION */
|
||||
|
||||
/* Codec mode */
|
||||
|
@ -34,29 +30,29 @@ typedef struct {
|
|||
int compress_type;
|
||||
|
||||
/* Predefined dictionary (experimental) */
|
||||
char* dictionary;
|
||||
char *dictionary;
|
||||
int dictionary_size;
|
||||
|
||||
/* 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 */
|
||||
UINT8* prior; /* filter storage (allocated) */
|
||||
UINT8* up;
|
||||
UINT8* average;
|
||||
UINT8* paeth;
|
||||
UINT8 *prior; /* filter storage (allocated) */
|
||||
UINT8 *up;
|
||||
UINT8 *average;
|
||||
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;
|
||||
|
|
|
@ -15,23 +15,22 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
#ifdef HAVE_LIBZ
|
||||
|
||||
#include "ZipCodecs.h"
|
||||
|
||||
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_ROW[] = { 0, 0, 4, 0, 2, 0, 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 OFFSET[] = {7, 3, 3, 1, 1, 0, 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 COL_INCREMENT[] = {8, 8, 4, 4, 2, 2, 1};
|
||||
static const int ROW_INCREMENT[] = {8, 8, 8, 4, 4, 2, 2};
|
||||
|
||||
/* Get the length in bytes of a scanline in the pass specified,
|
||||
* 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];
|
||||
return ((row_len * state->bits) + 7) / 8;
|
||||
}
|
||||
|
@ -41,17 +40,15 @@ static int get_row_len(ImagingCodecState state, int pass)
|
|||
/* -------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes)
|
||||
{
|
||||
ZIPSTATE* context = (ZIPSTATE*) state->context;
|
||||
ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
|
||||
ZIPSTATE *context = (ZIPSTATE *)state->context;
|
||||
int err;
|
||||
int n;
|
||||
UINT8* ptr;
|
||||
UINT8 *ptr;
|
||||
int i, bpp;
|
||||
int row_len;
|
||||
|
||||
if (!state->state) {
|
||||
|
||||
/* Initialization */
|
||||
if (context->mode == ZIP_PNG || context->mode == ZIP_PNG_PALETTE) {
|
||||
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 */
|
||||
free(state->buffer);
|
||||
/* malloc check ok, overflow checked above */
|
||||
state->buffer = (UINT8*) malloc(state->bytes+1);
|
||||
context->previous = (UINT8*) malloc(state->bytes+1);
|
||||
state->buffer = (UINT8 *)malloc(state->bytes + 1);
|
||||
context->previous = (UINT8 *)malloc(state->bytes + 1);
|
||||
if (!state->buffer || !context->previous) {
|
||||
state->errcode = IMAGING_CODEC_MEMORY;
|
||||
return -1;
|
||||
|
@ -76,12 +73,12 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
context->last_output = 0;
|
||||
|
||||
/* Initialize to black */
|
||||
memset(context->previous, 0, state->bytes+1);
|
||||
memset(context->previous, 0, state->bytes + 1);
|
||||
|
||||
/* Setup decompression context */
|
||||
context->z_stream.zalloc = (alloc_func) NULL;
|
||||
context->z_stream.zfree = (free_func) NULL;
|
||||
context->z_stream.opaque = (voidpf) NULL;
|
||||
context->z_stream.zalloc = (alloc_func)NULL;
|
||||
context->z_stream.zfree = (free_func)NULL;
|
||||
context->z_stream.opaque = (voidpf)NULL;
|
||||
|
||||
err = inflateInit(&context->z_stream);
|
||||
if (err < 0) {
|
||||
|
@ -98,7 +95,6 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
|
||||
/* Ready to decode */
|
||||
state->state = 1;
|
||||
|
||||
}
|
||||
|
||||
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 */
|
||||
while (context->z_stream.avail_in > 0) {
|
||||
|
||||
context->z_stream.next_out = state->buffer + context->last_output;
|
||||
context->z_stream.avail_out =
|
||||
row_len + context->prefix - context->last_output;
|
||||
context->z_stream.avail_out = row_len + context->prefix - context->last_output;
|
||||
|
||||
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 */
|
||||
switch (context->mode) {
|
||||
case ZIP_PNG:
|
||||
switch (state->buffer[0]) {
|
||||
case 0:
|
||||
case ZIP_PNG:
|
||||
switch (state->buffer[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;
|
||||
case 1:
|
||||
/* prior */
|
||||
case ZIP_TIFF_PREDICTOR:
|
||||
bpp = (state->bits + 7) / 8;
|
||||
for (i = bpp+1; i <= row_len; i++) {
|
||||
state->buffer[i] += state->buffer[i-bpp];
|
||||
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;
|
||||
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 */
|
||||
|
@ -220,20 +214,22 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
if (state->bits >= 8) {
|
||||
/* Stuff pixels in their correct location, one by one */
|
||||
for (i = 0; i < row_len; i += ((state->bits + 7) / 8)) {
|
||||
state->shuffle((UINT8*) im->image[state->y] +
|
||||
col * im->pixelsize,
|
||||
state->buffer + context->prefix + i, 1);
|
||||
state->shuffle(
|
||||
(UINT8 *)im->image[state->y] + col * im->pixelsize,
|
||||
state->buffer + context->prefix + i,
|
||||
1);
|
||||
col += COL_INCREMENT[context->pass];
|
||||
}
|
||||
} else {
|
||||
/* Handle case with more than a pixel in each byte */
|
||||
int row_bits = ((state->xsize + OFFSET[context->pass])
|
||||
/ COL_INCREMENT[context->pass]) * state->bits;
|
||||
int row_bits = ((state->xsize + OFFSET[context->pass]) /
|
||||
COL_INCREMENT[context->pass]) *
|
||||
state->bits;
|
||||
for (i = 0; i < row_bits; i += state->bits) {
|
||||
UINT8 byte = *(state->buffer + context->prefix + (i / 8));
|
||||
byte <<= (i % 8);
|
||||
state->shuffle((UINT8*) im->image[state->y] +
|
||||
col * im->pixelsize, &byte, 1);
|
||||
state->shuffle(
|
||||
(UINT8 *)im->image[state->y] + col * im->pixelsize, &byte, 1);
|
||||
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);
|
||||
/* Since we're moving to the "first" line, the previous line
|
||||
* should be black to make filters work correctly */
|
||||
memset(state->buffer, 0, state->bytes+1);
|
||||
memset(state->buffer, 0, state->bytes + 1);
|
||||
}
|
||||
} else {
|
||||
state->shuffle((UINT8*) im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize,
|
||||
state->buffer + context->prefix,
|
||||
state->xsize);
|
||||
state->shuffle(
|
||||
(UINT8 *)im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize,
|
||||
state->buffer + context->prefix,
|
||||
state->xsize);
|
||||
state->y++;
|
||||
}
|
||||
|
||||
|
@ -264,7 +261,6 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
context->last_output = 0;
|
||||
|
||||
if (state->y >= state->ysize || err == Z_STREAM_END) {
|
||||
|
||||
/* The image and the data should end simultaneously */
|
||||
/* if (state->y < state->ysize || err != Z_STREAM_END)
|
||||
state->errcode = IMAGING_CODEC_BROKEN; */
|
||||
|
@ -273,26 +269,23 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||
context->previous = NULL;
|
||||
inflateEnd(&context->z_stream);
|
||||
return -1; /* end of file (errcode=0) */
|
||||
|
||||
}
|
||||
|
||||
/* Swap buffer pointers */
|
||||
ptr = state->buffer;
|
||||
state->buffer = context->previous;
|
||||
context->previous = ptr;
|
||||
|
||||
}
|
||||
|
||||
return bytes; /* consumed all of it */
|
||||
|
||||
}
|
||||
|
||||
|
||||
int ImagingZipDecodeCleanup(ImagingCodecState state){
|
||||
int
|
||||
ImagingZipDecodeCleanup(ImagingCodecState state) {
|
||||
/* called to free the decompression engine when the decode terminates
|
||||
due to a corrupt or truncated image
|
||||
*/
|
||||
ZIPSTATE* context = (ZIPSTATE*) state->context;
|
||||
ZIPSTATE *context = (ZIPSTATE *)state->context;
|
||||
|
||||
/* Clean up */
|
||||
if (context->previous) {
|
||||
|
|
|
@ -14,25 +14,22 @@
|
|||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
#ifdef HAVE_LIBZ
|
||||
|
||||
#include "ZipCodecs.h"
|
||||
|
||||
int
|
||||
ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||
{
|
||||
ZIPSTATE* context = (ZIPSTATE*) state->context;
|
||||
ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
|
||||
ZIPSTATE *context = (ZIPSTATE *)state->context;
|
||||
int err;
|
||||
int compress_level, compress_type;
|
||||
UINT8* ptr;
|
||||
UINT8 *ptr;
|
||||
int i, bpp, s, sum;
|
||||
ImagingSectionCookie cookie;
|
||||
|
||||
if (!state->state) {
|
||||
|
||||
/* Initialization */
|
||||
|
||||
/* 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 */
|
||||
free(state->buffer);
|
||||
/* malloc check ok, overflow checked above */
|
||||
state->buffer = (UINT8*) malloc(state->bytes+1);
|
||||
context->previous = (UINT8*) malloc(state->bytes+1);
|
||||
context->prior = (UINT8*) malloc(state->bytes+1);
|
||||
context->up = (UINT8*) malloc(state->bytes+1);
|
||||
context->average = (UINT8*) malloc(state->bytes+1);
|
||||
context->paeth = (UINT8*) malloc(state->bytes+1);
|
||||
if (!state->buffer || !context->previous || !context->prior ||
|
||||
!context->up || !context->average || !context->paeth) {
|
||||
state->buffer = (UINT8 *)malloc(state->bytes + 1);
|
||||
context->previous = (UINT8 *)malloc(state->bytes + 1);
|
||||
context->prior = (UINT8 *)malloc(state->bytes + 1);
|
||||
context->up = (UINT8 *)malloc(state->bytes + 1);
|
||||
context->average = (UINT8 *)malloc(state->bytes + 1);
|
||||
context->paeth = (UINT8 *)malloc(state->bytes + 1);
|
||||
if (!state->buffer || !context->previous || !context->prior || !context->up ||
|
||||
!context->average || !context->paeth) {
|
||||
free(context->paeth);
|
||||
free(context->average);
|
||||
free(context->up);
|
||||
|
@ -72,7 +69,7 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
context->paeth[0] = 4;
|
||||
|
||||
/* Initialise previous buffer to black */
|
||||
memset(context->previous, 0, state->bytes+1);
|
||||
memset(context->previous, 0, state->bytes + 1);
|
||||
|
||||
/* Setup compression context */
|
||||
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.avail_in = 0;
|
||||
|
||||
compress_level = (context->optimize) ? Z_BEST_COMPRESSION
|
||||
: context->compress_level;
|
||||
compress_level =
|
||||
(context->optimize) ? Z_BEST_COMPRESSION : context->compress_level;
|
||||
|
||||
if (context->compress_type == -1) {
|
||||
compress_type = (context->mode == ZIP_PNG) ? Z_FILTERED
|
||||
: Z_DEFAULT_STRATEGY;
|
||||
compress_type =
|
||||
(context->mode == ZIP_PNG) ? Z_FILTERED : Z_DEFAULT_STRATEGY;
|
||||
} else {
|
||||
compress_type = context->compress_type;
|
||||
}
|
||||
|
||||
err = deflateInit2(&context->z_stream,
|
||||
/* compression level */
|
||||
compress_level,
|
||||
/* compression method */
|
||||
Z_DEFLATED,
|
||||
/* compression memory resources */
|
||||
15, 9,
|
||||
/* compression strategy (image data are filtered)*/
|
||||
compress_type);
|
||||
err = deflateInit2(
|
||||
&context->z_stream,
|
||||
/* compression level */
|
||||
compress_level,
|
||||
/* compression method */
|
||||
Z_DEFLATED,
|
||||
/* compression memory resources */
|
||||
15,
|
||||
9,
|
||||
/* compression strategy (image data are filtered)*/
|
||||
compress_type);
|
||||
if (err < 0) {
|
||||
state->errcode = IMAGING_CODEC_CONFIG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (context->dictionary && context->dictionary_size > 0) {
|
||||
err = deflateSetDictionary(&context->z_stream, (unsigned char *)context->dictionary,
|
||||
context->dictionary_size);
|
||||
err = deflateSetDictionary(
|
||||
&context->z_stream,
|
||||
(unsigned char *)context->dictionary,
|
||||
context->dictionary_size);
|
||||
if (err < 0) {
|
||||
state->errcode = IMAGING_CODEC_CONFIG;
|
||||
return -1;
|
||||
|
@ -116,7 +117,6 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
|
||||
/* Ready to decode */
|
||||
state->state = 1;
|
||||
|
||||
}
|
||||
|
||||
/* Setup the destination buffer */
|
||||
|
@ -147,203 +147,194 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
|
||||
ImagingSectionEnter(&cookie);
|
||||
for (;;) {
|
||||
|
||||
switch (state->state) {
|
||||
case 1:
|
||||
|
||||
case 1:
|
||||
|
||||
/* Compress image data */
|
||||
while (context->z_stream.avail_out > 0) {
|
||||
|
||||
if (state->y >= state->ysize) {
|
||||
/* 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;
|
||||
/* Compress image data */
|
||||
while (context->z_stream.avail_out > 0) {
|
||||
if (state->y >= state->ysize) {
|
||||
/* End of image; now flush compressor buffers */
|
||||
state->state = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* 2. Up. We'll test this first to save time when
|
||||
an image line is identical to the one above. */
|
||||
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 */
|
||||
}
|
||||
}
|
||||
/* Stuff image data into the compressor */
|
||||
state->shuffle(
|
||||
state->buffer + 1,
|
||||
(UINT8 *)im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize,
|
||||
state->xsize);
|
||||
|
||||
/* 1. Prior */
|
||||
if (sum > 0) {
|
||||
for (i = 1, s = 0; i <= bpp; i++) {
|
||||
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];
|
||||
context->prior[i] = v;
|
||||
s += (v < 128) ? v : 256 - v;
|
||||
sum += (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;
|
||||
|
||||
/* 2. Up. We'll test this first to save time when
|
||||
an image line is identical to the one above. */
|
||||
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;
|
||||
sum = s; /* 0 if line is solid */
|
||||
|
||||
/* 1. Prior */
|
||||
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,
|
||||
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;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
/* 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) {
|
||||
break; /* Buffer full */
|
||||
}
|
||||
}
|
||||
}
|
||||
ImagingSectionLeave(&cookie);
|
||||
return bytes - context->z_stream.avail_out;
|
||||
|
||||
}
|
||||
|
||||
/* Should never ever arrive here... */
|
||||
|
@ -358,21 +349,18 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
|
||||
int
|
||||
ImagingZipEncodeCleanup(ImagingCodecState state) {
|
||||
ZIPSTATE* context = (ZIPSTATE*) state->context;
|
||||
ZIPSTATE *context = (ZIPSTATE *)state->context;
|
||||
|
||||
if (context->dictionary) {
|
||||
free (context->dictionary);
|
||||
free(context->dictionary);
|
||||
context->dictionary = NULL;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char*
|
||||
ImagingZipVersion(void)
|
||||
{
|
||||
const char *
|
||||
ImagingZipVersion(void) {
|
||||
return zlibVersion();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
#include "Python.h"
|
||||
#include "Imaging.h"
|
||||
|
||||
|
||||
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
|
||||
-1 on error */
|
||||
|
||||
|
@ -29,16 +27,13 @@ _imaging_read_pyFd(PyObject *fd, char* dest, Py_ssize_t bytes)
|
|||
Py_DECREF(result);
|
||||
return length;
|
||||
|
||||
err:
|
||||
err:
|
||||
Py_DECREF(result);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
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 *byteObj;
|
||||
|
||||
|
@ -49,24 +44,20 @@ _imaging_write_pyFd(PyObject *fd, char* src, Py_ssize_t bytes)
|
|||
Py_DECREF(result);
|
||||
|
||||
return bytes;
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
result = PyObject_CallMethod(fd, "seek", "ni", offset, whence);
|
||||
|
||||
Py_DECREF(result);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
Py_ssize_t
|
||||
_imaging_tell_pyFd(PyObject *fd)
|
||||
{
|
||||
_imaging_tell_pyFd(PyObject *fd) {
|
||||
PyObject *result;
|
||||
Py_ssize_t location;
|
||||
|
||||
|
|
|
@ -63,8 +63,7 @@ typedef struct _raqm raqm_t;
|
|||
*
|
||||
* Since: 0.1
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
RAQM_DIRECTION_DEFAULT,
|
||||
RAQM_DIRECTION_RTL,
|
||||
RAQM_DIRECTION_LTR,
|
||||
|
@ -106,73 +105,50 @@ typedef struct raqm_glyph_t_01 {
|
|||
uint32_t cluster;
|
||||
} raqm_glyph_t_01;
|
||||
|
||||
raqm_t *
|
||||
raqm_create(void);
|
||||
|
||||
raqm_t *
|
||||
raqm_create (void);
|
||||
|
||||
raqm_t *
|
||||
raqm_reference (raqm_t *rq);
|
||||
raqm_reference(raqm_t *rq);
|
||||
|
||||
void
|
||||
raqm_destroy (raqm_t *rq);
|
||||
raqm_destroy(raqm_t *rq);
|
||||
|
||||
bool
|
||||
raqm_set_text (raqm_t *rq,
|
||||
const uint32_t *text,
|
||||
size_t len);
|
||||
raqm_set_text(raqm_t *rq, const uint32_t *text, size_t len);
|
||||
|
||||
bool
|
||||
raqm_set_text_utf8 (raqm_t *rq,
|
||||
const char *text,
|
||||
size_t len);
|
||||
raqm_set_text_utf8(raqm_t *rq, const char *text, size_t len);
|
||||
|
||||
bool
|
||||
raqm_set_par_direction (raqm_t *rq,
|
||||
raqm_direction_t dir);
|
||||
raqm_set_par_direction(raqm_t *rq, raqm_direction_t dir);
|
||||
|
||||
bool
|
||||
raqm_set_language (raqm_t *rq,
|
||||
const char *lang,
|
||||
size_t start,
|
||||
size_t len);
|
||||
raqm_set_language(raqm_t *rq, const char *lang, size_t start, size_t len);
|
||||
|
||||
bool
|
||||
raqm_add_font_feature (raqm_t *rq,
|
||||
const char *feature,
|
||||
int len);
|
||||
raqm_add_font_feature(raqm_t *rq, const char *feature, int len);
|
||||
|
||||
bool
|
||||
raqm_set_freetype_face (raqm_t *rq,
|
||||
FT_Face face);
|
||||
raqm_set_freetype_face(raqm_t *rq, FT_Face face);
|
||||
|
||||
bool
|
||||
raqm_set_freetype_face_range (raqm_t *rq,
|
||||
FT_Face face,
|
||||
size_t start,
|
||||
size_t len);
|
||||
raqm_set_freetype_face_range(raqm_t *rq, FT_Face face, size_t start, size_t len);
|
||||
|
||||
bool
|
||||
raqm_set_freetype_load_flags (raqm_t *rq,
|
||||
int flags);
|
||||
raqm_set_freetype_load_flags(raqm_t *rq, int flags);
|
||||
|
||||
bool
|
||||
raqm_layout (raqm_t *rq);
|
||||
raqm_layout(raqm_t *rq);
|
||||
|
||||
raqm_glyph_t *
|
||||
raqm_get_glyphs (raqm_t *rq,
|
||||
size_t *length);
|
||||
raqm_get_glyphs(raqm_t *rq, size_t *length);
|
||||
|
||||
bool
|
||||
raqm_index_to_position (raqm_t *rq,
|
||||
size_t *index,
|
||||
int *x,
|
||||
int *y);
|
||||
raqm_index_to_position(raqm_t *rq, size_t *index, int *x, int *y);
|
||||
|
||||
bool
|
||||
raqm_position_to_index (raqm_t *rq,
|
||||
int x,
|
||||
int y,
|
||||
size_t *index);
|
||||
raqm_position_to_index(raqm_t *rq, int x, int y, size_t *index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
182
src/map.c
182
src/map.c
|
@ -23,17 +23,18 @@
|
|||
#include "libImaging/Imaging.h"
|
||||
|
||||
/* compatibility wrappers (defined in _imaging.c) */
|
||||
extern int PyImaging_CheckBuffer(PyObject* buffer);
|
||||
extern int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view);
|
||||
extern int
|
||||
PyImaging_CheckBuffer(PyObject *buffer);
|
||||
extern int
|
||||
PyImaging_GetBuffer(PyObject *buffer, Py_buffer *view);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Standard mapper */
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
char* base;
|
||||
int size;
|
||||
int offset;
|
||||
PyObject_HEAD char *base;
|
||||
int size;
|
||||
int offset;
|
||||
#ifdef _WIN32
|
||||
HANDLE hFile;
|
||||
HANDLE hMap;
|
||||
|
@ -42,9 +43,8 @@ typedef struct {
|
|||
|
||||
static PyTypeObject ImagingMapperType;
|
||||
|
||||
ImagingMapperObject*
|
||||
PyImaging_MapperNew(const char* filename, int readonly)
|
||||
{
|
||||
ImagingMapperObject *
|
||||
PyImaging_MapperNew(const char *filename, int readonly) {
|
||||
ImagingMapperObject *mapper;
|
||||
|
||||
if (PyType_Ready(&ImagingMapperType) < 0) {
|
||||
|
@ -61,14 +61,15 @@ PyImaging_MapperNew(const char* filename, int readonly)
|
|||
|
||||
#ifdef _WIN32
|
||||
mapper->hFile = (HANDLE)-1;
|
||||
mapper->hMap = (HANDLE)-1;
|
||||
mapper->hMap = (HANDLE)-1;
|
||||
|
||||
/* FIXME: currently supports readonly mappings only */
|
||||
mapper->hFile = CreateFile(
|
||||
filename,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (mapper->hFile == (HANDLE)-1) {
|
||||
|
@ -77,10 +78,7 @@ PyImaging_MapperNew(const char* filename, int readonly)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
mapper->hMap = CreateFileMapping(
|
||||
mapper->hFile, NULL,
|
||||
PAGE_READONLY,
|
||||
0, 0, NULL);
|
||||
mapper->hMap = CreateFileMapping(mapper->hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (mapper->hMap == (HANDLE)-1) {
|
||||
CloseHandle(mapper->hFile);
|
||||
PyErr_SetString(PyExc_OSError, "cannot map file");
|
||||
|
@ -88,10 +86,7 @@ PyImaging_MapperNew(const char* filename, int readonly)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
mapper->base = (char*) MapViewOfFile(
|
||||
mapper->hMap,
|
||||
FILE_MAP_READ,
|
||||
0, 0, 0);
|
||||
mapper->base = (char *)MapViewOfFile(mapper->hMap, FILE_MAP_READ, 0, 0, 0);
|
||||
|
||||
mapper->size = GetFileSize(mapper->hFile, 0);
|
||||
#endif
|
||||
|
@ -100,8 +95,7 @@ PyImaging_MapperNew(const char* filename, int readonly)
|
|||
}
|
||||
|
||||
static void
|
||||
mapping_dealloc(ImagingMapperObject* mapper)
|
||||
{
|
||||
mapping_dealloc(ImagingMapperObject *mapper) {
|
||||
#ifdef _WIN32
|
||||
if (mapper->base != 0) {
|
||||
UnmapViewOfFile(mapper->base);
|
||||
|
@ -121,10 +115,9 @@ mapping_dealloc(ImagingMapperObject* mapper)
|
|||
/* -------------------------------------------------------------------- */
|
||||
/* standard file operations */
|
||||
|
||||
static PyObject*
|
||||
mapping_read(ImagingMapperObject* mapper, PyObject* args)
|
||||
{
|
||||
PyObject* buf;
|
||||
static PyObject *
|
||||
mapping_read(ImagingMapperObject *mapper, PyObject *args) {
|
||||
PyObject *buf;
|
||||
|
||||
int size = -1;
|
||||
if (!PyArg_ParseTuple(args, "|i", &size)) {
|
||||
|
@ -152,9 +145,8 @@ mapping_read(ImagingMapperObject* mapper, PyObject* args)
|
|||
return buf;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
mapping_seek(ImagingMapperObject* mapper, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
mapping_seek(ImagingMapperObject *mapper, PyObject *args) {
|
||||
int offset;
|
||||
int whence = 0;
|
||||
if (!PyArg_ParseTuple(args, "i|i", &offset, &whence)) {
|
||||
|
@ -183,27 +175,26 @@ mapping_seek(ImagingMapperObject* mapper, PyObject* args)
|
|||
/* -------------------------------------------------------------------- */
|
||||
/* map entire image */
|
||||
|
||||
extern PyObject*PyImagingNew(Imaging im);
|
||||
extern PyObject *
|
||||
PyImagingNew(Imaging im);
|
||||
|
||||
static void
|
||||
ImagingDestroyMap(Imaging im)
|
||||
{
|
||||
ImagingDestroyMap(Imaging im) {
|
||||
return; /* nothing to do! */
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
mapping_readimage(ImagingMapperObject* mapper, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
mapping_readimage(ImagingMapperObject *mapper, PyObject *args) {
|
||||
int y, size;
|
||||
Imaging im;
|
||||
|
||||
char* mode;
|
||||
char *mode;
|
||||
int xsize;
|
||||
int ysize;
|
||||
int stride;
|
||||
int orientation;
|
||||
if (!PyArg_ParseTuple(args, "s(ii)ii", &mode, &xsize, &ysize,
|
||||
&stride, &orientation)) {
|
||||
if (!PyArg_ParseTuple(
|
||||
args, "s(ii)ii", &mode, &xsize, &ysize, &stride, &orientation)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -237,7 +228,7 @@ mapping_readimage(ImagingMapperObject* mapper, PyObject* args)
|
|||
}
|
||||
} else {
|
||||
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 = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"ImagingMapper", /*tp_name*/
|
||||
sizeof(ImagingMapperObject), /*tp_size*/
|
||||
0, /*tp_itemsize*/
|
||||
/* methods */
|
||||
(destructor)mapping_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number */
|
||||
0, /*tp_as_sequence */
|
||||
0, /*tp_as_mapping */
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
methods, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
0, /*tp_getset*/
|
||||
PyVarObject_HEAD_INIT(NULL, 0) "ImagingMapper", /*tp_name*/
|
||||
sizeof(ImagingMapperObject), /*tp_size*/
|
||||
0, /*tp_itemsize*/
|
||||
/* methods */
|
||||
(destructor)mapping_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number */
|
||||
0, /*tp_as_sequence */
|
||||
0, /*tp_as_mapping */
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
methods, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
0, /*tp_getset*/
|
||||
};
|
||||
|
||||
PyObject*
|
||||
PyImaging_Mapper(PyObject* self, PyObject* args)
|
||||
{
|
||||
char* filename;
|
||||
PyObject *
|
||||
PyImaging_Mapper(PyObject *self, PyObject *args) {
|
||||
char *filename;
|
||||
if (!PyArg_ParseTuple(args, "s", &filename)) {
|
||||
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 {
|
||||
struct ImagingMemoryInstance im;
|
||||
PyObject* target;
|
||||
PyObject *target;
|
||||
Py_buffer view;
|
||||
} ImagingBufferInstance;
|
||||
|
||||
static void
|
||||
mapping_destroy_buffer(Imaging im)
|
||||
{
|
||||
ImagingBufferInstance* buffer = (ImagingBufferInstance*) im;
|
||||
mapping_destroy_buffer(Imaging im) {
|
||||
ImagingBufferInstance *buffer = (ImagingBufferInstance *)im;
|
||||
|
||||
PyBuffer_Release(&buffer->view);
|
||||
Py_XDECREF(buffer->target);
|
||||
}
|
||||
|
||||
PyObject*
|
||||
PyImaging_MapBuffer(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject *
|
||||
PyImaging_MapBuffer(PyObject *self, PyObject *args) {
|
||||
Py_ssize_t y, size;
|
||||
Imaging im;
|
||||
|
||||
PyObject* target;
|
||||
PyObject *target;
|
||||
Py_buffer view;
|
||||
char* mode;
|
||||
char* codec;
|
||||
char *mode;
|
||||
char *codec;
|
||||
Py_ssize_t offset;
|
||||
int xsize, ysize;
|
||||
int stride;
|
||||
int ystep;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O(ii)sn(sii)", &target, &xsize, &ysize,
|
||||
&codec, &offset, &mode, &stride, &ystep)) {
|
||||
if (!PyArg_ParseTuple(
|
||||
args,
|
||||
"O(ii)sn(sii)",
|
||||
&target,
|
||||
&xsize,
|
||||
&ysize,
|
||||
&codec,
|
||||
&offset,
|
||||
&mode,
|
||||
&stride,
|
||||
&ystep)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -360,7 +356,7 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
size = (Py_ssize_t) ysize * stride;
|
||||
size = (Py_ssize_t)ysize * stride;
|
||||
|
||||
if (offset > PY_SSIZE_T_MAX - size) {
|
||||
PyErr_SetString(PyExc_MemoryError, "Integer overflow in offset");
|
||||
|
@ -383,8 +379,7 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
im = ImagingNewPrologueSubtype(
|
||||
mode, xsize, ysize, sizeof(ImagingBufferInstance));
|
||||
im = ImagingNewPrologueSubtype(mode, xsize, ysize, sizeof(ImagingBufferInstance));
|
||||
if (!im) {
|
||||
PyBuffer_Release(&view);
|
||||
return NULL;
|
||||
|
@ -393,20 +388,19 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
|
|||
/* setup file pointers */
|
||||
if (ystep > 0) {
|
||||
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 {
|
||||
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;
|
||||
|
||||
Py_INCREF(target);
|
||||
((ImagingBufferInstance*) im)->target = target;
|
||||
((ImagingBufferInstance*) im)->view = view;
|
||||
((ImagingBufferInstance *)im)->target = target;
|
||||
((ImagingBufferInstance *)im)->view = view;
|
||||
|
||||
return PyImagingNew(im);
|
||||
}
|
||||
|
||||
|
|
112
src/outline.c
112
src/outline.c
|
@ -21,22 +21,19 @@
|
|||
|
||||
#include "libImaging/Imaging.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Class */
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
ImagingOutline outline;
|
||||
PyObject_HEAD ImagingOutline outline;
|
||||
} OutlineObject;
|
||||
|
||||
static PyTypeObject OutlineType;
|
||||
|
||||
#define PyOutline_Check(op) (Py_TYPE(op) == &OutlineType)
|
||||
|
||||
static OutlineObject*
|
||||
_outline_new(void)
|
||||
{
|
||||
static OutlineObject *
|
||||
_outline_new(void) {
|
||||
OutlineObject *self;
|
||||
|
||||
if (PyType_Ready(&OutlineType) < 0) {
|
||||
|
@ -54,43 +51,37 @@ _outline_new(void)
|
|||
}
|
||||
|
||||
static void
|
||||
_outline_dealloc(OutlineObject* self)
|
||||
{
|
||||
_outline_dealloc(OutlineObject *self) {
|
||||
ImagingOutlineDelete(self->outline);
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
ImagingOutline
|
||||
PyOutline_AsOutline(PyObject* outline)
|
||||
{
|
||||
PyOutline_AsOutline(PyObject *outline) {
|
||||
if (PyOutline_Check(outline)) {
|
||||
return ((OutlineObject*) outline)->outline;
|
||||
return ((OutlineObject *)outline)->outline;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Factories */
|
||||
|
||||
PyObject*
|
||||
PyOutline_Create(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject *
|
||||
PyOutline_Create(PyObject *self, PyObject *args) {
|
||||
if (!PyArg_ParseTuple(args, ":outline")) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (PyObject*) _outline_new();
|
||||
return (PyObject *)_outline_new();
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Methods */
|
||||
|
||||
static PyObject*
|
||||
_outline_move(OutlineObject* self, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
_outline_move(OutlineObject *self, PyObject *args) {
|
||||
float x0, y0;
|
||||
if (!PyArg_ParseTuple(args, "ff", &x0, &y0)) {
|
||||
return NULL;
|
||||
|
@ -102,9 +93,8 @@ _outline_move(OutlineObject* self, PyObject* args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_outline_line(OutlineObject* self, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
_outline_line(OutlineObject *self, PyObject *args) {
|
||||
float x1, y1;
|
||||
if (!PyArg_ParseTuple(args, "ff", &x1, &y1)) {
|
||||
return NULL;
|
||||
|
@ -116,9 +106,8 @@ _outline_line(OutlineObject* self, PyObject* args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_outline_curve(OutlineObject* self, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
_outline_curve(OutlineObject *self, PyObject *args) {
|
||||
float x1, y1, x2, y2, x3, y3;
|
||||
if (!PyArg_ParseTuple(args, "ffffff", &x1, &y1, &x2, &y2, &x3, &y3)) {
|
||||
return NULL;
|
||||
|
@ -130,9 +119,8 @@ _outline_curve(OutlineObject* self, PyObject* args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_outline_close(OutlineObject* self, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
_outline_close(OutlineObject *self, PyObject *args) {
|
||||
if (!PyArg_ParseTuple(args, ":close")) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -143,11 +131,10 @@ _outline_close(OutlineObject* self, PyObject* args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_outline_transform(OutlineObject* self, PyObject* args)
|
||||
{
|
||||
static PyObject *
|
||||
_outline_transform(OutlineObject *self, PyObject *args) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -167,35 +154,34 @@ static struct PyMethodDef _outline_methods[] = {
|
|||
};
|
||||
|
||||
static PyTypeObject OutlineType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"Outline", /*tp_name*/
|
||||
sizeof(OutlineObject), /*tp_size*/
|
||||
0, /*tp_itemsize*/
|
||||
PyVarObject_HEAD_INIT(NULL, 0) "Outline", /*tp_name*/
|
||||
sizeof(OutlineObject), /*tp_size*/
|
||||
0, /*tp_itemsize*/
|
||||
/* methods */
|
||||
(destructor)_outline_dealloc,/*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number */
|
||||
0, /*tp_as_sequence */
|
||||
0, /*tp_as_mapping */
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
_outline_methods, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
0, /*tp_getset*/
|
||||
(destructor)_outline_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number */
|
||||
0, /*tp_as_sequence */
|
||||
0, /*tp_as_mapping */
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
_outline_methods, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
0, /*tp_getset*/
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user