Mercurial > hg > octave-image
changeset 4:cd11b4c8ce4c Octave-Forge-2002.03.10
general image read/write functionality using imagemagick utilities
author | aadler |
---|---|
date | Mon, 11 Mar 2002 01:56:47 +0000 |
parents | 63c0537da1c1 |
children | 3ad01c0606eb |
files | imread.m imwrite.m |
diffstat | 2 files changed, 525 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/imread.m @@ -0,0 +1,316 @@ +#IMREAD: read images into octave from various file formats +# +# Note: this requires the ImageMagick "convert" utility +# get this from www.imagemagick.org if required +# additional documentation of options is available from the +# convert man page +# +# BASIC USAGE: +# img = imread( fname ) +# - img is a greyscale (0-255) of image in fname +# [im,map]=imread( fname ) +# - map is a matrix of [r,g,b], 0-1 triples +# - img is a matrix on indeces into map +# [r,g,b]= imread( fname ) +# - r,g,b are red,green,blue (0-255) compondents +# +# Formats for image fname +# 1. simple guess from extention ie "fig.jpg", "blah.gif" +# 2. specify explicitly "jpg:fig.jpg", "gif:blah.gif" +# 3. specify subimage for multi-image format "tiff:file.tif[3]" +# 4. raw images (row major format) specify geometry +# "raw:img[256x180]" +# +# IMREAD OPTIONS: +# imread will support most of the options for convert.1 +# +# img = imread( fname , options) +# [r,g,b]= imread( fname , options) +# +# where options is a string matrix (or list) of options +# +# example: options= ["-rotate 25"; +# "-crop 200x200+150+150"; +# "-sample 200%" ]; +# will rotate, crop, and then expand the image. +# note that the order of operations is important +# +# The following options are supported +# -antialias remove pixel-aliasing +# -blur geometry blur the image +# -border geometry surround image with a border of color +# -bordercolor color border color +# -colors value maximum number of colors in the image +# -colorspace type alternate image colorspace +# -contrast enhance or reduce the image contrast +# -crop geometry preferred size and location of the cropped image +# -despeckle reduce the speckles within an image +# -dither apply Floyd/Steinberg error diffusion to image +# -draw string annotate the image with a graphic primitive +# -edge radius apply a filter to detect edges in the image +# -emboss radius emboss an image +# -enhance apply a digital filter to enhance a noisy image +# -equalize perform histogram equalization to an image +# -filter type use this filter when resizing an image +# -flip flip image in the vertical direction +# -flop flop image in the horizontal direction +# -font name font for rendering text +# -frame geometry surround image with an ornamental border +# -fuzz distance colors within this distance are considered equal +# -gamma value level of gamma correction +# -geometry geometry perferred size or location of the image +# -gaussian geometry gaussian blur an image +# -gravity type vertical and horizontal text placement +# -implode amount implode image pixels about the center +# -intent type Absolute, Perceptual, Relative, or Saturation +# -interlace type None, Line, Plane, or Partition +# -level value adjust the level of image contrast +# -map filename transform image colors to match this set of colors +# -median radius apply a median filter to the image +# -modulate value vary the brightness, saturation, and hue +# -monochrome transform image to black and white +# -mosaic create an mosaic from an image sequence +# -negate replace every pixel with its complementary color +# -noise radius add or reduce noise in an image +# -normalize transform image to span the full range of colors +# -paint radius simulate an oil painting +# -raise value lighten/darken image edges to create a 3-D effect +# -region geometry apply options to a portion of the image +# -roll geometry roll an image vertically or horizontally +# -rotate degrees apply Paeth rotation to the image +# -sample geometry scale image with pixel sampling +# -scale geometry resize image +# -scene value image scene number +# -segment values segment an image +# -seed value pseudo-random number generator seed value +# -shade degrees shade the image using a distant light source +# -sharpen geometry sharpen the image +# -shave geometry shave pixels from the image edges +# -shear geometry slide one edge of the image along the X or Y axis +# -size geometry width and height of image +# -solarize threshold negate all pixels above the threshold level +# -spread amount displace image pixels by a random amount +# -swirl degrees swirl image pixels about the center +# -texture filename name of texture to tile onto the image background +# -threshold value threshold the image +# -transparent color make this color transparent within the image +# -treedepth value depth of the color tree +# -type type image type +# -unsharp geometry sharpen the image +# -wave geometry alter an image along a sine wave + + + +function [out1,out2,out3]= imread(filename, options ); + +save_empty_list_elements_ok= empty_list_elements_ok; +unwind_protect +empty_list_elements_ok= 1; + +if (nargin == 0) + usage (["img = imread (filename,options)\n", ... + "[r,g,b]= imread (filename,options)\n", ... + "[img,map]=imread (filename,options)" ]); +elseif (! isstr (filename)) + error ("imread: expecting filename as a string"); +endif + +if any(filename==':') || any(filename=='[') + # we've using special imagemagick characters, so we don't + # do any octave path processing + fname= filename; +else + fname= file_in_path(IMAGEPATH,filename); + if isempty(fname) + error(['imread: file ' filename ' not found']); + end +end + +# Put together the options string +# TODO: add some error checking here +if nargin==1 + option_str=""; +else + option_str=""; + if ( is_list( options ) ) + for i= 1:length(options) + option_str=[option_str," ", nth(options,i) ]; + end + elseif ( isstr( options ) ) + for i= 1:size(options,1) + option_str=[option_str," ", options(i,:) ]; + end + else + error ("imread: expecting options as a string"); + end +end +# +# decode the nargout to output what the user wants +# +if nargout==3; + wantgreyscale= 0; + wantmap= 0; + outputtype="ppm"; +elseif nargout==2; + wantgreyscale= 0; wantmap= 1; + outputtype="ppm"; +else + wantgreyscale= 1; wantmap= 0; + outputtype="pgm"; +end + + pname= sprintf("convert %s %s %s:- 2>/dev/null", + option_str, fname, outputtype); + fid= popen(pname ,'r'); +# disp(pname); disp(fid); +# +# can we open the pipe? +# if not 1) The file format is wrong and the conver program has bailed out +# 2) The apropriate converter program hasn't been installed +# + if fid<0; + fclose(fid); + error(['could not popen ' pname '. Is imagemagick installed?']); + end + +# get file type + line= fgetl( fid ); + if strcmp(line, 'P1'); bpp=1; spp=1; bindata=0; + elseif strcmp(line, 'P4'); bpp=1; spp=1; bindata=1; + elseif strcmp(line, 'P2'); bpp=8; spp=1; bindata=0; + elseif strcmp(line, 'P5'); bpp=8; spp=1; bindata=1; + elseif strcmp(line, 'P3'); bpp=8; spp=3; bindata=0; + elseif strcmp(line, 'P6'); bpp=8; spp=3; bindata=1; + else + fclose(fid); + error(['Image format error for ' fname ]); + end + +# ignore comments + line= fgetl( fid ); + while length(line)==0 || line(1)=='#' + line= fgetl( fid ); + end + +# get width, height + [wid, hig]= sscanf( line, '%d %d', 'C' ); + +# get max component value + if bpp==8 + max_component= sscanf( fgetl(fid), '%d' ); + end + + if bindata + data= fread(fid); + numdata= size(data,1); + + if bpp==1 + data= rem( floor( (data*ones(1,8)) ./ ... + (ones(length(data),1)*[128 64 32 16 8 4 2 1]) ), 2)'; + end + else + numdata= wid*hig*spp; + data= zeros( numdata,1 ); + dptr= 1; + + line= fgetl( fid ); + while !feof( fid) + rdata= sscanf( line ,' %d'); + nptr= dptr + size(rdata,1); + data( dptr:nptr-1 ) = rdata; + dptr= nptr; + line= fgetl( fid ); + end # feof + end #if bindata + + fclose( fid ); + + if spp==1 + greyimg= reshape( data(:), wid, hig )'; + elseif spp==3 + redimg= reshape( data(1:spp:numdata), wid, hig )'; + grnimg= reshape( data(2:spp:numdata), wid, hig )'; + bluimg= reshape( data(3:spp:numdata), wid, hig )'; + else + error(sprintf("imread: don't know how to handle pnm with spp=%d",spp)); + end + + +# This section outputs the image in the desired output format +# if the user requested the colour map, the we regenerate it from +# the image. +# +# Of course, 1) This may result in huge colourmaps +# 2) The colourmap will not be in the same order as +# in the original file + +if wantgreyscale + + if exist('greyimg') + out1= greyimg; + elseif exist('idximg') + greymap= mean(map')'; + out1= reshape( greymap( idximg ) , size(idximg,1), size(idximg,2) ); + else + out1= ( redimg+grnimg+bluimg ) / 3 ; + end + +elseif wantmap + + if exist('idximg') + out1= idximg; + out2= map; + elseif exist('greyimg') + [simg, sidx] = sort( greyimg(:) ); + [jnkval, sidx] = sort( sidx ); + + dimg= [1; diff(simg)>0 ]; + cimg= cumsum( dimg ); + out1= reshape( cimg( sidx ) , hig, wid); + out2= ( simg(find( dimg ))*[1,1,1] - 1)/256; + else +# +# attempt to generate a colourmap for r,g,b images, assume range is 0<v<1000 +# for each value ( This will also be inaccurate for noninteger v ) +# however, we shouldn't be getting any of that from the pnm converters +# + c_range= 1000; + [simg, sidx] = sort( round(redimg(:)) + ... + c_range *round(grnimg(:)) + ... + c_range^2 *round(bluimg(:)) ); + [jnkval, sidx] = sort( sidx ); + + dimg= [1; diff(simg)>0 ]; + cimg= cumsum( dimg ); + out1= reshape( cimg( sidx ) , hig, wid ); + tmpv= simg(find( dimg )) - (1 + c_range + c_range^2); + out2= [ rem(tmpv,c_range), ... + rem(floor(tmpv/c_range), c_range), ... + floor(tmpv/c_range^2) ]/256; + end + + +else + + if exist('greyimg') + out1= greyimg; + out2= greyimg; + out3= greyimg; + else + out1= redimg; + out2= grnimg; + out3= bluimg; + end + +end + +unwind_protect_cleanup +empty_list_elements_ok= save_empty_list_elements_ok; +end_unwind_protect + +# +# $Log$ +# Revision 1.1 2002/03/11 01:56:47 aadler +# general image read/write functionality using imagemagick utilities +# +#
new file mode 100644 --- /dev/null +++ b/imwrite.m @@ -0,0 +1,209 @@ +#IMWRITE: write image from octave to various file formats +# +# Note: this requires the ImageMagick "convert" utility. +# get this from www.imagemagick.org if required +# additional documentation of options is available from the +# convert man page +# +# BASIC USAGE: +# imwrite( fname, img ) +# - img is a greyscale (0-255) of image in fname +# imwrite( fname, img, map ) +# - map is a matrix of [r,g,b], 0-1 triples +# - img is a matrix on indeces into map +# imwrite( fname, r,g,b ); +# - r,g,b are red,green,blue (0-255) compondents +# +# Formats for image fname +# 1. simple guess from extention ie "fig.jpg", "blah.gif" +# 2. specify explicitly "jpg:fig.jpg", "gif:blah.gif" +# 3. specify subimage for multi-image format "tiff:file.tif[3]" +# 4. raw images (row major format) specify geometry +# "raw:img[256x180]" +# +# IMREAD OPTIONS: +# imread will support most of the options for convert.1 +# +# imwrite( fname, img, options ) +# imwrite( fname, img, map, options ) +# imwrite( fname, r,g,b, options ); +# +# where options is a string matrix (or list) of options +# +# example: options= ["-rotate 25"; +# "-crop 200x200+150+150"; +# "-sample 200%" ]; +# will rotate, crop, and then expand the image. +# note that the order of operations is important +# +# The following options are supported +# -antialias remove pixel-aliasing +# -background color background color +# -blur geometry blur the image +# -border geometry surround image with a border of color +# -bordercolor color border color +# -box color color for annotation bounding box +# -charcoal radius simulate a charcoal drawing +# -colorize value colorize the image with the fill color +# -colors value preferred number of colors in the image +# -colorspace type alternate image colorspace +# -comment string annotate image with comment +# -compress type type of image compression +# -contrast enhance or reduce the image contrast +# -crop geometry preferred size and location of the cropped image +# -density geometry vertical and horizontal density of the image +# -depth value depth of the image +# -despeckle reduce the speckles within an image +# -dispose method GIF disposal method +# -dither apply Floyd/Steinberg error diffusion to image +# -draw string annotate the image with a graphic primitive +# -edge radius apply a filter to detect edges in the image +# -emboss radius emboss an image +# -enhance apply a digital filter to enhance a noisy image +# -equalize perform histogram equalization to an image +# -fill color color to use when filling a graphic primitive +# -filter type use this filter when resizing an image +# -flip flip image in the vertical direction +# -flop flop image in the horizontal direction +# -font name font for rendering text +# -frame geometry surround image with an ornamental border +# -fuzz distance colors within this distance are considered equal +# -gamma value level of gamma correction +# -geometry geometry perferred size or location of the image +# -gaussian geometry gaussian blur an image +# -gravity type vertical and horizontal text placement +# -implode amount implode image pixels about the center +# -intent type Absolute, Perceptual, Relative, or Saturation +# -interlace type None, Line, Plane, or Partition +# -label name assign a label to an image +# -level value adjust the level of image contrast +# -list type Color, Delegate, Format, Magic, Module, or Type +# -map filename transform image colors to match this set of colors +# -matte store matte channel if the image has one +# -median radius apply a median filter to the image +# -modulate value vary the brightness, saturation, and hue +# -monochrome transform image to black and white +# -morph value morph an image sequence +# -negate replace every pixel with its complementary color +# -noise radius add or reduce noise in an image +# -normalize transform image to span the full range of colors +# -opaque color change this color to the fill color +# -page geometry size and location of an image canvas +# -paint radius simulate an oil painting +# -profile filename add ICM or IPTC information profile to image +# -quality value JPEG/MIFF/PNG compression level +# -raise value lighten/darken image edges to create a 3-D effect +# -region geometry apply options to a portion of the image +# -roll geometry roll an image vertically or horizontally +# -rotate degrees apply Paeth rotation to the image +# -sample geometry scale image with pixel sampling +# -scale geometry resize image +# -segment values segment an image +# -seed value pseudo-random number generator seed value +# -shade degrees shade the image using a distant light source +# -sharpen geometry sharpen the image +# -shave geometry shave pixels from the image edges +# -shear geometry slide one edge of the image along the X or Y axis +# -size geometry width and height of image +# -solarize threshold negate all pixels above the threshold level +# -spread amount displace image pixels by a random amount +# -stroke color color to use when stoking a graphic primitive +# -strokewidth value width of stroke +# -swirl degrees swirl image pixels about the center +# -texture filename name of texture to tile onto the image background +# -threshold value threshold the image +# -tile filename tile image when filling a graphic primitive +# -transparent color make this color transparent within the image +# -treedepth value depth of the color tree +# -type type image type +# -units type PixelsPerInch, PixelsPerCentimeter, or Undefined +# -unsharp geometry sharpen the image + + +function imwrite(fname, p2, p3 ,p4 ,p5 ); + +save_empty_list_elements_ok= empty_list_elements_ok; +unwind_protect +empty_list_elements_ok= 1; + +if ( nargin <= 1 ) || ... + ( ! isstr (fname)) || ... + ( nargin == 2 && isstr(p2) ) + usage([ ... + "imwrite( fname, img )\n", ... + "imwrite( fname, img, map )\n", ... + "imwrite( fname, r,g,b );\n", ... + "imwrite( fname, img, options )\n", ... + "imwrite( fname, img, map, options )\n", ... + "imwrite( fname, r,g,b, options );\n"]); +endif + +# Put together the options string +# TODO: add some error checking to options +option_str=""; +n_mat= nargin-1; + +options= eval(sprintf("p%d",nargin)); +# process options strings if given +if isstr(options) + n_mat--; + for i= 1:size(options,1) + option_str=[option_str," ", options(i,:) ]; + end +elseif is_list( options ) + n_mat--; + for i= 1:length(options) + option_str=[option_str," ", nth(options,i) ]; + end +end + +[hig,wid] = size(p2); +if n_mat==1 + data= p2'; + outputtype="pgm"; + pnm_sig="P5"; +elseif n_mat==2 + img= p2'; + data= [ 255*reshape(p3(img,1),1, hig*wid); + 255*reshape(p3(img,2),1, hig*wid); + 255*reshape(p3(img,3),1, hig*wid) ]; + outputtype="ppm"; + pnm_sig="P6"; +elseif n_mat==3 + data= [ reshape(p2',1, hig*wid); + reshape(p3',1, hig*wid); + reshape(p4',1, hig*wid) ]; + outputtype="ppm"; + pnm_sig="P6"; +else + error("imwrite: too many data matrices specified"); +end + + pname= sprintf("convert %s %s:- %s 2>/dev/null", + option_str, outputtype, fname); + fid= popen(pname ,'w'); +# disp(pname); disp(fid); + if fid<0; + fclose(fid); + error(['could not popen ',pname,'. Is imagemagick installed?']); + end + + fprintf(fid,"%s\n%d %d\n255\n",pnm_sig,wid,hig); + write_count= fwrite(fid,data(:)); + if write_count != prod(size(data)) + fclose(fid); + error(['Unable to write image: ', fname ]); + end + + fclose(fid); + +unwind_protect_cleanup +empty_list_elements_ok= save_empty_list_elements_ok; +end_unwind_protect + +# +# $Log$ +# Revision 1.1 2002/03/11 01:56:47 aadler +# general image read/write functionality using imagemagick utilities +# +#