blob: 227729ad76e1b2fb6a258e622a6c3f90fc25c6b8 [file] [log] [blame]
DRC3bad53f2011-02-23 02:20:49 +00001/*
2 * Copyright (C)2011 D. R. Commander. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * - Neither the name of the libjpeg-turbo Project nor the names of its
13 * contributors may be used to endorse or promote products derived from this
14 * software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * This program tests the various code paths in the TurboJPEG JNI Wrapper
31 */
32
33import java.io.*;
34import java.util.*;
DRC84a1bcc2011-02-23 12:09:56 +000035import java.awt.image.*;
36import javax.imageio.*;
DRC3bad53f2011-02-23 02:20:49 +000037import org.libjpegturbo.turbojpeg.*;
38
39public class TJUnitTest {
40
41 private static final String classname=new TJUnitTest().getClass().getName();
42
43 private static void usage() {
44 System.out.println("\nUSAGE: java "+classname+" [options]\n");
45 System.out.println("Options:\n");
46 System.out.println("-yuv = test YUV encoding/decoding support\n");
DRC84a1bcc2011-02-23 12:09:56 +000047 System.out.println("-bi = test BufferedImage support\n");
DRC3bad53f2011-02-23 02:20:49 +000048 System.exit(1);
49 }
50
51 private final static String _subnamel[]=
52 {"4:4:4", "4:2:2", "4:2:0", "GRAY"};
53 private final static String _subnames[]=
54 {"444", "422", "420", "GRAY"};
55 private final static int _hsf[]={1, 2, 2, 1};
56 private final static int _vsf[]={1, 1, 2, 1};
57
58 private final static String _pixformatstr[]=
59 {"RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "Grayscale"};
60 private final static int _roffset[]=
61 {0, 2, 0, 2, 3, 1, 0};
62 private final static int _goffset[]=
63 {1, 1, 1, 1, 2, 2, 0};
64 private final static int _boffset[]=
65 {2, 0, 2, 0, 1, 3, 0};
DRC84a1bcc2011-02-23 12:09:56 +000066 private final static int biType[]=
67 {0, BufferedImage.TYPE_3BYTE_BGR, BufferedImage.TYPE_INT_BGR,
68 BufferedImage.TYPE_INT_RGB, 0, 0, BufferedImage.TYPE_BYTE_GRAY};
DRC3bad53f2011-02-23 02:20:49 +000069
70 private final static int _3byteFormats[]=
71 {TJ.PF_RGB, TJ.PF_BGR};
DRC84a1bcc2011-02-23 12:09:56 +000072 private final static int _3byteFormatsBI[]=
73 {TJ.PF_BGR};
DRC3bad53f2011-02-23 02:20:49 +000074 private final static int _4byteFormats[]=
75 {TJ.PF_RGBX, TJ.PF_BGRX, TJ.PF_XBGR, TJ.PF_XRGB};
DRC84a1bcc2011-02-23 12:09:56 +000076 private final static int _4byteFormatsBI[]=
77 {TJ.PF_RGBX, TJ.PF_BGRX};
DRC3bad53f2011-02-23 02:20:49 +000078 private final static int _onlyGray[]=
79 {TJ.PF_GRAY};
80 private final static int _onlyRGB[]=
81 {TJ.PF_RGB};
82
83 private final static int YUVENCODE=1, YUVDECODE=2;
84 private static int yuv=0;
DRC84a1bcc2011-02-23 12:09:56 +000085 private static boolean bi=false;
DRC3bad53f2011-02-23 02:20:49 +000086
87 private static int exitstatus=0;
88
89 private static double gettime()
90 {
91 return (double)System.nanoTime()/1.0e9;
92 }
93
94 private final static byte pixels[][]=
95 {
96 {0, (byte)255, 0},
97 {(byte)255, 0, (byte)255},
98 {(byte)255, (byte)255, 0},
99 {0, 0, (byte)255},
100 {0, (byte)255, (byte)255},
101 {(byte)255, 0, 0},
102 {(byte)255, (byte)255, (byte)255},
103 {0, 0, 0},
104 {(byte)255, 0, 0}
105 };
106
107 private static void initbuf(byte [] buf, int w, int h, int pf, int flags)
108 {
109 int roffset=_roffset[pf], goffset=_goffset[pf], boffset=_boffset[pf];
110 int ps=TJ.pixelSize[pf];
111 int i, _i, j;
112
113 Arrays.fill(buf, (byte)0);
114 if(pf==TJ.PF_GRAY)
115 {
116 for(_i=0; _i<16; _i++)
117 {
118 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
119 for(j=0; j<w; j++)
120 {
121 if(((_i/8)+(j/8))%2==0) buf[w*i+j]=(byte)255;
122 else buf[w*i+j]=76;
123 }
124 }
125 for(_i=16; _i<h; _i++)
126 {
127 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
128 for(j=0; j<w; j++)
129 {
130 if(((_i/8)+(j/8))%2==0) buf[w*i+j]=0;
131 else buf[w*i+j]=(byte)226;
132 }
133 }
134 return;
135 }
136 for(_i=0; _i<16; _i++)
137 {
138 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
139 for(j=0; j<w; j++)
140 {
141 buf[(w*i+j)*ps+roffset]=(byte)255;
142 if(((_i/8)+(j/8))%2==0)
143 {
144 buf[(w*i+j)*ps+goffset]=(byte)255;
145 buf[(w*i+j)*ps+boffset]=(byte)255;
146 }
147 }
148 }
149 for(_i=16; _i<h; _i++)
150 {
151 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
152 for(j=0; j<w; j++)
153 {
154 if(((_i/8)+(j/8))%2!=0)
155 {
156 buf[(w*i+j)*ps+roffset]=(byte)255;
157 buf[(w*i+j)*ps+goffset]=(byte)255;
158 }
159 }
160 }
161 }
162
DRC84a1bcc2011-02-23 12:09:56 +0000163 private static void initimg(BufferedImage img, int pf, int flags)
164 {
165 int i, _i, j, w=img.getWidth(), h=img.getHeight(), pixel;
166
167 if(pf==TJ.PF_GRAY)
168 {
169 for(_i=0; _i<16; _i++)
170 {
171 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
172 for(j=0; j<w; j++)
173 {
174 if(((_i/8)+(j/8))%2==0) pixel=0xFFFFFFFF;
175 else pixel=0xFF4C4C4C;
176 img.setRGB(j, i, pixel);
177 }
178 }
179 for(_i=16; _i<h; _i++)
180 {
181 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
182 for(j=0; j<w; j++)
183 {
184 if(((_i/8)+(j/8))%2==0) pixel=0xFF000000;
185 else pixel=0xFFE2E2E2;
186 img.setRGB(j, i, pixel);
187 }
188 }
189 return;
190 }
191 for(_i=0; _i<16; _i++)
192 {
193 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
194 for(j=0; j<w; j++)
195 {
196 pixel=0xFFFF0000;
197 if(((_i/8)+(j/8))%2==0) pixel|=0x0000FFFF;
198 img.setRGB(j, i, pixel);
199 }
200 }
201 for(_i=16; _i<h; _i++)
202 {
203 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
204 for(j=0; j<w; j++)
205 {
206 pixel=0;
207 if(((_i/8)+(j/8))%2!=0) pixel=0xFFFFFF00;
208 img.setRGB(j, i, pixel);
209 }
210 }
211 }
212
DRC3bad53f2011-02-23 02:20:49 +0000213 private static void dumpbuf(byte [] buf, int w, int h, int pf,
214 int scalefactor, int flags)
215 {
216 int ps=TJ.pixelSize[pf];
217 int roffset=_roffset[pf], goffset=_goffset[pf], boffset=_boffset[pf];
218 int i, j;
219
220 System.out.print("\n");
221 for(i=0; i<h; i++)
222 {
223 for(j=0; j<w; j++)
224 {
225 int r=buf[(w*i+j)*ps+roffset];
226 int g=buf[(w*i+j)*ps+goffset];
227 int b=buf[(w*i+j)*ps+boffset];
228 if(r<0) r+=256; if(g<0) g+=256; if(b<0) b+=256;
229 System.out.format("%3d/%3d/%3d ", r, g, b);
230 }
231 System.out.print("\n");
232 }
233 }
234
DRC84a1bcc2011-02-23 12:09:56 +0000235 private static void checkval(int i, int j, int v, String vname, int cv)
DRC3bad53f2011-02-23 02:20:49 +0000236 throws Exception
237 {
DRC84a1bcc2011-02-23 12:09:56 +0000238 v=(v<0)? v+256:v;
239 if(v<cv-1 || v>cv+1)
DRC3bad53f2011-02-23 02:20:49 +0000240 {
DRC84a1bcc2011-02-23 12:09:56 +0000241 throw new Exception("\nComp. "+vname+" at "+i+","+j+" should be "+cv
DRC3bad53f2011-02-23 02:20:49 +0000242 +", not "+v+"\n");
243 }
244 }
245
DRC84a1bcc2011-02-23 12:09:56 +0000246 private static void checkval0(int i, int j, int v, String vname)
DRC3bad53f2011-02-23 02:20:49 +0000247 throws Exception
248 {
DRC84a1bcc2011-02-23 12:09:56 +0000249 v=(v<0)? v+256:v;
250 if(v>1)
DRC3bad53f2011-02-23 02:20:49 +0000251 {
252 throw new Exception("\nComp. "+vname+" at "+i+","+j+" should be 0, not "
253 +v+"\n");
254 }
255 }
256
DRC84a1bcc2011-02-23 12:09:56 +0000257 private static void checkval255(int i, int j, int v, String vname)
DRC3bad53f2011-02-23 02:20:49 +0000258 throws Exception
259 {
DRC84a1bcc2011-02-23 12:09:56 +0000260 v=(v<0)? v+256:v;
261 if(v<254 && !(v==217 && i==0 && j==21))
DRC3bad53f2011-02-23 02:20:49 +0000262 {
263 throw new Exception("\nComp. "+vname+" at "+i+","+j+" should be 255, not "
264 +v+"\n");
265 }
266 }
267
268 private static int checkbuf(byte [] buf, int w, int h, int pf, int subsamp,
269 int scalefactor, int flags) throws Exception
270 {
271 int roffset=_roffset[pf], goffset=_goffset[pf], boffset=_boffset[pf];
272 int ps=TJ.pixelSize[pf];
273 int i, _i, j, retval=1;
274 int halfway=16/scalefactor, blocksize=8/scalefactor;
275
276 try
277 {
278 if(subsamp==TJ.SAMP_GRAY)
279 {
280 for(_i=0; _i<halfway; _i++)
281 {
282 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
283 for(j=0; j<w; j++)
284 {
285 byte r=buf[(w*i+j)*ps+roffset],
286 g=buf[(w*i+j)*ps+goffset],
287 b=buf[(w*i+j)*ps+boffset];
288 if(((_i/blocksize)+(j/blocksize))%2==0)
289 {
290 checkval255(_i, j, r, "R");
291 checkval255(_i, j, g, "G");
292 checkval255(_i, j, b, "B");
293 }
294 else
295 {
296 checkval(_i, j, r, "R", 76);
297 checkval(_i, j, g, "G", 76);
298 checkval(_i, j, b, "B", 76);
299 }
300 }
301 }
302 for(_i=halfway; _i<h; _i++)
303 {
304 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
305 for(j=0; j<w; j++)
306 {
307 byte r=buf[(w*i+j)*ps+roffset],
308 g=buf[(w*i+j)*ps+goffset],
309 b=buf[(w*i+j)*ps+boffset];
310 if(((_i/blocksize)+(j/blocksize))%2==0)
311 {
312 checkval0(_i, j, r, "R");
313 checkval0(_i, j, g, "G");
314 checkval0(_i, j, b, "B");
315 }
316 else
317 {
318 checkval(_i, j, r, "R", 226);
319 checkval(_i, j, g, "G", 226);
320 checkval(_i, j, b, "B", 226);
321 }
322 }
323 }
324 }
325 else
326 {
327 for(_i=0; _i<halfway; _i++)
328 {
329 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
330 for(j=0; j<w; j++)
331 {
332 checkval255(_i, j, buf[(w*i+j)*ps+roffset], "R");
333 if(((_i/blocksize)+(j/blocksize))%2==0)
334 {
335 checkval255(_i, j, buf[(w*i+j)*ps+goffset], "G");
336 checkval255(_i, j, buf[(w*i+j)*ps+boffset], "B");
337 }
338 else
339 {
340 checkval0(_i, j, buf[(w*i+j)*ps+goffset], "G");
341 checkval0(_i, j, buf[(w*i+j)*ps+boffset], "B");
342 }
343 }
344 }
345 for(_i=halfway; _i<h; _i++)
346 {
347 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
348 for(j=0; j<w; j++)
349 {
350 checkval0(_i, j, buf[(w*i+j)*ps+boffset], "B");
351 if(((_i/blocksize)+(j/blocksize))%2==0)
352 {
353 checkval0(_i, j, buf[(w*i+j)*ps+roffset], "R");
354 checkval0(_i, j, buf[(w*i+j)*ps+goffset], "G");
355 }
356 else
357 {
358 checkval255(_i, j, buf[(w*i+j)*ps+roffset], "R");
359 checkval255(_i, j, buf[(w*i+j)*ps+goffset], "G");
360 }
361 }
362 }
363 }
364 }
365 catch(Exception e)
366 {
367 System.out.println(e);
368 retval=0;
369 }
370 return retval;
371 }
372
DRC84a1bcc2011-02-23 12:09:56 +0000373 private static int checkimg(BufferedImage img, int pf,
374 int subsamp, int scalefactor, int flags) throws Exception
375 {
376 int i, _i, j, retval=1, w=img.getWidth(), h=img.getHeight();
377 int halfway=16/scalefactor, blocksize=8/scalefactor;
378
379 try
380 {
381 if(subsamp==TJ.SAMP_GRAY)
382 {
383 for(_i=0; _i<halfway; _i++)
384 {
385 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
386 for(j=0; j<w; j++)
387 {
388 int r=(img.getRGB(j, i)>>16) & 0xFF;
389 int g=(img.getRGB(j, i)>>8) & 0xFF;
390 int b=img.getRGB(j, i) & 0xFF;
391 if(((_i/blocksize)+(j/blocksize))%2==0)
392 {
393 checkval255(_i, j, r, "R");
394 checkval255(_i, j, g, "G");
395 checkval255(_i, j, b, "B");
396 }
397 else
398 {
399 checkval(_i, j, r, "R", 76);
400 checkval(_i, j, g, "G", 76);
401 checkval(_i, j, b, "B", 76);
402 }
403 }
404 }
405 for(_i=halfway; _i<h; _i++)
406 {
407 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
408 for(j=0; j<w; j++)
409 {
410 int r=(img.getRGB(j, i)>>16) & 0xFF;
411 int g=(img.getRGB(j, i)>>8) & 0xFF;
412 int b=img.getRGB(j, i) & 0xFF;
413 if(((_i/blocksize)+(j/blocksize))%2==0)
414 {
415 checkval0(_i, j, r, "R");
416 checkval0(_i, j, g, "G");
417 checkval0(_i, j, b, "B");
418 }
419 else
420 {
421 checkval(_i, j, r, "R", 226);
422 checkval(_i, j, g, "G", 226);
423 checkval(_i, j, b, "B", 226);
424 }
425 }
426 }
427 }
428 else
429 {
430 for(_i=0; _i<halfway; _i++)
431 {
432 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
433 for(j=0; j<w; j++)
434 {
435 int r=(img.getRGB(j, i)>>16) & 0xFF;
436 int g=(img.getRGB(j, i)>>8) & 0xFF;
437 int b=img.getRGB(j, i) & 0xFF;
438 checkval255(_i, j, r, "R");
439 if(((_i/blocksize)+(j/blocksize))%2==0)
440 {
441 checkval255(_i, j, g, "G");
442 checkval255(_i, j, b, "B");
443 }
444 else
445 {
446 checkval0(_i, j, g, "G");
447 checkval0(_i, j, b, "B");
448 }
449 }
450 }
451 for(_i=halfway; _i<h; _i++)
452 {
453 if((flags&TJ.BOTTOMUP)!=0) i=h-_i-1; else i=_i;
454 for(j=0; j<w; j++)
455 {
456 int r=(img.getRGB(j, i)>>16) & 0xFF;
457 int g=(img.getRGB(j, i)>>8) & 0xFF;
458 int b=img.getRGB(j, i) & 0xFF;
459 checkval0(_i, j, b, "B");
460 if(((_i/blocksize)+(j/blocksize))%2==0)
461 {
462 checkval0(_i, j, r, "R");
463 checkval0(_i, j, g, "G");
464 }
465 else
466 {
467 checkval255(_i, j, r, "R");
468 checkval255(_i, j, g, "G");
469 }
470 }
471 }
472 }
473 }
474 catch(Exception e)
475 {
476 System.out.println(e);
477 retval=0;
478 }
479 return retval;
480 }
481
DRC3bad53f2011-02-23 02:20:49 +0000482 private static int PAD(int v, int p)
483 {
484 return ((v+(p)-1)&(~((p)-1)));
485 }
486
487 private static int checkbufyuv(byte [] buf, int size, int w, int h,
488 int subsamp)
489 {
490 int i, j;
491 int hsf=_hsf[subsamp], vsf=_vsf[subsamp];
492 int pw=PAD(w, hsf), ph=PAD(h, vsf);
493 int cw=pw/hsf, ch=ph/vsf;
494 int ypitch=PAD(pw, 4), uvpitch=PAD(cw, 4);
495 int retval=1;
496 int correctsize=ypitch*ph + (subsamp==TJ.SAMP_GRAY? 0:uvpitch*ch*2);
497
498 try
499 {
500 if(size!=correctsize)
501 throw new Exception("\nIncorrect size "+size+". Should be "
502 +correctsize);
503
504 for(i=0; i<16; i++)
505 {
506 for(j=0; j<pw; j++)
507 {
508 byte y=buf[ypitch*i+j];
509 if(((i/8)+(j/8))%2==0) checkval255(i, j, y, "Y");
510 else checkval(i, j, y, "Y", 76);
511 }
512 }
513 for(i=16; i<ph; i++)
514 {
515 for(j=0; j<pw; j++)
516 {
517 byte y=buf[ypitch*i+j];
518 if(((i/8)+(j/8))%2==0) checkval0(i, j, y, "Y");
519 else checkval(i, j, y, "Y", 226);
520 }
521 }
522 if(subsamp!=TJ.SAMP_GRAY)
523 {
524 for(i=0; i<16/vsf; i++)
525 {
526 for(j=0; j<cw; j++)
527 {
528 byte u=buf[ypitch*ph + (uvpitch*i+j)],
529 v=buf[ypitch*ph + uvpitch*ch + (uvpitch*i+j)];
530 if(((i*vsf/8)+(j*hsf/8))%2==0)
531 {
532 checkval(i, j, u, "U", 128); checkval(i, j, v, "V", 128);
533 }
534 else
535 {
536 checkval(i, j, u, "U", 85); checkval255(i, j, v, "V");
537 }
538 }
539 }
540 for(i=16/vsf; i<ch; i++)
541 {
542 for(j=0; j<cw; j++)
543 {
544 byte u=buf[ypitch*ph + (uvpitch*i+j)],
545 v=buf[ypitch*ph + uvpitch*ch + (uvpitch*i+j)];
546 if(((i*vsf/8)+(j*hsf/8))%2==0)
547 {
548 checkval(i, j, u, "U", 128); checkval(i, j, v, "V", 128);
549 }
550 else
551 {
552 checkval0(i, j, u, "U"); checkval(i, j, v, "V", 149);
553 }
554 }
555 }
556 }
557 }
558 catch(Exception e)
559 {
560 System.out.println(e);
561 retval=0;
562 }
563
564 if(retval==0)
565 {
566 for(i=0; i<ph; i++)
567 {
568 for(j=0; j<pw; j++)
569 {
570 int y=buf[ypitch*i+j];
571 if(y<0) y+=256;
572 System.out.format("%3d ", y);
573 }
574 System.out.print("\n");
575 }
576 System.out.print("\n");
577 for(i=0; i<ch; i++)
578 {
579 for(j=0; j<cw; j++)
580 {
581 int u=buf[ypitch*ph + (uvpitch*i+j)];
582 if(u<0) u+=256;
583 System.out.format("%3d ", u);
584 }
585 System.out.print("\n");
586 }
587 System.out.print("\n");
588 for(i=0; i<ch; i++)
589 {
590 for(j=0; j<cw; j++)
591 {
592 int v=buf[ypitch*ph + uvpitch*ch + (uvpitch*i+j)];
593 if(v<0) v+=256;
594 System.out.format("%3d ", v);
595 }
596 System.out.print("\n");
597 }
598 System.out.print("\n");
599 }
600
601 return retval;
602 }
603
604 private static void writejpeg(byte [] jpegbuf, int jpgbufsize,
605 String filename) throws Exception
606 {
607 File file=new File(filename);
608 FileOutputStream fos=new FileOutputStream(file);
609 fos.write(jpegbuf, 0, jpgbufsize);
610 fos.close();
611 }
612
613 private static int gentestjpeg(TJCompressor tjc, byte [] jpegbuf, int w,
614 int h, int pf, String basefilename, int subsamp, int qual,
615 int flags) throws Exception
616 {
DRC84a1bcc2011-02-23 12:09:56 +0000617 String tempstr; byte [] bmpbuf=null; BufferedImage img=null;
DRC3bad53f2011-02-23 02:20:49 +0000618 String pixformat; double t;
DRC84a1bcc2011-02-23 12:09:56 +0000619 int size=0, ps=TJ.pixelSize[pf];
DRC3bad53f2011-02-23 02:20:49 +0000620
621 if(yuv==YUVENCODE) flags|=TJ.YUV;
622
623 pixformat=_pixformatstr[pf];
624
625 System.out.print(pixformat+" ");
626 if((flags&TJ.BOTTOMUP)!=0) System.out.print("Bottom-Up");
627 else System.out.print("Top-Down ");
628 System.out.print(" -> "+_subnamel[subsamp]+" ");
629 if(yuv==YUVENCODE) System.out.print("YUV ... ");
630 else System.out.print("Q"+qual+" ... ");
631
DRC84a1bcc2011-02-23 12:09:56 +0000632 if(bi)
633 {
634 img=new BufferedImage(w, h, biType[pf]);
635 initimg(img, pf, flags);
636 tempstr=basefilename+"_enc_"+pixformat+"_"
637 +(((flags&TJ.BOTTOMUP)!=0)? "BU":"TD")+"_"+_subnames[subsamp]
638 +"_Q"+qual+".png";
639 File file=new File(tempstr);
640 ImageIO.write(img, "png", file);
641 }
642 else
643 {
644 bmpbuf=new byte[w*h*ps+1];
645 initbuf(bmpbuf, w, h, pf, flags);
646 }
DRC3bad53f2011-02-23 02:20:49 +0000647 Arrays.fill(jpegbuf, (byte)0);
648
649 t=gettime();
DRC84a1bcc2011-02-23 12:09:56 +0000650 if(bi)
651 size=tjc.compress(img, jpegbuf, subsamp, qual, flags);
652 else
653 {
654 tjc.setBitmapBuffer(bmpbuf, w, 0, h, pf);
655 size=tjc.compress(jpegbuf, subsamp, qual, flags);
656 }
DRC3bad53f2011-02-23 02:20:49 +0000657 t=gettime()-t;
658
659 if(yuv==YUVENCODE)
660 tempstr=basefilename+"_enc_"+pixformat+"_"
661 +(((flags&TJ.BOTTOMUP)!=0)? "BU":"TD")+"_"+_subnames[subsamp]+".yuv";
662 else
663 tempstr=basefilename+"_enc_"+pixformat+"_"
664 +(((flags&TJ.BOTTOMUP)!=0)? "BU":"TD")+"_"+_subnames[subsamp]
665 +"_Q"+qual+".jpg";
666 writejpeg(jpegbuf, size, tempstr);
DRC84a1bcc2011-02-23 12:09:56 +0000667
DRC3bad53f2011-02-23 02:20:49 +0000668 if(yuv==YUVENCODE)
669 {
670 if(checkbufyuv(jpegbuf, size, w, h, subsamp)==1)
671 System.out.print("Passed.");
672 else {System.out.print("FAILED!"); exitstatus=-1;}
673 }
674 else System.out.print("Done.");
675 System.out.format(" %.6f ms\n", t*1000.);
676 System.out.println(" Result in "+tempstr);
677
678 return size;
679 }
680
681 private static void _gentestbmp(TJDecompressor tjd, byte [] jpegbuf,
682 int jpegsize, int w, int h, int pf, String basefilename, int subsamp,
683 int flags, int scalefactor) throws Exception
684 {
DRC84a1bcc2011-02-23 12:09:56 +0000685 String pixformat, tempstr; int _hdrw=0, _hdrh=0, _hdrsubsamp=-1;
686 double t;
DRC3bad53f2011-02-23 02:20:49 +0000687 int scaledw=(w+scalefactor-1)/scalefactor;
688 int scaledh=(h+scalefactor-1)/scalefactor;
689 int temp1, temp2;
DRC84a1bcc2011-02-23 12:09:56 +0000690 BufferedImage img=null; byte [] bmpbuf=null;
DRC3bad53f2011-02-23 02:20:49 +0000691
692 if(yuv==YUVDECODE) flags|=TJ.YUV;
693 else if(yuv==YUVENCODE) return;
694
695 pixformat=_pixformatstr[pf];
696 System.out.print("JPEG -> ");
697 if(yuv==YUVDECODE)
698 System.out.print("YUV "+_subnames[subsamp]+" ... ");
699 else
700 {
701 System.out.print(pixformat+" ");
702 if((flags&TJ.BOTTOMUP)!=0) System.out.print("Bottom-Up ");
703 else System.out.print("Top-Down ");
704 if(scalefactor!=1) System.out.print("1/"+scalefactor+" ... ");
705 else System.out.print("... ");
706 }
707
708 t=gettime();
709 tjd.setJPEGBuffer(jpegbuf, jpegsize);
710 if(tjd.getWidth()!=w || tjd.getHeight()!=h || tjd.getSubsamp()!=subsamp)
711 throw new Exception("Incorrect JPEG header");
712
713 temp1=scaledw; temp2=scaledh;
714 temp1=tjd.getScaledWidth(temp1, temp2);
715 temp2=tjd.getScaledHeight(temp1, temp2);
716 if(temp1!=scaledw || temp2!=scaledh)
717 throw new Exception("Scaled size mismatch");
718
DRC84a1bcc2011-02-23 12:09:56 +0000719 if(bi)
720 {
721 img=new BufferedImage(scaledw, scaledh, biType[pf]);
722 tjd.decompress(img, flags);
723 }
724 else
725 bmpbuf=tjd.decompress(scaledw, 0, scaledh, pf, flags);
DRC3bad53f2011-02-23 02:20:49 +0000726 t=gettime()-t;
727
DRC84a1bcc2011-02-23 12:09:56 +0000728 if(bi)
729 {
730 tempstr=basefilename+"_dec_"+pixformat+"_"
731 +(((flags&TJ.BOTTOMUP)!=0)? "BU":"TD")+"_"+_subnames[subsamp]
732 +"_"+scalefactor+"x"+".png";
733 File file=new File(tempstr);
734 ImageIO.write(img, "png", file);
735 }
736
DRC3bad53f2011-02-23 02:20:49 +0000737 if(yuv==YUVDECODE)
738 {
739 if(checkbufyuv(bmpbuf, bmpbuf.length, w, h, subsamp)==1)
740 System.out.print("Passed.");
741 else {System.out.print("FAILED!"); exitstatus=-1;}
742 }
743 else
744 {
DRC84a1bcc2011-02-23 12:09:56 +0000745 if((bi && checkimg(img, pf, subsamp, scalefactor, flags)==1)
746 || (!bi && checkbuf(bmpbuf, scaledw, scaledh, pf, subsamp, scalefactor,
747 flags)==1))
DRC3bad53f2011-02-23 02:20:49 +0000748 System.out.print("Passed.");
749 else
750 {
751 System.out.print("FAILED!"); exitstatus=-1;
DRC84a1bcc2011-02-23 12:09:56 +0000752 if(bmpbuf!=null)
753 dumpbuf(bmpbuf, scaledw, scaledh, pf, scalefactor, flags);
DRC3bad53f2011-02-23 02:20:49 +0000754 }
755 }
756 System.out.format(" %.6f ms\n", t*1000.);
757 }
758
759 private static void gentestbmp(TJDecompressor tjd, byte [] jpegbuf,
760 int jpegsize, int w, int h, int pf, String basefilename, int subsamp,
761 int flags) throws Exception
762 {
763 int i;
764 if((subsamp==TJ.SAMP_444 || subsamp==TJ.SAMP_GRAY) && yuv==0)
765 {
766 for(i=1; i<=8; i*=2)
767 _gentestbmp(tjd, jpegbuf, jpegsize, w, h, pf, basefilename, subsamp,
768 flags, i);
769 }
770 else
771 _gentestbmp(tjd, jpegbuf, jpegsize, w, h, pf, basefilename, subsamp,
772 flags, 1);
773 System.out.print("\n");
774 }
775
776 private static void dotest(int w, int h, int [] formats, int subsamp,
777 String basefilename) throws Exception
778 {
779 TJCompressor tjc=null; TJDecompressor tjd=null;
780 int size; int pfstart, pfend;
781
782 byte [] jpegbuf=new byte[TJ.bufSize(w, h)];
783
784 try
785 {
786 tjc=new TJCompressor();
787 tjd=new TJDecompressor();
788
789 for(int pf : formats)
790 {
791 for(int i=0; i<2; i++)
792 {
793 int flags=0;
794 if(i==1)
795 {
796 if(yuv==YUVDECODE)
797 {
798 tjc.close(); tjd.close(); return;
799 }
800 else flags|=TJ.BOTTOMUP;
801 }
802 size=gentestjpeg(tjc, jpegbuf, w, h, pf, basefilename, subsamp, 100,
803 flags);
804 gentestbmp(tjd, jpegbuf, size, w, h, pf, basefilename, subsamp,
805 flags);
806 }
807 }
808 }
809 catch(Exception e)
810 {
811 if(tjc!=null) tjc.close();
812 if(tjd!=null) tjd.close();
813 throw e;
814 }
815 if(tjc!=null) tjc.close();
816 if(tjd!=null) tjd.close();
817 }
818
819 private final static int MAXLENGTH=2048;
820
821 private static void dotest1() throws Exception
822 {
823 int i, j, i2; byte [] bmpbuf, jpgbuf;
824 TJCompressor tjc=null; int size;
825
826 try
827 {
828 tjc=new TJCompressor();
829 System.out.println("Buffer size regression test");
830 for(j=1; j<48; j++)
831 {
832 for(i=1; i<(j==1?MAXLENGTH:48); i++)
833 {
834 if(i%100==0) System.out.format("%04d x %04d\b\b\b\b\b\b\b\b\b\b\b",
835 i, j);
836 bmpbuf=new byte[i*j*4];
837 jpgbuf=new byte[TJ.bufSize(i, j)];
838 Arrays.fill(bmpbuf, (byte)0);
839 for(i2=0; i2<i*j; i2++)
840 {
841 bmpbuf[i2*4]=pixels[i2%9][2];
842 bmpbuf[i2*4+1]=pixels[i2%9][1];
843 bmpbuf[i2*4+2]=pixels[i2%9][0];
844 }
845 tjc.setBitmapBuffer(bmpbuf, i, 0, j, TJ.PF_BGRX);
846 size=tjc.compress(jpgbuf, TJ.SAMP_444, 100, 0);
847
848 bmpbuf=new byte[j*i*4];
849 jpgbuf=new byte[TJ.bufSize(j, i)];
850 for(i2=0; i2<j*i; i2++)
851 {
852 if(i2%2==0) bmpbuf[i2*4]=bmpbuf[i2*4+1]=bmpbuf[i2*4+2]=(byte)0xFF;
853 else bmpbuf[i2*4]=bmpbuf[i2*4+1]=bmpbuf[i2*4+2]=0;
854 }
855 tjc.setBitmapBuffer(bmpbuf, j, 0, i, TJ.PF_BGRX);
856 size=tjc.compress(jpgbuf, TJ.SAMP_444, 100, 0);
857 }
858 }
859 System.out.println("Done. ");
860 }
861 catch(Exception e)
862 {
863 if(tjc!=null) tjc.close();
864 throw e;
865 }
866 if(tjc!=null) tjc.close();
867 }
868
869 public static void main(String argv[])
870 {
871 try
872 {
873 boolean doyuv=false;
874 for(int i=0; i<argv.length; i++)
875 {
876 if(argv[i].equalsIgnoreCase("-yuv")) doyuv=true;
877 if(argv[i].substring(0, 1).equalsIgnoreCase("-h")
878 || argv[i].equalsIgnoreCase("-?"))
879 usage();
DRC84a1bcc2011-02-23 12:09:56 +0000880 if(argv[i].equalsIgnoreCase("-bi")) bi=true;
DRC3bad53f2011-02-23 02:20:49 +0000881 }
DRC84a1bcc2011-02-23 12:09:56 +0000882 if(bi && doyuv)
883 throw new Exception("-bi and -yuv cannot be used together.");
DRC3bad53f2011-02-23 02:20:49 +0000884 if(doyuv) yuv=YUVENCODE;
DRC84a1bcc2011-02-23 12:09:56 +0000885 dotest(35, 39, bi? _3byteFormatsBI:_3byteFormats, TJ.SAMP_444, "test");
886 dotest(39, 41, bi? _4byteFormatsBI:_4byteFormats, TJ.SAMP_444, "test");
DRC3bad53f2011-02-23 02:20:49 +0000887 if(doyuv)
888 {
889 dotest(41, 35, _3byteFormats, TJ.SAMP_422, "test");
890 dotest(35, 39, _4byteFormats, TJ.SAMP_422, "test");
891 dotest(39, 41, _3byteFormats, TJ.SAMP_420, "test");
892 dotest(41, 35, _4byteFormats, TJ.SAMP_420, "test");
893 }
894 dotest(35, 39, _onlyGray, TJ.SAMP_GRAY, "test");
DRC84a1bcc2011-02-23 12:09:56 +0000895 dotest(39, 41, bi? _3byteFormatsBI:_3byteFormats, TJ.SAMP_GRAY, "test");
896 dotest(41, 35, bi? _4byteFormatsBI:_4byteFormats, TJ.SAMP_GRAY, "test");
897 if(!doyuv && !bi) dotest1();
DRC3bad53f2011-02-23 02:20:49 +0000898 if(doyuv)
899 {
900 yuv=YUVDECODE;
901 dotest(48, 48, _onlyRGB, TJ.SAMP_444, "test");
902 dotest(35, 39, _onlyRGB, TJ.SAMP_444, "test");
903 dotest(48, 48, _onlyRGB, TJ.SAMP_422, "test");
904 dotest(39, 41, _onlyRGB, TJ.SAMP_422, "test");
905 dotest(48, 48, _onlyRGB, TJ.SAMP_420, "test");
906 dotest(41, 35, _onlyRGB, TJ.SAMP_420, "test");
907 dotest(48, 48, _onlyGray, TJ.SAMP_GRAY, "test");
908 dotest(35, 39, _onlyGray, TJ.SAMP_GRAY, "test");
909 }
910 }
911 catch(Exception e)
912 {
913 System.out.println(e);
DRC84a1bcc2011-02-23 12:09:56 +0000914 exitstatus=-1;
DRC3bad53f2011-02-23 02:20:49 +0000915 }
916 System.exit(exitstatus);
917 }
918}