From 3ae2bdf4aaf5b5f4132fde763ef5dc6a610128d8 Mon Sep 17 00:00:00 2001 From: Steve Underwood Date: Tue, 7 Aug 2012 22:34:32 +0800 Subject: [PATCH] Improvements to dithering down colour and gray scale images to bi-level images, for images with different illuminants. --- libs/spandsp/src/fax.c | 4 - libs/spandsp/src/image_translate.c | 94 ++++++++++--------- libs/spandsp/src/spandsp/image_translate.h | 11 +-- .../src/spandsp/private/image_translate.h | 1 + libs/spandsp/src/spandsp/private/t4_tx.h | 7 ++ libs/spandsp/src/spandsp/t30.h | 6 +- libs/spandsp/src/spandsp/t30_fcf.h | 1 + libs/spandsp/src/t30.c | 10 +- libs/spandsp/src/t30_api.c | 4 - libs/spandsp/src/t30_logging.c | 6 +- libs/spandsp/src/t38_gateway.c | 4 - libs/spandsp/src/t38_terminal.c | 4 - libs/spandsp/src/t4_rx.c | 4 - libs/spandsp/src/t4_t6_decode.c | 4 - libs/spandsp/src/t4_t6_encode.c | 4 - libs/spandsp/src/t4_tx.c | 80 +++++++++------- libs/spandsp/tests/image_translate_tests.c | 12 +-- libs/spandsp/tests/t42_tests.c | 4 +- 18 files changed, 126 insertions(+), 134 deletions(-) diff --git a/libs/spandsp/src/fax.c b/libs/spandsp/src/fax.c index 19bf4cf5e6..1edba28eea 100644 --- a/libs/spandsp/src/fax.c +++ b/libs/spandsp/src/fax.c @@ -77,9 +77,7 @@ #include "spandsp/image_translate.h" #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" #endif @@ -111,9 +109,7 @@ #include "spandsp/private/timezone.h" #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/private/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" #endif diff --git a/libs/spandsp/src/image_translate.c b/libs/spandsp/src/image_translate.c index db6a7adc0e..785997def5 100644 --- a/libs/spandsp/src/image_translate.c +++ b/libs/spandsp/src/image_translate.c @@ -59,9 +59,7 @@ #include "spandsp/t4_tx.h" #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" #endif @@ -72,9 +70,7 @@ #include "spandsp/private/logging.h" #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/private/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" #endif @@ -132,13 +128,13 @@ static int get_and_scrunch_row(image_translate_state_t *s, uint8_t buf[], size_t /* Scrunch colour down to gray, and scrunch 16 bit pixels down to 8 bit pixels */ switch (s->input_format) { - case IMAGE_TRANSLATE_FROM_GRAY_16: + case T4_IMAGE_TYPE_GRAY_12BIT: image_gray16_to_gray8_row(buf, (uint16_t *) buf, s->input_width); break; - case IMAGE_TRANSLATE_FROM_COLOUR_16: + case T4_IMAGE_TYPE_COLOUR_12BIT: image_colour16_to_gray8_row(buf, (uint16_t *) buf, s->input_width); break; - case IMAGE_TRANSLATE_FROM_COLOUR_8: + case T4_IMAGE_TYPE_COLOUR_8BIT: image_colour8_to_gray8_row(buf, buf, s->input_width); break; } @@ -235,47 +231,17 @@ static __inline__ uint8_t find_closest_palette_color(int in) } /*- End of function --------------------------------------------------------*/ -SPAN_DECLARE(int) image_translate_row(image_translate_state_t *s, uint8_t buf[], size_t len) +static int floyd_steinberg_dither_row(image_translate_state_t *s, uint8_t buf[], int y) { int x; - int y; int i; int j; int limit; int old_pixel; int new_pixel; int quant_error; - uint8_t *p; uint8_t xx; - if (s->output_row < 0) - return 0; - y = s->output_row++; - /* This algorithm works over two rows, and outputs the earlier of the two. To - make this work: - - At row 0 we grab and scrunch two rows. - - From row 1 up to the last row we grab one new additional row each time. - - At the last row we dither and output, without getting an extra row in. */ - for (i = (y == 0) ? 0 : 1; i < 2; i++) - { - p = s->pixel_row[0]; - s->pixel_row[0] = s->pixel_row[1]; - s->pixel_row[1] = p; - - /* If this is the end of the image just ignore that there is now rubbish in pixel_row[1]. - Mark that the end has occurred. This row will be properly output, and the next one - will fail, with the end of image condition (i.e. returning zero length) */ - if (s->resize) - { - if (image_resize_row(s, s->pixel_row[1], s->output_width*s->bytes_per_pixel) != s->output_width*s->bytes_per_pixel) - s->output_row = -1; - } - else - { - if (get_and_scrunch_row(s, s->pixel_row[1], s->output_width*s->bytes_per_pixel) != s->output_width*s->bytes_per_pixel) - s->output_row = -1; - } - } /* Apply Floyd-Steinberg dithering to the 8 bit pixels, using a bustrophodontic scan, to reduce the grayscale image to pure black and white */ /* The first and last pixels in each row need special treatment, so we do not @@ -353,6 +319,46 @@ SPAN_DECLARE(int) image_translate_row(image_translate_state_t *s, uint8_t buf[], } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE(int) image_translate_row(image_translate_state_t *s, uint8_t buf[], size_t len) +{ + int y; + int i; + uint8_t *p; + + if (s->output_row < 0) + return 0; + y = s->output_row++; + /* This algorithm works over two rows, and outputs the earlier of the two. To + make this work: + - At row 0 we grab and scrunch two rows. + - From row 1 up to the last row we grab one new additional row each time. + - At the last row we dither and output, without getting an extra row in. */ + for (i = (y == 0) ? 0 : 1; i < 2; i++) + { + p = s->pixel_row[0]; + s->pixel_row[0] = s->pixel_row[1]; + s->pixel_row[1] = p; + + /* If this is the end of the image just ignore that there is now rubbish in pixel_row[1]. + Mark that the end has occurred. This row will be properly output, and the next one + will fail, with the end of image condition (i.e. returning zero length) */ + if (s->resize) + { + if (image_resize_row(s, s->pixel_row[1], s->output_width*s->bytes_per_pixel) != s->output_width*s->bytes_per_pixel) + s->output_row = -1; + } + else + { + if (get_and_scrunch_row(s, s->pixel_row[1], s->output_width*s->bytes_per_pixel) != s->output_width*s->bytes_per_pixel) + s->output_row = -1; + } + } + if (s->output_format == T4_IMAGE_TYPE_BILEVEL) + i = floyd_steinberg_dither_row(s, buf, y); + return i; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(int) image_translate_get_output_width(image_translate_state_t *s) { return s->output_width; @@ -369,6 +375,7 @@ SPAN_DECLARE(image_translate_state_t *) image_translate_init(image_translate_sta int input_format, int input_width, int input_length, + int output_format, int output_width, int output_length, t4_row_read_handler_t row_read_handler, @@ -384,10 +391,11 @@ SPAN_DECLARE(image_translate_state_t *) image_translate_init(image_translate_sta memset(s, 0, sizeof(*s)); s->input_format = input_format; - s->input_width = input_width; s->input_length = input_length; + s->output_format = output_format; + if ((s->resize = (output_width > 0))) { s->output_width = output_width; @@ -404,16 +412,16 @@ SPAN_DECLARE(image_translate_state_t *) image_translate_init(image_translate_sta switch (s->input_format) { - case IMAGE_TRANSLATE_FROM_GRAY_8: + case T4_IMAGE_TYPE_GRAY_8BIT: s->bytes_per_pixel = 1; break; - case IMAGE_TRANSLATE_FROM_GRAY_16: + case T4_IMAGE_TYPE_GRAY_12BIT: s->bytes_per_pixel = 2; break; - case IMAGE_TRANSLATE_FROM_COLOUR_8: + case T4_IMAGE_TYPE_COLOUR_8BIT: s->bytes_per_pixel = 3; break; - case IMAGE_TRANSLATE_FROM_COLOUR_16: + case T4_IMAGE_TYPE_COLOUR_12BIT: s->bytes_per_pixel = 6; break; default: diff --git a/libs/spandsp/src/spandsp/image_translate.h b/libs/spandsp/src/spandsp/image_translate.h index 80f29f0471..31f13d2845 100644 --- a/libs/spandsp/src/spandsp/image_translate.h +++ b/libs/spandsp/src/spandsp/image_translate.h @@ -40,15 +40,6 @@ typedef struct image_translate_state_s image_translate_state_t; -enum -{ - IMAGE_TRANSLATE_FROM_MONO = 1, - IMAGE_TRANSLATE_FROM_GRAY_8 = 2, - IMAGE_TRANSLATE_FROM_GRAY_16 = 3, - IMAGE_TRANSLATE_FROM_COLOUR_8 = 4, - IMAGE_TRANSLATE_FROM_COLOUR_16 = 5 -}; - #if defined(__cplusplus) extern "C" { @@ -75,6 +66,7 @@ SPAN_DECLARE(int) image_translate_get_output_length(image_translate_state_t *s); \param input_format x \param input_width The width of the source image, in pixels. \param input_length The length of the source image, in pixels. + \param output_format x \param output_width The width of the output image, in pixels. If this is set <= 0 the image will not be resized. \param output_length The length of the output image, in pixels. If this is set to <= 0 the @@ -88,6 +80,7 @@ SPAN_DECLARE(image_translate_state_t *) image_translate_init(image_translate_sta int input_format, int input_width, int input_length, + int output_format, int output_width, int output_length, t4_row_read_handler_t row_read_handler, diff --git a/libs/spandsp/src/spandsp/private/image_translate.h b/libs/spandsp/src/spandsp/private/image_translate.h index a4f7daa81f..e473a0f644 100644 --- a/libs/spandsp/src/spandsp/private/image_translate.h +++ b/libs/spandsp/src/spandsp/private/image_translate.h @@ -33,6 +33,7 @@ struct image_translate_state_s int input_format; int input_width; int input_length; + int output_format; int output_width; int output_length; int resize; diff --git a/libs/spandsp/src/spandsp/private/t4_tx.h b/libs/spandsp/src/spandsp/private/t4_tx.h index b7b5d11eff..9f4bf463be 100644 --- a/libs/spandsp/src/spandsp/private/t4_tx.h +++ b/libs/spandsp/src/spandsp/private/t4_tx.h @@ -90,6 +90,10 @@ struct t4_tx_state_s /*! \brief The type of compression used between the FAX machines. */ int line_encoding; + int line_encoding_bilevel; + int line_encoding_gray; + int line_encoding_colour; + /*! \brief The width of the current page, in pixels. */ uint32_t image_width; /*! \brief The length of the current page, in pixels. */ @@ -140,6 +144,9 @@ struct t4_tx_state_s image_translate_state_t translator; + int apply_lab; + lab_params_t lab_params; + /* Supporting information, like resolutions, which the backend may want. */ t4_tx_metadata_t metadata; diff --git a/libs/spandsp/src/spandsp/t30.h b/libs/spandsp/src/spandsp/t30.h index 8c0edffd83..88dd94be90 100644 --- a/libs/spandsp/src/spandsp/t30.h +++ b/libs/spandsp/src/spandsp/t30.h @@ -373,7 +373,11 @@ enum /*! T.81 + T.30 Annex K colour sYCC-JPEG compression */ T30_SUPPORT_SYCC_T81_COMPRESSION = 0x200, /*! T.88 monochrome JBIG2 compression */ - T30_SUPPORT_T88_COMPRESSION = 0x400 + T30_SUPPORT_T88_COMPRESSION = 0x400, + /*! Dither a gray scale image down a simple bilevel image, with rescaling to fit a FAX page */ + T30_SUPPORT_GRAY_TO_BILEVEL = 0x40000000, + /*! Dither a colour image down a simple bilevel image, with rescaling to fit a FAX page */ + T30_SUPPORT_COLOUR_TO_BILEVEL = 0x80000000 }; enum diff --git a/libs/spandsp/src/spandsp/t30_fcf.h b/libs/spandsp/src/spandsp/t30_fcf.h index 7414497247..763627e435 100644 --- a/libs/spandsp/src/spandsp/t30_fcf.h +++ b/libs/spandsp/src/spandsp/t30_fcf.h @@ -114,6 +114,7 @@ enum /*! Information frame types used for error correction mode, in T.4 */ T4_FCD = 0x06, /*! [0110 0000] Facsimile coded data */ + T4_CCD = 0x46, /*! [0110 0010] Character coded data */ T4_RCP = 0x86 /*! [0110 0001] Return to control for partial page */ }; diff --git a/libs/spandsp/src/t30.c b/libs/spandsp/src/t30.c index ec2852ef42..cf073b9049 100644 --- a/libs/spandsp/src/t30.c +++ b/libs/spandsp/src/t30.c @@ -64,9 +64,7 @@ #include "spandsp/image_translate.h" #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" #endif @@ -82,9 +80,7 @@ #include "spandsp/private/timezone.h" #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/private/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" #endif @@ -2072,7 +2068,7 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len) s->error_correcting_mode = (s->ecm_allowed && (s->far_dis_dtc_frame[6] & DISBIT3) != 0); /* 256 octets per ECM frame */ s->octets_per_ecm_frame = 256; - /* Select the compression to use. */ + /* Now we know if we are going to use ECM, select the compression to use. */ if (!s->error_correcting_mode) { /* Without error correction our choices are very limited */ @@ -2091,7 +2087,7 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len) { #if defined(SPANDSP_SUPPORT_T42x) || defined(SPANDSP_SUPPORT_T43) /* With error correction colour may be possible/required */ - if (0) + if ((0 & (T30_SUPPORT_T43_COMPRESSION | T30_SUPPORT_T45_COMPRESSION | T30_SUPPORT_T81_COMPRESSION | T30_SUPPORT_SYCC_T81_COMPRESSION))) { s->line_encoding = T4_COMPRESSION_ITU_T85_L0; } @@ -2382,7 +2378,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len) s->image_width = widths[i][dcs_frame[5] & (DISBIT2 | DISBIT1)]; /* Check which compression the far end has decided to use. */ -#if defined(SPANDSP_SUPPORT_T42x) +#if defined(SPANDSP_SUPPORT_T42) if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE)) { s->line_encoding = T4_COMPRESSION_ITU_T42; diff --git a/libs/spandsp/src/t30_api.c b/libs/spandsp/src/t30_api.c index ad7cb0e71c..86972c0fee 100644 --- a/libs/spandsp/src/t30_api.c +++ b/libs/spandsp/src/t30_api.c @@ -64,9 +64,7 @@ #include "spandsp/image_translate.h" #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" #endif @@ -82,9 +80,7 @@ #include "spandsp/private/timezone.h" #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/private/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" #endif diff --git a/libs/spandsp/src/t30_logging.c b/libs/spandsp/src/t30_logging.c index 9328c9b8f3..8347a2615d 100644 --- a/libs/spandsp/src/t30_logging.c +++ b/libs/spandsp/src/t30_logging.c @@ -64,9 +64,7 @@ #include "spandsp/image_translate.h" #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" #endif @@ -81,9 +79,7 @@ #include "spandsp/private/timezone.h" #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/private/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" #endif @@ -410,6 +406,8 @@ SPAN_DECLARE(const char *) t30_frametype(uint8_t x) return "NULL"; case T4_FCD: return "FCD"; + case T4_CCD: + return "CCD"; case T4_RCP: return "RCP"; } diff --git a/libs/spandsp/src/t38_gateway.c b/libs/spandsp/src/t38_gateway.c index e3c99a634a..11b653face 100644 --- a/libs/spandsp/src/t38_gateway.c +++ b/libs/spandsp/src/t38_gateway.c @@ -77,9 +77,7 @@ #include "spandsp/image_translate.h" #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" #endif @@ -109,9 +107,7 @@ #include "spandsp/private/timezone.h" #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/private/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" #endif diff --git a/libs/spandsp/src/t38_terminal.c b/libs/spandsp/src/t38_terminal.c index d16e3cd569..d947d13906 100644 --- a/libs/spandsp/src/t38_terminal.c +++ b/libs/spandsp/src/t38_terminal.c @@ -67,9 +67,7 @@ #include "spandsp/image_translate.h" #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" #endif @@ -87,9 +85,7 @@ #include "spandsp/private/timezone.h" #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/private/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" #endif diff --git a/libs/spandsp/src/t4_rx.c b/libs/spandsp/src/t4_rx.c index 4e096e6371..7de952b890 100644 --- a/libs/spandsp/src/t4_rx.c +++ b/libs/spandsp/src/t4_rx.c @@ -57,9 +57,7 @@ #include "spandsp/image_translate.h" #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" #endif @@ -70,9 +68,7 @@ #include "spandsp/private/logging.h" #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/private/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" #endif diff --git a/libs/spandsp/src/t4_t6_decode.c b/libs/spandsp/src/t4_t6_decode.c index b3c96222b8..ac528a6a89 100644 --- a/libs/spandsp/src/t4_t6_decode.c +++ b/libs/spandsp/src/t4_t6_decode.c @@ -88,9 +88,7 @@ #include "spandsp/image_translate.h" #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" #endif @@ -100,9 +98,7 @@ #include "spandsp/private/logging.h" #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/private/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" #endif diff --git a/libs/spandsp/src/t4_t6_encode.c b/libs/spandsp/src/t4_t6_encode.c index 59dbd251e9..c8c0c2f5bb 100644 --- a/libs/spandsp/src/t4_t6_encode.c +++ b/libs/spandsp/src/t4_t6_encode.c @@ -85,9 +85,7 @@ #include "spandsp/image_translate.h" #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" #endif @@ -97,9 +95,7 @@ #include "spandsp/private/logging.h" #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/private/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" #endif diff --git a/libs/spandsp/src/t4_tx.c b/libs/spandsp/src/t4_tx.c index d1060f8a82..17c832ecf5 100644 --- a/libs/spandsp/src/t4_tx.c +++ b/libs/spandsp/src/t4_tx.c @@ -57,9 +57,7 @@ #include "spandsp/image_translate.h" #include "spandsp/t81_t82_arith_coding.h" #include "spandsp/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/t43.h" #endif @@ -69,9 +67,7 @@ #include "spandsp/private/logging.h" #include "spandsp/private/t81_t82_arith_coding.h" #include "spandsp/private/t85.h" -#if defined(SPANDSP_SUPPORT_T42) #include "spandsp/private/t42.h" -#endif #if defined(SPANDSP_SUPPORT_T43) #include "spandsp/private/t43.h" #endif @@ -104,6 +100,8 @@ static const TIFFFieldInfo tiff_fx_tiff_field_info[] = {TIFFTAG_IMAGELAYER, 2, 2, TIFF_LONG, FIELD_CUSTOM, FALSE, FALSE, (char *) "ImageLayer"}, }; +static void t4_tx_set_image_length(t4_tx_state_t *s, int image_length); + static TIFFExtendProc _ParentExtender = NULL; static void TIFFFXDefaultDirectory(TIFF *tif) @@ -251,31 +249,14 @@ static int get_tiff_directory_info(t4_tx_state_t *s) } } t4_tx_set_image_width(s, s->image_width); + t4_tx_set_image_length(s, s->image_length); switch (s->line_encoding) { case T4_COMPRESSION_ITU_T4_1D: case T4_COMPRESSION_ITU_T4_2D: case T4_COMPRESSION_ITU_T6: - t4_t6_encode_set_image_width(&s->encoder.t4_t6, s->image_width); t4_t6_encode_set_max_2d_rows_per_1d_row(&s->encoder.t4_t6, -s->metadata.y_resolution); break; -#if defined(SPANDSP_SUPPORT_T42) - case T4_COMPRESSION_ITU_T42: - t42_encode_set_image_width(&s->encoder.t42, s->image_width); - t42_encode_set_image_length(&s->encoder.t42, s->image_length); - break; -#endif -#if defined(SPANDSP_SUPPORT_T43) - case T4_COMPRESSION_ITU_T43: - t43_encode_set_image_width(&s->encoder.t43, s->image_width); - t43_encode_set_image_length(&s->encoder.t43, s->image_length); - break; -#endif - case T4_COMPRESSION_ITU_T85: - case T4_COMPRESSION_ITU_T85_L0: - t85_encode_set_image_width(&s->encoder.t85, s->image_width); - t85_encode_set_image_length(&s->encoder.t85, s->image_length); - break; } #if defined(SPANDSP_SUPPORT_TIFF_FX) if (TIFFGetField(t->tiff_file, TIFFTAG_PROFILETYPE, &parm32)) @@ -426,6 +407,8 @@ static int row_read(void *user_data, uint8_t buf[], size_t len) return 0; if (TIFFReadScanline(s->tiff.tiff_file, buf, s->tiff.raw_row, 0) < 0) return 0; + if (s->apply_lab) + lab_to_srgb(&s->lab_params, buf, buf, len/3); s->tiff.raw_row++; return len; } @@ -438,23 +421,12 @@ static int read_tiff_image(t4_tx_state_t *s) int i; uint8_t *t; image_translate_state_t *translator; - int mode; if (s->tiff.image_type != T4_IMAGE_TYPE_BILEVEL) { /* We need to dither this image down to pure black and white, possibly resizing it along the way. */ - if (s->tiff.image_type == T4_IMAGE_TYPE_GRAY_8BIT) - mode = IMAGE_TRANSLATE_FROM_GRAY_8; - else if (s->tiff.image_type == T4_IMAGE_TYPE_GRAY_12BIT) - mode = IMAGE_TRANSLATE_FROM_GRAY_16; - else if (s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_8BIT) - mode = IMAGE_TRANSLATE_FROM_COLOUR_8; - else if (s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_12BIT) - mode = IMAGE_TRANSLATE_FROM_COLOUR_16; - else - return -1; - if ((translator = image_translate_init(NULL, mode, s->image_width, s->image_length, 1728, -1, row_read, s)) == NULL) + if ((translator = image_translate_init(NULL, s->tiff.image_type, s->image_width, s->image_length, T4_IMAGE_TYPE_BILEVEL, 1728, -1, row_read, s)) == NULL) return -1; s->image_width = image_translate_get_output_width(translator); s->image_length = image_translate_get_output_length(translator); @@ -469,6 +441,23 @@ static int read_tiff_image(t4_tx_state_t *s) s->tiff.image_buffer = t; } s->tiff.raw_row = 0; + switch (s->tiff.photo_metric) + { + case PHOTOMETRIC_CIELAB: + /* The default luminant is D50 */ + set_lab_illuminant(&s->lab_params, 0.96422f, 1.0f, 0.82521f); + set_lab_gamut(&s->lab_params, 0, 100, -128, 127, -128, 127, TRUE); + s->apply_lab = TRUE; + break; + case PHOTOMETRIC_ITULAB: + set_lab_illuminant(&s->lab_params, 0.9638f, 1.0f, 0.8245f); + set_lab_gamut(&s->lab_params, 0, 100, -85, 85, -75, 125, FALSE); + s->apply_lab = TRUE; + break; + default: + s->apply_lab = FALSE; + break; + } total_len = 0; for (i = 0; i < s->image_length; i++) total_len += image_translate_row(translator, &s->tiff.image_buffer[total_len], s->image_width/8); @@ -782,6 +771,29 @@ SPAN_DECLARE(void) t4_tx_set_image_width(t4_tx_state_t *s, int image_width) } /*- End of function --------------------------------------------------------*/ +static void t4_tx_set_image_length(t4_tx_state_t *s, int image_length) +{ + s->image_length = image_length; + switch (s->line_encoding) + { +#if defined(SPANDSP_SUPPORT_T42) + case T4_COMPRESSION_ITU_T42: + t42_encode_set_image_length(&s->encoder.t42, image_length); + break; +#endif +#if defined(SPANDSP_SUPPORT_T43) + case T4_COMPRESSION_ITU_T43: + t43_encode_set_image_length(&s->encoder.t43, image_length); + break; +#endif + case T4_COMPRESSION_ITU_T85: + case T4_COMPRESSION_ITU_T85_L0: + t85_encode_set_image_length(&s->encoder.t85, image_length); + break; + } +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(void) t4_tx_set_max_2d_rows_per_1d_row(t4_tx_state_t *s, int max) { switch (s->line_encoding) diff --git a/libs/spandsp/tests/image_translate_tests.c b/libs/spandsp/tests/image_translate_tests.c index 8c3f55f077..b57fe3965b 100644 --- a/libs/spandsp/tests/image_translate_tests.c +++ b/libs/spandsp/tests/image_translate_tests.c @@ -213,7 +213,7 @@ static void dither_tests_gray16(void) image[i*im.width + j] = j*1200; } - s = image_translate_init(s, IMAGE_TRANSLATE_FROM_GRAY_16, im.width, im.length, -1, -1, row_read, &im); + s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, T4_IMAGE_TYPE_BILEVEL, -1, -1, row_read, &im); get_flattened_image(s, TRUE); } /*- End of function --------------------------------------------------------*/ @@ -239,7 +239,7 @@ static void dither_tests_gray8(void) for (j = 0; j < im.width; j++) image[i*im.width + j] = j*1200/256; } - s = image_translate_init(s, IMAGE_TRANSLATE_FROM_GRAY_8, im.width, im.length, -1, -1, row_read, &im); + s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_8BIT, im.width, im.length, T4_IMAGE_TYPE_BILEVEL, -1, -1, row_read, &im); get_flattened_image(s, TRUE); } /*- End of function --------------------------------------------------------*/ @@ -269,7 +269,7 @@ static void dither_tests_colour16(void) image[i*3*im.width + 3*j + 2] = j*1200; } } - s = image_translate_init(s, IMAGE_TRANSLATE_FROM_COLOUR_16, im.width, im.length, -1, -1, row_read, &im); + s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, T4_IMAGE_TYPE_BILEVEL, -1, -1, row_read, &im); get_flattened_image(s, TRUE); } /*- End of function --------------------------------------------------------*/ @@ -300,7 +300,7 @@ static void dither_tests_colour8(void) } } - s = image_translate_init(s, IMAGE_TRANSLATE_FROM_COLOUR_8, im.width, im.length, -1, -1, row_read, &im); + s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_8BIT, im.width, im.length, T4_IMAGE_TYPE_BILEVEL, -1, -1, row_read, &im); get_flattened_image(s, TRUE); } /*- End of function --------------------------------------------------------*/ @@ -331,7 +331,7 @@ static void grow_tests_colour8(void) } } - s1 = image_translate_init(s1, IMAGE_TRANSLATE_FROM_COLOUR_8, im.width, im.length, 200, -1, row_read, &im); + s1 = image_translate_init(s1, T4_IMAGE_TYPE_COLOUR_8BIT, im.width, im.length, T4_IMAGE_TYPE_BILEVEL, 200, -1, row_read, &im); get_flattened_image(s1, FALSE); } @@ -409,7 +409,7 @@ static void lenna_tests(int output_width, int output_length_scaling, const char im.current_row = 0; im.bytes_per_pixel = samples_per_pixel; - s = image_translate_init(s, IMAGE_TRANSLATE_FROM_COLOUR_8, image_width, image_length, output_width, output_length, row_read, &im); + s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_8BIT, image_width, image_length, T4_IMAGE_TYPE_BILEVEL, output_width, output_length, row_read, &im); output_width = image_translate_get_output_width(s); output_length = image_translate_get_output_length(s); diff --git a/libs/spandsp/tests/t42_tests.c b/libs/spandsp/tests/t42_tests.c index c0d494c8ce..b00dac0707 100644 --- a/libs/spandsp/tests/t42_tests.c +++ b/libs/spandsp/tests/t42_tests.c @@ -476,8 +476,8 @@ int main(int argc, char *argv[]) } TIFFSetField(tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE); TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, w); - // libtiff requires IMAGELENGTH to be set before SAMPLESPERPIXEL, - // or StripOffsets and StripByteCounts will have SAMPLESPERPIXEL values + /* libtiff requires IMAGELENGTH to be set before SAMPLESPERPIXEL, + or StripOffsets and StripByteCounts will have SAMPLESPERPIXEL values */ TIFFSetField(tif, TIFFTAG_IMAGELENGTH, h); TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_JPEG); TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);