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.
- data/HISTORY +5 -0
- data/LICENSE +21 -0
- data/README.rdoc +99 -0
- data/Rakefile +47 -0
- data/cookbook.rdoc +239 -0
- data/free-image.gemspec +30 -0
- data/lib/free-image.rb +101 -0
- data/lib/free-image/bitmap.rb +154 -0
- data/lib/free-image/enums/color_types.rb +24 -0
- data/lib/free-image/enums/dithers.rb +24 -0
- data/lib/free-image/enums/filters.rb +12 -0
- data/lib/free-image/enums/formats.rb +84 -0
- data/lib/free-image/enums/image_types.rb +36 -0
- data/lib/free-image/errors.rb +44 -0
- data/lib/free-image/modules/conversions.rb +166 -0
- data/lib/free-image/modules/helper.rb +42 -0
- data/lib/free-image/modules/icc.rb +41 -0
- data/lib/free-image/modules/information.rb +305 -0
- data/lib/free-image/modules/modify.rb +261 -0
- data/lib/free-image/modules/pixels.rb +135 -0
- data/lib/free-image/modules/transforms.rb +83 -0
- data/lib/free-image/palette.rb +44 -0
- data/lib/free-image/scanline.rb +151 -0
- data/lib/free-image/sources/abstract_source.rb +172 -0
- data/lib/free-image/sources/file.rb +115 -0
- data/lib/free-image/sources/io.rb +154 -0
- data/lib/free-image/sources/memory.rb +189 -0
- data/lib/free-image/types/boolean.rb +14 -0
- data/lib/free-image/types/complex.rb +9 -0
- data/lib/free-image/types/ffi.rb +14 -0
- data/lib/free-image/types/rgb16.rb +11 -0
- data/lib/free-image/types/rgb_quad.rb +82 -0
- data/lib/free-image/types/rgb_triple.rb +42 -0
- data/lib/free-image/types/rgba16.rb +12 -0
- data/lib/free-image/types/rgbaf.rb +12 -0
- data/lib/free-image/types/rgbf.rb +11 -0
- data/test/cookbook.rb +46 -0
- data/test/images/gradient.png +0 -0
- data/test/images/lena.png +0 -0
- data/test/images/lena.tiff +0 -0
- data/test/images/lena_flipped.png +0 -0
- data/test/images/lena_rescale_bicubic.png +0 -0
- data/test/images/lena_rescale_bilinear.png +0 -0
- data/test/images/lena_rescale_box.png +0 -0
- data/test/images/lena_rescale_bspline.png +0 -0
- data/test/images/lena_rescale_catmullrom.png +0 -0
- data/test/images/lena_rescale_lanczos3.png +0 -0
- data/test/images/lena_rotate_45.png +0 -0
- data/test/images/lena_rotate_ex_45_masked.png +0 -0
- data/test/images/lena_rotate_ex_45_mirrored.png +0 -0
- data/test/images/lena_rotate_ex_45_top_left.png +0 -0
- data/test/images/lena_thumbnail.png +0 -0
- data/test/images/lena_thumbnail_border_enlarge.png +0 -0
- data/test/images/lena_thumbnail_border_paste.png +0 -0
- data/test/images/lena_thumbnail_border_scanline.png +0 -0
- data/test/images/not_an_image.txt +0 -0
- data/test/images/sample.png +0 -0
- data/test/images/sample_composite_color.png +0 -0
- data/test/test_bitmap.rb +43 -0
- data/test/test_conversions.rb +86 -0
- data/test/test_file.rb +51 -0
- data/test/test_free_image.rb +15 -0
- data/test/test_helper.rb +35 -0
- data/test/test_information.rb +118 -0
- data/test/test_io.rb +53 -0
- data/test/test_memory.rb +65 -0
- data/test/test_modify.rb +59 -0
- data/test/test_palette.rb +45 -0
- data/test/test_pixels.rb +62 -0
- data/test/test_rgb_quad.rb +26 -0
- data/test/test_scanline.rb +65 -0
- data/test/test_suite.rb +19 -0
- data/test/test_transforms.rb +30 -0
- metadata +169 -0
@@ -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,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
|
data/test/cookbook.rb
ADDED
@@ -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
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
File without changes
|
Binary file
|
Binary file
|
data/test/test_bitmap.rb
ADDED
@@ -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
|
data/test/test_file.rb
ADDED
@@ -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
|