Search code examples
ruby-on-railsrubybitmapgoogle-cloud-vision

How to get a bitmap image in ruby?


The google vision API requires a bitmap sent as an argument. I am trying to convert a png from a URL to a bitmap to pass to the google api:

require "google/cloud/vision"
PROJECT_ID = Rails.application.secrets["project_id"]
KEY_FILE = "#{Rails.root}/#{Rails.application.secrets["key_file"]}"
google_vision = Google::Cloud::Vision.new project: PROJECT_ID, keyfile: KEY_FILE
img = open("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png").read
image = google_vision.image img
ArgumentError: string contains null byte

This is the source code processing of the gem:

    def self.from_source source, vision = nil
      if source.respond_to?(:read) && source.respond_to?(:rewind)
        return from_io(source, vision)
      end
      # Convert Storage::File objects to the URL
      source = source.to_gs_url if source.respond_to? :to_gs_url
      # Everything should be a string from now on
      source = String source
      # Create an Image from a HTTP/HTTPS URL or Google Storage URL.
      return from_url(source, vision) if url? source
      # Create an image from a file on the filesystem
      if File.file? source
        unless File.readable? source
          fail ArgumentError, "Cannot read #{source}"
        end
        return from_io(File.open(source, "rb"), vision)
      end
      fail ArgumentError, "Unable to convert #{source} to an Image"
    end

https://github.com/GoogleCloudPlatform/google-cloud-ruby

Why is it telling me string contains null byte? How can I get a bitmap in ruby?


Solution

  • According to the documentation (which, to be fair, is not exactly easy to find without digging into the source code), Google::Cloud::Vision#image doesn't want the raw image bytes, it wants a path or URL of some sort:

    Use Vision::Project#image to create images for the Cloud Vision service.

    You can provide a file path:
    [...]
    Or any publicly-accessible image HTTP/HTTPS URL:
    [...]
    Or, you can initialize the image with a Google Cloud Storage URI:

    So you'd want to say something like:

    image = google_vision.image "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"
    

    instead of reading the image data yourself.