2017-10-30 8 views
1

私は現在CS50コースを受講していますが、私はサイズ変更の問題に悩まされています。割り当ては、入力.bmpファイルを取得し、n回スケールして出力.bmpファイルに書き込むプログラムを作成することです。しかし、私のコードは入力画像をちょっと歪ませ、サイズをまったく変えません。 https://imgur.com/1v55tjz を、私はそれのサイズを変更しようとすると、それだけでこの(まだ3×3)になります:これは、コードのはhttps://imgur.com/JAKQMfY.bmp画像のサイズを正しく変更できません(CS50 pset 4、サイズ変更、あまり快適ではありません)

ある これは(3×3画素が、ちょうどここでズーム)テストのために供給され、BMPですサイズ変更:

#include <stdio.h> 
#include <stdlib.h> 

#include "bmp.h" 

int main(int argc, char *argv[]) 
{ 
    // ensure proper usage 
    if (argc != 4) 
    { 
     fprintf(stderr, "Usage: ./copy infile outfile\n"); 
     return 1; 
    } 

    // remember filenames 
    int n = atoi(argv[1]); 
    char *infile = argv[2]; 
    char *outfile = argv[3]; 

    // open input file 
    FILE *inptr = fopen(infile, "r"); 
    if (inptr == NULL) 
    { 
     fprintf(stderr, "Could not open %s.\n", infile); 
     return 2; 
    } 

    // open output file 
    FILE *outptr = fopen(outfile, "w"); 
    if (outptr == NULL) 
    { 
     fclose(inptr); 
     fprintf(stderr, "Could not create %s.\n", outfile); 
     return 3; 
    } 

    // read infile's BITMAPFILEHEADER 
    BITMAPFILEHEADER bf; 
    fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr); 

    // read infile's BITMAPINFOHEADER 
    BITMAPINFOHEADER bi; 
    fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr); 


    // ensure infile is (likely) a 24-bit uncompressed BMP 4.0 
    if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 || 
     bi.biBitCount != 24 || bi.biCompression != 0) 
    { 
     fclose(outptr); 
     fclose(inptr); 
     fprintf(stderr, "Unsupported file format.\n"); 
     return 4; 
    } 

    // create file- and infoheader for output file 
    BITMAPFILEHEADER outBF = bf; 
    BITMAPINFOHEADER outBI = bi; 

    //Scale width and height by n 
    outBI.biWidth *= n; 
    outBI.biHeight *= n; 

    //Calculate padding for input and output file 
    int outPadding = (4 - (outBI.biWidth * sizeof(RGBTRIPLE) % 4) % 4); 
    int inPadding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4; 

    //Calculate biSizeImage and bfSize for output file 
    outBI.biSizeImage = ((sizeof(RGBTRIPLE) * outBI.biWidth) + outPadding * abs(outBI.biHeight)); 
    outBF.bfSize = outBI.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 

    // write outfile's BITMAPFILEHEADER 
    fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr); 

    // write outfile's BITMAPINFOHEADER 
    fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr); 

    //Instantiate two counters to keep track of whether we have reached the n - 1 times of the recopy method and to be able to fseek to the next line 
    int countIterations = 1; 
    int countPositionInFile = 0; 


    // iterate over infile's scanlines 
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++) 
    { 
     countIterations = 1; 
     for(int j = 0; j < n; j++) 
     { 
      // iterate over pixels in scanline 
      for (int k = 0; k < bi.biWidth; k++) 
      { 
       // temporary storage 
       RGBTRIPLE triple; 

       // read RGB triple from infile 
       fread(&triple, sizeof(RGBTRIPLE), 1, inptr); 

       // resize horizontally by writing every pixel in row n times 
       for(int l = 0; l < n; l++) 
       { 
        // write RGB triple to outfile 
        fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr); 
       } 
      } 

      // skip over padding, if any 
      fseek(inptr, inPadding, SEEK_CUR); 

      //Add padding for this line 
      for (int l = 0; l < outPadding; l++) 
      { 
      fputc(0x00, outptr); 
      } 

      if(countIterations == n) 
      { 
       countPositionInFile++; 
      } 

      int newPosition = (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (countPositionInFile * (bi.biWidth + inPadding))); 

      // return the "cursor" to the start of the file 
      fseek(inptr, newPosition, SEEK_SET); 
      countIterations++; 
     } 

    } 

    // close infile 
    fclose(inptr); 

    // close outfile 
    fclose(outptr); 

    // success 
    return 0; 
}  

そして、これがbmp.hファイルです:

/** 
* BMP-related data types based on Microsoft's own. 
*/ 

#include <stdint.h> 

/** 
* Common Data Types 
* 
* The data types in this section are essentially aliases for C/C++ 
* primitive data types. 
* 
* Adapted from https://msdn.microsoft.com/en-us/library/cc230309.aspx. 
* See http://en.wikipedia.org/wiki/Stdint.h for more on stdint.h. 
*/ 
typedef uint8_t BYTE; 
typedef uint32_t DWORD; 
typedef int32_t LONG; 
typedef uint16_t WORD; 

/** 
* BITMAPFILEHEADER 
* 
* The BITMAPFILEHEADER structure contains information about the type, size, 
* and layout of a file that contains a DIB [device-independent bitmap]. 
* 
* Adapted from https://msdn.microsoft.com/en-us/library/dd183374(v=vs.85).aspx. 
*/ 
typedef struct 
{ 
    WORD bfType; 
    DWORD bfSize; 
    WORD bfReserved1; 
    WORD bfReserved2; 
    DWORD bfOffBits; 
} __attribute__((__packed__)) 
BITMAPFILEHEADER; 

/** 
* BITMAPINFOHEADER 
* 
* The BITMAPINFOHEADER structure contains information about the 
* dimensions and color format of a DIB [device-independent bitmap]. 
* 
* Adapted from https://msdn.microsoft.com/en-us/library/dd183376(v=vs.85).aspx. 
*/ 
typedef struct 
{ 
    DWORD biSize; 
    LONG biWidth; 
    LONG biHeight; 
    WORD biPlanes; 
    WORD biBitCount; 
    DWORD biCompression; 
    DWORD biSizeImage; 
    LONG biXPelsPerMeter; 
    LONG biYPelsPerMeter; 
    DWORD biClrUsed; 
    DWORD biClrImportant; 
} __attribute__((__packed__)) 
BITMAPINFOHEADER; 

/** 
* RGBTRIPLE 
* 
* This structure describes a color consisting of relative intensities of 
* red, green, and blue. 
* 
* Adapted from https://msdn.microsoft.com/en-us/library/dd162939(v=vs.85).aspx. 
*/ 
typedef struct 
{ 
    BYTE rgbtBlue; 
    BYTE rgbtGreen; 
    BYTE rgbtRed; 
} __attribute__((__packed__)) 
RGBTRIPLE; 

私は誰かがこの割り当ての経験を持っていると役立つことを願って、私は、TBH、今はかなりこだわって感じるが、多分I'v eはちょうどそれをあまりにも長く見続けていました。 ありがとうございます!

+1

私はあなたがそれに対処しているように見えるので、行の埋め込みに関するこれまでのコメントを削除しました。あなたはCに関する質問ではなく、デバッグに関する質問です。問題を解決するには、最初に、ピクセル値に関係なく、新しいサイズのイメージを作成します。そのようにすると、賢明にはピクセルがほんの少ししかないので、ラスタ世代の各ループを調べることができます。 –

答えて

1

ファイルがバイナリフラグで開かれる必要があります。

FILE *inptr = fopen(infile, "rb"); 
FILE *outptr = fopen(outfile, "wb"); 

あなたはoutBIoutBFを無視している、あなたは新しいファイルに古いヘッダを書いている:

fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);//old header 
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);//old header 

2つの異なる方法をここで使用されていますパディングを計算する:

int outPadding = (4 - (outBI.biWidth * sizeof(RGBTRIPLE) % 4) % 4); 
int inPadding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4; 
                 ^  ^

彼らは偶然を除いて、どちらも正しいことができません。

:このケースでは、24ビットマップを使用していますが、私はこのコードを見つけ出すことができませんでした。これは、あなたが fseek(inptr, inPadding, SEEK_CUR);for(...) fputc(0x00, outptr);

でパディングをスキップする方法と一致します

int outPadding = outBI.biWidth % 4; 
int inPadding = bi.biWidth % 4; 

としてパディングを計算することができます

int newPosition = (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) 
    + (countPositionInFile * (bi.biWidth + inPadding)));<==remove 
fseek(inptr, newPosition, SEEK_SET);<==remove 

(bi.biWidth * 3)または、それを削除してftellを使用して位置を保存してから、その行を読み始めてから、fseekを使用してその位置に戻ることができます。

ビットマップの高さは下から上に読み込む必要がありますが、この場合は違いはありません。

+0

このような広範な答えを書く時間をとってくれてありがとう! :)これはすべて大いに役立ちました、そして、私はそれを今修正するように修正しました。どうもありがとう! – sunero4

関連する問題