/src/exiv2/src/gifimage.cpp
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | |
3 | | // included header files |
4 | | #include "gifimage.hpp" |
5 | | #include "basicio.hpp" |
6 | | #include "config.h" |
7 | | #include "error.hpp" |
8 | | #include "futils.hpp" |
9 | | |
10 | | #include <array> |
11 | | |
12 | | #ifdef EXIV2_DEBUG_MESSAGES |
13 | | #include <iostream> |
14 | | #endif |
15 | | |
16 | | // ***************************************************************************** |
17 | | // class member definitions |
18 | | namespace Exiv2 { |
19 | 50 | GifImage::GifImage(BasicIo::UniquePtr io) : Image(ImageType::gif, mdNone, std::move(io)) { |
20 | 50 | } |
21 | | |
22 | 0 | std::string GifImage::mimeType() const { |
23 | 0 | return "image/gif"; |
24 | 0 | } |
25 | | |
26 | 0 | void GifImage::setExifData(const ExifData& /*exifData*/) { |
27 | | // Todo: implement me! |
28 | 0 | throw(Error(ErrorCode::kerInvalidSettingForImage, "Exif metadata", "GIF")); |
29 | 0 | } |
30 | | |
31 | 0 | void GifImage::setIptcData(const IptcData& /*iptcData*/) { |
32 | | // Todo: implement me! |
33 | 0 | throw(Error(ErrorCode::kerInvalidSettingForImage, "IPTC metadata", "GIF")); |
34 | 0 | } |
35 | | |
36 | 0 | void GifImage::setComment(const std::string&) { |
37 | | // not supported |
38 | 0 | throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "GIF")); |
39 | 0 | } |
40 | | |
41 | 44 | void GifImage::readMetadata() { |
42 | | #ifdef EXIV2_DEBUG_MESSAGES |
43 | | std::cerr << "Exiv2::GifImage::readMetadata: Reading GIF file " << io_->path() << "\n"; |
44 | | #endif |
45 | 44 | if (io_->open() != 0) { |
46 | 0 | throw Error(ErrorCode::kerDataSourceOpenFailed, io_->path(), strError()); |
47 | 0 | } |
48 | 44 | IoCloser closer(*io_); |
49 | | // Ensure that this is the correct image type |
50 | 44 | if (!isGifType(*io_, true)) { |
51 | 0 | if (io_->error() || io_->eof()) |
52 | 0 | throw Error(ErrorCode::kerFailedToReadImageData); |
53 | 0 | throw Error(ErrorCode::kerNotAnImage, "GIF"); |
54 | 0 | } |
55 | 44 | clearMetadata(); |
56 | | |
57 | 44 | byte buf[4]; |
58 | 44 | if (io_->read(buf, sizeof(buf)) == sizeof(buf)) { |
59 | 44 | pixelWidth_ = getShort(buf, littleEndian); |
60 | 44 | pixelHeight_ = getShort(buf + 2, littleEndian); |
61 | 44 | } |
62 | 44 | } // GifImage::readMetadata |
63 | | |
64 | 2 | void GifImage::writeMetadata() { |
65 | | // Todo: implement me! |
66 | 2 | throw(Error(ErrorCode::kerWritingImageFormatUnsupported, "GIF")); |
67 | 2 | } // GifImage::writeMetadata |
68 | | |
69 | | // ************************************************************************* |
70 | | // free functions |
71 | 50 | Image::UniquePtr newGifInstance(BasicIo::UniquePtr io, bool /*create*/) { |
72 | 50 | auto image = std::make_unique<GifImage>(std::move(io)); |
73 | 50 | if (!image->good()) { |
74 | 6 | return nullptr; |
75 | 6 | } |
76 | 44 | return image; |
77 | 50 | } |
78 | | |
79 | 14.2k | bool isGifType(BasicIo& iIo, bool advance) { |
80 | 14.2k | const int32_t len = 6; |
81 | 14.2k | const std::array<byte, len> Gif87aId{'G', 'I', 'F', '8', '7', 'a'}; |
82 | 14.2k | const std::array<byte, len> Gif89aId{'G', 'I', 'F', '8', '9', 'a'}; |
83 | 14.2k | std::array<byte, len> buf; |
84 | 14.2k | iIo.read(buf.data(), len); |
85 | 14.2k | if (iIo.error() || iIo.eof()) { |
86 | 401 | return false; |
87 | 401 | } |
88 | 13.8k | bool matched = buf == Gif87aId || buf == Gif89aId; |
89 | 13.8k | if (!advance || !matched) { |
90 | 13.7k | iIo.seek(-len, BasicIo::cur); |
91 | 13.7k | } |
92 | 13.8k | return matched; |
93 | 14.2k | } |
94 | | } // namespace Exiv2 |