libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

image_ops_test.cc (4292B)


      1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file.
      5 
      6 #include "lib/jxl/image_ops.h"
      7 
      8 #include <stdint.h>
      9 #include <stdlib.h>
     10 
     11 #include <cstring>
     12 
     13 #include "lib/jxl/base/compiler_specific.h"
     14 #include "lib/jxl/base/printf_macros.h"
     15 #include "lib/jxl/base/random.h"
     16 #include "lib/jxl/base/status.h"
     17 #include "lib/jxl/cache_aligned.h"
     18 #include "lib/jxl/image.h"
     19 #include "lib/jxl/testing.h"
     20 
     21 namespace jxl {
     22 namespace {
     23 
     24 // Ensure entire payload is readable/writable for various size/offset combos.
     25 TEST(ImageTest, TestAllocator) {
     26   Rng rng(0);
     27   const size_t k32 = 32;
     28   const size_t kAlign = CacheAligned::kAlignment;
     29   for (size_t size : {k32 * 1, k32 * 2, k32 * 3, k32 * 4, k32 * 5,
     30                       CacheAligned::kAlias, 2 * CacheAligned::kAlias + 4}) {
     31     for (size_t offset = 0; offset <= CacheAligned::kAlias; offset += kAlign) {
     32       uint8_t* bytes =
     33           static_cast<uint8_t*>(CacheAligned::Allocate(size, offset));
     34       JXL_CHECK(reinterpret_cast<uintptr_t>(bytes) % kAlign == 0);
     35       // Ensure we can write/read the last byte. Use RNG to fool the compiler
     36       // into thinking the write is necessary.
     37       memset(bytes, 0, size);
     38       bytes[size - 1] = 1;                       // greatest element
     39       uint32_t pos = rng.UniformU(0, size - 1);  // random but != greatest
     40       JXL_CHECK(bytes[pos] < bytes[size - 1]);
     41 
     42       CacheAligned::Free(bytes);
     43     }
     44   }
     45 }
     46 
     47 template <typename T>
     48 void TestFillImpl(Image3<T>* img, const char* layout) {
     49   FillImage(static_cast<T>(1), img);
     50   for (size_t y = 0; y < img->ysize(); ++y) {
     51     for (size_t c = 0; c < 3; ++c) {
     52       T* JXL_RESTRICT row = img->PlaneRow(c, y);
     53       for (size_t x = 0; x < img->xsize(); ++x) {
     54         if (row[x] != static_cast<T>(1)) {
     55           printf("Not 1 at c=%" PRIuS " %" PRIuS ", %" PRIuS " (%" PRIuS
     56                  " x %" PRIuS ") (%s)\n",
     57                  c, x, y, img->xsize(), img->ysize(), layout);
     58           abort();
     59         }
     60         row[x] = static_cast<T>(2);
     61       }
     62     }
     63   }
     64 
     65   // Same for ZeroFillImage and swapped c/y loop ordering.
     66   ZeroFillImage(img);
     67   for (size_t c = 0; c < 3; ++c) {
     68     for (size_t y = 0; y < img->ysize(); ++y) {
     69       T* JXL_RESTRICT row = img->PlaneRow(c, y);
     70       for (size_t x = 0; x < img->xsize(); ++x) {
     71         if (row[x] != static_cast<T>(0)) {
     72           printf("Not 0 at c=%" PRIuS " %" PRIuS ", %" PRIuS " (%" PRIuS
     73                  " x %" PRIuS ") (%s)\n",
     74                  c, x, y, img->xsize(), img->ysize(), layout);
     75           abort();
     76         }
     77         row[x] = static_cast<T>(3);
     78       }
     79     }
     80   }
     81 }
     82 
     83 template <typename T>
     84 void TestFillT() {
     85   for (uint32_t xsize : {0, 1, 15, 16, 31, 32}) {
     86     for (uint32_t ysize : {0, 1, 15, 16, 31, 32}) {
     87       JXL_ASSIGN_OR_DIE(Image3<T> image, Image3<T>::Create(xsize, ysize));
     88       TestFillImpl(&image, "size ctor");
     89     }
     90   }
     91 }
     92 
     93 // Ensure y/c/x and c/y/x loops visit pixels no more than once.
     94 TEST(ImageTest, TestFill) {
     95   TestFillT<uint8_t>();
     96   TestFillT<int16_t>();
     97   TestFillT<float>();
     98   TestFillT<double>();
     99 }
    100 
    101 TEST(ImageTest, CopyImageToWithPaddingTest) {
    102   JXL_ASSIGN_OR_DIE(Plane<uint32_t> src, Plane<uint32_t>::Create(100, 61));
    103   for (size_t y = 0; y < src.ysize(); y++) {
    104     for (size_t x = 0; x < src.xsize(); x++) {
    105       src.Row(y)[x] = x * 1000 + y;
    106     }
    107   }
    108   Rect src_rect(10, 20, 30, 40);
    109   EXPECT_TRUE(src_rect.IsInside(src));
    110 
    111   JXL_ASSIGN_OR_DIE(Plane<uint32_t> dst, Plane<uint32_t>::Create(60, 50));
    112   FillImage(0u, &dst);
    113   Rect dst_rect(20, 5, 30, 40);
    114   EXPECT_TRUE(dst_rect.IsInside(dst));
    115 
    116   CopyImageToWithPadding(src_rect, src, /*padding=*/2, dst_rect, &dst);
    117 
    118   // ysize is + 3 instead of + 4 because we are at the y image boundary on the
    119   // source image.
    120   Rect padded_dst_rect(20 - 2, 5 - 2, 30 + 4, 40 + 3);
    121   for (size_t y = 0; y < dst.ysize(); y++) {
    122     for (size_t x = 0; x < dst.xsize(); x++) {
    123       if (Rect(x, y, 1, 1).IsInside(padded_dst_rect)) {
    124         EXPECT_EQ((x - dst_rect.x0() + src_rect.x0()) * 1000 +
    125                       (y - dst_rect.y0() + src_rect.y0()),
    126                   dst.Row(y)[x]);
    127       } else {
    128         EXPECT_EQ(0u, dst.Row(y)[x]);
    129       }
    130     }
    131   }
    132 }
    133 
    134 }  // namespace
    135 }  // namespace jxl