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 ANDROID_ULTRAHDR_JPEGENCODERHELPER_H 18 #define ANDROID_ULTRAHDR_JPEGENCODERHELPER_H 19 20 // We must include cstdio before jpeglib.h. It is a requirement of libjpeg. 21 #include <cstdio> 22 23 extern "C" { 24 #include <jerror.h> 25 #include <jpeglib.h> 26 } 27 28 #include <utils/Errors.h> 29 #include <vector> 30 31 namespace android::ultrahdr { 32 33 /* 34 * Encapsulates a converter from raw image (YUV420planer or grey-scale) to JPEG format. 35 * This class is not thread-safe. 36 */ 37 class JpegEncoderHelper { 38 public: 39 JpegEncoderHelper(); 40 ~JpegEncoderHelper(); 41 42 /* 43 * Compresses YUV420Planer image to JPEG format. After calling this method, call 44 * getCompressedImage() to get the image. |quality| is the jpeg image quality parameter to use. 45 * It ranges from 1 (poorest quality) to 100 (highest quality). |iccBuffer| is the buffer of 46 * ICC segment which will be added to the compressed image. 47 * Returns false if errors occur during compression. 48 */ 49 bool compressImage(const void* image, int width, int height, int quality, 50 const void* iccBuffer, unsigned int iccSize, bool isSingleChannel = false); 51 52 /* 53 * Returns the compressed JPEG buffer pointer. This method must be called only after calling 54 * compressImage(). 55 */ 56 void* getCompressedImagePtr(); 57 58 /* 59 * Returns the compressed JPEG buffer size. This method must be called only after calling 60 * compressImage(). 61 */ 62 size_t getCompressedImageSize(); 63 64 /* 65 * Process 16 lines of Y and 16 lines of U/V each time. 66 * We must pass at least 16 scanlines according to libjpeg documentation. 67 */ 68 static const int kCompressBatchSize = 16; 69 private: 70 // initDestination(), emptyOutputBuffer() and emptyOutputBuffer() are callback functions to be 71 // passed into jpeg library. 72 static void initDestination(j_compress_ptr cinfo); 73 static boolean emptyOutputBuffer(j_compress_ptr cinfo); 74 static void terminateDestination(j_compress_ptr cinfo); 75 static void outputErrorMessage(j_common_ptr cinfo); 76 77 // Returns false if errors occur. 78 bool encode(const void* inYuv, int width, int height, int jpegQuality, 79 const void* iccBuffer, unsigned int iccSize, bool isSingleChannel); 80 void setJpegDestination(jpeg_compress_struct* cinfo); 81 void setJpegCompressStruct(int width, int height, int quality, jpeg_compress_struct* cinfo, 82 bool isSingleChannel); 83 // Returns false if errors occur. 84 bool compress(jpeg_compress_struct* cinfo, const uint8_t* image, bool isSingleChannel); 85 bool compressYuv(jpeg_compress_struct* cinfo, const uint8_t* yuv); 86 bool compressSingleChannel(jpeg_compress_struct* cinfo, const uint8_t* image); 87 88 // The block size for encoded jpeg image buffer. 89 static const int kBlockSize = 16384; 90 91 // The buffer that holds the compressed result. 92 std::vector<JOCTET> mResultBuffer; 93 }; 94 95 } /* namespace android::ultrahdr */ 96 97 #endif // ANDROID_ULTRAHDR_JPEGENCODERHELPER_H 98