★画像処理(モザイク1)★


次はモザイク処理をやってみましょう。

モザイク処理とは、↓のような処理です。

画像が小さい四角形に区切られています。

昔のドット絵のように見えますが実現方法は色々あります。


まずは簡単な方法から説明します。

モザイクをかける四角形のサイズを決めます。

画像のサイズは320×240ピクセルですから、どちらも割り切れる数が理想です。

とりあえず上のサンプル画像と同じく8×8ピクセルで区切る事にしましょう。

この区切られた四角形の中から1つの画素の色情報を取り出します。

その色で四角形の中を塗りつぶせばOKです。

<sample program cpp037-01>

#include <iostream>
#include <fstream>

#include <Windows.h>

int main()
{
    std::ifstream ifsBitmap;

    ifsBitmap.open("omelet.bmp", std::ios::in | std::ios::binary);

    if (!ifsBitmap) {
        return 1;
    }

    BITMAPFILEHEADER bmFileHeader;

    ifsBitmap.read((char*)&bmFileHeader, sizeof(bmFileHeader));

    BITMAPINFOHEADER bmInfoHeader;

    ifsBitmap.read((char*)&bmInfoHeader, sizeof(bmInfoHeader));

    RGBTRIPLE *pColor = NULL;

    pColor = new RGBTRIPLE[bmInfoHeader.biWidth * bmInfoHeader.biHeight];

    if (!pColor) {
        if (ifsBitmap.is_open()) {
            ifsBitmap.close();
        }
        return 1;
    }

    ifsBitmap.read((char*)pColor, sizeof(RGBTRIPLE) * bmInfoHeader.biWidth * bmInfoHeader.biHeight);

    if (ifsBitmap.is_open()) {
        ifsBitmap.close();
    }

    //ここに画像処理のプログラムを書く

    const int mosaicSize = 8;

    RGBTRIPLE color;

    for (int i = 0; i < bmInfoHeader.biHeight; i += mosaicSize) {
        for (int j = 0; j < bmInfoHeader.biWidth; j += mosaicSize) {

            color = pColor[i * bmInfoHeader.biWidth + j];

            for (int y = 0; y < mosaicSize; y++) {
                for (int x = 0; x < mosaicSize; x++) {
                    pColor[(i + y) * bmInfoHeader.biWidth + (j + x)] = color;
                }
            }
        }
    }

    std::ofstream ofsBitmap;

    ofsBitmap.open("result.bmp", std::ios::out | std::ios::binary);

    if (!ofsBitmap) {
        if (pColor) {
            delete[] pColor;
            pColor = NULL;
        }
        return 1;
    }

    ofsBitmap.write((char*)&bmFileHeader, sizeof(bmFileHeader));

    ofsBitmap.write((char*)&bmInfoHeader, sizeof(bmInfoHeader));

    ofsBitmap.write((char*)pColor, sizeof(RGBTRIPLE) * bmInfoHeader.biWidth * bmInfoHeader.biHeight);

    if (ofsBitmap.is_open()) {
        ofsBitmap.close();
    }

    if (pColor) {
        delete[] pColor;
        pColor = NULL;
    }

    return 0;
}

<実行結果>

続行するには何かキーを押してください・・・

const int mosaicSize = 8;

for (int i = 0; i < bmInfoHeader.biHeight; i += mosaicSize) {
    for (int j = 0; j < bmInfoHeader.biWidth; j += mosaicSize) {

        color = pColor[i * bmInfoHeader.biWidth + j];

    }
}

この二重ループは画像を縦横8ピクセル飛ばしでアクセスするためのループです。

一次元配列を二次元配列風に使う方法はC言語編でもやりました。

まずは8×8ピクセルの四角形の左上の色情報を取得しています。

for (int y = 0; y < mosaicSize; y++) {
    for (int x = 0; x < mosaicSize; x++) {
        pColor[(i + y) * bmInfoHeader.biWidth + (j + x)] = color;
    }
}

外側の二重ループのi、jが指す画素から8×8の領域を取得した色情報で塗りつぶしています。


では、プロジェクトフォルダの「result.bmp」を見てください。

モザイクのサイズを変えて実行すると別の結果が得られるはずです。

次回は別の方法で作ってみましょう。


次へ

戻る

目次へ