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