free-image 0.5.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.
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