• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // constraint on max width and max height is only due to device alloc constraints
43 // can tune these values basing on the target device
44 static const int kMaxWidth = 8192;
45 static const int kMaxHeight = 8192;
46 
47 /*!\brief List of supported operations */
48 typedef enum {
49   PARSE_STREAM = (1 << 0),   /**< Parse jpeg header, APPn markers (Exif, Icc, Xmp, Iso) */
50   DECODE_STREAM = (1 << 16), /**< Single channel images are decoded to Grayscale format and multi
51                                 channel images are decoded to RGB format */
52   DECODE_TO_YCBCR_CS = (1 << 17), /**< Decode image to YCbCr Color Space  */
53   DECODE_TO_RGB_CS = (1 << 18),   /**< Decode image to RGB Color Space  */
54 } decode_mode_t;
55 
56 /*!\brief Encapsulates a converter from JPEG to raw image format. This class is not thread-safe */
57 class JpegDecoderHelper {
58  public:
59 
60   JpegDecoderHelper() = default;
61   ~JpegDecoderHelper() = default;
62 
63   /*!\brief This function decodes the bitstream that is passed to it to the desired format and
64    * stores the results internally. The result is accessible via getter functions.
65    *
66    * \param[in]  image    pointer to compressed image
67    * \param[in]  length   length of compressed image
68    * \param[in]  mode     output decode format
69    *
70    * \returns true if operation succeeds, false otherwise.
71    */
72   bool decompressImage(const void* image, int length, decode_mode_t mode = DECODE_TO_YCBCR_CS);
73 
74   /*!\brief This function parses the bitstream that is passed to it and makes image information
75    * available to the client via getter() functions. It does not decompress the image. That is done
76    * by decompressImage().
77    *
78    * \param[in]  image    pointer to compressed image
79    * \param[in]  length   length of compressed image
80    *
81    * \returns true if operation succeeds, false otherwise.
82    */
parseImage(const void * image,int length)83   bool parseImage(const void* image, int length) {
84     return decompressImage(image, length, PARSE_STREAM);
85   }
86 
87   /*! Below public methods are only effective if a call to decompressImage() is made and it returned
88    * true. */
89 
90   /*!\brief returns pointer to decompressed image */
getDecompressedImagePtr()91   void* getDecompressedImagePtr() { return mResultBuffer.data(); }
92 
93   /*!\brief returns size of decompressed image */
getDecompressedImageSize()94   size_t getDecompressedImageSize() { return mResultBuffer.size(); }
95 
96   /*!\brief returns format of decompressed image */
getDecompressedImageFormat()97   uhdr_img_fmt_t getDecompressedImageFormat() { return mOutFormat; }
98 
99   /*! Below public methods are only effective if a call to parseImage() or decompressImage() is made
100    * and it returned true. */
101 
102   /*!\brief returns image width */
getDecompressedImageWidth()103   size_t getDecompressedImageWidth() { return mPlaneWidth[0]; }
104 
105   /*!\brief returns image height */
getDecompressedImageHeight()106   size_t getDecompressedImageHeight() { return mPlaneHeight[0]; }
107 
108   /*!\brief returns pointer to xmp block present in input image */
getXMPPtr()109   void* getXMPPtr() { return mXMPBuffer.data(); }
110 
111   /*!\brief returns size of xmp block */
getXMPSize()112   size_t getXMPSize() { return mXMPBuffer.size(); }
113 
114   /*!\brief returns pointer to exif block present in input image */
getEXIFPtr()115   void* getEXIFPtr() { return mEXIFBuffer.data(); }
116 
117   /*!\brief returns size of exif block */
getEXIFSize()118   size_t getEXIFSize() { return mEXIFBuffer.size(); }
119 
120   /*!\brief returns pointer to icc block present in input image */
getICCPtr()121   void* getICCPtr() { return mICCBuffer.data(); }
122 
123   /*!\brief returns size of icc block */
getICCSize()124   size_t getICCSize() { return mICCBuffer.size(); }
125 
126   /*!\brief returns pointer to iso block present in input image */
getIsoMetadataPtr()127   void* getIsoMetadataPtr() { return mIsoMetadataBuffer.data(); }
128 
129   /*!\brief returns size of iso block */
getIsoMetadataSize()130   size_t getIsoMetadataSize() { return mIsoMetadataBuffer.size(); }
131 
132   /*!\brief returns the offset of exif data payload with reference to 'image' address that is passed
133    * via parseImage()/decompressImage() call. Note this does not include jpeg marker (0xffe1) and
134    * the next 2 bytes indicating the size of the payload. If exif block is not present in the image
135    * passed, then it returns -1. */
getEXIFPos()136   int getEXIFPos() { return mExifPayLoadOffset; }
137 
138  private:
139   // max number of components supported
140   static constexpr int kMaxNumComponents = 3;
141 
142   bool decode(const void* image, int length, decode_mode_t mode);
143   bool decode(jpeg_decompress_struct* cinfo, uint8_t* dest);
144   bool decodeToCSYCbCr(jpeg_decompress_struct* cinfo, uint8_t* dest);
145   bool decodeToCSRGB(jpeg_decompress_struct* cinfo, uint8_t* dest);
146 
147   // temporary storage
148   std::unique_ptr<uint8_t[]> mPlanesMCURow[kMaxNumComponents];
149 
150   std::vector<JOCTET> mResultBuffer;       // buffer to store decoded data
151   std::vector<JOCTET> mXMPBuffer;          // buffer to store xmp data
152   std::vector<JOCTET> mEXIFBuffer;         // buffer to store exif data
153   std::vector<JOCTET> mICCBuffer;          // buffer to store icc data
154   std::vector<JOCTET> mIsoMetadataBuffer;  // buffer to store iso data
155 
156   // image attributes
157   uhdr_img_fmt_t mOutFormat;
158   size_t mPlaneWidth[kMaxNumComponents];
159   size_t mPlaneHeight[kMaxNumComponents];
160 
161   int mExifPayLoadOffset;  // Position of EXIF package, default value is -1 which means no EXIF
162                            // package appears.
163 };
164 
165 } /* namespace ultrahdr  */
166 
167 #endif  // ULTRAHDR_JPEGDECODERHELPER_H
168