I've been working this problem for a couple of weeks and am unsure what the black is after the first line. It seems like my code is duplicating the pixels correctly for the width, but I'm getting stuck on the padding. I'm enlarging by a factor of 4, meaning it should be divisible by 4 (no padding) yet there is black space. Does anyone have any idea what I'm doing wrong? Thanks in advance.
is supposed to resize to by a factor of 4. (only considering scanlines right now not height).
/**
* copy.c
*
* Computer Science 50
* Problem Set 4
*
* Copies a BMP piece by piece, just because.
*/
#include <stdio.h>
#include <stdlib.h>
#include "bmp.h"
int main(int argc, char* argv[])
{
// ensure proper usage
if (argc != 4)
{
printf("Usage: ./copy n infile outfile\n");
return 1;
}
// remember filenames
char* infile = argv[2];
char* outfile = argv[3];
int n = atoi(argv[1]);
// open input file
FILE* inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("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
*/
// 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;
}
/*
TRANSFORM
[ ] pixel repeated n times
[ ] row repeated n times
*/
//store
// int before_bfSize = bf.bfSize;
// int before_biSizeImage = bi.biSizeImage;
// int before_biWidth = bi.biWidth;
// int before_biHeight = bi.biHeight;
//transform
/**the size (in bytes) of the bitmap file. [ ]
*/
bf.bfSize = bf.bfSize * n;
/**resize horizontally [x]
* width of image (in pixels)
* does not include padding
* write it n times in the outfile
*/
bi.biWidth = bi.biWidth * n;
/**resize vertically [ ]
* method 1: "Rewrite" methods | remember pixels in an array || write array as many times as needed
* method 2: "Re-copy" methods | go back to the start of the original row with fseek() || repeat the horizontal resizing
*/
bi.biHeight = bi.biHeight * n;
/**the size (in bytes) of the image [ ]
* total size of image (in bytes)
* includes pixels and padding
*/
bi.biSizeImage = bi.biSizeImage * n;
/*
WRITE
*/
// write outfile's BITMAPFILEHEADER
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
// determine padding for scanlines
int padding_in = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
// int padding_out = padding_in * n;
// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{
// 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);
for (int a = 0; a < n; a++)
{
// write RGB triple to outfile
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
/**add padding to row [ ]
* each pixel is 3 bytes
* size of each scanline must be a multiple of 4 bytes
* if the number of pixels isn't a multiple of 4 we need padding
* fputc(chr, output) to write padding | chr: char to write | outptr: FILE* to write to | fputc(0x00, outptr);
* fseek(inptr, amount, from); to move file position indicator | inptr:FILE* to seek in | amount: number of bytes to move cursor | from: SEEK_CUR(current position in file) || SEEK_SET (beginninng of file) || SEEK_END (end of file)
* make sure your file position indicator is at the correct point to resize vertically [ ]
* calculate input file padding and output file padding separately
*/
}
// skip over padding, if any
fseek(inptr, padding_in, SEEK_CUR);
// then add it back (to demonstrate how)
for (int k = 0; k < padding_in; k++)
{
fputc(0x00, outptr);
}
}
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// that's all folks
return 0;
}
_______________________________ Update 1 _______________________________
I've made some changes, but I'm still having trouble with the black spaces.
It seems to be turning out every way except the way it's supposed to. The black spaces are still visible. Any tips?
/**
* copy.c
*
* Computer Science 50
* Problem Set 4
*
* Copies a BMP piece by piece, just because.
*/
#include <stdio.h>
#include <stdlib.h>
#include "bmp.h"
int main(int argc, char* argv[])
{
// ensure proper usage
if (argc != 4)
{
printf("Usage: ./copy n infile outfile\n");
return 1;
}
// remember filenames
char* infile = argv[2];
char* outfile = argv[3];
int n = atoi(argv[1]);
// open input file
FILE* inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("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
*/
// 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;
}
/*
TRANSFORM
[ ] pixel repeated n times
[ ] row repeated n times
*/
//store
// int before_bfSize = bf.bfSize;
// int before_biSizeImage = bi.biSizeImage;
// int before_biWidth = bi.biWidth;
// int before_biHeight = bi.biHeight;
/**transform padding
* the input and the output files do not necessarily have the same amount of padding.
* calculate the output file padding, based on the changed header values.
*/
// determine padding for scanlines
int padding_in = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
// int padding_out = padding_in * n;
int padding_out = (4 - ((bi.biWidth * atoi(argv[1]) * sizeof(RGBTRIPLE)) % 4)) % 4;
//transform header properties
/**resize horizontally [x]
* width of image (in pixels)
* does not include padding
* write it n times in the outfile
*/
bi.biWidth = bi.biWidth * n;
/**resize vertically [ ]
* method 1: "Rewrite" methods | remember pixels in an array || write array as many times as needed
* method 2: "Re-copy" methods | go back to the start of the original row with fseek() || repeat the horizontal resizing
*/
bi.biHeight = bi.biHeight * n;
/**the size (in bytes) of the image
* total size of image (in bytes)
* includes pixels and padding
*/
// bi.biSizeImage = bi.biSizeImage * n;
bi.biSizeImage = (bi.biWidth * sizeof(RGBTRIPLE) + padding_out) * abs(bi.biHeight); // this works
/**the size (in bytes) of the bitmap file.
*/
// bf.bfSize = bf.bfSize * n;
bf.bfSize = bi.biSizeImage + 54; // 54 is the size of the meta data
/*
WRITE
*/
// write outfile's BITMAPFILEHEADER
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{
// 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);
for (int a = 0; a < n; a++)
{
for (int row = 0; row < n; row++ )
{
// write RGB triple to outfile
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
}
/**add padding to row [ ]
* each pixel is 3 bytes
* size of each scanline must be a multiple of 4 bytes
* if the number of pixels isn't a multiple of 4 we need padding
* fputc(chr, output) to write padding | chr: char to write | outptr: FILE* to write to | fputc(0x00, outptr);
* fseek(inptr, amount, from); to move file position indicator | inptr:FILE* to seek in | amount: number of bytes to move cursor | from: SEEK_CUR(current position in file) || SEEK_SET (beginninng of file) || SEEK_END (end of file)
* make sure your file position indicator is at the correct point to resize vertically [ ]
* calculate input file padding and output file padding separately
*/
}
// skip over padding, if any
fseek(inptr, padding_in, SEEK_CUR);
// then add it back (to demonstrate how)
for (int k = 0; k < padding_in; k++)
{
fputc(0x00, outptr);
}
}
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// that's all folks
return 0;
}
_______________________________ Update 2 _______________________________
Ok, now I'm just putting these up here for fun.
Ok, this is as close as I've come. I'm kind of hitting the wall again and have to do work. I'd like to move on with CS50, so any hints are greatly appreciated at this point.
/**
* copy.c
*
* Computer Science 50
* Problem Set 4
*
* Copies a BMP piece by piece, just because.
*/
#include <stdio.h>
#include <stdlib.h>
#include "bmp.h"
int main(int argc, char* argv[])
{
// ensure proper usage
if (argc != 4)
{
printf("Usage: ./copy n infile outfile\n");
return 1;
}
// remember filenames
char* infile = argv[2];
char* outfile = argv[3];
int n = atoi(argv[1]);
// open input file
FILE* inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("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
*/
// 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;
}
/*
TRANSFORM
[ ] pixel repeated n times
[X] row repeated n times
*/
/**transform padding
* the input and the output files do not necessarily have the same amount of padding.
* calculate the output file padding, based on the changed header values.
*/
// determine padding for scanlines
int padding_in = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
int padding_out = (4 - ((bi.biWidth * n * sizeof(RGBTRIPLE)) % 4)) % 4;
/**transform header properties
*/
// store infile header property values
// int in_biWidth = bi.biWidth;
int in_biHeight = bi.biHeight;
// int in_biSizeImage = bi.biSizeImage;
// int in_bfSize = bf.bfSize;
// calculate outfile header propery values
// int out_biWidth = bi.biWidth * n;
int out_biHeight = bi.biHeight * n;
// int out_biSizeImage = (bi.biWidth * sizeof(RGBTRIPLE) + padding_out) * abs(bi.biHeight); // this works;
// int out_bfSize = bi.biSizeImage + 54;
// update output object's values to write
/**resize horizontally [x]
* width of image (in pixels)
* does not include padding
* write it n times in the outfile
*/
bi.biWidth = bi.biWidth * n;
/**resize vertically [ ]
* method 1: "Rewrite" methods | remember pixels in an array || write array as many times as needed
* method 2: "Re-copy" methods | go back to the start of the original row with fseek() || repeat the horizontal resizing
*/
bi.biHeight = bi.biHeight * n;
/** biSizeImage = the size (in bytes) of the image
* total size of image (in bytes)
* includes pixels and padding
*/
bi.biSizeImage = (bi.biWidth * sizeof(RGBTRIPLE) + padding_out) * abs(bi.biHeight); // this works
/** bfsize = the size (in bytes) of the bitmap file.
*/
bf.bfSize = bi.biSizeImage + 54; // 54 is the size of the meta data
/*
WRITE
*/
// write outfile's BITMAPFILEHEADER
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
// temporary storage
RGBTRIPLE triple;
/**
* read the infile, pixel by pixel.
* for every pixel in the infile print n pixels to the outfile.
* for every row in the infile, produce n rows in the outfile.
*/
// iterate over infile's scanlines to read
for (int in_row = 0; in_row < abs(out_biHeight); in_row++)
{
//keep track of pointer position
int orig_pos = ftell(inptr);
// for every row in the infile, produce n rows in the outfile.
for (int out_row = 0; out_row < abs(in_biHeight); out_row++)
{
// iterate over pixels in scanline to read
// read RGB triple from infile
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
// write for each col
for (int out_col = 0; out_col < n; out_col++ )
{
// write RGB triple to outfile
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
}
/**add padding to row [ ]
* each pixel is 3 bytes
* size of each scanline must be a multiple of 4 bytes
* if the number of pixels isn't a multiple of 4 we need padding
* fputc(chr, output) to write padding | chr: char to write | outptr: FILE* to write to | fputc(0x00, outptr);
* fseek(inptr, amount, from); to move file position indicator | inptr:FILE* to seek in | amount: number of bytes to move cursor | from: SEEK_CUR(current position in file) || SEEK_SET (beginninng of file) || SEEK_END (end of file)
* make sure your file position indicator is at the correct point to resize vertically [ ]
* calculate input file padding and output file padding separately
*/
// skip over padding, if any
fseek(inptr, padding_in, SEEK_CUR);
// then add it back (to demonstrate how)
for (int k = 0; k < padding_out; k++)
{
fputc(0x00, outptr);
}
if(in_row < (n-1))
{
int curr_pos = ftell(inptr);
fseek(inptr, -(curr_pos - orig_pos), SEEK_CUR);
}
}
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// that's all folks
return 0;
}
_______________________________ Update 3 _______________________________
I need to solve this, this is crazy.