Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 643 lines (571 sloc) 16.11 kb
c14f645 sync to 1.1.90 upstream, change 691
Tom Gall authored
1 /*
2 * Copyright (C)2009-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 C Wrapper
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <errno.h>
37 #include "./tjutil.h"
38 #include "./turbojpeg.h"
39 #ifdef _WIN32
40 #include <time.h>
41 #define random() rand()
42 #endif
43
44
45 void usage(char *progName)
46 {
47 printf("\nUSAGE: %s [options]\n", progName);
48 printf("Options:\n");
49 printf("-yuv = test YUV encoding/decoding support\n");
50 printf("-alloc = test automatic buffer allocation\n");
51 exit(1);
52 }
53
54
55 #define _throwtj() {printf("TurboJPEG ERROR:\n%s\n", tjGetErrorStr()); \
56 bailout();}
57 #define _tj(f) {if((f)==-1) _throwtj();}
58 #define _throw(m) {printf("ERROR: %s\n", m); bailout();}
59
60 const char *subNameLong[TJ_NUMSAMP]=
61 {
62 "4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0"
63 };
64 const char *subName[TJ_NUMSAMP]={"444", "422", "420", "GRAY", "440"};
65
66 const char *pixFormatStr[TJ_NUMPF]=
67 {
68 "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "Grayscale"
69 };
70
71 const int _3byteFormats[]={TJPF_RGB, TJPF_BGR};
72 const int _4byteFormats[]={TJPF_RGBX, TJPF_BGRX, TJPF_XBGR, TJPF_XRGB};
73 const int _onlyGray[]={TJPF_GRAY};
74 const int _onlyRGB[]={TJPF_RGB};
75
76 enum {YUVENCODE=1, YUVDECODE};
77 int yuv=0, alloc=0;
78
79 int exitStatus=0;
80 #define bailout() {exitStatus=-1; goto bailout;}
81
82
83 void initBuf(unsigned char *buf, int w, int h, int pf, int flags)
84 {
85 int roffset=tjRedOffset[pf];
86 int goffset=tjGreenOffset[pf];
87 int boffset=tjBlueOffset[pf];
88 int ps=tjPixelSize[pf];
89 int index, row, col, halfway=16;
90
91 memset(buf, 0, w*h*ps);
92 if(pf==TJPF_GRAY)
93 {
94 for(row=0; row<h; row++)
95 {
96 for(col=0; col<w; col++)
97 {
98 if(flags&TJFLAG_BOTTOMUP) index=(h-row-1)*w+col;
99 else index=row*w+col;
100 if(((row/8)+(col/8))%2==0) buf[index]=(row<halfway)? 255:0;
101 else buf[index]=(row<halfway)? 76:226;
102 }
103 }
104 }
105 else
106 {
107 for(row=0; row<h; row++)
108 {
109 for(col=0; col<w; col++)
110 {
111 if(flags&TJFLAG_BOTTOMUP) index=(h-row-1)*w+col;
112 else index=row*w+col;
113 if(((row/8)+(col/8))%2==0)
114 {
115 if(row<halfway)
116 {
117 buf[index*ps+roffset]=255;
118 buf[index*ps+goffset]=255;
119 buf[index*ps+boffset]=255;
120 }
121 }
122 else
123 {
124 buf[index*ps+roffset]=255;
125 if(row>=halfway) buf[index*ps+goffset]=255;
126 }
127 }
128 }
129 }
130 }
131
132
133 #define checkval(v, cv) { \
134 if(v<cv-1 || v>cv+1) { \
135 printf("\nComp. %s at %d,%d should be %d, not %d\n", \
136 #v, row, col, cv, v); \
137 retval=0; exitStatus=-1; goto bailout; \
138 }}
139
140 #define checkval0(v) { \
141 if(v>1) { \
142 printf("\nComp. %s at %d,%d should be 0, not %d\n", #v, row, col, v); \
143 retval=0; exitStatus=-1; goto bailout; \
144 }}
145
146 #define checkval255(v) { \
147 if(v<254) { \
148 printf("\nComp. %s at %d,%d should be 255, not %d\n", #v, row, col, v); \
149 retval=0; exitStatus=-1; goto bailout; \
150 }}
151
152
153 int checkBuf(unsigned char *buf, int w, int h, int pf, int subsamp,
154 tjscalingfactor sf, int flags)
155 {
156 int roffset=tjRedOffset[pf];
157 int goffset=tjGreenOffset[pf];
158 int boffset=tjBlueOffset[pf];
159 int ps=tjPixelSize[pf];
160 int index, row, col, retval=1;
161 int halfway=16*sf.num/sf.denom;
162 int blocksize=8*sf.num/sf.denom;
163
164 for(row=0; row<h; row++)
165 {
166 for(col=0; col<w; col++)
167 {
168 unsigned char r, g, b;
169 if(flags&TJFLAG_BOTTOMUP) index=(h-row-1)*w+col;
170 else index=row*w+col;
171 r=buf[index*ps+roffset];
172 g=buf[index*ps+goffset];
173 b=buf[index*ps+boffset];
174 if(((row/blocksize)+(col/blocksize))%2==0)
175 {
176 if(row<halfway)
177 {
178 checkval255(r); checkval255(g); checkval255(b);
179 }
180 else
181 {
182 checkval0(r); checkval0(g); checkval0(b);
183 }
184 }
185 else
186 {
187 if(subsamp==TJSAMP_GRAY)
188 {
189 if(row<halfway)
190 {
191 checkval(r, 76); checkval(g, 76); checkval(b, 76);
192 }
193 else
194 {
195 checkval(r, 226); checkval(g, 226); checkval(b, 226);
196 }
197 }
198 else
199 {
200 if(row<halfway)
201 {
202 checkval255(r); checkval0(g); checkval0(b);
203 }
204 else
205 {
206 checkval255(r); checkval255(g); checkval0(b);
207 }
208 }
209 }
210 }
211 }
212
213 bailout:
214 if(retval==0)
215 {
216 printf("\n");
217 for(row=0; row<h; row++)
218 {
219 for(col=0; col<w; col++)
220 {
221 printf("%.3d/%.3d/%.3d ", buf[(row*w+col)*ps+roffset],
222 buf[(row*w+col)*ps+goffset], buf[(row*w+col)*ps+boffset]);
223 }
224 printf("\n");
225 }
226 }
227 return retval;
228 }
229
230
231 #define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
232
233 int checkBufYUV(unsigned char *buf, int w, int h, int subsamp)
234 {
235 int row, col;
236 int hsf=tjMCUWidth[subsamp]/8, vsf=tjMCUHeight[subsamp]/8;
237 int pw=PAD(w, hsf), ph=PAD(h, vsf);
238 int cw=pw/hsf, ch=ph/vsf;
239 int ypitch=PAD(pw, 4), uvpitch=PAD(cw, 4);
240 int retval=1;
241 int halfway=16;
242
243 for(row=0; row<ph; row++)
244 {
245 for(col=0; col<pw; col++)
246 {
247 unsigned char y=buf[ypitch*row+col];
248 if(((row/8)+(col/8))%2==0)
249 {
250 if(row<halfway) checkval255(y) else checkval0(y);
251 }
252 else
253 {
254 if(row<halfway) checkval(y, 76) else checkval(y, 226);
255 }
256 }
257 }
258 if(subsamp!=TJSAMP_GRAY)
259 {
260 halfway=16/vsf;
261 for(row=0; row<ch; row++)
262 {
263 for(col=0; col<cw; col++)
264 {
265 unsigned char u=buf[ypitch*ph + (uvpitch*row+col)],
266 v=buf[ypitch*ph + uvpitch*ch + (uvpitch*row+col)];
267 if(((row*vsf/8)+(col*hsf/8))%2==0)
268 {
269 checkval(u, 128); checkval(v, 128);
270 }
271 else
272 {
273 if(row<halfway)
274 {
275 checkval(u, 85); checkval255(v);
276 }
277 else
278 {
279 checkval0(u); checkval(v, 149);
280 }
281 }
282 }
283 }
284 }
285
286 bailout:
287 if(retval==0)
288 {
289 for(row=0; row<ph; row++)
290 {
291 for(col=0; col<pw; col++)
292 printf("%.3d ", buf[ypitch*row+col]);
293 printf("\n");
294 }
295 printf("\n");
296 for(row=0; row<ch; row++)
297 {
298 for(col=0; col<cw; col++)
299 printf("%.3d ", buf[ypitch*ph + (uvpitch*row+col)]);
300 printf("\n");
301 }
302 printf("\n");
303 for(row=0; row<ch; row++)
304 {
305 for(col=0; col<cw; col++)
306 printf("%.3d ", buf[ypitch*ph + uvpitch*ch + (uvpitch*row+col)]);
307 printf("\n");
308 }
309 printf("\n");
310 }
311
312 return retval;
313 }
314
315
316 void writeJPEG(unsigned char *jpegBuf, unsigned long jpegSize, char *filename)
317 {
318 FILE *file=fopen(filename, "wb");
319 if(!file || fwrite(jpegBuf, jpegSize, 1, file)!=1)
320 {
321 printf("ERROR: Could not write to %s.\n%s\n", filename, strerror(errno));
322 bailout();
323 }
324
325 bailout:
326 if(file) fclose(file);
327 }
328
329
330 void compTest(tjhandle handle, unsigned char **dstBuf,
331 unsigned long *dstSize, int w, int h, int pf, char *basename,
332 int subsamp, int jpegQual, int flags)
333 {
334 char tempStr[1024]; unsigned char *srcBuf=NULL;
335 double t;
336
337 if(yuv==YUVENCODE)
338 printf("%s %s -> %s YUV ... ", pixFormatStr[pf],
339 (flags&TJFLAG_BOTTOMUP)? "Bottom-Up":"Top-Down ", subNameLong[subsamp]);
340 else
341 printf("%s %s -> %s Q%d ... ", pixFormatStr[pf],
342 (flags&TJFLAG_BOTTOMUP)? "Bottom-Up":"Top-Down ", subNameLong[subsamp],
343 jpegQual);
344
345 if((srcBuf=(unsigned char *)malloc(w*h*tjPixelSize[pf]))==NULL)
346 _throw("Memory allocation failure");
347 initBuf(srcBuf, w, h, pf, flags);
348 if(*dstBuf && *dstSize>0) memset(*dstBuf, 0, *dstSize);
349
350 t=gettime();
351 if(yuv==YUVENCODE)
352 {
353 _tj(tjEncodeYUV2(handle, srcBuf, w, 0, h, pf, *dstBuf, subsamp, flags));
354 }
355 else
356 {
357 if(!alloc)
358 {
359 flags|=TJFLAG_NOREALLOC;
360 *dstSize=(yuv==YUVENCODE? tjBufSizeYUV(w, h, subsamp)
361 : tjBufSize(w, h, subsamp));
362 }
363 _tj(tjCompress2(handle, srcBuf, w, 0, h, pf, dstBuf, dstSize, subsamp,
364 jpegQual, flags));
365 }
366 t=gettime()-t;
367
368 if(yuv==YUVENCODE)
369 snprintf(tempStr, 1024, "%s_enc_%s_%s_%s.yuv", basename, pixFormatStr[pf],
370 (flags&TJFLAG_BOTTOMUP)? "BU":"TD", subName[subsamp]);
371 else
372 snprintf(tempStr, 1024, "%s_enc_%s_%s_%s_Q%d.jpg", basename,
373 pixFormatStr[pf], (flags&TJFLAG_BOTTOMUP)? "BU":"TD", subName[subsamp],
374 jpegQual);
375 writeJPEG(*dstBuf, *dstSize, tempStr);
376 if(yuv==YUVENCODE)
377 {
378 if(checkBufYUV(*dstBuf, w, h, subsamp)) printf("Passed.");
379 else printf("FAILED!");
380 }
381 else printf("Done.");
382 printf(" %f ms\n Result in %s\n", t*1000., tempStr);
383
384 bailout:
385 if(srcBuf) free(srcBuf);
386 }
387
388
389 void _decompTest(tjhandle handle, unsigned char *jpegBuf,
390 unsigned long jpegSize, int w, int h, int pf, char *basename, int subsamp,
391 int flags, tjscalingfactor sf)
392 {
393 unsigned char *dstBuf=NULL;
394 int _hdrw=0, _hdrh=0, _hdrsubsamp=-1; double t;
395 int scaledWidth=TJSCALED(w, sf);
396 int scaledHeight=TJSCALED(h, sf);
397 unsigned long dstSize=0;
398
399 if(yuv==YUVENCODE) return;
400
401 if(yuv==YUVDECODE)
402 printf("JPEG -> YUV %s ... ", subName[subsamp]);
403 else
404 {
405 printf("JPEG -> %s %s ", pixFormatStr[pf],
406 (flags&TJFLAG_BOTTOMUP)? "Bottom-Up":"Top-Down ");
407 if(sf.num!=1 || sf.denom!=1)
408 printf("%d/%d ... ", sf.num, sf.denom);
409 else printf("... ");
410 }
411
412 _tj(tjDecompressHeader2(handle, jpegBuf, jpegSize, &_hdrw, &_hdrh,
413 &_hdrsubsamp));
414 if(_hdrw!=w || _hdrh!=h || _hdrsubsamp!=subsamp)
415 _throw("Incorrect JPEG header");
416
417 if(yuv==YUVDECODE) dstSize=tjBufSizeYUV(w, h, subsamp);
418 else dstSize=scaledWidth*scaledHeight*tjPixelSize[pf];
419 if((dstBuf=(unsigned char *)malloc(dstSize))==NULL)
420 _throw("Memory allocation failure");
421 memset(dstBuf, 0, dstSize);
422
423 t=gettime();
424 if(yuv==YUVDECODE)
425 {
426 _tj(tjDecompressToYUV(handle, jpegBuf, jpegSize, dstBuf, flags));
427 }
428 else
429 {
430 _tj(tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, scaledWidth, 0,
431 scaledHeight, pf, flags));
432 }
433 t=gettime()-t;
434
435 if(yuv==YUVDECODE)
436 {
437 if(checkBufYUV(dstBuf, w, h, subsamp)) printf("Passed.");
438 else printf("FAILED!");
439 }
440 else
441 {
442 if(checkBuf(dstBuf, scaledWidth, scaledHeight, pf, subsamp, sf, flags))
443 printf("Passed.");
444 else printf("FAILED!");
445 }
446 printf(" %f ms\n", t*1000.);
447
448 bailout:
449 if(dstBuf) free(dstBuf);
450 }
451
452
453 void decompTest(tjhandle handle, unsigned char *jpegBuf,
454 unsigned long jpegSize, int w, int h, int pf, char *basename, int subsamp,
455 int flags)
456 {
457 int i, n=0;
458 tjscalingfactor *sf=tjGetScalingFactors(&n), sf1={1, 1};
459 if(!sf || !n) _throwtj();
460
461 if((subsamp==TJSAMP_444 || subsamp==TJSAMP_GRAY) && !yuv)
462 {
463 for(i=0; i<n; i++)
464 _decompTest(handle, jpegBuf, jpegSize, w, h, pf, basename, subsamp,
465 flags, sf[i]);
466 }
467 else
468 _decompTest(handle, jpegBuf, jpegSize, w, h, pf, basename, subsamp, flags,
469 sf1);
470
471 bailout:
472 printf("\n");
473 }
474
475
476 void doTest(int w, int h, const int *formats, int nformats, int subsamp,
477 char *basename)
478 {
479 tjhandle chandle=NULL, dhandle=NULL;
480 unsigned char *dstBuf=NULL;
481 unsigned long size=0; int pfi, pf, i;
482
483 if(!alloc)
484 {
485 size=(yuv==YUVENCODE? tjBufSizeYUV(w, h, subsamp)
486 : tjBufSize(w, h, subsamp));
487 if((dstBuf=(unsigned char *)tjAlloc(size))==NULL)
488 _throw("Memory allocation failure.");
489 }
490
491 if((chandle=tjInitCompress())==NULL || (dhandle=tjInitDecompress())==NULL)
492 _throwtj();
493
494 for(pfi=0; pfi<nformats; pfi++)
495 {
496 for(i=0; i<2; i++)
497 {
498 int flags=0;
499 if(i==1)
500 {
501 if(yuv==YUVDECODE) goto bailout;
502 else flags|=TJFLAG_BOTTOMUP;
503 }
504 pf=formats[pfi];
505 compTest(chandle, &dstBuf, &size, w, h, pf, basename, subsamp, 100,
506 flags);
507 decompTest(dhandle, dstBuf, size, w, h, pf, basename, subsamp,
508 flags);
509 }
510 }
511
512 bailout:
513 if(chandle) tjDestroy(chandle);
514 if(dhandle) tjDestroy(dhandle);
515
516 if(dstBuf) tjFree(dstBuf);
517 }
518
519
520 void bufSizeTest(void)
521 {
522 int w, h, i, subsamp;
523 unsigned char *srcBuf=NULL, *jpegBuf=NULL;
524 tjhandle handle=NULL;
525 unsigned long jpegSize=0;
526
527 if((handle=tjInitCompress())==NULL) _throwtj();
528
529 printf("Buffer size regression test\n");
530 for(subsamp=0; subsamp<TJ_NUMSAMP; subsamp++)
531 {
532 for(w=1; w<48; w++)
533 {
534 int maxh=(w==1)? 2048:48;
535 for(h=1; h<maxh; h++)
536 {
537 if(h%100==0) printf("%.4d x %.4d\b\b\b\b\b\b\b\b\b\b\b", w, h);
538 if((srcBuf=(unsigned char *)malloc(w*h*4))==NULL)
539 _throw("Memory allocation failure");
540 if(!alloc)
541 {
542 if((jpegBuf=(unsigned char *)tjAlloc(tjBufSize(w, h, subsamp)))
543 ==NULL)
544 _throw("Memory allocation failure");
545 jpegSize=tjBufSize(w, h, subsamp);
546 }
547
548 for(i=0; i<w*h*4; i++)
549 {
550 if(random()<RAND_MAX/2) srcBuf[i]=0;
551 else srcBuf[i]=255;
552 }
553
554 _tj(tjCompress2(handle, srcBuf, w, 0, h, TJPF_BGRX, &jpegBuf,
555 &jpegSize, subsamp, 100, alloc? 0:TJFLAG_NOREALLOC));
556 free(srcBuf); srcBuf=NULL;
557 tjFree(jpegBuf); jpegBuf=NULL;
558
559 if((srcBuf=(unsigned char *)malloc(h*w*4))==NULL)
560 _throw("Memory allocation failure");
561 if(!alloc)
562 {
563 if((jpegBuf=(unsigned char *)tjAlloc(tjBufSize(h, w, subsamp)))
564 ==NULL)
565 _throw("Memory allocation failure");
566 jpegSize=tjBufSize(h, w, subsamp);
567 }
568
569 for(i=0; i<h*w*4; i++)
570 {
571 if(random()<RAND_MAX/2) srcBuf[i]=0;
572 else srcBuf[i]=255;
573 }
574
575 _tj(tjCompress2(handle, srcBuf, h, 0, w, TJPF_BGRX, &jpegBuf,
576 &jpegSize, subsamp, 100, alloc? 0:TJFLAG_NOREALLOC));
577 free(srcBuf); srcBuf=NULL;
578 tjFree(jpegBuf); jpegBuf=NULL;
579 }
580 }
581 }
582 printf("Done. \n");
583
584 bailout:
585 if(srcBuf) free(srcBuf);
586 if(jpegBuf) free(jpegBuf);
587 if(handle) tjDestroy(handle);
588 }
589
590
591 int main(int argc, char *argv[])
592 {
593 int doyuv=0, i;
594 #ifdef _WIN32
595 srand((unsigned int)time(NULL));
596 #endif
597 if(argc>1)
598 {
599 for(i=1; i<argc; i++)
600 {
601 if(!strcasecmp(argv[i], "-yuv")) doyuv=1;
602 if(!strcasecmp(argv[i], "-alloc")) alloc=1;
603 if(!strncasecmp(argv[i], "-h", 2) || !strcasecmp(argv[i], "-?"))
604 usage(argv[0]);
605 }
606 }
607 if(alloc) printf("Testing automatic buffer allocation\n");
608 if(doyuv) {yuv=YUVENCODE; alloc=0;}
609 doTest(35, 39, _3byteFormats, 2, TJSAMP_444, "test");
610 doTest(39, 41, _4byteFormats, 4, TJSAMP_444, "test");
611 if(doyuv)
612 {
613 doTest(41, 35, _3byteFormats, 2, TJSAMP_422, "test");
614 doTest(35, 39, _4byteFormats, 4, TJSAMP_422, "test");
615 doTest(39, 41, _3byteFormats, 2, TJSAMP_420, "test");
616 doTest(41, 35, _4byteFormats, 4, TJSAMP_420, "test");
617 doTest(35, 39, _3byteFormats, 2, TJSAMP_440, "test");
618 doTest(39, 41, _4byteFormats, 4, TJSAMP_440, "test");
619 }
620 doTest(35, 39, _onlyGray, 1, TJSAMP_GRAY, "test");
621 doTest(39, 41, _3byteFormats, 2, TJSAMP_GRAY, "test");
622 doTest(41, 35, _4byteFormats, 4, TJSAMP_GRAY, "test");
623 if(!doyuv) bufSizeTest();
624 if(doyuv)
625 {
626 yuv=YUVDECODE;
627 doTest(48, 48, _onlyRGB, 1, TJSAMP_444, "test_yuv0");
628 doTest(35, 39, _onlyRGB, 1, TJSAMP_444, "test_yuv1");
629 doTest(48, 48, _onlyRGB, 1, TJSAMP_422, "test_yuv0");
630 doTest(39, 41, _onlyRGB, 1, TJSAMP_422, "test_yuv1");
631 doTest(48, 48, _onlyRGB, 1, TJSAMP_420, "test_yuv0");
632 doTest(41, 35, _onlyRGB, 1, TJSAMP_420, "test_yuv1");
633 doTest(48, 48, _onlyRGB, 1, TJSAMP_440, "test_yuv0");
634 doTest(35, 39, _onlyRGB, 1, TJSAMP_440, "test_yuv1");
635 doTest(48, 48, _onlyRGB, 1, TJSAMP_GRAY, "test_yuv0");
636 doTest(35, 39, _onlyRGB, 1, TJSAMP_GRAY, "test_yuv1");
637 doTest(48, 48, _onlyGray, 1, TJSAMP_GRAY, "test_yuv0");
638 doTest(39, 41, _onlyGray, 1, TJSAMP_GRAY, "test_yuv1");
639 }
640
641 return exitStatus;
642 }
Something went wrong with that request. Please try again.