Class: Pxlsrt::Colors

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

Overview

Includes color and image operations.

Class Method Summary collapse

Class Method Details

.arrayToRGB(a) ⇒ Object

Turns an RGB-like array into ChunkyPNG’s color



213
214
215
# File 'lib/pxlsrt/colors.rb', line 213

def self.arrayToRGB(a)
	return ChunkyPNG::Color.rgb(a[0], a[1], a[2])
end

.colorAverage(ca) ⇒ Object

Averages an array of RGB-like arrays.



115
116
117
118
119
120
121
122
123
# File 'lib/pxlsrt/colors.rb', line 115

def self.colorAverage(ca)
	if ca.length==1
		return ca.first
	end
	r=((ca.collect { |c| c[0] }).inject{ |sum, el| sum+el }).to_f / ca.size
	g=((ca.collect { |c| c[1] }).inject{ |sum, el| sum+el }).to_f / ca.size
	b=((ca.collect { |c| c[2] }).inject{ |sum, el| sum+el }).to_f / ca.size
	return [r,g,b]
end

.colorDistance(c1, c2) ⇒ Object

Determines color distance from each other using the Pythagorean theorem.



126
127
128
# File 'lib/pxlsrt/colors.rb', line 126

def self.colorDistance(c1,c2)
	return Math.sqrt((c1[0]-c2[0])**2+(c1[1]-c2[1])**2+(c1[2]-c2[2])**2)
end

.colorUniqueness(c, ca) ⇒ Object

Uses a combination of color averaging and color distance to find how “unique” a color is.



131
132
133
# File 'lib/pxlsrt/colors.rb', line 131

def self.colorUniqueness(c, ca)
	return Pxlsrt::Colors.colorDistance(c, Pxlsrt::Colors.colorAverage(ca))
end

.fromDiagonals(obj, width) ⇒ Object

Uses math to turn an array of diagonals into a linear array.



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/pxlsrt/colors.rb', line 190

def self.fromDiagonals(obj, width)
	ell=[]
	for k in obj.keys
		r=k.to_i
		n=r < 0
		if n
			x=0
			y=r.abs
		else
			x=r
			y=0
		end
		ell[x+y*width]=obj[k].first
		for v in 1..(obj[k].length-1)
			x+=1
			y+=1
			ell[x+y*width]=obj[k][v]
		end
	end
	return ell
end

.getDiagonals(array, width, height) ⇒ Object

Uses math to turn an array into an array of diagonals.



175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/pxlsrt/colors.rb', line 175

def self.getDiagonals(array, width, height)
	dias={}
	for x in (1-height)..(width-1)
		z=[]
		for y in 0..(height-1)
			if (x+(width+1)*y).between?(width*y, (width*(y+1)-1))
				z.push(array[(x+(width+1)*y)])
			end
		end
		dias[x.to_s]=z
	end
	return dias
end

.getRGB(pxl) ⇒ Object

Converts a ChunkyPNG pixel into an array of the reg, green, and blue values



9
10
11
# File 'lib/pxlsrt/colors.rb', line 9

def self.getRGB(pxl)
	return [ChunkyPNG::Color.r(pxl), ChunkyPNG::Color.g(pxl), ChunkyPNG::Color.b(pxl)]
end

.imageRGBLines(image, width) ⇒ Object

Gets “rows” of an array based on a width



41
42
43
# File 'lib/pxlsrt/colors.rb', line 41

def self.imageRGBLines(image, width)
	return image.each_slice(width).to_a
end

.isPNG?(path) ⇒ Boolean

Check if file is a PNG image. ChunkyPNG only works with PNG images. Eventually, I might use conversion tools to add support, but not right now.

Returns:

  • (Boolean)


14
15
16
# File 'lib/pxlsrt/colors.rb', line 14

def self.isPNG?(path)
	return File.read(path).bytes==[137, 80, 78, 71, 10]
end

.pixelSort(list, how, reverse) ⇒ Object

Sorts an array of colors based on a method.



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
# File 'lib/pxlsrt/colors.rb', line 136

def self.pixelSort(list, how, reverse)
	mhm=[]
	case how.downcase
		when "sum-rgb"
			mhm= list.sort_by { |c| Pxlsrt::Colors.pxldex(c) }
		when "red"
			mhm= list.sort_by { |c| c[0] }
		when "green"
			mhm= list.sort_by { |c| c[1] }
		when "blue"
			mhm= list.sort_by { |c| c[2] }
		when "hue"
			mhm= list.sort_by { |c| Pxlsrt::Colors.rgb2hsb(c)[0] }
		when "saturation"
			mhm= list.sort_by { |c| Pxlsrt::Colors.rgb2hsb(c)[1] }
		when "brightness"
			mhm= list.sort_by { |c| Pxlsrt::Colors.rgb2hsb(c)[2] }
		when "sum-hsb"
			mhm= list.sort_by { |c| k=Pxlsrt::Colors.rgb2hsb(c); k[0]*100/360+k[1]+k[2] }
		when "uniqueness"
			avg=Pxlsrt::Colors.colorAverage(list)
			mhm=list.sort_by { |c| Pxlsrt::Colors.colorUniqueness(c, [avg]) }
		when "luma"
			mhm=list.sort_by { |c| Pxlsrt::Colors.pxldex([c[0]*0.2126, c[1]*0.7152, c[2]*0.0722]) }
		when "random"
			mhm=list.shuffle
		else
			mhm= list.sort_by { |c| Pxlsrt::Colors.pxldex(c) }
	end
	if reverse == 0
		return mhm
	elsif reverse == 1
		return mhm.reverse
	else
		return rand(0..1)==0 ? mhm : mhm.reverse
	end
end

.pxldex(pxl) ⇒ Object

This is really lame. Adds first three values of an array together.



78
79
80
# File 'lib/pxlsrt/colors.rb', line 78

def self.pxldex(pxl)
	return pxl[0]+pxl[1]+pxl[2]
end

.randomSlices(arr, minLength, maxLength) ⇒ Object

Outputs random slices of an array. Because of the requirements of pxlsrt, it doesn’t actually slice the array, bute returns a range-like array. Example:

[0, 5], [6, 7], [8, 10]


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
# File 'lib/pxlsrt/colors.rb', line 48

def self.randomSlices(arr, minLength, maxLength)
	len=arr.length-1
	if len!=0
		min=[minLength, maxLength].min
		max=[maxLength, minLength].max
		if min > len
			min=len
		end
		if max > len
			max=len
		end
		nu=[[0, rand(min..max)]]
		last=nu.first[1]
		sorting=true
		while sorting do
			if (len-last) <= max
				nu.push([last+1, len])
				sorting=false
			else
				nu.push([last+1, last+1+rand(min..max)])
				last=nu.last[1]
			end
		end
	else
		nu=[[0,0]]
	end
	return nu
end

.rgb2hsb(rgb) ⇒ Object

Converts an RGB-like array ([red, green, blue]) into an HSB-like array ([hue, saturation, brightness]).



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
# File 'lib/pxlsrt/colors.rb', line 83

def self.rgb2hsb(rgb)
	r = rgb[0] / 255.0
	g = rgb[1] / 255.0
	b = rgb[2] / 255.0
	max = [r, g, b].max
	min = [r, g, b].min
	delta = max - min
	v = max * 100
	if (max != 0.0)
		s = delta / max *100
	else
		s = 0.0
	end
	if (s == 0.0) 
		h = 0.0
	else
		if (r == max)
			h = (g - b) / delta
		elsif (g == max)
			h = 2 + (b - r) / delta
		elsif (b == max)
			h = 4 + (r - g) / delta
		end
		h *= 60.0
		if (h < 0)
			h += 360.0
		end
	end
	return [h,s,v]
end

.rotateImage(what, width, height, a) ⇒ Object

ChunkyPNG’s rotation was a little slow and doubled runtime. This “rotates” an array, based on the width and height. It uses math and it’s really cool, trust me.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/pxlsrt/colors.rb', line 21

def self.rotateImage(what, width, height, a)
	nu=[]
	case a
		when 0, 360, 4
			nu=what
		when 1, 90
			for xy in 0..(what.length-1)
				nu[((height-1)-(xy/width).floor)+(xy % width)*height]=what[xy]
			end
		when 2, 180
			nu=what.reverse
		when 3, 270
			for xy in 0..(what.length-1)
				nu[(xy/width).floor+((width-1)-(xy % width))*height]=what[xy]
			end
	end
	return nu
end

.sobelate(i, x, y) ⇒ Object

Used in determining Sobel values.



218
219
220
# File 'lib/pxlsrt/colors.rb', line 218

def self.sobelate(i, x,y)
	return ChunkyPNG::Color.to_grayscale_bytes(i[x,y]).first
end