ruby-vips 2.0.13 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
- data/.github/workflows/test.yml +80 -0
- data/.standard.yml +17 -0
- data/.yardopts +0 -1
- data/CHANGELOG.md +44 -0
- data/Gemfile +3 -1
- data/README.md +45 -47
- data/Rakefile +13 -15
- data/TODO +19 -10
- data/VERSION +1 -1
- data/example/annotate.rb +7 -7
- data/example/connection.rb +26 -0
- data/example/daltonize8.rb +27 -29
- data/example/draw_lines.rb +30 -0
- data/example/example1.rb +5 -6
- data/example/example2.rb +11 -11
- data/example/example3.rb +9 -9
- data/example/example4.rb +8 -8
- data/example/example5.rb +8 -9
- data/example/inheritance_with_refcount.rb +203 -221
- data/example/progress.rb +30 -0
- data/example/thumb.rb +12 -14
- data/example/trim8.rb +7 -7
- data/example/watermark.rb +15 -36
- data/example/wobble.rb +25 -25
- data/lib/ruby-vips.rb +1 -1
- data/lib/vips.rb +473 -338
- data/lib/vips/access.rb +9 -9
- data/lib/vips/align.rb +7 -8
- data/lib/vips/angle.rb +8 -9
- data/lib/vips/angle45.rb +12 -13
- data/lib/vips/bandformat.rb +16 -18
- data/lib/vips/blend_mode.rb +36 -0
- data/lib/vips/coding.rb +11 -12
- data/lib/vips/compass_direction.rb +13 -14
- data/lib/vips/connection.rb +46 -0
- data/lib/vips/direction.rb +7 -8
- data/lib/vips/extend.rb +13 -14
- data/lib/vips/gobject.rb +111 -100
- data/lib/vips/gvalue.rb +243 -237
- data/lib/vips/image.rb +1501 -1338
- data/lib/vips/interesting.rb +10 -11
- data/lib/vips/interpolate.rb +50 -54
- data/lib/vips/interpretation.rb +25 -26
- data/lib/vips/kernel.rb +18 -19
- data/lib/vips/methods.rb +929 -309
- data/lib/vips/mutableimage.rb +154 -0
- data/lib/vips/object.rb +318 -208
- data/lib/vips/operation.rb +467 -320
- data/lib/vips/operationboolean.rb +10 -11
- data/lib/vips/operationcomplex.rb +8 -9
- data/lib/vips/operationcomplex2.rb +6 -7
- data/lib/vips/operationcomplexget.rb +7 -8
- data/lib/vips/operationmath.rb +14 -15
- data/lib/vips/operationmath2.rb +6 -7
- data/lib/vips/operationrelational.rb +11 -12
- data/lib/vips/operationround.rb +7 -8
- data/lib/vips/region.rb +73 -0
- data/lib/vips/size.rb +9 -10
- data/lib/vips/source.rb +88 -0
- data/lib/vips/sourcecustom.rb +89 -0
- data/lib/vips/target.rb +86 -0
- data/lib/vips/targetcustom.rb +77 -0
- data/lib/vips/version.rb +1 -2
- data/ruby-vips.gemspec +29 -20
- metadata +51 -40
- data/.travis.yml +0 -55
- data/install-vips.sh +0 -26
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            2.0 | 
| 1 | 
            +
            2.1.0
         | 
    
        data/example/annotate.rb
    CHANGED
    
    | @@ -1,17 +1,17 @@ | |
| 1 1 | 
             
            #!/usr/bin/ruby
         | 
| 2 2 |  | 
| 3 | 
            -
            require  | 
| 3 | 
            +
            require "vips"
         | 
| 4 4 |  | 
| 5 | 
            -
            im = Vips::Image.new_from_file ARGV[0], : | 
| 5 | 
            +
            im = Vips::Image.new_from_file ARGV[0], access: :sequential
         | 
| 6 6 |  | 
| 7 | 
            -
            left_text = Vips::Image.text "left corner", : | 
| 8 | 
            -
            left = left_text.embed 50, 50, im.width, 150 | 
| 7 | 
            +
            left_text = Vips::Image.text "left corner", dpi: 300
         | 
| 8 | 
            +
            left = left_text.embed 50, 50, im.width, 150
         | 
| 9 9 |  | 
| 10 | 
            -
            right_text = Vips::Image.text "right corner", : | 
| 10 | 
            +
            right_text = Vips::Image.text "right corner", dpi: 300
         | 
| 11 11 | 
             
            right = right_text.embed im.width - right_text.width - 50, 50, im.width, 150
         | 
| 12 12 |  | 
| 13 | 
            -
            footer = (left | right).ifthenelse(0, [255, 0, 0], : | 
| 13 | 
            +
            footer = (left | right).ifthenelse(0, [255, 0, 0], blend: true)
         | 
| 14 14 |  | 
| 15 | 
            -
            im = im.insert footer, 0, im.height, : | 
| 15 | 
            +
            im = im.insert footer, 0, im.height, expand: true
         | 
| 16 16 |  | 
| 17 17 | 
             
            im.write_to_file ARGV[1]
         | 
| @@ -0,0 +1,26 @@ | |
| 1 | 
            +
            #!/usr/bin/ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require "vips"
         | 
| 4 | 
            +
            require "down/http"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # byte_source = File.open ARGV[0], "rb"
         | 
| 7 | 
            +
            # eg. https://images.unsplash.com/photo-1491933382434-500287f9b54b
         | 
| 8 | 
            +
            byte_source = Down::Http.open(ARGV[0])
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            source = Vips::SourceCustom.new
         | 
| 11 | 
            +
            source.on_read do |length|
         | 
| 12 | 
            +
              puts "reading #{length} bytes ..."
         | 
| 13 | 
            +
              byte_source.read length
         | 
| 14 | 
            +
            end
         | 
| 15 | 
            +
            source.on_seek do |offset, whence|
         | 
| 16 | 
            +
              puts "seeking to #{offset}, #{whence}"
         | 
| 17 | 
            +
              byte_source.seek(offset, whence)
         | 
| 18 | 
            +
            end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            byte_target = File.open ARGV[1], "wb"
         | 
| 21 | 
            +
            target = Vips::TargetCustom.new
         | 
| 22 | 
            +
            target.on_write { |chunk| byte_target.write(chunk) }
         | 
| 23 | 
            +
            target.on_finish { byte_target.close }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            image = Vips::Image.new_from_source source, "", access: :sequential
         | 
| 26 | 
            +
            image.write_to_target target, ".jpg"
         | 
    
        data/example/daltonize8.rb
    CHANGED
    
    | @@ -7,20 +7,20 @@ | |
| 7 7 | 
             
            # http://libvips.blogspot.co.uk/2013/05/daltonize-in-ruby-vips-carrierwave-and.html
         | 
| 8 8 | 
             
            # for a discussion of this code
         | 
| 9 9 |  | 
| 10 | 
            -
            require  | 
| 10 | 
            +
            require "vips"
         | 
| 11 11 |  | 
| 12 | 
            -
            #Vips.set_debug true
         | 
| 12 | 
            +
            # Vips.set_debug true
         | 
| 13 13 |  | 
| 14 14 | 
             
            # matrices to convert D65 XYZ to and from bradford cone space
         | 
| 15 15 | 
             
            xyz_to_brad = [
         | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 16 | 
            +
              [0.8951, 0.2664, -0.1614],
         | 
| 17 | 
            +
              [-0.7502, 1.7135, 0.0367],
         | 
| 18 | 
            +
              [0.0389, -0.0685, 1.0296]
         | 
| 19 19 | 
             
            ]
         | 
| 20 20 | 
             
            brad_to_xyz = [
         | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 21 | 
            +
              [0.987, -0.147, 0.16],
         | 
| 22 | 
            +
              [0.432, 0.5184, 0.0493],
         | 
| 23 | 
            +
              [-0.0085, 0.04, 0.968]
         | 
| 24 24 | 
             
            ]
         | 
| 25 25 |  | 
| 26 26 | 
             
            im = Vips::Image.new_from_file ARGV[0]
         | 
| @@ -28,48 +28,46 @@ im = Vips::Image.new_from_file ARGV[0] | |
| 28 28 | 
             
            # remove any alpha channel before processing
         | 
| 29 29 | 
             
            alpha = nil
         | 
| 30 30 | 
             
            if im.bands == 4
         | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 31 | 
            +
              alpha = im[3]
         | 
| 32 | 
            +
              im = im.extract_band 0, n: 3
         | 
| 33 33 | 
             
            end
         | 
| 34 34 |  | 
| 35 35 | 
             
            begin
         | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 36 | 
            +
              # import to XYZ with lcms
         | 
| 37 | 
            +
              # if there's no profile there, we'll fall back to the thing below
         | 
| 38 | 
            +
              xyz = im.icc_import embedded: true, pcs: :xyz
         | 
| 39 39 | 
             
            rescue Vips::Error
         | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 40 | 
            +
              # nope .. use the built-in converter instead
         | 
| 41 | 
            +
              xyz = im.colourspace :xyz
         | 
| 42 42 | 
             
            end
         | 
| 43 43 |  | 
| 44 | 
            -
            brad = xyz.recomb xyz_to_brad | 
| 44 | 
            +
            brad = xyz.recomb xyz_to_brad
         | 
| 45 45 |  | 
| 46 46 | 
             
            # through the Deuteranope matrix
         | 
| 47 47 | 
             
            # we need rows to sum to 1 in Bradford space --- the matrix in the original
         | 
| 48 48 | 
             
            # Python code sums to 1.742
         | 
| 49 49 | 
             
            deut = brad.recomb [
         | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 50 | 
            +
              [1, 0, 0],
         | 
| 51 | 
            +
              [0.7, 0, 0.3],
         | 
| 52 | 
            +
              [0, 0, 1]
         | 
| 53 53 | 
             
            ]
         | 
| 54 54 |  | 
| 55 | 
            -
            xyz = deut.recomb brad_to_xyz | 
| 55 | 
            +
            xyz = deut.recomb brad_to_xyz
         | 
| 56 56 |  | 
| 57 | 
            -
            # .. and back to sRGB | 
| 57 | 
            +
            # .. and back to sRGB
         | 
| 58 58 | 
             
            rgb = xyz.colourspace :srgb
         | 
| 59 59 |  | 
| 60 | 
            -
            # so this is the colour error | 
| 60 | 
            +
            # so this is the colour error
         | 
| 61 61 | 
             
            err = im - rgb
         | 
| 62 62 |  | 
| 63 63 | 
             
            # add the error back to other channels to make a compensated image
         | 
| 64 | 
            -
            im  | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
                [0.7, 0, 1]
         | 
| 68 | 
            -
            ])
         | 
| 64 | 
            +
            im += err.recomb([[0, 0, 0],
         | 
| 65 | 
            +
              [0.7, 1, 0],
         | 
| 66 | 
            +
              [0.7, 0, 1]])
         | 
| 69 67 |  | 
| 70 68 | 
             
            # reattach any alpha we saved above
         | 
| 71 69 | 
             
            if alpha
         | 
| 72 | 
            -
             | 
| 70 | 
            +
              im = im.bandjoin(alpha)
         | 
| 73 71 | 
             
            end
         | 
| 74 72 |  | 
| 75 | 
            -
            im.write_to_file ARGV[1] | 
| 73 | 
            +
            im.write_to_file ARGV[1]
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            #!/usr/bin/ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require "vips"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            # load and stream into memory
         | 
| 6 | 
            +
            image = Vips::Image.new_from_file(ARGV[0], access: :sequential).copy_memory
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            lines = image
         | 
| 11 | 
            +
            (0..1).step 0.01 do |i|
         | 
| 12 | 
            +
              lines = lines.draw_line 255, lines.width * i, 0, 0, lines.height * (1 - i)
         | 
| 13 | 
            +
            end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
         | 
| 16 | 
            +
            puts "non-destructive took #{ending - starting}s"
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            lines = image
         | 
| 21 | 
            +
            lines = lines.mutate do |x|
         | 
| 22 | 
            +
              (0..1).step 0.01 do |i|
         | 
| 23 | 
            +
                x.draw_line! 255, x.width * i, 0, 0, x.height * (1 - i)
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
         | 
| 28 | 
            +
            puts "mutate took #{ending - starting}s"
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            lines.write_to_file ARGV[1]
         | 
    
        data/example/example1.rb
    CHANGED
    
    | @@ -1,12 +1,11 @@ | |
| 1 | 
            -
            #!/usr/bin/ | 
| 1 | 
            +
            #!/usr/bin/ruby
         | 
| 2 2 |  | 
| 3 | 
            -
            require  | 
| 4 | 
            -
            require  | 
| 3 | 
            +
            require "logger"
         | 
| 4 | 
            +
            require "vips"
         | 
| 5 5 |  | 
| 6 | 
            -
            GLib | 
| 6 | 
            +
            GLib.logger.level = Logger::DEBUG
         | 
| 7 7 |  | 
| 8 | 
            -
             | 
| 8 | 
            +
            Vips::Operation.new "black"
         | 
| 9 9 |  | 
| 10 | 
            -
            op = nil
         | 
| 11 10 | 
             
            GC.start
         | 
| 12 11 | 
             
            Vips::Operation.print_all
         | 
    
        data/example/example2.rb
    CHANGED
    
    | @@ -1,34 +1,34 @@ | |
| 1 1 | 
             
            #!/usr/bin/ruby
         | 
| 2 2 |  | 
| 3 | 
            -
            require  | 
| 4 | 
            -
            require  | 
| 3 | 
            +
            require "logger"
         | 
| 4 | 
            +
            require "vips"
         | 
| 5 5 |  | 
| 6 6 | 
             
            puts ""
         | 
| 7 7 | 
             
            puts "starting up:"
         | 
| 8 8 |  | 
| 9 9 | 
             
            # this makes vips keep a list of all active objects which we can print out
         | 
| 10 | 
            -
            Vips | 
| 10 | 
            +
            Vips.leak_set true
         | 
| 11 11 |  | 
| 12 12 | 
             
            # disable the operation cache
         | 
| 13 | 
            -
            Vips | 
| 13 | 
            +
            Vips.cache_set_max 0
         | 
| 14 14 |  | 
| 15 15 | 
             
            # GLib::logger.level = Logger::DEBUG
         | 
| 16 16 |  | 
| 17 17 | 
             
            n = 10000
         | 
| 18 18 |  | 
| 19 19 | 
             
            n.times do |i|
         | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 20 | 
            +
              puts ""
         | 
| 21 | 
            +
              puts "call #{i} ..."
         | 
| 22 | 
            +
              out = Vips::Operation.call "black", [200, 300]
         | 
| 23 | 
            +
              if out.width != 200 || out.height != 300
         | 
| 24 | 
            +
                puts "bad image result from black"
         | 
| 25 | 
            +
              end
         | 
| 26 26 | 
             
            end
         | 
| 27 27 |  | 
| 28 28 | 
             
            puts ""
         | 
| 29 29 | 
             
            puts "after #{n} calls:"
         | 
| 30 30 | 
             
            GC.start
         | 
| 31 | 
            -
            Vips::Object | 
| 31 | 
            +
            Vips::Object.print_all
         | 
| 32 32 |  | 
| 33 33 | 
             
            puts ""
         | 
| 34 34 | 
             
            puts "shutting down:"
         | 
    
        data/example/example3.rb
    CHANGED
    
    | @@ -1,19 +1,19 @@ | |
| 1 1 | 
             
            #!/usr/bin/ruby
         | 
| 2 2 |  | 
| 3 | 
            -
            require  | 
| 3 | 
            +
            require "vips"
         | 
| 4 4 |  | 
| 5 | 
            -
            # this makes vips keep a list of all active objects | 
| 6 | 
            -
            Vips | 
| 5 | 
            +
            # this makes vips keep a list of all active objects
         | 
| 6 | 
            +
            Vips.leak_set true
         | 
| 7 7 |  | 
| 8 8 | 
             
            # disable the operation cache
         | 
| 9 9 | 
             
            # Vips::cache_set_max 0
         | 
| 10 10 |  | 
| 11 11 | 
             
            # turn on debug logging
         | 
| 12 | 
            -
            GLib | 
| 12 | 
            +
            GLib.logger.level = Logger::DEBUG
         | 
| 13 13 |  | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 14 | 
            +
            10.times do |i|
         | 
| 15 | 
            +
              puts "loop #{i} ..."
         | 
| 16 | 
            +
              im = Vips::Image.new_from_file ARGV[0]
         | 
| 17 | 
            +
              im = im.embed 100, 100, 3000, 3000, extend: :mirror
         | 
| 18 | 
            +
              im.write_to_file "x.v"
         | 
| 19 19 | 
             
            end
         | 
    
        data/example/example4.rb
    CHANGED
    
    | @@ -1,18 +1,18 @@ | |
| 1 1 | 
             
            #!/usr/bin/ruby
         | 
| 2 2 |  | 
| 3 | 
            -
            require  | 
| 3 | 
            +
            require "vips"
         | 
| 4 4 |  | 
| 5 | 
            -
            # this makes vips keep a list of all active objects | 
| 6 | 
            -
            Vips | 
| 5 | 
            +
            # this makes vips keep a list of all active objects
         | 
| 6 | 
            +
            Vips.leak_set true
         | 
| 7 7 |  | 
| 8 8 | 
             
            # disable the operation cache
         | 
| 9 | 
            -
            #Vips::cache_set_max 0
         | 
| 9 | 
            +
            # Vips::cache_set_max 0
         | 
| 10 10 |  | 
| 11 11 | 
             
            # turn on debug logging
         | 
| 12 | 
            -
            #Vips.set_debug true
         | 
| 12 | 
            +
            # Vips.set_debug true
         | 
| 13 13 |  | 
| 14 14 | 
             
            ARGV.each do |filename|
         | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 15 | 
            +
              im = Vips::Image.new_from_file filename
         | 
| 16 | 
            +
              profile = im.get_value "icc-profile-data"
         | 
| 17 | 
            +
              puts "profile has #{profile.length} bytes"
         | 
| 18 18 | 
             
            end
         | 
    
        data/example/example5.rb
    CHANGED
    
    | @@ -1,31 +1,30 @@ | |
| 1 1 | 
             
            #!/usr/bin/ruby
         | 
| 2 2 |  | 
| 3 | 
            -
            require  | 
| 3 | 
            +
            require "vips"
         | 
| 4 4 |  | 
| 5 | 
            -
            # this makes vips keep a list of all active objects | 
| 5 | 
            +
            # this makes vips keep a list of all active objects
         | 
| 6 6 | 
             
            # Vips::leak_set true
         | 
| 7 7 |  | 
| 8 8 | 
             
            # disable the operation cache
         | 
| 9 9 | 
             
            # Vips::cache_set_max 0
         | 
| 10 10 |  | 
| 11 11 | 
             
            # turn on debug logging
         | 
| 12 | 
            -
            #Vips.set_debug true
         | 
| 12 | 
            +
            # Vips.set_debug true
         | 
| 13 13 |  | 
| 14 14 | 
             
            if ARGV.length < 2
         | 
| 15 | 
            -
             | 
| 15 | 
            +
              raise "usage: #{$PROGRAM_NAME}: input-file output-file"
         | 
| 16 16 | 
             
            end
         | 
| 17 17 |  | 
| 18 | 
            -
            im = Vips::Image.new_from_file ARGV[0], : | 
| 18 | 
            +
            im = Vips::Image.new_from_file ARGV[0], access: :sequential
         | 
| 19 19 |  | 
| 20 20 | 
             
            im *= [1, 2, 1]
         | 
| 21 21 |  | 
| 22 22 | 
             
            # we want to be able to specify a scale for the convolution mask, so we have to
         | 
| 23 23 | 
             
            # make it ourselves
         | 
| 24 24 | 
             
            # if you are OK with scale=1, you can just pass the array directly to .conv()
         | 
| 25 | 
            -
            mask = Vips::Image.new_from_array [
         | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
                [-1, -1, -1]], 8
         | 
| 25 | 
            +
            mask = Vips::Image.new_from_array [[-1, -1, -1],
         | 
| 26 | 
            +
              [-1, 16, -1],
         | 
| 27 | 
            +
              [-1, -1, -1]], 8
         | 
| 29 28 | 
             
            im = im.conv mask
         | 
| 30 29 |  | 
| 31 30 | 
             
            im.write_to_file ARGV[1]
         | 
| @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            #!/usr/bin/ruby
         | 
| 2 2 |  | 
| 3 | 
            -
            require  | 
| 4 | 
            -
            require  | 
| 3 | 
            +
            require "ffi"
         | 
| 4 | 
            +
            require "forwardable"
         | 
| 5 5 |  | 
| 6 6 | 
             
            # this is really very crude logging
         | 
| 7 7 |  | 
| @@ -10,277 +10,259 @@ $vips_debug = true | |
| 10 10 |  | 
| 11 11 | 
             
            # @private
         | 
| 12 12 | 
             
            def log str
         | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 13 | 
            +
              if $vips_debug
         | 
| 14 | 
            +
                puts str
         | 
| 15 | 
            +
              end
         | 
| 16 16 | 
             
            end
         | 
| 17 17 |  | 
| 18 18 | 
             
            def set_debug debug
         | 
| 19 | 
            -
             | 
| 19 | 
            +
              $vips_debug = debug
         | 
| 20 20 | 
             
            end
         | 
| 21 21 |  | 
| 22 22 | 
             
            module Libc
         | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 23 | 
            +
              extend FFI::Library
         | 
| 24 | 
            +
              ffi_lib FFI::Library::LIBC
         | 
| 25 25 |  | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 26 | 
            +
              attach_function :malloc, [:size_t], :pointer
         | 
| 27 | 
            +
              attach_function :free, [:pointer], :void
         | 
| 28 28 | 
             
            end
         | 
| 29 29 |  | 
| 30 30 | 
             
            module GLib
         | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
                 | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
                 | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
                     | 
| 70 | 
            -
             | 
| 71 | 
            -
                         | 
| 72 | 
            -
             | 
| 73 | 
            -
                                layout :g_type_instance, :pointer,
         | 
| 74 | 
            -
                                       :ref_count, :uint,
         | 
| 75 | 
            -
                                       :qdata, :pointer
         | 
| 76 | 
            -
                            end
         | 
| 77 | 
            -
                        end
         | 
| 78 | 
            -
                    end
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                    # the struct with unref ... manage object lifetime with this
         | 
| 81 | 
            -
                    class ManagedStruct < FFI::ManagedStruct
         | 
| 82 | 
            -
                        include GObjectLayout
         | 
| 83 | 
            -
             | 
| 84 | 
            -
                        def initialize(ptr)
         | 
| 85 | 
            -
                            log "GLib::GObject::ManagedStruct.new: #{ptr}"
         | 
| 86 | 
            -
                            super
         | 
| 87 | 
            -
                        end
         | 
| 88 | 
            -
             | 
| 89 | 
            -
                        def self.release(ptr)
         | 
| 90 | 
            -
                            log "GLib::GObject::ManagedStruct.release: unreffing #{ptr}"
         | 
| 91 | 
            -
                            GLib::g_object_unref(ptr) unless ptr.null?
         | 
| 92 | 
            -
                        end
         | 
| 93 | 
            -
             | 
| 31 | 
            +
              extend FFI::Library
         | 
| 32 | 
            +
              ffi_lib "gobject-2.0"
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              def self.set_log_domain(_domain)
         | 
| 35 | 
            +
                # FIXME: this needs hooking up
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              # we have a set of things we need to inherit in different ways:
         | 
| 39 | 
            +
              #
         | 
| 40 | 
            +
              # - we want to be able to subclass GObject in a simple way
         | 
| 41 | 
            +
              # - the layouts of the nested structs
         | 
| 42 | 
            +
              # - casting between structs which share a base
         | 
| 43 | 
            +
              # - gobject refcounting
         | 
| 44 | 
            +
              #
         | 
| 45 | 
            +
              # the solution is to split the class into four areas which we treat
         | 
| 46 | 
            +
              # differently:
         | 
| 47 | 
            +
              #
         | 
| 48 | 
            +
              # - we have a "wrapper" Ruby class to allow easy subclassing ... this has a
         | 
| 49 | 
            +
              #   @struct member which holds the actual pointer
         | 
| 50 | 
            +
              # - we use "forwardable" to forward the various ffi methods on to the
         | 
| 51 | 
            +
              #   @struct member ... we arrange things so that subclasses do not need to
         | 
| 52 | 
            +
              #   do the forwarding themselves
         | 
| 53 | 
            +
              # - we have two versions of the struct: a plain one which we can use for
         | 
| 54 | 
            +
              #   casting that will not change the refcounts
         | 
| 55 | 
            +
              # - and a managed one with an unref which we just use for .new
         | 
| 56 | 
            +
              # - we separate the struct layout into a separate module to avoid repeating
         | 
| 57 | 
            +
              #   ourselves
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              class GObject
         | 
| 60 | 
            +
                extend Forwardable
         | 
| 61 | 
            +
                extend SingleForwardable
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                def_instance_delegators :@struct, :[], :to_ptr
         | 
| 64 | 
            +
                def_single_delegators :ffi_struct, :ptr
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                # the layout of the GObject struct
         | 
| 67 | 
            +
                module GObjectLayout
         | 
| 68 | 
            +
                  def self.included(base)
         | 
| 69 | 
            +
                    base.class_eval do
         | 
| 70 | 
            +
                      layout :g_type_instance, :pointer,
         | 
| 71 | 
            +
                        :ref_count, :uint,
         | 
| 72 | 
            +
                        :qdata, :pointer
         | 
| 94 73 | 
             
                    end
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                end
         | 
| 95 76 |  | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 77 | 
            +
                # the struct with unref ... manage object lifetime with this
         | 
| 78 | 
            +
                class ManagedStruct < FFI::ManagedStruct
         | 
| 79 | 
            +
                  include GObjectLayout
         | 
| 99 80 |  | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 81 | 
            +
                  def initialize(ptr)
         | 
| 82 | 
            +
                    log "GLib::GObject::ManagedStruct.new: #{ptr}"
         | 
| 83 | 
            +
                    super
         | 
| 84 | 
            +
                  end
         | 
| 104 85 |  | 
| 105 | 
            -
             | 
| 86 | 
            +
                  def self.release(ptr)
         | 
| 87 | 
            +
                    log "GLib::GObject::ManagedStruct.release: unreffing #{ptr}"
         | 
| 88 | 
            +
                    GLib.g_object_unref(ptr) unless ptr.null?
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
                end
         | 
| 106 91 |  | 
| 107 | 
            -
             | 
| 108 | 
            -
             | 
| 109 | 
            -
             | 
| 110 | 
            -
                    # here we use ManagedStruct, not Struct, since this is the ref that will
         | 
| 111 | 
            -
                    # need the unref
         | 
| 112 | 
            -
                    def initialize(ptr)
         | 
| 113 | 
            -
                        log "GLib::GObject.initialize: ptr = #{ptr}"
         | 
| 114 | 
            -
                        @struct = ffi_managed_struct.new(ptr)
         | 
| 115 | 
            -
                    end
         | 
| 92 | 
            +
                # the plain struct ... cast with this
         | 
| 93 | 
            +
                class Struct < FFI::Struct
         | 
| 94 | 
            +
                  include GObjectLayout
         | 
| 116 95 |  | 
| 117 | 
            -
             | 
| 118 | 
            -
                     | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 96 | 
            +
                  def initialize(ptr)
         | 
| 97 | 
            +
                    log "GLib::GObject::Struct.new: #{ptr}"
         | 
| 98 | 
            +
                    super
         | 
| 99 | 
            +
                  end
         | 
| 100 | 
            +
                end
         | 
| 121 101 |  | 
| 122 | 
            -
             | 
| 123 | 
            -
             | 
| 124 | 
            -
             | 
| 125 | 
            -
             | 
| 126 | 
            -
             | 
| 102 | 
            +
                # don't allow ptr == nil, we never want to allocate a GObject struct
         | 
| 103 | 
            +
                # ourselves, we just want to wrap GLib-allocated GObjects
         | 
| 104 | 
            +
                #
         | 
| 105 | 
            +
                # here we use ManagedStruct, not Struct, since this is the ref that will
         | 
| 106 | 
            +
                # need the unref
         | 
| 107 | 
            +
                def initialize(ptr)
         | 
| 108 | 
            +
                  log "GLib::GObject.initialize: ptr = #{ptr}"
         | 
| 109 | 
            +
                  @struct = ffi_managed_struct.new(ptr)
         | 
| 110 | 
            +
                end
         | 
| 127 111 |  | 
| 128 | 
            -
             | 
| 129 | 
            -
             | 
| 130 | 
            -
             | 
| 131 | 
            -
             | 
| 112 | 
            +
                # access to the cast struct for this class
         | 
| 113 | 
            +
                def ffi_struct
         | 
| 114 | 
            +
                  self.class.ffi_struct
         | 
| 115 | 
            +
                end
         | 
| 132 116 |  | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 117 | 
            +
                class << self
         | 
| 118 | 
            +
                  def ffi_struct
         | 
| 119 | 
            +
                    const_get(:Struct)
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
                end
         | 
| 138 122 |  | 
| 123 | 
            +
                # access to the lifetime managed struct for this class
         | 
| 124 | 
            +
                def ffi_managed_struct
         | 
| 125 | 
            +
                  self.class.ffi_managed_struct
         | 
| 139 126 | 
             
                end
         | 
| 140 127 |  | 
| 141 | 
            -
                 | 
| 142 | 
            -
             | 
| 128 | 
            +
                class << self
         | 
| 129 | 
            +
                  def ffi_managed_struct
         | 
| 130 | 
            +
                    const_get(:ManagedStruct)
         | 
| 131 | 
            +
                  end
         | 
| 132 | 
            +
                end
         | 
| 133 | 
            +
              end
         | 
| 143 134 |  | 
| 135 | 
            +
              # :gtype will usually be 64-bit, but will be 32-bit on 32-bit Windows
         | 
| 136 | 
            +
              typedef :ulong, :GType
         | 
| 144 137 | 
             
            end
         | 
| 145 138 |  | 
| 146 139 | 
             
            module Vips
         | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 140 | 
            +
              extend FFI::Library
         | 
| 141 | 
            +
              ffi_lib "vips"
         | 
| 149 142 |  | 
| 150 | 
            -
             | 
| 151 | 
            -
             | 
| 143 | 
            +
              LOG_DOMAIN = "VIPS"
         | 
| 144 | 
            +
              GLib.set_log_domain(LOG_DOMAIN)
         | 
| 152 145 |  | 
| 153 | 
            -
             | 
| 154 | 
            -
             | 
| 146 | 
            +
              # need to repeat this
         | 
| 147 | 
            +
              typedef :ulong, :GType
         | 
| 155 148 |  | 
| 156 | 
            -
             | 
| 157 | 
            -
             | 
| 149 | 
            +
              attach_function :vips_init, [:string], :int
         | 
| 150 | 
            +
              attach_function :vips_shutdown, [], :void
         | 
| 158 151 |  | 
| 159 | 
            -
             | 
| 160 | 
            -
             | 
| 152 | 
            +
              attach_function :vips_error_buffer, [], :string
         | 
| 153 | 
            +
              attach_function :vips_error_clear, [], :void
         | 
| 161 154 |  | 
| 162 | 
            -
             | 
| 163 | 
            -
             | 
| 164 | 
            -
             | 
| 165 | 
            -
             | 
| 166 | 
            -
             | 
| 155 | 
            +
              def self.get_error
         | 
| 156 | 
            +
                errstr = Vips.vips_error_buffer
         | 
| 157 | 
            +
                Vips.vips_error_clear
         | 
| 158 | 
            +
                errstr
         | 
| 159 | 
            +
              end
         | 
| 167 160 |  | 
| 168 | 
            -
             | 
| 169 | 
            -
             | 
| 170 | 
            -
             | 
| 171 | 
            -
             | 
| 161 | 
            +
              if Vips.vips_init($0) != 0
         | 
| 162 | 
            +
                puts Vips.get_error
         | 
| 163 | 
            +
                exit 1
         | 
| 164 | 
            +
              end
         | 
| 172 165 |  | 
| 173 | 
            -
             | 
| 174 | 
            -
             | 
| 175 | 
            -
             | 
| 166 | 
            +
              at_exit do
         | 
| 167 | 
            +
                Vips.vips_shutdown
         | 
| 168 | 
            +
              end
         | 
| 176 169 |  | 
| 177 | 
            -
             | 
| 178 | 
            -
             | 
| 179 | 
            -
             | 
| 180 | 
            -
                def self.showall
         | 
| 181 | 
            -
                    if $vips_debug
         | 
| 182 | 
            -
                        GC.start
         | 
| 183 | 
            -
                        vips_object_print_all
         | 
| 184 | 
            -
                    end
         | 
| 185 | 
            -
                end
         | 
| 170 | 
            +
              attach_function :vips_object_print_all, [], :void
         | 
| 171 | 
            +
              attach_function :vips_leak_set, [:int], :void
         | 
| 186 172 |  | 
| 173 | 
            +
              def self.showall
         | 
| 187 174 | 
             
                if $vips_debug
         | 
| 188 | 
            -
             | 
| 175 | 
            +
                  GC.start
         | 
| 176 | 
            +
                  vips_object_print_all
         | 
| 189 177 | 
             
                end
         | 
| 190 | 
            -
             | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 194 | 
            -
             | 
| 195 | 
            -
             | 
| 196 | 
            -
             | 
| 197 | 
            -
             | 
| 198 | 
            -
             | 
| 199 | 
            -
             | 
| 200 | 
            -
             | 
| 201 | 
            -
             | 
| 202 | 
            -
             | 
| 203 | 
            -
             | 
| 204 | 
            -
             | 
| 205 | 
            -
             | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 208 | 
            -
             | 
| 209 | 
            -
                         | 
| 178 | 
            +
              end
         | 
| 179 | 
            +
             | 
| 180 | 
            +
              if $vips_debug
         | 
| 181 | 
            +
                vips_leak_set 1
         | 
| 182 | 
            +
              end
         | 
| 183 | 
            +
             | 
| 184 | 
            +
              class VipsObject < GLib::GObject
         | 
| 185 | 
            +
                # the layout of the VipsObject struct
         | 
| 186 | 
            +
                module VipsObjectLayout
         | 
| 187 | 
            +
                  def self.included(base)
         | 
| 188 | 
            +
                    base.class_eval do
         | 
| 189 | 
            +
                      # don't actually need most of these, remove them later
         | 
| 190 | 
            +
                      layout :parent, GLib::GObject::Struct,
         | 
| 191 | 
            +
                        :constructed, :int,
         | 
| 192 | 
            +
                        :static_object, :int,
         | 
| 193 | 
            +
                        :argument_table, :pointer,
         | 
| 194 | 
            +
                        :nickname, :string,
         | 
| 195 | 
            +
                        :description, :string,
         | 
| 196 | 
            +
                        :preclose, :int,
         | 
| 197 | 
            +
                        :close, :int,
         | 
| 198 | 
            +
                        :postclose, :int,
         | 
| 199 | 
            +
                        :local_memory, :size_t
         | 
| 210 200 | 
             
                    end
         | 
| 211 | 
            -
             | 
| 212 | 
            -
                    class Struct < GLib::GObject::Struct
         | 
| 213 | 
            -
                        include VipsObjectLayout
         | 
| 214 | 
            -
             | 
| 215 | 
            -
                        def initialize(ptr)
         | 
| 216 | 
            -
                            log "Vips::VipsObject::Struct.new: #{ptr}"
         | 
| 217 | 
            -
                            super
         | 
| 218 | 
            -
                        end
         | 
| 219 | 
            -
             | 
| 220 | 
            -
                    end
         | 
| 221 | 
            -
             | 
| 222 | 
            -
                    class ManagedStruct < GLib::GObject::ManagedStruct
         | 
| 223 | 
            -
                        include VipsObjectLayout
         | 
| 224 | 
            -
             | 
| 225 | 
            -
                        def initialize(ptr)
         | 
| 226 | 
            -
                            log "Vips::VipsObject::ManagedStruct.new: #{ptr}"
         | 
| 227 | 
            -
                            super
         | 
| 228 | 
            -
                        end
         | 
| 229 | 
            -
             | 
| 230 | 
            -
                    end
         | 
| 231 | 
            -
             | 
| 201 | 
            +
                  end
         | 
| 232 202 | 
             
                end
         | 
| 233 203 |  | 
| 234 | 
            -
                class  | 
| 235 | 
            -
             | 
| 236 | 
            -
                    # the layout of the VipsImage struct
         | 
| 237 | 
            -
                    module VipsImageLayout
         | 
| 238 | 
            -
                        def self.included(base)
         | 
| 239 | 
            -
                            base.class_eval do
         | 
| 240 | 
            -
                                layout :parent, VipsObject::Struct
         | 
| 241 | 
            -
                                # rest opaque
         | 
| 242 | 
            -
                            end
         | 
| 243 | 
            -
                        end
         | 
| 244 | 
            -
                    end
         | 
| 204 | 
            +
                class Struct < GLib::GObject::Struct
         | 
| 205 | 
            +
                  include VipsObjectLayout
         | 
| 245 206 |  | 
| 246 | 
            -
             | 
| 247 | 
            -
             | 
| 207 | 
            +
                  def initialize(ptr)
         | 
| 208 | 
            +
                    log "Vips::VipsObject::Struct.new: #{ptr}"
         | 
| 209 | 
            +
                    super
         | 
| 210 | 
            +
                  end
         | 
| 211 | 
            +
                end
         | 
| 248 212 |  | 
| 249 | 
            -
             | 
| 250 | 
            -
             | 
| 251 | 
            -
                            super
         | 
| 252 | 
            -
                        end
         | 
| 213 | 
            +
                class ManagedStruct < GLib::GObject::ManagedStruct
         | 
| 214 | 
            +
                  include VipsObjectLayout
         | 
| 253 215 |  | 
| 216 | 
            +
                  def initialize(ptr)
         | 
| 217 | 
            +
                    log "Vips::VipsObject::ManagedStruct.new: #{ptr}"
         | 
| 218 | 
            +
                    super
         | 
| 219 | 
            +
                  end
         | 
| 220 | 
            +
                end
         | 
| 221 | 
            +
              end
         | 
| 222 | 
            +
             | 
| 223 | 
            +
              class VipsImage < VipsObject
         | 
| 224 | 
            +
                # the layout of the VipsImage struct
         | 
| 225 | 
            +
                module VipsImageLayout
         | 
| 226 | 
            +
                  def self.included(base)
         | 
| 227 | 
            +
                    base.class_eval do
         | 
| 228 | 
            +
                      layout :parent, VipsObject::Struct
         | 
| 229 | 
            +
                      # rest opaque
         | 
| 254 230 | 
             
                    end
         | 
| 231 | 
            +
                  end
         | 
| 232 | 
            +
                end
         | 
| 255 233 |  | 
| 256 | 
            -
             | 
| 257 | 
            -
             | 
| 258 | 
            -
             | 
| 259 | 
            -
                        def initialize(ptr)
         | 
| 260 | 
            -
                            log "Vips::VipsImage::ManagedStruct.new: #{ptr}"
         | 
| 261 | 
            -
                            super
         | 
| 262 | 
            -
                        end
         | 
| 234 | 
            +
                class Struct < VipsObject::Struct
         | 
| 235 | 
            +
                  include VipsImageLayout
         | 
| 263 236 |  | 
| 264 | 
            -
             | 
| 237 | 
            +
                  def initialize(ptr)
         | 
| 238 | 
            +
                    log "Vips::VipsImage::Struct.new: #{ptr}"
         | 
| 239 | 
            +
                    super
         | 
| 240 | 
            +
                  end
         | 
| 241 | 
            +
                end
         | 
| 265 242 |  | 
| 266 | 
            -
             | 
| 267 | 
            -
             | 
| 268 | 
            -
                    end
         | 
| 243 | 
            +
                class ManagedStruct < VipsObject::ManagedStruct
         | 
| 244 | 
            +
                  include VipsImageLayout
         | 
| 269 245 |  | 
| 246 | 
            +
                  def initialize(ptr)
         | 
| 247 | 
            +
                    log "Vips::VipsImage::ManagedStruct.new: #{ptr}"
         | 
| 248 | 
            +
                    super
         | 
| 249 | 
            +
                  end
         | 
| 270 250 | 
             
                end
         | 
| 271 251 |  | 
| 272 | 
            -
                 | 
| 252 | 
            +
                def self.new_partial
         | 
| 253 | 
            +
                  VipsImage.new(Vips.vips_image_new)
         | 
| 254 | 
            +
                end
         | 
| 255 | 
            +
              end
         | 
| 273 256 |  | 
| 257 | 
            +
              attach_function :vips_image_new, [], :pointer
         | 
| 274 258 | 
             
            end
         | 
| 275 259 |  | 
| 276 260 | 
             
            puts "creating image"
         | 
| 277 | 
            -
            begin
         | 
| 278 | 
            -
                x = Vips::VipsImage.new_partial 
         | 
| 279 | 
            -
                puts "x = #{x}"
         | 
| 280 | 
            -
                puts ""
         | 
| 281 | 
            -
                puts "x[:parent] = #{x[:parent]}"
         | 
| 282 | 
            -
                puts ""
         | 
| 283 | 
            -
                puts "x[:parent][:description] = #{x[:parent][:description]}"
         | 
| 284 | 
            -
                puts ""
         | 
| 285 | 
            -
            end
         | 
| 286 261 |  | 
| 262 | 
            +
            x = Vips::VipsImage.new_partial
         | 
| 263 | 
            +
            puts "x = #{x}"
         | 
| 264 | 
            +
            puts ""
         | 
| 265 | 
            +
            puts "x[:parent] = #{x[:parent]}"
         | 
| 266 | 
            +
            puts ""
         | 
| 267 | 
            +
            puts "x[:parent][:description] = #{x[:parent][:description]}"
         | 
| 268 | 
            +
            puts ""
         |