tinyimg 0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a953ed5351abc1984d8739f8ec3d91a1bed9654a
4
+ data.tar.gz: c73c4110056238bc19a1c6e7ae6204b4c98a9968
5
+ SHA512:
6
+ metadata.gz: 810f4ae575ca67c08c7a1551eb0abf4f16ca6fb12c77d4d9dd9227bd448856644d063424c0d34a6251aa2a52ef0be38ad9180e29f05d3e2a81ccb487d7c260b3
7
+ data.tar.gz: f7021348faf7e950ed87c51c12383684238bdfef806fb9f11d36bdb0c1e51c600576bb7fe7ac2ef48f31361d6769ffb50b988166ffabbb625cdf6983e7142560
@@ -0,0 +1,5 @@
1
+ /*.gem
2
+ ext/tinyimg/Makefile
3
+ ext/tinyimg/mkmf.log
4
+ ext/tinyimg/*.bundle
5
+ ext/tinyimg/*.o
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,29 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ timyimg (0.1.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.2.5)
10
+ rspec (3.3.0)
11
+ rspec-core (~> 3.3.0)
12
+ rspec-expectations (~> 3.3.0)
13
+ rspec-mocks (~> 3.3.0)
14
+ rspec-core (3.3.2)
15
+ rspec-support (~> 3.3.0)
16
+ rspec-expectations (3.3.1)
17
+ diff-lcs (>= 1.2.0, < 2.0)
18
+ rspec-support (~> 3.3.0)
19
+ rspec-mocks (3.3.2)
20
+ diff-lcs (>= 1.2.0, < 2.0)
21
+ rspec-support (~> 3.3.0)
22
+ rspec-support (3.3.0)
23
+
24
+ PLATFORMS
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ rspec (~> 3.0)
29
+ timyimg!
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright 2015 Roger Nesbitt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,74 @@
1
+ # Tinyimg
2
+
3
+ Load a JPEG or PNG, get its dimensions, resize it, and extract it again as either a JPEG or PNG.
4
+
5
+ This gem can work from image data stored in memory, as well as from a file or IO stream.
6
+ It's been coded to be as efficient as possible, so doesn't use temporary files.
7
+
8
+ Tinyimg uses libgd for its image processing. libgd is significantly less painful to install than
9
+ ImageMagick and friends! Other than that, all that is required is Ruby 2.0+.
10
+
11
+ ## Installation
12
+
13
+ If you don't already have libgd installed on your system, install it.
14
+
15
+ On OS X, install Homebrew and
16
+
17
+ brew install libgd
18
+
19
+ On a Linux system, use your package manager. For example, on Debian/Ubuntu:
20
+
21
+ sudo apt-get install libgd-dev
22
+
23
+ Then add tinyimg to your project's Gemfile
24
+
25
+ gem 'tinyimg'
26
+
27
+ ## Usage
28
+
29
+ Load the image with the method that fits your use case:
30
+
31
+ image = Tinyimg.from_string(an_image_that_is_already_loaded)
32
+ image = Tinyimg.from_file("some_image.png")
33
+ image = Tinyimg.from_io(params[:uploaded_file])
34
+
35
+ Manipulate it by using one of the resize commands:
36
+
37
+ image.resize_to_fit!(100, 100) # image will be 100x100 maximum
38
+ image.resize_to_fill!(100, 100) # image will be 100x100 minimum
39
+ image.resize!(100, 100) # forces image to be exactly 100x100
40
+
41
+ Then get an image back:
42
+
43
+ image.to_png # returns a string
44
+ image.to_jpeg # returns a string
45
+ image.save("some_image.jpg") # file type auto-determined by extension
46
+
47
+ You can ask for the image's dimensions:
48
+
49
+ image.width # => 120
50
+ image.height # => 80
51
+ image.dimensions # => [120, 80]
52
+
53
+ You can also use the non-! versions of the resize methods: `resize`, `resize_to_fit` and `resize_to_fill`.
54
+ These create a new image in memory and return it, leaving the old image untouched. This is useful if you want
55
+ to resize an original image to multiple sizes. Using these methods will take more memory.
56
+
57
+ ## Examples
58
+
59
+ Take an uploaded file, save the original as a JPEG, then resize to create a thumbnail and save that too:
60
+
61
+ Tinyimg
62
+ .from_io(params[:uploaded_file])
63
+ .save("#{path}/full_size.jpg")
64
+ .resize_to_fit!(100, 100)
65
+ .save("#{path}/thumbnail.jpg")
66
+
67
+ Load a file from disk, make a thumbnail, and return it as a JPEG so we can save it into our database:
68
+
69
+ data = Tinyimg.from_file(image_filename).resize_to_fit!(100, 100).to_jpeg
70
+ user.update!(thumbnail_image: data)
71
+
72
+ ## Author and licence
73
+
74
+ Copyright 2015 Roger Nesbitt. Licenced under the MIT licence.
@@ -0,0 +1,35 @@
1
+ require 'mkmf'
2
+
3
+ def filter_dirs(dirs)
4
+ dirs.select {|dir| Dir.exists?(dir)}
5
+ end
6
+
7
+ def cannot_find_gd
8
+ abort <<-TEXT
9
+ *******************************************************************************
10
+ It looks like libgd is not installed on your system.
11
+
12
+ If you're on OS X, install homebrew and try
13
+ brew install libgd
14
+
15
+ If you're on Debian/Ubuntu linux, try
16
+ apt-get install libgd-dev
17
+ *******************************************************************************
18
+ TEXT
19
+ end
20
+
21
+ header_dirs = %w(/opt/local/include /usr/local/include /usr/include)
22
+ lib_dirs = %w(/opt/local/lib /usr/local/lib /usr/lib)
23
+
24
+ dir_config('gd', filter_dirs(header_dirs), filter_dirs(lib_dirs))
25
+
26
+ have_library('gd', 'gdFree') or cannot_find_gd
27
+ have_header('gd.h') or cannot_find_gd
28
+ have_func('gdImageJpegPtr') or abort "Your libgd is too old! You need at least version 1.8.0, and preferably 2.1.1+."
29
+ have_func('gdImageFile')
30
+ have_func('gdImageCreateFromFile')
31
+ have_func('gdImageAlphaBlending')
32
+ have_func('gdImageClone')
33
+ have_func('gdImagePngPtrEx')
34
+
35
+ create_makefile 'tinyimg/tinyimg'
@@ -0,0 +1,255 @@
1
+ #include <ruby.h>
2
+ #include <gd.h>
3
+
4
+ gdImagePtr get_image_data(VALUE self)
5
+ {
6
+ gdImagePtr image;
7
+ VALUE wrapped_image = rb_iv_get(self, "@data");
8
+ Data_Get_Struct(wrapped_image, struct gdImageStruct, image);
9
+ return image;
10
+ }
11
+
12
+ void set_image_data(VALUE self, gdImagePtr image)
13
+ {
14
+ VALUE klass, value;
15
+
16
+ klass = rb_const_get_at(rb_class_of(self), rb_intern("Image"));
17
+ value = Data_Wrap_Struct(klass, 0, gdImageDestroy, image);
18
+ rb_iv_set(self, "@data", value);
19
+ }
20
+
21
+ void set_alpha(gdImagePtr image)
22
+ {
23
+ #ifdef HAVE_GDIMAGEALPHABLENDING
24
+ gdImageAlphaBlending(image, 0);
25
+ gdImageSaveAlpha(image, 1);
26
+ #endif
27
+ }
28
+
29
+ VALUE retrieve_image_dimensions(VALUE self)
30
+ {
31
+ gdImagePtr image = get_image_data(self);
32
+
33
+ rb_iv_set(self, "@width", INT2FIX(gdImageSX(image)));
34
+ rb_iv_set(self, "@height", INT2FIX(gdImageSY(image)));
35
+
36
+ return Qnil;
37
+ }
38
+
39
+ VALUE load_from_string(VALUE self, VALUE input, VALUE type)
40
+ {
41
+ gdImagePtr image;
42
+ ID type_id;
43
+
44
+ Check_Type(input, T_STRING);
45
+ Check_Type(type, T_SYMBOL);
46
+ type_id = SYM2ID(type);
47
+
48
+ if (type_id == rb_intern("png")) {
49
+ image = gdImageCreateFromPngPtr(RSTRING_LEN(input), RSTRING_PTR(input));
50
+ }
51
+ else if (type_id == rb_intern("jpeg")) {
52
+ image = gdImageCreateFromJpegPtr(RSTRING_LEN(input), RSTRING_PTR(input));
53
+ }
54
+ else {
55
+ rb_raise(rb_eArgError, "type must be a supported image type");
56
+ }
57
+
58
+ if (!image) {
59
+ rb_raise(rb_eRuntimeError, "Error loading image data");
60
+ }
61
+
62
+ set_image_data(self, image);
63
+ set_alpha(image);
64
+
65
+ retrieve_image_dimensions(self);
66
+
67
+ return self;
68
+ }
69
+
70
+ #ifdef HAVE_GDIMAGECREATEFROMFILE
71
+ VALUE load_from_file(VALUE self, VALUE filename)
72
+ {
73
+ gdImagePtr image;
74
+
75
+ Check_Type(filename, T_STRING);
76
+
77
+ image = gdImageCreateFromFile(StringValueCStr(filename));
78
+ if (!image) {
79
+ rb_raise(rb_eRuntimeError, "Error loading image data");
80
+ }
81
+
82
+ set_image_data(self, image);
83
+ set_alpha(image);
84
+
85
+ retrieve_image_dimensions(self);
86
+
87
+ return self;
88
+ }
89
+ #endif
90
+
91
+ VALUE initialize_copy(int argc, VALUE *argv, VALUE self)
92
+ {
93
+ gdImagePtr image, original;
94
+
95
+ rb_call_super(argc, argv);
96
+
97
+ original = get_image_data(self);
98
+
99
+ #ifdef HAVE_GDIMAGECLONE
100
+ image = gdImageClone(original);
101
+ #else
102
+ int width = gdImageSX(original), height = gdImageSY(original);
103
+
104
+ image = gdImageCreateTrueColor(width, height);
105
+ set_alpha(image);
106
+
107
+ gdImageCopy(image, original, 0, 0, 0, 0, width, height);
108
+ #endif
109
+
110
+ set_image_data(self, image);
111
+
112
+ return Qnil;
113
+ }
114
+
115
+ #ifdef HAVE_GDIMAGEFILE
116
+ VALUE save_to_file(VALUE self, VALUE filename)
117
+ {
118
+ gdImagePtr image;
119
+ int result;
120
+
121
+ Check_Type(filename, T_STRING);
122
+
123
+ image = get_image_data(self);
124
+ result = gdImageFile(image, StringValueCStr(filename));
125
+
126
+ if (result == GD_FALSE) {
127
+ rb_raise(rb_eRuntimeError, "Unknown error occurred while trying to save the file; check it is using a known filename");
128
+ }
129
+
130
+ return self;
131
+ }
132
+ #endif
133
+
134
+ VALUE to_jpeg(int argc, VALUE *argv, VALUE self)
135
+ {
136
+ gdImagePtr image;
137
+ char *image_data;
138
+ int size, quality;
139
+ VALUE quality_value;
140
+
141
+ rb_scan_args(argc, argv, "01", &quality_value);
142
+
143
+ if (NIL_P(quality_value)) {
144
+ quality = -1;
145
+ }
146
+ else {
147
+ Check_Type(quality_value, T_FIXNUM);
148
+ quality = FIX2INT(quality_value);
149
+ }
150
+
151
+ if (quality < -1 || quality > 100) {
152
+ rb_raise(rb_eArgError, "Quality must be between 0 and 100, or -1 for default");
153
+ }
154
+
155
+ image = get_image_data(self);
156
+
157
+ image_data = (char *) gdImageJpegPtr(image, &size, quality);
158
+ if (!image_data) {
159
+ rb_raise(rb_eRuntimeError, "Unknown error occurred while trying to build a JPEG");
160
+ }
161
+
162
+ VALUE output = rb_str_new(image_data, size);
163
+ gdFree(image_data);
164
+ return output;
165
+ }
166
+
167
+ VALUE to_png(int argc, VALUE *argv, VALUE self)
168
+ {
169
+ gdImagePtr image;
170
+ char *image_data;
171
+ int size;
172
+ VALUE compression_value;
173
+ int compression;
174
+
175
+ rb_scan_args(argc, argv, "01", &compression_value);
176
+
177
+ image = get_image_data(self);
178
+
179
+ if (NIL_P(compression_value)) {
180
+ image_data = (char *) gdImagePngPtr(image, &size);
181
+ }
182
+ else {
183
+ Check_Type(compression_value, T_FIXNUM);
184
+ compression = FIX2INT(compression_value);
185
+
186
+ if (compression < 0 || compression > 9) {
187
+ rb_raise(rb_eArgError, "Compression must be between 0 and 9");
188
+ }
189
+
190
+ #ifdef HAVE_GDIMAGEPNGPTREX
191
+ image_data = (char *) gdImagePngPtrEx(image, &size, compression);
192
+ #else
193
+ image_data = (char *) gdImagePngPtr(image, &size);
194
+ #endif
195
+ }
196
+
197
+ if (!image_data) {
198
+ rb_raise(rb_eRuntimeError, "Unknown error occurred while trying to build a PNG");
199
+ }
200
+
201
+ VALUE output = rb_str_new(image_data, size);
202
+ gdFree(image_data);
203
+ return output;
204
+ }
205
+
206
+ VALUE resize_bang(VALUE self, VALUE width_value, VALUE height_value)
207
+ {
208
+ gdImagePtr image_in, image_out;
209
+ int width, height;
210
+
211
+ Check_Type(width_value, T_FIXNUM);
212
+ Check_Type(height_value, T_FIXNUM);
213
+
214
+ width = FIX2INT(width_value);
215
+ height = FIX2INT(height_value);
216
+
217
+ if (width < 0 || height < 0) {
218
+ rb_raise(rb_eArgError, "width and height must both be positive integers");
219
+ }
220
+
221
+ image_in = get_image_data(self);
222
+ image_out = gdImageCreateTrueColor(width, height);
223
+ set_alpha(image_out);
224
+
225
+ gdImageCopyResampled(
226
+ image_out, image_in, 0, 0, 0, 0,
227
+ gdImageSX(image_out), gdImageSY(image_out),
228
+ gdImageSX(image_in), gdImageSY(image_in)
229
+ );
230
+
231
+ set_image_data(self, image_out);
232
+
233
+ retrieve_image_dimensions(self);
234
+
235
+ return self;
236
+ }
237
+
238
+ void Init_tinyimg()
239
+ {
240
+ VALUE cTinyimg = rb_define_class("Tinyimg", rb_cObject);
241
+ rb_define_class_under(cTinyimg, "Image", rb_cObject);
242
+
243
+ rb_define_method(cTinyimg, "resize!", resize_bang, 2);
244
+ rb_define_method(cTinyimg, "to_jpeg", to_jpeg, -1);
245
+ rb_define_method(cTinyimg, "to_png", to_png, -1);
246
+ rb_define_private_method(cTinyimg, "initialize_copy", initialize_copy, -1);
247
+ rb_define_private_method(cTinyimg, "load_from_string", load_from_string, 2);
248
+ rb_define_private_method(cTinyimg, "retrieve_image_dimensions", retrieve_image_dimensions, 0);
249
+ #ifdef HAVE_GDIMAGECREATEFROMFILE
250
+ rb_define_private_method(cTinyimg, "load_from_file", load_from_file, 1);
251
+ #endif
252
+ #ifdef HAVE_GDIMAGEFILE
253
+ rb_define_private_method(cTinyimg, "save_to_file", save_to_file, 1);
254
+ #endif
255
+ }
@@ -0,0 +1,138 @@
1
+ require_relative '../ext/tinyimg/tinyimg'
2
+
3
+ class Tinyimg
4
+ attr_reader :width, :height
5
+
6
+ private_class_method :new
7
+
8
+ def self.from_file(filename)
9
+ new(:filename, filename)
10
+ end
11
+
12
+ def self.from_io(io)
13
+ from_string(io.read)
14
+ end
15
+
16
+ def self.from_string(data)
17
+ new(:string, data)
18
+ end
19
+
20
+ def dimensions
21
+ [width, height]
22
+ end
23
+
24
+ def resize(width, height)
25
+ dup.resize!(width, height)
26
+ end
27
+
28
+ # Implemented in C
29
+ # def resize!(width, height)
30
+ # end
31
+
32
+ def resize_to_fit(new_width, new_height)
33
+ dup.resize_to_fit!(new_width, new_height)
34
+ end
35
+
36
+ def resize_to_fit!(new_width, new_height)
37
+ resize_to_fit_or_fill!(new_width, new_height) do |old_ratio, new_ratio|
38
+ old_ratio > new_ratio
39
+ end
40
+ end
41
+
42
+ def resize_to_fill(new_width, new_height)
43
+ dup.resize_to_fill!(new_width, new_height)
44
+ end
45
+
46
+ def resize_to_fill!(new_width, new_height)
47
+ resize_to_fit_or_fill!(new_width, new_height) do |old_ratio, new_ratio|
48
+ old_ratio < new_ratio
49
+ end
50
+ end
51
+
52
+ def save(filename)
53
+ if respond_to?(:save_to_file)
54
+ save_to_file(filename)
55
+ else
56
+ data = case determine_by_extension(filename)
57
+ when :jpeg then to_jpeg
58
+ when :png then to_png
59
+ end
60
+
61
+ File.write(filename, data)
62
+ end
63
+ end
64
+
65
+ # Implemented in C
66
+ # def to_jpeg(quality = DEFAULT_JPEG_QUALITY)
67
+ # end
68
+
69
+ # Implemented in C
70
+ # def to_png(compression = nil)
71
+ # end
72
+
73
+ private
74
+
75
+ def initialize(mode, data, type = nil)
76
+ case mode
77
+ when :string
78
+ load_from_string(data, determine_type(data))
79
+ when :filename
80
+ if respond_to?(:load_from_file)
81
+ load_from_file(data)
82
+ else
83
+ content = File.read(data)
84
+ load_from_string(content, determine_type(content))
85
+ end
86
+ else
87
+ raise
88
+ end
89
+ end
90
+
91
+ def resize_to_fit_or_fill!(new_width, new_height)
92
+ old_ratio = width / height.to_f
93
+ new_ratio = new_width / new_height.to_f
94
+
95
+ if yield(old_ratio, new_ratio)
96
+ resize_width = new_width
97
+ resize_height = (height * (new_width / width.to_f)).to_i
98
+ else
99
+ resize_width = (width * (new_height / height.to_f)).to_i
100
+ resize_height = new_height
101
+ end
102
+
103
+ resize!(resize_width, resize_height)
104
+ end
105
+
106
+ def determine_type(data)
107
+ if data[0, 3].unpack("C*") == [255, 216, 255]
108
+ :jpeg
109
+ elsif data[0, 8].unpack("C*") == [137, 80, 78, 71, 13, 10, 26, 10]
110
+ :png
111
+ else
112
+ raise ArgumentError, "Only JPEG and PNG files are supported"
113
+ end
114
+ end
115
+
116
+ def determine_by_extension(filename)
117
+ case filename.split(".").last.to_s.downcase
118
+ when 'jpeg', 'jpg' then :jpeg
119
+ when 'png' then :png
120
+ else
121
+ raise ArgumentError, "Cannot determine image type based on the filename"
122
+ end
123
+ end
124
+
125
+ # Implemented in C
126
+ # def load_from_string(data, type)
127
+ # end
128
+
129
+ # Implemented in C
130
+ # Only available with libgd 2.1.1+
131
+ # def load_from_file(filename)
132
+ # end
133
+
134
+ # Implemented in C
135
+ # Only available with libgd 2.1.1+
136
+ # def save_to_file(filename)
137
+ # end
138
+ end
Binary file
@@ -0,0 +1,122 @@
1
+ require 'tinyimg'
2
+
3
+ RSpec.describe Tinyimg do
4
+ let(:samples_directory) { "#{File.dirname(__FILE__)}/samples" }
5
+ let(:sample_filename) { "#{samples_directory}/duck.png" }
6
+ let(:sample) { Tinyimg.from_file(sample_filename) }
7
+
8
+ let(:tmp_directory) { "#{File.dirname(__FILE__)}/tmp" }
9
+ let(:tmp_jpg_filename) { "#{tmp_directory}/test.jpg" }
10
+ let(:tmp_png_filename) { "#{tmp_directory}/test.png" }
11
+
12
+ describe "#from_file, #width, #height and #dimensions" do
13
+ it "loads from a file and returns the width and height of the image" do
14
+ expect(sample.width).to eq 200
15
+ expect(sample.height).to eq 153
16
+ expect(sample.dimensions).to eq [200, 153]
17
+ end
18
+ end
19
+
20
+ describe "#from_string" do
21
+ it "loads a PNG" do
22
+ image = Tinyimg.from_string(IO.read(sample_filename))
23
+ expect(image.dimensions).to eq [200, 153]
24
+ end
25
+ end
26
+
27
+ describe "#from_io" do
28
+ it "loads a PNG" do
29
+ File.open(sample_filename, "r") do |file|
30
+ image = Tinyimg.from_io(file)
31
+ expect(image.dimensions).to eq [200, 153]
32
+ end
33
+ end
34
+ end
35
+
36
+ describe "#resize" do
37
+ it "resizes the image as requested, creating a new image" do
38
+ result = sample.resize(100, 100)
39
+ expect(result).to_not eql sample
40
+ expect(sample.dimensions).to eq [200, 153]
41
+ expect(result.dimensions).to eq [100, 100]
42
+ end
43
+ end
44
+
45
+ describe "#resize!" do
46
+ it "resizes the image as requested" do
47
+ result = sample.resize!(100, 100)
48
+ expect(result).to eql sample
49
+ expect(sample.dimensions).to eq [100, 100]
50
+ end
51
+ end
52
+
53
+ describe "#resize_to_fit!" do
54
+ it "calculates the image dimensions so it fits the width and resizes" do
55
+ sample.resize_to_fit!(100, 100)
56
+ expect(sample.dimensions).to eq [100, 76]
57
+ end
58
+
59
+ it "calculates the image dimensions so it fits the height and resizes" do
60
+ sample.resize_to_fit!(1000, 100)
61
+ expect(sample.dimensions).to eq [130, 100]
62
+ end
63
+ end
64
+
65
+ describe "#resize_to_fill!" do
66
+ it "calculates the image dimensions so it fills the width and resizes" do
67
+ sample.resize_to_fill!(1000, 100)
68
+ expect(sample.dimensions).to eq [1000, 765]
69
+ end
70
+
71
+ it "calculates the image dimensions so it fills the height and resizes" do
72
+ sample.resize_to_fill!(100, 100)
73
+ expect(sample.dimensions).to eq [130, 100]
74
+ end
75
+ end
76
+
77
+ describe "#save" do
78
+ it "saves a JPEG" do
79
+ begin
80
+ sample.save(tmp_jpg_filename)
81
+ expect(File.read(tmp_jpg_filename, 3).unpack("C*")).to eq [255, 216, 255]
82
+
83
+ reloaded = Tinyimg.from_file(tmp_jpg_filename)
84
+ expect(reloaded.dimensions).to eq [200, 153]
85
+ ensure
86
+ File.unlink(tmp_jpg_filename)
87
+ end
88
+ end
89
+
90
+ it "saves a PNG" do
91
+ begin
92
+ sample.save(tmp_png_filename)
93
+ expect(File.read(tmp_png_filename, 3).unpack("C*")).to eq [137, 80, 78]
94
+
95
+ reloaded = Tinyimg.from_file(tmp_png_filename)
96
+ expect(reloaded.dimensions).to eq [200, 153]
97
+ ensure
98
+ File.unlink(tmp_png_filename)
99
+ end
100
+ end
101
+ end
102
+
103
+ describe "#to_jpeg" do
104
+ it "exports a JPEG" do
105
+ data = sample.to_jpeg
106
+ expect(data[0, 3].unpack("C*")).to eq [255, 216, 255]
107
+
108
+ reloaded = Tinyimg.from_string(data)
109
+ expect(reloaded.dimensions).to eq [200, 153]
110
+ end
111
+ end
112
+
113
+ describe "#to_png" do
114
+ it "exports a PNG" do
115
+ data = sample.to_png
116
+ expect(data[0, 3].unpack("C*")).to eq [137, 80, 78]
117
+
118
+ reloaded = Tinyimg.from_string(data)
119
+ expect(reloaded.dimensions).to eq [200, 153]
120
+ end
121
+ end
122
+ end
File without changes
@@ -0,0 +1,20 @@
1
+ Gem::Specification.new do |gem|
2
+ gem.name = 'tinyimg'
3
+ gem.version = '0.1.0'
4
+ gem.summary = "Tiny and fast JPEG/PNG resizer and converter"
5
+ gem.description = "Convert between JPEG/PNG and resize images, either all in memory or via disk. Only required libgd to function."
6
+ gem.has_rdoc = false
7
+ gem.author = "Roger Nesbitt"
8
+ gem.email = "roger@seriousorange.com"
9
+ gem.homepage = "http://github.com/mogest/tinyimg"
10
+ gem.license = 'MIT'
11
+
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- spec/*`.split("\n")
14
+ gem.require_paths = ["lib"]
15
+ gem.extensions = %w(ext/tinyimg/extconf.rb)
16
+
17
+ gem.required_ruby_version = '>= 2.0.0'
18
+
19
+ gem.add_development_dependency "rspec", "~> 3.0"
20
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tinyimg
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Roger Nesbitt
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ description: Convert between JPEG/PNG and resize images, either all in memory or via
28
+ disk. Only required libgd to function.
29
+ email: roger@seriousorange.com
30
+ executables: []
31
+ extensions:
32
+ - ext/tinyimg/extconf.rb
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".gitignore"
36
+ - Gemfile
37
+ - Gemfile.lock
38
+ - LICENSE
39
+ - README.md
40
+ - ext/tinyimg/extconf.rb
41
+ - ext/tinyimg/tinyimg.c
42
+ - lib/tinyimg.rb
43
+ - spec/samples/duck.png
44
+ - spec/tinyimg_spec.rb
45
+ - spec/tmp/.keep
46
+ - tinyimg.gemspec
47
+ homepage: http://github.com/mogest/tinyimg
48
+ licenses:
49
+ - MIT
50
+ metadata: {}
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 2.0.0
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project:
67
+ rubygems_version: 2.2.2
68
+ signing_key:
69
+ specification_version: 4
70
+ summary: Tiny and fast JPEG/PNG resizer and converter
71
+ test_files:
72
+ - spec/samples/duck.png
73
+ - spec/tinyimg_spec.rb
74
+ - spec/tmp/.keep