summaryrefslogtreecommitdiffstats
path: root/third_party/jpeg-xl/lib/extras/dec/decode.cc
blob: e1b036527448aa5d2451724eeb1ffddef8398006 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "lib/extras/dec/decode.h"

#include <locale>

#if JPEGXL_ENABLE_APNG
#include "lib/extras/dec/apng.h"
#endif
#if JPEGXL_ENABLE_EXR
#include "lib/extras/dec/exr.h"
#endif
#if JPEGXL_ENABLE_GIF
#include "lib/extras/dec/gif.h"
#endif
#if JPEGXL_ENABLE_JPEG
#include "lib/extras/dec/jpg.h"
#endif
#include "lib/extras/dec/pgx.h"
#include "lib/extras/dec/pnm.h"

namespace jxl {
namespace extras {
namespace {

// Any valid encoding is larger (ensures codecs can read the first few bytes)
constexpr size_t kMinBytes = 9;

}  // namespace

std::vector<Codec> AvailableCodecs() {
  std::vector<Codec> out;
#if JPEGXL_ENABLE_APNG
  out.push_back(Codec::kPNG);
#endif
#if JPEGXL_ENABLE_EXR
  out.push_back(Codec::kEXR);
#endif
#if JPEGXL_ENABLE_GIF
  out.push_back(Codec::kGIF);
#endif
#if JPEGXL_ENABLE_JPEG
  out.push_back(Codec::kJPG);
#endif
  out.push_back(Codec::kPGX);
  out.push_back(Codec::kPNM);
  return out;
}

Codec CodecFromExtension(std::string extension,
                         size_t* JXL_RESTRICT bits_per_sample) {
  std::transform(
      extension.begin(), extension.end(), extension.begin(),
      [](char c) { return std::tolower(c, std::locale::classic()); });
  if (extension == ".png") return Codec::kPNG;

  if (extension == ".jpg") return Codec::kJPG;
  if (extension == ".jpeg") return Codec::kJPG;

  if (extension == ".pgx") return Codec::kPGX;

  if (extension == ".pam") return Codec::kPNM;
  if (extension == ".pnm") return Codec::kPNM;
  if (extension == ".pgm") return Codec::kPNM;
  if (extension == ".ppm") return Codec::kPNM;
  if (extension == ".pfm") {
    if (bits_per_sample != nullptr) *bits_per_sample = 32;
    return Codec::kPNM;
  }

  if (extension == ".gif") return Codec::kGIF;

  if (extension == ".exr") return Codec::kEXR;

  return Codec::kUnknown;
}

Status DecodeBytes(const Span<const uint8_t> bytes,
                   const ColorHints& color_hints, extras::PackedPixelFile* ppf,
                   const SizeConstraints* constraints, Codec* orig_codec) {
  if (bytes.size() < kMinBytes) return JXL_FAILURE("Too few bytes");

  *ppf = extras::PackedPixelFile();

  // Default values when not set by decoders.
  ppf->info.uses_original_profile = true;
  ppf->info.orientation = JXL_ORIENT_IDENTITY;

  const auto choose_codec = [&]() -> Codec {
#if JPEGXL_ENABLE_APNG
    if (DecodeImageAPNG(bytes, color_hints, ppf, constraints)) {
      return Codec::kPNG;
    }
#endif
    if (DecodeImagePGX(bytes, color_hints, ppf, constraints)) {
      return Codec::kPGX;
    }
    if (DecodeImagePNM(bytes, color_hints, ppf, constraints)) {
      return Codec::kPNM;
    }
#if JPEGXL_ENABLE_GIF
    if (DecodeImageGIF(bytes, color_hints, ppf, constraints)) {
      return Codec::kGIF;
    }
#endif
#if JPEGXL_ENABLE_JPEG
    if (DecodeImageJPG(bytes, color_hints, ppf, constraints)) {
      return Codec::kJPG;
    }
#endif
#if JPEGXL_ENABLE_EXR
    if (DecodeImageEXR(bytes, color_hints, ppf, constraints)) {
      return Codec::kEXR;
    }
#endif
    return Codec::kUnknown;
  };

  Codec codec = choose_codec();
  if (codec == Codec::kUnknown) {
    return JXL_FAILURE("Codecs failed to decode");
  }
  if (orig_codec) *orig_codec = codec;

  return true;
}

}  // namespace extras
}  // namespace jxl