]> granicus.if.org Git - imagemagick/blobdiff - coders/wpg.c
(no commit message)
[imagemagick] / coders / wpg.c
index 411be695dec39709f2c25b0e7610f7a4f7484160..9d267328e2a56cd29ad6202468eb60cbebcf78a3 100644 (file)
@@ -16,7 +16,7 @@
 %                                 June 2000                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the License.  You may  %
 /*
   Include declarations.
 */
-#include "magick/studio.h"
-#include "magick/blob.h"
-#include "magick/blob-private.h"
-#include "magick/color-private.h"
-#include "magick/colormap.h"
-#include "magick/colormap-private.h"
-#include "magick/constitute.h"
-#include "magick/exception.h"
-#include "magick/exception-private.h"
-#include "magick/cache.h"
-#include "magick/image.h"
-#include "magick/image-private.h"
-#include "magick/list.h"
-#include "magick/magic.h"
-#include "magick/magick.h"
-#include "magick/memory_.h"
-#include "magick/resource_.h"
-#include "magick/quantum-private.h"
-#include "magick/shear.h"
-#include "magick/static.h"
-#include "magick/string_.h"
-#include "magick/module.h"
-#include "magick/transform.h"
-#include "magick/utility.h"
+#include "MagickCore/studio.h"
+#include "MagickCore/blob.h"
+#include "MagickCore/blob-private.h"
+#include "MagickCore/color-private.h"
+#include "MagickCore/colormap.h"
+#include "MagickCore/colormap-private.h"
+#include "MagickCore/constitute.h"
+#include "MagickCore/exception.h"
+#include "MagickCore/exception-private.h"
+#include "MagickCore/cache.h"
+#include "MagickCore/distort.h"
+#include "MagickCore/image.h"
+#include "MagickCore/image-private.h"
+#include "MagickCore/list.h"
+#include "MagickCore/magic.h"
+#include "MagickCore/magick.h"
+#include "MagickCore/memory_.h"
+#include "MagickCore/resource_.h"
+#include "MagickCore/pixel-accessor.h"
+#include "MagickCore/quantum-private.h"
+#include "MagickCore/static.h"
+#include "MagickCore/string_.h"
+#include "MagickCore/module.h"
+#include "MagickCore/transform.h"
+#include "MagickCore/utility.h"
+#include "MagickCore/utility-private.h"
 \f
 typedef struct
    {
@@ -262,53 +264,48 @@ static void Rd_WP_DWORD(Image *image,size_t *d)
   return;
 }
 
-static void InsertRow(unsigned char *p,ssize_t y,Image *image, int bpp)
+static void InsertRow(Image *image,unsigned char *p,ssize_t y,int bpp,
+  ExceptionInfo *exception)
 {
-  ExceptionInfo
-    *exception;
-
   int
     bit;
 
-  ssize_t
-    x;
+  Quantum
+    index;
 
-  register PixelPacket
+  register Quantum
     *q;
 
-  IndexPacket
-    index;
-
-  register IndexPacket
-    *indexes;
+  ssize_t
+    x;
 
-  exception=(&image->exception);
   switch (bpp)
     {
     case 1:  /* Convert bitmap scanline. */
       {
         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
-        if (q == (PixelPacket *) NULL)
+        if (q == (Quantum *) NULL)
           break;
-        indexes=GetAuthenticIndexQueue(image);
         for (x=0; x < ((ssize_t) image->columns-7); x+=8)
+        {
+          for (bit=0; bit < 8; bit++)
           {
-            for (bit=0; bit < 8; bit++)
-              {
-                index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);
-                indexes[x+bit]=index;
-                *q++=image->colormap[(int) index];
-              }
-            p++;
+            index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);
+            SetPixelIndex(image,index,q);
+            SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
+            q+=GetPixelChannels(image);
           }
+          p++;
+        }
         if ((image->columns % 8) != 0)
           {
             for (bit=0; bit < (ssize_t) (image->columns % 8); bit++)
-              {
-                index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);
-                indexes[x+bit]=index;
-                *q++=image->colormap[(int) index];
-              }
+            {
+              index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);
+              SetPixelIndex(image,index,q);
+              SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
+              q+=GetPixelChannels(image);
+            }
             p++;
           }
         if (!SyncAuthenticPixels(image,exception))
@@ -318,42 +315,49 @@ static void InsertRow(unsigned char *p,ssize_t y,Image *image, int bpp)
     case 2:  /* Convert PseudoColor scanline. */
       {
         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
-        if (q == (PixelPacket *) NULL)
+        if (q == (Quantum *) NULL)
           break;
-        indexes=GetAuthenticIndexQueue(image);
         for (x=0; x < ((ssize_t) image->columns-1); x+=2)
         {
-            index=ConstrainColormapIndex(image,(*p >> 6) & 0x3);
-            indexes[x]=index;
-            *q++=image->colormap[(ssize_t) index];
-            index=ConstrainColormapIndex(image,(*p >> 4) & 0x3);
-            indexes[x]=index;
-            *q++=image->colormap[(ssize_t) index];
-            index=ConstrainColormapIndex(image,(*p >> 2) & 0x3);
-            indexes[x]=index;
-            *q++=image->colormap[(ssize_t) index];
-            index=ConstrainColormapIndex(image,(*p) & 0x3);
-            indexes[x+1]=index;
-            *q++=image->colormap[(ssize_t) index];
+            index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);
+            SetPixelIndex(image,index,q);
+            SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
+            q+=GetPixelChannels(image);
+            index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);
+            SetPixelIndex(image,index,q);
+            SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
+            q+=GetPixelChannels(image);
+            index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,exception);
+            SetPixelIndex(image,index,q);
+            SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
+            q+=GetPixelChannels(image);
+            index=ConstrainColormapIndex(image,(*p) & 0x3,exception);
+            SetPixelIndex(image,index,q);
+            SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
             p++;
+            q+=GetPixelChannels(image);
         }
        if ((image->columns % 4) != 0)
           {
-            index=ConstrainColormapIndex(image,(*p >> 6) & 0x3);
-            indexes[x]=index;
-            *q++=image->colormap[(ssize_t) index];
+            index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);
+            SetPixelIndex(image,index,q);
+            SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
+            q+=GetPixelChannels(image);
             if ((image->columns % 4) >= 1)
 
               {
-                index=ConstrainColormapIndex(image,(*p >> 4) & 0x3);
-                indexes[x]=index;
-                *q++=image->colormap[(ssize_t) index];
+                index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);
+                SetPixelIndex(image,index,q);
+                SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
+                q+=GetPixelChannels(image);
                 if ((image->columns % 4) >= 2)
 
                   {
-                    index=ConstrainColormapIndex(image,(*p >> 2) & 0x3);
-                    indexes[x]=index;
-                    *q++=image->colormap[(ssize_t) index];
+                    index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,
+                      exception);
+                    SetPixelIndex(image,index,q);
+                    SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
+                    q+=GetPixelChannels(image);
                   }
               }
             p++;
@@ -366,25 +370,27 @@ static void InsertRow(unsigned char *p,ssize_t y,Image *image, int bpp)
     case 4:  /* Convert PseudoColor scanline. */
       {
         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
-        if (q == (PixelPacket *) NULL)
+        if (q == (Quantum *) NULL)
           break;
-        indexes=GetAuthenticIndexQueue(image);
         for (x=0; x < ((ssize_t) image->columns-1); x+=2)
           { 
-            index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f);
-            indexes[x]=index;
-            *q++=image->colormap[(ssize_t) index];
-            index=ConstrainColormapIndex(image,(*p) & 0x0f);
-            indexes[x+1]=index;
-            *q++=image->colormap[(ssize_t) index];
+            index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception);
+            SetPixelIndex(image,index,q);
+            SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
+            q+=GetPixelChannels(image);
+            index=ConstrainColormapIndex(image,(*p) & 0x0f,exception);
+            SetPixelIndex(image,index,q);
+            SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
             p++;
+            q+=GetPixelChannels(image);
           }
         if ((image->columns % 2) != 0)
           {
-            index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f);
-            indexes[x]=index;
-            *q++=image->colormap[(ssize_t) index];
+            index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception);
+            SetPixelIndex(image,index,q);
+            SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
             p++;
+            q+=GetPixelChannels(image);
           }
         if (SyncAuthenticPixels(image,exception) == MagickFalse)
           break;
@@ -393,15 +399,15 @@ static void InsertRow(unsigned char *p,ssize_t y,Image *image, int bpp)
     case 8: /* Convert PseudoColor scanline. */
       {
         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
-        if (q == (PixelPacket *) NULL) break;
-        indexes=GetAuthenticIndexQueue(image);
+        if (q == (Quantum *) NULL) break;
 
         for (x=0; x < (ssize_t) image->columns; x++)
           {
-            index=ConstrainColormapIndex(image,*p);
-            indexes[x]=index;
-            *q++=image->colormap[(ssize_t) index];
+            index=ConstrainColormapIndex(image,*p,exception);
+            SetPixelIndex(image,index,q);
+            SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
             p++;
+            q+=GetPixelChannels(image);
           }
         if (SyncAuthenticPixels(image,exception) == MagickFalse)
           break;
@@ -410,14 +416,14 @@ static void InsertRow(unsigned char *p,ssize_t y,Image *image, int bpp)
      
     case 24:     /*  Convert DirectColor scanline.  */
       q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
-      if (q == (PixelPacket *) NULL)
+      if (q == (Quantum *) NULL)
         break;
       for (x=0; x < (ssize_t) image->columns; x++)
         {
-          q->red=ScaleCharToQuantum(*p++);
-          q->green=ScaleCharToQuantum(*p++);
-          q->blue=ScaleCharToQuantum(*p++);
-          q++;
+          SetPixelRed(image,ScaleCharToQuantum(*p++),q);
+          SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
+          SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
+          q+=GetPixelChannels(image);
         }
       if (!SyncAuthenticPixels(image,exception))
         break;
@@ -433,13 +439,13 @@ static void InsertRow(unsigned char *p,ssize_t y,Image *image, int bpp)
   x++; \
   if((ssize_t) x>=ldblk) \
   { \
-    InsertRow(BImgBuff,(ssize_t) y,image,bpp); \
+    InsertRow(image,BImgBuff,(ssize_t) y,bpp,exception); \
     x=0; \
     y++; \
     } \
 }
 /* WPG1 raster reader. */
-static int UnpackWPGRaster(Image *image,int bpp)
+static int UnpackWPGRaster(Image *image,int bpp,ExceptionInfo *exception)
 {
   int
     x,
@@ -505,7 +511,7 @@ static int UnpackWPGRaster(Image *image,int bpp)
                   BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
                   return(-4);
                 }
-              InsertRow(BImgBuff,y-1,image,bpp);
+              InsertRow(image,BImgBuff,y-1,bpp,exception);
             }
         }
       }
@@ -525,14 +531,23 @@ static int UnpackWPGRaster(Image *image,int bpp)
   x++; \
   if((ssize_t) x >= ldblk) \
   { \
-    InsertRow(BImgBuff,(ssize_t) y,image,bpp); \
+    InsertRow(image,BImgBuff,(ssize_t) y,bpp,exception); \
     x=0; \
     y++; \
    } \
 }
 /* WPG2 raster reader. */
-static int UnpackWPG2Raster(Image *image,int bpp)
+static int UnpackWPG2Raster(Image *image,int bpp,ExceptionInfo *exception)
 {
+  size_t
+    x,
+    y;
+
+  ssize_t
+    ldblk;
+
+  int XorMe = 0;
+
   unsigned int
     SampleSize=1;
 
@@ -542,18 +557,9 @@ static int UnpackWPG2Raster(Image *image,int bpp)
     RunCount,
     SampleBuffer[8];
 
-  size_t
-    x,
-    y;
-
   unsigned int
     i;
 
-  ssize_t
-    ldblk;
-
-  int XorMe = 0;
-
   x=0;
   y=0;
   ldblk=(ssize_t) ((bpp*image->columns+7)/8);
@@ -576,8 +582,9 @@ static int UnpackWPG2Raster(Image *image,int bpp)
             return(-2);
           break;
         case 0x7E:
-          (void) fprintf(stderr,"\nUnsupported WPG token XOR, please report!");
-    XorMe=!XorMe;
+          (void) FormatLocaleFile(stderr,
+            "\nUnsupported WPG token XOR, please report!");
+          XorMe=!XorMe;
           break;
         case 0x7F:
           RunCount=ReadBlobByte(image);   /* BLK */
@@ -587,8 +594,8 @@ static int UnpackWPG2Raster(Image *image,int bpp)
             }
           break;
         case 0xFD:
-    RunCount=ReadBlobByte(image);   /* EXT */
-    for(i=0; i<= RunCount;i++)
+          RunCount=ReadBlobByte(image);   /* EXT */
+          for(i=0; i<= RunCount;i++)
             for(bbuf=0; bbuf < SampleSize; bbuf++)
               InsertByte6(SampleBuffer[bbuf]);          
           break;
@@ -596,17 +603,17 @@ static int UnpackWPG2Raster(Image *image,int bpp)
           RunCount=ReadBlobByte(image);  /* RST */
           if(x!=0)
             {
-              (void) fprintf(stderr,
-                             "\nUnsupported WPG2 unaligned token RST x=%lu, please report!\n"
-                             ,x);
+              (void) FormatLocaleFile(stderr,
+                "\nUnsupported WPG2 unaligned token RST x=%.20g, please report!\n"
+                ,(double) x);
               return(-3);
             }
           {
             /* duplicate the previous row RunCount x */
             for(i=0;i<=RunCount;i++)
               {      
-                InsertRow(BImgBuff,(ssize_t) (image->rows >= y ? y : image->rows-1),
-                          image,bpp);
+                InsertRow(image,BImgBuff,(ssize_t) (image->rows >= y ? y : image->rows-1),
+                          bpp,exception);
                 y++;
               }    
           }
@@ -735,7 +742,7 @@ static Image *ExtractPostscript(Image *image,const ImageInfo *image_info,
 
   /* Obtain temporary file */
   AcquireUniqueFilename(postscript_file);
-  ps_file=OpenMagickStream(postscript_file,"wb");
+  ps_file=fopen_utf8(postscript_file,"wb");
   if (ps_file == (FILE *) NULL)
     goto FINISH;
 
@@ -760,8 +767,8 @@ static Image *ExtractPostscript(Image *image,const ImageInfo *image_info,
   (void) CopyMagickMemory(clone_info->magick,magic_info->name,MaxTextExtent);
   
     /* Read nested image */
-  /*FormatString(clone_info->filename,"%s:%.1024s",magic_info->name,postscript_file);*/
-  FormatMagickString(clone_info->filename,MaxTextExtent,"%.1024s",postscript_file);
+  /*FormatString(clone_info->filename,"%s:%s",magic_info->name,postscript_file);*/
+  FormatLocaleString(clone_info->filename,MaxTextExtent,"%s",postscript_file);
   image2=ReadImage(clone_info,exception);
 
   if (!image2)
@@ -937,6 +944,9 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
   ssize_t
     ldblk;
 
+  size_t
+    one;
+
   unsigned char
     *BImgBuff;
 
@@ -949,7 +959,8 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
   assert(image_info->signature == MagickSignature);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
-  image=AcquireImage(image_info);
+  one=1;
+  image=AcquireImage(image_info,exception);
   image->depth=8;
   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
   if (status == MagickFalse)
@@ -1010,8 +1021,8 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
               if(BitmapHeader1.HorzRes && BitmapHeader1.VertRes)
                 {
                   image->units=PixelsPerCentimeterResolution;
-                  image->x_resolution=BitmapHeader1.HorzRes/470.0;
-                  image->y_resolution=BitmapHeader1.VertRes/470.0;
+                  image->resolution.x=BitmapHeader1.HorzRes/470.0;
+                  image->resolution.y=BitmapHeader1.VertRes/470.0;
                 }
               image->columns=BitmapHeader1.Width;
               image->rows=BitmapHeader1.Heigth;
@@ -1024,7 +1035,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
               WPG_Palette.NumOfEntries=ReadBlobLSBShort(image);
 
               image->colors=WPG_Palette.NumOfEntries;
-              if (!AcquireImageColormap(image,image->colors))
+              if (!AcquireImageColormap(image,image->colors,exception))
                 goto NoMemory;
               for (i=WPG_Palette.StartIndex;
                    i < (int)WPG_Palette.NumOfEntries; i++)
@@ -1066,8 +1077,8 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
               image->page.y=(int) (BitmapHeader2.LowLeftX/470.0);
               if(BitmapHeader2.HorzRes && BitmapHeader2.VertRes)
                 {
-                  image->x_resolution=BitmapHeader2.HorzRes/470.0;
-                  image->y_resolution=BitmapHeader2.VertRes/470.0;
+                  image->resolution.x=BitmapHeader2.HorzRes/470.0;
+                  image->resolution.y=BitmapHeader2.VertRes/470.0;
                 }
               image->columns=BitmapHeader2.Width;
               image->rows=BitmapHeader2.Heigth;
@@ -1076,8 +1087,8 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
             UnpackRaster:      
               if ((image->colors == 0) && (bpp != 24))
                 {
-                  image->colors=1 << bpp;
-                  if (!AcquireImageColormap(image,image->colors))
+                  image->colors=one << bpp;
+                  if (!AcquireImageColormap(image,image->colors,exception))
                     {
                     NoMemory:
                       ThrowReaderException(ResourceLimitError,
@@ -1094,9 +1105,9 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
               else
                 {
                   if (bpp < 24)
-                    if ( (image->colors < (1UL<<bpp)) && (bpp != 24) )
-                      image->colormap=(PixelPacket *) ResizeQuantumMemory(
-                        image->colormap,(size_t) (1UL << bpp),
+                    if ( (image->colors < (one << bpp)) && (bpp != 24) )
+                      image->colormap=(PixelInfo *) ResizeQuantumMemory(
+                        image->colormap,(size_t) (one << bpp),
                         sizeof(*image->colormap));
                 }
           
@@ -1115,7 +1126,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
                     }
                 }      
 
-              if(UnpackWPGRaster(image,bpp) < 0)
+              if(UnpackWPGRaster(image,bpp,exception) < 0)
                 /* The raster cannot be unpacked */
                 {
                 DecompressionFailed:
@@ -1155,7 +1166,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
                 }
 
               /* Allocate next image structure. */
-              AcquireNextImage(image_info,image);
+              AcquireNextImage(image_info,image,exception);
               image->depth=8;
               if (image->next == (Image *) NULL)
                 goto Finish;
@@ -1208,7 +1219,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
               WPG_Palette.NumOfEntries=ReadBlobLSBShort(image);
 
               image->colors=WPG_Palette.NumOfEntries;
-              if (AcquireImageColormap(image,image->colors) == MagickFalse)
+              if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
                 ThrowReaderException(ResourceLimitError,
                   "MemoryAllocationFailed");
               for (i=WPG_Palette.StartIndex;
@@ -1256,16 +1267,20 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
 
               if ((image->colors == 0) && (bpp != 24))
                 {
-                  image->colors=1 << bpp;
-                  if (!AcquireImageColormap(image,image->colors))
+                  size_t
+                    one;
+
+                  one=1;
+                  image->colors=one << bpp;
+                  if (!AcquireImageColormap(image,image->colors,exception))
                     goto NoMemory;
                 }
               else
                 {
                   if(bpp < 24)
-                    if( image->colors<(1UL<<bpp) && bpp!=24 )
-                      image->colormap=(PixelPacket *) ResizeQuantumMemory(
-                       image->colormap,(size_t) (1UL << bpp),
+                    if( image->colors<(one << bpp) && bpp!=24 )
+                      image->colormap=(PixelInfo *) ResizeQuantumMemory(
+                       image->colormap,(size_t) (one << bpp),
                        sizeof(*image->colormap));
                 }
 
@@ -1283,7 +1298,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
                     for(i=0; i< (ssize_t) image->rows; i++)
                       {
                         (void) ReadBlob(image,ldblk,BImgBuff);
-                        InsertRow(BImgBuff,i,image,bpp);
+                        InsertRow(image,BImgBuff,i,bpp,exception);
                       }
 
                     if(BImgBuff)
@@ -1292,7 +1307,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
                   }
                 case 1:    /*RLE for WPG2 */
                   {
-                    if( UnpackWPG2Raster(image,bpp) < 0)
+                    if( UnpackWPG2Raster(image,bpp,exception) < 0)
                       goto DecompressionFailed;
                     break;
                   }   
@@ -1328,7 +1343,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
     
 
               /* Allocate next image structure. */
-              AcquireNextImage(image_info,image);
+              AcquireNextImage(image_info,image,exception);
               image->depth=8;
               if (image->next == (Image *) NULL)
                 goto Finish;
@@ -1347,6 +1362,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
 
       case 0x1B:          /*bitmap rectangle*/
               WPG2Flags = LoadWPG2Flags(image,StartWPG.PosSizePrecision,NULL,&CTM);
+              (void) WPG2Flags;
               break;
             }
         }