VST3: fetch midi mappings all at once, use it for note/sound-off
[carla.git] / source / modules / juce_graphics / image_formats / juce_JPEGLoader.cpp
blob00f0251dd67c4572366ac5ab0fa54a4f928e4d46
1 /*
2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
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.
23 ==============================================================================
26 namespace juce
29 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4365 6240 6326 6386 6385 28182 28183 6387 6011 6001)
31 namespace jpeglibNamespace
33 #if JUCE_INCLUDE_JPEGLIB_CODE || ! defined (JUCE_INCLUDE_JPEGLIB_CODE)
34 #if JUCE_MINGW
35 typedef unsigned char boolean;
36 #endif
38 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wconversion",
39 "-Wdeprecated-register",
40 "-Wdeprecated-declarations",
41 "-Wsign-conversion",
42 "-Wcast-align",
43 "-Wswitch-enum",
44 "-Wswitch-default",
45 "-Wimplicit-fallthrough",
46 "-Wzero-as-null-pointer-constant",
47 "-Wshift-negative-value",
48 "-Wcomma")
50 #define JPEG_INTERNALS
51 #undef FAR
52 #include "jpglib/jpeglib.h"
54 #include "jpglib/jcapimin.c"
55 #include "jpglib/jcapistd.c"
56 #include "jpglib/jccoefct.c"
57 #include "jpglib/jccolor.c"
58 #undef FIX
59 #include "jpglib/jcdctmgr.c"
60 #undef CONST_BITS
61 #include "jpglib/jchuff.c"
62 #undef emit_byte
63 #include "jpglib/jcinit.c"
64 #include "jpglib/jcmainct.c"
65 #include "jpglib/jcmarker.c"
66 #include "jpglib/jcmaster.c"
67 #include "jpglib/jcomapi.c"
68 #include "jpglib/jcparam.c"
69 #include "jpglib/jcphuff.c"
70 #include "jpglib/jcprepct.c"
71 #include "jpglib/jcsample.c"
72 #include "jpglib/jctrans.c"
73 #include "jpglib/jdapistd.c"
74 #include "jpglib/jdapimin.c"
75 #include "jpglib/jdatasrc.c"
76 #include "jpglib/jdcoefct.c"
77 #undef FIX
78 #include "jpglib/jdcolor.c"
79 #undef FIX
80 #include "jpglib/jddctmgr.c"
81 #undef CONST_BITS
82 #undef ASSIGN_STATE
83 #include "jpglib/jdhuff.c"
84 #include "jpglib/jdinput.c"
85 #include "jpglib/jdmainct.c"
86 #include "jpglib/jdmarker.c"
87 #include "jpglib/jdmaster.c"
88 #undef FIX
89 #include "jpglib/jdmerge.c"
90 #undef ASSIGN_STATE
91 #include "jpglib/jdphuff.c"
92 #include "jpglib/jdpostct.c"
93 #undef FIX
94 #include "jpglib/jdsample.c"
95 #include "jpglib/jdtrans.c"
96 #include "jpglib/jfdctflt.c"
97 #include "jpglib/jfdctint.c"
98 #undef CONST_BITS
99 #undef MULTIPLY
100 #undef FIX_0_541196100
101 #include "jpglib/jfdctfst.c"
102 #undef FIX_0_541196100
103 #include "jpglib/jidctflt.c"
104 #undef CONST_BITS
105 #undef FIX_1_847759065
106 #undef MULTIPLY
107 #undef DEQUANTIZE
108 #undef DESCALE
109 #include "jpglib/jidctfst.c"
110 #undef CONST_BITS
111 #undef FIX_1_847759065
112 #undef MULTIPLY
113 #undef DEQUANTIZE
114 #include "jpglib/jidctint.c"
115 #include "jpglib/jidctred.c"
116 #include "jpglib/jmemmgr.c"
117 #include "jpglib/jmemnobs.c"
118 #include "jpglib/jquant1.c"
119 #include "jpglib/jquant2.c"
120 #include "jpglib/jutils.c"
121 #include "jpglib/transupp.c"
123 JUCE_END_IGNORE_WARNINGS_GCC_LIKE
124 #else
125 #define JPEG_INTERNALS
126 #undef FAR
127 #include <jpeglib.h>
128 #endif
131 #undef max
132 #undef min
134 JUCE_END_IGNORE_WARNINGS_MSVC
136 //==============================================================================
137 namespace JPEGHelpers
139 using namespace jpeglibNamespace;
141 #if ! (JUCE_WINDOWS && (JUCE_MSVC || JUCE_CLANG))
142 using jpeglibNamespace::boolean;
143 #endif
145 static void fatalErrorHandler (j_common_ptr p) { *((bool*) (p->client_data)) = true; }
146 static void silentErrorCallback1 (j_common_ptr) {}
147 static void silentErrorCallback2 (j_common_ptr, int) {}
148 static void silentErrorCallback3 (j_common_ptr, char*) {}
150 static void setupSilentErrorHandler (struct jpeg_error_mgr& err)
152 zerostruct (err);
154 err.error_exit = fatalErrorHandler;
155 err.emit_message = silentErrorCallback2;
156 err.output_message = silentErrorCallback1;
157 err.format_message = silentErrorCallback3;
158 err.reset_error_mgr = silentErrorCallback1;
161 //==============================================================================
162 #if ! JUCE_USING_COREIMAGE_LOADER
163 static void dummyCallback1 (j_decompress_ptr) {}
165 static void jpegSkip (j_decompress_ptr decompStruct, long num)
167 decompStruct->src->next_input_byte += num;
169 num = jmin (num, (long) decompStruct->src->bytes_in_buffer);
170 decompStruct->src->bytes_in_buffer -= (size_t) num;
173 static boolean jpegFill (j_decompress_ptr)
175 return 0;
177 #endif
179 //==============================================================================
180 const int jpegBufferSize = 512;
182 struct JuceJpegDest : public jpeg_destination_mgr
184 OutputStream* output;
185 char* buffer;
188 static void jpegWriteInit (j_compress_ptr) {}
190 static void jpegWriteTerminate (j_compress_ptr cinfo)
192 JuceJpegDest* const dest = static_cast<JuceJpegDest*> (cinfo->dest);
194 const size_t numToWrite = jpegBufferSize - dest->free_in_buffer;
195 dest->output->write (dest->buffer, numToWrite);
198 static boolean jpegWriteFlush (j_compress_ptr cinfo)
200 JuceJpegDest* const dest = static_cast<JuceJpegDest*> (cinfo->dest);
202 const int numToWrite = jpegBufferSize;
204 dest->next_output_byte = reinterpret_cast<JOCTET*> (dest->buffer);
205 dest->free_in_buffer = jpegBufferSize;
207 return (boolean) dest->output->write (dest->buffer, (size_t) numToWrite);
211 //==============================================================================
212 JPEGImageFormat::JPEGImageFormat()
213 : quality (-1.0f)
217 JPEGImageFormat::~JPEGImageFormat() {}
219 void JPEGImageFormat::setQuality (const float newQuality)
221 quality = newQuality;
224 String JPEGImageFormat::getFormatName() { return "JPEG"; }
225 bool JPEGImageFormat::usesFileExtension (const File& f) { return f.hasFileExtension ("jpeg;jpg"); }
227 bool JPEGImageFormat::canUnderstand (InputStream& in)
229 const int bytesNeeded = 24;
230 uint8 header [bytesNeeded];
232 if (in.read (header, bytesNeeded) == bytesNeeded
233 && header[0] == 0xff
234 && header[1] == 0xd8
235 && header[2] == 0xff)
236 return true;
238 #if JUCE_USING_COREIMAGE_LOADER
239 return header[20] == 'j'
240 && header[21] == 'p'
241 && header[22] == '2'
242 && header[23] == ' ';
243 #endif
245 return false;
248 #if JUCE_USING_COREIMAGE_LOADER
249 Image juce_loadWithCoreImage (InputStream& input);
250 #endif
252 Image JPEGImageFormat::decodeImage (InputStream& in)
254 #if JUCE_USING_COREIMAGE_LOADER
255 return juce_loadWithCoreImage (in);
256 #else
257 using namespace jpeglibNamespace;
258 using namespace JPEGHelpers;
260 MemoryOutputStream mb;
261 mb << in;
263 Image image;
265 if (mb.getDataSize() > 16)
267 struct jpeg_decompress_struct jpegDecompStruct;
269 struct jpeg_error_mgr jerr;
270 setupSilentErrorHandler (jerr);
271 jpegDecompStruct.err = &jerr;
273 jpeg_create_decompress (&jpegDecompStruct);
275 jpegDecompStruct.src = (jpeg_source_mgr*)(jpegDecompStruct.mem->alloc_small)
276 ((j_common_ptr)(&jpegDecompStruct), JPOOL_PERMANENT, sizeof (jpeg_source_mgr));
278 bool hasFailed = false;
279 jpegDecompStruct.client_data = &hasFailed;
281 jpegDecompStruct.src->init_source = dummyCallback1;
282 jpegDecompStruct.src->fill_input_buffer = jpegFill;
283 jpegDecompStruct.src->skip_input_data = jpegSkip;
284 jpegDecompStruct.src->resync_to_restart = jpeg_resync_to_restart;
285 jpegDecompStruct.src->term_source = dummyCallback1;
287 jpegDecompStruct.src->next_input_byte = static_cast<const unsigned char*> (mb.getData());
288 jpegDecompStruct.src->bytes_in_buffer = mb.getDataSize();
290 jpeg_read_header (&jpegDecompStruct, TRUE);
292 if (! hasFailed)
294 jpeg_calc_output_dimensions (&jpegDecompStruct);
296 if (! hasFailed)
298 const int width = (int) jpegDecompStruct.output_width;
299 const int height = (int) jpegDecompStruct.output_height;
301 jpegDecompStruct.out_color_space = JCS_RGB;
303 JSAMPARRAY buffer
304 = (*jpegDecompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegDecompStruct,
305 JPOOL_IMAGE,
306 (JDIMENSION) width * 3, 1);
308 if (jpeg_start_decompress (&jpegDecompStruct) && ! hasFailed)
310 image = Image (Image::RGB, width, height, false);
311 image.getProperties()->set ("originalImageHadAlpha", false);
312 const bool hasAlphaChan = image.hasAlphaChannel(); // (the native image creator may not give back what we expect)
314 const Image::BitmapData destData (image, Image::BitmapData::writeOnly);
316 for (int y = 0; y < height; ++y)
318 jpeg_read_scanlines (&jpegDecompStruct, buffer, 1);
320 if (hasFailed)
321 break;
323 const uint8* src = *buffer;
324 uint8* dest = destData.getLinePointer (y);
326 if (hasAlphaChan)
328 for (int i = width; --i >= 0;)
330 ((PixelARGB*) dest)->setARGB (0xff, src[0], src[1], src[2]);
331 ((PixelARGB*) dest)->premultiply();
332 dest += destData.pixelStride;
333 src += 3;
336 else
338 for (int i = width; --i >= 0;)
340 ((PixelRGB*) dest)->setARGB (0xff, src[0], src[1], src[2]);
341 dest += destData.pixelStride;
342 src += 3;
347 if (! hasFailed)
348 jpeg_finish_decompress (&jpegDecompStruct);
350 in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData());
355 jpeg_destroy_decompress (&jpegDecompStruct);
358 return image;
359 #endif
362 bool JPEGImageFormat::writeImageToStream (const Image& image, OutputStream& out)
364 using namespace jpeglibNamespace;
365 using namespace JPEGHelpers;
367 jpeg_compress_struct jpegCompStruct;
368 zerostruct (jpegCompStruct);
369 jpeg_create_compress (&jpegCompStruct);
371 struct jpeg_error_mgr jerr;
372 setupSilentErrorHandler (jerr);
373 jpegCompStruct.err = &jerr;
375 JuceJpegDest dest;
376 jpegCompStruct.dest = &dest;
378 dest.output = &out;
379 HeapBlock<char> tempBuffer (jpegBufferSize);
380 dest.buffer = tempBuffer;
381 dest.next_output_byte = (JOCTET*) dest.buffer;
382 dest.free_in_buffer = jpegBufferSize;
383 dest.init_destination = jpegWriteInit;
384 dest.empty_output_buffer = jpegWriteFlush;
385 dest.term_destination = jpegWriteTerminate;
387 jpegCompStruct.image_width = (JDIMENSION) image.getWidth();
388 jpegCompStruct.image_height = (JDIMENSION) image.getHeight();
389 jpegCompStruct.input_components = 3;
390 jpegCompStruct.in_color_space = JCS_RGB;
391 jpegCompStruct.write_JFIF_header = 1;
393 jpegCompStruct.X_density = 72;
394 jpegCompStruct.Y_density = 72;
396 jpeg_set_defaults (&jpegCompStruct);
398 jpegCompStruct.dct_method = JDCT_FLOAT;
399 jpegCompStruct.optimize_coding = 1;
401 if (quality < 0.0f)
402 quality = 0.85f;
404 jpeg_set_quality (&jpegCompStruct, jlimit (0, 100, roundToInt (quality * 100.0f)), TRUE);
406 jpeg_start_compress (&jpegCompStruct, TRUE);
408 const int strideBytes = (int) (jpegCompStruct.image_width * (unsigned int) jpegCompStruct.input_components);
410 JSAMPARRAY buffer = (*jpegCompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegCompStruct,
411 JPOOL_IMAGE, (JDIMENSION) strideBytes, 1);
413 const Image::BitmapData srcData (image, Image::BitmapData::readOnly);
415 while (jpegCompStruct.next_scanline < jpegCompStruct.image_height)
417 uint8* dst = *buffer;
419 if (srcData.pixelFormat == Image::RGB)
421 const uint8* src = srcData.getLinePointer ((int) jpegCompStruct.next_scanline);
423 for (int i = srcData.width; --i >= 0;)
425 *dst++ = ((const PixelRGB*) src)->getRed();
426 *dst++ = ((const PixelRGB*) src)->getGreen();
427 *dst++ = ((const PixelRGB*) src)->getBlue();
428 src += srcData.pixelStride;
431 else
433 for (int x = 0; x < srcData.width; ++x)
435 const Colour pixel (srcData.getPixelColour (x, (int) jpegCompStruct.next_scanline));
436 *dst++ = pixel.getRed();
437 *dst++ = pixel.getGreen();
438 *dst++ = pixel.getBlue();
442 jpeg_write_scanlines (&jpegCompStruct, buffer, 1);
445 jpeg_finish_compress (&jpegCompStruct);
446 jpeg_destroy_compress (&jpegCompStruct);
448 return true;
451 } // namespace juce