codec.cc (3522B)
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/extras/codec.h" 7 8 #include <jxl/decode.h> 9 #include <jxl/types.h> 10 11 #include "lib/extras/dec/decode.h" 12 #include "lib/extras/enc/apng.h" 13 #include "lib/extras/enc/exr.h" 14 #include "lib/extras/enc/jpg.h" 15 #include "lib/extras/enc/pgx.h" 16 #include "lib/extras/enc/pnm.h" 17 #include "lib/extras/packed_image.h" 18 #include "lib/extras/packed_image_convert.h" 19 #include "lib/jxl/base/status.h" 20 #include "lib/jxl/image_bundle.h" 21 22 namespace jxl { 23 namespace { 24 25 // Any valid encoding is larger (ensures codecs can read the first few bytes) 26 constexpr size_t kMinBytes = 9; 27 28 } // namespace 29 30 Status SetFromBytes(const Span<const uint8_t> bytes, 31 const extras::ColorHints& color_hints, CodecInOut* io, 32 ThreadPool* pool, const SizeConstraints* constraints, 33 extras::Codec* orig_codec) { 34 if (bytes.size() < kMinBytes) return JXL_FAILURE("Too few bytes"); 35 36 extras::PackedPixelFile ppf; 37 if (extras::DecodeBytes(bytes, color_hints, &ppf, constraints, orig_codec)) { 38 return ConvertPackedPixelFileToCodecInOut(ppf, pool, io); 39 } 40 return JXL_FAILURE("Codecs failed to decode"); 41 } 42 43 Status Encode(const extras::PackedPixelFile& ppf, const extras::Codec codec, 44 std::vector<uint8_t>* bytes, ThreadPool* pool) { 45 bytes->clear(); 46 std::unique_ptr<extras::Encoder> encoder; 47 switch (codec) { 48 case extras::Codec::kPNG: 49 encoder = extras::GetAPNGEncoder(); 50 if (encoder) { 51 break; 52 } else { 53 return JXL_FAILURE("JPEG XL was built without (A)PNG support"); 54 } 55 case extras::Codec::kJPG: 56 encoder = extras::GetJPEGEncoder(); 57 if (encoder) { 58 break; 59 } else { 60 return JXL_FAILURE("JPEG XL was built without JPEG support"); 61 } 62 case extras::Codec::kPNM: 63 if (ppf.info.alpha_bits > 0) { 64 encoder = extras::GetPAMEncoder(); 65 } else if (ppf.info.num_color_channels == 1) { 66 encoder = extras::GetPGMEncoder(); 67 } else if (ppf.info.bits_per_sample <= 16) { 68 encoder = extras::GetPPMEncoder(); 69 } else { 70 encoder = extras::GetPFMEncoder(); 71 } 72 break; 73 case extras::Codec::kPGX: 74 encoder = extras::GetPGXEncoder(); 75 break; 76 case extras::Codec::kGIF: 77 return JXL_FAILURE("Encoding to GIF is not implemented"); 78 case extras::Codec::kEXR: 79 encoder = extras::GetEXREncoder(); 80 if (encoder) { 81 break; 82 } else { 83 return JXL_FAILURE("JPEG XL was built without OpenEXR support"); 84 } 85 case extras::Codec::kJXL: 86 // TODO(user): implement 87 return JXL_FAILURE("Codec::kJXL is not supported yet"); 88 89 case extras::Codec::kUnknown: 90 return JXL_FAILURE("Cannot encode using Codec::kUnknown"); 91 } 92 93 if (!encoder) { 94 return JXL_FAILURE("Invalid codec."); 95 } 96 extras::EncodedImage encoded_image; 97 JXL_RETURN_IF_ERROR(encoder->Encode(ppf, &encoded_image, pool)); 98 JXL_ASSERT(encoded_image.bitstreams.size() == 1); 99 *bytes = encoded_image.bitstreams[0]; 100 101 return true; 102 } 103 104 Status Encode(const extras::PackedPixelFile& ppf, const std::string& pathname, 105 std::vector<uint8_t>* bytes, ThreadPool* pool) { 106 std::string extension; 107 const extras::Codec codec = 108 extras::CodecFromPath(pathname, nullptr, &extension); 109 return Encode(ppf, codec, bytes, pool); 110 } 111 112 } // namespace jxl