LoginSignup
0
0

More than 3 years have passed since last update.

【画像処理100本ノック】独自の画像入出力クラスを作る

Posted at

背景

画像処理100本ノックが面白そうなのでやってみることにしました。
基本的には配列操作しかしないだろうし、不慣れなOpenCVでやるよりも自分が使いやすいものを使いたい、ということで簡単な画像入出力クラスを作ってみました。

PPM形式

作るのが簡単なのでPPM形式の画像を扱うことにします。PPM形式の画像は非常に単純な構造をしています。簡単なので説明は省略します。

コード

100本ノックの画像はJPEGで与えられているので、ImageJを使ってPPMに変換します。PPM形式の仕様を完全に満たすのは面倒なので、ここではImageJでの読み書きに問題がない範囲で実装しました。なので、任意のPPM画像を読み込めるわけではないことに注意が必要です。また、エラーチェックも省略しています。

#include <iostream>
#include <stdio.h>

class PPM
{
private:
    int width;
    int height;
    int* R;
    int* G;
    int* B;
public:
    PPM(int width, int height)
    {
        this->width = width;
        this->height = height;
        R = new int[width * height];
        G = new int[width * height];
        B = new int[width * height];
    }
    PPM(const char* filename)
    {
        FILE* fp = fopen(filename, "rb");
        char tmp[256];
        fscanf(fp, "%s\n", tmp);
        if (fgetc(fp) == '#')//コメントありの場合
        {
            fseek(fp, -1, SEEK_CUR);
            while (fgetc(fp) != '\n');//読み飛ばす
        }
        else fseek(fp, -1, SEEK_CUR);
        fscanf(fp, "%d %d\n", &width,&height);
        fscanf(fp, "%s\n", tmp);
        R = new int[width * height];
        G = new int[width * height];
        B = new int[width * height];
        for (int j = 0; j < height; j++)
            for (int i = 0; i < width; i++)
            {
                R[i + width * j] = fgetc(fp);
                G[i + width * j] = fgetc(fp);
                B[i + width * j] = fgetc(fp);
            }
        fclose(fp);
    }
    int Get_width() const
    {
        return width;
    }
    int Get_height() const
    {
        return height;
    }

    int &operator()(int i, int j, char rgb)
    {
        if(rgb=='r') return R[i+width*j];
        if (rgb == 'g') return G[i + width * j];
        if (rgb == 'b') return B[i + width * j];
    }
    void Flush(const char *filename)
    {
        FILE* fp = fopen(filename, "wb");
        fprintf(fp, "P6\n");
        fprintf(fp, "%d %d\n", width, height);
        fprintf(fp, "255\n");
        for (int j = 0; j < height; j++)
            for (int i = 0; i < width; i++)
            {
                fputc(R[i + width * j], fp);
                fputc(G[i + width * j], fp);
                fputc(B[i + width * j], fp);
            }

        fclose(fp);
    }

    ~PPM()
    {
        delete[] R;
        delete[] G;
        delete[] B;
    }
};

int main()
{
    PPM ppm("imori.pnm");

    int width = ppm.Get_width();
    int height = ppm.Get_height();
    PPM ppm2(width, height);
    for(int j=0; j<height; j++)
        for (int i = 0; i < width; i++)
        {
            ppm2(i, j, 'r') = ppm(i, j, 'r');
            ppm2(i, j, 'g') = ppm(i, j, 'g');
            ppm2(i, j, 'b') = ppm(i, j, 'b');
        }
    ppm2.Flush("iout.ppm");

    return 0;
}

問題があれば随時修正予定です。

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