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:
Steve Underwood 2013-08-21 20:08:17 +08:00
parent d2fb03eda1
commit c09dec0de1
8 changed files with 71 additions and 26 deletions

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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");

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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