/
raw_image.cr
132 lines (115 loc) · 4.06 KB
/
raw_image.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
module Hpdf
# Raw contains helpers to create in memory gray, rgb and cmyk images.
#
# Example:
# ```
# pdf = Hpdf::Doc.new
# pdf.page do
# gi = Hpdf::Raw::GrayImage.new(4, 4)
# gi[0, 1] = 0x7f
# gi[3, 1] = 0x7f
# gi[1, 2] = 0xff
# gi[2, 2] = 0xff
# img = pdf.load_raw_image_from_mem gi
# draw_image img, 100, 100, 100, 100
# end
# ```
module Raw
abstract class Image
getter width
getter height
getter color_space
# create a new in-memory image
#
# * *width* the width of the image.
# * *height* the height of the image.
# * *color_space* `ColorSpace::DeviceGray` or `ColorSpace::DeviceRgb`
# or `ColorSpace::DeviceCmyk` is allowed.
def initialize(@width : UInt32, @height : UInt32, @color_space : ColorSpace)
case @color_space
when ColorSpace::DeviceGray
@buf = Array(UInt8).new(@width * @height, 0)
when ColorSpace::DeviceRgb
@buf = Array(UInt8).new(@width * @height * 3, 0)
when ColorSpace::DeviceCmyk
@buf = Array(UInt8).new(@width * @height * 4, 0)
else
raise ArgumentError.new("invalid color_space was used: #{@color_space}")
end
end
def to_unsafe
@buf.to_unsafe
end
end
# create a new in-memory image with gray scale. Import using `Doc#load_raw_image_from_mem`
class GrayImage < Image
def initialize(width : UInt32, height : UInt32)
super width, height, ColorSpace::DeviceGray
end
# sets the gray value at `x` and `y` via `scale`.
# `0xff` is white and `0x00` is black.
def gray_at(x : UInt32, y : UInt32, scale : UInt8)
@buf[y*@width + x] = scale
end
# sets the gray value at `x` and `y` via `scale`.
# `0xff` is white and `0x00` is black.
def []=(x : Number, y : Number, scale : Number)
gray_at(x.to_u32, y.to_u32, scale.to_u8)
end
end
# Color mixed of red, green and blue. Import using `Doc#load_raw_image_from_mem`
struct RgbColor
property red, green, blue
def initialize(@red : UInt8, @green : UInt8, @blue : UInt8)
end
def initialize(red : Number, green : Number, blue : Number)
@red = red.to_u8
@green = green.to_u8
@blue = blue.to_u8
end
end
# create a new in-memory RGB image
class RgbImage < Image
def initialize(width : UInt32, height : UInt32)
super width, height, ColorSpace::DeviceRgb
end
# sets the rgb value at `x` and `y`.
def rgb_at(x : UInt32, y : UInt32, red : UInt8, green : UInt8, blue : UInt8)
@buf[y*@width*3 + x*3] = red
@buf[y*@width*3 + x*3 + 1] = green
@buf[y*@width*3 + x*3 + 2] = blue
end
def []=(x : Number, y : Number, color : RgbColor)
rgb_at(x.to_u32, y.to_u32, color.red, color.green, color.blue)
end
end
# Color mixed of cyan, magenta, yellow and black. Import using `Doc#load_raw_image_from_mem`
struct CmykColor
property cyan, magenta, yellow, black
def initialize(@cyan : UInt8, @magenta : UInt8, @yellow : UInt8, @black : UInt8)
end
def initialize(cyan : Number, magenta : Number, yellow : Number, black : Number)
@cyan = cyan.to_u8
@magenta = magenta.to_u8
@yellow = yellow.to_u8
@black = black.to_u8
end
end
# create a new in-memory CMYK image. Import using `Doc#load_raw_image_from_mem`
class CmykImage < Image
def initialize(width : UInt32, height : UInt32)
super width, height, ColorSpace::DeviceCmyk
end
# sets the rgb value at `x` and `y`.
def rgb_at(x : UInt32, y : UInt32, cyan : UInt8, magenta : UInt8, yellow : UInt8, black : UInt8)
@buf[y*@width*4 + x*4] = cyan
@buf[y*@width*4 + x*4 + 1] = magenta
@buf[y*@width*4 + x*4 + 2] = yellow
@buf[y*@width*4 + x*4 + 3] = black
end
def []=(x : Number, y : Number, color : CmykColor)
rgb_at(x.to_u32, y.to_u32, color.cyan, color.magenta, color.yellow, color.black)
end
end
end
end