]> Pileus Git - ~andy/gtk/blobdiff - gdk-pixbuf/io-ras.c
Create the event_window at the right size using the same logic as in
[~andy/gtk] / gdk-pixbuf / io-ras.c
index c45f5bb475f71e867839d544a8c3cf5406f4dd0d..40ba370d53d094598a4fa683b00518bf9e6d49df 100644 (file)
@@ -1,3 +1,4 @@
+/* -*- mode: C; c-file-style: "linux" -*- */
 /* GdkPixbuf library - SUNRAS image loader
  *
  * Copyright (C) 1999 The Free Software Foundation
@@ -8,44 +9,44 @@
  * Based on io-gif.c, io-tiff.c and io-png.c
  *
  * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public
+ * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+
 /*
 
 Known bugs:
-       * "Indexed" (incl grayscale) sunras files don't work
-         ( 1999/11/10 - Fixed for non-progressive loading )
-       * 1 bpp sunrasfiles don't work yet
        * Compressed rasterfiles don't work yet
 
 */
 
 #include <config.h>
 #include <stdio.h>
-#include <glib.h>
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-#include "gdk-pixbuf.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include "gdk-pixbuf-private.h"
 #include "gdk-pixbuf-io.h"
-\f
 
+\f
 
 /* 
    Header structure for sunras files.
    All values are in big-endian order on disk
+   
+   Note: Every scanline is padded to be a multiple of 16 bits
  */
 
 struct rasterfile {
@@ -64,223 +65,161 @@ struct rasterfile {
        be32_to_cpu() ??
 */
 
-static unsigned int be32_to_cpu(guint i)
-{
-       unsigned int i2;
-       i2 =
-           ((i & 255) << 24) | (((i >> 8) & 255) << 16) |
-           (((i >> 16) & 255) << 8) | ((i >> 24) & 255);
-       return i2;
-}
-
-/* 
-       Destroy notification function for the libart pixbuf 
-*/
-
-static void free_buffer(gpointer user_data, gpointer data)
-{
-       free(data);
-}
-
-/*
-
-OneLineBGR_buf/file does what it says: Reads one line from file or buffer.
-Note: It also changes BGR pixelorder to RGB as libart currently
-doesn't support ART_PIX_BGR.
-
-*/
-static void OneLineBGR_buf(guchar * buffer, guint Width, guchar * pixels,
-                          guint bpp)
-{
-       guint X;
-
-       memcpy(pixels, buffer, (size_t) (Width * bpp));
-       X = 0;
-       while (X < Width) {
-               guchar Blue;
-               Blue = pixels[X * bpp];
-               pixels[X * bpp] = pixels[X * bpp + 2];
-               pixels[X * bpp + 2] = Blue;
-               X++;
-       }
-}
+/* Progressive loading */
 
-static void OneLineBGR_file(FILE * f, guint Width, guchar * pixels,
-                           guint bpp)
-{
-       size_t result;
-       guint X;
-       guchar DummyByte;
+struct ras_progressive_state {
+       GdkPixbufModuleSizeFunc size_func;
+       GdkPixbufModulePreparedFunc prepared_func;
+       GdkPixbufModuleUpdatedFunc updated_func;
+       gpointer user_data;
 
-       result = fread(pixels, 1, (size_t) (Width * bpp), f);
+       gint HeaderSize;        /* The size of the header-part (incl colormap) */
+       guchar *HeaderBuf;      /* The buffer for the header (incl colormap) */
+       gint HeaderDone;        /* The nr of bytes actually in HeaderBuf */
 
-       g_assert(result == (size_t) (Width * bpp));
-       if (((Width * bpp) & 1) != 0)   /*  Not 16 bit aligned */
-               (void) fread(&DummyByte, 1, 1, f);
-       X = 0;
-       while (X < Width) {
-               guchar Blue;
-               Blue = pixels[X * bpp];
-               pixels[X * bpp] = pixels[X * bpp + 2];
-               pixels[X * bpp + 2] = Blue;
-               X++;
-       }
-}
+       gint LineWidth;         /* The width of a line in bytes */
+       guchar *LineBuf;        /* Buffer for 1 line */
+       gint LineDone;          /* # of bytes in LineBuf */
+       gint Lines;             /* # of finished lines */
 
-static void OneLineMapped_file(FILE * f, guint Width, guchar * pixels,
-                           guint bpp, guchar *Map)
-{
-       size_t result;
-       guint X;
-       guchar DummyByte;
-       guchar *buffer;
-       
-       
-       buffer =g_malloc((size_t) (Width * bpp));
-       
-       g_assert(buffer!=NULL);
+       gint RasType;           /*  32 = BGRA
+                                  24 = BGR
+                                  8 = 8 bit colormapped
+                                  1  = 1 bit bitonal 
+                                */
+       gint DecoderState;        
 
-       result = fread(buffer, 1, (size_t) (Width * bpp), f);
+       struct rasterfile Header;       /* Decoded (BE->CPU) header */
 
-       g_assert(result == (size_t) (Width * bpp));
-       
-       if (((Width * bpp) & 1) != 0)   /*  Not 16 bit aligned */
-               (void) fread(&DummyByte, 1, 1, f);
-       X = 0;
-       while (X < Width) {
-               pixels[X * 3]   = Map[buffer[X]];
-               pixels[X * 3+1] = Map[buffer[X]+256];
-               pixels[X * 3+2] = Map[buffer[X]+512];
 
-               X++;
-       }
-       g_free(buffer);
-}
+       GdkPixbuf *pixbuf;      /* Our "target" */
+};
 
-static void OneLineMapped_buf(guchar *buffer, guint Width, guchar * pixels,
-                           guint bpp,guchar *Map)
+static gpointer
+gdk_pixbuf__ras_image_begin_load(GdkPixbufModuleSizeFunc size_func,
+                                 GdkPixbufModulePreparedFunc prepared_func,
+                                GdkPixbufModuleUpdatedFunc updated_func,
+                                gpointer user_data,
+                                 GError **error);
+static gboolean gdk_pixbuf__ras_image_stop_load(gpointer data, GError **error);
+static gboolean gdk_pixbuf__ras_image_load_increment(gpointer data,
+                                                     const guchar * buf, guint size,
+                                                     GError **error);
+
+static gboolean RAS2State(struct rasterfile *RAS,
+                         struct ras_progressive_state *State,
+                         GError **error)
 {
-       size_t result;
-       guint X;
-       
-       X = 0;
-       while (X < Width) {
-               pixels[X * 3]   = Map[buffer[X]*3];
-               pixels[X * 3+1] = Map[buffer[X]*3+1];
-               pixels[X * 3+2] = Map[buffer[X]*3+2];
-
-               X++;
+       State->Header.width = GUINT32_FROM_BE(RAS->width);
+       State->Header.height = GUINT32_FROM_BE(RAS->height);
+       State->Header.depth = GUINT32_FROM_BE(RAS->depth);
+       State->Header.type = GUINT32_FROM_BE(RAS->type);
+       State->Header.maptype = GUINT32_FROM_BE(RAS->maptype);
+       State->Header.maplength = GUINT32_FROM_BE(RAS->maplength);
+
+       if ((gint)State->Header.width <= 0 ||
+           (gint)State->Header.height <= 0 || 
+           State->Header.maplength > 768) {
+               g_set_error (error,
+                            GDK_PIXBUF_ERROR,
+                            GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+                            _("RAS image has bogus header data")); 
+               return FALSE;
        }
-}
 
-/* Shared library entry point */
-GdkPixbuf *image_load(FILE * f)
-{
-       guint bpp;
-       guint Y;
-       size_t i;
-       guchar *pixels;
-       guchar ColorMap[768];
-       struct rasterfile Header;
-
-       i = fread(&Header, 1, sizeof(Header), f);
-       g_assert(i == 32);
-       
-       /* Fill default colormap */
-       for (Y=0;Y<256;Y++) {
-               ColorMap[Y*3+0]=Y;
-               ColorMap[Y*3+1]=Y;
-               ColorMap[Y*3+2]=Y;
+       State->RasType = State->Header.depth;   /* This may be less trivial someday */
+       State->HeaderSize = 32 + State->Header.maplength;
+
+       if (State->RasType == 32)
+               State->LineWidth = State->Header.width * 4;
+       else if (State->RasType == 24)
+               State->LineWidth = State->Header.width * 3;
+       else if (State->RasType == 8)
+               State->LineWidth = State->Header.width * 1;
+       else if (State->RasType == 1) {
+               State->LineWidth = State->Header.width / 8;
+               if ((State->Header.width & 7) != 0)
+                       State->LineWidth++;
        }
-       /* Correct the byteorder of the header here */
-       Header.width = be32_to_cpu(Header.width);
-       Header.height = be32_to_cpu(Header.height);
-       Header.depth = be32_to_cpu(Header.depth);
-       Header.length = be32_to_cpu(Header.length);
-       Header.type = be32_to_cpu(Header.type);
-       Header.maptype = be32_to_cpu(Header.maptype);
-       Header.maplength = be32_to_cpu(Header.maplength);
-
-
-       bpp = 0;
-       if (Header.depth == 32)
-               bpp = 4;
-       if (Header.depth == 24)
-               bpp = 3;
-       if (Header.depth == 8)
-               bpp = 1;
-               
-       printf("mapl %i \n",Header.maplength);
-       if (Header.maplength>0)
-               i = fread(ColorMap,1,Header.maplength,f);
-                               
-
-       g_assert(bpp != 0);     /* Only 24 and 32 bpp for now */
-
-       if (bpp==4)
-               pixels = (guchar *) g_malloc(Header.width * Header.height * 4);
-       else
-               pixels = (guchar *) g_malloc(Header.width * Header.height * 3);
-       if (!pixels) {
-               return NULL;
+       else {
+               g_set_error (error,
+                            GDK_PIXBUF_ERROR,
+                            GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+                            _("RAS image has unknown type")); 
+               return FALSE;
        }
 
-       /* 
-
-          Loop through the file, one line at a time. 
-          Only BGR-style files are handled right now.
-
-        */
-       Y = 0;
-       while (Y < Header.height) {
-               if (bpp>1) 
-                       OneLineBGR_file(f, Header.width,
-                               &pixels[Y * Header.width * bpp], bpp);
-               else
-                       OneLineMapped_file(f, Header.width,
-                               &pixels[Y * Header.width * 3], bpp,&ColorMap[0]);
-               Y++;
+       if (State->Header.type > 2 || State->Header.maptype > 1) {
+               g_set_error (error,
+                            GDK_PIXBUF_ERROR,
+                            GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+                            _("unsupported RAS image variation")); 
+               return FALSE;
        }
 
+       /* Now pad the line to be a multiple of 16 bits */
+       if ((State->LineWidth & 1) != 0)
+               State->LineWidth++;
 
-       if (bpp == 4)
-               return gdk_pixbuf_new_from_data(pixels, ART_PIX_RGB, TRUE,
-                                               (gint) Header.width,
-                                               (gint) Header.height,
-                                               (gint) (Header.width *
-                                                       4), free_buffer,
-                                               NULL);
-       else
-               return gdk_pixbuf_new_from_data(pixels, ART_PIX_RGB, FALSE,
-                                               (gint) Header.width,
-                                               (gint) Header.height,
-                                               (gint) (Header.width *
-                                                       3), free_buffer,
-                                               NULL);
-}
+       if (!State->LineBuf) {
+               State->LineBuf = g_try_malloc (State->LineWidth);
 
+               if (!State->LineBuf) {
+                       g_set_error (error,
+                                    GDK_PIXBUF_ERROR,
+                                    GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+                                    _("Not enough memory to load RAS image")); 
+                       return FALSE;
+               }
+       }
 
-/* Progressive loading */
 
-struct ras_progressive_state {
-       ModulePreparedNotifyFunc prepared_func;
-       ModuleUpdatedNotifyFunc updated_func;
-       gpointer user_data;
-
-       GdkPixbuf *pixbuf;      /* Our "target" */
-       guchar *PixelData;      /* pointer to the next line */
-       struct rasterfile Header;
-       guint bpp;
-       guint BytesPerLine;
-       guchar *linebuf;
-       guchar *ColorMap;
-       guint BytesInLB;
-       guint LinesDone;
+       if (!State->pixbuf) {
+               if (State->size_func) {
+                       gint width = State->Header.width;
+                       gint height = State->Header.height;
+                       
+                       (*State->size_func) (&width, &height, State->user_data);
+                       if (width == 0 || height == 0)
+                               return FALSE;
+               }
 
+               if (State->RasType == 32)
+                       State->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+                                                       (gint) State->Header.width,
+                                                       (gint) State->Header.height);
+               else
+                       State->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
+                                                       (gint) State->Header.width,
+                                                       (gint) State->Header.height);
+               
+                if (!State->pixbuf) {
+                        g_set_error (error,
+                                     GDK_PIXBUF_ERROR,
+                                     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+                                     _("Not enough memory to load RAS image"));
+                        return FALSE;
+                }
+
+               if (State->prepared_func != NULL)
+                       /* Notify the client that we are ready to go */
+                       (*State->prepared_func) (State->pixbuf,
+                                                 NULL,
+                                                State->user_data);
 
+       }
+       
+       if ((State->Header.maplength == 0) && (State->RasType == 1)) {
+               State->HeaderBuf[32] = 255;
+               State->HeaderBuf[33] = 0;
+               State->HeaderBuf[34] = 255;
+               State->HeaderBuf[35] = 0;
+               State->HeaderBuf[36] = 255;
+               State->HeaderBuf[37] = 0;
+       }
 
-       gboolean have_header;
-};
+       return TRUE;
+}
 
 /* 
  * func - called when we have pixmap created (but no image data)
@@ -288,25 +227,39 @@ struct ras_progressive_state {
  * return context (opaque to user)
  */
 
-gpointer
-image_begin_load(ModulePreparedNotifyFunc prepared_func,
-                ModuleUpdatedNotifyFunc updated_func, gpointer user_data)
+static gpointer
+gdk_pixbuf__ras_image_begin_load(GdkPixbufModuleSizeFunc size_func, 
+                                 GdkPixbufModulePreparedFunc prepared_func,
+                                GdkPixbufModuleUpdatedFunc updated_func,
+                                gpointer user_data,
+                                 GError **error)
 {
        struct ras_progressive_state *context;
 
        context = g_new0(struct ras_progressive_state, 1);
-
+       context->size_func = size_func;
        context->prepared_func = prepared_func;
        context->updated_func = updated_func;
        context->user_data = user_data;
+
+       context->HeaderSize = 32;
+       context->HeaderBuf = g_malloc(32 + 768);        /* 32 for rasheader,
+                                                          768 for the colormap */
+       context->HeaderDone = 0;
+
+       context->LineWidth = 0;
+       context->LineBuf = NULL;
+       context->LineDone = 0;
+       context->Lines = 0;
+
+       context->RasType = 0;
+       context->DecoderState = 0;
+       
+       memset(&context->Header, 0, sizeof(struct rasterfile));
+
+
        context->pixbuf = NULL;
-       context->linebuf = NULL;
-       context->bpp = 0;
-       context->have_header = 0;
-       context->BytesInLB = 0;
-       context->BytesPerLine = 0;
-       context->LinesDone = 0;
-       context->ColorMap = NULL;
+
 
        return (gpointer) context;
 }
@@ -316,147 +269,280 @@ image_begin_load(ModulePreparedNotifyFunc prepared_func,
  *
  * free context, unref gdk_pixbuf
  */
-void image_stop_load(gpointer data)
+static gboolean
+gdk_pixbuf__ras_image_stop_load(gpointer data, GError **error)
 {
        struct ras_progressive_state *context =
            (struct ras_progressive_state *) data;
 
-       g_return_if_fail(context != NULL);
+        /* FIXME this thing needs to report errors if
+         * we have unused image data
+         */
+
+       g_return_val_if_fail(context != NULL, TRUE);
+
+       if (context->LineBuf != NULL)
+               g_free(context->LineBuf);
+       if (context->HeaderBuf != NULL)
+               g_free(context->HeaderBuf);
 
        if (context->pixbuf)
-               gdk_pixbuf_unref(context->pixbuf);
+               g_object_unref(context->pixbuf);
 
-       if (context->linebuf)
-               g_free(context->linebuf);
-       if (context->ColorMap)
-               g_free(context->ColorMap);
        g_free(context);
+
+        return TRUE;
 }
 
+/* 
+ OneLine is called when enough data is received to process 1 line 
+ of pixels 
+ */
+
+static void OneLine32(struct ras_progressive_state *context)
+{
+       gint X;
+       guchar *Pixels;
+
+       X = 0;
+       Pixels = context->pixbuf->pixels + context->pixbuf->rowstride * context->Lines;
+       while (X < context->Header.width) {
+               /* The joys of having a BGR byteorder */
+               Pixels[X * 4 + 0] = context->LineBuf[X * 4 + 2];
+               Pixels[X * 4 + 1] = context->LineBuf[X * 4 + 1];
+               Pixels[X * 4 + 2] = context->LineBuf[X * 4 + 0];
+               Pixels[X * 4 + 3] = context->LineBuf[X * 4 + 3];
+               X++;
+       }
+}
+
+static void OneLine24(struct ras_progressive_state *context)
+{
+       gint X;
+       guchar *Pixels;
+
+       X = 0;
+       Pixels = context->pixbuf->pixels + context->pixbuf->rowstride * context->Lines;
+       while (X < context->Header.width) {
+               /* The joys of having a BGR byteorder */
+               Pixels[X * 3 + 0] = context->LineBuf[X * 3 + 2];
+               Pixels[X * 3 + 1] = context->LineBuf[X * 3 + 1];
+               Pixels[X * 3 + 2] = context->LineBuf[X * 3 + 0];
+               X++;
+       }
+
+}
+
+static void OneLine8(struct ras_progressive_state *context)
+{
+       gint X;
+       guchar *Pixels;
+       int offset = context->Header.maplength / 3;
+
+       X = 0;
+       Pixels = context->pixbuf->pixels + context->pixbuf->rowstride * context->Lines;
+       while (X < context->Header.width) {
+               /* The joys of having a BGR byteorder */
+               Pixels[X * 3 + 0] =
+                   context->HeaderBuf[context->LineBuf[X] + 32];
+               Pixels[X * 3 + 1] =
+                   context->HeaderBuf[context->LineBuf[X] + offset + 32];
+               Pixels[X * 3 + 2] =
+                   context->HeaderBuf[context->LineBuf[X] + 2*offset + 32];
+               X++;
+       }
+}
+
+static void OneLine1(struct ras_progressive_state *context)
+{
+       gint X;
+       guchar *Pixels;
+
+       X = 0;
+       Pixels = context->pixbuf->pixels + context->pixbuf->rowstride * context->Lines;
+       while (X < context->Header.width) {
+               int Bit;
+               
+               Bit = (context->LineBuf[X/8])>>(7-(X&7));
+               Bit = Bit & 1;
+               /* The joys of having a BGR byteorder */
+               Pixels[X * 3 + 0] =
+                   context->HeaderBuf[Bit + 32];
+               Pixels[X * 3 + 1] =
+                   context->HeaderBuf[Bit + 2 + 32];
+               Pixels[X * 3 + 2] =
+                   context->HeaderBuf[Bit + 4 + 32];
+               X++;
+       }
+}
+
+
+static void OneLine(struct ras_progressive_state *context)
+{
+       context->LineDone = 0;
+       if (context->Lines >= context->Header.height)
+               return;
+       if (context->RasType == 32)
+               OneLine32(context);
+       if (context->RasType == 24)
+               OneLine24(context);
+       if (context->RasType == 8)
+               OneLine8(context);
+       if (context->RasType == 1)
+               OneLine1(context);
+
+       context->LineDone = 0;
+       context->Lines++;
+
+       if (context->updated_func != NULL) {
+               (*context->updated_func) (context->pixbuf,
+                                         0,
+                                         context->Lines,
+                                         context->Header.width,
+                                         1,
+                                         context->user_data);
+
+       }
+}
+
+static gboolean
+DoCompressed (struct ras_progressive_state *context,
+             const guchar * buf, guint size,
+             GError **error)
+{
+       int i;
+
+       for (i = 0; i < size; i++) {
+               switch (context->DecoderState) {
+                   case 0:
+                           if (buf[i] == 0x80)
+                                   context->DecoderState = 1;
+                           else
+                                   context->LineBuf[context->LineDone++] = buf[i];
+                           break;
+                   case 1:
+                           if (buf[i] == 0) {
+                                   context->LineBuf[context->LineDone++] = 0x80;
+                                   context->DecoderState = 0;
+                           }
+                           else
+                                   context->DecoderState = buf[i] + 1;
+                           break;
+                   default:
+                           for (; context->DecoderState; context->DecoderState--) {
+                                   context->LineBuf[context->LineDone++] = buf[i];
+                                   if ((context->LineDone >= context->LineWidth) && (context->LineWidth > 0))
+                                           OneLine(context);
+                           }
+               }
+               if ((context->LineDone >= context->LineWidth) && (context->LineWidth > 0))
+                       OneLine(context);
+       }
+       return TRUE;
+}
 
 /*
  * context - from image_begin_load
  * buf - new image data
  * size - length of new image data
  *
- * append image data onto inrecrementally built output image
+ * append image data onto incrementally built output image
  */
-gboolean image_load_increment(gpointer data, guchar * buf, guint size)
+static gboolean
+gdk_pixbuf__ras_image_load_increment(gpointer data,
+                                     const guchar * buf, guint size,
+                                     GError **error)
 {
        struct ras_progressive_state *context =
            (struct ras_progressive_state *) data;
 
-       if ((context->have_header == 0) && (size < 32))
-               return FALSE;
-
-       if (context->have_header == FALSE) {
-               memcpy(&context->Header, buf, 32);
-               buf += 32;
-               size -= 32;
-
-               context->Header.width = be32_to_cpu(context->Header.width);
-               context->Header.height =
-                   be32_to_cpu(context->Header.height);
-               context->Header.depth = be32_to_cpu(context->Header.depth);
-               context->Header.length =
-                   be32_to_cpu(context->Header.length);
-               context->Header.type = be32_to_cpu(context->Header.type);
-               context->Header.maptype =
-                   be32_to_cpu(context->Header.maptype);
-               context->Header.maplength =
-                   be32_to_cpu(context->Header.maplength);
-
-               context->bpp = 0;
-               if (context->Header.depth == 32)
-                       context->bpp = 4;
-               if (context->Header.depth == 24)
-                       context->bpp = 3;
-               if (context->Header.depth == 8)
-                       context->bpp = 1;
-                       
-
-               g_assert(context->bpp != 0);    /* Only 24 and 32 bpp for now */
+       gint BytesToCopy;
 
-
-               if (context->bpp == 4)
-                       context->pixbuf = gdk_pixbuf_new(ART_PIX_RGB, TRUE,
-                                                        8,
-                                                        (gint)
-                                                        context->Header.
-                                                        width,
-                                                        (gint)
-                                                        context->Header.
-                                                        height);
-               else
-                       context->pixbuf =
-                           gdk_pixbuf_new(ART_PIX_RGB, FALSE, 8,
-                                          (gint) context->Header.width,
-                                          (gint) context->Header.height);
-
-               /* Use pixbuf buffer to store decompressed data */
-               g_assert(context->pixbuf != NULL);
-               g_assert(context->pixbuf->art_pixbuf != NULL);
-               context->PixelData = context->pixbuf->art_pixbuf->pixels;
-               g_assert(context->PixelData != NULL);
-               context->BytesPerLine =
-                   context->Header.width * context->bpp;
-
-               if (((context->BytesPerLine) & 1) != 0) /*  Not 16 bit aligned */
-                       context->BytesPerLine++;
-
-               context->linebuf =
-                   (guchar *) g_malloc(context->BytesPerLine);
-               context->have_header = TRUE;
-               if (context->linebuf == NULL) {
-                       /* Failed to allocate memory */
-                       g_error("Couldn't allocate linebuf");
+       while (size > 0) {
+               if (context->HeaderDone < context->HeaderSize) {        /* We still 
+                                                                          have headerbytes to do */
+                       BytesToCopy =
+                           context->HeaderSize - context->HeaderDone;
+                       if (BytesToCopy > size)
+                               BytesToCopy = size;
+
+                       memmove(context->HeaderBuf + context->HeaderDone,
+                              buf, BytesToCopy);
+
+                       size -= BytesToCopy;
+                       buf += BytesToCopy;
+                       context->HeaderDone += BytesToCopy;
+
+               } else if (context->Header.type == 2) {
+                       if (!DoCompressed (context, buf, size, error)) {
+                               return FALSE;
+                       }
+                       size = 0;
                }
+               else {
+                       BytesToCopy =
+                           context->LineWidth - context->LineDone;
+                       if (BytesToCopy > size)
+                               BytesToCopy = size;
+
+                       if (BytesToCopy > 0) {
+                               memmove(context->LineBuf +
+                                      context->LineDone, buf,
+                                      BytesToCopy);
+
+                               size -= BytesToCopy;
+                               buf += BytesToCopy;
+                               context->LineDone += BytesToCopy;
+                       }
+                       if ((context->LineDone >= context->LineWidth) &&
+                           (context->LineWidth > 0))
+                               OneLine(context);
 
 
-               /* Notify the client that we are ready to go */
-               (*context->prepared_func) (context->pixbuf,
-                                          context->user_data);
-       }
-
-
-       while (size > 0) {
-               guint ToDo;
-               ToDo = context->BytesPerLine - context->BytesInLB;
-               if (ToDo > size)
-                       ToDo = size;
-               memcpy(context->linebuf + context->BytesInLB,
-                      buf, (size_t) ToDo);
-               size -= ToDo;
-               buf += ToDo;
-               context->BytesInLB += ToDo;
-               if (context->BytesInLB >= context->BytesPerLine) {
-                       /* linebuf if full */
-                       if (context->bpp>1)
-                               OneLineBGR_buf(context->linebuf,
-                                      context->Header.width,
-                                      context->PixelData, context->bpp);
-                       else                                 
-                               OneLineMapped_buf(context->linebuf,
-                                      context->Header.width,
-                                      context->PixelData, context->bpp,
-                                      context->ColorMap);
-                       context->BytesInLB = 0;
-                       context->PixelData +=
-                           context->pixbuf->art_pixbuf->rowstride;
-                       context->LinesDone++;
-
-                       (*context->updated_func) (context->pixbuf,
-                                                 context->user_data,
-                                                 0,
-                                                 context->LinesDone,
-                                                 context->Header.width,
-                                                 context->Header.height);
+               }
 
+               if (context->HeaderDone >= 32)
+                       if (!RAS2State((struct rasterfile *) context->HeaderBuf,
+                                      context, error)) {
+                               return FALSE;
+                       }
 
-               }
 
        }
 
        return TRUE;
 }
 
+void
+MODULE_ENTRY (ras, fill_vtable) (GdkPixbufModule *module)
+{
+       module->begin_load = gdk_pixbuf__ras_image_begin_load;
+       module->stop_load = gdk_pixbuf__ras_image_stop_load;
+       module->load_increment = gdk_pixbuf__ras_image_load_increment;
+}
+
+void
+MODULE_ENTRY (ras, fill_info) (GdkPixbufFormat *info)
+{
+       static GdkPixbufModulePattern signature[] = {
+               { "\x59\xa6\x6a\x95", NULL, 100 },
+               { NULL, NULL, 0 }
+       };
+       static gchar * mime_types[] = {
+               "image/x-cmu-raster",
+               "image/x-sun-raster",
+               NULL
+       };
+       static gchar * extensions[] = {
+               "ras",
+               NULL
+       };
+
+       info->name = "ras";
+       info->signature = signature;
+       info->description = N_("The Sun raster image format");
+       info->mime_types = mime_types;
+       info->extensions = extensions;
+       info->flags = 0;
+}
+