image_ops.cc (3554B)
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 <cstddef> 9 #include <cstring> 10 11 #include "lib/jxl/base/common.h" 12 #include "lib/jxl/base/compiler_specific.h" 13 #include "lib/jxl/base/status.h" 14 #include "lib/jxl/frame_dimensions.h" 15 #include "lib/jxl/image.h" 16 17 namespace jxl { 18 19 Status PadImageToBlockMultipleInPlace(Image3F* JXL_RESTRICT in, 20 size_t block_dim) { 21 const size_t xsize_orig = in->xsize(); 22 const size_t ysize_orig = in->ysize(); 23 const size_t xsize = RoundUpTo(xsize_orig, block_dim); 24 const size_t ysize = RoundUpTo(ysize_orig, block_dim); 25 // Expands image size to the originally-allocated size. 26 JXL_RETURN_IF_ERROR(in->ShrinkTo(xsize, ysize)); 27 for (size_t c = 0; c < 3; c++) { 28 for (size_t y = 0; y < ysize_orig; y++) { 29 float* JXL_RESTRICT row = in->PlaneRow(c, y); 30 for (size_t x = xsize_orig; x < xsize; x++) { 31 row[x] = row[xsize_orig - 1]; 32 } 33 } 34 const float* JXL_RESTRICT row_src = in->ConstPlaneRow(c, ysize_orig - 1); 35 for (size_t y = ysize_orig; y < ysize; y++) { 36 memcpy(in->PlaneRow(c, y), row_src, xsize * sizeof(float)); 37 } 38 } 39 return true; 40 } 41 42 static Status DoDownsampleImage(const ImageF& input, size_t factor, 43 ImageF* output) { 44 JXL_ENSURE(factor != 1); 45 JXL_RETURN_IF_ERROR(output->ShrinkTo(DivCeil(input.xsize(), factor), 46 DivCeil(input.ysize(), factor))); 47 size_t in_stride = input.PixelsPerRow(); 48 for (size_t y = 0; y < output->ysize(); y++) { 49 float* row_out = output->Row(y); 50 const float* row_in = input.Row(factor * y); 51 for (size_t x = 0; x < output->xsize(); x++) { 52 size_t cnt = 0; 53 float sum = 0; 54 for (size_t iy = 0; iy < factor && iy + factor * y < input.ysize(); 55 iy++) { 56 for (size_t ix = 0; ix < factor && ix + factor * x < input.xsize(); 57 ix++) { 58 sum += row_in[iy * in_stride + x * factor + ix]; 59 cnt++; 60 } 61 } 62 row_out[x] = sum / cnt; 63 } 64 } 65 return true; 66 } 67 68 StatusOr<ImageF> DownsampleImage(const ImageF& image, size_t factor) { 69 ImageF downsampled; 70 // Allocate extra space to avoid a reallocation when padding. 71 JxlMemoryManager* memory_manager = image.memory_manager(); 72 JXL_ASSIGN_OR_RETURN( 73 downsampled, 74 ImageF::Create(memory_manager, DivCeil(image.xsize(), factor) + kBlockDim, 75 DivCeil(image.ysize(), factor) + kBlockDim)); 76 JXL_RETURN_IF_ERROR(DoDownsampleImage(image, factor, &downsampled)); 77 return downsampled; 78 } 79 80 StatusOr<Image3F> DownsampleImage(const Image3F& opsin, size_t factor) { 81 JXL_ENSURE(factor != 1); 82 // Allocate extra space to avoid a reallocation when padding. 83 Image3F downsampled; 84 JxlMemoryManager* memory_manager = opsin.memory_manager(); 85 JXL_ASSIGN_OR_RETURN( 86 downsampled, Image3F::Create(memory_manager, 87 DivCeil(opsin.xsize(), factor) + kBlockDim, 88 DivCeil(opsin.ysize(), factor) + kBlockDim)); 89 JXL_RETURN_IF_ERROR(downsampled.ShrinkTo(downsampled.xsize() - kBlockDim, 90 downsampled.ysize() - kBlockDim)); 91 for (size_t c = 0; c < 3; c++) { 92 JXL_RETURN_IF_ERROR( 93 DoDownsampleImage(opsin.Plane(c), factor, &downsampled.Plane(c))); 94 } 95 return downsampled; 96 } 97 98 } // namespace jxl