janko / image_processing

High-level image processing wrapper for libvips and ImageMagick/GraphicsMagick
MIT License
863 stars 76 forks source link

TypeError: no implicit conversion of String into Integer #88

Closed thomas07vt closed 3 years ago

thomas07vt commented 3 years ago

Versions

ruby 3.0.1p64 ruby-vips 2.1.2 image_processing 1.12.1

Issue

I seem to be having the same issue as this: https://github.com/libvips/ruby-vips/issues/303

When I try to create a variant on a .heic file: file.variant(resize_to_limit: ["100", "100"]).processed

I get this error: TypeError: no implicit conversion of String into Integer

I don't believe it has to do with libvips recognizing the heic file because I can take the exact same file and convert it to a PNG:

io = ImageProcessing::Vips.source(blob).convert("png").call

Here is the truncated backtrace:

"/app/vendor/bundle/ruby/3.0.0/gems/ruby-vips-2.1.2/lib/vips/gvalue.rb:100:in `g_value_set_int'",
"/app/vendor/bundle/ruby/3.0.0/gems/ruby-vips-2.1.2/lib/vips/gvalue.rb:100:in `set'",
"/app/vendor/bundle/ruby/3.0.0/gems/ruby-vips-2.1.2/lib/vips/object.rb:258:in `set'",
"/app/vendor/bundle/ruby/3.0.0/gems/ruby-vips-2.1.2/lib/vips/operation.rb:272:in `set'",
"/app/vendor/bundle/ruby/3.0.0/gems/ruby-vips-2.1.2/lib/vips/operation.rb:450:in `block in call'",
"/app/vendor/bundle/ruby/3.0.0/gems/ruby-vips-2.1.2/lib/vips/operation.rb:442:in `each_index'",
"/app/vendor/bundle/ruby/3.0.0/gems/ruby-vips-2.1.2/lib/vips/operation.rb:442:in `call'",
"/app/vendor/bundle/ruby/3.0.0/gems/ruby-vips-2.1.2/lib/vips/image.rb:229:in `method_missing'",
"/app/vendor/bundle/ruby/3.0.0/gems/image_processing-1.12.1/lib/image_processing/vips.rb:145:in `thumbnail'",
"/app/vendor/bundle/ruby/3.0.0/gems/image_processing-1.12.1/lib/image_processing/processor.rb:62:in `public_send'",

Reproducibility Info

In case you want to reproduce, this is the heic previewer I am using:

class HeicPreviewer < ActiveStorage::Previewer
  CONTENT_TYPE = "image/heic".freeze

  class << self
    def accept?(blob)
      blob.content_type == CONTENT_TYPE && vips_exists?
    end

    def vips_exists?
      return @vips_exists unless @vips_exists.nil?

      require "image_processing/vips"
      @vips_exists = Vips.at_least_libvips?(0, 0)
    rescue
      @vips_exists = false
    end
  end

  def preview(**options)
    download_blob_to_tempfile do |input|
      io = ImageProcessing::Vips.source(input).convert("png").call
      yield io: io, filename: "#{blob.filename.base}.png", content_type: "image/png"
    end
  end
end

and this is in an initializer file:


Rails.application.configure do
  config.active_storage.previewers << HeicPreviewer
  config.active_storage.variable_content_types << "image/heic"
end
thomas07vt commented 3 years ago

So I added some debugging above the line that fails for image_processing:

#lib/image_processing/vips.rb:145
puts "width: #{width.inspect} | height: #{height.inspect} | options: #{options.inspect}"
image = self.image.thumbnail_image(width, height: height, **options)

which results in:

width: "100" | height: "100" | options: {:no_rotate=>true, :size=>:down}

So the width and height are being passed in as strings, which seems like it might be causing the issue?

Additionally, I added some debugging logs in ruby-vips

#lib/vips/gvalue.rb:99
when GINT_TYPE
        puts "VALUE: #{value.inspect} | #{value.class}"
        puts self.inspect
        ::GObject.g_value_set_int self, value

which results in

VALUE: "100" | String
#<GObject::GValue:0x000056170d218890>
thomas07vt commented 3 years ago

I just tested casting the value to an integer and it does work:

::GObject.g_value_set_int self, value.to_i

I am not sure if this is a bug in https://github.com/libvips/ruby-vips or https://github.com/janko/image_processing.

cc @janko @jcupitt

ps. thanks for image_processing and ruby-vips!

thomas07vt commented 3 years ago

I guess an easy fix would be to call file.variant(resize_to_limit: [100, 100]).processed and not use strings :)

jcupitt commented 3 years ago

Yes, the imagemagick backend builds a command-line for you and executes convert in a subshell, so strings for numbers are fine. Though actual numbers work too.

The ruby-vips backend makes direct calls into a native library, so it needs numbers as ints.

tldr: don't use strings for numbers, as you say

thomas07vt commented 3 years ago

I am going to go ahead and close this issue, but just an fyi, I know strings worked for image_processing (1.10.0) and ruby-vips (2.0.16)