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


次は別の方法でモザイク処理をやってみましょう。

前回よりは複雑になりますが、色情報の平均値を求める方法でやってみます。

モザイクの四角形のサイズは8×8ピクセルにします。

8×8=64ピクセルの色情報の平均値で四角形を塗りつぶすと、前回とは違う雰囲気のモザイク処理が出来ます。

それではプログラムを書いてみましょう。

<sample program cpp038-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;

    unsigned int red;
    unsigned int green;
    unsigned int blue;

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

            red = green = blue = 0;

            for (int y = 0; y < mosaicSize; y++) {
                for (int x = 0; x < mosaicSize; x++) {

                    color = pColor[(i + y) * bmInfoHeader.biWidth + (j + x)];
                    
                    red += color.rgbtRed;
                    green += color.rgbtGreen;
                    blue += color.rgbtBlue;
                }
            }

            color.rgbtRed = (BYTE)(red / (mosaicSize * mosaicSize));
            color.rgbtGreen = (BYTE)(green / (mosaicSize * mosaicSize));
            color.rgbtBlue = (BYTE)(blue / (mosaicSize * mosaicSize));

            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;
}

<実行結果>

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

red = green = blue = 0;

for (int y = 0; y < mosaicSize; y++) {
    for (int x = 0; x < mosaicSize; x++) {

        color = pColor[(i + y) * bmInfoHeader.biWidth + (j + x)];

        red += color.rgbtRed;
        green += color.rgbtGreen;
        blue += color.rgbtBlue;
    }
}

この部分でRGBそれぞれの合計値を計算しています。

color.rgbtRed = (BYTE)(red / (mosaicSize * mosaicSize));
color.rgbtGreen = (BYTE)(green / (mosaicSize * mosaicSize));
color.rgbtBlue = (BYTE)(blue / (mosaicSize * mosaicSize));

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

それぞれの色の合計値を64で割り、平均値を求めます。

その平均値で四角形を塗りつぶすと完成です。


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

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


次へ

戻る

目次へ