# FastImage Resize is an extremely light solution for resizing images in ruby by using libgd # # === Examples # # require 'fastimage_resize' # # FastImage.resize("http://stephensykes.com/images/ss.com_x.gif", 100, 20, :outfile=>"my.gif") # => 1 # # === Requirements # # RubyInline # # gem install RubyInline # # FastImage # # gem install fastimage # # Libgd # # See http://www.libgd.org/ # Libgd is commonly available on most unix platforms, including OSX. # # === References # # * http://blog.new-bamboo.co.uk/2007/12/3/super-f-simple-resizing require 'inline' require 'open-uri' require 'tempfile' require 'fastimage' class FastImage SUPPORTED_FORMATS = [:jpeg, :png, :gif] class FormatNotSupported < FastImageException # :nodoc: end # Resizes an image, storing the result in a file given in file_out # # Input can be a filename, a uri, or an IO object. # # FastImage Resize can resize GIF, JPEG and PNG files. # # === Example # # require 'fastimage_resize' # # FastImage.resize("http://stephensykes.com/images/ss.com_x.gif", 100, 20, :outfile=>"my.gif") # # === Supported options # [:jpeg_quality] # A figure passed to libgd to determine quality of output jpeg (only useful if input is jpeg) # [:outfile] # Name of a file to store the output in, in this case a temp file is not used # def self.resize(input, w, h, options={}) jpeg_quality = options[:jpeg_quality].to_i || -1 file_out = options[:outfile] if input.respond_to?(:read) file_in = read_to_local(input) else u = URI.parse(input) if u.scheme == "http" || u.scheme == "https" || u.scheme == "ftp" file_in = read_to_local(open(u)) else file_in = input.to_s end end if !file_out temp_file = Tempfile.new(name) file_out = temp_file.path else temp_file = nil end fast_image = new(file_in, :raise_on_failure=>true) type_index = SUPPORTED_FORMATS.index(fast_image.type) raise FormatNotSupported unless type_index in_path = file_in.respond_to?(:path) ? file_in.path : file_in fast_image.resize_image(in_path, file_out.to_s, w.to_i, h.to_i, type_index, jpeg_quality) if file_in.respond_to?(:close) file_in.close file_in.unlink end temp_file rescue OpenURI::HTTPError, SocketError, URI::InvalidURIError, RuntimeError => e raise ImageFetchFailure, e.class end private # returns readable tempfile def self.read_to_local(readable) temp = Tempfile.new(name) temp.write(readable.read) temp.close temp.open temp end def resize_image(filename_in, filename_out, w, h, image_type, jpeg_quality); end inline do |builder| builder.include '"gd.h"' builder.add_link_flags "-lgd" builder.c <<-"END" VALUE resize_image(char *filename_in, char *filename_out, int w, int h, int image_type, int jpeg_quality) { gdImagePtr im_in, im_out; FILE *in, *out; int trans = 0, x = 0, y = 0, f = 0; in = fopen(filename_in, "rb"); if (!in) return Qnil; im_out = gdImageCreateTrueColor(w, h); /* must be truecolor */ switch(image_type) { case 0: im_in = gdImageCreateFromJpeg(in); break; case 1: im_in = gdImageCreateFromPng(in); gdImageAlphaBlending(im_out, 0); /* handle transparency correctly */ gdImageSaveAlpha(im_out, 1); break; case 2: im_in = gdImageCreateFromGif(in); trans = gdImageGetTransparent(im_in); /* find a transparent pixel, then turn off transparency so that it copies correctly */ if (trans >= 0) { for (x=0; x= 0) { trans = gdImageGetPixel(im_out, x, y); /* get the color index of our transparent pixel */ gdImageColorTransparent(im_out, trans); /* may not always work as hoped */ } gdImageGif(im_out, out); break; } fclose(out); } gdImageDestroy(im_in); gdImageDestroy(im_out); return Qnil; } END end end