我在调整大小问题的垂直方向上卡住了。我从Zamayla的伪代码知道,我每次都需要在输出文件上写一个数组,但是我不知道如何将值从一个传递到另一个。我是否需要使用malloc函数并通过指针传递?我对使用它不是很有经验,因为我是编程新手。请告诉我我的代码是否朝着正确的方向前进。
// Resize 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: resize queficient infile outfile\n");
return 1;
}
int n = atoi(argv[1]);
if (n < 1 || n > 100)
{
printf ("Resize queficient should be between 1 and 100\n");
return 1;
}
// remember filenames
char *infile = argv[2];
char *outfile = argv[3];
// 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;
}
/* Update header info
*saving old information
*/
BITMAPINFOHEADER old_bi;
BITMAPFILEHEADER old_bf;
old_bi = bi;
old_bf = bf;
old_bi.biHeight = bi.biHeight;
old_bi.biWidth = bi.biWidth;
int old_padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
// assign new header
bi.biHeight = bi.biHeight * n;
bi.biWidth = bi.biWidth * n;
int new_padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
bi.biSizeImage = ((sizeof(RGBTRIPLE) * bi.biWidth) + new_padding) * abs(bi.biHeight);
bf.bfSize = bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
// write outfile's BITMAPFILEHEADER
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
// Resize horizontally
for (int i = 0, old_biHeight = abs(old_bi.biHeight); i < old_biHeight; i++)
{
// iterate over pixels in scanline
for (int j = 0; j < old_bi.biWidth; j++)
{
// temporary storage
RGBTRIPLE triple;
// read RGB triple from infile
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
triple.rgbtBlue = n * triple.rgbtBlue;
triple.rgbtRed = n * triple.rgbtRed;
triple.rgbtGreen = n * triple.rgbtGreen;
// write RGB triple to outfile
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
// skip over padding, if any
fseek(inptr, old_padding, SEEK_CUR);
// then add it back (to demonstrate how)
for (int k = 0; k < old_padding; k++)
{
fputc(0x00, outptr);
}
}
/*Resize vertically
for (int i = 0, old_biHeight = abs(old_bi.biHeight); i < old_biHeight; i++ )
{
for (int j = 0; j < old_bi.biWidth; j++)
{
RGBTRIPLE triple;
char *array_of_pixels_Blue = { "n * triple.rgbtBlue" };
char *array_of_pixels_Red = { "n * triple.rgbtRed" };
char *array_of_pixels_Green = { "n * triple.rgbtGreen" };
}
for (int k = 0; k < n; k++)
{
fwrite(&array_of_pixels_Blue, sizeof(RGBTRIPLE), 1, outptr);
fwrite(&array_of_pixels_Red, sizeof(RGBTRIPLE), 1, outptr);
fwrite(&array_of_pixels_Green, sizeof(RGBTRIPLE), 1, outptr);
for (int l = 0; l < new_padding; l++)
{
fputc(0x00, outptr);
}
}
}
fseek(inptr, new_padding, SEEK_CUR);
*/
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// success
return 0;
}
答案 0 :(得分:1)
为简单起见,可以说源图像为3x2像素。如果您使用像素坐标将其绘制在“纸”(我真的建议您使用真正的笔和纸)上进行绘制,则其外观将如下所示:
+-----+-----+-----+ | 0,0 | 1,0 | 2,0 | +-----+-----+-----+ | 0,1 | 1,1 | 2,1 | +-----+-----+-----+
如果将此值乘以2
(以获得双倍尺寸的图像),则该图像将变成6x4像素的图像。放大像素的最简单方法就是在所有方向上将像素也加倍。然后,放大后的图像将看起来像这样(具有 原始 图像的像素坐标):
+-----+-----+-----+-----+-----+-----+ | 0,0 | 0,0 | 1,0 | 1,0 | 2,0 | 2,0 | +-----+-----+-----+-----+-----+-----+ | 0,0 | 0,0 | 1,0 | 1,0 | 2,0 | 2,0 | +-----+-----+-----+-----+-----+-----+ | 0,1 | 0,1 | 1,1 | 1,1 | 2,2 | 2,2 | +-----+-----+-----+-----+-----+-----+ | 0,1 | 0,1 | 1,1 | 1,1 | 2,2 | 2,2 | +-----+-----+-----+-----+-----+-----+
原始图像中的每个像素现在是新图像中的四个像素。大小乘以乘数的平方(因此,乘数3
意味着原始图像中的每个像素变为新图像中的9
个像素)。
有几种方法可以按代码进行处理,但是最简单的方法是分配两个存储区,一个用于原始图像,WxH
个“像素”大,另一个用于{{1} }“像素”大。然后,您使用一个循环从原始图像中获取每个像素,然后嵌套在内部,您将拥有另一个循环,将该像素写入新图像中的所有位置。
在 伪 代码中,可能是这样的
(W*n)x(H*n)
现在,您可能已经注意到,我没有提到“像素”的类型。那是因为没关系。可以是浮点值,整数值或// Loops over all the pixels in the original source image
for (unsigned orig_x = 0; orig_x < ORIG_WIDTH; ++orig_x)
{
for (unsigned orig_y = 0; orig_y < ORIG_HEIGHT; ++orig_y)
{
orig_pixel = GetPixelAt(orig_pixel_data, orig_x, orig_y);
// Write the original pixel (orig_pixel) N*N times in the new image data
for (unsigned new_x = 0; new_x < N; ++new_x)
{
for (unsigned new_y = 0; new_y < N; ++new_y)
{
SetPixelAt(new_pixel_data, new_x + orig_x * N, new_y + orig_y * N, orig_pixel);
}
}
}
}
的结构。
正如我之前提到的,首先使用笔和纸来完成所有操作。
答案 1 :(得分:0)
有不同的处理方法。一种选择是:
n
次。 n
写入该像素一次。还请注意,在Windows中,您需要"rb"
和"wb"
才能以二进制形式读取/写入文件:
示例:
FILE *outptr = fopen(outfile, "wb");
...
FILE *inptr = fopen(infile, "rb");
...
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
int old_width_in_bytes = old_bi.biWidth * 3 + old_padding;
for(int i = 0, old_biHeight = abs(old_bi.biHeight); i < old_biHeight; i++)
{
//skip bytes for each row, 54 bytes to account for header size
//old_width_in_bytes to account for padding
fseek(inptr, 54 + old_width_in_bytes * i, SEEK_SET);
//read/write each row, n-times
for(int resize_height = 0; resize_height < n; resize_height++)
{
// iterate over pixels in scanline
for(int j = 0; j < old_bi.biWidth; j++)
{
RGBTRIPLE triple;
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
// write each pixel n-times
for(int resize_width = 0; resize_width < n; resize_width++)
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
//padding for output
for(int k = 0; k < new_padding; k++)
fputc(0x00, outptr);
}
}