xref: /aosp_15_r20/external/libultrahdr/lib/src/multipictureformat.cpp (revision 89a0ef05262152531a00a15832a2d3b1e3990773)
1*89a0ef05SAndroid Build Coastguard Worker /*
2*89a0ef05SAndroid Build Coastguard Worker  * Copyright 2023 The Android Open Source Project
3*89a0ef05SAndroid Build Coastguard Worker  *
4*89a0ef05SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*89a0ef05SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*89a0ef05SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*89a0ef05SAndroid Build Coastguard Worker  *
8*89a0ef05SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*89a0ef05SAndroid Build Coastguard Worker  *
10*89a0ef05SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*89a0ef05SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*89a0ef05SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*89a0ef05SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*89a0ef05SAndroid Build Coastguard Worker  * limitations under the License.
15*89a0ef05SAndroid Build Coastguard Worker  */
16*89a0ef05SAndroid Build Coastguard Worker 
17*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/multipictureformat.h"
18*89a0ef05SAndroid Build Coastguard Worker 
19*89a0ef05SAndroid Build Coastguard Worker namespace ultrahdr {
calculateMpfSize()20*89a0ef05SAndroid Build Coastguard Worker size_t calculateMpfSize() {
21*89a0ef05SAndroid Build Coastguard Worker   return sizeof(kMpfSig) +                 // Signature
22*89a0ef05SAndroid Build Coastguard Worker          kMpEndianSize +                   // Endianness
23*89a0ef05SAndroid Build Coastguard Worker          sizeof(uint32_t) +                // Index IFD Offset
24*89a0ef05SAndroid Build Coastguard Worker          sizeof(uint16_t) +                // Tag count
25*89a0ef05SAndroid Build Coastguard Worker          kTagSerializedCount * kTagSize +  // 3 tags at 12 bytes each
26*89a0ef05SAndroid Build Coastguard Worker          sizeof(uint32_t) +                // Attribute IFD offset
27*89a0ef05SAndroid Build Coastguard Worker          kNumPictures * kMPEntrySize;      // MP Entries for each image
28*89a0ef05SAndroid Build Coastguard Worker }
29*89a0ef05SAndroid Build Coastguard Worker 
generateMpf(size_t primary_image_size,size_t primary_image_offset,size_t secondary_image_size,size_t secondary_image_offset)30*89a0ef05SAndroid Build Coastguard Worker std::shared_ptr<DataStruct> generateMpf(size_t primary_image_size, size_t primary_image_offset,
31*89a0ef05SAndroid Build Coastguard Worker                                         size_t secondary_image_size,
32*89a0ef05SAndroid Build Coastguard Worker                                         size_t secondary_image_offset) {
33*89a0ef05SAndroid Build Coastguard Worker   size_t mpf_size = calculateMpfSize();
34*89a0ef05SAndroid Build Coastguard Worker   std::shared_ptr<DataStruct> dataStruct = std::make_shared<DataStruct>(mpf_size);
35*89a0ef05SAndroid Build Coastguard Worker 
36*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write(static_cast<const void*>(kMpfSig), sizeof(kMpfSig));
37*89a0ef05SAndroid Build Coastguard Worker #if USE_BIG_ENDIAN_IN_MPF
38*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write(static_cast<const void*>(kMpBigEndian), kMpEndianSize);
39*89a0ef05SAndroid Build Coastguard Worker #else
40*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write(static_cast<const void*>(kMpLittleEndian), kMpEndianSize);
41*89a0ef05SAndroid Build Coastguard Worker #endif
42*89a0ef05SAndroid Build Coastguard Worker 
43*89a0ef05SAndroid Build Coastguard Worker   // Set the Index IFD offset be the position after the endianness value and this offset.
44*89a0ef05SAndroid Build Coastguard Worker   constexpr uint32_t indexIfdOffset = static_cast<uint16_t>(kMpEndianSize + sizeof(kMpfSig));
45*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write32(Endian_SwapBE32(indexIfdOffset));
46*89a0ef05SAndroid Build Coastguard Worker 
47*89a0ef05SAndroid Build Coastguard Worker   // We will write 3 tags (version, number of images, MP entries).
48*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write16(Endian_SwapBE16(kTagSerializedCount));
49*89a0ef05SAndroid Build Coastguard Worker 
50*89a0ef05SAndroid Build Coastguard Worker   // Write the version tag.
51*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write16(Endian_SwapBE16(kVersionTag));
52*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write16(Endian_SwapBE16(kVersionType));
53*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write32(Endian_SwapBE32(kVersionCount));
54*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write(kVersionExpected, kVersionSize);
55*89a0ef05SAndroid Build Coastguard Worker 
56*89a0ef05SAndroid Build Coastguard Worker   // Write the number of images.
57*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write16(Endian_SwapBE16(kNumberOfImagesTag));
58*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write16(Endian_SwapBE16(kNumberOfImagesType));
59*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write32(Endian_SwapBE32(kNumberOfImagesCount));
60*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write32(Endian_SwapBE32(kNumPictures));
61*89a0ef05SAndroid Build Coastguard Worker 
62*89a0ef05SAndroid Build Coastguard Worker   // Write the MP entries.
63*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write16(Endian_SwapBE16(kMPEntryTag));
64*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write16(Endian_SwapBE16(kMPEntryType));
65*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write32(Endian_SwapBE32(kMPEntrySize * kNumPictures));
66*89a0ef05SAndroid Build Coastguard Worker   const uint32_t mpEntryOffset =
67*89a0ef05SAndroid Build Coastguard Worker       static_cast<uint32_t>(dataStruct->getBytesWritten() -  // The bytes written so far
68*89a0ef05SAndroid Build Coastguard Worker                             sizeof(kMpfSig) +                // Excluding the MPF signature
69*89a0ef05SAndroid Build Coastguard Worker                             sizeof(uint32_t) +               // The 4 bytes for this offset
70*89a0ef05SAndroid Build Coastguard Worker                             sizeof(uint32_t));  // The 4 bytes for the attribute IFD offset.
71*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write32(Endian_SwapBE32(mpEntryOffset));
72*89a0ef05SAndroid Build Coastguard Worker 
73*89a0ef05SAndroid Build Coastguard Worker   // Write the attribute IFD offset (zero because we don't write it).
74*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write32(0);
75*89a0ef05SAndroid Build Coastguard Worker 
76*89a0ef05SAndroid Build Coastguard Worker   // Write the MP entries for primary image
77*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write32(Endian_SwapBE32(kMPEntryAttributeFormatJpeg | kMPEntryAttributeTypePrimary));
78*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write32(Endian_SwapBE32(primary_image_size));
79*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write32(Endian_SwapBE32(primary_image_offset));
80*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write16(0);
81*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write16(0);
82*89a0ef05SAndroid Build Coastguard Worker 
83*89a0ef05SAndroid Build Coastguard Worker   // Write the MP entries for secondary image
84*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write32(Endian_SwapBE32(kMPEntryAttributeFormatJpeg));
85*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write32(Endian_SwapBE32(secondary_image_size));
86*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write32(Endian_SwapBE32(secondary_image_offset));
87*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write16(0);
88*89a0ef05SAndroid Build Coastguard Worker   dataStruct->write16(0);
89*89a0ef05SAndroid Build Coastguard Worker 
90*89a0ef05SAndroid Build Coastguard Worker   return dataStruct;
91*89a0ef05SAndroid Build Coastguard Worker }
92*89a0ef05SAndroid Build Coastguard Worker 
93*89a0ef05SAndroid Build Coastguard Worker }  // namespace ultrahdr
94