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