/* * SpanDSP - a series of DSP components for telephony * * image_translate_tests.c - Tests for the image translation routines. * * Written by Steve Underwood * * Copyright (C) 2009 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 image_translate_tests_page Image translation tests \section image_translate_tests_page_sec_1 What does it do? */ #if defined(HAVE_CONFIG_H) #include "config.h" #endif #include #include #include #include #include #include #include #include #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES #include "spandsp.h" #define INPUT_TIFF_FILE_NAME "../test-data/local/lenna-colour.tif" typedef struct { const uint8_t *image; int width; int length; int current_row; int bytes_per_pixel; } image_descriptor_t; static void display_row(int row, int width, uint8_t buf[]) { int i; int test_pixel; printf("%3d: ", row); for (i = 0; i < width; i++) { test_pixel = (buf[i >> 3] >> (7 - (i & 7))) & 0x01; printf("%c", (test_pixel) ? ' ' : '@'); } printf("\n"); } /*- End of function --------------------------------------------------------*/ static void create_undithered_50_by_50(image_descriptor_t *im, uint8_t buf[], int bytes_per_pixel) { unsigned int i; unsigned int j; uint8_t *image8; uint16_t *image16; int samples_per_pixel; im->image = (const uint8_t *) buf; im->width = 50; im->length = 50; im->bytes_per_pixel = bytes_per_pixel; im->current_row = 0; switch (bytes_per_pixel) { case 1: samples_per_pixel = 1; image8 = buf; for (i = 0; i < im->length; i++) { 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 < im->length; i++) { 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 < im->length; i++) { for (j = 0; j < im->width; j++) { #if 0 image8[samples_per_pixel*(im->width*i + j) + 0] = ((i + j)*655) >> 8; image8[samples_per_pixel*(im->width*i + j) + 1] = ((i + j)*655) >> 8; image8[samples_per_pixel*(im->width*i + j) + 2] = ((i + j)*655) >> 8; #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[samples_per_pixel*(im->width*i + j) + 0] = ((i + j)*655) >> 8; image8[samples_per_pixel*(im->width*i + j) + 1] = ((i + j)*655) >> 8; image8[samples_per_pixel*(im->width*i + j) + 2] = ((i + j)*655) >> 8; image8[samples_per_pixel*(im->width*i + j) + 3] = 0; #else image8[samples_per_pixel*(im->width*i + j) + 0] = saturateu8((((i + j)*655U)*36532U) >> 23); image8[samples_per_pixel*(im->width*i + j) + 1] = saturateu8((((i + j)*655U)*37216U) >> 24); image8[samples_per_pixel*(im->width*i + j) + 2] = saturateu8((((i + j)*655U)*47900U) >> 22); image8[samples_per_pixel*(im->width*i + j) + 3] = 0; #endif } } break; case 6: samples_per_pixel = 3; image16 = (uint16_t *) buf; for (i = 0; i < 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; #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); #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 } } break; } } /*- End of function --------------------------------------------------------*/ static int test_dithered_50_by_50(int row, int width, uint8_t buf[]) { static const char *image[50] = { " 0: @ @ @ @ @ @ @ @ ", " 1: @ @ @ @ @ @ @ @ @ @ @ @ @ @", " 2: @ @ @ @ @ @ @ @ @ @ @ @ @", " 3: @ @ @ @ @ @ @ @ @ @ @ @ @ @ ", " 4: @ @ @ @ @ @ @ @ @ @ @ @ @ @", " 5: @ @ @ @ @ @ @ @ @ @ @ @ @ ", " 6: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@", " 7: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ ", " 8: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ ", " 9: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @", " 10: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@ @@", " 11: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@ ", " 12: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@ @ @ @", " 13: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@ @", " 14: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@ @ @@", " 15: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@ @ @@ ", " 16: @ @ @ @ @ @ @ @ @ @ @@ @ @@@ @@", " 17: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @", " 18: @ @ @ @ @ @ @ @ @ @ @ @ @@ @@ @@ @@@ ", " 19: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@ @ @", " 20: @ @ @ @ @ @ @ @ @ @ @ @ @@ @@ @@@ @@@@@", " 21: @ @ @ @ @ @ @ @ @ @@ @ @ @ @ @ @ @ @@ @ @", " 22: @ @ @ @ @ @ @ @ @ @ @ @@ @@ @@@ @ @@ @@", " 23: @ @ @ @ @ @ @ @ @ @@ @ @ @ @ @ @ @@@ @@ @", " 24: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@ @@ @@@ @ @ @@ @@", " 25: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@@@@ @@@@", " 26: @ @ @ @ @ @ @ @ @ @ @ @ @@ @@ @@@ @ @ @@@ @ @", " 27: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@@ @@ @@@@@", " 28: @ @ @ @ @ @ @ @ @ @ @ @ @ @@ @@ @ @ @@ @@ @ @", " 29: @ @ @ @ @ @ @ @ @ @ @ @@ @@ @@ @@@@@ @@@ @@@@", " 30: @ @ @ @ @ @ @ @ @ @ @@ @@ @ @ @@ @ @@@ @@@ @@", " 31: @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@ @@@ @ @@ @@@ @@@@", " 32: @ @ @ @ @ @ @ @ @ @ @ @ @ @@ @@@@@ @@ @@@ @@", " 33: @ @ @ @ @ @ @ @ @ @ @ @@ @@@ @@ @ @ @ @@@@@ @@@@", " 34: @ @ @ @ @ @ @ @ @ @@ @ @ @ @@ @@@@@@@ @ @@@@ @@", " 35: @ @ @ @ @ @ @ @ @ @@ @@ @@ @@ @ @ @@@@@@ @@@@", " 36: @ @ @ @ @ @ @ @ @ @ @ @@ @@ @@ @@@ @@ @ @@@@@@ @", " 37: @ @ @ @ @ @ @ @ @@ @@ @ @ @@ @@ @ @@@@@@@ @@ @@@", " 38: @ @ @ @ @ @ @ @ @ @ @ @@@ @@ @@ @@@@ @ @@@@@@@@@@", " 39: @ @ @ @ @ @ @ @@ @@ @@ @@ @@@@ @@@@ @@ @@ @@@", " 40: @ @ @ @ @@ @ @ @@ @ @ @ @ @@ @@ @ @@ @@@@@@@@@@@@", " 41: @ @ @ @ @ @ @ @@ @ @@@ @@@ @@@ @@@@@@@@@ @@ @@ @@", " 42: @ @ @ @ @@ @ @ @ @@ @ @@ @@ @@@@ @ @ @@@@@@@@@@@@", " 43: @ @ @ @ @ @ @@ @@ @ @@ @@ @@@ @ @@@@@@@ @@ @@@@@@", " 44: @ @ @ @ @ @ @ @ @@ @@ @@ @@ @@@@@ @@ @@@@@@@@ @@@", " 45: @ @ @ @ @ @ @@ @@ @@ @@ @@ @@@ @ @@@@@@@@ @@@@@@@@", " 46: @ @ @ @ @ @ @@ @ @ @@ @@ @@ @@@@@ @ @@ @@@@@@@@@@", " 47: @ @ @ @ @ @@ @ @ @@@@ @@@@ @@@@@ @@@@@@@@@@@ @@@@@", " 48: @ @ @ @@ @ @@ @@ @ @@ @ @@@ @ @@@@@ @@@@@@@@@@@@@", " 49: @ @ @ @ @ @@ @@ @@ @@ @@@@ @@@@@@@ @@@@@@ @@@@@@@@" }; int i; int match; int ref_pixel; int test_pixel; match = 0; for (i = 0; i < width; i++) { ref_pixel = (image[row][i + 5] == ' '); test_pixel = (buf[i >> 3] >> (7 - (i & 7))) & 0x01; if (ref_pixel != test_pixel) match = -1; } return match; } /*- End of function --------------------------------------------------------*/ static int row_read(void *user_data, uint8_t buf[], size_t len) { image_descriptor_t *im; im = (image_descriptor_t *) user_data; if (im->current_row >= im->length) return 0; memcpy(buf, &im->image[im->current_row*im->width*im->bytes_per_pixel], len); im->current_row++; return len; } /*- End of function --------------------------------------------------------*/ static void get_bilevel_image(image_translate_state_t *s, int compare) { int i; int len; uint8_t row_buf[s->output_length*s->output_width/8]; for (i = 0; i < s->output_length; i++) { if ((len = image_translate_row(s, row_buf, (s->output_width + 7)/8)) != (s->output_width + 7)/8) { printf("Image finished early - %d %d\n", len, (s->output_width + 7)/8); exit(2); } display_row(i, s->output_width, row_buf); if (compare) { if (test_dithered_50_by_50(i, s->output_width, row_buf)) { printf("Dithered image mismatch at row %d\n", i); //exit(2); } } } if ((len = image_translate_row(s, row_buf, (s->output_width + 7)/8)) != 0) { printf("Image finished late - %d %d\n", len, (s->output_width + 7)/8); exit(2); } } /*- End of function --------------------------------------------------------*/ static void get_gray8_image(image_translate_state_t *s, int compare) { unsigned int i; unsigned int j; int len; uint8_t row_buf[s->output_length*s->output_width]; for (i = 0; i < s->output_length; i++) { if ((len = image_translate_row(s, row_buf, s->output_width)) != s->output_width) { printf("Image finished early - %d %d\n", len, s->output_width); exit(2); } if (compare) { for (j = 0; j < 50; j++) { if (row_buf[j] != (((i + j)*655) >> 8)) { printf("Image mismatch - %dx%d - %d %d\n", j, i, ((i + j)*655) >> 8, row_buf[j]); //exit(2); } } } } if ((len = image_translate_row(s, row_buf, s->output_width)) != 0) { printf("Image finished late - %d %d\n", len, s->output_width); exit(2); } } /*- End of function --------------------------------------------------------*/ static void get_gray16_image(image_translate_state_t *s, int compare) { unsigned int i; unsigned int j; int len; uint16_t row_buf[s->output_length*s->output_width]; for (i = 0; i < s->output_length; i++) { if ((len = image_translate_row(s, (uint8_t *) row_buf, 2*s->output_width)) != 2*s->output_width) { printf("Image finished early - %d %d\n", len, 2*s->output_width); exit(2); } if (compare) { for (j = 0; j < s->output_width; j++) { if (row_buf[j] != (i + j)*655) { printf("Image mismatch - %dx%d - %d %d\n", j, i, (i + j)*655, row_buf[j]); //exit(2); } } } } if ((len = image_translate_row(s, (uint8_t *) row_buf, 2*s->output_width)) != 0) { printf("Image finished late - %d %d\n", len, 2*s->output_width); exit(2); } } /*- End of function --------------------------------------------------------*/ 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[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, samples_per_pixel*s->output_width)) != samples_per_pixel*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 < s->output_width; j++) { #if 0 r = ((i + j)*655) >> 8; g = ((i + j)*655) >> 8; b = ((i + j)*655) >> 8; #else r = saturateu8((((i + j)*655U)*36532U) >> 23); g = saturateu8((((i + j)*655U)*37216U) >> 24); b = saturateu8((((i + j)*655U)*47900U) >> 22); #endif 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[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, samples_per_pixel*s->output_width)) != 0) { printf("Image finished late - %d %d\n", len, samples_per_pixel*s->output_width); exit(2); } } /*- End of function --------------------------------------------------------*/ 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[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, 2*samples_per_pixel*s->output_width)) != 2*samples_per_pixel*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 < s->output_width; j++) { #if 0 r = (i + j)*655; g = (i + j)*655; b = (i + j)*655; #else r = saturateu16((((i + j)*655U)*36532U) >> 15); g = saturateu16((((i + j)*655U)*37216U) >> 16); b = saturateu16((((i + j)*655U)*47900U) >> 14); #endif 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[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, 2*samples_per_pixel*s->output_width)) != 0) { printf("Image finished late - %d %d\n", len, 2*samples_per_pixel*s->output_width); exit(2); } } /*- End of function --------------------------------------------------------*/ static void translate_tests_gray8(void) { image_translate_state_t *s; uint8_t image[50*50]; image_descriptor_t im; printf("Dithering from a 8 bit per sample gray scale to bi-level\n"); create_undithered_50_by_50(&im, image, 1); s = image_translate_init(NULL, T4_IMAGE_TYPE_BILEVEL, -1, -1, T4_IMAGE_TYPE_GRAY_8BIT, im.width, im.length, row_read, &im); get_bilevel_image(s, true); printf("Scrunching from a 8 bit per sample gray scale to 8 bit per sample gray scale\n"); create_undithered_50_by_50(&im, image, 1); s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_8BIT, -1, -1, T4_IMAGE_TYPE_GRAY_8BIT, im.width, im.length, row_read, &im); get_gray8_image(s, true); printf("Scrunching from a 8 bit per sample gray scale to 16 bit per sample gray scale\n"); create_undithered_50_by_50(&im, image, 1); s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_12BIT, -1, -1, T4_IMAGE_TYPE_GRAY_8BIT, im.width, im.length, row_read, &im); get_gray16_image(s, true); printf("Scrunching from a 8 bit per sample gray scale to 3x8 bit per sample colour\n"); create_undithered_50_by_50(&im, image, 1); s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_8BIT, -1, -1, T4_IMAGE_TYPE_GRAY_8BIT, im.width, im.length, row_read, &im); get_colour8_image(s, true); printf("Scrunching from a 8 bit per sample gray scale to 3x16 bit per sample colour\n"); create_undithered_50_by_50(&im, image, 1); s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_12BIT, -1, -1, T4_IMAGE_TYPE_GRAY_8BIT, im.width, im.length, row_read, &im); get_colour16_image(s, true); image_translate_free(s); } /*- 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_colour8(void) { image_translate_state_t *s; uint8_t image[3*50*50]; image_descriptor_t im; printf("Dithering from a 3x8 bit per sample colour to bi-level\n"); create_undithered_50_by_50(&im, image, 3); s = image_translate_init(NULL, T4_IMAGE_TYPE_BILEVEL, -1, -1, T4_IMAGE_TYPE_COLOUR_8BIT, im.width, im.length, row_read, &im); get_bilevel_image(s, true); printf("Scrunching from a 3x8 bit per sample colour to 8 bit per sample gray scale\n"); create_undithered_50_by_50(&im, image, 3); s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_8BIT, -1, -1, T4_IMAGE_TYPE_COLOUR_8BIT, im.width, im.length, row_read, &im); get_gray8_image(s, true); printf("Scrunching from a 3x8 bit per sample colour to 16 bit per sample gray scale\n"); create_undithered_50_by_50(&im, image, 3); s = image_translate_init(s, T4_IMAGE_TYPE_GRAY_12BIT, -1, -1, T4_IMAGE_TYPE_COLOUR_8BIT, im.width, im.length, row_read, &im); get_gray16_image(s, true); printf("Scrunching from a 3x8 bit per sample colour to 3x8 bit per sample colour\n"); create_undithered_50_by_50(&im, image, 3); s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_8BIT, -1, -1, T4_IMAGE_TYPE_COLOUR_8BIT, im.width, im.length, row_read, &im); get_colour8_image(s, true); printf("Scrunching from a 3x8 bit per sample colour to 3x16 bit per sample colour\n"); create_undithered_50_by_50(&im, image, 3); s = image_translate_init(s, T4_IMAGE_TYPE_COLOUR_12BIT, -1, -1, T4_IMAGE_TYPE_COLOUR_8BIT, im.width, im.length, row_read, &im); get_colour16_image(s, true); image_translate_free(s); } /*- 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[3*50*50]; image_descriptor_t im; printf("Image growth tests\n"); create_undithered_50_by_50(&im, image, 3); s = image_translate_init(NULL, T4_IMAGE_TYPE_BILEVEL, 200, -1, T4_IMAGE_TYPE_COLOUR_8BIT, im.width, im.length, row_read, &im); get_bilevel_image(s, false); image_translate_free(s); } /*- End of function --------------------------------------------------------*/ static int row_read2(void *user_data, uint8_t buf[], size_t len) { image_translate_state_t *s; s = (image_translate_state_t *) user_data; image_translate_row(s, buf, len); return len; } /*- End of function --------------------------------------------------------*/ static void lenna_tests(int output_width, int output_length_scaling, const char *file) { TIFF *in_file; TIFF *out_file; int image_width; int image_length; int output_length; int len; int total; 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; if (output_length_scaling >= 0) printf("Dithering Lenna from colour to bi-level test\n"); else printf("Processing Lenna test\n"); if ((in_file = TIFFOpen(INPUT_TIFF_FILE_NAME, "r")) == NULL) return; image_width = 0; TIFFGetField(in_file, TIFFTAG_IMAGEWIDTH, &image_width); if (image_width <= 0) return; image_length = 0; TIFFGetField(in_file, TIFFTAG_IMAGELENGTH, &image_length); if (image_length <= 0) return; x_resolution = 200.0; TIFFGetField(in_file, TIFFTAG_XRESOLUTION, &x_resolution); y_resolution = 200.0; TIFFGetField(in_file, TIFFTAG_YRESOLUTION, &y_resolution); res_unit = RESUNIT_INCH; TIFFGetField(in_file, TIFFTAG_RESOLUTIONUNIT, &res_unit); bits_per_sample = 0; TIFFGetField(in_file, TIFFTAG_BITSPERSAMPLE, &bits_per_sample); samples_per_pixel = 0; TIFFGetField(in_file, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel); printf("Original image is %d x %d, %.2f x %.2f resolution, %d bits per sample, %d samples per pixel\n", image_width, image_length, x_resolution, y_resolution, bits_per_sample, samples_per_pixel); if ((image = malloc(image_width*image_length*samples_per_pixel)) == NULL) return; for (total = 0, i = 0; i < 1000; i++) { len = TIFFReadEncodedStrip(in_file, i, &image[total], image_width*image_length*samples_per_pixel - total); if (len <= 0) break; total += len; if (total == image_width*image_length*samples_per_pixel) { printf("Done\n"); break; } } printf("Input image size %d %d\n", total, image_width*image_length*samples_per_pixel); TIFFClose(in_file); if (output_length_scaling > 0) output_length = (double) image_length*output_length_scaling*output_width/image_width; else output_length = -1; im.image = image; im.width = image_width; im.length = image_length; im.current_row = 0; im.bytes_per_pixel = samples_per_pixel; s2 = NULL; switch (output_length_scaling) { case -2: s = image_translate_init(NULL, T4_IMAGE_TYPE_GRAY_8BIT, output_width, output_length, T4_IMAGE_TYPE_COLOUR_8BIT, image_width, image_length, row_read, &im); output_width = image_translate_get_output_width(s); output_length = image_translate_get_output_length(s); s2 = image_translate_init(NULL, T4_IMAGE_TYPE_COLOUR_8BIT, -1, -1, T4_IMAGE_TYPE_GRAY_8BIT, output_width, output_length, row_read2, s); output_width = image_translate_get_output_width(s2); output_length = image_translate_get_output_length(s2); break; case -1: s = image_translate_init(NULL, T4_IMAGE_TYPE_COLOUR_8BIT, output_width, output_length, T4_IMAGE_TYPE_COLOUR_8BIT, image_width, image_length, row_read, &im); output_width = image_translate_get_output_width(s); output_length = image_translate_get_output_length(s); break; default: s = image_translate_init(NULL, T4_IMAGE_TYPE_BILEVEL, output_width, output_length, T4_IMAGE_TYPE_COLOUR_8BIT, image_width, image_length, row_read, &im); output_width = image_translate_get_output_width(s); output_length = image_translate_get_output_length(s); break; } if ((out_file = TIFFOpen(file, "w")) == NULL) return; TIFFSetField(out_file, TIFFTAG_IMAGEWIDTH, output_width); TIFFSetField(out_file, TIFFTAG_IMAGELENGTH, output_length); TIFFSetField(out_file, TIFFTAG_RESOLUTIONUNIT, res_unit); switch (output_length_scaling) { case -2: case -1: TIFFSetField(out_file, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(out_file, TIFFTAG_SAMPLESPERPIXEL, 3); TIFFSetField(out_file, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); break; default: TIFFSetField(out_file, TIFFTAG_BITSPERSAMPLE, 1); TIFFSetField(out_file, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(out_file, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE); break; } if (output_length_scaling > 0) y_resolution *= output_length_scaling; TIFFSetField(out_file, TIFFTAG_XRESOLUTION, x_resolution); TIFFSetField(out_file, TIFFTAG_YRESOLUTION, y_resolution); TIFFSetField(out_file, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(out_file, TIFFTAG_ROWSPERSTRIP, -1); TIFFSetField(out_file, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(out_file, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB); TIFFSetField(out_file, TIFFTAG_PAGENUMBER, 0, 1); printf("Input %d x %d, output %d x %d\n", image_width, image_length, output_width, output_length); switch (output_length_scaling) { case -2: if ((image2 = malloc(output_width*output_length*3)) == NULL) return; memset(image2, 0, output_width*output_length*3); n = 0; for (i = 0; i < output_length; i++) n += image_translate_row(s2, &image2[n], output_width*3); TIFFWriteEncodedStrip(out_file, 0, image2, n); break; case -1: if ((image2 = malloc(output_width*output_length*3)) == NULL) return; memset(image2, 0, output_width*output_length*3); n = 0; for (i = 0; i < output_length; i++) n += image_translate_row(s, &image2[n], output_width*3); TIFFWriteEncodedStrip(out_file, 0, image2, n); break; default: if ((image2 = malloc(output_width*output_length/8)) == NULL) return; memset(image2, 0, output_width*output_length/8); n = 0; for (i = 0; i < output_length; i++) n += image_translate_row(s, &image2[n], output_width/8); TIFFWriteEncodedStrip(out_file, 0, image2, n); break; } TIFFWriteDirectory(out_file); TIFFClose(out_file); image_translate_free(s); free(image); free(image2); } /*- End of function --------------------------------------------------------*/ int main(int argc, char **argv) { #if 1 translate_tests_gray16(); translate_tests_gray8(); translate_tests_colour16(); translate_tests_colour8(); #endif #if 1 grow_tests_colour8(); #endif #if 1 lenna_tests(0, 0, "lenna-bw.tif"); lenna_tests(200, 0, "lenna-bw-200.tif"); lenna_tests(1728, 0, "lenna-bw-1728.tif"); lenna_tests(1728, 2, "lenna-bw-1728-superfine.tif"); lenna_tests(1728, -1, "lenna-colour-1728.tif"); lenna_tests(1728, -2, "lenna-gray-1728.tif"); #endif printf("Tests passed.\n"); return 0; } /*- End of function --------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/