/src/libultrahdr/lib/include/ultrahdr/jpegdecoderhelper.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2022 The Android Open Source Project |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | |
17 | | #ifndef ULTRAHDR_JPEGDECODERHELPER_H |
18 | | #define ULTRAHDR_JPEGDECODERHELPER_H |
19 | | |
20 | | #include <stdio.h> // For jpeglib.h. |
21 | | |
22 | | // C++ build requires extern C for jpeg internals. |
23 | | #ifdef __cplusplus |
24 | | extern "C" { |
25 | | #endif |
26 | | |
27 | | #include <jerror.h> |
28 | | #include <jpeglib.h> |
29 | | |
30 | | #ifdef __cplusplus |
31 | | } // extern "C" |
32 | | #endif |
33 | | |
34 | | #include <cstdint> |
35 | | #include <memory> |
36 | | #include <vector> |
37 | | |
38 | | #include "ultrahdr_api.h" |
39 | | |
40 | | namespace ultrahdr { |
41 | | |
42 | | /*!\brief List of supported operations */ |
43 | | typedef enum { |
44 | | PARSE_STREAM = (1 << 0), /**< Parse jpeg header, APPn markers (Exif, Icc, Xmp, Iso) */ |
45 | | DECODE_STREAM = (1 << 16), /**< Single channel images are decoded to Grayscale format and multi |
46 | | channel images are decoded to RGB format */ |
47 | | DECODE_TO_YCBCR_CS = (1 << 17), /**< Decode image to YCbCr Color Space */ |
48 | | DECODE_TO_RGB_CS = (1 << 18), /**< Decode image to RGB Color Space */ |
49 | | } decode_mode_t; |
50 | | |
51 | | /*!\brief Encapsulates a converter from JPEG to raw image format. This class is not thread-safe */ |
52 | | class JpegDecoderHelper { |
53 | | public: |
54 | 50.9k | JpegDecoderHelper() = default; |
55 | 50.9k | ~JpegDecoderHelper() = default; |
56 | | |
57 | | /*!\brief This function decodes the bitstream that is passed to it to the desired format and |
58 | | * stores the results internally. The result is accessible via getter functions. |
59 | | * |
60 | | * \param[in] image pointer to compressed image |
61 | | * \param[in] length length of compressed image |
62 | | * \param[in] mode output decode format |
63 | | * |
64 | | * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise. |
65 | | */ |
66 | | uhdr_error_info_t decompressImage(const void* image, size_t length, |
67 | | decode_mode_t mode = DECODE_TO_YCBCR_CS); |
68 | | |
69 | | /*!\brief This function parses the bitstream that is passed to it and makes image information |
70 | | * available to the client via getter() functions. It does not decompress the image. That is done |
71 | | * by decompressImage(). |
72 | | * |
73 | | * \param[in] image pointer to compressed image |
74 | | * \param[in] length length of compressed image |
75 | | * |
76 | | * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise. |
77 | | */ |
78 | 39.7k | uhdr_error_info_t parseImage(const void* image, size_t length) { |
79 | 39.7k | return decompressImage(image, length, PARSE_STREAM); |
80 | 39.7k | } |
81 | | |
82 | | /*! Below public methods are only effective if a call to decompressImage() is made and it returned |
83 | | * true. */ |
84 | | |
85 | | /*!\brief returns decompressed image descriptor */ |
86 | | uhdr_raw_image_t getDecompressedImage(); |
87 | | |
88 | | /*!\brief returns pointer to decompressed image |
89 | | * \deprecated This function is deprecated instead use getDecompressedImage(). |
90 | | */ |
91 | 0 | void* getDecompressedImagePtr() { return mResultBuffer.data(); } |
92 | | |
93 | | /*!\brief returns size of decompressed image |
94 | | * \deprecated This function is deprecated instead use getDecompressedImage(). |
95 | | */ |
96 | 0 | size_t getDecompressedImageSize() { return mResultBuffer.size(); } |
97 | | |
98 | | /*! Below public methods are only effective if a call to parseImage() or decompressImage() is made |
99 | | * and it returned true. */ |
100 | | |
101 | | /*!\brief returns image width */ |
102 | 36.9k | unsigned int getDecompressedImageWidth() { return mPlaneWidth[0]; } |
103 | | |
104 | | /*!\brief returns image height */ |
105 | 36.9k | unsigned int getDecompressedImageHeight() { return mPlaneHeight[0]; } |
106 | | |
107 | | /*!\brief returns number of components in image */ |
108 | 36.9k | unsigned int getNumComponentsInImage() { return mNumComponents; } |
109 | | |
110 | | /*!\brief returns pointer to xmp block present in input image */ |
111 | 8.86k | void* getXMPPtr() { return mXMPBuffer.data(); } |
112 | | |
113 | | /*!\brief returns size of xmp block */ |
114 | 51.7k | size_t getXMPSize() { return mXMPBuffer.size(); } |
115 | | |
116 | | /*!\brief returns pointer to exif block present in input image */ |
117 | 112 | void* getEXIFPtr() { return mEXIFBuffer.data(); } |
118 | | |
119 | | /*!\brief returns size of exif block */ |
120 | 37.1k | size_t getEXIFSize() { return mEXIFBuffer.size(); } |
121 | | |
122 | | /*!\brief returns pointer to icc block present in input image */ |
123 | 9.63k | void* getICCPtr() { return mICCBuffer.data(); } |
124 | | |
125 | | /*!\brief returns size of icc block */ |
126 | 48.6k | size_t getICCSize() { return mICCBuffer.size(); } |
127 | | |
128 | | /*!\brief returns pointer to iso block present in input image */ |
129 | 30.8k | void* getIsoMetadataPtr() { return mIsoMetadataBuffer.data(); } |
130 | | |
131 | | /*!\brief returns size of iso block */ |
132 | 95.5k | size_t getIsoMetadataSize() { return mIsoMetadataBuffer.size(); } |
133 | | |
134 | | /*!\brief returns the offset of exif data payload with reference to 'image' address that is passed |
135 | | * via parseImage()/decompressImage() call. Note this does not include jpeg marker (0xffe1) and |
136 | | * the next 2 bytes indicating the size of the payload. If exif block is not present in the image |
137 | | * passed, then it returns -1. */ |
138 | 0 | long getEXIFPos() { return mExifPayLoadOffset; } |
139 | | |
140 | | private: |
141 | | // max number of components supported |
142 | | static constexpr int kMaxNumComponents = 3; |
143 | | |
144 | | uhdr_error_info_t decode(const void* image, size_t length, decode_mode_t mode); |
145 | | uhdr_error_info_t decode(jpeg_decompress_struct* cinfo, uint8_t* dest); |
146 | | uhdr_error_info_t decodeToCSYCbCr(jpeg_decompress_struct* cinfo, uint8_t* dest); |
147 | | uhdr_error_info_t decodeToCSRGB(jpeg_decompress_struct* cinfo, uint8_t* dest); |
148 | | |
149 | | // temporary storage |
150 | | std::unique_ptr<uint8_t[]> mPlanesMCURow[kMaxNumComponents]; |
151 | | |
152 | | std::vector<JOCTET> mResultBuffer; // buffer to store decoded data |
153 | | std::vector<JOCTET> mXMPBuffer; // buffer to store xmp data |
154 | | std::vector<JOCTET> mEXIFBuffer; // buffer to store exif data |
155 | | std::vector<JOCTET> mICCBuffer; // buffer to store icc data |
156 | | std::vector<JOCTET> mIsoMetadataBuffer; // buffer to store iso data |
157 | | |
158 | | // image attributes |
159 | | uhdr_img_fmt_t mOutFormat; |
160 | | unsigned int mNumComponents; |
161 | | unsigned int mPlaneWidth[kMaxNumComponents]; |
162 | | unsigned int mPlaneHeight[kMaxNumComponents]; |
163 | | unsigned int mPlaneHStride[kMaxNumComponents]; |
164 | | unsigned int mPlaneVStride[kMaxNumComponents]; |
165 | | |
166 | | long mExifPayLoadOffset; // Position of EXIF package, default value is -1 which means no EXIF |
167 | | // package appears. |
168 | | }; |
169 | | |
170 | | } /* namespace ultrahdr */ |
171 | | |
172 | | #endif // ULTRAHDR_JPEGDECODERHELPER_H |