Added tests and fixed a few bugs that the tests threw up.

This commit is contained in:
Alastair Houghton 2014-03-19 12:16:14 +00:00
parent 68fd58a7e2
commit ac8ebccfa6
7 changed files with 78 additions and 16 deletions

View File

@ -153,11 +153,15 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
self.reduce = 0
self.layers = 0
fd = -1
if hasattr(self.fp, "fileno"):
fd = self.fp.fileno()
try:
fd = self.fp.fileno()
except:
fd = -1
self.tile = [('jpeg2k', (0, 0) + self.size, 0,
(self.codec, self.reduce, self.layers, fd))]
@ -167,6 +171,12 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
adjust = power >> 1
self.size = ((self.size[0] + adjust) / power,
(self.size[1] + adjust) / power)
if self.tile:
# Update the reduce and layers settings
t = self.tile[0]
t3 = (t[3][0], self.reduce, self.layers, t[3][3])
self.tile = [(t[0], t[1], t[2], t3)]
ImageFile.ImageFile.load(self)
@ -200,7 +210,10 @@ def _save(im, fp, filename):
fd = -1
if hasattr(fp, "fileno"):
fd = fp.fileno()
try:
fd = fp.fileno()
except:
fd = -1
im.encoderconfig = (
offset,

View File

@ -827,7 +827,7 @@ PyImaging_Jpeg2KDecoderNew(PyObject* self, PyObject* args)
context->format = codec_format;
context->reduce = reduce;
context->layers = layers;
return (PyObject*) decoder;
}
#endif /* HAVE_OPENJPEG */

View File

@ -885,7 +885,7 @@ PyImaging_Jpeg2KEncoderNew(PyObject *self, PyObject *args)
else
return NULL;
encoder = PyImaging_EncoderNew(sizeof(JPEG2KENCODESTATE));
encoder = PyImaging_EncoderNew(sizeof(JPEG2KENCODESTATE));
if (!encoder)
return NULL;
@ -906,6 +906,24 @@ PyImaging_Jpeg2KEncoderNew(PyObject *self, PyObject *args)
&context->tile_size_x,
&context->tile_size_y);
/* Error on illegal tile offsets */
if (context->tile_size_x && context->tile_size_y) {
if (context->tile_offset_x <= context->offset_x - context->tile_size_x
|| context->tile_offset_y <= context->offset_y - context->tile_size_y) {
PyErr_SetString(PyExc_ValueError,
"JPEG 2000 tile offset too small; top left tile must "
"intersect image area");
}
if (context->tile_offset_x > context->offset_x
|| context->tile_offset_y > context->offset_y) {
PyErr_SetString(PyExc_ValueError,
"JPEG 2000 tile offset too large to cover image area");
Py_DECREF(encoder);
return NULL;
}
}
if (quality_layers && PySequence_Check(quality_layers)) {
context->quality_is_in_db = strcmp (quality_mode, "dB") == 0;
context->quality_layers = quality_layers;

View File

@ -93,8 +93,12 @@ codec_thread(void *ptr)
{
ImagingIncrementalCodec codec = (ImagingIncrementalCodec)ptr;
DEBUG("Entering thread\n");
codec->result = codec->entry(codec->im, codec->state, codec);
DEBUG("Leaving thread (%d)\n", codec->result);
flush_stream(codec);
SetEvent(codec->hCodecEvent);
@ -107,8 +111,12 @@ codec_thread(void *ptr)
{
ImagingIncrementalCodec codec = (ImagingIncrementalCodec)ptr;
DEBUG("Entering thread\n");
codec->result = codec->entry(codec->im, codec->state, codec);
DEBUG("Leaving thread (%d)\n", codec->result);
flush_stream(codec);
pthread_mutex_lock(&codec->codec_mutex);
@ -335,6 +343,11 @@ ImagingIncrementalCodecPushBuffer(ImagingIncrementalCodec codec,
pthread_cond_wait(&codec->codec_cond, &codec->codec_mutex);
pthread_mutex_unlock(&codec->codec_mutex);
#endif
if (codec->result < 0) {
DEBUG("got result %d\n", codec->result);
return codec->result;
}
}
/* Codecs using an fd don't need data, so when we get here, we're done */

View File

@ -91,7 +91,7 @@ static void
j2ku_gray_l(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
const UINT8 *tiledata, Imaging im)
{
unsigned x0 = tileinfo->x0, y0 = tileinfo->y0;
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
unsigned w = tileinfo->x1 - tileinfo->x0;
unsigned h = tileinfo->y1 - tileinfo->y0;
@ -139,7 +139,7 @@ static void
j2ku_gray_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
const UINT8 *tiledata, Imaging im)
{
unsigned x0 = tileinfo->x0, y0 = tileinfo->y0;
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
unsigned w = tileinfo->x1 - tileinfo->x0;
unsigned h = tileinfo->y1 - tileinfo->y0;
@ -199,7 +199,7 @@ static void
j2ku_graya_la(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
const UINT8 *tiledata, Imaging im)
{
unsigned x0 = tileinfo->x0, y0 = tileinfo->y0;
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
unsigned w = tileinfo->x1 - tileinfo->x0;
unsigned h = tileinfo->y1 - tileinfo->y0;
@ -256,7 +256,7 @@ static void
j2ku_srgb_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
const UINT8 *tiledata, Imaging im)
{
unsigned x0 = tileinfo->x0, y0 = tileinfo->y0;
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
unsigned w = tileinfo->x1 - tileinfo->x0;
unsigned h = tileinfo->y1 - tileinfo->y0;
@ -308,7 +308,7 @@ static void
j2ku_sycc_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
const UINT8 *tiledata, Imaging im)
{
unsigned x0 = tileinfo->x0, y0 = tileinfo->y0;
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
unsigned w = tileinfo->x1 - tileinfo->x0;
unsigned h = tileinfo->y1 - tileinfo->y0;
@ -363,7 +363,7 @@ static void
j2ku_srgba_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
const UINT8 *tiledata, Imaging im)
{
unsigned x0 = tileinfo->x0, y0 = tileinfo->y0;
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
unsigned w = tileinfo->x1 - tileinfo->x0;
unsigned h = tileinfo->y1 - tileinfo->y0;
@ -414,7 +414,7 @@ static void
j2ku_sycca_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
const UINT8 *tiledata, Imaging im)
{
unsigned x0 = tileinfo->x0, y0 = tileinfo->y0;
unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0;
unsigned w = tileinfo->x1 - tileinfo->x0;
unsigned h = tileinfo->y1 - tileinfo->y0;
@ -517,7 +517,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state,
opj_stream_set_read_function(stream, j2k_read);
opj_stream_set_skip_function(stream, j2k_skip);
opj_stream_set_user_data(stream, context->decoder);
opj_stream_set_user_data(stream, decoder);
/* Setup decompression context */
context->error_msg = NULL;
@ -650,6 +650,20 @@ j2k_decode_entry(Imaging im, ImagingCodecState state,
goto quick_exit;
}
/* Check the tile bounds; if the tile is outside the image area,
or if it has a negative width or height (i.e. the coordinates are
swapped), bail. */
if (tile_info.x0 >= tile_info.x1
|| tile_info.y0 >= tile_info.y1
|| tile_info.x0 < image->x0
|| tile_info.y0 < image->y0
|| tile_info.x1 - image->x0 > im->xsize
|| tile_info.y1 - image->y0 > im->ysize) {
state->errcode = IMAGING_CODEC_BROKEN;
state->state = J2K_STATE_FAILED;
goto quick_exit;
}
unpack(image, &tile_info, state->buffer, im);
}

View File

@ -254,7 +254,7 @@ j2k_encode_entry(Imaging im, ImagingCodecState state,
opj_stream_set_skip_function(stream, j2k_skip);
opj_stream_set_seek_function(stream, j2k_seek);
opj_stream_set_user_data(stream, context->encoder);
opj_stream_set_user_data(stream, encoder);
/* Setup an opj_image */
if (strcmp (im->mode, "L") == 0) {
@ -425,8 +425,11 @@ j2k_encode_entry(Imaging im, ImagingCodecState state,
}
/* Write each tile */
tiles_x = (im->xsize + tile_width - 1) / tile_width;
tiles_y = (im->ysize + tile_height - 1) / tile_height;
tiles_x = (im->xsize + (params.image_offset_x0 - params.cp_tx0)
+ tile_width - 1) / tile_width;
tiles_y = (im->ysize + (params.image_offset_y0 - params.cp_ty0)
+ tile_height - 1) / tile_height;
num_tiles = tiles_x * tiles_y;
state->buffer = malloc (tile_width * tile_height * components);

View File

@ -192,6 +192,7 @@ if __name__ == "__main__":
check_module("PIL CORE", "PIL._imaging")
check_module("TKINTER", "PIL._imagingtk")
check_codec("JPEG", "jpeg")
check_codec("JPEG 2000", "jpeg2k")
check_codec("ZLIB (PNG/ZIP)", "zip")
check_codec("LIBTIFF", "libtiff")
check_module("FREETYPE2", "PIL._imagingft")