提交 88587ec0 authored 作者: Steve Underwood's avatar Steve Underwood

Minor tweaks from cleaning up spandsp

上级 a55d70ed
......@@ -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])
......
......@@ -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 */
......
......@@ -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_)
......
......@@ -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;
......
......@@ -48,7 +48,6 @@
#include "floating_fudge.h"
#include <tiffio.h>
#include <assert.h>
#include <jpeglib.h>
#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)
{
......
......@@ -41,7 +41,6 @@
#endif
#include <time.h>
#include "floating_fudge.h"
#include <jpeglib.h>
#include <setjmp.h>
#include "spandsp/telephony.h"
......
......@@ -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
......
......@@ -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,9 +885,8 @@ 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
if (colour_enabled)
{
t30_set_supported_colour_resolutions(t30_state[i],
T4_SUPPORT_RESOLUTION_100_100
| T4_SUPPORT_RESOLUTION_200_200
......@@ -890,7 +894,11 @@ int main(int argc, char *argv[])
| T4_SUPPORT_RESOLUTION_400_400
| T4_SUPPORT_RESOLUTION_600_600
| T4_SUPPORT_RESOLUTION_1200_1200);
#endif
}
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],
......
......@@ -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}
}
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"
......
......@@ -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[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[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[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;
image8[samples_per_pixel*(im->width*i + j) + 3] = 0;
#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);
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)
......
......@@ -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;
......
/*
* 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 <steveu@coppice.org>
*
* 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 <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <memory.h>
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
#include "spandsp.h"
#if defined(SPANDSP_SUPPORT_TIFF_FX)
#include <tif_dir.h>
#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 ------------------------------------------------------------*/
......@@ -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,6 +266,7 @@ 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;
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;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论