Fixed jaggies in image resizing.
Split naming of T.81/T.42 type JPEG from normal JPEG. This is in preparation for allowing the selective output of normal JPEG (like most people want) and the T.81/T.42 type you might want for forwarding as T.37
This commit is contained in:
parent
d2fb03eda1
commit
c09dec0de1
|
@ -337,6 +337,7 @@ static int image_resize_row(image_translate_state_t *s, uint8_t buf[])
|
|||
double int_part;
|
||||
double frac_row;
|
||||
double frac_col;
|
||||
double width_scaling;
|
||||
#endif
|
||||
uint8_t *row8[2];
|
||||
uint16_t *row16[2];
|
||||
|
@ -352,17 +353,13 @@ static int image_resize_row(image_translate_state_t *s, uint8_t buf[])
|
|||
input_width = s->input_width - 1;
|
||||
input_length = s->input_length - 1;
|
||||
|
||||
skip = s->raw_output_row*input_length/output_length;
|
||||
skip = s->raw_output_row*input_length/output_length + 1;
|
||||
if (skip >= s->raw_input_row)
|
||||
{
|
||||
skip++;
|
||||
while (skip >= s->raw_input_row)
|
||||
{
|
||||
if (s->raw_input_row >= s->input_length)
|
||||
{
|
||||
s->raw_output_row = -1;
|
||||
break;
|
||||
}
|
||||
row_len = get_and_scrunch_row(s, s->raw_pixel_row[0]);
|
||||
if (row_len != s->output_width)
|
||||
{
|
||||
|
@ -380,6 +377,7 @@ static int image_resize_row(image_translate_state_t *s, uint8_t buf[])
|
|||
frac_row = ((s->raw_output_row*256*input_length)/output_length) & 0xFF;
|
||||
#else
|
||||
frac_row = modf((double) s->raw_output_row*input_length/output_length, &int_part);
|
||||
width_scaling = (double) input_width/output_width;
|
||||
#endif
|
||||
|
||||
switch (s->output_format)
|
||||
|
@ -402,7 +400,7 @@ static int image_resize_row(image_translate_state_t *s, uint8_t buf[])
|
|||
buf[3*i + j] = saturateu8(c1 + (((c2 - c1)*frac_row) >> 8));
|
||||
}
|
||||
#else
|
||||
frac_col = modf((double) i*input_width/output_width, &int_part);
|
||||
frac_col = modf(width_scaling*i, &int_part);
|
||||
x = 3*int_part;
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
|
@ -431,7 +429,7 @@ static int image_resize_row(image_translate_state_t *s, uint8_t buf[])
|
|||
buf16[3*i + j] = saturateu16(c1 + (((c2 - c1)*frac_row) >> 8));
|
||||
}
|
||||
#else
|
||||
frac_col = modf((double) i*input_width/output_width, &int_part);
|
||||
frac_col = modf(width_scaling*i, &int_part);
|
||||
x = 3*int_part;
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
|
@ -456,7 +454,7 @@ static int image_resize_row(image_translate_state_t *s, uint8_t buf[])
|
|||
c2 = row8[1][x] + (((row8[1][x + 1] - row8[1][x])*frac_col) >> 8);
|
||||
buf[i] = saturateu8(c1 + (((c2 - c1)*frac_row) >> 8));
|
||||
#else
|
||||
frac_col = modf((double) i*input_width/output_width, &int_part);
|
||||
frac_col = modf(width_scaling*i, &int_part);
|
||||
x = int_part;
|
||||
c1 = row8[0][x] + (row8[0][x + 1] - row8[0][x])*frac_col;
|
||||
c2 = row8[1][x] + (row8[1][x + 1] - row8[1][x])*frac_col;
|
||||
|
@ -478,7 +476,7 @@ static int image_resize_row(image_translate_state_t *s, uint8_t buf[])
|
|||
c2 = row16[1][x] + (((row16[1][x + 1] - row16[1][x])*frac_col) >> 8);
|
||||
buf[i] = saturateu8(c1 + (((c2 - c1)*frac_row) >> 8));
|
||||
#else
|
||||
frac_col = modf((double) i*input_width/output_width, &int_part);
|
||||
frac_col = modf(width_scaling*i, &int_part);
|
||||
x = int_part;
|
||||
c1 = row16[0][x] + (row16[0][x + 1] - row16[0][x])*frac_col;
|
||||
c2 = row16[1][x] + (row16[1][x + 1] - row16[1][x])*frac_col;
|
||||
|
|
|
@ -40,10 +40,13 @@ struct lab_params_s
|
|||
float offset_b;
|
||||
int ab_are_signed;
|
||||
|
||||
/* Illuminant */
|
||||
/* Illuminant, forward and reverse */
|
||||
float x_n;
|
||||
float y_n;
|
||||
float z_n;
|
||||
float x_rn;
|
||||
float y_rn;
|
||||
float z_rn;
|
||||
};
|
||||
|
||||
/* State of a working instance of the T.42 JPEG FAX encoder */
|
||||
|
|
|
@ -70,6 +70,12 @@ typedef enum
|
|||
T4_COMPRESSION_SYCC_T81 = 0x200,
|
||||
/*! T.88 monochrome JBIG2 compression */
|
||||
T4_COMPRESSION_T88 = 0x400,
|
||||
/*! Uncompressed image. This compression cannot be used for FAXes. It is provided for specifying
|
||||
output formats for received images. */
|
||||
T4_COMPRESSION_UNCOMPRESSED = 0x1000,
|
||||
/*! Conventional JPEG. This compression cannot be used for FAXes. It is provided for specifying
|
||||
output formats for received images. */
|
||||
T4_COMPRESSION_JPEG = 0x2000,
|
||||
/*! Support solour compression without sub-sampling */
|
||||
T4_COMPRESSION_NO_SUBSAMPLING = 0x800000,
|
||||
/*! Gray-scale support by multi-level codecs */
|
||||
|
|
|
@ -6706,9 +6706,9 @@ 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. 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_T42_T81;
|
||||
/* 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. */
|
||||
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);
|
||||
span_log_set_protocol(&s->logging, "T.30");
|
||||
|
|
|
@ -309,6 +309,9 @@ SPAN_DECLARE(void) set_lab_illuminant(lab_params_t *lab, float new_xn, float new
|
|||
lab->y_n = new_yn;
|
||||
lab->z_n = new_zn;
|
||||
}
|
||||
lab->x_rn = 1.0f/lab->x_n;
|
||||
lab->y_rn = 1.0f/lab->y_n;
|
||||
lab->z_rn = 1.0f/lab->z_n;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -475,9 +478,9 @@ SPAN_DECLARE(void) srgb_to_lab(lab_params_t *s, uint8_t lab[], const uint8_t srg
|
|||
z = 0.0193f*r + 0.1192f*g + 0.9505f*b;
|
||||
|
||||
/* Normalise for the illuminant */
|
||||
x /= s->x_n;
|
||||
y /= s->y_n;
|
||||
z /= s->z_n;
|
||||
x *= s->x_rn;
|
||||
y *= s->y_rn;
|
||||
z *= s->z_rn;
|
||||
|
||||
/* XYZ to Lab */
|
||||
xx = (x <= 0.008856f) ? (7.787f*x + 0.1379f) : cbrtf(x);
|
||||
|
@ -946,15 +949,16 @@ SPAN_DECLARE(int) t42_encode_restart(t42_encode_state_t *s, uint32_t image_width
|
|||
{
|
||||
/* ITU-YCC */
|
||||
/* Illuminant D65 */
|
||||
set_lab_illuminant(&s->lab, 95.047f, 100.000f, 108.883f);
|
||||
//set_lab_illuminant(&s->lab, 95.047f, 100.000f, 108.883f);
|
||||
set_lab_illuminant(&s->lab, 100.0f, 100.0f, 100.0f);
|
||||
set_lab_gamut(&s->lab, 0, 100, -127, 127, -127, 127, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ITULAB */
|
||||
/* Illuminant D50 */
|
||||
set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f);
|
||||
set_lab_illuminant(&s->lab, 95.047f, 100.000f, 108.883f);
|
||||
//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->compressed_image_size = 0;
|
||||
|
@ -1312,15 +1316,16 @@ SPAN_DECLARE(int) t42_decode_restart(t42_decode_state_t *s)
|
|||
{
|
||||
/* ITU-YCC */
|
||||
/* Illuminant D65 */
|
||||
set_lab_illuminant(&s->lab, 95.047f, 100.000f, 108.883f);
|
||||
//set_lab_illuminant(&s->lab, 95.047f, 100.000f, 108.883f);
|
||||
set_lab_illuminant(&s->lab, 100.0f, 100.0f, 100.0f);
|
||||
set_lab_gamut(&s->lab, 0, 100, -127, 127, -127, 127, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ITULAB */
|
||||
/* Illuminant D50 */
|
||||
set_lab_illuminant(&s->lab, 96.422f, 100.000f, 82.521f);
|
||||
set_lab_illuminant(&s->lab, 95.047f, 100.000f, 108.883f);
|
||||
//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);
|
||||
}
|
||||
|
||||
|
|
|
@ -123,6 +123,11 @@ SPAN_DECLARE(const char *) t4_compression_to_str(int compression)
|
|||
return "T.43";
|
||||
case T4_COMPRESSION_T45:
|
||||
return "T.45";
|
||||
/* Compressions which can only be used in TIFF files */
|
||||
case T4_COMPRESSION_UNCOMPRESSED:
|
||||
return "Uncompressed";
|
||||
case T4_COMPRESSION_JPEG:
|
||||
return "JPEG";
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
|
@ -238,13 +243,27 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
|
|||
break;
|
||||
#endif
|
||||
#if defined(SPANDSP_SUPPORT_T42)
|
||||
case T4_COMPRESSION_JPEG:
|
||||
output_compression = COMPRESSION_JPEG;
|
||||
bits_per_sample = 8;
|
||||
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;
|
||||
case T4_COMPRESSION_T42_T81:
|
||||
output_compression = COMPRESSION_JPEG;
|
||||
bits_per_sample = 8;
|
||||
if (t->image_type == T4_IMAGE_TYPE_COLOUR_8BIT)
|
||||
{
|
||||
samples_per_pixel = 3;
|
||||
photometric = PHOTOMETRIC_YCBCR; //PHOTOMETRIC_ITULAB;
|
||||
photometric = PHOTOMETRIC_ITULAB;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -306,12 +325,20 @@ static int set_tiff_directory_info(t4_rx_state_t *s)
|
|||
TIFFSetField(t->tiff_file, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_PHOTOMETRIC, photometric);
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB);
|
||||
if (t->compression == T4_COMPRESSION_T42_T81)
|
||||
switch (t->compression)
|
||||
{
|
||||
case T4_COMPRESSION_JPEG:
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_YCBCRSUBSAMPLING, 2, 2);
|
||||
//TIFFSetField(t->tiff_file, TIFFTAG_YCBCRSUBSAMPLING, 1, 1);
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_JPEGQUALITY, 75);
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
|
||||
break;
|
||||
case T4_COMPRESSION_T42_T81:
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_YCBCRSUBSAMPLING, 2, 2);
|
||||
//TIFFSetField(t->tiff_file, TIFFTAG_YCBCRSUBSAMPLING, 1, 1);
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_JPEGQUALITY, 75);
|
||||
TIFFSetField(t->tiff_file, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
|
||||
break;
|
||||
}
|
||||
/* TIFFTAG_STRIPBYTECOUNTS and TIFFTAG_STRIPOFFSETS are added automatically */
|
||||
|
||||
|
@ -815,10 +842,14 @@ static void select_tiff_compression(t4_rx_state_t *s, int output_image_type)
|
|||
}
|
||||
else
|
||||
{
|
||||
if ((s->supported_tiff_compressions & T4_COMPRESSION_T42_T81))
|
||||
if ((s->supported_tiff_compressions & T4_COMPRESSION_JPEG))
|
||||
s->tiff.compression = T4_COMPRESSION_JPEG;
|
||||
else if ((s->supported_tiff_compressions & T4_COMPRESSION_T42_T81))
|
||||
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_UNCOMPRESSED))
|
||||
s->tiff.compression = T4_COMPRESSION_UNCOMPRESSED;
|
||||
}
|
||||
s->tiff.image_type = output_image_type;
|
||||
}
|
||||
|
|
|
@ -2009,6 +2009,8 @@ SPAN_DECLARE(int) t4_tx_set_tx_image_format(t4_tx_state_t *s,
|
|||
/* We can't rework a bilevel image that fits none of the patterns */
|
||||
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;
|
||||
res = T4_IMAGE_FORMAT_OK;
|
||||
/* Any other kind of image might be resizable */
|
||||
s->metadata.image_width = T4_WIDTH_200_A4;
|
||||
|
|
|
@ -926,7 +926,7 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
t30_set_supported_colour_resolutions(t30_state[i], 0);
|
||||
}
|
||||
//t30_set_supported_output_compressions(t30_state[i], T4_COMPRESSION_T85);
|
||||
t30_set_supported_output_compressions(t30_state[i], T4_COMPRESSION_T6 | T4_COMPRESSION_JPEG);
|
||||
t30_set_ecm_capability(t30_state[i], use_ecm);
|
||||
t30_set_supported_compressions(t30_state[i],
|
||||
T4_COMPRESSION_T4_1D
|
||||
|
|
Loading…
Reference in New Issue