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