代码之家  ›  专栏  ›  技术社区  ›  navy1978

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

  •  0
  • navy1978  · 技术社区  · 3 年前

    我用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所建议的,也许我需要通过正确的解码来操作像素,但我不知道如何做到这一点,有人有其他建议吗?

    我得到的图像确实失真了: enter image description here

    0 回复  |  直到 3 年前
        1
  •  4
  •   Mark Setchell    3 年前

    更新的答案

    如果您想在不使用的情况下解码RGB565并写入NetPBM格式的PNM文件 ImageMagick ,您可以执行以下操作:

    #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() 它只需写入304x98x2字节,起始于 &(example.pixel_data) 到stdout:

    使用以下内容编译它:

    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);
    }
    

    如果我用你通过谷歌硬盘提供的文件运行这个,我会得到:

    enter image description here