質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.80%

BMP画像の拡大と縮小

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 506
退会済みユーザー

退会済みユーザー

BMP画像を、任意にの数を入力して元の画像を拡大したいです。
一倍では画像の作成を出来るのですけど、二倍、三倍では、BMP画像が作成できません。
縮小は拡大とは別の処理が必要なのでしょうか。
必要なら教えていただけると幸いです。
拡大はどこが問題あるのか知りたいです。

#include<stdio.h>
#include<math.h>

typedef unsigned char BYTE;

//アライメント
#pragma pack(push,1)
typedef struct tagBITMAPFILEHEADER 
{
    unsigned short bfType;            //ファイルタイプ
    unsigned long  bfSize;            //ファイルサイズ (byte)
    unsigned short bfReserved1;        //予約領域
    unsigned short bfReserved2;        //予約領域
    unsigned long  bfOffBits;        //予約領域
} BITMAPFILEHEADER;
#pragma pack(pop)

typedef struct tagBITMAPINFOHEADER
{
    unsigned long  biSize;            //情報ヘッダのサイズ (byte)
    long           biWidth;            //画像の幅 (ピクセル)
    long           biHeight;        //画像の高さ (ピクセル)
    unsigned short biPlanes;        //プレーン数
    unsigned short biBitCount;        //1 画素あたりのデータサイズ (bit)
    unsigned long  biCompression;    //圧縮形式
    unsigned long  biSizeImage;        //画像データ部のサイズ (byte)
    long           biXPixPerMeter;    //横方向解像度 (1mあたりの画素数)
    long           biYPixPerMeter;    //縦方向解像度 (1mあたりの画素数)
    unsigned long  biClrUsed;        //格納されているパレット数 (使用色数)
    unsigned long  biClrImporant;    //重要なパレットのインデックス
} BITMAPINFOHEADER;

typedef struct tagRGBQUAD
{
    unsigned char rgbBlue;            //青
    unsigned char rgbGreen;            //緑
    unsigned char rgbRed;            //赤
    unsigned char rgbReserved;        //予約領域
} RGBQUAD;

void main(int argc, char **argv)
{
    BITMAPFILEHEADER BitMapFileHeader;     //BMPのファイルヘッダー
    BITMAPINFOHEADER BitMapInfoHeader;     //BMPの情報ヘッダー
    RGBQUAD BitMapColor;                //カラーパレット
    BYTE *pImg, *pChangeImg;
    int i, j, k,l, m, iSize, sp1=0, sp2=0;
    long lWidth, lHeight;
    double dMult;
    FILE *fp;

    if(argc != 3)
    {
        printf("フォーマットが違います。");
        exit(1);
    }

    fp = fopen(argv[1],"rb");

    if(fp == NULL)
    {
        printf("ファイルが存在しません。");
        exit(1);
    }
    printf("%s file open\n", argv[1]);

     //ファイルヘッダーを読み込む
    fread(&BitMapFileHeader,sizeof(BITMAPFILEHEADER),1,fp);
    if(BitMapFileHeader.bfType != 0x4D42){
        printf("ビットマップではありません。\n");
        exit(1);
    }

     //情報ヘッダーを読み込む
    fread(&BitMapInfoHeader,sizeof(BITMAPINFOHEADER),1,fp);

    //カラーパレットを読み込む
    switch(BitMapInfoHeader.biBitCount)
    {
    case 8:
        fread(&BitMapColor,sizeof(RGBQUAD),1,fp);
        iSize = BitMapFileHeader.bfSize - ( 14 + 40 + 4 );
        printf("%d\n",BitMapInfoHeader.biBitCount);
        break;
    case 24:
        iSize = BitMapFileHeader.bfSize - ( 14 + 40 );
        printf("%d\n",BitMapInfoHeader.biBitCount);
        break;
    case 32:
        iSize = BitMapFileHeader.bfSize - ( 14 + 40 );
        printf("%d\n",BitMapInfoHeader.biBitCount);
        break;
    default:
        printf("失敗しました");
        exit(1);
    }

    pImg = (BYTE *) malloc(iSize);

    //画像データ部の読み込み
    fread(pImg,sizeof(BYTE),iSize,fp); 

    //ファイルを閉じる
    if(fclose(fp) == EOF){
        printf("ファイルを閉じることが出来ませんでした。\n");
    }

    //パスのファイルへ書き込み
    fp = fopen("sample.bmp","wb"); 

    //書き込み
    dMult = atoi(argv[2]);

    BitMapFileHeader.bfSize = BitMapFileHeader.bfSize + iSize*(dMult-1);
    BitMapInfoHeader.biWidth *= dMult;
    BitMapInfoHeader.biHeight *= dMult;
    BitMapInfoHeader.biSizeImage *= dMult;

    lWidth = BitMapInfoHeader.biWidth;
    lHeight = BitMapInfoHeader.biHeight;

    //拡大、縮小 の倍率
    iSize *= dMult;

    printf("倍率   %lf\n",dMult);
    printf("width  %d\n",lWidth);
    printf("height %d\n",lHeight);
    printf("Size   %d\n",iSize);

    printf("倍率   %lf\n",dMult);
    printf("width  %d\n",BitMapInfoHeader.biWidth);
    printf("height %d\n",BitMapInfoHeader.biHeight);
    printf("Size   %d\n",BitMapFileHeader.bfSize);
    printf("Size   %d\n",BitMapInfoHeader.biSizeImage);

    //ファイルヘッダーを書き込む
    fwrite(&BitMapFileHeader,sizeof(BITMAPFILEHEADER),1,fp);
    //情報ヘッダーを書き込む
    fwrite(&BitMapInfoHeader,sizeof(BITMAPINFOHEADER),1,fp);

    //マロック
    pChangeImg = (BYTE *) malloc(iSize);

    //画像データを書き込む
    switch(BitMapInfoHeader.biBitCount)
    {
    //8bitのときを書き込む
    case 8:
        fwrite(&BitMapColor,sizeof(RGBQUAD),1,fp);

        for(j=0; j<lHeight; j++)
        {
            for(m=0; m<dMult; m++)
            {
                for(i=0; i<lWidth; i++)
                {
                    for(l=0; l<dMult; l++)
                    {
                        *(pChangeImg+sp2) = *(pImg+sp1);
                        sp1++;
                        sp2++;
                    }
                    sp1 = sp1-(dMult-1);
                }
                sp1 = sp1-lWidth*(dMult-1);
            }
        }
        break;
    //24bitのときを書き込む
    case 24:
        for(j=0; j<lHeight; j++)
        {
            for(i=0; i<lWidth; i++)
            {
                for(k=0; k<3; k++)
                {
                    *(pChangeImg+sp2) = *(pImg+sp1);
                    sp1++;
                    sp2++;
                }
            }
        }
        break;
    //32bitのときを書き込む
    case 32:
        for(i=0; i<lHeight; i++)
        {
            for(j=0; j<lWidth; j++)
            {
                for(k=0; k<4; k++)
                {
                    *(pChangeImg+sp2) = *(pImg+sp1);
                    sp1++;
                    sp2++;
                }
            }
        }
        break;
    }

    //画像データ部を書き込む
    fwrite(pChangeImg,sizeof(BYTE),iSize ,fp);

    //ファイルを閉じる
    fclose(fp);
}


利用環境 Visual Studio 2019

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+1

細かくは見てないですが、パっと見て画像サイズ(BitMapInfoHeader.biSizeImage)の算出方法が間違っています。
我流でやる前に、まずは既存の拡大縮小処理のサンプルを参考にしてみた方がよいでしょう。

ニアレストネイバー

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

0

前も言いましたが、まずはBMPのデータ形式をしっかり調べましょう。
そこから、画像のX方向、Y方向の各ピクセルのデータ配置がわかりますんで、まずはそれをしっかり把握しましょう。
それが理解できれば、整数倍の拡大は簡単にできるでしょう

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/12/04 12:11

    それがわかってもBMPファイルがうまく書き込めなくて困っています。

    キャンセル

  • 2020/12/04 12:16

    他のペイントソフトで拡大して保存したBMPとファイルサイズやヘッダを比較検証してみれば、違いが分かると思いますよ

    キャンセル

  • 2020/12/04 12:24

    そもそも保存することができないです。
    一倍だと実行を出来るんですけど、二倍以上にすると一文字も読み込めません。
    ヘッダーのみで行うと数字はあっています。

    キャンセル

  • 2020/12/04 13:36 編集

    まあ既に私が回答した通り画像サイズの算出方法がおかしいし、そのサイズを元にmallocで確保してバッファ以上にループ回してるからまともに動かないでしょうね。
    変換以前に、最後のswitch文の所を丸ごとコメントアウトして、拡大後のサイズのBMPを出力して他のソフトで読めるようにする所から始めた方がよいでしょう。(memsetで適当な数値で画像データを埋めると判り易いかも)
    一度に全部やろうとせず、コツコツと段階踏んでハードルをクリアしてください。どこまで正しく動いているか把握できない状態では、検証もデバッグもままなりません。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る