ruby-on-railspdfdata-url

Is it possible to add DataUrl Image in RBPDF?


I am making pdf file from DataUrl Image in ruby on rails.

I have selected RBPDF to produce pdf file in server side.

But in this code I have following error

 @pdf.Image(object["src"] , object["left"], object["top"], object["width"], object["height"])

Here object["src"] is DataUrl Image.

RuntimeError (RBPDF error: Missing image file: data:image/jpeg;base64,/9j/4REORXhp...

Is it impossible to add RBPDF image from DataUrl image?

Adding files dynamically is not effective I think.


Solution

  • You may monkey patch the origin method.

    I use the data_uri gem to parse the image data.

    require 'data_uri'
    require 'rmagick'
    module Rbpdf
      alias_method :old_getimagesize, :getimagesize
    # @param [String]  date_url
      def getimagesize(date_url)
        if date_url.start_with? 'data:'
          uri = URI::Data.new date_url
          image_from_blob = Magick::Image.from_blob(uri.data)
          origin_process_image(image_from_blob[0])
        else
          old_getimagesize date_url
        end
      end
    
    # this method is extracted without comments from the origin implementation of getimagesize 
      def origin_process_image(image)
        out = Hash.new
        out[0] = image.columns
        out[1] = image.rows
    
        case image.mime_type
          when "image/gif"
            out[2] = "GIF"
          when "image/jpeg"
            out[2] = "JPEG"
          when "image/png"
            out[2] = "PNG"
          when "    image/vnd.wap.wbmp"
            out[2] = "WBMP"
          when "image/x-xpixmap"
            out[2] = "XPM"
        end
        out[3] = "height=\"#{image.rows}\" width=\"#{image.columns}\""
        out['mime'] = image.mime_type
    
        case image.colorspace.to_s.downcase
          when 'cmykcolorspace'
            out['channels'] = 4
          when 'rgbcolorspace', 'srgbcolorspace' # Mac OS X : sRGBColorspace
            if image.image_type.to_s == 'GrayscaleType' and image.class_type.to_s == 'PseudoClass'
              out['channels'] = 0
            else
              out['channels'] = 3
            end
          when 'graycolorspace'
            out['channels'] = 0
        end
    
        out['bits'] = image.channel_depth
    
        out
      end
    end