// Write a scalar attribute only if all channels of |value| are equal (otherwise, write // nothing). auto maybe_write_scalar_attr = [&write_scalar_attr](constchar* attrib, SkColor4f value) { if (!is_single_channel(value)) { return;
}
write_scalar_attr(attrib, value.fR);
};
// Write a float3 attribute as a list ony if not all channels of |value| are equal (otherwise, // write nothing). auto maybe_write_float3_attr = [&s](constchar* attrib, SkColor4f value) { if (is_single_channel(value)) { return;
}
s.writeText(" <");
s.writeText(attrib);
s.writeText(">\n");
s.writeText(" \n");
s.writeText(" ");
s.writeScalarAsText(value.fR);
s.writeText("\n");
s.writeText(" ");
s.writeScalarAsText(value.fG);
s.writeText("\n");
s.writeText(" ");
s.writeScalarAsText(value.fB);
s.writeText("\n");
s.writeText(" \n");
s.writeText(" ");
s.writeText(attrib);
s.writeText(">\n");
};
// Write any of the vector parameters that cannot be represented as scalars (and thus cannot // be written inline as above).
maybe_write_float3_attr("hdrgm:GainMapMin", gainMapMin);
maybe_write_float3_attr("hdrgm:GainMapMax", gainMapMax);
maybe_write_float3_attr("hdrgm:Gamma", gamma);
maybe_write_float3_attr("hdrgm:OffsetSDR", gainmapInfo.fEpsilonSdr);
maybe_write_float3_attr("hdrgm:OffsetHDR", gainmapInfo.fEpsilonHdr);
s.writeText( " \n" " \n" ""); return s.detachAsData();
}
// Include the ICC profile of the alternate color space, if it is used. if (gainmapInfo.fGainmapMathColorSpace) {
SkJpegMetadataEncoder::AppendICC(
metadataSegments, gainmapOptions, gainmapInfo.fGainmapMathColorSpace.get());
}
// Add the ISO 21946-1 metadata.
metadataSegments.emplace_back(kISOGainmapMarker,
get_iso_gainmap_segment_params(gainmapInfo.serialize()));
// Encode the gainmap image.
gainmapData = encode_to_data(gainmap, gainmapOptions, metadataSegments); if (!gainmapData) {
SkCodecPrintf("Failed to encode gainmap image.\n"); returnfalse;
}
}
// Encode the base image.
sk_sp<SkData> baseData;
{
SkJpegMetadataEncoder::SegmentList metadataSegments;
// Start with Exif metadata.
metadataSegments.emplace_back(kExifMarker, exif_params);
// MPF segment will be inserted after this.
// Include XMP. if (includeUltraHDRv1) { // Add to the gainmap image size the size of the MPF segment for image 1 of a 2-image // file.
SkJpegMultiPictureParameters mpParams(2);
size_t gainmapImageSize = gainmapData->size() + get_mpf_segment(mpParams, 1)->size();
SkJpegMetadataEncoder::AppendXMPStandard(
metadataSegments,
get_base_image_xmp_metadata(static_cast<int32_t>(gainmapImageSize)).get());
}
// Include ICC profile metadata.
SkJpegMetadataEncoder::AppendICC(metadataSegments, baseOptions, base.colorSpace());
// Include the ISO 21946-1 version metadata.
metadataSegments.emplace_back(
kISOGainmapMarker,
get_iso_gainmap_segment_params(SkGainmapInfo::SerializeVersion()));
// Encode the base image.
baseData = encode_to_data(base, baseOptions, metadataSegments); if (!baseData) {
SkCodecPrintf("Failed to encode base image.\n"); returnfalse;
}
}
// Combine them into an MPF. const SkData* images[] = {
baseData.get(),
gainmapData.get(),
}; return MakeMPF(dst, images, 2);
}
// Compute the offset into |image| at which the MP segment should be inserted. Return 0 on failure. static size_t mp_segment_offset(const SkData* image) { // Scan the image until StartOfScan marker.
SkJpegSegmentScanner scan(kJpegMarkerStartOfScan);
scan.onBytes(image->data(), image->size()); if (!scan.isDone()) {
SkCodecPrintf("Failed to scan image header.\n"); return 0;
} constauto& segments = scan.getSegments();
// Search for the Exif segment and place the MP parameters immediately after. See 5.1. // Basic MP File Structure, which indicates "The MP Extensions are specified in the APP2 // marker segment which follows immediately after the Exif Attributes in the APP1 marker // segment except as specified in section 7". for (size_t segmentIndex = 0; segmentIndex < segments.size() - 1; ++segmentIndex) { constauto& segment = segments[segmentIndex]; if (segment.marker != kExifMarker) { continue;
} auto params = SkJpegSegmentScanner::GetParameters(image, segment); if (params->size() < sizeof(kExifSig) ||
memcmp(params->data(), kExifSig, sizeof(kExifSig)) != 0) { continue;
} // Insert the MPF segment at the offset of the next segment. return segments[segmentIndex + 1].offset;
}
// If there is no Exif segment, then insert the MPF segment just before the StartOfScan. return segments.back().offset;
}
// The offset into each image at which the MP segment will be written.
std::vector<size_t> mpSegmentOffsets(imageCount);
// Populate the MP parameters (image sizes and offsets).
SkJpegMultiPictureParameters mpParams(imageCount);
size_t cumulativeSize = 0; for (size_t i = 0; i < imageCount; ++i) { // Compute the offset into the each image where we will write the MP parameters.
mpSegmentOffsets[i] = mp_segment_offset(images[i]); if (!mpSegmentOffsets[i]) { returnfalse;
}
// Add the size of the MPF segment to image size. Note that the contents of // get_mpf_segment() are incorrect (because we don't have the right offset values), but // the size is correct. const size_t imageSize = images[i]->size() + get_mpf_segment(mpParams, i)->size();
mpParams.images[i].dataOffset = SkJpegMultiPictureParameters::GetImageDataOffset(
cumulativeSize, mpSegmentOffsets[0]);
mpParams.images[i].size = static_cast<uint32_t>(imageSize);
cumulativeSize += imageSize;
}
// Write the images. for (size_t i = 0; i < imageCount; ++i) { // Write up to the MP segment. if (!dst->write(images[i]->bytes(), mpSegmentOffsets[i])) {
SkCodecPrintf("Failed to write image header.\n"); returnfalse;
}
// Write the MP segment. auto mpfSegment = get_mpf_segment(mpParams, i); if (!dst->write(mpfSegment->data(), mpfSegment->size())) {
SkCodecPrintf("Failed to write MPF segment.\n"); returnfalse;
}
// Write the rest of the image. if (!dst->write(images[i]->bytes() + mpSegmentOffsets[i],
images[i]->size() - mpSegmentOffsets[i])) {
SkCodecPrintf("Failed to write image body.\n"); returnfalse;
}
}
returntrue;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.