Line data Source code
1 : /**
2 : Copyright (c) 2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef STAPPLER_BITMAP_SPBITMAPFORMAT_H_
25 : #define STAPPLER_BITMAP_SPBITMAPFORMAT_H_
26 :
27 : #include "SPIO.h"
28 : #include "SPBytesView.h"
29 :
30 : namespace STAPPLER_VERSIONIZED stappler::bitmap {
31 :
32 : class BitmapFormat;
33 :
34 : enum class FileFormat {
35 : Png,
36 : Jpeg,
37 : WebpLossless,
38 : WebpLossy,
39 : Svg,
40 : Gif,
41 : Tiff,
42 : Custom
43 : };
44 :
45 : enum class AlphaFormat {
46 : Premultiplied,
47 : Unpremultiplied,
48 : Opaque,
49 : };
50 :
51 : enum class PixelFormat {
52 : Auto, // used by application, do not use with Bitmap directly
53 : A8,
54 : I8,
55 : IA88,
56 : RGB888,
57 : RGBA8888,
58 : };
59 :
60 : struct ImageInfo {
61 : PixelFormat color = PixelFormat::Auto;
62 : AlphaFormat alpha = AlphaFormat::Premultiplied;
63 : uint32_t width = 0;
64 : uint32_t height = 0;
65 : uint32_t stride = 0;
66 :
67 : const BitmapFormat *format = nullptr;
68 : };
69 :
70 : using StrideFn = Callback<uint32_t(PixelFormat, uint32_t)>;
71 :
72 : bool getImageSize(StringView file, uint32_t &width, uint32_t &height);
73 : bool getImageSize(const io::Producer &file, uint32_t &width, uint32_t &height);
74 :
75 : bool getImageInfo(BytesView, ImageInfo &);
76 :
77 : bool isImage(StringView file, bool readable = true);
78 : bool isImage(const io::Producer &file, bool readable = true);
79 : bool isImage(const uint8_t * data, size_t dataLen, bool readable = true);
80 :
81 : Pair<FileFormat, StringView> detectFormat(StringView file);
82 : Pair<FileFormat, StringView> detectFormat(const io::Producer &file);
83 : Pair<FileFormat, StringView> detectFormat(const uint8_t * data, size_t dataLen);
84 :
85 : StringView getMimeType(FileFormat);
86 : StringView getMimeType(StringView);
87 :
88 : bool check(FileFormat, const uint8_t * data, size_t dataLen);
89 : bool check(StringView, const uint8_t * data, size_t dataLen);
90 :
91 7337 : inline uint8_t getBytesPerPixel(PixelFormat c) {
92 7337 : switch (c) {
93 578 : case PixelFormat::A8: return 1; break;
94 494 : case PixelFormat::I8: return 1; break;
95 753 : case PixelFormat::IA88: return 2; break;
96 3903 : case PixelFormat::RGB888: return 3; break;
97 1584 : case PixelFormat::RGBA8888: return 4; break;
98 25 : case PixelFormat::Auto: return 0; break;
99 : }
100 0 : return 0;
101 : }
102 :
103 : template<PixelFormat Source, PixelFormat Target>
104 : void convertLine(const uint8_t *in, uint8_t *out, uint32_t ins, uint32_t outs);
105 :
106 : template<PixelFormat Source, PixelFormat Target>
107 1213 : bool convertData(BytesView dataVec, BytesView out, uint32_t inStride, uint32_t outStride) {
108 1213 : auto dataLen = dataVec.size();
109 1213 : auto height = dataLen / inStride;
110 1213 : auto data = dataVec.data();
111 : // out.resize(height * outStride);
112 1213 : auto outData = (uint8_t *)out.data();
113 366326 : for (size_t j = 0; j < height; j ++) {
114 365113 : convertLine<Source, Target>(data + inStride * j, outData + outStride * j, inStride, outStride);
115 : }
116 1213 : return true;
117 : }
118 :
119 : struct BitmapWriter : ImageInfo {
120 : void *target;
121 :
122 : uint32_t (*getStride) (void *, PixelFormat, uint32_t);
123 :
124 : void (*push) (void *, const uint8_t *, uint32_t);
125 : void (*resize) (void *, uint32_t size);
126 : uint8_t * (*getData) (void *, uint32_t location);
127 : void (*assign) (void *, const uint8_t *, uint32_t);
128 : void (*clear) (void *);
129 : };
130 :
131 : class BitmapFormat {
132 : public:
133 : enum Flags {
134 : None = 0,
135 : Recognizable = 1 << 0,
136 : Readable = 1 << 1,
137 : Writable = 1 << 2,
138 : };
139 :
140 : using check_fn = bool (*) (const uint8_t * data, size_t dataLen);
141 : using size_fn = bool (*) (const io::Producer &file, StackBuffer<512> &, uint32_t &width, uint32_t &height);
142 : using info_fn = bool (*) (const uint8_t *data, size_t size, ImageInfo &);
143 : using load_fn = bool (*) (const uint8_t *data, size_t size, BitmapWriter &);
144 : using write_fn = bool (*) (const uint8_t *data, BitmapWriter &, bool invert);
145 : using save_fn = bool (*) (StringView, const uint8_t *data, BitmapWriter &, bool invert);
146 :
147 : static void add(BitmapFormat &&);
148 :
149 : BitmapFormat(FileFormat, const check_fn&, const size_fn &, const info_fn & = nullptr,
150 : const load_fn & = nullptr, const write_fn & = nullptr, const save_fn & = nullptr);
151 :
152 : BitmapFormat(StringView name, StringView mime, const check_fn&, const size_fn &, const info_fn & = nullptr,
153 : const load_fn & = nullptr, const write_fn & = nullptr, const save_fn & = nullptr);
154 :
155 5577 : StringView getName() const { return _name; }
156 700 : StringView getMime() const { return _mime; }
157 :
158 : bool isRecognizable() const;
159 : bool isReadable() const;
160 : bool isWritable() const;
161 :
162 : Flags getFlags() const { return _flags; }
163 1500 : FileFormat getFormat() const { return _format; }
164 :
165 : bool is(const uint8_t * data, size_t dataLen) const;
166 : bool getSize(const io::Producer &file, StackBuffer<512> &, uint32_t &width, uint32_t &height) const;
167 :
168 : bool getInfo(const uint8_t *data, size_t size, ImageInfo &) const;
169 :
170 : bool load(const uint8_t *data, size_t size, BitmapWriter &) const;
171 :
172 : bool write(const uint8_t *data, BitmapWriter &, bool invert) const;
173 :
174 : bool save(StringView, const uint8_t *data, BitmapWriter &, bool invert) const;
175 :
176 1400 : check_fn getCheckFn() const { return check_ptr; }
177 400 : size_fn getSizeFn() const { return size_ptr; }
178 350 : info_fn getInfoFn() const { return info_ptr; }
179 350 : load_fn getLoadFn() const { return load_ptr; }
180 400 : write_fn getWriteFn() const { return write_ptr; }
181 400 : save_fn getSaveFn() const { return save_ptr; }
182 :
183 : protected:
184 : check_fn check_ptr = nullptr;
185 : size_fn size_ptr = nullptr;
186 : info_fn info_ptr = nullptr;
187 : load_fn load_ptr = nullptr;
188 : write_fn write_ptr = nullptr;
189 : save_fn save_ptr = nullptr;
190 :
191 : Flags _flags = None;
192 : FileFormat _format = FileFormat::Custom;
193 : StringView _name;
194 : StringView _mime;
195 : };
196 :
197 : SP_DEFINE_ENUM_AS_MASK(BitmapFormat::Flags)
198 :
199 : }
200 :
201 : #endif /* STAPPLER_BITMAP_SPBITMAPFORMAT_H_ */
|