mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-05-04 16:03:42 +03:00
Merge pull request #1781 from wiredfool/malloc_check
Integer overflow checks on malloc
This commit is contained in:
commit
bdd0a6a4e4
52
_imaging.c
52
_imaging.c
|
@ -362,9 +362,20 @@ getbands(const char* mode)
|
||||||
#define TYPE_DOUBLE (0x400|sizeof(double))
|
#define TYPE_DOUBLE (0x400|sizeof(double))
|
||||||
|
|
||||||
static void*
|
static void*
|
||||||
getlist(PyObject* arg, int* length, const char* wrong_length, int type)
|
getlist(PyObject* arg, Py_ssize_t* length, const char* wrong_length, int type)
|
||||||
{
|
{
|
||||||
int i, n, itemp;
|
/* - allocates and returns a c array of the items in the
|
||||||
|
python sequence arg.
|
||||||
|
- the size of the returned array is in length
|
||||||
|
- all of the arg items must be numeric items of the type
|
||||||
|
specified in type
|
||||||
|
- sequence length is checked against the length parameter IF
|
||||||
|
an error parameter is passed in wrong_length
|
||||||
|
- caller is responsible for freeing the memory
|
||||||
|
*/
|
||||||
|
|
||||||
|
Py_ssize_t i, n;
|
||||||
|
int itemp;
|
||||||
double dtemp;
|
double dtemp;
|
||||||
void* list;
|
void* list;
|
||||||
PyObject* seq;
|
PyObject* seq;
|
||||||
|
@ -381,7 +392,9 @@ getlist(PyObject* arg, int* length, const char* wrong_length, int type)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
list = malloc(n * (type & 0xff));
|
/* malloc check ok, type & ff is just a sizeof(something)
|
||||||
|
calloc checks for overflow */
|
||||||
|
list = calloc(n, type & 0xff);
|
||||||
if (!list)
|
if (!list)
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
|
|
||||||
|
@ -845,7 +858,7 @@ static PyObject*
|
||||||
_filter(ImagingObject* self, PyObject* args)
|
_filter(ImagingObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
PyObject* imOut;
|
PyObject* imOut;
|
||||||
int kernelsize;
|
Py_ssize_t kernelsize;
|
||||||
FLOAT32* kerneldata;
|
FLOAT32* kerneldata;
|
||||||
|
|
||||||
int xsize, ysize;
|
int xsize, ysize;
|
||||||
|
@ -859,7 +872,7 @@ _filter(ImagingObject* self, PyObject* args)
|
||||||
kerneldata = getlist(kernel, &kernelsize, NULL, TYPE_FLOAT32);
|
kerneldata = getlist(kernel, &kernelsize, NULL, TYPE_FLOAT32);
|
||||||
if (!kerneldata)
|
if (!kerneldata)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (kernelsize != xsize * ysize) {
|
if (kernelsize != (Py_ssize_t) xsize * (Py_ssize_t) ysize) {
|
||||||
free(kerneldata);
|
free(kerneldata);
|
||||||
return ImagingError_ValueError("bad kernel size");
|
return ImagingError_ValueError("bad kernel size");
|
||||||
}
|
}
|
||||||
|
@ -1148,8 +1161,8 @@ _point(ImagingObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
static const char* wrong_number = "wrong number of lut entries";
|
static const char* wrong_number = "wrong number of lut entries";
|
||||||
|
|
||||||
int n, i;
|
Py_ssize_t n;
|
||||||
int bands;
|
int i, bands;
|
||||||
Imaging im;
|
Imaging im;
|
||||||
|
|
||||||
PyObject* list;
|
PyObject* list;
|
||||||
|
@ -1614,7 +1627,7 @@ _transform2(ImagingObject* self, PyObject* args)
|
||||||
static const char* wrong_number = "wrong number of matrix entries";
|
static const char* wrong_number = "wrong number of matrix entries";
|
||||||
|
|
||||||
Imaging imOut;
|
Imaging imOut;
|
||||||
int n;
|
Py_ssize_t n;
|
||||||
double *a;
|
double *a;
|
||||||
|
|
||||||
ImagingObject* imagep;
|
ImagingObject* imagep;
|
||||||
|
@ -1849,6 +1862,7 @@ _getprojection(ImagingObject* self, PyObject* args)
|
||||||
unsigned char* yprofile;
|
unsigned char* yprofile;
|
||||||
PyObject* result;
|
PyObject* result;
|
||||||
|
|
||||||
|
/* malloc check ok */
|
||||||
xprofile = malloc(self->image->xsize);
|
xprofile = malloc(self->image->xsize);
|
||||||
yprofile = malloc(self->image->ysize);
|
yprofile = malloc(self->image->ysize);
|
||||||
|
|
||||||
|
@ -2295,7 +2309,7 @@ _draw_dealloc(ImagingDrawObject* self)
|
||||||
PyObject_Del(self);
|
PyObject_Del(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int PyPath_Flatten(PyObject* data, double **xy);
|
extern Py_ssize_t PyPath_Flatten(PyObject* data, double **xy);
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
_draw_ink(ImagingDrawObject* self, PyObject* args)
|
_draw_ink(ImagingDrawObject* self, PyObject* args)
|
||||||
|
@ -2316,7 +2330,7 @@ static PyObject*
|
||||||
_draw_arc(ImagingDrawObject* self, PyObject* args)
|
_draw_arc(ImagingDrawObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
double* xy;
|
double* xy;
|
||||||
int n;
|
Py_ssize_t n;
|
||||||
|
|
||||||
PyObject* data;
|
PyObject* data;
|
||||||
int ink;
|
int ink;
|
||||||
|
@ -2352,7 +2366,7 @@ static PyObject*
|
||||||
_draw_bitmap(ImagingDrawObject* self, PyObject* args)
|
_draw_bitmap(ImagingDrawObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
double *xy;
|
double *xy;
|
||||||
int n;
|
Py_ssize_t n;
|
||||||
|
|
||||||
PyObject *data;
|
PyObject *data;
|
||||||
ImagingObject* bitmap;
|
ImagingObject* bitmap;
|
||||||
|
@ -2388,7 +2402,7 @@ static PyObject*
|
||||||
_draw_chord(ImagingDrawObject* self, PyObject* args)
|
_draw_chord(ImagingDrawObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
double* xy;
|
double* xy;
|
||||||
int n;
|
Py_ssize_t n;
|
||||||
|
|
||||||
PyObject* data;
|
PyObject* data;
|
||||||
int ink, fill;
|
int ink, fill;
|
||||||
|
@ -2424,7 +2438,7 @@ static PyObject*
|
||||||
_draw_ellipse(ImagingDrawObject* self, PyObject* args)
|
_draw_ellipse(ImagingDrawObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
double* xy;
|
double* xy;
|
||||||
int n;
|
Py_ssize_t n;
|
||||||
|
|
||||||
PyObject* data;
|
PyObject* data;
|
||||||
int ink;
|
int ink;
|
||||||
|
@ -2475,7 +2489,7 @@ static PyObject*
|
||||||
_draw_lines(ImagingDrawObject* self, PyObject* args)
|
_draw_lines(ImagingDrawObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
double *xy;
|
double *xy;
|
||||||
int i, n;
|
Py_ssize_t i, n;
|
||||||
|
|
||||||
PyObject *data;
|
PyObject *data;
|
||||||
int ink;
|
int ink;
|
||||||
|
@ -2543,7 +2557,7 @@ static PyObject*
|
||||||
_draw_points(ImagingDrawObject* self, PyObject* args)
|
_draw_points(ImagingDrawObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
double *xy;
|
double *xy;
|
||||||
int i, n;
|
Py_ssize_t i, n;
|
||||||
|
|
||||||
PyObject *data;
|
PyObject *data;
|
||||||
int ink;
|
int ink;
|
||||||
|
@ -2605,7 +2619,7 @@ static PyObject*
|
||||||
_draw_pieslice(ImagingDrawObject* self, PyObject* args)
|
_draw_pieslice(ImagingDrawObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
double* xy;
|
double* xy;
|
||||||
int n;
|
Py_ssize_t n;
|
||||||
|
|
||||||
PyObject* data;
|
PyObject* data;
|
||||||
int ink, fill;
|
int ink, fill;
|
||||||
|
@ -2641,7 +2655,7 @@ _draw_polygon(ImagingDrawObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
double *xy;
|
double *xy;
|
||||||
int *ixy;
|
int *ixy;
|
||||||
int n, i;
|
Py_ssize_t n, i;
|
||||||
|
|
||||||
PyObject* data;
|
PyObject* data;
|
||||||
int ink;
|
int ink;
|
||||||
|
@ -2660,7 +2674,7 @@ _draw_polygon(ImagingDrawObject* self, PyObject* args)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy list of vertices to array */
|
/* Copy list of vertices to array */
|
||||||
ixy = (int*) malloc(n * 2 * sizeof(int));
|
ixy = (int*) calloc(n, 2 * sizeof(int));
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
ixy[i+i] = (int) xy[i+i];
|
ixy[i+i] = (int) xy[i+i];
|
||||||
|
@ -2685,7 +2699,7 @@ static PyObject*
|
||||||
_draw_rectangle(ImagingDrawObject* self, PyObject* args)
|
_draw_rectangle(ImagingDrawObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
double* xy;
|
double* xy;
|
||||||
int n;
|
Py_ssize_t n;
|
||||||
|
|
||||||
PyObject* data;
|
PyObject* data;
|
||||||
int ink;
|
int ink;
|
||||||
|
|
7
decode.c
7
decode.c
|
@ -188,8 +188,13 @@ _setimage(ImagingDecoderObject* decoder, PyObject* args)
|
||||||
|
|
||||||
/* Allocate memory buffer (if bits field is set) */
|
/* Allocate memory buffer (if bits field is set) */
|
||||||
if (state->bits > 0) {
|
if (state->bits > 0) {
|
||||||
if (!state->bytes)
|
if (!state->bytes) {
|
||||||
|
if (state->xsize > ((INT_MAX / state->bits)-7)){
|
||||||
|
return PyErr_NoMemory();
|
||||||
|
}
|
||||||
state->bytes = (state->bits * state->xsize+7)/8;
|
state->bytes = (state->bits * state->xsize+7)/8;
|
||||||
|
}
|
||||||
|
/* malloc check ok, oveflow checked above */
|
||||||
state->buffer = (UINT8*) malloc(state->bytes);
|
state->buffer = (UINT8*) malloc(state->bytes);
|
||||||
if (!state->buffer)
|
if (!state->buffer)
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
|
|
29
encode.c
29
encode.c
|
@ -159,6 +159,7 @@ _encode_to_file(ImagingEncoderObject* encoder, PyObject* args)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Allocate an encoder buffer */
|
/* Allocate an encoder buffer */
|
||||||
|
/* malloc check ok, either constant int, or checked by PyArg_ParseTuple */
|
||||||
buf = (UINT8*) malloc(bufsize);
|
buf = (UINT8*) malloc(bufsize);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
|
@ -233,7 +234,11 @@ _setimage(ImagingEncoderObject* encoder, PyObject* args)
|
||||||
|
|
||||||
/* Allocate memory buffer (if bits field is set) */
|
/* Allocate memory buffer (if bits field is set) */
|
||||||
if (state->bits > 0) {
|
if (state->bits > 0) {
|
||||||
|
if (state->xsize > ((INT_MAX / state->bits)-7)) {
|
||||||
|
return PyErr_NoMemory();
|
||||||
|
}
|
||||||
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)
|
if (!state->buffer)
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
|
@ -478,10 +483,9 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args)
|
||||||
&dictionary, &dictionary_size))
|
&dictionary, &dictionary_size))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Copy to avoid referencing Python's memory, but there's no mechanism to
|
/* Copy to avoid referencing Python's memory */
|
||||||
free this memory later, so this function (and several others here)
|
|
||||||
leaks. */
|
|
||||||
if (dictionary && dictionary_size > 0) {
|
if (dictionary && dictionary_size > 0) {
|
||||||
|
/* malloc check ok, size comes from PyArg_ParseTuple */
|
||||||
char* p = malloc(dictionary_size);
|
char* p = malloc(dictionary_size);
|
||||||
if (!p)
|
if (!p)
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
|
@ -498,6 +502,7 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
encoder->encode = ImagingZipEncode;
|
encoder->encode = ImagingZipEncode;
|
||||||
|
encoder->cleanup = ImagingZipEncodeCleanup;
|
||||||
|
|
||||||
if (rawmode[0] == 'P')
|
if (rawmode[0] == 'P')
|
||||||
/* disable filtering */
|
/* disable filtering */
|
||||||
|
@ -559,6 +564,7 @@ static unsigned int* get_qtables_arrays(PyObject* qtables, int* qtablesLen) {
|
||||||
Py_DECREF(tables);
|
Py_DECREF(tables);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/* malloc check ok, num_tables <4, DCTSIZE2 == 64 from jpeglib.h */
|
||||||
qarrays = (unsigned int*) malloc(num_tables * DCTSIZE2 * sizeof(unsigned int));
|
qarrays = (unsigned int*) malloc(num_tables * DCTSIZE2 * sizeof(unsigned int));
|
||||||
if (!qarrays) {
|
if (!qarrays) {
|
||||||
Py_DECREF(tables);
|
Py_DECREF(tables);
|
||||||
|
@ -631,9 +637,11 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args)
|
||||||
if (get_packer(encoder, mode, rawmode) < 0)
|
if (get_packer(encoder, mode, rawmode) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
// Freed in JpegEncode, Case 5
|
||||||
qarrays = get_qtables_arrays(qtables, &qtablesLen);
|
qarrays = get_qtables_arrays(qtables, &qtablesLen);
|
||||||
|
|
||||||
if (extra && extra_size > 0) {
|
if (extra && extra_size > 0) {
|
||||||
|
/* malloc check ok, length is from python parsearg */
|
||||||
char* p = malloc(extra_size); // Freed in JpegEncode, Case 5
|
char* p = malloc(extra_size); // Freed in JpegEncode, Case 5
|
||||||
if (!p)
|
if (!p)
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
|
@ -643,6 +651,7 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args)
|
||||||
extra = NULL;
|
extra = NULL;
|
||||||
|
|
||||||
if (rawExif && rawExifLen > 0) {
|
if (rawExif && rawExifLen > 0) {
|
||||||
|
/* malloc check ok, length is from python parsearg */
|
||||||
char* pp = malloc(rawExifLen); // Freed in JpegEncode, Case 5
|
char* pp = malloc(rawExifLen); // Freed in JpegEncode, Case 5
|
||||||
if (!pp)
|
if (!pp)
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
|
@ -757,15 +766,16 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
|
||||||
(ttag_t) PyInt_AsLong(key),
|
(ttag_t) PyInt_AsLong(key),
|
||||||
PyBytes_AsString(value));
|
PyBytes_AsString(value));
|
||||||
} else if (PyTuple_Check(value)) {
|
} else if (PyTuple_Check(value)) {
|
||||||
int len,i;
|
Py_ssize_t len,i;
|
||||||
float *floatav;
|
float *floatav;
|
||||||
int *intav;
|
int *intav;
|
||||||
TRACE(("Setting from Tuple: %d \n", (int)PyInt_AsLong(key)));
|
TRACE(("Setting from Tuple: %d \n", (int)PyInt_AsLong(key)));
|
||||||
len = (int)PyTuple_Size(value);
|
len = PyTuple_Size(value);
|
||||||
if (len) {
|
if (len) {
|
||||||
if (PyInt_Check(PyTuple_GetItem(value,0))) {
|
if (PyInt_Check(PyTuple_GetItem(value,0))) {
|
||||||
TRACE((" %d elements, setting as ints \n", len));
|
TRACE((" %d elements, setting as ints \n", (int)len));
|
||||||
intav = malloc(sizeof(int)*len);
|
/* malloc check ok, calloc checks for overflow */
|
||||||
|
intav = calloc(len, sizeof(int));
|
||||||
if (intav) {
|
if (intav) {
|
||||||
for (i=0;i<len;i++) {
|
for (i=0;i<len;i++) {
|
||||||
intav[i] = (int)PyInt_AsLong(PyTuple_GetItem(value,i));
|
intav[i] = (int)PyInt_AsLong(PyTuple_GetItem(value,i));
|
||||||
|
@ -776,8 +786,9 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
|
||||||
free(intav);
|
free(intav);
|
||||||
}
|
}
|
||||||
} else if (PyFloat_Check(PyTuple_GetItem(value,0))) {
|
} else if (PyFloat_Check(PyTuple_GetItem(value,0))) {
|
||||||
TRACE((" %d elements, setting as floats \n", len));
|
TRACE((" %d elements, setting as floats \n", (int)len));
|
||||||
floatav = malloc(sizeof(float)*len);
|
/* malloc check ok, calloc checks for overflow */
|
||||||
|
floatav = calloc(len, sizeof(float));
|
||||||
if (floatav) {
|
if (floatav) {
|
||||||
for (i=0;i<len;i++) {
|
for (i=0;i<len;i++) {
|
||||||
floatav[i] = (float)PyFloat_AsDouble(PyTuple_GetItem(value,i));
|
floatav[i] = (float)PyFloat_AsDouble(PyTuple_GetItem(value,i));
|
||||||
|
|
176
libImaging/Dib.c
176
libImaging/Dib.c
|
@ -39,14 +39,14 @@ ImagingGetModeDIB(int size_out[2])
|
||||||
|
|
||||||
mode = "P";
|
mode = "P";
|
||||||
if (!(GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE)) {
|
if (!(GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE)) {
|
||||||
mode = "RGB";
|
mode = "RGB";
|
||||||
if (GetDeviceCaps(dc, BITSPIXEL) == 1)
|
if (GetDeviceCaps(dc, BITSPIXEL) == 1)
|
||||||
mode = "1";
|
mode = "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size_out) {
|
if (size_out) {
|
||||||
size_out[0] = GetDeviceCaps(dc, HORZRES);
|
size_out[0] = GetDeviceCaps(dc, HORZRES);
|
||||||
size_out[1] = GetDeviceCaps(dc, VERTRES);
|
size_out[1] = GetDeviceCaps(dc, VERTRES);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteDC(dc);
|
DeleteDC(dc);
|
||||||
|
@ -66,18 +66,20 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
|
||||||
|
|
||||||
/* Check mode */
|
/* Check mode */
|
||||||
if (strcmp(mode, "1") != 0 && strcmp(mode, "L") != 0 &&
|
if (strcmp(mode, "1") != 0 && strcmp(mode, "L") != 0 &&
|
||||||
strcmp(mode, "RGB") != 0)
|
strcmp(mode, "RGB") != 0)
|
||||||
return (ImagingDIB) ImagingError_ModeError();
|
return (ImagingDIB) ImagingError_ModeError();
|
||||||
|
|
||||||
/* Create DIB context and info header */
|
/* Create DIB context and info header */
|
||||||
|
/* malloc check ok, small constant allocation */
|
||||||
dib = (ImagingDIB) malloc(sizeof(*dib));
|
dib = (ImagingDIB) malloc(sizeof(*dib));
|
||||||
if (!dib)
|
if (!dib)
|
||||||
return (ImagingDIB) ImagingError_MemoryError();
|
return (ImagingDIB) ImagingError_MemoryError();
|
||||||
|
/* malloc check ok, small constant allocation */
|
||||||
dib->info = (BITMAPINFO*) malloc(sizeof(BITMAPINFOHEADER) +
|
dib->info = (BITMAPINFO*) malloc(sizeof(BITMAPINFOHEADER) +
|
||||||
256 * sizeof(RGBQUAD));
|
256 * sizeof(RGBQUAD));
|
||||||
if (!dib->info) {
|
if (!dib->info) {
|
||||||
free(dib);
|
free(dib);
|
||||||
return (ImagingDIB) ImagingError_MemoryError();
|
return (ImagingDIB) ImagingError_MemoryError();
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(dib->info, 0, sizeof(BITMAPINFOHEADER));
|
memset(dib->info, 0, sizeof(BITMAPINFOHEADER));
|
||||||
|
@ -91,17 +93,17 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
|
||||||
/* Create DIB */
|
/* Create DIB */
|
||||||
dib->dc = CreateCompatibleDC(NULL);
|
dib->dc = CreateCompatibleDC(NULL);
|
||||||
if (!dib->dc) {
|
if (!dib->dc) {
|
||||||
free(dib->info);
|
free(dib->info);
|
||||||
free(dib);
|
free(dib);
|
||||||
return (ImagingDIB) ImagingError_MemoryError();
|
return (ImagingDIB) ImagingError_MemoryError();
|
||||||
}
|
}
|
||||||
|
|
||||||
dib->bitmap = CreateDIBSection(dib->dc, dib->info, DIB_RGB_COLORS,
|
dib->bitmap = CreateDIBSection(dib->dc, dib->info, DIB_RGB_COLORS,
|
||||||
&dib->bits, NULL, 0);
|
&dib->bits, NULL, 0);
|
||||||
if (!dib->bitmap) {
|
if (!dib->bitmap) {
|
||||||
free(dib->info);
|
free(dib->info);
|
||||||
free(dib);
|
free(dib);
|
||||||
return (ImagingDIB) ImagingError_MemoryError();
|
return (ImagingDIB) ImagingError_MemoryError();
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(dib->mode, mode);
|
strcpy(dib->mode, mode);
|
||||||
|
@ -112,10 +114,10 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
|
||||||
dib->linesize = (xsize * dib->pixelsize + 3) & -4;
|
dib->linesize = (xsize * dib->pixelsize + 3) & -4;
|
||||||
|
|
||||||
if (dib->pixelsize == 1)
|
if (dib->pixelsize == 1)
|
||||||
dib->pack = dib->unpack = (ImagingShuffler) memcpy;
|
dib->pack = dib->unpack = (ImagingShuffler) memcpy;
|
||||||
else {
|
else {
|
||||||
dib->pack = ImagingPackBGR;
|
dib->pack = ImagingPackBGR;
|
||||||
dib->unpack = ImagingPackBGR;
|
dib->unpack = ImagingPackBGR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bind the DIB to the device context */
|
/* Bind the DIB to the device context */
|
||||||
|
@ -125,88 +127,88 @@ ImagingNewDIB(const char *mode, int xsize, int ysize)
|
||||||
|
|
||||||
/* Bind a palette to it as well (only required for 8-bit DIBs) */
|
/* Bind a palette to it as well (only required for 8-bit DIBs) */
|
||||||
if (dib->pixelsize == 1) {
|
if (dib->pixelsize == 1) {
|
||||||
for (i = 0; i < 256; i++) {
|
for (i = 0; i < 256; i++) {
|
||||||
palette[i].rgbRed =
|
palette[i].rgbRed =
|
||||||
palette[i].rgbGreen =
|
palette[i].rgbGreen =
|
||||||
palette[i].rgbBlue = i;
|
palette[i].rgbBlue = i;
|
||||||
palette[i].rgbReserved = 0;
|
palette[i].rgbReserved = 0;
|
||||||
}
|
}
|
||||||
SetDIBColorTable(dib->dc, 0, 256, palette);
|
SetDIBColorTable(dib->dc, 0, 256, palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create an associated palette (for 8-bit displays only) */
|
/* Create an associated palette (for 8-bit displays only) */
|
||||||
if (strcmp(ImagingGetModeDIB(NULL), "P") == 0) {
|
if (strcmp(ImagingGetModeDIB(NULL), "P") == 0) {
|
||||||
|
|
||||||
char palbuf[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)];
|
char palbuf[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)];
|
||||||
LPLOGPALETTE pal = (LPLOGPALETTE) palbuf;
|
LPLOGPALETTE pal = (LPLOGPALETTE) palbuf;
|
||||||
int i, r, g, b;
|
int i, r, g, b;
|
||||||
|
|
||||||
/* Load system palette */
|
/* Load system palette */
|
||||||
pal->palVersion = 0x300;
|
pal->palVersion = 0x300;
|
||||||
pal->palNumEntries = 256;
|
pal->palNumEntries = 256;
|
||||||
GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry);
|
GetSystemPaletteEntries(dib->dc, 0, 256, pal->palPalEntry);
|
||||||
|
|
||||||
if (strcmp(mode, "L") == 0) {
|
if (strcmp(mode, "L") == 0) {
|
||||||
|
|
||||||
/* Greyscale DIB. Fill all 236 slots with a greyscale ramp
|
/* Greyscale DIB. Fill all 236 slots with a greyscale ramp
|
||||||
* (this is usually overkill on Windows since VGA only offers
|
* (this is usually overkill on Windows since VGA only offers
|
||||||
* 6 bits greyscale resolution). Ignore the slots already
|
* 6 bits greyscale resolution). Ignore the slots already
|
||||||
* allocated by Windows */
|
* allocated by Windows */
|
||||||
|
|
||||||
i = 10;
|
i = 10;
|
||||||
for (r = 0; r < 236; r++) {
|
for (r = 0; r < 236; r++) {
|
||||||
pal->palPalEntry[i].peRed =
|
pal->palPalEntry[i].peRed =
|
||||||
pal->palPalEntry[i].peGreen =
|
pal->palPalEntry[i].peGreen =
|
||||||
pal->palPalEntry[i].peBlue = i;
|
pal->palPalEntry[i].peBlue = i;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
dib->palette = CreatePalette(pal);
|
dib->palette = CreatePalette(pal);
|
||||||
|
|
||||||
} else if (strcmp(mode, "RGB") == 0) {
|
} else if (strcmp(mode, "RGB") == 0) {
|
||||||
|
|
||||||
#ifdef CUBE216
|
#ifdef CUBE216
|
||||||
|
|
||||||
/* Colour DIB. Create a 6x6x6 colour cube (216 entries) and
|
/* Colour DIB. Create a 6x6x6 colour cube (216 entries) and
|
||||||
* add 20 extra greylevels for best result with greyscale
|
* add 20 extra greylevels for best result with greyscale
|
||||||
* images. */
|
* images. */
|
||||||
|
|
||||||
i = 10;
|
i = 10;
|
||||||
for (r = 0; r < 256; r += 51)
|
for (r = 0; r < 256; r += 51)
|
||||||
for (g = 0; g < 256; g += 51)
|
for (g = 0; g < 256; g += 51)
|
||||||
for (b = 0; b < 256; b += 51) {
|
for (b = 0; b < 256; b += 51) {
|
||||||
pal->palPalEntry[i].peRed = r;
|
pal->palPalEntry[i].peRed = r;
|
||||||
pal->palPalEntry[i].peGreen = g;
|
pal->palPalEntry[i].peGreen = g;
|
||||||
pal->palPalEntry[i].peBlue = b;
|
pal->palPalEntry[i].peBlue = b;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
for (r = 1; r < 22-1; r++) {
|
for (r = 1; r < 22-1; r++) {
|
||||||
/* Black and white are already provided by the cube. */
|
/* Black and white are already provided by the cube. */
|
||||||
pal->palPalEntry[i].peRed =
|
pal->palPalEntry[i].peRed =
|
||||||
pal->palPalEntry[i].peGreen =
|
pal->palPalEntry[i].peGreen =
|
||||||
pal->palPalEntry[i].peBlue = r * 255 / (22-1);
|
pal->palPalEntry[i].peBlue = r * 255 / (22-1);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/* Colour DIB. Alternate palette. */
|
/* Colour DIB. Alternate palette. */
|
||||||
|
|
||||||
i = 10;
|
i = 10;
|
||||||
for (r = 0; r < 256; r += 37)
|
for (r = 0; r < 256; r += 37)
|
||||||
for (g = 0; g < 256; g += 32)
|
for (g = 0; g < 256; g += 32)
|
||||||
for (b = 0; b < 256; b += 64) {
|
for (b = 0; b < 256; b += 64) {
|
||||||
pal->palPalEntry[i].peRed = r;
|
pal->palPalEntry[i].peRed = r;
|
||||||
pal->palPalEntry[i].peGreen = g;
|
pal->palPalEntry[i].peGreen = g;
|
||||||
pal->palPalEntry[i].peBlue = b;
|
pal->palPalEntry[i].peBlue = b;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dib->palette = CreatePalette(pal);
|
dib->palette = CreatePalette(pal);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,8 +224,8 @@ ImagingPasteDIB(ImagingDIB dib, Imaging im, int xy[4])
|
||||||
|
|
||||||
int y;
|
int y;
|
||||||
for (y = 0; y < im->ysize; y++)
|
for (y = 0; y < im->ysize; y++)
|
||||||
dib->pack(dib->bits + dib->linesize*(dib->ysize-(xy[1]+y)-1) +
|
dib->pack(dib->bits + dib->linesize*(dib->ysize-(xy[1]+y)-1) +
|
||||||
xy[0]*dib->pixelsize, im->image[y], im->xsize);
|
xy[0]*dib->pixelsize, im->image[y], im->xsize);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +235,7 @@ ImagingExposeDIB(ImagingDIB dib, void *dc)
|
||||||
/* Copy bitmap to display */
|
/* Copy bitmap to display */
|
||||||
|
|
||||||
if (dib->palette != 0)
|
if (dib->palette != 0)
|
||||||
SelectPalette((HDC) dc, dib->palette, FALSE);
|
SelectPalette((HDC) dc, dib->palette, FALSE);
|
||||||
BitBlt((HDC) dc, 0, 0, dib->xsize, dib->ysize, dib->dc, 0, 0, SRCCOPY);
|
BitBlt((HDC) dc, 0, 0, dib->xsize, dib->ysize, dib->dc, 0, 0, SRCCOPY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,15 +268,15 @@ ImagingQueryPaletteDIB(ImagingDIB dib, void *dc)
|
||||||
|
|
||||||
if (dib->palette != 0) {
|
if (dib->palette != 0) {
|
||||||
|
|
||||||
/* Realize associated palette */
|
/* Realize associated palette */
|
||||||
HPALETTE now = SelectPalette((HDC) dc, dib->palette, FALSE);
|
HPALETTE now = SelectPalette((HDC) dc, dib->palette, FALSE);
|
||||||
n = RealizePalette((HDC) dc);
|
n = RealizePalette((HDC) dc);
|
||||||
|
|
||||||
/* Restore palette */
|
/* Restore palette */
|
||||||
SelectPalette((HDC) dc, now, FALSE);
|
SelectPalette((HDC) dc, now, FALSE);
|
||||||
|
|
||||||
} else
|
} else
|
||||||
n = 0;
|
n = 0;
|
||||||
|
|
||||||
return n; /* number of colours that was changed */
|
return n; /* number of colours that was changed */
|
||||||
}
|
}
|
||||||
|
@ -285,13 +287,13 @@ ImagingDeleteDIB(ImagingDIB dib)
|
||||||
/* Clean up */
|
/* Clean up */
|
||||||
|
|
||||||
if (dib->palette)
|
if (dib->palette)
|
||||||
DeleteObject(dib->palette);
|
DeleteObject(dib->palette);
|
||||||
if (dib->bitmap) {
|
if (dib->bitmap) {
|
||||||
SelectObject(dib->dc, dib->old_bitmap);
|
SelectObject(dib->dc, dib->old_bitmap);
|
||||||
DeleteObject(dib->bitmap);
|
DeleteObject(dib->bitmap);
|
||||||
}
|
}
|
||||||
if (dib->dc)
|
if (dib->dc)
|
||||||
DeleteDC(dib->dc);
|
DeleteDC(dib->dc);
|
||||||
free(dib->info);
|
free(dib->info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -434,7 +434,8 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the edge table and find polygon boundaries */
|
/* Initialize the edge table and find polygon boundaries */
|
||||||
edge_table = malloc(sizeof(Edge*) * n);
|
/* malloc check ok, using calloc */
|
||||||
|
edge_table = calloc(n, sizeof(Edge*));
|
||||||
if (!edge_table) {
|
if (!edge_table) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -462,7 +463,8 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process the edge table with a scan line searching for intersections */
|
/* Process the edge table with a scan line searching for intersections */
|
||||||
xx = malloc(sizeof(float) * edge_count * 2);
|
/* malloc check ok, using calloc */
|
||||||
|
xx = calloc(edge_count * 2, sizeof(float));
|
||||||
if (!xx) {
|
if (!xx) {
|
||||||
free(edge_table);
|
free(edge_table);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -700,7 +702,8 @@ ImagingDrawPolygon(Imaging im, int count, int* xy, const void* ink_,
|
||||||
if (fill) {
|
if (fill) {
|
||||||
|
|
||||||
/* Build edge list */
|
/* Build edge list */
|
||||||
Edge* e = malloc(count * sizeof(Edge));
|
/* malloc check ok, using calloc */
|
||||||
|
Edge* e = calloc(count, sizeof(Edge));
|
||||||
if (!e) {
|
if (!e) {
|
||||||
(void) ImagingError_MemoryError();
|
(void) ImagingError_MemoryError();
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -769,10 +772,16 @@ ellipse(Imaging im, int x0, int y0, int x1, int y1,
|
||||||
while (end < start)
|
while (end < start)
|
||||||
end += 360;
|
end += 360;
|
||||||
|
|
||||||
|
if (end - start > 360) {
|
||||||
|
/* no need to go in loops */
|
||||||
|
end = start + 361;
|
||||||
|
}
|
||||||
|
|
||||||
if (mode != ARC && fill) {
|
if (mode != ARC && fill) {
|
||||||
|
|
||||||
/* Build edge list */
|
/* Build edge list */
|
||||||
Edge* e = malloc((end - start + 3) * sizeof(Edge));
|
/* malloc check UNDONE, FLOAT? */
|
||||||
|
Edge* e = calloc((end - start + 3), sizeof(Edge));
|
||||||
if (!e) {
|
if (!e) {
|
||||||
ImagingError_MemoryError();
|
ImagingError_MemoryError();
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -929,10 +938,16 @@ allocate(ImagingOutline outline, int extra)
|
||||||
if (outline->count + extra > outline->size) {
|
if (outline->count + extra > outline->size) {
|
||||||
/* expand outline buffer */
|
/* expand outline buffer */
|
||||||
outline->size += extra + 25;
|
outline->size += extra + 25;
|
||||||
if (!outline->edges)
|
if (!outline->edges) {
|
||||||
e = malloc(outline->size * sizeof(Edge));
|
/* malloc check ok, uses calloc for overflow */
|
||||||
else
|
e = calloc(outline->size, sizeof(Edge));
|
||||||
|
} else {
|
||||||
|
if (outline->size > INT_MAX / sizeof(Edge)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* malloc check ok, overflow checked above */
|
||||||
e = realloc(outline->edges, outline->size * sizeof(Edge));
|
e = realloc(outline->edges, outline->size * sizeof(Edge));
|
||||||
|
}
|
||||||
if (!e)
|
if (!e)
|
||||||
return NULL;
|
return NULL;
|
||||||
outline->edges = e;
|
outline->edges = e;
|
||||||
|
|
|
@ -684,7 +684,8 @@ ImagingScaleAffine(Imaging imOut, Imaging imIn,
|
||||||
if (y1 > imOut->ysize)
|
if (y1 > imOut->ysize)
|
||||||
y1 = imOut->ysize;
|
y1 = imOut->ysize;
|
||||||
|
|
||||||
xintab = (int*) malloc(imOut->xsize * sizeof(int));
|
/* malloc check ok, uses calloc for overflow */
|
||||||
|
xintab = (int*) calloc(imOut->xsize, sizeof(int));
|
||||||
if (!xintab) {
|
if (!xintab) {
|
||||||
ImagingDelete(imOut);
|
ImagingDelete(imOut);
|
||||||
return (Imaging) ImagingError_MemoryError();
|
return (Imaging) ImagingError_MemoryError();
|
||||||
|
|
|
@ -61,6 +61,7 @@ emit(GIFENCODERSTATE *context, int byte)
|
||||||
block = context->free;
|
block = context->free;
|
||||||
context->free = NULL;
|
context->free = NULL;
|
||||||
} else {
|
} else {
|
||||||
|
/* malloc check ok, small constant allocation */
|
||||||
block = malloc(sizeof(GIFENCODERBLOCK));
|
block = malloc(sizeof(GIFENCODERBLOCK));
|
||||||
if (!block)
|
if (!block)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -168,9 +168,9 @@ extern Imaging ImagingNewMap(const char* filename, int readonly,
|
||||||
const char* mode, int xsize, int ysize);
|
const char* mode, int xsize, int ysize);
|
||||||
|
|
||||||
extern Imaging ImagingNewPrologue(const char *mode,
|
extern Imaging ImagingNewPrologue(const char *mode,
|
||||||
unsigned xsize, unsigned ysize);
|
int xsize, int ysize);
|
||||||
extern Imaging ImagingNewPrologueSubtype(const char *mode,
|
extern Imaging ImagingNewPrologueSubtype(const char *mode,
|
||||||
unsigned xsize, unsigned ysize,
|
int xsize, int ysize,
|
||||||
int structure_size);
|
int structure_size);
|
||||||
extern Imaging ImagingNewEpilogue(Imaging im);
|
extern Imaging ImagingNewEpilogue(Imaging im);
|
||||||
|
|
||||||
|
@ -453,6 +453,7 @@ extern int ImagingZipDecode(Imaging im, ImagingCodecState state,
|
||||||
UINT8* buffer, int bytes);
|
UINT8* buffer, int bytes);
|
||||||
extern int ImagingZipEncode(Imaging im, ImagingCodecState state,
|
extern int ImagingZipEncode(Imaging im, ImagingCodecState state,
|
||||||
UINT8* buffer, int bytes);
|
UINT8* buffer, int bytes);
|
||||||
|
extern int ImagingZipEncodeCleanup(ImagingCodecState state);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void (*ImagingShuffler)(UINT8* out, const UINT8* in, int pixels);
|
typedef void (*ImagingShuffler)(UINT8* out, const UINT8* in, int pixels);
|
||||||
|
|
|
@ -168,6 +168,7 @@ ImagingIncrementalCodecCreate(ImagingIncrementalCodecEntry codec_entry,
|
||||||
int seekable,
|
int seekable,
|
||||||
int fd)
|
int fd)
|
||||||
{
|
{
|
||||||
|
/* malloc check ok, small constant allocation */
|
||||||
ImagingIncrementalCodec codec = (ImagingIncrementalCodec)malloc(sizeof(struct ImagingIncrementalCodecStruct));
|
ImagingIncrementalCodec codec = (ImagingIncrementalCodec)malloc(sizeof(struct ImagingIncrementalCodecStruct));
|
||||||
|
|
||||||
codec->entry = codec_entry;
|
codec->entry = codec_entry;
|
||||||
|
@ -370,7 +371,17 @@ ImagingIncrementalCodecPushBuffer(ImagingIncrementalCodec codec,
|
||||||
/* In this specific case, we append to a buffer we allocate ourselves */
|
/* In this specific case, we append to a buffer we allocate ourselves */
|
||||||
size_t old_size = codec->stream.end - codec->stream.buffer;
|
size_t old_size = codec->stream.end - codec->stream.buffer;
|
||||||
size_t new_size = codec->stream.end - codec->stream.buffer + bytes;
|
size_t new_size = codec->stream.end - codec->stream.buffer + bytes;
|
||||||
UINT8 *new = (UINT8 *)realloc (codec->stream.buffer, new_size);
|
UINT8 *new;
|
||||||
|
|
||||||
|
if (old_size > SIZE_MAX - bytes) {
|
||||||
|
codec->state->errcode = IMAGING_CODEC_MEMORY;
|
||||||
|
#ifndef _WIN32
|
||||||
|
pthread_mutex_unlock(&codec->data_mutex);
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* malloc check ok, overflow checked */
|
||||||
|
new = (UINT8 *)realloc (codec->stream.buffer, new_size);
|
||||||
|
|
||||||
if (!new) {
|
if (!new) {
|
||||||
codec->state->errcode = IMAGING_CODEC_MEMORY;
|
codec->state->errcode = IMAGING_CODEC_MEMORY;
|
||||||
|
|
|
@ -702,6 +702,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state,
|
||||||
tile_info.y1 = (tile_info.y1 + correction) >> context->reduce;
|
tile_info.y1 = (tile_info.y1 + correction) >> context->reduce;
|
||||||
|
|
||||||
if (buffer_size < tile_info.data_size) {
|
if (buffer_size < tile_info.data_size) {
|
||||||
|
/* malloc check ok, tile_info.data_size from openjpeg */
|
||||||
UINT8 *new = realloc (state->buffer, tile_info.data_size);
|
UINT8 *new = realloc (state->buffer, tile_info.data_size);
|
||||||
if (!new) {
|
if (!new) {
|
||||||
state->errcode = IMAGING_CODEC_MEMORY;
|
state->errcode = IMAGING_CODEC_MEMORY;
|
||||||
|
|
|
@ -31,20 +31,20 @@ ImagingPaletteNew(const char* mode)
|
||||||
ImagingPalette palette;
|
ImagingPalette palette;
|
||||||
|
|
||||||
if (strcmp(mode, "RGB") && strcmp(mode, "RGBA"))
|
if (strcmp(mode, "RGB") && strcmp(mode, "RGBA"))
|
||||||
return (ImagingPalette) ImagingError_ModeError();
|
return (ImagingPalette) ImagingError_ModeError();
|
||||||
|
|
||||||
palette = calloc(1, sizeof(struct ImagingPaletteInstance));
|
palette = calloc(1, sizeof(struct ImagingPaletteInstance));
|
||||||
if (!palette)
|
if (!palette)
|
||||||
return (ImagingPalette) ImagingError_MemoryError();
|
return (ImagingPalette) ImagingError_MemoryError();
|
||||||
|
|
||||||
strncpy(palette->mode, mode, IMAGING_MODE_LENGTH);
|
strncpy(palette->mode, mode, IMAGING_MODE_LENGTH);
|
||||||
|
|
||||||
/* Initialize to ramp */
|
/* Initialize to ramp */
|
||||||
for (i = 0; i < 256; i++) {
|
for (i = 0; i < 256; i++) {
|
||||||
palette->palette[i*4+0] =
|
palette->palette[i*4+0] =
|
||||||
palette->palette[i*4+1] =
|
palette->palette[i*4+1] =
|
||||||
palette->palette[i*4+2] = (UINT8) i;
|
palette->palette[i*4+2] = (UINT8) i;
|
||||||
palette->palette[i*4+3] = 255; /* opaque */
|
palette->palette[i*4+3] = 255; /* opaque */
|
||||||
}
|
}
|
||||||
|
|
||||||
return palette;
|
return palette;
|
||||||
|
@ -60,35 +60,35 @@ ImagingPaletteNewBrowser(void)
|
||||||
|
|
||||||
palette = ImagingPaletteNew("RGB");
|
palette = ImagingPaletteNew("RGB");
|
||||||
if (!palette)
|
if (!palette)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Blank out unused entries */
|
/* Blank out unused entries */
|
||||||
/* FIXME: Add 10-level windows palette here? */
|
/* FIXME: Add 10-level windows palette here? */
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
palette->palette[i*4+0] =
|
palette->palette[i*4+0] =
|
||||||
palette->palette[i*4+1] =
|
palette->palette[i*4+1] =
|
||||||
palette->palette[i*4+2] = 0;
|
palette->palette[i*4+2] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Simple 6x6x6 colour cube */
|
/* Simple 6x6x6 colour cube */
|
||||||
|
|
||||||
for (b = 0; b < 256; b += 51)
|
for (b = 0; b < 256; b += 51)
|
||||||
for (g = 0; g < 256; g += 51)
|
for (g = 0; g < 256; g += 51)
|
||||||
for (r = 0; r < 256; r += 51) {
|
for (r = 0; r < 256; r += 51) {
|
||||||
palette->palette[i*4+0] = r;
|
palette->palette[i*4+0] = r;
|
||||||
palette->palette[i*4+1] = g;
|
palette->palette[i*4+1] = g;
|
||||||
palette->palette[i*4+2] = b;
|
palette->palette[i*4+2] = b;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Blank out unused entries */
|
/* Blank out unused entries */
|
||||||
/* FIXME: add 30-level greyscale wedge here? */
|
/* FIXME: add 30-level greyscale wedge here? */
|
||||||
|
|
||||||
for (; i < 256; i++) {
|
for (; i < 256; i++) {
|
||||||
palette->palette[i*4+0] =
|
palette->palette[i*4+0] =
|
||||||
palette->palette[i*4+1] =
|
palette->palette[i*4+1] =
|
||||||
palette->palette[i*4+2] = 0;
|
palette->palette[i*4+2] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return palette;
|
return palette;
|
||||||
|
@ -102,11 +102,11 @@ ImagingPaletteDuplicate(ImagingPalette palette)
|
||||||
ImagingPalette new_palette;
|
ImagingPalette new_palette;
|
||||||
|
|
||||||
if (!palette)
|
if (!palette)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
/* malloc check ok, small constant allocation */
|
||||||
new_palette = malloc(sizeof(struct ImagingPaletteInstance));
|
new_palette = malloc(sizeof(struct ImagingPaletteInstance));
|
||||||
if (!new_palette)
|
if (!new_palette)
|
||||||
return (ImagingPalette) ImagingError_MemoryError();
|
return (ImagingPalette) ImagingError_MemoryError();
|
||||||
|
|
||||||
memcpy(new_palette, palette, sizeof(struct ImagingPaletteInstance));
|
memcpy(new_palette, palette, sizeof(struct ImagingPaletteInstance));
|
||||||
|
|
||||||
|
@ -122,15 +122,15 @@ ImagingPaletteDelete(ImagingPalette palette)
|
||||||
/* Destroy palette object */
|
/* Destroy palette object */
|
||||||
|
|
||||||
if (palette) {
|
if (palette) {
|
||||||
if (palette->cache)
|
if (palette->cache)
|
||||||
free(palette->cache);
|
free(palette->cache);
|
||||||
free(palette);
|
free(palette);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/* Colour mapping */
|
/* Colour mapping */
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* This code is used to map RGB triplets to palette indices, using
|
/* This code is used to map RGB triplets to palette indices, using
|
||||||
|
@ -143,26 +143,26 @@ ImagingPaletteDelete(ImagingPalette palette)
|
||||||
*
|
*
|
||||||
* The IJG JPEG library is copyright (C) 1991-1995, Thomas G. Lane. */
|
* The IJG JPEG library is copyright (C) 1991-1995, Thomas G. Lane. */
|
||||||
|
|
||||||
#define DIST(a, b, s) (a - b) * (a - b) * s
|
#define DIST(a, b, s) (a - b) * (a - b) * s
|
||||||
|
|
||||||
/* Colour weights (no scaling, for now) */
|
/* Colour weights (no scaling, for now) */
|
||||||
#define RSCALE 1
|
#define RSCALE 1
|
||||||
#define GSCALE 1
|
#define GSCALE 1
|
||||||
#define BSCALE 1
|
#define BSCALE 1
|
||||||
|
|
||||||
/* Calculated scaled distances */
|
/* Calculated scaled distances */
|
||||||
#define RDIST(a, b) DIST(a, b, RSCALE*RSCALE)
|
#define RDIST(a, b) DIST(a, b, RSCALE*RSCALE)
|
||||||
#define GDIST(a, b) DIST(a, b, GSCALE*GSCALE)
|
#define GDIST(a, b) DIST(a, b, GSCALE*GSCALE)
|
||||||
#define BDIST(a, b) DIST(a, b, BSCALE*BSCALE)
|
#define BDIST(a, b) DIST(a, b, BSCALE*BSCALE)
|
||||||
|
|
||||||
/* Incremental steps */
|
/* Incremental steps */
|
||||||
#define RSTEP (4 * RSCALE)
|
#define RSTEP (4 * RSCALE)
|
||||||
#define GSTEP (4 * GSCALE)
|
#define GSTEP (4 * GSCALE)
|
||||||
#define BSTEP (4 * BSCALE)
|
#define BSTEP (4 * BSCALE)
|
||||||
|
|
||||||
#define BOX 8
|
#define BOX 8
|
||||||
|
|
||||||
#define BOXVOLUME BOX*BOX*BOX
|
#define BOXVOLUME BOX*BOX*BOX
|
||||||
|
|
||||||
void
|
void
|
||||||
ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
|
ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
|
||||||
|
@ -191,25 +191,25 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
|
||||||
|
|
||||||
for (i = 0; i < 256; i++) {
|
for (i = 0; i < 256; i++) {
|
||||||
|
|
||||||
int r, g, b;
|
int r, g, b;
|
||||||
unsigned int tmin, tmax;
|
unsigned int tmin, tmax;
|
||||||
|
|
||||||
/* Find min and max distances to any point in the box */
|
/* Find min and max distances to any point in the box */
|
||||||
r = palette->palette[i*4+0];
|
r = palette->palette[i*4+0];
|
||||||
tmin = (r < r0) ? RDIST(r, r1) : (r > r1) ? RDIST(r, r0) : 0;
|
tmin = (r < r0) ? RDIST(r, r1) : (r > r1) ? RDIST(r, r0) : 0;
|
||||||
tmax = (r <= rc) ? RDIST(r, r1) : RDIST(r, r0);
|
tmax = (r <= rc) ? RDIST(r, r1) : RDIST(r, r0);
|
||||||
|
|
||||||
g = palette->palette[i*4+1];
|
g = palette->palette[i*4+1];
|
||||||
tmin += (g < g0) ? GDIST(g, g1) : (g > g1) ? GDIST(g, g0) : 0;
|
tmin += (g < g0) ? GDIST(g, g1) : (g > g1) ? GDIST(g, g0) : 0;
|
||||||
tmax += (g <= gc) ? GDIST(g, g1) : GDIST(g, g0);
|
tmax += (g <= gc) ? GDIST(g, g1) : GDIST(g, g0);
|
||||||
|
|
||||||
b = palette->palette[i*4+2];
|
b = palette->palette[i*4+2];
|
||||||
tmin += (b < b0) ? BDIST(b, b1) : (b > b1) ? BDIST(b, b0) : 0;
|
tmin += (b < b0) ? BDIST(b, b1) : (b > b1) ? BDIST(b, b0) : 0;
|
||||||
tmax += (b <= bc) ? BDIST(b, b1) : BDIST(b, b0);
|
tmax += (b <= bc) ? BDIST(b, b1) : BDIST(b, b0);
|
||||||
|
|
||||||
dmin[i] = tmin;
|
dmin[i] = tmin;
|
||||||
if (tmax < dmax)
|
if (tmax < dmax)
|
||||||
dmax = tmax; /* keep the smallest max distance only */
|
dmax = tmax; /* keep the smallest max distance only */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,47 +220,47 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
|
||||||
* distance is less than or equal the smallest max distance */
|
* distance is less than or equal the smallest max distance */
|
||||||
|
|
||||||
for (i = 0; i < BOXVOLUME; i++)
|
for (i = 0; i < BOXVOLUME; i++)
|
||||||
d[i] = (unsigned int) ~0;
|
d[i] = (unsigned int) ~0;
|
||||||
|
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
|
|
||||||
if (dmin[i] <= dmax) {
|
if (dmin[i] <= dmax) {
|
||||||
|
|
||||||
int rd, gd, bd;
|
int rd, gd, bd;
|
||||||
int ri, gi, bi;
|
int ri, gi, bi;
|
||||||
int rx, gx, bx;
|
int rx, gx, bx;
|
||||||
|
|
||||||
ri = (r0 - palette->palette[i*4+0]) * RSCALE;
|
ri = (r0 - palette->palette[i*4+0]) * RSCALE;
|
||||||
gi = (g0 - palette->palette[i*4+1]) * GSCALE;
|
gi = (g0 - palette->palette[i*4+1]) * GSCALE;
|
||||||
bi = (b0 - palette->palette[i*4+2]) * BSCALE;
|
bi = (b0 - palette->palette[i*4+2]) * BSCALE;
|
||||||
|
|
||||||
rd = ri*ri + gi*gi + bi*bi;
|
rd = ri*ri + gi*gi + bi*bi;
|
||||||
|
|
||||||
ri = ri * (2 * RSTEP) + RSTEP * RSTEP;
|
ri = ri * (2 * RSTEP) + RSTEP * RSTEP;
|
||||||
gi = gi * (2 * GSTEP) + GSTEP * GSTEP;
|
gi = gi * (2 * GSTEP) + GSTEP * GSTEP;
|
||||||
bi = bi * (2 * BSTEP) + BSTEP * BSTEP;
|
bi = bi * (2 * BSTEP) + BSTEP * BSTEP;
|
||||||
|
|
||||||
rx = ri;
|
rx = ri;
|
||||||
for (r = j = 0; r < BOX; r++) {
|
for (r = j = 0; r < BOX; r++) {
|
||||||
gd = rd; gx = gi;
|
gd = rd; gx = gi;
|
||||||
for (g = 0; g < BOX; g++) {
|
for (g = 0; g < BOX; g++) {
|
||||||
bd = gd; bx = bi;
|
bd = gd; bx = bi;
|
||||||
for (b = 0; b < BOX; b++) {
|
for (b = 0; b < BOX; b++) {
|
||||||
if ((unsigned int) bd < d[j]) {
|
if ((unsigned int) bd < d[j]) {
|
||||||
d[j] = bd;
|
d[j] = bd;
|
||||||
c[j] = (UINT8) i;
|
c[j] = (UINT8) i;
|
||||||
}
|
}
|
||||||
bd += bx;
|
bd += bx;
|
||||||
bx += 2 * BSTEP * BSTEP;
|
bx += 2 * BSTEP * BSTEP;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
gd += gx;
|
gd += gx;
|
||||||
gx += 2 * GSTEP * GSTEP;
|
gx += 2 * GSTEP * GSTEP;
|
||||||
}
|
}
|
||||||
rd += rx;
|
rd += rx;
|
||||||
rx += 2 * RSTEP * RSTEP;
|
rx += 2 * RSTEP * RSTEP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step 3 -- Update cache */
|
/* Step 3 -- Update cache */
|
||||||
|
|
||||||
|
@ -269,9 +269,9 @@ ImagingPaletteCacheUpdate(ImagingPalette palette, int r, int g, int b)
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
for (r = r0; r < r1; r+=4)
|
for (r = r0; r < r1; r+=4)
|
||||||
for (g = g0; g < g1; g+=4)
|
for (g = g0; g < g1; g+=4)
|
||||||
for (b = b0; b < b1; b+=4)
|
for (b = b0; b < b1; b+=4)
|
||||||
ImagingPaletteCache(palette, r, g, b) = c[j++];
|
ImagingPaletteCache(palette, r, g, b) = c[j++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -285,18 +285,19 @@ ImagingPaletteCachePrepare(ImagingPalette palette)
|
||||||
|
|
||||||
if (palette->cache == NULL) {
|
if (palette->cache == NULL) {
|
||||||
|
|
||||||
/* The cache is 512k. It might be a good idea to break it
|
/* The cache is 512k. It might be a good idea to break it
|
||||||
up into a pointer array (e.g. an 8-bit image?) */
|
up into a pointer array (e.g. an 8-bit image?) */
|
||||||
|
|
||||||
palette->cache = (INT16*) malloc(entries * sizeof(INT16));
|
/* malloc check ok, small constant allocation */
|
||||||
if (!palette->cache) {
|
palette->cache = (INT16*) malloc(entries * sizeof(INT16));
|
||||||
(void) ImagingError_MemoryError();
|
if (!palette->cache) {
|
||||||
return -1;
|
(void) ImagingError_MemoryError();
|
||||||
}
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Mark all entries as empty */
|
/* Mark all entries as empty */
|
||||||
for (i = 0; i < entries; i++)
|
for (i = 0; i < entries; i++)
|
||||||
palette->cache[i] = 0x100;
|
palette->cache[i] = 0x100;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,7 +311,7 @@ ImagingPaletteCacheDelete(ImagingPalette palette)
|
||||||
/* Release the colour cache, if any */
|
/* Release the colour cache, if any */
|
||||||
|
|
||||||
if (palette && palette->cache) {
|
if (palette && palette->cache) {
|
||||||
free(palette->cache);
|
free(palette->cache);
|
||||||
palette->cache = NULL;
|
palette->cache = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,11 @@
|
||||||
#include "QuantHash.h"
|
#include "QuantHash.h"
|
||||||
#include "QuantHeap.h"
|
#include "QuantHeap.h"
|
||||||
|
|
||||||
|
/* MSVC9.0 */
|
||||||
|
#ifndef UINT32_MAX
|
||||||
|
#define UINT32_MAX 0xffffffff
|
||||||
|
#endif
|
||||||
|
|
||||||
#define NO_OUTPUT
|
#define NO_OUTPUT
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -150,6 +155,7 @@ create_pixel_hash(Pixel *pixelData,uint32_t nPixels)
|
||||||
uint32_t timer,timer2,timer3;
|
uint32_t timer,timer2,timer3;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* malloc check ok, small constant allocation */
|
||||||
d=malloc(sizeof(PixelHashData));
|
d=malloc(sizeof(PixelHashData));
|
||||||
if (!d) return NULL;
|
if (!d) return NULL;
|
||||||
hash=hashtable_new(pixel_hash,pixel_cmp);
|
hash=hashtable_new(pixel_hash,pixel_cmp);
|
||||||
|
@ -234,6 +240,7 @@ hash_to_list(const HashTable *h, const Pixel pixel, const uint32_t count, void *
|
||||||
|
|
||||||
PIXEL_SCALE(&pixel,&q,d->scale);
|
PIXEL_SCALE(&pixel,&q,d->scale);
|
||||||
|
|
||||||
|
/* malloc check ok, small constant allocation */
|
||||||
p=malloc(sizeof(PixelList));
|
p=malloc(sizeof(PixelList));
|
||||||
if (!p) return;
|
if (!p) return;
|
||||||
|
|
||||||
|
@ -557,6 +564,7 @@ split(BoxNode *node)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
/* malloc check ok, small constant allocation */
|
||||||
left=malloc(sizeof(BoxNode));
|
left=malloc(sizeof(BoxNode));
|
||||||
right=malloc(sizeof(BoxNode));
|
right=malloc(sizeof(BoxNode));
|
||||||
if (!left||!right) {
|
if (!left||!right) {
|
||||||
|
@ -613,6 +621,7 @@ median_cut(PixelList *hl[3],
|
||||||
BoxNode *thisNode;
|
BoxNode *thisNode;
|
||||||
|
|
||||||
h=ImagingQuantHeapNew(box_heap_cmp);
|
h=ImagingQuantHeapNew(box_heap_cmp);
|
||||||
|
/* malloc check ok, small constant allocation */
|
||||||
root=malloc(sizeof(BoxNode));
|
root=malloc(sizeof(BoxNode));
|
||||||
if (!root) { ImagingQuantHeapFree(h); return NULL; }
|
if (!root) { ImagingQuantHeapFree(h); return NULL; }
|
||||||
for(i=0;i<3;i++) {
|
for(i=0;i<3;i++) {
|
||||||
|
@ -954,15 +963,16 @@ compute_palette_from_median_cut(
|
||||||
uint32_t *count;
|
uint32_t *count;
|
||||||
|
|
||||||
*palette=NULL;
|
*palette=NULL;
|
||||||
if (!(count=malloc(sizeof(uint32_t)*nPaletteEntries))) {
|
/* malloc check ok, using calloc */
|
||||||
|
if (!(count=calloc(nPaletteEntries, sizeof(uint32_t)))) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memset(count,0,sizeof(uint32_t)*nPaletteEntries);
|
|
||||||
for(i=0;i<3;i++) {
|
for(i=0;i<3;i++) {
|
||||||
avg[i]=NULL;
|
avg[i]=NULL;
|
||||||
}
|
}
|
||||||
for(i=0;i<3;i++) {
|
for(i=0;i<3;i++) {
|
||||||
if (!(avg[i]=malloc(sizeof(uint32_t)*nPaletteEntries))) {
|
/* malloc check ok, using calloc */
|
||||||
|
if (!(avg[i]=calloc(nPaletteEntries, sizeof(uint32_t)))) {
|
||||||
for(i=0;i<3;i++) {
|
for(i=0;i<3;i++) {
|
||||||
if (avg[i]) free (avg[i]);
|
if (avg[i]) free (avg[i]);
|
||||||
}
|
}
|
||||||
|
@ -970,9 +980,6 @@ compute_palette_from_median_cut(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(i=0;i<3;i++) {
|
|
||||||
memset(avg[i],0,sizeof(uint32_t)*nPaletteEntries);
|
|
||||||
}
|
|
||||||
for (i=0;i<nPixels;i++) {
|
for (i=0;i<nPixels;i++) {
|
||||||
#ifdef TEST_SPLIT_INTEGRITY
|
#ifdef TEST_SPLIT_INTEGRITY
|
||||||
if (!(i%100)) { printf ("%05d\r",i); fflush(stdout); }
|
if (!(i%100)) { printf ("%05d\r",i); fflush(stdout); }
|
||||||
|
@ -1004,7 +1011,8 @@ compute_palette_from_median_cut(
|
||||||
avg[2][paletteEntry]+=pixelData[i].c.b;
|
avg[2][paletteEntry]+=pixelData[i].c.b;
|
||||||
count[paletteEntry]++;
|
count[paletteEntry]++;
|
||||||
}
|
}
|
||||||
p=malloc(sizeof(Pixel)*nPaletteEntries);
|
/* malloc check ok, using calloc */
|
||||||
|
p=calloc(nPaletteEntries, sizeof(Pixel));
|
||||||
if (!p) {
|
if (!p) {
|
||||||
for(i=0;i<3;i++) free (avg[i]);
|
for(i=0;i<3;i++) free (avg[i]);
|
||||||
free(count);
|
free(count);
|
||||||
|
@ -1090,21 +1098,33 @@ k_means(Pixel *pixelData,
|
||||||
int changes;
|
int changes;
|
||||||
int built=0;
|
int built=0;
|
||||||
|
|
||||||
if (!(count=malloc(sizeof(uint32_t)*nPaletteEntries))) {
|
if (nPaletteEntries > UINT32_MAX / (sizeof(uint32_t))) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* malloc check ok, using calloc */
|
||||||
|
if (!(count=calloc(nPaletteEntries, sizeof(uint32_t)))) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for(i=0;i<3;i++) {
|
for(i=0;i<3;i++) {
|
||||||
avg[i]=NULL;
|
avg[i]=NULL;
|
||||||
}
|
}
|
||||||
for(i=0;i<3;i++) {
|
for(i=0;i<3;i++) {
|
||||||
if (!(avg[i]=malloc(sizeof(uint32_t)*nPaletteEntries))) {
|
/* malloc check ok, using calloc */
|
||||||
|
if (!(avg[i]=calloc(nPaletteEntries, sizeof(uint32_t)))) {
|
||||||
goto error_1;
|
goto error_1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
avgDist=malloc(sizeof(uint32_t)*nPaletteEntries*nPaletteEntries);
|
|
||||||
|
/* this is enough of a check, since the multiplication n*size is done above */
|
||||||
|
if (nPaletteEntries > UINT32_MAX / nPaletteEntries) {
|
||||||
|
goto error_1;
|
||||||
|
}
|
||||||
|
/* malloc check ok, using calloc, checking n*n above */
|
||||||
|
avgDist=calloc(nPaletteEntries*nPaletteEntries, sizeof(uint32_t));
|
||||||
if (!avgDist) { goto error_1; }
|
if (!avgDist) { goto error_1; }
|
||||||
|
|
||||||
avgDistSortKey=malloc(sizeof(uint32_t *)*nPaletteEntries*nPaletteEntries);
|
/* malloc check ok, using calloc, checking n*n above */
|
||||||
|
avgDistSortKey=calloc(nPaletteEntries*nPaletteEntries, sizeof(uint32_t *));
|
||||||
if (!avgDistSortKey) { goto error_2; }
|
if (!avgDistSortKey) { goto error_2; }
|
||||||
|
|
||||||
#ifndef NO_OUTPUT
|
#ifndef NO_OUTPUT
|
||||||
|
@ -1251,13 +1271,19 @@ quantize(Pixel *pixelData,
|
||||||
free_box_tree(root);
|
free_box_tree(root);
|
||||||
root=NULL;
|
root=NULL;
|
||||||
|
|
||||||
qp=malloc(sizeof(uint32_t)*nPixels);
|
/* malloc check ok, using calloc for overflow */
|
||||||
|
qp=calloc(nPixels, sizeof(uint32_t));
|
||||||
if (!qp) { goto error_4; }
|
if (!qp) { goto error_4; }
|
||||||
|
|
||||||
avgDist=malloc(sizeof(uint32_t)*nPaletteEntries*nPaletteEntries);
|
if (nPaletteEntries > UINT32_MAX / nPaletteEntries ) {
|
||||||
|
goto error_5;
|
||||||
|
}
|
||||||
|
/* malloc check ok, using calloc for overflow, check of n*n above */
|
||||||
|
avgDist=calloc(nPaletteEntries*nPaletteEntries, sizeof(uint32_t));
|
||||||
if (!avgDist) { goto error_5; }
|
if (!avgDist) { goto error_5; }
|
||||||
|
|
||||||
avgDistSortKey=malloc(sizeof(uint32_t *)*nPaletteEntries*nPaletteEntries);
|
/* malloc check ok, using calloc for overflow, check of n*n above */
|
||||||
|
avgDistSortKey=calloc(nPaletteEntries*nPaletteEntries, sizeof(uint32_t *));
|
||||||
if (!avgDistSortKey) { goto error_6; }
|
if (!avgDistSortKey) { goto error_6; }
|
||||||
|
|
||||||
if (!build_distance_tables(avgDist,avgDistSortKey,p,nPaletteEntries)) {
|
if (!build_distance_tables(avgDist,avgDistSortKey,p,nPaletteEntries)) {
|
||||||
|
@ -1400,7 +1426,8 @@ quantize2(Pixel *pixelData,
|
||||||
uint32_t *avgDist;
|
uint32_t *avgDist;
|
||||||
uint32_t **avgDistSortKey;
|
uint32_t **avgDistSortKey;
|
||||||
|
|
||||||
p=malloc(sizeof(Pixel)*nQuantPixels);
|
/* malloc check ok, using calloc */
|
||||||
|
p=calloc(nQuantPixels, sizeof(Pixel));
|
||||||
if (!p) return 0;
|
if (!p) return 0;
|
||||||
mean[0]=mean[1]=mean[2]=0;
|
mean[0]=mean[1]=mean[2]=0;
|
||||||
h=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
|
h=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
|
||||||
|
@ -1422,13 +1449,20 @@ quantize2(Pixel *pixelData,
|
||||||
}
|
}
|
||||||
hashtable_free(h);
|
hashtable_free(h);
|
||||||
|
|
||||||
qp=malloc(sizeof(uint32_t)*nPixels);
|
/* malloc check ok, using calloc */
|
||||||
|
qp=calloc(nPixels, sizeof(uint32_t));
|
||||||
if (!qp) { goto error_1; }
|
if (!qp) { goto error_1; }
|
||||||
|
|
||||||
avgDist=malloc(sizeof(uint32_t)*nQuantPixels*nQuantPixels);
|
if (nQuantPixels > UINT32_MAX / nQuantPixels ) {
|
||||||
|
goto error_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* malloc check ok, using calloc for overflow, check of n*n above */
|
||||||
|
avgDist=calloc(nQuantPixels*nQuantPixels, sizeof(uint32_t));
|
||||||
if (!avgDist) { goto error_2; }
|
if (!avgDist) { goto error_2; }
|
||||||
|
|
||||||
avgDistSortKey=malloc(sizeof(uint32_t *)*nQuantPixels*nQuantPixels);
|
/* malloc check ok, using calloc for overflow, check of n*n above */
|
||||||
|
avgDistSortKey=calloc(nQuantPixels*nQuantPixels, sizeof(uint32_t *));
|
||||||
if (!avgDistSortKey) { goto error_3; }
|
if (!avgDistSortKey) { goto error_3; }
|
||||||
|
|
||||||
if (!build_distance_tables(avgDist,avgDistSortKey,p,nQuantPixels)) {
|
if (!build_distance_tables(avgDist,avgDistSortKey,p,nQuantPixels)) {
|
||||||
|
@ -1474,7 +1508,7 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans)
|
||||||
ImagingSectionCookie cookie;
|
ImagingSectionCookie cookie;
|
||||||
|
|
||||||
if (!im)
|
if (!im)
|
||||||
return ImagingError_ModeError();
|
return ImagingError_ModeError();
|
||||||
if (colors < 1 || colors > 256)
|
if (colors < 1 || colors > 256)
|
||||||
/* FIXME: for colors > 256, consider returning an RGB image
|
/* FIXME: for colors > 256, consider returning an RGB image
|
||||||
instead (see @PIL205) */
|
instead (see @PIL205) */
|
||||||
|
@ -1488,7 +1522,11 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans)
|
||||||
if (!strcmp(im->mode, "RGBA") && mode != 2 && mode != 3)
|
if (!strcmp(im->mode, "RGBA") && mode != 2 && mode != 3)
|
||||||
return ImagingError_ModeError();
|
return ImagingError_ModeError();
|
||||||
|
|
||||||
p = malloc(sizeof(Pixel) * im->xsize * im->ysize);
|
if (im->xsize > INT_MAX / im->ysize) {
|
||||||
|
return ImagingError_MemoryError();
|
||||||
|
}
|
||||||
|
/* malloc check ok, using calloc for final overflow, x*y above */
|
||||||
|
p = calloc(im->xsize * im->ysize, sizeof(Pixel));
|
||||||
if (!p)
|
if (!p)
|
||||||
return ImagingError_MemoryError();
|
return ImagingError_MemoryError();
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "QuantHeap.h"
|
#include "QuantHeap.h"
|
||||||
|
|
||||||
|
@ -47,7 +48,12 @@ static int _heap_grow(Heap *h,int newsize) {
|
||||||
void *newheap;
|
void *newheap;
|
||||||
if (!newsize) newsize=h->heapsize<<1;
|
if (!newsize) newsize=h->heapsize<<1;
|
||||||
if (newsize<h->heapsize) return 0;
|
if (newsize<h->heapsize) return 0;
|
||||||
newheap=malloc(sizeof(void *)*newsize);
|
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;
|
if (!newheap) return 0;
|
||||||
memcpy(newheap,h->heap,sizeof(void *)*h->heapsize);
|
memcpy(newheap,h->heap,sizeof(void *)*h->heapsize);
|
||||||
free(h->heap);
|
free(h->heap);
|
||||||
|
@ -132,11 +138,16 @@ int ImagingQuantHeapTop(Heap *h,void **r) {
|
||||||
Heap *ImagingQuantHeapNew(HeapCmpFunc cf) {
|
Heap *ImagingQuantHeapNew(HeapCmpFunc cf) {
|
||||||
Heap *h;
|
Heap *h;
|
||||||
|
|
||||||
|
/* malloc check ok, small constant allocation */
|
||||||
h=malloc(sizeof(Heap));
|
h=malloc(sizeof(Heap));
|
||||||
if (!h) return NULL;
|
if (!h) return NULL;
|
||||||
h->heapsize=INITIAL_SIZE;
|
h->heapsize=INITIAL_SIZE;
|
||||||
h->heap=malloc(sizeof(void *)*h->heapsize);
|
/* malloc check ok, using calloc for overflow */
|
||||||
if (!h->heap) { free(h); return NULL; }
|
h->heap=calloc(h->heapsize, sizeof(void *));
|
||||||
|
if (!h->heap) {
|
||||||
|
free(h);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
h->heapcount=0;
|
h->heapcount=0;
|
||||||
h->cf=cf;
|
h->cf=cf;
|
||||||
return h;
|
return h;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "QuantOctree.h"
|
#include "QuantOctree.h"
|
||||||
|
|
||||||
|
@ -53,6 +54,7 @@ static ColorCube
|
||||||
new_color_cube(int r, int g, int b, int a) {
|
new_color_cube(int r, int g, int b, int a) {
|
||||||
ColorCube cube;
|
ColorCube cube;
|
||||||
|
|
||||||
|
/* malloc check ok, small constant allocation */
|
||||||
cube = malloc(sizeof(struct _ColorCube));
|
cube = malloc(sizeof(struct _ColorCube));
|
||||||
if (!cube) return NULL;
|
if (!cube) return NULL;
|
||||||
|
|
||||||
|
@ -61,6 +63,12 @@ new_color_cube(int r, int g, int b, int a) {
|
||||||
cube->bBits = MAX(b, 0);
|
cube->bBits = MAX(b, 0);
|
||||||
cube->aBits = MAX(a, 0);
|
cube->aBits = MAX(a, 0);
|
||||||
|
|
||||||
|
/* overflow check for size multiplication below */
|
||||||
|
if (cube->rBits + cube->gBits + cube->bBits + cube->aBits > 31) {
|
||||||
|
free(cube);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* the width of the cube for each dimension */
|
/* the width of the cube for each dimension */
|
||||||
cube->rWidth = 1<<cube->rBits;
|
cube->rWidth = 1<<cube->rBits;
|
||||||
cube->gWidth = 1<<cube->gBits;
|
cube->gWidth = 1<<cube->gBits;
|
||||||
|
@ -76,6 +84,7 @@ new_color_cube(int r, int g, int b, int a) {
|
||||||
|
|
||||||
/* the number of color buckets */
|
/* the number of color buckets */
|
||||||
cube->size = cube->rWidth * cube->gWidth * cube->bWidth * cube->aWidth;
|
cube->size = cube->rWidth * cube->gWidth * cube->bWidth * cube->aWidth;
|
||||||
|
/* malloc check ok, overflow checked above */
|
||||||
cube->buckets = calloc(cube->size, sizeof(struct _ColorBucket));
|
cube->buckets = calloc(cube->size, sizeof(struct _ColorBucket));
|
||||||
|
|
||||||
if (!cube->buckets) {
|
if (!cube->buckets) {
|
||||||
|
@ -154,7 +163,11 @@ compare_bucket_count(const ColorBucket a, const ColorBucket b) {
|
||||||
static ColorBucket
|
static ColorBucket
|
||||||
create_sorted_color_palette(const ColorCube cube) {
|
create_sorted_color_palette(const ColorCube cube) {
|
||||||
ColorBucket buckets;
|
ColorBucket buckets;
|
||||||
buckets = malloc(sizeof(struct _ColorBucket)*cube->size);
|
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;
|
if (!buckets) return NULL;
|
||||||
memcpy(buckets, cube->buckets, sizeof(struct _ColorBucket)*cube->size);
|
memcpy(buckets, cube->buckets, sizeof(struct _ColorBucket)*cube->size);
|
||||||
|
|
||||||
|
@ -280,7 +293,15 @@ void add_lookup_buckets(ColorCube cube, ColorBucket palette, long nColors, long
|
||||||
ColorBucket
|
ColorBucket
|
||||||
combined_palette(ColorBucket bucketsA, long nBucketsA, ColorBucket bucketsB, long nBucketsB) {
|
combined_palette(ColorBucket bucketsA, long nBucketsA, ColorBucket bucketsB, long nBucketsB) {
|
||||||
ColorBucket result;
|
ColorBucket result;
|
||||||
result = malloc(sizeof(struct _ColorBucket)*(nBucketsA+nBucketsB));
|
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, bucketsA, sizeof(struct _ColorBucket) * nBucketsA);
|
||||||
memcpy(&result[nBucketsA], bucketsB, sizeof(struct _ColorBucket) * nBucketsB);
|
memcpy(&result[nBucketsA], bucketsB, sizeof(struct _ColorBucket) * nBucketsB);
|
||||||
return result;
|
return result;
|
||||||
|
@ -291,7 +312,8 @@ create_palette_array(const ColorBucket palette, unsigned int paletteLength) {
|
||||||
Pixel *paletteArray;
|
Pixel *paletteArray;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
paletteArray = malloc(sizeof(Pixel)*paletteLength);
|
/* malloc check ok, calloc for overflow */
|
||||||
|
paletteArray = calloc(paletteLength, sizeof(Pixel));
|
||||||
if (!paletteArray) return NULL;
|
if (!paletteArray) return NULL;
|
||||||
|
|
||||||
for (i=0; i<paletteLength; i++) {
|
for (i=0; i<paletteLength; i++) {
|
||||||
|
@ -405,6 +427,7 @@ int quantize_octree(Pixel *pixelData,
|
||||||
paletteBucketsFine = NULL;
|
paletteBucketsFine = NULL;
|
||||||
free(paletteBucketsCoarse);
|
free(paletteBucketsCoarse);
|
||||||
paletteBucketsCoarse = NULL;
|
paletteBucketsCoarse = NULL;
|
||||||
|
if (!paletteBuckets) goto error;
|
||||||
|
|
||||||
/* add all coarse colors to our coarse lookup cube. */
|
/* add all coarse colors to our coarse lookup cube. */
|
||||||
coarseLookupCube = new_color_cube(cubeBits[4], cubeBits[5],
|
coarseLookupCube = new_color_cube(cubeBits[4], cubeBits[5],
|
||||||
|
@ -422,7 +445,8 @@ int quantize_octree(Pixel *pixelData,
|
||||||
add_lookup_buckets(lookupCube, paletteBuckets, nFineColors, nCoarseColors);
|
add_lookup_buckets(lookupCube, paletteBuckets, nFineColors, nCoarseColors);
|
||||||
|
|
||||||
/* create result pixels and map palette indices */
|
/* create result pixels and map palette indices */
|
||||||
qp = malloc(sizeof(Pixel)*nPixels);
|
/* malloc check ok, calloc for overflow */
|
||||||
|
qp = calloc(nPixels, sizeof(Pixel));
|
||||||
if (!qp) goto error;
|
if (!qp) goto error;
|
||||||
map_image_pixels(pixelData, nPixels, lookupCube, qp);
|
map_image_pixels(pixelData, nPixels, lookupCube, qp);
|
||||||
|
|
||||||
|
|
|
@ -55,21 +55,28 @@ ImagingRankFilter(Imaging im, int size, int rank)
|
||||||
int i, margin, size2;
|
int i, margin, size2;
|
||||||
|
|
||||||
if (!im || im->bands != 1 || im->type == IMAGING_TYPE_SPECIAL)
|
if (!im || im->bands != 1 || im->type == IMAGING_TYPE_SPECIAL)
|
||||||
return (Imaging) ImagingError_ModeError();
|
return (Imaging) ImagingError_ModeError();
|
||||||
|
|
||||||
if (!(size & 1))
|
if (!(size & 1))
|
||||||
return (Imaging) ImagingError_ValueError("bad filter size");
|
return (Imaging) ImagingError_ValueError("bad filter size");
|
||||||
|
|
||||||
|
/* malloc check ok, for overflow in the define below */
|
||||||
|
if (size > INT_MAX / size ||
|
||||||
|
size > INT_MAX / (size * sizeof(FLOAT32))) {
|
||||||
|
return (Imaging) ImagingError_ValueError("filter size too large");
|
||||||
|
}
|
||||||
|
|
||||||
size2 = size * size;
|
size2 = size * size;
|
||||||
margin = (size-1) / 2;
|
margin = (size-1) / 2;
|
||||||
|
|
||||||
if (rank < 0 || rank >= size2)
|
if (rank < 0 || rank >= size2)
|
||||||
return (Imaging) ImagingError_ValueError("bad rank value");
|
return (Imaging) ImagingError_ValueError("bad rank value");
|
||||||
|
|
||||||
imOut = ImagingNew(im->mode, im->xsize - 2*margin, im->ysize - 2*margin);
|
imOut = ImagingNew(im->mode, im->xsize - 2*margin, im->ysize - 2*margin);
|
||||||
if (!imOut)
|
if (!imOut)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* malloc check ok, checked above */
|
||||||
#define RANK_BODY(type) do {\
|
#define RANK_BODY(type) do {\
|
||||||
type* buf = malloc(size2 * sizeof(type));\
|
type* buf = malloc(size2 * sizeof(type));\
|
||||||
if (!buf)\
|
if (!buf)\
|
||||||
|
|
|
@ -98,15 +98,13 @@ ImagingPrecompute(int inSize, int outSize, struct filter *filterp,
|
||||||
if (outSize > INT_MAX / (kmax * sizeof(double)))
|
if (outSize > INT_MAX / (kmax * sizeof(double)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// sizeof(double) should be greater than 0 as well
|
|
||||||
if (outSize > INT_MAX / (2 * sizeof(double)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* coefficient buffer */
|
/* coefficient buffer */
|
||||||
|
/* malloc check ok, overflow checked above */
|
||||||
kk = malloc(outSize * kmax * sizeof(double));
|
kk = malloc(outSize * kmax * sizeof(double));
|
||||||
if ( ! kk)
|
if ( ! kk)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* malloc check ok, kmax*sizeof(double) > 2*sizeof(int) */
|
||||||
xbounds = malloc(outSize * 2 * sizeof(int));
|
xbounds = malloc(outSize * 2 * sizeof(int));
|
||||||
if ( ! xbounds) {
|
if ( ! xbounds) {
|
||||||
free(kk);
|
free(kk);
|
||||||
|
|
|
@ -46,7 +46,7 @@ int ImagingNewCount = 0;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Imaging
|
Imaging
|
||||||
ImagingNewPrologueSubtype(const char *mode, unsigned xsize, unsigned ysize,
|
ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize,
|
||||||
int size)
|
int size)
|
||||||
{
|
{
|
||||||
Imaging im;
|
Imaging im;
|
||||||
|
@ -56,6 +56,11 @@ ImagingNewPrologueSubtype(const char *mode, unsigned xsize, unsigned ysize,
|
||||||
if (!im)
|
if (!im)
|
||||||
return (Imaging) ImagingError_MemoryError();
|
return (Imaging) ImagingError_MemoryError();
|
||||||
|
|
||||||
|
/* linesize overflow check, roughly the current largest space req'd */
|
||||||
|
if (xsize > (INT_MAX / 4) - 1) {
|
||||||
|
return (Imaging) ImagingError_MemoryError();
|
||||||
|
}
|
||||||
|
|
||||||
/* Setup image descriptor */
|
/* Setup image descriptor */
|
||||||
im->xsize = xsize;
|
im->xsize = xsize;
|
||||||
im->ysize = ysize;
|
im->ysize = ysize;
|
||||||
|
@ -226,7 +231,7 @@ ImagingNewPrologueSubtype(const char *mode, unsigned xsize, unsigned ysize,
|
||||||
}
|
}
|
||||||
|
|
||||||
Imaging
|
Imaging
|
||||||
ImagingNewPrologue(const char *mode, unsigned xsize, unsigned ysize)
|
ImagingNewPrologue(const char *mode, int xsize, int ysize)
|
||||||
{
|
{
|
||||||
return ImagingNewPrologueSubtype(
|
return ImagingNewPrologueSubtype(
|
||||||
mode, xsize, ysize, sizeof(struct ImagingMemoryInstance)
|
mode, xsize, ysize, sizeof(struct ImagingMemoryInstance)
|
||||||
|
@ -306,7 +311,8 @@ ImagingNewArray(const char *mode, int xsize, int ysize)
|
||||||
|
|
||||||
/* Allocate image as an array of lines */
|
/* Allocate image as an array of lines */
|
||||||
for (y = 0; y < im->ysize; y++) {
|
for (y = 0; y < im->ysize; y++) {
|
||||||
p = (char *) malloc(im->linesize);
|
/* malloc check linesize checked in prologue */
|
||||||
|
p = (char *) calloc(1, im->linesize);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
ImagingDestroyArray(im);
|
ImagingDestroyArray(im);
|
||||||
break;
|
break;
|
||||||
|
@ -339,24 +345,32 @@ ImagingNewBlock(const char *mode, int xsize, int ysize)
|
||||||
{
|
{
|
||||||
Imaging im;
|
Imaging im;
|
||||||
Py_ssize_t y, i;
|
Py_ssize_t y, i;
|
||||||
Py_ssize_t bytes;
|
|
||||||
|
|
||||||
im = ImagingNewPrologue(mode, xsize, ysize);
|
im = ImagingNewPrologue(mode, xsize, ysize);
|
||||||
if (!im)
|
if (!im)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Use a single block */
|
/* We shouldn't overflow, since the threshold defined
|
||||||
bytes = (Py_ssize_t) im->ysize * im->linesize;
|
below says that we're only going to allocate max 4M
|
||||||
if (bytes <= 0)
|
here before going to the array allocator. Check anyway.
|
||||||
|
*/
|
||||||
|
if (im->linesize &&
|
||||||
|
im->ysize > INT_MAX / im->linesize) {
|
||||||
|
/* punt if we're going to overflow */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (im->ysize * im->linesize <= 0) {
|
||||||
/* some platforms return NULL for malloc(0); this fix
|
/* some platforms return NULL for malloc(0); this fix
|
||||||
prevents MemoryError on zero-sized images on such
|
prevents MemoryError on zero-sized images on such
|
||||||
platforms */
|
platforms */
|
||||||
bytes = 1;
|
im->block = (char *) malloc(1);
|
||||||
im->block = (char *) malloc(bytes);
|
} else {
|
||||||
|
/* malloc check ok, overflow check above */
|
||||||
|
im->block = (char *) calloc(im->ysize, im->linesize);
|
||||||
|
}
|
||||||
|
|
||||||
if (im->block) {
|
if (im->block) {
|
||||||
memset(im->block, 0, bytes);
|
|
||||||
|
|
||||||
for (y = i = 0; y < im->ysize; y++) {
|
for (y = i = 0; y < im->ysize; y++) {
|
||||||
im->image[y] = im->block + i;
|
im->image[y] = im->block + i;
|
||||||
i += im->linesize;
|
i += im->linesize;
|
||||||
|
@ -392,7 +406,7 @@ ImagingNew(const char* mode, int xsize, int ysize)
|
||||||
} else
|
} else
|
||||||
bytes = strlen(mode); /* close enough */
|
bytes = strlen(mode); /* close enough */
|
||||||
|
|
||||||
if ((int64_t) xsize * (int64_t) ysize * bytes <= THRESHOLD) {
|
if ((int64_t) xsize * (int64_t) ysize <= THRESHOLD / bytes) {
|
||||||
im = ImagingNewBlock(mode, xsize, ysize);
|
im = ImagingNewBlock(mode, xsize, ysize);
|
||||||
if (im)
|
if (im)
|
||||||
return im;
|
return im;
|
||||||
|
|
|
@ -58,10 +58,14 @@ tsize_t _tiffWriteProc(thandle_t hdata, tdata_t buf, tsize_t size) {
|
||||||
tdata_t new;
|
tdata_t new;
|
||||||
tsize_t newsize=state->size;
|
tsize_t newsize=state->size;
|
||||||
while (newsize < (size + state->size)) {
|
while (newsize < (size + state->size)) {
|
||||||
|
if (newsize > (tsize_t)SIZE_MAX - 64*1024){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
newsize += 64*1024;
|
newsize += 64*1024;
|
||||||
// newsize*=2; // UNDONE, by 64k chunks?
|
// newsize*=2; // UNDONE, by 64k chunks?
|
||||||
}
|
}
|
||||||
TRACE(("Reallocing in write to %d bytes\n", (int)newsize));
|
TRACE(("Reallocing in write to %d bytes\n", (int)newsize));
|
||||||
|
/* malloc check ok, overflow checked above */
|
||||||
new = realloc(state->data, newsize);
|
new = realloc(state->data, newsize);
|
||||||
if (!new) {
|
if (!new) {
|
||||||
// fail out
|
// fail out
|
||||||
|
@ -305,6 +309,7 @@ int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp) {
|
||||||
} else {
|
} else {
|
||||||
// malloc a buffer to write the tif, we're going to need to realloc or something if we need bigger.
|
// malloc a buffer to write the tif, we're going to need to realloc or something if we need bigger.
|
||||||
TRACE(("Opening a buffer for writing \n"));
|
TRACE(("Opening a buffer for writing \n"));
|
||||||
|
/* malloc check ok, small constant allocation */
|
||||||
clientstate->data = malloc(bufsize);
|
clientstate->data = malloc(bufsize);
|
||||||
clientstate->size = bufsize;
|
clientstate->size = bufsize;
|
||||||
clientstate->flrealloc=1;
|
clientstate->flrealloc=1;
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include "Imaging.h"
|
#include "Imaging.h"
|
||||||
|
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
|
|
||||||
#include "Zip.h"
|
#include "Zip.h"
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ static int get_row_len(ImagingCodecState state, int pass)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/* Decoder */
|
/* Decoder */
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -52,50 +52,56 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||||
|
|
||||||
if (!state->state) {
|
if (!state->state) {
|
||||||
|
|
||||||
/* Initialization */
|
/* Initialization */
|
||||||
if (context->mode == ZIP_PNG || context->mode == ZIP_PNG_PALETTE)
|
if (context->mode == ZIP_PNG || context->mode == ZIP_PNG_PALETTE)
|
||||||
context->prefix = 1; /* PNG */
|
context->prefix = 1; /* PNG */
|
||||||
|
|
||||||
/* Expand standard buffer to make room for the (optional) filter
|
/* overflow check for malloc */
|
||||||
prefix, and allocate a buffer to hold the previous line */
|
if (state->bytes > INT_MAX - 1) {
|
||||||
free(state->buffer);
|
state->errcode = IMAGING_CODEC_MEMORY;
|
||||||
state->buffer = (UINT8*) malloc(state->bytes+1);
|
return -1;
|
||||||
context->previous = (UINT8*) malloc(state->bytes+1);
|
}
|
||||||
if (!state->buffer || !context->previous) {
|
/* Expand standard buffer to make room for the (optional) filter
|
||||||
state->errcode = IMAGING_CODEC_MEMORY;
|
prefix, and allocate a buffer to hold the previous line */
|
||||||
return -1;
|
free(state->buffer);
|
||||||
}
|
/* malloc check ok, overflow checked above */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
context->last_output = 0;
|
context->last_output = 0;
|
||||||
|
|
||||||
/* Initialize to black */
|
/* Initialize to black */
|
||||||
memset(context->previous, 0, state->bytes+1);
|
memset(context->previous, 0, state->bytes+1);
|
||||||
|
|
||||||
/* Setup decompression context */
|
/* Setup decompression context */
|
||||||
context->z_stream.zalloc = (alloc_func) NULL;
|
context->z_stream.zalloc = (alloc_func) NULL;
|
||||||
context->z_stream.zfree = (free_func) NULL;
|
context->z_stream.zfree = (free_func) NULL;
|
||||||
context->z_stream.opaque = (voidpf) NULL;
|
context->z_stream.opaque = (voidpf) NULL;
|
||||||
|
|
||||||
err = inflateInit(&context->z_stream);
|
err = inflateInit(&context->z_stream);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
state->errcode = IMAGING_CODEC_CONFIG;
|
state->errcode = IMAGING_CODEC_CONFIG;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context->interlaced) {
|
if (context->interlaced) {
|
||||||
context->pass = 0;
|
context->pass = 0;
|
||||||
state->y = STARTING_ROW[context->pass];
|
state->y = STARTING_ROW[context->pass];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ready to decode */
|
/* Ready to decode */
|
||||||
state->state = 1;
|
state->state = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context->interlaced) {
|
if (context->interlaced) {
|
||||||
row_len = get_row_len(state, context->pass);
|
row_len = get_row_len(state, context->pass);
|
||||||
} else {
|
} else {
|
||||||
row_len = state->bytes;
|
row_len = state->bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup the source buffer */
|
/* Setup the source buffer */
|
||||||
|
@ -105,162 +111,162 @@ ImagingZipDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||||
/* Decompress what we've got this far */
|
/* Decompress what we've got this far */
|
||||||
while (context->z_stream.avail_in > 0) {
|
while (context->z_stream.avail_in > 0) {
|
||||||
|
|
||||||
context->z_stream.next_out = state->buffer + context->last_output;
|
context->z_stream.next_out = state->buffer + context->last_output;
|
||||||
context->z_stream.avail_out =
|
context->z_stream.avail_out =
|
||||||
row_len + context->prefix - context->last_output;
|
row_len + context->prefix - context->last_output;
|
||||||
|
|
||||||
err = inflate(&context->z_stream, Z_NO_FLUSH);
|
err = inflate(&context->z_stream, Z_NO_FLUSH);
|
||||||
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
/* Something went wrong inside the compression library */
|
/* Something went wrong inside the compression library */
|
||||||
if (err == Z_DATA_ERROR)
|
if (err == Z_DATA_ERROR)
|
||||||
state->errcode = IMAGING_CODEC_BROKEN;
|
state->errcode = IMAGING_CODEC_BROKEN;
|
||||||
else if (err == Z_MEM_ERROR)
|
else if (err == Z_MEM_ERROR)
|
||||||
state->errcode = IMAGING_CODEC_MEMORY;
|
state->errcode = IMAGING_CODEC_MEMORY;
|
||||||
else
|
else
|
||||||
state->errcode = IMAGING_CODEC_CONFIG;
|
state->errcode = IMAGING_CODEC_CONFIG;
|
||||||
free(context->previous);
|
free(context->previous);
|
||||||
inflateEnd(&context->z_stream);
|
inflateEnd(&context->z_stream);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = row_len + context->prefix - context->z_stream.avail_out;
|
n = row_len + context->prefix - context->z_stream.avail_out;
|
||||||
|
|
||||||
if (n < row_len + context->prefix) {
|
if (n < row_len + context->prefix) {
|
||||||
context->last_output = n;
|
context->last_output = n;
|
||||||
break; /* need more input data */
|
break; /* need more input data */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply predictor */
|
/* Apply predictor */
|
||||||
switch (context->mode) {
|
switch (context->mode) {
|
||||||
case ZIP_PNG:
|
case ZIP_PNG:
|
||||||
switch (state->buffer[0]) {
|
switch (state->buffer[0]) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
/* prior */
|
/* prior */
|
||||||
bpp = (state->bits + 7) / 8;
|
bpp = (state->bits + 7) / 8;
|
||||||
for (i = bpp+1; i <= row_len; i++)
|
for (i = bpp+1; i <= row_len; i++)
|
||||||
state->buffer[i] += state->buffer[i-bpp];
|
state->buffer[i] += state->buffer[i-bpp];
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
/* up */
|
/* up */
|
||||||
for (i = 1; i <= row_len; i++)
|
for (i = 1; i <= row_len; i++)
|
||||||
state->buffer[i] += context->previous[i];
|
state->buffer[i] += context->previous[i];
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
/* average */
|
/* average */
|
||||||
bpp = (state->bits + 7) / 8;
|
bpp = (state->bits + 7) / 8;
|
||||||
for (i = 1; i <= bpp; i++)
|
for (i = 1; i <= bpp; i++)
|
||||||
state->buffer[i] += context->previous[i]/2;
|
state->buffer[i] += context->previous[i]/2;
|
||||||
for (; i <= row_len; i++)
|
for (; i <= row_len; i++)
|
||||||
state->buffer[i] +=
|
state->buffer[i] +=
|
||||||
(state->buffer[i-bpp] + context->previous[i])/2;
|
(state->buffer[i-bpp] + context->previous[i])/2;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
/* paeth filtering */
|
/* paeth filtering */
|
||||||
bpp = (state->bits + 7) / 8;
|
bpp = (state->bits + 7) / 8;
|
||||||
for (i = 1; i <= bpp; i++)
|
for (i = 1; i <= bpp; i++)
|
||||||
state->buffer[i] += context->previous[i];
|
state->buffer[i] += context->previous[i];
|
||||||
for (; i <= row_len; i++) {
|
for (; i <= row_len; i++) {
|
||||||
int a, b, c;
|
int a, b, c;
|
||||||
int pa, pb, pc;
|
int pa, pb, pc;
|
||||||
|
|
||||||
/* fetch pixels */
|
/* fetch pixels */
|
||||||
a = state->buffer[i-bpp];
|
a = state->buffer[i-bpp];
|
||||||
b = context->previous[i];
|
b = context->previous[i];
|
||||||
c = context->previous[i-bpp];
|
c = context->previous[i-bpp];
|
||||||
|
|
||||||
/* distances to surrounding pixels */
|
/* distances to surrounding pixels */
|
||||||
pa = abs(b - c);
|
pa = abs(b - c);
|
||||||
pb = abs(a - c);
|
pb = abs(a - c);
|
||||||
pc = abs(a + b - 2*c);
|
pc = abs(a + b - 2*c);
|
||||||
|
|
||||||
/* pick predictor with the shortest distance */
|
/* pick predictor with the shortest distance */
|
||||||
state->buffer[i] +=
|
state->buffer[i] +=
|
||||||
(pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
|
(pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
state->errcode = IMAGING_CODEC_UNKNOWN;
|
state->errcode = IMAGING_CODEC_UNKNOWN;
|
||||||
free(context->previous);
|
free(context->previous);
|
||||||
inflateEnd(&context->z_stream);
|
inflateEnd(&context->z_stream);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ZIP_TIFF_PREDICTOR:
|
case ZIP_TIFF_PREDICTOR:
|
||||||
bpp = (state->bits + 7) / 8;
|
bpp = (state->bits + 7) / 8;
|
||||||
for (i = bpp+1; i <= row_len; i++)
|
for (i = bpp+1; i <= row_len; i++)
|
||||||
state->buffer[i] += state->buffer[i-bpp];
|
state->buffer[i] += state->buffer[i-bpp];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stuff data into the image */
|
/* Stuff data into the image */
|
||||||
if (context->interlaced) {
|
if (context->interlaced) {
|
||||||
int col = STARTING_COL[context->pass];
|
int col = STARTING_COL[context->pass];
|
||||||
if (state->bits >= 8) {
|
if (state->bits >= 8) {
|
||||||
/* Stuff pixels in their correct location, one by one */
|
/* Stuff pixels in their correct location, one by one */
|
||||||
for (i = 0; i < row_len; i += ((state->bits + 7) / 8)) {
|
for (i = 0; i < row_len; i += ((state->bits + 7) / 8)) {
|
||||||
state->shuffle((UINT8*) im->image[state->y] +
|
state->shuffle((UINT8*) im->image[state->y] +
|
||||||
col * im->pixelsize,
|
col * im->pixelsize,
|
||||||
state->buffer + context->prefix + i, 1);
|
state->buffer + context->prefix + i, 1);
|
||||||
col += COL_INCREMENT[context->pass];
|
col += COL_INCREMENT[context->pass];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Handle case with more than a pixel in each byte */
|
/* Handle case with more than a pixel in each byte */
|
||||||
int row_bits = ((state->xsize + OFFSET[context->pass])
|
int row_bits = ((state->xsize + OFFSET[context->pass])
|
||||||
/ COL_INCREMENT[context->pass]) * state->bits;
|
/ COL_INCREMENT[context->pass]) * state->bits;
|
||||||
for (i = 0; i < row_bits; i += state->bits) {
|
for (i = 0; i < row_bits; i += state->bits) {
|
||||||
UINT8 byte = *(state->buffer + context->prefix + (i / 8));
|
UINT8 byte = *(state->buffer + context->prefix + (i / 8));
|
||||||
byte <<= (i % 8);
|
byte <<= (i % 8);
|
||||||
state->shuffle((UINT8*) im->image[state->y] +
|
state->shuffle((UINT8*) im->image[state->y] +
|
||||||
col * im->pixelsize, &byte, 1);
|
col * im->pixelsize, &byte, 1);
|
||||||
col += COL_INCREMENT[context->pass];
|
col += COL_INCREMENT[context->pass];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Find next valid scanline */
|
/* Find next valid scanline */
|
||||||
state->y += ROW_INCREMENT[context->pass];
|
state->y += ROW_INCREMENT[context->pass];
|
||||||
while (state->y >= state->ysize || row_len <= 0) {
|
while (state->y >= state->ysize || row_len <= 0) {
|
||||||
context->pass++;
|
context->pass++;
|
||||||
if (context->pass == 7) {
|
if (context->pass == 7) {
|
||||||
/* Force exit below */
|
/* Force exit below */
|
||||||
state->y = state->ysize;
|
state->y = state->ysize;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
state->y = STARTING_ROW[context->pass];
|
state->y = STARTING_ROW[context->pass];
|
||||||
row_len = get_row_len(state, context->pass);
|
row_len = get_row_len(state, context->pass);
|
||||||
/* Since we're moving to the "first" line, the previous line
|
/* Since we're moving to the "first" line, the previous line
|
||||||
* should be black to make filters work corectly */
|
* should be black to make filters work corectly */
|
||||||
memset(state->buffer, 0, state->bytes+1);
|
memset(state->buffer, 0, state->bytes+1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
state->shuffle((UINT8*) im->image[state->y + state->yoff] +
|
state->shuffle((UINT8*) im->image[state->y + state->yoff] +
|
||||||
state->xoff * im->pixelsize,
|
state->xoff * im->pixelsize,
|
||||||
state->buffer + context->prefix,
|
state->buffer + context->prefix,
|
||||||
state->xsize);
|
state->xsize);
|
||||||
state->y++;
|
state->y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* all inflate output has been consumed */
|
/* all inflate output has been consumed */
|
||||||
context->last_output = 0;
|
context->last_output = 0;
|
||||||
|
|
||||||
if (state->y >= state->ysize || err == Z_STREAM_END) {
|
if (state->y >= state->ysize || err == Z_STREAM_END) {
|
||||||
|
|
||||||
/* The image and the data should end simultaneously */
|
/* The image and the data should end simultaneously */
|
||||||
/* if (state->y < state->ysize || err != Z_STREAM_END)
|
/* if (state->y < state->ysize || err != Z_STREAM_END)
|
||||||
state->errcode = IMAGING_CODEC_BROKEN; */
|
state->errcode = IMAGING_CODEC_BROKEN; */
|
||||||
|
|
||||||
free(context->previous);
|
free(context->previous);
|
||||||
inflateEnd(&context->z_stream);
|
inflateEnd(&context->z_stream);
|
||||||
return -1; /* end of file (errcode=0) */
|
return -1; /* end of file (errcode=0) */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Swap buffer pointers */
|
/* Swap buffer pointers */
|
||||||
ptr = state->buffer;
|
ptr = state->buffer;
|
||||||
state->buffer = context->previous;
|
state->buffer = context->previous;
|
||||||
context->previous = ptr;
|
context->previous = ptr;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
* coder for ZIP (deflated) image data
|
* coder for ZIP (deflated) image data
|
||||||
*
|
*
|
||||||
* History:
|
* History:
|
||||||
* 96-12-29 fl created
|
* 96-12-29 fl created
|
||||||
* 96-12-30 fl adaptive filter selection, encoder tuning
|
* 96-12-30 fl adaptive filter selection, encoder tuning
|
||||||
*
|
*
|
||||||
* Copyright (c) Fredrik Lundh 1996.
|
* Copyright (c) Fredrik Lundh 1996.
|
||||||
* Copyright (c) Secret Labs AB 1997.
|
* Copyright (c) Secret Labs AB 1997.
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
#include "Imaging.h"
|
#include "Imaging.h"
|
||||||
|
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
|
|
||||||
#include "Zip.h"
|
#include "Zip.h"
|
||||||
|
|
||||||
|
@ -33,82 +33,89 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||||
|
|
||||||
if (!state->state) {
|
if (!state->state) {
|
||||||
|
|
||||||
/* Initialization */
|
/* Initialization */
|
||||||
|
|
||||||
/* Valid modes are ZIP_PNG, ZIP_PNG_PALETTE, and ZIP_TIFF */
|
/* Valid modes are ZIP_PNG, ZIP_PNG_PALETTE, and ZIP_TIFF */
|
||||||
|
|
||||||
/* Expand standard buffer to make room for the filter selector,
|
/* overflow check for malloc */
|
||||||
and allocate filter buffers */
|
if (state->bytes > INT_MAX - 1) {
|
||||||
free(state->buffer);
|
state->errcode = IMAGING_CODEC_MEMORY;
|
||||||
state->buffer = (UINT8*) malloc(state->bytes+1);
|
return -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);
|
|
||||||
free(context->prior);
|
|
||||||
free(context->previous);
|
|
||||||
state->errcode = IMAGING_CODEC_MEMORY;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initalise filter buffers */
|
/* Expand standard buffer to make room for the filter selector,
|
||||||
state->buffer[0] = 0;
|
and allocate filter buffers */
|
||||||
context->prior[0] = 1;
|
free(state->buffer);
|
||||||
context->up[0] = 2;
|
/* malloc check ok, overflow checked above */
|
||||||
context->average[0] = 3;
|
state->buffer = (UINT8*) malloc(state->bytes+1);
|
||||||
context->paeth[0] = 4;
|
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);
|
||||||
|
free(context->prior);
|
||||||
|
free(context->previous);
|
||||||
|
state->errcode = IMAGING_CODEC_MEMORY;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialise previous buffer to black */
|
/* Initalise filter buffers */
|
||||||
memset(context->previous, 0, state->bytes+1);
|
state->buffer[0] = 0;
|
||||||
|
context->prior[0] = 1;
|
||||||
|
context->up[0] = 2;
|
||||||
|
context->average[0] = 3;
|
||||||
|
context->paeth[0] = 4;
|
||||||
|
|
||||||
/* Setup compression context */
|
/* Initialise previous buffer to black */
|
||||||
context->z_stream.zalloc = (alloc_func)0;
|
memset(context->previous, 0, state->bytes+1);
|
||||||
context->z_stream.zfree = (free_func)0;
|
|
||||||
context->z_stream.opaque = (voidpf)0;
|
|
||||||
context->z_stream.next_in = 0;
|
|
||||||
context->z_stream.avail_in = 0;
|
|
||||||
|
|
||||||
compress_level = (context->optimize) ? Z_BEST_COMPRESSION
|
/* Setup compression context */
|
||||||
: context->compress_level;
|
context->z_stream.zalloc = (alloc_func)0;
|
||||||
|
context->z_stream.zfree = (free_func)0;
|
||||||
|
context->z_stream.opaque = (voidpf)0;
|
||||||
|
context->z_stream.next_in = 0;
|
||||||
|
context->z_stream.avail_in = 0;
|
||||||
|
|
||||||
if (context->compress_type == -1) {
|
compress_level = (context->optimize) ? Z_BEST_COMPRESSION
|
||||||
compress_type = (context->mode == ZIP_PNG) ? Z_FILTERED
|
: context->compress_level;
|
||||||
: Z_DEFAULT_STRATEGY;
|
|
||||||
} else {
|
|
||||||
compress_type = context->compress_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = deflateInit2(&context->z_stream,
|
if (context->compress_type == -1) {
|
||||||
/* compression level */
|
compress_type = (context->mode == ZIP_PNG) ? Z_FILTERED
|
||||||
compress_level,
|
: Z_DEFAULT_STRATEGY;
|
||||||
/* compression method */
|
} else {
|
||||||
Z_DEFLATED,
|
compress_type = context->compress_type;
|
||||||
/* 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 = deflateInit2(&context->z_stream,
|
||||||
err = deflateSetDictionary(&context->z_stream, (unsigned char *)context->dictionary,
|
/* compression level */
|
||||||
context->dictionary_size);
|
compress_level,
|
||||||
if (err < 0) {
|
/* compression method */
|
||||||
state->errcode = IMAGING_CODEC_CONFIG;
|
Z_DEFLATED,
|
||||||
return -1;
|
/* compression memory resources */
|
||||||
}
|
15, 9,
|
||||||
}
|
/* compression strategy (image data are filtered)*/
|
||||||
|
compress_type);
|
||||||
|
if (err < 0) {
|
||||||
|
state->errcode = IMAGING_CODEC_CONFIG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Ready to decode */
|
if (context->dictionary && context->dictionary_size > 0) {
|
||||||
state->state = 1;
|
err = deflateSetDictionary(&context->z_stream, (unsigned char *)context->dictionary,
|
||||||
|
context->dictionary_size);
|
||||||
|
if (err < 0) {
|
||||||
|
state->errcode = IMAGING_CODEC_CONFIG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ready to decode */
|
||||||
|
state->state = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,222 +123,222 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||||
context->z_stream.next_out = buf;
|
context->z_stream.next_out = buf;
|
||||||
context->z_stream.avail_out = bytes;
|
context->z_stream.avail_out = bytes;
|
||||||
if (context->z_stream.next_in && context->z_stream.avail_in > 0) {
|
if (context->z_stream.next_in && context->z_stream.avail_in > 0) {
|
||||||
/* We have some data from previous round, deflate it first */
|
/* We have some data from previous round, deflate it first */
|
||||||
err = deflate(&context->z_stream, Z_NO_FLUSH);
|
err = deflate(&context->z_stream, Z_NO_FLUSH);
|
||||||
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
/* Something went wrong inside the compression library */
|
/* Something went wrong inside the compression library */
|
||||||
if (err == Z_DATA_ERROR)
|
if (err == Z_DATA_ERROR)
|
||||||
state->errcode = IMAGING_CODEC_BROKEN;
|
state->errcode = IMAGING_CODEC_BROKEN;
|
||||||
else if (err == Z_MEM_ERROR)
|
else if (err == Z_MEM_ERROR)
|
||||||
state->errcode = IMAGING_CODEC_MEMORY;
|
state->errcode = IMAGING_CODEC_MEMORY;
|
||||||
else
|
else
|
||||||
state->errcode = IMAGING_CODEC_CONFIG;
|
state->errcode = IMAGING_CODEC_CONFIG;
|
||||||
free(context->paeth);
|
free(context->paeth);
|
||||||
free(context->average);
|
free(context->average);
|
||||||
free(context->up);
|
free(context->up);
|
||||||
free(context->prior);
|
free(context->prior);
|
||||||
free(context->previous);
|
free(context->previous);
|
||||||
deflateEnd(&context->z_stream);
|
deflateEnd(&context->z_stream);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImagingSectionEnter(&cookie);
|
ImagingSectionEnter(&cookie);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
switch (state->state) {
|
switch (state->state) {
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
|
|
||||||
/* Compress image data */
|
/* Compress image data */
|
||||||
while (context->z_stream.avail_out > 0) {
|
while (context->z_stream.avail_out > 0) {
|
||||||
|
|
||||||
if (state->y >= state->ysize) {
|
if (state->y >= state->ysize) {
|
||||||
/* End of image; now flush compressor buffers */
|
/* End of image; now flush compressor buffers */
|
||||||
state->state = 2;
|
state->state = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stuff image data into the compressor */
|
/* Stuff image data into the compressor */
|
||||||
state->shuffle(state->buffer+1,
|
state->shuffle(state->buffer+1,
|
||||||
(UINT8*) im->image[state->y + state->yoff] +
|
(UINT8*) im->image[state->y + state->yoff] +
|
||||||
state->xoff * im->pixelsize,
|
state->xoff * im->pixelsize,
|
||||||
state->xsize);
|
state->xsize);
|
||||||
|
|
||||||
state->y++;
|
state->y++;
|
||||||
|
|
||||||
context->output = state->buffer;
|
context->output = state->buffer;
|
||||||
|
|
||||||
if (context->mode == ZIP_PNG) {
|
if (context->mode == ZIP_PNG) {
|
||||||
|
|
||||||
/* Filter the image data. For each line, select
|
/* Filter the image data. For each line, select
|
||||||
the filter that gives the least total distance
|
the filter that gives the least total distance
|
||||||
from zero for the filtered data (taken from
|
from zero for the filtered data (taken from
|
||||||
LIBPNG) */
|
LIBPNG) */
|
||||||
|
|
||||||
bpp = (state->bits + 7) / 8;
|
bpp = (state->bits + 7) / 8;
|
||||||
|
|
||||||
/* 0. No filter */
|
/* 0. No filter */
|
||||||
for (i = 1, sum = 0; i <= state->bytes; i++) {
|
for (i = 1, sum = 0; i <= state->bytes; i++) {
|
||||||
UINT8 v = state->buffer[i];
|
UINT8 v = state->buffer[i];
|
||||||
sum += (v < 128) ? v : 256 - v;
|
sum += (v < 128) ? v : 256 - v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2. Up. We'll test this first to save time when
|
/* 2. Up. We'll test this first to save time when
|
||||||
an image line is identical to the one above. */
|
an image line is identical to the one above. */
|
||||||
if (sum > 0) {
|
if (sum > 0) {
|
||||||
for (i = 1, s = 0; i <= state->bytes; i++) {
|
for (i = 1, s = 0; i <= state->bytes; i++) {
|
||||||
UINT8 v = state->buffer[i] - context->previous[i];
|
UINT8 v = state->buffer[i] - context->previous[i];
|
||||||
context->up[i] = v;
|
context->up[i] = v;
|
||||||
s += (v < 128) ? v : 256 - v;
|
s += (v < 128) ? v : 256 - v;
|
||||||
}
|
}
|
||||||
if (s < sum) {
|
if (s < sum) {
|
||||||
context->output = context->up;
|
context->output = context->up;
|
||||||
sum = s; /* 0 if line was duplicated */
|
sum = s; /* 0 if line was duplicated */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 1. Prior */
|
/* 1. Prior */
|
||||||
if (sum > 0) {
|
if (sum > 0) {
|
||||||
for (i = 1, s = 0; i <= bpp; i++) {
|
for (i = 1, s = 0; i <= bpp; i++) {
|
||||||
UINT8 v = state->buffer[i];
|
UINT8 v = state->buffer[i];
|
||||||
context->prior[i] = v;
|
context->prior[i] = v;
|
||||||
s += (v < 128) ? v : 256 - v;
|
s += (v < 128) ? v : 256 - v;
|
||||||
}
|
}
|
||||||
for (; i <= state->bytes; i++) {
|
for (; i <= state->bytes; i++) {
|
||||||
UINT8 v = state->buffer[i] - state->buffer[i-bpp];
|
UINT8 v = state->buffer[i] - state->buffer[i-bpp];
|
||||||
context->prior[i] = v;
|
context->prior[i] = v;
|
||||||
s += (v < 128) ? v : 256 - v;
|
s += (v < 128) ? v : 256 - v;
|
||||||
}
|
}
|
||||||
if (s < sum) {
|
if (s < sum) {
|
||||||
context->output = context->prior;
|
context->output = context->prior;
|
||||||
sum = s; /* 0 if line is solid */
|
sum = s; /* 0 if line is solid */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 3. Average (not very common in real-life images,
|
/* 3. Average (not very common in real-life images,
|
||||||
so its only used with the optimize option) */
|
so its only used with the optimize option) */
|
||||||
if (context->optimize && sum > 0) {
|
if (context->optimize && sum > 0) {
|
||||||
for (i = 1, s = 0; i <= bpp; i++) {
|
for (i = 1, s = 0; i <= bpp; i++) {
|
||||||
UINT8 v = state->buffer[i] - context->previous[i]/2;
|
UINT8 v = state->buffer[i] - context->previous[i]/2;
|
||||||
context->average[i] = v;
|
context->average[i] = v;
|
||||||
s += (v < 128) ? v : 256 - v;
|
s += (v < 128) ? v : 256 - v;
|
||||||
}
|
}
|
||||||
for (; i <= state->bytes; i++) {
|
for (; i <= state->bytes; i++) {
|
||||||
UINT8 v = state->buffer[i] -
|
UINT8 v = state->buffer[i] -
|
||||||
(state->buffer[i-bpp] + context->previous[i])/2;
|
(state->buffer[i-bpp] + context->previous[i])/2;
|
||||||
context->average[i] = v;
|
context->average[i] = v;
|
||||||
s += (v < 128) ? v : 256 - v;
|
s += (v < 128) ? v : 256 - v;
|
||||||
}
|
}
|
||||||
if (s < sum) {
|
if (s < sum) {
|
||||||
context->output = context->average;
|
context->output = context->average;
|
||||||
sum = s;
|
sum = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 4. Paeth */
|
/* 4. Paeth */
|
||||||
if (sum > 0) {
|
if (sum > 0) {
|
||||||
for (i = 1, s = 0; i <= bpp; i++) {
|
for (i = 1, s = 0; i <= bpp; i++) {
|
||||||
UINT8 v = state->buffer[i] - context->previous[i];
|
UINT8 v = state->buffer[i] - context->previous[i];
|
||||||
context->paeth[i] = v;
|
context->paeth[i] = v;
|
||||||
s += (v < 128) ? v : 256 - v;
|
s += (v < 128) ? v : 256 - v;
|
||||||
}
|
}
|
||||||
for (; i <= state->bytes; i++) {
|
for (; i <= state->bytes; i++) {
|
||||||
UINT8 v;
|
UINT8 v;
|
||||||
int a, b, c;
|
int a, b, c;
|
||||||
int pa, pb, pc;
|
int pa, pb, pc;
|
||||||
|
|
||||||
/* fetch pixels */
|
/* fetch pixels */
|
||||||
a = state->buffer[i-bpp];
|
a = state->buffer[i-bpp];
|
||||||
b = context->previous[i];
|
b = context->previous[i];
|
||||||
c = context->previous[i-bpp];
|
c = context->previous[i-bpp];
|
||||||
|
|
||||||
/* distances to surrounding pixels */
|
/* distances to surrounding pixels */
|
||||||
pa = abs(b - c);
|
pa = abs(b - c);
|
||||||
pb = abs(a - c);
|
pb = abs(a - c);
|
||||||
pc = abs(a + b - 2*c);
|
pc = abs(a + b - 2*c);
|
||||||
|
|
||||||
/* pick predictor with the shortest distance */
|
/* pick predictor with the shortest distance */
|
||||||
v = state->buffer[i] -
|
v = state->buffer[i] -
|
||||||
((pa <= pb && pa <= pc) ? a :
|
((pa <= pb && pa <= pc) ? a :
|
||||||
(pb <= pc) ? b : c);
|
(pb <= pc) ? b : c);
|
||||||
context->paeth[i] = v;
|
context->paeth[i] = v;
|
||||||
s += (v < 128) ? v : 256 - v;
|
s += (v < 128) ? v : 256 - v;
|
||||||
}
|
}
|
||||||
if (s < sum) {
|
if (s < sum) {
|
||||||
context->output = context->paeth;
|
context->output = context->paeth;
|
||||||
sum = s;
|
sum = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compress this line */
|
/* Compress this line */
|
||||||
context->z_stream.next_in = context->output;
|
context->z_stream.next_in = context->output;
|
||||||
context->z_stream.avail_in = state->bytes+1;
|
context->z_stream.avail_in = state->bytes+1;
|
||||||
|
|
||||||
err = deflate(&context->z_stream, Z_NO_FLUSH);
|
err = deflate(&context->z_stream, Z_NO_FLUSH);
|
||||||
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
/* Something went wrong inside the compression library */
|
/* Something went wrong inside the compression library */
|
||||||
if (err == Z_DATA_ERROR)
|
if (err == Z_DATA_ERROR)
|
||||||
state->errcode = IMAGING_CODEC_BROKEN;
|
state->errcode = IMAGING_CODEC_BROKEN;
|
||||||
else if (err == Z_MEM_ERROR)
|
else if (err == Z_MEM_ERROR)
|
||||||
state->errcode = IMAGING_CODEC_MEMORY;
|
state->errcode = IMAGING_CODEC_MEMORY;
|
||||||
else
|
else
|
||||||
state->errcode = IMAGING_CODEC_CONFIG;
|
state->errcode = IMAGING_CODEC_CONFIG;
|
||||||
free(context->paeth);
|
free(context->paeth);
|
||||||
free(context->average);
|
free(context->average);
|
||||||
free(context->up);
|
free(context->up);
|
||||||
free(context->prior);
|
free(context->prior);
|
||||||
free(context->previous);
|
free(context->previous);
|
||||||
deflateEnd(&context->z_stream);
|
deflateEnd(&context->z_stream);
|
||||||
ImagingSectionLeave(&cookie);
|
ImagingSectionLeave(&cookie);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Swap buffer pointers */
|
/* Swap buffer pointers */
|
||||||
ptr = state->buffer;
|
ptr = state->buffer;
|
||||||
state->buffer = context->previous;
|
state->buffer = context->previous;
|
||||||
context->previous = ptr;
|
context->previous = ptr;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context->z_stream.avail_out == 0)
|
if (context->z_stream.avail_out == 0)
|
||||||
break; /* Buffer full */
|
break; /* Buffer full */
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
|
|
||||||
/* End of image data; flush compressor buffers */
|
/* End of image data; flush compressor buffers */
|
||||||
|
|
||||||
while (context->z_stream.avail_out > 0) {
|
while (context->z_stream.avail_out > 0) {
|
||||||
|
|
||||||
err = deflate(&context->z_stream, Z_FINISH);
|
err = deflate(&context->z_stream, Z_FINISH);
|
||||||
|
|
||||||
if (err == Z_STREAM_END) {
|
if (err == Z_STREAM_END) {
|
||||||
|
|
||||||
free(context->paeth);
|
free(context->paeth);
|
||||||
free(context->average);
|
free(context->average);
|
||||||
free(context->up);
|
free(context->up);
|
||||||
free(context->prior);
|
free(context->prior);
|
||||||
free(context->previous);
|
free(context->previous);
|
||||||
|
|
||||||
deflateEnd(&context->z_stream);
|
deflateEnd(&context->z_stream);
|
||||||
|
|
||||||
state->errcode = IMAGING_CODEC_END;
|
state->errcode = IMAGING_CODEC_END;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context->z_stream.avail_out == 0)
|
if (context->z_stream.avail_out == 0)
|
||||||
break; /* Buffer full */
|
break; /* Buffer full */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
ImagingSectionLeave(&cookie);
|
ImagingSectionLeave(&cookie);
|
||||||
return bytes - context->z_stream.avail_out;
|
return bytes - context->z_stream.avail_out;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,6 +348,24 @@ ImagingZipEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/* Cleanup */
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int
|
||||||
|
ImagingZipEncodeCleanup(ImagingCodecState state) {
|
||||||
|
ZIPSTATE* context = (ZIPSTATE*) state->context;
|
||||||
|
|
||||||
|
if (context->dictionary) {
|
||||||
|
free (context->dictionary);
|
||||||
|
context->dictionary = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
ImagingZipVersion(void)
|
ImagingZipVersion(void)
|
||||||
{
|
{
|
||||||
|
|
201
path.c
201
path.c
|
@ -37,7 +37,7 @@ extern int PyImaging_CheckBuffer(PyObject* buffer);
|
||||||
extern int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view);
|
extern int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/* Class */
|
/* Class */
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -86,7 +86,7 @@ path_new(Py_ssize_t count, double* xy, int duplicate)
|
||||||
|
|
||||||
path = PyObject_New(PyPathObject, &PyPathType);
|
path = PyObject_New(PyPathObject, &PyPathType);
|
||||||
if (path == NULL)
|
if (path == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
path->count = count;
|
path->count = count;
|
||||||
path->xy = xy;
|
path->xy = xy;
|
||||||
|
@ -102,26 +102,26 @@ path_dealloc(PyPathObject* path)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
#define PyPath_Check(op) (Py_TYPE(op) == &PyPathType)
|
#define PyPath_Check(op) (Py_TYPE(op) == &PyPathType)
|
||||||
|
|
||||||
int
|
Py_ssize_t
|
||||||
PyPath_Flatten(PyObject* data, double **pxy)
|
PyPath_Flatten(PyObject* data, double **pxy)
|
||||||
{
|
{
|
||||||
int i, j, n;
|
Py_ssize_t i, j, n;
|
||||||
double *xy;
|
double *xy;
|
||||||
|
|
||||||
if (PyPath_Check(data)) {
|
if (PyPath_Check(data)) {
|
||||||
/* This was another path object. */
|
/* This was another path object. */
|
||||||
PyPathObject *path = (PyPathObject*) data;
|
PyPathObject *path = (PyPathObject*) data;
|
||||||
xy = alloc_array(path->count);
|
xy = alloc_array(path->count);
|
||||||
if (!xy)
|
if (!xy)
|
||||||
return -1;
|
return -1;
|
||||||
memcpy(xy, path->xy, 2 * path->count * sizeof(double));
|
memcpy(xy, path->xy, 2 * path->count * sizeof(double));
|
||||||
*pxy = xy;
|
*pxy = xy;
|
||||||
return path->count;
|
return path->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PyImaging_CheckBuffer(data)) {
|
if (PyImaging_CheckBuffer(data)) {
|
||||||
|
@ -143,8 +143,8 @@ PyPath_Flatten(PyObject* data, double **pxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PySequence_Check(data)) {
|
if (!PySequence_Check(data)) {
|
||||||
PyErr_SetString(PyExc_TypeError, "argument must be sequence");
|
PyErr_SetString(PyExc_TypeError, "argument must be sequence");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
|
@ -156,7 +156,7 @@ PyPath_Flatten(PyObject* data, double **pxy)
|
||||||
/* Allocate for worst case */
|
/* Allocate for worst case */
|
||||||
xy = alloc_array(n);
|
xy = alloc_array(n);
|
||||||
if (!xy)
|
if (!xy)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Copy table to path array */
|
/* Copy table to path array */
|
||||||
if (PyList_Check(data)) {
|
if (PyList_Check(data)) {
|
||||||
|
@ -164,9 +164,9 @@ PyPath_Flatten(PyObject* data, double **pxy)
|
||||||
double x, y;
|
double x, y;
|
||||||
PyObject *op = PyList_GET_ITEM(data, i);
|
PyObject *op = PyList_GET_ITEM(data, i);
|
||||||
if (PyFloat_Check(op))
|
if (PyFloat_Check(op))
|
||||||
xy[j++] = PyFloat_AS_DOUBLE(op);
|
xy[j++] = PyFloat_AS_DOUBLE(op);
|
||||||
else if (PyInt_Check(op))
|
else if (PyInt_Check(op))
|
||||||
xy[j++] = (float) PyInt_AS_LONG(op);
|
xy[j++] = (float) PyInt_AS_LONG(op);
|
||||||
else if (PyNumber_Check(op))
|
else if (PyNumber_Check(op))
|
||||||
xy[j++] = PyFloat_AsDouble(op);
|
xy[j++] = PyFloat_AsDouble(op);
|
||||||
else if (PyArg_ParseTuple(op, "dd", &x, &y)) {
|
else if (PyArg_ParseTuple(op, "dd", &x, &y)) {
|
||||||
|
@ -182,9 +182,9 @@ PyPath_Flatten(PyObject* data, double **pxy)
|
||||||
double x, y;
|
double x, y;
|
||||||
PyObject *op = PyTuple_GET_ITEM(data, i);
|
PyObject *op = PyTuple_GET_ITEM(data, i);
|
||||||
if (PyFloat_Check(op))
|
if (PyFloat_Check(op))
|
||||||
xy[j++] = PyFloat_AS_DOUBLE(op);
|
xy[j++] = PyFloat_AS_DOUBLE(op);
|
||||||
else if (PyInt_Check(op))
|
else if (PyInt_Check(op))
|
||||||
xy[j++] = (float) PyInt_AS_LONG(op);
|
xy[j++] = (float) PyInt_AS_LONG(op);
|
||||||
else if (PyNumber_Check(op))
|
else if (PyNumber_Check(op))
|
||||||
xy[j++] = PyFloat_AsDouble(op);
|
xy[j++] = PyFloat_AsDouble(op);
|
||||||
else if (PyArg_ParseTuple(op, "dd", &x, &y)) {
|
else if (PyArg_ParseTuple(op, "dd", &x, &y)) {
|
||||||
|
@ -211,9 +211,9 @@ PyPath_Flatten(PyObject* data, double **pxy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (PyFloat_Check(op))
|
if (PyFloat_Check(op))
|
||||||
xy[j++] = PyFloat_AS_DOUBLE(op);
|
xy[j++] = PyFloat_AS_DOUBLE(op);
|
||||||
else if (PyInt_Check(op))
|
else if (PyInt_Check(op))
|
||||||
xy[j++] = (float) PyInt_AS_LONG(op);
|
xy[j++] = (float) PyInt_AS_LONG(op);
|
||||||
else if (PyNumber_Check(op))
|
else if (PyNumber_Check(op))
|
||||||
xy[j++] = PyFloat_AsDouble(op);
|
xy[j++] = PyFloat_AsDouble(op);
|
||||||
else if (PyArg_ParseTuple(op, "dd", &x, &y)) {
|
else if (PyArg_ParseTuple(op, "dd", &x, &y)) {
|
||||||
|
@ -229,9 +229,9 @@ PyPath_Flatten(PyObject* data, double **pxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j & 1) {
|
if (j & 1) {
|
||||||
PyErr_SetString(PyExc_ValueError, "wrong number of coordinates");
|
PyErr_SetString(PyExc_ValueError, "wrong number of coordinates");
|
||||||
free(xy);
|
free(xy);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pxy = xy;
|
*pxy = xy;
|
||||||
|
@ -240,7 +240,7 @@ PyPath_Flatten(PyObject* data, double **pxy)
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/* Factories */
|
/* Factories */
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
PyObject*
|
PyObject*
|
||||||
|
@ -274,7 +274,7 @@ PyPath_Create(PyObject* self, PyObject* args)
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/* Methods */
|
/* Methods */
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
|
@ -283,29 +283,30 @@ path_compact(PyPathObject* self, PyObject* args)
|
||||||
/* Simple-minded method to shorten path. A point is removed if
|
/* Simple-minded method to shorten path. A point is removed if
|
||||||
the city block distance to the previous point is less than the
|
the city block distance to the previous point is less than the
|
||||||
given distance */
|
given distance */
|
||||||
int i, j;
|
Py_ssize_t i, j;
|
||||||
double *xy;
|
double *xy;
|
||||||
|
|
||||||
double cityblock = 2.0;
|
double cityblock = 2.0;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "|d:compact", &cityblock))
|
if (!PyArg_ParseTuple(args, "|d:compact", &cityblock))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
xy = self->xy;
|
xy = self->xy;
|
||||||
|
|
||||||
/* remove bogus vertices */
|
/* remove bogus vertices */
|
||||||
for (i = j = 1; i < self->count; i++) {
|
for (i = j = 1; i < self->count; i++) {
|
||||||
if (fabs(xy[j+j-2]-xy[i+i]) + fabs(xy[j+j-1]-xy[i+i+1]) >= cityblock) {
|
if (fabs(xy[j+j-2]-xy[i+i]) + fabs(xy[j+j-1]-xy[i+i+1]) >= cityblock) {
|
||||||
xy[j+j] = xy[i+i];
|
xy[j+j] = xy[i+i];
|
||||||
xy[j+j+1] = xy[i+i+1];
|
xy[j+j+1] = xy[i+i+1];
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i = self->count - j;
|
i = self->count - j;
|
||||||
self->count = j;
|
self->count = j;
|
||||||
|
|
||||||
/* shrink coordinate array */
|
/* shrink coordinate array */
|
||||||
|
/* malloc check ok, self->count is smaller than it was before */
|
||||||
self->xy = realloc(self->xy, 2 * self->count * sizeof(double));
|
self->xy = realloc(self->xy, 2 * self->count * sizeof(double));
|
||||||
|
|
||||||
return Py_BuildValue("i", i); /* number of removed vertices */
|
return Py_BuildValue("i", i); /* number of removed vertices */
|
||||||
|
@ -331,12 +332,12 @@ static PyObject*
|
||||||
path_getbbox(PyPathObject* self, PyObject* args)
|
path_getbbox(PyPathObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
/* Find bounding box */
|
/* Find bounding box */
|
||||||
int i;
|
Py_ssize_t i;
|
||||||
double *xy;
|
double *xy;
|
||||||
double x0, y0, x1, y1;
|
double x0, y0, x1, y1;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, ":getbbox"))
|
if (!PyArg_ParseTuple(args, ":getbbox"))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
xy = self->xy;
|
xy = self->xy;
|
||||||
|
|
||||||
|
@ -344,27 +345,27 @@ path_getbbox(PyPathObject* self, PyObject* args)
|
||||||
y0 = y1 = xy[1];
|
y0 = y1 = xy[1];
|
||||||
|
|
||||||
for (i = 1; i < self->count; i++) {
|
for (i = 1; i < self->count; i++) {
|
||||||
if (xy[i+i] < x0)
|
if (xy[i+i] < x0)
|
||||||
x0 = xy[i+i];
|
x0 = xy[i+i];
|
||||||
if (xy[i+i] > x1)
|
if (xy[i+i] > x1)
|
||||||
x1 = xy[i+i];
|
x1 = xy[i+i];
|
||||||
if (xy[i+i+1] < y0)
|
if (xy[i+i+1] < y0)
|
||||||
y0 = xy[i+i+1];
|
y0 = xy[i+i+1];
|
||||||
if (xy[i+i+1] > y1)
|
if (xy[i+i+1] > y1)
|
||||||
y1 = xy[i+i+1];
|
y1 = xy[i+i+1];
|
||||||
}
|
}
|
||||||
|
|
||||||
return Py_BuildValue("dddd", x0, y0, x1, y1);
|
return Py_BuildValue("dddd", x0, y0, x1, y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
path_getitem(PyPathObject* self, int i)
|
path_getitem(PyPathObject* self, Py_ssize_t i)
|
||||||
{
|
{
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
i = self->count + i;
|
i = self->count + i;
|
||||||
if (i < 0 || i >= self->count) {
|
if (i < 0 || i >= self->count) {
|
||||||
PyErr_SetString(PyExc_IndexError, "path index out of range");
|
PyErr_SetString(PyExc_IndexError, "path index out of range");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Py_BuildValue("dd", self->xy[i+i], self->xy[i+i+1]);
|
return Py_BuildValue("dd", self->xy[i+i], self->xy[i+i+1]);
|
||||||
|
@ -398,27 +399,27 @@ static PyObject*
|
||||||
path_map(PyPathObject* self, PyObject* args)
|
path_map(PyPathObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
/* Map coordinate set through function */
|
/* Map coordinate set through function */
|
||||||
int i;
|
Py_ssize_t i;
|
||||||
double *xy;
|
double *xy;
|
||||||
PyObject* function;
|
PyObject* function;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O:map", &function))
|
if (!PyArg_ParseTuple(args, "O:map", &function))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
xy = self->xy;
|
xy = self->xy;
|
||||||
|
|
||||||
/* apply function to coordinate set */
|
/* apply function to coordinate set */
|
||||||
for (i = 0; i < self->count; i++) {
|
for (i = 0; i < self->count; i++) {
|
||||||
double x = xy[i+i];
|
double x = xy[i+i];
|
||||||
double y = xy[i+i+1];
|
double y = xy[i+i+1];
|
||||||
PyObject* item = PyObject_CallFunction(function, "dd", x, y);
|
PyObject* item = PyObject_CallFunction(function, "dd", x, y);
|
||||||
if (!item || !PyArg_ParseTuple(item, "dd", &x, &y)) {
|
if (!item || !PyArg_ParseTuple(item, "dd", &x, &y)) {
|
||||||
Py_XDECREF(item);
|
Py_XDECREF(item);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
xy[i+i] = x;
|
xy[i+i] = x;
|
||||||
xy[i+i+1] = y;
|
xy[i+i+1] = y;
|
||||||
Py_DECREF(item);
|
Py_DECREF(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
|
@ -426,7 +427,7 @@ path_map(PyPathObject* self, PyObject* args)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
path_setitem(PyPathObject* self, int i, PyObject* op)
|
path_setitem(PyPathObject* self, Py_ssize_t i, PyObject* op)
|
||||||
{
|
{
|
||||||
double* xy;
|
double* xy;
|
||||||
|
|
||||||
|
@ -454,11 +455,11 @@ static PyObject*
|
||||||
path_tolist(PyPathObject* self, PyObject* args)
|
path_tolist(PyPathObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
PyObject *list;
|
PyObject *list;
|
||||||
int i;
|
Py_ssize_t i;
|
||||||
|
|
||||||
int flat = 0;
|
int flat = 0;
|
||||||
if (!PyArg_ParseTuple(args, "|i:tolist", &flat))
|
if (!PyArg_ParseTuple(args, "|i:tolist", &flat))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (flat) {
|
if (flat) {
|
||||||
list = PyList_New(self->count*2);
|
list = PyList_New(self->count*2);
|
||||||
|
@ -491,39 +492,39 @@ static PyObject*
|
||||||
path_transform(PyPathObject* self, PyObject* args)
|
path_transform(PyPathObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
/* Apply affine transform to coordinate set */
|
/* Apply affine transform to coordinate set */
|
||||||
int i;
|
Py_ssize_t i;
|
||||||
double *xy;
|
double *xy;
|
||||||
double a, b, c, d, e, f;
|
double a, b, c, d, e, f;
|
||||||
|
|
||||||
double wrap = 0.0;
|
double wrap = 0.0;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "(dddddd)|d:transform",
|
if (!PyArg_ParseTuple(args, "(dddddd)|d:transform",
|
||||||
&a, &b, &c, &d, &e, &f,
|
&a, &b, &c, &d, &e, &f,
|
||||||
&wrap))
|
&wrap))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
xy = self->xy;
|
xy = self->xy;
|
||||||
|
|
||||||
/* transform the coordinate set */
|
/* transform the coordinate set */
|
||||||
if (b == 0.0 && d == 0.0)
|
if (b == 0.0 && d == 0.0)
|
||||||
/* scaling */
|
/* scaling */
|
||||||
for (i = 0; i < self->count; i++) {
|
for (i = 0; i < self->count; i++) {
|
||||||
xy[i+i] = a*xy[i+i]+c;
|
xy[i+i] = a*xy[i+i]+c;
|
||||||
xy[i+i+1] = e*xy[i+i+1]+f;
|
xy[i+i+1] = e*xy[i+i+1]+f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* affine transform */
|
/* affine transform */
|
||||||
for (i = 0; i < self->count; i++) {
|
for (i = 0; i < self->count; i++) {
|
||||||
double x = xy[i+i];
|
double x = xy[i+i];
|
||||||
double y = xy[i+i+1];
|
double y = xy[i+i+1];
|
||||||
xy[i+i] = a*x+b*y+c;
|
xy[i+i] = a*x+b*y+c;
|
||||||
xy[i+i+1] = d*x+e*y+f;
|
xy[i+i+1] = d*x+e*y+f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* special treatment of geographical map data */
|
/* special treatment of geographical map data */
|
||||||
if (wrap != 0.0)
|
if (wrap != 0.0)
|
||||||
for (i = 0; i < self->count; i++)
|
for (i = 0; i < self->count; i++)
|
||||||
xy[i+i] = fmod(xy[i+i], wrap);
|
xy[i+i] = fmod(xy[i+i], wrap);
|
||||||
|
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
|
@ -543,7 +544,7 @@ static struct PyMethodDef methods[] = {
|
||||||
static PyObject*
|
static PyObject*
|
||||||
path_getattr_id(PyPathObject* self, void* closure)
|
path_getattr_id(PyPathObject* self, void* closure)
|
||||||
{
|
{
|
||||||
return Py_BuildValue("n", (Py_ssize_t) self->xy);
|
return Py_BuildValue("n", (Py_ssize_t) self->xy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct PyGetSetDef getsetters[] = {
|
static struct PyGetSetDef getsetters[] = {
|
||||||
|
@ -593,13 +594,13 @@ path_subscript(PyPathObject* self, PyObject* item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static PySequenceMethods path_as_sequence = {
|
static PySequenceMethods path_as_sequence = {
|
||||||
(lenfunc)path_len, /*sq_length*/
|
(lenfunc)path_len, /*sq_length*/
|
||||||
(binaryfunc)0, /*sq_concat*/
|
(binaryfunc)0, /*sq_concat*/
|
||||||
(ssizeargfunc)0, /*sq_repeat*/
|
(ssizeargfunc)0, /*sq_repeat*/
|
||||||
(ssizeargfunc)path_getitem, /*sq_item*/
|
(ssizeargfunc)path_getitem, /*sq_item*/
|
||||||
(ssizessizeargfunc)path_getslice, /*sq_slice*/
|
(ssizessizeargfunc)path_getslice, /*sq_slice*/
|
||||||
(ssizeobjargproc)path_setitem, /*sq_ass_item*/
|
(ssizeobjargproc)path_setitem, /*sq_ass_item*/
|
||||||
(ssizessizeobjargproc)0, /*sq_ass_slice*/
|
(ssizessizeobjargproc)0, /*sq_ass_slice*/
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyMappingMethods path_as_mapping = {
|
static PyMappingMethods path_as_mapping = {
|
||||||
|
@ -609,19 +610,19 @@ static PyMappingMethods path_as_mapping = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyTypeObject PyPathType = {
|
static PyTypeObject PyPathType = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
"Path", /*tp_name*/
|
"Path", /*tp_name*/
|
||||||
sizeof(PyPathObject), /*tp_size*/
|
sizeof(PyPathObject), /*tp_size*/
|
||||||
0, /*tp_itemsize*/
|
0, /*tp_itemsize*/
|
||||||
/* methods */
|
/* methods */
|
||||||
(destructor)path_dealloc, /*tp_dealloc*/
|
(destructor)path_dealloc, /*tp_dealloc*/
|
||||||
0, /*tp_print*/
|
0, /*tp_print*/
|
||||||
0, /*tp_getattr*/
|
0, /*tp_getattr*/
|
||||||
0, /*tp_setattr*/
|
0, /*tp_setattr*/
|
||||||
0, /*tp_compare*/
|
0, /*tp_compare*/
|
||||||
0, /*tp_repr*/
|
0, /*tp_repr*/
|
||||||
0, /*tp_as_number */
|
0, /*tp_as_number */
|
||||||
&path_as_sequence, /*tp_as_sequence */
|
&path_as_sequence, /*tp_as_sequence */
|
||||||
&path_as_mapping, /*tp_as_mapping */
|
&path_as_mapping, /*tp_as_mapping */
|
||||||
0, /*tp_hash*/
|
0, /*tp_hash*/
|
||||||
0, /*tp_call*/
|
0, /*tp_call*/
|
||||||
|
|
Loading…
Reference in New Issue
Block a user