I needed a few EXR files with different color types for testing, so I added an option to specify a color type to the exr coder. It adds an exr:color-type define, which can be set to the various EXR color output types, and the -sampling-rate option can be used (set to 2x2 or 4:2:0) to create a YC(A) file.OpenEXR now supports high dynamic-range YCA (luminance/chroma/alpha) images with subsampled chroma channels. These files are supported via the RGBA convenience interface, so that data is presented to the application as RGB(A) but stored in the file as YC(A). OpenEXR also supports Y and YA (black-and-white/black-and-white with alpha) images.
I added my patch below (but probably still requires some work before integration). However I'm working on Windows so I'm not able to use an SVN checkout. I'm using the source archive here instead: http://www.imagemagick.org/download/win ... indows.zip (version 6.9.1-4).
For reading these files no change is required, since ImageMagick uses the RGBA convenience interface.
--
Roeland
Patch:
Code: Select all
--- coders\exr.c.original 2014-12-15 11:36:27.000000000 +1200
+++ coders\exr.c 2015-06-04 16:05:22.000000000 +1200
@@ -350,33 +350,39 @@
%
% o image_info: the image info.
%
% o image: The image.
%
*/
static MagickBooleanType WriteEXRImage(const ImageInfo *image_info,Image *image)
{
+ const char
+ *sampling_factor,
+ *value;
+
ImageInfo
*write_info;
ImfHalf
half_quantum;
ImfHeader
*hdr_info;
ImfOutputFile
*file;
ImfRgba
*scanline;
int
- compression;
+ compression,
+ channels,
+ factors[3];
MagickBooleanType
status;
register const PixelPacket
*p;
register ssize_t
@@ -417,19 +423,105 @@
#if defined(B44Compression)
if (write_info->compression == B44Compression)
compression=IMF_B44_COMPRESSION;
#endif
#if defined(B44ACompression)
if (write_info->compression == B44ACompression)
compression=IMF_B44A_COMPRESSION;
#endif
+
+ channels = 0;
+ value=GetImageOption(image_info,"exr:color-type");
+ if (value!=NULL)
+ {
+ if (LocaleCompare(value, "RGB") == 0)
+ channels = IMF_WRITE_RGB;
+
+ else if (LocaleCompare(value, "RGBA") == 0)
+ channels = IMF_WRITE_RGBA;
+
+ else if (LocaleCompare(value, "YC") == 0)
+ channels = IMF_WRITE_YC;
+
+ else if (LocaleCompare(value, "YCA") == 0)
+ channels = IMF_WRITE_YCA;
+
+ else if (LocaleCompare(value, "Y") == 0)
+ channels = IMF_WRITE_Y;
+
+ else if (LocaleCompare(value, "YA") == 0)
+ channels = IMF_WRITE_YA;
+
+ else if (LocaleCompare(value, "R") == 0)
+ channels = IMF_WRITE_R;
+
+ else if (LocaleCompare(value, "G") == 0)
+ channels = IMF_WRITE_G;
+
+ else if (LocaleCompare(value, "B") == 0)
+ channels = IMF_WRITE_B;
+
+ else if (LocaleCompare(value, "A") == 0)
+ channels = IMF_WRITE_A;
+
+ else
+ (void) ThrowMagickException(&image->exception,GetMagickModule(),CoderWarning,
+ "ignoring invalid defined exr:color-type",
+ "=%s",value);
+ }
+
+ sampling_factor=(const char *) NULL;
+ factors[0] = 0;
+ if (image_info->sampling_factor != (char *) NULL)
+ sampling_factor=image_info->sampling_factor;
+ /* parse sampling factors, valid values are 1x1 or 2x2 */
+ if (sampling_factor != NULL)
+ {
+ if (sscanf(sampling_factor, "%d:%d:%d",
+ factors, factors+1, factors+2) == 3)
+ {
+ if (factors[0] == factors[1] && factors[1] == factors[2])
+ factors[0] = 1;
+ else if (factors[0] == factors[1] * 2 && factors[2] == 0)
+ factors[0] = 2;
+ }
+ else if (sscanf(sampling_factor, "%dx%d",
+ factors, factors+1) == 2)
+ {
+ if (factors[0] != factors[1])
+ factors[0] = 0;
+ }
+
+ if (factors[0] != 1 && factors[0] != 2)
+ {
+ (void) ThrowMagickException(&image->exception,GetMagickModule(),CoderWarning,
+ "ignoring sampling-factor",
+ "=%s",sampling_factor);
+ }
+ else if (channels != 0)
+ {
+ /* cross check given color type and subsampling */
+ factors[1] = (channels == IMF_WRITE_YCA || channels == IMF_WRITE_YC) ? 2 : 1;
+ if (factors[0] != factors[1])
+ (void) ThrowMagickException(&image->exception,GetMagickModule(),CoderWarning,
+ "sampling-factor and color type mismatch",
+ "=%s",sampling_factor);
+ }
+ }
+ /* if no color type given, select it now */
+ if (channels == 0)
+ if (factors[0] == 2)
+ channels = image->matte ? IMF_WRITE_YCA : IMF_WRITE_YC;
+ else
+ channels = image->matte ? IMF_WRITE_RGBA : IMF_WRITE_RGB;
+
ImfHeaderSetCompression(hdr_info,compression);
ImfHeaderSetLineOrder(hdr_info,IMF_INCREASING_Y);
- file=ImfOpenOutputFile(write_info->filename,hdr_info,IMF_WRITE_RGBA);
+ file=ImfOpenOutputFile(write_info->filename,hdr_info,channels);
ImfDeleteHeader(hdr_info);
if (file == (ImfOutputFile *) NULL)
{
(void) RelinquishUniqueFileResource(write_info->filename);
write_info=DestroyImageInfo(write_info);
ThrowFileException(&image->exception,BlobError,"UnableToOpenBlob",
ImfErrorMessage());
return(MagickFalse);