f8g

モザイク

画像を分割して、そのブロックごとに色の平均出して描画するやつ。

class System::Drawing::Bitmap
	def mosaic(width, height)
		newImage = Drawing::Bitmap.new(self.width, self.height)

		column_size = (1*right - left) / width
		row_size    = (1*down - top) / height
		blocks      = []

		self.width.times {|x|
			y = 0

			while y < self.height
				# mosaic
				if x >= left and x < right and y >= top and y < down then

					unless blocks[x / width] then
						blocks[x / width] = []
					end

					unless blocks[x / width][y / height] then
						blocks[x / width][y / height] = [0, 0, 0, 0]
					end

					pixel = self.GetPixel(x, y)
					blocks[x / width][y / height][0] += 1*pixel.r
					blocks[x / width][y / height][1] += 1*pixel.g
					blocks[x / width][y / height][2] += 1*pixel.b
					blocks[x / width][y / height][3] += 1
				end

				y += 1
			end
		}

		# avrage
		i = 0
		while i < blocks.length
			unless blocks[i] then
				i += 1
				next
			end

			j = 0

			while j < blocks[i].length
				unless blocks[i][j] then
					j += 1
					next
				end

				k = 0

				while k < 3
					blocks[i][j][k] /= blocks[i][j][3]
					k += 1
				end

				j += 1
			end

			i += 1
		end

		self.width.times {|x|
			y = 0

			while y < self.height

				if x >= left and x < right and y >= top and y < down then
					rgb = blocks[x / width][y / height]
					newImage.SetPixel(x, y, Drawing::Color::FromArgb(rgb[0], rgb[1], rgb[2]))
				else
					newImage.SetPixel(x, y, self.GetPixel(x, y))
				end

				y += 1
			end
		}

		newImage
	end
end

なるべくループの中でブロックは使わない。凄い長いけど、フィルタよりはずっと速い。頭いい人なら相当行数減らせそう。