free-image 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/HISTORY +5 -0
  2. data/LICENSE +21 -0
  3. data/README.rdoc +99 -0
  4. data/Rakefile +47 -0
  5. data/cookbook.rdoc +239 -0
  6. data/free-image.gemspec +30 -0
  7. data/lib/free-image.rb +101 -0
  8. data/lib/free-image/bitmap.rb +154 -0
  9. data/lib/free-image/enums/color_types.rb +24 -0
  10. data/lib/free-image/enums/dithers.rb +24 -0
  11. data/lib/free-image/enums/filters.rb +12 -0
  12. data/lib/free-image/enums/formats.rb +84 -0
  13. data/lib/free-image/enums/image_types.rb +36 -0
  14. data/lib/free-image/errors.rb +44 -0
  15. data/lib/free-image/modules/conversions.rb +166 -0
  16. data/lib/free-image/modules/helper.rb +42 -0
  17. data/lib/free-image/modules/icc.rb +41 -0
  18. data/lib/free-image/modules/information.rb +305 -0
  19. data/lib/free-image/modules/modify.rb +261 -0
  20. data/lib/free-image/modules/pixels.rb +135 -0
  21. data/lib/free-image/modules/transforms.rb +83 -0
  22. data/lib/free-image/palette.rb +44 -0
  23. data/lib/free-image/scanline.rb +151 -0
  24. data/lib/free-image/sources/abstract_source.rb +172 -0
  25. data/lib/free-image/sources/file.rb +115 -0
  26. data/lib/free-image/sources/io.rb +154 -0
  27. data/lib/free-image/sources/memory.rb +189 -0
  28. data/lib/free-image/types/boolean.rb +14 -0
  29. data/lib/free-image/types/complex.rb +9 -0
  30. data/lib/free-image/types/ffi.rb +14 -0
  31. data/lib/free-image/types/rgb16.rb +11 -0
  32. data/lib/free-image/types/rgb_quad.rb +82 -0
  33. data/lib/free-image/types/rgb_triple.rb +42 -0
  34. data/lib/free-image/types/rgba16.rb +12 -0
  35. data/lib/free-image/types/rgbaf.rb +12 -0
  36. data/lib/free-image/types/rgbf.rb +11 -0
  37. data/test/cookbook.rb +46 -0
  38. data/test/images/gradient.png +0 -0
  39. data/test/images/lena.png +0 -0
  40. data/test/images/lena.tiff +0 -0
  41. data/test/images/lena_flipped.png +0 -0
  42. data/test/images/lena_rescale_bicubic.png +0 -0
  43. data/test/images/lena_rescale_bilinear.png +0 -0
  44. data/test/images/lena_rescale_box.png +0 -0
  45. data/test/images/lena_rescale_bspline.png +0 -0
  46. data/test/images/lena_rescale_catmullrom.png +0 -0
  47. data/test/images/lena_rescale_lanczos3.png +0 -0
  48. data/test/images/lena_rotate_45.png +0 -0
  49. data/test/images/lena_rotate_ex_45_masked.png +0 -0
  50. data/test/images/lena_rotate_ex_45_mirrored.png +0 -0
  51. data/test/images/lena_rotate_ex_45_top_left.png +0 -0
  52. data/test/images/lena_thumbnail.png +0 -0
  53. data/test/images/lena_thumbnail_border_enlarge.png +0 -0
  54. data/test/images/lena_thumbnail_border_paste.png +0 -0
  55. data/test/images/lena_thumbnail_border_scanline.png +0 -0
  56. data/test/images/not_an_image.txt +0 -0
  57. data/test/images/sample.png +0 -0
  58. data/test/images/sample_composite_color.png +0 -0
  59. data/test/test_bitmap.rb +43 -0
  60. data/test/test_conversions.rb +86 -0
  61. data/test/test_file.rb +51 -0
  62. data/test/test_free_image.rb +15 -0
  63. data/test/test_helper.rb +35 -0
  64. data/test/test_information.rb +118 -0
  65. data/test/test_io.rb +53 -0
  66. data/test/test_memory.rb +65 -0
  67. data/test/test_modify.rb +59 -0
  68. data/test/test_palette.rb +45 -0
  69. data/test/test_pixels.rb +62 -0
  70. data/test/test_rgb_quad.rb +26 -0
  71. data/test/test_scanline.rb +65 -0
  72. data/test/test_suite.rb +19 -0
  73. data/test/test_transforms.rb +30 -0
  74. metadata +169 -0
@@ -0,0 +1,14 @@
1
+ module FreeImage
2
+ class Boolean
3
+ extend FFI::DataConverter
4
+ native_type :uint32
5
+
6
+ def self.to_native(val, ctx)
7
+ val == false ? 0 : 1
8
+ end
9
+
10
+ def self.from_native(val, ctx)
11
+ val == 0 ? false : true
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: UTF-8
2
+
3
+ module FreeImage
4
+ # Structure for COMPLEX type (complex number) images
5
+ class Complex < FFI::Struct
6
+ layout :r, :double,
7
+ :i, :double
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ module FreeImage
2
+ if !self.msvc?
3
+ typedef :int32, :bool
4
+ typedef :uint32, :byte
5
+ typedef :uint16, :word
6
+ typedef :uint32, :dword
7
+ typedef :int32, :long
8
+ else
9
+ typedef :long, :bool
10
+ typedef :uchar, :byte
11
+ typedef :ushort, :word
12
+ typedef :ulong, :dword
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: UTF-8
2
+
3
+ module FreeImage
4
+ # Used to specify a color for a :rgb16
5
+ # {image type}[rdoc-ref:FreeImage.images_types].
6
+ class RGB16 < FFI::Struct
7
+ layout :red, :word,
8
+ :green, :word,
9
+ :blue, :word
10
+ end
11
+ end
@@ -0,0 +1,82 @@
1
+ # encoding: UTF-8
2
+
3
+ module FreeImage
4
+ # Used to specify a color for a :bitmap
5
+ # {image type}[rdoc-ref:FreeImage.images_types].
6
+ #--
7
+ # This structure is packed with pragma (1)
8
+ class RGBQuad < FFI::Struct
9
+ if FFI::Platform::BYTE_ORDER == FFI::Platform::LITTLE_ENDIAN
10
+ layout :blue, :byte, 0,
11
+ :green, :byte, 1,
12
+ :red, :byte, 2,
13
+ :reserved, :byte, 3
14
+ else
15
+ layout :red, :byte, 0,
16
+ :green, :byte, 1,
17
+ :blue, :byte, 2,
18
+ :reserved, :byte, 3
19
+ end
20
+
21
+ # Define masks to extract colors from bytes
22
+ if FFI::Platform::BYTE_ORDER == FFI::Platform::LITTLE_ENDIAN
23
+ # Little Endian (x86 / MS Windows, Linux) : BGR(A) order
24
+ RED = 2
25
+ GREEN = 1
26
+ BLUE = 0
27
+ ALPHA = 3
28
+ RED_MASK = 0x00FF0000
29
+ GREEN_MASK = 0x0000FF00
30
+ BLUE_MASK = 0x000000FF
31
+ ALPHA_MASK = 0xFF000000
32
+ RED_SHIFT = 16
33
+ GREEN_SHIFT = 8
34
+ BLUE_SHIFT = 0
35
+ ALPHA_SHIFT = 24
36
+ else
37
+ # Big Endian (PPC / Linux, MaxOSX) : RGB(A) order
38
+ RED = 0
39
+ GREEN = 1
40
+ BLUE = 2
41
+ ALPHA = 3
42
+ RED_MASK = 0xFF000000
43
+ GREEN_MASK = 0x00FF0000
44
+ BLUE_MASK = 0x0000FF00
45
+ ALPHA_MASK = 0x000000FF
46
+ RED_SHIFT = 24
47
+ GREEN_SHIFT = 16
48
+ BLUE_SHIFT = 8
49
+ ALPHA_SHIFT = 0
50
+ end
51
+ RGB_MASK = (RED_MASK | GREEN_MASK | BLUE_MASK)
52
+
53
+ # Creates a new RGBQuad color
54
+ #
55
+ # == Parameters
56
+ # red:: Value for red, should be between 0 and 255
57
+ # green:: Value for green, should be between 0 and 255
58
+ # blue:: Value for blue, should be between 0 and 255
59
+ # reserved:: Reserved value, by default is 0
60
+ def self.create(red, green, blue, reserved = 0)
61
+ result = self.new
62
+ result[:red] = red
63
+ result[:green] = green
64
+ result[:blue] = blue
65
+ result[:reserved] = reserved
66
+ result
67
+ end
68
+
69
+ def eql?(other)
70
+ other.instance_of?(RGBQuad) and
71
+ self[:red] == other[:red] and
72
+ self[:green] == other[:green] and
73
+ self[:blue] == other[:blue] and
74
+ self[:reserved] == other[:reserved]
75
+ end
76
+ alias :== :eql?
77
+
78
+ def to_s
79
+ "RGBQuad - Red: #{self[:red]}, Green: #{self[:green]}, Blue: #{self[:blue]}, Alpha: #{self[:reserved]}"
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,42 @@
1
+ # encoding: UTF-8
2
+
3
+ module FreeImage
4
+ class RGBTriple < FFI::Struct
5
+ if FFI::Platform::BYTE_ORDER == FFI::Platform::LITTLE_ENDIAN
6
+ layout :blue, :byte, 0,
7
+ :green, :byte, 1,
8
+ :red, :byte, 2
9
+ else
10
+ layout :red, :byte, 0,
11
+ :green, :byte, 1,
12
+ :blue, :byte, 2
13
+ end
14
+
15
+ # Creates a new RGBTriple color
16
+ #
17
+ # == Parameters
18
+ # red:: Value for red, should be between 0 and 255
19
+ # green:: Value for green, should be between 0 and 255
20
+ # blue:: Value for blue, should be between 0 and 255
21
+ #
22
+ def self.create(red, green, blue)
23
+ result = self.new
24
+ result[:red] = red
25
+ result[:green] = green
26
+ result[:blue] = blue
27
+ result
28
+ end
29
+
30
+ def eql?(other)
31
+ other.instance_of?(RGBQuad) and
32
+ self[:red] == other[:red] and
33
+ self[:green] == other[:green] and
34
+ self[:blue] == other[:blue]
35
+ end
36
+ alias :== :eql?
37
+
38
+ def to_s
39
+ "RGBQuad - Red: #{self[:red]}, Green: #{self[:green]}, Blue: #{self[:blue]}"
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,12 @@
1
+ # encoding: UTF-8
2
+
3
+ module FreeImage
4
+ # Used to specify a color for a :rgb16a
5
+ # {image type}[rdoc-ref:FreeImage.images_types].
6
+ class RGBA16 < FFI::Struct
7
+ layout :red, :word,
8
+ :green, :word,
9
+ :blue, :word,
10
+ :alpha, :word
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # encoding: UTF-8
2
+
3
+ module FreeImage
4
+ # Used to specify a color for a :rgbaf
5
+ # {image type}[rdoc-ref:FreeImage.images_types].
6
+ class RGBAF < FFI::Struct
7
+ layout :red, :float,
8
+ :green, :float,
9
+ :blue, :float,
10
+ :alpha, :float
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: UTF-8
2
+
3
+ module FreeImage
4
+ # Used to specify a color for a :rgbf
5
+ # {image type}[rdoc-ref:FreeImage.images_types].
6
+ class RGBF < FFI::Struct
7
+ layout :red, :float,
8
+ :green, :float,
9
+ :blue, :float
10
+ end
11
+ end
@@ -0,0 +1,46 @@
1
+ # encoding: UTF-8
2
+
3
+ require './test_helper'
4
+ require 'test/unit'
5
+
6
+ def set_to_red(color)
7
+ color[:red] = 255
8
+ color[:green] = 0
9
+ color[:blue] = 0
10
+ end
11
+
12
+ image = FreeImage::Bitmap.open('images/lena.png')
13
+ thumbnail = image.make_thumbnail(100)
14
+
15
+ # Make the bottom row red
16
+ scanline = thumbnail.scanline(0)
17
+
18
+ # Draw bottom border
19
+ (0..3).each do |index|
20
+ scanline = thumbnail.scanline(index)
21
+ scanline.each do |color|
22
+ set_to_red(color)
23
+ end
24
+ end
25
+
26
+ # Draw top border
27
+ ((thumbnail.height - 5)..(thumbnail.height - 1)).each do |index|
28
+ scanline = thumbnail.scanline(index)
29
+ scanline.each do |color|
30
+ set_to_red(color)
31
+ end
32
+ end
33
+
34
+ # Draw left and right borders
35
+ (1..(thumbnail.height - 2)).each do |index|
36
+ scanline = thumbnail.scanline(index)
37
+ (0..4).each do |index|
38
+ set_to_red(scanline[index])
39
+ end
40
+
41
+ ((thumbnail.width - 5)..(thumbnail.width - 1)).each do |index|
42
+ set_to_red(scanline[index])
43
+ end
44
+ end
45
+
46
+ thumbnail.save("images/lena_thumbnail_border_scanline.png", :png)
Binary file
Binary file
Binary file
File without changes
Binary file
@@ -0,0 +1,43 @@
1
+ # encoding: UTF-8
2
+
3
+ require './test_helper'
4
+ require 'test/unit'
5
+
6
+ class BitmapTest < Test::Unit::TestCase
7
+ def test_bits
8
+ bytes = sample_image.bits
9
+ assert_equal(6466, bytes.size)
10
+
11
+ if defined?(Encoding)
12
+ assert_equal(Encoding::BINARY, bytes.encoding)
13
+ assert_equal(bytes.size, bytes.bytesize)
14
+ end
15
+ end
16
+
17
+ def test_open
18
+ bitmap = FreeImage::Bitmap.open('images/lena.png')
19
+ assert_kind_of(FreeImage::Bitmap, bitmap)
20
+ end
21
+
22
+ def test_open_yield
23
+ result = FreeImage::Bitmap.open('images/lena.png') do |bitmap|
24
+ assert_kind_of(FreeImage::Bitmap, bitmap)
25
+ end
26
+ assert_equal(true, result)
27
+ end
28
+
29
+ def test_open_yield_error
30
+ assert_raise(ArgumentError) do
31
+ FreeImage::Bitmap.open('images/lena.png') do |bitmap|
32
+ raise(ArgumentError, "Let's mess things up")
33
+ end
34
+ end
35
+ end
36
+
37
+ def test_free
38
+ 1000.times do
39
+ image = sample_image
40
+ image.free
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,86 @@
1
+ # encoding: UTF-8
2
+
3
+ require './test_helper'
4
+ require 'test/unit'
5
+
6
+ class ConverstionsTest < Test::Unit::TestCase
7
+ def test_convert_to_4bits
8
+ bitmap = sample_image.convert_to_4bits
9
+ assert_kind_of(FreeImage::Bitmap, bitmap)
10
+ assert_equal(4, bitmap.bits_per_pixel)
11
+ end
12
+
13
+ def test_convert_to_8bits
14
+ bitmap = sample_image.convert_to_8bits
15
+ assert_kind_of(FreeImage::Bitmap, bitmap)
16
+ assert_equal(8, bitmap.bits_per_pixel)
17
+ end
18
+
19
+ def test_convert_to_greyscale
20
+ bitmap = sample_image.convert_to_greyscale
21
+ assert_kind_of(FreeImage::Bitmap, bitmap)
22
+ assert_equal(8, bitmap.bits_per_pixel)
23
+ end
24
+
25
+ def test_convert_to_16bits_555
26
+ bitmap = sample_image.convert_to_16bits_555
27
+ assert_kind_of(FreeImage::Bitmap, bitmap)
28
+ assert_equal(16, bitmap.bits_per_pixel)
29
+ end
30
+
31
+ def test_convert_to_16bits_565
32
+ bitmap = sample_image.convert_to_16bits_565
33
+ assert_kind_of(FreeImage::Bitmap, bitmap)
34
+ assert_equal(16, bitmap.bits_per_pixel)
35
+ end
36
+
37
+ def test_convert_to_24bits
38
+ bitmap = sample_image.convert_to_24bits
39
+ assert_kind_of(FreeImage::Bitmap, bitmap)
40
+ assert_equal(24, bitmap.bits_per_pixel)
41
+ end
42
+
43
+ def test_convert_to_32bits
44
+ bitmap = sample_image.convert_to_32bits
45
+ assert_kind_of(FreeImage::Bitmap, bitmap)
46
+ assert_equal(32, bitmap.bits_per_pixel)
47
+ end
48
+
49
+ def test_convert_to_standard_type
50
+ bitmap = sample_image.convert_to_standard_type
51
+ assert_kind_of(FreeImage::Bitmap, bitmap)
52
+ assert_equal(8, bitmap.bits_per_pixel)
53
+ end
54
+
55
+ def test_convert_to_type
56
+ bitmap = sample_image.convert_to_type(:rgb16)
57
+ assert_kind_of(FreeImage::Bitmap, bitmap)
58
+ assert_equal(48, bitmap.bits_per_pixel)
59
+ end
60
+
61
+ def test_dither
62
+ bitmap = sample_image.dither(:bayer4x4)
63
+ assert_kind_of(FreeImage::Bitmap, bitmap)
64
+ assert_equal(1, bitmap.bits_per_pixel)
65
+ end
66
+
67
+ def test_threshold
68
+ bitmap = sample_image.threshold(7)
69
+ assert_kind_of(FreeImage::Bitmap, bitmap)
70
+ assert_equal(1, bitmap.bits_per_pixel)
71
+ end
72
+
73
+ def test_threshold_low
74
+ error = assert_raise(RangeError) do
75
+ sample_image.threshold(-1)
76
+ end
77
+ assert_equal("Value is out of range 0..255. Value: -1", error.message)
78
+ end
79
+
80
+ def test_threshold_hight
81
+ error = assert_raise(RangeError) do
82
+ sample_image.threshold(5555)
83
+ end
84
+ assert_equal("Value is out of range 0..255. Value: 5555", error.message)
85
+ end
86
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: UTF-8
2
+
3
+ require './test_helper'
4
+ require 'test/unit'
5
+
6
+ class FIFileTest < Test::Unit::TestCase
7
+ def file(image = 'sample.png')
8
+ path = image_path(image)
9
+ FreeImage::File.new(path)
10
+ end
11
+
12
+ def test_format
13
+ assert_equal(:png, file.format)
14
+ end
15
+
16
+ def test_format_unknown
17
+ assert_equal(:unknown, file('not_an_image.txt').format)
18
+ end
19
+
20
+ def test_load
21
+ bitmap = file.open
22
+ assert_kind_of(FreeImage::Bitmap, bitmap)
23
+ end
24
+
25
+ def test_load_format
26
+ error = assert_raise(FreeImage::Error) do
27
+ file('not_an_image.txt').open
28
+ end
29
+ assert_equal('Cannot load :unknown image format', error.to_s)
30
+ end
31
+
32
+ def test_load_wrong_format
33
+ error = assert_raise(FreeImage::Error) do
34
+ file.open(:jpeg)
35
+ end
36
+ assert_equal("Not a JPEG file: starts with 0x89 0x50", error.to_s)
37
+ end
38
+
39
+ def test_save
40
+ tmp_file = Tempfile.new('test_free_image')
41
+ dst = FreeImage::File.new(tmp_file.path)
42
+
43
+ bitmap = file.open
44
+ result = bitmap.save(dst, :png)
45
+ assert(result)
46
+ assert(File.exists?(tmp_file))
47
+ ensure
48
+ tmp_file.close
49
+ tmp_file.unlink
50
+ end
51
+ end