/** * Copyright (C) 2003 Billy Biggs . * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #include #include #include "jpeginput.h" struct jpeginput_s { int width; int height; uint8_t *buffer; }; struct my_error_mgr { struct jpeg_error_mgr pub; /* "public" fields */ jmp_buf setjmp_buffer; /* for return to caller */ }; typedef struct my_error_mgr * my_error_ptr; void my_error_exit( j_common_ptr cinfo ) { my_error_ptr myerr = (my_error_ptr) cinfo->err; (*cinfo->err->output_message)( cinfo ); longjmp( myerr->setjmp_buffer, 1 ); } jpeginput_t *jpeginput_new( const char *filename, int ycbcr ) { jpeginput_t *jpeginput = malloc( sizeof( jpeginput_t ) ); struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; JSAMPARRAY buffer; int row_stride; FILE *infile; if( !jpeginput ) { return 0; } infile = fopen( filename, "rb" ); if( !infile ) { fprintf( stderr, "jpeginput: Cannot open %s: %s\n", filename, strerror( errno ) ); free( jpeginput ); return 0; } cinfo.err = jpeg_std_error( &jerr.pub ); jerr.pub.error_exit = my_error_exit; if( setjmp( jerr.setjmp_buffer ) ) { jpeg_destroy_decompress( &cinfo ); fclose( infile ); free( jpeginput ); return 0; } jpeg_create_decompress( &cinfo ); jpeg_stdio_src( &cinfo, infile ); jpeg_read_header( &cinfo, TRUE ); if( ycbcr ) { cinfo.out_color_space = JCS_YCbCr; } fprintf( stderr, "jpeginput: Colour space %d (YCbCr %d).\n", cinfo.jpeg_color_space, JCS_YCbCr ); fprintf( stderr, "jpeginput: 601 sampling %d.\n", cinfo.CCIR601_sampling ); jpeg_start_decompress( &cinfo ); row_stride = cinfo.output_width * cinfo.output_components; buffer = (*cinfo.mem->alloc_sarray)( (j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1 ); jpeginput->width = cinfo.image_width; jpeginput->height = cinfo.image_height; jpeginput->buffer = malloc( jpeginput->width * jpeginput->height * 3 ); while( cinfo.output_scanline < cinfo.output_height ) { jpeg_read_scanlines( &cinfo, buffer, 1 ); memcpy( jpeginput->buffer + ((cinfo.output_scanline - 1) * jpeginput->width * 3), buffer[ 0 ], row_stride ); } jpeg_finish_decompress( &cinfo ); jpeg_destroy_decompress( &cinfo ); fclose( infile ); return jpeginput; } void jpeginput_delete( jpeginput_t *jpeginput ) { free( jpeginput->buffer ); free( jpeginput ); } unsigned int jpeginput_get_width( jpeginput_t *jpeginput ) { return jpeginput->width; } unsigned int jpeginput_get_height( jpeginput_t *jpeginput ) { return jpeginput->height; } uint8_t *jpeginput_get_scanline( jpeginput_t *jpeginput, int num ) { return jpeginput->buffer + (jpeginput->width * num * 3); }