I'm really sorry for doing this again, but I really need to understand how to do this correctly. I'll post both my horizontal resize code and my vertical resize code. The former is working correctly, but I'll post it just in case.
This is the entire for-loop, by the way:
for (int i = 0, biHeight = abs(img_height); i < biHeight; i++)
{
// iterate over pixels in scanline
for (int j = 0; j < img_width; j++)
{
// temporary storage
RGBTRIPLE triple;
// read RGB triple from infile
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
for (int index = 0; index <= n - 1; index++)
{
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
}
for (int k = 0; k < new_padding; k++)
{
fputc(0x00, outptr);
}
fseek(inptr, padding, SEEK_CUR);
// send infile cursor back
// before reading the next RGBTRIPLE data
long offset = sizeof(RGBTRIPLE);
fseek(inptr, -1 * (offset * img_width + padding), SEEK_CUR);
// vertical resize
// for each row
for (int l = 0; l < biHeight; l++)
{
// temporary storage for triples data
RGBTRIPLE triple;
int m;
for (int iii = 0; iii < n - 1; iii++)
{
for (m = 0; m < img_width; m++)
{
// read triples data from infile
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
// for n - 1 times:
// write pixels and padding to outfile:
for (int index = 0; index < n; index++)
{
// write pixels to outfile
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
}
// write padding to outfile
for (int k = 0; k < new_padding; k++)
{
fputc(0x00, outptr);
}
// send infile cursor back
fseek(inptr, -1 * (offset * m), SEEK_CUR);
}
// write pixels and padding to outfile
// skip over infile padding:
for (m = 0; m < img_width; m++)
{
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
for (int index = 0; index < n; index++)
{
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
}
for (int k = 0; k < new_padding; k++)
{
fputc(0x00, outptr);
}
fseek(inptr, padding, SEEK_CUR);
}
}
This is the pseudo code for vertical resize I'm trying to implement:
for each row
for n - 1 times
write pixels and padding to outfile
send infile cursor back
write pixels and padding to outfile
skip over infile padding
I found the vertical resize code that I'm using on another post on this forum, and I'm trying to have it work on my code (to no avail).
Isn't there a way to use the return value ftell() to see whether the cursor is at the right position in the infile and to send it back if it isn't? If there's a good way to do this, please help me figure it out.
Oh and, by the way, the output for resize.c currently looks like this:
Again, I'm really sorry to keep doing this. But I really want to figure out how to do this and I'm having a lot of trouble with it.
Edit: Okay, I'll add in the whole code because of Cliff B said.
/**
* resize.c
*
* Computer Science 50
* Problem Set 4
*
* Resizes the file whose name is passed to it as a commandline argument.
*/
#include <stdio.h>
#include <stdlib.h>
#include "bmp.h"
int main(int argc, char* argv[])
{
// ensure proper usage
if (argc != 4)
{
printf("Usage: ./resize n infile outfile\n");
return 1;
}
// remember filenames
char* infile = argv[2];
char* outfile = argv[3];
// change n into a number so we can use it as such
int n = atoi(argv[1]);
if (n <= 0 || n > 100)
{
printf("The value provided as the size must be that of a positive integer less than or equal to 100!\n");
return 2;
}
// open input file
FILE* inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("Could not open %s.\n", infile);
return 3;
}
// open output file
FILE* outptr = fopen(outfile, "w");
if (outptr == NULL)
{
fclose(inptr);
fprintf(stderr, "Could not create %s.\n", outfile);
return 4;
}
// 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;
}
// remember the old padding
int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
// remember dimensions of original image
int img_height = bi.biHeight;
int img_width = bi.biWidth;
// calculate dimensions of resized image
bi.biHeight *= n;
bi.biWidth *= n;
int resized_height = bi.biHeight;
int resized_width = bi.biWidth;
// determine scanline padding
int new_padding = (4 - (resized_width * sizeof(RGBTRIPLE)) % 4) % 4;
// update header info
bi.biSizeImage = ((resized_width * sizeof(RGBTRIPLE) + new_padding) * abs(resized_height));
bf.bfSize = bi.biSizeImage + (sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER));
// 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(img_height); i < biHeight; i++)
{
// iterate over pixels in scanline
for (int j = 0; j < img_width; j++)
{
// temporary storage
RGBTRIPLE triple;
long offset = sizeof(RGBTRIPLE);
// read RGB triple from infile
for (int l = 0; l < n - 1; l++)
{
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
for (int index = 0; index <= n - 1; index++)
{
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
for (int k = 0; k < new_padding; k++)
{
fputc(0x00, outptr);
}
fseek(inptr, -1 * offset * j, SEEK_CUR);
}
for (int index = 0; index <= n - 1; index++)
{
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
for (int k = 0; k < new_padding; k++)
{
fputc(0x00, outptr);
}
fseek(inptr, padding, SEEK_CUR);
}
}
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// that's all folks
return 0;
}
Edit2: Okay, I've made some changes to the code. It's still completely wrong, but I feel like I'm getting somewhere with Cliff B's pointers. Anyway, here's the output for when n=1:
Edit3: I said this in below comments, and I'll repeat it here:
I used RISHABH KALAKOTI's code as a reference to fix mine. Now I want to study it to make sure I understand it because it actually works perfectly. Can you help me out so that I can call the code mine? I'll leave a note in comments to tell David that I found the code on this site. Hopefully it's not completely against the course's academic honesty code.
Here's the code I have now (and it works):
/**
* resize.c
*
* Computer Science 50
* Problem Set 4
*
* Resizes the file whose name is passed to it as a commandline argument.
*/
#include <stdio.h>
#include <stdlib.h>
#include "bmp.h"
int main(int argc, char* argv[])
{
// ensure proper usage
if (argc != 4)
{
printf("Usage: ./resize n infile outfile\n");
return 1;
}
// remember filenames
char* infile = argv[2];
char* outfile = argv[3];
// change n into a number so we can use it as such
int n = atoi(argv[1]);
if (n <= 0 || n > 100)
{
printf("The value provided as the size must be that of a positive integer less than or equal to 100!\n");
return 2;
}
// open input file
FILE* inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("Could not open %s.\n", infile);
return 3;
}
// open output file
FILE* outptr = fopen(outfile, "w");
if (outptr == NULL)
{
fclose(inptr);
fprintf(stderr, "Could not create %s.\n", outfile);
return 4;
}
// 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;
}
// remember the old padding
int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
// remember dimensions of original image
int img_height = bi.biHeight;
int img_width = bi.biWidth;
// calculate dimensions of resized image
bi.biHeight *= n;
bi.biWidth *= n;
int resized_height = bi.biHeight;
int resized_width = bi.biWidth;
// determine scanline padding
int new_padding = (4 - (resized_width * sizeof(RGBTRIPLE)) % 4) % 4;
// update header info
bi.biSizeImage = ((resized_width * sizeof(RGBTRIPLE) + new_padding) * abs(resized_height));
bf.bfSize = bi.biSizeImage + (sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER));
// write outfile's BITMAPFILEHEADER
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
// pseudo code for resizing:
// for each row
// for n - 1 times
// write pixels and padding to outfile
// send infile cursor back
// write pixels and padding to outfile
// skip over infile padding
// iterate over infile's scanlines
// for each row
for (int outer_index = 0, biHeight = abs(img_height); outer_index < biHeight; outer_index++)
{
int img_width_ref;
// variable to store the size of RGBTRIPLE
// as a signed long, so that it can store
// negative values
long offset = sizeof(RGBTRIPLE);
// temporary storage
RGBTRIPLE triple;
for (int inner_index = 0; inner_index < n - 1; inner_index++)
{
// write pixels and padding to the file
// have img_width_ref represent original image's width
// as it'll go until that value in the loop
for (img_width_ref = 0; img_width_ref < img_width; img_width_ref++)
{
// read pixels from infile
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
// write pixels to outfile
for (int write_index = 0; write_index < n; write_index++)
{
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
}
// write padding to the outfile
for (int outfile_padding_index = 0; outfile_padding_index < new_padding; outfile_padding_index++)
{
fputc(0x00, outptr);
}
// send infile cursor back
// by the size of an RGBTIRPLE
// multiplied by the the width of the scanline
fseek(inptr, -1 * offset * img_width_ref, SEEK_CUR);
}
// write pixels, padding to outfile
for (img_width_ref = 0; img_width_ref < img_width; img_width_ref++)
{
// read pixels from infile
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
// write pixels and padding to the file
// write pixels to outfile
for (int write_index = 0; write_index < n; write_index++)
{
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
}
// write padding to the outfile
for (int outfile_padding_index = 0; outfile_padding_index < new_padding; outfile_padding_index++)
{
fputc(0x00, outptr);
}
// skip over infile padding
fseek(inptr, padding, SEEK_CUR);
}
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// that's all folks
return 0;
}
I'll also post a link to the where the code I used as reference is (I'm trying to see what it's doing before I submit mine):
cs50 pset4 resize 're-copy' implementation
I just need to ask about the "for each row" thing. Is that just the loop going from 0 until the width of the infile? And the "for n - 1 times" part is the loop going from 0 to n - 2, reading from the infile, then the loop going from 0 to n - 1 and writing pixels to the outfile? Am I right so far?
But why does it have to write pixels to the outfile twice, once in each of the different loops? Is it because it has to complete the scanlines like that and it won't work with just writing pixels to the outfile once?
I'm doing my best to understand this, so please work with me here. Thanks in advance.