0

I hit a wall a while ago on 'more comfortable' and since downgrading have been trying attempts on this for a few days - fully aware i'll be missing something, either in my logic or implementation but at this point my thinking is so misty. Any help and clarity would be totally brilliant. The output image is not correct - Where am i going wrong?

large.bmp f=2 output looks like: enter image description here

smiley.bmp f=2 output looks like: enter image description here

My truncated pseudocode is as follows:

  1. loop over height one by one
  2. loop through input pixels one by one, skipping the padding
  3. add f (resize factor) number of pixels into a new array
  4. write that array to the destination f (resize factor) times, adding any padding

My code is as follows:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "bmp.h"

int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 4)
{
    fprintf(stderr, "Usage: ./resize [scale factor] infile outfile\n");
    return 1;
}

  // remember filenames
char *infile = argv[2];
char *outfile = argv[3];

    // remember factor if between 100.0 and 0.1
float value = atof(argv[1]);
float f = roundf(10 * value) / 10;
printf("%f\n", f);


if (f>100||f<0.1)
{
    fprintf(stderr, "Usage: ./resize [scale factor BETWEEN 0.1 and 100.0] infile outfile\n");
    return 1;
}

// 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;
}

//define input dimension variables
int inWidth = bi.biWidth;
printf("%i", inWidth);
int inHeight = abs(bi.biHeight);
printf("%i", inHeight);

//define output dimension variables
bi.biWidth = round(inWidth*f);
bi.biHeight = round(inHeight*f);

  // determine padding for scanlines
int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

// determine padding for scanlines
int oldPadding = (4 - (inWidth * sizeof(RGBTRIPLE)) % 4) % 4;

// add padding to biSizeImage calculations
bi.biSizeImage = abs(bi.biHeight) * (bi.biWidth+padding);

// calculate bfSize which is total file size of bmp:
//      - biSizeImage*RGBTRIPLE size - pixels including padding
//      - biSize - info header size
//      - bfOffBits - bitmapfile header and infoheader size
bf.bfSize = (bi.biSizeImage*sizeof(RGBTRIPLE)) + bf.bfOffBits;

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

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

// size of temporary storage
int RGBTRIPLE_sizeof = sizeof(RGBTRIPLE);

// allocate memory
RGBTRIPLE * pixString = malloc(RGBTRIPLE_sizeof*bi.biWidth); 

// temporary storage
RGBTRIPLE triple;

// iterate over infile's scanlines
for (int i = 0; i < inHeight; i++)
{
    // iterate over pixels in scanline
    for (int j = 0; j < inWidth; j++)
    {
    // read RGB triple from infile
    fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
    // skip over padding, if any
    fseek(inptr, oldPadding, SEEK_CUR);
    int c=0;
    for (int y = 0; y<f; y++){
        pixString[c]=triple;
        c++;
    }
 }
    for (int s = 0; s<f; s++){
    for (int z = 0; z<bi.biWidth;z++){
        triple = pixString[z];
        fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
    }
    // then add it back
    for (int k = 0; k < padding; k++)
    {
        fputc(0x00, outptr);
    }    
    }
}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// success
return 0;
}

1 Answer 1

-1

ok so i've managed it. the count variable instantiation and definition which dictated the index value of the array that the pixels were being assigned to was inside the loop, so reset itself every time. Now I took it out of the loop and it fixed this issue.

// iterate over infile's scanlines
for (int i = 0; i < inHeight; i++)
{
// iterate over pixels in scanline
for (int j = 0; j < inWidth; j++)
{
// read RGB triple from infile
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
// skip over padding, if any
fseek(inptr, oldPadding, SEEK_CUR);
int c=0;
for (int y = 0; y<f; y++){
    pixString[c]=triple;
    c++;
    }
}
for (int s = 0; s<f; s++){
for (int z = 0; z<bi.biWidth;z++){
    triple = pixString[z];
    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
// then add it back
for (int k = 0; k < padding; k++)
{
    fputc(0x00, outptr);
}    
}
}

next issue i found was that it was upside down - a simple error of committing a positive dimension to the header file which I amended by inserting a minus into the brackets:

bi.biHeight = round(-inHeight*f);

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .