GraphicsMagick: 2 new changesets
GraphicsMagick Commits <[email protected]>
| Newsgroups | gmane.comp.video.graphicsmagick.cvs |
|---|---|
| Message-ID | <mailman.11300.1682786649.1602.graphicsmagick-commit@lists.sourceforge.net> |
changeset 8263ceca7fb3 in /hg/GraphicsMagick details: http://hg.GraphicsMagick.org/hg/GraphicsMagick?cmd=changeset;node=8263ceca7fb3 summary: RoundDoubleToQuantumN(): Version of RoundDoubleToQuantum() which handles NaN. Use where needed. changeset 646dd7d9dda2 in /hg/GraphicsMagick details: http://hg.GraphicsMagick.org/hg/GraphicsMagick?cmd=changeset;node=646dd7d9dda2 summary: Merge heads diffstat: ChangeLog | 17 ++++ coders/topol.c | 171 +++++++++++++++++++++++++++++++++++++++++-- coders/viff.c | 11 +-- magick/blob.c | 23 +++++ magick/blob.h | 1 + magick/image.h | 4 +- magick/import.c | 206 +++++++++++++++++++++++++--------------------------- www/Changelog.html | 9 ++ 8 files changed, 317 insertions(+), 125 deletions(-) diffs (truncated from 1119 to 500 lines): diff -r c2a4d0286bcb -r 646dd7d9dda2 ChangeLog --- a/ChangeLog Sat Apr 29 10:51:20 2023 -0500 +++ b/ChangeLog Sat Apr 29 11:43:45 2023 -0500 @@ -1,5 +1,22 @@ +2023-04-29 Fojtik Jaroslav <[email protected]> + + * coders/topol.c: First attempt to make a writer. + * magick/blob.h magick/blob.c: New function WriteBlobLSBDouble. + 2023-04-29 Bob Friesenhahn <[email protected]> + * magick/image.h (RoundDoubleToQuantumN): New macro to address NaN + issues when converting a double to a Quantum. Use it where + needed. + + * magick/import.c (ImportGrayQuantumType): If value is nan, then + use 0.0. Addresses SourceForge issue #706 "Integer overflow, + floating-point exception, pointer overflow in gm". + + * coders/viff.c (ReadVIFFImage): If value is nan, then use 0.0. + Addresses SourceForge issue #706 "Integer overflow, floating-point + exception, pointer overflow in gm". + * coders/mat.c (InsertComplexDoubleRow): If computed f is nan, then use 0.0. Addresses SourceForge issue #708 "Undefined behavior while converting negative infinity to integer". diff -r c2a4d0286bcb -r 646dd7d9dda2 coders/topol.c --- a/coders/topol.c Sat Apr 29 10:51:20 2023 -0500 +++ b/coders/topol.c Sat Apr 29 11:43:45 2023 -0500 @@ -20,13 +20,13 @@ % % % Software Design % % Jaroslav Fojtik % -% 2003 - 2018 % +% 2003 - 2023 % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% +% Note: TopoL GIS is here: http://www.topol.eu/articles/about */ /* @@ -294,17 +294,17 @@ % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% Method ReadTOPOLImage reads an TOPOL X image file and returns it. It +% Method ReadTopoLImage reads an TOPOL X image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % -% The format of the ReadTOPOLImage method is: +% The format of the ReadTopoLImage method is: % -% Image *ReadTOPOLImage(const ImageInfo *image_info,ExceptionInfo *exception) +% Image *ReadTopoLImage(const ImageInfo *image_info,ExceptionInfo *exception) % % A description of each parameter follows: % -% o image: Method ReadTOPOLImage returns a pointer to the image after +% o image: Method ReadTopoLImage returns a pointer to the image after % reading. A null image is returned if there is a memory shortage or if % the image cannot be read. % @@ -325,7 +325,7 @@ ThrowReaderException(code_,reason_,image_); \ } -static Image *ReadTOPOLImage(const ImageInfo * image_info, ExceptionInfo * exception) +static Image *ReadTopoLImage(const ImageInfo * image_info, ExceptionInfo * exception) { Image *image, @@ -418,7 +418,7 @@ } if (Header.Komprese != 0 || (Header.Version >= 2 && Header.TileCompression != 0)) ThrowTOPOLReaderException(CorruptImageError, UnrecognizedImageCompression, image); - if (((Header.Rows == 0 || Header.Cols == 0)) || + if(Header.Rows == 0 || Header.Cols == 0 || ((Header.Version >= 2) && (Header.TileWidth == 0 || Header.TileHeight == 0 || @@ -466,7 +466,7 @@ i = GetBlobSize(image); if(i>0) - if(((magick_uint64_t)8*Header.Cols*(magick_uint64_t)Header.Rows) / image->depth > (magick_uint64_t)GetBlobSize(image)) + if(((magick_uint64_t)depth*Header.Cols*(magick_uint64_t)Header.Rows) / 8 > (magick_uint64_t)GetBlobSize(image)) goto TOPOL_KO; /* Check for forged image that overflows file size. */ /* If ping is true, then only set image size and colors without reading any image data. */ @@ -743,6 +743,154 @@ if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),"return"); return (image); } + + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % +% W r i t e T o p o L I m a g e % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Function WriteTopoLImage writes an WPG image to a file. +% +% The format of the WriteTopoLImage method is: +% +% unsigned int WriteTopoLImage(const ImageInfo *image_info,Image *image) +% +% A description of each parameter follows. +% +% o status: Function WriteTopoLImage 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 WriteTopoLImage(const ImageInfo *image_info, Image *image) +{ + long y; + unsigned int status; + int logging; + unsigned char *pixels; + RasHeader Header; + size_t DataSize; + QuantumType qt; + int bpp; + + /* 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 TopoL"); + + DataSize = 0; + memset(&Header,0,sizeof(Header)); + memset(&Header.Name,' ',sizeof(Header.Name)); + //Header.Version = 0; + Header.Cols = image->columns; + Header.Rows = image->rows; + if(image->colors>=1 && image->colors<=255) + { + if(image->colors <= 2) + { + Header.FileType = 0; + DataSize = (Header.Cols+7) / 8; + qt = GrayQuantum; + bpp =1; + } else if(image->colors <= 16) + { + Header.FileType = 4; + DataSize = (Header.Cols+1) / 2; + qt = IndexQuantum; + bpp = 4; + } + else + { + Header.FileType = 2; + DataSize = Header.Cols; + qt = IndexQuantum; + bpp = 8; + } + } + else // RGB + { + Header.FileType = 5; + DataSize = 3*Header.Cols; + qt = RGBQuantum; + bpp = 8; + } + + if(DataSize==0) + ThrowWriterException(FileOpenError,UnableToOpenFile,image); + pixels = MagickAllocateResourceLimitedMemory(unsigned char *,(size_t) (DataSize)); + + status = OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); + if(status == MagickFail) + ThrowWriterException(FileOpenError,UnableToOpenFile,image); + + /* Write TopoL hader. */ + WriteBlob(image, 20, Header.Name); + WriteBlobLSBShort(image, Header.Rows); + WriteBlobLSBShort(image, Header.Cols); + WriteBlobLSBShort(image, Header.FileType); + WriteBlobLSBLong(image, Header.Zoom); + WriteBlobLSBShort(image, Header.Version); + WriteBlobLSBShort(image, Header.Komprese); + WriteBlobLSBShort(image, Header.Stav); + + WriteBlobLSBDouble(image, Header.xRasMin); + WriteBlobLSBDouble(image, Header.yRasMin); + WriteBlobLSBDouble(image, Header.xRasMax); + WriteBlobLSBDouble(image, Header.yRasMax); + WriteBlobLSBDouble(image, Header.Scale); + //from release 2 + WriteBlobLSBShort(image, Header.TileWidth); + WriteBlobLSBShort(image, Header.TileHeight); + WriteBlobLSBLong(image, Header.TileOffsets); + WriteBlobLSBLong(image, Header.TileByteCounts); + WriteBlobByte(image, Header.TileCompression); + + WriteBlob(image, 423, Header.Dummy); + + /* Palette */ + + + /* Store image data. */ + for(y=0; y<(long)image->rows; y++) + { + if(AcquireImagePixels(image,0,y,image->columns,1,&image->exception) == (const PixelPacket *)NULL) + { + status=MagickFail; + break; + } + if(ExportImagePixelArea(image,qt,bpp,pixels,0,0) != MagickPass) + { + status = MagickFail; + break; + } + if(WriteBlob(image,DataSize,pixels) != DataSize) + { + status = MagickFail; + break; + } + } + + CloseBlob(image); + + if(logging) + (void)LogMagickEvent(CoderEvent,GetMagickModule(),"return TopoL"); + + return(status); +} + + /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -772,9 +920,10 @@ MagickInfo * entry; entry = SetMagickInfo("TOPOL"); - entry->decoder = (DecoderHandler) ReadTOPOLImage; + entry->decoder = (DecoderHandler) ReadTopoLImage; + entry->encoder = (EncoderHandler) WriteTopoLImage; entry->seekable_stream = True; - entry->description = "TOPOL X Image"; + entry->description = "TopoL X Image"; entry->module = "TOPOL"; (void) RegisterMagickInfo(entry); } diff -r c2a4d0286bcb -r 646dd7d9dda2 coders/viff.c --- a/coders/viff.c Sat Apr 29 10:51:20 2023 -0500 +++ b/coders/viff.c Sat Apr 29 11:43:45 2023 -0500 @@ -1,5 +1,5 @@ /* -% Copyright (C) 2003-2020 GraphicsMagick Group +% Copyright (C) 2003-2023 GraphicsMagick Group % Copyright (C) 2002 ImageMagick Studio % Copyright 1991-1999 E. I. du Pont de Nemours and Company % @@ -78,7 +78,7 @@ typedef struct _ViffInfo { unsigned char - identifier, + identifier, file_type, release, version, @@ -735,13 +735,8 @@ if (viff_info.map_scheme == VFF_MS_NONE) { value=(value-min_value)*scale_factor; - if (value > MaxRGB) - value=MaxRGB; - else - if (value < 0) - value=0; } - *p=(Quantum) value; + *p=RoundDoubleToQuantumN(value); p++; } /* diff -r c2a4d0286bcb -r 646dd7d9dda2 magick/blob.c --- a/magick/blob.c Sat Apr 29 10:51:20 2023 -0500 +++ b/magick/blob.c Sat Apr 29 11:43:45 2023 -0500 @@ -5458,6 +5458,7 @@ */ MagickExport size_t WriteBlobLSBLong(Image *image,const magick_uint32_t value) { +#if defined(WORDS_BIGENDIAN) unsigned char buffer[4]; @@ -5468,6 +5469,12 @@ buffer[2]=(unsigned char) (value >> 16); buffer[3]=(unsigned char) (value >> 24); return(WriteBlob(image,4,buffer)); +#else + assert(image != (Image *) NULL); + assert(image->signature == MagickSignature); + assert(sizeof(value) == 4); + return(WriteBlob(image,4,&value)); +#endif } /* @@ -5602,6 +5609,21 @@ buffer[1]=(unsigned char) (uvalue.uint16 >> 8); return(WriteBlob(image,2,buffer)); } + + +MagickExport size_t WriteBlobLSBDouble(Image *image, double d) +{ + assert(image != (Image *) NULL); + assert(image->signature == MagickSignature); + assert(sizeof(d) == 8); + +#if defined(WORDS_BIGENDIAN) + MagickSwabDouble(&d); +#endif + return(WriteBlob(image,8,&d)); +} + + /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -5654,6 +5676,7 @@ return octets_read; } + /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff -r c2a4d0286bcb -r 646dd7d9dda2 magick/blob.h --- a/magick/blob.h Sat Apr 29 10:51:20 2023 -0500 +++ b/magick/blob.h Sat Apr 29 11:43:45 2023 -0500 @@ -398,6 +398,7 @@ const magick_int32_t value); + extern MagickExport size_t WriteBlobLSBDouble(Image *image, double d); /* Write a 32-bit unsigned "long" value to the file or BLOB in big-endian diff -r c2a4d0286bcb -r 646dd7d9dda2 magick/image.h --- a/magick/image.h Sat Apr 29 10:51:20 2023 -0500 +++ b/magick/image.h Sat Apr 29 11:43:45 2023 -0500 @@ -1,5 +1,5 @@ /* - Copyright (C) 2003 - 2019 GraphicsMagick Group + Copyright (C) 2003 - 2023 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio Copyright 1991-1999 E. I. du Pont de Nemours and Company @@ -126,6 +126,8 @@ #define TransparentOpacity MaxRGB #define RoundDoubleToQuantum(value) ((Quantum) (value < 0.0 ? 0U : \ (value > MaxRGBDouble) ? MaxRGB : value + 0.5)) +#define RoundDoubleToQuantumN(value) ((Quantum) (MAGICK_ISNAN(value) ? 0U : \ + (value < 0.0 ? 0U : (value > MaxRGBDouble) ? MaxRGB : value + 0.5))) #define RoundFloatToQuantum(value) ((Quantum) (value < 0.0f ? 0U : \ (value > MaxRGBFloat) ? MaxRGB : value + 0.5f)) #define ConstrainToRange(min,max,value) (value < min ? min : \ diff -r c2a4d0286bcb -r 646dd7d9dda2 magick/import.c --- a/magick/import.c Sat Apr 29 10:51:20 2023 -0500 +++ b/magick/import.c Sat Apr 29 11:43:45 2023 -0500 @@ -1,5 +1,5 @@ /* - Copyright (C) 2003 - 2022 GraphicsMagick Group + Copyright (C) 2003 - 2023 GraphicsMagick Group Copyright (C) 2002 ImageMagick Studio This program is covered by multiple licenses, which are described in @@ -187,8 +187,6 @@ fu_.c[0]=*p++; \ value=fu_.f; \ } \ - if (MAGICK_ISNAN(value)) \ - value = 0.0; \ } #define ImportFloat64Quantum(endian,value,p) \ { \ @@ -215,8 +213,6 @@ du_.c[0]=*p++; \ value=du_.d; \ } \ - if (MAGICK_ISNAN(value)) \ - value = 0.0; \ } /* @@ -978,7 +974,7 @@ ImportFloat16Quantum(endian,double_value,p); double_value -= double_minvalue; double_value *= double_scale; - SetGraySample(q,RoundDoubleToQuantum(double_value)); + SetGraySample(q,RoundDoubleToQuantumN(double_value)); q++; } break; @@ -990,7 +986,7 @@ ImportFloat24Quantum(endian,double_value,p); double_value -= double_minvalue; double_value *= double_scale; - SetGraySample(q,RoundDoubleToQuantum(double_value)); + SetGraySample(q,RoundDoubleToQuantumN(double_value)); q++; } break; @@ -1002,7 +998,7 @@ ImportFloat32Quantum(endian,double_value,p); double_value -= double_minvalue; double_value *= double_scale; - SetGraySample(q,RoundDoubleToQuantum(double_value)); + SetGraySample(q,RoundDoubleToQuantumN(double_value)); q++; } break; @@ -1014,7 +1010,7 @@ ImportFloat64Quantum(endian,double_value,p); double_value -= double_minvalue; double_value *= double_scale; - SetGraySample(q,RoundDoubleToQuantum(double_value)); + SetGraySample(q,RoundDoubleToQuantumN(double_value)); q++; } break; @@ -1324,11 +1320,11 @@ ImportFloat16Quantum(endian,double_value,p); double_value -= double_minvalue; double_value *= double_scale; - SetGraySample(q,RoundDoubleToQuantum(double_value)); + SetGraySample(q,RoundDoubleToQuantumN(double_value)); ImportFloat16Quantum(endian,double_value,p); double_value -= double_minvalue; double_value *= double_scale; - SetOpacitySample(q,MaxRGB-RoundDoubleToQuantum(double_value)); + SetOpacitySample(q,MaxRGB-RoundDoubleToQuantumN(double_value)); q++; } break; @@ -1340,11 +1336,11 @@ ImportFloat24Quantum(endian,double_value,p); double_value -= double_minvalue; double_value *= double_scale; - SetGraySample(q,RoundDoubleToQuantum(double_value)); + SetGraySample(q,RoundDoubleToQuantumN(double_value)); ImportFloat24Quantum(endian,double_value,p); double_value -= double_minvalue; double_value *= double_scale; - SetOpacitySample(q,MaxRGB-RoundDoubleToQuantum(double_value)); + SetOpacitySample(q,MaxRGB-RoundDoubleToQuantumN(double_value)); q++; } break; @@ -1356,11 +1352,11 @@ ImportFloat32Quantum(endian,double_value,p); double_value -= double_minvalue; double_value *= double_scale; - SetGraySample(q,RoundDoubleToQuantum(double_value)); + SetGraySample(q,RoundDoubleToQuantumN(double_value)); ImportFloat32Quantum(endian,double_value,p); double_value -= double_minvalue; double_value *= double_scale; - SetOpacitySample(q,MaxRGB-RoundDoubleToQuantum(double_value)); + SetOpacitySample(q,MaxRGB-RoundDoubleToQuantumN(double_value)); q++; } break; @@ -1372,11 +1368,11 @@ ImportFloat64Quantum(endian,double_value,p); double_value -= double_minvalue; double_value *= double_scale; - SetGraySample(q,RoundDoubleToQuantum(double_value)); + SetGraySample(q,RoundDoubleToQuantumN(double_value)); ImportFloat64Quantum(endian,double_value,p); double_value -= double_minvalue; double_value *= double_scale; - SetOpacitySample(q,MaxRGB-RoundDoubleToQuantum(double_value)); + SetOpacitySample(q,MaxRGB-RoundDoubleToQuantumN(double_value)); q++; } break;