view scripts/image/imwrite.m @ 17332:eb7e9a991ffb

Implement writing of CMYK and fix writing of image alpha channel (bug #32986). * __magick_read__.cc (bitdepth_from_class, init_encode_image): new functions created from pieces of encode_indexed_images () to be used by the other encode image functions. (encode_indexed_images): make use of new bitdepth_from_class(), and init_encode_image() functions. (encode_bool_image): rewritten to match flow of the other encode functions, use fortran_vec for performance, and use only 4th dimension for frames. (encode_uint_image): completely rewritten to identify images of CMYK type and not confuse them with RGB plus alpha channel. Now accepts the alpha channel as separate argument. Image argument must now be of same class as the template. (__magick_write__): changed to match new API for the encode functions. * private/__imwrite__.m: set default and input check for alpha channel option. * imwrite.m: document alpha channel option as separate argument. * NEWS: announce rewrite of the image IO functions and warn about possible backwards incompatibilities.
author Carnë Draug <carandraug@octave.org>
date Mon, 19 Aug 2013 16:11:18 +0100
parents bc924baa2c4e
children 1c89599167a6
line wrap: on
line source

## Copyright (C) 2008-2012 John W. Eaton
## Copyright (C) 2013 Carnë Draug
##
## This file is part of Octave.
##
## Octave is free software; you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 3 of the License, or (at
## your option) any later version.
##
## Octave is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Octave; see the file COPYING.  If not, see
## <http://www.gnu.org/licenses/>.

## -*- texinfo -*-
## @deftypefn  {Function File} {} imwrite (@var{img}, @var{filename})
## @deftypefnx {Function File} {} imwrite (@var{img}, @var{filename}, @var{ext})
## @deftypefnx {Function File} {} imwrite (@var{img}, @var{map}, @var{filename})
## @deftypefnx {Function File} {} imwrite (@dots{}, @var{param1}, @var{val1}, @dots{})
## Write images in various file formats.
##
## The image @var{img} can be a binary, grayscale, RGB, or multi-dimensional
## image.  The size and class of @var{img} should be the same as what should
## be expected when reading it with @code{imread}: the 3rd and 4th dimensions
## reserved for color space, and multiple pages respectively.  If it's an
## indexed image, the colormap @var{map} must also be specified.
##
## If @var{ext} is not supplied, the file extension of @var{filename} is used
## to determine the format.  The actual supported formats are dependent on
## options made during the build of Octave.  Use @code{imformats} to check
## the support of the different image formats.
##
## Depending on the file format, it is possible to configure the writing
## of images with @var{param}, @var{val} pairs.  The following options
## are supported:
##
## @table @samp
## @item Alpha
## Alpha (transparency) channel for the image.  This must be a matrix with
## same class, and number of rows and columns of @var{img}.  In case of a
## 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 Quality
## Set the quality of the compression.  The value should be an
## integer between 0 and 100, with larger values indicating higher visual
## quality and lower compression.  Defaults to 75.
##
## @item WriteMode
## Some file formats, such as TIFF and GIF, are able to store multiple
## images in a single file.  This option specifies if @var{img} should be
## appended to the file (if it exists) or if a new file should be created
## for it (possibly overwriting an existing file).  The value should be
## the string @qcode{"Overwrite"} (default), or @qcode{"Append"}.
##
## Despite this option, the most efficient method of writing a multipage
## image is to pass a 4 dimensional @var{img} to @code{imwrite}, the
## same matrix that could be expected when using @code{imread} with the
## option @qcode{"Index"} set to @qcode{"all"}.
##
## @end table
##
## @seealso{imread, imfinfo, imformats}
## @end deftypefn

function imwrite (varargin)
  if (nargin < 2)
    print_usage ();
  endif
  [filename, ext] = imwrite_filename (varargin{2:end});

  fmt = imformats (ext);
  ## When there is no match, fmt will be a 1x1 structure with
  ## no fields, so we can't just use `isempty (fmt)'.
  if (isempty (fieldnames (fmt)))
    if (isempty (ext))
      error ("imwrite: no extension found for %s to identify the image format",
             filename);
    endif
    warning ("imwrite: unlisted image format %s (see imformats). Trying to save anyway.",
             ext);
    __imwrite__ (varargin{:});
  else
    fmt.write (varargin{:});
  endif

endfunction

%% Test input validation
%!error imwrite ()                            # Wrong # of args
%!error imwrite (1)                           # Wrong # of args
%!error imwrite ({"cell"}, "filename.jpg")    # Wrong class for img
%!error imwrite (1, [], "filename.jpg")       # Empty image map
%!error imwrite (1, 2, 3)                     # No filename specified
%!error imwrite (1, "filename")               # No fmt specified
%!error imwrite (1, "filename", "junk")       # Invalid fmt specified
%!error imwrite ([], "filename.jpg")          # Empty img matrix
%!error imwrite (spones (2), "filename.jpg")  # Invalid sparse img

%!testif HAVE_MAGICK
%! imw = randi (255, 100, "uint8");
%! filename = [tmpnam() ".png"];
%! unwind_protect
%!   imwrite (imw, filename);
%!   imr = imread (filename);
%! unwind_protect_cleanup
%!   unlink (filename);
%! end_unwind_protect
%! assert (imw, imr)