xref: /aosp_15_r20/external/libjpeg-turbo/tjunittest.c (revision dfc6aa5c1cfd4bc4e2018dc74aa96e29ee49c6da)
1 /*
2  * Copyright (C)2009-2014, 2017-2019, 2022-2023 D. R. Commander.
3  *                                              All Rights Reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * - Redistributions of source code must retain the above copyright notice,
9  *   this list of conditions and the following disclaimer.
10  * - Redistributions in binary form must reproduce the above copyright notice,
11  *   this list of conditions and the following disclaimer in the documentation
12  *   and/or other materials provided with the distribution.
13  * - Neither the name of the libjpeg-turbo Project nor the names of its
14  *   contributors may be used to endorse or promote products derived from this
15  *   software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 /*
31  * This program tests the various code paths in the TurboJPEG C Wrapper
32  */
33 
34 #ifdef _MSC_VER
35 #define _CRT_SECURE_NO_DEPRECATE
36 #endif
37 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <limits.h>
42 #include <errno.h>
43 #include "tjutil.h"
44 #include "turbojpeg.h"
45 #include "md5/md5.h"
46 #include "cmyk.h"
47 #ifdef _WIN32
48 #include <time.h>
49 #define random()  rand()
50 #else
51 #include <unistd.h>
52 #endif
53 
54 
55 #ifndef GTEST
usage(char * progName)56 static void usage(char *progName)
57 {
58   printf("\nUSAGE: %s [options]\n\n", progName);
59   printf("Options:\n");
60   printf("-yuv = test YUV encoding/compression/decompression/decoding\n");
61   printf("-noyuvpad = do not pad each row in each Y, U, and V plane to the nearest\n");
62   printf("            multiple of 4 bytes\n");
63   printf("-alloc = test automatic JPEG buffer allocation\n");
64   printf("-bmp = test packed-pixel image I/O\n");
65   exit(1);
66 }
67 #endif
68 
69 
70 #define THROW_TJ() { \
71   fprintf(stderr, "TurboJPEG ERROR:\n%s\n", tjGetErrorStr()); \
72   BAILOUT() \
73 }
74 #define TRY_TJ(f) { if ((f) == -1) THROW_TJ(); }
75 #define THROW(m) { printf("ERROR: %s\n", m);  BAILOUT() }
76 #define THROW_MD5(filename, md5sum, ref) { \
77   fprintf(stderr, "\n%s has an MD5 sum of %s.\n   Should be %s.\n", filename, \
78           md5sum, ref); \
79   BAILOUT() \
80 }
81 
82 static const char *subNameLong[TJ_NUMSAMP] = {
83   "4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0", "4:1:1"
84 };
85 static const char *subName[TJ_NUMSAMP] = {
86   "444", "422", "420", "GRAY", "440", "411"
87 };
88 
89 static const char *pixFormatStr[TJ_NUMPF] = {
90   "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "Grayscale",
91   "RGBA", "BGRA", "ABGR", "ARGB", "CMYK"
92 };
93 
94 static const int _3byteFormats[] = { TJPF_RGB, TJPF_BGR };
95 static const int _4byteFormats[] = {
96   TJPF_RGBX, TJPF_BGRX, TJPF_XBGR, TJPF_XRGB, TJPF_CMYK
97 };
98 static const int _onlyGray[] = { TJPF_GRAY };
99 static const int _onlyRGB[] = { TJPF_RGB };
100 
101 static int doYUV = 0, alloc = 0, yuvAlign = 4;
102 
103 static int exitStatus = 0;
104 #define BAILOUT() { exitStatus = -1;  goto bailout; }
105 
106 static const size_t filePathSize = 1024;
107 
108 
initBuf(unsigned char * buf,int w,int h,int pf,int flags)109 static void initBuf(unsigned char *buf, int w, int h, int pf, int flags)
110 {
111   int roffset = tjRedOffset[pf];
112   int goffset = tjGreenOffset[pf];
113   int boffset = tjBlueOffset[pf];
114   int ps = tjPixelSize[pf];
115   int index, row, col, halfway = 16;
116 
117   if (pf == TJPF_GRAY) {
118     memset(buf, 0, w * h * ps);
119     for (row = 0; row < h; row++) {
120       for (col = 0; col < w; col++) {
121         if (flags & TJFLAG_BOTTOMUP) index = (h - row - 1) * w + col;
122         else index = row * w + col;
123         if (((row / 8) + (col / 8)) % 2 == 0)
124           buf[index] = (row < halfway) ? 255 : 0;
125         else buf[index] = (row < halfway) ? 76 : 226;
126       }
127     }
128   } else if (pf == TJPF_CMYK) {
129     memset(buf, 255, w * h * ps);
130     for (row = 0; row < h; row++) {
131       for (col = 0; col < w; col++) {
132         if (flags & TJFLAG_BOTTOMUP) index = (h - row - 1) * w + col;
133         else index = row * w + col;
134         if (((row / 8) + (col / 8)) % 2 == 0) {
135           if (row >= halfway) buf[index * ps + 3] = 0;
136         } else {
137           buf[index * ps + 2] = 0;
138           if (row < halfway) buf[index * ps + 1] = 0;
139         }
140       }
141     }
142   } else {
143     memset(buf, 0, w * h * ps);
144     for (row = 0; row < h; row++) {
145       for (col = 0; col < w; col++) {
146         if (flags & TJFLAG_BOTTOMUP) index = (h - row - 1) * w + col;
147         else index = row * w + col;
148         if (((row / 8) + (col / 8)) % 2 == 0) {
149           if (row < halfway) {
150             buf[index * ps + roffset] = 255;
151             buf[index * ps + goffset] = 255;
152             buf[index * ps + boffset] = 255;
153           }
154         } else {
155           buf[index * ps + roffset] = 255;
156           if (row >= halfway) buf[index * ps + goffset] = 255;
157         }
158       }
159     }
160   }
161 }
162 
163 
164 #define CHECKVAL(v, cv) { \
165   if (v < cv - 1 || v > cv + 1) { \
166     fprintf(stderr, "\nComp. %s at %d,%d should be %d, not %d\n", #v, row, \
167             col, cv, v); \
168     retval = 0;  exitStatus = -1;  goto bailout; \
169   } \
170 }
171 
172 #define CHECKVAL0(v) { \
173   if (v > 1) { \
174     fprintf(stderr, "\nComp. %s at %d,%d should be 0, not %d\n", #v, row, \
175             col, v); \
176     retval = 0;  exitStatus = -1;  goto bailout; \
177   } \
178 }
179 
180 #define CHECKVAL255(v) { \
181   if (v < 254) { \
182     fprintf(stderr, "\nComp. %s at %d,%d should be 255, not %d\n", #v, row, \
183             col, v); \
184     retval = 0;  exitStatus = -1;  goto bailout; \
185   } \
186 }
187 
188 
checkBuf(unsigned char * buf,int w,int h,int pf,int subsamp,tjscalingfactor sf,int flags)189 static int checkBuf(unsigned char *buf, int w, int h, int pf, int subsamp,
190                     tjscalingfactor sf, int flags)
191 {
192   int roffset = tjRedOffset[pf];
193   int goffset = tjGreenOffset[pf];
194   int boffset = tjBlueOffset[pf];
195   int aoffset = tjAlphaOffset[pf];
196   int ps = tjPixelSize[pf];
197   int index, row, col, retval = 1;
198   int halfway = 16 * sf.num / sf.denom;
199   int blocksize = 8 * sf.num / sf.denom;
200 
201   if (pf == TJPF_GRAY) roffset = goffset = boffset = 0;
202 
203   if (pf == TJPF_CMYK) {
204     for (row = 0; row < h; row++) {
205       for (col = 0; col < w; col++) {
206         unsigned char c, m, y, k;
207 
208         if (flags & TJFLAG_BOTTOMUP) index = (h - row - 1) * w + col;
209         else index = row * w + col;
210         c = buf[index * ps];
211         m = buf[index * ps + 1];
212         y = buf[index * ps + 2];
213         k = buf[index * ps + 3];
214         if (((row / blocksize) + (col / blocksize)) % 2 == 0) {
215           CHECKVAL255(c);  CHECKVAL255(m);  CHECKVAL255(y);
216           if (row < halfway) CHECKVAL255(k)
217           else CHECKVAL0(k)
218         } else {
219           CHECKVAL255(c);  CHECKVAL0(y);  CHECKVAL255(k);
220           if (row < halfway) CHECKVAL0(m)
221           else CHECKVAL255(m)
222         }
223       }
224     }
225     return 1;
226   }
227 
228   for (row = 0; row < h; row++) {
229     for (col = 0; col < w; col++) {
230       unsigned char r, g, b, a;
231 
232       if (flags & TJFLAG_BOTTOMUP) index = (h - row - 1) * w + col;
233       else index = row * w + col;
234       r = buf[index * ps + roffset];
235       g = buf[index * ps + goffset];
236       b = buf[index * ps + boffset];
237       a = aoffset >= 0 ? buf[index * ps + aoffset] : 0xFF;
238       if (((row / blocksize) + (col / blocksize)) % 2 == 0) {
239         if (row < halfway) {
240           CHECKVAL255(r);  CHECKVAL255(g);  CHECKVAL255(b);
241         } else {
242           CHECKVAL0(r);  CHECKVAL0(g);  CHECKVAL0(b);
243         }
244       } else {
245         if (subsamp == TJSAMP_GRAY) {
246           if (row < halfway) {
247             CHECKVAL(r, 76);  CHECKVAL(g, 76);  CHECKVAL(b, 76);
248           } else {
249             CHECKVAL(r, 226);  CHECKVAL(g, 226);  CHECKVAL(b, 226);
250           }
251         } else {
252           if (row < halfway) {
253             CHECKVAL255(r);  CHECKVAL0(g);  CHECKVAL0(b);
254           } else {
255             CHECKVAL255(r);  CHECKVAL255(g);  CHECKVAL0(b);
256           }
257         }
258       }
259       CHECKVAL255(a);
260     }
261   }
262 
263 bailout:
264   if (retval == 0) {
265     for (row = 0; row < h; row++) {
266       for (col = 0; col < w; col++) {
267         if (pf == TJPF_CMYK)
268           fprintf(stderr, "%.3d/%.3d/%.3d/%.3d ", buf[(row * w + col) * ps],
269                   buf[(row * w + col) * ps + 1], buf[(row * w + col) * ps + 2],
270                   buf[(row * w + col) * ps + 3]);
271         else
272           fprintf(stderr, "%.3d/%.3d/%.3d ",
273                   buf[(row * w + col) * ps + roffset],
274                   buf[(row * w + col) * ps + goffset],
275                   buf[(row * w + col) * ps + boffset]);
276       }
277       fprintf(stderr, "\n");
278     }
279   }
280   return retval;
281 }
282 
283 
284 #define PAD(v, p)  ((v + (p) - 1) & (~((p) - 1)))
285 
checkBufYUV(unsigned char * buf,int w,int h,int subsamp,tjscalingfactor sf)286 static int checkBufYUV(unsigned char *buf, int w, int h, int subsamp,
287                        tjscalingfactor sf)
288 {
289   int row, col;
290   int hsf = tjMCUWidth[subsamp] / 8, vsf = tjMCUHeight[subsamp] / 8;
291   int pw = PAD(w, hsf), ph = PAD(h, vsf);
292   int cw = pw / hsf, ch = ph / vsf;
293   int ypitch = PAD(pw, yuvAlign), uvpitch = PAD(cw, yuvAlign);
294   int retval = 1;
295   int halfway = 16 * sf.num / sf.denom;
296   int blocksize = 8 * sf.num / sf.denom;
297 
298   for (row = 0; row < ph; row++) {
299     for (col = 0; col < pw; col++) {
300       unsigned char y = buf[ypitch * row + col];
301 
302       if (((row / blocksize) + (col / blocksize)) % 2 == 0) {
303         if (row < halfway) CHECKVAL255(y)
304         else CHECKVAL0(y);
305       } else {
306         if (row < halfway) CHECKVAL(y, 76)
307         else CHECKVAL(y, 226);
308       }
309     }
310   }
311   if (subsamp != TJSAMP_GRAY) {
312     halfway = 16 / vsf * sf.num / sf.denom;
313 
314     for (row = 0; row < ch; row++) {
315       for (col = 0; col < cw; col++) {
316         unsigned char u = buf[ypitch * ph + (uvpitch * row + col)],
317           v = buf[ypitch * ph + uvpitch * ch + (uvpitch * row + col)];
318 
319         if (((row * vsf / blocksize) + (col * hsf / blocksize)) % 2 == 0) {
320           CHECKVAL(u, 128);  CHECKVAL(v, 128);
321         } else {
322           if (row < halfway) {
323             CHECKVAL(u, 85);  CHECKVAL255(v);
324           } else {
325             CHECKVAL0(u);  CHECKVAL(v, 149);
326           }
327         }
328       }
329     }
330   }
331 
332 bailout:
333   if (retval == 0) {
334     for (row = 0; row < ph; row++) {
335       for (col = 0; col < pw; col++)
336         fprintf(stderr, "%.3d ", buf[ypitch * row + col]);
337       fprintf(stderr, "\n");
338     }
339     fprintf(stderr, "\n");
340     for (row = 0; row < ch; row++) {
341       for (col = 0; col < cw; col++)
342         fprintf(stderr, "%.3d ", buf[ypitch * ph + (uvpitch * row + col)]);
343       fprintf(stderr, "\n");
344     }
345     fprintf(stderr, "\n");
346     for (row = 0; row < ch; row++) {
347       for (col = 0; col < cw; col++)
348         fprintf(stderr, "%.3d ",
349                 buf[ypitch * ph + uvpitch * ch + (uvpitch * row + col)]);
350       fprintf(stderr, "\n");
351     }
352   }
353 
354   return retval;
355 }
356 
357 
writeJPEG(unsigned char * jpegBuf,unsigned long jpegSize,char * filename)358 static void writeJPEG(unsigned char *jpegBuf, unsigned long jpegSize,
359                       char *filename)
360 {
361 #if defined(ANDROID) && defined(GTEST)
362   char path[filePathSize];
363   SNPRINTF(path, filePathSize, "/sdcard/%s", filename);
364   FILE *file = fopen(path, "wb");
365 #else
366   FILE *file = fopen(filename, "wb");
367 #endif
368   if (!file || fwrite(jpegBuf, jpegSize, 1, file) != 1) {
369     fprintf(stderr, "ERROR: Could not write to %s.\n%s\n", filename,
370             strerror(errno));
371     BAILOUT()
372   }
373 
374 bailout:
375   if (file) fclose(file);
376 }
377 
378 
compTest(tjhandle handle,unsigned char ** dstBuf,unsigned long * dstSize,int w,int h,int pf,char * basename,int subsamp,int jpegQual,int flags)379 static void compTest(tjhandle handle, unsigned char **dstBuf,
380                      unsigned long *dstSize, int w, int h, int pf,
381                      char *basename, int subsamp, int jpegQual, int flags)
382 {
383   char tempStr[filePathSize];
384   unsigned char *srcBuf = NULL, *yuvBuf = NULL;
385   const char *pfStr = pixFormatStr[pf];
386   const char *buStrLong =
387     (flags & TJFLAG_BOTTOMUP) ? "Bottom-Up" : "Top-Down ";
388   const char *buStr = (flags & TJFLAG_BOTTOMUP) ? "BU" : "TD";
389 
390   if ((srcBuf = (unsigned char *)malloc(w * h * tjPixelSize[pf])) == NULL)
391     THROW("Memory allocation failure");
392   initBuf(srcBuf, w, h, pf, flags);
393 
394   if (*dstBuf && *dstSize > 0) memset(*dstBuf, 0, *dstSize);
395 
396   if (!alloc) flags |= TJFLAG_NOREALLOC;
397   if (doYUV) {
398     unsigned long yuvSize = tjBufSizeYUV2(w, yuvAlign, h, subsamp);
399     tjscalingfactor sf = { 1, 1 };
400     tjhandle handle2 = tjInitCompress();
401 
402     if (!handle2) THROW_TJ();
403 
404     if ((yuvBuf = (unsigned char *)malloc(yuvSize)) == NULL)
405       THROW("Memory allocation failure");
406     memset(yuvBuf, 0, yuvSize);
407 
408     fprintf(stderr, "%s %s -> YUV %s ... ", pfStr, buStrLong,
409             subNameLong[subsamp]);
410     TRY_TJ(tjEncodeYUV3(handle2, srcBuf, w, 0, h, pf, yuvBuf, yuvAlign,
411                         subsamp, flags));
412     tjDestroy(handle2);
413     if (checkBufYUV(yuvBuf, w, h, subsamp, sf)) fprintf(stderr, "Passed.\n");
414     else fprintf(stderr, "FAILED!\n");
415 
416     fprintf(stderr, "YUV %s %s -> JPEG Q%d ... ", subNameLong[subsamp],
417             buStrLong, jpegQual);
418     TRY_TJ(tjCompressFromYUV(handle, yuvBuf, w, yuvAlign, h, subsamp, dstBuf,
419                              dstSize, jpegQual, flags));
420   } else {
421     fprintf(stderr, "%s %s -> %s Q%d ... ", pfStr, buStrLong,
422             subNameLong[subsamp], jpegQual);
423     TRY_TJ(tjCompress2(handle, srcBuf, w, 0, h, pf, dstBuf, dstSize, subsamp,
424                        jpegQual, flags));
425   }
426 
427   SNPRINTF(tempStr, filePathSize, "%s_enc_%s_%s_%s_Q%d.jpg", basename, pfStr,
428            buStr, subName[subsamp], jpegQual);
429   writeJPEG(*dstBuf, *dstSize, tempStr);
430   fprintf(stderr, "Done.\n  Result in %s\n", tempStr);
431 
432 bailout:
433   free(yuvBuf);
434   free(srcBuf);
435 }
436 
437 
_decompTest(tjhandle handle,unsigned char * jpegBuf,unsigned long jpegSize,int w,int h,int pf,char * basename,int subsamp,int flags,tjscalingfactor sf)438 static void _decompTest(tjhandle handle, unsigned char *jpegBuf,
439                         unsigned long jpegSize, int w, int h, int pf,
440                         char *basename, int subsamp, int flags,
441                         tjscalingfactor sf)
442 {
443   unsigned char *dstBuf = NULL, *yuvBuf = NULL;
444   int _hdrw = 0, _hdrh = 0, _hdrsubsamp = -1;
445   int scaledWidth = TJSCALED(w, sf);
446   int scaledHeight = TJSCALED(h, sf);
447   unsigned long dstSize = 0;
448 
449   TRY_TJ(tjDecompressHeader2(handle, jpegBuf, jpegSize, &_hdrw, &_hdrh,
450                              &_hdrsubsamp));
451   if (_hdrw != w || _hdrh != h || _hdrsubsamp != subsamp)
452     THROW("Incorrect JPEG header");
453 
454   dstSize = scaledWidth * scaledHeight * tjPixelSize[pf];
455   if ((dstBuf = (unsigned char *)malloc(dstSize)) == NULL)
456     THROW("Memory allocation failure");
457   memset(dstBuf, 0, dstSize);
458 
459   if (doYUV) {
460     unsigned long yuvSize = tjBufSizeYUV2(scaledWidth, yuvAlign, scaledHeight,
461                                           subsamp);
462     tjhandle handle2 = tjInitDecompress();
463 
464     if (!handle2) THROW_TJ();
465 
466     if ((yuvBuf = (unsigned char *)malloc(yuvSize)) == NULL)
467       THROW("Memory allocation failure");
468     memset(yuvBuf, 0, yuvSize);
469 
470     fprintf(stderr, "JPEG -> YUV %s ", subNameLong[subsamp]);
471     if (sf.num != 1 || sf.denom != 1)
472       fprintf(stderr, "%d/%d ... ", sf.num, sf.denom);
473     else fprintf(stderr, "... ");
474     /* We pass scaledWidth + 1 and scaledHeight + 1 to validate that
475        tjDecompressToYUV2() generates the largest possible scaled image that
476        fits within the desired dimensions, as documented. */
477     TRY_TJ(tjDecompressToYUV2(handle, jpegBuf, jpegSize, yuvBuf,
478                               scaledWidth + 1, yuvAlign, scaledHeight + 1,
479                               flags));
480     if (checkBufYUV(yuvBuf, scaledWidth, scaledHeight, subsamp, sf))
481       fprintf(stderr, "Passed.\n");
482     else fprintf(stderr, "FAILED!\n");
483 
484     fprintf(stderr, "YUV %s -> %s %s ... ", subNameLong[subsamp],
485             pixFormatStr[pf],
486             (flags & TJFLAG_BOTTOMUP) ? "Bottom-Up" : "Top-Down ");
487     TRY_TJ(tjDecodeYUV(handle2, yuvBuf, yuvAlign, subsamp, dstBuf, scaledWidth, 0,
488                        scaledHeight, pf, flags));
489     tjDestroy(handle2);
490   } else {
491     fprintf(stderr, "JPEG -> %s %s ", pixFormatStr[pf],
492             (flags & TJFLAG_BOTTOMUP) ? "Bottom-Up" : "Top-Down ");
493     if (sf.num != 1 || sf.denom != 1)
494       fprintf(stderr, "%d/%d ... ", sf.num, sf.denom);
495     else fprintf(stderr, "... ");
496     /* We pass scaledWidth + 1 and scaledHeight + 1 to validate that
497        tjDecompress2() generates the largest possible scaled image that fits
498        within the desired dimensions, as documented. */
499     TRY_TJ(tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, scaledWidth + 1, 0,
500                          scaledHeight + 1, pf, flags));
501   }
502 
503   if (checkBuf(dstBuf, scaledWidth, scaledHeight, pf, subsamp, sf, flags))
504     fprintf(stderr, "Passed.");
505   else fprintf(stderr, "FAILED!");
506   fprintf(stderr, "\n");
507 
508 bailout:
509   free(yuvBuf);
510   free(dstBuf);
511 }
512 
513 
decompTest(tjhandle handle,unsigned char * jpegBuf,unsigned long jpegSize,int w,int h,int pf,char * basename,int subsamp,int flags)514 static void decompTest(tjhandle handle, unsigned char *jpegBuf,
515                        unsigned long jpegSize, int w, int h, int pf,
516                        char *basename, int subsamp, int flags)
517 {
518   int i, n = 0;
519   tjscalingfactor *sf = tjGetScalingFactors(&n);
520 
521   if (!sf || !n) THROW_TJ();
522 
523   for (i = 0; i < n; i++) {
524     if (subsamp == TJSAMP_444 || subsamp == TJSAMP_GRAY ||
525         (subsamp == TJSAMP_411 && sf[i].num == 1 &&
526          (sf[i].denom == 2 || sf[i].denom == 1)) ||
527         (subsamp != TJSAMP_411 && sf[i].num == 1 &&
528          (sf[i].denom == 4 || sf[i].denom == 2 || sf[i].denom == 1)))
529       _decompTest(handle, jpegBuf, jpegSize, w, h, pf, basename, subsamp,
530                   flags, sf[i]);
531   }
532 
533 bailout:
534   return;
535 }
536 
537 
doTest(int w,int h,const int * formats,int nformats,int subsamp,char * basename)538 static void doTest(int w, int h, const int *formats, int nformats, int subsamp,
539                    char *basename)
540 {
541   tjhandle chandle = NULL, dhandle = NULL;
542   unsigned char *dstBuf = NULL;
543   unsigned long size = 0;
544   int pfi, pf, i;
545 
546   if (!alloc)
547     size = tjBufSize(w, h, subsamp);
548   if (size != 0)
549     if ((dstBuf = (unsigned char *)tjAlloc(size)) == NULL)
550       THROW("Memory allocation failure.");
551 
552   if ((chandle = tjInitCompress()) == NULL ||
553       (dhandle = tjInitDecompress()) == NULL)
554     THROW_TJ();
555 
556   for (pfi = 0; pfi < nformats; pfi++) {
557     for (i = 0; i < 2; i++) {
558       int flags = 0;
559 
560       if (subsamp == TJSAMP_422 || subsamp == TJSAMP_420 ||
561           subsamp == TJSAMP_440 || subsamp == TJSAMP_411)
562         flags |= TJFLAG_FASTUPSAMPLE;
563       if (i == 1) flags |= TJFLAG_BOTTOMUP;
564       pf = formats[pfi];
565       compTest(chandle, &dstBuf, &size, w, h, pf, basename, subsamp, 100,
566                flags);
567       decompTest(dhandle, dstBuf, size, w, h, pf, basename, subsamp, flags);
568       if (pf >= TJPF_RGBX && pf <= TJPF_XRGB) {
569         fprintf(stderr, "\n");
570         decompTest(dhandle, dstBuf, size, w, h, pf + (TJPF_RGBA - TJPF_RGBX),
571                    basename, subsamp, flags);
572       }
573       fprintf(stderr, "\n");
574     }
575   }
576   fprintf(stderr, "--------------------\n\n");
577 
578 bailout:
579   if (chandle) tjDestroy(chandle);
580   if (dhandle) tjDestroy(dhandle);
581   tjFree(dstBuf);
582 }
583 
584 
585 #if SIZEOF_SIZE_T == 8
586 #define CHECKSIZE(function) { \
587   if ((unsigned long long)size < (unsigned long long)0xFFFFFFFF) \
588     THROW(#function " overflow"); \
589 }
590 #else
591 #define CHECKSIZE(function) { \
592   if (size != (unsigned long)(-1) || \
593       !strcmp(tjGetErrorStr2(NULL), "No error")) \
594     THROW(#function " overflow"); \
595 }
596 #endif
597 #define CHECKSIZEINT(function) { \
598   if (intsize != -1 || !strcmp(tjGetErrorStr2(NULL), "No error")) \
599     THROW(#function " overflow"); \
600 }
601 
602 #ifndef GTEST
overflowTest(void)603 static void overflowTest(void)
604 {
605   /* Ensure that the various buffer size functions don't overflow */
606   unsigned long size;
607   int intsize;
608 
609   size = tjBufSize(26755, 26755, TJSAMP_444);
610   CHECKSIZE(tjBufSize());
611   size = TJBUFSIZE(26755, 26755);
612   CHECKSIZE(TJBUFSIZE());
613   size = tjBufSizeYUV2(37838, 1, 37838, TJSAMP_444);
614   CHECKSIZE(tjBufSizeYUV2());
615   size = tjBufSizeYUV2(37837, 3, 37837, TJSAMP_444);
616   CHECKSIZE(tjBufSizeYUV2());
617   size = tjBufSizeYUV2(37837, -1, 37837, TJSAMP_444);
618   CHECKSIZE(tjBufSizeYUV2());
619   size = TJBUFSIZEYUV(37838, 37838, TJSAMP_444);
620   CHECKSIZE(TJBUFSIZEYUV());
621   size = tjBufSizeYUV(37838, 37838, TJSAMP_444);
622   CHECKSIZE(tjBufSizeYUV());
623   size = tjPlaneSizeYUV(0, 65536, 0, 65536, TJSAMP_444);
624   CHECKSIZE(tjPlaneSizeYUV());
625   intsize = tjPlaneWidth(0, INT_MAX, TJSAMP_420);
626   CHECKSIZEINT(tjPlaneWidth());
627   intsize = tjPlaneHeight(0, INT_MAX, TJSAMP_420);
628   CHECKSIZEINT(tjPlaneHeight());
629 
630 bailout:
631   return;
632 }
633 #endif
634 
635 
bufSizeTest(void)636 static void bufSizeTest(void)
637 {
638   int w, h, i, subsamp;
639   unsigned char *srcBuf = NULL, *dstBuf = NULL;
640   tjhandle handle = NULL;
641   unsigned long dstSize = 0;
642 
643   if ((handle = tjInitCompress()) == NULL) THROW_TJ();
644 
645   fprintf(stderr, "Buffer size regression test\n");
646   for (subsamp = 0; subsamp < TJ_NUMSAMP; subsamp++) {
647     for (w = 1; w < 48; w++) {
648       int maxh = (w == 1) ? 2048 : 48;
649 
650       for (h = 1; h < maxh; h++) {
651         if (h % 100 == 0)
652           fprintf(stderr, "%.4d x %.4d\b\b\b\b\b\b\b\b\b\b\b", w, h);
653         if ((srcBuf = (unsigned char *)malloc(w * h * 4)) == NULL)
654           THROW("Memory allocation failure");
655         if (!alloc || doYUV) {
656           if (doYUV) dstSize = tjBufSizeYUV2(w, yuvAlign, h, subsamp);
657           else dstSize = tjBufSize(w, h, subsamp);
658           if ((dstBuf = (unsigned char *)tjAlloc(dstSize)) == NULL)
659             THROW("Memory allocation failure");
660         }
661 
662         for (i = 0; i < w * h * 4; i++) {
663           if (random() < RAND_MAX / 2) srcBuf[i] = 0;
664           else srcBuf[i] = 255;
665         }
666 
667         if (doYUV) {
668           TRY_TJ(tjEncodeYUV3(handle, srcBuf, w, 0, h, TJPF_BGRX, dstBuf,
669                               yuvAlign, subsamp, 0));
670         } else {
671           TRY_TJ(tjCompress2(handle, srcBuf, w, 0, h, TJPF_BGRX, &dstBuf,
672                              &dstSize, subsamp, 100,
673                              alloc ? 0 : TJFLAG_NOREALLOC));
674         }
675         free(srcBuf);  srcBuf = NULL;
676         if (!alloc || doYUV) {
677           tjFree(dstBuf);  dstBuf = NULL;
678         }
679 
680         if ((srcBuf = (unsigned char *)malloc(h * w * 4)) == NULL)
681           THROW("Memory allocation failure");
682         if (!alloc || doYUV) {
683           if (doYUV) dstSize = tjBufSizeYUV2(h, yuvAlign, w, subsamp);
684           else dstSize = tjBufSize(h, w, subsamp);
685           if ((dstBuf = (unsigned char *)tjAlloc(dstSize)) == NULL)
686             THROW("Memory allocation failure");
687         }
688 
689         for (i = 0; i < h * w * 4; i++) {
690           if (random() < RAND_MAX / 2) srcBuf[i] = 0;
691           else srcBuf[i] = 255;
692         }
693 
694         if (doYUV) {
695           TRY_TJ(tjEncodeYUV3(handle, srcBuf, h, 0, w, TJPF_BGRX, dstBuf,
696                               yuvAlign, subsamp, 0));
697         } else {
698           TRY_TJ(tjCompress2(handle, srcBuf, h, 0, w, TJPF_BGRX, &dstBuf,
699                              &dstSize, subsamp, 100,
700                              alloc ? 0 : TJFLAG_NOREALLOC));
701         }
702         free(srcBuf);  srcBuf = NULL;
703         if (!alloc || doYUV) {
704           tjFree(dstBuf);  dstBuf = NULL;
705         }
706       }
707     }
708   }
709   fprintf(stderr, "Done.      \n");
710 
711 bailout:
712   free(srcBuf);
713   tjFree(dstBuf);
714   if (handle) tjDestroy(handle);
715 }
716 
717 
initBitmap(unsigned char * buf,int width,int pitch,int height,int pf,int flags)718 static void initBitmap(unsigned char *buf, int width, int pitch, int height,
719                        int pf, int flags)
720 {
721   int roffset = tjRedOffset[pf];
722   int goffset = tjGreenOffset[pf];
723   int boffset = tjBlueOffset[pf];
724   int ps = tjPixelSize[pf];
725   int i, j;
726 
727   for (j = 0; j < height; j++) {
728     int row = (flags & TJFLAG_BOTTOMUP) ? height - j - 1 : j;
729 
730     for (i = 0; i < width; i++) {
731       unsigned char r = (i * 256 / width) % 256;
732       unsigned char g = (j * 256 / height) % 256;
733       unsigned char b = (j * 256 / height + i * 256 / width) % 256;
734 
735       memset(&buf[row * pitch + i * ps], 0, ps);
736       if (pf == TJPF_GRAY) buf[row * pitch + i * ps] = b;
737       else if (pf == TJPF_CMYK)
738         rgb_to_cmyk(r, g, b, &buf[row * pitch + i * ps + 0],
739                     &buf[row * pitch + i * ps + 1],
740                     &buf[row * pitch + i * ps + 2],
741                     &buf[row * pitch + i * ps + 3]);
742       else {
743         buf[row * pitch + i * ps + roffset] = r;
744         buf[row * pitch + i * ps + goffset] = g;
745         buf[row * pitch + i * ps + boffset] = b;
746       }
747     }
748   }
749 }
750 
751 
cmpBitmap(unsigned char * buf,int width,int pitch,int height,int pf,int flags,int gray2rgb)752 static int cmpBitmap(unsigned char *buf, int width, int pitch, int height,
753                      int pf, int flags, int gray2rgb)
754 {
755   int roffset = tjRedOffset[pf];
756   int goffset = tjGreenOffset[pf];
757   int boffset = tjBlueOffset[pf];
758   int aoffset = tjAlphaOffset[pf];
759   int ps = tjPixelSize[pf];
760   int i, j;
761 
762   for (j = 0; j < height; j++) {
763     int row = (flags & TJFLAG_BOTTOMUP) ? height - j - 1 : j;
764 
765     for (i = 0; i < width; i++) {
766       unsigned char r = (i * 256 / width) % 256;
767       unsigned char g = (j * 256 / height) % 256;
768       unsigned char b = (j * 256 / height + i * 256 / width) % 256;
769 
770       if (pf == TJPF_GRAY) {
771         if (buf[row * pitch + i * ps] != b)
772           return 0;
773       } else if (pf == TJPF_CMYK) {
774         unsigned char rf, gf, bf;
775 
776         cmyk_to_rgb(buf[row * pitch + i * ps + 0],
777                     buf[row * pitch + i * ps + 1],
778                     buf[row * pitch + i * ps + 2],
779                     buf[row * pitch + i * ps + 3], &rf, &gf, &bf);
780         if (gray2rgb) {
781           if (rf != b || gf != b || bf != b)
782             return 0;
783         } else if (rf != r || gf != g || bf != b) return 0;
784       } else {
785         if (gray2rgb) {
786           if (buf[row * pitch + i * ps + roffset] != b ||
787               buf[row * pitch + i * ps + goffset] != b ||
788               buf[row * pitch + i * ps + boffset] != b)
789             return 0;
790         } else if (buf[row * pitch + i * ps + roffset] != r ||
791                    buf[row * pitch + i * ps + goffset] != g ||
792                    buf[row * pitch + i * ps + boffset] != b)
793           return 0;
794         if (aoffset >= 0 && buf[row * pitch + i * ps + aoffset] != 0xFF)
795           return 0;
796       }
797     }
798   }
799   return 1;
800 }
801 
802 
doBmpTest(const char * ext,int width,int align,int height,int pf,int flags)803 static int doBmpTest(const char *ext, int width, int align, int height, int pf,
804                      int flags)
805 {
806   const size_t filenameSize = 80;
807   char filename[filenameSize], *md5sum, md5buf[65];
808   int ps = tjPixelSize[pf], pitch = PAD(width * ps, align), loadWidth = 0,
809     loadHeight = 0, retval = 0, pixelFormat = pf;
810   unsigned char *buf = NULL;
811   char *md5ref;
812 
813   if (pf == TJPF_GRAY) {
814     md5ref = !strcasecmp(ext, "ppm") ? "112c682e82ce5de1cca089e20d60000b" :
815                                        "51976530acf75f02beddf5d21149101d";
816   } else {
817     md5ref = !strcasecmp(ext, "ppm") ? "c0c9f772b464d1896326883a5c79c545" :
818                                        "6d659071b9bfcdee2def22cb58ddadca";
819   }
820 
821   if ((buf = (unsigned char *)tjAlloc(pitch * height)) == NULL)
822     THROW("Could not allocate memory");
823   initBitmap(buf, width, pitch, height, pf, flags);
824 
825 #if defined(ANDROID) && defined(GTEST)
826   SNPRINTF(filename, filenameSize, "/sdcard/test_bmp_%s_%d_%s.%s",
827            pixFormatStr[pf], align, (flags & TJFLAG_BOTTOMUP) ? "bu" : "td",
828            ext);
829 #else
830   SNPRINTF(filename, filenameSize, "test_bmp_%s_%d_%s.%s", pixFormatStr[pf],
831            align, (flags & TJFLAG_BOTTOMUP) ? "bu" : "td", ext);
832 #endif
833   TRY_TJ(tjSaveImage(filename, buf, width, pitch, height, pf, flags));
834   md5sum = MD5File(filename, md5buf);
835   if (strcasecmp(md5sum, md5ref))
836     THROW_MD5(filename, md5sum, md5ref);
837 
838   tjFree(buf);  buf = NULL;
839   if ((buf = tjLoadImage(filename, &loadWidth, align, &loadHeight, &pf,
840                          flags)) == NULL)
841     THROW_TJ();
842   if (width != loadWidth || height != loadHeight) {
843     fprintf(stderr, "\n   Image dimensions of %s are bogus\n", filename);
844     retval = -1;  goto bailout;
845   }
846   if (!cmpBitmap(buf, width, pitch, height, pf, flags, 0)) {
847     fprintf(stderr, "\n   Pixel data in %s is bogus\n", filename);
848     retval = -1;  goto bailout;
849   }
850   if (pf == TJPF_GRAY) {
851     tjFree(buf);  buf = NULL;
852     pf = TJPF_XBGR;
853     if ((buf = tjLoadImage(filename, &loadWidth, align, &loadHeight, &pf,
854                            flags)) == NULL)
855       THROW_TJ();
856     pitch = PAD(width * tjPixelSize[pf], align);
857     if (!cmpBitmap(buf, width, pitch, height, pf, flags, 1)) {
858       fprintf(stderr, "\n   Converting %s to RGB failed\n", filename);
859       retval = -1;  goto bailout;
860     }
861 
862     tjFree(buf);  buf = NULL;
863     pf = TJPF_CMYK;
864     if ((buf = tjLoadImage(filename, &loadWidth, align, &loadHeight, &pf,
865                            flags)) == NULL)
866       THROW_TJ();
867     pitch = PAD(width * tjPixelSize[pf], align);
868     if (!cmpBitmap(buf, width, pitch, height, pf, flags, 1)) {
869       fprintf(stderr, "\n   Converting %s to CMYK failed\n", filename);
870       retval = -1;  goto bailout;
871     }
872   }
873   /* Verify that tjLoadImage() returns the proper "preferred" pixel format for
874      the file type. */
875   tjFree(buf);  buf = NULL;
876   pf = pixelFormat;
877   pixelFormat = TJPF_UNKNOWN;
878   if ((buf = tjLoadImage(filename, &loadWidth, align, &loadHeight,
879                          &pixelFormat, flags)) == NULL)
880     THROW_TJ();
881   if ((pf == TJPF_GRAY && pixelFormat != TJPF_GRAY) ||
882       (pf != TJPF_GRAY && !strcasecmp(ext, "bmp") &&
883        pixelFormat != TJPF_BGR) ||
884       (pf != TJPF_GRAY && !strcasecmp(ext, "ppm") &&
885        pixelFormat != TJPF_RGB)) {
886     fprintf(stderr,
887             "\n   tjLoadImage() returned unexpected pixel format: %s\n",
888             pixFormatStr[pixelFormat]);
889     retval = -1;
890   }
891   unlink(filename);
892 
893 bailout:
894   tjFree(buf);
895   if (exitStatus < 0) return exitStatus;
896   return retval;
897 }
898 
899 
bmpTest(void)900 static int bmpTest(void)
901 {
902   int align, width = 35, height = 39, format;
903 
904   for (align = 1; align <= 8; align *= 2) {
905     for (format = 0; format < TJ_NUMPF; format++) {
906       fprintf(stderr, "%s Top-Down BMP (row alignment = %d bytes)  ...  ",
907               pixFormatStr[format], align);
908       if (doBmpTest("bmp", width, align, height, format, 0) == -1)
909         return -1;
910       fprintf(stderr, "OK.\n");
911 
912       fprintf(stderr, "%s Top-Down PPM (row alignment = %d bytes)  ...  ",
913               pixFormatStr[format], align);
914       if (doBmpTest("ppm", width, align, height, format,
915                     TJFLAG_BOTTOMUP) == -1)
916         return -1;
917       fprintf(stderr, "OK.\n");
918 
919       fprintf(stderr, "%s Bottom-Up BMP (row alignment = %d bytes)  ...  ",
920               pixFormatStr[format], align);
921       if (doBmpTest("bmp", width, align, height, format, 0) == -1)
922         return -1;
923       fprintf(stderr, "OK.\n");
924 
925       fprintf(stderr, "%s Bottom-Up PPM (row alignment = %d bytes)  ...  ",
926               pixFormatStr[format], align);
927       if (doBmpTest("ppm", width, align, height, format,
928                     TJFLAG_BOTTOMUP) == -1)
929         return -1;
930       fprintf(stderr, "OK.\n");
931     }
932   }
933 
934   return 0;
935 }
936 
937 
938 #ifdef GTEST
initTJUnitTest(int yuv,int noyuvpad,int autoalloc)939 static void initTJUnitTest(int yuv, int noyuvpad, int autoalloc)
940 {
941   doYUV = yuv ? 1 : 0;
942   yuvAlign = noyuvpad ? 1 : 4;
943   alloc = autoalloc ? 1 : 0;
944 
945   exitStatus = 0;
946 }
947 
948 
testBmp(int yuv,int noyuvpad,int autoalloc)949 int testBmp(int yuv, int noyuvpad, int autoalloc)
950 {
951   initTJUnitTest(yuv, noyuvpad, autoalloc);
952 
953   return bmpTest();
954 }
955 
956 
testThreeByte444(int yuv,int noyuvpad,int autoalloc)957 int testThreeByte444(int yuv, int noyuvpad, int autoalloc)
958 {
959   initTJUnitTest(yuv, noyuvpad, autoalloc);
960 
961   doTest(35, 39, _3byteFormats, 2, TJSAMP_444, "test");
962   return exitStatus;
963 }
964 
965 
testFourByte444(int yuv,int noyuvpad,int autoalloc)966 int testFourByte444(int yuv, int noyuvpad, int autoalloc)
967 {
968   initTJUnitTest(yuv, noyuvpad, autoalloc);
969 
970   int num4bf = doYUV ? 4 : 5;
971   doTest(39, 41, _4byteFormats, num4bf, TJSAMP_444, "test");
972   return exitStatus;
973 }
974 
975 
testThreeByte422(int yuv,int noyuvpad,int autoalloc)976 int testThreeByte422(int yuv, int noyuvpad, int autoalloc)
977 {
978   initTJUnitTest(yuv, noyuvpad, autoalloc);
979 
980   doTest(41, 35, _3byteFormats, 2, TJSAMP_422, "test");
981   return exitStatus;
982 }
983 
984 
testFourByte422(int yuv,int noyuvpad,int autoalloc)985 int testFourByte422(int yuv, int noyuvpad, int autoalloc)
986 {
987   initTJUnitTest(yuv, noyuvpad, autoalloc);
988 
989   int num4bf = doYUV ? 4 : 5;
990   doTest(35, 39, _4byteFormats, num4bf, TJSAMP_422, "test");
991   return exitStatus;
992 }
993 
994 
testThreeByte420(int yuv,int noyuvpad,int autoalloc)995 int testThreeByte420(int yuv, int noyuvpad, int autoalloc)
996 {
997   initTJUnitTest(yuv, noyuvpad, autoalloc);
998 
999   doTest(39, 41, _3byteFormats, 2, TJSAMP_420, "test");
1000   return exitStatus;
1001 }
1002 
1003 
testFourByte420(int yuv,int noyuvpad,int autoalloc)1004 int testFourByte420(int yuv, int noyuvpad, int autoalloc)
1005 {
1006   initTJUnitTest(yuv, noyuvpad, autoalloc);
1007 
1008   int num4bf = doYUV ? 4 : 5;
1009   doTest(41, 35, _4byteFormats, num4bf, TJSAMP_420, "test");
1010   return exitStatus;
1011 }
1012 
1013 
testThreeByte440(int yuv,int noyuvpad,int autoalloc)1014 int testThreeByte440(int yuv, int noyuvpad, int autoalloc)
1015 {
1016   initTJUnitTest(yuv, noyuvpad, autoalloc);
1017 
1018   doTest(35, 39, _3byteFormats, 2, TJSAMP_440, "test");
1019   return exitStatus;
1020 }
1021 
1022 
testFourByte440(int yuv,int noyuvpad,int autoalloc)1023 int testFourByte440(int yuv, int noyuvpad, int autoalloc)
1024 {
1025   initTJUnitTest(yuv, noyuvpad, autoalloc);
1026 
1027   int num4bf = doYUV ? 4 : 5;
1028   doTest(39, 41, _4byteFormats, num4bf, TJSAMP_440, "test");
1029   return exitStatus;
1030 }
1031 
1032 
testThreeByte411(int yuv,int noyuvpad,int autoalloc)1033 int testThreeByte411(int yuv, int noyuvpad, int autoalloc)
1034 {
1035   initTJUnitTest(yuv, noyuvpad, autoalloc);
1036 
1037   doTest(41, 35, _3byteFormats, 2, TJSAMP_411, "test");
1038   return exitStatus;
1039 }
1040 
1041 
testFourByte411(int yuv,int noyuvpad,int autoalloc)1042 int testFourByte411(int yuv, int noyuvpad, int autoalloc)
1043 {
1044   initTJUnitTest(yuv, noyuvpad, autoalloc);
1045 
1046   int num4bf = doYUV ? 4 : 5;
1047   doTest(35, 39, _4byteFormats, num4bf, TJSAMP_411, "test");
1048   return exitStatus;
1049 }
1050 
1051 
testOnlyGray(int yuv,int noyuvpad,int autoalloc)1052 int testOnlyGray(int yuv, int noyuvpad, int autoalloc)
1053 {
1054   initTJUnitTest(yuv, noyuvpad, autoalloc);
1055 
1056   doTest(39, 41, _onlyGray, 1, TJSAMP_GRAY, "test");
1057   return exitStatus;
1058 }
1059 
1060 
testThreeByteGray(int yuv,int noyuvpad,int autoalloc)1061 int testThreeByteGray(int yuv, int noyuvpad, int autoalloc)
1062 {
1063   initTJUnitTest(yuv, noyuvpad, autoalloc);
1064 
1065   doTest(41, 35, _3byteFormats, 2, TJSAMP_GRAY, "test");
1066   return exitStatus;
1067 }
1068 
1069 
testFourByteGray(int yuv,int noyuvpad,int autoalloc)1070 int testFourByteGray(int yuv, int noyuvpad, int autoalloc)
1071 {
1072   initTJUnitTest(yuv, noyuvpad, autoalloc);
1073 
1074   doTest(35, 39, _4byteFormats, 4, TJSAMP_GRAY, "test");
1075   return exitStatus;
1076 }
1077 
1078 
testBufSize(int yuv,int noyuvpad,int autoalloc)1079 int testBufSize(int yuv, int noyuvpad, int autoalloc)
1080 {
1081   initTJUnitTest(yuv, noyuvpad, autoalloc);
1082 
1083   bufSizeTest();
1084   return exitStatus;
1085 }
1086 
1087 
testYUVOnlyRGB444(int noyuvpad,int autoalloc)1088 int testYUVOnlyRGB444(int noyuvpad, int autoalloc)
1089 {
1090   initTJUnitTest(1, noyuvpad, autoalloc);
1091 
1092   doTest(48, 48, _onlyRGB, 1, TJSAMP_444, "test_yuv0");
1093   return exitStatus;
1094 }
1095 
1096 
testYUVOnlyRGB422(int noyuvpad,int autoalloc)1097 int testYUVOnlyRGB422(int noyuvpad, int autoalloc)
1098 {
1099   initTJUnitTest(1, noyuvpad, autoalloc);
1100 
1101   doTest(48, 48, _onlyRGB, 1, TJSAMP_422, "test_yuv0");
1102   return exitStatus;
1103 }
1104 
1105 
testYUVOnlyRGB420(int noyuvpad,int autoalloc)1106 int testYUVOnlyRGB420(int noyuvpad, int autoalloc)
1107 {
1108   initTJUnitTest(1, noyuvpad, autoalloc);
1109 
1110   doTest(48, 48, _onlyRGB, 1, TJSAMP_420, "test_yuv0");
1111   return exitStatus;
1112 }
1113 
1114 
testYUVOnlyRGB440(int noyuvpad,int autoalloc)1115 int testYUVOnlyRGB440(int noyuvpad, int autoalloc)
1116 {
1117   initTJUnitTest(1, noyuvpad, autoalloc);
1118 
1119   doTest(48, 48, _onlyRGB, 1, TJSAMP_440, "test_yuv0");
1120   return exitStatus;
1121 }
1122 
1123 
testYUVOnlyRGB411(int noyuvpad,int autoalloc)1124 int testYUVOnlyRGB411(int noyuvpad, int autoalloc)
1125 {
1126   initTJUnitTest(1, noyuvpad, autoalloc);
1127 
1128   doTest(48, 48, _onlyRGB, 1, TJSAMP_411, "test_yuv0");
1129   return exitStatus;
1130 }
1131 
1132 
testYUVOnlyRGBGray(int noyuvpad,int autoalloc)1133 int testYUVOnlyRGBGray(int noyuvpad, int autoalloc)
1134 {
1135   initTJUnitTest(1, noyuvpad, autoalloc);
1136 
1137   doTest(48, 48, _onlyRGB, 1, TJSAMP_GRAY, "test_yuv0");
1138   return exitStatus;
1139 }
1140 
1141 
testYUVOnlyGrayGray(int noyuvpad,int autoalloc)1142 int testYUVOnlyGrayGray(int noyuvpad, int autoalloc)
1143 {
1144   initTJUnitTest(1, noyuvpad, autoalloc);
1145 
1146   doTest(48, 48, _onlyGray, 1, TJSAMP_GRAY, "test_yuv0");
1147   return exitStatus;
1148 }
1149 
1150 #else
1151 
main(int argc,char * argv[])1152 int main(int argc, char *argv[])
1153 {
1154   int i, num4bf = 5;
1155 
1156 #ifdef _WIN32
1157   srand((unsigned int)time(NULL));
1158 #endif
1159   if (argc > 1) {
1160     for (i = 1; i < argc; i++) {
1161       if (!strcasecmp(argv[i], "-yuv")) doYUV = 1;
1162       else if (!strcasecmp(argv[i], "-noyuvpad")) yuvAlign = 1;
1163       else if (!strcasecmp(argv[i], "-alloc")) alloc = 1;
1164       else if (!strcasecmp(argv[i], "-bmp")) return bmpTest();
1165       else usage(argv[0]);
1166     }
1167   }
1168   if (alloc) printf("Testing automatic buffer allocation\n");
1169   if (doYUV) num4bf = 4;
1170   overflowTest();
1171   doTest(35, 39, _3byteFormats, 2, TJSAMP_444, "test");
1172   doTest(39, 41, _4byteFormats, num4bf, TJSAMP_444, "test");
1173   doTest(41, 35, _3byteFormats, 2, TJSAMP_422, "test");
1174   doTest(35, 39, _4byteFormats, num4bf, TJSAMP_422, "test");
1175   doTest(39, 41, _3byteFormats, 2, TJSAMP_420, "test");
1176   doTest(41, 35, _4byteFormats, num4bf, TJSAMP_420, "test");
1177   doTest(35, 39, _3byteFormats, 2, TJSAMP_440, "test");
1178   doTest(39, 41, _4byteFormats, num4bf, TJSAMP_440, "test");
1179   doTest(41, 35, _3byteFormats, 2, TJSAMP_411, "test");
1180   doTest(35, 39, _4byteFormats, num4bf, TJSAMP_411, "test");
1181   doTest(39, 41, _onlyGray, 1, TJSAMP_GRAY, "test");
1182   doTest(41, 35, _3byteFormats, 2, TJSAMP_GRAY, "test");
1183   doTest(35, 39, _4byteFormats, 4, TJSAMP_GRAY, "test");
1184   bufSizeTest();
1185   if (doYUV) {
1186     printf("\n--------------------\n\n");
1187     doTest(48, 48, _onlyRGB, 1, TJSAMP_444, "test_yuv0");
1188     doTest(48, 48, _onlyRGB, 1, TJSAMP_422, "test_yuv0");
1189     doTest(48, 48, _onlyRGB, 1, TJSAMP_420, "test_yuv0");
1190     doTest(48, 48, _onlyRGB, 1, TJSAMP_440, "test_yuv0");
1191     doTest(48, 48, _onlyRGB, 1, TJSAMP_411, "test_yuv0");
1192     doTest(48, 48, _onlyRGB, 1, TJSAMP_GRAY, "test_yuv0");
1193     doTest(48, 48, _onlyGray, 1, TJSAMP_GRAY, "test_yuv0");
1194   }
1195 
1196   return exitStatus;
1197 }
1198 #endif
1199