diff options
Diffstat (limited to 'libs/ultrahdr/jpegrutils.cpp')
-rw-r--r-- | libs/ultrahdr/jpegrutils.cpp | 600 |
1 files changed, 0 insertions, 600 deletions
diff --git a/libs/ultrahdr/jpegrutils.cpp b/libs/ultrahdr/jpegrutils.cpp deleted file mode 100644 index c434eb6459..0000000000 --- a/libs/ultrahdr/jpegrutils.cpp +++ /dev/null @@ -1,600 +0,0 @@ -/* - * 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. - */ - -#include <ultrahdr/jpegrutils.h> - -#include <algorithm> -#include <cmath> - -#include <image_io/xml/xml_reader.h> -#include <image_io/xml/xml_writer.h> -#include <image_io/base/message_handler.h> -#include <image_io/xml/xml_element_rules.h> -#include <image_io/xml/xml_handler.h> -#include <image_io/xml/xml_rule.h> -#include <utils/Log.h> - -using namespace photos_editing_formats::image_io; -using namespace std; - -namespace android::ultrahdr { -/* - * Helper function used for generating XMP metadata. - * - * @param prefix The prefix part of the name. - * @param suffix The suffix part of the name. - * @return A name of the form "prefix:suffix". - */ -static inline string Name(const string &prefix, const string &suffix) { - std::stringstream ss; - ss << prefix << ":" << suffix; - return ss.str(); -} - -DataStruct::DataStruct(int s) { - data = malloc(s); - length = s; - memset(data, 0, s); - writePos = 0; -} - -DataStruct::~DataStruct() { - if (data != nullptr) { - free(data); - } -} - -void* DataStruct::getData() { - return data; -} - -int DataStruct::getLength() { - return length; -} - -int DataStruct::getBytesWritten() { - return writePos; -} - -bool DataStruct::write8(uint8_t value) { - uint8_t v = value; - return write(&v, 1); -} - -bool DataStruct::write16(uint16_t value) { - uint16_t v = value; - return write(&v, 2); -} -bool DataStruct::write32(uint32_t value) { - uint32_t v = value; - return write(&v, 4); -} - -bool DataStruct::write(const void* src, int size) { - if (writePos + size > length) { - ALOGE("Writing out of boundary: write position: %d, size: %d, capacity: %d", - writePos, size, length); - return false; - } - memcpy((uint8_t*) data + writePos, src, size); - writePos += size; - return true; -} - -/* - * Helper function used for writing data to destination. - */ -status_t Write(jr_compressed_ptr destination, const void* source, size_t length, int &position) { - if (position + length > destination->maxLength) { - return ERROR_JPEGR_BUFFER_TOO_SMALL; - } - - memcpy((uint8_t*)destination->data + sizeof(uint8_t) * position, source, length); - position += length; - return NO_ERROR; -} - -// Extremely simple XML Handler - just searches for interesting elements -class XMPXmlHandler : public XmlHandler { -public: - - XMPXmlHandler() : XmlHandler() { - state = NotStrarted; - versionFound = false; - minContentBoostFound = false; - maxContentBoostFound = false; - gammaFound = false; - offsetSdrFound = false; - offsetHdrFound = false; - hdrCapacityMinFound = false; - hdrCapacityMaxFound = false; - baseRenditionIsHdrFound = false; - } - - enum ParseState { - NotStrarted, - Started, - Done - }; - - virtual DataMatchResult StartElement(const XmlTokenContext& context) { - string val; - if (context.BuildTokenValue(&val)) { - if (!val.compare(containerName)) { - state = Started; - } else { - if (state != Done) { - state = NotStrarted; - } - } - } - return context.GetResult(); - } - - virtual DataMatchResult FinishElement(const XmlTokenContext& context) { - if (state == Started) { - state = Done; - lastAttributeName = ""; - } - return context.GetResult(); - } - - virtual DataMatchResult AttributeName(const XmlTokenContext& context) { - string val; - if (state == Started) { - if (context.BuildTokenValue(&val)) { - if (!val.compare(versionAttrName)) { - lastAttributeName = versionAttrName; - } else if (!val.compare(maxContentBoostAttrName)) { - lastAttributeName = maxContentBoostAttrName; - } else if (!val.compare(minContentBoostAttrName)) { - lastAttributeName = minContentBoostAttrName; - } else if (!val.compare(gammaAttrName)) { - lastAttributeName = gammaAttrName; - } else if (!val.compare(offsetSdrAttrName)) { - lastAttributeName = offsetSdrAttrName; - } else if (!val.compare(offsetHdrAttrName)) { - lastAttributeName = offsetHdrAttrName; - } else if (!val.compare(hdrCapacityMinAttrName)) { - lastAttributeName = hdrCapacityMinAttrName; - } else if (!val.compare(hdrCapacityMaxAttrName)) { - lastAttributeName = hdrCapacityMaxAttrName; - } else if (!val.compare(baseRenditionIsHdrAttrName)) { - lastAttributeName = baseRenditionIsHdrAttrName; - } else { - lastAttributeName = ""; - } - } - } - return context.GetResult(); - } - - virtual DataMatchResult AttributeValue(const XmlTokenContext& context) { - string val; - if (state == Started) { - if (context.BuildTokenValue(&val, true)) { - if (!lastAttributeName.compare(versionAttrName)) { - versionStr = val; - versionFound = true; - } else if (!lastAttributeName.compare(maxContentBoostAttrName)) { - maxContentBoostStr = val; - maxContentBoostFound = true; - } else if (!lastAttributeName.compare(minContentBoostAttrName)) { - minContentBoostStr = val; - minContentBoostFound = true; - } else if (!lastAttributeName.compare(gammaAttrName)) { - gammaStr = val; - gammaFound = true; - } else if (!lastAttributeName.compare(offsetSdrAttrName)) { - offsetSdrStr = val; - offsetSdrFound = true; - } else if (!lastAttributeName.compare(offsetHdrAttrName)) { - offsetHdrStr = val; - offsetHdrFound = true; - } else if (!lastAttributeName.compare(hdrCapacityMinAttrName)) { - hdrCapacityMinStr = val; - hdrCapacityMinFound = true; - } else if (!lastAttributeName.compare(hdrCapacityMaxAttrName)) { - hdrCapacityMaxStr = val; - hdrCapacityMaxFound = true; - } else if (!lastAttributeName.compare(baseRenditionIsHdrAttrName)) { - baseRenditionIsHdrStr = val; - baseRenditionIsHdrFound = true; - } - } - } - return context.GetResult(); - } - - bool getVersion(string* version, bool* present) { - if (state == Done) { - *version = versionStr; - *present = versionFound; - return true; - } else { - return false; - } - } - - bool getMaxContentBoost(float* max_content_boost, bool* present) { - if (state == Done) { - *present = maxContentBoostFound; - stringstream ss(maxContentBoostStr); - float val; - if (ss >> val) { - *max_content_boost = exp2(val); - return true; - } else { - return false; - } - } else { - return false; - } - } - - bool getMinContentBoost(float* min_content_boost, bool* present) { - if (state == Done) { - *present = minContentBoostFound; - stringstream ss(minContentBoostStr); - float val; - if (ss >> val) { - *min_content_boost = exp2(val); - return true; - } else { - return false; - } - } else { - return false; - } - } - - bool getGamma(float* gamma, bool* present) { - if (state == Done) { - *present = gammaFound; - stringstream ss(gammaStr); - float val; - if (ss >> val) { - *gamma = val; - return true; - } else { - return false; - } - } else { - return false; - } - } - - - bool getOffsetSdr(float* offset_sdr, bool* present) { - if (state == Done) { - *present = offsetSdrFound; - stringstream ss(offsetSdrStr); - float val; - if (ss >> val) { - *offset_sdr = val; - return true; - } else { - return false; - } - } else { - return false; - } - } - - - bool getOffsetHdr(float* offset_hdr, bool* present) { - if (state == Done) { - *present = offsetHdrFound; - stringstream ss(offsetHdrStr); - float val; - if (ss >> val) { - *offset_hdr = val; - return true; - } else { - return false; - } - } else { - return false; - } - } - - - bool getHdrCapacityMin(float* hdr_capacity_min, bool* present) { - if (state == Done) { - *present = hdrCapacityMinFound; - stringstream ss(hdrCapacityMinStr); - float val; - if (ss >> val) { - *hdr_capacity_min = exp2(val); - return true; - } else { - return false; - } - } else { - return false; - } - } - - - bool getHdrCapacityMax(float* hdr_capacity_max, bool* present) { - if (state == Done) { - *present = hdrCapacityMaxFound; - stringstream ss(hdrCapacityMaxStr); - float val; - if (ss >> val) { - *hdr_capacity_max = exp2(val); - return true; - } else { - return false; - } - } else { - return false; - } - } - - - bool getBaseRenditionIsHdr(bool* base_rendition_is_hdr, bool* present) { - if (state == Done) { - *present = baseRenditionIsHdrFound; - if (!baseRenditionIsHdrStr.compare("False")) { - *base_rendition_is_hdr = false; - return true; - } else if (!baseRenditionIsHdrStr.compare("True")) { - *base_rendition_is_hdr = true; - return true; - } else { - return false; - } - } else { - return false; - } - } - - - -private: - static const string containerName; - - static const string versionAttrName; - string versionStr; - bool versionFound; - static const string maxContentBoostAttrName; - string maxContentBoostStr; - bool maxContentBoostFound; - static const string minContentBoostAttrName; - string minContentBoostStr; - bool minContentBoostFound; - static const string gammaAttrName; - string gammaStr; - bool gammaFound; - static const string offsetSdrAttrName; - string offsetSdrStr; - bool offsetSdrFound; - static const string offsetHdrAttrName; - string offsetHdrStr; - bool offsetHdrFound; - static const string hdrCapacityMinAttrName; - string hdrCapacityMinStr; - bool hdrCapacityMinFound; - static const string hdrCapacityMaxAttrName; - string hdrCapacityMaxStr; - bool hdrCapacityMaxFound; - static const string baseRenditionIsHdrAttrName; - string baseRenditionIsHdrStr; - bool baseRenditionIsHdrFound; - - string lastAttributeName; - ParseState state; -}; - -// GContainer XMP constants - URI and namespace prefix -const string kContainerUri = "http://ns.google.com/photos/1.0/container/"; -const string kContainerPrefix = "Container"; - -// GContainer XMP constants - element and attribute names -const string kConDirectory = Name(kContainerPrefix, "Directory"); -const string kConItem = Name(kContainerPrefix, "Item"); - -// GContainer XMP constants - names for XMP handlers -const string XMPXmlHandler::containerName = "rdf:Description"; -// Item XMP constants - URI and namespace prefix -const string kItemUri = "http://ns.google.com/photos/1.0/container/item/"; -const string kItemPrefix = "Item"; - -// Item XMP constants - element and attribute names -const string kItemLength = Name(kItemPrefix, "Length"); -const string kItemMime = Name(kItemPrefix, "Mime"); -const string kItemSemantic = Name(kItemPrefix, "Semantic"); - -// Item XMP constants - element and attribute values -const string kSemanticPrimary = "Primary"; -const string kSemanticGainMap = "GainMap"; -const string kMimeImageJpeg = "image/jpeg"; - -// GainMap XMP constants - URI and namespace prefix -const string kGainMapUri = "http://ns.adobe.com/hdr-gain-map/1.0/"; -const string kGainMapPrefix = "hdrgm"; - -// GainMap XMP constants - element and attribute names -const string kMapVersion = Name(kGainMapPrefix, "Version"); -const string kMapGainMapMin = Name(kGainMapPrefix, "GainMapMin"); -const string kMapGainMapMax = Name(kGainMapPrefix, "GainMapMax"); -const string kMapGamma = Name(kGainMapPrefix, "Gamma"); -const string kMapOffsetSdr = Name(kGainMapPrefix, "OffsetSDR"); -const string kMapOffsetHdr = Name(kGainMapPrefix, "OffsetHDR"); -const string kMapHDRCapacityMin = Name(kGainMapPrefix, "HDRCapacityMin"); -const string kMapHDRCapacityMax = Name(kGainMapPrefix, "HDRCapacityMax"); -const string kMapBaseRenditionIsHDR = Name(kGainMapPrefix, "BaseRenditionIsHDR"); - -// GainMap XMP constants - names for XMP handlers -const string XMPXmlHandler::versionAttrName = kMapVersion; -const string XMPXmlHandler::minContentBoostAttrName = kMapGainMapMin; -const string XMPXmlHandler::maxContentBoostAttrName = kMapGainMapMax; -const string XMPXmlHandler::gammaAttrName = kMapGamma; -const string XMPXmlHandler::offsetSdrAttrName = kMapOffsetSdr; -const string XMPXmlHandler::offsetHdrAttrName = kMapOffsetHdr; -const string XMPXmlHandler::hdrCapacityMinAttrName = kMapHDRCapacityMin; -const string XMPXmlHandler::hdrCapacityMaxAttrName = kMapHDRCapacityMax; -const string XMPXmlHandler::baseRenditionIsHdrAttrName = kMapBaseRenditionIsHDR; - -bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, ultrahdr_metadata_struct* metadata) { - string nameSpace = "http://ns.adobe.com/xap/1.0/\0"; - - if (xmp_size < nameSpace.size()+2) { - // Data too short - return false; - } - - if (strncmp(reinterpret_cast<char*>(xmp_data), nameSpace.c_str(), nameSpace.size())) { - // Not correct namespace - return false; - } - - // Position the pointers to the start of XMP XML portion - xmp_data += nameSpace.size()+1; - xmp_size -= nameSpace.size()+1; - XMPXmlHandler handler; - - // We need to remove tail data until the closing tag. Otherwise parser will throw an error. - while(xmp_data[xmp_size-1]!='>' && xmp_size > 1) { - xmp_size--; - } - - string str(reinterpret_cast<const char*>(xmp_data), xmp_size); - MessageHandler msg_handler; - unique_ptr<XmlRule> rule(new XmlElementRule); - XmlReader reader(&handler, &msg_handler); - reader.StartParse(std::move(rule)); - reader.Parse(str); - reader.FinishParse(); - if (reader.HasErrors()) { - // Parse error - return false; - } - - // Apply default values to any not-present fields, except for Version, - // maxContentBoost, and hdrCapacityMax, which are required. Return false if - // we encounter a present field that couldn't be parsed, since this - // indicates it is invalid (eg. string where there should be a float). - bool present = false; - if (!handler.getVersion(&metadata->version, &present) || !present) { - return false; - } - if (!handler.getMaxContentBoost(&metadata->maxContentBoost, &present) || !present) { - return false; - } - if (!handler.getHdrCapacityMax(&metadata->hdrCapacityMax, &present) || !present) { - return false; - } - if (!handler.getMinContentBoost(&metadata->minContentBoost, &present)) { - if (present) return false; - metadata->minContentBoost = 1.0f; - } - if (!handler.getGamma(&metadata->gamma, &present)) { - if (present) return false; - metadata->gamma = 1.0f; - } - if (!handler.getOffsetSdr(&metadata->offsetSdr, &present)) { - if (present) return false; - metadata->offsetSdr = 1.0f / 64.0f; - } - if (!handler.getOffsetHdr(&metadata->offsetHdr, &present)) { - if (present) return false; - metadata->offsetHdr = 1.0f / 64.0f; - } - if (!handler.getHdrCapacityMin(&metadata->hdrCapacityMin, &present)) { - if (present) return false; - metadata->hdrCapacityMin = 1.0f; - } - - bool base_rendition_is_hdr; - if (!handler.getBaseRenditionIsHdr(&base_rendition_is_hdr, &present)) { - if (present) return false; - base_rendition_is_hdr = false; - } - if (base_rendition_is_hdr) { - ALOGE("Base rendition of HDR is not supported!"); - return false; - } - - return true; -} - -string generateXmpForPrimaryImage(int secondary_image_length, ultrahdr_metadata_struct& metadata) { - const vector<string> kConDirSeq({kConDirectory, string("rdf:Seq")}); - const vector<string> kLiItem({string("rdf:li"), kConItem}); - - std::stringstream ss; - photos_editing_formats::image_io::XmlWriter writer(ss); - writer.StartWritingElement("x:xmpmeta"); - writer.WriteXmlns("x", "adobe:ns:meta/"); - writer.WriteAttributeNameAndValue("x:xmptk", "Adobe XMP Core 5.1.2"); - writer.StartWritingElement("rdf:RDF"); - writer.WriteXmlns("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); - writer.StartWritingElement("rdf:Description"); - writer.WriteXmlns(kContainerPrefix, kContainerUri); - writer.WriteXmlns(kItemPrefix, kItemUri); - writer.WriteXmlns(kGainMapPrefix, kGainMapUri); - writer.WriteAttributeNameAndValue(kMapVersion, metadata.version); - - writer.StartWritingElements(kConDirSeq); - - size_t item_depth = writer.StartWritingElement("rdf:li"); - writer.WriteAttributeNameAndValue("rdf:parseType", "Resource"); - writer.StartWritingElement(kConItem); - writer.WriteAttributeNameAndValue(kItemSemantic, kSemanticPrimary); - writer.WriteAttributeNameAndValue(kItemMime, kMimeImageJpeg); - writer.FinishWritingElementsToDepth(item_depth); - - writer.StartWritingElement("rdf:li"); - writer.WriteAttributeNameAndValue("rdf:parseType", "Resource"); - writer.StartWritingElement(kConItem); - writer.WriteAttributeNameAndValue(kItemSemantic, kSemanticGainMap); - writer.WriteAttributeNameAndValue(kItemMime, kMimeImageJpeg); - writer.WriteAttributeNameAndValue(kItemLength, secondary_image_length); - - writer.FinishWriting(); - - return ss.str(); -} - -string generateXmpForSecondaryImage(ultrahdr_metadata_struct& metadata) { - const vector<string> kConDirSeq({kConDirectory, string("rdf:Seq")}); - - std::stringstream ss; - photos_editing_formats::image_io::XmlWriter writer(ss); - writer.StartWritingElement("x:xmpmeta"); - writer.WriteXmlns("x", "adobe:ns:meta/"); - writer.WriteAttributeNameAndValue("x:xmptk", "Adobe XMP Core 5.1.2"); - writer.StartWritingElement("rdf:RDF"); - writer.WriteXmlns("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); - writer.StartWritingElement("rdf:Description"); - writer.WriteXmlns(kGainMapPrefix, kGainMapUri); - writer.WriteAttributeNameAndValue(kMapVersion, metadata.version); - writer.WriteAttributeNameAndValue(kMapGainMapMin, log2(metadata.minContentBoost)); - writer.WriteAttributeNameAndValue(kMapGainMapMax, log2(metadata.maxContentBoost)); - writer.WriteAttributeNameAndValue(kMapGamma, metadata.gamma); - writer.WriteAttributeNameAndValue(kMapOffsetSdr, metadata.offsetSdr); - writer.WriteAttributeNameAndValue(kMapOffsetHdr, metadata.offsetHdr); - writer.WriteAttributeNameAndValue(kMapHDRCapacityMin, log2(metadata.hdrCapacityMin)); - writer.WriteAttributeNameAndValue(kMapHDRCapacityMax, log2(metadata.hdrCapacityMax)); - writer.WriteAttributeNameAndValue(kMapBaseRenditionIsHDR, "False"); - writer.FinishWriting(); - - return ss.str(); -} - -} // namespace android::ultrahdr |