2017-04-26 63 views
0
#include <stdio.h> 
#include <stdlib.h> 

#include "bmp.h" 

int main(int argc, char *argv[]) 
{ 
    // ensure proper usage 
    if (argc != 4) 
    { 
     fprintf(stderr, "Usage: ./resize scale 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; 
    } 

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


    //Changes the Width and Height of the final image 
    bi.biWidth *= n; 
    bi.biHeight *= n; 

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

    int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4; 

    // iterate over infile's scanlines 
    for (int i = 1, biHeight = abs(bi.biHeight) + 1; i < biHeight; i++) { 
     //array where the last line will be stored 
     for (int curn = 0; curn < n; curn++) { 
      long int temp = sizeof(RGBTRIPLE); 
      // iterate over pixels in scanline 
      for (int j = 0; j < bi.biWidth; j++) { 

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

       // write RGB triple to outfile 
       for (int k = 0; k < n; k++) { 
        fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr); 
       } 
      } 
      fseek(inptr, -temp * bi.biWidth, SEEK_CUR); 
     } 

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

     // then add it back (to demonstrate how) 
     for (int k = 0; k < padding; k++) 
     { 
      fputc(0x00, outptr); 
     } 
    } 

    // close infile 
    fclose(inptr); 

    // close outfile 
    fclose(outptr); 

    // success 
    return 0; 
} 

這是我長時間使用的代碼。我試圖理解關於同一主題的其他問題,但我無法將答案與我自己的代碼關聯起來。我個人認爲n次邏輯有問題,因爲如果沒有它,它會打印出水平拉伸的圖像,但我無法確定解決方案是什麼。我的僞代碼很簡單:CS50 pset 4調整大小垂直拉伸給出奇怪的輸出

for each row 
     for n times 
      for each pixel in the row 
       read from inptr 
       for n times (second time) 
        write into outptr 
       end of n times (second time) 
      end of each pixel in the row 
    skip over padding 
    put the padding back 
end of each row 

這是應該被拉伸Image1

,這是什麼樣子,當我使用./resize 4 smiley.bmp final.bmp Image3

感謝您的幫助!

回答

0

您還沒有寫BITMAPFILEHEADER
BITMAPINFOHEADER之前更新biSizeImagebfSize

此外,新文件的填充將改變。

因此,使用

padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4; 
bi.biSizeImage = ((sizeof(RGBTRIPLE) * bi.biWidth + padding) * abs(bi.biHeight); 
bi.bfSize = bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 

填充在fseek()關於 'IntPtr的' 將大於關於 'outptr' 不同計算新的填充,biSizeImage,和bfSize。因此將這兩個填充存儲在
不同的變量中。