/* * 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 //#if defined(WITH_SPANDSP_INTERNALS) #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES //#endif #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 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_flattened_image(image_translate_state_t *s, int compare) { int i; int len; uint8_t row_buf[5000]; 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); printf("Test failed\n"); 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 dither_tests_gray16(void) { int i; int j; image_translate_state_t bw; image_translate_state_t *s = &bw; uint16_t image[50*50]; image_descriptor_t im; printf("Dithering from a 16 bit per sample gray scale to bi-level\n"); im.image = (const uint8_t *) image; im.width = 50; im.length = 50; im.bytes_per_pixel = 2; im.current_row = 0; for (i = 0; i < im.length; i++) { for (j = 0; j < im.width; j++) image[i*im.width + j] = j*1200; } s = image_translate_init(s, IMAGE_TRANSLATE_FROM_GRAY_16, im.width, im.length, -1, row_read, &im); get_flattened_image(s, TRUE); } /*- End of function --------------------------------------------------------*/ static void dither_tests_gray8(void) { int i; int j; image_translate_state_t bw; image_translate_state_t *s = &bw; uint8_t image[50*50]; image_descriptor_t im; printf("Dithering from a 8 bit per sample gray scale to bi-level\n"); im.image = image; im.width = 50; im.length = 50; im.bytes_per_pixel = 1; im.current_row = 0; for (i = 0; i < im.length; i++) { for (j = 0; j < im.width; j++) image[i*im.width + j] = j*1200/256; } s = image_translate_init(s, IMAGE_TRANSLATE_FROM_GRAY_8, im.width, im.length, -1, row_read, &im); get_flattened_image(s, TRUE); } /*- End of function --------------------------------------------------------*/ static void dither_tests_colour16(void) { int i; int j; image_translate_state_t bw; image_translate_state_t *s = &bw; uint16_t image[50*50*3]; image_descriptor_t im; printf("Dithering from a 3x16 bit per sample colour to bi-level\n"); im.image = (const uint8_t *) image; im.width = 50; im.length = 50; im.bytes_per_pixel = 6; im.current_row = 0; for (i = 0; i < im.length; i++) { for (j = 0; j < im.width; j++) { image[i*3*im.width + 3*j + 0] = j*1200; image[i*3*im.width + 3*j + 1] = j*1200; image[i*3*im.width + 3*j + 2] = j*1200; } } s = image_translate_init(s, IMAGE_TRANSLATE_FROM_COLOUR_16, im.width, im.length, -1, row_read, &im); get_flattened_image(s, TRUE); } /*- End of function --------------------------------------------------------*/ static void dither_tests_colour8(void) { int i; int j; image_translate_state_t bw; image_translate_state_t *s = &bw; uint8_t image[50*50*3]; image_descriptor_t im; printf("Dithering from a 3x8 bit per sample colour to bi-level\n"); im.image = image; im.width = 50; im.length = 50; im.bytes_per_pixel = 3; im.current_row = 0; for (i = 0; i < im.length; i++) { for (j = 0; j < im.width; j++) { image[i*3*im.width + 3*j + 0] = j*1200/256; image[i*3*im.width + 3*j + 1] = j*1200/256; image[i*3*im.width + 3*j + 2] = j*1200/256; } } s = image_translate_init(s, IMAGE_TRANSLATE_FROM_COLOUR_8, im.width, im.length, -1, row_read, &im); get_flattened_image(s, TRUE); } /*- End of function --------------------------------------------------------*/ static void grow_tests_colour8(void) { int i; int j; image_translate_state_t resize; image_translate_state_t *s1 = &resize; uint8_t image[50*50*3]; image_descriptor_t im; printf("Image growth tests\n"); im.image = image; im.width = 50; im.length = 50; im.bytes_per_pixel = 3; im.current_row = 0; for (i = 0; i < im.length; i++) { for (j = 0; j < im.width; j++) { image[i*3*im.width + 3*j + 0] = j*1200/256; image[i*3*im.width + 3*j + 1] = j*1200/256; image[i*3*im.width + 3*j + 2] = j*1200/256; } } s1 = image_translate_init(s1, IMAGE_TRANSLATE_FROM_COLOUR_8, im.width, im.length, 200, row_read, &im); get_flattened_image(s1, FALSE); } /*- End of function --------------------------------------------------------*/ static void lenna_tests(int output_width, const char *file) { TIFF *in_file; TIFF *out_file; int image_width; int image_length; int output_length; uint8_t *image; uint8_t *image2; int len; int total; int16_t bits_per_sample; int16_t samples_per_pixel; int i; int n; image_translate_state_t bw; image_translate_state_t *s = &bw; image_descriptor_t im; printf("Dithering Lenna from colour to bi-level 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; 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, %d bits per sample, %d samples per pixel\n", image_width, image_length, 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("Image size %d %d\n", total, image_width*image_length*samples_per_pixel); TIFFClose(in_file); im.image = image; im.width = image_width; im.length = image_length; im.current_row = 0; im.bytes_per_pixel = samples_per_pixel; s = image_translate_init(s, IMAGE_TRANSLATE_FROM_COLOUR_8, image_width, image_length, output_width, row_read, &im); output_width = image_translate_get_output_width(s); output_length = image_translate_get_output_length(s); 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_BITSPERSAMPLE, 1); TIFFSetField(out_file, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(out_file, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(out_file, TIFFTAG_ROWSPERSTRIP, -1); TIFFSetField(out_file, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(out_file, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE); TIFFSetField(out_file, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB); TIFFSetField(out_file, TIFFTAG_PAGENUMBER, 0, 1); TIFFSetField(out_file, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE); TIFFSetField(out_file, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB); printf("Input %d x %d, output %d x %d\n", image_width, image_length, output_width, output_length); 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, output_width*output_length/8); TIFFWriteDirectory(out_file); TIFFClose(out_file); } /*- End of function --------------------------------------------------------*/ int main(int argc, char **argv) { #if 1 dither_tests_gray16(); dither_tests_gray8(); dither_tests_colour16(); dither_tests_colour8(); #endif #if 1 grow_tests_colour8(); #endif #if 1 lenna_tests(0, "lenna-bw.tif"); lenna_tests(1728, "lenna-bw-1728.tif"); lenna_tests(200, "lenna-bw-200.tif"); #endif printf("Tests passed.\n"); return 0; } /*- End of function --------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/