LoginSignup
3
1

rubyで画像の色を変更してみた

Last updated at Posted at 2024-03-28

はじめに

今回は遊びで画像の色を変換させるプログラムを作成したので、
メモ程度に投稿します。

本題

前提

この記事のゴールとしては、
画像の色を反転させる、または一部色を指定して変更させることです。

  1. Docker環境の準備
  2. 色を反転
  3. 色の変更

作成したファイルは以下になります

作成したファイル
-  Dockerfile 
-  docker-compose.yml
-  detail.rb
-  reverse.rb
-  color_change.rb

画像は以下の画像で試してみることとします。
(調べた限り著作権的にも問題なさそうなので?)
画像を実行ファイルと同様のディレクトリに配置した場合を仮定して、以下記述します。

image.png

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を引くことによって色が反転する仕組みになっています。
こちらのファイルを実行してみます。

以下のように、白い部分と黒い部分を反転することができました。

image2.png

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")

実行すると以下のように色を変更することができました。
xxxx_image.png

他にも設定する値を変更すると色々な色に変更できると思います。

pink2_image.pnggreen_image.pngblue_image.png
gold_image.png

最後に

遊びで作ってみたので、もろもろツッコミどころは多いですが、
暇つぶしにやってみたいと思った際に参考にして頂ければ幸いです。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1