The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

444 lines
14KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE 6 technical preview.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. You may use this code under the terms of the GPL v3
  6. (see www.gnu.org/licenses).
  7. For this technical preview, this file is not subject to commercial licensing.
  8. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  9. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  10. DISCLAIMED.
  11. ==============================================================================
  12. */
  13. namespace juce
  14. {
  15. JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4365)
  16. namespace jpeglibNamespace
  17. {
  18. #if JUCE_INCLUDE_JPEGLIB_CODE || ! defined (JUCE_INCLUDE_JPEGLIB_CODE)
  19. #if JUCE_MINGW
  20. typedef unsigned char boolean;
  21. #endif
  22. JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wconversion",
  23. "-Wdeprecated-register",
  24. "-Wsign-conversion",
  25. "-Wcast-align",
  26. "-Wswitch-enum",
  27. "-Wswitch-default",
  28. "-Wimplicit-fallthrough",
  29. "-Wzero-as-null-pointer-constant",
  30. "-Wshift-negative-value",
  31. "-Wcomma")
  32. #define JPEG_INTERNALS
  33. #undef FAR
  34. #include "jpglib/jpeglib.h"
  35. #include "jpglib/jcapimin.c"
  36. #include "jpglib/jcapistd.c"
  37. #include "jpglib/jccoefct.c"
  38. #include "jpglib/jccolor.c"
  39. #undef FIX
  40. #include "jpglib/jcdctmgr.c"
  41. #undef CONST_BITS
  42. #include "jpglib/jchuff.c"
  43. #undef emit_byte
  44. #include "jpglib/jcinit.c"
  45. #include "jpglib/jcmainct.c"
  46. #include "jpglib/jcmarker.c"
  47. #include "jpglib/jcmaster.c"
  48. #include "jpglib/jcomapi.c"
  49. #include "jpglib/jcparam.c"
  50. #include "jpglib/jcphuff.c"
  51. #include "jpglib/jcprepct.c"
  52. #include "jpglib/jcsample.c"
  53. #include "jpglib/jctrans.c"
  54. #include "jpglib/jdapistd.c"
  55. #include "jpglib/jdapimin.c"
  56. #include "jpglib/jdatasrc.c"
  57. #include "jpglib/jdcoefct.c"
  58. #undef FIX
  59. #include "jpglib/jdcolor.c"
  60. #undef FIX
  61. #include "jpglib/jddctmgr.c"
  62. #undef CONST_BITS
  63. #undef ASSIGN_STATE
  64. #include "jpglib/jdhuff.c"
  65. #include "jpglib/jdinput.c"
  66. #include "jpglib/jdmainct.c"
  67. #include "jpglib/jdmarker.c"
  68. #include "jpglib/jdmaster.c"
  69. #undef FIX
  70. #include "jpglib/jdmerge.c"
  71. #undef ASSIGN_STATE
  72. #include "jpglib/jdphuff.c"
  73. #include "jpglib/jdpostct.c"
  74. #undef FIX
  75. #include "jpglib/jdsample.c"
  76. #include "jpglib/jdtrans.c"
  77. #include "jpglib/jfdctflt.c"
  78. #include "jpglib/jfdctint.c"
  79. #undef CONST_BITS
  80. #undef MULTIPLY
  81. #undef FIX_0_541196100
  82. #include "jpglib/jfdctfst.c"
  83. #undef FIX_0_541196100
  84. #include "jpglib/jidctflt.c"
  85. #undef CONST_BITS
  86. #undef FIX_1_847759065
  87. #undef MULTIPLY
  88. #undef DEQUANTIZE
  89. #undef DESCALE
  90. #include "jpglib/jidctfst.c"
  91. #undef CONST_BITS
  92. #undef FIX_1_847759065
  93. #undef MULTIPLY
  94. #undef DEQUANTIZE
  95. #include "jpglib/jidctint.c"
  96. #include "jpglib/jidctred.c"
  97. #include "jpglib/jmemmgr.c"
  98. #include "jpglib/jmemnobs.c"
  99. #include "jpglib/jquant1.c"
  100. #include "jpglib/jquant2.c"
  101. #include "jpglib/jutils.c"
  102. #include "jpglib/transupp.c"
  103. JUCE_END_IGNORE_WARNINGS_GCC_LIKE
  104. #else
  105. #define JPEG_INTERNALS
  106. #undef FAR
  107. #include <jpeglib.h>
  108. #endif
  109. }
  110. #undef max
  111. #undef min
  112. JUCE_END_IGNORE_WARNINGS_MSVC
  113. //==============================================================================
  114. namespace JPEGHelpers
  115. {
  116. using namespace jpeglibNamespace;
  117. #if ! (JUCE_WINDOWS && (JUCE_MSVC || JUCE_CLANG))
  118. using jpeglibNamespace::boolean;
  119. #endif
  120. static void fatalErrorHandler (j_common_ptr p) { *((bool*) (p->client_data)) = true; }
  121. static void silentErrorCallback1 (j_common_ptr) {}
  122. static void silentErrorCallback2 (j_common_ptr, int) {}
  123. static void silentErrorCallback3 (j_common_ptr, char*) {}
  124. static void setupSilentErrorHandler (struct jpeg_error_mgr& err)
  125. {
  126. zerostruct (err);
  127. err.error_exit = fatalErrorHandler;
  128. err.emit_message = silentErrorCallback2;
  129. err.output_message = silentErrorCallback1;
  130. err.format_message = silentErrorCallback3;
  131. err.reset_error_mgr = silentErrorCallback1;
  132. }
  133. //==============================================================================
  134. #if ! JUCE_USING_COREIMAGE_LOADER
  135. static void dummyCallback1 (j_decompress_ptr) {}
  136. static void jpegSkip (j_decompress_ptr decompStruct, long num)
  137. {
  138. decompStruct->src->next_input_byte += num;
  139. num = jmin (num, (long) decompStruct->src->bytes_in_buffer);
  140. decompStruct->src->bytes_in_buffer -= (size_t) num;
  141. }
  142. static boolean jpegFill (j_decompress_ptr)
  143. {
  144. return 0;
  145. }
  146. #endif
  147. //==============================================================================
  148. const int jpegBufferSize = 512;
  149. struct JuceJpegDest : public jpeg_destination_mgr
  150. {
  151. OutputStream* output;
  152. char* buffer;
  153. };
  154. static void jpegWriteInit (j_compress_ptr) {}
  155. static void jpegWriteTerminate (j_compress_ptr cinfo)
  156. {
  157. JuceJpegDest* const dest = static_cast<JuceJpegDest*> (cinfo->dest);
  158. const size_t numToWrite = jpegBufferSize - dest->free_in_buffer;
  159. dest->output->write (dest->buffer, numToWrite);
  160. }
  161. static boolean jpegWriteFlush (j_compress_ptr cinfo)
  162. {
  163. JuceJpegDest* const dest = static_cast<JuceJpegDest*> (cinfo->dest);
  164. const int numToWrite = jpegBufferSize;
  165. dest->next_output_byte = reinterpret_cast<JOCTET*> (dest->buffer);
  166. dest->free_in_buffer = jpegBufferSize;
  167. return (boolean) dest->output->write (dest->buffer, (size_t) numToWrite);
  168. }
  169. }
  170. //==============================================================================
  171. JPEGImageFormat::JPEGImageFormat()
  172. : quality (-1.0f)
  173. {
  174. }
  175. JPEGImageFormat::~JPEGImageFormat() {}
  176. void JPEGImageFormat::setQuality (const float newQuality)
  177. {
  178. quality = newQuality;
  179. }
  180. String JPEGImageFormat::getFormatName() { return "JPEG"; }
  181. bool JPEGImageFormat::usesFileExtension (const File& f) { return f.hasFileExtension ("jpeg;jpg"); }
  182. bool JPEGImageFormat::canUnderstand (InputStream& in)
  183. {
  184. const int bytesNeeded = 24;
  185. uint8 header [bytesNeeded];
  186. if (in.read (header, bytesNeeded) == bytesNeeded
  187. && header[0] == 0xff
  188. && header[1] == 0xd8
  189. && header[2] == 0xff)
  190. return true;
  191. #if JUCE_USING_COREIMAGE_LOADER
  192. return header[20] == 'j'
  193. && header[21] == 'p'
  194. && header[22] == '2'
  195. && header[23] == ' ';
  196. #endif
  197. return false;
  198. }
  199. #if JUCE_USING_COREIMAGE_LOADER
  200. Image juce_loadWithCoreImage (InputStream& input);
  201. #endif
  202. Image JPEGImageFormat::decodeImage (InputStream& in)
  203. {
  204. #if JUCE_USING_COREIMAGE_LOADER
  205. return juce_loadWithCoreImage (in);
  206. #else
  207. using namespace jpeglibNamespace;
  208. using namespace JPEGHelpers;
  209. MemoryOutputStream mb;
  210. mb << in;
  211. Image image;
  212. if (mb.getDataSize() > 16)
  213. {
  214. struct jpeg_decompress_struct jpegDecompStruct;
  215. struct jpeg_error_mgr jerr;
  216. setupSilentErrorHandler (jerr);
  217. jpegDecompStruct.err = &jerr;
  218. jpeg_create_decompress (&jpegDecompStruct);
  219. jpegDecompStruct.src = (jpeg_source_mgr*)(jpegDecompStruct.mem->alloc_small)
  220. ((j_common_ptr)(&jpegDecompStruct), JPOOL_PERMANENT, sizeof (jpeg_source_mgr));
  221. bool hasFailed = false;
  222. jpegDecompStruct.client_data = &hasFailed;
  223. jpegDecompStruct.src->init_source = dummyCallback1;
  224. jpegDecompStruct.src->fill_input_buffer = jpegFill;
  225. jpegDecompStruct.src->skip_input_data = jpegSkip;
  226. jpegDecompStruct.src->resync_to_restart = jpeg_resync_to_restart;
  227. jpegDecompStruct.src->term_source = dummyCallback1;
  228. jpegDecompStruct.src->next_input_byte = static_cast<const unsigned char*> (mb.getData());
  229. jpegDecompStruct.src->bytes_in_buffer = mb.getDataSize();
  230. jpeg_read_header (&jpegDecompStruct, TRUE);
  231. if (! hasFailed)
  232. {
  233. jpeg_calc_output_dimensions (&jpegDecompStruct);
  234. if (! hasFailed)
  235. {
  236. const int width = (int) jpegDecompStruct.output_width;
  237. const int height = (int) jpegDecompStruct.output_height;
  238. jpegDecompStruct.out_color_space = JCS_RGB;
  239. JSAMPARRAY buffer
  240. = (*jpegDecompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegDecompStruct,
  241. JPOOL_IMAGE,
  242. (JDIMENSION) width * 3, 1);
  243. if (jpeg_start_decompress (&jpegDecompStruct) && ! hasFailed)
  244. {
  245. image = Image (Image::RGB, width, height, false);
  246. image.getProperties()->set ("originalImageHadAlpha", false);
  247. const bool hasAlphaChan = image.hasAlphaChannel(); // (the native image creator may not give back what we expect)
  248. const Image::BitmapData destData (image, Image::BitmapData::writeOnly);
  249. for (int y = 0; y < height; ++y)
  250. {
  251. jpeg_read_scanlines (&jpegDecompStruct, buffer, 1);
  252. if (hasFailed)
  253. break;
  254. const uint8* src = *buffer;
  255. uint8* dest = destData.getLinePointer (y);
  256. if (hasAlphaChan)
  257. {
  258. for (int i = width; --i >= 0;)
  259. {
  260. ((PixelARGB*) dest)->setARGB (0xff, src[0], src[1], src[2]);
  261. ((PixelARGB*) dest)->premultiply();
  262. dest += destData.pixelStride;
  263. src += 3;
  264. }
  265. }
  266. else
  267. {
  268. for (int i = width; --i >= 0;)
  269. {
  270. ((PixelRGB*) dest)->setARGB (0xff, src[0], src[1], src[2]);
  271. dest += destData.pixelStride;
  272. src += 3;
  273. }
  274. }
  275. }
  276. if (! hasFailed)
  277. jpeg_finish_decompress (&jpegDecompStruct);
  278. in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData());
  279. }
  280. }
  281. }
  282. jpeg_destroy_decompress (&jpegDecompStruct);
  283. }
  284. return image;
  285. #endif
  286. }
  287. bool JPEGImageFormat::writeImageToStream (const Image& image, OutputStream& out)
  288. {
  289. using namespace jpeglibNamespace;
  290. using namespace JPEGHelpers;
  291. jpeg_compress_struct jpegCompStruct;
  292. zerostruct (jpegCompStruct);
  293. jpeg_create_compress (&jpegCompStruct);
  294. struct jpeg_error_mgr jerr;
  295. setupSilentErrorHandler (jerr);
  296. jpegCompStruct.err = &jerr;
  297. JuceJpegDest dest;
  298. jpegCompStruct.dest = &dest;
  299. dest.output = &out;
  300. HeapBlock<char> tempBuffer (jpegBufferSize);
  301. dest.buffer = tempBuffer;
  302. dest.next_output_byte = (JOCTET*) dest.buffer;
  303. dest.free_in_buffer = jpegBufferSize;
  304. dest.init_destination = jpegWriteInit;
  305. dest.empty_output_buffer = jpegWriteFlush;
  306. dest.term_destination = jpegWriteTerminate;
  307. jpegCompStruct.image_width = (JDIMENSION) image.getWidth();
  308. jpegCompStruct.image_height = (JDIMENSION) image.getHeight();
  309. jpegCompStruct.input_components = 3;
  310. jpegCompStruct.in_color_space = JCS_RGB;
  311. jpegCompStruct.write_JFIF_header = 1;
  312. jpegCompStruct.X_density = 72;
  313. jpegCompStruct.Y_density = 72;
  314. jpeg_set_defaults (&jpegCompStruct);
  315. jpegCompStruct.dct_method = JDCT_FLOAT;
  316. jpegCompStruct.optimize_coding = 1;
  317. if (quality < 0.0f)
  318. quality = 0.85f;
  319. jpeg_set_quality (&jpegCompStruct, jlimit (0, 100, roundToInt (quality * 100.0f)), TRUE);
  320. jpeg_start_compress (&jpegCompStruct, TRUE);
  321. const int strideBytes = (int) (jpegCompStruct.image_width * (unsigned int) jpegCompStruct.input_components);
  322. JSAMPARRAY buffer = (*jpegCompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegCompStruct,
  323. JPOOL_IMAGE, (JDIMENSION) strideBytes, 1);
  324. const Image::BitmapData srcData (image, Image::BitmapData::readOnly);
  325. while (jpegCompStruct.next_scanline < jpegCompStruct.image_height)
  326. {
  327. uint8* dst = *buffer;
  328. if (srcData.pixelFormat == Image::RGB)
  329. {
  330. const uint8* src = srcData.getLinePointer ((int) jpegCompStruct.next_scanline);
  331. for (int i = srcData.width; --i >= 0;)
  332. {
  333. *dst++ = ((const PixelRGB*) src)->getRed();
  334. *dst++ = ((const PixelRGB*) src)->getGreen();
  335. *dst++ = ((const PixelRGB*) src)->getBlue();
  336. src += srcData.pixelStride;
  337. }
  338. }
  339. else
  340. {
  341. for (int x = 0; x < srcData.width; ++x)
  342. {
  343. const Colour pixel (srcData.getPixelColour (x, (int) jpegCompStruct.next_scanline));
  344. *dst++ = pixel.getRed();
  345. *dst++ = pixel.getGreen();
  346. *dst++ = pixel.getBlue();
  347. }
  348. }
  349. jpeg_write_scanlines (&jpegCompStruct, buffer, 1);
  350. }
  351. jpeg_finish_compress (&jpegCompStruct);
  352. jpeg_destroy_compress (&jpegCompStruct);
  353. return true;
  354. }
  355. } // namespace juce