LoginSignup
4
4

More than 1 year has passed since last update.

ハーフトーニングをUnityでやってみよう

Last updated at Posted at 2021-10-19

ハーフトーニングとは?

みなさんはプリンターを使ったことはありますか?あのコピーとか印刷とかをやってくれるあれです。もちろん使ったことありますよね?

最近のプリンターは家庭用でもカラープリントができるようになりましたよね。

しかし、原始的なプリンターにはカラープリント機能は無く、印刷対象に対して「インクを出す」という行為と「インクを出さない」という2つの機能しかありませんでした。

ここで、あることが問題になります。それは「白黒の濃淡をどう表現するか」という問題です。

原始的なプリンタはインクを出すか出さないかの2つの行動しかとれず、少しだけインクを出すなんてこともできません。

この問題を解決する手法がハーフトーニングです。ずばり、白インクと黒インクの打ち方を工夫することで、あたかも濃淡がついているように見せる技術といったところでしょうか。

有名なハーフトーニング

有名なハーフトーニングの中でも今回は以下の3つについてお話します。

  1. 濃度パターン法
  2. ディザ法
  3. 誤差拡散法

濃度パターン法

資料画像その1.png

123456789.png

987654321.png

元画像の4 * 4画素を17諧調に分類し、諧調に対応する 4 * 4 画素のパターンで置き換え、2値画像(モノクロ画像)で表す方式。

・メリット
17諧調で表現できる

・デメリット
画像が荒くなる

ディザ法

資料画像その3 (1).png

資料画像その6.png

元画像を4 * 4の領域で処理し、画素ごとに異なる基準値を用いる方式。

・メリット
解像度(画像サイズ)を維持できる

・デメリット
繰り返しパターンが目立つ

誤差拡散法

資料画像その4.png

資料画像その7.png

ある画素の基準値からの誤差を周辺の画素に伝播させ、誤差を軽減する方式。

・メリット
誤差を周りの画素に伝播させるため比較的正しく表現できる
解像度(画像サイズ)を維持できる

・デメリット
画像のざらざら感が増える(語彙力)

Unityで実装する

さっそく実装していきましょう!

おおまかな処理は、

  1. スクリプトがアタッチされているオブジェクトのSpriteのTextureを取得する
  2. 取得したTextureのピクセル情報を配列Aに格納する
  3. ピクセルのグレイスケール化とピクセルの諧調に対するパターンを新しい配列Bに格納する
  4. Textureを配列Bで更新する
  5. Textureをpng形式で画像を保存する

です。頑張ってコードを書いていきましょう。

濃度パターン法

はいそして出来上がったものがこちらになります。コードが非常に長いので折りたためるようにしてあります。

※実行するときにかなり重くなりますので注意!


濃度パターン法(DensityPattern_Logic)のコード
DensityPattern_Logic.C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEditor;
using System;

public class DensityPattern_Re_Logic : MonoBehaviour
{
    public Texture2D drawTexture;

    public int[] DensityPattern;
    public Color32[] DensityPatternBuffer;

    void Start()
    {
        Texture2D mainTexture = GetComponent<SpriteRenderer>().sprite.texture;
        Color32[] pixels = mainTexture.GetPixels32();

        DensityPattern = new int[pixels.Length];
        DensityPatternBuffer = new Color32[(mainTexture.width) * (mainTexture.height)];

        drawTexture = new Texture2D(mainTexture.width, mainTexture.height, TextureFormat.RGBA32, false);
        drawTexture.filterMode = FilterMode.Point;


        for (int i = 0; i < mainTexture.height; i++)
        {
            for (int j = 0; j < mainTexture.width; j++)
            {
                /////↓グレイスケール化の処理

                int k = j + i * mainTexture.width;

                byte gray = (byte)(pixels[k].r * 0.2126 + pixels[k].g * 0.7152 + pixels[k].b * 0.0722);

                pixels[k] = new Color32((byte)(gray), (byte)(gray), (byte)(gray), pixels[k].a);

                /////↑グレイスケール化の処理
            }
        }

        for (int i = 0; i < mainTexture.height - 4; i++)
        {
            for (int j = 0; j < mainTexture.width - 4; j++)
            {
                if (i % 4 == 0 && j % 4 == 0)
                {
                    float Adv = 0;

                    for (int k = 0; k < 4; k++)
                    {
                        for (int l = 0; l < 4; l++)
                        {
                            Adv += pixels[(j + l) + (i + k) * mainTexture.width].r;
                        }
                    }

                    float gray = Adv / 16;

                    Debug.Log(" i = " + i + " | j = " + j + " | gray = " + gray);

                    if (0 <= gray && gray < 8)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.black;

                    }
                    else if (8 <= gray && gray < 16)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.black;
                    }
                    else if (16 <= gray && gray < 32)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.black;
                    }
                    else if (32 <= gray && gray < 48)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.black;
                    }
                    else if (48 <= gray && gray < 64)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.black;
                    }
                    else if (64 <= gray && gray < 80)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.white;
                    }
                    else if (80 <= gray && gray < 96)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.white;
                    }
                    else if (96 <= gray && gray < 112)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.white;
                    }
                    else if (112 <= gray && gray < 128)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.white;
                    }
                    else if (128 <= gray && gray < 144)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.black;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.white;
                    }
                    else if (144 <= gray && gray < 160)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.white;
                    }
                    else if (160 <= gray && gray < 176)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.white;
                    }
                    else if (176 <= gray && gray < 192)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.white;
                    }
                    else if (192 <= gray && gray < 208)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.white;
                    }
                    else if (208 <= gray && gray < 224)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.white;
                    }
                    else if (224 <= gray && gray < 240)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.black;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.white;
                    }
                    else if (240 <= gray && gray <= 255)
                    {
                        DensityPatternBuffer[(j + 0) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 0) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 0) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 1) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 1) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 2) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 2) * (mainTexture.width)] = Color.white;

                        DensityPatternBuffer[(j + 0) + (i + 3) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 1) + (i + 3) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 2) + (i + 3) * (mainTexture.width)] = Color.white;
                        DensityPatternBuffer[(j + 3) + (i + 3) * (mainTexture.width)] = Color.white;
                    }

                }
            }
        }

        drawTexture.SetPixels32(DensityPatternBuffer);
        drawTexture.Apply();

        this.GetComponent<SpriteRenderer>().sprite = Sprite.Create(drawTexture, new Rect(0, 0, drawTexture.width, drawTexture.height), Vector2.zero);

        // PNG 画像としてファイル保存
        string filename = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + "_DensityPattern.png";
        File.WriteAllBytes($"{Application.dataPath}/Images/DensityPattern/{filename}", drawTexture.EncodeToPNG());
    }
}


ディザ法

コードが非常に長いので折りたためるようにしてあります。


ディザ法(Dither_Logic)のコード
Dither_Logic.C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEditor;
using System;

//ディザ法(dither method)
public class Dither_Logic : MonoBehaviour
{
    public Texture2D drawTexture;

    public Color32[] DitherBuffer;

    void Start()
    {
        Texture2D mainTexture = GetComponent<SpriteRenderer>().sprite.texture;
        Color32[] pixels = mainTexture.GetPixels32();

        DitherBuffer = new Color32[mainTexture.width * mainTexture.height];

        drawTexture = new Texture2D(mainTexture.width, mainTexture.height, TextureFormat.RGBA32, false);
        drawTexture.filterMode = FilterMode.Point;

        for (int i = 0; i < mainTexture.height; i++)
        {
            for (int j = 0; j < mainTexture.width; j++)
            {
                /////↓グレイスケール化の処理

                int k = j + i * mainTexture.width;

                byte gray = (byte)(pixels[k].r * 0.2126 + pixels[k].g * 0.7152 + pixels[k].b * 0.0722);

                pixels[k] = new Color32((byte)(gray), (byte)(gray), (byte)(gray), pixels[k].a);

                /////↑グレイスケール化の処理

                if (i % 4 == 0)
                {
                    if (j % 4 == 0)
                    {
                        if ((gray / 16) > 0)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                    else if (j % 4 == 1)
                    {
                        if ((gray / 16) > 8)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                    else if (j % 4 == 2)
                    {
                        if ((gray / 16) > 2)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                    else if (j % 4 == 3)
                    {
                        if ((gray / 16) > 10)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                }
                else if (i % 4 == 1)
                {
                    if (j % 4 == 0)
                    {
                        if ((gray / 16) > 12)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                    else if (j % 4 == 1)
                    {
                        if ((gray / 16) > 4)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                    else if (j % 4 == 2)
                    {
                        if ((gray / 16) > 14)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                    else if (j % 4 == 3)
                    {
                        if ((gray / 16) > 6)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                }
                else if (i % 4 == 2)
                {
                    if (j % 4 == 0)
                    {
                        if ((gray / 16) > 3)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                    else if (j % 4 == 1)
                    {
                        if ((gray / 16) > 11)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                    else if (j % 4 == 2)
                    {
                        if ((gray / 16) > 1)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                    else if (j % 4 == 3)
                    {
                        if ((gray / 16) > 9)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                }
                else if (i % 4 == 3)
                {
                    if (j % 4 == 0)
                    {
                        if ((gray / 16) > 15)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                    else if (j % 4 == 1)
                    {
                        if ((gray / 16) > 7)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                    else if (j % 4 == 2)
                    {
                        if ((gray / 16) > 13)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                    else if (j % 4 == 3)
                    {
                        if ((gray / 16) > 5)
                        {
                            DitherBuffer[k] = Color.white;
                        }
                        else
                        {
                            DitherBuffer[k] = Color.black;
                        }
                    }
                }

            }
        }

        drawTexture.SetPixels32(DitherBuffer);
        drawTexture.Apply();

        this.GetComponent<SpriteRenderer>().sprite = Sprite.Create(drawTexture, new Rect(0, 0, drawTexture.width, drawTexture.height), Vector2.zero);

        // PNG 画像としてファイル保存
        string filename = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + "_DitherPattern.png";
        File.WriteAllBytes($"{Application.dataPath}/Images/DitherPattern/{filename}", drawTexture.EncodeToPNG());
    }
}


誤差拡散法

コードが非常に長いので折りたためるようにしてあります。


誤差拡散法(ErrorDiffusion_Logic)のコード
ErrorDiffusion_Logic.C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEditor;
using System;

//誤差拡散法(error diffusion method)
public class ErrorDiffusion_Logic : MonoBehaviour
{
    public Texture2D drawTexture;

    public float[] ErrorBuffer;
    public Color32[] ErrorDiffusionPatternBuffer;

    void Start()
    {
        Texture2D mainTexture = GetComponent<SpriteRenderer>().sprite.texture;
        Color32[] pixels = mainTexture.GetPixels32();

        ErrorBuffer = new float[pixels.Length];
        ErrorDiffusionPatternBuffer = new Color32[mainTexture.width * mainTexture.height];

        drawTexture = new Texture2D(mainTexture.width, mainTexture.height, TextureFormat.RGBA32, false);
        drawTexture.filterMode = FilterMode.Point;

        for (int i = 0; i < mainTexture.height; i++)
        {
            for (int j = 0; j < mainTexture.width; j++)
            {
                /////↓グレイスケール化の処理

                int k = j + i * mainTexture.width;

                byte gray = (byte)(pixels[k].r * 0.2126 + pixels[k].g * 0.7152 + pixels[k].b * 0.0722);

                //buffer[k] = new Color32((byte)(gray), (byte)(gray), (byte)(gray), buffer[k].a);

                /////↑グレイスケール化の処理

                ErrorBuffer[k] = (float)gray;
            }
        }

        for (int i = 0; i < mainTexture.height; i++)
        {
            for (int j = 0; j < mainTexture.width; j++)
            {
                float error = 0;

                int k = j + i * mainTexture.width;

                if (ErrorBuffer[k] > 127)
                {
                    error = ErrorBuffer[k] - 255;

                    ErrorDiffusionPatternBuffer[k] = Color.white;
                }
                else if (ErrorBuffer[k] <= 127)
                {
                    error = ErrorBuffer[k] - 0;

                    ErrorDiffusionPatternBuffer[k] = Color.black;
                }

                if (j + 1 < mainTexture.width)
                {
                    ErrorBuffer[(j + 1) + i * mainTexture.width] = ErrorBuffer[(j + 1) + i * mainTexture.width] + ((5.0f / 16.0f) * error);
                }

                if (j < 0 && i + 1 < mainTexture.height)
                {
                    ErrorBuffer[(j - 1) + (i + 1) * mainTexture.width] = ErrorBuffer[(j - 1) + (i + 1) * mainTexture.width] + ((3.0f / 16.0f) * error);
                }

                if (i + 1 < mainTexture.height)
                {
                    ErrorBuffer[j + (i + 1) * mainTexture.width] = ErrorBuffer[j + (i + 1) * mainTexture.width] + ((5.0f / 16.0f) * error);
                }

                if (j + 1 < mainTexture.width && i + 1 < mainTexture.height)
                {
                    ErrorBuffer[(j + 1) + (i + 1) * mainTexture.width] = ErrorBuffer[(j + 1) + (i + 1) * mainTexture.width] + ((3.0f / 16.0f) * error);
                }
            }
        }

        drawTexture.SetPixels32(ErrorDiffusionPatternBuffer);
        drawTexture.Apply();

        this.GetComponent<SpriteRenderer>().sprite = Sprite.Create(drawTexture, new Rect(0, 0, drawTexture.width, drawTexture.height), Vector2.zero);

        // PNG 画像としてファイル保存
        string filename = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + "_ErrorDiffusion.png";
        File.WriteAllBytes($"{Application.dataPath}/Images/ErrorDiffusionPattern/{filename}", drawTexture.EncodeToPNG());
    }
}


おわりに

いかがでしたか?ハーフトーニングって面白いでしょう?
簡単な画像処理ならUnityでも強引に実装できるんですね!
それではまたこんど~

4
4
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
4
4