From 88587ec03bfc423be1ea0986b846f51f99d28eda Mon Sep 17 00:00:00 2001 From: Steve Underwood Date: Sat, 1 Jun 2013 01:05:08 +0800 Subject: [PATCH] Minor tweaks from cleaning up spandsp --- libs/spandsp/configure.ac | 8 +- libs/spandsp/src/g722.c | 6 - libs/spandsp/src/spandsp/g722.h | 7 - libs/spandsp/src/t30_api.c | 15 + libs/spandsp/src/t42.c | 21 +- libs/spandsp/src/t43.c | 1 - libs/spandsp/tests/Makefile.am | 4 + libs/spandsp/tests/fax_tests.c | 34 +- libs/spandsp/tests/fax_tests.sh | 81 +- libs/spandsp/tests/image_translate_tests.c | 263 ++-- libs/spandsp/tests/t42_tests.c | 21 +- libs/spandsp/tests/t43_tests.c | 1401 ++++++++++++++++++++ libs/spandsp/tests/udptl.c | 35 +- 13 files changed, 1737 insertions(+), 160 deletions(-) create mode 100644 libs/spandsp/tests/t43_tests.c diff --git a/libs/spandsp/configure.ac b/libs/spandsp/configure.ac index 63bca1dd7f..bfdf80381e 100644 --- a/libs/spandsp/configure.ac +++ b/libs/spandsp/configure.ac @@ -257,10 +257,10 @@ then esac fi -#AC_DEFINE([SPANDSP_SUPPORT_T42], [1], [Support T.42 JPEG compression]) -SPANDSP_SUPPORT_T42="#undef SPANDSP_SUPPORT_T42" -#AC_DEFINE([SPANDSP_SUPPORT_T43], [1], [Support T.43 JBIG gray and colour compression]) -SPANDSP_SUPPORT_T43="#undef SPANDSP_SUPPORT_T43" +AC_DEFINE([SPANDSP_SUPPORT_T42], [1], [Support T.42 JPEG compression]) +SPANDSP_SUPPORT_T42="#define SPANDSP_SUPPORT_T42 1" +AC_DEFINE([SPANDSP_SUPPORT_T43], [1], [Support T.43 JBIG gray and colour compression]) +SPANDSP_SUPPORT_T43="#define SPANDSP_SUPPORT_T43 1" #AC_DEFINE([SPANDSP_SUPPORT_V32BIS], [1], [Support the V.32bis modem]) SPANDSP_SUPPORT_V32BIS="#undef SPANDSP_SUPPORT_V32BIS" #AC_DEFINE([SPANDSP_SUPPORT_V34], [1], [Support the V.34 FAX modem]) diff --git a/libs/spandsp/src/g722.c b/libs/spandsp/src/g722.c index f223592dc8..22715cfa4a 100644 --- a/libs/spandsp/src/g722.c +++ b/libs/spandsp/src/g722.c @@ -21,12 +21,6 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Based in part on a single channel G.722 codec which is: - * - * Copyright (c) CMU 1993 - * Computer Science, Speech Group - * Chengxiang Lu and Alex Hauptmann */ /*! \file */ diff --git a/libs/spandsp/src/spandsp/g722.h b/libs/spandsp/src/spandsp/g722.h index 1716e0a0db..ee36c456ca 100644 --- a/libs/spandsp/src/spandsp/g722.h +++ b/libs/spandsp/src/spandsp/g722.h @@ -21,15 +21,8 @@ * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Based on a single channel G.722 codec which is: - * - ***** Copyright (c) CMU 1993 ***** - * Computer Science, Speech Group - * Chengxiang Lu and Alex Hauptmann */ - /*! \file */ #if !defined(_SPANDSP_G722_H_) diff --git a/libs/spandsp/src/t30_api.c b/libs/spandsp/src/t30_api.c index 9f16eec141..af90452d91 100644 --- a/libs/spandsp/src/t30_api.c +++ b/libs/spandsp/src/t30_api.c @@ -690,9 +690,24 @@ SPAN_DECLARE(int) t30_set_supported_compressions(t30_state_t *s, int supported_c | T4_SUPPORT_COMPRESSION_T6 | T4_SUPPORT_COMPRESSION_T85 | T4_SUPPORT_COMPRESSION_T85_L0 +#if defined(SPANDSP_SUPPORT_T88) + | T4_SUPPORT_COMPRESSION_T88 +#endif //| T4_SUPPORT_COMPRESSION_T81 #if defined(SPANDSP_SUPPORT_T43) | T4_SUPPORT_COMPRESSION_T43 +#endif +#if defined(SPANDSP_SUPPORT_T45) + | T4_SUPPORT_COMPRESSION_T45 +#endif +#if 0 + | T4_SUPPORT_COMPRESSION_GRAYSCALE + | T4_SUPPORT_COMPRESSION_COLOUR + | T4_SUPPORT_COMPRESSION_12BIT + | T4_SUPPORT_COMPRESSION_COLOUR_TO_GRAY + | T4_SUPPORT_COMPRESSION_GRAY_TO_BILEVEL + | T4_SUPPORT_COMPRESSION_COLOUR_TO_BILEVEL + | T4_SUPPORT_COMPRESSION_RESCALING #endif | 0; s->supported_compressions = supported_compressions; diff --git a/libs/spandsp/src/t42.c b/libs/spandsp/src/t42.c index a1547a6f85..8d0023f7d7 100644 --- a/libs/spandsp/src/t42.c +++ b/libs/spandsp/src/t42.c @@ -48,7 +48,6 @@ #include "floating_fudge.h" #include #include -#include #include "spandsp/telephony.h" #include "spandsp/fast_convert.h" @@ -719,15 +718,17 @@ static void jpg_encode_error_exit(j_common_ptr cinfo) /*- End of function --------------------------------------------------------*/ /* This is the error catcher */ -#ifndef WIN32 static struct jpeg_error_mgr encode_error_handler = { +#if defined(_MSC_VER) || defined(__sunos) || defined(__solaris) || defined(__sun) + jpg_encode_error_exit, + 0, + jpg_encode_error_exit +#else .error_exit = jpg_encode_error_exit, .output_message = jpg_encode_error_exit -}; -#else -static struct jpeg_error_mgr encode_error_handler = {jpg_encode_error_exit,0,jpg_encode_error_exit}; #endif +}; static int t42_srgb_to_itulab_jpeg(t42_encode_state_t *s) { @@ -1032,15 +1033,17 @@ static void jpg_decode_error_exit(j_common_ptr cinfo) /*- End of function --------------------------------------------------------*/ /* This is the error catcher */ -#ifndef WIN32 static struct jpeg_error_mgr decode_error_handler = { +#if defined(_MSC_VER) || defined(__sunos) || defined(__solaris) || defined(__sun) + jpg_decode_error_exit, + 0, + jpg_decode_error_exit +#else .error_exit = jpg_decode_error_exit, .output_message = jpg_decode_error_exit -}; -#else -static struct jpeg_error_mgr decode_error_handler = {jpg_decode_error_exit,0,jpg_decode_error_exit}; #endif +}; static int t42_itulab_jpeg_to_srgb(t42_decode_state_t *s) { diff --git a/libs/spandsp/src/t43.c b/libs/spandsp/src/t43.c index d81e8da25c..b0e1abffb9 100644 --- a/libs/spandsp/src/t43.c +++ b/libs/spandsp/src/t43.c @@ -41,7 +41,6 @@ #endif #include #include "floating_fudge.h" -#include #include #include "spandsp/telephony.h" diff --git a/libs/spandsp/tests/Makefile.am b/libs/spandsp/tests/Makefile.am index 651c82f33c..e35408c3b7 100644 --- a/libs/spandsp/tests/Makefile.am +++ b/libs/spandsp/tests/Makefile.am @@ -112,6 +112,7 @@ noinst_PROGRAMS = ademco_contactid_tests \ t4_tests \ t4_t6_tests \ t42_tests \ + t43_tests \ t81_t82_arith_coding_tests \ t85_tests \ time_scale_tests \ @@ -325,6 +326,9 @@ t4_t6_tests_LDADD = $(LIBDIR) -lspandsp t42_tests_SOURCES = t42_tests.c t42_tests_LDADD = $(LIBDIR) -lspandsp +t43_tests_SOURCES = t43_tests.c +t43_tests_LDADD = $(LIBDIR) -lspandsp + t81_t82_arith_coding_tests_SOURCES = t81_t82_arith_coding_tests.c t81_t82_arith_coding_tests_LDADD = $(LIBDIR) -lspandsp diff --git a/libs/spandsp/tests/fax_tests.c b/libs/spandsp/tests/fax_tests.c index 49958571a9..bea71ca2db 100644 --- a/libs/spandsp/tests/fax_tests.c +++ b/libs/spandsp/tests/fax_tests.c @@ -490,6 +490,7 @@ int main(int argc, char *argv[]) int noise_level; int code_to_look_up; int scan_line_time; + int colour_enabled; t38_stats_t t38_stats; t30_stats_t t30_stats; logging_state_t *logging; @@ -528,14 +529,18 @@ int main(int argc, char *argv[]) scan_line_time = 0; decode_file_name = NULL; code_to_look_up = -1; + colour_enabled = FALSE; t38_transport = T38_TRANSPORT_UDPTL; - while ((opt = getopt(argc, argv, "c:d:D:efFgH:i:Ilm:M:n:p:s:S:tT:u:v:z:")) != -1) + while ((opt = getopt(argc, argv, "c:Cd:D:efFgH:i:Ilm:M:n:p:s:S:tT:u:v:z:")) != -1) { switch (opt) { case 'c': code_to_look_up = atoi(optarg); break; + case 'C': + colour_enabled = TRUE; + break; case 'd': decode_file_name = optarg; break; @@ -845,7 +850,7 @@ int main(int argc, char *argv[]) | T4_SUPPORT_LENGTH_US_LETTER | T4_SUPPORT_LENGTH_US_LEGAL | T4_SUPPORT_LENGTH_UNLIMITED); -#if 0 +#if 1 t30_set_supported_bilevel_resolutions(t30_state[i], T4_SUPPORT_RESOLUTION_R8_STANDARD | T4_SUPPORT_RESOLUTION_R8_FINE @@ -880,17 +885,20 @@ int main(int argc, char *argv[]) | T4_SUPPORT_RESOLUTION_600_1200 | T4_SUPPORT_RESOLUTION_1200_1200); #endif -#if 1 - t30_set_supported_colour_resolutions(t30_state[i], 0); -#else - t30_set_supported_colour_resolutions(t30_state[i], - T4_SUPPORT_RESOLUTION_100_100 - | T4_SUPPORT_RESOLUTION_200_200 - | T4_SUPPORT_RESOLUTION_300_300 - | T4_SUPPORT_RESOLUTION_400_400 - | T4_SUPPORT_RESOLUTION_600_600 - | T4_SUPPORT_RESOLUTION_1200_1200); -#endif + if (colour_enabled) + { + t30_set_supported_colour_resolutions(t30_state[i], + T4_SUPPORT_RESOLUTION_100_100 + | T4_SUPPORT_RESOLUTION_200_200 + | T4_SUPPORT_RESOLUTION_300_300 + | T4_SUPPORT_RESOLUTION_400_400 + | T4_SUPPORT_RESOLUTION_600_600 + | T4_SUPPORT_RESOLUTION_1200_1200); + } + else + { + t30_set_supported_colour_resolutions(t30_state[i], 0); + } t30_set_supported_output_compressions(t30_state[i], T4_SUPPORT_COMPRESSION_T4_2D); t30_set_ecm_capability(t30_state[i], use_ecm); t30_set_supported_compressions(t30_state[i], diff --git a/libs/spandsp/tests/fax_tests.sh b/libs/spandsp/tests/fax_tests.sh index 4e0c078c62..4d4d1bc4e5 100755 --- a/libs/spandsp/tests/fax_tests.sh +++ b/libs/spandsp/tests/fax_tests.sh @@ -17,7 +17,7 @@ run_fax_test() { - rm -f fax_tests_1.tif + rm -f fax_tests.tif echo ./fax_tests ${OPTS} -i ${FILE} ./fax_tests ${OPTS} -i ${FILE} >xyzzy 2>xyzzy2 RETVAL=$? @@ -35,12 +35,87 @@ run_fax_test() echo fax_tests failed! exit $RETVAL fi - rm -f fax_tests_1.tif + rm -f fax_tests.tif echo tested ${FILE} } -ITUTESTS_DIR=../test-data/itu/fax +run_colour_fax_test() +{ + rm -f fax_tests.tif + echo ./fax_tests ${OPTS} -i ${IN_FILE} + ./fax_tests ${OPTS} -i ${IN_FILE} >xyzzy 2>xyzzy2 + RETVAL=$? + if [ $RETVAL != 0 ] + then + echo fax_tests failed! + exit $RETVAL + fi + # Now use tiffcmp to check the results. It will return non-zero if any page images differ. The -t + # option means the normal differences in tags will be ignored. + tiffcmp -t ${OUT_FILE} fax_tests.tif >/dev/null + RETVAL=$? + if [ $RETVAL != 0 ] + then + echo fax_tests failed! + exit $RETVAL + fi + rm -f fax_tests.tif + echo tested ${IN_FILE} to ${OUT_FILE} +} +ITUTESTS_DIR=../test-data/itu/fax +TIFFFX_DIR=../test-data/itu/tiff-fx +LOCALTESTS_DIR=../test-data/local + +# Colour/gray -> bilevel by not allowing ECM +for OPTS in "-p AA" "-p TT" "-p GG" "-p TG" "-p GT" +do + IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif" + OUT_FILE="${LOCALTESTS_DIR}/lenna-colour-bilevel.tif" + run_colour_fax_test + + IN_FILE="${LOCALTESTS_DIR}/lenna-bw.tif" + OUT_FILE="${LOCALTESTS_DIR}/lenna-bw-bilevel.tif" + run_colour_fax_test + + IN_FILE="${TIFFFX_DIR}/c03x_02x.tif" + OUT_FILE="${TIFFFX_DIR}/c03x_02x.tif" + run_colour_fax_test + + IN_FILE="${TIFFFX_DIR}/l02x_02x.tif" + OUT_FILE="${TIFFFX_DIR}/l02x_02x.tif" + run_colour_fax_test + + IN_FILE="${TIFFFX_DIR}/l04x_02x.tif" + OUT_FILE="${TIFFFX_DIR}/l04x_02x.tif" + run_colour_fax_test +done + +# Colour/gray -> colour/gray by allowing ECM +for OPTS in "-p AA -C -e" "-p TT -C -e" "-p GG -C -e" "-p TG -C -e" "-p GT -C -e" +do + IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif" + OUT_FILE="${LOCALTESTS_DIR}/lenna-colour.tif" + run_colour_fax_test + + IN_FILE="${LOCALTESTS_DIR}/lenna-bw.tif" + OUT_FILE="${LOCALTESTS_DIR}/lenna-bw.tif" + run_colour_fax_test + + IN_FILE="${TIFFFX_DIR}/c03x_02x.tif" + OUT_FILE="${TIFFFX_DIR}/c03x_02x.tif" + run_colour_fax_test + + IN_FILE="${TIFFFX_DIR}/l02x_02x.tif" + OUT_FILE="${TIFFFX_DIR}/l02x_02x.tif" + run_colour_fax_test + + IN_FILE="${TIFFFX_DIR}/l04x_02x.tif" + OUT_FILE="${TIFFFX_DIR}/l04x_02x.tif" + run_colour_fax_test +done + +# Bi-level tests for OPTS in "-p AA" "-p AA -e" "-p TT" "-p TT -e" "-p GG" "-p GG -e" "-p TG" "-p TG -e" "-p GT" "-p GT -e" do FILE="${ITUTESTS_DIR}/itutests.tif" diff --git a/libs/spandsp/tests/image_translate_tests.c b/libs/spandsp/tests/image_translate_tests.c index c1afd4ebfa..51807f10c7 100644 --- a/libs/spandsp/tests/image_translate_tests.c +++ b/libs/spandsp/tests/image_translate_tests.c @@ -78,6 +78,7 @@ static void create_undithered_50_by_50(image_descriptor_t *im, uint8_t buf[], in unsigned int j; uint8_t *image8; uint16_t *image16; + int samples_per_pixel; im->image = (const uint8_t *) buf; im->width = 50; @@ -88,53 +89,99 @@ static void create_undithered_50_by_50(image_descriptor_t *im, uint8_t buf[], in switch (bytes_per_pixel) { case 1: + samples_per_pixel = 1; image8 = buf; - for (i = 0; i < 50; i++) + for (i = 0; i < im->length; i++) { - for (j = 0; j < 50; j++) - image8[50*i + j] = ((i + j)*655) >> 8; + for (j = 0; j < im->width; j++) + image8[im->width*i + j] = ((i + j)*655) >> 8; } break; case 2: + samples_per_pixel = 1; image16 = (uint16_t *) buf; - for (i = 0; i < 50; i++) + for (i = 0; i < im->length; i++) { - for (j = 0; j < 50; j++) - image16[50*i + j] = (i + j)*655; + for (j = 0; j < im->width; j++) + image16[im->width*i + j] = (i + j)*655; } break; case 3: + samples_per_pixel = 3; image8 = buf; - for (i = 0; i < 50; i++) + for (i = 0; i < im->length; i++) { - for (j = 0; j < 50; j++) + for (j = 0; j < im->width; j++) { #if 0 - image8[50*3*i + 3*j + 0] = ((i + j)*655) >> 8; - image8[50*3*i + 3*j + 1] = ((i + j)*655) >> 8; - image8[50*3*i + 3*j + 2] = ((i + j)*655) >> 8; + image8[samples_per_pixel*(im->width*i + j) + 0] = ((i + j)*655) >> 8; + image8[samples_per_pixel*(im->width*i + j) + 1] = ((i + j)*655) >> 8; + image8[samples_per_pixel*(im->width*i + j) + 2] = ((i + j)*655) >> 8; #else - image8[50*3*i + 3*j + 0] = saturateu8((((i + j)*655U)*36532U) >> 23); - image8[50*3*i + 3*j + 1] = saturateu8((((i + j)*655U)*37216U) >> 24); - image8[50*3*i + 3*j + 2] = saturateu8((((i + j)*655U)*47900U) >> 22); + image8[samples_per_pixel*(im->width*i + j) + 0] = saturateu8((((i + j)*655U)*36532U) >> 23); + image8[samples_per_pixel*(im->width*i + j) + 1] = saturateu8((((i + j)*655U)*37216U) >> 24); + image8[samples_per_pixel*(im->width*i + j) + 2] = saturateu8((((i + j)*655U)*47900U) >> 22); +#endif + } + } + break; + case 4: + samples_per_pixel = 4; + image8 = buf; + for (i = 0; i < im->length; i++) + { + for (j = 0; j < im->width; j++) + { +#if 0 + image8[samples_per_pixel*(im->width*i + j) + 0] = ((i + j)*655) >> 8; + image8[samples_per_pixel*(im->width*i + j) + 1] = ((i + j)*655) >> 8; + image8[samples_per_pixel*(im->width*i + j) + 2] = ((i + j)*655) >> 8; + image8[samples_per_pixel*(im->width*i + j) + 3] = 0; +#else + image8[samples_per_pixel*(im->width*i + j) + 0] = saturateu8((((i + j)*655U)*36532U) >> 23); + image8[samples_per_pixel*(im->width*i + j) + 1] = saturateu8((((i + j)*655U)*37216U) >> 24); + image8[samples_per_pixel*(im->width*i + j) + 2] = saturateu8((((i + j)*655U)*47900U) >> 22); + image8[samples_per_pixel*(im->width*i + j) + 3] = 0; #endif } } break; case 6: + samples_per_pixel = 3; image16 = (uint16_t *) buf; - for (i = 0; i < 50; i++) + for (i = 0; i < im->length; i++) { - for (j = 0; j < 50; j++) + for (j = 0; j < im->width; j++) { #if 0 - image16[50*3*i + 3*j + 0] = (i + j)*655; - image16[50*3*i + 3*j + 1] = (i + j)*655; - image16[50*3*i + 3*j + 2] = (i + j)*655; + image16[samples_per_pixel*(im->width*i + j) + 0] = (i + j)*655; + image16[samples_per_pixel*(im->width*i + j) + 1] = (i + j)*655; + image16[samples_per_pixel*(im->width*i + j) + 2] = (i + j)*655; #else - image16[50*3*i + 3*j + 0] = saturateu16((((i + j)*655U)*36532U) >> 15); - image16[50*3*i + 3*j + 1] = saturateu16((((i + j)*655U)*37216U) >> 16); - image16[50*3*i + 3*j + 2] = saturateu16((((i + j)*655U)*47900U) >> 14); + image16[samples_per_pixel*(im->width*i + j) + 0] = saturateu16((((i + j)*655U)*36532U) >> 15); + image16[samples_per_pixel*(im->width*i + j) + 1] = saturateu16((((i + j)*655U)*37216U) >> 16); + image16[samples_per_pixel*(im->width*i + j) + 2] = saturateu16((((i + j)*655U)*47900U) >> 14); +#endif + } + } + break; + case 8: + samples_per_pixel = 4; + image16 = (uint16_t *) buf; + for (i = 0; i < im->length; i++) + { + for (j = 0; j < im->width; j++) + { +#if 0 + image16[samples_per_pixel*(im->width*i + j) + 0] = (i + j)*655; + image16[samples_per_pixel*(im->width*i + j) + 1] = (i + j)*655; + image16[samples_per_pixel*(im->width*i + j) + 2] = (i + j)*655; + image16[samples_per_pixel*(im->width*i + j) + 3] = 0; +#else + image16[samples_per_pixel*(im->width*i + j) + 0] = saturateu16((((i + j)*655U)*36532U) >> 15); + image16[samples_per_pixel*(im->width*i + j) + 1] = saturateu16((((i + j)*655U)*37216U) >> 16); + image16[samples_per_pixel*(im->width*i + j) + 2] = saturateu16((((i + j)*655U)*47900U) >> 14); + image16[samples_per_pixel*(im->width*i + j) + 3] = 0; #endif } } @@ -232,7 +279,7 @@ static void get_bilevel_image(image_translate_state_t *s, int compare) { int i; int len; - uint8_t row_buf[5000]; + uint8_t row_buf[s->output_length*s->output_width/8]; for (i = 0; i < s->output_length; i++) { @@ -264,7 +311,7 @@ static void get_gray8_image(image_translate_state_t *s, int compare) unsigned int i; unsigned int j; int len; - uint8_t row_buf[5000]; + uint8_t row_buf[s->output_length*s->output_width]; for (i = 0; i < s->output_length; i++) { @@ -298,7 +345,7 @@ static void get_gray16_image(image_translate_state_t *s, int compare) unsigned int i; unsigned int j; int len; - uint16_t row_buf[5000]; + uint16_t row_buf[s->output_length*s->output_width]; for (i = 0; i < s->output_length; i++) { @@ -309,7 +356,7 @@ static void get_gray16_image(image_translate_state_t *s, int compare) } if (compare) { - for (j = 0; j < 50; j++) + for (j = 0; j < s->output_width; j++) { if (row_buf[j] != (i + j)*655) { @@ -331,22 +378,24 @@ static void get_colour8_image(image_translate_state_t *s, int compare) { unsigned int i; unsigned int j; + int samples_per_pixel; int len; int r; int g; int b; - uint8_t row_buf[5000]; + uint8_t row_buf[3*s->output_length*s->output_width]; + samples_per_pixel = 3; for (i = 0; i < s->output_length; i++) { - if ((len = image_translate_row(s, row_buf, 3*s->output_width)) != 3*s->output_width) + if ((len = image_translate_row(s, row_buf, samples_per_pixel*s->output_width)) != samples_per_pixel*s->output_width) { - printf("Image finished early - %d %d\n", len, 3*s->output_width); + printf("Image finished early - %d %d\n", len, samples_per_pixel*s->output_width); exit(2); } if (compare) { - for (j = 0; j < 50; j++) + for (j = 0; j < s->output_width; j++) { #if 0 r = ((i + j)*655) >> 8; @@ -357,20 +406,24 @@ static void get_colour8_image(image_translate_state_t *s, int compare) g = saturateu8((((i + j)*655U)*37216U) >> 24); b = saturateu8((((i + j)*655U)*47900U) >> 22); #endif - if (row_buf[3*j + 0] != r || row_buf[3*j + 1] != g || row_buf[3*j + 2] != b) + if (row_buf[samples_per_pixel*j + 0] != r + || + row_buf[samples_per_pixel*j + 1] != g + || + row_buf[samples_per_pixel*j + 2] != b) { printf("Image mismatch - %dx%d - (%d %d %d) (%d %d %d)\n", j, i, r, g, b, - row_buf[3*j + 0], row_buf[3*j + 1], row_buf[3*j + 2]); + row_buf[samples_per_pixel*j + 0], row_buf[samples_per_pixel*j + 1], row_buf[samples_per_pixel*j + 2]); //exit(2); } } } } - if ((len = image_translate_row(s, row_buf, 2*s->output_width)) != 0) + if ((len = image_translate_row(s, row_buf, samples_per_pixel*s->output_width)) != 0) { - printf("Image finished late - %d %d\n", len, 3*s->output_width); + printf("Image finished late - %d %d\n", len, samples_per_pixel*s->output_width); exit(2); } } @@ -380,22 +433,24 @@ static void get_colour16_image(image_translate_state_t *s, int compare) { unsigned int i; unsigned int j; + int samples_per_pixel; int len; int r; int g; int b; - uint16_t row_buf[5000]; + uint16_t row_buf[3*s->output_length*s->output_width]; + samples_per_pixel = 3; for (i = 0; i < s->output_length; i++) { - if ((len = image_translate_row(s, (uint8_t *) row_buf, 6*s->output_width)) != 6*s->output_width) + if ((len = image_translate_row(s, (uint8_t *) row_buf, 2*samples_per_pixel*s->output_width)) != 2*samples_per_pixel*s->output_width) { - printf("Image finished early - %d %d\n", len, 6*s->output_width); + printf("Image finished early - %d %d\n", len, 2*samples_per_pixel*s->output_width); exit(2); } if (compare) { - for (j = 0; j < 50; j++) + for (j = 0; j < s->output_width; j++) { #if 0 r = (i + j)*655; @@ -406,60 +461,29 @@ static void get_colour16_image(image_translate_state_t *s, int compare) g = saturateu16((((i + j)*655U)*37216U) >> 16); b = saturateu16((((i + j)*655U)*47900U) >> 14); #endif - if (row_buf[3*j + 0] != r || row_buf[3*j + 1] != g || row_buf[3*j + 2] != b) + if (row_buf[samples_per_pixel*j + 0] != r + || + row_buf[samples_per_pixel*j + 1] != g + || + row_buf[samples_per_pixel*j + 2] != b) { printf("Image mismatch - %dx%d - (%d %d %d) (%d %d %d)\n", j, i, r, g, b, - row_buf[3*j + 0], row_buf[3*j + 1], row_buf[3*j + 2]); + row_buf[samples_per_pixel*j + 0], row_buf[samples_per_pixel*j + 1], row_buf[samples_per_pixel*j + 2]); //exit(2); } } } } - if ((len = image_translate_row(s, (uint8_t *) row_buf, 6*s->output_width)) != 0) + if ((len = image_translate_row(s, (uint8_t *) row_buf, 2*samples_per_pixel*s->output_width)) != 0) { - printf("Image finished late - %d %d\n", len, 6*s->output_width); + printf("Image finished late - %d %d\n", len, 2*samples_per_pixel*s->output_width); exit(2); } } /*- End of function --------------------------------------------------------*/ -static void translate_tests_gray16(void) -{ - image_translate_state_t *s; - uint16_t image[50*50]; - image_descriptor_t im; - - printf("Dithering from a 16 bit per sample gray scale to bi-level\n"); - create_undithered_50_by_50(&im, (uint8_t *) image, 2); - s = image_translate_init(NULL, T4_IMAGE_TYPE_BILEVEL, -1, -1, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, row_read, &im); - get_bilevel_image(s, TRUE); - - printf("Scrunching from a 16 bit per sample gray scale to 8 bit per sample gray scale\n"); - create_undithered_50_by_50(&im, (uint8_t *) image, 2); - s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_8BIT, -1, -1, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, row_read, &im); - get_gray8_image(s, TRUE); - - printf("Scrunching from a 16 bit per sample gray scale to 16 bit per sample gray scale\n"); - create_undithered_50_by_50(&im, (uint8_t *) image, 2); - s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_12BIT, -1, -1, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, row_read, &im); - get_gray16_image(s, TRUE); - - printf("Scrunching from a 16 bit per sample gray scale to 3x8 bit per sample colour\n"); - create_undithered_50_by_50(&im, (uint8_t *) image, 2); - s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_8BIT, -1, -1, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, row_read, &im); - get_colour8_image(s, TRUE); - - printf("Scrunching from a 16 bit per sample gray scale to 3x16 bit per sample colour\n"); - create_undithered_50_by_50(&im, (uint8_t *) image, 2); - s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_12BIT, -1, -1, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, row_read, &im); - get_colour16_image(s, TRUE); - - image_translate_free(s); -} -/*- End of function --------------------------------------------------------*/ - static void translate_tests_gray8(void) { image_translate_state_t *s; @@ -495,35 +519,35 @@ static void translate_tests_gray8(void) } /*- End of function --------------------------------------------------------*/ -static void translate_tests_colour16(void) +static void translate_tests_gray16(void) { image_translate_state_t *s; - uint16_t image[50*50*3]; + uint16_t image[50*50]; image_descriptor_t im; - printf("Dithering from a 3x16 bit per sample colour to bi-level\n"); - create_undithered_50_by_50(&im, (uint8_t *) image, 6); - s = image_translate_init(NULL, T4_IMAGE_TYPE_BILEVEL, -1, -1, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, row_read, &im); + printf("Dithering from a 16 bit per sample gray scale to bi-level\n"); + create_undithered_50_by_50(&im, (uint8_t *) image, 2); + s = image_translate_init(NULL, T4_IMAGE_TYPE_BILEVEL, -1, -1, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, row_read, &im); get_bilevel_image(s, TRUE); - printf("Scrunching from a 3x16 bit per sample colour to 8 bit per sample gray scale\n"); - create_undithered_50_by_50(&im, (uint8_t *) image, 6); - s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_8BIT, -1, -1, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, row_read, &im); + printf("Scrunching from a 16 bit per sample gray scale to 8 bit per sample gray scale\n"); + create_undithered_50_by_50(&im, (uint8_t *) image, 2); + s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_8BIT, -1, -1, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, row_read, &im); get_gray8_image(s, TRUE); - printf("Scrunching from a 3x16 bit per sample colour to 16 bit per sample gray scale\n"); - create_undithered_50_by_50(&im, (uint8_t *) image, 6); - s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_12BIT, -1, -1, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, row_read, &im); + printf("Scrunching from a 16 bit per sample gray scale to 16 bit per sample gray scale\n"); + create_undithered_50_by_50(&im, (uint8_t *) image, 2); + s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_12BIT, -1, -1, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, row_read, &im); get_gray16_image(s, TRUE); - printf("Scrunching from a 3x16 bit per sample colour to 3x8 bit per sample colour\n"); - create_undithered_50_by_50(&im, (uint8_t *) image, 6); - s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_8BIT, -1, -1, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, row_read, &im); + printf("Scrunching from a 16 bit per sample gray scale to 3x8 bit per sample colour\n"); + create_undithered_50_by_50(&im, (uint8_t *) image, 2); + s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_8BIT, -1, -1, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, row_read, &im); get_colour8_image(s, TRUE); - printf("Scrunching from a 3x16 bit per sample colour to 3x16 bit per sample colour\n"); - create_undithered_50_by_50(&im, (uint8_t *) image, 6); - s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_12BIT, -1, -1, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, row_read, &im); + printf("Scrunching from a 16 bit per sample gray scale to 3x16 bit per sample colour\n"); + create_undithered_50_by_50(&im, (uint8_t *) image, 2); + s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_12BIT, -1, -1, T4_IMAGE_TYPE_GRAY_12BIT, im.width, im.length, row_read, &im); get_colour16_image(s, TRUE); image_translate_free(s); @@ -533,7 +557,7 @@ static void translate_tests_colour16(void) static void translate_tests_colour8(void) { image_translate_state_t *s; - uint8_t image[50*50*3]; + uint8_t image[3*50*50]; image_descriptor_t im; printf("Dithering from a 3x8 bit per sample colour to bi-level\n"); @@ -565,10 +589,45 @@ static void translate_tests_colour8(void) } /*- End of function --------------------------------------------------------*/ +static void translate_tests_colour16(void) +{ + image_translate_state_t *s; + uint16_t image[3*50*50]; + image_descriptor_t im; + + printf("Dithering from a 3x16 bit per sample colour to bi-level\n"); + create_undithered_50_by_50(&im, (uint8_t *) image, 6); + s = image_translate_init(NULL, T4_IMAGE_TYPE_BILEVEL, -1, -1, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, row_read, &im); + get_bilevel_image(s, TRUE); + + printf("Scrunching from a 3x16 bit per sample colour to 8 bit per sample gray scale\n"); + create_undithered_50_by_50(&im, (uint8_t *) image, 6); + s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_8BIT, -1, -1, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, row_read, &im); + get_gray8_image(s, TRUE); + + printf("Scrunching from a 3x16 bit per sample colour to 16 bit per sample gray scale\n"); + create_undithered_50_by_50(&im, (uint8_t *) image, 6); + s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_12BIT, -1, -1, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, row_read, &im); + get_gray16_image(s, TRUE); + + printf("Scrunching from a 3x16 bit per sample colour to 3x8 bit per sample colour\n"); + create_undithered_50_by_50(&im, (uint8_t *) image, 6); + s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_8BIT, -1, -1, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, row_read, &im); + get_colour8_image(s, TRUE); + + printf("Scrunching from a 3x16 bit per sample colour to 3x16 bit per sample colour\n"); + create_undithered_50_by_50(&im, (uint8_t *) image, 6); + s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_12BIT, -1, -1, T4_IMAGE_TYPE_COLOUR_12BIT, im.width, im.length, row_read, &im); + get_colour16_image(s, TRUE); + + image_translate_free(s); +} +/*- End of function --------------------------------------------------------*/ + static void grow_tests_colour8(void) { image_translate_state_t *s; - uint8_t image[50*50*3]; + uint8_t image[3*50*50]; image_descriptor_t im; printf("Image growth tests\n"); @@ -597,20 +656,20 @@ static void lenna_tests(int output_width, int output_length_scaling, const char int image_width; int image_length; int output_length; - uint8_t *image; - uint8_t *image2; int len; int total; - int16_t bits_per_sample; - int16_t samples_per_pixel; int i; int n; + uint8_t *image; + uint8_t *image2; + int16_t bits_per_sample; + int16_t samples_per_pixel; + uint16_t res_unit; image_translate_state_t *s; image_translate_state_t *s2; image_descriptor_t im; float x_resolution; float y_resolution; - uint16_t res_unit; if (output_length_scaling >= 0) printf("Dithering Lenna from colour to bi-level test\n"); @@ -651,7 +710,7 @@ static void lenna_tests(int output_width, int output_length_scaling, const char break; } } - printf("Image size %d %d\n", total, image_width*image_length*samples_per_pixel); + printf("Input image size %d %d\n", total, image_width*image_length*samples_per_pixel); TIFFClose(in_file); if (output_length_scaling > 0) diff --git a/libs/spandsp/tests/t42_tests.c b/libs/spandsp/tests/t42_tests.c index 712c80242b..105ce60371 100644 --- a/libs/spandsp/tests/t42_tests.c +++ b/libs/spandsp/tests/t42_tests.c @@ -157,7 +157,8 @@ int main(int argc, char *argv[]) TIFF_FX_init(); #endif - set_lab_illuminant(&lab_param, 0.9638f, 1.0f, 0.8245f); + /* The default luminant is D50 */ + set_lab_illuminant(&lab_param, 96.422f, 100.000f, 82.521f); set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, FALSE); source_file = (argc > 1) ? argv[1] : IN_FILE_NAME; @@ -218,7 +219,8 @@ int main(int argc, char *argv[]) #endif lab_params_t lab; - set_lab_illuminant(&lab, 0.9638f, 1.0f, 0.8245f); + /* The default luminant is D50 */ + set_lab_illuminant(&lab, 96.422f, 100.000f, 82.521f); set_lab_gamut(&lab, 0, 100, -85, 85, -75, 125, FALSE); lab_to_srgb(&lab, colour_map, colour_map, 256); for (i = 0; i < (1 << bits_per_pixel); i++) @@ -447,12 +449,13 @@ int main(int argc, char *argv[]) if (photometric == PHOTOMETRIC_ITULAB) { printf("YYY ITULAB\n"); - - if (!t42_itulab_to_itulab(logging, (tdata_t) &outptr, &outsize, data, off, w, h)) +#if 0 + if (!t42_itulab_to_itulab(logging, (tdata_t) &outptr, &outsize, data, off, w, h, 3)) { printf("Failed to convert to ITULAB\n"); return 1; } +#endif free(data); data = (uint8_t *) outptr; off = outsize; @@ -470,11 +473,12 @@ int main(int argc, char *argv[]) lab_to_srgb(&lab_param, data, data, w*h); break; case PHOTOMETRIC_ITULAB: - set_lab_illuminant(&lab_param, 0.9638f, 1.0f, 0.8245f); + /* The default luminant is D50 */ + set_lab_illuminant(&lab_param, 96.422f, 100.000f, 82.521f); set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, FALSE); break; } - if (!t42_srgb_to_itulab(logging, &lab_param, (tdata_t) &outptr, &outsize, data, off, w, h)) + //if (!t42_srgb_to_itulab_jpeg(logging, &lab_param, (tdata_t) &outptr, &outsize, data, off, w, h, 3)) { printf("Failed to convert to ITULAB\n"); return 1; @@ -532,7 +536,8 @@ int main(int argc, char *argv[]) bytes_per_row = (bits_per_pixel + 7)/8; bytes_per_row *= w*samples_per_pixel; totdata = h*bytes_per_row; - set_lab_illuminant(&lab_param, 0.9638f, 1.0f, 0.8245f); + /* The default luminant is D50 */ + set_lab_illuminant(&lab_param, 96.422f, 100.000f, 82.521f); set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, FALSE); #if 0 start = rdtscll(); @@ -551,7 +556,7 @@ int main(int argc, char *argv[]) #else data2 = malloc(totdata); start = rdtscll(); - if (!t42_itulab_to_srgb(logging, &lab_param, data2, &off, data, off, &w, &h)) + //if (!t42_itulab_jpeg_to_srgb(logging, &lab_param, data2, &off, data, off, &w, &h, &samples_per_pixel)) { printf("Failed to convert from ITULAB\n"); return 1; diff --git a/libs/spandsp/tests/t43_tests.c b/libs/spandsp/tests/t43_tests.c new file mode 100644 index 0000000000..e43699197b --- /dev/null +++ b/libs/spandsp/tests/t43_tests.c @@ -0,0 +1,1401 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * t43_tests.c - ITU T.43 JBIG for grey and colour FAX image processing + * + * Written by Steve Underwood + * + * Copyright (C) 2011, 2013 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/*! \file */ + +/*! \page t43_tests_page T.43 tests +\section t43_tests_page_sec_1 What does it do +*/ + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES + +#include "spandsp.h" + +#if defined(SPANDSP_SUPPORT_TIFF_FX) +#include +#endif + +#define IN_FILE_NAME "../test-data/itu/tiff-fx/l04x_02x.tif" +#define OUT_FILE_NAME "t43_tests_receive.tif" + +t43_decode_state_t t43; +t85_decode_state_t t85; + +lab_params_t lab_param; + +int write_row = 0; + +typedef struct +{ + uint8_t *buf; + int ptr; +} packer_t; + +#if defined(SPANDSP_SUPPORT_TIFF_FX) +/* TIFF-FX related extensions to the tag set supported by libtiff */ +static const TIFFFieldInfo tiff_fx_tiff_field_info[] = +{ + {TIFFTAG_INDEXED, 1, 1, TIFF_SHORT, FIELD_CUSTOM, FALSE, FALSE, (char *) "Indexed"}, + {TIFFTAG_GLOBALPARAMETERSIFD, 1, 1, TIFF_IFD8, FIELD_CUSTOM, FALSE, FALSE, (char *) "GlobalParametersIFD"}, + {TIFFTAG_PROFILETYPE, 1, 1, TIFF_LONG, FIELD_CUSTOM, FALSE, FALSE, (char *) "ProfileType"}, + {TIFFTAG_FAXPROFILE, 1, 1, TIFF_BYTE, FIELD_CUSTOM, FALSE, FALSE, (char *) "FaxProfile"}, + {TIFFTAG_CODINGMETHODS, 1, 1, TIFF_LONG, FIELD_CUSTOM, FALSE, FALSE, (char *) "CodingMethods"}, + {TIFFTAG_VERSIONYEAR, 4, 4, TIFF_BYTE, FIELD_CUSTOM, FALSE, FALSE, (char *) "VersionYear"}, + {TIFFTAG_MODENUMBER, 1, 1, TIFF_BYTE, FIELD_CUSTOM, FALSE, FALSE, (char *) "ModeNumber"}, + {TIFFTAG_DECODE, TIFF_VARIABLE, TIFF_VARIABLE, TIFF_SRATIONAL, FIELD_CUSTOM, FALSE, TRUE, (char *) "Decode"}, + {TIFFTAG_IMAGEBASECOLOR, TIFF_VARIABLE, TIFF_VARIABLE, TIFF_SHORT, FIELD_CUSTOM, FALSE, TRUE, (char *) "ImageBaseColor"}, + {TIFFTAG_T82OPTIONS, 1, 1, TIFF_LONG, FIELD_CUSTOM, FALSE, FALSE, (char *) "T82Options"}, + {TIFFTAG_STRIPROWCOUNTS, TIFF_VARIABLE, TIFF_VARIABLE, TIFF_LONG, FIELD_CUSTOM, FALSE, TRUE, (char *) "StripRowCounts"}, + {TIFFTAG_IMAGELAYER, 2, 2, TIFF_LONG, FIELD_CUSTOM, FALSE, FALSE, (char *) "ImageLayer"}, +}; + +static TIFFFieldArray tifffxFieldArray; + +static TIFFField tiff_fx_tiff_fields[] = +{ + { TIFFTAG_INDEXED, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "Indexed" }, + { TIFFTAG_GLOBALPARAMETERSIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, (char *) "GlobalParametersIFD", &tifffxFieldArray }, + { TIFFTAG_PROFILETYPE, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "ProfileType", NULL }, + { TIFFTAG_FAXPROFILE, 1, 1, TIFF_BYTE, 0, TIFF_SETGET_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "FaxProfile", NULL }, + { TIFFTAG_CODINGMETHODS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "CodingMethods", NULL }, + { TIFFTAG_VERSIONYEAR, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "VersionYear", NULL }, + { TIFFTAG_MODENUMBER, 1, 1, TIFF_BYTE, 0, TIFF_SETGET_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "ModeNumber", NULL }, + { TIFFTAG_DECODE, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, (char *) "Decode", NULL }, + { TIFFTAG_IMAGEBASECOLOR, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, (char *) "ImageBaseColor", NULL }, + { TIFFTAG_T82OPTIONS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "T82Options", NULL }, + { TIFFTAG_STRIPROWCOUNTS, -1, -1, TIFF_LONG, 0, TIFF_SETGET_C16_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, (char *) "StripRowCounts", NULL }, + { TIFFTAG_IMAGELAYER, 2, 2, TIFF_LONG, 0, TIFF_SETGET_C0_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, (char *) "ImageLayer", NULL }, +}; + +static TIFFFieldArray tiff_fx_field_array = { tfiatOther, 0, 12, tiff_fx_tiff_fields }; +#endif + +typedef struct +{ + TIFF *tif; + int pre_compressed; + uint32_t compressed_image_len; + uint32_t image_width; + uint32_t image_length; + float x_resolution; + float y_resolution; + uint16_t resolution_unit; + uint16_t bits_per_sample; + uint16_t samples_per_pixel; + uint16_t compression; + uint16_t photometric; + int16_t YCbCrSubsampleHoriz; + int16_t YCbCrSubsampleVert; + int16_t planar_config; + int32_t tile_width; + int32_t tile_length; + uint8_t *colour_map; + float lmin; + float lmax; + float amin; + float amax; + float bmin; + float bmax; +} meta_t; + +int write_file(meta_t *meta, int page, const uint8_t buf[]); +int read_file(meta_t *meta, int page); +int read_compressed_image(meta_t *meta, uint8_t **buf); +int read_decompressed_image(meta_t *meta, uint8_t **buf); + +static int row_write_handler(void *user_data, const uint8_t buf[], size_t len) +{ + packer_t *s; + + s = (packer_t *) user_data; + memcpy(&s->buf[s->ptr], buf, len); + s->ptr += len; + return 0; +} +/*- End of function --------------------------------------------------------*/ + +static int t85_comment_handler(void *user_data, const uint8_t buf[], size_t len) +{ + if (buf) + printf("Comment (%lu): %s\n", (unsigned long int) len, buf); + else + printf("Comment (%lu): ---\n", (unsigned long int) len); + return 0; +} +/*- End of function --------------------------------------------------------*/ + +static int row_read_handler(void *user_data, uint8_t row[], size_t len) +{ + packer_t *s; + + s = (packer_t *) user_data; + memcpy(row, &s->buf[s->ptr], len); + s->ptr += len; + return len; +} +/*- End of function --------------------------------------------------------*/ + +int write_file(meta_t *meta, int page, const uint8_t buf[]) +{ + TIFF *tif; + int off; + int i; + time_t now; + struct tm *tm; + char date_buf[50 + 1]; + int bytes_per_row; + t85_encode_state_t t85; + t43_encode_state_t t43; + int out_buf_len; + int out_len; + int chunk_len; + uint8_t *out_buf; + uint8_t *out_buf2; + packer_t packer; +#if defined(SPANDSP_SUPPORT_TIFF_FX) + uint64_t offset; +#endif + + tif = meta->tif; + TIFFSetField(tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE); + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, meta->image_width); + /* libtiff requires IMAGELENGTH to be set before SAMPLESPERPIXEL, + or StripOffsets and StripByteCounts will have SAMPLESPERPIXEL values */ + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, meta->image_length); + TIFFSetField(tif, TIFFTAG_COMPRESSION, meta->compression); + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, meta->bits_per_sample); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, meta->samples_per_pixel); + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, meta->image_length); + TIFFSetField(tif, TIFFTAG_XRESOLUTION, meta->x_resolution); + TIFFSetField(tif, TIFFTAG_YRESOLUTION, meta->y_resolution); + TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, meta->resolution_unit); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, meta->photometric); + if (meta->samples_per_pixel > 1 && (meta->YCbCrSubsampleHoriz || meta->YCbCrSubsampleVert)) + TIFFSetField(tif, TIFFTAG_YCBCRSUBSAMPLING, meta->YCbCrSubsampleHoriz, meta->YCbCrSubsampleVert); + TIFFSetField(tif, TIFFTAG_SOFTWARE, "spandsp"); + TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "Test"); + time(&now); + tm = localtime(&now); + sprintf(date_buf, + "%4d/%02d/%02d %02d:%02d:%02d", + tm->tm_year + 1900, + tm->tm_mon + 1, + tm->tm_mday, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + TIFFSetField(tif, TIFFTAG_DATETIME, date_buf); + TIFFSetField(tif, TIFFTAG_MAKE, "soft-switch.org"); + TIFFSetField(tif, TIFFTAG_MODEL, "spandsp"); + TIFFSetField(tif, TIFFTAG_HOSTCOMPUTER, "i7.coppice.org"); +#if defined(SPANDSP_SUPPORT_TIFF_FX) + /* Make space for this to be filled in later */ + TIFFSetField(tif, TIFFTAG_GLOBALPARAMETERSIFD, 0); +#endif + + if (meta->pre_compressed) + { + if (TIFFWriteRawStrip(tif, 0, (tdata_t) buf, meta->compressed_image_len) < 0) + printf("Error writing TIFF strip.\n"); + } + else + { + switch (meta->compression) + { + case COMPRESSION_T85: + packer.buf = (uint8_t *) buf; + packer.ptr = 0; + t85_encode_init(&t85, meta->image_width, meta->image_length, row_read_handler, &packer); + //if (meta->compression == T4_COMPRESSION_T85_L0) + // t85_encode_set_options(&t85, 256, -1, -1); + out_len = 0; + out_buf_len = 0; + out_buf = NULL; + do + { + if (out_buf_len < out_len + 50000) + { + out_buf_len += 50000; + if ((out_buf2 = realloc(out_buf, out_buf_len)) == NULL) + { + if (out_buf) + free(out_buf); + return -1; + } + out_buf = out_buf2; + } + chunk_len = t85_encode_get(&t85, &out_buf[out_len], 50000); + out_len += chunk_len; + } + while (chunk_len > 0); + if (TIFFWriteRawStrip(tif, 0, out_buf, out_len) < 0) + printf("Error writing TIFF strip.\n"); + t85_encode_release(&t85); + free(out_buf); + break; + case COMPRESSION_T43: + packer.buf = (uint8_t *) buf; + packer.ptr = 0; + t43_encode_init(&t43, meta->image_width, meta->image_length, row_read_handler, &packer); + out_len = 0; + out_buf_len = 0; + out_buf = NULL; + do + { + if (out_buf_len < out_len + 50000) + { + out_buf_len += 50000; + if ((out_buf2 = realloc(out_buf, out_buf_len)) == NULL) + { + if (out_buf) + free(out_buf); + return -1; + } + out_buf = out_buf2; + } + chunk_len = t43_encode_get(&t43, &out_buf[out_len], 50000); + out_len += chunk_len; + } + while (chunk_len > 0); + if (TIFFWriteRawStrip(tif, 0, out_buf, out_len) < 0) + printf("Error writing TIFF strip.\n"); + t43_encode_release(&t43); + free(out_buf); + break; + default: + bytes_per_row = TIFFScanlineSize(tif); + for (off = 0, i = 0; i < meta->image_length; off += bytes_per_row, i++) + { + if (TIFFWriteScanline(tif, (tdata_t) &buf[off], i, 0) < 0) + printf("Error writing TIFF scan line.\n"); + } + break; + } + } + + if (!TIFFWriteDirectory(tif)) + printf("Failed to write directory.\n"); + +#if defined(SPANDSP_SUPPORT_TIFF_FX) + if (!TIFFCreateCustomDirectory(tif, &tiff_fx_field_array)) + { + TIFFSetField(tif, TIFFTAG_PROFILETYPE, PROFILETYPE_G3_FAX); + TIFFSetField(tif, TIFFTAG_FAXPROFILE, FAXPROFILE_F); + TIFFSetField(tif, TIFFTAG_CODINGMETHODS, CODINGMETHODS_T4_1D | CODINGMETHODS_T4_2D | CODINGMETHODS_T6); + TIFFSetField(tif, TIFFTAG_VERSIONYEAR, "1998"); + TIFFSetField(tif, TIFFTAG_MODENUMBER, 3); + + offset = 0; + if (!TIFFWriteCustomDirectory(tif, &offset)) + printf("Failed to write custom directory.\n"); + + if (!TIFFSetDirectory(tif, (tdir_t) page)) + printf("Failed to set directory.\n"); + if (!TIFFSetField(tif, TIFFTAG_GLOBALPARAMETERSIFD, offset)) + printf("Failed to set global parameters IFD.\n"); + if (!TIFFWriteDirectory(tif)) + printf("Failed to write directory.\n"); + } +#endif + return 0; +} +/*- End of function --------------------------------------------------------*/ + +int read_file(meta_t *meta, int page) +{ +#if defined(SPANDSP_SUPPORT_TIFF_FX) + static const char *tiff_fx_fax_profiles[] = + { + "???", + "profile S", + "profile F", + "profile J", + "profile C", + "profile L", + "profile M" + }; + uint8_t parm8; + uint16_t parm16; + uint32_t parm32; + float *fl_parms; + char uu[10]; + char *u; + uint64_t offset; +#endif + TIFF *tif; + uint16_t *map_L; + uint16_t *map_a; + uint16_t *map_b; + uint16_t *map_z; + lab_params_t lab; + int entries; + int i; + + tif = meta->tif; + printf("Read %d\n", page); + if (!TIFFSetDirectory(tif, (tdir_t) page)) + { + printf("Unable to set TIFF directory %d!\n", page); + return -1; + } + meta->image_width = 0; + TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &meta->image_width); + meta->image_length = 0; + TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &meta->image_length); + meta->x_resolution = 200.0f; + TIFFGetField(tif, TIFFTAG_XRESOLUTION, &meta->x_resolution); + meta->y_resolution = 200.0f; + TIFFGetField(tif, TIFFTAG_YRESOLUTION, &meta->y_resolution); + meta->resolution_unit = RESUNIT_INCH; + TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &meta->resolution_unit); + meta->bits_per_sample = 0; + TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &meta->bits_per_sample); + meta->samples_per_pixel = 0; + TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &meta->samples_per_pixel); + meta->compression = 0; + TIFFGetField(tif, TIFFTAG_COMPRESSION, &meta->compression); + meta->photometric = 0; + TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &meta->photometric); + meta->YCbCrSubsampleHoriz = 0; + meta->YCbCrSubsampleVert = 0; + TIFFGetField(tif, TIFFTAG_YCBCRSUBSAMPLING, &meta->YCbCrSubsampleHoriz, &meta->YCbCrSubsampleVert); + meta->planar_config = PLANARCONFIG_CONTIG; + TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &meta->planar_config); + meta->tile_width = 0; + TIFFGetField(tif, TIFFTAG_TILEWIDTH, &meta->tile_width); + meta->tile_length = 0; + TIFFGetField(tif, TIFFTAG_TILELENGTH, &meta->tile_length); + + switch (meta->photometric) + { + case PHOTOMETRIC_ITULAB: + meta->lmin = 0.0f; + meta->lmax = 100.0f; + meta->amin = -21760.0f/255.0f; // For 12 bit -348160.0f/4095.0f + meta->amax = 21590.0f/255.0f; // For 12 bit 347990.0f/4095.0f + meta->bmin = -19200.0f/255.0f; // For 12 bit -307200.0f/4095.0f + meta->bmax = 31800.0f/255.0f; // For 12 bit 511800.0f/4095.0f + break; + default: + meta->lmin = 0.0f; + meta->lmax = 0.0f; + meta->amin = 0.0f; + meta->amax = 0.0f; + meta->bmin = 0.0f; + meta->bmax = 0.0f; + break; + } +#if defined(SPANDSP_SUPPORT_TIFF_FX) + if (TIFFGetField(tif, TIFFTAG_DECODE, &parm16, &fl_parms)) + { + meta->lmin = fl_parms[0]; + meta->lmax = fl_parms[1]; + meta->amin = fl_parms[2]; + meta->amax = fl_parms[3]; + meta->bmin = fl_parms[4]; + meta->bmax = fl_parms[5]; + printf("Got decode tag %f %f %f %f %f %f\n", meta->lmin, meta->lmax, meta->amin, meta->amax, meta->bmin, meta->bmax); + } +#endif + +#if defined(SPANDSP_SUPPORT_TIFF_FX) + printf("Trying to get global parameters\n"); + if (TIFFGetField(tif, TIFFTAG_GLOBALPARAMETERSIFD, &offset)) + { + printf("Got global parameters - %" PRIu64 "\n", offset); + if (!TIFFReadCustomDirectory(tif, offset, &tiff_fx_field_array)) + { + printf("Failed to set global parameters IFD.\n"); + } + else + { + if (TIFFGetField(tif, TIFFTAG_PROFILETYPE, &parm32)) + printf(" Profile type %u\n", parm32); + if (TIFFGetField(tif, TIFFTAG_FAXPROFILE, &parm8)) + printf(" FAX profile %s (%u)\n", tiff_fx_fax_profiles[parm8], parm8); + if (TIFFGetField(tif, TIFFTAG_CODINGMETHODS, &parm32)) + printf(" Coding methods 0x%x\n", parm32); + if (TIFFGetField(tif, TIFFTAG_VERSIONYEAR, &u)) + { + memcpy(uu, u, 4); + uu[4] = '\0'; + printf(" Version year \"%s\"\n", uu); + } + if (TIFFGetField(tif, TIFFTAG_MODENUMBER, &parm8)) + printf(" Mode number %u\n", parm8); + } + TIFFSetDirectory(tif, (tdir_t) page); + } + + if (TIFFGetField(tif, TIFFTAG_PROFILETYPE, &parm32)) + printf("Profile type %u\n", parm32); + if (TIFFGetField(tif, TIFFTAG_FAXPROFILE, &parm8)) + printf("FAX profile %s (%u)\n", tiff_fx_fax_profiles[parm8], parm8); + if (TIFFGetField(tif, TIFFTAG_CODINGMETHODS, &parm32)) + printf("Coding methods 0x%x\n", parm32); + if (TIFFGetField(tif, TIFFTAG_VERSIONYEAR, &u)) + { + memcpy(uu, u, 4); + uu[4] = '\0'; + printf("Version year \"%s\"\n", uu); + } + if (TIFFGetField(tif, TIFFTAG_MODENUMBER, &parm8)) + printf("Mode number %u\n", parm8); + if (TIFFGetField(tif, TIFFTAG_T82OPTIONS, &parm32)) + printf("T.82 options 0x%x\n", parm32); +#endif + + map_L = NULL; + map_a = NULL; + map_b = NULL; + map_z = NULL; + if (TIFFGetField(tif, TIFFTAG_COLORMAP, &map_L, &map_a, &map_b, &map_z)) + { + entries = 1 << meta->bits_per_sample; + meta->colour_map = malloc(3*entries); + if (meta->colour_map) + { +#if 0 + /* Sweep the colormap in the proper order */ + for (i = 0; i < entries; i++) + { + meta->colour_map[3*i] = (map_L[i] >> 8) & 0xFF; + meta->colour_map[3*i + 1] = (map_a[i] >> 8) & 0xFF; + meta->colour_map[3*i + 2] = (map_b[i] >> 8) & 0xFF; + printf("Map %3d - %5d %5d %5d\n", i, meta->colour_map[3*i], meta->colour_map[3*i + 1], meta->colour_map[3*i + 2]); + } +#else + /* Sweep the colormap in the order that seems to work for l04x_02x.tif */ + for (i = 0; i < entries; i++) + { + meta->colour_map[i] = (map_L[i] >> 8) & 0xFF; + meta->colour_map[256 + i] = (map_a[i] >> 8) & 0xFF; + meta->colour_map[2*256 + i] = (map_b[i] >> 8) & 0xFF; + } +#endif + /* The default luminant is D50 */ + set_lab_illuminant(&lab_param, 96.422f, 100.000f, 82.521f); + set_lab_gamut(&lab, 0, 100, -85, 85, -75, 125, FALSE); + lab_to_srgb(&lab, meta->colour_map, meta->colour_map, 256); + for (i = 0; i < entries; i++) + printf("Map %3d - %5d %5d %5d\n", i, meta->colour_map[3*i], meta->colour_map[3*i + 1], meta->colour_map[3*i + 2]); + } + } + meta->tif = tif; + return 0; +} +/*- End of function --------------------------------------------------------*/ + +int read_compressed_image(meta_t *meta, uint8_t **buf) +{ + int i; + int len; + int total_len; + int read_len; + int num_strips; + uint8_t *data; + + num_strips = TIFFNumberOfStrips(meta->tif); + for (i = 0, total_len = 0; i < num_strips; i++) + { + total_len += TIFFRawStripSize(meta->tif, i); + } + if ((data = malloc(total_len)) == NULL) + return -1; + for (i = 0, read_len = 0; i < num_strips; i++, read_len += len) + { + if ((len = TIFFReadRawStrip(meta->tif, i, &data[read_len], total_len - read_len)) < 0) + { + printf("TIFF read error.\n"); + return -1; + } + } + *buf = data; + return total_len; +} +/*- End of function --------------------------------------------------------*/ + +int read_decompressed_image(meta_t *meta, uint8_t **buf) +{ + int bytes_per_row; + tsize_t off; + int x; + int y; + int xx; + int yy; + int xxx; + int yyy; + int i; + int j; + uint32_t w; + uint32_t h; + uint16_t samples_per_pixel; + int result; + int total_raw; + int total_data; + uint8_t *raw_buf; + uint8_t *image_buf; + uint8_t *jpeg_table; + uint32_t jpeg_table_len; + t85_decode_state_t t85; + t43_decode_state_t t43; + packer_t pack; + logging_state_t *logging; + logging_state_t logging2; + + image_buf = NULL; + total_data = 0; + switch (meta->compression) + { + case COMPRESSION_T85: + bytes_per_row = (meta->image_width + 7)/8; + total_data = meta->image_length*bytes_per_row; + printf("Total decompressed data %d, %d per row\n", total_data, bytes_per_row); + + /* Read the image into memory. */ + if ((image_buf = malloc(total_data)) == NULL) + { + printf("Failed to allocated image buffer\n"); + return -1; + } + total_raw = read_compressed_image(meta, &raw_buf); + t85_decode_init(&t85, row_write_handler, &pack); + t85_decode_set_comment_handler(&t85, 1000, t85_comment_handler, NULL); + logging = t85_decode_get_logging_state(&t85); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + + pack.buf = image_buf; + pack.ptr = 0; + + result = t85_decode_put(&t85, raw_buf, total_raw); + if (result == T4_DECODE_MORE_DATA) + result = t85_decode_put(&t85, NULL, 0); + total_data = t85_decode_get_compressed_image_size(&t85); + printf("Compressed image is %d/%d bytes, %d rows\n", total_raw, total_data/8, write_row); + t85_decode_release(&t85); + free(raw_buf); + break; + case COMPRESSION_T43: + bytes_per_row = meta->samples_per_pixel*meta->image_width; + total_data = meta->image_length*bytes_per_row; + printf("Total decompressed data %d, %d per row\n", total_data, bytes_per_row); + +total_data *= 8; + /* Read the image into memory. */ + if ((image_buf = malloc(total_data)) == NULL) + printf("Failed to allocated image buffer\n"); + + total_raw = read_compressed_image(meta, &raw_buf); + t43_decode_init(&t43, row_write_handler, &pack); + t43_decode_set_comment_handler(&t43, 1000, t85_comment_handler, NULL); + logging = t43_decode_get_logging_state(&t43); + span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); + + pack.buf = image_buf; + pack.ptr = 0; + + result = t43_decode_put(&t43, raw_buf, total_raw); + if (result == T4_DECODE_MORE_DATA) + result = t43_decode_put(&t43, NULL, 0); + t43_decode_release(&t43); + free(raw_buf); + + meta->samples_per_pixel = 1; + meta->photometric = PHOTOMETRIC_RGB; + printf("Image %d x %d pixels\n", meta->image_width, meta->image_length); + break; + case COMPRESSION_JPEG: + if (meta->photometric == PHOTOMETRIC_ITULAB) + { + printf(" ITULAB"); + + span_log_init(&logging2, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW, "lab"); + bytes_per_row = TIFFScanlineSize(meta->tif); + total_data = meta->image_length*bytes_per_row; + printf("Total decompressed data %d, %d per row\n", total_data, bytes_per_row); + + /* Read the image into memory. */ + if ((image_buf = malloc(total_data)) == NULL) + printf("Failed to allocated image buffer\n"); + + jpeg_table_len = 0; +#if 0 + if (TIFFGetField(meta->tif, TIFFTAG_JPEGTABLES, &jpeg_table_len, &jpeg_table)) + { + total_image_len += (jpeg_table_len - 4); + printf("JPEG tables %u\n", jpeg_table_len); +{ +int ii; +printf("YYY1 %d - ", jpeg_table_len); +for (ii = 0; ii < jpeg_table_len; ii++) + printf(" %02x", jpeg_table[ii]); +printf("\n"); +} + } +#endif + total_raw = read_compressed_image(meta, &raw_buf); + //if (!t42_itulab_jpeg_to_srgb(&logging2, &lab_param, (tdata_t) image_buf, &off, raw_buf, total_raw, &w, &h, &samples_per_pixel)) + { + printf("Failed to convert from ITULAB.\n"); + return 1; + } + meta->photometric = PHOTOMETRIC_RGB; + +#if 0 + total_len = 0; + if (jpeg_table_len > 0) + total_len += jpeg_table_len - 4; + +printf("nstrips %d\n", nstrips); + data2 = NULL; + for (i = 0; i < nstrips; i++, total_len += len) + { + total_len = 0; + if (jpeg_table_len > 0) + total_len += jpeg_table_len - 4; + if ((len = TIFFReadRawStrip(tif, i, &data[total_len], total_image_len - total_len)) < 0) + { + printf("TIFF read error.\n"); + return -1; + } + if (jpeg_table_len > 0) + { + memcpy(data, jpeg_table, jpeg_table_len - 2); +printf("%02x %02x %02x %02x\n", data[total_len], data[total_len + 1], data[total_len + 2], data[total_len + 3]); + } + totdata = meta->image_width*3000*meta->samples_per_pixel; + data2 = realloc(data2, totdata); + off = total_len; + if (!t42_itulab_jpeg_to_srgb(&logging2, &lab_param, data2, &off, data, off, &w, &h, &samples_per_pixel)) + { + printf("Failed to convert from ITULAB.\n"); + return 1; + } + } + if (data2) + free(data2); + //exit(2); + if (jpeg_table_len > 0) + memcpy(data, jpeg_table, jpeg_table_len - 2); + + if (total_len != total_image_len) + printf("Size mismatch %d %d\n", (int) total_len, (int) total_image_len); +{ +int ii; + +printf("YYY2 %d - ", jpeg_table_len); +for (ii = 0; ii < 800; ii++) + printf(" %02x", data[ii]); +printf("\n"); +} + off = total_len; + len = total_len; +#endif + break; + } + /* Fall through */ + default: + if (meta->tile_width > 0) + { + /* The image is tiled, so we need to patch together a bunch of tiles */ + switch (meta->planar_config) + { + case PLANARCONFIG_CONTIG: + bytes_per_row = TIFFScanlineSize(meta->tif); + total_data = meta->image_length*bytes_per_row; + printf("Total decompressed data %d, %d per row\n", total_data, bytes_per_row); + + /* Read the image into memory. */ + if ((image_buf = malloc(total_data)) == NULL) + printf("Failed to allocated image buffer\n"); + + for (y = 0; y < meta->image_length; y += meta->tile_length) + { + for (x = 0; x < meta->image_width; x += meta->tile_width) + { + uint8_t data[meta->tile_width*meta->tile_length*meta->samples_per_pixel]; + + TIFFReadTile(meta->tif, data, x, y, 0, 0); + yyy = meta->tile_length; + if (y + meta->tile_length > meta->image_length) + yyy = meta->image_length - y; + xxx = meta->tile_width; + if (x + meta->tile_width > meta->image_width) + xxx = meta->image_width - x; + for (yy = 0; yy < yyy; yy++) + { + for (xx = 0; xx < xxx; xx++) + { + for (j = 0; j < meta->samples_per_pixel; j++) + image_buf[meta->samples_per_pixel*((y + yy)*meta->image_width + x + xx) + j] = data[meta->samples_per_pixel*(yy*meta->tile_width + xx) + j]; + } + } + } + } + break; + case PLANARCONFIG_SEPARATE: + bytes_per_row = TIFFScanlineSize(meta->tif); + total_data = meta->samples_per_pixel*meta->image_length*bytes_per_row; + printf("Total decompressed data %d, %d per row\n", total_data, bytes_per_row); + + /* Read the image into memory. */ + if ((image_buf = malloc(total_data)) == NULL) + printf("Failed to allocated image buffer\n"); + + for (j = 0; j < meta->samples_per_pixel; j++) + { + for (y = 0; y < meta->image_length; y += meta->tile_length) + { + for (x = 0; x < meta->image_width; x += meta->tile_width) + { + uint8_t data[meta->tile_width*meta->tile_length*meta->samples_per_pixel]; + + TIFFReadTile(meta->tif, data, x, y, 0, j); + yyy = meta->tile_length; + if (y + meta->tile_length > meta->image_length) + yyy = meta->image_length - y; + xxx = meta->tile_width; + if (x + meta->tile_width > meta->image_width) + xxx = meta->image_width - x; + for (yy = 0; yy < yyy; yy++) + { + for (xx = 0; xx < xxx; xx++) + { + image_buf[meta->samples_per_pixel*((y + yy)*meta->image_width + x + xx) + j] = data[yy*meta->tile_width + xx]; + } + } + } + } + } + break; + } + } + else + { + /* There is no tiling to worry about, but we might have planar issues to resolve */ + switch (meta->planar_config) + { + case PLANARCONFIG_CONTIG: + bytes_per_row = TIFFScanlineSize(meta->tif); + total_data = meta->image_length*bytes_per_row; + printf("Total decompressed data %d, %d per row\n", total_data, bytes_per_row); + + /* Read the image into memory. */ + if ((image_buf = malloc(total_data)) == NULL) + printf("Failed to allocated image buffer\n"); + + for (y = 0; y < meta->image_length; y++) + { + if (TIFFReadScanline(meta->tif, &image_buf[y*bytes_per_row], y, 0) < 0) + return 1; + } + break; + case PLANARCONFIG_SEPARATE: + bytes_per_row = TIFFScanlineSize(meta->tif); + total_data = meta->samples_per_pixel*meta->image_length*bytes_per_row; + printf("Total decompressed data %d, %d per row\n", total_data, bytes_per_row); + + /* Read the image into memory. */ + if ((image_buf = malloc(total_data)) == NULL) + printf("Failed to allocated image buffer\n"); + + for (j = 0; j < meta->samples_per_pixel; j++) + { + uint8_t data[bytes_per_row]; + + for (y = 0; y < meta->image_length; y++) + { + if (TIFFReadScanline(meta->tif, data, y, j) < 0) + return 1; + for (x = 0; x < meta->image_width; x++) + image_buf[meta->samples_per_pixel*(y*bytes_per_row + x) + j] = data[x]; + } + } + break; + } + } + break; + } + /* Normalise bi-level images, so they are always in PHOTOMETRIC_MINISWHITE form */ + if (image_buf && meta->samples_per_pixel == 1 && meta->bits_per_sample == 1) + { + if (meta->photometric != PHOTOMETRIC_MINISWHITE) + { + for (i = 0; i < total_data; i++) + image_buf[i] = ~image_buf[i]; + meta->photometric = PHOTOMETRIC_MINISWHITE; + } + } + + *buf = image_buf; + return total_data; +} +/*- End of function --------------------------------------------------------*/ + +int main(int argc, char *argv[]) +{ + const char *source_file; + const char *destination_file; + TIFF *tif; + tstrip_t nstrips; + uint32_t totdata; + tsize_t off; + uint8_t *data; + uint8_t *data2; + int row; + int bytes_per_row; + tsize_t outsize; + char *outptr; + int i; + int k; + int x; + int y; + uint64_t start; + uint64_t end; + logging_state_t logging2; + meta_t in_meta; + meta_t meta; + int output_compression; + int page_no; +#if defined(SPANDSP_SUPPORT_TIFF_FX) + uint64_t offset; +#endif + + source_file = (argc > 1) ? argv[1] : IN_FILE_NAME; + printf("Processing '%s'\n", source_file); + destination_file = OUT_FILE_NAME; + output_compression = (argc > 2) ? atoi(argv[2]) : COMPRESSION_CCITT_T6; + +#if defined(SPANDSP_SUPPORT_TIFF_FX) + TIFF_FX_init(); +#endif + + if ((in_meta.tif = TIFFOpen(source_file, "r")) == NULL) + { + printf("Unable to open '%s'!\n", source_file); + return 1; + } + + if ((meta.tif = TIFFOpen(destination_file, "w")) == NULL) + { + printf("Unable to open '%s'!\n", destination_file); + return 1; + } + span_log_init(&logging2, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW, "lab"); + + /* The default luminant is D50 */ + set_lab_illuminant(&lab_param, 96.422f, 100.000f, 82.521f); + set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, FALSE); + + for (page_no = 0; ; page_no++) + { + if (read_file(&in_meta, page_no) < 0) + { + printf("Failed to read from %s\n", source_file); + TIFFClose(in_meta.tif); + TIFFClose(meta.tif); + exit(2); + } + + tif = in_meta.tif; + + nstrips = TIFFNumberOfStrips(tif); + if (in_meta.compression == output_compression && nstrips == 1 && in_meta.tile_width == 0) + { + /* There might be no need to re-compress the image */ + } + else + { + /* It looks like we need to decompress and recompress the image */ + } + + printf("Width %d, height %d, bits %d, samples %d\n", in_meta.image_width, in_meta.image_length, in_meta.bits_per_sample, in_meta.samples_per_pixel); + + totdata = read_decompressed_image(&in_meta, &data); + off = totdata; + + bytes_per_row = TIFFScanlineSize(tif); + + printf("bits_per_sample %d, samples_per_pixel %d, w %d, h %d\n", in_meta.bits_per_sample, in_meta.samples_per_pixel, in_meta.image_width, in_meta.image_length); + + + printf("total %d, off %d\n", totdata, (int) off); + + switch (in_meta.samples_per_pixel) + { + case 1: + if (in_meta.bits_per_sample == 1) + { + printf("Bi-level\n"); + + /* We have finished acquiring the image. Now we need to push it out */ + meta.pre_compressed = FALSE; + meta.image_width = in_meta.image_width; + meta.image_length = in_meta.image_length; + meta.x_resolution = in_meta.x_resolution; + meta.y_resolution = in_meta.y_resolution; + meta.resolution_unit = in_meta.resolution_unit; + meta.bits_per_sample = in_meta.bits_per_sample; + meta.samples_per_pixel = in_meta.samples_per_pixel; + meta.compression = COMPRESSION_CCITT_T6; + meta.photometric = PHOTOMETRIC_MINISWHITE; + + write_file(&meta, page_no, data); + } + else + { + printf("Gray scale, %d bits\n", in_meta.bits_per_sample); + if (in_meta.bits_per_sample == 8) + { + /* Nothing needs to be done */ + } + else if (in_meta.bits_per_sample == 16) + { + if ((outptr = malloc(in_meta.image_width*in_meta.image_length)) == NULL) + printf("Failed to allocate buffer\n"); + for (i = 0; i < in_meta.image_width*in_meta.image_length; i++) + outptr[i] = data[2*i]; + free(data); + data = (uint8_t *) outptr; + } + else + { + uint32_t bitstream; + int bits; + int j; + + /* Deal with the messy cases where the number of bits is not a whole + number of bytes. */ + if ((outptr = malloc(in_meta.image_width*in_meta.image_length)) == NULL) + printf("Failed to allocate buffer\n"); + bitstream = 0; + bits = 0; + j = 0; + for (i = 0; i < in_meta.image_width*in_meta.image_length; i++) + { + while (bits < in_meta.bits_per_sample) + { + bitstream = (bitstream << 8) | data[j++]; + bits += 8; + } + outptr[i] = bitstream >> (bits - 8); + bits -= in_meta.bits_per_sample; + } + free(data); + data = (uint8_t *) outptr; + } + off = in_meta.samples_per_pixel*in_meta.image_width*in_meta.image_length; + + /* We have finished acquiring the image. Now we need to push it out */ + meta.pre_compressed = FALSE; + meta.image_width = in_meta.image_width; + meta.image_length = in_meta.image_length; + meta.x_resolution = in_meta.x_resolution; + meta.y_resolution = in_meta.y_resolution; + meta.resolution_unit = in_meta.resolution_unit; + meta.bits_per_sample = 8; + meta.samples_per_pixel = in_meta.samples_per_pixel; + meta.compression = COMPRESSION_JPEG; + meta.photometric = PHOTOMETRIC_MINISBLACK; + + write_file(&meta, page_no, data); + } + break; + case 3: + printf("Photometric is %d\n", in_meta.photometric); + + /* We now have the image in memory in RGB form */ + + if (in_meta.photometric == PHOTOMETRIC_ITULAB) + { + printf("ITU Lab\n"); + /* We are already in the ITULAB color space */ + if ((outptr = malloc(totdata)) == NULL) + printf("Failed to allocate buffer\n"); + lab_to_srgb(&lab_param, (tdata_t) outptr, data, totdata/3); + free(data); + data = (uint8_t *) outptr; + + meta.pre_compressed = FALSE; + meta.image_width = in_meta.image_width; + meta.image_length = in_meta.image_length; + meta.x_resolution = in_meta.x_resolution; + meta.y_resolution = in_meta.y_resolution; + meta.resolution_unit = in_meta.resolution_unit; + meta.bits_per_sample = 8; + meta.samples_per_pixel = in_meta.samples_per_pixel; + meta.compression = COMPRESSION_JPEG; + meta.photometric = PHOTOMETRIC_RGB; + } + else + { +#if 1 + start = rdtscll(); + switch (in_meta.photometric) + { + case PHOTOMETRIC_CIELAB: + printf("CIELAB\n"); + /* Convert this to sRGB first */ + /* The default luminant is D50 */ + set_lab_illuminant(&lab_param, 96.422f, 100.000f, 82.521f); + set_lab_gamut(&lab_param, 0, 100, -128, 127, -128, 127, TRUE); + lab_to_srgb(&lab_param, data, data, in_meta.image_width*in_meta.image_length); + break; + case PHOTOMETRIC_RGB: + printf("RGB\n"); + if (in_meta.bits_per_sample == 8) + { + } + else if (in_meta.bits_per_sample == 16) + { + printf("Pack %d to %d\n", totdata, in_meta.samples_per_pixel*in_meta.image_width*in_meta.image_length); + if ((outptr = malloc(in_meta.samples_per_pixel*in_meta.image_width*in_meta.image_length)) == NULL) + printf("Failed to allocate buffer\n"); + for (i = 0; i < in_meta.image_width*in_meta.image_length; i++) + { + outptr[in_meta.samples_per_pixel*i + 0] = (data[in_meta.samples_per_pixel*2*i + 1] << 4) | (data[in_meta.samples_per_pixel*2*i + 0] >> 4); + outptr[in_meta.samples_per_pixel*i + 1] = (data[in_meta.samples_per_pixel*2*i + 3] << 4) | (data[in_meta.samples_per_pixel*2*i + 2] >> 4); + outptr[in_meta.samples_per_pixel*i + 2] = (data[in_meta.samples_per_pixel*2*i + 5] << 4) | (data[in_meta.samples_per_pixel*2*i + 4] >> 4); + } + free(data); + data = (uint8_t *) outptr; + off = in_meta.samples_per_pixel*in_meta.image_width*in_meta.image_length; + in_meta.bits_per_sample = 8; + } + else + { + uint32_t bitstream; + int bits; + int j; + + /* Deal with the messy cases where the number of bits is not a whole number of bytes. */ + printf("Pack %d to %d\n", totdata, in_meta.samples_per_pixel*in_meta.image_width*in_meta.image_length); + if ((outptr = malloc(in_meta.samples_per_pixel*in_meta.image_width*in_meta.image_length)) == NULL) + printf("Failed to allocate buffer\n"); + bitstream = 0; + bits = 0; + j = 0; + for (i = 0; i < in_meta.image_width*in_meta.image_length; i++) + { + for (k = 0; k < in_meta.samples_per_pixel; k++) + { + while (bits < in_meta.bits_per_sample) + { + bitstream = (bitstream << 8) | data[j++]; + bits += 8; + } + outptr[in_meta.samples_per_pixel*i + k] = bitstream >> (bits - 8); + bits -= in_meta.bits_per_sample; + } + } + free(data); + data = (uint8_t *) outptr; + off = in_meta.samples_per_pixel*in_meta.image_width*in_meta.image_length; + in_meta.bits_per_sample = 8; + } + break; + } +#if 0 + /* The default luminant is D50 */ + set_lab_illuminant(&lab_param, 96.422f, 100.000f, 82.521f); + set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, FALSE); + if (!t42_srgb_to_itulab_jpeg(&logging2, &lab_param, (tdata_t) &outptr, &outsize, data, off, in_meta.image_width, in_meta.image_length, 3)) + { + printf("Failed to convert to ITULAB (B).\n"); + return 1; + } + end = rdtscll(); + printf("Duration %" PRIu64 "\n", end - start); + free(data); + data = (uint8_t *) outptr; + off = outsize; +#endif +#endif + meta.pre_compressed = FALSE; + meta.image_width = in_meta.image_width; + meta.image_length = in_meta.image_length; + meta.x_resolution = in_meta.x_resolution; + meta.y_resolution = in_meta.y_resolution; + meta.resolution_unit = in_meta.resolution_unit; + meta.bits_per_sample = 8; + meta.samples_per_pixel = in_meta.samples_per_pixel; + meta.compression = COMPRESSION_JPEG; + meta.photometric = PHOTOMETRIC_RGB; + } + write_file(&meta, page_no, data); + break; + case 4: + printf("Photometric is %d\n", in_meta.photometric); + + /* We now have the image in memory in RGB form */ + + if (in_meta.photometric == PHOTOMETRIC_ITULAB) + { + /* We are already in the ITULAB color space */ +#if 0 + if (!t42_itulab_to_itulab(&logging2, (tdata_t) &outptr, &outsize, data, off, in_meta.image_width, in_meta.image_length, 3)) + { + printf("Failed to convert to ITULAB (C).\n"); + return 1; + } +#endif + free(data); + data = (uint8_t *) outptr; + off = outsize; + } + else + { + start = rdtscll(); + switch (in_meta.photometric) + { + case PHOTOMETRIC_CIELAB: + printf("CIELAB\n"); + /* TODO: This doesn't work yet */ + /* Convert this to sRGB first */ + /* The default luminant is D50 */ + set_lab_illuminant(&lab_param, 96.422f, 100.000f, 82.521f); + set_lab_gamut(&lab_param, 0, 100, -128, 127, -128, 127, TRUE); + lab_to_srgb(&lab_param, data, data, in_meta.image_width*in_meta.image_length); + break; + case PHOTOMETRIC_SEPARATED: + for (y = 0; y < in_meta.image_length; y++) + { + for (x = 0; x < in_meta.image_width; x++) + { + k = data[(y*in_meta.image_width + x)*4 + 0] + data[(y*in_meta.image_width + x)*4 + 3]; + if (k > 255) + k = 255; + data[(y*in_meta.image_width + x)*3 + 0] = 255 - k; + k = data[(y*in_meta.image_width + x)*4 + 1] + data[(y*in_meta.image_width + x)*4 + 3]; + if (k > 255) + k = 255; + data[(y*in_meta.image_width + x)*3 + 1] = 255 - k; + k = data[(y*in_meta.image_width + x)*4 + 2] + data[(y*in_meta.image_width + x)*4 + 3]; + if (k > 255) + k = 255; + data[(y*in_meta.image_width + x)*3 + 2] = 255 - k; + } + } + off = 3*in_meta.image_width*in_meta.image_length; + in_meta.bits_per_sample = 8; + break; + } + + /* The default luminant is D50 */ + set_lab_illuminant(&lab_param, 96.422f, 100.000f, 82.521f); + set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, FALSE); + //if (!t42_srgb_to_itulab_jpeg(&logging2, &lab_param, (tdata_t) &outptr, &outsize, data, off, in_meta.image_width, in_meta.image_length, 3)) + { + printf("Failed to convert to ITULAB (D).\n"); + return 1; + } + end = rdtscll(); + printf("Duration %" PRIu64 "\n", end - start); + off = outsize; + in_meta.bits_per_sample = 8; + } + meta.pre_compressed = FALSE; + meta.image_width = in_meta.image_width; + meta.image_length = in_meta.image_length; + meta.x_resolution = in_meta.x_resolution; + meta.y_resolution = in_meta.y_resolution; + meta.resolution_unit = in_meta.resolution_unit; + meta.bits_per_sample = 8; + meta.samples_per_pixel = 3; + meta.compression = COMPRESSION_JPEG; + meta.photometric = PHOTOMETRIC_RGB; + + write_file(&meta, page_no, data); + break; + } + } + + + + printf("XXX - image is %d by %d, %d bytes\n", in_meta.image_width, in_meta.image_length, (int) off); + + /* We now have the image in memory in ITULAB form */ + + meta.pre_compressed = FALSE; + meta.compressed_image_len = off; + meta.image_width = in_meta.image_width; + meta.image_length = in_meta.image_length; + meta.x_resolution = in_meta.x_resolution; + meta.y_resolution = in_meta.y_resolution; + meta.resolution_unit = in_meta.resolution_unit; + meta.bits_per_sample = 8; + meta.samples_per_pixel = 3; + meta.compression = COMPRESSION_JPEG; +#if 1 + meta.photometric = PHOTOMETRIC_RGB; +#elif 1 + /* Most image processors won't know what to do with the ITULAB colorspace. + So we'll be converting it to RGB for portability. */ + /* If PHOTOMETRIC_ITULAB is not available the admin cannot enable color fax anyway. + This is done so that older libtiffs without it can build fine. */ + meta.photometric = PHOTOMETRIC_ITULAB; +#else + meta.photometric = PHOTOMETRIC_YCBCR; +#endif + meta.YCbCrSubsampleHoriz = in_meta.YCbCrSubsampleHoriz; + meta.YCbCrSubsampleVert = in_meta.YCbCrSubsampleVert; + + if ((tif = TIFFOpen(destination_file, "w")) == NULL) + { + printf("Unable to open '%s'!\n", destination_file); + return 1; + } + TIFFSetField(tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE); + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, meta.image_width); + /* libtiff requires IMAGELENGTH to be set before SAMPLESPERPIXEL, + or StripOffsets and StripByteCounts will have SAMPLESPERPIXEL values */ + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, meta.image_length); + TIFFSetField(tif, TIFFTAG_COMPRESSION, meta.compression); + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, meta.bits_per_sample); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, meta.samples_per_pixel); + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, meta.image_length); + TIFFSetField(tif, TIFFTAG_XRESOLUTION, meta.x_resolution); + TIFFSetField(tif, TIFFTAG_YRESOLUTION, meta.y_resolution); + TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, meta.resolution_unit); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, meta.photometric); + if (meta.samples_per_pixel > 1 && (meta.YCbCrSubsampleHoriz || meta.YCbCrSubsampleVert)) + TIFFSetField(tif, TIFFTAG_YCBCRSUBSAMPLING, meta.YCbCrSubsampleHoriz, meta.YCbCrSubsampleVert); + TIFFSetField(tif, TIFFTAG_SOFTWARE, "spandsp"); + TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "Test"); + TIFFSetField(tif, TIFFTAG_DATETIME, "2011/02/03 12:30:45"); + TIFFSetField(tif, TIFFTAG_MAKE, "soft-switch.org"); + TIFFSetField(tif, TIFFTAG_MODEL, "spandsp"); + TIFFSetField(tif, TIFFTAG_HOSTCOMPUTER, "i7.coppice.org"); +#if defined(SPANDSP_SUPPORT_TIFF_FX) + /* Make space for this to be filled in later */ + TIFFSetField(tif, TIFFTAG_GLOBALPARAMETERSIFD, 0); +#endif + + if (meta.pre_compressed) + { + if (TIFFWriteRawStrip(tif, 0, (tdata_t) data, meta.compressed_image_len) == -1) + { + printf("Write error to TIFF file\n"); + return 1; + } + free(data); + } + else + { + if (in_meta.samples_per_pixel > 1) + { + bytes_per_row = ((meta.bits_per_sample + 7)/8)*meta.image_width*meta.samples_per_pixel; + totdata = meta.image_length*bytes_per_row; + /* The default luminant is D50 */ + set_lab_illuminant(&lab_param, 96.422f, 100.000f, 82.521f); + set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, FALSE); +#if 0 + start = rdtscll(); + data2 = NULL; + totdata = 0; + if (!t42_itulab_to_JPEG(&logging2, &lab_param, (void **) &data2, &totdata, data, off)) + { + printf("Failed to convert from ITULAB (A).\n"); + return 1; + } + end = rdtscll(); + printf("Duration %" PRIu64 "\n", end - start); + printf("Compressed length %d (%p)\n", totdata, data2); + if (TIFFWriteRawStrip(tif, 0, data2, totdata) < 0) + { + printf("Failed to convert from ITULAB (B).\n"); + return 1; + } + free(data); + data = data2; +#elif 1 + data2 = malloc(totdata); + start = rdtscll(); + //if (!t42_itulab_jpeg_to_srgb(&logging2, &lab_param, data2, &off, data, off, &meta.image_width, &meta.image_length, &meta.samples_per_pixel)) + { + printf("Failed to convert from ITULAB.\n"); + return 1; + } + end = rdtscll(); + printf("Duration %" PRIu64 "\n", end - start); + free(data); + data = data2; +#endif + } + off = 0; + bytes_per_row = ((meta.bits_per_sample + 7)/8)*meta.image_width*meta.samples_per_pixel; + for (row = 0; row < meta.image_length; row++) + { + if (TIFFWriteScanline(tif, &data[off], row, 0) < 0) + return 1; + off += bytes_per_row; + } + free(data); + } + + if (!TIFFWriteDirectory(tif)) + printf("Failed to write directory.\n"); + +#if defined(SPANDSP_SUPPORT_TIFF_FX) + if (!TIFFCreateCustomDirectory(tif, &tiff_fx_field_array)) + { + TIFFSetField(tif, TIFFTAG_PROFILETYPE, PROFILETYPE_G3_FAX); + TIFFSetField(tif, TIFFTAG_FAXPROFILE, FAXPROFILE_F); + TIFFSetField(tif, TIFFTAG_CODINGMETHODS, CODINGMETHODS_T4_1D | CODINGMETHODS_T4_2D | CODINGMETHODS_T6); + TIFFSetField(tif, TIFFTAG_VERSIONYEAR, "1998"); + TIFFSetField(tif, TIFFTAG_MODENUMBER, 3); + + offset = 0; + if (!TIFFWriteCustomDirectory(tif, &offset)) + printf("Failed to write custom directory.\n"); + + if (!TIFFSetDirectory(tif, (tdir_t) page_no)) + printf("Failed to set directory.\n"); + if (!TIFFSetField(tif, TIFFTAG_GLOBALPARAMETERSIFD, offset)) + printf("Failed to set global parameters IFD.\n"); + if (!TIFFWriteDirectory(tif)) + printf("Failed to write directory.\n"); + } +#endif + TIFFClose(tif); + printf("Done!\n"); + return 0; +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/ diff --git a/libs/spandsp/tests/udptl.c b/libs/spandsp/tests/udptl.c index 96f2c25162..c153a6c803 100644 --- a/libs/spandsp/tests/udptl.c +++ b/libs/spandsp/tests/udptl.c @@ -37,8 +37,12 @@ #include "udptl.h" +#if !defined(FALSE) #define FALSE 0 +#endif +#if !defined(TRUE) #define TRUE (!FALSE) +#endif static int decode_length(const uint8_t *buf, int limit, int *len, int *pvalue) { @@ -58,7 +62,7 @@ static int decode_length(const uint8_t *buf, int limit, int *len, int *pvalue) return 0; } *pvalue = (buf[(*len)++] & 0x3F) << 14; - /* Indicate we have a fragment */ + /* Indicate that we have a fragment */ return 1; } /*- End of function --------------------------------------------------------*/ @@ -66,11 +70,13 @@ static int decode_length(const uint8_t *buf, int limit, int *len, int *pvalue) static int decode_open_type(const uint8_t *buf, int limit, int *len, const uint8_t **p_object, int *p_num_octets) { int octet_cnt; +#if 0 int octet_idx; int stat; const uint8_t **pbuf; - for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt) + *p_num_octets = 0; + for (octet_idx = 0; ; octet_idx += octet_cnt) { if ((stat = decode_length(buf, limit, len, &octet_cnt)) < 0) return -1; @@ -89,6 +95,21 @@ static int decode_open_type(const uint8_t *buf, int limit, int *len, const uint8 if (stat == 0) break; } +#else + /* We do not deal with fragments, so there is no point in looping through them. Just say that something + fragmented is bad. */ + if (decode_length(buf, limit, len, &octet_cnt) != 0) + return -1; + *p_num_octets = octet_cnt; + if (octet_cnt > 0) + { + /* Make sure the buffer contains at least the number of bits requested */ + if ((*len + octet_cnt) > limit) + return -1; + *p_object = &buf[*len]; + *len += octet_cnt; + } +#endif return 0; } /*- End of function --------------------------------------------------------*/ @@ -153,7 +174,6 @@ static int encode_open_type(uint8_t *buf, int *len, const uint8_t *data, int num int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len) { int stat; - int stat2; int i; int j; int k; @@ -216,16 +236,16 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len) total_count = 0; do { - if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0) + if ((stat = decode_length(buf, len, &ptr, &count)) < 0) return -1; for (i = 0; i < count; i++) { - if ((stat = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0) + if (decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i]) != 0) return -1; } total_count += count; } - while (stat2 > 0); + while (stat > 0); /* We should now be exactly at the end of the packet. If not, this is a fault. */ if (ptr != len) return -1; @@ -246,7 +266,8 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len) /* Save the new packet. Redundancy mode won't use this, but some systems will switch into FEC mode after sending some redundant packets, and this may then be important. */ x = (seq_no - i) & UDPTL_BUF_MASK; - memcpy(s->rx[x].buf, bufs[i - 1], lengths[i - 1]); + if (lengths[i - 1] > 0) + memcpy(s->rx[x].buf, bufs[i - 1], lengths[i - 1]); s->rx[x].buf_len = lengths[i - 1]; s->rx[x].fec_len[0] = 0; s->rx[x].fec_span = 0;