1 /* $Id: raw_decode.c,v 1.7 2015-08-16 20:08:21 bfriesen Exp $ */
2
3 /*
4 * Copyright (c) 2012, Frank Warmerdam <warmerdam@pobox.com>
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and
7 * its documentation for any purpose is hereby granted without fee, provided
8 * that (i) the above copyright notices and this permission notice appear in
9 * all copies of the software and related documentation, and (ii) the names of
10 * Sam Leffler and Silicon Graphics may not be used in any advertising or
11 * publicity relating to the software without the specific, prior written
12 * permission of Sam Leffler and Silicon Graphics.
13 *
14 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
16 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
17 *
18 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
19 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
20 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
21 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
22 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23 * OF THIS SOFTWARE.
24 */
25
26 /*
27 * TIFF Library
28 *
29 * The objective of this test suite is to test the JPEGRawDecode()
30 * interface via TIFReadEncodedTile(). This function with YCbCr subsampling
31 * is a frequent source of bugs.
32 */
33
34 #include "tif_config.h"
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #ifdef HAVE_UNISTD_H
40 # include <unistd.h>
41 #endif
42
43 #include "tiffio.h"
44
45 /*
46 Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is
47 not defined. Unfortunately, the MinGW and Borland compilers include
48 a typedef for INT32, which causes a conflict. MSVC does not include
49 a conficting typedef given the headers which are included.
50 */
51 #if defined(__BORLANDC__) || defined(__MINGW32__)
52 # define XMD_H 1
53 #endif
54
55 /*
56 The windows RPCNDR.H file defines boolean, but defines it with the
57 unsigned char size. You should compile JPEG library using appropriate
58 definitions in jconfig.h header, but many users compile library in wrong
59 way. That causes errors of the following type:
60
61 "JPEGLib: JPEG parameter struct mismatch: library thinks size is 432,
62 caller expects 464"
63
64 For such users we wil fix the problem here. See install.doc file from
65 the JPEG library distribution for details.
66 */
67
68 /* Define "boolean" as unsigned char, not int, per Windows custom. */
69 #if defined(__WIN32__) && !defined(__MINGW32__)
70 # ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
71 typedef unsigned char boolean;
72 # endif
73 # define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
74 #endif
75 #include "jpeglib.h" /* Needed for JPEG_LIB_VERSION */
76
77 static unsigned char cluster_0[] = { 0, 0, 2, 0, 138, 139 };
78 static unsigned char cluster_64[] = { 0, 0, 9, 6, 134, 119 };
79 static unsigned char cluster_128[] = { 44, 40, 63, 59, 230, 95 };
80
check_cluster(int cluster,unsigned char * buffer,unsigned char * expected_cluster)81 static int check_cluster( int cluster, unsigned char *buffer, unsigned char *expected_cluster ) {
82 unsigned char *target = buffer + cluster*6;
83
84 if (memcmp(target, expected_cluster, 6) == 0) {
85 return 0;
86 }
87
88 fprintf( stderr, "Cluster %d did not match expected results.\n", cluster );
89 fprintf( stderr,
90 "Expect: %3d %3d %3d %3d\n"
91 " %3d %3d\n",
92 expected_cluster[0], expected_cluster[1],
93 expected_cluster[4], expected_cluster[5],
94 expected_cluster[2], expected_cluster[3] );
95 fprintf( stderr,
96 " Got: %3d %3d %3d %3d\n"
97 " %3d %3d\n",
98 target[0], target[1],
99 target[4], target[5],
100 target[2], target[3] );
101 return 1;
102 }
103
check_rgb_pixel(int pixel,int min_red,int max_red,int min_green,int max_green,int min_blue,int max_blue,unsigned char * buffer)104 static int check_rgb_pixel( int pixel,
105 int min_red, int max_red,
106 int min_green, int max_green,
107 int min_blue, int max_blue,
108 unsigned char *buffer ) {
109 unsigned char *rgb = buffer + 3 * pixel;
110
111 if( rgb[0] >= min_red && rgb[0] <= max_red &&
112 rgb[1] >= min_green && rgb[1] <= max_green &&
113 rgb[2] >= min_blue && rgb[2] <= max_blue ) {
114 return 0;
115 }
116
117 fprintf( stderr, "Pixel %d did not match expected results.\n", pixel );
118 fprintf( stderr, "Got R=%d (expected %d..%d), G=%d (expected %d..%d), B=%d (expected %d..%d)\n",
119 rgb[0], min_red, max_red,
120 rgb[1], min_green, max_green,
121 rgb[2], min_blue, max_blue );
122 return 1;
123 }
124
check_rgba_pixel(int pixel,int min_red,int max_red,int min_green,int max_green,int min_blue,int max_blue,int min_alpha,int max_alpha,uint32 * buffer)125 static int check_rgba_pixel( int pixel,
126 int min_red, int max_red,
127 int min_green, int max_green,
128 int min_blue, int max_blue,
129 int min_alpha, int max_alpha,
130 uint32 *buffer ) {
131 /* RGBA images are upside down - adjust for normal ordering */
132 int adjusted_pixel = pixel % 128 + (127 - (pixel/128)) * 128;
133 uint32 rgba = buffer[adjusted_pixel];
134
135 if( TIFFGetR(rgba) >= (uint32) min_red &&
136 TIFFGetR(rgba) <= (uint32) max_red &&
137 TIFFGetG(rgba) >= (uint32) min_green &&
138 TIFFGetG(rgba) <= (uint32) max_green &&
139 TIFFGetB(rgba) >= (uint32) min_blue &&
140 TIFFGetB(rgba) <= (uint32) max_blue &&
141 TIFFGetA(rgba) >= (uint32) min_alpha &&
142 TIFFGetA(rgba) <= (uint32) max_alpha ) {
143 return 0;
144 }
145
146 fprintf( stderr, "Pixel %d did not match expected results.\n", pixel );
147 fprintf( stderr, "Got R=%d (expected %d..%d), G=%d (expected %d..%d), B=%d (expected %d..%d), A=%d (expected %d..%d)\n",
148 TIFFGetR(rgba), min_red, max_red,
149 TIFFGetG(rgba), min_green, max_green,
150 TIFFGetB(rgba), min_blue, max_blue,
151 TIFFGetA(rgba), min_alpha, max_alpha );
152 return 1;
153 }
154
155 int
main(int argc,char ** argv)156 main(int argc, char **argv)
157 {
158 TIFF *tif;
159 static const char *srcfilerel = "images/quad-tile.jpg.tiff";
160 char *srcdir = NULL;
161 char srcfile[1024];
162 unsigned short h, v;
163 int status;
164 unsigned char *buffer;
165 uint32 *rgba_buffer;
166 tsize_t sz, szout;
167 unsigned int pixel_status = 0;
168
169 (void) argc;
170 (void) argv;
171
172 if ((srcdir = getenv("srcdir")) == NULL) {
173 srcdir = ".";
174 }
175 if ((strlen(srcdir) + 1 + strlen(srcfilerel)) >= sizeof(srcfile)) {
176 fprintf( stderr, "srcdir too long %s\n", srcdir);
177 exit( 1 );
178 }
179 strcpy(srcfile,srcdir);
180 strcat(srcfile,"/");
181 strcat(srcfile,srcfilerel);
182
183 tif = TIFFOpen(srcfile,"r");
184 if ( tif == NULL ) {
185 fprintf( stderr, "Could not open %s\n", srcfile);
186 exit( 1 );
187 }
188
189 status = TIFFGetField(tif,TIFFTAG_YCBCRSUBSAMPLING, &h, &v);
190 if ( status == 0 || h != 2 || v != 2) {
191 fprintf( stderr, "Could not retrieve subsampling tag.\n" );
192 exit(1);
193 }
194
195 /*
196 * What is the appropriate size of a YCbCr encoded tile?
197 */
198 sz = TIFFTileSize(tif);
199 if( sz != 24576) {
200 fprintf(stderr, "tiles are %d bytes\n", (int)sz);
201 exit(1);
202 }
203
204 buffer = (unsigned char *) malloc(sz);
205
206 /*
207 * Read a tile in decompressed form, but still YCbCr subsampled.
208 */
209 szout = TIFFReadEncodedTile(tif,9,buffer,sz);
210 if (szout != sz) {
211 fprintf( stderr,
212 "Did not get expected result code from TIFFReadEncodedTile()(%d instead of %d)\n",
213 (int) szout, (int) sz );
214 return 1;
215 }
216
217 if( check_cluster( 0, buffer, cluster_0 )
218 || check_cluster( 64, buffer, cluster_64 )
219 || check_cluster( 128, buffer, cluster_128 ) ) {
220 exit(1);
221 }
222 free(buffer);
223
224 /*
225 * Read a tile using the built-in conversion to RGB format provided by the JPEG library.
226 */
227 TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
228
229 sz = TIFFTileSize(tif);
230 if( sz != 128*128*3) {
231 fprintf(stderr, "tiles are %d bytes\n", (int)sz);
232 exit(1);
233 }
234
235 buffer = (unsigned char *) malloc(sz);
236
237 szout = TIFFReadEncodedTile(tif,9,buffer,sz);
238 if (szout != sz) {
239 fprintf( stderr,
240 "Did not get expected result code from TIFFReadEncodedTile()(%d instead of %d)\n",
241 (int) szout, (int) sz );
242 return 1;
243 }
244
245 /*
246 * JPEG decoding is inherently inexact, so we can't test for exact
247 * pixel values. (Well, if we knew exactly which libjpeg version
248 * we were using, and with what settings, we could expect specific
249 * values ... but it's not worth the trouble to keep track of.)
250 * Hence, use ranges of expected values. The ranges may need to be
251 * widened over time as more versions of libjpeg appear.
252 */
253 pixel_status |= check_rgb_pixel( 0, 15, 18, 0, 0, 18, 41, buffer );
254 pixel_status |= check_rgb_pixel( 64, 0, 0, 0, 0, 0, 2, buffer );
255 pixel_status |= check_rgb_pixel( 512, 5, 6, 34, 36, 182, 196, buffer );
256
257 free( buffer );
258
259 TIFFClose(tif);
260
261 /*
262 * Reopen and test reading using the RGBA interface.
263 */
264 tif = TIFFOpen(srcfile,"r");
265
266 sz = 128 * 128 * sizeof(uint32);
267 rgba_buffer = (uint32 *) malloc(sz);
268
269 if (!TIFFReadRGBATile( tif, 1*128, 2*128, rgba_buffer )) {
270 fprintf( stderr, "TIFFReadRGBATile() returned failure code.\n" );
271 return 1;
272 }
273
274 /*
275 * Currently TIFFReadRGBATile() just uses JPEGCOLORMODE_RGB so this
276 * trivally matches the last results. Eventually we should actually
277 * accomplish it from the YCbCr subsampled buffer ourselves in which
278 * case the results may be subtly different but similar.
279 */
280 pixel_status |= check_rgba_pixel( 0, 15, 18, 0, 0, 18, 41, 255, 255,
281 rgba_buffer );
282 pixel_status |= check_rgba_pixel( 64, 0, 0, 0, 0, 0, 2, 255, 255,
283 rgba_buffer );
284 pixel_status |= check_rgba_pixel( 512, 5, 6, 34, 36, 182, 196, 255, 255,
285 rgba_buffer );
286
287 free( rgba_buffer );
288 TIFFClose(tif);
289
290 if (pixel_status) {
291 exit(1);
292 }
293
294 exit( 0 );
295 }
296
297 /* vim: set ts=8 sts=8 sw=8 noet: */
298 /*
299 * Local Variables:
300 * mode: c
301 * c-basic-offset: 8
302 * fill-column: 78
303 * End:
304 */
305