ffi-gmagick 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +56 -0
- data/Rakefile +12 -0
- data/ffi-gmagick.gemspec +30 -0
- data/lib/ffi/gmagick/image.rb +253 -0
- data/lib/ffi/gmagick/struct.rb +16 -0
- data/lib/ffi/gmagick/version.rb +5 -0
- data/lib/ffi/gmagick.rb +138 -0
- data/test/image_test.rb +79 -0
- data/test/test_helper.rb +5 -0
- metadata +106 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c44392e5977b3e429dc8c977131f5223cf391554
|
4
|
+
data.tar.gz: 4e169e7a89e4ece9154c8a930cdf53ad50104870
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a28e768fd12e76ccc36f0d193b54f5010e660add60ba10a241a65e70f8d21327ee490681e93a924fbb8254c72b932054d5d931917c94ab89de8d5227351f55e8
|
7
|
+
data.tar.gz: 598a9f18be1265c25ec7a23ce90d6dfc5c30ec68ab59f5db41d82f8f3790939217c9619d4056aa48171d6d2368cb07dcc44779fe49278030ed0b2cf037d88187
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Richard Hurt
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# FFI::GMagick
|
2
|
+
|
3
|
+
FFI wrapper for the GraphicsMagick image processing library.
|
4
|
+
|
5
|
+
## Introduction
|
6
|
+
|
7
|
+
This Gem provides an FFI wrapper for the GraphicsMagick image processing library. All of the
|
8
|
+
other *Magick Gems I found either only worked with ImageMagick or were simply wrappers around
|
9
|
+
the command line interfaces. These are great Gems but I needed to work with images in RAM
|
10
|
+
and not hit the hard drive at all. So, I created this Gem to allow me to work with images
|
11
|
+
completely in RAM without touching the file system at all.
|
12
|
+
|
13
|
+
[![Build Status](https://travis-ci.org/rnhurt/ffi-gmagick.png)](https://travis-ci.org/rnhurt/ffi-gmagick)
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Add this line to your application's Gemfile:
|
18
|
+
|
19
|
+
gem 'ffi-gmagick'
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
$ gem install ffi-gmagick
|
28
|
+
|
29
|
+
You also must have a recent version of GraphicsMagick installed and the library in your
|
30
|
+
systems load path. Don't worry about the load path, most installers do that for you.
|
31
|
+
|
32
|
+
## Usage
|
33
|
+
|
34
|
+
Basic usage is as following:
|
35
|
+
|
36
|
+
require 'ffi/gmagick'
|
37
|
+
|
38
|
+
WATERMARK = FFI::GMagick::Image.new
|
39
|
+
WATERMARK.from_blob(File.open("watermark.png").read)
|
40
|
+
|
41
|
+
image = FFI::GMagick::Image.new
|
42
|
+
image.from_blob(File.open("./my_picture.jpg").read)
|
43
|
+
|
44
|
+
new_thumbnail = image.thumbnail(100, 100, true)
|
45
|
+
new_thumbnail.compose(WATERMARK)
|
46
|
+
|
47
|
+
new_thumbnail.to_file("./my_thumb.jpg")
|
48
|
+
|
49
|
+
|
50
|
+
## Contributing
|
51
|
+
|
52
|
+
1. Fork it
|
53
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
54
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
55
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
56
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/ffi-gmagick.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ffi/gmagick/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ffi-gmagick"
|
8
|
+
spec.version = FFI::GMagick::VERSION
|
9
|
+
spec.authors = ["Richard Hurt"]
|
10
|
+
spec.email = ["rnhurt@gmail.com"]
|
11
|
+
spec.summary = "Use the C GraphicsMagick bindings to provide a Ruby interface"
|
12
|
+
spec.description = "This is not a simple 'Ruby'-like implementation. It is more of a
|
13
|
+
raw 'C' implementation. As such, it may be a bit more difficult to
|
14
|
+
work with than something like rmagick, but it should perform just as
|
15
|
+
well."
|
16
|
+
spec.homepage = "https://github.com/rnhurt/ffi-gmagick"
|
17
|
+
spec.license = "MIT"
|
18
|
+
|
19
|
+
spec.files = `git ls-files`.split($/)
|
20
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.requirements << 'libGraphicsMagick, v1.3.18'
|
25
|
+
|
26
|
+
spec.add_runtime_dependency 'ffi', '~> 1.9'
|
27
|
+
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
29
|
+
spec.add_development_dependency "rake"
|
30
|
+
end
|
@@ -0,0 +1,253 @@
|
|
1
|
+
module FFI
|
2
|
+
module GMagick
|
3
|
+
class Image
|
4
|
+
# This is a convenience class that takes care of most of the messy work
|
5
|
+
# of dealing with the raw FFI::GMagick interface.
|
6
|
+
#
|
7
|
+
# Basic usage is as following:
|
8
|
+
#
|
9
|
+
# require 'ffi/gmagick'
|
10
|
+
#
|
11
|
+
# WATERMARK = FFI::GMagick::Image.new
|
12
|
+
# WATERMARK.from_blob(File.open("watermark.png").read)
|
13
|
+
#
|
14
|
+
# image = FFI::GMagick::Image.new
|
15
|
+
# image.from_blob(File.open("./my_picture.jpg").read)
|
16
|
+
#
|
17
|
+
# new_thumbnail = image.thumbnail(100, 100, true)
|
18
|
+
# new_thumbnail.compose(WATERMARK)
|
19
|
+
#
|
20
|
+
# new_thumbnail.to_file("./my_thumb.jpg")
|
21
|
+
#
|
22
|
+
# This will open two images, a picture and a watermark, create a square
|
23
|
+
# thumbnail and apply the watermark in the center of the image.
|
24
|
+
attr_accessor :wand, :status
|
25
|
+
|
26
|
+
def initialize(old_wand=nil)
|
27
|
+
if old_wand
|
28
|
+
@wand = FFI::GMagick.CloneMagickWand( old_wand )
|
29
|
+
else
|
30
|
+
@wand ||= FFI::GMagick.NewMagickWand
|
31
|
+
end
|
32
|
+
@status = 1
|
33
|
+
end
|
34
|
+
|
35
|
+
# Read image data from a BLOB
|
36
|
+
def from_blob(blob)
|
37
|
+
@status = FFI::GMagick.MagickReadImageBlob( @wand, blob, blob.bytesize)
|
38
|
+
|
39
|
+
# Note: PDF images don't report proper bytesize
|
40
|
+
return blob.bytesize
|
41
|
+
end
|
42
|
+
|
43
|
+
# Write image data to a BLOB
|
44
|
+
def to_blob
|
45
|
+
output = nil
|
46
|
+
FFI::MemoryPointer.new(:ulong, 64) do |length|
|
47
|
+
blobout = FFI::GMagick.MagickWriteImageBlob( @wand, length )
|
48
|
+
output = blobout.read_string(length.read_long)
|
49
|
+
end
|
50
|
+
return output
|
51
|
+
end
|
52
|
+
|
53
|
+
# Read image data from a filename
|
54
|
+
def from_file(filename)
|
55
|
+
blob = File.open(filename).read
|
56
|
+
self.from_blob(blob)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Write image data to a filename
|
60
|
+
def to_file(filename)
|
61
|
+
@status = FFI::GMagick.MagickWriteImage( @wand, filename )
|
62
|
+
end
|
63
|
+
|
64
|
+
# Return the width of the image in pixels
|
65
|
+
def width
|
66
|
+
FFI::GMagick.MagickGetImageWidth( @wand ).to_f
|
67
|
+
end
|
68
|
+
alias_method :cols, :width
|
69
|
+
|
70
|
+
# Return the height of the image in pixels
|
71
|
+
def height
|
72
|
+
FFI::GMagick.MagickGetImageHeight( @wand ).to_f
|
73
|
+
end
|
74
|
+
alias_method :rows, :height
|
75
|
+
|
76
|
+
# Return the size of the image in bytes
|
77
|
+
def size
|
78
|
+
FFI::GMagick.MagickGetImageSize( @wand )
|
79
|
+
end
|
80
|
+
alias_method :length, :size
|
81
|
+
|
82
|
+
# Return the image format
|
83
|
+
def format
|
84
|
+
FFI::GMagick.MagickGetImageFormat( @wand )
|
85
|
+
end
|
86
|
+
|
87
|
+
# Set the image format
|
88
|
+
def format=(format)
|
89
|
+
FFI::GMagick.MagickSetImageFormat( @wand, format )
|
90
|
+
end
|
91
|
+
|
92
|
+
# Negate the colors in the specified channel
|
93
|
+
def negate_channel(channel, gray=0)
|
94
|
+
@status = FFI::GMagick.MagickNegateImageChannel( @wand, channel, gray )
|
95
|
+
end
|
96
|
+
|
97
|
+
# Set the gamma value for the specified channel
|
98
|
+
def gamma_channel(channel, gamma=0)
|
99
|
+
@status = FFI::GMagick.MagickGammaImageChannel( @wand, channel, gamma )
|
100
|
+
end
|
101
|
+
|
102
|
+
# Return the value of the named attribute
|
103
|
+
def attribute(name)
|
104
|
+
FFI::GMagick.MagickGetImageAttribute( @wand, name )
|
105
|
+
end
|
106
|
+
|
107
|
+
# Return the image type
|
108
|
+
def type
|
109
|
+
FFI::GMagick.MagickGetImageType( @wand )
|
110
|
+
end
|
111
|
+
|
112
|
+
# Set the image type to one of the valid
|
113
|
+
# <a href="http://www.graphicsmagick.org/api/types.html#imagetype">image types</a>
|
114
|
+
def type=(type)
|
115
|
+
@status = FFI::GMagick.MagickSetImageType( @wand, type )
|
116
|
+
end
|
117
|
+
|
118
|
+
# Return the colorspace
|
119
|
+
def colorspace
|
120
|
+
FFI::GMagick.MagickGetImageColorspace( @wand )
|
121
|
+
end
|
122
|
+
alias_method :colormodel, :colorspace
|
123
|
+
|
124
|
+
# Set the image colorspace to one of the valid
|
125
|
+
# <a href="http://www.graphicsmagick.org/api/types.html#colorspacetype">colorspace types</a>.
|
126
|
+
def colorspace=(colorspace)
|
127
|
+
FFI::GMagick.MagickSetImageColorspace( @wand, colorspace )
|
128
|
+
end
|
129
|
+
alias_method :colormodel=, :colorspace=
|
130
|
+
|
131
|
+
# Return the information for a specific profile in the image
|
132
|
+
def profile(name="ICC")
|
133
|
+
output = nil
|
134
|
+
FFI::MemoryPointer.new(:ulong, 64) do |length|
|
135
|
+
blobout = FFI::GMagick.MagickGetImageProfile( @wand, name, length )
|
136
|
+
output = blobout.read_string(length.read_long)
|
137
|
+
end
|
138
|
+
return output
|
139
|
+
end
|
140
|
+
|
141
|
+
# Add a profile to this image
|
142
|
+
def add_profile(name, profile)
|
143
|
+
@status = FFI::GMagick.MagickProfileImage( @wand, name, profile, profile.size )
|
144
|
+
raise "invalid profile" unless 1 == status
|
145
|
+
end
|
146
|
+
|
147
|
+
# Return the interlace information as one of the valid
|
148
|
+
# <a href="http://www.graphicsmagick.org/api/types.html#interlacetype">interlace types</a>.
|
149
|
+
def interlace
|
150
|
+
FFI::GMagick.MagickGetImageInterlaceScheme( @wand )
|
151
|
+
end
|
152
|
+
|
153
|
+
# Set the interlace information to one of the valid
|
154
|
+
# <a href="http://www.graphicsmagick.org/api/types.html#interlacetype">interlace types</a>.
|
155
|
+
def interlace=(interlace)
|
156
|
+
@status = FFI::GMagick.MagickSetImageInterlaceScheme( @wand, interlace )
|
157
|
+
raise "invalid interlace type" unless 1 == status
|
158
|
+
end
|
159
|
+
|
160
|
+
# Strip the image of extra data (comments, profiles, etc.)
|
161
|
+
def strip
|
162
|
+
@status = FFI::GMagick.MagickStripImage( @wand )
|
163
|
+
end
|
164
|
+
|
165
|
+
def quality=(quality)
|
166
|
+
@status = FFI::GMagick.MagickSetCompressionQuality( @wand, quality )
|
167
|
+
end
|
168
|
+
|
169
|
+
# Resize the image to the desired dimensions using various
|
170
|
+
# <a href="http://www.graphicsmagick.org/api/types.html#filtertypes">filters</a>.
|
171
|
+
def resize(width, height, filter=:BoxFilter, blur=1.0)
|
172
|
+
@status = FFI::GMagick.MagickResizeImage( @wand, width, height, filter, blur )
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
# Crop the image to the desired dimensions. If you don't provide an
|
177
|
+
# X,Y offset the crop will be centered.
|
178
|
+
def crop(width, height, x=nil, y=nil)
|
179
|
+
if x.nil? || y.nil?
|
180
|
+
old_width = self.width
|
181
|
+
old_height = self.height
|
182
|
+
|
183
|
+
x = (old_width / 2) - (width / 2)
|
184
|
+
y = (old_height / 2) - (height / 2)
|
185
|
+
end
|
186
|
+
|
187
|
+
@status = FFI::GMagick.MagickCropImage( @wand, width, height, x, y )
|
188
|
+
end
|
189
|
+
|
190
|
+
# A convenience method. Resize the image to fit within the specified
|
191
|
+
# dimensions while retaining the aspect ratio of the original image.
|
192
|
+
# If necessary, crop the image in the larger dimension.
|
193
|
+
#
|
194
|
+
# Returns a new image object
|
195
|
+
def resize_to_fill(new_width, new_height=nil)
|
196
|
+
new_height ||= new_width
|
197
|
+
local_image = FFI::GMagick::Image.new(@wand)
|
198
|
+
|
199
|
+
if new_width != local_image.width || new_height != local_image.height
|
200
|
+
scale = [new_width/local_image.width.to_f, new_height/local_image.height.to_f].max
|
201
|
+
local_image.resize(scale*width+0.5, scale*height+0.5)
|
202
|
+
end
|
203
|
+
|
204
|
+
if new_width != local_image.width || new_height != local_image.height
|
205
|
+
local_image.crop(new_width, new_height)
|
206
|
+
end
|
207
|
+
|
208
|
+
return local_image
|
209
|
+
end
|
210
|
+
|
211
|
+
# A convenience method. Resize the image to fit within the
|
212
|
+
# specified dimensions while retaining the original aspect
|
213
|
+
# ratio. The image may be shorter or narrower than specified
|
214
|
+
# in the smaller dimension but will not be larger than the
|
215
|
+
# specified values.
|
216
|
+
#
|
217
|
+
# Returns a new image object
|
218
|
+
def resize_to_fit(width, height=nil)
|
219
|
+
height ||= width
|
220
|
+
geometry = "#{width}x#{height}>"
|
221
|
+
local_wand = FFI::GMagick.MagickTransformImage( @wand, "", geometry )
|
222
|
+
return FFI::GMagick::Image.new(local_wand)
|
223
|
+
end
|
224
|
+
|
225
|
+
# Composites an Image (such as a watermark) with this one using various
|
226
|
+
# <a href="http://www.graphicsmagick.org/api/types.html#compositeoperator">composite operators</a>.
|
227
|
+
#
|
228
|
+
# If you don't provide an X,Y offset then the operation with be centered on the base image.
|
229
|
+
def compose(image, operator=:OverCompositeOp, x=nil, y=nil)
|
230
|
+
if x.nil? || y.nil?
|
231
|
+
width = self.width
|
232
|
+
height = self.height
|
233
|
+
new_width = image.width
|
234
|
+
new_height = image.height
|
235
|
+
|
236
|
+
x = (width / 2) - (new_width / 2)
|
237
|
+
y = (height / 2) - (new_height / 2)
|
238
|
+
end
|
239
|
+
@status = FFI::GMagick.MagickCompositeImage(@wand, image.wand, operator, x, y)
|
240
|
+
end
|
241
|
+
|
242
|
+
# Is this a valid image
|
243
|
+
def valid?
|
244
|
+
@status == 1
|
245
|
+
end
|
246
|
+
|
247
|
+
# Return the copywrite notification for GraphicsMagick
|
248
|
+
def copywrite
|
249
|
+
FFI::GMagick.MagickGetCopyright
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module FFI
|
2
|
+
module GMagick
|
3
|
+
class PixelPacket < FFI::Struct
|
4
|
+
layout :red, :uint,
|
5
|
+
:green, :uint,
|
6
|
+
:blue, :uint,
|
7
|
+
:opacity, :uint
|
8
|
+
end
|
9
|
+
|
10
|
+
class ImageInfo < FFI::Struct
|
11
|
+
layout :adjoin, :uint,
|
12
|
+
:antialias, :uint,
|
13
|
+
:background_color, PixelPacket.ptr
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/ffi/gmagick.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
require "ffi"
|
2
|
+
require "ffi/gmagick/image"
|
3
|
+
require "ffi/gmagick/version"
|
4
|
+
|
5
|
+
module FFI
|
6
|
+
# FFI::GMagick is an FFI binding for the GraphicsMagick MagickWand image library.
|
7
|
+
# Basic usage is as following:
|
8
|
+
#
|
9
|
+
# require 'ffi/gmagick'
|
10
|
+
#
|
11
|
+
# wand = FFI::GMagick.NewMagickWand
|
12
|
+
# FFI::GMagick.MagickReadImage( wand, "./test.jpg")
|
13
|
+
#
|
14
|
+
# FFI::GMagick.MagickSetImageFormat( wand, "PNG" )
|
15
|
+
#
|
16
|
+
# FFI::GMagick.MagickResizeImage( wand, 500, 500, :UndefinedFilter, 0.0)
|
17
|
+
# FFI::GMagick.MagickWriteImage( wand, "./test-out.jpg" )
|
18
|
+
#
|
19
|
+
# For more information on commands and syntax see http://www.graphicsmagick.org/wand/magick_wand.html
|
20
|
+
#
|
21
|
+
module GMagick
|
22
|
+
extend FFI::Library
|
23
|
+
ffi_lib "GraphicsMagickWand"
|
24
|
+
|
25
|
+
enum :interlace_type, [:UndefinedInterlace, :NoInterlace, :LineInterlace, :PlaneInterlace, :PartitionInterlace]
|
26
|
+
|
27
|
+
enum :filter_type, [:UndefinedFilter, :PointFilter, :BoxFilter, :TriangleFilter,
|
28
|
+
:HermiteFilter, :HanningFilter, :HammingFilter, :BlackmanFilter,
|
29
|
+
:GaussianFilter, :QuadraticFilter, :CubicFilter, :CatromFilter,
|
30
|
+
:MitchellFilter, :LanczosFilter, :BesselFilter, :SincFilter]
|
31
|
+
enum :channel_type, [:UndefinedChannel, :RedChannel, :CyanChannel, :GreenChannel, :MagentaChannel,
|
32
|
+
:BlueChannel, :YellowChannel, :OpacityChannel, :BlackChannel, :MatteChannel,
|
33
|
+
:AllChannels, :GrayChannel]
|
34
|
+
|
35
|
+
enum :image_type, [:UndefinedType, :BilevelType, :GrayscaleType, :PaletteType, :PaletteMatteType,
|
36
|
+
:TrueColorType, :TrueColorMatteType, :ColorSeparationType]
|
37
|
+
|
38
|
+
enum :colorspace, [:UndefinedColorspace, :RGBColorspace, :GRAYColorspace,
|
39
|
+
:TransparentColorspace, :OHTAColorspace, :XYZColorspace, :YCCColorspace,
|
40
|
+
:YIQColorspace, :YPbPrColorspace, :YUVColorspace, :CMYKColorspace,
|
41
|
+
:sRGBColorspace, :HSLColorspace, :HWBColorspace, :LABColorspace,
|
42
|
+
:CineonLogRGBColorspace, :Rec601LumaColorspace, :Rec601YCbCrColorspace,
|
43
|
+
:Rec709LumaColorspace, :Rec709YCbCrColorspace]
|
44
|
+
|
45
|
+
enum :gravity_type, [:ForgetGravity, :NorthWestGravity, :NorthGravity, :NorthEastGravity,
|
46
|
+
:WestGravity, :CenterGravity, :EastGravity, :SouthWestGravity,
|
47
|
+
:SouthGravity, :SouthEastGravity]
|
48
|
+
|
49
|
+
enum :composite_operator, [:UndefinedCompositeOp, :OverCompositeOp, :InCompositeOp, :OutCompositeOp,
|
50
|
+
:AtopCompositeOp, :XorCompositeOp, :PlusCompositeOp, :MinusCompositeOp,
|
51
|
+
:AddCompositeOp, :SubtractCompositeOp, :DifferenceCompositeOp, :BumpmapCompositeOp,
|
52
|
+
:CopyCompositeOp, :CopyRedCompositeOp, :CopyGreenCompositeOp, :CopyBlueCompositeOp,
|
53
|
+
:CopyOpacityCompositeOp, :ClearCompositeOp, :DissolveCompositeOp, :DisplaceCompositeOp,
|
54
|
+
:ModulateCompositeOp, :ThresholdCompositeOp, :NoCompositeOp, :DarkenCompositeOp,
|
55
|
+
:LightenCompositeOp, :HueCompositeOp, :SaturateCompositeOp, :ColorizeCompositeOp,
|
56
|
+
:LuminizeCompositeOp, :ScreenCompositeOp, :OverlayCompositeOp, :CopyCyanCompositeOp,
|
57
|
+
:CopyMagentaCompositeOp, :CopyYellowCompositeOp, :CopyBlackCompositeOp, :DivideCompositeOp]
|
58
|
+
|
59
|
+
typedef :pointer, :wand
|
60
|
+
typedef :pointer, :composite_wand
|
61
|
+
typedef :pointer, :blob
|
62
|
+
typedef :pointer, :profile
|
63
|
+
typedef :string, :name
|
64
|
+
typedef :string, :filename
|
65
|
+
typedef :string, :format
|
66
|
+
typedef :string, :geometry
|
67
|
+
typedef :string, :crop
|
68
|
+
typedef :uint, :magick_pass_fail
|
69
|
+
typedef :uint, :dither
|
70
|
+
typedef :uint, :measure_error
|
71
|
+
typedef :uint, :gray
|
72
|
+
typedef :ulong, :columns
|
73
|
+
typedef :ulong, :rows
|
74
|
+
typedef :ulong, :depth
|
75
|
+
typedef :ulong, :quality
|
76
|
+
typedef :ulong, :width
|
77
|
+
typedef :ulong, :height
|
78
|
+
typedef :ulong, :number_colors
|
79
|
+
typedef :ulong, :tree_depth
|
80
|
+
typedef :long, :x
|
81
|
+
typedef :long, :y
|
82
|
+
typedef :double, :blur
|
83
|
+
typedef :double, :radius
|
84
|
+
typedef :double, :sigma
|
85
|
+
typedef :double, :gamma
|
86
|
+
typedef :double, :amount
|
87
|
+
typedef :double, :threshold
|
88
|
+
typedef :double, :x_resolution
|
89
|
+
typedef :double, :y_resolution
|
90
|
+
typedef :size_t, :length
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
attach_function :NewMagickWand, [], :wand
|
95
|
+
attach_function :CloneMagickWand, [ :wand ], :wand
|
96
|
+
|
97
|
+
attach_function :MagickReadImage, [ :wand, :filename ], :magick_pass_fail
|
98
|
+
attach_function :MagickReadImageBlob, [ :wand, :blob, :length ], :magick_pass_fail
|
99
|
+
attach_function :MagickWriteImage, [ :wand, :filename ], :magick_pass_fail
|
100
|
+
attach_function :MagickWriteImageBlob, [ :wand, :pointer ], :pointer
|
101
|
+
|
102
|
+
attach_function :MagickGetImageFormat, [ :wand ], :string
|
103
|
+
attach_function :MagickSetImageFormat, [ :wand, :format ], :uint
|
104
|
+
attach_function :MagickGetImageHeight, [ :wand ], :ulong
|
105
|
+
attach_function :MagickGetImageWidth, [ :wand ], :ulong
|
106
|
+
attach_function :MagickGetImageType, [ :wand ], :image_type
|
107
|
+
attach_function :MagickSetImageType, [ :wand, :image_type ], :magick_pass_fail
|
108
|
+
attach_function :MagickGetImageAttribute, [ :wand, :string ], :string
|
109
|
+
attach_function :MagickGetImageColorspace, [ :wand ], :colorspace
|
110
|
+
attach_function :MagickSetImageColorspace, [ :wand, :colorspace ], :magick_pass_fail
|
111
|
+
attach_function :MagickGetImageDepth, [ :wand ], :depth
|
112
|
+
attach_function :MagickSetImageDepth, [ :wand, :depth ], :magick_pass_fail
|
113
|
+
attach_function :MagickGetImageSize, [ :wand ], :ulong
|
114
|
+
|
115
|
+
attach_function :MagickSetCompressionQuality, [ :wand, :quality ], :magick_pass_fail
|
116
|
+
attach_function :MagickStripImage, [ :wand ], :magick_pass_fail
|
117
|
+
attach_function :MagickUnsharpMaskImage, [ :wand, :radius, :sigma, :amount, :threshold ], :magick_pass_fail
|
118
|
+
attach_function :MagickQuantizeImage, [ :wand, :number_colors, :colorspace, :tree_depth, :dither, :measure_error ], :magick_pass_fail
|
119
|
+
attach_function :MagickNegateImageChannel, [ :wand, :channel_type, :gray ], :magick_pass_fail
|
120
|
+
attach_function :MagickGammaImageChannel, [ :wand, :channel_type, :gamma ], :magick_pass_fail
|
121
|
+
attach_function :MagickProfileImage, [ :wand, :name, :profile, :length], :magick_pass_fail
|
122
|
+
attach_function :MagickGetImageProfile, [ :wand, :name, :profile ], :profile
|
123
|
+
attach_function :MagickSetImageProfile, [ :wand, :name, :profile, :ulong ], :magick_pass_fail
|
124
|
+
attach_function :MagickGetImageInterlaceScheme, [ :wand ], :interlace_type
|
125
|
+
attach_function :MagickSetImageInterlaceScheme, [ :wand, :interlace_type ], :magick_pass_fail
|
126
|
+
|
127
|
+
attach_function :MagickResizeImage, [ :wand, :columns, :rows, :filter_type, :blur ], :magick_pass_fail
|
128
|
+
attach_function :MagickResampleImage, [ :wand, :x_resolution, :y_resolution, :filter_type, :blur ], :magick_pass_fail
|
129
|
+
attach_function :MagickTransformImage, [ :wand, :crop, :geometry ], :wand
|
130
|
+
attach_function :MagickScaleImage, [ :wand, :columns, :rows ], :magick_pass_fail
|
131
|
+
attach_function :MagickCropImage, [ :wand, :width, :height, :x, :y ], :magick_pass_fail
|
132
|
+
attach_function :MagickCompositeImage, [ :wand, :composite_wand, :composite_operator, :x, :y ], :magick_pass_fail
|
133
|
+
|
134
|
+
attach_function :MagickGetConfigureInfo, [ :wand, :string ], :string
|
135
|
+
attach_function :MagickGetVersion, [ :pointer ], :string
|
136
|
+
attach_function :MagickGetCopyright, [], :string
|
137
|
+
end
|
138
|
+
end
|
data/test/image_test.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ImageTest < MiniTest::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@image = FFI::GMagick::Image.new()
|
6
|
+
@image.from_blob(BLOB)
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_size
|
10
|
+
assert_equal 2005, @image.size, "BLOBs are not equal"
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_crop
|
14
|
+
@image.crop(10,10)
|
15
|
+
assert_equal 10, @image.width, "invalid width"
|
16
|
+
assert_equal 10, @image.height, "invalid height"
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_crop_with_offset
|
20
|
+
@image.crop(10,10, 5, 15)
|
21
|
+
assert_equal 10, @image.width, "invalid width"
|
22
|
+
assert_equal 10, @image.height, "invalid height"
|
23
|
+
# TODO: How do you test offsets??
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_resize
|
27
|
+
@image.resize(10,20)
|
28
|
+
assert_equal 10, @image.width, "invalid width"
|
29
|
+
assert_equal 20, @image.height, "invalid height"
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_resize_to_fill
|
33
|
+
new_image = @image.resize_to_fill(100,200)
|
34
|
+
assert_equal 100, new_image.width, "invalid width"
|
35
|
+
assert_equal 200, new_image.height, "invalid height"
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_resize_to_fill_by_width
|
39
|
+
new_image = @image.resize_to_fill(100)
|
40
|
+
assert_equal 100, new_image.width, "invalid width"
|
41
|
+
assert_equal 100, new_image.height, "invalid height"
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_resize_to_fit
|
45
|
+
new_image = @image.resize_to_fit(100,200)
|
46
|
+
assert_equal 100, new_image.width, "invalid width"
|
47
|
+
assert_equal 63, new_image.height, "invalid height"
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_resize_to_fit_by_width
|
51
|
+
new_image = @image.resize_to_fit(100)
|
52
|
+
assert_equal 100, new_image.width, "invalid width"
|
53
|
+
assert_equal 63, new_image.height, "invalid height"
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_colorspace
|
57
|
+
assert_equal :RGBColorspace, @image.colorspace, "invalid color space"
|
58
|
+
assert_equal :RGBColorspace, @image.colormodel, "invalid color model"
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_get_type
|
62
|
+
assert_equal :TrueColorMatteType, @image.type, "invalid type"
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_set_type
|
66
|
+
skip # not yet working
|
67
|
+
@image.type = :TrueColorType
|
68
|
+
assert @image.valid?
|
69
|
+
assert_equal :TrueColorType, @image.type, "invalid type"
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_strip
|
73
|
+
skip # not yet working
|
74
|
+
old_size = @image.size
|
75
|
+
@image.strip
|
76
|
+
assert @image.valid?
|
77
|
+
assert old_size > @image.size, "image is not smaller"
|
78
|
+
end
|
79
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'ffi/gmagick'
|
3
|
+
|
4
|
+
# JPEG 150x94+0+0 DirectClass 8-bit 2.0K (2,005 bytes) TrueColorMatteType
|
5
|
+
BLOB = "\xFF\xD8\xFF\xE0\u0000\u0010JFIF\u0000\u0001\u0001\u0001\u0000H\u0000H\u0000\u0000\xFF\xFE\u0000\u0013This is a comment\xFF\xDB\u0000C\u0000\b\u0006\u0006\a\u0006\u0005\b\a\a\a\t\t\b\n\f\u0014\r\f\v\v\f\u0019\u0012\u0013\u000F\u0014\u001D\u001A\u001F\u001E\u001D\u001A\u001C\u001C $.' \",#\u001C\u001C(7),01444\u001F'9=82<.342\xFF\xDB\u0000C\u0001\t\t\t\f\v\f\u0018\r\r\u00182!\u001C!22222222222222222222222222222222222222222222222222\xFF\xC0\u0000\u0011\b\u0000^\u0000\x96\u0003\u0001\"\u0000\u0002\u0011\u0001\u0003\u0011\u0001\xFF\xC4\u0000\u001C\u0000\u0000\u0002\u0002\u0003\u0001\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0005\u0003\u0004\u0006\a\b\u0002\u0001\xFF\xC4\u0000B\u0010\u0000\u0001\u0002\u0003\u0002\b\v\u0004\a\t\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0003\u0002\u0004\u0005\u0006\u0011\u0012\u0016!14qr\xB1\a236AQt\x81\x93\x94\xC1\u0015TU\xB2#57Va\x92\xD1\u0013\u0017$BRs\x91\xA1\xE1\xFF\xC4\u0000\e\u0001\u0000\u0002\u0003\u0001\u0001\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0006\a\u0000\u0004\u0005\u0003\u0002\u0001\xFF\xC4\u00004\u0011\u0000\u0002\u0000\u0003\u0003\b\t\u0004\u0003\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0003\u0004\u00064q\u0005\u0011\u0013!13\xB1\xC1\u00142AQRar\x91\xD1\u0012\"5\x81\u0016\x92\xA1S\xFF\xDA\u0000\f\u0003\u0001\u0000\u0002\u0011\u0003\u0011\u0000?\u0000\xDB\xC0\u0000B\u001E\xA0\xE3\u0013\u0010\xC1\xC6&\u0001-\u0015\xF7\xF4\xB9\x96\xE4\xF5C\xABP\xBAs\x95\x87dcը]9\xCAòv\xB2ߐX>F=\xA0\xB9<W2\u0000\u0000\u0019\xC0 \x91s\xA8\u0002\xE7P\u0014/i\xA4U\xA8\xE8.wo\u0012&t\xD4;\xA8\xE8.wo\u0012&t\xD43\xACe\xC2/S\xE0\x86u\x8C\xB8E\xEA|\u0010t\t\xAA\x9AD;\u001E\xA3\x9E\x815SH\x87c\xD4\xD4\xCB\xF7'\x8A\r\xA9\xF7\x85 \u0000\u0001\r#\u0018\u007FHwiw\x91\x92?\xA4;\xB4\xBB\xC8ǽ6\xE6\f\u0017\u0004!*w\xD1\xE2\xF8\xB0\u0000\u0002\xC1\xC4\xEA\u0010\u0000\u0013\xC1\t\xEA\u000E11\f\u001Cb`\u0012\xD1_\u007FK\x99nOT:\xB5\v\xA79XvF=Z\x85Ӝ\xAC;'k-\xF9\u0005\x83\xE4c\xDA\v\x93\xC5s \u0000\u0001\x9C\u0002\t\u0017:\x80.u\u0001B\xF6\x9AEZ\x8E\x82\xE7v\xF1\"gMC\xBA\x8E\x82\xE7v\xF1\"gMC:\xC6\\\"\xF5>\bgX˄^\xA7\xC1\a@\x9A\xA9\xA4C\xB1\xEA9\xE8\u0013U4\x88v=ML\xBFrx\xA0ڟxR\u0000\u0000\u0010\xD21\x87\xF4\x87v\x97y\u0019#\xFAC\xBBK\xBC\x8C{\xD3n`\xC1pB\u0012\xA7}\u001E/\x8B\u0000\u0000,\u001CN\xA1\u0000\u0001<\u0010\x9E\xA0\xE3\u0013\u0010\xC1\xC6&\u0001-\u0015\xF7\xF4\xB9\x96\xE4\xF5C\xABP\xBAs\x95\x87dcը]9\xCAòv\xB2ߐX>F=\xA0\xB9<W2\u0000\u0000\u0019\xC0 \x91s\xA8\u0002\xE7P\u0014/i\xA4U\xA8\xE8.wo\u0012&t\xD4;\xA8\xE8.wo\u0012&t\xD43\xACe\xC2/S\xE0\x86u\x8C\xB8E\xEA|\u0010t\t\xAA\x9AD;\u001E\xA3\x9E\x815SH\x87c\xD4\xD4\xCB\xF7'\x8A\r\xA9\xF7\x85 \u0000\u0001\r#\u0018\u007FHwiw\x91\x92?\xA4;\xB4\xBB\xC8ǽ6\xE6\f\u0017\u0004!*w\xD1\xE2\xF8\xB0\u0000\u0002\xC1\xC4\xEA\u0010\u0014cU\x9F\xF8\xDD?DŽ1\xAA\xCF\xFCn\x9F\xE3\xC2):4\xFF\u0000\u0003\xF6\u007F\u0006\xFE\x92\u001E\xF1\xCC\u001Cbk\x8C~+af؇\r\xCA\xF5:\bs_\u0014\xC4(y\xC7\xCB%\xF7\x96\x95\xE6\xA0\xFD@[EK?\xA6\xEE\xDE\xC5\xD8\xFC\xFC\x8Brb_N\xD3!\xBDn\xBC];\xCBC\x913\v\xA1\xB7VY8\xF6\x86\x97\u000E\xB9\xA8?S\xE2\xDA\nEC\xE9\xA4\xEA2\x93\r\xA2\xE0\xACm\xBC\x91%\xFDY\u000E\xB6^\x9El\u0015\xE9\xC5\v\xD8\xFB\u001F\x97\x91\x97\x97%\xC56\x93閳\xBC\xEBf\xBE\u0019\xCBw\x85\xE5Oh\xCA{\xCB\u001E\"\a\xB4\xA4\xFD\xE5\x8F\u0011\u0006O\xD1\u0017p\u001D\xD0*\xBF\xE5\u0017\xF5\x8B࠹\xD4\u0004\xABk\xAC\xEA*\xDF[\xA7\xF9\x98\u000F\x98\xDFg~7O\xF3\u0010\ngO7?U\xFB?\x82ւg\x85\xFB?\x81\x85K@wRo\u0012]}עf.E[\xA5U\eYi\n\x84\xAC\xD3\xD1䅦]H\xA2[\xB2\xADȟ\x81\u0014R\u0013\xC9r\xC3$\xE2\xA5\xDFң\"ǭ\u001D\fPǫ\xEE{uv!\x8Be'˧\xA1\x8A\u0019\xB1(_\xD4\xF6\xB4\xBB\u0017{D\u0019\xD1r\t\xEA\xA9\xFCD9\u0013\x89\xEAd)#;\xEE\xAE~E1\x8BE4\xD5:u\xA6\xE7\u001Cn]ț\xC2H]\\\u0015T\xBDr\xE54\xF2\xEBQѸa\xEFA\x855u+\x99\x99L\x87\xFB/\x92\u0000({b\x97\xEF\xF2\xDE\"\a\xB6)~\xFF\u0000-\xE2 \u0011\xA2\x8F\xB8\xD3\xE9R<k\xDD|\x89\xDF\xD2\u001D\xDA]\xE4cx\xAC\xE5ne\u007Fn\xC5\"u\xD6\\\xFAH#\x85\x85T\x8A\u0015ʊ\x8B\xD5pb\xAD\xA0\xF8\u001C\xFF\u0000\x97\x88v\xD3T\xC8Ra\xFB\xD6\xC5ڻ\x97\x98\x90\xA8\x82':-]\xAF\x8B\u0014\u0000\xDF\u0015m\a\xC0\xE7\xFC\xBC@v\xE9R<k\xDD|\x9Ctqw\t\xB0\x93\xAD\u0003\t:Ј\u000FzF|\xCCU\xAB\xC1\u0013\xF28\u0010B\xB1ņ\x8Bre)Sl\x85\xA3\xAC5\e\xD4\xDA4\xEC\xD3PE\x81\u0014L\xB2\xB1\".{\x86\xE6\xF3\xE07\x9B\xD5N؟$ \xAD\xA2\xA2\x85\xC0\xEA\xF3\xEBԳv\u001A\u0014sZz3@\xFE\xEEm\xA6U\xC5z\xAF\x96\x88\xD96\u0016\xCA\xD7\xE9\xD6}\xD6')\u0013\x8C8\xAF\xC5\u0012B\xE3K\n\xDDt9N\x88ȉ\xF8\u001EW.eN\xF0V\x9E{\x91\u001E\x91,\xE6\xCD-TT\xD34\x90\xAC望\xA6O\xC8\xCB957&\xE3,6\x97\xC6\xE3\x90ܐ\xA7Z\xA8\x9A*\xC51Q/\x9E\x97\xFC\xE8m~\u0011~ϫ}\x99w\xA1\xCC+\xAC-\xC9/\xA6\xCAqǫ3ͫ\u0002\xDC\xFBM>SI@\xBF\xD3\u0015\x8EBm\\\x89R]\xCC\xEB\xFC\xA7\x9FgM\xFB\xBB\x9F\x94\xCA\xC0\xF9\xFCfG\x8D\xFF\u0000\x80\xCFN\x8B\xB8\xF3\xC1\xBC\xE4\xAD&\xDE\xC8\xCCT^\x82Y\xA6\xD1Ď7\x97\u0005!\xBD\xB8\x91/\xFF\u0000&\xF9\xC7{.\x991\x82\x9F\u007F\xF7\x90\xE6\u001A\x9F\xD6O.[\xB0\x8A\x99\xD7X12.\x8F6)K^f\xCF5Y6]dJlm\xADGTc͗\xBF%~\x9D㡦\xF8^\xABS\xAB6\x92M\xFAl\xEB3M\xC1&\x90E\u00131a\".\u001Ckw\xFB5Ңߔ\xFBz'\xFCS\x94\xC9\xEE5\x99\xA2Rd\x99t\xB3t\xB0\xC4߱\xE0u/d\xAD\fԻs\u0012\xF4i\xD7Yr\u0014\x8A\b\xE0iU\"Ę%:^\xC7\xF3>\x89\xD8\xDA\xDCp5\u0006\xB4Kefd,\xFD6Nn\xBFObe\x89V\x9Ay\xA7\u001ED\x8A\b\xE1\x85\u0011QS\xA1QQP\xBF\x8F\xD6C\xEF%3\xCC!\xCAփ\x9C\x95N\xD8\xF7\u03A2\xD2\u0010\xEB\xBC~\xB2\u001Fy)\x9Ea\u0000\xE4@!\f\xD4\u0000\u0006\xB9\x82\u0006\xF3\xE07\x9B\xD5N؟\"\u001A0\xDE|\u0006\xF3z\xA9\xDB\u0013\xE4C\u0016\xD0\\b\xC5q,\xD2oM\xAC\u0000\u0000\u0011\xAAb\xDC#}\x9FV\xFB2\xEFC\x97\xD79\xD4\u001C#}\x9FV\xFB2\xEFC\x97\xD78gfn\xF1\xE3\xC8ͭ\xEB \u0000\u0000\x90\xA6c\u0015O\xAC\x9E\xDA(\x97\xAA\x9FY=\xB4Q\u0016u\xB7\x99\x98\xBE,ۗ\xD4@\u0000\u0005C\xD8\u001D/c\xF9\x9FD\xECmn9\xA0\xE9{\u001F\xCC\xFA'ckq\bs\u0560\xE7%S\xB6=\xF3\xA8\xB4eh9\xC9T\xED\x8F|\xEA-!\u0000\u0000\bC\xFF\xD9"
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ffi-gmagick
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Richard Hurt
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-11-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ffi
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.9'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.9'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: |-
|
56
|
+
This is not a simple 'Ruby'-like implementation. It is more of a
|
57
|
+
raw 'C' implementation. As such, it may be a bit more difficult to
|
58
|
+
work with than something like rmagick, but it should perform just as
|
59
|
+
well.
|
60
|
+
email:
|
61
|
+
- rnhurt@gmail.com
|
62
|
+
executables: []
|
63
|
+
extensions: []
|
64
|
+
extra_rdoc_files: []
|
65
|
+
files:
|
66
|
+
- .gitignore
|
67
|
+
- .travis.yml
|
68
|
+
- Gemfile
|
69
|
+
- LICENSE.txt
|
70
|
+
- README.md
|
71
|
+
- Rakefile
|
72
|
+
- ffi-gmagick.gemspec
|
73
|
+
- lib/ffi/gmagick.rb
|
74
|
+
- lib/ffi/gmagick/image.rb
|
75
|
+
- lib/ffi/gmagick/struct.rb
|
76
|
+
- lib/ffi/gmagick/version.rb
|
77
|
+
- test/image_test.rb
|
78
|
+
- test/test_helper.rb
|
79
|
+
homepage: https://github.com/rnhurt/ffi-gmagick
|
80
|
+
licenses:
|
81
|
+
- MIT
|
82
|
+
metadata: {}
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements:
|
98
|
+
- libGraphicsMagick, v1.3.18
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 2.1.11
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: Use the C GraphicsMagick bindings to provide a Ruby interface
|
104
|
+
test_files:
|
105
|
+
- test/image_test.rb
|
106
|
+
- test/test_helper.rb
|