Pillow
661 строка · 18.9 Кб
1/*
2* The Python Imaging Library.
3* $Id$
4*
5* decoder for JPEG2000 image data.
6*
7* history:
8* 2014-03-12 ajh Created
9*
10* Copyright (c) 2014 Coriolis Systems Limited
11* Copyright (c) 2014 Alastair Houghton
12*
13* See the README file for details on usage and redistribution.
14*/
15
16#include "Imaging.h"
17
18#ifdef HAVE_OPENJPEG
19
20#include "Jpeg2K.h"
21
22#define CINEMA_24_CS_LENGTH 1302083
23#define CINEMA_48_CS_LENGTH 651041
24#define COMP_24_CS_MAX_LENGTH 1041666
25#define COMP_48_CS_MAX_LENGTH 520833
26
27/* -------------------------------------------------------------------- */
28/* Error handler */
29/* -------------------------------------------------------------------- */
30
31static void
32j2k_error(const char *msg, void *client_data) {
33JPEG2KENCODESTATE *state = (JPEG2KENCODESTATE *)client_data;
34free((void *)state->error_msg);
35state->error_msg = strdup(msg);
36}
37
38static void
39j2k_warn(const char *msg, void *client_data) {
40// Null handler
41}
42
43/* -------------------------------------------------------------------- */
44/* Buffer output stream */
45/* -------------------------------------------------------------------- */
46
47static OPJ_SIZE_T
48j2k_write(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) {
49ImagingCodecState state = (ImagingCodecState)p_user_data;
50unsigned int result;
51
52result = _imaging_write_pyFd(state->fd, p_buffer, p_nb_bytes);
53
54return result ? result : (OPJ_SIZE_T)-1;
55}
56
57static OPJ_OFF_T
58j2k_skip(OPJ_OFF_T p_nb_bytes, void *p_user_data) {
59ImagingCodecState state = (ImagingCodecState)p_user_data;
60char *buffer;
61int result;
62
63/* Explicitly write zeros */
64buffer = calloc(p_nb_bytes, 1);
65if (!buffer) {
66return (OPJ_OFF_T)-1;
67}
68
69result = _imaging_write_pyFd(state->fd, buffer, p_nb_bytes);
70
71free(buffer);
72
73return result ? result : p_nb_bytes;
74}
75
76static OPJ_BOOL
77j2k_seek(OPJ_OFF_T p_nb_bytes, void *p_user_data) {
78ImagingCodecState state = (ImagingCodecState)p_user_data;
79off_t pos = 0;
80
81_imaging_seek_pyFd(state->fd, p_nb_bytes, SEEK_SET);
82pos = _imaging_tell_pyFd(state->fd);
83
84return pos == p_nb_bytes;
85}
86
87/* -------------------------------------------------------------------- */
88/* Encoder */
89/* -------------------------------------------------------------------- */
90
91typedef void (*j2k_pack_tile_t)(
92Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h
93);
94
95static void
96j2k_pack_l(Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h) {
97UINT8 *ptr = buf;
98unsigned x, y;
99for (y = 0; y < h; ++y) {
100UINT8 *data = (UINT8 *)(im->image[y + y0] + x0);
101for (x = 0; x < w; ++x) {
102*ptr++ = *data++;
103}
104}
105}
106
107static void
108j2k_pack_i16(Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h) {
109UINT8 *ptr = buf;
110unsigned x, y;
111for (y = 0; y < h; ++y) {
112UINT8 *data = (UINT8 *)(im->image[y + y0] + x0);
113for (x = 0; x < w; ++x) {
114#ifdef WORDS_BIGENDIAN
115ptr[0] = data[1];
116ptr[1] = data[0];
117#else
118ptr[0] = data[0];
119ptr[1] = data[1];
120#endif
121ptr += 2;
122data += 2;
123}
124}
125}
126
127static void
128j2k_pack_la(Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h) {
129UINT8 *ptr = buf;
130UINT8 *ptra = buf + w * h;
131unsigned x, y;
132for (y = 0; y < h; ++y) {
133UINT8 *data = (UINT8 *)(im->image[y + y0] + 4 * x0);
134for (x = 0; x < w; ++x) {
135*ptr++ = data[0];
136*ptra++ = data[3];
137data += 4;
138}
139}
140}
141
142static void
143j2k_pack_rgb(Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h) {
144UINT8 *pr = buf;
145UINT8 *pg = pr + w * h;
146UINT8 *pb = pg + w * h;
147unsigned x, y;
148for (y = 0; y < h; ++y) {
149UINT8 *data = (UINT8 *)(im->image[y + y0] + 4 * x0);
150for (x = 0; x < w; ++x) {
151*pr++ = data[0];
152*pg++ = data[1];
153*pb++ = data[2];
154data += 4;
155}
156}
157}
158
159static void
160j2k_pack_rgba(
161Imaging im, UINT8 *buf, unsigned x0, unsigned y0, unsigned w, unsigned h
162) {
163UINT8 *pr = buf;
164UINT8 *pg = pr + w * h;
165UINT8 *pb = pg + w * h;
166UINT8 *pa = pb + w * h;
167unsigned x, y;
168for (y = 0; y < h; ++y) {
169UINT8 *data = (UINT8 *)(im->image[y + y0] + 4 * x0);
170for (x = 0; x < w; ++x) {
171*pr++ = *data++;
172*pg++ = *data++;
173*pb++ = *data++;
174*pa++ = *data++;
175}
176}
177}
178
179enum {
180J2K_STATE_START = 0,
181J2K_STATE_ENCODING = 1,
182J2K_STATE_DONE = 2,
183J2K_STATE_FAILED = 3,
184};
185
186static void
187j2k_set_cinema_params(Imaging im, int components, opj_cparameters_t *params) {
188float rate;
189int n;
190
191/* These settings have been copied from opj_compress in the OpenJPEG
192sources. */
193
194params->tile_size_on = OPJ_FALSE;
195params->cp_tdx = params->cp_tdy = 1;
196params->tp_flag = 'C';
197params->tp_on = 1;
198params->cp_tx0 = params->cp_ty0 = 0;
199params->image_offset_x0 = params->image_offset_y0 = 0;
200params->cblockw_init = 32;
201params->cblockh_init = 32;
202params->csty |= 0x01;
203params->prog_order = OPJ_CPRL;
204params->roi_compno = -1;
205params->subsampling_dx = params->subsampling_dy = 1;
206params->irreversible = 1;
207
208if (params->cp_cinema == OPJ_CINEMA4K_24) {
209float max_rate =
210((float)(components * im->xsize * im->ysize * 8) / (CINEMA_24_CS_LENGTH * 8)
211);
212
213params->POC[0].tile = 1;
214params->POC[0].resno0 = 0;
215params->POC[0].compno0 = 0;
216params->POC[0].layno1 = 1;
217params->POC[0].resno1 = params->numresolution - 1;
218params->POC[0].compno1 = 3;
219params->POC[0].prg1 = OPJ_CPRL;
220params->POC[1].tile = 1;
221params->POC[1].resno0 = 0;
222params->POC[1].compno0 = 0;
223params->POC[1].layno1 = 1;
224params->POC[1].resno1 = params->numresolution - 1;
225params->POC[1].compno1 = 3;
226params->POC[1].prg1 = OPJ_CPRL;
227params->numpocs = 2;
228
229for (n = 0; n < params->tcp_numlayers; ++n) {
230rate = 0;
231if (params->tcp_rates[0] == 0) {
232params->tcp_rates[n] = max_rate;
233} else {
234rate =
235((float)(components * im->xsize * im->ysize * 8) /
236(params->tcp_rates[n] * 8));
237if (rate > CINEMA_24_CS_LENGTH) {
238params->tcp_rates[n] = max_rate;
239}
240}
241}
242
243params->max_comp_size = COMP_24_CS_MAX_LENGTH;
244} else {
245float max_rate =
246((float)(components * im->xsize * im->ysize * 8) / (CINEMA_48_CS_LENGTH * 8)
247);
248
249for (n = 0; n < params->tcp_numlayers; ++n) {
250rate = 0;
251if (params->tcp_rates[0] == 0) {
252params->tcp_rates[n] = max_rate;
253} else {
254rate =
255((float)(components * im->xsize * im->ysize * 8) /
256(params->tcp_rates[n] * 8));
257if (rate > CINEMA_48_CS_LENGTH) {
258params->tcp_rates[n] = max_rate;
259}
260}
261}
262
263params->max_comp_size = COMP_48_CS_MAX_LENGTH;
264}
265}
266
267static int
268j2k_encode_entry(Imaging im, ImagingCodecState state) {
269JPEG2KENCODESTATE *context = (JPEG2KENCODESTATE *)state->context;
270opj_stream_t *stream = NULL;
271opj_image_t *image = NULL;
272opj_codec_t *codec = NULL;
273opj_cparameters_t params;
274unsigned components;
275OPJ_COLOR_SPACE color_space;
276opj_image_cmptparm_t image_params[4];
277unsigned xsiz, ysiz;
278unsigned tile_width, tile_height;
279unsigned tiles_x, tiles_y;
280unsigned x, y, tile_ndx;
281unsigned n;
282j2k_pack_tile_t pack;
283int ret = -1;
284
285unsigned prec = 8;
286unsigned _overflow_scale_factor;
287
288stream = opj_stream_create(BUFFER_SIZE, OPJ_FALSE);
289
290if (!stream) {
291state->errcode = IMAGING_CODEC_BROKEN;
292state->state = J2K_STATE_FAILED;
293goto quick_exit;
294}
295
296opj_stream_set_write_function(stream, j2k_write);
297opj_stream_set_skip_function(stream, j2k_skip);
298opj_stream_set_seek_function(stream, j2k_seek);
299
300/* OpenJPEG 2.0 doesn't have OPJ_VERSION_MAJOR */
301#ifndef OPJ_VERSION_MAJOR
302opj_stream_set_user_data(stream, state);
303#else
304opj_stream_set_user_data(stream, state, NULL);
305#endif
306
307/* Setup an opj_image */
308if (strcmp(im->mode, "L") == 0) {
309components = 1;
310color_space = OPJ_CLRSPC_GRAY;
311pack = j2k_pack_l;
312} else if (strcmp(im->mode, "I;16") == 0 || strcmp(im->mode, "I;16B") == 0) {
313components = 1;
314color_space = OPJ_CLRSPC_GRAY;
315pack = j2k_pack_i16;
316prec = 16;
317} else if (strcmp(im->mode, "LA") == 0) {
318components = 2;
319color_space = OPJ_CLRSPC_GRAY;
320pack = j2k_pack_la;
321} else if (strcmp(im->mode, "RGB") == 0) {
322components = 3;
323color_space = OPJ_CLRSPC_SRGB;
324pack = j2k_pack_rgb;
325} else if (strcmp(im->mode, "YCbCr") == 0) {
326components = 3;
327color_space = OPJ_CLRSPC_SYCC;
328pack = j2k_pack_rgb;
329} else if (strcmp(im->mode, "RGBA") == 0) {
330components = 4;
331color_space = OPJ_CLRSPC_SRGB;
332pack = j2k_pack_rgba;
333} else {
334state->errcode = IMAGING_CODEC_BROKEN;
335state->state = J2K_STATE_FAILED;
336goto quick_exit;
337}
338
339for (n = 0; n < components; ++n) {
340image_params[n].dx = image_params[n].dy = 1;
341image_params[n].w = im->xsize;
342image_params[n].h = im->ysize;
343image_params[n].x0 = image_params[n].y0 = 0;
344image_params[n].prec = prec;
345image_params[n].sgnd = context->sgnd == 0 ? 0 : 1;
346}
347
348image = opj_image_create(components, image_params, color_space);
349if (!image) {
350state->errcode = IMAGING_CODEC_BROKEN;
351state->state = J2K_STATE_FAILED;
352goto quick_exit;
353}
354
355/* Setup compression context */
356context->error_msg = NULL;
357
358opj_set_default_encoder_parameters(¶ms);
359
360params.image_offset_x0 = context->offset_x;
361params.image_offset_y0 = context->offset_y;
362
363if (context->tile_size_x && context->tile_size_y) {
364params.tile_size_on = OPJ_TRUE;
365params.cp_tx0 = context->tile_offset_x;
366params.cp_ty0 = context->tile_offset_y;
367params.cp_tdx = context->tile_size_x;
368params.cp_tdy = context->tile_size_y;
369
370tile_width = params.cp_tdx;
371tile_height = params.cp_tdy;
372} else {
373params.cp_tx0 = 0;
374params.cp_ty0 = 0;
375params.cp_tdx = 1;
376params.cp_tdy = 1;
377
378tile_width = im->xsize;
379tile_height = im->ysize;
380}
381
382if (context->quality_layers && PySequence_Check(context->quality_layers)) {
383Py_ssize_t len = PySequence_Length(context->quality_layers);
384Py_ssize_t n;
385float *pq;
386
387if (len > 0) {
388if ((size_t)len > sizeof(params.tcp_rates) / sizeof(params.tcp_rates[0])) {
389len = sizeof(params.tcp_rates) / sizeof(params.tcp_rates[0]);
390}
391
392params.tcp_numlayers = (int)len;
393
394if (context->quality_is_in_db) {
395params.cp_disto_alloc = params.cp_fixed_alloc = 0;
396params.cp_fixed_quality = 1;
397pq = params.tcp_distoratio;
398} else {
399params.cp_disto_alloc = 1;
400params.cp_fixed_alloc = params.cp_fixed_quality = 0;
401pq = params.tcp_rates;
402}
403
404for (n = 0; n < len; ++n) {
405PyObject *obj = PySequence_ITEM(context->quality_layers, n);
406pq[n] = PyFloat_AsDouble(obj);
407}
408}
409} else {
410params.tcp_numlayers = 1;
411params.tcp_rates[0] = 0;
412params.cp_disto_alloc = 1;
413}
414
415if (context->num_resolutions) {
416params.numresolution = context->num_resolutions;
417}
418
419if (context->cblk_width >= 4 && context->cblk_width <= 1024 &&
420context->cblk_height >= 4 && context->cblk_height <= 1024 &&
421context->cblk_width * context->cblk_height <= 4096) {
422params.cblockw_init = context->cblk_width;
423params.cblockh_init = context->cblk_height;
424}
425
426if (context->precinct_width >= 4 && context->precinct_height >= 4 &&
427context->precinct_width >= context->cblk_width &&
428context->precinct_height > context->cblk_height) {
429params.prcw_init[0] = context->precinct_width;
430params.prch_init[0] = context->precinct_height;
431params.res_spec = 1;
432params.csty |= 0x01;
433}
434
435params.irreversible = context->irreversible;
436if (components == 3) {
437params.tcp_mct = context->mct;
438}
439
440if (context->comment) {
441params.cp_comment = context->comment;
442}
443
444params.prog_order = context->progression;
445
446params.cp_cinema = context->cinema_mode;
447
448switch (params.cp_cinema) {
449case OPJ_OFF:
450params.cp_rsiz = OPJ_STD_RSIZ;
451break;
452case OPJ_CINEMA2K_24:
453case OPJ_CINEMA2K_48:
454params.cp_rsiz = OPJ_CINEMA2K;
455if (params.numresolution > 6) {
456params.numresolution = 6;
457}
458break;
459case OPJ_CINEMA4K_24:
460params.cp_rsiz = OPJ_CINEMA4K;
461if (params.numresolution > 7) {
462params.numresolution = 7;
463}
464break;
465}
466
467if (!context->num_resolutions) {
468while (tile_width < (1U << (params.numresolution - 1U)) ||
469tile_height < (1U << (params.numresolution - 1U))) {
470params.numresolution -= 1;
471}
472}
473
474if (context->cinema_mode != OPJ_OFF) {
475j2k_set_cinema_params(im, components, ¶ms);
476}
477
478/* Set up the reference grid in the image */
479image->x0 = params.image_offset_x0;
480image->y0 = params.image_offset_y0;
481image->x1 = xsiz = im->xsize + params.image_offset_x0;
482image->y1 = ysiz = im->ysize + params.image_offset_y0;
483
484/* Create the compressor */
485codec = opj_create_compress(context->format);
486
487if (!codec) {
488state->errcode = IMAGING_CODEC_BROKEN;
489state->state = J2K_STATE_FAILED;
490goto quick_exit;
491}
492
493if (strcmp(im->mode, "RGBA") == 0) {
494image->comps[3].alpha = 1;
495} else if (strcmp(im->mode, "LA") == 0) {
496image->comps[1].alpha = 1;
497}
498
499opj_set_error_handler(codec, j2k_error, context);
500opj_set_info_handler(codec, j2k_warn, context);
501opj_set_warning_handler(codec, j2k_warn, context);
502opj_setup_encoder(codec, ¶ms, image);
503
504/* Enabling PLT markers only supported in OpenJPEG 2.4.0 and up */
505#if ((OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR >= 4) || OPJ_VERSION_MAJOR > 2)
506if (context->plt) {
507const char *plt_option[2] = {"PLT=YES", NULL};
508opj_encoder_set_extra_options(codec, plt_option);
509}
510#endif
511
512/* Start encoding */
513if (!opj_start_compress(codec, image, stream)) {
514state->errcode = IMAGING_CODEC_BROKEN;
515state->state = J2K_STATE_FAILED;
516goto quick_exit;
517}
518
519/* Write each tile */
520tiles_x = (im->xsize + (params.image_offset_x0 - params.cp_tx0) + tile_width - 1) /
521tile_width;
522tiles_y = (im->ysize + (params.image_offset_y0 - params.cp_ty0) + tile_height - 1) /
523tile_height;
524
525/* check for integer overflow for the malloc line, checking any expression
526that may multiply either tile_width or tile_height */
527_overflow_scale_factor = components * prec;
528if ((tile_width > UINT_MAX / _overflow_scale_factor) ||
529(tile_height > UINT_MAX / _overflow_scale_factor) ||
530(tile_width > UINT_MAX / (tile_height * _overflow_scale_factor)) ||
531(tile_height > UINT_MAX / (tile_width * _overflow_scale_factor))) {
532state->errcode = IMAGING_CODEC_BROKEN;
533state->state = J2K_STATE_FAILED;
534goto quick_exit;
535}
536/* malloc check ok, checked for overflow above */
537state->buffer = malloc(tile_width * tile_height * components * prec / 8);
538if (!state->buffer) {
539state->errcode = IMAGING_CODEC_BROKEN;
540state->state = J2K_STATE_FAILED;
541goto quick_exit;
542}
543
544tile_ndx = 0;
545for (y = 0; y < tiles_y; ++y) {
546int ty0 = params.cp_ty0 + y * tile_height;
547unsigned ty1 = ty0 + tile_height;
548unsigned pixy, pixh;
549
550if (ty0 < params.image_offset_y0) {
551ty0 = params.image_offset_y0;
552}
553if (ty1 > ysiz) {
554ty1 = ysiz;
555}
556
557pixy = ty0 - params.image_offset_y0;
558pixh = ty1 - ty0;
559
560for (x = 0; x < tiles_x; ++x) {
561int tx0 = params.cp_tx0 + x * tile_width;
562unsigned tx1 = tx0 + tile_width;
563unsigned pixx, pixw;
564unsigned data_size;
565
566if (tx0 < params.image_offset_x0) {
567tx0 = params.image_offset_x0;
568}
569if (tx1 > xsiz) {
570tx1 = xsiz;
571}
572
573pixx = tx0 - params.image_offset_x0;
574pixw = tx1 - tx0;
575
576pack(im, state->buffer, pixx, pixy, pixw, pixh);
577
578data_size = pixw * pixh * components * prec / 8;
579
580if (!opj_write_tile(codec, tile_ndx++, state->buffer, data_size, stream)) {
581state->errcode = IMAGING_CODEC_BROKEN;
582state->state = J2K_STATE_FAILED;
583goto quick_exit;
584}
585}
586}
587
588if (!opj_end_compress(codec, stream)) {
589state->errcode = IMAGING_CODEC_BROKEN;
590state->state = J2K_STATE_FAILED;
591goto quick_exit;
592}
593
594state->errcode = IMAGING_CODEC_END;
595state->state = J2K_STATE_DONE;
596ret = -1;
597
598quick_exit:
599if (codec) {
600opj_destroy_codec(codec);
601}
602if (image) {
603opj_image_destroy(image);
604}
605if (stream) {
606opj_stream_destroy(stream);
607}
608
609return ret;
610}
611
612int
613ImagingJpeg2KEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
614if (state->state == J2K_STATE_FAILED) {
615return -1;
616}
617
618if (state->state == J2K_STATE_START) {
619state->state = J2K_STATE_ENCODING;
620
621return j2k_encode_entry(im, state);
622}
623
624return -1;
625}
626
627/* -------------------------------------------------------------------- */
628/* Cleanup */
629/* -------------------------------------------------------------------- */
630
631int
632ImagingJpeg2KEncodeCleanup(ImagingCodecState state) {
633JPEG2KENCODESTATE *context = (JPEG2KENCODESTATE *)state->context;
634
635if (context->quality_layers) {
636Py_XDECREF(context->quality_layers);
637context->quality_layers = NULL;
638}
639
640if (context->error_msg) {
641free((void *)context->error_msg);
642}
643
644if (context->comment) {
645free((void *)context->comment);
646}
647
648context->error_msg = NULL;
649context->comment = NULL;
650
651return -1;
652}
653
654#endif /* HAVE_OPENJPEG */
655
656/*
657* Local Variables:
658* c-basic-offset: 4
659* End:
660*
661*/
662