I've been trying to fix this code. Everything seems to be working fine based on the printf tests I've added but the new image isn't resizing horizontally.
This is for an online course I'm taking so the coding may look elementary but we may not have covered more advanced solutions yet.
I've pasted both programs needed to execute the program and also included the pics.
Execute the program using this argument or similar ./copy 2 staff.bmp large.bmp
.
// Copies a BMP file
#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 num = atoi(argv[1]);
char *infile = argv[2];
char *outfile = argv[3];
if (num < 1 || num > 100)
{
fprintf(stderr, "Resize only 1-100. Try again.\n");
return 4;
}
// 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;
}
int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
printf("padding%i ", padding);
BITMAPINFOHEADER newbi = bi;
BITMAPFILEHEADER newbf = bf;
newbi.biWidth = bi.biWidth * num;
printf("newbiwidth%i ", newbi.biWidth);
newbi.biHeight = bi.biHeight * num;
printf("newbiheight%i ", newbi.biHeight);
// determine padding for scanlines
int newpadding = (4 - (newbi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
printf("newpadding%i ", newpadding);
newbi.biSizeImage = (newbi.biWidth * sizeof(RGBTRIPLE) + newpadding) * abs(newbi.biHeight);
printf("newbisizeimage%i ", newbi.biSizeImage);
newbf.bfSize = newbi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
printf("newbfsize%i ", newbf.bfSize);
// write outfile's BITMAPFILEHEADER
fwrite(&newbf, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&newbi, sizeof(BITMAPINFOHEADER), 1, outptr);
// temporary storage
RGBTRIPLE triple;
RGBTRIPLE *newtriple = malloc(num * sizeof(RGBTRIPLE) + 1);
RGBTRIPLE *sline = malloc(newbi.biWidth * sizeof(RGBTRIPLE));
// read RGB triple from infile
for (int i = 0, biheight = abs(bi.biHeight); i < biheight; i++)
{
printf("H%i ", i);
for (int j = 0; j < bi.biWidth; j++)
{
printf("W%i ", j);
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
//store triple times resize number
for (int m = 0; m < num; m++)
{
newtriple[m] = triple;
printf("T%i ", m);
}
//store new triple as new scanline
sline[j] = *newtriple;
printf("S%i ", j);
}
//write new scanline to file
for (int k = 0; k < num; k++)
{
printf("F%i ", k);
fwrite(sline, newbi.biWidth * 3, 1, outptr);
// add padding if any
for (int h = 0; h < newpadding; h++)
{
fputc(0x00, outptr);
}
// skip over padding, if any
fseek(inptr, padding, SEEK_CUR);
}
}
free(newtriple);
free(sline);
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// success
return 0;
}
// BMP-related data types based on Microsoft's own
#include <stdint.h>
// aliases for C/C++ primitive data types
// https://msdn.microsoft.com/en-us/library/cc230309.aspx
typedef uint8_t BYTE;
typedef uint32_t DWORD;
typedef int32_t LONG;
typedef uint16_t WORD;
// information about the type, size, and layout of a file
// 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;
// information about the dimensions and color format
// 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;
// relative intensities of red, green, and blue
// https://msdn.microsoft.com/en-us/library/dd162939(v=vs.85).aspx
typedef struct
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;
for (int j = 0; j < bi.biWidth; j++) { ... sline[j] = *newtriple; }
This is only setting pixels from 0 to the original width, for each row. So for example, if you double the width, then the second right half of the image is not initialized, which is what appears in your output image. You should set all the pixels as shown below. You don't actually need newtriple
Also make sure to skip for padding immediately after reading each row.
for(int j = 0; j < bi.biWidth; j++)
{
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
for(int m = 0; m < num; m++)
{
sline[j * num + m] = triple;
}
//sline[j] = *newtriple; <- remove
}
fseek(inptr, padding, SEEK_CUR); //<- move fseek here
What sline[j * num + m]
is doing:
Lets say we have this row:
sline_in[4]: 0 1 2 3 4
And we want to zoom in with a factor 2. It should become:
sline_out[8]: 0 0 1 1 2 2 3 3 4 4
We use the loop:
for(int j = 0; j < width; j++)
{
sline_out[j * 2 + 0] = sline_in[j];
sline_out[j * 2 + 1] = sline_in[j];
}
For an arbitrary zoom factor, we use the following:
for(int j = 0; j < width; j++)
{
for(int m = 0; m < zoom; m++)
sline_out[j * zoom + m] = sline_in[j];
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.