Tweaks to the spandsp alloc functions, and a fix for bi-level image row
squashing.
This commit is contained in:
parent
8f0dbcaaf8
commit
2ed8e04776
|
@ -50,21 +50,25 @@
|
|||
#include "spandsp/telephony.h"
|
||||
#include "spandsp/alloc.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4232) /* address of dllimport is not static, identity not guaranteed */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ALIGNED_ALLOC)
|
||||
static span_aligned_alloc_t __span_aligned_alloc = aligned_alloc;
|
||||
static span_aligned_free_t __span_aligned_free = free;
|
||||
#elif defined(HAVE_MEMALIGN)
|
||||
static span_aligned_alloc_t __span_aligned_alloc = memalign;
|
||||
#elif defined(HAVE_POSIX_MEMALIGN)
|
||||
static void *fake_posix_memalign(size_t alignment, size_t size);
|
||||
static span_aligned_alloc_t __span_aligned_alloc = fake_posix_memalign;
|
||||
static span_aligned_free_t __span_aligned_free = free;
|
||||
#elif defined(__MSVC__)
|
||||
static void *fake_aligned_alloc(size_t alignment, size_t size);
|
||||
static span_aligned_alloc_t __span_aligned_alloc = fake_aligned_alloc;
|
||||
static span_aligned_free_t __span_aligned_free = _aligned_free;
|
||||
#else
|
||||
static void *fake_aligned_alloc(size_t alignment, size_t size);
|
||||
static span_aligned_alloc_t __span_aligned_alloc = fake_aligned_alloc;
|
||||
static span_aligned_free_t __span_aligned_free = free;
|
||||
#endif
|
||||
static span_alloc_t __span_alloc = malloc;
|
||||
static span_realloc_t __span_realloc = realloc;
|
||||
|
@ -76,12 +80,19 @@ static span_free_t __span_free = free;
|
|||
|
||||
#if defined(HAVE_ALIGNED_ALLOC)
|
||||
#elif defined(HAVE_MEMALIGN)
|
||||
#elif defined(__MSVC__)
|
||||
static void *fake_aligned_alloc(size_t alignment, size_t size)
|
||||
{
|
||||
/* Make Microsoft's _aligned_malloc() look like the C11 aligned_alloc */
|
||||
return _aligned_malloc(size, alignment);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
#elif defined(HAVE_POSIX_MEMALIGN)
|
||||
static void *fake_posix_memalign(size_t alignment, size_t size)
|
||||
static void *fake_aligned_alloc(size_t alignment, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
/* Make posix_memalign look like the more modern aligned_alloc */
|
||||
/* Make posix_memalign() look like the C11 aligned_alloc */
|
||||
posix_memalign(&ptr, alignment, size);
|
||||
return ptr;
|
||||
}
|
||||
|
@ -94,12 +105,6 @@ static void *fake_aligned_alloc(size_t alignment, size_t size)
|
|||
/*- End of function --------------------------------------------------------*/
|
||||
#endif
|
||||
|
||||
SPAN_DECLARE(void *) span_aligned_alloc(size_t alignment, size_t size)
|
||||
{
|
||||
return __span_aligned_alloc(alignment, size);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(void *) span_alloc(size_t size)
|
||||
{
|
||||
return __span_alloc(size);
|
||||
|
@ -118,11 +123,28 @@ SPAN_DECLARE(void) span_free(void *ptr)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) span_mem_allocators(span_aligned_alloc_t custom_aligned_alloc,
|
||||
span_alloc_t custom_alloc,
|
||||
span_realloc_t custom_realloc,
|
||||
span_free_t custom_free)
|
||||
SPAN_DECLARE(void *) span_aligned_alloc(size_t alignment, size_t size)
|
||||
{
|
||||
return __span_aligned_alloc(alignment, size);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(void) span_aligned_free(void *ptr)
|
||||
{
|
||||
__span_aligned_free(ptr);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) span_mem_allocators(span_alloc_t custom_alloc,
|
||||
span_realloc_t custom_realloc,
|
||||
span_free_t custom_free,
|
||||
span_aligned_alloc_t custom_aligned_alloc,
|
||||
span_aligned_free_t custom_aligned_free)
|
||||
{
|
||||
__span_alloc = (custom_alloc) ? custom_alloc : malloc;
|
||||
__span_realloc = (custom_realloc) ? custom_realloc : realloc;
|
||||
__span_free = (custom_free) ? custom_free : free;
|
||||
|
||||
__span_aligned_alloc = (custom_aligned_alloc)
|
||||
?
|
||||
custom_aligned_alloc
|
||||
|
@ -131,14 +153,18 @@ SPAN_DECLARE(int) span_mem_allocators(span_aligned_alloc_t custom_aligned_alloc,
|
|||
aligned_alloc;
|
||||
#elif defined(HAVE_MEMALIGN)
|
||||
memalign;
|
||||
#elif defined(HAVE_POSIX_MEMALIGN)
|
||||
fake_posix_memalign;
|
||||
#else
|
||||
fake_aligned_alloc;
|
||||
#endif
|
||||
__span_alloc = (custom_alloc) ? custom_alloc : malloc;
|
||||
__span_realloc = (custom_realloc) ? custom_realloc : realloc;
|
||||
__span_free = (custom_free) ? custom_free : free;
|
||||
__span_aligned_free = (custom_aligned_free)
|
||||
?
|
||||
custom_aligned_free
|
||||
:
|
||||
#if defined(__MSVC__)
|
||||
_aligned_free;
|
||||
#else
|
||||
free;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
|
|
@ -28,7 +28,17 @@
|
|||
#if !defined(_SPANDSP_ALLOC_H_)
|
||||
#define _SPANDSP_ALLOC_H_
|
||||
|
||||
/* Notes:
|
||||
- Most platforms don't have an aligned realloc function, so we don't try to
|
||||
support an aligned realloc on any platform.
|
||||
- Some platforms use a special free function for memory which was allocated
|
||||
by alligned allocation functions. We use a separate aligned_free function
|
||||
on all platforms, for compatibility, even though it may simply reduce to
|
||||
free().
|
||||
*/
|
||||
|
||||
typedef void *(*span_aligned_alloc_t)(size_t alignment, size_t size);
|
||||
typedef void (*span_aligned_free_t)(void *ptr);
|
||||
typedef void *(*span_alloc_t)(size_t size);
|
||||
typedef void *(*span_realloc_t)(void *ptr, size_t size);
|
||||
typedef void (*span_free_t)(void *ptr);
|
||||
|
@ -41,20 +51,24 @@ extern "C"
|
|||
/* Allocate size bytes allocated to ALIGNMENT bytes. */
|
||||
SPAN_DECLARE(void *) span_aligned_alloc(size_t alignment, size_t size);
|
||||
|
||||
/* Free a block allocated by span_aligned_alloc, or span_aligned_realloc. */
|
||||
SPAN_DECLARE(void) span_aligned_free(void *ptr);
|
||||
|
||||
/* Allocate size bytes of memory. */
|
||||
SPAN_DECLARE(void *) span_alloc(size_t size);
|
||||
|
||||
/* Re-allocate the previously allocated block in ptr, making the new block size bytes long. */
|
||||
SPAN_DECLARE(void *) span_realloc(void *ptr, size_t size);
|
||||
|
||||
/* Free a block allocated by span_alloc, span_aligned_alloc, or span_realloc. */
|
||||
/* Free a block allocated by span_alloc or span_realloc. */
|
||||
SPAN_DECLARE(void) span_free(void *ptr);
|
||||
|
||||
SPAN_DECLARE(int) span_mem_allocators(span_aligned_alloc_t custom_aligned_alloc,
|
||||
span_alloc_t custom_alloc,
|
||||
SPAN_DECLARE(int) span_mem_allocators(span_alloc_t custom_alloc,
|
||||
span_realloc_t custom_realloc,
|
||||
span_free_t custom_free);
|
||||
|
||||
span_free_t custom_free,
|
||||
span_aligned_alloc_t custom_aligned_alloc,
|
||||
span_aligned_free_t custom_aligned_free);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -91,6 +91,13 @@ typedef struct
|
|||
const char *dcs;
|
||||
} t4_rx_metadata_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *buf;
|
||||
int buf_len;
|
||||
int buf_ptr;
|
||||
} no_decoder_state_t;
|
||||
|
||||
/*!
|
||||
T.4 FAX decompression descriptor. This defines the working state
|
||||
for a single instance of a T.4 FAX decompression channel.
|
||||
|
@ -114,6 +121,7 @@ struct t4_rx_state_s
|
|||
|
||||
union
|
||||
{
|
||||
no_decoder_state_t no_decoder;
|
||||
t4_t6_decode_state_t t4_t6;
|
||||
t85_decode_state_t t85;
|
||||
#if defined(SPANDSP_SUPPORT_T88)
|
||||
|
@ -132,11 +140,6 @@ struct t4_rx_state_s
|
|||
|
||||
int current_decoder;
|
||||
|
||||
uint8_t *pre_encoded_buf;
|
||||
int pre_encoded_len;
|
||||
int pre_encoded_ptr;
|
||||
int pre_encoded_bit;
|
||||
|
||||
/* Supporting information, like resolutions, which the backend may want. */
|
||||
t4_rx_metadata_t metadata;
|
||||
|
||||
|
|
|
@ -100,6 +100,14 @@ typedef struct
|
|||
int resolution_code;
|
||||
} t4_tx_metadata_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *buf;
|
||||
int buf_len;
|
||||
int buf_ptr;
|
||||
int bit;
|
||||
} no_encoder_state_t;
|
||||
|
||||
/*!
|
||||
T.4 FAX compression descriptor. This defines the working state
|
||||
for a single instance of a T.4 FAX compression channel.
|
||||
|
@ -149,6 +157,7 @@ struct t4_tx_state_s
|
|||
|
||||
union
|
||||
{
|
||||
no_encoder_state_t no_encoder;
|
||||
t4_t6_encode_state_t t4_t6;
|
||||
t85_encode_state_t t85;
|
||||
#if defined(SPANDSP_SUPPORT_T88)
|
||||
|
@ -176,10 +185,7 @@ struct t4_tx_state_s
|
|||
int pack_row;
|
||||
int pack_bit_mask;
|
||||
|
||||
uint8_t *pre_encoded_buf;
|
||||
int pre_encoded_len;
|
||||
int pre_encoded_ptr;
|
||||
int pre_encoded_bit;
|
||||
no_encoder_state_t no_encoder;
|
||||
|
||||
/*! \brief Supporting information, like resolutions, which the backend may want. */
|
||||
t4_tx_metadata_t metadata;
|
||||
|
|
|
@ -76,6 +76,8 @@ SPAN_DECLARE(void) set_lab_gamut2(lab_params_t *s, int L_P, int L_Q, int a_P, in
|
|||
|
||||
SPAN_DECLARE(void) get_lab_gamut2(lab_params_t *s, int *L_P, int *L_Q, int *a_P, int *a_Q, int *b_P, int *b_Q);
|
||||
|
||||
SPAN_DECLARE(bool) t42_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len);
|
||||
|
||||
SPAN_DECLARE(void) t42_encode_set_options(t42_encode_state_t *s, uint32_t l0, int quality, int options);
|
||||
|
||||
SPAN_DECLARE(int) t42_encode_set_image_width(t42_encode_state_t *s, uint32_t image_width);
|
||||
|
|
|
@ -64,6 +64,8 @@ extern "C"
|
|||
{
|
||||
#endif
|
||||
|
||||
SPAN_DECLARE(bool) t85_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len);
|
||||
|
||||
/*! \brief Check if we are at the end of the current document page.
|
||||
\param s The T.85 context.
|
||||
\return 0 for more data to come. SIG_STATUS_END_OF_DATA for no more data. */
|
||||
|
|
|
@ -1505,8 +1505,6 @@ static int build_dcs(t30_state_t *s)
|
|||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
|
||||
if (image_type == T4_IMAGE_TYPE_GRAY_12BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
|
||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT);
|
||||
//if (???????? & T4_COMPRESSION_NO_SUBSAMPLING))
|
||||
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING);
|
||||
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1);
|
||||
use_bilevel = false;
|
||||
break;
|
||||
|
@ -1789,17 +1787,13 @@ static int analyze_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
|
|||
}
|
||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE))
|
||||
{
|
||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED))
|
||||
s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_200_400;
|
||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED))
|
||||
s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_R8_SUPERFINE;
|
||||
s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_200_400;
|
||||
s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_R8_SUPERFINE;
|
||||
}
|
||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE))
|
||||
{
|
||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED))
|
||||
s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_200_200;
|
||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED))
|
||||
s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_R8_FINE;
|
||||
s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_200_200;
|
||||
s->mutual_bilevel_resolutions &= ~T4_RESOLUTION_R8_FINE;
|
||||
s->mutual_colour_resolutions &= ~T4_RESOLUTION_200_200;
|
||||
}
|
||||
else
|
||||
|
@ -6706,8 +6700,8 @@ SPAN_DECLARE(t30_state_t *) t30_init(t30_state_t *s,
|
|||
| T4_SUPPORT_LENGTH_A4
|
||||
| T4_SUPPORT_LENGTH_B4
|
||||
| T4_SUPPORT_LENGTH_UNLIMITED;
|
||||
/* Set the output encoding to something safe. For bi-level images ost things get
|
||||
1D and 2D encoding right. Quite a lot get other things wrong. */
|
||||
/* Set the output encoding to something safe. For bi-level images most things
|
||||
get 1D and 2D encoding right. Quite a lot get other things wrong. */
|
||||
s->supported_output_compressions = T4_COMPRESSION_T4_2D | T4_COMPRESSION_JPEG;
|
||||
s->local_min_scan_time_code = T30_MIN_SCAN_0MS;
|
||||
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
#include "spandsp/private/t85.h"
|
||||
#include "spandsp/private/t42.h"
|
||||
|
||||
/* The open_memstream() and fmemopen() in older versions of glibc seems quirky */
|
||||
/* The open_memstream() and fmemopen() in older versions of glibc seem quirky */
|
||||
#if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 12))
|
||||
#undef OPEN_MEMSTREAM
|
||||
#endif
|
||||
|
@ -230,6 +230,38 @@ static __inline__ int unpack_16(uint8_t *s, uint16_t value)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(bool) t42_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len)
|
||||
{
|
||||
int type;
|
||||
int seg;
|
||||
int pos;
|
||||
|
||||
/* Search the image data for its width and length */
|
||||
*length = 0;
|
||||
*width = 0;
|
||||
|
||||
pos = 0;
|
||||
if (pack_16(&data[pos]) != 0xFFD8)
|
||||
return false;
|
||||
pos += 2;
|
||||
while (pos < len)
|
||||
{
|
||||
type = pack_16(&data[pos]);
|
||||
pos += 2;
|
||||
seg = pack_16(&data[pos]) - 2;
|
||||
pos += 2;
|
||||
if (type == 0xFFC0)
|
||||
{
|
||||
*length = pack_16(&data[pos + 1]);
|
||||
*width = pack_16(&data[pos + 3]);
|
||||
return true;
|
||||
}
|
||||
pos += seg;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) xyz_to_corrected_color_temp(float *temp, float xyz[3])
|
||||
{
|
||||
float us;
|
||||
|
|
|
@ -865,7 +865,8 @@ SPAN_DECLARE(int) t43_decode_restart(t43_decode_state_t *s)
|
|||
{
|
||||
/* ITULAB */
|
||||
/* Illuminant D50 */
|
||||
set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f);
|
||||
//set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f);
|
||||
set_lab_illuminant(&s->lab, 100.0f, 100.0f, 100.0f);
|
||||
set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, false);
|
||||
|
||||
s->t85.min_bit_planes = 1;
|
||||
|
@ -898,7 +899,8 @@ SPAN_DECLARE(t43_decode_state_t *) t43_decode_init(t43_decode_state_t *s,
|
|||
|
||||
/* ITULAB */
|
||||
/* Illuminant D50 */
|
||||
set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f);
|
||||
//set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f);
|
||||
set_lab_illuminant(&s->lab, 100.0f, 100.0f, 100.0f);
|
||||
set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, false);
|
||||
|
||||
s->t85.min_bit_planes = 1;
|
||||
|
|
|
@ -213,6 +213,8 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
|
|||
int bits_per_sample;
|
||||
int samples_per_pixel;
|
||||
int photometric;
|
||||
uint32_t width;
|
||||
uint32_t length;
|
||||
|
||||
t = &s->tiff;
|
||||
/* Prepare the directory entry fully before writing the image, or libtiff complains */
|
||||
|
@ -274,8 +276,16 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
|
|||
case T4_COMPRESSION_SYCC_T81:
|
||||
output_compression = COMPRESSION_JPEG;
|
||||
bits_per_sample = 8;
|
||||
samples_per_pixel = 3;
|
||||
photometric = PHOTOMETRIC_YCBCR;
|
||||
if (t->image_type == T4_IMAGE_TYPE_COLOUR_8BIT)
|
||||
{
|
||||
samples_per_pixel = 3;
|
||||
photometric = PHOTOMETRIC_YCBCR;
|
||||
}
|
||||
else
|
||||
{
|
||||
samples_per_pixel = 1;
|
||||
photometric = PHOTOMETRIC_MINISBLACK;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if defined(SPANDSP_SUPPORT_T43)
|
||||
|
@ -399,7 +409,21 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
|
|||
switch (s->current_decoder)
|
||||
{
|
||||
case 0:
|
||||
s->metadata.image_length = 1024;
|
||||
switch (t->compression)
|
||||
{
|
||||
case T4_COMPRESSION_T42_T81:
|
||||
case T4_COMPRESSION_SYCC_T81:
|
||||
t42_analyse_header(&width, &length, s->decoder.no_decoder.buf, s->decoder.no_decoder.buf_ptr);
|
||||
s->metadata.image_width = width;
|
||||
s->metadata.image_length = length;
|
||||
break;
|
||||
case T4_COMPRESSION_T85:
|
||||
case T4_COMPRESSION_T85_L0:
|
||||
t85_analyse_header(&width, &length, s->decoder.no_decoder.buf, s->decoder.no_decoder.buf_ptr);
|
||||
s->metadata.image_width = width;
|
||||
s->metadata.image_length = length;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
|
||||
if ((s->metadata.compression & (T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D)))
|
||||
|
@ -607,7 +631,7 @@ static int write_tiff_image(t4_rx_state_t *s)
|
|||
#endif
|
||||
|
||||
t = &s->tiff;
|
||||
if (s->pre_encoded_ptr <= 0 && (t->image_buffer == NULL || t->image_size <= 0))
|
||||
if (s->decoder.no_decoder.buf_ptr <= 0 && (t->image_buffer == NULL || t->image_size <= 0))
|
||||
return -1;
|
||||
/* Set up the TIFF directory info... */
|
||||
set_tiff_directory_info(s);
|
||||
|
@ -616,9 +640,9 @@ static int write_tiff_image(t4_rx_state_t *s)
|
|||
//if (!TIFFCheckpointDirectory(t->tiff_file))
|
||||
// span_log(&s->logging, SPAN_LOG_WARNING, "%s: Failed to checkpoint directory for page %d.\n", t->file, s->current_page);
|
||||
/* ...and write out the image... */
|
||||
if (s->pre_encoded_ptr > 0)
|
||||
if (s->current_decoder == 0)
|
||||
{
|
||||
if (TIFFWriteRawStrip(s->tiff.tiff_file, 0, s->pre_encoded_buf, s->pre_encoded_ptr) < 0)
|
||||
if (TIFFWriteRawStrip(s->tiff.tiff_file, 0, s->decoder.no_decoder.buf, s->decoder.no_decoder.buf_ptr) < 0)
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "%s: Error writing TIFF strip.\n", s->tiff.file);
|
||||
}
|
||||
else
|
||||
|
@ -752,30 +776,57 @@ SPAN_DECLARE(int) t4_rx_put_bit(t4_rx_state_t *s, int bit)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void pre_encoded_restart(no_decoder_state_t *s)
|
||||
{
|
||||
s->buf_ptr = 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void pre_encoded_init(no_decoder_state_t *s)
|
||||
{
|
||||
s->buf = NULL;
|
||||
s->buf_len = 0;
|
||||
s->buf_ptr = 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int pre_encoded_release(no_decoder_state_t *s)
|
||||
{
|
||||
if (s->buf)
|
||||
span_free(s->buf);
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int pre_encoded_put(no_decoder_state_t *s, const uint8_t data[], size_t len)
|
||||
{
|
||||
uint8_t *buf;
|
||||
|
||||
if (s->buf_len < s->buf_ptr + len)
|
||||
{
|
||||
s->buf_len += 65536;
|
||||
if ((buf = span_realloc(s->buf, s->buf_len)) == NULL)
|
||||
{
|
||||
if (s->buf)
|
||||
{
|
||||
span_free(s->buf);
|
||||
s->buf = NULL;
|
||||
s->buf_len = 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
s->buf = buf;
|
||||
}
|
||||
memcpy(&s->buf[s->buf_ptr], data, len);
|
||||
s->buf_ptr += len;
|
||||
return T4_DECODE_MORE_DATA;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) t4_rx_put(t4_rx_state_t *s, const uint8_t buf[], size_t len)
|
||||
{
|
||||
uint8_t *buf2;
|
||||
|
||||
s->line_image_size += 8*len;
|
||||
|
||||
if (s->pre_encoded_len > 0)
|
||||
{
|
||||
if (s->pre_encoded_len < s->pre_encoded_ptr + 65536)
|
||||
{
|
||||
s->pre_encoded_len += 65536;
|
||||
if ((buf2 = span_realloc(s->pre_encoded_buf, s->pre_encoded_len)) == NULL)
|
||||
{
|
||||
if (s->pre_encoded_buf)
|
||||
span_free(s->pre_encoded_buf);
|
||||
return -1;
|
||||
}
|
||||
s->pre_encoded_buf = buf2;
|
||||
}
|
||||
memcpy(&s->pre_encoded_buf[s->pre_encoded_ptr], buf, len);
|
||||
s->pre_encoded_ptr += len;
|
||||
return T4_DECODE_MORE_DATA;
|
||||
}
|
||||
|
||||
if (s->image_put_handler)
|
||||
return s->image_put_handler((void *) &s->decoder, buf, len);
|
||||
|
||||
|
@ -825,13 +876,23 @@ SPAN_DECLARE(void) t4_rx_set_model(t4_rx_state_t *s, const char *model)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void select_tiff_compression(t4_rx_state_t *s, int output_image_type)
|
||||
static bool select_tiff_compression(t4_rx_state_t *s, int output_image_type)
|
||||
{
|
||||
s->tiff.image_type = output_image_type;
|
||||
if ((s->metadata.compression & (s->supported_tiff_compressions & (T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0 | T4_COMPRESSION_T42_T81 | T4_COMPRESSION_SYCC_T81))))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Image can be written without recoding\n");
|
||||
s->tiff.compression = s->metadata.compression;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (output_image_type == T4_IMAGE_TYPE_BILEVEL)
|
||||
{
|
||||
/* Only provide for one form of coding throughout the file, even though the
|
||||
coding on the wire could change between pages. */
|
||||
if ((s->supported_tiff_compressions & T4_COMPRESSION_T85))
|
||||
if ((s->supported_tiff_compressions & T4_COMPRESSION_T88))
|
||||
s->tiff.compression = T4_COMPRESSION_T88;
|
||||
else if ((s->supported_tiff_compressions & T4_COMPRESSION_T85))
|
||||
s->tiff.compression = T4_COMPRESSION_T85;
|
||||
else if ((s->supported_tiff_compressions & T4_COMPRESSION_T6))
|
||||
s->tiff.compression = T4_COMPRESSION_T6;
|
||||
|
@ -848,22 +909,46 @@ static void select_tiff_compression(t4_rx_state_t *s, int output_image_type)
|
|||
s->tiff.compression = T4_COMPRESSION_T42_T81;
|
||||
else if ((s->supported_tiff_compressions & T4_COMPRESSION_T43))
|
||||
s->tiff.compression = T4_COMPRESSION_T43;
|
||||
else if ((s->supported_tiff_compressions & T4_COMPRESSION_T45))
|
||||
s->tiff.compression = T4_COMPRESSION_T45;
|
||||
else if ((s->supported_tiff_compressions & T4_COMPRESSION_UNCOMPRESSED))
|
||||
s->tiff.compression = T4_COMPRESSION_UNCOMPRESSED;
|
||||
}
|
||||
s->tiff.image_type = output_image_type;
|
||||
return true;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int release_current_decoder(t4_rx_state_t *s)
|
||||
{
|
||||
switch (s->current_decoder)
|
||||
{
|
||||
case 0:
|
||||
return pre_encoded_release(&s->decoder.no_decoder);
|
||||
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
|
||||
return t4_t6_decode_release(&s->decoder.t4_t6);
|
||||
case T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0:
|
||||
return t85_decode_release(&s->decoder.t85);
|
||||
#if defined(SPANDSP_SUPPORT_T88)
|
||||
case T4_COMPRESSION_T88:
|
||||
return t88_decode_release(&s->decoder.t88);
|
||||
#endif
|
||||
case T4_COMPRESSION_T42_T81:
|
||||
return t42_decode_release(&s->decoder.t42);
|
||||
#if defined(SPANDSP_SUPPORT_T43)
|
||||
case T4_COMPRESSION_T43:
|
||||
return t43_decode_release(&s->decoder.t43);
|
||||
#endif
|
||||
#if defined(SPANDSP_SUPPORT_T45)
|
||||
case T4_COMPRESSION_T45:
|
||||
return t45_decode_release(&s->decoder.t45);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
||||
{
|
||||
#if 0
|
||||
output_image_type = T4_IMAGE_TYPE_BILEVEL;
|
||||
s->metadata.compression = compression;
|
||||
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
|
||||
s->current_decoder = 0;
|
||||
return 0;
|
||||
#else
|
||||
switch (compression)
|
||||
{
|
||||
case T4_COMPRESSION_T4_1D:
|
||||
|
@ -876,12 +961,18 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
|||
case T4_COMPRESSION_T6:
|
||||
break;
|
||||
default:
|
||||
release_current_decoder(s);
|
||||
t4_t6_decode_init(&s->decoder.t4_t6, compression, s->metadata.image_width, s->row_handler, s->row_handler_user_data);
|
||||
s->current_decoder = T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6;
|
||||
break;
|
||||
}
|
||||
s->metadata.compression = compression;
|
||||
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
|
||||
if (!select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL))
|
||||
{
|
||||
release_current_decoder(s);
|
||||
s->current_decoder = 0;
|
||||
pre_encoded_init(&s->decoder.no_decoder);
|
||||
}
|
||||
return t4_t6_decode_set_encoding(&s->decoder.t4_t6, compression);
|
||||
case T4_COMPRESSION_T85:
|
||||
case T4_COMPRESSION_T85_L0:
|
||||
|
@ -891,6 +982,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
|||
case T4_COMPRESSION_T85_L0:
|
||||
break;
|
||||
default:
|
||||
release_current_decoder(s);
|
||||
t85_decode_init(&s->decoder.t85, s->row_handler, s->row_handler_user_data);
|
||||
s->current_decoder = T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0;
|
||||
/* Constrain received images to the maximum width of any FAX. This will
|
||||
|
@ -900,7 +992,12 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
|||
break;
|
||||
}
|
||||
s->metadata.compression = compression;
|
||||
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
|
||||
if (!select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL))
|
||||
{
|
||||
release_current_decoder(s);
|
||||
s->current_decoder = 0;
|
||||
pre_encoded_init(&s->decoder.no_decoder);
|
||||
}
|
||||
return 0;
|
||||
#if defined(SPANDSP_SUPPORT_T88)
|
||||
case T4_COMPRESSION_T88:
|
||||
|
@ -909,12 +1006,18 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
|||
case T4_COMPRESSION_T88:
|
||||
break;
|
||||
default:
|
||||
release_current_decoder(s);
|
||||
t88_decode_init(&s->decoder.t88, s->row_handler, s->row_handler_user_data);
|
||||
s->current_decoder = T4_COMPRESSION_T88;
|
||||
break;
|
||||
}
|
||||
s->metadata.compression = compression;
|
||||
select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL);
|
||||
if (!select_tiff_compression(s, T4_IMAGE_TYPE_BILEVEL))
|
||||
{
|
||||
release_current_decoder(s);
|
||||
s->current_decoder = 0;
|
||||
pre_encoded_init(&s->decoder.no_decoder);
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
case T4_COMPRESSION_T42_T81:
|
||||
|
@ -925,6 +1028,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
|||
case T4_COMPRESSION_SYCC_T81:
|
||||
break;
|
||||
default:
|
||||
release_current_decoder(s);
|
||||
t42_decode_init(&s->decoder.t42, s->row_handler, s->row_handler_user_data);
|
||||
s->current_decoder = T4_COMPRESSION_T42_T81;
|
||||
/* Constrain received images to the maximum width of any FAX. This will
|
||||
|
@ -934,7 +1038,12 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
|||
break;
|
||||
}
|
||||
s->metadata.compression = compression;
|
||||
select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT);
|
||||
if (!select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT))
|
||||
{
|
||||
release_current_decoder(s);
|
||||
s->current_decoder = 0;
|
||||
pre_encoded_init(&s->decoder.no_decoder);
|
||||
}
|
||||
return 0;
|
||||
#if defined(SPANDSP_SUPPORT_T43)
|
||||
case T4_COMPRESSION_T43:
|
||||
|
@ -943,6 +1052,7 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
|||
case T4_COMPRESSION_T43:
|
||||
break;
|
||||
default:
|
||||
release_current_decoder(s);
|
||||
t43_decode_init(&s->decoder.t43, s->row_handler, s->row_handler_user_data);
|
||||
s->current_decoder = T4_COMPRESSION_T43;
|
||||
/* Constrain received images to the maximum width of any FAX. This will
|
||||
|
@ -952,7 +1062,12 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
|||
break;
|
||||
}
|
||||
s->metadata.compression = compression;
|
||||
select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT);
|
||||
if (!select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT))
|
||||
{
|
||||
release_current_decoder(s);
|
||||
s->current_decoder = 0;
|
||||
pre_encoded_init(&s->decoder.no_decoder);
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
#if defined(SPANDSP_SUPPORT_T45)
|
||||
|
@ -962,18 +1077,23 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int compression)
|
|||
case T4_COMPRESSION_T45:
|
||||
break;
|
||||
default:
|
||||
release_current_decoder(s);
|
||||
t45_decode_init(&s->decoder.t45, s->row_handler, s->row_handler_user_data);
|
||||
s->current_decoder = T4_COMPRESSION_T45;
|
||||
break;
|
||||
}
|
||||
s->metadata.compression = compression;
|
||||
select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT);
|
||||
if (!select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT))
|
||||
{
|
||||
release_current_decoder(s);
|
||||
s->current_decoder = 0;
|
||||
pre_encoded_init(&s->decoder.no_decoder);
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -1026,6 +1146,15 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t
|
|||
t->compression = s->metadata.compression;
|
||||
switch (s->current_decoder)
|
||||
{
|
||||
case 0:
|
||||
t->type = 0;
|
||||
t->width = s->metadata.image_width;
|
||||
t->length = s->metadata.image_length;
|
||||
t->image_type = 0;
|
||||
t->image_width = t->width;
|
||||
t->image_length = t->length;
|
||||
t->line_image_size = s->line_image_size;
|
||||
break;
|
||||
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
|
||||
t->type = T4_IMAGE_TYPE_BILEVEL;
|
||||
t->width = t4_t6_decode_get_image_width(&s->decoder.t4_t6);
|
||||
|
@ -1085,9 +1214,8 @@ SPAN_DECLARE(int) t4_rx_start_page(t4_rx_state_t *s)
|
|||
switch (s->current_decoder)
|
||||
{
|
||||
case 0:
|
||||
s->pre_encoded_ptr = 0;
|
||||
s->pre_encoded_len = 0;
|
||||
s->image_put_handler = NULL;
|
||||
pre_encoded_restart(&s->decoder.no_decoder);
|
||||
s->image_put_handler = (t4_image_put_handler_t) pre_encoded_put;
|
||||
break;
|
||||
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
|
||||
t4_t6_decode_restart(&s->decoder.t4_t6, s->metadata.image_width);
|
||||
|
@ -1163,7 +1291,7 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s)
|
|||
switch (s->current_decoder)
|
||||
{
|
||||
case 0:
|
||||
length = s->pre_encoded_ptr;
|
||||
length = s->decoder.no_decoder.buf_ptr;
|
||||
break;
|
||||
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
|
||||
length = t4_t6_decode_get_image_length(&s->decoder.t4_t6);
|
||||
|
@ -1179,9 +1307,9 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s)
|
|||
case T4_COMPRESSION_T42_T81:
|
||||
length = t42_decode_get_image_length(&s->decoder.t42);
|
||||
if (s->decoder.t42.samples_per_pixel == 3)
|
||||
select_tiff_compression(s, T4_IMAGE_TYPE_COLOUR_8BIT);
|
||||
s->tiff.image_type = T4_IMAGE_TYPE_COLOUR_8BIT;
|
||||
else
|
||||
select_tiff_compression(s, T4_IMAGE_TYPE_GRAY_8BIT);
|
||||
s->tiff.image_type = T4_IMAGE_TYPE_GRAY_8BIT;
|
||||
break;
|
||||
#if defined(SPANDSP_SUPPORT_T43)
|
||||
case T4_COMPRESSION_T43:
|
||||
|
@ -1203,7 +1331,6 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s)
|
|||
if (write_tiff_image(s) == 0)
|
||||
s->current_page++;
|
||||
s->tiff.image_size = 0;
|
||||
s->pre_encoded_ptr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1240,6 +1367,15 @@ SPAN_DECLARE(t4_rx_state_t *) t4_rx_init(t4_rx_state_t *s, const char *file, int
|
|||
span_log(&s->logging, SPAN_LOG_FLOW, "Start rx document\n");
|
||||
|
||||
s->supported_tiff_compressions = supported_output_compressions;
|
||||
#if !defined(SPANDSP_SUPPORT_T88)
|
||||
s->supported_tiff_compressions &= ~T4_COMPRESSION_T88;
|
||||
#endif
|
||||
#if !defined(SPANDSP_SUPPORT_T43)
|
||||
s->supported_tiff_compressions &= ~T4_COMPRESSION_T43;
|
||||
#endif
|
||||
#if !defined(SPANDSP_SUPPORT_T45)
|
||||
s->supported_tiff_compressions &= ~T4_COMPRESSION_T45;
|
||||
#endif
|
||||
|
||||
/* Set some default values */
|
||||
s->metadata.x_resolution = T4_X_RESOLUTION_R8;
|
||||
|
@ -1272,27 +1408,7 @@ SPAN_DECLARE(int) t4_rx_release(t4_rx_state_t *s)
|
|||
{
|
||||
if (s->tiff.file)
|
||||
tiff_rx_release(s);
|
||||
switch (s->current_decoder)
|
||||
{
|
||||
case T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6:
|
||||
return t4_t6_decode_release(&s->decoder.t4_t6);
|
||||
case T4_COMPRESSION_T85 | T4_COMPRESSION_T85_L0:
|
||||
return t85_decode_release(&s->decoder.t85);
|
||||
#if defined(SPANDSP_SUPPORT_T88)
|
||||
case T4_COMPRESSION_T88:
|
||||
return t88_decode_release(&s->decoder.t88);
|
||||
#endif
|
||||
case T4_COMPRESSION_T42_T81:
|
||||
return t42_decode_release(&s->decoder.t42);
|
||||
#if defined(SPANDSP_SUPPORT_T43)
|
||||
case T4_COMPRESSION_T43:
|
||||
return t43_decode_release(&s->decoder.t43);
|
||||
#endif
|
||||
#if defined(SPANDSP_SUPPORT_T45)
|
||||
case T4_COMPRESSION_T45:
|
||||
return t45_decode_release(&s->decoder.t45);
|
||||
#endif
|
||||
}
|
||||
release_current_decoder(s);
|
||||
return -1;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
|
|
@ -873,20 +873,20 @@ static int read_tiff_raw_image(t4_tx_state_t *s)
|
|||
total_len = 0;
|
||||
for (i = 0; i < num_strips; i++)
|
||||
total_len += TIFFRawStripSize(s->tiff.tiff_file, i);
|
||||
if ((s->pre_encoded_buf = span_realloc(s->pre_encoded_buf, total_len)) == NULL)
|
||||
if ((s->no_encoder.buf = span_realloc(s->no_encoder.buf, total_len)) == NULL)
|
||||
return -1;
|
||||
total_len = 0;
|
||||
for (i = 0; i < num_strips; i++, total_len += len)
|
||||
{
|
||||
len = TIFFRawStripSize(s->tiff.tiff_file, i);
|
||||
if ((len = TIFFReadRawStrip(s->tiff.tiff_file, i, &s->pre_encoded_buf[total_len], len)) < 0)
|
||||
if ((len = TIFFReadRawStrip(s->tiff.tiff_file, i, &s->no_encoder.buf[total_len], len)) < 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "%s: TIFFReadRawStrip error.\n", s->tiff.file);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
s->pre_encoded_len = total_len;
|
||||
s->pre_encoded_ptr = 0;
|
||||
s->no_encoder.buf_len = total_len;
|
||||
s->no_encoder.buf_ptr = 0;
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -1674,7 +1674,7 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s,
|
|||
int width_code;
|
||||
int res_code; /* Correct resolution code */
|
||||
int alt_res_code; /* Fallback resolution code, where a metric/inch swap is possible */
|
||||
} width_info[] =
|
||||
} width_and_res_info[] =
|
||||
{
|
||||
{ T4_WIDTH_100_A4, T4_SUPPORT_WIDTH_215MM, T4_RESOLUTION_100_100, 0},
|
||||
{ T4_WIDTH_100_B4, T4_SUPPORT_WIDTH_255MM, T4_RESOLUTION_100_100, 0},
|
||||
|
@ -1777,7 +1777,9 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s,
|
|||
int entry;
|
||||
int compression;
|
||||
int res;
|
||||
int supported_colour_compressions;
|
||||
|
||||
supported_colour_compressions = supported_compressions & (T4_COMPRESSION_T42_T81 | T4_COMPRESSION_T43 | T4_COMPRESSION_T45 | T4_COMPRESSION_SYCC_T81);
|
||||
compression = -1;
|
||||
s->metadata.image_type = s->tiff.image_type;
|
||||
if (s->tiff.image_type != T4_IMAGE_TYPE_BILEVEL)
|
||||
|
@ -1786,7 +1788,7 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s,
|
|||
/* Can we send this page as it is? */
|
||||
if (supported_colour_resolutions
|
||||
&&
|
||||
(supported_compressions & (T4_COMPRESSION_T42_T81 | T4_COMPRESSION_T43 | T4_COMPRESSION_T45 | T4_COMPRESSION_SYCC_T81))
|
||||
supported_colour_compressions
|
||||
&&
|
||||
(((s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL || s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_8BIT || s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
|
||||
&&
|
||||
|
@ -1798,28 +1800,6 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s,
|
|||
{
|
||||
/* Gray-scale/colour is possible */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Gray-scale/colour is allowed\n");
|
||||
if (s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL
|
||||
||
|
||||
s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_8BIT
|
||||
||
|
||||
s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
|
||||
{
|
||||
if (!(supported_compressions & T4_COMPRESSION_COLOUR))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Colour is not allowed\n");
|
||||
return T4_IMAGE_FORMAT_INCOMPATIBLE;
|
||||
}
|
||||
}
|
||||
else if (s->tiff.image_type == T4_IMAGE_TYPE_GRAY_8BIT
|
||||
||
|
||||
s->tiff.image_type == T4_IMAGE_TYPE_GRAY_12BIT)
|
||||
{
|
||||
if (!(supported_compressions & T4_COMPRESSION_GRAYSCALE))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Gray-scale is not allowed\n");
|
||||
return T4_IMAGE_FORMAT_INCOMPATIBLE;
|
||||
}
|
||||
}
|
||||
/* Choose the best gray-scale/colour encoding available to us */
|
||||
if (s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL && (supported_compressions & T4_COMPRESSION_T43))
|
||||
compression = T4_COMPRESSION_T43;
|
||||
|
@ -1838,32 +1818,29 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s,
|
|||
{
|
||||
/* Gray-scale/colour is not possible. Can we flatten the image to send it? */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Gray-scale/colour is not allowed\n");
|
||||
if (s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL
|
||||
||
|
||||
s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_8BIT
|
||||
||
|
||||
s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
|
||||
switch (s->tiff.image_type)
|
||||
{
|
||||
case T4_IMAGE_TYPE_COLOUR_BILEVEL:
|
||||
case T4_IMAGE_TYPE_COLOUR_8BIT:
|
||||
case T4_IMAGE_TYPE_COLOUR_12BIT:
|
||||
if (!(supported_compressions & T4_COMPRESSION_COLOUR_TO_BILEVEL))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Flattening is not allowed\n");
|
||||
return T4_IMAGE_FORMAT_INCOMPATIBLE;
|
||||
}
|
||||
s->metadata.image_type = T4_IMAGE_TYPE_BILEVEL;
|
||||
}
|
||||
else if (s->tiff.image_type == T4_IMAGE_TYPE_GRAY_8BIT
|
||||
||
|
||||
s->tiff.image_type == T4_IMAGE_TYPE_GRAY_12BIT)
|
||||
{
|
||||
break;
|
||||
case T4_IMAGE_TYPE_GRAY_8BIT:
|
||||
case T4_IMAGE_TYPE_GRAY_12BIT:
|
||||
if (!(supported_compressions & T4_COMPRESSION_GRAY_TO_BILEVEL))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Flattening is not allowed\n");
|
||||
return T4_IMAGE_FORMAT_INCOMPATIBLE;
|
||||
}
|
||||
s->metadata.image_type = T4_IMAGE_TYPE_BILEVEL;
|
||||
break;
|
||||
}
|
||||
/* Squashing to a bi-level image is possible */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "The image may be flattened to %d\n", s->metadata.image_type);
|
||||
s->metadata.image_type = T4_IMAGE_TYPE_BILEVEL;
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "The image will be flattened to %d\n", s->metadata.image_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1884,26 +1861,20 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s,
|
|||
|
||||
/* Deal with the image width/resolution combination. */
|
||||
/* Look for a pattern that matches the image */
|
||||
res = T4_IMAGE_FORMAT_NOSIZESUPPORT;
|
||||
for (entry = 0; s->tiff.image_width >= width_info[entry].width; entry++)
|
||||
s->metadata.width_code = -1;
|
||||
for (entry = 0; s->tiff.image_width >= width_and_res_info[entry].width; entry++)
|
||||
{
|
||||
if (s->tiff.image_width == width_info[entry].width && s->tiff.resolution_code == width_info[entry].res_code)
|
||||
if (s->tiff.image_width == width_and_res_info[entry].width && s->tiff.resolution_code == width_and_res_info[entry].res_code)
|
||||
{
|
||||
res = T4_IMAGE_FORMAT_OK;
|
||||
s->metadata.width_code = width_and_res_info[entry].width_code;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s->metadata.width_code = width_info[entry].width_code;
|
||||
|
||||
res = T4_IMAGE_FORMAT_NOSIZESUPPORT;
|
||||
s->row_squashing_ratio = 1;
|
||||
if (res == T4_IMAGE_FORMAT_OK)
|
||||
if (s->metadata.width_code >= 0 && (supported_image_sizes & s->metadata.width_code))
|
||||
{
|
||||
/* We have a valid width/resolution combination */
|
||||
|
||||
/* Check if this width/resolution combination is supported */
|
||||
if (!(supported_image_sizes & width_info[entry].width_code))
|
||||
return T4_IMAGE_FORMAT_NOSIZESUPPORT;
|
||||
/* We have a valid and supported width/resolution combination */
|
||||
|
||||
/* No resize necessary */
|
||||
s->metadata.image_width = s->tiff.image_width;
|
||||
|
@ -1912,7 +1883,7 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s,
|
|||
res = T4_IMAGE_FORMAT_NORESSUPPORT;
|
||||
if (s->metadata.image_type == T4_IMAGE_TYPE_BILEVEL)
|
||||
{
|
||||
if ((width_info[entry].res_code & supported_bilevel_resolutions))
|
||||
if ((width_and_res_info[entry].res_code & supported_bilevel_resolutions))
|
||||
{
|
||||
/* We can use the resolution of the original image */
|
||||
s->metadata.resolution_code = s->tiff.resolution_code;
|
||||
|
@ -1920,56 +1891,51 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s,
|
|||
s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code);
|
||||
res = T4_IMAGE_FORMAT_OK;
|
||||
}
|
||||
else if ((width_and_res_info[entry].alt_res_code & supported_bilevel_resolutions))
|
||||
{
|
||||
/* We can do a metric/imperial swap, and have a usable resolution */
|
||||
span_log(&s->logging,
|
||||
SPAN_LOG_FLOW,
|
||||
"Image resolution %s falls back to %s\n",
|
||||
t4_image_resolution_to_str(s->tiff.resolution_code),
|
||||
t4_image_resolution_to_str(width_and_res_info[entry].alt_res_code));
|
||||
s->metadata.resolution_code = width_and_res_info[entry].alt_res_code;
|
||||
s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code);
|
||||
s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code);
|
||||
res = T4_IMAGE_FORMAT_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The resolution is not supported, but there might be an approximation, or a length
|
||||
squashing that might work. */
|
||||
if ((width_info[entry].alt_res_code & supported_bilevel_resolutions))
|
||||
if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL)
|
||||
{
|
||||
/* We can do a metric/imperial swap, and have a usable resolution */
|
||||
span_log(&s->logging,
|
||||
SPAN_LOG_FLOW,
|
||||
"Image resolution %s falls back to %s\n",
|
||||
t4_image_resolution_to_str(s->tiff.resolution_code),
|
||||
t4_image_resolution_to_str(width_info[entry].alt_res_code));
|
||||
s->metadata.resolution_code = width_info[entry].alt_res_code;
|
||||
s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code);
|
||||
s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code);
|
||||
res = T4_IMAGE_FORMAT_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL)
|
||||
if ((s->tiff.resolution_code & (T4_RESOLUTION_200_400 | T4_RESOLUTION_200_200 | T4_RESOLUTION_R8_SUPERFINE | T4_RESOLUTION_R8_FINE)))
|
||||
{
|
||||
if ((s->tiff.resolution_code & (T4_RESOLUTION_200_400 | T4_RESOLUTION_200_200 | T4_RESOLUTION_R8_SUPERFINE | T4_RESOLUTION_R8_FINE)))
|
||||
/* This might be a resolution we can squash down to something which is supported */
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
/* This might be a resolution we can squash down to something which is supported */
|
||||
for (i = 0; i < 4; i++)
|
||||
if ((s->tiff.resolution_code & squashable[i].resolution))
|
||||
break;
|
||||
}
|
||||
if (i < 4)
|
||||
{
|
||||
/* This is a squashable resolution, so let's see if there is a valid
|
||||
fallback we can squash the image to, scanning through the entries
|
||||
in their order of preference. */
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
if ((s->tiff.resolution_code & squashable[i].resolution))
|
||||
break;
|
||||
}
|
||||
if (i < 4)
|
||||
{
|
||||
/* This is a squashable resolution, so let's see if there is a valid
|
||||
fallback we can squash the image to, scanning through the entries
|
||||
in their order of preference. */
|
||||
for (j = 0; j < 4; j++)
|
||||
if ((supported_bilevel_resolutions & squashable[i].fallback[j].resolution))
|
||||
{
|
||||
if ((supported_bilevel_resolutions & squashable[i].fallback[j].resolution))
|
||||
{
|
||||
span_log(&s->logging,
|
||||
SPAN_LOG_FLOW,
|
||||
"Image resolution %s falls back to %s\n",
|
||||
t4_image_resolution_to_str(s->tiff.resolution_code),
|
||||
t4_image_resolution_to_str(squashable[i].fallback[j].resolution));
|
||||
s->row_squashing_ratio = squashable[i].fallback[j].squashing_factor;
|
||||
s->metadata.resolution_code = squashable[i].fallback[j].resolution;
|
||||
s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code);
|
||||
s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code);
|
||||
res = T4_IMAGE_FORMAT_OK;
|
||||
break;
|
||||
}
|
||||
span_log(&s->logging,
|
||||
SPAN_LOG_FLOW,
|
||||
"Image resolution %s falls back to %s\n",
|
||||
t4_image_resolution_to_str(s->tiff.resolution_code),
|
||||
t4_image_resolution_to_str(squashable[i].fallback[j].resolution));
|
||||
s->row_squashing_ratio = squashable[i].fallback[j].squashing_factor;
|
||||
s->metadata.resolution_code = squashable[i].fallback[j].resolution;
|
||||
s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code);
|
||||
s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code);
|
||||
res = T4_IMAGE_FORMAT_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1977,25 +1943,25 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s,
|
|||
}
|
||||
}
|
||||
/* If we have not succeeded in matching up the size and resolution, the next step will
|
||||
depend on whether the original was a bi-level image. If it was we are stuck, as you can't
|
||||
depend on whether the original was a bi-level image. If it was, we are stuck, as you can't
|
||||
really resize those. If it was not, a resize might be possible */
|
||||
if (res != T4_IMAGE_FORMAT_OK)
|
||||
{
|
||||
if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL)
|
||||
return T4_IMAGE_FORMAT_NORESSUPPORT;
|
||||
if (!(supported_compressions & T4_COMPRESSION_RESCALING))
|
||||
return T4_IMAGE_FORMAT_NORESSUPPORT;
|
||||
return T4_IMAGE_FORMAT_NOSIZESUPPORT;
|
||||
}
|
||||
/* TODO */
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((width_info[entry].res_code & supported_bilevel_resolutions))
|
||||
if ((width_and_res_info[entry].res_code & supported_bilevel_resolutions))
|
||||
{
|
||||
if ((s->tiff.resolution_code & supported_colour_resolutions))
|
||||
{
|
||||
/* We can use the resolution of the original image */
|
||||
s->metadata.resolution_code = width_info[entry].res_code;
|
||||
s->metadata.resolution_code = width_and_res_info[entry].res_code;
|
||||
s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code);
|
||||
s->metadata.y_resolution = code_to_y_resolution(s->metadata.resolution_code);
|
||||
res = T4_IMAGE_FORMAT_OK;
|
||||
|
@ -2007,12 +1973,13 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s,
|
|||
{
|
||||
/* Can we rework the image to fit? */
|
||||
/* We can't rework a bilevel image that fits none of the patterns */
|
||||
if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL)
|
||||
if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL || s->tiff.image_type == T4_IMAGE_TYPE_COLOUR_BILEVEL)
|
||||
return T4_IMAGE_FORMAT_NORESSUPPORT;
|
||||
if (!(supported_compressions & T4_COMPRESSION_RESCALING))
|
||||
return T4_IMAGE_FORMAT_NORESSUPPORT;
|
||||
res = T4_IMAGE_FORMAT_OK;
|
||||
return T4_IMAGE_FORMAT_NOSIZESUPPORT;
|
||||
/* Any other kind of image might be resizable */
|
||||
res = T4_IMAGE_FORMAT_OK;
|
||||
/* TODO: use more sophisticated resizing */
|
||||
s->metadata.image_width = T4_WIDTH_200_A4;
|
||||
s->metadata.resolution_code = T4_RESOLUTION_200_200;
|
||||
s->metadata.x_resolution = code_to_x_resolution(s->metadata.resolution_code);
|
||||
|
@ -2430,9 +2397,9 @@ SPAN_DECLARE(void) t4_tx_get_transfer_statistics(t4_tx_state_t *s, t4_stats_t *t
|
|||
|
||||
SPAN_DECLARE(int) t4_tx_image_complete(t4_tx_state_t *s)
|
||||
{
|
||||
if (s->pre_encoded_len > 0)
|
||||
if (s->no_encoder.buf_len > 0)
|
||||
{
|
||||
if (s->pre_encoded_ptr >= s->pre_encoded_len)
|
||||
if (s->no_encoder.buf_ptr >= s->no_encoder.buf_len)
|
||||
return SIG_STATUS_END_OF_DATA;
|
||||
return 0;
|
||||
}
|
||||
|
@ -2471,15 +2438,15 @@ SPAN_DECLARE(int) t4_tx_get_bit(t4_tx_state_t *s)
|
|||
int bit;
|
||||
|
||||
/* We only get bit by bit for T.4 1D and T.4 2-D. */
|
||||
if (s->pre_encoded_len > 0)
|
||||
if (s->no_encoder.buf_len > 0)
|
||||
{
|
||||
if (s->pre_encoded_ptr >= s->pre_encoded_len)
|
||||
if (s->no_encoder.buf_ptr >= s->no_encoder.buf_len)
|
||||
return SIG_STATUS_END_OF_DATA;
|
||||
bit = (s->pre_encoded_buf[s->pre_encoded_ptr] >> s->pre_encoded_bit) & 1;
|
||||
if (++s->pre_encoded_bit >= 8)
|
||||
bit = (s->no_encoder.buf[s->no_encoder.buf_ptr] >> s->no_encoder.bit) & 1;
|
||||
if (++s->no_encoder.bit >= 8)
|
||||
{
|
||||
s->pre_encoded_bit = 0;
|
||||
s->pre_encoded_ptr++;
|
||||
s->no_encoder.bit = 0;
|
||||
s->no_encoder.buf_ptr++;
|
||||
}
|
||||
return bit;
|
||||
}
|
||||
|
@ -2489,12 +2456,12 @@ SPAN_DECLARE(int) t4_tx_get_bit(t4_tx_state_t *s)
|
|||
|
||||
SPAN_DECLARE(int) t4_tx_get(t4_tx_state_t *s, uint8_t buf[], size_t max_len)
|
||||
{
|
||||
if (s->pre_encoded_len > 0)
|
||||
if (s->no_encoder.buf_len > 0)
|
||||
{
|
||||
if (max_len > (s->pre_encoded_len - s->pre_encoded_ptr))
|
||||
max_len = s->pre_encoded_len - s->pre_encoded_ptr;
|
||||
memcpy(buf, &s->pre_encoded_buf[s->pre_encoded_ptr], max_len);
|
||||
s->pre_encoded_ptr += max_len;
|
||||
if (max_len > (s->no_encoder.buf_len - s->no_encoder.buf_ptr))
|
||||
max_len = s->no_encoder.buf_len - s->no_encoder.buf_ptr;
|
||||
memcpy(buf, &s->no_encoder.buf[s->no_encoder.buf_ptr], max_len);
|
||||
s->no_encoder.buf_ptr += max_len;
|
||||
return max_len;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
#include "spandsp/private/t81_t82_arith_coding.h"
|
||||
#include "spandsp/private/t85.h"
|
||||
|
||||
static __inline__ int32_t pack_32(uint8_t *s)
|
||||
static __inline__ int32_t pack_32(const uint8_t *s)
|
||||
{
|
||||
int32_t value;
|
||||
|
||||
|
@ -265,6 +265,16 @@ static int finish_sde(t85_decode_state_t *s)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(bool) t85_analyse_header(uint32_t *width, uint32_t *length, const uint8_t data[], size_t len)
|
||||
{
|
||||
if (len < 20)
|
||||
return false;
|
||||
*width = pack_32(&data[6]);
|
||||
*length = pack_32(&data[10]);
|
||||
return true;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int check_bih(t85_decode_state_t *s)
|
||||
{
|
||||
/* Check that the fixed parameters have the values they are expected to be
|
||||
|
|
Loading…
Reference in New Issue