将 C 源图像转储转换为原始图像

Posted

技术标签:

【中文标题】将 C 源图像转储转换为原始图像【英文标题】:Convert C-Source image dump into original image 【发布时间】:2022-01-09 21:44:57 【问题描述】:

我使用 GIMP 创建了一个 C 源图像转储,如下所示:

/* GIMP RGBA C-Source image dump (example.c) */

static const struct 
  guint      width;
  guint      height;
  guint      bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ 
  guint8     pixel_data[304 * 98 * 2 + 1];
 example= 
  304, 98, 2,
  "\206\061\206\061..... 

有没有办法在 GIMP 中再次读取它以取回原始图像?因为这似乎不可能。 或者它是否存在可以进行这种反向转换的工具?

已编辑

根据一些建议,我尝试编写一个简单的 C 程序,以使反向覆盖最终得到与在互联网上找到的另一个代码非常相似的东西,但两者都不起作用:

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "imgs_press.h"
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

using namespace std;

int main(int argc, char** argv) 
    int fd;
    char *name = "orignal_img.pnm";
    fd = open(name, O_WRONLY | O_CREAT, 0644);
    if (fd == -1) 
        perror("open failed");
        exit(1);
    

    if (dup2(fd, 1) == -1) 
        perror("dup2 failed"); 
        exit(1);
    

    // file descriptor 1, i.e. stdout, now points to the file
    // "helloworld" which is open for writing
    // You can now use printf which writes specifically to stdout

  printf("P2\n");
  printf("%d %d\n", press_high.width, press_high.height);
  for(int x=0; x<press_high.width * press_high.height * 2; x++) 
    printf("%d ", press_high.pixel_data[x]);
  

根据 n-1-8e9-wheres-my-share-m 的建议,也许我需要使用正确的解码来操作像素,但我不知道该怎么做,还有其他建议吗?

我得到的图像确实是失真的:

【问题讨论】:

评论不用于扩展讨论;这个对话是moved to chat。 【参考方案1】:

更新答案

如果你想解码 RGB565 并在不使用 ImageMagick 的情况下编写 NetPBM 格式的 PNM 文件,你可以这样做:

#include <stdint.h>   /* for uint8_t */
#include <stdio.h>    /* for printf */

/* tell compiler what those GIMP types are */
typedef int guint;
typedef uint8_t guint8;

#include <YOURGIMPIMAGE>

int main()

   int w = gimp_image.width;
   int h = gimp_image.height;
   int i;
   uint16_t*  RGB565p = (uint16_t*)&(gimp_image.pixel_data);

   /* Print P3 PNM header on stdout */
   printf("P3\n%d %d\n255\n",w, h);

   /* Print RGB pixels, ASCII, one RGB pixel per line */
   for(i=0;i<w*h;i++)
      uint16_t RGB565 = *RGB565p++;
      uint8_t r = (RGB565 & 0xf800) >> 8;
      uint8_t g = (RGB565 & 0x07e0) >> 3;
      uint8_t b = (RGB565 & 0x001f) << 3;
      printf("%d %d %d\n", r, g ,b);
   

编译:

clang example.c

然后运行:

./a.out > result.pnm

除了您的示例图像之外,我还没有对它进行过广泛的测试,因此您可能需要制作一个带有一些红色、绿色、蓝色和灰色阴影的测试图像,以确保我所有的操作都是正确的。

原答案

恢复图像的最简单方法是……让 ImageMagick 来做。

所以,获取你的 C 文件并添加一个 main() 到它,它只是将从 &amp;(example.pixel_data) 开始的 304x98x2 字节写入标准输出:

用类似的东西编译它:

clang example.c -o program    # or with GCC
gcc example.c -o program

然后运行它,写入 ImageMagick 的文件:

./program > image.bin

并告诉 ImageMagick 它的大小、类型、位置以及您想要的结果:

magick -size 304x98 RGB565:image.bin result.png

我对以下代码进行了快速但不太彻底的测试,它适用于我使用 GIMP 生成的图像。请注意,它不处理 alpha/透明度,但如有必要可以添加。另存为program.c:

#include <unistd.h>   /* for write() */
#include <stdint.h>   /* for uint8_t */

/* tell compiler what those GIMP types are */
typedef int guint;
typedef uint8_t guint8;

<PASTE YOUR GIMP FILE HERE>

int main()

   /* Work out how many bytes to write */
   int nbytes = example.width * example.height * 2;

   /* Write on stdout for redirection to a file - may need to reopen in binary mode if on Windows */
   write(1, &(example.pixel_data), nbytes);

如果我使用您通过 Google 云端硬盘提供的文件运行此程序,我会得到:

【讨论】:

无需手动粘贴 GIMP 文件。只需使用#include "example.c" @thebusybee 我建议扩展他已经拥有的 OP 的 example.c,这就是我建议的 clanggcc 命令中的文件名......但我同意你的观点。跨度> 我已经尝试过了,但它不起作用,你的建议等于:gist.github.com/svenk/… 但它不起作用,reuslt 是图像失真,我已经按照你告诉我的做了:convert -size 304x98 source.bin 结果.png 顺便说一句,图像由魔术师识别,例如:“PGM 304x98 304x98+0+0 8-bit Grayscale Gray 212071B 0.000u 0:00.000” @MarkSetchell 我已经用我使用的代码更新了我的问题,我写的代码似乎不对,需要对像素进行一些解码

以上是关于将 C 源图像转储转换为原始图像的主要内容,如果未能解决你的问题,请参考以下文章

如果使用 javascript 或 jQuery 找不到源图像,如何显示图像标题

使用 OpenCV 中的轮廓点从源图像创建图像?

获取 HTML 并使用 rasterizehtml 在画布中生成图像 - 动态源图像

opencv的img.flat的函数用法

qt 5 对图片解析

c# 在保持纵横比的同时将图像调整为不同的大小