Using Amazon product images on your website

Posted by Dan Sosedoff on June 15, 2010

Amazon has an awesome image service. You can use their product images on your site, adjusting them for you needs. All you have to know – one image url of your product. Having that string will provide you an access to its dynamic image scaling service which i had to use recently.

So, lets say you have books on your website, but you dont have any good images for them. There is 2 ways to solve your problem: 1) download it from whatever place and resize 2) use amazon!

Here goes small overview.

Unfortunately, i didnt have any time to play with image service for different countries, but i assume that wont change that much. Lets take a look on a regular image:

http://ecx.images-amazon.com/images/I/41ygBmdaIfL._SL500_SS100_.jpg

It has different parts:
1) URL base: http://ecx.images-amazon.com/images/I/
2) Image code: 41ygBmdaIfL
3) Size format (surrounded by underscores): _SL500_SS100_
4) Format: jpg/gif/png

Some words about image format. It can vary from square thumbnails to images with specific max width and height. For example: _SX100_ will produce image that 100 pixels wide, height will be calculated proportionally. SH100 will give opposite result, scaled by 100 pixels maximum height, SS100 – 100×100 pixels thumbnail. And so on, you can find other similar crop codes while exploring amazon store on different pages, all you need is to take a look on image sources.

Now, we need to use this with Ruby:

require 'net/http'
 
module Amazon
  # parse amazon image url and get image code and extension
  def self.parse_image(url)
    result = url.scan(/^http:\/\/ecx.images-amazon.com\/images\/I\/([a-z0-9\-\%]{1,})(.*)_.(jpg|jpeg|gif)/i)
    unless result.nil?
      unless result[0].nil?
        match = result.first
        return {:code => match.first.to_s, :extension => match.last.to_s}
      end
    end
  end
 
  # make a new amazon image url based on code and size
  def self.make_image(image, size)
    "http://ecx.images-amazon.com/images/I/#{image[:code]}._#{size.upcase}.#{image[:extension]}"
  end
 
  # check if actual image exists
  def self.check_image(url)
    begin
      uri = URI.parse(url)
      req = Net::HTTP::Get.new(uri.path)
      res = Net::HTTP.start(uri.host, uri.port) { |http| http.request(req) }
      return res.code == '200' && res.content_length.to_i > 0
    rescue Exception
      false
    end
  end
end

And usage:

url = 'http://ecx.images-amazon.com/images/I/51O65dIoZCL._SX117_.jpg'
info = Amazon.parse_image(url)
unless info.nil?
  new_url = Amazon.make_image(info, 'sx100')
  if Amazon.check_image(new_url)
    puts "Cool! Resized image: #{new_url}"
  else
    puts "Sorry, this image does not exist!"
  end
else
  puts "Cant identify image!"
end

Some notes about the process. The only reason why method “check_image” uses GET method instead of HEAD is because if image cannot be generated or not found in amazon`s cache the response is still valid sometimes. I`ve checked it on 50k images and sometimes HEAD request indicates that response is valid while it not supposed to. Otherwise i would use HEAD.

Scaling images with RMagick

Posted by Dan Sosedoff on March 14, 2009

Simple class that providing scaling (rectangle and thumbnails) for images using RMagick and Ruby.
Code:

class ImageScale
    def change_geometry(sz,value)
        w = sz[0] ; h = sz[1]
            if w > h
                sz[0] = value
                sz[1] = ((value * h) / w).floor
            else
                sz[1] = value
                sz[0] = ((value * w) / h).floor
            end
            return sz
    end
 
    def make_rect(file_in,file_out, width, quality=85, sharp=false) 
        if FileTest.exists?(file_in)
            begin
                img = Magick::Image.read(file_in).first
                img.crop_resized!(width,width, Magick::CenterGravity)
                img = img.sharpen(0.5, 0.5) if sharp
                img.write(file_out) { self.quality = quality }
                return true if FileTest.exists?(file_out)
            rescue Magick::ImageMagickError
                return false
            end
        end
        return false
    end
 
    def make_thumb(file_in,file_out, width_to, quality=85, sharp=false) 
        if FileTest.exists?(file_in)
            begin
                img = Magick::Image.read(file_in).first
                info = [img.columns,img.rows]
                sz = change_geometry(info, width_to)
                img = img.resize(sz[0],sz[1])
                img = img.sharpen(0.5, 0.5) if sharp
                img.write(file_out) { self.quality = quality }
                return true if FileTest.exists?(file_out)
            rescue Magick::ImageMagickError
                return false
            end
        end
        return false
    end
end

Ok, let`s see how this class working. For example, we have source image:
Source Image

Function ImageScale.make_rect(src,dest,64) will produce such image:
Rectangle Image

Function ImageScale.make_thumb(src,dest,200) will produce thumbnail:
Thumbnail Image

There is optional parameter sharp to use sharping. Optional parameter quality is set to 85% compression value.