loader_jpg.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #include "main.h"
  2. #include "loader_jpg.h"
  3. #include "api__jpeg.h"
  4. #include "../xml/ifc_xmlreaderparams.h"
  5. #include <api/memmgr/api_memmgr.h>
  6. #include <shlwapi.h>
  7. #include <setjmp.h>
  8. #include <wingdi.h>
  9. #include <intsafe.h>
  10. /*BIG BIG THING TO NOTE
  11. I have modified jmorecfg.h line 319 to specify 4 bytes per pixel with RGB. it is normally three.
  12. */
  13. extern "C"
  14. {
  15. #undef FAR
  16. #include "jpeglib.h"
  17. };
  18. int JpgLoad::isMine( const wchar_t *filename )
  19. {
  20. if ( !filename )
  21. return 0;
  22. const wchar_t *ext = PathFindExtensionW( filename );
  23. if ( !ext )
  24. return 0;
  25. if ( !_wcsicmp( ext, L".jpg" ) )
  26. return 1;
  27. if ( !_wcsicmp( ext, L".jpeg" ) )
  28. return 1;
  29. return 0;
  30. }
  31. const wchar_t *JpgLoad::mimeType()
  32. {
  33. return L"image/jpeg";
  34. }
  35. int JpgLoad::getHeaderSize()
  36. {
  37. return 3;
  38. }
  39. int JpgLoad::testData( const void *data, int datalen )
  40. {
  41. if ( datalen < 3 )
  42. return 0;
  43. const unsigned __int8 *text = static_cast<const unsigned __int8 *>( data );
  44. if ( text[ 0 ] == 0xFF && text[ 1 ] == 0xD8 && text[ 2 ] == 0xFF )
  45. return 1;
  46. return 0;
  47. }
  48. /*
  49. struct jpeg_source_mgr {
  50. const JOCTET * next_input_byte; // => next byte to read from buffer
  51. size_t bytes_in_buffer; // # of bytes remaining in buffer
  52. JMETHOD(void, init_source, (j_decompress_ptr cinfo));
  53. JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo));
  54. JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes));
  55. JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired));
  56. JMETHOD(void, term_source, (j_decompress_ptr cinfo));
  57. };
  58. */
  59. // our reader...
  60. extern "C"
  61. {
  62. static void init_source( j_decompress_ptr cinfo )
  63. {}
  64. static const JOCTET jpeg_eof[] = { (JOCTET)0xFF, (JOCTET)JPEG_EOI };
  65. static boolean fill_input_buffer( j_decompress_ptr cinfo )
  66. {
  67. cinfo->src->next_input_byte = jpeg_eof;
  68. cinfo->src->bytes_in_buffer = 2;
  69. return TRUE;
  70. }
  71. static void skip_input_data( j_decompress_ptr cinfo, long num_bytes )
  72. {
  73. //my_src_ptr src = (my_src_ptr) cinfo->src;
  74. if ( num_bytes > 0 )
  75. {
  76. if ( num_bytes > (long)cinfo->src->bytes_in_buffer )
  77. {
  78. fill_input_buffer( cinfo );
  79. }
  80. else
  81. {
  82. cinfo->src->next_input_byte += (size_t)num_bytes;
  83. cinfo->src->bytes_in_buffer -= (size_t)num_bytes;
  84. }
  85. }
  86. }
  87. static void term_source( j_decompress_ptr cinfo )
  88. {}
  89. };
  90. static void wasabi_jpgload_error_exit( j_common_ptr cinfo )
  91. {
  92. jmp_buf *stack_env = (jmp_buf *)cinfo->client_data;
  93. longjmp( *stack_env, 1 );
  94. }
  95. static bool IsAMG( jpeg_saved_marker_ptr marker_list )
  96. {
  97. while ( marker_list )
  98. {
  99. if ( marker_list->marker == JPEG_COM && marker_list->data_length == 7 && memcmp( (const char *)marker_list->data, "AMG/AOL", 7 ) == 0 )
  100. {
  101. return true;
  102. }
  103. marker_list = marker_list->next;
  104. }
  105. return false;
  106. }
  107. ARGB32 *JpgLoad::loadImage( const void *data, int datalen, int *w, int *h, ifc_xmlreaderparams *params )
  108. {
  109. int fail_on_amg = 0;
  110. if ( params ) // epic failness
  111. fail_on_amg = params->getItemValueInt( L"AMG", 0 );
  112. ARGB32 *buf = 0;
  113. jpeg_error_mgr jerr;
  114. jpeg_decompress_struct cinfo;
  115. jpeg_source_mgr src = { (const JOCTET *)data,(size_t)datalen,init_source,fill_input_buffer,skip_input_data,jpeg_resync_to_restart,term_source };
  116. cinfo.err = jpeg_std_error( &jerr );
  117. jpeg_create_decompress( &cinfo );
  118. cinfo.src = &src;
  119. /* set up error handling. basically C style exceptions :) */
  120. jmp_buf stack_env;
  121. cinfo.client_data = &stack_env;
  122. cinfo.err->error_exit = wasabi_jpgload_error_exit;
  123. if ( setjmp( stack_env ) )
  124. {
  125. // longjmp will goto here
  126. jpeg_destroy_decompress( &cinfo );
  127. if ( buf )
  128. WASABI_API_MEMMGR->sysFree( buf );
  129. return 0;
  130. }
  131. if ( fail_on_amg )
  132. jpeg_save_markers( &cinfo, JPEG_COM, 10 );
  133. if ( jpeg_read_header( &cinfo, TRUE ) == JPEG_HEADER_OK )
  134. {
  135. cinfo.out_color_space = JCS_RGB;
  136. /*int ret = */jpeg_start_decompress( &cinfo );
  137. if ( !fail_on_amg || !IsAMG( cinfo.marker_list ) )
  138. {
  139. size_t image_size = 0;
  140. if ( SizeTMult( cinfo.output_width, cinfo.output_height, &image_size ) == S_OK && SizeTMult( image_size, 4, &image_size ) == S_OK )
  141. {
  142. buf = (ARGB32 *)WASABI_API_MEMMGR->sysMalloc( image_size );
  143. int row_stride = cinfo.output_width * cinfo.output_components;
  144. ARGB32 *p = buf;// + (cinfo.output_width * cinfo.output_height);
  145. void* line = malloc(row_stride);
  146. while ( cinfo.output_scanline < cinfo.output_height )
  147. {
  148. //p -= cinfo.output_width;
  149. jpeg_read_scanlines( &cinfo, (JSAMPARRAY)&line, 1 );
  150. unsigned char* rgb = (unsigned char*)line;
  151. unsigned char* argb = (unsigned char*)p;
  152. for (size_t i = 0; i < cinfo.output_width; i++)
  153. {
  154. argb[4 * i] = rgb[3 * i + 2];
  155. argb[4 * i + 1] = rgb[3 * i + 1];
  156. argb[4 * i + 2] = rgb[3 * i];
  157. argb[4 * i + 3] = 0xff;
  158. }
  159. p += cinfo.output_width;
  160. }
  161. free(line);
  162. if ( w )
  163. *w = cinfo.output_width;
  164. if ( h )
  165. *h = cinfo.output_height;
  166. jpeg_finish_decompress( &cinfo );
  167. }
  168. }
  169. }
  170. jpeg_destroy_decompress( &cinfo );
  171. return buf;
  172. }
  173. #define CBCLASS JpgLoad
  174. START_DISPATCH;
  175. CB( ISMINE, isMine );
  176. CB( MIMETYPE, mimeType );
  177. CB( TESTDATA, testData );
  178. CB( GETHEADERSIZE, getHeaderSize );
  179. CB( LOADIMAGE, loadImage );
  180. END_DISPATCH;
  181. #undef CBCLASS