1. // png2gpn.cpp
  2. //
  3.  
  4. #include "stdafx.h"
  5.  
  6. #ifndef MAX_PATH
  7. #define MAX_PATH 260
  8. #endif
  9.  
  10. struct StImage {
  11.     int signature;
  12.     int version;
  13.     short width;
  14.     short height;
  15.     int size;
  16.     unsigned int data[1];
  17. };
  18.  
  19. struct StOption {
  20.     bool use_alpha;
  21.     bool verbose;
  22. } g_option;
  23.  
  24. enum _errors {
  25.     ERROR_NOERROR,
  26.     ERROR_FOPEN,
  27.     ERROR_DECODE,
  28.     ERROR_NOMEMORY,
  29.     ERROR_UNKNOWN_OPTION,
  30.     COUNT_OF_ERROR
  31. };
  32.  
  33. char g_szErrorBuf[1024] = "";
  34.  
  35. int processFile(const char *file)
  36. {
  37.     class Finalizer {
  38.     public:
  39.         Finalizer() {
  40.             fp = NULL;
  41.             buf = NULL;
  42.             img = NULL;
  43.         }
  44.         ~Finalizer() {
  45.             if (fp) {
  46.                 fclose(fp);
  47.             }
  48.             if (fp) {
  49.                 fclose(fp);
  50.             }
  51.             if (buf) {
  52.                 delete[] buf;
  53.             }
  54.             if (img) {
  55.                 gdImageDestroy(img);
  56.             }
  57.         }
  58.         FILE *fp;
  59.         unsigned char *buf;
  60.         gdImagePtr img;
  61.     } obj;
  62.  
  63.     FILE *fp = fopen(file, "r");
  64.     if (!fp) {
  65.         printf("Filename: %s\n", file);
  66.         return ERROR_FOPEN;
  67.     }
  68.     obj.fp = fp;
  69.  
  70.     gdImagePtr img = gdImageCreateFromPng(fp);
  71.     if (!img) {
  72.         return ERROR_DECODE;
  73.     }
  74.     obj.img = img;
  75.  
  76.     fclose(fp);
  77.     obj.fp = NULL;
  78.  
  79.     int bytes_per_pixel = g_option.use_alpha ? 4 : 2;
  80.     int size = sizeof (StImage) - 4 + bytes_per_pixel * gdImageSX(img) * gdImageSY(img);
  81.     unsigned char *buf = new unsigned char[size];
  82.     if (!buf) {
  83.         return ERROR_NOMEMORY;
  84.     }
  85.     obj.buf = buf;
  86.  
  87.     StImage *gpn = (StImage *)buf;
  88.     gpn->signature = *(int *)"gpng";
  89.     gpn->version = g_option.use_alpha ? 1 : 0;
  90.     gpn->width = gdImageSX(img);
  91.     gpn->height = gdImageSY(img);
  92.     gpn->size = size;
  93.  
  94.     unsigned short *p = (unsigned short *)gpn->data;
  95.     unsigned int pixel;
  96.  
  97.     for (int y = 0; y < gpn->height; y++) {
  98.         for (int x = 0; x < gpn->width; x++) {
  99.             int color = gdImageGetPixel(img, x, y);
  100.             int r = gdTrueColorGetRed(color);
  101.             int g = gdTrueColorGetGreen(color);
  102.             int b = gdTrueColorGetBlue(color);
  103.             int a = 255 - (gdTrueColorGetAlpha(color) << 1);
  104.  
  105.             if (g_option.use_alpha) {
  106.                 pixel = (b>>3<<10) | (g>>3<<21) | (r>>3) | ((a + 1)>>3<<15);
  107.                 *(unsigned int *)p = pixel;
  108.                 p += 2;
  109.             } else {
  110.                 pixel = (b>>3<<10)|(g>>3<<5)|(r>>3)|(1<<15);
  111.                 *p = (unsigned short)pixel;
  112.                 p++;
  113.             }
  114.  
  115.             if (g_option.verbose) {
  116.                 char bits[33];
  117.                 int i = 0;
  118.                 unsigned int mask = g_option.use_alpha ? 0x80000000 : 0x8000;
  119.                 for (; mask; i++, mask >>= 1) {
  120.                     bits[i] = (pixel & mask) ? '1' : '0';
  121.                 }
  122.                 bits[i] = 0;
  123.                 printf("(%3d,%3d) %02X.%02X,%02X/%02X %08X=%s\n", x, y, r, g, b, a, pixel, bits);
  124.             }
  125.         }
  126.     }
  127.  
  128.     char szOutName[MAX_PATH];
  129.     strcpy(szOutName, file);
  130.     char *dot = strrchr(szOutName, '.');
  131.     if (!dot) {
  132.         dot = szOutName + strlen(szOutName);
  133.     }
  134.     strcpy(dot, ".gpn");
  135.  
  136.     fp = fopen(szOutName, "w");
  137.     if (!fp) {
  138.         return ERROR_FOPEN;
  139.     }
  140.     obj.fp = fp;
  141.  
  142.     fwrite(buf, size, 1, fp);
  143.  
  144.     return 0;
  145. }
  146.  
  147. int main(int argc, char *argv[])
  148. {
  149.     memset(&g_option, 0, sizeof (g_option));
  150.  
  151.     int i, ret;
  152.  
  153.     for (i = 1; i < argc; i++) {
  154.         if (argv[i][0] == '-') {
  155.             switch (argv[i][1]) {
  156.             case 'a':
  157.                 g_option.use_alpha = true;
  158.                 continue;
  159.             case 'n':
  160.                 g_option.use_alpha = false;
  161.                 continue;
  162.             case 'v':
  163.                 g_option.verbose = true;
  164.                 continue;
  165.             }
  166.  
  167.             ret = ERROR_UNKNOWN_OPTION;
  168.             strcpy(g_szErrorBuf, "Unknown option");
  169.         } else {
  170.             ret = processFile(argv[i]);
  171.         }
  172.  
  173.         if (ret != 0) {
  174.             printf("Error(%d) %s: %s\n", ret, g_szErrorBuf, argv[i]);
  175.             return ret;
  176.         }
  177.     }
  178.  
  179.     return 0;
  180. }