Home | History | Annotate | Download | only in codec
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <stdint.h>
      6 
      7 #include <limits>
      8 
      9 #include "codec_int.h"
     10 #include "testing/fx_string_testhelpers.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 
     13 static const OPJ_OFF_T kSkipError = static_cast<OPJ_OFF_T>(-1);
     14 static const OPJ_SIZE_T kReadError = static_cast<OPJ_SIZE_T>(-1);
     15 static const OPJ_SIZE_T kWriteError = static_cast<OPJ_SIZE_T>(-1);
     16 
     17 static unsigned char stream_data[] = {
     18     0x00, 0x01, 0x02, 0x03,
     19     0x84, 0x85, 0x86, 0x87,  // Include some hi-bytes, too.
     20 };
     21 
     22 TEST(fxcodec, DecodeDataNullDecodeData) {
     23   unsigned char buffer[16];
     24   DecodeData* ptr = nullptr;
     25 
     26   // Error codes, not segvs, should callers pass us a NULL pointer.
     27   EXPECT_EQ(kReadError, opj_read_from_memory(buffer, sizeof(buffer), ptr));
     28   EXPECT_EQ(kWriteError, opj_write_from_memory(buffer, sizeof(buffer), ptr));
     29   EXPECT_EQ(kSkipError, opj_skip_from_memory(1, ptr));
     30   EXPECT_FALSE(opj_seek_from_memory(1, ptr));
     31 }
     32 
     33 TEST(fxcodec, DecodeDataNullStream) {
     34   DecodeData dd(nullptr, 0);
     35   unsigned char buffer[16];
     36 
     37   // Reads of size 0 do nothing but return an error code.
     38   memset(buffer, 0xbd, sizeof(buffer));
     39   EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 0, &dd));
     40   EXPECT_EQ(0xbd, buffer[0]);
     41 
     42   // Reads of nonzero size do nothing but return an error code.
     43   memset(buffer, 0xbd, sizeof(buffer));
     44   EXPECT_EQ(kReadError, opj_read_from_memory(buffer, sizeof(buffer), &dd));
     45   EXPECT_EQ(0xbd, buffer[0]);
     46 
     47   // writes of size 0 do nothing but return an error code.
     48   EXPECT_EQ(kWriteError, opj_write_from_memory(buffer, 0, &dd));
     49 
     50   // writes of nonzero size do nothing but return an error code.
     51   EXPECT_EQ(kWriteError, opj_write_from_memory(buffer, sizeof(buffer), &dd));
     52 
     53   // Skips of size 0 always return an error code.
     54   EXPECT_EQ(kSkipError, opj_skip_from_memory(0, &dd));
     55 
     56   // Skips of nonzero size always return an error code.
     57   EXPECT_EQ(kSkipError, opj_skip_from_memory(1, &dd));
     58 
     59   // Seeks to 0 offset return in error.
     60   EXPECT_FALSE(opj_seek_from_memory(0, &dd));
     61 
     62   // Seeks to non-zero offsets return in error.
     63   EXPECT_FALSE(opj_seek_from_memory(1, &dd));
     64 }
     65 
     66 TEST(fxcodec, DecodeDataZeroSize) {
     67   DecodeData dd(stream_data, 0);
     68   unsigned char buffer[16];
     69 
     70   // Reads of size 0 do nothing but return an error code.
     71   memset(buffer, 0xbd, sizeof(buffer));
     72   EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 0, &dd));
     73   EXPECT_EQ(0xbd, buffer[0]);
     74 
     75   // Reads of nonzero size do nothing but return an error code.
     76   memset(buffer, 0xbd, sizeof(buffer));
     77   EXPECT_EQ(kReadError, opj_read_from_memory(buffer, sizeof(buffer), &dd));
     78   EXPECT_EQ(0xbd, buffer[0]);
     79 
     80   // writes of size 0 do nothing but return an error code.
     81   EXPECT_EQ(kWriteError, opj_write_from_memory(buffer, 0, &dd));
     82 
     83   // writes of nonzero size do nothing but return an error code.
     84   EXPECT_EQ(kWriteError, opj_write_from_memory(buffer, sizeof(buffer), &dd));
     85 
     86   // Skips of size 0 always return an error code.
     87   EXPECT_EQ(kSkipError, opj_skip_from_memory(0, &dd));
     88 
     89   // Skips of nonzero size always return an error code.
     90   EXPECT_EQ(kSkipError, opj_skip_from_memory(1, &dd));
     91 
     92   // Seeks to 0 offset return in error.
     93   EXPECT_FALSE(opj_seek_from_memory(0, &dd));
     94 
     95   // Seeks to non-zero offsets return in error.
     96   EXPECT_FALSE(opj_seek_from_memory(1, &dd));
     97 }
     98 
     99 TEST(fxcodec, DecodeDataReadInBounds) {
    100   unsigned char buffer[16];
    101   {
    102     DecodeData dd(stream_data, sizeof(stream_data));
    103 
    104     // Exact sized read in a single call.
    105     memset(buffer, 0xbd, sizeof(buffer));
    106     EXPECT_EQ(8u, opj_read_from_memory(buffer, sizeof(buffer), &dd));
    107     EXPECT_EQ(0x00, buffer[0]);
    108     EXPECT_EQ(0x01, buffer[1]);
    109     EXPECT_EQ(0x02, buffer[2]);
    110     EXPECT_EQ(0x03, buffer[3]);
    111     EXPECT_EQ(0x84, buffer[4]);
    112     EXPECT_EQ(0x85, buffer[5]);
    113     EXPECT_EQ(0x86, buffer[6]);
    114     EXPECT_EQ(0x87, buffer[7]);
    115     EXPECT_EQ(0xbd, buffer[8]);
    116   }
    117   {
    118     DecodeData dd(stream_data, sizeof(stream_data));
    119 
    120     // Simple read.
    121     memset(buffer, 0xbd, sizeof(buffer));
    122     EXPECT_EQ(2u, opj_read_from_memory(buffer, 2, &dd));
    123     EXPECT_EQ(0x00, buffer[0]);
    124     EXPECT_EQ(0x01, buffer[1]);
    125     EXPECT_EQ(0xbd, buffer[2]);
    126 
    127     // Read of size 0 doesn't affect things.
    128     memset(buffer, 0xbd, sizeof(buffer));
    129     EXPECT_EQ(0u, opj_read_from_memory(buffer, 0, &dd));
    130     EXPECT_EQ(0xbd, buffer[0]);
    131 
    132     // Read exactly up to end of data.
    133     memset(buffer, 0xbd, sizeof(buffer));
    134     EXPECT_EQ(6u, opj_read_from_memory(buffer, 6, &dd));
    135     EXPECT_EQ(0x02, buffer[0]);
    136     EXPECT_EQ(0x03, buffer[1]);
    137     EXPECT_EQ(0x84, buffer[2]);
    138     EXPECT_EQ(0x85, buffer[3]);
    139     EXPECT_EQ(0x86, buffer[4]);
    140     EXPECT_EQ(0x87, buffer[5]);
    141     EXPECT_EQ(0xbd, buffer[6]);
    142 
    143     // Read of size 0 at EOF is still an error.
    144     memset(buffer, 0xbd, sizeof(buffer));
    145     EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 0, &dd));
    146     EXPECT_EQ(0xbd, buffer[0]);
    147   }
    148 }
    149 
    150 TEST(fxcodec, DecodeDataReadBeyondBounds) {
    151   unsigned char buffer[16];
    152   {
    153     DecodeData dd(stream_data, sizeof(stream_data));
    154 
    155     // Read beyond bounds in a single step.
    156     memset(buffer, 0xbd, sizeof(buffer));
    157     EXPECT_EQ(8u, opj_read_from_memory(buffer, sizeof(buffer) + 1, &dd));
    158     EXPECT_EQ(0x00, buffer[0]);
    159     EXPECT_EQ(0x01, buffer[1]);
    160     EXPECT_EQ(0x02, buffer[2]);
    161     EXPECT_EQ(0x03, buffer[3]);
    162     EXPECT_EQ(0x84, buffer[4]);
    163     EXPECT_EQ(0x85, buffer[5]);
    164     EXPECT_EQ(0x86, buffer[6]);
    165     EXPECT_EQ(0x87, buffer[7]);
    166     EXPECT_EQ(0xbd, buffer[8]);
    167   }
    168   {
    169     DecodeData dd(stream_data, sizeof(stream_data));
    170 
    171     // Read well beyond bounds in a single step.
    172     memset(buffer, 0xbd, sizeof(buffer));
    173     EXPECT_EQ(8u, opj_read_from_memory(
    174                       buffer, std::numeric_limits<OPJ_SIZE_T>::max(), &dd));
    175     EXPECT_EQ(0x00, buffer[0]);
    176     EXPECT_EQ(0x01, buffer[1]);
    177     EXPECT_EQ(0x02, buffer[2]);
    178     EXPECT_EQ(0x03, buffer[3]);
    179     EXPECT_EQ(0x84, buffer[4]);
    180     EXPECT_EQ(0x85, buffer[5]);
    181     EXPECT_EQ(0x86, buffer[6]);
    182     EXPECT_EQ(0x87, buffer[7]);
    183     EXPECT_EQ(0xbd, buffer[8]);
    184   }
    185   {
    186     DecodeData dd(stream_data, sizeof(stream_data));
    187 
    188     // Read of size 6 gets first 6 bytes.
    189     // rest of buffer intact.
    190     memset(buffer, 0xbd, sizeof(buffer));
    191     EXPECT_EQ(6u, opj_read_from_memory(buffer, 6, &dd));
    192     EXPECT_EQ(0x00, buffer[0]);
    193     EXPECT_EQ(0x01, buffer[1]);
    194     EXPECT_EQ(0x02, buffer[2]);
    195     EXPECT_EQ(0x03, buffer[3]);
    196     EXPECT_EQ(0x84, buffer[4]);
    197     EXPECT_EQ(0x85, buffer[5]);
    198     EXPECT_EQ(0xbd, buffer[6]);
    199 
    200     // Read of size 6 gets remaining two bytes.
    201     memset(buffer, 0xbd, sizeof(buffer));
    202     EXPECT_EQ(2u, opj_read_from_memory(buffer, 6, &dd));
    203     EXPECT_EQ(0x86, buffer[0]);
    204     EXPECT_EQ(0x87, buffer[1]);
    205     EXPECT_EQ(0xbd, buffer[2]);
    206 
    207     // Read of 6 more gets nothing and leaves rest of buffer intact.
    208     memset(buffer, 0xbd, sizeof(buffer));
    209     EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 6, &dd));
    210     EXPECT_EQ(0xbd, buffer[0]);
    211   }
    212 }
    213 
    214 TEST(fxcodec, DecodeDataWriteInBounds) {
    215   unsigned char stream[16];
    216   static unsigned char buffer_data[] = {
    217       0x00, 0x01, 0x02, 0x03, 0x80, 0x80, 0x81, 0x82, 0x83, 0x84,
    218   };
    219   {
    220     // Pretend the stream can only hold 4 bytes.
    221     DecodeData dd(stream, 4);
    222 
    223     memset(stream, 0xbd, sizeof(stream));
    224     EXPECT_EQ(4u, opj_write_from_memory(buffer_data, 4, &dd));
    225     EXPECT_EQ(0x00, stream[0]);
    226     EXPECT_EQ(0x01, stream[1]);
    227     EXPECT_EQ(0x02, stream[2]);
    228     EXPECT_EQ(0x03, stream[3]);
    229     EXPECT_EQ(0xbd, stream[4]);
    230   }
    231   {
    232     // Pretend the stream can only hold 4 bytes.
    233     DecodeData dd(stream, 4);
    234 
    235     memset(stream, 0xbd, sizeof(stream));
    236     EXPECT_EQ(2u, opj_write_from_memory(buffer_data, 2, &dd));
    237     EXPECT_EQ(2u, opj_write_from_memory(buffer_data, 2, &dd));
    238     EXPECT_EQ(0x00, stream[0]);
    239     EXPECT_EQ(0x01, stream[1]);
    240     EXPECT_EQ(0x00, stream[2]);
    241     EXPECT_EQ(0x01, stream[3]);
    242     EXPECT_EQ(0xbd, stream[4]);
    243   }
    244 }
    245 
    246 TEST(fxcodec, DecodeDataWriteBeyondBounds) {
    247   unsigned char stream[16];
    248   static unsigned char buffer_data[] = {
    249       0x10, 0x11, 0x12, 0x13, 0x94, 0x95, 0x96, 0x97,
    250   };
    251   {
    252     // Pretend the stream can only hold 4 bytes.
    253     DecodeData dd(stream, 4);
    254 
    255     // Write ending past EOF transfers up til EOF.
    256     memset(stream, 0xbd, sizeof(stream));
    257     EXPECT_EQ(4u, opj_write_from_memory(buffer_data, 5, &dd));
    258     EXPECT_EQ(0x10, stream[0]);
    259     EXPECT_EQ(0x11, stream[1]);
    260     EXPECT_EQ(0x12, stream[2]);
    261     EXPECT_EQ(0x13, stream[3]);
    262     EXPECT_EQ(0xbd, stream[4]);
    263 
    264     // Subsequent writes fail.
    265     memset(stream, 0xbd, sizeof(stream));
    266     EXPECT_EQ(kWriteError, opj_write_from_memory(buffer_data, 5, &dd));
    267     EXPECT_EQ(0xbd, stream[0]);
    268   }
    269   {
    270     // Pretend the stream can only hold 4 bytes.
    271     DecodeData dd(stream, 4);
    272 
    273     // Write ending past EOF (two steps) transfers up til EOF.
    274     memset(stream, 0xbd, sizeof(stream));
    275     EXPECT_EQ(2u, opj_write_from_memory(buffer_data, 2, &dd));
    276     EXPECT_EQ(2u, opj_write_from_memory(buffer_data, 4, &dd));
    277     EXPECT_EQ(0x10, stream[0]);
    278     EXPECT_EQ(0x11, stream[1]);
    279     EXPECT_EQ(0x10, stream[2]);
    280     EXPECT_EQ(0x11, stream[3]);
    281     EXPECT_EQ(0xbd, stream[4]);
    282 
    283     // Subsequent writes fail.
    284     memset(stream, 0xbd, sizeof(stream));
    285     EXPECT_EQ(kWriteError, opj_write_from_memory(buffer_data, 5, &dd));
    286     EXPECT_EQ(0xbd, stream[0]);
    287   }
    288 }
    289 
    290 // Note: Some care needs to be taken here because the skip/seek functions
    291 // take OPJ_OFF_T's as arguments, which are typically a signed type.
    292 TEST(fxcodec, DecodeDataSkip) {
    293   unsigned char buffer[16];
    294   {
    295     DecodeData dd(stream_data, sizeof(stream_data));
    296 
    297     // Skiping within buffer is allowed.
    298     memset(buffer, 0xbd, sizeof(buffer));
    299     EXPECT_EQ(1, opj_skip_from_memory(1, &dd));
    300     EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
    301     EXPECT_EQ(0x01, buffer[0]);
    302     EXPECT_EQ(0xbd, buffer[1]);
    303 
    304     // Skiping 0 bytes changes nothing.
    305     memset(buffer, 0xbd, sizeof(buffer));
    306     EXPECT_EQ(0, opj_skip_from_memory(0, &dd));
    307     EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
    308     EXPECT_EQ(0x02, buffer[0]);
    309     EXPECT_EQ(0xbd, buffer[1]);
    310 
    311     // Skiping to EOS-1 is possible.
    312     memset(buffer, 0xbd, sizeof(buffer));
    313     EXPECT_EQ(4, opj_skip_from_memory(4, &dd));
    314     EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
    315     EXPECT_EQ(0x87, buffer[0]);
    316     EXPECT_EQ(0xbd, buffer[1]);
    317 
    318     // Next read fails.
    319     memset(buffer, 0xbd, sizeof(buffer));
    320     EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
    321     EXPECT_EQ(0xbd, buffer[0]);
    322   }
    323   {
    324     DecodeData dd(stream_data, sizeof(stream_data));
    325 
    326     // Skiping directly to EOS is allowed.
    327     memset(buffer, 0xbd, sizeof(buffer));
    328     EXPECT_EQ(8, opj_skip_from_memory(8, &dd));
    329 
    330     // Next read fails.
    331     EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
    332     EXPECT_EQ(0xbd, buffer[0]);
    333   }
    334   {
    335     DecodeData dd(stream_data, sizeof(stream_data));
    336 
    337     // Skipping beyond end of stream is allowed and returns full distance.
    338     memset(buffer, 0xbd, sizeof(buffer));
    339     EXPECT_EQ(9, opj_skip_from_memory(9, &dd));
    340 
    341     // Next read fails.
    342     EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
    343     EXPECT_EQ(0xbd, buffer[0]);
    344   }
    345   {
    346     DecodeData dd(stream_data, sizeof(stream_data));
    347 
    348     // Skipping way beyond EOS is allowd, doesn't wrap, and returns
    349     // full distance.
    350     memset(buffer, 0xbd, sizeof(buffer));
    351     EXPECT_EQ(4, opj_skip_from_memory(4, &dd));
    352     EXPECT_EQ(std::numeric_limits<OPJ_OFF_T>::max(),
    353               opj_skip_from_memory(std::numeric_limits<OPJ_OFF_T>::max(), &dd));
    354 
    355     // Next read fails. If it succeeds, it may mean we wrapped.
    356     EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
    357     EXPECT_EQ(0xbd, buffer[0]);
    358   }
    359   {
    360     DecodeData dd(stream_data, sizeof(stream_data));
    361 
    362     // Negative skip within buffer not is allowed, position unchanged.
    363     memset(buffer, 0xbd, sizeof(buffer));
    364     EXPECT_EQ(4, opj_skip_from_memory(4, &dd));
    365     EXPECT_EQ(kSkipError, opj_skip_from_memory(-2, &dd));
    366 
    367     // Next read succeeds as if nothing has happenned.
    368     EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
    369     EXPECT_EQ(0x84, buffer[0]);
    370     EXPECT_EQ(0xbd, buffer[1]);
    371 
    372     // Negative skip before buffer is not allowed, position unchanged.
    373     memset(buffer, 0xbd, sizeof(buffer));
    374     EXPECT_EQ(kSkipError, opj_skip_from_memory(-4, &dd));
    375 
    376     // Next read succeeds as if nothing has happenned.
    377     EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
    378     EXPECT_EQ(0x85, buffer[0]);
    379     EXPECT_EQ(0xbd, buffer[1]);
    380   }
    381   {
    382     DecodeData dd(stream_data, sizeof(stream_data));
    383 
    384     // Negative skip way before buffer is not allowed, doesn't wrap
    385     memset(buffer, 0xbd, sizeof(buffer));
    386     EXPECT_EQ(4, opj_skip_from_memory(4, &dd));
    387     EXPECT_EQ(kSkipError,
    388               opj_skip_from_memory(std::numeric_limits<OPJ_OFF_T>::min(), &dd));
    389 
    390     // Next read succeeds. If it fails, it may mean we wrapped.
    391     EXPECT_EQ(1, opj_read_from_memory(buffer, 1, &dd));
    392     EXPECT_EQ(0x84, buffer[0]);
    393     EXPECT_EQ(0xbd, buffer[1]);
    394   }
    395   {
    396     DecodeData dd(stream_data, sizeof(stream_data));
    397 
    398     // Negative skip after EOS isn't alowed, still EOS.
    399     memset(buffer, 0xbd, sizeof(buffer));
    400     EXPECT_EQ(8, opj_skip_from_memory(8, &dd));
    401     EXPECT_EQ(kSkipError, opj_skip_from_memory(-4, &dd));
    402 
    403     // Next read fails.
    404     EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
    405     EXPECT_EQ(0xbd, buffer[0]);
    406   }
    407 }
    408 
    409 TEST(fxcodec, DecodeDataSeek) {
    410   unsigned char buffer[16];
    411   DecodeData dd(stream_data, sizeof(stream_data));
    412 
    413   // Seeking within buffer is allowed and read succeeds
    414   memset(buffer, 0xbd, sizeof(buffer));
    415   EXPECT_TRUE(opj_seek_from_memory(1, &dd));
    416   EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
    417   EXPECT_EQ(0x01, buffer[0]);
    418   EXPECT_EQ(0xbd, buffer[1]);
    419 
    420   // Seeking before start returns error leaving position unchanged.
    421   memset(buffer, 0xbd, sizeof(buffer));
    422   EXPECT_FALSE(opj_seek_from_memory(-1, &dd));
    423   EXPECT_EQ(1, opj_read_from_memory(buffer, 1, &dd));
    424   EXPECT_EQ(0x02, buffer[0]);
    425   EXPECT_EQ(0xbd, buffer[1]);
    426 
    427   // Seeking way before start returns error leaving position unchanged.
    428   memset(buffer, 0xbd, sizeof(buffer));
    429   EXPECT_FALSE(
    430       opj_seek_from_memory(std::numeric_limits<OPJ_OFF_T>::min(), &dd));
    431   EXPECT_EQ(1, opj_read_from_memory(buffer, 1, &dd));
    432   EXPECT_EQ(0x03, buffer[0]);
    433   EXPECT_EQ(0xbd, buffer[1]);
    434 
    435   // Seeking exactly to EOS is allowed but read fails.
    436   memset(buffer, 0xbd, sizeof(buffer));
    437   EXPECT_TRUE(opj_seek_from_memory(8, &dd));
    438   EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
    439   EXPECT_EQ(0xbd, buffer[0]);
    440 
    441   // Seeking back to zero offset is allowed and read succeeds.
    442   memset(buffer, 0xbd, sizeof(buffer));
    443   EXPECT_TRUE(opj_seek_from_memory(0, &dd));
    444   EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
    445   EXPECT_EQ(0x00, buffer[0]);
    446   EXPECT_EQ(0xbd, buffer[1]);
    447 
    448   // Seeking beyond end of stream is allowed but read fails.
    449   memset(buffer, 0xbd, sizeof(buffer));
    450   EXPECT_TRUE(opj_seek_from_memory(16, &dd));
    451   EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
    452   EXPECT_EQ(0xbd, buffer[0]);
    453 
    454   // Seeking within buffer after seek past EOF restores good state.
    455   memset(buffer, 0xbd, sizeof(buffer));
    456   EXPECT_TRUE(opj_seek_from_memory(4, &dd));
    457   EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
    458   EXPECT_EQ(0x84, buffer[0]);
    459   EXPECT_EQ(0xbd, buffer[1]);
    460 
    461   // Seeking way beyond EOS is allowed, doesn't wrap, and read fails.
    462   memset(buffer, 0xbd, sizeof(buffer));
    463   EXPECT_TRUE(opj_seek_from_memory(std::numeric_limits<OPJ_OFF_T>::max(), &dd));
    464   EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
    465   EXPECT_EQ(0xbd, buffer[0]);
    466 }
    467 
    468 TEST(fxcodec, YUV420ToRGB) {
    469   opj_image_comp_t u;
    470   memset(&u, 0, sizeof(u));
    471   u.dx = 1;
    472   u.dy = 1;
    473   u.w = 16;
    474   u.h = 16;
    475   u.prec = 8;
    476   u.bpp = 8;
    477   opj_image_comp_t v;
    478   memset(&v, 0, sizeof(v));
    479   v.dx = 1;
    480   v.dy = 1;
    481   v.w = 16;
    482   v.h = 16;
    483   v.prec = 8;
    484   v.bpp = 8;
    485   opj_image_comp_t y;
    486   memset(&y, 0, sizeof(y));
    487   y.dx = 1;
    488   y.dy = 1;
    489   y.prec = 8;
    490   y.bpp = 8;
    491   opj_image_t img;
    492   memset(&img, 0, sizeof(img));
    493   img.numcomps = 3;
    494   img.color_space = OPJ_CLRSPC_SYCC;
    495   img.comps = FX_Alloc(opj_image_comp_t, 3);
    496   const struct {
    497     OPJ_UINT32 w;
    498     bool expected;
    499   } cases[] = {{0, false},
    500                {1, false},
    501                {30, false},
    502                {31, true},
    503                {32, true},
    504                {33, true},
    505                {34, false},
    506                {UINT_MAX, false}};
    507   for (int i = 0; i < sizeof(cases) / sizeof(cases[0]); ++i) {
    508     y.w = cases[i].w;
    509     y.h = y.w;
    510     img.x1 = y.w;
    511     img.y1 = y.h;
    512     y.data = FX_Alloc(OPJ_INT32, y.w * y.h);
    513     memset(y.data, 1, y.w * y.h * sizeof(OPJ_INT32));
    514     u.data = FX_Alloc(OPJ_INT32, u.w * u.h);
    515     memset(u.data, 0, u.w * u.h * sizeof(OPJ_INT32));
    516     v.data = FX_Alloc(OPJ_INT32, v.w * v.h);
    517     memset(v.data, 0, v.w * v.h * sizeof(OPJ_INT32));
    518     img.comps[0] = y;
    519     img.comps[1] = u;
    520     img.comps[2] = v;
    521     sycc420_to_rgb(&img);
    522     if (cases[i].expected) {
    523       EXPECT_EQ(img.comps[0].w, img.comps[1].w);
    524       EXPECT_EQ(img.comps[0].h, img.comps[1].h);
    525       EXPECT_EQ(img.comps[0].w, img.comps[2].w);
    526       EXPECT_EQ(img.comps[0].h, img.comps[2].h);
    527     } else {
    528       EXPECT_NE(img.comps[0].w, img.comps[1].w);
    529       EXPECT_NE(img.comps[0].h, img.comps[1].h);
    530       EXPECT_NE(img.comps[0].w, img.comps[2].w);
    531       EXPECT_NE(img.comps[0].h, img.comps[2].h);
    532     }
    533     FX_Free(img.comps[0].data);
    534     FX_Free(img.comps[1].data);
    535     FX_Free(img.comps[2].data);
    536   }
    537   FX_Free(img.comps);
    538 }
    539