[英]C - Parsing arbitrary image file
对于一个学习示例,我给了一个图像文件以这种格式进行解析:
我已经创建了一个结构,并且可以成功地用二进制文件中的数据填充它。
但是,我现在的任务是缩小/裁剪图像。 我计划取两个x,y坐标。 一个坐标表示图像数据中的开始像素,然后另一个坐标确定结束像素,以便它将从原始图像中切割出一个矩形并将其保存到文件中(结果图像将是2组中的矩形)。坐标)。
什么是进行此种植操作的有效方法? 我正在考虑将每个“像素”放入一个像素结构中,并具有一个二维像素数组。 但是,这似乎使它变得比必要的更为复杂。
我已经在网上搜索过,但是发现的大多数与图像处理有关的示例都使用了api。
最好的事情是拥有一个新的结构,将其视为一个对象。 从文件加载图像或创建新图像(用零填充)。 之后,您可以使用使用帮助器功能来获取像素或向/从图像对象放置像素。
在内部,您可以将对象表示为字节数组(无符号char *)或结构数组,但是需要仔细定义它们。 现在,我将使用字节数组方法。 为了使结构正常工作,您可能需要小心,例如,确保结构的大小与下面的大小相同。 使用字节数组,您只需将(y * width + x)* pixel_size用作像素的指针,将+0表示红色,将+1表示绿色,等等。由于这听起来像是一个播放项目或工作分配,因此不必它运行起来很快,只需使其运行即可,让编译器担心速度。
----进行改造----
for (x=0;x<x_new_max;x++)
for (y=0;y<y_new_max;y++) {
unsigned old_x = transform_x(x); // essentially old_x = x * scale;
unsigned old_y = transform_y(y); // essentially old_y = y * scale;
put_pixel(new_image,x,y,get_pixel(old_image,old_x,old_y));
}
或类似的东西,转换函数是关键,x = x * scale,比例将取决于操作函数,即使您在整数数学方面也不错,则可以以float或fixed进行转换。 x比例尺和y比例尺可能不同。
将图片缩小一半new_max_x = old_max_x / 2; new_max_y = old_max_y / 2; x_scale = 0.5; y_scale = 0.5;
玩得开心
这取决于您如何设置图像类。 如果您将像素存储在矩阵中,则可以执行以下操作:
for (int i = 0; i <= height*shrink_factor; ++i){
for (int j = y1; j <= width*shrink_factor; ++j){
new.pixels[i][j] = old.pixels[i/shrink_factor][j/shrink_factor];
}
}
对于裁剪:
for (int i = x1; i <= x2; ++i){
for(int j = y1; j <= y2; ++j){
new.pixels[i-x1][j-y1] = old.pixels[i][j];
}
}
为新的图像数据分配一个内存块。 然后将指针src
设置为指向原始图像数据的左上像素,另一个dst
指向新图像数据的开始。 然后,只需为新图像的每一行将一条(新)行的像素数据从src
复制到dst
在每行之后将src
原始宽度,将dst
新宽度。
编辑:我做了一个快速的实现-这是裁剪操作的关键部分。
我用于图像数据的结构:
struct image {
uint32_t w; /* width in pixels */
uint32_t h; /* height in pixels */
uint32_t *data; /* pixel data */
};
...这是裁剪代码,其中oimg
和nimg
是分别指向原始图像和裁剪图像的struct image
的指针。 已分配裁剪图像的data
(大小为nimg->w * nimg->h * sizeof(uint32_t)
),但未初始化。 x
和y
是oimg
裁剪区域的左上角坐标。 nimg->w
和nimg->h
已设置为裁剪图像的宽度和高度(以像素为单位)。
/* src is offset by y lines, plus x pixels into source image data */
uint32_t *src = oimg->data + y * oimg->w + x;
/* dst is at start of new image data */
uint32_t *dst = nimg->data;
for (i = 0; i < nimg->h; i++) {
/* memcpy() one full new image line (nimg->w * sizeof(uint32_t)) */
memcpy(dst, src, sizeof(uint32_t) * nimg->w);
dst += nimg->w; /* increment dst by a full new image line */
src += oimg->w; /* increment src by a full source image line */
}
上面的代码假定在一个图像行的末尾与下一个图像行的末尾之间没有多余的数据,并且每个图像都有自己的像素数据。 一些库将保留“跨步”值以及图像宽度,该值保留行之间的偏移量。 这允许在图像线之间添加额外的填充或未使用的像素,这对于保持对齐或允许包含较大图像的一部分的图像可以共享像素数据,而不是每个图像都有单独的副本是有用的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.