From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Juanma Barranquero Newsgroups: gmane.emacs.devel Subject: Re: Problem with library images on Windows (again) Date: Tue, 14 Jun 2005 04:02:28 +0200 Message-ID: References: <853brzh9o6.fsf@lola.goethe.zz> Reply-To: Juanma Barranquero NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-Trace: sea.gmane.org 1118714953 18008 80.91.229.2 (14 Jun 2005 02:09:13 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Tue, 14 Jun 2005 02:09:13 +0000 (UTC) Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue Jun 14 04:09:08 2005 Return-path: Original-Received: from lists.gnu.org ([199.232.76.165]) by ciao.gmane.org with esmtp (Exim 4.43) id 1Di0rP-0007XW-VJ for ged-emacs-devel@m.gmane.org; Tue, 14 Jun 2005 04:09:04 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Di0wK-0006kZ-8v for ged-emacs-devel@m.gmane.org; Mon, 13 Jun 2005 22:14:08 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Di0uv-0006BG-04 for emacs-devel@gnu.org; Mon, 13 Jun 2005 22:12:41 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Di0ug-00063S-HM for emacs-devel@gnu.org; Mon, 13 Jun 2005 22:12:27 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Di0ug-0005zq-4T for emacs-devel@gnu.org; Mon, 13 Jun 2005 22:12:26 -0400 Original-Received: from [64.233.182.203] (helo=nproxy.gmail.com) by monty-python.gnu.org with esmtp (Exim 4.34) id 1Di0mE-0006IZ-Jl for emacs-devel@gnu.org; Mon, 13 Jun 2005 22:03:42 -0400 Original-Received: by nproxy.gmail.com with SMTP id i2so112288nfe for ; Mon, 13 Jun 2005 19:02:28 -0700 (PDT) DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=beta; d=gmail.com; h=received:message-id:date:from:reply-to:to:subject:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; b=DPFsCfZBuV6pcEdeR52Kpiu7/BVwh37Ilcws6pgT55Dc9JJAM6K5+So8OE8DNDVQ8I7iriLkHIWO/S0iHUXFGnlSw7gJbUVUFxMA7ainDAuxdCvmIf2Kyvx2NMWNkPHRfW26A4inIipx2dHyeUYTSTjaYboTOYYrUm6jnMm/lfU= Original-Received: by 10.48.240.16 with SMTP id n16mr87682nfh; Mon, 13 Jun 2005 19:02:28 -0700 (PDT) Original-Received: by 10.48.250.5 with HTTP; Mon, 13 Jun 2005 19:02:28 -0700 (PDT) Original-To: emacs-devel@gnu.org In-Reply-To: Content-Disposition: inline X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:38776 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:38776 > (I suppose I could get around the issue by writing read functions for > libpng and jpeg and bypassing the standard code altogether; And finally, that's what I've done. The following patch gets rid of png_init_io() and jpeg_stdio_src(), and instead define custom read functions to read image data from FILE *. With it, image support finally works as expected on MSVC and MinGW builds of Emacs on Windows. Highlights of the patch: - It has no ChangeLog entries :-) (I'll write them once the patch is accep= ted) - Deletion of png_init_io() and jpeg_stdio_src() is not conditional on HAVE_NTGUI; I've assumed it's best to have just one mechanism for Windows, Unix, GNU/Linux and MacOS platforms. I can reinstate the deleted functions and put the alternative into #ifdef's if deemed necessary. - I've changed a few names of the memory-reading data source functions for JPEG so it's clearer the paralelism between from-memory and from-file data source setups. - Most jpeg code I've added is heavily based on jdatasrc.c, from the JPEG library. I assume there's no legal trouble, as other jpeg code comes also from JPEG library examples. --=20 /L/e/k/t/u Index: src/image.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/emacs/emacs/src/image.c,v retrieving revision 1.27 diff -u -2 -r1.27 image.c --- src/image.c=0911 Jun 2005 16:24:36 -0000=091.27 +++ src/image.c=0914 Jun 2005 01:46:10 -0000 @@ -5632,5 +5632,4 @@ DEF_IMGLIB_FN (png_destroy_read_struct); DEF_IMGLIB_FN (png_set_read_fn); -DEF_IMGLIB_FN (png_init_io); DEF_IMGLIB_FN (png_set_sig_bytes); DEF_IMGLIB_FN (png_read_info); @@ -5664,5 +5663,4 @@ LOAD_IMGLIB_FN (library, png_destroy_read_struct); LOAD_IMGLIB_FN (library, png_set_read_fn); - LOAD_IMGLIB_FN (library, png_init_io); LOAD_IMGLIB_FN (library, png_set_sig_bytes); LOAD_IMGLIB_FN (library, png_read_info); @@ -5690,5 +5688,4 @@ #define fn_png_destroy_read_struct=09png_destroy_read_struct #define fn_png_set_read_fn=09=09png_set_read_fn -#define fn_png_init_io=09=09=09png_init_io #define fn_png_set_sig_bytes=09=09png_set_sig_bytes #define fn_png_read_info=09=09png_read_info @@ -5763,4 +5760,21 @@ =20 =20 +/* Function set as reader function when reading PNG image from a file. + PNG_PTR is a pointer to the PNG control structure. Copy LENGTH + bytes from the input to DATA. */ + +static void +png_read_from_file (png_ptr, data, length) + png_structp png_ptr; + png_bytep data; + png_size_t length; +{ + FILE *fp =3D (FILE *) fn_png_get_io_ptr (png_ptr); + + if (fread (data, 1, length, fp) < length) + fn_png_error (png_ptr, "Read error"); +} + + /* Load PNG image IMG for use on frame F. Value is non-zero if successful. */ @@ -5896,5 +5910,5 @@ fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory); else - fn_png_init_io (png_ptr, fp); + fn_png_set_read_fn (png_ptr, (void *) fp, png_read_from_file); =20 fn_png_set_sig_bytes (png_ptr, sizeof sig); @@ -6295,5 +6309,4 @@ DEF_IMGLIB_FN (jpeg_read_header); DEF_IMGLIB_FN (jpeg_read_scanlines); -DEF_IMGLIB_FN (jpeg_stdio_src); DEF_IMGLIB_FN (jpeg_std_error); DEF_IMGLIB_FN (jpeg_resync_to_restart); @@ -6311,5 +6324,4 @@ LOAD_IMGLIB_FN (library, jpeg_start_decompress); LOAD_IMGLIB_FN (library, jpeg_read_header); - LOAD_IMGLIB_FN (library, jpeg_stdio_src); LOAD_IMGLIB_FN (library, jpeg_CreateDecompress); LOAD_IMGLIB_FN (library, jpeg_destroy_decompress); @@ -6337,5 +6349,4 @@ #define fn_jpeg_read_header=09=09jpeg_read_header #define fn_jpeg_read_scanlines=09=09jpeg_read_scanlines -#define fn_jpeg_stdio_src=09=09jpeg_stdio_src #define fn_jpeg_std_error=09=09jpeg_std_error #define jpeg_resync_to_restart_wrapper=09jpeg_resync_to_restart @@ -6359,4 +6370,15 @@ =20 =20 +/* Method to terminate data source. Called by + jpeg_finish_decompress() after all data has been processed. + Common to memory and file source managers. */ + +static void +our_common_term_source (cinfo) + j_decompress_ptr cinfo; +{ +} + + /* Init source method for JPEG data source manager. Called by jpeg_read_header() before any data is actually read. See @@ -6364,5 +6386,5 @@ =20 static void -our_init_source (cinfo) +our_memory_init_source (cinfo) j_decompress_ptr cinfo; { @@ -6375,5 +6397,5 @@ =20 static boolean -our_fill_input_buffer (cinfo) +our_memory_fill_input_buffer (cinfo) j_decompress_ptr cinfo; { @@ -6395,5 +6417,5 @@ =20 static void -our_skip_input_data (cinfo, num_bytes) +our_memory_skip_input_data (cinfo, num_bytes) j_decompress_ptr cinfo; long num_bytes; @@ -6412,14 +6434,4 @@ =20 =20 -/* Method to terminate data source. Called by - jpeg_finish_decompress() after all data has been processed. */ - -static void -our_term_source (cinfo) - j_decompress_ptr cinfo; -{ -} - - /* Set up the JPEG lib for reading an image from DATA which contains LEN bytes. CINFO is the decompression info structure created for @@ -6445,9 +6457,9 @@ =20 src =3D (struct jpeg_source_mgr *) cinfo->src; - src->init_source =3D our_init_source; - src->fill_input_buffer =3D our_fill_input_buffer; - src->skip_input_data =3D our_skip_input_data; + src->init_source =3D our_memory_init_source; + src->fill_input_buffer =3D our_memory_fill_input_buffer; + src->skip_input_data =3D our_memory_skip_input_data; src->resync_to_restart =3D jpeg_resync_to_restart_wrapper; /* Use default method. */ - src->term_source =3D our_term_source; + src->term_source =3D our_common_term_source; src->bytes_in_buffer =3D len; src->next_input_byte =3D data; @@ -6455,4 +6467,136 @@ =20 =20 +/* JPEG data source manager setup for JPEG images read from a file. + Heavily based on jdatasrc.c from the JPEG library. */ + +struct my_jpeg_file_src { + struct jpeg_source_mgr pub; /* public fields */ + + FILE *infile; /* source stream */ + JOCTET *buffer; /* start of buffer */ + boolean start_of_file; /* have we gotten any data yet? */ +}; + +typedef struct my_jpeg_file_src *my_jpeg_file_ptr; + +#define JPEG_INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able si= ze */ + + +/* Init source method for JPEG data source manager. + Called by jpeg_read_header() before any data is actually read. */ + +static void +our_file_init_source (j_decompress_ptr cinfo) +{ + my_jpeg_file_ptr src =3D (my_jpeg_file_ptr) cinfo->src; + + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one sour= ce. + */ + src->start_of_file =3D 1; +} + + +/* Fill input buffer method for JPEG data source manager. + Called whenever more data is needed. */ + +static boolean +our_file_fill_input_buffer (j_decompress_ptr cinfo) +{ + my_jpeg_file_ptr src =3D (my_jpeg_file_ptr) cinfo->src; + size_t nbytes; + + nbytes =3D fread (src->buffer, 1, JPEG_INPUT_BUF_SIZE, src->infile); + + if (nbytes <=3D 0) { + if (src->start_of_file)=09/* Treat empty input file as fatal error */ + ERREXIT (cinfo, JERR_INPUT_EMPTY); + WARNMS (cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] =3D (JOCTET) 0xFF; + src->buffer[1] =3D (JOCTET) JPEG_EOI; + nbytes =3D 2; + } + + src->pub.next_input_byte =3D src->buffer; + src->pub.bytes_in_buffer =3D nbytes; + src->start_of_file =3D 0; + + return 1; +} + + +/* Method to skip over NUM_BYTES bytes in the image data. + CINFO->src is the JPEG data source manager. */ + +static void +our_file_skip_input_data (j_decompress_ptr cinfo, long num_bytes) +{ + my_jpeg_file_ptr src =3D (my_jpeg_file_ptr) cinfo->src; + + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes.=09Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) + { + while (num_bytes > (long) src->pub.bytes_in_buffer) + { + num_bytes -=3D (long) src->pub.bytes_in_buffer; + (void) our_file_fill_input_buffer (cinfo); + /* note we assume that fill_file_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->pub.next_input_byte +=3D (size_t) num_bytes; + src->pub.bytes_in_buffer -=3D (size_t) num_bytes; + } +} + + +/* Set up the JPEG lib for reading an image from a FILE * via + a customized function, thus avoiding FILE * conflicts between + different builds of the image library. CINFO is the + decompression info structure created for reading the image. */ + +static void +jpeg_file_src (cinfo, infile) + j_decompress_ptr cinfo; + FILE *infile; +{ + my_jpeg_file_ptr src; + + /* The source object and input buffer are made permanent so that a serie= s + * of JPEG images can be read from the same file by calling jpeg_stdio_s= rc + * only before the first one.=09 (If we discarded the buffer at the end = of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src =3D=3D NULL) + { + /* first time for this JPEG object? */ + cinfo->src =3D (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANEN= T, + sizeof (struct my_jpeg_file_src)); + src =3D (my_jpeg_file_ptr) cinfo->src; + src->buffer =3D (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANEN= T, + JPEG_INPUT_BUF_SIZE * sizeof (JOCTET= )); + } + + src =3D (my_jpeg_file_ptr) cinfo->src; + src->pub.init_source =3D our_file_init_source; + src->pub.fill_input_buffer =3D our_file_fill_input_buffer; + src->pub.skip_input_data =3D our_file_skip_input_data; + src->pub.resync_to_restart =3D jpeg_resync_to_restart_wrapper; /* use default method */ + src->pub.term_source =3D our_common_term_source; + src->infile =3D infile; + src->pub.bytes_in_buffer =3D 0; /* forces fill_input_buffer on first r= ead */ + src->pub.next_input_byte =3D NULL; /* until buffer loaded */ +} + + /* Load image IMG for use on frame F. Patterned after example.c from the JPEG lib. */ @@ -6538,5 +6682,5 @@ =20 if (NILP (specified_data)) - fn_jpeg_stdio_src (&cinfo, (FILE *) fp); + jpeg_file_src (&cinfo, fp); else jpeg_memory_src (&cinfo, SDATA (specified_data),