summaryrefslogtreecommitdiff
path: root/coders/wpg.c
diff options
context:
space:
mode:
Diffstat (limited to 'coders/wpg.c')
-rw-r--r--coders/wpg.c445
1 files changed, 404 insertions, 41 deletions
diff --git a/coders/wpg.c b/coders/wpg.c
index edfedc3..25fa13b 100644
--- a/coders/wpg.c
+++ b/coders/wpg.c
@@ -1,5 +1,5 @@
/*
-% Copyright (C) 2003-2021 GraphicsMagick Group
+% Copyright (C) 2003-2023 GraphicsMagick Group
% Copyright (C) 2002 ImageMagick Studio
%
% This program is covered by multiple licenses, which are described in
@@ -21,7 +21,7 @@
% %
% Software Design %
% Jaroslav Fojtik %
-% June 2000 - 2021 %
+% June 2000 - 2023 %
% Rework for GraphicsMagick %
% Bob Friesenhahn %
% Feb-May 2003 %
@@ -46,6 +46,7 @@
#include "magick/shear.h"
#include "magick/tempfile.h"
#include "magick/transform.h"
+#include "magick/quantize.h"
#include "magick/utility.h"
@@ -189,9 +190,19 @@ static const RGB_Record WPG1_Palette[256]={
};
-static int ApproveFormatForWPG(const char *Format)
+static int ApproveFormatForWPG(const char *Format, ExceptionInfo *exception)
{
+ const MagickInfo *magick_info;
+
if(!strcmp(Format,"PFB")) return 0;
+
+ /*if(!strcmp(Format,"8BIMTEXT")) return 0; This test is no longer needed, META module includes this case. */
+ magick_info = GetMagickInfo(Format,exception);
+ if(magick_info != (const MagickInfo *)NULL)
+ {
+ if(strcmp(magick_info->module, "META") == 0) return 0;
+ }
+
return 1;
}
@@ -235,28 +246,6 @@ static unsigned int IsWPG(const unsigned char *magick,const size_t length)
return(False);
}
-static MagickPassFail ReallocColormap(Image *image,unsigned int colors)
-{
- PixelPacket *colormap;
-
- /* FIXME: This implementation would be better using a true realloc */
- colormap=MagickAllocateClearedArray(PixelPacket *,colors,sizeof(PixelPacket));
- if (colormap != (PixelPacket *) NULL)
- {
- if (image->colormap != (PixelPacket *) NULL)
- {
- (void) memcpy(colormap,image->colormap,
- (size_t) Min(image->colors,colors)*sizeof(PixelPacket));
- MagickFreeMemory(image->colormap);
- }
- image->colormap = colormap;
- image->colors = colors;
- return MagickPass;
- }
-
- return MagickFail;
-}
-
static int Rd_WP_DWORD(Image *image, unsigned long *d)
{
unsigned char b;
@@ -886,7 +875,7 @@ static Image *ExtractPostscript(Image *image,const ImageInfo *image_info,
/*
Verify if this is an allowed subordinate image format
*/
- if(!ApproveFormatForWPG(format))
+ if(!ApproveFormatForWPG(format,exception))
{
(void) LogMagickEvent(CoderEvent, GetMagickModule(),
"Format \"%s\" cannot be embedded inside WPG.", format);
@@ -975,7 +964,7 @@ static Image *ExtractPostscript(Image *image,const ImageInfo *image_info,
clone_info->blob=(void *) NULL;
/* clone_info->length=0; */
(void) strlcpy(clone_info->magick, format, sizeof(clone_info->magick));
- (void) strcpy(clone_info->filename, "");
+ (void) strlcpy(clone_info->filename, "", sizeof(clone_info->filename));
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
"Reading embedded \"%s\" content from blob...", clone_info->magick);
image2 = BlobToImage(clone_info, ps_data, PS_Size, &image->exception );
@@ -984,8 +973,18 @@ static Image *ExtractPostscript(Image *image,const ImageInfo *image_info,
{
goto FINISH_UNL;
}
- if(exception->severity>=ErrorException) /* When exception is raised, destroy image2 read. */
+ if(exception->severity >= ErrorException) /* When exception is raised, destroy image2 read. */
{
+ if(image->logging)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Exception raised during embedded image reading.");
+ CloseBlob(image2);
+ DestroyImageList(image2);
+ goto FINISH_UNL;
+ }
+ if(!GetPixelCachePresent(image2))
+ {
+ if(image->logging)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(), "Pixel cache is missing for embedded image.");
CloseBlob(image2);
DestroyImageList(image2);
goto FINISH_UNL;
@@ -1037,6 +1036,62 @@ static Image *ExtractPostscript(Image *image,const ImageInfo *image_info,
return(image);
}
+#define LogHeaderWPG(_WPG_HEADER) \
+ (void)LogMagickEvent(CoderEvent,GetMagickModule(), \
+ "WPG Header Id=%Xh:\n" \
+ " DataOffset=%u\n" \
+ " ProductType=%u\n" \
+ " FileType=%u\n" \
+ " Version=%u.%u\n" \
+ " EncryptKey=%u\n" \
+ " Reserved=%u", \
+ (unsigned int)_WPG_HEADER.FileId, \
+ (unsigned int)_WPG_HEADER.DataOffset, \
+ (unsigned int)_WPG_HEADER.ProductType, \
+ (unsigned int)_WPG_HEADER.FileType, \
+ (unsigned int)_WPG_HEADER.MajorVersion, \
+ (unsigned int)_WPG_HEADER.MinorVersion, \
+ (unsigned int)_WPG_HEADER.EncryptKey, \
+ (unsigned int)_WPG_HEADER.Reserved)
+
+#define LogWPGBitmapType1(_WPG_BITMAP_TYPE1) \
+ (void)LogMagickEvent(CoderEvent,GetMagickModule(), \
+ "WPG Bitmap1 Header:\n" \
+ " Width=%u\n" \
+ " Heigth=%u\n" \
+ " Depth=%u\n" \
+ " HorzRes=%u\n" \
+ " VertRes=%u", \
+ (unsigned int)_WPG_BITMAP_TYPE1.Width, \
+ (unsigned int)_WPG_BITMAP_TYPE1.Heigth, \
+ (unsigned int)_WPG_BITMAP_TYPE1.Depth, \
+ (unsigned int)_WPG_BITMAP_TYPE1.HorzRes, \
+ (unsigned int)_WPG_BITMAP_TYPE1.VertRes)
+
+#define LogWPGBitmapType2(_WPG_BITMAP_TYPE2) \
+ (void)LogMagickEvent(CoderEvent,GetMagickModule(), \
+ "WPG Bitmap2 Header:\n" \
+ " RotAngle=%u\n" \
+ " LowLeftX=%u\n" \
+ " LowLeftY=%u\n" \
+ " UpRightX=%u\n" \
+ " UpRightY=%u\n" \
+ " Width=%u\n" \
+ " Heigth=%u\n" \
+ " Depth=%u\n" \
+ " HorzRes=%u\n" \
+ " VertRes=%u", \
+ (unsigned int)_WPG_BITMAP_TYPE2.RotAngle, \
+ (unsigned int)_WPG_BITMAP_TYPE2.LowLeftX, \
+ (unsigned int)_WPG_BITMAP_TYPE2.LowLeftY, \
+ (unsigned int)_WPG_BITMAP_TYPE2.UpRightX, \
+ (unsigned int)_WPG_BITMAP_TYPE2.UpRightY, \
+ (unsigned int)_WPG_BITMAP_TYPE2.Width, \
+ (unsigned int)_WPG_BITMAP_TYPE2.Heigth, \
+ (unsigned int)_WPG_BITMAP_TYPE2.Depth, \
+ (unsigned int)_WPG_BITMAP_TYPE2.HorzRes, \
+ (unsigned int)_WPG_BITMAP_TYPE2.VertRes)
+
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1067,7 +1122,6 @@ static Image *ExtractPostscript(Image *image,const ImageInfo *image_info,
%
% o exception: return any errors or warnings in this structure.
%
-%
*/
static Image *ReadWPGImage(const ImageInfo *image_info,
ExceptionInfo *exception)
@@ -1076,8 +1130,8 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
{
unsigned long FileId;
ExtendedSignedIntegralType DataOffset; /* magick_uint32_t */
- unsigned int ProductType;
- unsigned int FileType;
+ unsigned char ProductType;
+ unsigned char FileType;
unsigned char MajorVersion;
unsigned char MinorVersion;
unsigned int EncryptKey;
@@ -1217,14 +1271,15 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
*/
Header.FileId=ReadBlobLSBLong(image);
Header.DataOffset=(ExtendedSignedIntegralType) ReadBlobLSBLong(image);
- Header.ProductType=ReadBlobLSBShort(image);
- Header.FileType=ReadBlobLSBShort(image);
+ Header.ProductType=ReadBlobByte(image);
+ Header.FileType=ReadBlobByte(image);
Header.MajorVersion=ReadBlobByte(image);
Header.MinorVersion=ReadBlobByte(image);
Header.EncryptKey=ReadBlobLSBShort(image);
Header.Reserved=ReadBlobLSBShort(image);
+ if(logging) LogHeaderWPG(Header);
- if (Header.FileId!=0x435057FF || (Header.ProductType>>8)!=0x16)
+ if (Header.FileId!=0x435057FF || Header.FileType!=0x16)
ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
if (Header.EncryptKey!=0)
ThrowReaderException(CoderError,EncryptedWPGImageFileNotSupported,image);
@@ -1251,7 +1306,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
ThrowReaderException(CorruptImageError,AnErrorHasOccurredReadingFromFile,image);
}
- switch(Header.FileType)
+ switch(Header.MajorVersion)
{
case 1: /* WPG level 1 */
BitmapHeader2.RotAngle = 0;
@@ -1293,6 +1348,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
BitmapHeader1.Depth=ReadBlobLSBShort(image);
BitmapHeader1.HorzRes=ReadBlobLSBShort(image);
BitmapHeader1.VertRes=ReadBlobLSBShort(image);
+ if(logging) LogWPGBitmapType1(BitmapHeader1);
if(BitmapHeader1.HorzRes && BitmapHeader1.VertRes)
{
@@ -1303,7 +1359,16 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
image->columns=BitmapHeader1.Width;
image->rows=BitmapHeader1.Heigth;
bpp=BitmapHeader1.Depth;
-
+ // Whole palette is useless for bilevel image.
+ if(bpp==1)
+ {
+ image->storage_class = PseudoClass;
+ image->colors = 2;
+ if (!AllocateImageColormap(image,2)) goto NoMemory;
+ image->colormap[0].red = image->colormap[0].green = image->colormap[0].blue = 0;
+ image->colormap[1].red = image->colormap[1].green = image->colormap[1].blue = MaxRGB;
+ image->colormap[0].opacity = image->colormap[1].opacity = OpaqueOpacity;
+ }
goto UnpackRaster;
case 0x0E: /*Color palette */
@@ -1344,6 +1409,7 @@ static Image *ReadWPGImage(const ImageInfo *image_info,
BitmapHeader2.Depth=ReadBlobLSBShort(image);
BitmapHeader2.HorzRes=ReadBlobLSBShort(image);
BitmapHeader2.VertRes=ReadBlobLSBShort(image);
+ if(logging) LogWPGBitmapType2(BitmapHeader2);
image->units=PixelsPerCentimeterResolution;
image->page.width=(unsigned int)
@@ -1365,7 +1431,7 @@ UnpackRaster:
if(bpp>24)
{ThrowReaderException(CoderError,ColorTypeNotSupported,image)}
- if ((image->storage_class != PseudoClass) && (bpp != 24))
+ if ((image->storage_class != PseudoClass) && (bpp != 24) && bpp!=1)
{
image->colors=1 << bpp;
if (!AllocateImageColormap(image,image->colors))
@@ -1387,8 +1453,8 @@ UnpackRaster:
else
{
if (bpp < 24)
- if ( (image->colors < (1UL<<bpp)) && (bpp != 24) )
- if (!ReallocColormap(image,1U<<bpp))
+ if ( (image->colors != (1UL<<bpp)) && (bpp != 24) )
+ if (!ReallocateImageColormap(image,1U<<bpp))
goto NoMemory;
}
@@ -1589,8 +1655,8 @@ UnpackRaster:
else
{
if(bpp < 24)
- if( image->colors<(1UL<<bpp) && bpp!=24 )
- if (!ReallocColormap(image,1U<<bpp))
+ if(image->colors!=(1UL<<bpp) && bpp!=24)
+ if (!ReallocateImageColormap(image,1U<<bpp))
goto NoMemory;
}
@@ -1742,6 +1808,301 @@ UnpackRaster:
ThrowReaderException(CorruptImageError,ImageFileDoesNotContainAnyImageData,image);
return(image);
}
+
+
+/* RLE helper structure. */
+typedef struct
+{
+ unsigned char count;
+ unsigned char pos;
+ unsigned char buf[254];
+} WPG_RLE_packer;
+
+//FILE *DebugRLE = NULL;
+
+static void WPG_RLE_Flush(WPG_RLE_packer *WPG_RLE, Image *image, unsigned char n)
+{
+ if(n>WPG_RLE->pos) n=WPG_RLE->pos;
+ if(n>0x7F) n=0x7F;
+ if(n>0)
+ {
+ //if(DebugRLE) fprintf(DebugRLE," size=%X",n);
+ WriteBlobByte(image,n);
+ WriteBlob(image, n, WPG_RLE->buf);
+ WPG_RLE->pos -= n;
+ if(WPG_RLE->pos>0)
+ memcpy(WPG_RLE->buf, WPG_RLE->buf+n, n);
+ else
+ WPG_RLE->count = 0;
+ }
+}
+
+
+static void WPG_RLE_AddCharacter(WPG_RLE_packer *WPG_RLE, unsigned char b, Image *image)
+{
+ WPG_RLE->buf[WPG_RLE->pos++] = b;
+
+/* if(DebugRLE)
+ {
+ fprintf(DebugRLE,"\n%u",b);
+ if(WPG_RLE->pos>=0x7E)
+ fprintf(DebugRLE," *%u %X", WPG_RLE->pos, WPG_RLE->pos);
+ } */
+
+ if(WPG_RLE->pos>1)
+ {
+ if(WPG_RLE->count==0x7E || WPG_RLE->buf[WPG_RLE->pos-2]!=b)
+ {
+ if(WPG_RLE->count>=1)
+ {
+ WPG_RLE->count++; // True number of repeated BYTEs.
+ WPG_RLE_Flush(WPG_RLE, image, WPG_RLE->pos-1-WPG_RLE->count);
+ WriteBlobByte(image, WPG_RLE->count|0x80);
+ WriteBlobByte(image, WPG_RLE->buf[0]);
+ //if(DebugRLE) fprintf(DebugRLE," count=%X, val=%X",WPG_RLE->count,WPG_RLE->buf[0]);
+ WPG_RLE->pos = 1;
+ WPG_RLE->buf[0] = b;
+ }
+ WPG_RLE->count = 0;
+ }
+ else
+ WPG_RLE->count++;
+ }
+
+ if(WPG_RLE->pos-WPG_RLE->count>0x7E) // We have uncompressible block with size 0x7F.
+ {
+ WPG_RLE_Flush(WPG_RLE, image, 0x7F);
+ return;
+ }
+ if(WPG_RLE->pos>0x7E && WPG_RLE->count>=1)
+ {
+ WPG_RLE_Flush(WPG_RLE, image, WPG_RLE->pos-1-WPG_RLE->count);
+ return;
+ }
+}
+
+
+static void WPG_RLE_FinalFlush(WPG_RLE_packer *WPG_RLE, Image *image)
+{
+ if(WPG_RLE->count>1)
+ {
+ WPG_RLE_AddCharacter(WPG_RLE, WPG_RLE->buf[WPG_RLE->pos-1]^0xFF, image); // Add a fake BYTE.
+ WPG_RLE->pos = 0; // Take a last fake BYTE away.
+ }
+ else
+ {
+ WPG_RLE_Flush(WPG_RLE,image,0x7F);
+ WPG_RLE_Flush(WPG_RLE,image,0x7F);
+ WPG_RLE->count = 0;
+ }
+}
+
+
+static void WPG_RLE_AddBlock(WPG_RLE_packer *WPG_RLE, Image *image, const unsigned char *blk, magick_uint16_t size)
+{
+ while(size-- > 0)
+ {
+ WPG_RLE_AddCharacter(WPG_RLE, *blk, image);
+ blk++;
+ }
+}
+
+
+static void WPG_RLE_Init(WPG_RLE_packer *WPG_RLE)
+{
+ WPG_RLE->pos = WPG_RLE->count = 0;
+}
+
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% W r i t e W P G I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Function WriteWPGImage writes an WPG image to a file.
+%
+% The format of the WriteWPGImage method is:
+%
+% unsigned int WriteWPGImage(const ImageInfo *image_info,Image *image)
+%
+% A description of each parameter follows.
+%
+% o status: Function WriteWPGImage return True if the image is written.
+% False is returned is there is a memory shortage or if the image file
+% fails to write.
+%
+% o image_info: Specifies a pointer to a ImageInfo structure.
+%
+% o image: A pointer to an Image structure.
+*/
+static MagickPassFail WriteWPGImage(const ImageInfo *image_info, Image *image)
+{
+ long y;
+ unsigned int status;
+ int logging;
+ unsigned char StoredPlanes;
+ unsigned ldblk;
+ magick_off_t NumericOffs, CurrOffs;
+ QuantizeInfo quantize_info;
+ WPG_RLE_packer PackRLE;
+ unsigned char *pixels;
+
+ /*
+ Open output image file.
+ */
+ assert(image_info != (const ImageInfo *) NULL);
+ assert(image_info->signature == MagickSignature);
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ logging = LogMagickEvent(CoderEvent,GetMagickModule(),"enter WPG");
+ status = OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
+ if(status == MagickFail)
+ ThrowWriterException(FileOpenError,UnableToOpenFile,image);
+ WPG_RLE_Init(&PackRLE);
+
+ (void)TransformColorspace(image,RGBColorspace);
+
+ if ((image->storage_class == DirectClass) ||
+ ((image->storage_class == PseudoClass) && (image->colors<=0 || image->colors>256)))
+ {
+ GetQuantizeInfo(&quantize_info);
+ quantize_info.dither = image_info->dither;
+ quantize_info.number_colors = 256;
+ status = QuantizeImage(&quantize_info,image);
+ if(status==MagickFail || image->colors==0) goto ImageFailure;
+ }
+ if(image->colors <= 2)
+ {
+ StoredPlanes=1;
+ ldblk = (image->columns+7)/8;
+ } else if(image->colors <= 16)
+ {
+ StoredPlanes=4;
+ ldblk = (image->columns+1)/2;
+ } else
+ {
+ StoredPlanes = 8;
+ ldblk = image->columns;
+ }
+
+ pixels = MagickAllocateResourceLimitedMemory(unsigned char *,(size_t)(ldblk));
+ if(pixels == (unsigned char *) NULL)
+ ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
+
+ /* Write WPG hader. */
+ WriteBlobLSBLong(image,0x435057FF); //DWORD FileId
+ WriteBlobLSBLong(image,16); //DWORD DataOffset;
+ WriteBlobByte(image,1); //BYTE Product Type
+ WriteBlobByte(image,0x16); //BYTE FileType;
+ WriteBlobByte(image,1); //BYTE MajorVersion;
+ WriteBlobByte(image,0); //BYTE MinorVersion;
+ WriteBlobLSBShort(image,0); //WORD EncryptKey;
+ WriteBlobLSBShort(image,0); //WORD Reserved;
+
+ /* Start WPG l1 */
+ WriteBlobByte(image,0xF);
+ WriteBlobByte(image,0x6);
+ WriteBlobByte(image,1); //BYTE Version number
+ WriteBlobByte(image,0); //BYTE Flags (bit 0 PostScript, maybe bitmap, bit 1 PostScript, no bitmap
+ WriteBlobLSBShort(image,image->columns); //WORD Width of image (arbitrary units)
+ WriteBlobLSBShort(image,image->rows); //WORD Height of image (arbitrary units)
+
+ /* Palette */
+ if(StoredPlanes>1)
+ {
+ magick_uint16_t i;
+ WriteBlobByte(image,0xE);
+ i = 4+3*(1<<StoredPlanes);
+ if(i<0xFF)
+ WriteBlobByte(image,i);
+ else
+ {
+ WriteBlobByte(image,0xFF);
+ WriteBlobLSBShort(image,i);
+ }
+ WriteBlobLSBShort(image,0); // Start index
+ WriteBlobLSBShort(image,1<<StoredPlanes); // Num entries
+
+ for(i=0; i<(1<<StoredPlanes); i++)
+ {
+ if(i>=image->colors || image->colormap==NULL)
+ {
+ WriteBlobByte(image,i);
+ WriteBlobByte(image,i);
+ WriteBlobByte(image,i);
+ }
+ else
+ {
+ WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].red));
+ WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].green));
+ WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].blue));
+ }
+ }
+ }
+
+ /* Bitmap 1 header */
+ WriteBlobByte(image,0xB);
+ WriteBlobByte(image,0xFF);
+ NumericOffs = TellBlob(image);
+ WriteBlobLSBShort(image,0x8000);
+ WriteBlobLSBShort(image,0);
+
+ WriteBlobLSBShort(image,image->columns); //WORD Width
+ WriteBlobLSBShort(image,image->rows); //WORD Height
+ WriteBlobLSBShort(image,StoredPlanes); //WORD Depth;
+ WriteBlobLSBShort(image,75); //WORD HorzRes;
+ WriteBlobLSBShort(image,75); //WORD VertRes;
+
+ /*
+ Store image data.
+ */
+ for(y=0; y<(long)image->rows; y++)
+ {
+ //if(y==1310 && DebugRLE==NULL) DebugRLE=fopen("o:\\temp\\14\\debug.txt","wb");
+ //if(y>1310 && DebugRLE) {fclose(DebugRLE);DebugRLE=NULL;}
+
+ if(AcquireImagePixels(image,0,y,image->columns,1,&image->exception) == (const PixelPacket *)NULL)
+ {
+ status = MagickFail;
+ break;
+ }
+ if(ExportImagePixelArea(image, (StoredPlanes==1)?GrayQuantum:IndexQuantum, StoredPlanes,pixels,0,0) != MagickPass)
+ {
+ status = MagickFail;
+ break;
+ }
+ WPG_RLE_AddBlock(&PackRLE,image,pixels,ldblk);
+ WPG_RLE_FinalFlush(&PackRLE,image);
+ }
+
+ CurrOffs = TellBlob(image);
+ SeekBlob(image,NumericOffs,SEEK_SET);
+ NumericOffs = CurrOffs - NumericOffs - 4;
+ WriteBlobLSBShort(image, 0x8000|(NumericOffs>>16));
+ WriteBlobLSBShort(image, NumericOffs&0xFFFF);
+ SeekBlob(image,CurrOffs,SEEK_SET);
+
+ /* End of WPG data */
+ WriteBlobByte(image,0x10);
+ WriteBlobByte(image,0);
+
+ MagickFreeResourceLimitedMemory(pixels);
+ImageFailure:
+ CloseBlob(image);
+
+
+ if (logging)
+ (void)LogMagickEvent(CoderEvent,GetMagickModule(),"return WPG");
+
+ return(status);
+}
+
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1773,10 +2134,12 @@ ModuleExport void RegisterWPGImage(void)
entry=SetMagickInfo("WPG");
entry->decoder=(DecoderHandler) ReadWPGImage;
+ entry->encoder = (EncoderHandler)WriteWPGImage;
entry->magick=(MagickHandler) IsWPG;
entry->description="Word Perfect Graphics";
entry->module="WPG";
entry->seekable_stream=True;
+ entry->adjoin=MagickFalse;
entry->coder_class=UnstableCoderClass;
(void) RegisterMagickInfo(entry);
}