はじめに
今回は遊びで画像の色を変換させるプログラムを作成したので、
メモ程度に投稿します。
本題
前提
この記事のゴールとしては、
画像の色を反転させる、または一部色を指定して変更させることです。
- Docker環境の準備
- 色を反転
- 色の変更
作成したファイルは以下になります
作成したファイル
- Dockerfile
- docker-compose.yml
- detail.rb
- reverse.rb
- color_change.rb
画像は以下の画像で試してみることとします。
(調べた限り著作権的にも問題なさそうなので?)
画像を実行ファイルと同様のディレクトリに配置した場合を仮定して、以下記述します。
1. Docker環境の準備
まずはDocker環境の準備をしていきます。
gemはgdk_pixbuf2
,numo-narray
を使用しました。
(今回はお試しで遊ぶだけなので、Gemfileの作成/マウントはしていません)
Dockerfile
FROM ruby:latest
LABEL manintainer chawan.ignore
ENV TZ=Asia/Tokyo
RUN apt-get update && apt-get install -y \
bash \
vim
WORKDIR /app
RUN gem install gdk_pixbuf2
RUN gem install numo-narray
上記で作成したDockerfileでイメージをbuildし、それを元に以下のdocker-compose.ymlを使用します。
docker-compose.yml
version: '3'
services:
ruby:
container_name: "ruby-mkimage"
image: ruby:latest
volumes:
- type: bind
source: ../
target: /app
tty: true
stdin_open: true
2. 色を反転
まず色の反転を行ってみます。
その前に、対象の画像がRGBか、RGBAかを判別するために、
以下のdetail.rbを実行します。
require 'gdk_pixbuf2'
image = GdkPixbuf::Pixbuf.new(file: "image.png")
width = image.width
height = image.height
data = image.pixels
puts width
puts height
puts data.length
出力結果としては以下が得られます。
root@259467731a59:/app# ruby detail.rb
192
192
110592
このことから、
n = 110592/192*192
n = 3
なのでRGBとわかります。
nが4であればRGBAとなります。
上記が分かったところで、色の反転を行います。
色の反転をするには以下のファイルを使用します。
reverse.rb
require 'numo/narray'
require 'gdk_pixbuf2'
# 画像の取得
image = GdkPixbuf::Pixbuf.new(file: "xxx.png")
# ピクセルデータを取得し、Numo::UInt8型の配列に変換
width = image.width
height = image.height
data = Numo::UInt8.from_string(image.pixel_bytes.to_str)
# 配列データの形状を変更
data = data.reshape(height, width, 3)
# 色を反転させる(255から各色成分を引く)
data[true, true, 0..2] = 255 - data[true, true, 0..2]
# 変更したピクセルデータを元の画像に戻す
image_data = data.to_string
image2 = GdkPixbuf::Pixbuf.new(data: image_data, width: image.width, height: image.height, has_alpha: false)
image2.save("xxx.png")
こちらのファイルでは、それぞれのRGBから255を引くことによって色が反転する仕組みになっています。
こちらのファイルを実行してみます。
以下のように、白い部分と黒い部分を反転することができました。
3. 色の変更
次に反転だけではなく、色を変更してみたいと思います。
色を変更するために以下のcolor_change.rbを実行します。
今回使用している画像が背景がRGB(247,247,247)で恐竜自体がRGB(82,82,82)で
構成されているので指定する値をそちらで設定しています。
以下では背景を黄色、恐竜をオレンジ色に指定してみました。
color_change.rb
require 'numo/narray'
require 'gdk_pixbuf2'
# 画像の取得
image = GdkPixbuf::Pixbuf.new(file: "xxx.png")
# ピクセルデータを取得し、Numo::UInt8型の配列に変換
height = image.height
width = image.width
data = Numo::UInt8.from_string(image.pixel_bytes.to_str)
# 配列データの形状を変更
data = data.reshape(height, width, 3)
# 色を変更する
height.times do |y|
width.times do |x|
if (data[y, x, 0] == 247) & (data[y, x, 1] == 247) & (data[y, x, 2] == 247) then
data[y, x, 0] = 255
data[y, x, 1] = 255
data[y, x, 2] = 0
elsif (data[y, x, 0] == 82) & (data[y, x, 1] == 82) & (data[y, x, 2] == 82) then
data[y, x, 0] = 255
data[y, x, 1] = 140
data[y, x, 2] = 0
end
end
end
# 変更したピクセルデータを元の画像に戻す
image_data = data.to_string
image2 = GdkPixbuf::Pixbuf.new(data: image_data, width: image.width, height: image.height, has_alpha: false)
image2.save("xxxx_image.png")
他にも設定する値を変更すると色々な色に変更できると思います。
最後に
遊びで作ってみたので、もろもろツッコミどころは多いですが、
暇つぶしにやってみたいと思った際に参考にして頂ければ幸いです。