C 解析任意图像文件

C 解析任意图像文件,c,arrays,image,binary,binaryfiles,C,Arrays,Image,Binary,Binaryfiles,作为一个学习示例,我得到了一个要解析的图像文件,其格式如下: 八个字节表示高度和宽度为32位整数 文件的其余部分是填充了像素信息的图像数据,由32位信息表示: 红色、绿色、蓝色各8位 8位用于透明度信息 我已经创建了一个结构,我可以成功地用二进制文件中的数据填充它 但是,我现在的任务是缩小/裁剪图像。我计划取两个x,y坐标。一个坐标表示图像数据中的起始像素,然后另一个坐标确定结束像素,这样它将从原始图像中剪切一个矩形并将其保存到文件中(生成的图像将是两组坐标中的矩形) 进行这种种植操作的

作为一个学习示例,我得到了一个要解析的图像文件,其格式如下:

  • 八个字节表示高度和宽度为32位整数
  • 文件的其余部分是填充了像素信息的图像数据,由32位信息表示:
    • 红色、绿色、蓝色各8位
    • 8位用于透明度信息
我已经创建了一个结构,我可以成功地用二进制文件中的数据填充它

但是,我现在的任务是缩小/裁剪图像。我计划取两个x,y坐标。一个坐标表示图像数据中的起始像素,然后另一个坐标确定结束像素,这样它将从原始图像中剪切一个矩形并将其保存到文件中(生成的图像将是两组坐标中的矩形)

进行这种种植操作的有效方法是什么?我在考虑将每个“像素”放入像素结构中,并拥有一个2d像素阵列。然而,这似乎使它比可能需要的更复杂


我在网上搜索过,但我发现的大多数与图像处理相关的示例都使用api

最好是有一个新的结构,把它当作一个对象。从文件加载图像或创建新图像(用零填充)。之后,您可以使用帮助器函数来获取像素或将像素放入图像对象或从图像对象放入像素

在内部,可以将对象表示为字节数组(unsigned char*)或结构数组,但需要仔细定义它们。现在我将使用字节数组方法。要使结构正常工作,您可能需要小心,例如,确保结构的大小与下面的大小相同。使用字节数组,您只需将(y*width+x)*pixel_size作为指向像素的指针,+0表示红色,+1表示绿色等。因为它听起来确实像是一个播放项目或任务,忘记了如何加快它,只需让它开始工作,让编译器担心速度

----为了转型----


for(x=0;x取决于图像类的设置方式。如果将像素存储在矩阵中,则可以执行以下操作:

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=0;i为新图像数据分配一块内存。然后设置一个指针
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
的指针。裁剪图像的
数据
已分配(大小为
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 */
}
/*src被y线偏移,加上源图像数据中的x像素*/
uint32_t*src=oimg->data+y*oimg->w+x;
/*dst位于新图像数据的开始处*/
uint32_t*dst=nimg->data;
对于(i=0;ih;i++){
/*memcpy()一个全新的图像行(nimg->w*sizeof(uint32\u t))*/
memcpy(dst、src、sizeof(uint32_t)*nimg->w);
dst+=nimg->w;/*通过一个全新的图像行增加dst*/
src+=oimg->w;/*通过完整源映像行增加src*/
}

上面的代码假设在一个图像行的末尾和下一个图像行的开头之间没有额外的数据,并且每个图像都有自己的像素数据。一些库将保持“跨步”值以及图像宽度,该值保留行之间的偏移量;这允许图像行之间有额外的填充或未使用的像素,有助于保持对齐,或允许由较大图像的一部分组成的图像与其共享像素数据,而不是每个图像都有单独的副本。

两个字节表示高度和宽度宽度为32位整数,你的意思是8字节。是的,谢谢你指出这一点。对于你正在尝试做的事情,你甚至不需要像素结构。像素的确切组成并不重要——只是它是32位的事实。这里有一个算法来进行裁剪,我想我还不清楚。这实际上是我已经完成的。我想找出h如何进行我所描述的裁剪操作。
struct image {
  uint32_t    w;      /* width in pixels */
  uint32_t    h;      /* height in pixels */
  uint32_t    *data;  /* pixel data */
};
/* 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 */
}