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