diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/jpeg/loader_jpg.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/jpeg/loader_jpg.cpp')
-rw-r--r-- | Src/jpeg/loader_jpg.cpp | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/Src/jpeg/loader_jpg.cpp b/Src/jpeg/loader_jpg.cpp new file mode 100644 index 00000000..234ca4d5 --- /dev/null +++ b/Src/jpeg/loader_jpg.cpp @@ -0,0 +1,223 @@ +#include "main.h" + +#include "loader_jpg.h" + +#include "api__jpeg.h" +#include "../xml/ifc_xmlreaderparams.h" +#include <api/memmgr/api_memmgr.h> +#include <shlwapi.h> +#include <setjmp.h> + +#include <wingdi.h> +#include <intsafe.h> + +/*BIG BIG THING TO NOTE +I have modified jmorecfg.h line 319 to specify 4 bytes per pixel with RGB. it is normally three. +*/ +extern "C" +{ +#undef FAR +#include "jpeglib.h" +}; + +int JpgLoad::isMine( const wchar_t *filename ) +{ + if ( !filename ) + return 0; + + const wchar_t *ext = PathFindExtensionW( filename ); + + if ( !ext ) + return 0; + + if ( !_wcsicmp( ext, L".jpg" ) ) + return 1; + + if ( !_wcsicmp( ext, L".jpeg" ) ) + return 1; + + return 0; +} + +const wchar_t *JpgLoad::mimeType() +{ + return L"image/jpeg"; +} + +int JpgLoad::getHeaderSize() +{ + return 3; +} + +int JpgLoad::testData( const void *data, int datalen ) +{ + if ( datalen < 3 ) + return 0; + + const unsigned __int8 *text = static_cast<const unsigned __int8 *>( data ); + if ( text[ 0 ] == 0xFF && text[ 1 ] == 0xD8 && text[ 2 ] == 0xFF ) + return 1; + + return 0; +} +/* +struct jpeg_source_mgr { + const JOCTET * next_input_byte; // => next byte to read from buffer + size_t bytes_in_buffer; // # of bytes remaining in buffer + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; +*/ + +// our reader... +extern "C" +{ + static void init_source( j_decompress_ptr cinfo ) + {} + static const JOCTET jpeg_eof[] = { (JOCTET)0xFF, (JOCTET)JPEG_EOI }; + static boolean fill_input_buffer( j_decompress_ptr cinfo ) + { + cinfo->src->next_input_byte = jpeg_eof; + cinfo->src->bytes_in_buffer = 2; + return TRUE; + } + static void skip_input_data( j_decompress_ptr cinfo, long num_bytes ) + { + //my_src_ptr src = (my_src_ptr) cinfo->src; + if ( num_bytes > 0 ) + { + if ( num_bytes > (long)cinfo->src->bytes_in_buffer ) + { + fill_input_buffer( cinfo ); + } + else + { + cinfo->src->next_input_byte += (size_t)num_bytes; + cinfo->src->bytes_in_buffer -= (size_t)num_bytes; + } + } + } + static void term_source( j_decompress_ptr cinfo ) + {} +}; + +static void wasabi_jpgload_error_exit( j_common_ptr cinfo ) +{ + jmp_buf *stack_env = (jmp_buf *)cinfo->client_data; + longjmp( *stack_env, 1 ); +} + +static bool IsAMG( jpeg_saved_marker_ptr marker_list ) +{ + while ( marker_list ) + { + if ( marker_list->marker == JPEG_COM && marker_list->data_length == 7 && memcmp( (const char *)marker_list->data, "AMG/AOL", 7 ) == 0 ) + { + return true; + } + + marker_list = marker_list->next; + } + + return false; +} + +ARGB32 *JpgLoad::loadImage( const void *data, int datalen, int *w, int *h, ifc_xmlreaderparams *params ) +{ + int fail_on_amg = 0; + + if ( params ) // epic failness + fail_on_amg = params->getItemValueInt( L"AMG", 0 ); + + ARGB32 *buf = 0; + jpeg_error_mgr jerr; + jpeg_decompress_struct cinfo; + jpeg_source_mgr src = { (const JOCTET *)data,(size_t)datalen,init_source,fill_input_buffer,skip_input_data,jpeg_resync_to_restart,term_source }; + + cinfo.err = jpeg_std_error( &jerr ); + + jpeg_create_decompress( &cinfo ); + cinfo.src = &src; + + /* set up error handling. basically C style exceptions :) */ + jmp_buf stack_env; + cinfo.client_data = &stack_env; + cinfo.err->error_exit = wasabi_jpgload_error_exit; + if ( setjmp( stack_env ) ) + { + // longjmp will goto here + jpeg_destroy_decompress( &cinfo ); + if ( buf ) + WASABI_API_MEMMGR->sysFree( buf ); + + return 0; + } + + if ( fail_on_amg ) + jpeg_save_markers( &cinfo, JPEG_COM, 10 ); + + if ( jpeg_read_header( &cinfo, TRUE ) == JPEG_HEADER_OK ) + { + cinfo.out_color_space = JCS_RGB; + /*int ret = */jpeg_start_decompress( &cinfo ); + if ( !fail_on_amg || !IsAMG( cinfo.marker_list ) ) + { + size_t image_size = 0; + if ( SizeTMult( cinfo.output_width, cinfo.output_height, &image_size ) == S_OK && SizeTMult( image_size, 4, &image_size ) == S_OK ) + { + buf = (ARGB32 *)WASABI_API_MEMMGR->sysMalloc( image_size ); + int row_stride = cinfo.output_width * cinfo.output_components; + + ARGB32 *p = buf;// + (cinfo.output_width * cinfo.output_height); + + void* line = malloc(row_stride); + + while ( cinfo.output_scanline < cinfo.output_height ) + { + //p -= cinfo.output_width; + jpeg_read_scanlines( &cinfo, (JSAMPARRAY)&line, 1 ); + + unsigned char* rgb = (unsigned char*)line; + unsigned char* argb = (unsigned char*)p; + for (size_t i = 0; i < cinfo.output_width; i++) + { + argb[4 * i] = rgb[3 * i + 2]; + argb[4 * i + 1] = rgb[3 * i + 1]; + argb[4 * i + 2] = rgb[3 * i]; + argb[4 * i + 3] = 0xff; + } + + + p += cinfo.output_width; + } + free(line); + + if ( w ) + *w = cinfo.output_width; + + if ( h ) + *h = cinfo.output_height; + + jpeg_finish_decompress( &cinfo ); + } + } + } + + jpeg_destroy_decompress( &cinfo ); + + return buf; +} + +#define CBCLASS JpgLoad +START_DISPATCH; +CB( ISMINE, isMine ); +CB( MIMETYPE, mimeType ); +CB( TESTDATA, testData ); +CB( GETHEADERSIZE, getHeaderSize ); +CB( LOADIMAGE, loadImage ); +END_DISPATCH; +#undef CBCLASS
\ No newline at end of file |