From 4bef010ff7f382aed91aaa3534502b0af22c09e7 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 24 Jul 2025 15:08:48 +0100 Subject: [PATCH 1/6] improve gflags argument handling --- CHANGELOG.md | 1 + lib/vips/gvalue.rb | 35 ++++++++++++++++++++++++++++++++--- lib/vips/image.rb | 10 +++++----- lib/vips/object.rb | 1 + spec/vips_spec.rb | 29 +++++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 686cbe92..4a266017 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## master * improve NULL pointer handling [dloebl] +* improve GFlags argument handling [jcupitt] ## Version 2.2.4 (2025-06-05) diff --git a/lib/vips/gvalue.rb b/lib/vips/gvalue.rb index c6a1cb8a..ebff2e83 100644 --- a/lib/vips/gvalue.rb +++ b/lib/vips/gvalue.rb @@ -25,7 +25,7 @@ class GValue < FFI::ManagedStruct :data, [:ulong_long, 2] # convert an enum value (str/symb/int) into an int ready for libvips - def self.from_nick(gtype, value) + def self.enum_from_nick(gtype, value) value = value.to_s if value.is_a? Symbol if value.is_a? String @@ -40,6 +40,34 @@ def self.from_nick(gtype, value) value end + # convert an flags value (array[str/symb/int] | str/symb/int) into an + # int ready for libvips + def self.flags_from_nick(gtype, value) + if value.is_a? String + # libvips will parse strings like "sub|up" etc. + name = value.tr("_", "-") + value = Vips.vips_flags_from_nick "ruby-vips", gtype, name + else + value = [value] if !value.is_a? Array + + # convert each item to a set of bits, OR them together + result = 0 + value.map do |item| + item = item.to_s if item.is_a? Symbol + if item.is_a? String + name = item.tr("_", "-") + item = Vips.vips_flags_from_nick "ruby-vips", gtype, name + end + + result |= item + end + + value = result + end + + value + end + # convert an int enum back into a symbol def self.to_nick(gtype, enum_value) enum_name = Vips.vips_enum_nick gtype, enum_value @@ -148,10 +176,11 @@ def set value else case fundamental when GFLAGS_TYPE - ::GObject.g_value_set_flags self, value + flags_value = GValue.flags_from_nick(self[:gtype], value) + ::GObject.g_value_set_flags self, flags_value when GENUM_TYPE - enum_value = GValue.from_nick(self[:gtype], value) + enum_value = GValue.enum_from_nick(self[:gtype], value) ::GObject.g_value_set_enum self, enum_value when GOBJECT_TYPE diff --git a/lib/vips/image.rb b/lib/vips/image.rb index 9ee303ac..9a0df715 100644 --- a/lib/vips/image.rb +++ b/lib/vips/image.rb @@ -114,12 +114,12 @@ def self.smap x, &block end def self.complex? format - format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format + format_number = GObject::GValue.enum_from_nick BAND_FORMAT_TYPE, format Vips.vips_band_format_iscomplex(format_number) != 0 end def self.float? format - format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format + format_number = GObject::GValue.enum_from_nick BAND_FORMAT_TYPE, format Vips.vips_band_format_isfloat(format_number) != 0 end @@ -380,7 +380,7 @@ def self.new_from_memory data, width, height, bands, format size = data.bytesize end - format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format + format_number = GObject::GValue.enum_from_nick BAND_FORMAT_TYPE, format vi = Vips.vips_image_new_from_memory data, size, width, height, bands, format_number raise Vips::Error if vi.null? @@ -405,7 +405,7 @@ def self.new_from_memory data, width, height, bands, format # @param format [Symbol] band format # @return [Image] the loaded image def self.new_from_memory_copy data, width, height, bands, format - format_number = GObject::GValue.from_nick BAND_FORMAT_TYPE, format + format_number = GObject::GValue.enum_from_nick BAND_FORMAT_TYPE, format if data.is_a?(FFI::Pointer) if data.size == UNKNOWN_POINTER_SIZE @@ -1319,7 +1319,7 @@ def composite overlay, mode, **opts end mode = mode.map do |x| - GObject::GValue.from_nick Vips::BLEND_MODE_TYPE, x + GObject::GValue.enum_from_nick Vips::BLEND_MODE_TYPE, x end Vips::Image.composite([self] + overlay, mode, **opts) diff --git a/lib/vips/object.rb b/lib/vips/object.rb index 9541c6f1..4ac23ab8 100644 --- a/lib/vips/object.rb +++ b/lib/vips/object.rb @@ -125,6 +125,7 @@ class Progress < FFI::Struct attach_function :vips_enum_from_nick, [:string, :GType, :string], :int attach_function :vips_enum_nick, [:GType, :int], :string + attach_function :vips_flags_from_nick, [:string, :GType, :string], :int attach_function :vips_value_set_ref_string, [GObject::GValue.ptr, :string], :void diff --git a/spec/vips_spec.rb b/spec/vips_spec.rb index 3b8c407d..54b2c266 100644 --- a/spec/vips_spec.rb +++ b/spec/vips_spec.rb @@ -166,6 +166,35 @@ expect(rot.bands).to eq(1) end + it "can handle symbol flag arguments" do + black = Vips::Operation.call "black", [200, 200] + bytes = Vips::Operation.call "pngsave_buffer", [black], keep: :icc + + expect(bytes.length).to be > 100 + end + + it "can handle int flag arguments" do + black = Vips::Operation.call "black", [200, 200] + bytes = Vips::Operation.call "pngsave_buffer", [black], keep: 1 << 3 + + expect(bytes.length).to be > 100 + end + + it "can handle string flag arguments" do + black = Vips::Operation.call "black", [200, 200] + bytes = Vips::Operation.call "pngsave_buffer", [black], keep: "icc" + + expect(bytes.length).to be > 100 + end + + it "can handle array flag arguments" do + black = Vips::Operation.call "black", [200, 200] + bytes = Vips::Operation.call "pngsave_buffer", [black], + keep: [:icc, :xmp] + + expect(bytes.length).to be > 100 + end + it "can return optional output args" do point = Vips::Operation.call "black", [1, 1] test = Vips::Operation.call "embed", [point, 20, 10, 100, 100], From f735e663cf6438d479b6644022bb6c126e5e1f92 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 24 Jul 2025 15:23:56 +0100 Subject: [PATCH 2/6] fix lint failure --- lib/vips/x.png | Bin 0 -> 139 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 lib/vips/x.png diff --git a/lib/vips/x.png b/lib/vips/x.png new file mode 100644 index 0000000000000000000000000000000000000000..11848edd870375bdcca226fd853383851161832d GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^CqS43NHBC5e{=#;oCO|{#S9G0FF=@aYjsdIP|()X w#WAE}&f9~Gyg=Te1>gO1`PoH)Od`OCw7DD%jEV0pFM Date: Thu, 24 Jul 2025 15:24:30 +0100 Subject: [PATCH 3/6] oops! --- lib/vips/x.png | Bin 139 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lib/vips/x.png diff --git a/lib/vips/x.png b/lib/vips/x.png deleted file mode 100644 index 11848edd870375bdcca226fd853383851161832d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^CqS43NHBC5e{=#;oCO|{#S9G0FF=@aYjsdIP|()X w#WAE}&f9~Gyg=Te1>gO1`PoH)Od`OCw7DD%jEV0pFM Date: Thu, 24 Jul 2025 15:26:24 +0100 Subject: [PATCH 4/6] add a compat method --- lib/vips/gvalue.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/vips/gvalue.rb b/lib/vips/gvalue.rb index ebff2e83..52456c74 100644 --- a/lib/vips/gvalue.rb +++ b/lib/vips/gvalue.rb @@ -40,7 +40,13 @@ def self.enum_from_nick(gtype, value) value end - # convert an flags value (array[str/symb/int] | str/symb/int) into an + # compatibility ... we used to call it this, perhaps someone has used this + # internal method + def self.from_nick(gtype, value) + GValue.enum_from_nick(gtype, value) + end + + # convert an flags value (array[str/symb/int] | str/symb/int) into an # int ready for libvips def self.flags_from_nick(gtype, value) if value.is_a? String From eae8f921163f48a6f9d28455d806eac88067e8e4 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 24 Jul 2025 15:28:46 +0100 Subject: [PATCH 5/6] throw an error for bad flag --- lib/vips/gvalue.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/vips/gvalue.rb b/lib/vips/gvalue.rb index 52456c74..9b5340f4 100644 --- a/lib/vips/gvalue.rb +++ b/lib/vips/gvalue.rb @@ -63,6 +63,9 @@ def self.flags_from_nick(gtype, value) if item.is_a? String name = item.tr("_", "-") item = Vips.vips_flags_from_nick "ruby-vips", gtype, name + if item == -1 + raise Vips::Error + end end result |= item From 742d3d409511bab70bd56dc77789ef692d320d84 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 24 Jul 2025 15:31:30 +0100 Subject: [PATCH 6/6] another lint --- spec/vips_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/vips_spec.rb b/spec/vips_spec.rb index 54b2c266..c22f9245 100644 --- a/spec/vips_spec.rb +++ b/spec/vips_spec.rb @@ -189,7 +189,7 @@ it "can handle array flag arguments" do black = Vips::Operation.call "black", [200, 200] - bytes = Vips::Operation.call "pngsave_buffer", [black], + bytes = Vips::Operation.call "pngsave_buffer", [black], keep: [:icc, :xmp] expect(bytes.length).to be > 100