# HG changeset patch # User Carnë Draug # Date 1438101803 -3600 # Node ID 5b8e4f668c538517a5fa5816a882a07422c87bfc # Parent e3f84a8c6788666d0e2449cd85b340ba34138d92 Add compression option to imwrite and default to "none" (bug #45565) * libinterp/dldfcn/__magick_read__.cc: we did not specify compression type and let it up to GM coder. However, Matlab users seem to be expect it to be uncompressed since Matlab only does that (except for jpeg). So we add the compression method and apply to the images being writen. * scripts/image/imwrite.m: document new option and add tests (bug was about bmp and type compression is defined at offset byte 30) * scripts/image/private/__imwrite__.m: parse new compression option. diff -r e3f84a8c6788 -r 5b8e4f668c53 libinterp/dldfcn/__magick_read__.cc --- a/libinterp/dldfcn/__magick_read__.cc Tue Jul 28 08:52:39 2015 -0700 +++ b/libinterp/dldfcn/__magick_read__.cc Tue Jul 28 17:43:23 2015 +0100 @@ -1551,6 +1551,23 @@ // Note that this only needs to be set on the first frame imvec[0].animationIterations (options.getfield ("loopcount").uint_value ()); + const std::string compression = options.getfield ("compression").string_value (); +#define COMPRESS_MAGICK_IMAGE_VECTOR(COMPRESSION_STRING, GM_TYPE) \ + if (compression == COMPRESSION_STRING) \ + for (std::vector::size_type i = 0; i < imvec.size (); i++) \ + imvec[i].compressType (GM_TYPE); + + COMPRESS_MAGICK_IMAGE_VECTOR("none", Magick::NoCompression) + else COMPRESS_MAGICK_IMAGE_VECTOR("bzip", Magick::BZipCompression) + else COMPRESS_MAGICK_IMAGE_VECTOR("fax3", Magick::FaxCompression) + else COMPRESS_MAGICK_IMAGE_VECTOR("fax4", Magick::Group4Compression) + else COMPRESS_MAGICK_IMAGE_VECTOR("jpeg", Magick::JPEGCompression) + else COMPRESS_MAGICK_IMAGE_VECTOR("lzw", Magick::LZWCompression) + else COMPRESS_MAGICK_IMAGE_VECTOR("rle", Magick::RLECompression) + else COMPRESS_MAGICK_IMAGE_VECTOR("deflate", Magick::ZipCompression) + +#undef COMPRESS_MAGICK_IMAGE_VECTOR + write_file (filename, ext, imvec); if (error_state) return retval; diff -r e3f84a8c6788 -r 5b8e4f668c53 scripts/image/imwrite.m --- a/scripts/image/imwrite.m Tue Jul 28 08:52:39 2015 -0700 +++ b/scripts/image/imwrite.m Tue Jul 28 17:43:23 2015 +0100 @@ -46,6 +46,12 @@ ## multipage image, the size of the 4th dimension must also match and the third ## dimension must be a singleton. By default, image will be completely opaque. ## +## @item Compression +## Compression to use one the image. Can be one of the following: "none" +## (default), "bzip", "fax3", "fax4", "jpeg", "lzw", "rle", or "deflate". +## Note that not all compression types are available for all image formats +## in which it defaults to your Magick library. +## ## @item DelayTime ## For formats that accept animations (such as GIF), controls for how long a ## frame is displayed until it moves to the next one. The value must be scalar @@ -200,3 +206,32 @@ %! [g] = write_and_read (".jpeg", gray, "quality", 100); %! assert (g, gray) +%!function [compression] = get_bmp_compression (ext, cmap = [], varargin) +%! gray = repmat (uint8 (0:255), 100, 1); +%! filename = [tempname() ext]; +%! unwind_protect +%! if (isempty (cmap)) +%! imwrite (gray, filename, varargin{1:end}); +%! else +%! imwrite (gray, cmap, filename, varargin{1:end}); +%! endif +%! fid = fopen (filename); +%! unwind_protect +%! compression = fread (fid, 31)(end); +%! unwind_protect_cleanup +%! fclose (fid); +%! end_unwind_protect +%! unwind_protect_cleanup +%! unlink (filename); +%! end_unwind_protect +%!endfunction + +## BMP images must be saved uncompressed by default (bug #45565) +%!testif HAVE_MAGICK +%! assert (get_bmp_compression ("", [], "BMP"), 0) +%! assert (get_bmp_compression ("", [], "bmp"), 0) +%! assert (get_bmp_compression (".BMP"), 0) +%! assert (get_bmp_compression (".bmp"), 0) +%! assert (get_bmp_compression (".bmp", [], "bmp"), 0) +%! assert (get_bmp_compression ("", gray (256), "bmp"), 0) +%! assert (get_bmp_compression (".bmp", gray (256), "Compression", "rle"), 1) diff -r e3f84a8c6788 -r 5b8e4f668c53 scripts/image/private/__imwrite__.m --- a/scripts/image/private/__imwrite__.m Tue Jul 28 08:52:39 2015 -0700 +++ b/scripts/image/private/__imwrite__.m Tue Jul 28 17:43:23 2015 +0100 @@ -46,7 +46,8 @@ "quality", 75, "delaytime", ones (1, size (img, 4)) *500, # 0.5 seconds "loopcount", 0, ## this is actually Inf - "alpha", cast ([], class (img))); + "alpha", cast ([], class (img)), + "compression", "none"); for idx = 1:2:numel (param_list) @@ -67,6 +68,19 @@ param_list{idx}); endif + case "compression" + options.compression = param_list{idx+1}; + if (! ischar (options.compression)) + error ("imwrite: value for %s option must be a string", + param_list{idx}); + endif + options.compression = tolower (options.compression); + if (! any (strcmp (options.compression, {"none", "bzip", "fax3", ... + "fax4", "jpeg", "lzw", ... + "rle", "deflate"}))) + error ("imwrite: invalid compression `%s'", options.compression); + endif + case "delaytime" options.delaytime = param_list{idx+1}; if (! isnumeric (options.delaytime))