Class: Pxlsrt::Smart

Inherits:
Object
  • Object
show all
Defined in:
lib/pxlsrt/smart.rb

Overview

sorteds, just a specified range to create bands.

Class Method Summary collapse

Class Method Details

.smart(input, o = {}) ⇒ Object

The main attraction of the Smart class. Returns a ChunkyPNG::Image that is sorted according to the options provided. Will return nil if it encounters an errors.



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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/pxlsrt/smart.rb', line 20

def self.smart(input, o={})
	startTime=Time.now
	defOptions={
		:reverse => "no",
		:vertical => false,
		:diagonal => false,
		:smooth => false,
		:method => "sum-rgb",
		:verbose => false,
		:absolute => false,
		:threshold => 20,
		:sorted => 2,
		:trusted => false,
		:middle => false
	}
	defRules={
		:reverse => ["no", "reverse", "either"],
		:vertical => [false, true],
		:diagonal => [false, true],
		:smooth => [false, true],
		:method => ["sum-rgb", "red", "green", "blue", "sum-hsb", "hue", "saturation", "brightness", "uniqueness", "luma", "random", "cyan", "magenta", "yellow", "alpha", "sum-rgba", "sum-hsba"],
		:verbose => [false, true],
		:absolute => [false, true],
		:threshold => [{:class => [Float, Fixnum]}],
		:sorted => [{:class => [Fixnum]}],
		:trusted => [false, true],
		:middle => :anything
	}
	options=defOptions.merge(o)
	if o.length==0 or options[:trusted]==true or (options[:trusted]==false and o.length!=0 and Pxlsrt::Helpers.checkOptions(options, defRules)!=false)
		Pxlsrt::Helpers.verbose("Options are all good.") if options[:verbose]
		if input.class==String
			Pxlsrt::Helpers.verbose("Getting image from file...") if options[:verbose]
			if File.file?(input)
				if Pxlsrt::Colors.isPNG?(input)
					input=ChunkyPNG::Image.from_file(input)
				else
					Pxlsrt::Helpers.error("File #{input} is not a valid PNG.") if options[:verbose]
					return
				end
			else
				Pxlsrt::Helpers.error("File #{input} doesn't exist!") if options[:verbose]
				return
			end
		elsif input.class!=String and input.class!=ChunkyPNG::Image
			Pxlsrt::Helpers.error("Input is not a filename or ChunkyPNG::Image") if options[:verbose]
			return
		end
		Pxlsrt::Helpers.verbose("Smart mode.") if options[:verbose]
		case options[:reverse].downcase
			when "reverse"
				nre=1
			when "either"
				nre=-1
			else
				nre=0
		end
		img=input
		w,h=img.width,img.height
		sobel_x = [[-1,0,1], [-2,0,2], [-1,0,1]]
		sobel_y = [[-1,-2,-1], [ 0, 0, 0], [ 1, 2, 1]]
		edge = ChunkyPNG::Image.new(w, h, ChunkyPNG::Color::TRANSPARENT)
		valued="start"
		k=[]
		Pxlsrt::Helpers.verbose("Getting Sobel values and colors for pixels...") if options[:verbose]
		grey=img.grayscale
		for xy in 0..(w*h-1)
			x=xy % w
			y=(xy/w).floor
			if x!=0 and x!=(w-1) and y!=0 and y!=(h-1)
				t1=ChunkyPNG::Color.r(grey[x-1,y-1])
				t2=ChunkyPNG::Color.r(grey[x,y-1])
				t3=ChunkyPNG::Color.r(grey[x+1,y-1])
				t4=ChunkyPNG::Color.r(grey[x-1,y])
				t5=ChunkyPNG::Color.r(grey[x,y])
				t6=ChunkyPNG::Color.r(grey[x+1,y])
				t7=ChunkyPNG::Color.r(grey[x-1,y+1])
				t8=ChunkyPNG::Color.r(grey[x,y+1])
				t9=ChunkyPNG::Color.r(grey[x+1,y+1])
				pixel_x=(sobel_x[0][0]*t1)+(sobel_x[0][1]*t2)+(sobel_x[0][2]*t3)+(sobel_x[1][0]*t4)+(sobel_x[1][1]*t5)+(sobel_x[1][2]*t6)+(sobel_x[2][0]*t7)+(sobel_x[2][1]*t8)+(sobel_x[2][2]*t9)
				pixel_y=(sobel_y[0][0]*t1)+(sobel_y[0][1]*t2)+(sobel_y[0][2]*t3)+(sobel_y[1][0]*t4)+(sobel_y[1][1]*t5)+(sobel_y[1][2]*t6)+(sobel_y[2][0]*t7)+(sobel_y[2][1]*t8)+(sobel_y[2][2]*t9)
				val = Math.sqrt(pixel_x * pixel_x + pixel_y * pixel_y).ceil
			else
				val = 2000000000
			end
			k.push({ "sobel" => val, "pixel" => [x, y], "color" => Pxlsrt::Colors.getRGBA(img[x, y]) })
		end
		if options[:vertical]==true
			Pxlsrt::Helpers.verbose("Rotating image for vertical mode...") if options[:verbose]
			k=Pxlsrt::Lines.rotateImage(k,w,h,3)
			w,h=h,w
		end
		if !options[:diagonal]
			lines=Pxlsrt::Lines.imageRGBLines(k, w)
			Pxlsrt::Helpers.verbose("Determining bands with a#{options[:absolute] ? "n absolute" : " relative"} threshold of #{options[:threshold]}...") if options[:verbose]
			bands=Array.new()
			for j in lines
				slicing=true
				pixel=0
				m=Array.new()
				while slicing do
					n=Array.new
					if m.length > 1
						while m.last.length < options[:edge]
							if m.length > 1
								m[-2].concat(m[-1])
								m.pop
							else
								break
							end
						end
					end
					bandWorking=true
					while bandWorking do
						n.push(j[pixel]["color"])
						if (options[:absolute] ? (j[pixel+1]["sobel"]) : (j[pixel+1]["sobel"]-j[pixel]["sobel"])) > options[:threshold]
							bandWorking=false
						end
						if (pixel+1)==(j.length-1)
							n.push(j[pixel+1]["color"])
							slicing=false
							bandWorking=false
						end
						pixel+=1
					end
					m.push(n)
				end
				bands.concat(m)
			end
			Pxlsrt::Helpers.verbose("Pixel sorting using method '#{options[:method]}'...") if options[:verbose]
			image=[]
			if options[:smooth]
				for band in bands
					u=band.group_by {|x| x}
					image.concat(Pxlsrt::Lines.handleMiddlate(Pxlsrt::Colors.pixelSort(u.keys, options[:method], nre).map { |x| u[x] }.flatten(1), options[:middle]))
				end
			else
				for band in bands
					image.concat(Pxlsrt::Lines.handleMiddlate(Pxlsrt::Colors.pixelSort(band, options[:method], nre), options[:middle]))
				end
			end
		else
			Pxlsrt::Helpers.verbose("Determining diagonals...") if options[:verbose]
			dia=Pxlsrt::Lines.getDiagonals(k,w,h)
			Pxlsrt::Helpers.verbose("Determining bands with a#{options[:absolute] ? "n absolute" : " relative"} threshold of #{options[:threshold]}...") if options[:verbose]
			for j in dia.keys
				bands=[]
				if dia[j].length>1
					slicing=true
					pixel=0
					m=Array.new()
					while slicing do
						n=Array.new
						if m.length > 1
							while m.last.length < options[:edge]
								if m.length > 1
									m[-2].concat(m[-1])
									m.pop
								else
									break
								end
							end
						end
						bandWorking=true
						while bandWorking do
							n.push(dia[j][pixel]["color"])
							if (options[:absolute] ? (dia[j][pixel+1]["sobel"]) : (dia[j][pixel+1]["sobel"]-dia[j][pixel]["sobel"])) > options[:threshold]
								bandWorking=false
							end
							if (pixel+1)==(dia[j].length-1)
								n.push(dia[j][pixel+1]["color"])
								slicing=false
								bandWorking=false
							end
							pixel+=1
						end
						m.push(n)
					end
				else
					m=[[dia[j].first["color"]]]
				end
				dia[j]=bands.concat(m)
			end
			Pxlsrt::Helpers.verbose("Pixel sorting using method '#{options[:method]}'...") if options[:verbose]
			for j in dia.keys
				ell=[]
				if options[:smooth]
					for band in dia[j]
						u=band.group_by {|x| x}
						ell.concat(Pxlsrt::Lines.handleMiddlate(Pxlsrt::Colors.pixelSort(u.keys, options[:method], nre).map { |x| u[x] }.flatten(1), options[:middle]))
					end
				else
					for band in dia[j]
						ell.concat(Pxlsrt::Lines.handleMiddlate(Pxlsrt::Colors.pixelSort(band, options[:method], nre), options[:middle]))
					end
				end
				dia[j]=ell
			end
			Pxlsrt::Helpers.verbose("Setting diagonals back to standard lines...") if options[:verbose]
			image=Pxlsrt::Lines.fromDiagonals(dia,w)
		end
		if options[:vertical]==true
			Pxlsrt::Helpers.verbose("Rotating back (because of vertical mode).") if options[:verbose]
			image=Pxlsrt::Lines.rotateImage(image,w,h,1)
			w,h=h,w
		end
		Pxlsrt::Helpers.verbose("Giving pixels new RGB values...") if options[:verbose]
		for px in 0..(w*h-1)
			edge[px % w, (px/w).floor]=Pxlsrt::Colors.arrayToRGBA(image[px])
		end
		endTime=Time.now
		timeElapsed=endTime-startTime
		if timeElapsed < 60
			Pxlsrt::Helpers.verbose("Took #{timeElapsed.round(4)} second#{ timeElapsed.round(4)!=1.0 ? "s" : "" }.") if options[:verbose]
		else
			minutes=(timeElapsed/60).floor
			seconds=(timeElapsed % 60).round(4)
			Pxlsrt::Helpers.verbose("Took #{minutes} minute#{ minutes!=1 ? "s" : "" } and #{seconds} second#{ seconds!=1.0 ? "s" : "" }.") if options[:verbose]
		end
		Pxlsrt::Helpers.verbose("Returning ChunkyPNG::Image...") if options[:verbose]
		return edge
	else
		Pxlsrt::Helpers.error("Options specified do not follow the correct format.") if options[:verbose]
		return
	end
end

.suite(inputFileName, outputFileName, o = {}) ⇒ Object

Uses Pxlsrt::Smart.smart to input and output from pne method.



12
13
14
15
16
17
# File 'lib/pxlsrt/smart.rb', line 12

def self.suite(inputFileName, outputFileName, o={})
	kml=Pxlsrt::Smart.smart(inputFileName, o)
	if Pxlsrt::Helpers.contented(kml)
		kml.save(outputFileName)
	end
end