fastimage 1.3.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 41430d6372593b80ee08688d0d5ba73e6b75afe7
4
- data.tar.gz: 6c087874cf7dc4fbc330bdc57b07d7e2a8adec2c
3
+ metadata.gz: fc7eb99ff0f61cddf103ac901c5bda2d37f83752
4
+ data.tar.gz: fccb0a33cfccefc1400c4d7c3c27a1124d2b6400
5
5
  SHA512:
6
- metadata.gz: 8c8a4315619a334e8de54d5162a7a96a1de1aadb272b7ad1bdb530559a4f465d4f821680c2ff06e9650c1f5b7130a803c0549a45086b9f6ef4d468269493b558
7
- data.tar.gz: ad654e975fd54b5f7d3fd583d4d03bbae3d3b143622f292aa859f43c18d3d89279274bce3a271e2339da43b42a66c775557b4a6b4b3278c1bdd6f5e36f31d128
6
+ metadata.gz: 000bc8011c9da184973abc60e5b119fd5a8ef8b1d3657cd80dd26ae12c67298d1dcd73ad7d2ed60c783be8d4542f1f57228e6c0b888ebb313499739173c5ec7b
7
+ data.tar.gz: fa02a8dfdaf54cc85e94fa468839b2c2fb718f35c4199959859109925f20c3fa63fcf6574fcce83c22a13cda94ccc4caed6f05eb82a907a635d4bc7f59c9fe55
data/README.textile CHANGED
@@ -10,7 +10,7 @@ But the image is not locally stored - it's on another asset server, or in the cl
10
10
 
11
11
  You don't want to download the entire image to your app server - it could be many tens of kilobytes, or even megabytes just to get this information. For most image types, the size of the image is simply stored at the start of the file. For JPEG files it's a little bit more complex, but even so you do not need to fetch much of the image to find the size.
12
12
 
13
- FastImage does this minimal fetch for image types GIF, JPEG, PNG and BMP. And it doesn't rely on installing external libraries such as RMagick (which relies on ImageMagick or GraphicsMagick) or ImageScience (which relies on FreeImage).
13
+ FastImage does this minimal fetch for image types GIF, JPEG, PNG, TIFF and BMP. And it doesn't rely on installing external libraries such as RMagick (which relies on ImageMagick or GraphicsMagick) or ImageScience (which relies on FreeImage).
14
14
 
15
15
  You only need supply the uri, and FastImage will do the rest.
16
16
 
@@ -70,13 +70,13 @@ h2. Tests
70
70
 
71
71
  You'll need to @gem install fakeweb@ to be able to run the tests.
72
72
 
73
- bc.. ruby ./test/test.rb
74
- Loaded suite test/test
75
- Started
76
- ...............
77
- Finished in 0.059392 seconds.
73
+ bc.. $ ruby test.rb
74
+ Run options:
78
75
 
79
- 15 tests, 27 assertions, 0 failures, 0 errors
76
+ # Running tests:
77
+
78
+ Finished tests in 1.033640s, 23.2189 tests/s, 82.2337 assertions/s.
79
+ 24 tests, 85 assertions, 0 failures, 0 errors, 0 skips
80
80
 
81
81
  h2. References
82
82
 
@@ -84,6 +84,7 @@ h2. References
84
84
  * "DZone - Determine Image Size":http://snippets.dzone.com/posts/show/805
85
85
  * "Antti Kupila - Getting JPG dimensions with AS3 without loading the entire file":http://www.anttikupila.com/flash/getting-jpg-dimensions-with-as3-without-loading-the-entire-file/
86
86
  * "imagesize gem documentation":http://imagesize.rubyforge.org/
87
+ * "EXIF Reader":https://github.com/remvee/exifr
87
88
 
88
89
  h2. Licence
89
90
 
data/lib/fastimage.rb CHANGED
@@ -8,7 +8,7 @@
8
8
  # No external libraries such as ImageMagick are used here, this is a very lightweight solution to
9
9
  # finding image information.
10
10
  #
11
- # FastImage knows about GIF, JPEG, BMP and PNG files.
11
+ # FastImage knows about GIF, JPEG, BMP, TIFF and PNG files.
12
12
  #
13
13
  # FastImage can also read files from the local filesystem by supplying the path instead of a uri.
14
14
  # In this case FastImage uses the open-uri library to read the file in chunks of 256 bytes until
@@ -37,13 +37,17 @@
37
37
  # * http://www.anttikupila.com/flash/getting-jpg-dimensions-with-as3-without-loading-the-entire-file/
38
38
  # * http://pennysmalls.wordpress.com/2008/08/19/find-jpeg-dimensions-fast-in-pure-ruby-no-ima/
39
39
  # * http://imagesize.rubyforge.org/
40
+ # * https://github.com/remvee/exifr
40
41
  #
41
42
 
42
43
  require 'net/https'
43
44
  require 'open-uri'
45
+ require 'fastimage/fbr.rb'
44
46
 
45
47
  class FastImage
46
48
  attr_reader :size, :type
49
+
50
+ attr_reader :bytes_read
47
51
 
48
52
  class FastImageException < StandardError # :nodoc:
49
53
  end
@@ -55,6 +59,8 @@ class FastImage
55
59
  end
56
60
  class SizeNotFound < FastImageException # :nodoc:
57
61
  end
62
+ class CannotParseImage < FastImageException # :nodoc:
63
+ end
58
64
 
59
65
  DefaultTimeout = 2
60
66
 
@@ -69,7 +75,7 @@ class FastImage
69
75
  # If you wish FastImage to raise if it cannot size the image for any reason, then pass
70
76
  # :raise_on_failure => true in the options.
71
77
  #
72
- # FastImage knows about GIF, JPEG, BMP and PNG files.
78
+ # FastImage knows about GIF, JPEG, BMP, TIFF and PNG files.
73
79
  #
74
80
  # === Example
75
81
  #
@@ -133,6 +139,8 @@ class FastImage
133
139
  # => nil
134
140
  # File.open("/some/local/file.gif", "r") {|io| FastImage.type(io)}
135
141
  # => :gif
142
+ # FastImage.type("test/fixtures/test.tiff")
143
+ # => :tiff
136
144
  #
137
145
  # === Supported options
138
146
  # [:timeout]
@@ -164,7 +172,9 @@ class FastImage
164
172
  end
165
173
  end
166
174
  end
175
+
167
176
  raise SizeNotFound if options[:raise_on_failure] && @property == :size && !@size
177
+
168
178
  rescue Timeout::Error, SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ECONNRESET,
169
179
  ImageFetchFailure, Net::HTTPBadResponse, EOFError, Errno::ENOENT
170
180
  raise ImageFetchFailure if options[:raise_on_failure]
@@ -172,6 +182,15 @@ class FastImage
172
182
  raise ImageFetchFailure if options[:raise_on_failure]
173
183
  rescue UnknownImageType
174
184
  raise UnknownImageType if options[:raise_on_failure]
185
+ rescue CannotParseImage
186
+ if options[:raise_on_failure]
187
+ if @property == :size
188
+ raise SizeNotFound
189
+ else
190
+ raise ImageFetchFailure
191
+ end
192
+ end
193
+
175
194
  end
176
195
 
177
196
  private
@@ -198,10 +217,14 @@ class FastImage
198
217
 
199
218
  raise ImageFetchFailure unless res.is_a?(Net::HTTPSuccess)
200
219
 
201
- res.read_body do |str|
202
- break if parse_packet(str)
220
+ @read_fiber = Fiber.new do
221
+ res.read_body do |str|
222
+ Fiber.yield str
223
+ end
203
224
  end
204
225
 
226
+ parse_packets
227
+
205
228
  break # needed to actively quit out of the fetch
206
229
  end
207
230
  end
@@ -231,9 +254,13 @@ class FastImage
231
254
  end
232
255
 
233
256
  def fetch_using_read(readable)
234
- while str = readable.read(LocalFileChunkSize)
235
- break if parse_packet(str)
257
+ @read_fiber = Fiber.new do
258
+ while str = readable.read(LocalFileChunkSize)
259
+ Fiber.yield str
260
+ end
236
261
  end
262
+
263
+ parse_packets
237
264
  end
238
265
 
239
266
  def fetch_using_open_uri
@@ -242,20 +269,21 @@ class FastImage
242
269
  end
243
270
  end
244
271
 
245
- # returns true once result is achieved
246
- #
247
- def parse_packet(str)
248
- @str = (@unused_str || "") + str
272
+ def parse_packets
273
+ @str = ""
249
274
  @str.force_encoding("ASCII-8BIT") if has_encoding?
250
275
  @strpos = 0
276
+ @bytes_read = 0
277
+
251
278
  begin
252
279
  result = send("parse_#{@property}")
253
280
  if result
254
281
  instance_variable_set("@#{@property}", result)
255
- true
282
+ else
283
+ raise CannotParseImage
256
284
  end
257
- rescue MoreCharsNeeded
258
- false
285
+ rescue FiberError
286
+ raise CannotParseImage
259
287
  end
260
288
  end
261
289
 
@@ -274,15 +302,25 @@ class FastImage
274
302
  end
275
303
 
276
304
  def get_chars(n)
277
- if @strpos + n - 1 >= @str.size
278
- @unused_str = @str[@strpos..-1]
279
- raise MoreCharsNeeded
280
- else
281
- result = @str[@strpos..(@strpos + n - 1)]
282
- @strpos += n
305
+ while @strpos + n - 1 >= @str.size
306
+ unused_str = @str[@strpos..-1]
307
+ new_string = @read_fiber.resume
308
+ raise CannotParseImage if !new_string
309
+
283
310
  # we are dealing with bytes here, so force the encoding
284
- has_encoding? ? result.force_encoding("ASCII-8BIT") : result
311
+ if has_encoding?
312
+ new_string.force_encoding("ASCII-8BIT")
313
+ end
314
+
315
+ @bytes_read += new_string.size
316
+
317
+ @str = unused_str + new_string
318
+ @strpos = 0
285
319
  end
320
+
321
+ result = @str[@strpos..(@strpos + n - 1)]
322
+ @strpos += n
323
+ result
286
324
  end
287
325
 
288
326
  def get_byte
@@ -304,6 +342,10 @@ class FastImage
304
342
  :jpeg
305
343
  when 0x89.chr + "P"
306
344
  :png
345
+ when "II"
346
+ :tiff
347
+ when "MM"
348
+ :tiff
307
349
  else
308
350
  raise UnknownImageType
309
351
  end
@@ -353,4 +395,37 @@ class FastImage
353
395
  d = get_chars(29)[14..28]
354
396
  d.unpack("C")[0] == 40 ? d[4..-1].unpack('LL') : d[4..8].unpack('SS')
355
397
  end
398
+
399
+ def parse_size_for_tiff
400
+ byte_order = get_chars(2)
401
+ case byte_order
402
+ when 'II'; short, long = 'v', 'V'
403
+ when 'MM'; short, long = 'n', 'N'
404
+ end
405
+ get_chars(2) # 42
406
+
407
+ offset = get_chars(4).unpack(long)[0]
408
+ get_chars(offset - 8)
409
+
410
+ width = height = nil
411
+
412
+ tag_count = get_chars(2).unpack(short)[0]
413
+ tag_count.downto(1) do
414
+ type = get_chars(2).unpack(short)[0]
415
+ get_chars(6)
416
+ data = get_chars(2).unpack(short)[0]
417
+ case type
418
+ when 0x0100 # image width
419
+ width = data
420
+ when 0x0101 # image height
421
+ height = data
422
+ end
423
+ if width && height
424
+ return [width, height]
425
+ end
426
+ get_chars(2)
427
+ end
428
+
429
+ raise CannotParseImage
430
+ end
356
431
  end
@@ -0,0 +1,67 @@
1
+ # Poor Man's Fiber (API compatible Thread based Fiber implementation for Ruby 1.8)
2
+ # (c) 2008 Aman Gupta (tmm1)
3
+
4
+ unless defined? Fiber
5
+ require 'thread'
6
+
7
+ class FiberError < StandardError; # :nodoc:
8
+ end
9
+
10
+ class Fiber # :nodoc:
11
+ def initialize
12
+ raise ArgumentError, 'new Fiber requires a block' unless block_given?
13
+
14
+ @yield = Queue.new
15
+ @resume = Queue.new
16
+
17
+ @thread = Thread.new{ @yield.push [yield(*@resume.pop)] }
18
+ @thread.abort_on_exception = true
19
+ @thread[:fiber] = self
20
+ end
21
+ attr_reader :thread
22
+
23
+ def resume *args
24
+ raise FiberError, 'dead fiber called' unless @thread.alive?
25
+ @resume.push(args)
26
+ result = @yield.pop
27
+ result.size > 1 ? result : result.first
28
+ end
29
+
30
+ def yield *args
31
+ @yield.push(args)
32
+ result = @resume.pop
33
+ result.size > 1 ? result : result.first
34
+ end
35
+
36
+ def self.yield *args
37
+ if fiber = Thread.current[:fiber]
38
+ fiber.yield(*args)
39
+ else
40
+ raise FiberError, 'not inside a fiber'
41
+ end
42
+ end
43
+
44
+ def self.current
45
+ if Thread.current == Thread.main
46
+ return Thread.main[:fiber] ||= RootFiber.new
47
+ end
48
+
49
+ Thread.current[:fiber] or raise FiberError, 'not inside a fiber'
50
+ end
51
+
52
+ def inspect
53
+ "#<#{self.class}:0x#{self.object_id.to_s(16)}>"
54
+ end
55
+ end
56
+
57
+ class RootFiber < Fiber # :nodoc:
58
+ def initialize
59
+ # XXX: what is a root fiber anyway?
60
+ end
61
+
62
+ def self.yield *args
63
+ raise FiberError, "can't yield from root fiber"
64
+ end
65
+ end
66
+ end
67
+
Binary file
Binary file
data/test/test.rb CHANGED
@@ -3,9 +3,9 @@ require 'rubygems'
3
3
  require 'test/unit'
4
4
 
5
5
  PathHere = File.dirname(__FILE__)
6
+ $LOAD_PATH.unshift File.join(PathHere, "..", "lib")
6
7
 
7
- require File.join(PathHere, "..", "lib", 'fastimage')
8
-
8
+ require 'fastimage'
9
9
  require 'fakeweb'
10
10
 
11
11
  FixturePath = File.join(PathHere, "fixtures")
@@ -16,7 +16,9 @@ GoodFixtures = {
16
16
  "test.jpg"=>[:jpeg, [882, 470]],
17
17
  "test.png"=>[:png, [30, 20]],
18
18
  "test2.jpg"=>[:jpeg, [250, 188]],
19
- "test3.jpg"=>[:jpeg, [630,367]]
19
+ "test3.jpg"=>[:jpeg, [630, 367]],
20
+ "test.tiff"=>[:tiff, [85, 67]],
21
+ "test2.tiff"=>[:tiff, [333, 225]]
20
22
  }
21
23
 
22
24
  BadFixtures = [
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastimage
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Sykes
@@ -21,6 +21,7 @@ files:
21
21
  - MIT-LICENSE
22
22
  - README.textile
23
23
  - lib/fastimage.rb
24
+ - lib/fastimage/fbr.rb
24
25
  - test/fixtures/faulty.jpg
25
26
  - test/fixtures/test.bmp
26
27
  - test/fixtures/test.gif
@@ -29,6 +30,8 @@ files:
29
30
  - test/fixtures/test.png
30
31
  - test/fixtures/test2.jpg
31
32
  - test/fixtures/test3.jpg
33
+ - test/fixtures/test.tiff
34
+ - test/fixtures/test2.tiff
32
35
  - test/fixtures/folder with spaces/test.bmp
33
36
  - test/test.rb
34
37
  homepage: http://github.com/sdsykes/fastimage