Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Resizes a BMP image by n-factor
- */
- #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 n infile outfile\n");
- return 1;
- }
- // remember filenames
- float n = atof(argv[1]);
- char *infile = argv[2];
- char *outfile = argv[3];
- // check if n value in range
- if (n < 0.0 || n > 100.0)
- {
- fprintf(stderr, "n value out of range! [0.0-100.0]\n");
- return 2;
- }
- // open input file
- FILE *inptr = fopen(infile, "r");
- if (inptr == NULL)
- {
- fprintf(stderr, "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 5;
- }
- // determine padding for scanlines of infile
- int og_padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
- // keep infile's width, height
- LONG og_biWidth = bi.biWidth,
- og_biHeight = bi.biHeight;
- // allocate memory for scanline pixels(array of RGBTRIPLE)
- RGBTRIPLE *rgb_array = malloc(og_biWidth * sizeof(RGBTRIPLE));
- // calculate outfile's header parameters
- bi.biWidth *= n;
- bi.biHeight *= n;
- // determine padding for scanlines of outfile
- int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
- // calculate rest of outfile's header parameters
- bi.biSizeImage = abs(bi.biHeight) * (bi.biWidth * sizeof(RGBTRIPLE) + padding);
- bf.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bi.biSizeImage;
- // 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(og_biHeight); i < biHeight; i++)
- {
- printf("\n\ncurrent scanline: %d\n\n", i);
- // write horizontal scanlines n-times (vertical resize)
- for (int v_row = 0; v_row < n; v_row++)
- {
- if (v_row > 0)
- printf("\n\nCopied %i scanline\n\n", i);
- printf("new rgb_array loaded:\n");
- // read scanline's RGB triples from infile to rgb_array
- for (int pixel = 0; pixel < og_biWidth; pixel++)
- {
- fread(&rgb_array[pixel], sizeof(RGBTRIPLE), 1, inptr);
- printf("pixel %d: %x ", pixel, rgb_array[pixel].rgbtRed);
- printf("%x ", rgb_array[pixel].rgbtGreen);
- printf("%x\n", rgb_array[pixel].rgbtBlue);
- }
- // iterate over pixels in scanline
- for (int j = 0; j < og_biWidth; j++)
- {
- // write horizontal scanline n-times (resize)
- for (int h_row = 0; h_row < n; h_row++)
- {
- printf("J = %d\n", j);
- // if n has a decimal point
- if (fmod(n, 1)!= 0)
- {
- // first pixel is always the first pixel from scanline
- if (j == 0)
- {
- printf("First (%d) pixel of scanline written.\n", j);
- fwrite(&rgb_array[j], sizeof(RGBTRIPLE), 1, outptr);
- }
- // if n is bigger than 1 - bmp has more pixels, so rewrite last row for each pixel in scanline
- if (n > 1)
- {
- // only write enough pixels to fill extended scanline
- if (j < bi.biWidth)
- {
- printf("Write %dTH pixel of scanline (rgb_array = %d)\n", j+1, j);
- fwrite(&rgb_array[j], sizeof(RGBTRIPLE), 1, outptr);
- }
- }
- // else if n less than 1
- else
- {
- // only write enough pixels to fill shrunk scanline
- if (j < bi.biWidth)
- {
- printf("%d pixel: value %d of rgb_array\n", j+1, j+2);
- fwrite(&rgb_array[j + 2], sizeof(RGBTRIPLE), 1, outptr);
- }
- }
- }
- else
- {
- printf("Wrote normally\n");
- fwrite(&rgb_array[j], sizeof(RGBTRIPLE), 1, outptr);
- }
- }
- }
- // skip over og_padding, if any
- fseek(inptr, og_padding, SEEK_CUR);
- // then add it back (to demonstrate how)
- for (int k = 0; k < padding; k++)
- {
- fputc(0x00, outptr);
- }
- // go back with seeker for vertical resizing of scanlines
- if (v_row < n - 1)
- {
- fseek(inptr, -(abs(og_biWidth) * (int)sizeof(RGBTRIPLE) + og_padding), SEEK_CUR);
- }
- }
- }
- // free memory of rgb_array
- free(rgb_array);
- // close infile
- fclose(inptr);
- // close outfile
- fclose(outptr);
- // success
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement