blob: 3bbcb898f1f66fc761325715a77d361279c750f7 [file] [log] [blame]
DRC2e7b76b2009-04-03 12:04:24 +00001/* Copyright (C)2004 Landmark Graphics Corporation
2 * Copyright (C)2005 Sun Microsystems, Inc.
DRCcfef7f12011-02-15 05:17:20 +00003 * Copyright (C)2009-2011 D. R. Commander
DRC2e7b76b2009-04-03 12:04:24 +00004 *
5 * This library is free software and may be redistributed and/or modified under
6 * the terms of the wxWindows Library License, Version 3.1 or (at your option)
7 * any later version. The full license is in the LICENSE.txt file included
8 * with this distribution.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * wxWindows Library License for more details.
14 */
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include "./rrtimer.h"
20#include "./turbojpeg.h"
DRCfbb67472010-11-24 04:02:37 +000021#ifndef _WIN32
22 #define stricmp strcasecmp
23#endif
DRC2e7b76b2009-04-03 12:04:24 +000024
DRC65d05c12010-02-18 00:40:17 +000025#define _catch(f) {if((f)==-1) {printf("TJPEG: %s\n", tjGetErrorStr()); bailout();}}
DRC2e7b76b2009-04-03 12:04:24 +000026
DRC61e51f92009-04-05 21:53:20 +000027const char *_subnamel[NUMSUBOPT]={"4:4:4", "4:2:2", "4:2:0", "GRAY"};
28const char *_subnames[NUMSUBOPT]={"444", "422", "420", "GRAY"};
DRCfbb67472010-11-24 04:02:37 +000029const int _hsf[NUMSUBOPT]={1, 2, 2, 1};
30const int _vsf[NUMSUBOPT]={1, 1, 2, 1};
31
DRC9e17f7d2010-12-10 04:59:13 +000032enum {YUVENCODE=1, YUVDECODE};
DRCfbb67472010-11-24 04:02:37 +000033int yuv=0;
DRC2e7b76b2009-04-03 12:04:24 +000034
DRC65d05c12010-02-18 00:40:17 +000035int exitstatus=0;
36#define bailout() {exitstatus=-1; goto finally;}
37
DRC2e7b76b2009-04-03 12:04:24 +000038int pixels[9][3]=
39{
40 {0, 255, 0},
41 {255, 0, 255},
42 {255, 255, 0},
43 {0, 0, 255},
44 {0, 255, 255},
45 {255, 0, 0},
46 {255, 255, 255},
47 {0, 0, 0},
48 {255, 0, 0}
49};
50
51void initbuf(unsigned char *buf, int w, int h, int ps, int flags)
52{
53 int roffset=(flags&TJ_BGR)?2:0, goffset=1, boffset=(flags&TJ_BGR)?0:2, i,
54 _i, j;
55 if(flags&TJ_ALPHAFIRST) {roffset++; goffset++; boffset++;}
56 memset(buf, 0, w*h*ps);
DRC09854f52010-11-04 22:39:59 +000057 if(ps==1)
58 {
59 for(_i=0; _i<16; _i++)
60 {
61 if(flags&TJ_BOTTOMUP) i=h-_i-1; else i=_i;
62 for(j=0; j<w; j++)
63 {
64 if(((_i/8)+(j/8))%2==0) buf[w*i+j]=255;
65 else buf[w*i+j]=76;
66 }
67 }
68 for(_i=16; _i<h; _i++)
69 {
70 if(flags&TJ_BOTTOMUP) i=h-_i-1; else i=_i;
71 for(j=0; j<w; j++)
72 {
73 if(((_i/8)+(j/8))%2==0) buf[w*i+j]=0;
74 else buf[w*i+j]=226;
75 }
76 }
77 return;
78 }
DRC2e7b76b2009-04-03 12:04:24 +000079 for(_i=0; _i<16; _i++)
80 {
81 if(flags&TJ_BOTTOMUP) i=h-_i-1; else i=_i;
82 for(j=0; j<w; j++)
83 {
84 buf[(w*i+j)*ps+roffset]=255;
85 if(((_i/8)+(j/8))%2==0)
86 {
87 buf[(w*i+j)*ps+goffset]=255;
88 buf[(w*i+j)*ps+boffset]=255;
89 }
90 }
91 }
92 for(_i=16; _i<h; _i++)
93 {
94 if(flags&TJ_BOTTOMUP) i=h-_i-1; else i=_i;
95 for(j=0; j<w; j++)
96 {
97 if(((_i/8)+(j/8))%2!=0)
98 {
99 buf[(w*i+j)*ps+roffset]=255;
100 buf[(w*i+j)*ps+goffset]=255;
101 }
102 }
103 }
104}
105
DRCea197882010-02-18 05:12:58 +0000106void dumpbuf(unsigned char *buf, int w, int h, int ps, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000107{
108 int roffset=(flags&TJ_BGR)?2:0, goffset=1, boffset=(flags&TJ_BGR)?0:2, i,
109 j;
DRCda58a912011-02-27 00:07:51 +0000110 printf("\n");
DRC2e7b76b2009-04-03 12:04:24 +0000111 for(i=0; i<h; i++)
112 {
113 for(j=0; j<w; j++)
114 {
115 printf("%.3d/%.3d/%.3d ", buf[(w*i+j)*ps+roffset],
DRCcce6b432011-02-23 01:41:26 +0000116 buf[(w*i+j)*ps+goffset], buf[(w*i+j)*ps+boffset]);
DRC2e7b76b2009-04-03 12:04:24 +0000117 }
118 printf("\n");
119 }
120}
121
122int checkbuf(unsigned char *buf, int w, int h, int ps, int subsamp, int flags)
123{
124 int roffset=(flags&TJ_BGR)?2:0, goffset=1, boffset=(flags&TJ_BGR)?0:2, i,
125 _i, j;
126 if(flags&TJ_ALPHAFIRST) {roffset++; goffset++; boffset++;}
DRC09854f52010-11-04 22:39:59 +0000127 if(ps==1) roffset=goffset=boffset=0;
DRC2e7b76b2009-04-03 12:04:24 +0000128 if(subsamp==TJ_GRAYSCALE)
129 {
130 for(_i=0; _i<16; _i++)
131 {
132 if(flags&TJ_BOTTOMUP) i=h-_i-1; else i=_i;
133 for(j=0; j<w; j++)
134 {
135 unsigned char r=buf[(w*i+j)*ps+roffset],
136 g=buf[(w*i+j)*ps+goffset],
137 b=buf[(w*i+j)*ps+boffset];
138 if(((_i/8)+(j/8))%2==0)
139 {
140 if(r<253 || g<253 || b<253) return 0;
141 }
142 else
143 {
144 if(r<74 || r>78 || g<74 || g>78 || b<74 || b>78) return 0;
145 }
146 }
147 }
148 for(_i=16; _i<h; _i++)
149 {
150 if(flags&TJ_BOTTOMUP) i=h-_i-1; else i=_i;
151 for(j=0; j<w; j++)
152 {
153 unsigned char r=buf[(w*i+j)*ps+roffset],
154 g=buf[(w*i+j)*ps+goffset],
155 b=buf[(w*i+j)*ps+boffset];
156 if(((_i/8)+(j/8))%2==0)
157 {
158 if(r>2 || g>2 || b>2) return 0;
159 }
160 else
161 {
162 if(r<224 || r>228 || g<224 || g>228 || b<224 || b>228) return 0;
163 }
164 }
165 }
166 }
167 else
168 {
169 for(_i=0; _i<16; _i++)
170 {
171 if(flags&TJ_BOTTOMUP) i=h-_i-1; else i=_i;
172 for(j=0; j<w; j++)
173 {
174 if(buf[(w*i+j)*ps+roffset]<253) return 0;
175 if(((_i/8)+(j/8))%2==0)
176 {
177 if(buf[(w*i+j)*ps+goffset]<253) return 0;
178 if(buf[(w*i+j)*ps+boffset]<253) return 0;
179 }
180 else
181 {
182 if(buf[(w*i+j)*ps+goffset]>2) return 0;
183 if(buf[(w*i+j)*ps+boffset]>2) return 0;
184 }
185 }
186 }
187 for(_i=16; _i<h; _i++)
188 {
189 if(flags&TJ_BOTTOMUP) i=h-_i-1; else i=_i;
190 for(j=0; j<w; j++)
191 {
192 if(buf[(w*i+j)*ps+boffset]>2) return 0;
193 if(((_i/8)+(j/8))%2==0)
194 {
195 if(buf[(w*i+j)*ps+roffset]>2) return 0;
196 if(buf[(w*i+j)*ps+goffset]>2) return 0;
197 }
198 else
199 {
200 if(buf[(w*i+j)*ps+roffset]<253) return 0;
201 if(buf[(w*i+j)*ps+goffset]<253) return 0;
202 }
203 }
204 }
205 }
206 return 1;
207}
208
DRCfbb67472010-11-24 04:02:37 +0000209#define checkval(v, cv) { \
210 if(v<cv-1 || v>cv+1) { \
211 printf("\nComp. %s at %d,%d should be %d, not %d\n", #v, i, j, cv, v); \
212 retval=0; goto bailout; \
213 }}
214
215#define checkval0(v) { \
216 if(v>1) { \
217 printf("\nComp. %s at %d,%d should be 0, not %d\n", #v, i, j, v); \
218 retval=0; goto bailout; \
219 }}
220
221#define checkval255(v) { \
DRC6ee54592011-03-01 08:18:30 +0000222 if(v<254) { \
DRCfbb67472010-11-24 04:02:37 +0000223 printf("\nComp. %s at %d,%d should be 255, not %d\n", #v, i, j, v); \
224 retval=0; goto bailout; \
225 }}
226
227#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
228
DRCeeab6952011-02-25 00:02:04 +0000229int checkbufyuv(unsigned char *buf, int w, int h, int subsamp)
DRCfbb67472010-11-24 04:02:37 +0000230{
231 int i, j;
232 int hsf=_hsf[subsamp], vsf=_vsf[subsamp];
233 int pw=PAD(w, hsf), ph=PAD(h, vsf);
DRCf9cf5c72010-12-10 10:58:49 +0000234 int cw=pw/hsf, ch=ph/vsf;
235 int ypitch=PAD(pw, 4), uvpitch=PAD(cw, 4);
DRCfbb67472010-11-24 04:02:37 +0000236 int retval=1;
DRCfbb67472010-11-24 04:02:37 +0000237
238 for(i=0; i<16; i++)
239 {
240 for(j=0; j<pw; j++)
241 {
242 unsigned char y=buf[ypitch*i+j];
243 if(((i/8)+(j/8))%2==0) checkval255(y)
244 else checkval(y, 76)
245 }
246 }
247 for(i=16; i<ph; i++)
248 {
249 for(j=0; j<pw; j++)
250 {
251 unsigned char y=buf[ypitch*i+j];
252 if(((i/8)+(j/8))%2==0) checkval0(y)
253 else checkval(y, 226)
254 }
255 }
256 if(subsamp!=TJ_GRAYSCALE)
257 {
258 for(i=0; i<16/vsf; i++)
259 {
260 for(j=0; j<cw; j++)
261 {
262 unsigned char u=buf[ypitch*ph + (uvpitch*i+j)],
263 v=buf[ypitch*ph + uvpitch*ch + (uvpitch*i+j)];
264 if(((i*vsf/8)+(j*hsf/8))%2==0)
265 {
266 checkval(u, 128); checkval(v, 128);
267 }
268 else
269 {
270 checkval(u, 85); checkval255(v);
271 }
272 }
273 }
274 for(i=16/vsf; i<ch; i++)
275 {
276 for(j=0; j<cw; j++)
277 {
278 unsigned char u=buf[ypitch*ph + (uvpitch*i+j)],
279 v=buf[ypitch*ph + uvpitch*ch + (uvpitch*i+j)];
280 if(((i*vsf/8)+(j*hsf/8))%2==0)
281 {
282 checkval(u, 128); checkval(v, 128);
283 }
284 else
285 {
286 checkval0(u); checkval(v, 149);
287 }
288 }
289 }
290 }
291
292 bailout:
293 if(retval==0)
294 {
295 for(i=0; i<ph; i++)
296 {
297 for(j=0; j<pw; j++)
298 printf("%.3d ", buf[ypitch*i+j]);
299 printf("\n");
300 }
301 printf("\n");
302 for(i=0; i<ch; i++)
303 {
304 for(j=0; j<cw; j++)
305 printf("%.3d ", buf[ypitch*ph + (uvpitch*i+j)]);
306 printf("\n");
307 }
308 printf("\n");
309 for(i=0; i<ch; i++)
310 {
311 for(j=0; j<cw; j++)
312 printf("%.3d ", buf[ypitch*ph + uvpitch*ch + (uvpitch*i+j)]);
313 printf("\n");
314 }
315 printf("\n");
316 }
317
318 return retval;
319}
320
DRC2e7b76b2009-04-03 12:04:24 +0000321void writejpeg(unsigned char *jpegbuf, unsigned long jpgbufsize, char *filename)
322{
323 FILE *outfile=NULL;
324 if((outfile=fopen(filename, "wb"))==NULL)
325 {
326 printf("ERROR: Could not open %s for writing.\n", filename);
DRC65d05c12010-02-18 00:40:17 +0000327 bailout();
DRC2e7b76b2009-04-03 12:04:24 +0000328 }
329 if(fwrite(jpegbuf, jpgbufsize, 1, outfile)!=1)
330 {
331 printf("ERROR: Could not write to %s.\n", filename);
DRC65d05c12010-02-18 00:40:17 +0000332 bailout();
DRC2e7b76b2009-04-03 12:04:24 +0000333 }
334
335 finally:
336 if(outfile) fclose(outfile);
337}
338
339void gentestjpeg(tjhandle hnd, unsigned char *jpegbuf, unsigned long *size,
340 int w, int h, int ps, char *basefilename, int subsamp, int qual, int flags)
341{
342 char tempstr[1024]; unsigned char *bmpbuf=NULL;
343 const char *pixformat; double t;
344
345 if(flags&TJ_BGR)
346 {
347 if(ps==3) pixformat="BGR";
DRCb4b31402011-02-19 17:31:24 +0000348 else {if(flags&TJ_ALPHAFIRST) pixformat="XBGR"; else pixformat="BGRX";}
DRC2e7b76b2009-04-03 12:04:24 +0000349 }
350 else
351 {
352 if(ps==3) pixformat="RGB";
DRCb4b31402011-02-19 17:31:24 +0000353 else {if(flags&TJ_ALPHAFIRST) pixformat="XRGB"; else pixformat="RGBX";}
DRC2e7b76b2009-04-03 12:04:24 +0000354 }
DRC09854f52010-11-04 22:39:59 +0000355 if(ps==1) pixformat="Grayscale";
DRC9e17f7d2010-12-10 04:59:13 +0000356 if(yuv==YUVENCODE)
DRCfbb67472010-11-24 04:02:37 +0000357 printf("%s %s -> %s YUV ... ", pixformat,
358 (flags&TJ_BOTTOMUP)?"Bottom-Up":"Top-Down ", _subnamel[subsamp]);
359 else
360 printf("%s %s -> %s Q%d ... ", pixformat,
361 (flags&TJ_BOTTOMUP)?"Bottom-Up":"Top-Down ", _subnamel[subsamp], qual);
DRC2e7b76b2009-04-03 12:04:24 +0000362
363 if((bmpbuf=(unsigned char *)malloc(w*h*ps+1))==NULL)
364 {
DRC65d05c12010-02-18 00:40:17 +0000365 printf("ERROR: Could not allocate buffer\n"); bailout();
DRC2e7b76b2009-04-03 12:04:24 +0000366 }
367 initbuf(bmpbuf, w, h, ps, flags);
DRCeeab6952011-02-25 00:02:04 +0000368 memset(jpegbuf, 0,
369 yuv==YUVENCODE? TJBUFSIZEYUV(w, h, subsamp):TJBUFSIZE(w, h));
DRC2e7b76b2009-04-03 12:04:24 +0000370
371 t=rrtime();
DRCeeab6952011-02-25 00:02:04 +0000372 if(yuv==YUVENCODE)
373 {
374 _catch(tjEncodeYUV(hnd, bmpbuf, w, 0, h, ps, jpegbuf, subsamp, flags));
375 *size=TJBUFSIZEYUV(w, h, subsamp);
376 }
377 else
378 {
379 _catch(tjCompress(hnd, bmpbuf, w, 0, h, ps, jpegbuf, size, subsamp, qual,
380 flags));
381 }
DRC2e7b76b2009-04-03 12:04:24 +0000382 t=rrtime()-t;
383
DRC9e17f7d2010-12-10 04:59:13 +0000384 if(yuv==YUVENCODE)
DRCfbb67472010-11-24 04:02:37 +0000385 sprintf(tempstr, "%s_enc_%s_%s_%s.yuv", basefilename, pixformat,
386 (flags&TJ_BOTTOMUP)? "BU":"TD", _subnames[subsamp]);
387 else
388 sprintf(tempstr, "%s_enc_%s_%s_%sQ%d.jpg", basefilename, pixformat,
389 (flags&TJ_BOTTOMUP)? "BU":"TD", _subnames[subsamp], qual);
DRC2e7b76b2009-04-03 12:04:24 +0000390 writejpeg(jpegbuf, *size, tempstr);
DRC9e17f7d2010-12-10 04:59:13 +0000391 if(yuv==YUVENCODE)
DRCfbb67472010-11-24 04:02:37 +0000392 {
DRCeeab6952011-02-25 00:02:04 +0000393 if(checkbufyuv(jpegbuf, w, h, subsamp)) printf("Passed.");
DRCcfef7f12011-02-15 05:17:20 +0000394 else {printf("FAILED!"); exitstatus=-1;}
DRCfbb67472010-11-24 04:02:37 +0000395 }
396 else printf("Done.");
397 printf(" %f ms\n Result in %s\n", t*1000., tempstr);
DRC2e7b76b2009-04-03 12:04:24 +0000398
399 finally:
400 if(bmpbuf) free(bmpbuf);
401}
402
403void gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
DRC9e17f7d2010-12-10 04:59:13 +0000404 int w, int h, int ps, char *basefilename, int subsamp, int flags)
DRC2e7b76b2009-04-03 12:04:24 +0000405{
406 unsigned char *bmpbuf=NULL;
407 const char *pixformat; int _w=0, _h=0; double t;
DRC9e17f7d2010-12-10 04:59:13 +0000408 unsigned long size=0;
DRC2e7b76b2009-04-03 12:04:24 +0000409
DRCeeab6952011-02-25 00:02:04 +0000410 if(yuv==YUVENCODE) return;
DRCfbb67472010-11-24 04:02:37 +0000411
DRC2e7b76b2009-04-03 12:04:24 +0000412 if(flags&TJ_BGR)
413 {
414 if(ps==3) pixformat="BGR";
DRCb4b31402011-02-19 17:31:24 +0000415 else {if(flags&TJ_ALPHAFIRST) pixformat="XBGR"; else pixformat="BGRX";}
DRC2e7b76b2009-04-03 12:04:24 +0000416 }
417 else
418 {
419 if(ps==3) pixformat="RGB";
DRCb4b31402011-02-19 17:31:24 +0000420 else {if(flags&TJ_ALPHAFIRST) pixformat="XRGB"; else pixformat="RGBX";}
DRC2e7b76b2009-04-03 12:04:24 +0000421 }
DRC09854f52010-11-04 22:39:59 +0000422 if(ps==1) pixformat="Grayscale";
DRC9e17f7d2010-12-10 04:59:13 +0000423 if(yuv==YUVDECODE)
424 printf("JPEG -> YUV %s ... ", _subnames[subsamp]);
425 else
426 printf("JPEG -> %s %s ... ", pixformat,
427 (flags&TJ_BOTTOMUP)?"Bottom-Up":"Top-Down ");
DRC2e7b76b2009-04-03 12:04:24 +0000428
429 _catch(tjDecompressHeader(hnd, jpegbuf, jpegsize, &_w, &_h));
430 if(_w!=w || _h!=h)
431 {
DRC65d05c12010-02-18 00:40:17 +0000432 printf("Incorrect JPEG header\n"); bailout();
DRC2e7b76b2009-04-03 12:04:24 +0000433 }
434
DRCeeab6952011-02-25 00:02:04 +0000435 if(yuv==YUVDECODE) size=TJBUFSIZEYUV(w, h, subsamp);
436 else size=w*h*ps+1;
437 if((bmpbuf=(unsigned char *)malloc(size))==NULL)
DRC2e7b76b2009-04-03 12:04:24 +0000438 {
DRC65d05c12010-02-18 00:40:17 +0000439 printf("ERROR: Could not allocate buffer\n"); bailout();
DRC2e7b76b2009-04-03 12:04:24 +0000440 }
DRCeeab6952011-02-25 00:02:04 +0000441 memset(bmpbuf, 0, size);
DRC2e7b76b2009-04-03 12:04:24 +0000442
443 t=rrtime();
DRCeeab6952011-02-25 00:02:04 +0000444 if(yuv==YUVDECODE)
445 {
446 _catch(tjDecompressToYUV(hnd, jpegbuf, jpegsize, bmpbuf, flags));
447 }
448 else
449 {
450 _catch(tjDecompress(hnd, jpegbuf, jpegsize, bmpbuf, w, w*ps, h, ps,
451 flags));
452 }
DRC2e7b76b2009-04-03 12:04:24 +0000453 t=rrtime()-t;
454
DRC9e17f7d2010-12-10 04:59:13 +0000455 if(yuv==YUVDECODE)
456 {
DRCeeab6952011-02-25 00:02:04 +0000457 if(checkbufyuv(bmpbuf, w, h, subsamp)) printf("Passed.");
DRCcfef7f12011-02-15 05:17:20 +0000458 else {printf("FAILED!"); exitstatus=-1;}
DRC9e17f7d2010-12-10 04:59:13 +0000459 }
460 else
461 {
462 if(checkbuf(bmpbuf, w, h, ps, subsamp, flags)) printf("Passed.");
DRCcfef7f12011-02-15 05:17:20 +0000463 else
464 {
465 printf("FAILED!"); exitstatus=-1;
466 dumpbuf(bmpbuf, w, h, ps, flags);
467 }
DRC9e17f7d2010-12-10 04:59:13 +0000468 }
DRC2e7b76b2009-04-03 12:04:24 +0000469 printf(" %f ms\n\n", t*1000.);
470
471 finally:
472 if(bmpbuf) free(bmpbuf);
473}
474
475void dotest(int w, int h, int ps, int subsamp, char *basefilename)
476{
477 tjhandle hnd=NULL, dhnd=NULL; unsigned char *jpegbuf=NULL;
478 unsigned long size;
479
DRCeeab6952011-02-25 00:02:04 +0000480 size=(yuv==YUVENCODE? TJBUFSIZEYUV(w, h, subsamp):TJBUFSIZE(w, h));
481 if((jpegbuf=(unsigned char *)malloc(size)) == NULL)
DRC2e7b76b2009-04-03 12:04:24 +0000482 {
DRC65d05c12010-02-18 00:40:17 +0000483 puts("ERROR: Could not allocate buffer."); bailout();
DRC2e7b76b2009-04-03 12:04:24 +0000484 }
485
486 if((hnd=tjInitCompress())==NULL)
DRC65d05c12010-02-18 00:40:17 +0000487 {printf("Error in tjInitCompress():\n%s\n", tjGetErrorStr()); bailout();}
DRC2e7b76b2009-04-03 12:04:24 +0000488 if((dhnd=tjInitDecompress())==NULL)
DRC65d05c12010-02-18 00:40:17 +0000489 {printf("Error in tjInitDecompress():\n%s\n", tjGetErrorStr()); bailout();}
DRC2e7b76b2009-04-03 12:04:24 +0000490
491 gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, 0);
DRC9e17f7d2010-12-10 04:59:13 +0000492 gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, 0);
DRC2e7b76b2009-04-03 12:04:24 +0000493
DRC9e17f7d2010-12-10 04:59:13 +0000494 if(ps==1 || yuv==YUVDECODE) goto finally;
DRC09854f52010-11-04 22:39:59 +0000495
DRC2e7b76b2009-04-03 12:04:24 +0000496 gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_BGR);
DRC9e17f7d2010-12-10 04:59:13 +0000497 gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_BGR);
DRC2e7b76b2009-04-03 12:04:24 +0000498
499 gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_BOTTOMUP);
DRC9e17f7d2010-12-10 04:59:13 +0000500 gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_BOTTOMUP);
DRC2e7b76b2009-04-03 12:04:24 +0000501
502 gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_BGR|TJ_BOTTOMUP);
DRC9e17f7d2010-12-10 04:59:13 +0000503 gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_BGR|TJ_BOTTOMUP);
DRC2e7b76b2009-04-03 12:04:24 +0000504
505 if(ps==4)
506 {
507 gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST);
DRC9e17f7d2010-12-10 04:59:13 +0000508 gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_ALPHAFIRST);
DRC2e7b76b2009-04-03 12:04:24 +0000509
510 gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST|TJ_BGR);
DRC9e17f7d2010-12-10 04:59:13 +0000511 gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_ALPHAFIRST|TJ_BGR);
DRC2e7b76b2009-04-03 12:04:24 +0000512
513 gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST|TJ_BOTTOMUP);
DRC9e17f7d2010-12-10 04:59:13 +0000514 gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_ALPHAFIRST|TJ_BOTTOMUP);
DRC2e7b76b2009-04-03 12:04:24 +0000515
516 gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST|TJ_BGR|TJ_BOTTOMUP);
DRC9e17f7d2010-12-10 04:59:13 +0000517 gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_ALPHAFIRST|TJ_BGR|TJ_BOTTOMUP);
DRC2e7b76b2009-04-03 12:04:24 +0000518 }
519
520 finally:
521 if(hnd) tjDestroy(hnd);
522 if(dhnd) tjDestroy(dhnd);
523
524 if(jpegbuf) free(jpegbuf);
525}
526
527#define MAXLENGTH 2048
528
529void dotest1(void)
530{
531 int i, j, i2; unsigned char *bmpbuf=NULL, *jpgbuf=NULL;
532 tjhandle hnd=NULL; unsigned long size;
533 if((hnd=tjInitCompress())==NULL)
DRC65d05c12010-02-18 00:40:17 +0000534 {printf("Error in tjInitCompress():\n%s\n", tjGetErrorStr()); bailout();}
DRC2e7b76b2009-04-03 12:04:24 +0000535 printf("Buffer size regression test\n");
536 for(j=1; j<48; j++)
537 {
538 for(i=1; i<(j==1?MAXLENGTH:48); i++)
539 {
540 if(i%100==0) printf("%.4d x %.4d\b\b\b\b\b\b\b\b\b\b\b", i, j);
541 if((bmpbuf=(unsigned char *)malloc(i*j*4))==NULL
542 || (jpgbuf=(unsigned char *)malloc(TJBUFSIZE(i, j)))==NULL)
543 {
DRC65d05c12010-02-18 00:40:17 +0000544 printf("Memory allocation failure\n"); bailout();
DRC2e7b76b2009-04-03 12:04:24 +0000545 }
546 memset(bmpbuf, 0, i*j*4);
547 for(i2=0; i2<i*j; i2++)
548 {
549 bmpbuf[i2*4]=pixels[i2%9][2];
550 bmpbuf[i2*4+1]=pixels[i2%9][1];
DRCd5a69af2011-02-25 02:13:07 +0000551 bmpbuf[i2*4+2]=pixels[i2%9][0];
DRC2e7b76b2009-04-03 12:04:24 +0000552 }
DRCd5a69af2011-02-25 02:13:07 +0000553 _catch(tjCompress(hnd, bmpbuf, i, 0, j, 4,
DRC2e7b76b2009-04-03 12:04:24 +0000554 jpgbuf, &size, TJ_444, 100, TJ_BGR));
555 free(bmpbuf); bmpbuf=NULL; free(jpgbuf); jpgbuf=NULL;
556
557 if((bmpbuf=(unsigned char *)malloc(j*i*4))==NULL
558 || (jpgbuf=(unsigned char *)malloc(TJBUFSIZE(j, i)))==NULL)
559 {
DRC65d05c12010-02-18 00:40:17 +0000560 printf("Memory allocation failure\n"); bailout();
DRC2e7b76b2009-04-03 12:04:24 +0000561 }
DRCd5a69af2011-02-25 02:13:07 +0000562 for(i2=0; i2<j*i; i2++)
DRC2e7b76b2009-04-03 12:04:24 +0000563 {
DRCd5a69af2011-02-25 02:13:07 +0000564 if(i2%2==0) bmpbuf[i2*4]=bmpbuf[i2*4+1]=bmpbuf[i2*4+2]=0xFF;
565 else bmpbuf[i2*4]=bmpbuf[i2*4+1]=bmpbuf[i2*4+2]=0;
DRC2e7b76b2009-04-03 12:04:24 +0000566 }
DRCd5a69af2011-02-25 02:13:07 +0000567 _catch(tjCompress(hnd, bmpbuf, j, 0, i, 4,
DRC2e7b76b2009-04-03 12:04:24 +0000568 jpgbuf, &size, TJ_444, 100, TJ_BGR));
569 free(bmpbuf); bmpbuf=NULL; free(jpgbuf); jpgbuf=NULL;
570 }
571 }
572 printf("Done. \n");
573
574 finally:
575 if(bmpbuf) free(bmpbuf); if(jpgbuf) free(jpgbuf);
576 if(hnd) tjDestroy(hnd);
577}
578
579int main(int argc, char *argv[])
580{
DRC9e17f7d2010-12-10 04:59:13 +0000581 int doyuv=0;
582 if(argc>1 && !stricmp(argv[1], "-yuv")) doyuv=1;
583 if(doyuv) yuv=YUVENCODE;
584 dotest(35, 39, 3, TJ_444, "test");
585 dotest(39, 41, 4, TJ_444, "test");
586 if(doyuv)
DRCfbb67472010-11-24 04:02:37 +0000587 {
DRC9e17f7d2010-12-10 04:59:13 +0000588 dotest(41, 35, 3, TJ_422, "test");
589 dotest(35, 39, 4, TJ_422, "test");
590 dotest(39, 41, 3, TJ_420, "test");
591 dotest(41, 35, 4, TJ_420, "test");
DRCfbb67472010-11-24 04:02:37 +0000592 }
DRC9e17f7d2010-12-10 04:59:13 +0000593 dotest(35, 39, 1, TJ_GRAYSCALE, "test");
594 dotest(39, 41, 3, TJ_GRAYSCALE, "test");
595 dotest(41, 35, 4, TJ_GRAYSCALE, "test");
596 if(!doyuv) dotest1();
597 if(doyuv)
598 {
599 yuv=YUVDECODE;
DRCf9cf5c72010-12-10 10:58:49 +0000600 dotest(48, 48, 3, TJ_444, "test");
DRC9e17f7d2010-12-10 04:59:13 +0000601 dotest(35, 39, 3, TJ_444, "test");
DRC404e82e2011-02-22 19:59:54 +0000602 dotest(48, 48, 3, TJ_422, "test");
603 dotest(39, 41, 3, TJ_422, "test");
604 dotest(48, 48, 3, TJ_420, "test");
605 dotest(41, 35, 3, TJ_420, "test");
DRC3484e0b2011-02-25 06:21:15 +0000606 dotest(48, 48, 3, TJ_GRAYSCALE, "test");
607 dotest(35, 39, 3, TJ_GRAYSCALE, "test");
DRCf9cf5c72010-12-10 10:58:49 +0000608 dotest(48, 48, 1, TJ_GRAYSCALE, "test");
DRC3484e0b2011-02-25 06:21:15 +0000609 dotest(39, 41, 1, TJ_GRAYSCALE, "test");
DRC9e17f7d2010-12-10 04:59:13 +0000610 }
DRC2e7b76b2009-04-03 12:04:24 +0000611
DRC65d05c12010-02-18 00:40:17 +0000612 return exitstatus;
DRC2e7b76b2009-04-03 12:04:24 +0000613}