Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 309ff55c authored by Fyodor Kyslov's avatar Fyodor Kyslov Committed by Android (Google) Code Review
Browse files

Merge "JPEGR Decoder. Inital implementation"

parents 6a477233 1dcc4429
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ cc_library_static {
    srcs: [
        "recoverymap.cpp",
        "recoverymapmath.cpp",
        "recoverymaputils.cpp",
    ],

    shared_libs: [
+18 −0
Original line number Diff line number Diff line
@@ -61,6 +61,21 @@ public:
     * decompressImage().
     */
    size_t getDecompressedImageHeight();
    /*
     * Returns the XMP data from the image.
     */
    void* getXMPPtr();
    /*
     * Returns the decompressed XMP buffer size. This method must be called only after
     * calling decompressImage().
     */
    size_t getXMPSize();

    bool getCompressedImageParameters(const void* image, int length,
                              size_t* pWidth, size_t* pHeight,
                              std::vector<uint8_t>* &iccData,
                              std::vector<uint8_t>* &exifData);

private:
    bool decode(const void* image, int length);
    // Returns false if errors occur.
@@ -72,6 +87,9 @@ private:
    static const int kCompressBatchSize = 16;
    // The buffer that holds the decompressed result.
    std::vector<JOCTET> mResultBuffer;
    // The buffer that holds XMP Data.
    std::vector<JOCTET> mXMPBuffer;

    // Resolution of the decompressed image.
    size_t mWidth;
    size_t mHeight;
+33 −5
Original line number Diff line number Diff line
@@ -34,6 +34,13 @@ typedef enum {
  JPEGR_TF_PQ = 1,
} jpegr_transfer_function;

struct jpegr_info_struct {
    size_t width;
    size_t height;
    std::vector<uint8_t>* iccData;
    std::vector<uint8_t>* exifData;
};

/*
 * Holds information for uncompressed image or recovery map.
 */
@@ -117,6 +124,7 @@ typedef struct jpegr_uncompressed_struct* jr_uncompressed_ptr;
typedef struct jpegr_compressed_struct* jr_compressed_ptr;
typedef struct jpegr_exif_struct* jr_exif_ptr;
typedef struct jpegr_metadata* jr_metadata_ptr;
typedef struct jpegr_info_struct* jr_info_ptr;

class RecoveryMap {
public:
@@ -200,8 +208,19 @@ public:
     */
    status_t decodeJPEGR(jr_compressed_ptr compressed_jpegr_image,
                         jr_uncompressed_ptr dest,
                         jr_exif_ptr exif,
                         bool request_sdr);
                         jr_exif_ptr exif = nullptr,
                         bool request_sdr = false);

    /*
    * Gets Info from JPEGR file without decoding it.
    *
    * The output is filled jpegr_info structure
    * @param compressed_jpegr_image compressed JPEGR image
    * @param jpegr_info pointer to output JPEGR info
    * @return NO_ERROR if JPEGR parsing succeeds, error code otherwise
    */
    status_t getJPEGRInfo(jr_compressed_ptr compressed_jpegr_image,
                          jr_info_ptr jpegr_info);
private:
    /*
     * This method is called in the decoding pipeline. It will decode the recovery map.
@@ -259,18 +278,27 @@ private:
                              jr_metadata_ptr metadata,
                              jr_uncompressed_ptr dest);

    /*
     * This methoud is called to separate primary image and recovery map image from JPEGR
     *
     * @param compressed_jpegr_image compressed JPEGR image
     * @param primary_image destination of primary image
     * @param recovery_map destination of compressed recovery map
     * @return NO_ERROR if calculation succeeds, error code if error occurs.
    */
    status_t extractPrimaryImageAndRecoveryMap(jr_compressed_ptr compressed_jpegr_image,
                                               jr_compressed_ptr primary_image,
                                               jr_compressed_ptr recovery_map);
    /*
     * This method is called in the decoding pipeline. It will read XMP metadata to find the start
     * position of the compressed recovery map, and will extract the compressed recovery map.
     *
     * @param compressed_jpegr_image compressed JPEGR image
     * @param dest destination of compressed recovery map
     * @param metadata destination of the recovery map metadata
     * @return NO_ERROR if calculation succeeds, error code if error occurs.
     */
    status_t extractRecoveryMap(jr_compressed_ptr compressed_jpegr_image,
                                jr_compressed_ptr dest,
                                jr_metadata_ptr metadata);
                                jr_compressed_ptr dest);

    /*
     * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image
+40 −0
Original line number Diff line number Diff line
/*
 * Copyright 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_JPEGRECOVERYMAP_RECOVERYMAPUTILS_H
#define ANDROID_JPEGRECOVERYMAP_RECOVERYMAPUTILS_H

#include <stdint.h>
#include <cstdio>


namespace android::recoverymap {

struct jpegr_metadata;

/*
 * Parses XMP packet and fills metadata with data from XMP
 *
 * @param xmp_data pointer to XMP packet
 * @param xmp_size size of XMP packet
 * @param metadata place to store HDR metadata values
 * @return true if metadata is successfully retrieved, false otherwise
*/
bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata* metadata);

}

#endif //ANDROID_JPEGRECOVERYMAP_RECOVERYMAPUTILS_H
 No newline at end of file
+73 −0
Original line number Diff line number Diff line
@@ -20,8 +20,15 @@

#include <errno.h>
#include <setjmp.h>
#include <string>

using namespace std;

namespace android::recoverymap {

const uint32_t kExifMarker = JPEG_APP0 + 1;
const uint32_t kICCMarker = JPEG_APP0 + 2;

struct jpegr_source_mgr : jpeg_source_mgr {
    jpegr_source_mgr(const uint8_t* ptr, int len);
    ~jpegr_source_mgr();
@@ -88,6 +95,7 @@ bool JpegDecoder::decompressImage(const void* image, int length) {
    }

    mResultBuffer.clear();
    mXMPBuffer.clear();
    if (!decode(image, length)) {
        return false;
    }
@@ -103,6 +111,15 @@ size_t JpegDecoder::getDecompressedImageSize() {
    return mResultBuffer.size();
}

void* JpegDecoder::getXMPPtr() {
    return mXMPBuffer.data();
}

size_t JpegDecoder::getXMPSize() {
    return mXMPBuffer.size();
}


size_t JpegDecoder::getDecompressedImageWidth() {
    return mWidth;
}
@@ -115,6 +132,8 @@ bool JpegDecoder::decode(const void* image, int length) {
    jpeg_decompress_struct cinfo;
    jpegr_source_mgr mgr(static_cast<const uint8_t*>(image), length);
    jpegrerror_mgr myerr;
    string nameSpace = "http://ns.adobe.com/xap/1.0/";

    cinfo.err = jpeg_std_error(&myerr.pub);
    myerr.pub.error_exit = jpegrerror_exit;

@@ -124,9 +143,26 @@ bool JpegDecoder::decode(const void* image, int length) {
    }
    jpeg_create_decompress(&cinfo);

    jpeg_save_markers(&cinfo, kExifMarker, 0xFFFF);

    cinfo.src = &mgr;
    jpeg_read_header(&cinfo, TRUE);

    // Save XMP Data
    for (jpeg_marker_struct* marker = cinfo.marker_list; marker; marker = marker->next) {
        if (marker->marker == kExifMarker) {
            const unsigned int len = marker->data_length;
            if (len > nameSpace.size() &&
                !strncmp(reinterpret_cast<const char*>(marker->data),
                         nameSpace.c_str(), nameSpace.size())) {
                mXMPBuffer.resize(len+1, 0);
                memcpy(static_cast<void*>(mXMPBuffer.data()), marker->data, len);
                break;
            }
        }
    }


    mWidth = cinfo.image_width;
    mHeight = cinfo.image_height;

@@ -161,6 +197,43 @@ bool JpegDecoder::decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest,
    return decompressYUV(cinfo, dest);
}

bool JpegDecoder::getCompressedImageParameters(const void* image, int length,
                              size_t *pWidth, size_t *pHeight,
                              std::vector<uint8_t> *&iccData , std::vector<uint8_t> *&exifData) {
    jpeg_decompress_struct cinfo;
    jpegr_source_mgr mgr(static_cast<const uint8_t*>(image), length);
    jpegrerror_mgr myerr;
    cinfo.err = jpeg_std_error(&myerr.pub);
    myerr.pub.error_exit = jpegrerror_exit;

    if (setjmp(myerr.setjmp_buffer)) {
        jpeg_destroy_decompress(&cinfo);
        return false;
    }
    jpeg_create_decompress(&cinfo);

    jpeg_save_markers(&cinfo, kExifMarker, 0xFFFF);
    jpeg_save_markers(&cinfo, kICCMarker, 0xFFFF);

    cinfo.src = &mgr;
    if (jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK) {
        jpeg_destroy_decompress(&cinfo);
        return false;
    }

    *pWidth = cinfo.image_width;
    *pHeight = cinfo.image_height;

    //TODO: Parse iccProfile and exifData
    (void)iccData;
    (void)exifData;


    jpeg_destroy_decompress(&cinfo);
    return true;
}


bool JpegDecoder::decompressYUV(jpeg_decompress_struct* cinfo, const uint8_t* dest) {

    JSAMPROW y[kCompressBatchSize];
Loading