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 Original line Diff line number Diff line
@@ -31,6 +31,7 @@ cc_library_static {
    srcs: [
    srcs: [
        "recoverymap.cpp",
        "recoverymap.cpp",
        "recoverymapmath.cpp",
        "recoverymapmath.cpp",
        "recoverymaputils.cpp",
    ],
    ],


    shared_libs: [
    shared_libs: [
+18 −0
Original line number Original line Diff line number Diff line
@@ -61,6 +61,21 @@ public:
     * decompressImage().
     * decompressImage().
     */
     */
    size_t getDecompressedImageHeight();
    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:
private:
    bool decode(const void* image, int length);
    bool decode(const void* image, int length);
    // Returns false if errors occur.
    // Returns false if errors occur.
@@ -72,6 +87,9 @@ private:
    static const int kCompressBatchSize = 16;
    static const int kCompressBatchSize = 16;
    // The buffer that holds the decompressed result.
    // The buffer that holds the decompressed result.
    std::vector<JOCTET> mResultBuffer;
    std::vector<JOCTET> mResultBuffer;
    // The buffer that holds XMP Data.
    std::vector<JOCTET> mXMPBuffer;

    // Resolution of the decompressed image.
    // Resolution of the decompressed image.
    size_t mWidth;
    size_t mWidth;
    size_t mHeight;
    size_t mHeight;
+33 −5
Original line number Original line Diff line number Diff line
@@ -34,6 +34,13 @@ typedef enum {
  JPEGR_TF_PQ = 1,
  JPEGR_TF_PQ = 1,
} jpegr_transfer_function;
} 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.
 * 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_compressed_struct* jr_compressed_ptr;
typedef struct jpegr_exif_struct* jr_exif_ptr;
typedef struct jpegr_exif_struct* jr_exif_ptr;
typedef struct jpegr_metadata* jr_metadata_ptr;
typedef struct jpegr_metadata* jr_metadata_ptr;
typedef struct jpegr_info_struct* jr_info_ptr;


class RecoveryMap {
class RecoveryMap {
public:
public:
@@ -200,8 +208,19 @@ public:
     */
     */
    status_t decodeJPEGR(jr_compressed_ptr compressed_jpegr_image,
    status_t decodeJPEGR(jr_compressed_ptr compressed_jpegr_image,
                         jr_uncompressed_ptr dest,
                         jr_uncompressed_ptr dest,
                         jr_exif_ptr exif,
                         jr_exif_ptr exif = nullptr,
                         bool request_sdr);
                         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:
private:
    /*
    /*
     * This method is called in the decoding pipeline. It will decode the recovery map.
     * This method is called in the decoding pipeline. It will decode the recovery map.
@@ -259,18 +278,27 @@ private:
                              jr_metadata_ptr metadata,
                              jr_metadata_ptr metadata,
                              jr_uncompressed_ptr dest);
                              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
     * 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.
     * position of the compressed recovery map, and will extract the compressed recovery map.
     *
     *
     * @param compressed_jpegr_image compressed JPEGR image
     * @param compressed_jpegr_image compressed JPEGR image
     * @param dest destination of compressed recovery map
     * @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.
     * @return NO_ERROR if calculation succeeds, error code if error occurs.
     */
     */
    status_t extractRecoveryMap(jr_compressed_ptr compressed_jpegr_image,
    status_t extractRecoveryMap(jr_compressed_ptr compressed_jpegr_image,
                                jr_compressed_ptr dest,
                                jr_compressed_ptr dest);
                                jr_metadata_ptr metadata);


    /*
    /*
     * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image
     * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image
+40 −0
Original line number Original line 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 Original line Diff line number Diff line
@@ -20,8 +20,15 @@


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

using namespace std;


namespace android::recoverymap {
namespace android::recoverymap {

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

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


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


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

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


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

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


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


    jpeg_save_markers(&cinfo, kExifMarker, 0xFFFF);

    cinfo.src = &mgr;
    cinfo.src = &mgr;
    jpeg_read_header(&cinfo, TRUE);
    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;
    mWidth = cinfo.image_width;
    mHeight = cinfo.image_height;
    mHeight = cinfo.image_height;


@@ -161,6 +197,43 @@ bool JpegDecoder::decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest,
    return decompressYUV(cinfo, 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) {
bool JpegDecoder::decompressYUV(jpeg_decompress_struct* cinfo, const uint8_t* dest) {


    JSAMPROW y[kCompressBatchSize];
    JSAMPROW y[kCompressBatchSize];
Loading