summaryrefslogtreecommitdiffstats
path: root/contrib/python/Pillow/py3/libImaging/JpegEncode.c
diff options
context:
space:
mode:
authorshumkovnd <[email protected]>2023-11-10 14:39:34 +0300
committershumkovnd <[email protected]>2023-11-10 16:42:24 +0300
commit77eb2d3fdcec5c978c64e025ced2764c57c00285 (patch)
treec51edb0748ca8d4a08d7c7323312c27ba1a8b79a /contrib/python/Pillow/py3/libImaging/JpegEncode.c
parentdd6d20cadb65582270ac23f4b3b14ae189704b9d (diff)
KIKIMR-19287: add task_stats_drawing script
Diffstat (limited to 'contrib/python/Pillow/py3/libImaging/JpegEncode.c')
-rw-r--r--contrib/python/Pillow/py3/libImaging/JpegEncode.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/contrib/python/Pillow/py3/libImaging/JpegEncode.c b/contrib/python/Pillow/py3/libImaging/JpegEncode.c
new file mode 100644
index 00000000000..2a24eff39ca
--- /dev/null
+++ b/contrib/python/Pillow/py3/libImaging/JpegEncode.c
@@ -0,0 +1,354 @@
+/*
+ * The Python Imaging Library.
+ * $Id$
+ *
+ * coder for JPEG data
+ *
+ * history:
+ * 1996-05-06 fl created
+ * 1996-07-16 fl don't drop last block of encoded data
+ * 1996-12-30 fl added quality and progressive settings
+ * 1997-01-08 fl added streamtype settings
+ * 1998-01-31 fl adapted to libjpeg 6a
+ * 1998-07-12 fl added YCbCr support
+ * 2001-04-16 fl added DPI write support
+ *
+ * Copyright (c) 1997-2001 by Secret Labs AB
+ * Copyright (c) 1995-1997 by Fredrik Lundh
+ *
+ * See the README file for details on usage and redistribution.
+ */
+
+#include "Imaging.h"
+
+#ifdef HAVE_LIBJPEG
+
+#undef HAVE_PROTOTYPES
+#undef HAVE_STDLIB_H
+#undef HAVE_STDDEF_H
+#undef UINT8
+#undef UINT16
+#undef UINT32
+#undef INT16
+#undef INT32
+
+#include "Jpeg.h"
+
+/* -------------------------------------------------------------------- */
+/* Suspending output handler */
+/* -------------------------------------------------------------------- */
+
+METHODDEF(void)
+stub(j_compress_ptr cinfo) { /* empty */ }
+
+METHODDEF(boolean)
+empty_output_buffer(j_compress_ptr cinfo) {
+ /* Suspension */
+ return FALSE;
+}
+
+GLOBAL(void)
+jpeg_buffer_dest(j_compress_ptr cinfo, JPEGDESTINATION *destination) {
+ cinfo->dest = (void *)destination;
+
+ destination->pub.init_destination = stub;
+ destination->pub.empty_output_buffer = empty_output_buffer;
+ destination->pub.term_destination = stub;
+}
+
+/* -------------------------------------------------------------------- */
+/* Error handler */
+/* -------------------------------------------------------------------- */
+
+METHODDEF(void)
+error(j_common_ptr cinfo) {
+ JPEGERROR *error;
+ error = (JPEGERROR *)cinfo->err;
+ (*cinfo->err->output_message)(cinfo);
+ longjmp(error->setjmp_buffer, 1);
+}
+
+/* -------------------------------------------------------------------- */
+/* Encoder */
+/* -------------------------------------------------------------------- */
+
+int
+ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
+ JPEGENCODERSTATE *context = (JPEGENCODERSTATE *)state->context;
+ int ok;
+
+ if (setjmp(context->error.setjmp_buffer)) {
+ /* JPEG error handler */
+ jpeg_destroy_compress(&context->cinfo);
+ state->errcode = IMAGING_CODEC_BROKEN;
+ return -1;
+ }
+
+ if (!state->state) {
+ /* Setup compression context (very similar to the decoder) */
+ context->cinfo.err = jpeg_std_error(&context->error.pub);
+ context->error.pub.error_exit = error;
+ jpeg_create_compress(&context->cinfo);
+ jpeg_buffer_dest(&context->cinfo, &context->destination);
+
+ context->extra_offset = 0;
+
+ /* Ready to encode */
+ state->state = 1;
+ }
+
+ /* Load the destination buffer */
+ context->destination.pub.next_output_byte = buf;
+ context->destination.pub.free_in_buffer = bytes;
+
+ switch (state->state) {
+ case 1:
+
+ context->cinfo.image_width = state->xsize;
+ context->cinfo.image_height = state->ysize;
+
+ switch (state->bits) {
+ case 8:
+ context->cinfo.input_components = 1;
+ context->cinfo.in_color_space = JCS_GRAYSCALE;
+ break;
+ case 24:
+ context->cinfo.input_components = 3;
+ if (strcmp(im->mode, "YCbCr") == 0) {
+ context->cinfo.in_color_space = JCS_YCbCr;
+ } else {
+ context->cinfo.in_color_space = JCS_RGB;
+ }
+ break;
+ case 32:
+ context->cinfo.input_components = 4;
+ context->cinfo.in_color_space = JCS_CMYK;
+#ifdef JCS_EXTENSIONS
+ if (strcmp(context->rawmode, "RGBX") == 0) {
+ context->cinfo.in_color_space = JCS_EXT_RGBX;
+ }
+#endif
+ break;
+ default:
+ state->errcode = IMAGING_CODEC_CONFIG;
+ return -1;
+ }
+
+ /* Compressor configuration */
+ jpeg_set_defaults(&context->cinfo);
+
+ /* Use custom quantization tables */
+ if (context->qtables) {
+ int i;
+ int quality = 100;
+ int last_q = 0;
+ if (context->quality != -1) {
+ quality = context->quality;
+ }
+ for (i = 0; i < context->qtablesLen; i++) {
+ jpeg_add_quant_table(
+ &context->cinfo,
+ i,
+ &context->qtables[i * DCTSIZE2],
+ quality,
+ FALSE);
+ context->cinfo.comp_info[i].quant_tbl_no = i;
+ last_q = i;
+ }
+ if (context->qtablesLen == 1) {
+ // jpeg_set_defaults created two qtables internally, but we only
+ // wanted one.
+ jpeg_add_quant_table(
+ &context->cinfo, 1, &context->qtables[0], quality, FALSE);
+ }
+ for (i = last_q; i < context->cinfo.num_components; i++) {
+ context->cinfo.comp_info[i].quant_tbl_no = last_q;
+ }
+ } else if (context->quality != -1) {
+ jpeg_set_quality(&context->cinfo, context->quality, TRUE);
+ }
+
+ /* Set subsampling options */
+ switch (context->subsampling) {
+ case 0: /* 1x1 1x1 1x1 (4:4:4) : None */
+ {
+ context->cinfo.comp_info[0].h_samp_factor = 1;
+ context->cinfo.comp_info[0].v_samp_factor = 1;
+ context->cinfo.comp_info[1].h_samp_factor = 1;
+ context->cinfo.comp_info[1].v_samp_factor = 1;
+ context->cinfo.comp_info[2].h_samp_factor = 1;
+ context->cinfo.comp_info[2].v_samp_factor = 1;
+ break;
+ }
+ case 1: /* 2x1, 1x1, 1x1 (4:2:2) : Medium */
+ {
+ context->cinfo.comp_info[0].h_samp_factor = 2;
+ context->cinfo.comp_info[0].v_samp_factor = 1;
+ context->cinfo.comp_info[1].h_samp_factor = 1;
+ context->cinfo.comp_info[1].v_samp_factor = 1;
+ context->cinfo.comp_info[2].h_samp_factor = 1;
+ context->cinfo.comp_info[2].v_samp_factor = 1;
+ break;
+ }
+ case 2: /* 2x2, 1x1, 1x1 (4:2:0) : High */
+ {
+ context->cinfo.comp_info[0].h_samp_factor = 2;
+ context->cinfo.comp_info[0].v_samp_factor = 2;
+ context->cinfo.comp_info[1].h_samp_factor = 1;
+ context->cinfo.comp_info[1].v_samp_factor = 1;
+ context->cinfo.comp_info[2].h_samp_factor = 1;
+ context->cinfo.comp_info[2].v_samp_factor = 1;
+ break;
+ }
+ default: {
+ /* Use the lib's default */
+ break;
+ }
+ }
+ if (context->progressive) {
+ jpeg_simple_progression(&context->cinfo);
+ }
+ context->cinfo.smoothing_factor = context->smooth;
+ context->cinfo.optimize_coding = (boolean)context->optimize;
+ if (context->xdpi > 0 && context->ydpi > 0) {
+ context->cinfo.write_JFIF_header = TRUE;
+ context->cinfo.density_unit = 1; /* dots per inch */
+ context->cinfo.X_density = context->xdpi;
+ context->cinfo.Y_density = context->ydpi;
+ }
+ switch (context->streamtype) {
+ case 1:
+ /* tables only -- not yet implemented */
+ state->errcode = IMAGING_CODEC_CONFIG;
+ return -1;
+ case 2:
+ /* image only */
+ jpeg_suppress_tables(&context->cinfo, TRUE);
+ jpeg_start_compress(&context->cinfo, FALSE);
+ /* suppress extra section */
+ context->extra_offset = context->extra_size;
+ break;
+ default:
+ /* interchange stream */
+ jpeg_start_compress(&context->cinfo, TRUE);
+ break;
+ }
+ state->state++;
+ /* fall through */
+
+ case 2:
+ // check for exif len + 'APP1' header bytes
+ if (context->rawExifLen + 5 > context->destination.pub.free_in_buffer) {
+ break;
+ }
+ // add exif header
+ if (context->rawExifLen > 0) {
+ jpeg_write_marker(
+ &context->cinfo,
+ JPEG_APP0 + 1,
+ (unsigned char *)context->rawExif,
+ context->rawExifLen);
+ }
+
+ state->state++;
+ /* fall through */
+ case 3:
+
+ if (context->extra) {
+ /* copy extra buffer to output buffer */
+ unsigned int n = context->extra_size - context->extra_offset;
+ if (n > context->destination.pub.free_in_buffer) {
+ n = context->destination.pub.free_in_buffer;
+ }
+ memcpy(
+ context->destination.pub.next_output_byte,
+ context->extra + context->extra_offset,
+ n);
+ context->destination.pub.next_output_byte += n;
+ context->destination.pub.free_in_buffer -= n;
+ context->extra_offset += n;
+ if (context->extra_offset >= context->extra_size) {
+ state->state++;
+ } else {
+ break;
+ }
+ } else {
+ state->state++;
+ }
+
+ case 4:
+
+ if (context->comment) {
+ jpeg_write_marker(&context->cinfo, JPEG_COM, (unsigned char *)context->comment, context->comment_size);
+ }
+ state->state++;
+
+ case 5:
+ if (1024 > context->destination.pub.free_in_buffer) {
+ break;
+ }
+
+ ok = 1;
+ while (state->y < state->ysize) {
+ state->shuffle(
+ state->buffer,
+ (UINT8 *)im->image[state->y + state->yoff] +
+ state->xoff * im->pixelsize,
+ state->xsize);
+ ok = jpeg_write_scanlines(&context->cinfo, &state->buffer, 1);
+ if (ok != 1) {
+ break;
+ }
+ state->y++;
+ }
+
+ if (ok != 1) {
+ break;
+ }
+ state->state++;
+ /* fall through */
+
+ case 6:
+
+ /* Finish compression */
+ if (context->destination.pub.free_in_buffer < 100) {
+ break;
+ }
+ jpeg_finish_compress(&context->cinfo);
+
+ /* Clean up */
+ if (context->comment) {
+ free(context->comment);
+ context->comment = NULL;
+ }
+ if (context->extra) {
+ free(context->extra);
+ context->extra = NULL;
+ }
+ if (context->rawExif) {
+ free(context->rawExif);
+ context->rawExif = NULL;
+ }
+ if (context->qtables) {
+ free(context->qtables);
+ context->qtables = NULL;
+ }
+
+ jpeg_destroy_compress(&context->cinfo);
+ /* if (jerr.pub.num_warnings) return BROKEN; */
+ state->errcode = IMAGING_CODEC_END;
+ break;
+ }
+
+ /* Return number of bytes in output buffer */
+ return context->destination.pub.next_output_byte - buf;
+}
+
+const char *
+ImagingJpegVersion(void) {
+ static char version[20];
+ sprintf(version, "%d.%d", JPEG_LIB_VERSION / 10, JPEG_LIB_VERSION % 10);
+ return version;
+}
+
+#endif