prawn-gmagick 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 71345ece376bc00b760d62440468697d2505208f
4
+ data.tar.gz: a5dd71dd5675e504cb17775428d0e3a57d10d230
5
+ SHA512:
6
+ metadata.gz: 5d1c789b398543732e3ba20412f54a50615b21c75c56d623602e7de76eb2cedd606adb24840a00905e5392eb5fd4bd12929de7832720aab1b0965d9d9555d060
7
+ data.tar.gz: fe6abf387dd53d29af71aee61e8d82243345ebc40639c88b74015c28f9111d07ec3e43b17a7d3bda4581233daef721a33b74d382ad873b1bfd8bf8ed7d009caf
@@ -0,0 +1,34 @@
1
+ # prawn-gmagick
2
+
3
+ A [graphicsmagick](http:////www.graphicsmagick.org/) binding to add support for
4
+ additional image formats to [prawn](https://github.com/prawnpdf/prawn).
5
+
6
+ ## Usage
7
+
8
+ **Gemfile**
9
+
10
+ ```ruby
11
+ gem "prawn-gmagick"
12
+ ```
13
+
14
+ **Your code**
15
+
16
+ ```ruby
17
+ require "prawn-gmagick"
18
+ ```
19
+
20
+ ## Found a bug?
21
+ Open a [github issue](https://github.com/packetmonkey/prawn-gmagick/issues)
22
+
23
+ ## Contributing & Development
24
+ 1. Fork the project.
25
+ 2. Make your feature addition or bug fix. All specs should pass.
26
+ 3. Add specs for your changes.
27
+ 4. Commit
28
+ 5. Send a pull request. Bonus points for topic branches.
29
+
30
+ ## Licence
31
+ prawn-gmagick is released under the [MIT Licence](http://choosealicense.com/licenses/mit/)
32
+
33
+ ## Authors
34
+ prawn-gmagick is written and maintained by Evan Sharp.
@@ -0,0 +1,36 @@
1
+ $LOAD_PATH.unshift File.join(__dir__, "lib")
2
+
3
+ require "rake/testtask"
4
+ require "rake/extensiontask"
5
+
6
+ task "default" => :test
7
+
8
+ Rake::ExtensionTask.new "gmagick" do |ext|
9
+ ext.lib_dir = "lib/prawn-gmagick/gmagick"
10
+ end
11
+
12
+ Rake::TestTask.new do |t|
13
+ t.pattern = "test/**/*_test.rb"
14
+ end
15
+ task "test" => :compile
16
+
17
+ desc "Generate an example PDF using the images in test/fixtures"
18
+ task "example" do
19
+ $LOAD_PATH.unshift "./lib"
20
+ require "prawn-gmagick"
21
+ doc = Prawn::Document.new margin: 0
22
+ files = %w(rgb.gif rgb_alpha.gif rgb.jpg cmyk.jpg rgb.pdf rgb_alpha.pdf rgb.png rgb_alpha.png rgb.tiff rgb.bmp)
23
+ files.each do |filename|
24
+ start_time = Time.now
25
+ doc.start_new_page unless filename == files.first
26
+
27
+ doc.fill_color "00FF11"
28
+ doc.fill_rectangle [0, 11 * 72], 400, 400
29
+ doc.fill_color "000000"
30
+ file_path = File.join __dir__, "test", "fixtures", filename
31
+ doc.text file_path
32
+ doc.image file_path, height: 200
33
+ puts "Added #{file_path} in #{Time.now-start_time} seconds"
34
+ end
35
+ doc.render_file "example.pdf"
36
+ end
@@ -0,0 +1,4 @@
1
+ require "mkmf"
2
+
3
+ pkg_config("GraphicsMagickWand")
4
+ create_makefile("gmagick")
@@ -0,0 +1,150 @@
1
+ #include <ruby.h>
2
+ #include <string.h>
3
+ #include <wand/magick_wand.h>
4
+
5
+ VALUE format(VALUE self, VALUE rb_image_blob)
6
+ {
7
+ const char *format = NULL;
8
+ long double image_blob_length = RSTRING_LEN(rb_image_blob);
9
+ char *image_blob = RSTRING_PTR(rb_image_blob);
10
+
11
+ InitializeMagick(".");
12
+ MagickWand *magick_wand = NewMagickWand();
13
+ MagickReadImageBlob(magick_wand, (const unsigned char *)image_blob, image_blob_length);
14
+ format = MagickGetImageFormat(magick_wand);
15
+
16
+ if (format) {
17
+ return rb_str_new2(format);
18
+ } else {
19
+ return Qnil;
20
+ }
21
+ }
22
+
23
+ VALUE image_initialize(VALUE self, VALUE rb_image_blob)
24
+ {
25
+ MagickWand *magick_wand;
26
+
27
+ InitializeMagick(".");
28
+
29
+ magick_wand = NewMagickWand();
30
+
31
+ long double image_blob_length = RSTRING_LEN(rb_image_blob);
32
+ char *image_blob = RSTRING_PTR(rb_image_blob);
33
+ MagickReadImageBlob(magick_wand, (const unsigned char *)image_blob, image_blob_length);
34
+
35
+ VALUE rb_wand = Data_Wrap_Struct(rb_cObject, NULL, NULL, magick_wand);
36
+
37
+ rb_funcall(self, rb_intern("wand="), 1, rb_wand);
38
+ rb_funcall(self, rb_intern("blob="), 1, rb_image_blob);
39
+
40
+ return Qtrue;
41
+ }
42
+
43
+ VALUE image_depth(VALUE self)
44
+ {
45
+ VALUE rb_wand = rb_funcall(self, rb_intern("wand"), 0);
46
+ MagickWand *magick_wand;
47
+ Data_Get_Struct(rb_wand, MagickWand, magick_wand);
48
+
49
+ unsigned long depth = MagickGetImageChannelDepth(magick_wand, RedChannel);
50
+ return INT2NUM(depth);
51
+ }
52
+
53
+ VALUE image_width(VALUE self)
54
+ {
55
+ VALUE rb_wand = rb_funcall(self, rb_intern("wand"), 0);
56
+ MagickWand *magick_wand;
57
+ Data_Get_Struct(rb_wand, MagickWand, magick_wand);
58
+ unsigned long width = MagickGetImageWidth(magick_wand);
59
+ return INT2NUM(width);
60
+ }
61
+
62
+ VALUE image_height(VALUE self)
63
+ {
64
+ VALUE rb_wand = rb_funcall(self, rb_intern("wand"), 0);
65
+ MagickWand *magick_wand;
66
+ Data_Get_Struct(rb_wand, MagickWand, magick_wand);
67
+ unsigned long height = MagickGetImageHeight(magick_wand);
68
+ return INT2NUM(height);
69
+ }
70
+
71
+ VALUE image_colorspace(VALUE self)
72
+ {
73
+ VALUE rb_wand = rb_funcall(self, rb_intern("wand"), 0);
74
+ MagickWand *magick_wand;
75
+ Data_Get_Struct(rb_wand, MagickWand, magick_wand);
76
+ ColorspaceType color_space = MagickGetImageColorspace(magick_wand);
77
+ if (color_space == RGBColorspace) {
78
+ return ID2SYM(rb_intern("DeviceRGB"));
79
+ } else if (color_space == CMYKColorspace) {
80
+ return ID2SYM(rb_intern("DeviceCMYK"));
81
+ } else {
82
+ rb_raise(rb_eTypeError, "Unknown colorspace");
83
+ }
84
+ }
85
+
86
+ VALUE image_unpack(VALUE self)
87
+ {
88
+ VALUE rb_wand = rb_funcall(self, rb_intern("wand"), 0);
89
+ MagickWand *magick_wand;
90
+ Data_Get_Struct(rb_wand, MagickWand, magick_wand);
91
+ ColorspaceType color_space = MagickGetImageColorspace(magick_wand);
92
+
93
+ int height = NUM2INT( rb_funcall(self, rb_intern("height"), 0) );
94
+ int width = NUM2INT( rb_funcall(self, rb_intern("width"), 0) );
95
+ int pixel_count = height * width;
96
+ int buffer_size;
97
+ char color_format[8];
98
+ unsigned char *pixels;
99
+
100
+ if (color_space == RGBColorspace) {
101
+ buffer_size = 3 * pixel_count;
102
+ strcpy(color_format, "RGB");
103
+ } else if (color_space == CMYKColorspace) {
104
+ buffer_size = 4 * pixel_count;
105
+ strcpy(color_format, "CMYK");
106
+ } else {
107
+ rb_raise(rb_eTypeError, "Unknown colorspace");
108
+ }
109
+
110
+ pixels = (unsigned char *)malloc(buffer_size * sizeof(char));
111
+ MagickGetImagePixels(magick_wand, 0, 0, width, height, color_format, CharPixel, pixels);
112
+
113
+ return rb_str_new((const char *)pixels, buffer_size);
114
+ }
115
+
116
+ VALUE image_alpha_unpack(VALUE self)
117
+ {
118
+ VALUE rb_wand = rb_funcall(self, rb_intern("wand"), 0);
119
+ MagickWand *magick_wand;
120
+ Data_Get_Struct(rb_wand, MagickWand, magick_wand);
121
+ int height = NUM2INT( rb_funcall(self, rb_intern("height"), 0) );
122
+ int width = NUM2INT( rb_funcall(self, rb_intern("width"), 0) );
123
+ int pixel_count = height * width;
124
+ unsigned char *pixels;
125
+
126
+ pixels = (unsigned char *)malloc(pixel_count * sizeof(char));
127
+ MagickGetImagePixels(magick_wand, 0, 0, width, height, "A", CharPixel, pixels);
128
+ return rb_str_new((const char *)pixels, pixel_count);
129
+ }
130
+
131
+ void Init_gmagick(void)
132
+ {
133
+ // Deine our name spaces and classes
134
+ VALUE m_gmagick = rb_define_module("GMagick");
135
+ VALUE c_image = rb_define_class_under(m_gmagick, "Image", rb_cObject);
136
+
137
+ // Define our class methods
138
+ rb_define_singleton_method(c_image, "format", format, 1);
139
+
140
+ // Define our instance methods
141
+ rb_define_attr(c_image, "blob", 1, 1);
142
+ rb_define_attr(c_image, "wand", 1, 1);
143
+ rb_define_method(c_image, "initialize", image_initialize, 1);
144
+ rb_define_method(c_image, "depth", image_depth, 0);
145
+ rb_define_method(c_image, "width", image_width, 0);
146
+ rb_define_method(c_image, "height", image_height, 0);
147
+ rb_define_method(c_image, "colorspace", image_colorspace, 0);
148
+ rb_define_method(c_image, "unpack", image_unpack, 0);
149
+ rb_define_method(c_image, "alpha_unpack", image_alpha_unpack, 0);
150
+ }
@@ -0,0 +1,52 @@
1
+ require "prawn-gmagick/gmagick/gmagick"
2
+
3
+ require "prawn"
4
+
5
+ class Gmagick < Prawn::Images::Image
6
+ attr_reader :width, :height, :bits, :channels
7
+ attr_accessor :scaled_width, :scaled_height
8
+ attr_accessor :gimage
9
+
10
+ def self.can_render? image_blob
11
+ GMagick::Image.format(image_blob) ? true : false
12
+ end
13
+
14
+ def initialize image_blob
15
+ self.gimage = GMagick::Image.new image_blob
16
+
17
+ @bits = self.gimage.depth
18
+ @width = self.gimage.width
19
+ @height = self.gimage.height
20
+ end
21
+
22
+ def build_pdf_object(document)
23
+ obj = document.ref!(
24
+ Type: :XObject,
25
+ Subtype: :Image,
26
+ ColorSpace: gimage.colorspace,
27
+ Height: @height,
28
+ Width: @width,
29
+ BitsPerComponent: @bits
30
+ )
31
+ obj << gimage.unpack
32
+
33
+ alpha_mask = self.gimage.alpha_unpack
34
+ if alpha_mask.unpack("C*").uniq.length > 1
35
+ smask_obj = document.ref!(
36
+ :Type => :XObject,
37
+ :Subtype => :Image,
38
+ :Height => gimage.height,
39
+ :Width => gimage.width,
40
+ :BitsPerComponent => gimage.depth,
41
+ :ColorSpace => :DeviceGray,
42
+ :Decode => [0, 1]
43
+ )
44
+ smask_obj.stream << alpha_mask
45
+ obj.data[:SMask] = smask_obj
46
+ end
47
+
48
+ obj
49
+ end
50
+ end
51
+
52
+ Prawn.image_handler.register! Gmagick
@@ -0,0 +1,12 @@
1
+ ___,,___
2
+ _,-='=- =- -`"--.__,,.._
3
+ ,-;// / - - - -= - "=.
4
+ ,'/// - - - = - ==-=\`.
5
+ |/// / = `. - = == - =.=_,,._ `=/|
6
+ /// - - \ - - = ,ndDMHHMM/\b \\
7
+ ,' - / / / /\ = - /MM(,,._`YQMML `|
8
+ <_,=^Kkm / / / / ///H|wnWWdMKKK#""-;. `"0\ |
9
+ `""QkmmmmmnWMMM\""WHMKKMM\ `--. \> \
10
+ hjm `""' `->>> ``WHMb,. `-_<@)
11
+ `"QMM`.
12
+ `>>>
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,111 @@
1
+ require_relative "../test_helper"
2
+
3
+ describe "GMagick::Image::format" do
4
+ describe "with a JPEG image" do
5
+ before do
6
+ fixture_path = File.join __dir__, "..", "fixtures", "rgb.jpg"
7
+ @fixture_blob = File.open(fixture_path).read
8
+ end
9
+
10
+ it "returns a string containing 'JPEG'" do
11
+ GMagick::Image.format(@fixture_blob).must_equal "JPEG"
12
+ end
13
+ end
14
+
15
+ describe "with an unknown image" do
16
+ before do
17
+ fixture_path = File.join __dir__, "..", "fixtures", "random.bin"
18
+ @fixture_blob = File.open(fixture_path).read
19
+ end
20
+
21
+ it "returns nil" do
22
+ GMagick::Image.format(@fixture_blob).must_equal nil
23
+ end
24
+ end
25
+ end
26
+
27
+ describe GMagick::Image do
28
+ before do
29
+ fixture_path = File.join __dir__, "..", "fixtures", "rgb.jpg"
30
+ fixture_blob = File.open(fixture_path).read
31
+ @image = GMagick::Image.new fixture_blob
32
+ end
33
+
34
+ describe "#depth" do
35
+ it "returns the image bit depth as an integer" do
36
+ @image.depth.must_equal 8
37
+ end
38
+ end
39
+
40
+ describe "#width" do
41
+ it "returns the image width in pixels as an integer" do
42
+ @image.width.must_equal 13
43
+ end
44
+ end
45
+
46
+ describe "#height" do
47
+ it "returns the image height in pixels as an integer" do
48
+ @image.height.must_equal 17
49
+ end
50
+ end
51
+
52
+ describe "#colorspace" do
53
+ describe "with an RGB image" do
54
+ it "returns the symbol :DeviceRGB" do
55
+ @image.colorspace.must_equal :DeviceRGB
56
+ end
57
+ end
58
+
59
+ describe "with a CMYK image" do
60
+ before do
61
+ fixture_path = File.join __dir__, "..", "fixtures", "cmyk.jpg"
62
+ fixture_blob = File.open(fixture_path).read
63
+ @image = GMagick::Image.new fixture_blob
64
+ end
65
+
66
+ it "returns the symbol :DeviceCMYK" do
67
+ @image.colorspace.must_equal :DeviceCMYK
68
+ end
69
+ end
70
+ end
71
+
72
+ describe "#unpack" do
73
+ describe "with an RGB image" do
74
+ it "returns a string containing the pixel color information" do
75
+ @image.unpack.unpack("CCC").must_equal [255, 38, 0]
76
+ end
77
+ end
78
+
79
+ describe "with a CMYK image" do
80
+ before do
81
+ fixture_path = File.join __dir__, "..", "fixtures", "cmyk.jpg"
82
+ fixture_blob = File.open(fixture_path).read
83
+ @image = GMagick::Image.new fixture_blob
84
+ end
85
+
86
+ it "returns a string containing the pixel color information" do
87
+ @image.unpack.unpack("CCCC").must_equal [55, 27, 0, 0]
88
+ end
89
+ end
90
+ end
91
+
92
+ describe "#unpack_alpha" do
93
+ describe "with an opaque JPEG" do
94
+ it "returns a string containing the pixel alpha information" do
95
+ @image.alpha_unpack.unpack("CCCC").must_equal [255, 255, 255, 255]
96
+ end
97
+ end
98
+
99
+ describe "with an transparent GIF" do
100
+ before do
101
+ fixture_path = File.join __dir__, "..", "fixtures", "rgb_alpha.gif"
102
+ fixture_blob = File.open(fixture_path).read
103
+ @image = GMagick::Image.new fixture_blob
104
+ end
105
+
106
+ it "returns a string containing the pixel alpha information" do
107
+ @image.alpha_unpack.unpack("C*").slice(11, 3).must_equal [255, 255, 0]
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require "minitest/autorun"
3
+ require "minitest/pride"
4
+ require "minitest/hell"
5
+
6
+ require "prawn-gmagick"
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: prawn-gmagick
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Evan Sharp
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: prawn
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.13.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.13.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake-compiler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
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
+ email:
57
+ executables: []
58
+ extensions:
59
+ - ext/gmagick/extconf.rb
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ext/gmagick/extconf.rb
63
+ - ext/gmagick/gmagick.c
64
+ - lib/prawn-gmagick/gmagick/gmagick.bundle
65
+ - lib/prawn-gmagick.rb
66
+ - test/fixtures/ascii.txt
67
+ - test/fixtures/cmyk.jpg
68
+ - test/fixtures/random.bin
69
+ - test/fixtures/rgb.bmp
70
+ - test/fixtures/rgb.gif
71
+ - test/fixtures/rgb.jpg
72
+ - test/fixtures/rgb.pdf
73
+ - test/fixtures/rgb.png
74
+ - test/fixtures/rgb.tiff
75
+ - test/fixtures/rgb_alpha.gif
76
+ - test/fixtures/rgb_alpha.pdf
77
+ - test/fixtures/rgb_alpha.png
78
+ - test/gmagick/image_test.rb
79
+ - test/test_helper.rb
80
+ - README.markdown
81
+ - Rakefile
82
+ homepage:
83
+ licenses:
84
+ - MIT
85
+ metadata: {}
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubyforge_project:
102
+ rubygems_version: 2.0.3
103
+ signing_key:
104
+ specification_version: 4
105
+ summary: Use GraphicsMagick to load images in a Prawn docuemnt
106
+ test_files: []