]> granicus.if.org Git - imagemagick/blobdiff - coders/xcf.c
(no commit message)
[imagemagick] / coders / xcf.c
index ee1b7d618896795567613fbf9809b14ff0b394da..598ddad231bd6471ad25b957b8db7720e1786fb7 100644 (file)
@@ -121,8 +121,8 @@ typedef struct
   size_t
     file_size;
 
-  ExceptionInfo
-    *exception;
+  size_t
+    number_layers;
 } XCFDocInfo;
 
 typedef struct
@@ -366,7 +366,7 @@ static MagickBooleanType load_tile(Image *image,Image *tile_image,
       image->filename);
   for (y=0; y < (ssize_t) tile_image->rows; y++)
   {
-    q=QueueAuthenticPixels(tile_image,0,y,tile_image->columns,1,exception);
+    q=GetAuthenticPixels(tile_image,0,y,tile_image->columns,1,exception);
     if (q == (Quantum *) NULL)
       break;
     if (inDocInfo->image_type == GIMP_GRAY)
@@ -388,7 +388,7 @@ static MagickBooleanType load_tile(Image *image,Image *tile_image,
             SetPixelRed(tile_image,ScaleCharToQuantum(xcfdata->red),q);
             SetPixelGreen(tile_image,ScaleCharToQuantum(xcfdata->green),q);
             SetPixelBlue(tile_image,ScaleCharToQuantum(xcfdata->blue),q);
-            SetPixelAlpha(tile_image,xcfdata->alpha == 0U ? OpaqueAlpha :
+            SetPixelAlpha(tile_image,xcfdata->alpha == 255U ? TransparentAlpha :
               ScaleCharToQuantum((unsigned char) inLayerInfo->alpha),q);
             xcfdata++;
             q+=GetPixelChannels(tile_image);
@@ -408,6 +408,9 @@ static MagickBooleanType load_tile_rle(Image *image,Image *tile_image,
   MagickOffsetType
     size;
 
+  Quantum
+    alpha;
+
   register Quantum
     *q;
 
@@ -435,11 +438,13 @@ static MagickBooleanType load_tile_rle(Image *image,Image *tile_image,
   xcfodata=xcfdata;
   count=ReadBlob(image, (size_t) data_length, xcfdata);
   xcfdatalimit = xcfodata+count-1;
-  exception=(exception);
+  alpha=ScaleCharToQuantum((unsigned char) inLayerInfo->alpha);
   for (i=0; i < (ssize_t) bytes_per_pixel; i++)
   {
     q=GetAuthenticPixels(tile_image,0,0,tile_image->columns,tile_image->rows,
       exception);
+    if (q == (Quantum *) NULL)
+      continue;
     size=(MagickOffsetType) tile_image->rows*tile_image->columns;
     while (size > 0)
     {
@@ -474,14 +479,14 @@ static MagickBooleanType load_tile_rle(Image *image,Image *tile_image,
                       SetPixelRed(tile_image,ScaleCharToQuantum(data),q);
                       SetPixelGreen(tile_image,ScaleCharToQuantum(data),q);
                       SetPixelBlue(tile_image,ScaleCharToQuantum(data),q);
-                      SetPixelAlpha(tile_image,ScaleCharToQuantum(
-                        (unsigned char) inLayerInfo->alpha),q);
+                      SetPixelAlpha(tile_image,data == 255U ? alpha :
+                        ScaleCharToQuantum(data),q);
                     }
                   else
                     {
                       SetPixelGray(tile_image,ScaleCharToQuantum(data),q);
-                      SetPixelAlpha(tile_image,ScaleCharToQuantum(
-                        (unsigned char) inLayerInfo->alpha),q);
+                      SetPixelAlpha(tile_image,data == 255U ? alpha :
+                        ScaleCharToQuantum(data),q);
                     }
                   break;
                 }
@@ -497,8 +502,8 @@ static MagickBooleanType load_tile_rle(Image *image,Image *tile_image,
                 }
                 case 3:
                 {
-                  SetPixelAlpha(tile_image,data == 0 ? OpaqueAlpha :
-                    ScaleCharToQuantum((unsigned char) inLayerInfo->alpha),q);
+                  SetPixelAlpha(tile_image,data == 255U ? alpha :
+                    ScaleCharToQuantum(data),q);
                   break;
                 }
               }
@@ -521,7 +526,7 @@ static MagickBooleanType load_tile_rle(Image *image,Image *tile_image,
             if (xcfdata > xcfdatalimit)
               goto bogus_rle;
             pixel=(*xcfdata++);
-            for (j= 0; j < (ssize_t) length; j++)
+            for (j=0; j < (ssize_t) length; j++)
             {
               data=pixel;
               switch (i)
@@ -533,14 +538,14 @@ static MagickBooleanType load_tile_rle(Image *image,Image *tile_image,
                       SetPixelRed(tile_image,ScaleCharToQuantum(data),q);
                       SetPixelGreen(tile_image,ScaleCharToQuantum(data),q);
                       SetPixelBlue(tile_image,ScaleCharToQuantum(data),q);
-                      SetPixelAlpha(tile_image,ScaleCharToQuantum(
-                        (unsigned char) inLayerInfo->alpha),q);
+                      SetPixelAlpha(tile_image,data == 255U ? alpha :
+                        ScaleCharToQuantum(data),q);
                     }
                   else
                     {
                       SetPixelGray(tile_image,ScaleCharToQuantum(data),q);
-                      SetPixelAlpha(tile_image,ScaleCharToQuantum(
-                        (unsigned char) inLayerInfo->alpha),q);
+                      SetPixelAlpha(tile_image,data == 255U ? alpha :
+                        ScaleCharToQuantum(data),q);
                     }
                   break;
                 }
@@ -556,8 +561,8 @@ static MagickBooleanType load_tile_rle(Image *image,Image *tile_image,
                 }
                 case 3:
                 {
-                  SetPixelAlpha(tile_image,data == 0 ? OpaqueAlpha :
-                    ScaleCharToQuantum((unsigned char) inLayerInfo->alpha),q);
+                  SetPixelAlpha(tile_image,data == 255U ? alpha :
+                    ScaleCharToQuantum(data),q);
                   break;
                 }
               }
@@ -578,11 +583,8 @@ static MagickBooleanType load_tile_rle(Image *image,Image *tile_image,
 }
 
 static MagickBooleanType load_level(Image *image,XCFDocInfo *inDocInfo,
-  XCFLayerInfo *inLayerInfo)
+  XCFLayerInfo *inLayerInfo,ExceptionInfo *exception)
 {
-  ExceptionInfo
-    *exception;
-
   int
     destLeft = 0,
     destTop = 0;
@@ -611,7 +613,6 @@ static MagickBooleanType load_level(Image *image,XCFDocInfo *inDocInfo,
     tile_image_height;
 
   /* start reading the data */
-  exception=inDocInfo->exception;
   width=ReadBlobMSBLong(image);
   height=ReadBlobMSBLong(image);
 
@@ -683,7 +684,7 @@ static MagickBooleanType load_level(Image *image,XCFDocInfo *inDocInfo,
 
       /* composite the tile onto the layer's image, and then destroy it */
       (void) CompositeImage(inLayerInfo->image,tile_image,CopyCompositeOp,
-        MagickTrue,destLeft*TILE_WIDTH,destTop*TILE_HEIGHT,exception);
+        MagickTrue,destLeft * TILE_WIDTH,destTop*TILE_HEIGHT,exception);
       tile_image=DestroyImage(tile_image);
 
       /* adjust tile position */
@@ -708,7 +709,7 @@ static MagickBooleanType load_level(Image *image,XCFDocInfo *inDocInfo,
 }
 
 static MagickBooleanType load_hierarchy(Image *image,XCFDocInfo *inDocInfo,
-   XCFLayerInfo *inLayer)
+   XCFLayerInfo *inLayer, ExceptionInfo *exception)
 {
   MagickOffsetType
     saved_pos,
@@ -750,7 +751,7 @@ static MagickBooleanType load_hierarchy(Image *image,XCFDocInfo *inDocInfo,
   offset=SeekBlob(image, offset, SEEK_SET);
 
   /* read in the level */
-  if (load_level (image, inDocInfo, inLayer) == 0)
+  if (load_level (image, inDocInfo, inLayer, exception) == 0)
     return(MagickFalse);
   /* restore the saved position so we'll be ready to
    *  read the next offset.
@@ -759,8 +760,9 @@ static MagickBooleanType load_hierarchy(Image *image,XCFDocInfo *inDocInfo,
   return(MagickTrue);
 }
 
-static MagickBooleanType ReadOneLayer(Image* image,XCFDocInfo* inDocInfo,
-  XCFLayerInfo *outLayer, ExceptionInfo *exception )
+static MagickBooleanType ReadOneLayer(const ImageInfo *image_info,Image* image,
+  XCFDocInfo* inDocInfo,XCFLayerInfo *outLayer,const ssize_t layer,
+  ExceptionInfo *exception )
 {
   MagickOffsetType
     offset;
@@ -780,11 +782,6 @@ static MagickBooleanType ReadOneLayer(Image* image,XCFDocInfo* inDocInfo,
   outLayer->type = ReadBlobMSBLong(image);
   (void) ReadBlobStringWithLongSize(image, outLayer->name,
     sizeof(outLayer->name),exception);
-  /* allocate the image for this layer */
-  outLayer->image=CloneImage(image,outLayer->width, outLayer->height,MagickTrue,
-     exception);
-  if (outLayer->image == (Image *) NULL)
-    return MagickFalse;
   /* read the layer properties! */
   foundPropEnd = 0;
   while ( (foundPropEnd == MagickFalse) && (EOFBlob(image) == MagickFalse) ) {
@@ -877,11 +874,38 @@ static MagickBooleanType ReadOneLayer(Image* image,XCFDocInfo* inDocInfo,
 
   if (foundPropEnd == MagickFalse)
     return(MagickFalse);
+  /* allocate the image for this layer */
+  if (image_info->number_scenes != 0)
+    {
+      ssize_t
+        scene;
+
+      scene=inDocInfo->number_layers-layer-1;
+      if (scene > (image_info->scene+image_info->number_scenes-1))
+        {
+          outLayer->image=CloneImage(image,0,0,MagickTrue,exception);
+          if (outLayer->image == (Image *) NULL)
+            return(MagickFalse);
+          outLayer->image->page.x=outLayer->offset_x;
+          outLayer->image->page.y=outLayer->offset_y;
+          outLayer->image->page.width=outLayer->width;
+          outLayer->image->page.height=outLayer->height;
+          return(MagickTrue);
+        }
+    }
+  outLayer->image=CloneImage(image,outLayer->width, outLayer->height,MagickTrue,
+    exception);
+  if (outLayer->image == (Image *) NULL)
+    return(MagickFalse);
   /* clear the image based on the layer opacity */
   outLayer->image->background_color.alpha=
-    ScaleCharToQuantum((unsigned char) (255-outLayer->alpha));    
+    ScaleCharToQuantum((unsigned char) outLayer->alpha);
   (void) SetImageBackgroundColor(outLayer->image,exception);
 
+  outLayer->image->page.x=outLayer->offset_x;
+  outLayer->image->page.y=outLayer->offset_y;
+  outLayer->image->page.width=outLayer->width;
+  outLayer->image->page.height=outLayer->height;
   /* set the compositing mode */
   outLayer->image->compose = GIMPBlendModeToCompositeOperator( outLayer->mode );
   if ( outLayer->visible == MagickFalse )
@@ -899,7 +923,7 @@ static MagickBooleanType ReadOneLayer(Image* image,XCFDocInfo* inDocInfo,
   if (offset < 0)
     (void) ThrowMagickException(exception,GetMagickModule(),
       CorruptImageError,"InvalidImageHeader","`%s'",image->filename);
-  if (load_hierarchy (image, inDocInfo, outLayer) == 0)
+  if (load_hierarchy (image, inDocInfo, outLayer, exception) == 0)
     return(MagickFalse);
 
   /* read in the layer mask */
@@ -937,7 +961,7 @@ static MagickBooleanType ReadOneLayer(Image* image,XCFDocInfo* inDocInfo,
 
   return MagickTrue;
 }
-
+\f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                             %
@@ -963,7 +987,6 @@ static MagickBooleanType ReadOneLayer(Image* image,XCFDocInfo* inDocInfo,
 %
 %    o exception: return any errors or warnings in this structure.
 %
-%
 */
 static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception)
 {
@@ -1017,7 +1040,6 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception)
       (LocaleNCompare((char *) magick,"gimp xcf",8) != 0))
     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   (void) ResetMagickMemory(&doc_info,0,sizeof(XCFDocInfo));
-  doc_info.exception=exception;
   doc_info.width=ReadBlobMSBLong(image);
   doc_info.height=ReadBlobMSBLong(image);
   if ((doc_info.width > 262144) || (doc_info.height > 262144))
@@ -1040,6 +1062,7 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception)
     else
       if (image_type == GIMP_INDEXED)
         ThrowReaderException(CoderError,"ColormapTypeNotSupported");
+  (void) SetImageBackgroundColor(image,exception);
   image->matte=MagickTrue;
   /*
     Read properties.
@@ -1194,8 +1217,8 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception)
         /*BOGUS: ignored for now */
         /*float  factor = (float) */ (void) ReadBlobMSBLong(image);
         /* size_t digits =  */ (void) ReadBlobMSBLong(image);
-        for (i=0; i < 5; i++)
-         (void) ReadBlobStringWithLongSize(image,unit_string,
+        for (i=0; i<5; i++)
+         (void) ReadBlobStringWithLongSize(image, unit_string,
            sizeof(unit_string),exception);
       }
      break;
@@ -1228,16 +1251,12 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception)
   else
     {
       int
-        number_layers = 0,
-        num_layers = 0,
         current_layer = 0,
-        first_layer = 0,
-        last_layer = 0,
-        last = 0,
-        foundAllLayers = MagickFalse;
+        foundAllLayers = MagickFalse,
+        number_layers = 0;
 
       MagickOffsetType
-        oldPos;
+        oldPos=TellBlob(image);
 
       XCFLayerInfo
         *layer_info;
@@ -1245,7 +1264,6 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception)
       /* 
         the read pointer
       */
-      oldPos=TellBlob(image);
       do
       {
         ssize_t offset = (int) ReadBlobMSBLong(image);
@@ -1260,23 +1278,10 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception)
             break;
           }
     } while (foundAllLayers == MagickFalse);
+    doc_info.number_layers=number_layers;
     offset=SeekBlob(image,oldPos,SEEK_SET); /* restore the position! */
     if (offset < 0)
       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
-    first_layer=image_info->scene;
-    num_layers=number_layers;
-    /* number_scenes==0 means read all the images */
-    if ((image_info->number_scenes > 0) &&
-        (image_info->number_scenes < number_layers))
-      num_layers=image_info->scene;
-    last_layer=first_layer+num_layers-1;
-
-    /* XCF has layers backwards. */
-    last=last_layer;
-    last_layer=number_layers-first_layer - 1;
-    first_layer=number_layers-last-1;
-    number_layers=num_layers;
-
     /* allocate our array of layer info blocks */
     length=(size_t) number_layers;
     layer_info=(XCFLayerInfo *) AcquireQuantumMemory(length,
@@ -1304,29 +1309,26 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception)
       *  next layer offset is stored.
       */
       saved_pos=TellBlob(image);
-      if ((first_layer <= current_layer) && (current_layer <= last_layer))
+      /* seek to the layer offset */
+      offset=SeekBlob(image,offset,SEEK_SET);
+      /* read in the layer */
+      layer_ok=ReadOneLayer(image_info,image,&doc_info,
+        &layer_info[current_layer],current_layer,exception);
+      if (layer_ok == MagickFalse)
         {
-          /* seek to the layer offset */
-          offset=SeekBlob(image,offset,SEEK_SET);
-          /* read in the layer */
-          layer_ok=ReadOneLayer(image,&doc_info,&layer_info[current_layer],
-            exception);
-          if (layer_ok == MagickFalse)
-            {
-              int j;
-    
-              for (j=0; j < current_layer; j++)
-                layer_info[j].image=DestroyImage(layer_info[j].image);
-              layer_info=(XCFLayerInfo *) RelinquishMagickMemory(layer_info);
-              ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
-            }
-          /* restore the saved position so we'll be ready to
-          *  read the next offset.
-          */
-          offset=SeekBlob(image, saved_pos, SEEK_SET);
+          int j;
+
+          for (j=0; j < current_layer; j++)
+            layer_info[j].image=DestroyImage(layer_info[j].image);
+          layer_info=(XCFLayerInfo *) RelinquishMagickMemory(layer_info);
+          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
         }
-        current_layer++;
-      }
+      /* restore the saved position so we'll be ready to
+      *  read the next offset.
+      */
+      offset=SeekBlob(image, saved_pos, SEEK_SET);
+      current_layer++;
+    }
     if (number_layers == 1)
       {
         /*
@@ -1334,7 +1336,7 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception)
         */
         (void) CompositeImage(image,layer_info[0].image,OverCompositeOp,
           MagickTrue,layer_info[0].offset_x,layer_info[0].offset_y,exception);
-        layer_info[0].image=DestroyImage( layer_info[0].image);
+        layer_info[0].image =DestroyImage( layer_info[0].image);
       }
     else
       {
@@ -1346,11 +1348,11 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception)
           /* BOGUS: need to consider layer blending modes!! */
 
           if ( layer_info[j].visible ) { /* only visible ones, please! */
-            CompositeImage(image, layer_info[j].image, OverCompositeOp,
-               MagickTrue, layer_info[j].offset_x, layer_info[j].offset_y );
+            CompositeImage(image, OverCompositeOp, layer_info[j].image,
+                     layer_info[j].offset_x, layer_info[j].offset_y );
              layer_info[j].image =DestroyImage( layer_info[j].image );
 
-            /*  If we do this, we'll get REAL gray images! */
+            /* If we do this, we'll get REAL gray images! */
             if ( image_type == GIMP_GRAY ) {
               QuantizeInfo  qi;
               GetQuantizeInfo(&qi);
@@ -1363,31 +1365,20 @@ static Image *ReadXCFImage(const ImageInfo *image_info,ExceptionInfo *exception)
 #else
       {
         /* NOTE: XCF layers are REVERSED from composite order! */
-        signed int  j;
+        ssize_t  j;
 
         /* first we copy the last layer on top of the main image */
         (void) CompositeImage(image,layer_info[number_layers-1].image,
           CopyCompositeOp,MagickTrue,layer_info[number_layers-1].offset_x,
           layer_info[number_layers-1].offset_y,exception);
-        layer_info[number_layers-1].image=DestroyImage(
-          layer_info[number_layers-1].image);
+          layer_info[number_layers-1].image=DestroyImage(
+            layer_info[number_layers-1].image);
 
         /* now reverse the order of the layers as they are put
            into subimages
         */
-      image->next=layer_info[number_layers-2].image;
-      layer_info[number_layers-2].image->previous=image;
-      for (j=number_layers-2; j>=0; j--)
-      {
-        if (j > 0)
-          layer_info[j].image->next=layer_info[j-1].image;
-        if (j < (number_layers-1))
-          layer_info[j].image->previous=layer_info[j+1].image;
-        layer_info[j].image->page.x = layer_info[j].offset_x;
-        layer_info[j].image->page.y = layer_info[j].offset_y;
-        layer_info[j].image->page.width = layer_info[j].width;
-        layer_info[j].image->page.height = layer_info[j].height;
-        }
+        for (j=(ssize_t) number_layers-2; j >= 0; j--)
+          AppendImageToList(&image,layer_info[j].image);
       }
 #endif
     }