2017-04-26 6 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; 
} 

Ceci est mon long morceau de code que j'utilise. J'ai essayé de comprendre d'autres questions sur le même sujet mais je n'ai pas pu corréler les réponses à mon propre code. Personnellement, je pense qu'il y a quelque chose qui ne va pas dans la logique avec le n fois parce que sans cela, il imprime une image étirée horizontalement mais je ne peux pas identifier la solution. Mon code pseudo est simplement:CS50 pset 4 redimensionner L'étirement vertical donne une sortie étrange

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 

C'est ce qui est censé être étiré Image1

et voici ce qu'il ressemble quand je l'utilise ./resize 4 smiley.bmp final.bmp Image3

Merci pour l'aide!

Répondre

0

Vous ne l'avez pas mis à jour le biSizeImage et bfSize avant d'écrire le BITMAPFILEHEADER et
BITMAPINFOHEADER.

En outre, le remplissage pour le nouveau fichier va changer.

Par conséquent, calculer le nouveau rembourrage, biSizeImage et bfSize utilisant

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); 

Rembourrage en fseek() pour 'IntPtr' sera différent de celui pour 'outptr'. Par conséquent stocker les deux paddings en
différentes variables.