transform.h (5231B)
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 #ifndef LIB_JXL_MODULAR_TRANSFORM_TRANSFORM_H_ 7 #define LIB_JXL_MODULAR_TRANSFORM_TRANSFORM_H_ 8 9 #include <cstdint> 10 #include <string> 11 #include <vector> 12 13 #include "lib/jxl/base/data_parallel.h" 14 #include "lib/jxl/fields.h" 15 #include "lib/jxl/modular/encoding/context_predict.h" 16 #include "lib/jxl/modular/options.h" 17 18 namespace jxl { 19 20 enum class TransformId : uint32_t { 21 // G, R-G, B-G and variants (including YCoCg). 22 kRCT = 0, 23 24 // Color palette. Parameters are: [begin_c] [end_c] [nb_colors] 25 kPalette = 1, 26 27 // Squeezing (Haar-style) 28 kSqueeze = 2, 29 30 // Invalid for now. 31 kInvalid = 3, 32 }; 33 34 struct SqueezeParams : public Fields { 35 JXL_FIELDS_NAME(SqueezeParams) 36 bool horizontal; 37 bool in_place; 38 uint32_t begin_c; 39 uint32_t num_c; 40 SqueezeParams(); 41 Status VisitFields(Visitor *JXL_RESTRICT visitor) override { 42 JXL_QUIET_RETURN_IF_ERROR(visitor->Bool(false, &horizontal)); 43 JXL_QUIET_RETURN_IF_ERROR(visitor->Bool(false, &in_place)); 44 JXL_QUIET_RETURN_IF_ERROR(visitor->U32(Bits(3), BitsOffset(6, 8), 45 BitsOffset(10, 72), 46 BitsOffset(13, 1096), 0, &begin_c)); 47 JXL_QUIET_RETURN_IF_ERROR( 48 visitor->U32(Val(1), Val(2), Val(3), BitsOffset(4, 4), 2, &num_c)); 49 return true; 50 } 51 }; 52 53 class Transform : public Fields { 54 public: 55 TransformId id; 56 // for Palette and RCT. 57 uint32_t begin_c; 58 // for RCT. 42 possible values starting from 0. 59 uint32_t rct_type; 60 // Only for Palette and NearLossless. 61 uint32_t num_c; 62 // Only for Palette. 63 uint32_t nb_colors; 64 uint32_t nb_deltas; 65 // for Squeeze. Default squeeze if empty. 66 std::vector<SqueezeParams> squeezes; 67 // for NearLossless, not serialized. 68 int max_delta_error; 69 // Serialized for Palette. 70 Predictor predictor; 71 // for Palette, not serialized. 72 bool ordered_palette = true; 73 bool lossy_palette = false; 74 75 explicit Transform(TransformId id); 76 // default constructor for bundles. 77 Transform() : Transform(TransformId::kInvalid) {} 78 79 Status VisitFields(Visitor *JXL_RESTRICT visitor) override { 80 JXL_QUIET_RETURN_IF_ERROR( 81 visitor->U32(Val(static_cast<uint32_t>(TransformId::kRCT)), 82 Val(static_cast<uint32_t>(TransformId::kPalette)), 83 Val(static_cast<uint32_t>(TransformId::kSqueeze)), 84 Val(static_cast<uint32_t>(TransformId::kInvalid)), 85 static_cast<uint32_t>(TransformId::kRCT), 86 reinterpret_cast<uint32_t *>(&id))); 87 if (id == TransformId::kInvalid) { 88 return JXL_FAILURE("Invalid transform ID"); 89 } 90 if (visitor->Conditional(id == TransformId::kRCT || 91 id == TransformId::kPalette)) { 92 JXL_QUIET_RETURN_IF_ERROR( 93 visitor->U32(Bits(3), BitsOffset(6, 8), BitsOffset(10, 72), 94 BitsOffset(13, 1096), 0, &begin_c)); 95 } 96 if (visitor->Conditional(id == TransformId::kRCT)) { 97 // 0-41, default YCoCg. 98 JXL_QUIET_RETURN_IF_ERROR(visitor->U32(Val(6), Bits(2), BitsOffset(4, 2), 99 BitsOffset(6, 10), 6, &rct_type)); 100 if (rct_type >= 42) { 101 return JXL_FAILURE("Invalid transform RCT type"); 102 } 103 } 104 if (visitor->Conditional(id == TransformId::kPalette)) { 105 JXL_QUIET_RETURN_IF_ERROR( 106 visitor->U32(Val(1), Val(3), Val(4), BitsOffset(13, 1), 3, &num_c)); 107 JXL_QUIET_RETURN_IF_ERROR(visitor->U32( 108 BitsOffset(8, 0), BitsOffset(10, 256), BitsOffset(12, 1280), 109 BitsOffset(16, 5376), 256, &nb_colors)); 110 JXL_QUIET_RETURN_IF_ERROR( 111 visitor->U32(Val(0), BitsOffset(8, 1), BitsOffset(10, 257), 112 BitsOffset(16, 1281), 0, &nb_deltas)); 113 JXL_QUIET_RETURN_IF_ERROR( 114 visitor->Bits(4, static_cast<uint32_t>(Predictor::Zero), 115 reinterpret_cast<uint32_t *>(&predictor))); 116 if (predictor >= Predictor::Best) { 117 return JXL_FAILURE("Invalid predictor"); 118 } 119 } 120 121 if (visitor->Conditional(id == TransformId::kSqueeze)) { 122 uint32_t num_squeezes = static_cast<uint32_t>(squeezes.size()); 123 JXL_QUIET_RETURN_IF_ERROR( 124 visitor->U32(Val(0), BitsOffset(4, 1), BitsOffset(6, 9), 125 BitsOffset(8, 41), 0, &num_squeezes)); 126 if (visitor->IsReading()) squeezes.resize(num_squeezes); 127 for (size_t i = 0; i < num_squeezes; i++) { 128 JXL_QUIET_RETURN_IF_ERROR(visitor->VisitNested(&squeezes[i])); 129 } 130 } 131 return true; 132 } 133 134 JXL_FIELDS_NAME(Transform) 135 136 Status Inverse(Image &input, const weighted::Header &wp_header, 137 ThreadPool *pool = nullptr); 138 Status MetaApply(Image &input); 139 }; 140 141 Status CheckEqualChannels(const Image &image, uint32_t c1, uint32_t c2); 142 143 static inline pixel_type PixelAdd(pixel_type a, pixel_type b) { 144 return static_cast<pixel_type>(static_cast<uint32_t>(a) + 145 static_cast<uint32_t>(b)); 146 } 147 148 } // namespace jxl 149 150 #endif // LIB_JXL_MODULAR_TRANSFORM_TRANSFORM_H_