"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "srcs/examples/example.cpp" between
heif-3.6.1.tar.gz and heif-3.6.2.tar.gz

About: HEIF (High Efficiency Image File Format) is a visual media container format for images and image sequences (MPEG-standard). This HEIF engine demonstrates its powerful features and capabilities (under Nokia HEIF license).

example.cpp  (heif-3.6.1):example.cpp  (heif-3.6.2)
/* This file is part of Nokia HEIF library /* This file is part of Nokia HEIF library
* *
* Copyright (c) 2015-2020 Nokia Corporation and/or its subsidiary(-ies). All ri ghts reserved. * Copyright (c) 2015-2021 Nokia Corporation and/or its subsidiary(-ies). All ri ghts reserved.
* *
* Contact: heif@nokia.com * Contact: heif@nokia.com
* *
* This software, including documentation, is protected by copyright controlled by Nokia Corporation and/ or its * This software, including documentation, is protected by copyright controlled by Nokia Corporation and/ or its
* subsidiaries. All rights are reserved. * subsidiaries. All rights are reserved.
* *
* Copying, including reproducing, storing, adapting or translating, any or all of this material requires the prior * Copying, including reproducing, storing, adapting or translating, any or all of this material requires the prior
* written consent of Nokia. * written consent of Nokia.
*/ */
/** This file includes some examples about using the reader API and writer API ( /** This file includes some examples about using the reader API and writer API (
example7) example7).
* Note that binary execution fails if proper .heic files are not located in th * Note:
e directory */ * - Binary execution fails if proper .heic files are not located in the direct
ory.
* - Input files are available from https://github.com/nokiatech/heif_conforman
ce
* - Code for image decoding or rendering is not present here.
* - Most error checking and proper cleanup in error cases are omitted to keep
examples brief. */
#include <algorithm> // std::min_element #include <algorithm>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <map> #include <map>
#include "heifreader.h" #include "heifreader.h"
#include "heifwriter.h" #include "heifwriter.h"
using namespace std; using namespace std;
using namespace HEIF; using namespace HEIF;
void example1(); void example1();
void example2(); void example2();
void example3(); void example3();
void example4(); void example4();
void example5(); void example5();
void example6(); void example6();
void example7(); void example7();
void example8(); void example8();
void printInfo(const char* file);
/// Access and read a cover image /// Access and read a cover image
void example1() void example1()
{ {
auto* reader = Reader::Create(); auto* reader = Reader::Create();
// Input file available from https://github.com/nokiatech/heif_conformance // Input file available from https://github.com/nokiatech/heif_conformance
const char* filename = "C003.heic"; const char* filename = "C003.heic";
if (reader->initialize(filename) == ErrorCode::OK) if (reader->initialize(filename) != ErrorCode::OK)
{ {
FileInformation info; printInfo(filename);
reader->getFileInformation(info); Reader::Destroy(reader);
return;
}
// Find the item ID FileInformation info;
ImageId itemId; reader->getFileInformation(info);
reader->getPrimaryItem(itemId);
uint64_t memoryBufferSize = 1024 * 1024; // Find the item ID
auto* memoryBuffer = new uint8_t[memoryBufferSize]; ImageId itemId;
reader->getItemDataWithDecoderParameters(itemId, memoryBuffer, memoryBuf reader->getPrimaryItem(itemId);
ferSize);
uint64_t memoryBufferSize = 1024 * 1024;
auto* memoryBuffer = new uint8_t[memoryBufferSize];
reader->getItemDataWithDecoderParameters(itemId, memoryBuffer, memoryBufferS
ize);
// Feed 'data' to decoder and display the cover image... // Feed 'data' to decoder and display the cover image...
delete[] memoryBuffer; delete[] memoryBuffer;
}
else
{
cout << "Can't find input file: " << filename << ". "
<< "Please download it from https://github.com/nokiatech/heif_confo
rmance "
<< "and place it in same directory with the executable." << endl;
}
Reader::Destroy(reader); Reader::Destroy(reader);
} }
/// Access and read image item and its thumbnail /// Access and read image item and its thumbnail
void example2() void example2()
{ {
Array<ImageId> itemIds;
uint64_t itemSize = 1024 * 1024;
auto* itemData = new uint8_t[itemSize];
auto* reader = Reader::Create(); auto* reader = Reader::Create();
// Input file available from https://github.com/nokiatech/heif_conformance // Input file available from https://github.com/nokiatech/heif_conformance
const char* filename = "C012.heic"; const char* filename = "C012.heic";
if (reader->initialize(filename) == ErrorCode::OK) if (reader->initialize(filename) != ErrorCode::OK)
{ {
FileInformation info; printInfo(filename);
if (reader->getFileInformation(info) != ErrorCode::OK) Reader::Destroy(reader);
{ return;
// handle error here... }
delete[] itemData;
return;
}
// Verify that the file has one or several images in the MetaBox FileInformation info;
if (!(info.features & FileFeatureEnum::HasSingleImage || info.features & if (reader->getFileInformation(info) != ErrorCode::OK)
FileFeatureEnum::HasImageCollection)) {
{ // handle error here...
delete[] itemData; return;
return; }
}
// Find the item ID of the first master image // Verify that the file has one or several images in the MetaBox
reader->getMasterImages(itemIds); if (!(info.features & FileFeatureEnum::HasSingleImage || info.features & Fil
const ImageId masterId = itemIds[0]; eFeatureEnum::HasImageCollection))
{
return;
}
const auto metaBoxFeatures = info.rootMetaBoxInformation.features; // F // Find the item ID of the first master image
or convenience Array<ImageId> itemIds;
if (metaBoxFeatures & MetaBoxFeatureEnum::HasThumbnails) reader->getMasterImages(itemIds);
{ const ImageId masterId = itemIds[0];
// Thumbnail references ('thmb') are from the thumbnail image to the uint64_t itemSize = 1024 * 1024;
master image auto* itemData = new uint8_t[itemSize];
reader->getReferencedToItemListByType(masterId, "thmb", itemIds);
const auto thumbnailId = itemIds[0]; const auto metaBoxFeatures = info.rootMetaBoxInformation.features; // For c
onvenience
if (metaBoxFeatures & MetaBoxFeatureEnum::HasThumbnails)
{
// Thumbnail references ('thmb') are from the thumbnail image to the mas
ter image
reader->getReferencedToItemListByType(masterId, "thmb", itemIds);
const auto thumbnailId = itemIds[0];
if (reader->getItemDataWithDecoderParameters(thumbnailId.get(), item if (reader->getItemDataWithDecoderParameters(thumbnailId.get(), itemData
Data, itemSize) == ErrorCode::OK) , itemSize) == ErrorCode::OK)
{
// ...decode data and display the image, show master image later
}
}
else
{ {
// There was no thumbnail, show just the master image // ...decode data and display the image, show master image later
if (reader->getItemDataWithDecoderParameters(masterId.get(), itemDat
a, itemSize) == ErrorCode::OK)
{
// ...decode and display...
}
} }
} }
else else
{ {
cout << "Can't find input file: " << filename << ". " // There was no thumbnail, show just the master image
<< "Please download it from https://github.com/nokiatech/heif_confo if (reader->getItemDataWithDecoderParameters(masterId.get(), itemData, i
rmance " temSize) == ErrorCode::OK)
<< "and place it in same directory with the executable." << endl; {
// ...decode and display...
}
} }
Reader::Destroy(reader); Reader::Destroy(reader);
delete[] itemData; delete[] itemData;
} }
/// Access and read image items and their thumbnails in a collection /// Access and read image items and their thumbnails in a collection
void example3() void example3()
{ {
auto* reader = Reader::Create(); auto* reader = Reader::Create();
typedef ImageId MasterItemId; typedef ImageId MasterItemId;
typedef ImageId ThumbnailItemId; typedef ImageId ThumbnailItemId;
Array<ImageId> itemIds; Array<ImageId> itemIds;
map<MasterItemId, ThumbnailItemId> imageMap; map<MasterItemId, ThumbnailItemId> imageMap;
// Input file available from https://github.com/nokiatech/heif_conformance // Input file available from https://github.com/nokiatech/heif_conformance
const char* filename = "C012.heic"; const char* filename = "C012.heic";
if (reader->initialize(filename) == ErrorCode::OK) if (reader->initialize(filename) != ErrorCode::OK)
{ {
FileInformation info; printInfo(filename);
reader->getFileInformation(info); Reader::Destroy(reader);
return;
}
// Find item IDs of master images FileInformation info;
reader->getMasterImages(itemIds); reader->getFileInformation(info);
// Find thumbnails for each master. There can be several thumbnails for // Find item IDs of master images
one master image, get narrowest ones reader->getMasterImages(itemIds);
// here.
for (const auto masterId : itemIds) // Find thumbnails for each master. There can be several thumbnails for one
master image, get narrowest ones
// here.
for (const auto masterId : itemIds)
{
// Thumbnail references ('thmb') are from the thumbnail image to the mas
ter image
Array<ImageId> thumbIds;
reader->getReferencedToItemListByType(masterId, "thmb", thumbIds);
const auto thumbId = std::min_element(thumbIds.begin(), thumbIds.end(),
[&](ImageId a, ImageId b) {
uint32_t widthA, widthB;
reader->getWidth(a, widthA);
reader->getWidth(b, widthB);
return (widthA < widthB);
});
if (thumbId != thumbIds.end()) // For images without thumbnail thumbId
equals to end()
{ {
// Thumbnail references ('thmb') are from the thumbnail image to the imageMap[masterId] = thumbId->get();
master image
Array<ImageId> thumbIds;
reader->getReferencedToItemListByType(masterId, "thmb", thumbIds);
const ImageId thumbId = *std::min_element(thumbIds.begin(), thumbIds
.end(), [&](ImageId a, ImageId b) {
uint32_t widthA, widthB;
reader->getWidth(a, widthA);
reader->getWidth(b, widthB);
return (widthA < widthB);
});
imageMap[masterId] = thumbId;
} }
} }
else
{
cout << "Can't find input file: " << filename << ". "
<< "Please download it from https://github.com/nokiatech/heif_confo
rmance "
<< "and place it in same directory with the executable." << endl;
}
// We have now item IDs of thumbnails and master images. Decode and show the m from imageMap as wanted. // We have now item IDs of thumbnails and master images. Decode and show the m from imageMap as wanted.
Reader::Destroy(reader); Reader::Destroy(reader);
} }
/// Access and read derived images /// Access and read derived images
void example4() void example4()
{ {
auto* reader = Reader::Create(); auto* reader = Reader::Create();
Array<ImageId> itemIds; Array<ImageId> itemIds;
// Input file available from https://github.com/nokiatech/heif_conformance // Input file available from https://github.com/nokiatech/heif_conformance
const char* filename = "C008.heic"; const char* filename = "C008.heic";
if (reader->initialize(filename) == ErrorCode::OK) if (reader->initialize(filename) != ErrorCode::OK)
{ {
FileInformation info; printInfo(filename);
reader->getFileInformation(info); Reader::Destroy(reader);
return;
}
// Find item IDs of 'iden' (identity transformation) type derived images FileInformation info;
reader->getItemListByType("iden", itemIds); reader->getFileInformation(info);
const auto itemId = itemIds[0]; // For demo purposes, assume there was // Find item IDs of 'iden' (identity transformation) type derived images
one 'iden' item reader->getItemListByType("iden", itemIds);
// 'dimg' item reference points from the 'iden' derived item to the inpu const auto itemId = itemIds[0]; // For demo purposes, assume there was one
t(s) of the derivation 'iden' item
Array<ImageId> referencedImages;
reader->getReferencedFromItemListByType(itemId, "dimg", referencedImages
);
const ImageId sourceItemId = referencedImages[0]; // For demo purposes,
assume there was one
// Get 'iden' item properties to find out what kind of derivation it is // 'dimg' item reference points from the 'iden' derived item to the input(s)
Array<ItemPropertyInfo> propertyInfos; of the derivation
reader->getItemProperties(itemId, propertyInfos); Array<ImageId> referencedImages;
reader->getReferencedFromItemListByType(itemId, "dimg", referencedImages);
const ImageId sourceItemId = referencedImages[0]; // For demo purposes, ass
ume there was one
unsigned int rotation = 0; // Get 'iden' item properties to find out what kind of derivation it is
for (const auto& property : propertyInfos) Array<ItemPropertyInfo> propertyInfos;
{ reader->getItemProperties(itemId, propertyInfos);
// For example, handle 'irot' transformational property is anti-cloc
kwise rotation
if (property.type == ItemPropertyType::IROT)
{
// Get property struct by index to access rotation angle
Rotate irot;
reader->getProperty(property.index, irot);
rotation = irot.angle;
break; // Assume only one property
}
}
cout << "To render derived image item ID " << itemId.get() << ":" << end unsigned int rotation = 0;
l; for (const auto& property : propertyInfos)
cout << "-retrieve data for source image item ID " << sourceItemId.get()
<< endl;
cout << "-rotating image " << rotation << " degrees." << endl;
}
else
{ {
cout << "Can't find input file: " << filename << ". " // For example, handle 'irot' transformational property is anti-clockwis
<< "Please download it from https://github.com/nokiatech/heif_confo e rotation
rmance " if (property.type == ItemPropertyType::IROT)
<< "and place it in same directory with the executable." << endl; {
// Get property struct by index to access rotation angle
Rotate irot;
reader->getProperty(property.index, irot);
rotation = irot.angle;
break; // Assume only one property
}
} }
cout << "To render derived image item ID " << itemId.get() << ":" << endl;
cout << "-retrieve data for source image item ID " << sourceItemId.get() <<
endl;
cout << "-rotating image " << rotation << " degrees." << endl;
Reader::Destroy(reader); Reader::Destroy(reader);
} }
/// Access and read media track samples, thumbnail track samples and timestamps /// Access and read media track samples, thumbnail track samples and timestamps
void example5() void example5()
{ {
auto* reader = Reader::Create(); auto* reader = Reader::Create();
Array<uint32_t> itemIds; Array<uint32_t> itemIds;
// Input file available from https://github.com/nokiatech/heif_conformance // Input file available from https://github.com/nokiatech/heif_conformance
const char* filename = "C032.heic"; const char* filename = "C032.heic";
if (reader->initialize(filename) == ErrorCode::OK) if (reader->initialize(filename) != ErrorCode::OK)
{ {
FileInformation info; printInfo(filename);
reader->getFileInformation(info); Reader::Destroy(reader);
return;
}
FileInformation info;
reader->getFileInformation(info);
// Print information for every track read // Print information for every track read
for (const auto& trackProperties : info.trackInformation) for (const auto& trackProperties : info.trackInformation)
{ {
const auto sequenceId = trackProperties.trackId; const auto sequenceId = trackProperties.trackId;
cout << "Track ID " << sequenceId.get() << endl; // Context ID corr cout << "Track ID " << sequenceId.get() << endl; // Context ID correspo
esponds to the track ID nds to the track ID
if (trackProperties.features & TrackFeatureEnum::IsMasterImageSequen if (trackProperties.features & TrackFeatureEnum::IsMasterImageSequence)
ce) {
{ cout << "This is a master image sequence." << endl;
cout << "This is a master image sequence." << endl; }
}
if (trackProperties.features & TrackFeatureEnum::IsThumbnailImageSeq if (trackProperties.features & TrackFeatureEnum::IsThumbnailImageSequenc
uence) e)
{
// Assume there is only one type track reference, so check reference
type and master track ID(s) from
// the first one.
const auto tref = trackProperties.referenceTrackIds[0];
cout << "Track reference type is '" << tref.type.value << "'" << end
l;
cout << "This is a thumbnail track for track ID ";
for (const auto masterTrackId : tref.trackIds)
{ {
// Assume there is only one type track reference, so check refer cout << masterTrackId.get() << endl;
ence type and master track ID(s) from
// the first one.
const auto tref = trackProperties.referenceTrackIds[0];
cout << "Track reference type is '" << tref.type.value << "'" <<
endl;
cout << "This is a thumbnail track for track ID ";
for (const auto masterTrackId : tref.trackIds)
{
cout << masterTrackId.get() << endl;
}
} }
}
Array<TimestampIDPair> timestamps; Array<TimestampIDPair> timestamps;
reader->getItemTimestamps(sequenceId, timestamps); reader->getItemTimestamps(sequenceId, timestamps);
cout << "Sample timestamps:" << endl; cout << "Sample timestamps:" << endl;
for (const auto& timestamp : timestamps) for (const auto& timestamp : timestamps)
{ {
cout << " Timestamp=" << timestamp.timeStamp << "ms, sample ID=" cout << " Timestamp=" << timestamp.timeStamp << "ms, sample ID=" <<
<< timestamp.itemId.get() << endl; timestamp.itemId.get() << endl;
} }
for (const auto& sampleProperties : trackProperties.sampleProperties for (const auto& sampleProperties : trackProperties.sampleProperties)
) {
// A sample might have decoding dependencies. The simplest way to ha
ndle this is just to always ask and
// decode all dependencies.
Array<SequenceImageId> itemsToDecode;
reader->getDecodeDependencies(sequenceId, sampleProperties.sampleId,
itemsToDecode);
for (auto dependencyId : itemsToDecode)
{ {
// A sample might have decoding dependencies. The simplest way t uint64_t size = 1024 * 1024;
o handle this is just to always ask and auto* sampleData = new uint8_t[size];
// decode all dependencies. reader->getItemDataWithDecoderParameters(sequenceId, dependencyI
Array<SequenceImageId> itemsToDecode; d, sampleData, size);
reader->getDecodeDependencies(sequenceId, sampleProperties.sampl
eId, itemsToDecode);
for (auto dependencyId : itemsToDecode)
{
uint64_t size = 1024 * 1024;
auto* sampleData = new uint8_t[size];
reader->getItemDataWithDecoderParameters(sequenceId, depende
ncyId, sampleData, size);
// Feed data to decoder... // Feed data to decoder...
delete[] sampleData; delete[] sampleData;
}
// Store or show the image...
} }
// Store or show the image...
} }
} }
else
{
cout << "Can't find input file: " << filename << ". "
<< "Please download it from https://github.com/nokiatech/heif_confo
rmance "
<< "and place it in same directory with the executable." << endl;
}
Reader::Destroy(reader); Reader::Destroy(reader);
} }
/// Access and read media alternative /// Access and read media alternative
void example6() void example6()
{ {
auto* reader = Reader::Create(); auto* reader = Reader::Create();
Array<uint32_t> itemIds; Array<uint32_t> itemIds;
// Input file available from https://github.com/nokiatech/heif_conformance // Input file available from https://github.com/nokiatech/heif_conformance
const char* filename = "C032.heic"; const char* filename = "C032.heic";
if (reader->initialize(filename) == ErrorCode::OK) if (reader->initialize(filename) != ErrorCode::OK)
{ {
FileInformation info; printInfo(filename);
reader->getFileInformation(info); Reader::Destroy(reader);
return;
}
FileInformation info;
reader->getFileInformation(info);
SequenceId trackId = 0; SequenceId trackId = 0;
if (info.trackInformation.size > 0) if (info.trackInformation.size > 0)
{
const auto& trackInfo = info.trackInformation[0];
trackId = trackInfo.trackId;
if (trackInfo.features & TrackFeatureEnum::HasAlternatives)
{ {
const auto& trackInfo = info.trackInformation[0]; const SequenceId alternativeTrackId = trackInfo.alternateTrackIds[0]
trackId = trackInfo.trackId; ; // Take the first alternative
uint32_t alternativeWidth;
reader->getDisplayWidth(alternativeTrackId, alternativeWidth);
uint32_t trackWidth;
reader->getDisplayWidth(trackId, trackWidth);
if (trackInfo.features & TrackFeatureEnum::HasAlternatives) if (trackWidth > alternativeWidth)
{ {
const SequenceId alternativeTrackId = trackInfo.alternateTrackId cout << "The alternative track has wider display width, let's us
s[0]; // Take the first alternative e it from now on..." << endl;
uint32_t alternativeWidth; trackId = alternativeTrackId;
reader->getDisplayWidth(alternativeTrackId, alternativeWidth);
uint32_t trackWidth;
reader->getDisplayWidth(trackId, trackWidth);
if (trackWidth > alternativeWidth)
{
cout << "The alternative track has wider display width, let'
s use it from now on..." << endl;
trackId = alternativeTrackId;
}
} }
} }
} }
else
{
cout << "Can't find input file: " << filename << ". "
<< "Please download it from https://github.com/nokiatech/heif_confo
rmance "
<< "and place it in same directory with the executable." << endl;
}
Reader::Destroy(reader); Reader::Destroy(reader);
} }
// Example about reading file and writing it to output. Note most error checking omitted. // Example about reading file and writing it to output. Note most error checking omitted.
void example7() void example7()
{ {
// create reader and writer instances // create reader and writer instances
auto* reader = Reader::Create(); auto* reader = Reader::Create();
auto* writer = Writer::Create(); auto* writer = Writer::Create();
// partially configure writer output // partially configure writer output
OutputConfig writerOutputConf{}; OutputConfig writerOutputConf{};
writerOutputConf.fileName = "example7_output.heic"; writerOutputConf.fileName = "example7_output.heic";
writerOutputConf.progressiveFile = true; writerOutputConf.progressiveFile = true;
// Input file available from https://github.com/nokiatech/heif_conformance // Input file available from https://github.com/nokiatech/heif_conformance
const char* filename = "C014.heic"; const char* filename = "C014.heic";
if (reader->initialize(filename) == ErrorCode::OK) if (reader->initialize(filename) != ErrorCode::OK)
{
printInfo(filename);
Reader::Destroy(reader);
Writer::Destroy(writer);
return;
}
// read major brand of file and store it to writer config.
FourCC inputMajorBrand{};
reader->getMajorBrand(inputMajorBrand);
// add major brand to writer config
writerOutputConf.majorBrand = inputMajorBrand;
// read compatible brands of file and store it to writer config.
Array<FourCC> inputCompatibleBrands{};
reader->getCompatibleBrands(inputCompatibleBrands);
// add compatible brands to writer config
writerOutputConf.compatibleBrands = inputCompatibleBrands;
// initialize writer now that we have all the needed information from reader
if (writer->initialize(writerOutputConf) != ErrorCode::OK)
{ {
// read major brand of file and store it to writer config. return;
FourCC inputMajorBrand{}; }
reader->getMajorBrand(inputMajorBrand); // get information about all input file content
FileInformation fileInfo{};
reader->getFileInformation(fileInfo);
// add major brand to writer config // map which input decoder config id matches the writer output decoder confi
writerOutputConf.majorBrand = inputMajorBrand; g ids
map<DecoderConfigId, DecoderConfigId> inputToOutputDecoderConfigIds;
// read compatible brands of file and store it to writer config. // Image Rotation property as an example of Image Properties:
Array<FourCC> inputCompatibleBrands{}; map<PropertyId, Rotate> imageRotationProperties;
reader->getCompatibleBrands(inputCompatibleBrands);
// add compatible brands to writer config // map which input image property maach the writer output property.
writerOutputConf.compatibleBrands = inputCompatibleBrands; map<PropertyId, PropertyId> inputToOutputImageProperties;
// initialize writer now that we have all the needed information from re // go through all items in input file and store master image decoder configs
ader for (const auto& image : fileInfo.rootMetaBoxInformation.itemInformations)
if (writer->initialize(writerOutputConf) == ErrorCode::OK) {
if (image.features & ItemFeatureEnum::IsMasterImage)
{ {
// get information about all input file content // read image decoder config and store its id if not seen before
FileInformation fileInfo{}; DecoderConfiguration inputdecoderConfig{};
reader->getFileInformation(fileInfo); reader->getDecoderParameterSets(image.itemId, inputdecoderConfig);
if (!inputToOutputDecoderConfigIds.count(inputdecoderConfig.decoderC
onfigId))
{
// feed new decoder config to writer and store input to output i
d pairing information
DecoderConfigId outputDecoderConfigId;
writer->feedDecoderConfig(inputdecoderConfig.decoderSpecificInfo
, outputDecoderConfigId);
inputToOutputDecoderConfigIds[inputdecoderConfig.decoderConfigId
] = outputDecoderConfigId;
}
// map which input decoder config id matches the writer output decod // read image data
er config ids Data imageData{};
map<DecoderConfigId, DecoderConfigId> inputToOutputDecoderConfigIds; imageData.size = image.size;
imageData.data = new uint8_t[imageData.size];
reader->getItemData(image.itemId, imageData.data, imageData.size, fa
lse);
// feed image data to writer
imageData.mediaFormat = MediaFormat::HEVC;
imageData.decoderConfigId = inputToOutputDecoderConfigIds.at(inputde
coderConfig.decoderConfigId);
MediaDataId outputMediaId;
writer->feedMediaData(imageData, outputMediaId);
delete[] imageData.data;
// create new image based on that data:
ImageId outputImageId;
writer->addImage(outputMediaId, outputImageId);
// Image Rotation property as an example of Image Properties: // if this input image was the primary image -> also mark output ima
map<PropertyId, Rotate> imageRotationProperties; ge as primary image
if (image.features & ItemFeatureEnum::IsPrimaryImage)
{
writer->setPrimaryItem(outputImageId);
}
// map which input image property maach the writer output property. // copy other properties over
map<PropertyId, PropertyId> inputToOutputImageProperties; Array<ItemPropertyInfo> imageProperties;
reader->getItemProperties(image.itemId, imageProperties);
// go through all items in input file and store master image decoder for (const auto& imageProperty : imageProperties)
configs
for (const auto& image : fileInfo.rootMetaBoxInformation.itemInforma
tions)
{ {
if (image.features & ItemFeatureEnum::IsMasterImage) switch (imageProperty.type)
{ {
// read image decoder config and store its id if not seen be case ItemPropertyType::IROT:
fore {
DecoderConfiguration inputdecoderConfig{}; if (!imageRotationProperties.count(imageProperty.index))
reader->getDecoderParameterSets(image.itemId, inputdecoderCo
nfig);
if (!inputToOutputDecoderConfigIds.count(inputdecoderConfig.
decoderConfigId))
{
// feed new decoder config to writer and store input to
output id pairing information
DecoderConfigId outputDecoderConfigId;
writer->feedDecoderConfig(inputdecoderConfig.decoderSpec
ificInfo, outputDecoderConfigId);
inputToOutputDecoderConfigIds[inputdecoderConfig.decoder
ConfigId] = outputDecoderConfigId;
}
// read image data
Data imageData{};
imageData.size = image.size;
imageData.data = new uint8_t[imageData.size];
reader->getItemData(image.itemId, imageData.data, imageData.
size, false);
// feed image data to writer
imageData.mediaFormat = MediaFormat::HEVC;
imageData.decoderConfigId = inputToOutputDecoderConfigIds.at
(inputdecoderConfig.decoderConfigId);
MediaDataId outputMediaId;
writer->feedMediaData(imageData, outputMediaId);
delete[] imageData.data;
// create new image based on that data:
ImageId outputImageId;
writer->addImage(outputMediaId, outputImageId);
// if this input image was the primary image -> also mark ou
tput image as primary image
if (image.features & ItemFeatureEnum::IsPrimaryImage)
{ {
writer->setPrimaryItem(outputImageId); // if we haven't yet read this property for other image
} -> do so and add it to writer as
// well
// copy other properties over Rotate rotateInfo{};
Array<ItemPropertyInfo> imageProperties; reader->getProperty(imageProperty.index, rotateInfo);
reader->getItemProperties(image.itemId, imageProperties); imageRotationProperties[imageProperty.index] = rotateInf
o;
for (const auto& imageProperty : imageProperties) // create new property for images in writer
{ writer->addProperty(rotateInfo, inputToOutputImageProper
switch (imageProperty.type) ties[imageProperty.index]);
{
case ItemPropertyType::IROT:
{
if (!imageRotationProperties.count(imageProperty.ind
ex))
{
// if we haven't yet read this property for othe
r image -> do so and add it to writer as
// well
Rotate rotateInfo{};
reader->getProperty(imageProperty.index, rotateI
nfo);
imageRotationProperties[imageProperty.index] = r
otateInfo;
// create new property for images in writer
writer->addProperty(rotateInfo, inputToOutputIma
geProperties[imageProperty.index]);
}
// associate property with this output image
writer->associateProperty(image.itemId,
inputToOutputImageProperti
es.at(imageProperty.index),
imageProperty.essential);
break;
}
//
// ... other properties
//
default:
break;
}
} }
// associate property with this output image
writer->associateProperty(image.itemId, inputToOutputImagePr
operties.at(imageProperty.index),
imageProperty.essential);
break;
}
//
// ... other properties
//
default:
break;
} }
} }
writer->finalize();
} }
} }
else
{ writer->finalize();
cout << "Can't find input file: " << filename << ". "
<< "Please download it from https://github.com/nokiatech/heif_confo
rmance "
<< "and place it in same directory with the executable." << endl;
}
Reader::Destroy(reader); Reader::Destroy(reader);
Writer::Destroy(writer); Writer::Destroy(writer);
} }
/// Read Exif metadata. Note that most error checking is omitted. /// Read Exif metadata. Note that most error checking is omitted.
void example8() void example8()
{ {
auto* reader = Reader::Create(); auto* reader = Reader::Create();
// Try opening a file with an "Exif" item. // Try opening a file with an "Exif" item.
// The file is available from https://github.com/nokiatech/heif_conformance // The file is available from https://github.com/nokiatech/heif_conformance
const char* filename = "C034.heic"; const char* filename = "C034.heic";
if (reader->initialize(filename) != ErrorCode::OK) if (reader->initialize(filename) != ErrorCode::OK)
{ {
cout << "Can't find input file: " << filename << ". " printInfo(filename);
<< "Please download it from https://github.com/nokiatech/heif_confo Reader::Destroy(reader);
rmance "
<< "and place it in same directory with the executable." << endl;
return; return;
} }
FileInformation fileInfo{}; FileInformation fileInfo{};
reader->getFileInformation(fileInfo); reader->getFileInformation(fileInfo);
// Find the primary item ID. // Find the primary item ID.
ImageId primaryItemId; ImageId primaryItemId;
reader->getPrimaryItem(primaryItemId); reader->getPrimaryItem(primaryItemId);
skipping to change at line 526 skipping to change at line 517
ImageId exifItemId = metadataIds[0]; ImageId exifItemId = metadataIds[0];
// Optional: verify the item ID we got is really of "Exif" type. // Optional: verify the item ID we got is really of "Exif" type.
FourCC itemType; FourCC itemType;
reader->getItemType(exifItemId, itemType); reader->getItemType(exifItemId, itemType);
if (itemType != "Exif") if (itemType != "Exif")
{ {
return; return;
} }
// Get item size from parsed information. For simplicity, assume it is the f // Get item size from parsed information.
irst and only non-image item in the const auto it = std::find_if(fileInfo.rootMetaBoxInformation.itemInformation
// file. s.begin(),
if (fileInfo.rootMetaBoxInformation.itemInformations[0].itemId != exifItemId fileInfo.rootMetaBoxInformation.itemInformation
) s.end(),
[exifItemId](ItemInformation a) { return a.item
Id == exifItemId; });
if (it == fileInfo.rootMetaBoxInformation.itemInformations.end())
{ {
Reader::Destroy(reader);
return; return;
} }
auto itemSize = fileInfo.rootMetaBoxInformation.itemInformations[0].size; auto itemSize = it->size;
// Request item data. // Request item data.
auto* memoryBuffer = new uint8_t[itemSize]; auto* memoryBuffer = new uint8_t[itemSize];
reader->getItemData(metadataIds[0], memoryBuffer, itemSize); reader->getItemData(metadataIds[0], memoryBuffer, itemSize);
// Write Exif item data to a file. // Write Exif item data to a file.
// Note this data does not contain Exif payload only. The payload is precede d by 4-byte exif_tiff_header_offset // Note this data does not contain Exif payload only. The payload is precede d by 4-byte exif_tiff_header_offset
// field as defined by class ExifDataBlock() in ISO/IEC 23008-12:2017. // field as defined by class ExifDataBlock() in ISO/IEC 23008-12:2017.
ofstream file("exifdata.bin", ios::out | ios::binary); ofstream file("exifdata.bin", ios::out | ios::binary);
file.write(reinterpret_cast<char*>(memoryBuffer), static_cast<std::streamsiz e>(itemSize)); file.write(reinterpret_cast<char*>(memoryBuffer), static_cast<std::streamsiz e>(itemSize));
delete[] memoryBuffer; delete[] memoryBuffer;
Reader::Destroy(reader); Reader::Destroy(reader);
} }
void printInfo(const char* filename)
{
cout << "Can't find input file: " << filename << ". "
<< "Please download it from https://github.com/nokiatech/heif_conforman
ce "
<< "and place it in same directory with the executable." << endl;
}
int main() int main()
{ {
example1(); example1();
example2(); example2();
example3(); example3();
example4(); example4();
example5(); example5();
example6(); example6();
example7(); example7();
example8(); example8();
 End of changes. 81 change blocks. 
360 lines changed or deleted 347 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)