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