1 /*
2 * Copyright (C) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "buffer_metadata_stream.h"
17 #include "dng_exif_metadata_accessor.h"
18 #include "file_metadata_stream.h"
19 #include "image_log.h"
20 #include "image_type.h"
21 #include "heif_exif_metadata_accessor.h"
22 #include "jpeg_exif_metadata_accessor.h"
23 #include "metadata_accessor_factory.h"
24 #include "png_exif_metadata_accessor.h"
25 #include "tiff_parser.h"
26 #include "webp_exif_metadata_accessor.h"
27
28 #undef LOG_DOMAIN
29 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
30
31 #undef LOG_TAG
32 #define LOG_TAG "MetadataAccessorFactory"
33
34 namespace OHOS {
35 namespace Media {
36 const int IMAGE_HEADER_SIZE = 12;
37 const int WEBP_HEADER_OFFSET = 8;
38 const int IMAGE_HEIF_HEADER_OFFSET = 4;
39 const byte jpegHeader[] = { 0xff, 0xd8, 0xff };
40 const byte pngHeader[] = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };
41 const byte webpHeader[] = { 0x57, 0x45, 0x42, 0x50 };
42 const byte riffHeader[] = { 0x52, 0x49, 0x46, 0x46 };
43 const byte heifHeader[] = { 0x66, 0x74, 0x79, 0x70 };
44 const byte DNG_LITTLE_ENDIAN_HEADER[] = { 0x49, 0x49, 0x2A, 0x00 };
45 const byte DNG_BIG_ENDIAN_HEADER[] = { 0x4D, 0x4D, 0x00, 0x2A };
46 const ssize_t STREAM_READ_ERROR = -1;
47
Create(uint8_t * buffer,const uint32_t size,BufferMetadataStream::MemoryMode mode)48 std::shared_ptr<MetadataAccessor> MetadataAccessorFactory::Create(uint8_t *buffer, const uint32_t size,
49 BufferMetadataStream::MemoryMode mode)
50 {
51 DataInfo dataInfo {buffer, size};
52 uint32_t error = SUCCESS;
53 return Create(dataInfo, error, mode);
54 }
55
Create(const int fd)56 std::shared_ptr<MetadataAccessor> MetadataAccessorFactory::Create(const int fd)
57 {
58 uint32_t error = SUCCESS;
59 return Create(fd, error);
60 }
61
Create(const std::string & path)62 std::shared_ptr<MetadataAccessor> MetadataAccessorFactory::Create(const std::string &path)
63 {
64 uint32_t error = SUCCESS;
65 return Create(path, error);
66 }
67
Create(const DataInfo & dataInfo,uint32_t & error,BufferMetadataStream::MemoryMode mode,int originalFd,const std::string & originalPath)68 std::shared_ptr<MetadataAccessor> MetadataAccessorFactory::Create(const DataInfo &dataInfo, uint32_t &error,
69 BufferMetadataStream::MemoryMode mode,
70 int originalFd,
71 const std::string &originalPath)
72 {
73 if (dataInfo.buffer == nullptr) {
74 return nullptr;
75 }
76 std::shared_ptr<MetadataStream> stream = std::make_shared<BufferMetadataStream>(dataInfo.buffer, dataInfo.size,
77 mode, originalFd, originalPath);
78 return Create(stream, error);
79 }
80
Create(const int fd,uint32_t & error,const int originalFd)81 std::shared_ptr<MetadataAccessor> MetadataAccessorFactory::Create(const int fd, uint32_t &error, const int originalFd)
82 {
83 std::shared_ptr<MetadataStream> stream = std::make_shared<FileMetadataStream>(fd, originalFd);
84 if (!stream->Open(OpenMode::ReadWrite)) {
85 IMAGE_LOGE("Failed to open the stream with file descriptor: %{public}d", fd);
86 return nullptr;
87 }
88 return Create(stream, error);
89 }
90
Create(const std::string & path,uint32_t & error,const std::string & originalPath)91 std::shared_ptr<MetadataAccessor> MetadataAccessorFactory::Create(const std::string &path, uint32_t &error,
92 const std::string &originalPath)
93 {
94 std::shared_ptr<MetadataStream> stream = std::make_shared<FileMetadataStream>(path, originalPath);
95 if (!stream->Open(OpenMode::ReadWrite)) {
96 IMAGE_LOGE("Failed to open the stream with file");
97 return nullptr;
98 }
99 return Create(stream, error);
100 }
101
Create(std::shared_ptr<MetadataStream> & stream,uint32_t & error)102 std::shared_ptr<MetadataAccessor> MetadataAccessorFactory::Create(std::shared_ptr<MetadataStream> &stream,
103 uint32_t &error)
104 {
105 EncodedFormat type = GetImageType(stream, error);
106
107 switch (type) {
108 case EncodedFormat::JPEG:
109 return std::make_shared<JpegExifMetadataAccessor>(stream);
110 case EncodedFormat::PNG:
111 return std::make_shared<PngExifMetadataAccessor>(stream);
112 case EncodedFormat::WEBP:
113 return std::make_shared<WebpExifMetadataAccessor>(stream);
114 case EncodedFormat::HEIF:
115 return std::make_shared<HeifExifMetadataAccessor>(stream);
116 case EncodedFormat::DNG:
117 return std::make_shared<DngExifMetadataAccessor>(stream);
118 default:
119 return nullptr;
120 }
121 }
122
GetImageType(std::shared_ptr<MetadataStream> & stream,uint32_t & error)123 EncodedFormat MetadataAccessorFactory::GetImageType(std::shared_ptr<MetadataStream> &stream, uint32_t &error)
124 {
125 byte buff[IMAGE_HEADER_SIZE] = {0};
126 auto byteSize = static_cast<uint32_t>(sizeof(byte));
127 stream->Seek(0, SeekPos::BEGIN);
128 auto ret = stream->Read(buff, IMAGE_HEADER_SIZE * byteSize);
129 stream->Seek(0, SeekPos::BEGIN);
130 if (ret == STREAM_READ_ERROR) {
131 IMAGE_LOGE("Failed to read image type from stream.");
132 if (stream->IsFileChanged()) {
133 error = ERR_MEDIA_MMAP_FILE_CHANGED;
134 }
135 return EncodedFormat::UNKNOWN;
136 }
137
138 if (memcmp(buff, jpegHeader, sizeof(jpegHeader) * byteSize) == 0) {
139 return EncodedFormat::JPEG;
140 }
141
142 if (memcmp(buff, pngHeader, sizeof(pngHeader) * byteSize) == 0) {
143 return EncodedFormat::PNG;
144 }
145
146 if (memcmp(buff, riffHeader, sizeof(riffHeader) * byteSize) == 0 &&
147 memcmp(buff + WEBP_HEADER_OFFSET, webpHeader, sizeof(webpHeader) * byteSize) == 0) {
148 return EncodedFormat::WEBP;
149 }
150
151 if (memcmp(buff + IMAGE_HEIF_HEADER_OFFSET, heifHeader, sizeof(heifHeader) * byteSize) == 0) {
152 return EncodedFormat::HEIF;
153 }
154
155 if ((memcmp(buff, DNG_LITTLE_ENDIAN_HEADER, sizeof(DNG_LITTLE_ENDIAN_HEADER) * byteSize) == 0) ||
156 (memcmp(buff, DNG_BIG_ENDIAN_HEADER, sizeof(DNG_BIG_ENDIAN_HEADER) * byteSize) == 0)) {
157 return EncodedFormat::DNG;
158 }
159
160 return EncodedFormat::UNKNOWN;
161 }
162 } // namespace Media
163 } // namespace OHOS
164