unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Juanma Barranquero <lekktu@gmail.com>
Subject: Re: Problem with library images on Windows (again)
Date: Tue, 14 Jun 2005 04:02:28 +0200	[thread overview]
Message-ID: <f7ccd24b050613190251cc92e@mail.gmail.com> (raw)
In-Reply-To: <f7ccd24b050606042622111ca9@mail.gmail.com>

> (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 accepted)
 - 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.

-- 
                    /L/e/k/t/u


Index: src/image.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/image.c,v
retrieving revision 1.27
diff -u -2 -r1.27 image.c
--- src/image.c	11 Jun 2005 16:24:36 -0000	1.27
+++ src/image.c	14 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	png_destroy_read_struct
 #define fn_png_set_read_fn		png_set_read_fn
-#define fn_png_init_io			png_init_io
 #define fn_png_set_sig_bytes		png_set_sig_bytes
 #define fn_png_read_info		png_read_info
@@ -5763,4 +5760,21 @@
 
 
+/* 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 = (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);
 
   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		jpeg_read_header
 #define fn_jpeg_read_scanlines		jpeg_read_scanlines
-#define fn_jpeg_stdio_src		jpeg_stdio_src
 #define fn_jpeg_std_error		jpeg_std_error
 #define jpeg_resync_to_restart_wrapper	jpeg_resync_to_restart
@@ -6359,4 +6370,15 @@
 
 
+/* 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 @@
 
 static void
-our_init_source (cinfo)
+our_memory_init_source (cinfo)
      j_decompress_ptr cinfo;
 {
@@ -6375,5 +6397,5 @@
 
 static boolean
-our_fill_input_buffer (cinfo)
+our_memory_fill_input_buffer (cinfo)
      j_decompress_ptr cinfo;
 {
@@ -6395,5 +6417,5 @@
 
 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 @@
 
 
-/* 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 @@
 
   src = (struct jpeg_source_mgr *) cinfo->src;
-  src->init_source = our_init_source;
-  src->fill_input_buffer = our_fill_input_buffer;
-  src->skip_input_data = our_skip_input_data;
+  src->init_source = our_memory_init_source;
+  src->fill_input_buffer = our_memory_fill_input_buffer;
+  src->skip_input_data = our_memory_skip_input_data;
   src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use
default method.  */
-  src->term_source = our_term_source;
+  src->term_source = our_common_term_source;
   src->bytes_in_buffer = len;
   src->next_input_byte = data;
@@ -6455,4 +6467,136 @@
 
 
+/* 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 size */
+
+
+/* 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 = (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 source.
+   */
+  src->start_of_file = 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 = (my_jpeg_file_ptr) cinfo->src;
+  size_t nbytes;
+
+  nbytes = fread (src->buffer, 1, JPEG_INPUT_BUF_SIZE, src->infile);
+
+  if (nbytes <= 0) {
+    if (src->start_of_file)	/* 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] = (JOCTET) 0xFF;
+    src->buffer[1] = (JOCTET) JPEG_EOI;
+    nbytes = 2;
+  }
+
+  src->pub.next_input_byte = src->buffer;
+  src->pub.bytes_in_buffer = nbytes;
+  src->start_of_file = 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 = (my_jpeg_file_ptr) cinfo->src;
+
+  /* Just a dumb implementation for now.  Could use fseek() except
+   * it doesn't work on pipes.	Not 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 -= (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 += (size_t) num_bytes;
+      src->pub.bytes_in_buffer -= (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 series
+   * of JPEG images can be read from the same file by calling jpeg_stdio_src
+   * only before the first one.	 (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 == NULL)
+      {
+        /* first time for this JPEG object? */
+        cinfo->src = (struct jpeg_source_mgr *)
+          (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+                                      sizeof (struct my_jpeg_file_src));
+        src = (my_jpeg_file_ptr) cinfo->src;
+        src->buffer = (JOCTET *)
+          (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+                                      JPEG_INPUT_BUF_SIZE * sizeof (JOCTET));
+      }
+
+    src = (my_jpeg_file_ptr) cinfo->src;
+    src->pub.init_source = our_file_init_source;
+    src->pub.fill_input_buffer = our_file_fill_input_buffer;
+    src->pub.skip_input_data = our_file_skip_input_data;
+    src->pub.resync_to_restart = jpeg_resync_to_restart_wrapper; /*
use default method */
+    src->pub.term_source = our_common_term_source;
+    src->infile = infile;
+    src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+    src->pub.next_input_byte = NULL; /* until buffer loaded */
+}
+
+
 /* Load image IMG for use on frame F.  Patterned after example.c
    from the JPEG lib.  */
@@ -6538,5 +6682,5 @@
 
   if (NILP (specified_data))
-    fn_jpeg_stdio_src (&cinfo, (FILE *) fp);
+    jpeg_file_src (&cinfo, fp);
   else
     jpeg_memory_src (&cinfo, SDATA (specified_data),

  reply	other threads:[~2005-06-14  2:02 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-05-18 15:53 Problem with library images on Windows (again) Juanma Barranquero
2005-05-18 19:30 ` Andreas Schwab
2005-05-18 22:44   ` Juanma Barranquero
2005-05-19  6:58     ` Jason Rumney
2005-05-18 22:16 ` Jason Rumney
2005-05-18 22:52   ` Juanma Barranquero
2005-05-19  3:50     ` Eli Zaretskii
2005-05-19  8:13       ` Juanma Barranquero
2005-05-19 19:05         ` Eli Zaretskii
2005-05-19 19:31           ` Juanma Barranquero
2005-05-19 19:32             ` Juanma Barranquero
2005-05-20  7:20             ` Eli Zaretskii
2005-05-20  8:24               ` Kim F. Storm
2005-05-20 10:01                 ` Eli Zaretskii
2005-05-20 10:16                 ` Jason Rumney
2005-05-20 10:42                   ` Juanma Barranquero
2005-05-20 14:44                     ` Eli Zaretskii
2005-05-20 15:46                       ` Jason Rumney
2005-05-20 15:52                         ` Eli Zaretskii
2005-05-20 16:33                           ` Juanma Barranquero
2005-05-20 17:57                             ` Juanma Barranquero
2005-05-21 10:21                               ` Jason Rumney
2005-05-21 10:33                                 ` Juanma Barranquero
2005-05-21 21:13                                   ` Jason Rumney
2005-05-22 21:21                                     ` Juanma Barranquero
2005-06-03 12:08                                       ` Juanma Barranquero
2005-06-03 13:06                                         ` David Kastrup
2005-06-03 15:28                                           ` jasonr
2005-06-03 17:23                                             ` Stefan Monnier
2005-06-05  0:44                                           ` Juanma Barranquero
2005-06-06 11:26                                             ` Juanma Barranquero
2005-06-14  2:02                                               ` Juanma Barranquero [this message]
2005-06-14  7:32                                                 ` David Kastrup
2005-06-14  9:15                                                   ` Juanma Barranquero
2005-05-20 16:31                         ` Juanma Barranquero
2005-05-20 16:29                       ` Juanma Barranquero
2005-05-20 12:19                   ` Benjamin Riefenstahl

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f7ccd24b050613190251cc92e@mail.gmail.com \
    --to=lekktu@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).