view scripts/image/imwrite.m @ 21580:ecce63c99c3f

maint: Add semicolons to terminate code in %! blocks. * splineimages.m, Cell.cc, bsxfun.cc, cellfun.cc, conv2.cc, data.cc, debug.cc, file-io.cc, gcd.cc, getrusage.cc, graphics.cc, kron.cc, mappers.cc, oct-map.cc, ordschur.cc, psi.cc, rand.cc, variables.cc, __osmesa_print__.cc, amd.cc, audiodevinfo.cc, dmperm.cc, qr.cc, ov-bool-mat.cc, ov-class.cc, ov-fcn-handle.cc, ov-java.cc, oct-parse.in.yy, bicubic.m, delaunay3.m, accumarray.m, flip.m, fliplr.m, flipud.m, gradient.m, inputParser.m, interp1.m, narginchk.m, rot90.m, validateattributes.m, delaunay.m, delaunayn.m, griddata3.m, inpolygon.m, waitbar.m, gray2ind.m, hsv2rgb.m, im2double.m, image.m, imformats.m, imread.m, imshow.m, imwrite.m, ntsc2rgb.m, rgb2hsv.m, rgb2ntsc.m, isbanded.m, onenormest.m, edit.m, fullfile.m, license.m, ode23.m, ode45.m, glpk.m, annotation.m, legend.m, orient.m, text.m, area.m, barh.m, contour.m, line.m, plot.m, plot3.m, plotyy.m, quiver.m, stem.m, clf.m, copyobj.m, findobj.m, subplot.m, ppval.m, splinefit.m, ismember.m, freqz.m, unwrap.m, eigs.m, ichol.m, pcg.m, spdiags.m, svds.m, magic.m, lscov.m, median.m, ols.m, dec2base.m, strsplit.m, strtok.m, test.m, bug-31371.tst, bug-36025.tst, bug-44940.tst, build-sparse-tests.sh, class-concat.tst, classdef.tst, classes.tst, colormaps.tst, command.tst, ctor-vs-method.tst, error.tst, fcn-handle-derived-resolution.tst, for.tst, index.tst, io.tst, jit.tst, null-assign.tst, parser.tst, struct.tst, system.tst: Add semicolons to terminate code in %! blocks.
author Rik <rik@octave.org>
date Fri, 01 Apr 2016 16:03:29 -0700
parents 3d60ed163b70
children b571fc85953f
line wrap: on
line source

## Copyright (C) 2008-2015 John W. Eaton
## Copyright (C) 2013-2015 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  {} {} imwrite (@var{img}, @var{filename})
## @deftypefnx {} {} imwrite (@var{img}, @var{filename}, @var{ext})
## @deftypefnx {} {} imwrite (@var{img}, @var{map}, @var{filename})
## @deftypefnx {} {} 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 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 @nospell{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
## (which will applied to all frames in @var{img}), or a vector of length
## equal to the number of frames in @var{im}.  The value is in seconds, must
## be between 0 and 655.35, and defaults to 0.5.
##
## @item DisposalMethod
## For formats that accept animations (such as GIF), controls what happens to
## a frame before drawing the next one.  Its value can be one of the
## following strings: "doNotSpecify" (default); "leaveInPlace"; "restoreBG";
## and "restorePrevious", or a cell array of those string with length equal
## to the number of frames in @var{img}.
##
## @item LoopCount
## For formats that accept animations (such as GIF), controls how many times
## the sequence is repeated.  A value of Inf means an infinite loop (default),
## a value of 0 or 1 that the sequence is played only once (loops zero times),
## while a value of 2 or above loops that number of times (looping twice means
## it plays the complete sequence 3 times).  This option is ignored when there
## is only a single image at the end of writing the file.
##
## @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 (numfields (fmt) == 0)
    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

%!function [r, cmap, a] = write_and_read (format, varargin)
%!  filename = [tempname() format];
%!  unwind_protect
%!    imwrite (varargin{1}, filename, varargin{2:end});
%!    [r, cmap, a] = imread (filename, "Index", "all");
%!  unwind_protect_cleanup
%!    unlink (filename);
%!  end_unwind_protect
%!endfunction

## typical usage with grayscale uint8 images
%!testif HAVE_MAGICK
%! gray = randi (255, 10, 10, 1, "uint8");
%! r = write_and_read (".tif", gray);
%! assert (r, gray);

## grayscale uint8 images with alpha channel
%!testif HAVE_MAGICK
%! gray  = randi (255, 10, 10, 1, "uint8");
%! alpha = randi (255, 10, 10, 1, "uint8");
%! [r, ~, a] = write_and_read (".tif", gray, "Alpha", alpha);
%! assert (r, gray);
%! assert (a, alpha);

## multipage grayscale uint8 images
%!testif HAVE_MAGICK
%! gray = randi (255, 10, 10, 1, 5, "uint8");
%! r    = write_and_read (".tif", gray);
%! assert (r, gray);

## multipage RGB uint8 images with alpha channel
%!testif HAVE_MAGICK
%! gray  = randi (255, 10, 10, 3, 5, "uint8");
%! alpha = randi (255, 10, 10, 1, 5, "uint8");
%! [r, ~, a] = write_and_read (".tif", gray, "Alpha", alpha);
%! assert (r, gray);
%! assert (a, alpha);

## typical usage with RGB uint8 images
%!testif HAVE_MAGICK
%! rgb = randi (255, 10, 10, 3, "uint8");
%! r = write_and_read (".tif", rgb);
%! assert (r, rgb);

## RGB uint8 images with alpha channel
%!testif HAVE_MAGICK
%! rgb   = randi (255, 10, 10, 3, "uint8");
%! alpha = randi (255, 10, 10, 1, "uint8");
%! [r, ~, a] = write_and_read (".tif", rgb, "Alpha", alpha);
%! assert (r, rgb);
%! assert (a, alpha);

## multipage RGB uint8 images
%!testif HAVE_MAGICK
%! rgb = randi (255, 10, 10, 3, 5, "uint8");
%! r = write_and_read (".tif", rgb);
%! assert (r, rgb);

## multipage RGB uint8 images with alpha channel
%!testif HAVE_MAGICK
%! rgb   = randi (255, 10, 10, 3, 5, "uint8");
%! alpha = randi (255, 10, 10, 1, 5, "uint8");
%! [r, ~, a] = write_and_read (".tif", rgb, "Alpha", alpha);
%! assert (r, rgb);
%! assert (a, alpha);

%!testif HAVE_MAGICK
%! gray = repmat (uint8 (0:255), 100, 1);
%! [g] = write_and_read (".jpeg", gray);
%! assert (g, gray, 2);

%!testif HAVE_MAGICK
%! gray = repmat (uint8 (0:255), 100, 1);
%! [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);