Images from database

I have an application that stores thumbnail images in a database as simple RGB uncompressed data. I am currently writing a rails application to display the contents of this database. I am wondering what's the fastest and most portable way to have that RGB data (blobs) converted as a valid image that a browser can display. Ideally, due to the large number of images I'll be dealing with and displaying at a time, I am trying to avoid having to use something like rmagick to create the images temporarily on disk as they are fetched from the database.

gga wrote:

I have an application that stores thumbnail images in a database as simple RGB uncompressed data. I am currently writing a rails application to display the contents of this database. I am wondering what's the fastest and most portable way to have that RGB data (blobs) converted as a valid image that a browser can display. Ideally, due to the large number of images I'll be dealing with and displaying at a time, I am trying to avoid having to use something like rmagick to create the images temporarily on disk as they are fetched from the database.

Well caching them to disc may save a lot of load on your DB and Rails app (it's kind of wasteful to tie up a Rails process just to serve image data) but if you want to serve them directly from the database and assuming the data is in some format the browser will recognize use send_data. E.g.:

@thumb = Thumb.find(params[:id])

send_data(@thumb.data,    :filename => "some_file_name_here",    :type => "image/png",    :disposition => "inline")

Well caching them to disc may save a lot of load on your DB and Rails app (it's kind of wasteful to tie up a Rails process just to serve image data) but if you want to serve them directly from the database and assuming the data is in some format the browser will recognize use send_data. E.g.:

Thanks, but no. They are not in a browser compatible format. Currently they are just RAW RGB 8-bit unsigned chars.

gga wrote:

Well caching them to disc may save a lot of load on your DB and Rails app (it's kind of wasteful to tie up a Rails process just to serve image data) but if you want to serve them directly from the database and assuming the data is in some format the browser will recognize use send_data. E.g.:

Thanks, but no. They are not in a browser compatible format. Currently they are just RAW RGB 8-bit unsigned chars.

So you are trying to send it as a file (attachment) and not display it inline? You could try setting :disposition to "attachment" with send_data and see if that works. Not sure what :type to use, though.

So you are trying to send it as a file (attachment) and not display it inline? You could try setting :disposition to "attachment" with send_data and see if that works. Not sure what :type to use, though.

No. I am trying to display them inline, but the data is not in a browser compatible format as it is created elsewhere by another utility. This is done to save space. In the future the image stored in the database should also end up being compressed, instead of RAW RGB.

I currently have it working using RMagick and generating the files to disk, but I find this unsatisfactory, as I am creating a lot of useless .png images on disk. I mean, if I have to create the images on disk, not much sense in keeping the rgb data in the database in the first place.

Retrieving the rgb data from the database is very fast, but it can be somewhat slow with a 32-bits imagemagick as it forces me to turn all 0...255 to floats.

I am no (x)HTML expert, but most of the (x)HTML inline methods for images seem to be the equivalent as saving the image to disk, as you need to store inline data in the html that is a valid gif, png or jpg... which kind of beats the purpose of inlining. I'm kind of amazed there's not a simple way to just pass RGB uchar triplets or RGBA and have the browser show that as an image.

gga wrote:

So you are trying to send it as a file (attachment) and not display it inline? You could try setting :disposition to "attachment" with send_data and see if that works. Not sure what :type to use, though.

No. I am trying to display them inline, but the data is not in a browser compatible format as it is created elsewhere by another utility. This is done to save space. In the future the image stored in the database should also end up being compressed, instead of RAW RGB.

I currently have it working using RMagick and generating the files to disk, but I find this unsatisfactory, as I am creating a lot of useless .png images on disk. I mean, if I have to create the images on disk, not much sense in keeping the rgb data in the database in the first place.

If you are using RMagick to do the conversion in memory (rather than calling something on the command line) you can just pass the data into send_data bypassing the save to file step.

If you are using RMagick to do the conversion in memory (rather than calling something on the command line) you can just pass the data into send_data bypassing the save to file step.

I am doing the conversion in memory, but not sure I follow you. How can send_data() be used multiple times (like in the list view) to show the thumbnails. This is what I tried with no success.

  def list     @image_pages, @images = paginate :images, :per_page => 20     @images.each do |image|

      file = "images/dbimage-#{image.id}.png"

      #next if File.exists?(file)

      thumbnail = image.thumbnail

      width, height = image.thumbnail_width, image.thumbnail_height

      next if width <= 0 or height <= 0

      thumbnail = thumbnail.unpack('C*').map { |x| x / 255.0 }

      img = Magick::Image.constitute(width, height, 'BGRA', thumbnail)       #img.write(file)

      img.format = 'PNG'

      send_data(img.to_blob,                 :filename => file,                 :type => "image/png",                 :disposition => "inline")     end   end

gga wrote:

If you are using RMagick to do the conversion in memory (rather than calling something on the command line) you can just pass the data into send_data bypassing the save to file step.

I am doing the conversion in memory, but not sure I follow you. How can send_data() be used multiple times (like in the list view) to show the thumbnails. This is what I tried with no success.

How many images are you trying to send per page? I was assuming you had it setup where each image was it's own URL like:

http://localhost/image/image_key

and you would just use image_tag multiple times on the page. send_data is not going to work if you are trying to push out multiple images in a single call.

If only IE supported the data: URI. Then you could return all your images inline.

Others are right though. You'll need to have some method of referring to an image using a URI, and have that method render the image. Using send_data() will let you send the raw image data directly, rather than using a temporary file.

I've started storing images (base64 encoded) in a Postgresql database, and send_data is very handy there.

--Michael