JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_PixelFormats.h
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//==============================================================================
30#if JUCE_MSVC
31 #pragma pack (push, 1)
32#endif
33
34class PixelRGB;
35class PixelAlpha;
36
37inline uint32 maskPixelComponents (uint32 x) noexcept
38{
39 return (x >> 8) & 0x00ff00ff;
40}
41
42inline uint32 clampPixelComponents (uint32 x) noexcept
43{
44 return (x | (0x01000100 - maskPixelComponents (x))) & 0x00ff00ff;
45}
46
47//==============================================================================
58class JUCE_API PixelARGB
59{
60public:
62 PixelARGB() noexcept = default;
63
64 PixelARGB (uint8 a, uint8 r, uint8 g, uint8 b) noexcept
65 {
66 components.b = b;
67 components.g = g;
68 components.r = r;
69 components.a = a;
70 }
71
72 //==============================================================================
74 forcedinline uint32 getNativeARGB() const noexcept { return internal; }
75
79 {
80 #if JUCE_ANDROID
81 return (uint32) ((components.a << 24) | (components.r << 16) | (components.g << 8) | (components.b << 0));
82 #else
83 return getNativeARGB();
84 #endif
85 }
86
89 inline uint32 getInARGBMemoryOrder() const noexcept
90 {
91 #if JUCE_BIG_ENDIAN
92 return getInARGBMaskOrder();
93 #else
94 return (uint32) ((components.b << 24) | (components.g << 16) | (components.r << 8) | components.a);
95 #endif
96 }
97
100 forcedinline uint32 getEvenBytes() const noexcept { return 0x00ff00ff & internal; }
101
104 forcedinline uint32 getOddBytes() const noexcept { return 0x00ff00ff & (internal >> 8); }
105
106 //==============================================================================
107 forcedinline uint8 getAlpha() const noexcept { return components.a; }
108 forcedinline uint8 getRed() const noexcept { return components.r; }
109 forcedinline uint8 getGreen() const noexcept { return components.g; }
110 forcedinline uint8 getBlue() const noexcept { return components.b; }
111
112 //==============================================================================
117 template <class Pixel>
118 forcedinline void set (const Pixel& src) noexcept
119 {
120 internal = src.getNativeARGB();
121 }
122
123 //==============================================================================
125 void setARGB (uint8 a, uint8 r, uint8 g, uint8 b) noexcept
126 {
127 components.b = b;
128 components.g = g;
129 components.r = r;
130 components.a = a;
131 }
132
133 //==============================================================================
139 template <class Pixel>
140 forcedinline void blend (const Pixel& src) noexcept
141 {
142 auto rb = src.getEvenBytes();
143 auto ag = src.getOddBytes();
144
145 const auto alpha = 0x100 - (ag >> 16);
146
147 rb += maskPixelComponents (getEvenBytes() * alpha);
148 ag += maskPixelComponents (getOddBytes() * alpha);
149
150 internal = clampPixelComponents (rb) | (clampPixelComponents (ag) << 8);
151 }
152
158 forcedinline void blend (PixelRGB src) noexcept;
159
160
166 template <class Pixel>
167 forcedinline void blend (const Pixel& src, uint32 extraAlpha) noexcept
168 {
169 auto rb = maskPixelComponents (extraAlpha * src.getEvenBytes());
170 auto ag = maskPixelComponents (extraAlpha * src.getOddBytes());
171
172 const auto alpha = 0x100 - (ag >> 16);
173
174 rb += maskPixelComponents (getEvenBytes() * alpha);
175 ag += maskPixelComponents (getOddBytes() * alpha);
176
177 internal = clampPixelComponents (rb) | (clampPixelComponents (ag) << 8);
178 }
179
183 template <class Pixel>
184 forcedinline void tween (const Pixel& src, uint32 amount) noexcept
185 {
186 auto dEvenBytes = getEvenBytes();
187 dEvenBytes += (((src.getEvenBytes() - dEvenBytes) * amount) >> 8);
188 dEvenBytes &= 0x00ff00ff;
189
190 auto dOddBytes = getOddBytes();
191 dOddBytes += (((src.getOddBytes() - dOddBytes) * amount) >> 8);
192 dOddBytes &= 0x00ff00ff;
193 dOddBytes <<= 8;
194
195 dOddBytes |= dEvenBytes;
196 internal = dOddBytes;
197 }
198
199 //==============================================================================
201 forcedinline void setAlpha (uint8 newAlpha) noexcept
202 {
203 components.a = newAlpha;
204 }
205
207 forcedinline void multiplyAlpha (int multiplier) noexcept
208 {
209 // increment alpha by 1, so that if multiplier == 255 (full alpha),
210 // this function will not change the values.
211 ++multiplier;
212
213 internal = ((((uint32) multiplier) * getOddBytes()) & 0xff00ff00)
214 | (((((uint32) multiplier) * getEvenBytes()) >> 8) & 0x00ff00ff);
215 }
216
217 forcedinline void multiplyAlpha (float multiplier) noexcept
218 {
219 multiplyAlpha ((int) (multiplier * 255.0f));
220 }
221
222
223 inline PixelARGB getUnpremultiplied() const noexcept
224 {
225 PixelARGB p (internal);
226 p.unpremultiply();
227 return p;
228 }
229
231 forcedinline void premultiply() noexcept
232 {
233 const auto alpha = components.a;
234
235 if (alpha < 0xff)
236 {
237 if (alpha == 0)
238 {
239 components.b = 0;
240 components.g = 0;
241 components.r = 0;
242 }
243 else
244 {
245 components.b = (uint8) ((components.b * alpha + 0x7f) >> 8);
246 components.g = (uint8) ((components.g * alpha + 0x7f) >> 8);
247 components.r = (uint8) ((components.r * alpha + 0x7f) >> 8);
248 }
249 }
250 }
251
254 {
255 const auto alpha = components.a;
256
257 if (alpha < 0xff)
258 {
259 if (alpha == 0)
260 {
261 components.b = 0;
262 components.g = 0;
263 components.r = 0;
264 }
265 else
266 {
267 components.b = (uint8) jmin ((uint32) 0xffu, (components.b * 0xffu) / alpha);
268 components.g = (uint8) jmin ((uint32) 0xffu, (components.g * 0xffu) / alpha);
269 components.r = (uint8) jmin ((uint32) 0xffu, (components.r * 0xffu) / alpha);
270 }
271 }
272 }
273
274 forcedinline void desaturate() noexcept
275 {
276 if (components.a < 0xff && components.a > 0)
277 {
278 const auto newUnpremultipliedLevel = (0xff * ((int) components.r + (int) components.g + (int) components.b) / (3 * components.a));
279
280 components.r = components.g = components.b
281 = (uint8) ((newUnpremultipliedLevel * components.a + 0x7f) >> 8);
282 }
283 else
284 {
285 components.r = components.g = components.b
286 = (uint8) (((int) components.r + (int) components.g + (int) components.b) / 3);
287 }
288 }
289
290 //==============================================================================
292 #if JUCE_ANDROID
293 #if JUCE_BIG_ENDIAN
294 enum { indexA = 0, indexR = 3, indexG = 2, indexB = 1 };
295 #else
296 enum { indexA = 3, indexR = 0, indexG = 1, indexB = 2 };
297 #endif
298 #else
299 #if JUCE_BIG_ENDIAN
300 enum { indexA = 0, indexR = 1, indexG = 2, indexB = 3 };
301 #else
302 enum { indexA = 3, indexR = 2, indexG = 1, indexB = 0 };
303 #endif
304 #endif
305
306private:
307 //==============================================================================
308 PixelARGB (uint32 internalValue) noexcept
309 : internal (internalValue)
310 {
311 }
312
313 //==============================================================================
314 struct Components
315 {
316 #if JUCE_ANDROID
317 #if JUCE_BIG_ENDIAN
318 uint8 a, b, g, r;
319 #else
320 uint8 r, g, b, a;
321 #endif
322 #else
323 #if JUCE_BIG_ENDIAN
324 uint8 a, r, g, b;
325 #else
326 uint8 b, g, r, a;
327 #endif
328 #endif
329 } JUCE_PACKED;
330
331 union
332 {
333 uint32 internal;
334 Components components;
335 };
336}
337#ifndef DOXYGEN
338 JUCE_PACKED
339#endif
340;
341
342
343//==============================================================================
353class JUCE_API PixelRGB
354{
355public:
357 PixelRGB() noexcept = default;
358
359 //==============================================================================
364 forcedinline uint32 getNativeARGB() const noexcept
365 {
366 #if JUCE_ANDROID
367 return (uint32) ((0xffu << 24) | r | ((uint32) g << 8) | ((uint32) b << 16));
368 #else
369 return (uint32) ((0xffu << 24) | b | ((uint32) g << 8) | ((uint32) r << 16));
370 #endif
371 }
372
376 {
377 #if JUCE_ANDROID
378 return (uint32) ((0xffu << 24) | b | ((uint32) g << 8) | ((uint32) r << 16));
379 #else
380 return getNativeARGB();
381 #endif
382 }
383
386 inline uint32 getInARGBMemoryOrder() const noexcept
387 {
388 #if JUCE_BIG_ENDIAN
389 return getInARGBMaskOrder();
390 #else
391 return (uint32) ((b << 24) | (g << 16) | (r << 8) | 0xff);
392 #endif
393 }
394
401 {
402 #if JUCE_ANDROID
403 return (uint32) (r | (b << 16));
404 #else
405 return (uint32) (b | (r << 16));
406 #endif
407 }
408
414 forcedinline uint32 getOddBytes() const noexcept { return (uint32) 0xff0000 | g; }
415
416 //==============================================================================
417 forcedinline uint8 getAlpha() const noexcept { return 0xff; }
418 forcedinline uint8 getRed() const noexcept { return r; }
419 forcedinline uint8 getGreen() const noexcept { return g; }
420 forcedinline uint8 getBlue() const noexcept { return b; }
421
422 //==============================================================================
429 template <class Pixel>
430 forcedinline void set (const Pixel& src) noexcept
431 {
432 b = src.getBlue();
433 g = src.getGreen();
434 r = src.getRed();
435 }
436
438 void setARGB (uint8, uint8 red, uint8 green, uint8 blue) noexcept
439 {
440 r = red;
441 g = green;
442 b = blue;
443 }
444
445 //==============================================================================
451 template <class Pixel>
452 forcedinline void blend (const Pixel& src) noexcept
453 {
454 const auto alpha = (uint32) (0x100 - src.getAlpha());
455
456 // getEvenBytes returns 0x00rr00bb on non-android
457 const auto rb = clampPixelComponents (src.getEvenBytes() + maskPixelComponents (getEvenBytes() * alpha));
458 // getOddBytes returns 0x00aa00gg on non-android
459 const auto ag = clampPixelComponents (src.getOddBytes() + ((g * alpha) >> 8));
460
461 g = (uint8) (ag & 0xff);
462
463 #if JUCE_ANDROID
464 b = (uint8) (rb >> 16);
465 r = (uint8) (rb & 0xff);
466 #else
467 r = (uint8) (rb >> 16);
468 b = (uint8) (rb & 0xff);
469 #endif
470 }
471
472 forcedinline void blend (PixelRGB src) noexcept
473 {
474 set (src);
475 }
476
482 template <class Pixel>
483 forcedinline void blend (const Pixel& src, uint32 extraAlpha) noexcept
484 {
485 auto ag = maskPixelComponents (extraAlpha * src.getOddBytes());
486 auto rb = maskPixelComponents (extraAlpha * src.getEvenBytes());
487
488 const auto alpha = 0x100 - (ag >> 16);
489
490 ag = clampPixelComponents (ag + (g * alpha >> 8));
491 rb = clampPixelComponents (rb + maskPixelComponents (getEvenBytes() * alpha));
492
493 g = (uint8) (ag & 0xff);
494
495 #if JUCE_ANDROID
496 b = (uint8) (rb >> 16);
497 r = (uint8) (rb & 0xff);
498 #else
499 r = (uint8) (rb >> 16);
500 b = (uint8) (rb & 0xff);
501 #endif
502 }
503
507 template <class Pixel>
508 forcedinline void tween (const Pixel& src, uint32 amount) noexcept
509 {
510 auto dEvenBytes = getEvenBytes();
511 dEvenBytes += (((src.getEvenBytes() - dEvenBytes) * amount) >> 8);
512
513 auto dOddBytes = getOddBytes();
514 dOddBytes += (((src.getOddBytes() - dOddBytes) * amount) >> 8);
515
516 g = (uint8) (dOddBytes & 0xff); // dOddBytes = 0x00aa00gg
517
518 #if JUCE_ANDROID
519 r = (uint8) (dEvenBytes & 0xff); // dEvenBytes = 0x00bb00rr
520 b = (uint8) (dEvenBytes >> 16);
521 #else
522 b = (uint8) (dEvenBytes & 0xff); // dEvenBytes = 0x00rr00bb
523 r = (uint8) (dEvenBytes >> 16);
524 #endif
525 }
526
527 //==============================================================================
529 forcedinline void setAlpha (uint8) noexcept {}
530
532 forcedinline void multiplyAlpha (int) noexcept {}
533
535 forcedinline void multiplyAlpha (float) noexcept {}
536
538 forcedinline void premultiply() noexcept {}
539
541 forcedinline void unpremultiply() noexcept {}
542
543 forcedinline void desaturate() noexcept
544 {
545 r = g = b = (uint8) (((int) r + (int) g + (int) b) / 3);
546 }
547
548 //==============================================================================
550 #if JUCE_MAC
551 enum { indexR = 0, indexG = 1, indexB = 2 };
552 #else
553 enum { indexR = 2, indexG = 1, indexB = 0 };
554 #endif
555
556private:
557 //==============================================================================
558 PixelRGB (uint32 internal) noexcept
559 {
560 #if JUCE_ANDROID
561 b = (uint8) (internal >> 16);
562 g = (uint8) (internal >> 8);
563 r = (uint8) (internal);
564 #else
565 r = (uint8) (internal >> 16);
566 g = (uint8) (internal >> 8);
567 b = (uint8) (internal);
568 #endif
569 }
570
571 //==============================================================================
572 #if JUCE_MAC
573 uint8 r, g, b;
574 #else
575 uint8 b, g, r;
576 #endif
577
578}
579#ifndef DOXYGEN
580 JUCE_PACKED
581#endif
582;
583
585{
586 set (src);
587}
588
589//==============================================================================
599class JUCE_API PixelAlpha
600{
601public:
603 PixelAlpha() noexcept = default;
604
605 //==============================================================================
610 forcedinline uint32 getNativeARGB() const noexcept { return (uint32) ((a << 24) | (a << 16) | (a << 8) | a); }
611
614 forcedinline uint32 getInARGBMaskOrder() const noexcept { return getNativeARGB(); }
615
618 inline uint32 getInARGBMemoryOrder() const noexcept { return getNativeARGB(); }
619
625 forcedinline uint32 getEvenBytes() const noexcept { return (uint32) ((a << 16) | a); }
626
632 forcedinline uint32 getOddBytes() const noexcept { return (uint32) ((a << 16) | a); }
633
634 //==============================================================================
635 forcedinline uint8 getAlpha() const noexcept { return a; }
636 forcedinline uint8 getRed() const noexcept { return 0; }
637 forcedinline uint8 getGreen() const noexcept { return 0; }
638 forcedinline uint8 getBlue() const noexcept { return 0; }
639
640 //==============================================================================
645 template <class Pixel>
646 forcedinline void set (const Pixel& src) noexcept
647 {
648 a = src.getAlpha();
649 }
650
653 {
654 a = a_;
655 }
656
657 //==============================================================================
663 template <class Pixel>
664 forcedinline void blend (const Pixel& src) noexcept
665 {
666 const auto srcA = src.getAlpha();
667 a = (uint8) ((a * (0x100 - srcA) >> 8) + srcA);
668 }
669
675 template <class Pixel>
676 forcedinline void blend (const Pixel& src, uint32 extraAlpha) noexcept
677 {
678 ++extraAlpha;
679 const auto srcAlpha = (int) ((extraAlpha * src.getAlpha()) >> 8);
680 a = (uint8) ((a * (0x100 - srcAlpha) >> 8) + srcAlpha);
681 }
682
686 template <class Pixel>
687 forcedinline void tween (const Pixel& src, uint32 amount) noexcept
688 {
689 a += ((src.getAlpha() - a) * amount) >> 8;
690 }
691
692 //==============================================================================
694 forcedinline void setAlpha (uint8 newAlpha) noexcept
695 {
696 a = newAlpha;
697 }
698
700 forcedinline void multiplyAlpha (int multiplier) noexcept
701 {
702 ++multiplier;
703 a = (uint8) ((a * multiplier) >> 8);
704 }
705
706 forcedinline void multiplyAlpha (float multiplier) noexcept
707 {
708 a = (uint8) (a * multiplier);
709 }
710
712 forcedinline void premultiply() noexcept {}
713
715 forcedinline void unpremultiply() noexcept {}
716
717 forcedinline void desaturate() noexcept {}
718
719 //==============================================================================
721 enum { indexA = 0 };
722
723private:
724 //==============================================================================
725 PixelAlpha (uint32 internal) noexcept
726 : a ((uint8) (internal >> 24)) { }
727
728 //==============================================================================
729 uint8 a;
730}
731#ifndef DOXYGEN
732 JUCE_PACKED
733#endif
734;
735
736#if JUCE_MSVC
737 #pragma pack (pop)
738#endif
739
740} // namespace juce
Represents a 32-bit INTERNAL pixel with premultiplied alpha, and can perform compositing operations w...
forcedinline void tween(const Pixel &src, uint32 amount) noexcept
Blends another pixel with this one, creating a colour that is somewhere between the two,...
forcedinline void set(const Pixel &src) noexcept
Copies another pixel colour over this one.
PixelARGB() noexcept=default
Creates a pixel without defining its colour.
uint32 getInARGBMemoryOrder() const noexcept
Returns a uint32 which when written to memory, will be in the order a, r, g, b.
forcedinline uint32 getNativeARGB() const noexcept
Returns a uint32 which represents the pixel in a platform dependent format.
forcedinline void setAlpha(uint8 newAlpha) noexcept
Replaces the colour's alpha value with another one.
forcedinline void blend(const Pixel &src) noexcept
Blends another pixel onto this one.
forcedinline void unpremultiply() noexcept
Unpremultiplies the pixel's RGB values.
forcedinline uint32 getInARGBMaskOrder() const noexcept
Returns a uint32 which will be in argb order as if constructed with the following mask operation ((al...
forcedinline void blend(const Pixel &src, uint32 extraAlpha) noexcept
Blends another pixel onto this one, applying an extra multiplier to its opacity.
void setARGB(uint8 a, uint8 r, uint8 g, uint8 b) noexcept
Sets the pixel's colour from individual components.
forcedinline void premultiply() noexcept
Premultiplies the pixel's RGB values by its alpha.
forcedinline uint32 getEvenBytes() const noexcept
Return channels with an even index and insert zero bytes between them.
forcedinline void multiplyAlpha(int multiplier) noexcept
Multiplies the colour's alpha value with another one.
forcedinline uint32 getOddBytes() const noexcept
Return channels with an odd index and insert zero bytes between them.
Represents an 8-bit single-channel pixel, and can perform compositing operations on it.
forcedinline void setARGB(uint8 a_, uint8, uint8, uint8) noexcept
Sets the pixel's colour from individual components.
uint32 getInARGBMemoryOrder() const noexcept
Returns a uint32 which when written to memory, will be in the order a, r, g, b.
forcedinline void tween(const Pixel &src, uint32 amount) noexcept
Blends another pixel with this one, creating a colour that is somewhere between the two,...
forcedinline void multiplyAlpha(int multiplier) noexcept
Multiplies the colour's alpha value with another one.
forcedinline uint32 getEvenBytes() const noexcept
Return channels with an even index and insert zero bytes between them.
forcedinline void setAlpha(uint8 newAlpha) noexcept
Replaces the colour's alpha value with another one.
forcedinline void premultiply() noexcept
Premultiplies the pixel's RGB values by its alpha.
forcedinline void blend(const Pixel &src) noexcept
Blends another pixel onto this one.
forcedinline uint32 getInARGBMaskOrder() const noexcept
Returns a uint32 which will be in argb order as if constructed with the following mask operation ((al...
forcedinline void set(const Pixel &src) noexcept
Copies another pixel colour over this one.
forcedinline uint32 getOddBytes() const noexcept
Return channels with an odd index and insert zero bytes between them.
forcedinline void unpremultiply() noexcept
Unpremultiplies the pixel's RGB values.
PixelAlpha() noexcept=default
Creates a pixel without defining its colour.
forcedinline void blend(const Pixel &src, uint32 extraAlpha) noexcept
Blends another pixel onto this one, applying an extra multiplier to its opacity.
Represents a 24-bit RGB pixel, and can perform compositing operations on it.
forcedinline void premultiply() noexcept
Premultiplies the pixel's RGB values by its alpha.
forcedinline void setAlpha(uint8) noexcept
This method is included for compatibility with the PixelARGB class.
forcedinline uint32 getInARGBMaskOrder() const noexcept
Returns a uint32 which will be in argb order as if constructed with the following mask operation ((al...
forcedinline uint32 getOddBytes() const noexcept
Return channels with an odd index and insert zero bytes between them.
void setARGB(uint8, uint8 red, uint8 green, uint8 blue) noexcept
Sets the pixel's colour from individual components.
forcedinline void set(const Pixel &src) noexcept
Copies another pixel colour over this one.
forcedinline void blend(const Pixel &src, uint32 extraAlpha) noexcept
Blends another pixel onto this one, applying an extra multiplier to its opacity.
forcedinline void blend(const Pixel &src) noexcept
Blends another pixel onto this one.
forcedinline void multiplyAlpha(int) noexcept
Multiplies the colour's alpha value with another one.
uint32 getInARGBMemoryOrder() const noexcept
Returns a uint32 which when written to memory, will be in the order a, r, g, b.
forcedinline uint32 getEvenBytes() const noexcept
Return channels with an even index and insert zero bytes between them.
forcedinline void tween(const Pixel &src, uint32 amount) noexcept
Blends another pixel with this one, creating a colour that is somewhere between the two,...
PixelRGB() noexcept=default
Creates a pixel without defining its colour.
forcedinline void unpremultiply() noexcept
Unpremultiplies the pixel's RGB values.
forcedinline void multiplyAlpha(float) noexcept
Multiplies the colour's alpha value with another one.
#define forcedinline
A platform-independent way of forcing an inline function.
T internal(T... args)
typedef int
JUCE Namespace.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
unsigned int uint32
A platform-independent 32-bit unsigned integer type.
unsigned char uint8
A platform-independent 8-bit unsigned integer type.