LMMS
Loading...
Searching...
No Matches
juce_GIFLoader.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce
27{
28
29#if (JUCE_MAC || JUCE_IOS) && USE_COREGRAPHICS_RENDERING && JUCE_USE_COREIMAGE_LOADER
30 Image juce_loadWithCoreImage (InputStream& input);
31#else
32
34
35//==============================================================================
37{
38public:
40 : input (in),
42 currentBit (0), lastBit (0), lastByteIndex (0),
43 codeSize (0), setCodeSize (0), maxCode (0), maxCodeSize (0),
44 firstcode (0), oldcode (0), clearCode (0), endCode (0)
45 {
46 int imageWidth, imageHeight;
47 if (! getSizeFromHeader (imageWidth, imageHeight))
48 return;
49
50 uint8 buf [16];
51 if (in.read (buf, 3) != 3)
52 return;
53
54 int numColours = 2 << (buf[0] & 7);
55 int transparent = -1;
56
57 if ((buf[0] & 0x80) != 0)
58 readPalette (numColours);
59
60 for (;;)
61 {
62 if (input.read (buf, 1) != 1 || buf[0] == ';')
63 break;
64
65 if (buf[0] == '!')
66 {
67 if (readExtension (transparent))
68 continue;
69
70 break;
71 }
72
73 if (buf[0] != ',')
74 continue;
75
76 if (input.read (buf, 9) == 9)
77 {
78 imageWidth = (int) ByteOrder::littleEndianShort (buf + 4);
79 imageHeight = (int) ByteOrder::littleEndianShort (buf + 6);
80
81 numColours = 2 << (buf[8] & 7);
82
83 if ((buf[8] & 0x80) != 0)
84 if (! readPalette (numColours))
85 break;
86
87 image = Image (transparent >= 0 ? Image::ARGB : Image::RGB,
88 imageWidth, imageHeight, transparent >= 0);
89
90 image.getProperties()->set ("originalImageHadAlpha", transparent >= 0);
91
92 readImage ((buf[8] & 0x40) != 0, transparent);
93 }
94
95 break;
96 }
97 }
98
100
101private:
111 enum { maxGifCode = 1 << 12 };
112 int table [2] [maxGifCode];
113 int stack [2 * maxGifCode];
114 int* sp;
115
116 bool getSizeFromHeader (int& w, int& h)
117 {
118 // Add an extra byte for the zero terminator
119 char b[7]{};
120
121 if (input.read (b, 6) == 6
122 && (strncmp ("GIF87a", b, 6) == 0
123 || strncmp ("GIF89a", b, 6) == 0))
124 {
125 if (input.read (b, 4) == 4)
126 {
129 return w > 0 && h > 0;
130 }
131 }
132
133 return false;
134 }
135
136 bool readPalette (const int numCols)
137 {
138 for (int i = 0; i < numCols; ++i)
139 {
140 uint8 rgb[4];
141 input.read (rgb, 3);
142
143 palette[i].setARGB (0xff, rgb[0], rgb[1], rgb[2]);
144 palette[i].premultiply();
145 }
146
147 return true;
148 }
149
150 int readDataBlock (uint8* const dest)
151 {
152 uint8 n;
153 if (input.read (&n, 1) == 1)
154 {
155 dataBlockIsZero = (n == 0);
156
157 if (dataBlockIsZero || (input.read (dest, n) == n))
158 return n;
159 }
160
161 return -1;
162 }
163
164 int readExtension (int& transparent)
165 {
166 uint8 type;
167 if (input.read (&type, 1) != 1)
168 return false;
169
170 uint8 b [260];
171 int n = 0;
172
173 if (type == 0xf9)
174 {
175 n = readDataBlock (b);
176 if (n < 0)
177 return 1;
178
179 if ((b[0] & 1) != 0)
180 transparent = b[3];
181 }
182
183 do
184 {
185 n = readDataBlock (b);
186 }
187 while (n > 0);
188
189 return n >= 0;
190 }
191
193 {
194 int i;
195 for (i = 0; i < clearCode; ++i)
196 {
197 table[0][i] = 0;
198 table[1][i] = i;
199 }
200
201 for (; i < maxGifCode; ++i)
202 {
203 table[0][i] = 0;
204 table[1][i] = 0;
205 }
206 }
207
208 void initialise (const int inputCodeSize)
209 {
210 setCodeSize = inputCodeSize;
211 codeSize = setCodeSize + 1;
212 clearCode = 1 << setCodeSize;
213 endCode = clearCode + 1;
215 maxCode = clearCode + 2;
216
217 getCode (0, true);
218
219 fresh = true;
220 clearTable();
221 sp = stack;
222 }
223
225 {
226 if (fresh)
227 {
228 fresh = false;
229
230 for (;;)
231 {
232 firstcode = oldcode = getCode (codeSize, false);
233
234 if (firstcode != clearCode)
235 return firstcode;
236 }
237 }
238
239 if (sp > stack)
240 return *--sp;
241
242 int code;
243
244 while ((code = getCode (codeSize, false)) >= 0)
245 {
246 if (code == clearCode)
247 {
248 clearTable();
249 codeSize = setCodeSize + 1;
251 maxCode = clearCode + 2;
252 sp = stack;
253 firstcode = oldcode = getCode (codeSize, false);
254 return firstcode;
255 }
256 else if (code == endCode)
257 {
258 if (dataBlockIsZero)
259 return -2;
260
261 uint8 buf [260];
262 int n;
263
264 while ((n = readDataBlock (buf)) > 0)
265 {}
266
267 if (n != 0)
268 return -2;
269 }
270
271 const int incode = code;
272
273 if (code >= maxCode)
274 {
275 *sp++ = firstcode;
276 code = oldcode;
277 }
278
279 while (code >= clearCode)
280 {
281 *sp++ = table[1][code];
282 if (code == table[0][code])
283 return -2;
284
285 code = table[0][code];
286 }
287
288 *sp++ = firstcode = table[1][code];
289
290 if ((code = maxCode) < maxGifCode)
291 {
292 table[0][code] = oldcode;
293 table[1][code] = firstcode;
294 ++maxCode;
295
297 {
298 maxCodeSize <<= 1;
299 ++codeSize;
300 }
301 }
302
303 oldcode = incode;
304
305 if (sp > stack)
306 return *--sp;
307 }
308
309 return code;
310 }
311
312 int getCode (const int codeSize_, const bool shouldInitialise)
313 {
314 if (shouldInitialise)
315 {
316 currentBit = 0;
317 lastBit = 0;
318 finished = false;
319 return 0;
320 }
321
322 if ((currentBit + codeSize_) >= lastBit)
323 {
324 if (finished)
325 return -1;
326
327 buffer[0] = buffer [lastByteIndex - 2];
328 buffer[1] = buffer [lastByteIndex - 1];
329
330 const int n = readDataBlock (buffer + 2);
331
332 if (n == 0)
333 finished = true;
334
335 lastByteIndex = 2 + n;
336 currentBit = (currentBit - lastBit) + 16;
337 lastBit = (2 + n) * 8 ;
338 }
339
340 int result = 0;
341 int i = currentBit;
342
343 for (int j = 0; j < codeSize_; ++j)
344 {
345 result |= ((buffer[i >> 3] & (1 << (i & 7))) != 0) << j;
346 ++i;
347 }
348
349 currentBit += codeSize_;
350 return result;
351 }
352
353 bool readImage (const int interlace, const int transparent)
354 {
355 uint8 c;
356 if (input.read (&c, 1) != 1)
357 return false;
358
359 initialise (c);
360
361 if (transparent >= 0)
362 palette [transparent].setARGB (0, 0, 0, 0);
363
364 int xpos = 0, ypos = 0, yStep = 8, pass = 0;
365
367 uint8* p = destData.getPixelPointer (0, 0);
368 const bool hasAlpha = image.hasAlphaChannel();
369
370 for (;;)
371 {
372 const int index = readLZWByte();
373 if (index < 0)
374 break;
375
376 if (hasAlpha)
377 ((PixelARGB*) p)->set (palette [index]);
378 else
379 ((PixelRGB*) p)->set (palette [index]);
380
381 p += destData.pixelStride;
382
383 if (++xpos == destData.width)
384 {
385 xpos = 0;
386
387 if (interlace)
388 {
389 ypos += yStep;
390
391 while (ypos >= destData.height)
392 {
393 switch (++pass)
394 {
395 case 1: ypos = 4; yStep = 8; break;
396 case 2: ypos = 2; yStep = 4; break;
397 case 3: ypos = 1; yStep = 2; break;
398 default: return true;
399 }
400 }
401 }
402 else
403 {
404 if (++ypos >= destData.height)
405 break;
406 }
407
408 p = destData.getPixelPointer (xpos, ypos);
409 }
410 }
411
412 return true;
413 }
414
416};
417
419
420#endif
421
422//==============================================================================
425
427bool GIFImageFormat::usesFileExtension (const File& f) { return f.hasFileExtension ("gif"); }
428
430{
431 char header [4];
432
433 return (in.read (header, sizeof (header)) == (int) sizeof (header))
434 && header[0] == 'G'
435 && header[1] == 'I'
436 && header[2] == 'F';
437}
438
440{
441 #if (JUCE_MAC || JUCE_IOS) && USE_COREGRAPHICS_RENDERING && JUCE_USE_COREIMAGE_LOADER
442 return juce_loadWithCoreImage (in);
443 #else
444 const std::unique_ptr<GIFLoader> loader (new GIFLoader (in));
445 return loader->image;
446 #endif
447}
448
449bool GIFImageFormat::writeImageToStream (const Image& /*sourceImage*/, OutputStream& /*destStream*/)
450{
451 jassertfalse; // writing isn't implemented for GIFs!
452 return false;
453}
454
455} // namespace juce
CAdPlugDatabase::CRecord::RecordType type
Definition adplugdb.cpp:93
static constexpr uint16 littleEndianShort(const void *bytes) noexcept
Definition juce_ByteOrder.h:202
Definition juce_File.h:45
GIFImageFormat()
Definition juce_GIFLoader.cpp:423
String getFormatName() override
Definition juce_GIFLoader.cpp:426
~GIFImageFormat() override
Definition juce_GIFLoader.cpp:424
bool usesFileExtension(const File &) override
Definition juce_GIFLoader.cpp:427
bool canUnderstand(InputStream &) override
Definition juce_GIFLoader.cpp:429
bool writeImageToStream(const Image &, OutputStream &) override
Definition juce_GIFLoader.cpp:449
Image decodeImage(InputStream &) override
Definition juce_GIFLoader.cpp:439
Definition juce_GIFLoader.cpp:37
int clearCode
Definition juce_GIFLoader.cpp:110
int setCodeSize
Definition juce_GIFLoader.cpp:107
int readExtension(int &transparent)
Definition juce_GIFLoader.cpp:164
bool dataBlockIsZero
Definition juce_GIFLoader.cpp:105
int codeSize
Definition juce_GIFLoader.cpp:107
int stack[2 *maxGifCode]
Definition juce_GIFLoader.cpp:113
int lastBit
Definition juce_GIFLoader.cpp:106
int readDataBlock(uint8 *const dest)
Definition juce_GIFLoader.cpp:150
bool readPalette(const int numCols)
Definition juce_GIFLoader.cpp:136
int * sp
Definition juce_GIFLoader.cpp:114
int table[2][maxGifCode]
Definition juce_GIFLoader.cpp:112
int readLZWByte()
Definition juce_GIFLoader.cpp:224
InputStream & input
Definition juce_GIFLoader.cpp:102
uint8 buffer[260]
Definition juce_GIFLoader.cpp:103
int maxCode
Definition juce_GIFLoader.cpp:108
bool getSizeFromHeader(int &w, int &h)
Definition juce_GIFLoader.cpp:116
int lastByteIndex
Definition juce_GIFLoader.cpp:106
int oldcode
Definition juce_GIFLoader.cpp:109
PixelARGB palette[256]
Definition juce_GIFLoader.cpp:104
bool fresh
Definition juce_GIFLoader.cpp:105
bool readImage(const int interlace, const int transparent)
Definition juce_GIFLoader.cpp:353
bool finished
Definition juce_GIFLoader.cpp:105
void initialise(const int inputCodeSize)
Definition juce_GIFLoader.cpp:208
int firstcode
Definition juce_GIFLoader.cpp:109
int getCode(const int codeSize_, const bool shouldInitialise)
Definition juce_GIFLoader.cpp:312
int endCode
Definition juce_GIFLoader.cpp:110
int currentBit
Definition juce_GIFLoader.cpp:106
Image image
Definition juce_GIFLoader.cpp:99
GIFLoader(InputStream &in)
Definition juce_GIFLoader.cpp:39
@ maxGifCode
Definition juce_GIFLoader.cpp:111
int maxCodeSize
Definition juce_GIFLoader.cpp:108
void clearTable()
Definition juce_GIFLoader.cpp:192
Definition juce_Image.h:310
int pixelStride
Definition juce_Image.h:355
int height
Definition juce_Image.h:356
@ writeOnly
Definition juce_Image.h:315
uint8 * getPixelPointer(int x, int y) const noexcept
Definition juce_Image.h:334
int width
Definition juce_Image.h:356
Definition juce_Image.h:58
@ ARGB
Definition juce_Image.h:67
@ RGB
Definition juce_Image.h:66
Definition juce_InputStream.h:37
Definition juce_OutputStream.h:38
Definition juce_PixelFormats.h:59
Definition juce_PixelFormats.h:354
Definition juce_String.h:53
UINT_D64 w
Definition inflate.c:942
register unsigned j
Definition inflate.c:1576
register unsigned i
Definition inflate.c:1575
unsigned f
Definition inflate.c:1572
#define JUCE_BEGIN_IGNORE_WARNINGS_MSVC(warnings)
Definition juce_CompilerWarnings.h:198
#define JUCE_END_IGNORE_WARNINGS_MSVC
Definition juce_CompilerWarnings.h:199
#define JUCE_DECLARE_NON_COPYABLE(className)
#define jassertfalse
float in
Definition lilv_test.c:1460
Definition carla_juce.cpp:31
unsigned char uint8
Definition juce_MathsFunctions.h:37
#define false
Definition ordinals.h:83
Definition inftrees.h:27
int n
Definition crypt.c:458
uch * p
Definition crypt.c:594
return c
Definition crypt.c:175
if(GLOBAL(newzip))
Definition crypt.c:475
uch h[RAND_HEAD_LEN]
Definition crypt.c:459
b
Definition crypt.c:628
int result
Definition process.c:1455
typedef int(UZ_EXP MsgFn)()