% July 1992 %
% %
% %
-% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2012 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/cache.h"
-#include "magick/colorspace.h"
-#include "magick/exception.h"
-#include "magick/exception-private.h"
-#include "magick/image.h"
-#include "magick/image-private.h"
-#include "magick/list.h"
-#include "magick/magick.h"
-#include "magick/memory_.h"
-#include "magick/monitor.h"
-#include "magick/monitor-private.h"
-#include "magick/property.h"
-#include "magick/quantum-private.h"
-#include "magick/static.h"
-#include "magick/string_.h"
-#include "magick/string-private.h"
-#include "magick/module.h"
+#include "MagickCore/studio.h"
+#include "MagickCore/blob.h"
+#include "MagickCore/blob-private.h"
+#include "MagickCore/cache.h"
+#include "MagickCore/colorspace.h"
+#include "MagickCore/colorspace-private.h"
+#include "MagickCore/exception.h"
+#include "MagickCore/exception-private.h"
+#include "MagickCore/image.h"
+#include "MagickCore/image-private.h"
+#include "MagickCore/list.h"
+#include "MagickCore/magick.h"
+#include "MagickCore/memory_.h"
+#include "MagickCore/monitor.h"
+#include "MagickCore/monitor-private.h"
+#include "MagickCore/pixel-accessor.h"
+#include "MagickCore/property.h"
+#include "MagickCore/quantum-private.h"
+#include "MagickCore/static.h"
+#include "MagickCore/string_.h"
+#include "MagickCore/string-private.h"
+#include "MagickCore/module.h"
+\f
+/*
+ Forward declarations.
+*/
+static MagickBooleanType
+ WriteHDRImage(const ImageInfo *,Image *,ExceptionInfo *);
\f
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
return(MagickFalse);
if (LocaleNCompare((const char *) magick,"#?RADIANCE",10) == 0)
return(MagickTrue);
+ if (LocaleNCompare((const char *) magick,"#?RGBE",6) == 0)
+ return(MagickTrue);
return(MagickFalse);
}
\f
status,
value_expected;
- register PixelPacket
+ register Quantum
*q;
- register unsigned char
- *p;
-
register ssize_t
i,
x;
+ register unsigned char
+ *p;
+
ssize_t
count,
y;
image_info->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
- image=AcquireImage(image_info);
+ image=AcquireImage(image_info,exception);
status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
if (status == MagickFalse)
{
}
while (isgraph(c) && (image->columns == 0) && (image->rows == 0))
{
- if (isalnum(c) == MagickFalse)
- c=ReadBlobByte(image);
- else
+ if (c == (int) '#')
{
+ char
+ *comment;
+
register char
*p;
+ size_t
+ length;
+
/*
- Determine a keyword and its value.
+ Read comment-- any text between # and end-of-line.
*/
- p=keyword;
- do
- {
- if ((size_t) (p-keyword) < (MaxTextExtent-1))
- *p++=c;
- c=ReadBlobByte(image);
- } while (isalnum(c) || (c == '_'));
- *p='\0';
- value_expected=MagickFalse;
- while ((isspace((int) ((unsigned char) c)) != 0) || (c == '='))
- {
- if (c == '=')
- value_expected=MagickTrue;
- c=ReadBlobByte(image);
- }
- if (LocaleCompare(keyword,"Y") == 0)
- value_expected=MagickTrue;
- if (value_expected == MagickFalse)
- continue;
- p=value;
- while ((c != '\n') && (c != '\0'))
+ length=MaxTextExtent;
+ comment=AcquireString((char *) NULL);
+ for (p=comment; comment != (char *) NULL; p++)
{
- if ((size_t) (p-value) < (MaxTextExtent-1))
- *p++=c;
c=ReadBlobByte(image);
+ if ((c == EOF) || (c == (int) '\n'))
+ break;
+ if ((size_t) (p-comment+1) >= length)
+ {
+ *p='\0';
+ length<<=1;
+ comment=(char *) ResizeQuantumMemory(comment,length+
+ MaxTextExtent,sizeof(*comment));
+ if (comment == (char *) NULL)
+ break;
+ p=comment+strlen(comment);
+ }
+ *p=(char) c;
}
+ if (comment == (char *) NULL)
+ ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
*p='\0';
- /*
- Assign a value to the specified keyword.
- */
- switch (*keyword)
+ (void) SetImageProperty(image,"comment",comment,exception);
+ comment=DestroyString(comment);
+ c=ReadBlobByte(image);
+ }
+ else
+ if (isalnum(c) == MagickFalse)
+ c=ReadBlobByte(image);
+ else
{
- case 'F':
- case 'f':
+ register char
+ *p;
+
+ /*
+ Determine a keyword and its value.
+ */
+ p=keyword;
+ do
{
- if (LocaleCompare(keyword,"format") == 0)
- {
- (void) CopyMagickString(format,value,MaxTextExtent);
- break;
- }
- (void) FormatMagickString(tag,MaxTextExtent,"hdr:%s",keyword);
- (void) SetImageProperty(image,tag,value);
- break;
- }
- case 'G':
- case 'g':
+ if ((size_t) (p-keyword) < (MaxTextExtent-1))
+ *p++=c;
+ c=ReadBlobByte(image);
+ } while (isalnum(c) || (c == '_'));
+ *p='\0';
+ value_expected=MagickFalse;
+ while ((isspace((int) ((unsigned char) c)) != 0) || (c == '='))
{
- if (LocaleCompare(keyword,"gamma") == 0)
- {
- image->gamma=StringToDouble(value);
- break;
- }
- (void) FormatMagickString(tag,MaxTextExtent,"hdr:%s",keyword);
- (void) SetImageProperty(image,tag,value);
- break;
+ if (c == '=')
+ value_expected=MagickTrue;
+ c=ReadBlobByte(image);
}
- case 'P':
- case 'p':
+ if (LocaleCompare(keyword,"Y") == 0)
+ value_expected=MagickTrue;
+ if (value_expected == MagickFalse)
+ continue;
+ p=value;
+ while ((c != '\n') && (c != '\0'))
{
- if (LocaleCompare(keyword,"primaries") == 0)
- {
- float
- chromaticity[6],
- white_point[2];
-
- (void) sscanf(value,"%g %g %g %g %g %g %g %g",&chromaticity[0],
- &chromaticity[1],&chromaticity[2],&chromaticity[3],
- &chromaticity[4],&chromaticity[5],&white_point[0],
- &white_point[1]);
- image->chromaticity.red_primary.x=chromaticity[0];
- image->chromaticity.red_primary.y=chromaticity[1];
- image->chromaticity.green_primary.x=chromaticity[2];
- image->chromaticity.green_primary.y=chromaticity[3];
- image->chromaticity.blue_primary.x=chromaticity[4];
- image->chromaticity.blue_primary.y=chromaticity[5];
- image->chromaticity.white_point.x=white_point[0],
- image->chromaticity.white_point.y=white_point[1];
- break;
- }
- (void) FormatMagickString(tag,MaxTextExtent,"hdr:%s",keyword);
- (void) SetImageProperty(image,tag,value);
- break;
+ if ((size_t) (p-value) < (MaxTextExtent-1))
+ *p++=c;
+ c=ReadBlobByte(image);
}
- case 'Y':
- case 'y':
+ *p='\0';
+ /*
+ Assign a value to the specified keyword.
+ */
+ switch (*keyword)
{
- if (strcmp(keyword,"Y") == 0)
- {
- int
- height,
- width;
+ case 'F':
+ case 'f':
+ {
+ if (LocaleCompare(keyword,"format") == 0)
+ {
+ (void) CopyMagickString(format,value,MaxTextExtent);
+ break;
+ }
+ (void) FormatLocaleString(tag,MaxTextExtent,"hdr:%s",keyword);
+ (void) SetImageProperty(image,tag,value,exception);
+ break;
+ }
+ case 'G':
+ case 'g':
+ {
+ if (LocaleCompare(keyword,"gamma") == 0)
+ {
+ image->gamma=StringToDouble(value,(char **) NULL);
+ break;
+ }
+ (void) FormatLocaleString(tag,MaxTextExtent,"hdr:%s",keyword);
+ (void) SetImageProperty(image,tag,value,exception);
+ break;
+ }
+ case 'P':
+ case 'p':
+ {
+ if (LocaleCompare(keyword,"primaries") == 0)
+ {
+ float
+ chromaticity[6],
+ white_point[2];
- (void) sscanf(value,"%d +X %d",&height,&width);
- image->columns=(size_t) width;
- image->rows=(size_t) height;
- break;
- }
- (void) FormatMagickString(tag,MaxTextExtent,"hdr:%s",keyword);
- (void) SetImageProperty(image,tag,value);
- break;
- }
- default:
- {
- (void) FormatMagickString(tag,MaxTextExtent,"hdr:%s",keyword);
- (void) SetImageProperty(image,tag,value);
- break;
+ (void) sscanf(value,"%g %g %g %g %g %g %g %g",
+ &chromaticity[0],&chromaticity[1],&chromaticity[2],
+ &chromaticity[3],&chromaticity[4],&chromaticity[5],
+ &white_point[0],&white_point[1]);
+ image->chromaticity.red_primary.x=chromaticity[0];
+ image->chromaticity.red_primary.y=chromaticity[1];
+ image->chromaticity.green_primary.x=chromaticity[2];
+ image->chromaticity.green_primary.y=chromaticity[3];
+ image->chromaticity.blue_primary.x=chromaticity[4];
+ image->chromaticity.blue_primary.y=chromaticity[5];
+ image->chromaticity.white_point.x=white_point[0],
+ image->chromaticity.white_point.y=white_point[1];
+ break;
+ }
+ (void) FormatLocaleString(tag,MaxTextExtent,"hdr:%s",keyword);
+ (void) SetImageProperty(image,tag,value,exception);
+ break;
+ }
+ case 'Y':
+ case 'y':
+ {
+ if (strcmp(keyword,"Y") == 0)
+ {
+ int
+ height,
+ width;
+
+ (void) sscanf(value,"%d +X %d",&height,&width);
+ image->columns=(size_t) width;
+ image->rows=(size_t) height;
+ break;
+ }
+ (void) FormatLocaleString(tag,MaxTextExtent,"hdr:%s",keyword);
+ (void) SetImageProperty(image,tag,value,exception);
+ break;
+ }
+ default:
+ {
+ (void) FormatLocaleString(tag,MaxTextExtent,"hdr:%s",keyword);
+ (void) SetImageProperty(image,tag,value,exception);
+ break;
+ }
}
}
- }
if ((image->columns == 0) && (image->rows == 0))
while (isspace((int) ((unsigned char) c)) != 0)
c=ReadBlobByte(image);
}
- if (LocaleCompare(format,"32-bit_rle_rgbe") != 0)
+ if ((LocaleCompare(format,"32-bit_rle_rgbe") != 0) &&
+ (LocaleCompare(format,"32-bit_rle_xyze") != 0))
ThrowReaderException(CorruptImageError,"ImproperImageHeader");
if ((image->columns == 0) || (image->rows == 0))
ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
+ if (LocaleCompare(format,"32-bit_rle_xyze") == 0)
+ SetImageColorspace(image,XYZColorspace,exception);
+ image->compression=(image->columns < 8) || (image->columns > 0x7ffff) ?
+ NoCompression : RLECompression;
if (image_info->ping != MagickFalse)
{
(void) CloseBlob(image);
/*
Read RGBE (red+green+blue+exponent) pixels.
*/
- pixels=(unsigned char *) AcquireQuantumMemory(image->columns,
- 4*sizeof(*pixels));
+ pixels=(unsigned char *) AcquireQuantumMemory(image->columns,4*
+ sizeof(*pixels));
if (pixels == (unsigned char *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
for (y=0; y < (ssize_t) image->rows; y++)
{
- count=ReadBlob(image,4*sizeof(*pixel),pixel);
- if (count != 4)
- break;
- if ((size_t) ((((size_t) pixel[2]) << 8) | pixel[3]) != image->columns)
- break;
- p=pixels;
- for (i=0; i < 4; i++)
- {
- end=&pixels[(i+1)*image->columns];
- while (p < end)
+ if (image->compression != RLECompression)
+ {
+ count=ReadBlob(image,4*image->columns*sizeof(*pixels),pixels);
+ if (count != (ssize_t) (4*image->columns*sizeof(*pixels)))
+ break;
+ }
+ else
{
- count=ReadBlob(image,2*sizeof(*pixel),pixel);
- if (count < 1)
+ count=ReadBlob(image,4*sizeof(*pixel),pixel);
+ if (count != 4)
break;
- if (pixel[0] > 128)
+ if ((size_t) ((((size_t) pixel[2]) << 8) | pixel[3]) != image->columns)
{
- count=(ssize_t) pixel[0]-128;
- if ((count == 0) || (count > (ssize_t) (end-p)))
- break;
- while (count-- > 0)
- *p++=pixel[1];
+ (void) memcpy(pixels,pixel,4*sizeof(*pixel));
+ count=ReadBlob(image,4*(image->columns-1)*sizeof(*pixels),pixels+4);
+ image->compression=NoCompression;
}
else
{
- count=(ssize_t) pixel[0];
- if ((count == 0) || (count > (ssize_t) (end-p)))
- break;
- *p++=pixel[1];
- if (--count > 0)
+ p=pixels;
+ for (i=0; i < 4; i++)
+ {
+ end=&pixels[(i+1)*image->columns];
+ while (p < end)
{
- count=ReadBlob(image,(size_t) count*sizeof(*p),p);
+ count=ReadBlob(image,2*sizeof(*pixel),pixel);
if (count < 1)
break;
- p+=count;
+ if (pixel[0] > 128)
+ {
+ count=(ssize_t) pixel[0]-128;
+ if ((count == 0) || (count > (ssize_t) (end-p)))
+ break;
+ while (count-- > 0)
+ *p++=pixel[1];
+ }
+ else
+ {
+ count=(ssize_t) pixel[0];
+ if ((count == 0) || (count > (ssize_t) (end-p)))
+ break;
+ *p++=pixel[1];
+ if (--count > 0)
+ {
+ count=ReadBlob(image,(size_t) count*sizeof(*p),p);
+ if (count < 1)
+ break;
+ p+=count;
+ }
+ }
}
+ }
}
}
- }
q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
- if (q == (PixelPacket *) NULL)
+ if (q == (Quantum *) NULL)
break;
+ i=0;
for (x=0; x < (ssize_t) image->columns; x++)
{
- pixel[0]=pixels[x];
- pixel[1]=pixels[x+image->columns];
- pixel[2]=pixels[x+2*image->columns];
- pixel[3]=pixels[x+3*image->columns];
- q->red=0;
- q->green=0;
- q->blue=0;
+ if (image->compression == RLECompression)
+ {
+ pixel[0]=pixels[x];
+ pixel[1]=pixels[x+image->columns];
+ pixel[2]=pixels[x+2*image->columns];
+ pixel[3]=pixels[x+3*image->columns];
+ }
+ else
+ {
+ pixel[0]=pixels[i++];
+ pixel[1]=pixels[i++];
+ pixel[2]=pixels[i++];
+ pixel[3]=pixels[i++];
+ }
+ SetPixelRed(image,0,q);
+ SetPixelGreen(image,0,q);
+ SetPixelBlue(image,0,q);
if (pixel[3] != 0)
{
gamma=pow(2.0,pixel[3]-(128.0+8.0));
- q->red=ClampToQuantum(QuantumRange*gamma*pixel[0]);
- q->green=ClampToQuantum(QuantumRange*gamma*pixel[1]);
- q->blue=ClampToQuantum(QuantumRange*gamma*pixel[2]);
+ SetPixelRed(image,ClampToQuantum(QuantumRange*gamma*pixel[0]),q);
+ SetPixelGreen(image,ClampToQuantum(QuantumRange*gamma*pixel[1]),q);
+ SetPixelBlue(image,ClampToQuantum(QuantumRange*gamma*pixel[2]),q);
}
- q++;
+ q+=GetPixelChannels(image);
}
if (SyncAuthenticPixels(image,exception) == MagickFalse)
break;
entry=SetMagickInfo("HDR");
entry->decoder=(DecodeImageHandler *) ReadHDRImage;
+ entry->encoder=(EncodeImageHandler *) WriteHDRImage;
entry->description=ConstantString("Radiance RGBE image format");
entry->module=ConstantString("HDR");
entry->magick=(IsImageFormatHandler *) IsHDR;
{
(void) UnregisterMagickInfo("HDR");
}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% W r i t e H D R I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% WriteHDRImage() writes an image in the Radience RGBE image format.
+%
+% The format of the WriteHDRImage method is:
+%
+% MagickBooleanType WriteHDRImage(const ImageInfo *image_info,
+% Image *image,ExceptionInfo *exception)
+%
+% A description of each parameter follows.
+%
+% o image_info: the image info.
+%
+% o image: The image.
+%
+*/
+
+static size_t HDRWriteRunlengthPixels(Image *image,unsigned char *pixels)
+{
+#define MinimumRunlength 4
+
+ register size_t
+ p,
+ q;
+
+ size_t
+ runlength;
+
+ ssize_t
+ count,
+ previous_count;
+
+ unsigned char
+ pixel[2];
+
+ for (p=0; p < image->columns; )
+ {
+ q=p;
+ runlength=0;
+ previous_count=0;
+ while ((runlength < MinimumRunlength) && (q < image->columns))
+ {
+ q+=runlength;
+ previous_count=(ssize_t) runlength;
+ runlength=1;
+ while ((pixels[q] == pixels[q+runlength]) &&
+ ((q+runlength) < image->columns) && (runlength < 127))
+ runlength++;
+ }
+ if ((previous_count > 1) && (previous_count == (ssize_t) (q-p)))
+ {
+ pixel[0]=(unsigned char) (128+previous_count);
+ pixel[1]=pixels[p];
+ if (WriteBlob(image,2*sizeof(*pixel),pixel) < 1)
+ break;
+ p=q;
+ }
+ while (p < q)
+ {
+ count=(ssize_t) (q-p);
+ if (count > 128)
+ count=128;
+ pixel[0]=(unsigned char) count;
+ if (WriteBlob(image,sizeof(*pixel),pixel) < 1)
+ break;
+ if (WriteBlob(image,(size_t) count*sizeof(*pixel),&pixels[p]) < 1)
+ break;
+ p+=count;
+ }
+ if (runlength >= MinimumRunlength)
+ {
+ pixel[0]=(unsigned char) (128+runlength);
+ pixel[1]=pixels[q];
+ if (WriteBlob(image,2*sizeof(*pixel),pixel) < 1)
+ break;
+ p+=runlength;
+ }
+ }
+ return(p);
+}
+
+static MagickBooleanType WriteHDRImage(const ImageInfo *image_info,Image *image,
+ ExceptionInfo *exception)
+{
+ char
+ header[MaxTextExtent];
+
+ const char
+ *property;
+
+ MagickBooleanType
+ status;
+
+ register const Quantum
+ *p;
+
+ register ssize_t
+ i,
+ x;
+
+ size_t
+ length;
+
+ ssize_t
+ count,
+ y;
+
+ unsigned char
+ pixel[4],
+ *pixels;
+
+ /*
+ Open output image file.
+ */
+ assert(image_info != (const ImageInfo *) NULL);
+ assert(image_info->signature == MagickSignature);
+ assert(image != (Image *) NULL);
+ assert(image->signature == MagickSignature);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ assert(exception != (ExceptionInfo *) NULL);
+ assert(exception->signature == MagickSignature);
+ status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
+ if (status == MagickFalse)
+ return(status);
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+ (void) TransformImageColorspace(image,sRGBColorspace,exception);
+ /*
+ Write header.
+ */
+ (void) ResetMagickMemory(header,' ',MaxTextExtent);
+ length=CopyMagickString(header,"#?RGBE\n",MaxTextExtent);
+ (void) WriteBlob(image,length,(unsigned char *) header);
+ property=GetImageProperty(image,"comment",exception);
+ if ((property != (const char *) NULL) &&
+ (strchr(property,'\n') == (char *) NULL))
+ {
+ count=FormatLocaleString(header,MaxTextExtent,"#%s\n",property);
+ (void) WriteBlob(image,(size_t) count,(unsigned char *) header);
+ }
+ property=GetImageProperty(image,"hdr:exposure",exception);
+ if (property != (const char *) NULL)
+ {
+ count=FormatLocaleString(header,MaxTextExtent,"EXPOSURE=%g\n",
+ atof(property));
+ (void) WriteBlob(image,(size_t) count,(unsigned char *) header);
+ }
+ if (image->gamma != 0.0)
+ {
+ count=FormatLocaleString(header,MaxTextExtent,"GAMMA=%g\n",image->gamma);
+ (void) WriteBlob(image,(size_t) count,(unsigned char *) header);
+ }
+ count=FormatLocaleString(header,MaxTextExtent,
+ "PRIMARIES=%g %g %g %g %g %g %g %g\n",
+ image->chromaticity.red_primary.x,image->chromaticity.red_primary.y,
+ image->chromaticity.green_primary.x,image->chromaticity.green_primary.y,
+ image->chromaticity.blue_primary.x,image->chromaticity.blue_primary.y,
+ image->chromaticity.white_point.x,image->chromaticity.white_point.y);
+ (void) WriteBlob(image,(size_t) count,(unsigned char *) header);
+ length=CopyMagickString(header,"FORMAT=32-bit_rle_rgbe\n\n",MaxTextExtent);
+ (void) WriteBlob(image,length,(unsigned char *) header);
+ count=FormatLocaleString(header,MaxTextExtent,"-Y %.20g +X %.20g\n",
+ (double) image->rows,(double) image->columns);
+ (void) WriteBlob(image,(size_t) count,(unsigned char *) header);
+ /*
+ Write HDR pixels.
+ */
+ pixels=(unsigned char *) AcquireQuantumMemory(image->columns,4*
+ sizeof(*pixels));
+ if (pixels == (unsigned char *) NULL)
+ ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+ for (y=0; y < (ssize_t) image->rows; y++)
+ {
+ p=GetVirtualPixels(image,0,y,image->columns,1,exception);
+ if (p == (const Quantum *) NULL)
+ break;
+ if ((image->columns >= 8) && (image->columns <= 0x7ffff))
+ {
+ pixel[0]=2;
+ pixel[1]=2;
+ pixel[2]=(unsigned char) (image->columns >> 8);
+ pixel[3]=(unsigned char) (image->columns & 0xff);
+ count=WriteBlob(image,4*sizeof(*pixel),pixel);
+ if (count != (ssize_t) (4*sizeof(*pixel)))
+ break;
+ }
+ i=0;
+ for (x=0; x < (ssize_t) image->columns; x++)
+ {
+ double
+ gamma;
+
+ pixel[0]=0;
+ pixel[1]=0;
+ pixel[2]=0;
+ pixel[3]=0;
+ gamma=QuantumScale*GetPixelRed(image,p);
+ if ((QuantumScale*GetPixelGreen(image,p)) > gamma)
+ gamma=QuantumScale*GetPixelGreen(image,p);
+ if ((QuantumScale*GetPixelBlue(image,p)) > gamma)
+ gamma=QuantumScale*GetPixelBlue(image,p);
+ if (gamma > MagickEpsilon)
+ {
+ int
+ exponent;
+
+ gamma=frexp(gamma,&exponent)*256.0/gamma;
+ pixel[0]=(unsigned char) (gamma*QuantumScale*GetPixelRed(image,p));
+ pixel[1]=(unsigned char) (gamma*QuantumScale*GetPixelGreen(image,p));
+ pixel[2]=(unsigned char) (gamma*QuantumScale*GetPixelBlue(image,p));
+ pixel[3]=(unsigned char) (exponent+128);
+ }
+ if ((image->columns >= 8) && (image->columns <= 0x7ffff))
+ {
+ pixels[x]=pixel[0];
+ pixels[x+image->columns]=pixel[1];
+ pixels[x+2*image->columns]=pixel[2];
+ pixels[x+3*image->columns]=pixel[3];
+ }
+ else
+ {
+ pixels[i++]=pixel[0];
+ pixels[i++]=pixel[1];
+ pixels[i++]=pixel[2];
+ pixels[i++]=pixel[3];
+ }
+ p+=GetPixelChannels(image);
+ }
+ if ((image->columns >= 8) && (image->columns <= 0x7ffff))
+ {
+ for (i=0; i < 4; i++)
+ length=HDRWriteRunlengthPixels(image,&pixels[i*image->columns]);
+ }
+ else
+ {
+ count=WriteBlob(image,4*image->columns*sizeof(*pixel),pixel);
+ if (count != (ssize_t) (4*image->columns*sizeof(*pixel)))
+ break;
+ }
+ status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
+ image->rows);
+ if (status == MagickFalse)
+ break;
+ }
+ pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+ (void) CloseBlob(image);
+ return(MagickTrue);
+}