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.

425 lines
13KB

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