+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* GdkPixbuf library - PNM image loader
*
* Copyright (C) 1999 Red Hat, Inc.
*
- * Authors: Michael Fulbright <drmike@redhat.com>
+ * Authors: Jeffrey Stedfast <fejj@helixcode.com>
+ * Michael Fulbright <drmike@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* Boston, MA 02111-1307, USA.
*/
-/* Notes (11/05/99):
- *
- * raw pnm, pgm, and pbm files will load now.
- *
- * ascii support coming soon.
- *
- * next will be incremental loading.
- */
-
-
-#include <config.h>
-#include <ctype.h>
+#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
-#include <jpeglib.h>
-#include "gdk-pixbuf.h"
+#include "gdk-pixbuf-private.h"
#include "gdk-pixbuf-io.h"
-\f
-
#define PNM_BUF_SIZE 4096
-#define PNM_SUSPEND 0
-#define PNM_OK 1
#define PNM_FATAL_ERR -1
+#define PNM_SUSPEND 0
+#define PNM_OK 1
typedef enum {
- PNM_FORMAT_PGM,
+ PNM_FORMAT_PGM = 1,
PNM_FORMAT_PGM_RAW,
PNM_FORMAT_PPM,
PNM_FORMAT_PPM_RAW,
} PnmFormat;
typedef struct {
- guchar buffer[PNM_BUF_SIZE];
- guchar *next_byte;
- guint bytes_left;
+ guchar buffer[PNM_BUF_SIZE];
+ guchar *byte;
+ guint nbytes;
} PnmIOBuffer;
typedef struct {
- ModuleUpdatedNotifyFunc updated_func;
- ModulePreparedNotifyFunc prepared_func;
- gpointer user_data;
+ GdkPixbufModuleUpdatedFunc updated_func;
+ GdkPixbufModulePreparedFunc prepared_func;
+ GdkPixbufModuleSizeFunc size_func;
+ gpointer user_data;
- GdkPixbuf *pixbuf;
- guchar *pixels; /* incoming pixel data buffer */
- guchar *dptr; /* current position in pixbuf */
-
- PnmIOBuffer inbuf;
-
- guint width;
- guint height;
- guint maxval;
- PnmFormat type;
+ GdkPixbuf *pixbuf;
+ guchar *pixels; /* incoming pixel data buffer */
+ guchar *dptr; /* current position in pixbuf */
+
+ PnmIOBuffer inbuf;
+
+ guint width;
+ guint height;
+ guint maxval;
+ guint rowstride;
+ PnmFormat type;
+
+ guint output_row; /* last row to be completed */
+ guint output_col;
+ gboolean did_prescan; /* are we in image data yet? */
+ gboolean got_header; /* have we loaded pnm header? */
+
+ guint scan_state;
- guint output_row; /* last row to be completed */
- guint output_col;
- gboolean did_prescan; /* are we in image data yet? */
- gboolean got_header; /* have we loaded jpeg header? */
+ GError **error;
+
} PnmLoaderContext;
-GdkPixbuf *image_load (FILE *f);
-gpointer image_begin_load (ModulePreparedNotifyFunc func,
- ModuleUpdatedNotifyFunc func2, gpointer user_data);
-void image_stop_load (gpointer context);
-gboolean image_load_increment(gpointer context, guchar *buf, guint size);
+static GdkPixbuf *gdk_pixbuf__pnm_image_load (FILE *f, GError **error);
+static gpointer gdk_pixbuf__pnm_image_begin_load (GdkPixbufModuleSizeFunc size_func,
+ GdkPixbufModulePreparedFunc func,
+ GdkPixbufModuleUpdatedFunc func2,
+ gpointer user_data,
+ GError **error);
+static gboolean gdk_pixbuf__pnm_image_stop_load (gpointer context, GError **error);
+static gboolean gdk_pixbuf__pnm_image_load_increment (gpointer context,
+ const guchar *buf, guint size,
+ GError **error);
-static void explode_bitmap_into_buf (PnmLoaderContext *context);
-static void explode_gray_into_buf (PnmLoaderContext *context);
-
-/* Destroy notification function for the libart pixbuf */
-static void
-free_buffer (gpointer user_data, gpointer data)
-{
- free (data);
-}
+static void explode_bitmap_into_buf (PnmLoaderContext *context);
+static void explode_gray_into_buf (PnmLoaderContext *context);
/* explode bitmap data into rgb components */
guchar *from, *to, data;
gint bit;
guchar *dptr;
- gint wid, x, y;
-
+ gint wid, x;
+
g_return_if_fail (context != NULL);
g_return_if_fail (context->dptr != NULL);
-
+
/* I'm no clever bit-hacker so I'm sure this can be optimized */
dptr = context->dptr;
- y = context->output_row;
wid = context->width;
-
- from = dptr + (wid - 1)/8;
+
+ from = dptr + ((wid - 1) / 8);
to = dptr + (wid - 1) * 3;
- bit = 7 - (((y+1)*wid - 1) % 8);
-
+ bit = 7 - ((wid-1) % 8);
+
/* get first byte and align properly */
data = from[0];
for (j = 0; j < bit; j++, data >>= 1);
-
+
for (x = wid-1; x >= 0; x--) {
-
- to[0] = to[1] = to[2] = (data & 1) ? 0x00 : 0xff;
-
+/* g_print ("%c", (data & 1) ? '*' : ' '); */
+
+ to[0] = to[1] = to[2] = (data & 0x01) ? 0x00 : 0xff;
+
to -= 3;
bit++;
-
- if (bit > 7) {
+
+ if (bit > 7 && x > 0) {
from--;
data = from[0];
bit = 0;
data >>= 1;
}
}
+
+/* g_print ("\n"); */
}
/* explode gray image row into rgb components in pixbuf */
gint j;
guchar *from, *to;
guint w;
-
+
g_return_if_fail (context != NULL);
g_return_if_fail (context->dptr != NULL);
-
+
/* Expand grey->colour. Expand from the end of the
* memory down, so we can use the same buffer.
*/
}
}
-/* skip over whitespace in file from current pos. */
-/* also skips comments */
-/* returns pointer to first non-whitespace char hit or, or NULL if */
-/* we ran out of data w/o hitting a whitespace */
-/* internal pointer in inbuf isnt moved ahead in this case */
-static guchar *
-skip_ahead_whitespace (PnmIOBuffer *inbuf)
-{
- gboolean in_comment;
- guchar *ptr;
- guint num_left;
-
- g_return_val_if_fail (inbuf != NULL, NULL);
- g_return_val_if_fail (inbuf->next_byte != NULL, NULL);
-
- in_comment = FALSE;
- num_left = inbuf->bytes_left;
- ptr = inbuf->next_byte;
- while (num_left > 0) {
- if (in_comment) {
- if (*ptr == '\n')
- in_comment = FALSE;
- } else if (*ptr == '#') {
- in_comment = TRUE;
- } else if (!isspace (*ptr)) {
- inbuf->bytes_left -= (ptr-inbuf->next_byte);
- inbuf->next_byte = ptr;
- return ptr;
- }
- ptr ++;
- num_left--;
- }
- return NULL;
-}
-
-/* reads into buffer until we hit whitespace in file from current pos, */
-/* return NULL if ran out of data */
-/* advances inbuf if successful */
-static guchar *
-read_til_whitespace (PnmIOBuffer *inbuf, guchar *buf, guint size)
+/* skip over whitespace and comments in input buffer */
+static gint
+pnm_skip_whitespace (PnmIOBuffer *inbuf, GError **error)
{
- guchar *p;
- guchar *ptr;
- guint num_left;
-
- g_return_val_if_fail (inbuf != NULL, NULL);
- g_return_val_if_fail (inbuf->next_byte != NULL, NULL);
-
- p = buf;
- num_left = inbuf->bytes_left;
- ptr = inbuf->next_byte;
- while (num_left > 0 && (p-buf)+1 < size) {
- if (isspace (*ptr)) {
- *p = '\0';
- inbuf->bytes_left = num_left;
- inbuf->next_byte = ptr;
- return ptr;
- } else {
- *p = *ptr;
- p++;
- ptr++;
- num_left--;
+ register guchar *inptr;
+ guchar *inend;
+
+ g_return_val_if_fail (inbuf != NULL, PNM_FATAL_ERR);
+ g_return_val_if_fail (inbuf->byte != NULL, PNM_FATAL_ERR);
+
+ inend = inbuf->byte + inbuf->nbytes;
+ inptr = inbuf->byte;
+
+ for ( ; inptr < inend; inptr++) {
+ if (*inptr == '#') {
+ /* in comment - skip to the end of this line */
+ for ( ; *inptr != '\n' && inptr < inend; inptr++)
+ ;
+
+ if ( inptr == inend || *inptr != '\n' ) {
+ /* couldn't read whole comment */
+ return PNM_SUSPEND;
+ }
+
+ } else if (!g_ascii_isspace (*inptr)) {
+ inbuf->byte = inptr;
+ inbuf->nbytes = (guint) (inend - inptr);
+ return PNM_OK;
}
}
- return NULL;
+
+ inbuf->byte = inptr;
+ inbuf->nbytes = (guint) (inend - inptr);
+
+ return PNM_SUSPEND;
}
-/* read next number from buffer */
-/* -1 if failed, 0 if successful */
+/* read next number from buffer */
static gint
-read_next_number (PnmIOBuffer *inbuf, guint *value)
+pnm_read_next_value (PnmIOBuffer *inbuf, gint max_length, guint *value, GError **error)
{
- guchar *tmpptr;
- guchar *old_next_byte;
- gchar *errptr;
- guint old_bytes_left;
- guchar buf[128];
-
- g_return_val_if_fail (inbuf != NULL, -1);
- g_return_val_if_fail (inbuf->next_byte != NULL, -1);
- g_return_val_if_fail (value != NULL, -1);
-
- old_next_byte = inbuf->next_byte;
- old_bytes_left = inbuf->bytes_left;
-
- if ((tmpptr = skip_ahead_whitespace (inbuf)) == NULL)
- return -1;
-
- if ((tmpptr = read_til_whitespace (inbuf, buf, 128)) == NULL) {
- inbuf->next_byte = old_next_byte;
- inbuf->bytes_left = old_bytes_left;
- return -1;
- }
+ register guchar *inptr, *word, *p;
+ guchar *inend, buf[129];
+ gchar *endptr;
+ gint retval;
+ glong result;
- *value = strtol (buf, &errptr, 10);
+ g_return_val_if_fail (inbuf != NULL, PNM_FATAL_ERR);
+ g_return_val_if_fail (inbuf->byte != NULL, PNM_FATAL_ERR);
+ g_return_val_if_fail (value != NULL, PNM_FATAL_ERR);
+
+ if (max_length < 0)
+ max_length = 128;
- if (*errptr != '\0') {
- inbuf->next_byte = old_next_byte;
- inbuf->bytes_left = old_bytes_left;
- return -1;
+ /* skip white space */
+ if ((retval = pnm_skip_whitespace (inbuf, error)) != PNM_OK)
+ return retval;
+
+ inend = inbuf->byte + inbuf->nbytes;
+ inptr = inbuf->byte;
+
+ /* copy this pnm 'word' into a temp buffer */
+ for (p = inptr, word = buf; (p < inend) && !g_ascii_isspace (*p) && (*p != '#') && (p - inptr < max_length); p++, word++)
+ *word = *p;
+ *word = '\0';
+
+ /* hmmm, there must be more data to this 'word' */
+ if (p == inend || (!g_ascii_isspace (*p) && (*p != '#') && (p - inptr < max_length)))
+ return PNM_SUSPEND;
+
+ /* get the value */
+ result = strtol ((gchar *)buf, &endptr, 10);
+ if (*endptr != '\0' || result < 0 || result > G_MAXUINT) {
+ g_set_error_literal (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("PNM loader expected to find an integer, but didn't"));
+ return PNM_FATAL_ERR;
}
+ *value = result;
- return 0;
+ inbuf->byte = p;
+ inbuf->nbytes = (guint) (inend - p);
+
+ return PNM_OK;
}
/* returns PNM_OK, PNM_SUSPEND, or PNM_FATAL_ERR */
static gint
pnm_read_header (PnmLoaderContext *context)
{
- guchar *old_next_byte;
- guint old_bytes_left;
PnmIOBuffer *inbuf;
- guint w, h;
- gint rc;
- PnmFormat type;
-
- g_return_val_if_fail (context != NULL, PNM_FATAL_ERR);
-
- inbuf = &context->inbuf;
- old_bytes_left = inbuf->bytes_left;
- old_next_byte = inbuf->next_byte;
+ gint retval;
- /* file must start with a 'P' followed by a numeral */
- /* so loop till we get enough data to determine type*/
- if (inbuf->bytes_left < 2)
- return PNM_SUSPEND;
+ g_return_val_if_fail (context != NULL, PNM_FATAL_ERR);
- if (*inbuf->next_byte != 'P')
- return PNM_FATAL_ERR;
+ inbuf = &context->inbuf;
- switch (*(inbuf->next_byte+1)) {
- case '1':
- type = PNM_FORMAT_PBM;
- break;
- case '2':
- type = PNM_FORMAT_PGM;
- break;
- case '3':
- type = PNM_FORMAT_PPM;
- break;
- case '4':
- type = PNM_FORMAT_PBM_RAW;
- break;
- case '5':
- type = PNM_FORMAT_PGM_RAW;
- break;
- case '6':
- type = PNM_FORMAT_PPM_RAW;
- break;
- default:
- return PNM_FATAL_ERR;
+ if (!context->type) {
+ /* file must start with a 'P' followed by a numeral */
+ /* so loop till we get enough data to determine type */
+ if (inbuf->nbytes < 2)
+ return PNM_SUSPEND;
+
+ if (*inbuf->byte != 'P') {
+ g_set_error_literal (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("PNM file has an incorrect initial byte"));
+ return PNM_FATAL_ERR;
+ }
+
+ inbuf->byte++;
+ inbuf->nbytes--;
+
+ switch (*inbuf->byte) {
+ case '1':
+ context->type = PNM_FORMAT_PBM;
+ break;
+ case '2':
+ context->type = PNM_FORMAT_PGM;
+ break;
+ case '3':
+ context->type = PNM_FORMAT_PPM;
+ break;
+ case '4':
+ context->type = PNM_FORMAT_PBM_RAW;
+ break;
+ case '5':
+ context->type = PNM_FORMAT_PGM_RAW;
+ break;
+ case '6':
+ context->type = PNM_FORMAT_PPM_RAW;
+ break;
+ default:
+ g_set_error_literal (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("PNM file is not in a recognized PNM subformat"));
+ return PNM_FATAL_ERR;
+ }
+
+ if (!inbuf->nbytes)
+ return PNM_SUSPEND;
+
+ inbuf->byte++;
+ inbuf->nbytes--;
}
- g_print ("File format is %d\n", type);
-
- context->type = type;
-
- inbuf->next_byte += 2;
- inbuf->bytes_left -= 2;
-
- /* now read remainder of header */
- if ((rc = read_next_number (inbuf, &w))) {
- inbuf->next_byte = old_next_byte;
- inbuf->bytes_left = old_bytes_left;
- return PNM_SUSPEND;
+ if (!context->width) {
+ /* read the pixmap width */
+ guint width = 0;
+
+ retval = pnm_read_next_value (inbuf, -1, &width,
+ context->error);
+
+ if (retval != PNM_OK)
+ return retval;
+
+ if (!width) {
+ g_set_error_literal (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("PNM file has an image width of 0"));
+ return PNM_FATAL_ERR;
+ }
+
+ context->width = width;
}
- if ((rc = read_next_number (inbuf, &h))) {
- inbuf->next_byte = old_next_byte;
- inbuf->bytes_left = old_bytes_left;
- return PNM_SUSPEND;
+ if (!context->height) {
+ /* read the pixmap height */
+ guint height = 0;
+
+ retval = pnm_read_next_value (inbuf, -1, &height,
+ context->error);
+
+ if (retval != PNM_OK)
+ return retval;
+
+ if (!height) {
+ g_set_error_literal (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("PNM file has an image height of 0"));
+ return PNM_FATAL_ERR;
+ }
+
+ context->height = height;
}
- g_print ("Dimensions are %d x %d\n", w, h);
-
- context->width = w;
- context->height = h;
-
- switch (type) {
+ switch (context->type) {
case PNM_FORMAT_PPM:
case PNM_FORMAT_PPM_RAW:
case PNM_FORMAT_PGM:
case PNM_FORMAT_PGM_RAW:
- if ((rc = read_next_number (inbuf, &context->maxval)) < 0) {
- inbuf->next_byte = old_next_byte;
- inbuf->bytes_left = old_bytes_left;
- return PNM_SUSPEND;
+ if (!context->maxval) {
+ retval = pnm_read_next_value (inbuf, -1, &context->maxval,
+ context->error);
+
+ if (retval != PNM_OK)
+ return retval;
+
+ if (context->maxval == 0) {
+ g_set_error_literal (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Maximum color value in PNM file is 0"));
+ return PNM_FATAL_ERR;
+ }
+
+ if (context->maxval > 65535) {
+ g_set_error_literal (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Maximum color value in PNM file is too large"));
+ return PNM_FATAL_ERR;
+ }
+
}
-
- g_print ("Maximum component value is %d\n", context->maxval);
break;
default:
break;
}
-
+
return PNM_OK;
}
-
static gint
pnm_read_raw_scanline (PnmLoaderContext *context)
{
- guint numpix;
- guint numbytes, offset;
PnmIOBuffer *inbuf;
-
+ guint numbytes, offset;
+ guint numpix = 0;
+ guchar *dest;
+ guint i;
+
g_return_val_if_fail (context != NULL, PNM_FATAL_ERR);
-
+
inbuf = &context->inbuf;
-
+
switch (context->type) {
case PNM_FORMAT_PBM_RAW:
- numpix = inbuf->bytes_left * 8;
+ numpix = inbuf->nbytes * 8;
break;
case PNM_FORMAT_PGM_RAW:
- numpix = inbuf->bytes_left;
+ numpix = inbuf->nbytes;
break;
case PNM_FORMAT_PPM_RAW:
- numpix = inbuf->bytes_left/3;
+ numpix = inbuf->nbytes / 3;
break;
default:
- g_warning ("io-pnm.c: Illegal raw pnm type!\n");
+ g_set_error_literal (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Raw PNM image type is invalid"));
return PNM_FATAL_ERR;
- break;
}
+ if(context->maxval>255)
+ numpix/=2;
numpix = MIN (numpix, context->width - context->output_col);
- if (numpix == 0)
+ if (!numpix)
return PNM_SUSPEND;
- context->dptr = context->pixels +
- context->output_row * context->width * 3;
+ context->dptr = context->pixels + context->output_row * context->rowstride;
switch (context->type) {
case PNM_FORMAT_PBM_RAW:
- numbytes = numpix/8;
- offset = context->output_col/8;
+ numbytes = (numpix / 8) + ((numpix % 8) ? 1 : 0);
+ offset = context->output_col / 8;
break;
case PNM_FORMAT_PGM_RAW:
numbytes = numpix;
offset = context->output_col;
break;
case PNM_FORMAT_PPM_RAW:
- numbytes = numpix*3;
- offset = context->output_col*3;
+ numbytes = numpix * 3;
+ offset = context->output_col * 3;
break;
default:
- g_warning ("io-pnm.c: Illegal raw pnm type!\n");
- break;
+ g_set_error_literal (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Raw PNM image type is invalid"));
+ return PNM_FATAL_ERR;
}
+ if(context->maxval>255)
+ numbytes*=2;
- memcpy (context->dptr + offset, inbuf->next_byte, numbytes);
+ switch (context->type) {
+ case PNM_FORMAT_PBM_RAW:
+ dest = context->dptr + offset;
+ memcpy (dest, inbuf->byte, numbytes);
+ break;
+ case PNM_FORMAT_PGM_RAW:
+ case PNM_FORMAT_PPM_RAW:
+ dest = context->dptr + offset;
+
+ if (context->maxval == 255) {
+ /* special-case optimization */
+ memcpy (dest, inbuf->byte, numbytes);
+ } else if(context->maxval == 65535) {
+ /* optimized version of the next case */
+ for(i=0; i < numbytes ; i+=2) {
+ *dest++=inbuf->byte[i];
+ }
+ } else if(context->maxval > 255) {
+ /* scale down to 256 colors */
+ for(i=0; i < numbytes ; i+=2) {
+ guint v=inbuf->byte[i]*256+inbuf->byte[i+1];
+ *dest++=v*255/context->maxval;
+ }
+ } else {
+ for (i = 0; i < numbytes; i++) {
+ guchar *byte = inbuf->byte + i;
+
+ /* scale the color to an 8-bit color depth */
+ if (*byte > context->maxval)
+ *dest++ = 255;
+ else
+ *dest++ = (guchar) (255 * *byte / context->maxval);
+ }
+ }
+ break;
+ default:
+ g_set_error_literal (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Raw PNM image type is invalid"));
+ return PNM_FATAL_ERR;
+ }
- inbuf->next_byte += numbytes;
- inbuf->bytes_left -= numbytes;
+ inbuf->byte += numbytes;
+ inbuf->nbytes -= numbytes;
context->output_col += numpix;
if (context->output_col == context->width) {
- if ( context->type == PNM_FORMAT_PBM_RAW )
- explode_bitmap_into_buf(context);
- else if ( context->type == PNM_FORMAT_PGM_RAW )
+ if (context->type == PNM_FORMAT_PBM_RAW)
+ explode_bitmap_into_buf (context);
+ else if (context->type == PNM_FORMAT_PGM_RAW)
explode_gray_into_buf (context);
context->output_col = 0;
context->output_row++;
-
} else {
return PNM_SUSPEND;
}
-
+
return PNM_OK;
}
-
static gint
-pnm_read_ascii_scanline (PnmLoaderContext *context)
+pnm_read_ascii_mono_scanline (PnmLoaderContext *context)
{
- guint numpix;
- guint numbytes, offset;
- gint rc;
- guint value, numval, i;
- guchar data;
- guchar mask;
- guchar *old_next_byte, *dptr;
- guint old_bytes_left;
PnmIOBuffer *inbuf;
+ guint value;
+ gint retval;
+ guchar *dptr;
+ gint max_length;
- g_return_val_if_fail (context != NULL, PNM_FATAL_ERR);
+ if (context->type == PNM_FORMAT_PBM)
+ max_length = 1;
+ else
+ max_length = -1;
inbuf = &context->inbuf;
- context->dptr = context->pixels +
- context->output_row * context->width * 3;
+ context->dptr = context->pixels + context->output_row * context->rowstride;
- switch (context->type) {
- case PNM_FORMAT_PBM:
- mask = 0x80;
- data = 0;
- numval = 8;
- break;
- case PNM_FORMAT_PGM:
- numval = 1;
- break;
- case PNM_FORMAT_PPM:
- numval = 3;
- break;
-
- default:
- g_warning ("Can't happen\n");
- return PNM_FATAL_ERR;
- }
+ dptr = context->dptr + context->output_col * 3;
- old_next_byte = inbuf->next_byte;
- old_bytes_left = inbuf->bytes_left;
- dptr = context->dptr;
+ while (TRUE) {
+ retval = pnm_read_next_value (inbuf, max_length, &value, context->error);
+ if (retval != PNM_OK)
+ return retval;
- for (i=0; i<numval; i++) {
- if ((rc = read_next_number (inbuf, &value))) {
- inbuf->next_byte = old_next_byte;
- inbuf->bytes_left = old_bytes_left;
- return PNM_SUSPEND;
+ if (context->type == PNM_FORMAT_PBM) {
+ value = value ? 0 : 0xff;
}
- printf ("0x%x ", value);
- fflush (stdout);
-
- switch (context->type) {
- case PNM_FORMAT_PBM:
- if (value)
- data |= mask;
- mask >>= 1;
-
- break;
- case PNM_FORMAT_PGM:
- *dptr++ = (guchar)(255.0*((double)value/(double)context->maxval));
- break;
- case PNM_FORMAT_PPM:
- *dptr++ = (guchar)(255.0*((double)value/(double)context->maxval));
- break;
- default:
- g_warning ("io-pnm.c: Illegal raw pnm type!\n");
+ else {
+ /* scale the color up or down to an 8-bit color depth */
+ if (value > context->maxval)
+ value = 255;
+ else
+ value = (guchar)(255 * value / context->maxval);
+ }
+
+ *dptr++ = value;
+ *dptr++ = value;
+ *dptr++ = value;
+
+ context->output_col++;
+
+ if (context->output_col == context->width) {
+ context->output_col = 0;
+ context->output_row++;
break;
}
}
- if (context->type == PNM_FORMAT_PBM)
- *dptr++ = value;
+ return PNM_OK;
+}
- context->output_col++;
- if (context->output_col == context->width) {
- if ( context->type == PNM_FORMAT_PBM_RAW )
- explode_bitmap_into_buf(context);
- else if ( context->type == PNM_FORMAT_PGM_RAW )
- explode_gray_into_buf (context);
+static gint
+pnm_read_ascii_color_scanline (PnmLoaderContext *context)
+{
+ PnmIOBuffer *inbuf;
+ guint value, i;
+ guchar *dptr;
+ gint retval;
+
+ inbuf = &context->inbuf;
+
+ context->dptr = context->pixels + context->output_row * context->rowstride;
+
+ dptr = context->dptr + context->output_col * 3 + context->scan_state;
+
+ while (TRUE) {
+ for (i = context->scan_state; i < 3; i++) {
+ retval = pnm_read_next_value (inbuf, -1, &value, context->error);
+ if (retval != PNM_OK) {
+ /* save state and return */
+ context->scan_state = i;
+ return retval;
+ }
+
+ if (value > context->maxval)
+ *dptr++ = 255;
+ else
+ *dptr++ = (guchar)(255 * value / context->maxval);
+ }
- context->output_col = 0;
- context->output_row++;
+ context->scan_state = 0;
+ context->output_col++;
- } else {
- return PNM_SUSPEND;
+ if (context->output_col == context->width) {
+ context->output_col = 0;
+ context->output_row++;
+ break;
+ }
}
-
+
return PNM_OK;
}
-/* returns 1 if a scanline was converted, 0 means we ran out of data */
+/* returns 1 if a scanline was converted, 0 means we ran out of data */
static gint
pnm_read_scanline (PnmLoaderContext *context)
{
- gint rc;
-
+ gint retval;
+
g_return_val_if_fail (context != NULL, PNM_FATAL_ERR);
-
+
/* read in image data */
/* for raw formats this is trivial */
switch (context->type) {
case PNM_FORMAT_PBM_RAW:
case PNM_FORMAT_PGM_RAW:
case PNM_FORMAT_PPM_RAW:
- rc = pnm_read_raw_scanline (context);
- if (rc == PNM_SUSPEND)
- return rc;
+ retval = pnm_read_raw_scanline (context);
+ if (retval != PNM_OK)
+ return retval;
break;
-
case PNM_FORMAT_PBM:
case PNM_FORMAT_PGM:
+ retval = pnm_read_ascii_mono_scanline (context);
+ if (retval != PNM_OK)
+ return retval;
+ break;
case PNM_FORMAT_PPM:
-#if 0
-
- rc = pnm_read_ascii_scanline (context);
- if (rc == PNM_SUSPEND)
- return rc;
+ retval = pnm_read_ascii_color_scanline (context);
+ if (retval != PNM_OK)
+ return retval;
break;
-#endif
-
-
default:
- g_print ("Cannot load these image types (yet)\n");
+ g_set_error_literal (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
+ _("PNM image loader does not support this PNM subformat"));
+
return PNM_FATAL_ERR;
}
-
+
return PNM_OK;
}
/* Shared library entry point */
-GdkPixbuf *
-image_load (FILE *f)
+static GdkPixbuf *
+gdk_pixbuf__pnm_image_load (FILE *f, GError **error)
{
- guint nbytes;
- gint rc;
-
PnmLoaderContext context;
PnmIOBuffer *inbuf;
-
-
-#if 0
- G_BREAKPOINT();
-#endif
-
+ gint nbytes;
+ gint retval;
+
/* pretend to be doing progressive loading */
- context.updated_func = context.prepared_func = NULL;
+ context.updated_func = NULL;
+ context.prepared_func = NULL;
context.user_data = NULL;
- context.inbuf.bytes_left = 0;
- context.inbuf.next_byte = NULL;
- context.pixels = context.pixbuf = NULL;
- context.got_header = context.did_prescan = FALSE;
-
+ context.type = 0;
+ context.inbuf.nbytes = 0;
+ context.inbuf.byte = NULL;
+ context.width = 0;
+ context.height = 0;
+ context.maxval = 0;
+ context.pixels = NULL;
+ context.pixbuf = NULL;
+ context.got_header = FALSE;
+ context.did_prescan = FALSE;
+ context.scan_state = 0;
+ context.error = error;
+
inbuf = &context.inbuf;
-
+
while (TRUE) {
- guint num_to_read;
-
+ guint num_to_read;
+
/* keep buffer as full as possible */
- num_to_read = PNM_BUF_SIZE - inbuf->bytes_left;
-
- if (inbuf->next_byte != NULL && inbuf->bytes_left > 0)
- memmove (inbuf->buffer, inbuf->next_byte,
- inbuf->bytes_left);
-
- nbytes = fread (inbuf->buffer+inbuf->bytes_left,
- 1, num_to_read, f);
- inbuf->bytes_left += nbytes;
- inbuf->next_byte = inbuf->buffer;
+ num_to_read = PNM_BUF_SIZE - inbuf->nbytes;
- /* ran out of data and we haven't exited main loop */
- /* something is wrong */
- if (inbuf->bytes_left == 0) {
- if (context.pixels)
- g_free (context.pixels);
- g_warning ("io-pnm.c: Ran out of data...\n");
+ if (inbuf->byte != NULL && inbuf->nbytes > 0)
+ memmove (inbuf->buffer, inbuf->byte, inbuf->nbytes);
+
+ nbytes = fread (inbuf->buffer + inbuf->nbytes, 1, num_to_read, f);
+
+ /* error checking */
+ if (nbytes == 0) {
+ /* we ran out of data? */
+ if (context.pixbuf)
+ g_object_unref (context.pixbuf);
+ g_set_error_literal (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Premature end-of-file encountered"));
return NULL;
}
-
+
+ inbuf->nbytes += nbytes;
+ inbuf->byte = inbuf->buffer;
+
/* get header if needed */
if (!context.got_header) {
-
- rc = pnm_read_header (&context);
- if (rc == PNM_FATAL_ERR)
+ retval = pnm_read_header (&context);
+ if (retval == PNM_FATAL_ERR)
return NULL;
- else if (rc == PNM_SUSPEND)
+ else if (retval == PNM_SUSPEND)
continue;
-
+
context.got_header = TRUE;
}
-
+
/* scan until we hit image data */
if (!context.did_prescan) {
-
- g_print ("doing prescan\n");
- if (skip_ahead_whitespace (inbuf) == NULL)
- continue;
-
+ switch (context.type) {
+ case PNM_FORMAT_PBM_RAW:
+ case PNM_FORMAT_PGM_RAW:
+ case PNM_FORMAT_PPM_RAW:
+ if (inbuf->nbytes <= 0)
+ continue;
+ /* raw formats require exactly one whitespace */
+ if (!g_ascii_isspace(*(inbuf->byte)))
+ {
+ g_set_error_literal (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Raw PNM formats require exactly one whitespace before sample data"));
+ return NULL;
+ }
+ inbuf->nbytes--;
+ inbuf->byte++;
+ break;
+ default:
+ retval = pnm_skip_whitespace (inbuf,
+ context.error);
+ if (retval == PNM_FATAL_ERR)
+ return NULL;
+ else if (retval == PNM_SUSPEND)
+ continue;
+ break;
+ }
context.did_prescan = TRUE;
context.output_row = 0;
context.output_col = 0;
-
- context.pixels = g_malloc (context.height *
- context.width * 3);
- if (!context.pixels)
+
+ context.pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
+ context.width, context.height);
+
+ if (!context.pixbuf) {
+ /* Failed to allocate memory */
+ g_set_error_literal (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+ _("Cannot allocate memory for loading PNM image"));
return NULL;
+ }
- g_print ("prescan complete\n");
+ context.rowstride = context.pixbuf->rowstride;
+ context.pixels = context.pixbuf->pixels;
}
-
+
/* if we got here we're reading image data */
while (context.output_row < context.height) {
- rc = pnm_read_scanline (&context);
-
- if (rc == PNM_SUSPEND) {
+ retval = pnm_read_scanline (&context);
+
+ if (retval == PNM_SUSPEND) {
break;
- } else if (rc == PNM_FATAL_ERR) {
- if (context.pixels)
- g_free (context.pixels);
- g_warning ("io-pnm.c: error reading rows..\n");
+ } else if (retval == PNM_FATAL_ERR) {
+ if (context.pixbuf)
+ g_object_unref (context.pixbuf);
+
return NULL;
}
}
-
+
if (context.output_row < context.height)
continue;
else
break;
}
-
- return gdk_pixbuf_new_from_data (context.pixels, ART_PIX_RGB, FALSE,
- context.width, context.height,
- context.width * 3, free_buffer, NULL);
-
-}
-
-#if 0
-/**** Progressive image loading handling *****/
-
-/* these routines required because we are acting as a source manager for */
-/* libjpeg. */
-static void
-init_source (j_decompress_ptr cinfo)
-{
- my_src_ptr src = (my_src_ptr) cinfo->src;
-
- src->skip_next = 0;
-}
-
-
-static void
-term_source (j_decompress_ptr cinfo)
-{
- /* XXXX - probably should scream something has happened */
-}
-
-
-/* for progressive loading (called "I/O Suspension" by libjpeg docs) */
-/* we do nothing except return "FALSE" */
-static boolean
-fill_input_buffer (j_decompress_ptr cinfo)
-{
- return FALSE;
-}
-
-
-static void
-skip_input_data (j_decompress_ptr cinfo, long num_bytes)
-{
- my_src_ptr src = (my_src_ptr) cinfo->src;
- long num_can_do;
-
- /* move as far as we can into current buffer */
- /* then set skip_next to catch the rest */
- if (num_bytes > 0) {
- num_can_do = MIN (src->pub.bytes_in_buffer, num_bytes);
- src->pub.next_input_byte += (size_t) num_can_do;
- src->pub.bytes_in_buffer -= (size_t) num_can_do;
-
- src->skip_next = num_bytes - num_can_do;
- }
+
+ return context.pixbuf;
}
-
/*
* func - called when we have pixmap created (but no image data)
* user_data - passed as arg 1 to func
* return context (opaque to user)
*/
-gpointer
-image_begin_load (ModulePreparedNotifyFunc prepared_func,
- ModuleUpdatedNotifyFunc updated_func,
- gpointer user_data)
+static gpointer
+gdk_pixbuf__pnm_image_begin_load (GdkPixbufModuleSizeFunc size_func,
+ GdkPixbufModulePreparedFunc prepared_func,
+ GdkPixbufModuleUpdatedFunc updated_func,
+ gpointer user_data,
+ GError **error)
{
- JpegProgContext *context;
- my_source_mgr *src;
-
- context = g_new0 (JpegProgContext, 1);
+ PnmLoaderContext *context;
+
+ context = g_try_malloc (sizeof (PnmLoaderContext));
+ if (!context) {
+ g_set_error_literal (error, GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+ _("Insufficient memory to load PNM context struct"));
+ return NULL;
+ }
+ memset (context, 0, sizeof (PnmLoaderContext));
+ context->size_func = size_func;
context->prepared_func = prepared_func;
context->updated_func = updated_func;
context->user_data = user_data;
+ context->width = 0;
+ context->height = 0;
+ context->maxval = 0;
context->pixbuf = NULL;
+ context->pixels = NULL;
context->got_header = FALSE;
context->did_prescan = FALSE;
- context->src_initialized = FALSE;
-
- /* create libjpeg structures */
- jpeg_create_decompress (&context->cinfo);
-
- context->cinfo.src = (struct jpeg_source_mgr *) g_new0 (my_source_mgr, 1);
- src = (my_src_ptr) context->cinfo.src;
-
- context->cinfo.err = jpeg_std_error (&context->jerr.pub);
-
- src = (my_src_ptr) context->cinfo.src;
- src->pub.init_source = init_source;
- src->pub.fill_input_buffer = fill_input_buffer;
- src->pub.skip_input_data = skip_input_data;
- src->pub.resync_to_restart = jpeg_resync_to_restart;
- src->pub.term_source = term_source;
- src->pub.bytes_in_buffer = 0;
- src->pub.next_input_byte = NULL;
+ context->scan_state = 0;
+
+ context->inbuf.nbytes = 0;
+ context->inbuf.byte = NULL;
+ context->error = error;
+
return (gpointer) context;
}
*
* free context, unref gdk_pixbuf
*/
-void
-image_stop_load (gpointer data)
+static gboolean
+gdk_pixbuf__pnm_image_stop_load (gpointer data,
+ GError **error)
{
- JpegProgContext *context = (JpegProgContext *) data;
-
- g_return_if_fail (context != NULL);
-
+ PnmLoaderContext *context = (PnmLoaderContext *) data;
+ gboolean retval = TRUE;
+
+ g_return_val_if_fail (context != NULL, TRUE);
+
if (context->pixbuf)
- gdk_pixbuf_unref (context->pixbuf);
-
- jpeg_finish_decompress(&context->cinfo);
- jpeg_destroy_decompress(&context->cinfo);
+ g_object_unref (context->pixbuf);
- if (context->cinfo.src) {
- my_src_ptr src = (my_src_ptr) context->cinfo.src;
-
- g_free (src);
+#if 0
+ /* We should ignore trailing newlines and we can't
+ generally complain about trailing stuff at all, since
+ pnm allows to put multiple images in a file
+ */
+ if (context->inbuf.nbytes > 0) {
+ g_set_error_literal (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Unexpected end of PNM image data"));
+ retval = FALSE;
}
-
+#endif
+
g_free (context);
-}
-
-
+ return retval;
+}
/*
* context - from image_begin_load
*
* append image data onto inrecrementally built output image
*/
-gboolean
-image_load_increment (gpointer data, guchar *buf, guint size)
+static gboolean
+gdk_pixbuf__pnm_image_load_increment (gpointer data,
+ const guchar *buf, guint size,
+ GError **error)
{
- JpegProgContext *context = (JpegProgContext *)data;
- struct jpeg_decompress_struct *cinfo;
- my_src_ptr src;
- guint num_left, num_copy;
- guint last_bytes_left;
- guint spinguard;
- guchar *bufhd;
-
+ PnmLoaderContext *context = (PnmLoaderContext *)data;
+ PnmIOBuffer *inbuf;
+ const guchar *bufhd;
+ guint num_left, spinguard;
+ gint retval;
+
g_return_val_if_fail (context != NULL, FALSE);
g_return_val_if_fail (buf != NULL, FALSE);
- src = (my_src_ptr) context->cinfo.src;
-
- cinfo = &context->cinfo;
-
- /* XXXXXXX (drmike) - loop(s) below need to be recoded now I
- * have a grasp of what the flow needs to be!
- */
-
-
- /* skip over data if requested, handle unsigned int sizes cleanly */
- /* only can happen if we've already called jpeg_get_header once */
- if (context->src_initialized && src->skip_next) {
- if (src->skip_next > size) {
- src->skip_next -= size;
- return TRUE;
- } else {
- num_left = size - src->skip_next;
- bufhd = buf + src->skip_next;
- src->skip_next = 0;
- }
- } else {
- num_left = size;
- bufhd = buf;
- }
-
-
- last_bytes_left = 0;
+ context->error = error;
+
+ bufhd = buf;
+ inbuf = &context->inbuf;
+
+ num_left = size;
spinguard = 0;
- while (src->pub.bytes_in_buffer != 0 || num_left != 0) {
-
- /* handle any data from caller we haven't processed yet */
- if (num_left > 0) {
- if(src->pub.bytes_in_buffer &&
- src->pub.next_input_byte != src->buffer)
- memmove(src->buffer, src->pub.next_input_byte,
- src->pub.bytes_in_buffer);
-
-
- num_copy = MIN (JPEG_PROG_BUF_SIZE - src->pub.bytes_in_buffer,
- num_left);
-
-/* if (num_copy == 0)
- g_error ("Buffer overflow!");
-*/
- memcpy(src->buffer + src->pub.bytes_in_buffer, bufhd,num_copy);
- src->pub.next_input_byte = src->buffer;
- src->pub.bytes_in_buffer += num_copy;
- bufhd += num_copy;
- num_left -= num_copy;
- } else {
- /* did anything change from last pass, if not return */
- if (last_bytes_left == 0)
- last_bytes_left = src->pub.bytes_in_buffer;
- else if (src->pub.bytes_in_buffer == last_bytes_left)
- spinguard++;
- else
- last_bytes_left = src->pub.bytes_in_buffer;
- }
-
- /* should not go through twice and not pull bytes out of buf */
- if (spinguard > 2)
+ while (TRUE) {
+ guint num_to_copy;
+
+ /* keep buffer as full as possible */
+ num_to_copy = MIN (PNM_BUF_SIZE - inbuf->nbytes, num_left);
+
+ if (num_to_copy == 0)
+ spinguard++;
+
+ if (spinguard > 1)
return TRUE;
-
- /* try to load jpeg header */
+
+ if (inbuf->byte != NULL && inbuf->nbytes > 0)
+ memmove (inbuf->buffer, inbuf->byte, inbuf->nbytes);
+
+ memcpy (inbuf->buffer + inbuf->nbytes, bufhd, num_to_copy);
+ bufhd += num_to_copy;
+ inbuf->nbytes += num_to_copy;
+ inbuf->byte = inbuf->buffer;
+ num_left -= num_to_copy;
+
+ /* ran out of data and we haven't exited main loop */
+ if (inbuf->nbytes == 0)
+ return TRUE;
+
+ /* get header if needed */
if (!context->got_header) {
- int rc;
-
- rc = jpeg_read_header (cinfo, TRUE);
- context->src_initialized = TRUE;
-
- if (rc == JPEG_SUSPENDED)
+ retval = pnm_read_header (context);
+
+ if (retval == PNM_FATAL_ERR)
+ return FALSE;
+ else if (retval == PNM_SUSPEND)
continue;
-
+
context->got_header = TRUE;
+ }
- if (jpeg_has_multiple_scans (cinfo)) {
- g_print ("io-jpeg.c: Does not currently "
- "support progressive jpeg files.\n");
+ if (context->size_func) {
+ gint w = context->width;
+ gint h = context->height;
+ (*context->size_func) (&w, &h, context->user_data);
+
+ if (w == 0 || h == 0)
return FALSE;
+ }
+
+
+ /* scan until we hit image data */
+ if (!context->did_prescan) {
+ switch (context->type) {
+ case PNM_FORMAT_PBM_RAW:
+ case PNM_FORMAT_PGM_RAW:
+ case PNM_FORMAT_PPM_RAW:
+ if (inbuf->nbytes <= 0)
+ continue;
+ /* raw formats require exactly one whitespace */
+ if (!g_ascii_isspace(*(inbuf->byte)))
+ {
+ g_set_error_literal (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Raw PNM formats require exactly one whitespace before sample data"));
+ return FALSE;
+ }
+ inbuf->nbytes--;
+ inbuf->byte++;
+ break;
+ default:
+ retval = pnm_skip_whitespace (inbuf,
+ context->error);
+ if (retval == PNM_FATAL_ERR)
+ return FALSE;
+ else if (retval == PNM_SUSPEND)
+ continue;
+ break;
}
-
- context->pixbuf = gdk_pixbuf_new(ART_PIX_RGB,
- /*have_alpha*/ FALSE,
- 8,
- cinfo->image_width,
- cinfo->image_height);
-
+ context->did_prescan = TRUE;
+ context->output_row = 0;
+ context->output_col = 0;
+
+ context->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+ FALSE,
+ 8,
+ context->width,
+ context->height);
+
if (context->pixbuf == NULL) {
- /* Failed to allocate memory */
- g_error ("Couldn't allocate gdkpixbuf");
+ g_set_error_literal (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+ _("Insufficient memory to load PNM file"));
+ return FALSE;
}
-
- /* Use pixbuf buffer to store decompressed data */
- context->dptr = context->pixbuf->art_pixbuf->pixels;
-
+
+ context->pixels = context->pixbuf->pixels;
+ context->rowstride = context->pixbuf->rowstride;
+
/* Notify the client that we are ready to go */
- (* context->prepared_func) (context->pixbuf,
- context->user_data);
-
- } else if (!context->did_prescan) {
- int rc;
-
- /* start decompression */
- rc = jpeg_start_decompress (cinfo);
- cinfo->do_fancy_upsampling = FALSE;
- cinfo->do_block_smoothing = FALSE;
-
- if (rc == JPEG_SUSPENDED)
- continue;
-
- context->did_prescan = TRUE;
- } else {
- /* we're decompressing so feed jpeg lib scanlines */
- guchar *lines[4];
- guchar **lptr;
- guchar *rowptr, *p;
- gint nlines, i;
- gint start_scanline;
-
- /* keep going until we've done all scanlines */
- while (cinfo->output_scanline < cinfo->output_height) {
- start_scanline = cinfo->output_scanline;
- lptr = lines;
- rowptr = context->dptr;
- for (i=0; i < cinfo->rec_outbuf_height; i++) {
- *lptr++ = rowptr;
- rowptr += context->pixbuf->art_pixbuf->rowstride;;
- }
-
-#ifdef IO_JPEG_DEBUG_GREY
- for (p=lines[0],i=0; i< context->pixbuf->art_pixbuf->rowstride;i++, p++)
- *p = 0;
-
-#endif
- nlines = jpeg_read_scanlines (cinfo, lines,
- cinfo->rec_outbuf_height);
- if (nlines == 0)
- break;
-
- /* handle gray */
- if (cinfo->output_components == 1)
- explode_gray_into_buf (cinfo, lines);
-
- context->dptr += nlines * context->pixbuf->art_pixbuf->rowstride;
-
+ if (context->prepared_func)
+ (* context->prepared_func) (context->pixbuf,
+ NULL,
+ context->user_data);
+ }
+
+ /* if we got here we're reading image data */
+ while (context->output_row < context->height) {
+ retval = pnm_read_scanline (context);
+
+ if (retval == PNM_SUSPEND) {
+ break;
+ } else if (retval == PNM_FATAL_ERR) {
+ return FALSE;
+ } else if (retval == PNM_OK && context->updated_func) {
/* send updated signal */
(* context->updated_func) (context->pixbuf,
- context->user_data,
- 0,
- cinfo->output_scanline-1,
- cinfo->image_width,
- nlines);
-
-#undef DEBUG_JPEG_PROGRESSIVE
-#ifdef DEBUG_JPEG_PROGRESSIVE
-
- if (start_scanline != cinfo->output_scanline)
- g_print("jpeg: Input pass=%2d, next input scanline=%3d,"
- " emitted %3d - %3d\n",
- cinfo->input_scan_number, cinfo->input_iMCU_row * 16,
- start_scanline, cinfo->output_scanline - 1);
-
-
-
- g_print ("Scanline %d of %d - ",
- cinfo->output_scanline,
- cinfo->output_height);
-/* g_print ("rec_height %d -", cinfo->rec_outbuf_height); */
- g_print ("Processed %d lines - bytes left = %d\n",
- nlines, cinfo->src->bytes_in_buffer);
-#endif
+ 0,
+ context->output_row-1,
+ context->width,
+ 1,
+ context->user_data);
}
- /* did entire image */
- if (cinfo->output_scanline >= cinfo->output_height)
- return TRUE;
- else
- continue;
}
+
+ if (context->output_row < context->height)
+ continue;
+ else
+ break;
}
-
+
return TRUE;
}
+
+#ifndef INCLUDE_pnm
+#define MODULE_ENTRY(function) G_MODULE_EXPORT void function
+#else
+#define MODULE_ENTRY(function) void _gdk_pixbuf__pnm_ ## function
#endif
+
+MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module)
+{
+ module->load = gdk_pixbuf__pnm_image_load;
+ module->begin_load = gdk_pixbuf__pnm_image_begin_load;
+ module->stop_load = gdk_pixbuf__pnm_image_stop_load;
+ module->load_increment = gdk_pixbuf__pnm_image_load_increment;
+}
+
+MODULE_ENTRY (fill_info) (GdkPixbufFormat *info)
+{
+ static GdkPixbufModulePattern signature[] = {
+ { "P1", NULL, 100 },
+ { "P2", NULL, 100 },
+ { "P3", NULL, 100 },
+ { "P4", NULL, 100 },
+ { "P5", NULL, 100 },
+ { "P6", NULL, 100 },
+ { NULL, NULL, 0 }
+ };
+ static gchar * mime_types[] = {
+ "image/x-portable-anymap",
+ "image/x-portable-bitmap",
+ "image/x-portable-graymap",
+ "image/x-portable-pixmap",
+ NULL
+ };
+ static gchar * extensions[] = {
+ "pnm",
+ "pbm",
+ "pgm",
+ "ppm",
+ NULL
+ };
+
+ info->name = "pnm";
+ info->signature = signature;
+ info->description = N_("The PNM/PBM/PGM/PPM image format family");
+ info->mime_types = mime_types;
+ info->extensions = extensions;
+ info->flags = GDK_PIXBUF_FORMAT_THREADSAFE;
+ info->license = "LGPL";
+}