読者です 読者をやめる 読者になる 読者になる

Let's write β

趣味で書いたこととか、RustとLispが好き

ファイルを画像ファイル(BMP)にしたり戻したり

普通のファイルを画像にしたり、その画像からファイルに戻したりしたら面白いだろうなぁ
と思っていたので、今BMPにするものを書いてみました。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "bmp.h"

main(int argc, char** argv)
{
        FILE *fp;
        fpos_t sz;
        int v, cnt;
        if(argc < 2) {
                exit(1);
        }
        if((fp = fopen(argv[1],"r")) == NULL) {
                exit(1);
        }
        cnt = 0;
        //Get File size
        fseek( fp, 0, SEEK_END );
        fgetpos( fp, &sz );
        printf("file size: %d\n",sz);
        fseek( fp, 0, SEEK_SET );
        int *data;
        data = (int *)malloc(sizeof(int) * sz);
        printf("---------------------------\n");
        while((v = fgetc(fp)) != EOF) {
                data[cnt] = v;
                cnt++;
        }
        printf("\n---------------------------\n");
        printf("Count: %d\n", cnt);
        int i,j;
        for(i = 0; i < cnt; i++) {
                printf("%d ",data[i]);
        }
        printf("\n---------------------------\n");
        //Find width height
        int width = floor(sqrt(cnt));
        double h = (double)cnt/(double)width;
        for(; (double)floor(h) != (double)h;
                        --width,
                        h = (double)cnt/(double)width) { }
        printf("width: %d\n",width);
        printf("height: %lf\n",h);

        img *tmp;
        tmp = (img *)malloc(sizeof(img));
        tmp->height = h;
        tmp->width = width;
        for(i = 0; i < tmp->height; i++) {
                for(j = 0; j < tmp->width; j++) {
                        int val = data[i * (tmp->width) + j];
                        tmp->data[i][j].r = val;
                        tmp->data[i][j].g = val;
                        tmp->data[i][j].b = val;
                }
        }
        WriteBmp("img.bmp",tmp);

        fclose(fp);
        free(data);
        free(tmp);
        return 0;
}

こちらが画像ファイルにするプログラムです
BMPを書き出す処理は
C言語による画像処理プログラミング
こちらのbmp.{c|h}を利用させていただいております。
次が復元するプログラムです

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "bmp.h"

main(int argc, char** argv)
{
        if(argc != 3)
                exit(1);

        img *tmp;
        tmp = (img *)malloc(sizeof(img));

        ReadBmp(argv[1], tmp);
        int size = tmp->width * tmp->height;
        int *data = (int *)malloc(sizeof(int) * size);
        int i, j;
        for(i = 0; i < tmp->height; i++) {
                for(j = 0; j < tmp->width; j++) {
                        data[i * tmp->width + j] = tmp->data[i][j].r;
                }
        }
        FILE *fp;
        if((fp = fopen(argv[2], "w")) == NULL) {
                exit(1);
        }
        for(i = 0; i < size; i++) {
                fputc(data[i], fp);
        }
        fclose(fp);
        free(data);
        free(tmp);
}

こんな感じです。
このプログラムソースじたいをかけてみると
f:id:Pocket7878_dev:20121218135833j:plain
このようなグレースケールの画像になります(0~255)で都合がよかったので
そして復元すると

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "bmp.h"

main(int argc, char** argv)
{
        FILE *fp;
        fpos_t sz;
        int v, cnt;
        if(argc < 2) {
                exit(1);
        }
        if((fp = fopen(argv[1],"r")) == NULL) {
                exit(1);
        }
        cnt = 0;
        //Get File size
        fseek( fp, 0, SEEK_END );
        fgetpos( fp, &sz );
        printf("file size: %d\n",sz);
        fseek( fp, 0, SEEK_SET );
        int *data;
        data = (int *)malloc(sizeof(int) * sz);
        printf("---------------------------\n");
        while((v = fgetc(fp)) != EOF) {
                data[cnt] = v;
                cnt++;
        }
        printf("\n---------------------------\n");
        printf("Count: %d\n", cnt);
        int i,j;
        for(i = 0; i < cnt; i++) {
                printf("%d ",data[i]);
        }
        printf("\n---------------------------\n");
        //Find width height
        int width = floor(sqrt(cnt));
        double h = (double)cnt/(double)width;
        for(; (double)floor(h) != (double)h;
                        --width,
                        h = (double)cnt/(double)width) { }
        printf("width: %d\n",width);
        printf("height: %lf\n",h);

        img *tmp;
        tmp = (img *)malloc(sizeof(img));
        tmp->height = h;
        tmp->width = width;
        for(i = 0; i < tmp->height; i++) {
                for(j = 0; j < tmp->width; j++) {
                        int val = data[i * (tmp->width) + j];
                        tmp->data[i][j].r = val;
                        tmp->data[i][j].g = val;
                        tmp->data[i][j].b = val;
                }
        }
        WriteBmp("img.bmp",tmp);

        fclose(fp);
        free(data);
        free(tmp);
        return 0;
}

とちゃんと復元されているのがわかります。

BMPだけでなくPNGやJPEGやらGIFに対応させたり
複数のファイルだったらGIFアニメにしたりとやってみたいと思っています。

僕が働いているAzit.incでは一緒に働けるエンジニアを募集しています!
採用情報 — 株式会社アジット|Azit Inc.