X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gdk-pixbuf%2Fio-pnm.c;h=2f9fbaa729917fdfed6c40fe39d213dd2fd8660e;hb=affea672d2d450b6ad5b5435356458080e14d7be;hp=b568b4bccc357efff5c8062764f3dfdce1e100fd;hpb=5fcc15abbeea4b9351a99d0171a8042c0fe8ff7b;p=~andy%2Fgtk diff --git a/gdk-pixbuf/io-pnm.c b/gdk-pixbuf/io-pnm.c index b568b4bcc..2f9fbaa72 100644 --- a/gdk-pixbuf/io-pnm.c +++ b/gdk-pixbuf/io-pnm.c @@ -22,7 +22,7 @@ * Boston, MA 02111-1307, USA. */ -#include +#include "config.h" #include #include #include @@ -108,19 +108,17 @@ explode_bitmap_into_buf (PnmLoaderContext *context) 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); to = dptr + (wid - 1) * 3; -/* bit = 7 - (((y+1)*wid-1) % 8); */ bit = 7 - ((wid-1) % 8); /* get first byte and align properly */ @@ -135,7 +133,7 @@ explode_bitmap_into_buf (PnmLoaderContext *context) to -= 3; bit++; - if (bit > 7) { + if (bit > 7 && x > 0) { from--; data = from[0]; bit = 0; @@ -245,11 +243,11 @@ pnm_read_next_value (PnmIOBuffer *inbuf, gint max_length, guint *value, GError * /* get the value */ result = strtol (buf, &endptr, 10); - if (*endptr != '\0' || result < 0) { - g_set_error (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("PNM loader expected to find an integer, but didn't")); + 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; @@ -278,10 +276,10 @@ pnm_read_header (PnmLoaderContext *context) return PNM_SUSPEND; if (*inbuf->byte != 'P') { - g_set_error (context->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("PNM file has an incorrect initial byte")); + 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; } @@ -308,10 +306,10 @@ pnm_read_header (PnmLoaderContext *context) context->type = PNM_FORMAT_PPM_RAW; break; default: - g_set_error (context->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("PNM file is not in a recognized PNM subformat")); + 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; } @@ -333,10 +331,10 @@ pnm_read_header (PnmLoaderContext *context) return retval; if (!width) { - g_set_error (context->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("PNM file has an image width of 0")); + 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; } @@ -354,10 +352,10 @@ pnm_read_header (PnmLoaderContext *context) return retval; if (!height) { - g_set_error (context->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("PNM file has an image height of 0")); + 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; } @@ -377,28 +375,21 @@ pnm_read_header (PnmLoaderContext *context) return retval; if (context->maxval == 0) { - g_set_error (context->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("Maximum color value in PNM file is 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 (context->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("Maximum color value in PNM file is too large")); + 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; } - if (context->maxval > 255) { - g_set_error (context->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("Cannot handle PNM files with maximum color values greater than 255")); - return PNM_FATAL_ERR; - } } break; default: @@ -432,12 +423,14 @@ pnm_read_raw_scanline (PnmLoaderContext *context) numpix = inbuf->nbytes / 3; break; default: - g_set_error (context->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("Raw PNM image type is invalid")); + 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) + numpix/=2; numpix = MIN (numpix, context->width - context->output_col); @@ -460,12 +453,14 @@ pnm_read_raw_scanline (PnmLoaderContext *context) offset = context->output_col * 3; break; default: - g_set_error (context->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("Raw PNM image type is invalid")); + 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; switch (context->type) { case PNM_FORMAT_PBM_RAW: @@ -479,6 +474,17 @@ pnm_read_raw_scanline (PnmLoaderContext *context) 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; @@ -492,10 +498,10 @@ pnm_read_raw_scanline (PnmLoaderContext *context) } break; default: - g_set_error (context->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("Raw PNM image type is invalid")); + g_set_error_literal (context->error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Raw PNM image type is invalid")); return PNM_FATAL_ERR; } @@ -519,109 +525,90 @@ pnm_read_raw_scanline (PnmLoaderContext *context) } static gint -pnm_read_ascii_scanline (PnmLoaderContext *context) +pnm_read_ascii_mono_scanline (PnmLoaderContext *context) { PnmIOBuffer *inbuf; - guint offset; - guint value, numval, i; - guchar data; - guchar mask; - guchar *dptr; + guint value; gint retval; + guchar *dptr; gint max_length; - - g_return_val_if_fail (context != NULL, PNM_FATAL_ERR); - - data = mask = 0; - - inbuf = &context->inbuf; - - context->dptr = context->pixels + context->output_row * context->rowstride; - - switch (context->type) { - case PNM_FORMAT_PBM: + + if (context->type == PNM_FORMAT_PBM) max_length = 1; - numval = MIN (8, context->width - context->output_col); - offset = context->output_col / 8; - break; - case PNM_FORMAT_PGM: - max_length = -1; - numval = 1; - offset = context->output_col; - break; - case PNM_FORMAT_PPM: + else max_length = -1; - numval = 3; - offset = context->output_col * 3; - break; - - default: - g_set_error (context->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("PNM image format is invalid")); - return PNM_FATAL_ERR; + inbuf = &context->inbuf; + + context->dptr = context->pixels + context->output_row * context->rowstride; + + dptr = context->dptr + context->output_col * 3; + + while (TRUE) { + retval = pnm_read_next_value (inbuf, max_length, &value, context->error); + if (retval != PNM_OK) + return retval; + + if (context->type == PNM_FORMAT_PBM) { + value = value ? 0 : 0xff; + } + 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; + } } + + return PNM_OK; +} + +static gint +pnm_read_ascii_color_scanline (PnmLoaderContext *context) +{ + PnmIOBuffer *inbuf; + guint value, i; + guchar *dptr; + gint retval; - dptr = context->dptr + offset + context->scan_state; + inbuf = &context->inbuf; + + context->dptr = context->pixels + context->output_row * context->rowstride; + + dptr = context->dptr + context->output_col * 3 + context->scan_state; while (TRUE) { - if (context->type == PNM_FORMAT_PBM) { - mask = 0x80; - data = 0; - numval = MIN (8, context->width - context->output_col); - } - - for (i = context->scan_state; i < numval; i++) { - retval = pnm_read_next_value (inbuf, max_length, - &value, context->error); + 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; } - switch (context->type) { - case PNM_FORMAT_PBM: - if (value) - data |= mask; - mask >>= 1; - - break; - case PNM_FORMAT_PGM: - case PNM_FORMAT_PPM: - /* scale the color to an 8-bit color depth */ - if (value > context->maxval) - *dptr++ = 255; - else - *dptr++ = (guchar)(255 * value / context->maxval); - break; - default: - g_set_error (context->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("PNM image format is invalid")); - return PNM_FATAL_ERR; - break; - } + if (value > context->maxval) + *dptr++ = 255; + else + *dptr++ = (guchar)(255 * value / context->maxval); } context->scan_state = 0; - - if (context->type == PNM_FORMAT_PBM) { - *dptr++ = data; - context->output_col += numval; - } else { - context->output_col++; - } + context->output_col++; if (context->output_col == context->width) { - if (context->type == PNM_FORMAT_PBM) - explode_bitmap_into_buf (context); - else if (context->type == PNM_FORMAT_PGM) - explode_gray_into_buf (context); - context->output_col = 0; context->output_row++; break; @@ -651,16 +638,20 @@ pnm_read_scanline (PnmLoaderContext *context) 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: - retval = pnm_read_ascii_scanline (context); + retval = pnm_read_ascii_color_scanline (context); if (retval != PNM_OK) return retval; break; default: - g_set_error (context->error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_UNKNOWN_TYPE, - _("PNM image loader does not support this PNM subformat")); + 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; } @@ -712,10 +703,10 @@ gdk_pixbuf__pnm_image_load (FILE *f, GError **error) /* we ran out of data? */ if (context.pixbuf) g_object_unref (context.pixbuf); - g_set_error (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("Premature end-of-file encountered")); + g_set_error_literal (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Premature end-of-file encountered")); return NULL; } @@ -744,10 +735,10 @@ gdk_pixbuf__pnm_image_load (FILE *f, GError **error) /* raw formats require exactly one whitespace */ if (!g_ascii_isspace(*(inbuf->byte))) { - g_set_error (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("Raw PNM formats require exactly one whitespace before sample data")); + 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--; @@ -771,10 +762,10 @@ gdk_pixbuf__pnm_image_load (FILE *f, GError **error) if (!context.pixbuf) { /* Failed to allocate memory */ - g_set_error (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, - _("Cannot allocate memory for loading PNM image")); + g_set_error_literal (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Cannot allocate memory for loading PNM image")); return NULL; } @@ -822,9 +813,9 @@ gdk_pixbuf__pnm_image_begin_load (GdkPixbufModuleSizeFunc size_func, context = g_try_malloc (sizeof (PnmLoaderContext)); if (!context) { - g_set_error(error, GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, - _("Insufficient memory to load PNM context struct")); + 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)); @@ -872,10 +863,10 @@ gdk_pixbuf__pnm_image_stop_load (gpointer data, pnm allows to put multiple images in a file */ if (context->inbuf.nbytes > 0) { - g_set_error (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("Unexpected end of PNM image data")); + g_set_error_literal (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Unexpected end of PNM image data")); retval = FALSE; } #endif @@ -899,8 +890,6 @@ gdk_pixbuf__pnm_image_load_increment (gpointer data, { PnmLoaderContext *context = (PnmLoaderContext *)data; PnmIOBuffer *inbuf; - guchar *old_byte; - guint old_nbytes; const guchar *bufhd; guint num_left, spinguard; gint retval; @@ -912,8 +901,6 @@ gdk_pixbuf__pnm_image_load_increment (gpointer data, bufhd = buf; inbuf = &context->inbuf; - old_nbytes = inbuf->nbytes; - old_byte = inbuf->byte; num_left = size; spinguard = 0; @@ -975,10 +962,10 @@ gdk_pixbuf__pnm_image_load_increment (gpointer data, /* raw formats require exactly one whitespace */ if (!g_ascii_isspace(*(inbuf->byte))) { - g_set_error (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("Raw PNM formats require exactly one whitespace before sample data")); + 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--; @@ -1004,10 +991,10 @@ gdk_pixbuf__pnm_image_load_increment (gpointer data, context->height); if (context->pixbuf == NULL) { - g_set_error (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, - _("Insufficient memory to load PNM file")); + g_set_error_literal (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Insufficient memory to load PNM file")); return FALSE; } @@ -1015,9 +1002,10 @@ gdk_pixbuf__pnm_image_load_increment (gpointer data, context->rowstride = context->pixbuf->rowstride; /* Notify the client that we are ready to go */ - (* context->prepared_func) (context->pixbuf, - NULL, - context->user_data); + if (context->prepared_func) + (* context->prepared_func) (context->pixbuf, + NULL, + context->user_data); } /* if we got here we're reading image data */ @@ -1028,7 +1016,7 @@ gdk_pixbuf__pnm_image_load_increment (gpointer data, break; } else if (retval == PNM_FATAL_ERR) { return FALSE; - } else if (retval == PNM_OK) { + } else if (retval == PNM_OK && context->updated_func) { /* send updated signal */ (* context->updated_func) (context->pixbuf, 0, @@ -1048,8 +1036,13 @@ gdk_pixbuf__pnm_image_load_increment (gpointer data, return TRUE; } -void -MODULE_ENTRY (pnm, fill_vtable) (GdkPixbufModule *module) +#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; @@ -1057,8 +1050,7 @@ MODULE_ENTRY (pnm, fill_vtable) (GdkPixbufModule *module) module->load_increment = gdk_pixbuf__pnm_image_load_increment; } -void -MODULE_ENTRY (pnm, fill_info) (GdkPixbufFormat *info) +MODULE_ENTRY (fill_info) (GdkPixbufFormat *info) { static GdkPixbufModulePattern signature[] = { { "P1", NULL, 100 },