pikl 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,12 @@
1
+ #ifndef _LIB_PIKL_RESIZE_
2
+ #define _LIB_PIKL_RESIZE_
3
+
4
+ #include <stdio.h>
5
+ #include <stdlib.h>
6
+ #include <string.h>
7
+ #include <math.h>
8
+
9
+ #include "pikl.h"
10
+ #include "pikl_private.h"
11
+
12
+ #endif
@@ -0,0 +1,70 @@
1
+ #include "pikl_rotate.h"
2
+
3
+ //=================================================================================
4
+ // pkl_rotate
5
+ //=================================================================================
6
+ PKLExport int pkl_rotate(PKLImage pkl, PKL_ANGLE angle)
7
+ {
8
+ unsigned char *wrk;
9
+ int rsin, rcos;
10
+ int width, height;
11
+ int sx, sy, ex, ey;
12
+ int i, j, x, y;
13
+
14
+ switch(angle){
15
+ case PKL_ANGLE_000:
16
+ return(0);
17
+ case PKL_ANGLE_090:
18
+ rcos = 0;
19
+ rsin = -1;
20
+ width = pkl->height;
21
+ height = pkl->width;
22
+ sx = -(pkl->height-1);
23
+ sy = 0;
24
+ ex = 0;
25
+ ey = pkl->width-1;
26
+ break;
27
+ case PKL_ANGLE_180:
28
+ rcos = -1;
29
+ rsin = 0;
30
+ width = pkl->width;
31
+ height = pkl->height;
32
+ sx = -(pkl->width-1);
33
+ sy = -(pkl->height-1);
34
+ ex = 0;
35
+ ey = 0;
36
+ break;
37
+ case PKL_ANGLE_270:
38
+ rcos = 0;
39
+ rsin = 1;
40
+ width = pkl->height;
41
+ height = pkl->width;
42
+ sx = 0;
43
+ sy = -(pkl->width-1);
44
+ ex = pkl->height-1;
45
+ ey = 0;
46
+ break;
47
+ default:
48
+ return(1);
49
+ }
50
+
51
+ wrk = malloc(width * height * pkl->channel);
52
+ if(!wrk) return(1);
53
+
54
+ for(i=sy; i<=ey; i++){
55
+ for(j=sx; j<=ex; j++){
56
+ x = rcos * j - rsin * i;
57
+ y = rsin * j + rcos * i;
58
+ memcpy(&wrk[((i-sy)*width+j-sx)*pkl->channel], &pkl->image[(y*pkl->width+x)*pkl->channel], pkl->channel);
59
+ }
60
+ }
61
+
62
+ free(pkl->image);
63
+ pkl->image = wrk;
64
+ pkl->width = width;
65
+ pkl->height = height;
66
+
67
+ return(0);
68
+ }
69
+
70
+
@@ -0,0 +1,12 @@
1
+ #ifndef _LIB_PIKL_ROTATE_
2
+ #define _LIB_PIKL_ROTATE_
3
+
4
+ #include <stdio.h>
5
+ #include <stdlib.h>
6
+ #include <string.h>
7
+ #include <math.h>
8
+
9
+ #include "pikl.h"
10
+ #include "pikl_private.h"
11
+
12
+ #endif
@@ -0,0 +1,28 @@
1
+ #include "pikl_trim.h"
2
+
3
+ //=================================================================================
4
+ // pkl_trim
5
+ //=================================================================================
6
+ PKLExport int pkl_trim(PKLImage pkl, int sx, int sy, int width, int height)
7
+ {
8
+ unsigned char *wrk;
9
+ int p, y;
10
+
11
+ if( sx < 0 || sy < 0 || width <= 0 || height <= 0 ) return(1);
12
+ if( sx+width > pkl->width ) return(1);
13
+ if( sy+height > pkl->height ) return(1);
14
+
15
+ wrk = malloc(height * width * pkl->channel);
16
+ if(!wrk) return(1);
17
+
18
+ for(p=0,y=sy; y<sy+height; p++,y++){
19
+ memcpy(&wrk[p*width*pkl->channel], &pkl->image[(y*pkl->width+sx)*pkl->channel], width*pkl->channel);
20
+ }
21
+
22
+ free(pkl->image);
23
+ pkl->image = wrk;
24
+ pkl->height = height;
25
+ pkl->width = width;
26
+
27
+ return(0);
28
+ }
@@ -0,0 +1,11 @@
1
+ #ifndef _LIB_PIKL_TRIM_
2
+ #define _LIB_PIKL_TRIM_
3
+
4
+ #include <stdio.h>
5
+ #include <stdlib.h>
6
+ #include <string.h>
7
+
8
+ #include "pikl.h"
9
+ #include "pikl_private.h"
10
+
11
+ #endif
data/lib/pikl.rb ADDED
@@ -0,0 +1,14 @@
1
+ #--
2
+ # = Pikl - a simple image library.
3
+ # Author:: Ryota Maruko and Keiko Soejima
4
+ # Copyright:: (c) 2008 Ryota Maruko and Keiko Soejima
5
+ # License:: MIT License
6
+ #++
7
+ $:.unshift(File.dirname(__FILE__)) unless
8
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
9
+ module Pikl
10
+ require "pikl/const"
11
+ require "pikl/ext"
12
+ require "pikl/errors"
13
+ require "pikl/image"
14
+ end
data/lib/pikl/const.rb ADDED
@@ -0,0 +1,49 @@
1
+ module Pikl
2
+
3
+ JPEG = 1
4
+ JPG = JPEG
5
+ PNG = 2
6
+ BITMAP = 3
7
+ BMP = BITMAP
8
+
9
+ ANGLE000 = 0
10
+ ANGLE090 = 1
11
+ ANGLE180 = 2
12
+ ANGLE270 = 3
13
+
14
+ SAMPLE_NN = 1 #nearest neighbor
15
+ SAMPLE_BC = 2 #bicubic(4points)
16
+ SAMPLE_BC2 = 3 #bicubic(16points)
17
+ SAMPLE_PA = 4 #pixcel average(reduce only)
18
+ SAMPLE_LZ = 5 #lanczos
19
+
20
+ SAMPLES = {
21
+ :nearest_neighbor => SAMPLE_NN,
22
+ :bicubic => SAMPLE_BC,
23
+ :bicubic2 => SAMPLE_BC2,
24
+ :pixcel_averate => SAMPLE_PA,
25
+ :lanczoz => SAMPLE_LZ,
26
+ }
27
+
28
+ ROTATE_ANGLE = {
29
+ 0 => ANGLE000,
30
+ 90 => ANGLE090,
31
+ 180 => ANGLE180,
32
+ 270 => ANGLE270,
33
+ 360 => ANGLE000,
34
+ }
35
+
36
+
37
+ EXTENSIONS_FORMATS = {
38
+ "jpeg" => JPEG,
39
+ "jpg" => JPEG,
40
+ "png" => PNG,
41
+ "bmp" => BITMAP,
42
+ }
43
+
44
+ EXTENSIONS = EXTENSIONS_FORMATS.keys
45
+ FORMATS = EXTENSIONS_FORMATS.values.uniq
46
+
47
+ PIX_LIMIT = 6000
48
+
49
+ end
@@ -0,0 +1,7 @@
1
+ module Pikl
2
+
3
+ class ParameterException < Exception; end
4
+
5
+ class ImageProcessException < Exception; end
6
+
7
+ end
data/lib/pikl/ext.rb ADDED
@@ -0,0 +1,32 @@
1
+ module Pikl
2
+ require "dl/import"
3
+ require "dl/struct"
4
+ require "rbconfig"
5
+
6
+ module Ext
7
+ extend DL::Importable
8
+ dlload "#{File.dirname(__FILE__)}/pikl.#{RbConfig::CONFIG['DLEXT']}"
9
+
10
+ typealias("KKImage", "void")
11
+ typealias("PKL_FORMAT", "int")
12
+ typealias("PKL_ANGLE", "int")
13
+ typealias("PKL_SAMPLE", "int")
14
+
15
+ extern "PKLImage *pkl_open(char*)"
16
+ extern "void pkl_close(PKLImage*)"
17
+ extern "int pkl_save(PKLImage*, const char *, PKL_FORMAT)"
18
+ extern "int pkl_compress(PKLImage*, int)"
19
+ extern "PKL_FORMAT pkl_format(PKLImage *)"
20
+ extern "int pkl_width(PKLImage *)"
21
+ extern "int pkl_height(PKLImage *)"
22
+ extern "int pkl_trim(PKLImage *, int, int, int, int)"
23
+ extern "int pkl_rotate(PKLImage *, PKL_ANGLE)"
24
+ extern "int pkl_resize(PKLImage*, int, int, PKL_SAMPLE)"
25
+ extern "int pkl_unsharp(PKLImage *, int, double)"
26
+ extern "int pkl_contrast(PKLImage *, int)"
27
+ extern "int pkl_level(PKLImage *, double, double, double)"
28
+ extern "int pkl_brightness(PKLImage*, int)"
29
+ extern "int pkl_hls(PKLImage*, double, double, double)"
30
+ extern "int pkl_gamma(PKLImage*, double)"
31
+ end
32
+ end
data/lib/pikl/image.rb ADDED
@@ -0,0 +1,219 @@
1
+ module Pikl
2
+
3
+ class Image
4
+
5
+ def self.open(inpath, &block)
6
+ image = Pikl::Image.new(inpath)
7
+ image.instance_variable_set(:@block,block)
8
+
9
+ return image unless block_given?
10
+
11
+ begin
12
+ block.call(image)
13
+ ensure
14
+ image.close if image
15
+ end
16
+
17
+ end
18
+
19
+ def initialize( inpath )
20
+ @pkl_image = Ext.pkl_open(File.expand_path(inpath))
21
+ end
22
+
23
+ def save(outpath, format = nil, compress = nil)
24
+ raise Pikl::ImageProcessException.new("image already closed.") unless @pkl_image
25
+ format ||= @format ||= split_extensions(outpath)
26
+ validate_format(format)
27
+ if compress
28
+ validate_compress(compress)
29
+ Ext.pkl_compress(@pkl_image, compress.to_i)
30
+ end
31
+ Ext.pkl_save(@pkl_image, File.expand_path(outpath), EXTENSIONS_FORMATS[format.to_s] || format.to_i)
32
+ self.close unless(@block)
33
+ end
34
+
35
+ def close()
36
+ Ext.pkl_close(@pkl_image) if @pkl_image
37
+ @pkl_image = nil
38
+ end
39
+
40
+ def width
41
+ Ext.pkl_width(@pkl_image) if(@pkl_image)
42
+ end
43
+
44
+ def height
45
+ Ext.pkl_height(@pkl_image) if(@pkl_image)
46
+ end
47
+
48
+ def format
49
+ Ext.pkl_format(@pkl_image) if(@pkl_image)
50
+ end
51
+
52
+ def trim(x, y, dist_x, dist_y)
53
+ validate_trim(x, y, dist_x, dist_y)
54
+ dist_x = trim_dist(x, self.width, dist_x)
55
+ dist_y = trim_dist(y, self.height, dist_y)
56
+
57
+ Ext.pkl_trim(@pkl_image, x, y, dist_x, dist_y)
58
+ end
59
+
60
+ def trim_dist(start, dist_from, dist_to)
61
+ if dist_to == :auto || dist_to > (dist_from - start)
62
+ dist_to = dist_from - start
63
+ elsif dist_to < 0
64
+ dist_to += (dist_from - start)
65
+ else
66
+ dist_to
67
+ end
68
+ end
69
+
70
+ def rotate(angle)
71
+ validate_rotate(angle)
72
+ Ext.pkl_rotate(@pkl_image, ROTATE_ANGLE[angle.to_i])
73
+ end
74
+
75
+ def resize(width, height, sample = :nearest_neighbor)
76
+ validate_auto(width,height)
77
+
78
+ case sample.class.name
79
+ when 'Symbol', 'String'
80
+ sample = SAMPLES[sample.to_sym]
81
+ end
82
+
83
+ width = self.width * height / self.height if(width == :auto)
84
+ height = self.height * width / self.width if(height == :auto)
85
+
86
+ validate_resize(width, height)
87
+
88
+ Ext.pkl_resize(@pkl_image, width, height, sample)
89
+ end
90
+
91
+ # threshold=0-255
92
+ # threshold=0の時は変化しません
93
+ # threshold=255の時は全ての色にアンシャープ処理が働きます
94
+ # edge=-10 .. 10
95
+ # edge=0の時は変化しません
96
+ # edge>0の時は値が大きいほど先鋭化されます
97
+ # edge<0の時は値が小さいほどぼやけます
98
+ #
99
+ # 想定結果が得られる範囲は-10 .. 10程度です。
100
+ # これを超える場合は、品質の保証はありません
101
+ # ※画質によりこの通りではありません。-10..10の範囲より小さくなる可能性があります。
102
+ def unshapmask(threshold, edge)
103
+ Ext.pkl_unsharp(@pkl_image, threshold.to_i, edge.to_f)
104
+ end
105
+
106
+ # コントラスト調整
107
+ # コントラストを強くするということは、白い部分をより白く、
108
+ # 黒い部分をより黒くするような変換を意味します。
109
+ # 逆にコントラストを弱くした場合、白い部分と黒い部分の差が無くなり、灰色っぽい画像になります。
110
+ # <rate>
111
+ # 範囲:-127 .. 127
112
+ # rate=0の時は変化しません
113
+ # * rateが0以上の時は周波数によるコントラスト強調がおこなわれます
114
+ # * rateが0未満の時は直線的に平坦化されます
115
+ def contrast(rate)
116
+ Ext.pkl_contrast(@pkl_image, rate.to_f)
117
+ end
118
+
119
+ # レベル補正
120
+ # ヒストグラムの平坦化をおこないます。各色の分布に偏りがある画像に有効な場合があります。
121
+ # coeff = 平坦化時の係数です。1が標準です。1より小さい場合は暗く、1より大きい場合は明るくなります(0.0..2.0)
122
+ # low = 全ピクセル数に対して、切り捨てる暗い色の総数の割合(0-100%)
123
+ # high = 全ピクセル数に対して、切り捨てる明るい色の総数の割合(0-100%)
124
+ def level(low, high, coeff)
125
+ Ext.pkl_level(@pkl_image, low.to_f, high.to_f, coeff.to_f)
126
+ end
127
+
128
+ # 明るさ調整
129
+ # この明るさ調整は各色からcolor値を加算する単純な処理です。
130
+ # colorに255を指定すれば、ただの白い画像になります
131
+ # colorに-255を指定すると、ただの黒い画像になります。
132
+ def brightness(color)
133
+ Ext.pkl_brightness(@pkl_image, color.to_i)
134
+ end
135
+
136
+ # 輝度(明るさ)・彩度(鮮やかさ)・色相(色合い)調整
137
+ # * 具体的にどういうことかを理解したい場合は、mspaintの「色の編集」を見ると良いでしょう。
138
+ # ym(輝度) -1 .. 1(0.1で10%up).0では変化なし
139
+ # sm(彩度) -1 .. 1(0.1で10%up).0では変化なし
140
+ # hd(色相) 360.0度回転(R=113.2/Ye=173.0/G=225.0/Cy=293.2/B=353.0/Mg=45.0).360の倍数では変化なし
141
+ def hls(ym, sm ,hd)
142
+ Ext.pkl_hls(@pkl_image, ym.to_f, sm.to_f, hd.to_f)
143
+ end
144
+
145
+ # ガンマ補正
146
+ # ガンマ補正をします。
147
+ # gmは補正係数です。
148
+ # gm=0以上の値が指定できます。
149
+ # 1.0より小さい時は暗く、1.0より大きい時は明るく調整されます。
150
+ # 1.0を指定した時は調整されません。
151
+ def gamma(gm)
152
+ Ext.pkl_gamma(@pkl_image, gm.to_f)
153
+ end
154
+
155
+ # regular expressions to try for identifying extensions
156
+ def split_extensions(path)
157
+ filename = path.split('/').last
158
+ (filename =~ %r|.+\.([a-z,A-Z]+)$|) ? $1 : nil
159
+ end
160
+
161
+ def validate_auto(width, height)
162
+ error("invalid :autoto in the both of width and height.") if(width == :auto && height == :auto)
163
+ end
164
+
165
+ # validate identifying extensions
166
+ def validate_format(ext)
167
+ error(ext) unless (ext || EXTENSIONS.include?(ext.to_s.downcase) || FORMATS.include?(ext.to_i))
168
+ end
169
+
170
+ def validate_trim(x, y, dist_x, dist_y)
171
+ validate_numeric(x, y)
172
+
173
+ validate_pix(dist_x, true)
174
+ validate_pix(dist_y, true)
175
+
176
+ error("left is outside the range. #{x}") if x > self.width.to_i
177
+ error("top is outside the range. #{y}") if y > self.height.to_i
178
+ end
179
+
180
+ def validate_rotate(angle)
181
+ validate_numeric(angle)
182
+ error("invalid angle. # => #{angle}") unless ROTATE_ANGLE.has_key?(angle)
183
+ end
184
+
185
+ def validate_resize(width, height)
186
+ validate_auto(width, height)
187
+ validate_pix(width)
188
+ validate_pix(height)
189
+ end
190
+
191
+ def validate_pix(value, allow_minus = false)
192
+ return if value == :auto
193
+ validate_numeric(value)
194
+ error("value is outside the range. #{value}") if value == 0
195
+ error("value is outside the range. #{value}") if !allow_minus && value < 0
196
+ error("value is outside the range. #{value}") if value > PIX_LIMIT
197
+ end
198
+
199
+ def validate_numeric(*args)
200
+ args = [args] unless args.is_a?(Array)
201
+ args.each do |v|
202
+ error("invalid parameter. # => #{v}") unless /^[-\d]+$/ =~ v.to_s
203
+ end
204
+ end
205
+
206
+ def validate_compress(v)
207
+ error("invalid compress parameter. # => #{v}") unless /^\d+$/ =~ v.to_s
208
+ error("invalid compress parameter. # => #{v}") unless v.to_i >= 0 && v.to_i <= 10
209
+ end
210
+
211
+ def error(message)
212
+ #self.close
213
+ raise Pikl::ParameterException.new(message)
214
+ end
215
+ end
216
+ end
217
+
218
+
219
+