xref: /aosp_15_r20/external/libultrahdr/lib/include/ultrahdr/jpegdecoderhelper.h (revision 89a0ef05262152531a00a15832a2d3b1e3990773)
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   JpegDecoderHelper() = default;
55   ~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    */
parseImage(const void * image,size_t length)78   uhdr_error_info_t parseImage(const void* image, size_t length) {
79     return decompressImage(image, length, PARSE_STREAM);
80   }
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    */
getDecompressedImagePtr()91   void* getDecompressedImagePtr() { return mResultBuffer.data(); }
92 
93   /*!\brief returns size of decompressed image
94    * \deprecated This function is deprecated instead use getDecompressedImage().
95    */
getDecompressedImageSize()96   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 */
getDecompressedImageWidth()102   unsigned int getDecompressedImageWidth() { return mPlaneWidth[0]; }
103 
104   /*!\brief returns image height */
getDecompressedImageHeight()105   unsigned int getDecompressedImageHeight() { return mPlaneHeight[0]; }
106 
107   /*!\brief returns number of components in image */
getNumComponentsInImage()108   unsigned int getNumComponentsInImage() { return mNumComponents; }
109 
110   /*!\brief returns pointer to xmp block present in input image */
getXMPPtr()111   void* getXMPPtr() { return mXMPBuffer.data(); }
112 
113   /*!\brief returns size of xmp block */
getXMPSize()114   size_t getXMPSize() { return mXMPBuffer.size(); }
115 
116   /*!\brief returns pointer to exif block present in input image */
getEXIFPtr()117   void* getEXIFPtr() { return mEXIFBuffer.data(); }
118 
119   /*!\brief returns size of exif block */
getEXIFSize()120   size_t getEXIFSize() { return mEXIFBuffer.size(); }
121 
122   /*!\brief returns pointer to icc block present in input image */
getICCPtr()123   void* getICCPtr() { return mICCBuffer.data(); }
124 
125   /*!\brief returns size of icc block */
getICCSize()126   size_t getICCSize() { return mICCBuffer.size(); }
127 
128   /*!\brief returns pointer to iso block present in input image */
getIsoMetadataPtr()129   void* getIsoMetadataPtr() { return mIsoMetadataBuffer.data(); }
130 
131   /*!\brief returns size of iso block */
getIsoMetadataSize()132   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. */
getEXIFPos()138   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
173