png2raw.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. // _________ __ __
  2. // / _____// |_____________ _/ |______ ____ __ __ ______
  3. // \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
  4. // / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
  5. // /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
  6. // \/ \/ \//_____/ \/
  7. // ______________________ ______________________
  8. // T H E W A R B E G I N S
  9. // Utility for Stratagus - A free fantasy real time strategy game engine
  10. //
  11. // Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
  12. //
  13. // This program is free software; you can redistribute it and/or
  14. // modify it under the terms of the GNU General Public License
  15. // as published by the Free Software Foundation; either version 2
  16. // of the License, or (at your option) any later version.
  17. //
  18. // This program is distributed in the hope that it will be useful,
  19. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. // GNU General Public License for more details.
  22. //
  23. // You should have received a copy of the GNU General Public License
  24. // along with this program; if not, write to the Free Software
  25. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  26. /* To compile this program:
  27. % g++ -o png2stratagus png2stratagus.cpp -lpng
  28. */
  29. /* This program can be used to fix the palette of a indexed png file
  30. to be suitable for Stratagus. It works like this:
  31. 1) You create a RGBA image in Gimp
  32. 2) You convert it to indexed with 227 colors
  33. [Generate Optimal Palette # Colors 227] (MAX_COLORS - 1)
  34. 3) You run png2stratagus on the image
  35. 4) The final images will be written to out.png in the current
  36. directory
  37. */
  38. #include <string>
  39. #include <fstream>
  40. #include <vector>
  41. #include <iostream>
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <png.h>
  45. #include <assert.h>
  46. class Color
  47. {
  48. public:
  49. unsigned int red;
  50. unsigned int green;
  51. unsigned int blue;
  52. Color ()
  53. : red (0), green (255), blue (0)
  54. {
  55. }
  56. Color (int r, int g, int b)
  57. : red (r), green (g), blue (b)
  58. {
  59. }
  60. };
  61. class Image
  62. {
  63. private:
  64. int m_width;
  65. int m_height;
  66. int m_transcol;
  67. std::vector<unsigned char> m_image;
  68. std::vector<Color> m_palette;
  69. public:
  70. /** Load an image from a given png source */
  71. Image (const std::string& filename)
  72. {
  73. FILE* fp;
  74. png_structp png_ptr;
  75. png_infop info_ptr;
  76. png_uint_32 pwidth, pheight;
  77. int bit_depth, color_type, interlace_type, compression_type, filter_type;
  78. int row_bytes;
  79. if ((fp = fopen(filename.c_str (), "rb")) == NULL)
  80. {
  81. perror (filename.c_str ());
  82. exit (EXIT_FAILURE);
  83. }
  84. png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
  85. NULL, NULL, NULL);
  86. info_ptr = png_create_info_struct(png_ptr);
  87. png_init_io(png_ptr, fp);
  88. png_read_info(png_ptr, info_ptr);
  89. png_get_IHDR(png_ptr, info_ptr, &pwidth, &pheight,
  90. &bit_depth, &color_type, &interlace_type,
  91. &compression_type, &filter_type);
  92. row_bytes = png_get_rowbytes(png_ptr, info_ptr);
  93. // Create the 'data' array
  94. png_bytep row_pointers[pheight];
  95. for (unsigned int i = 0; i < pheight; i++)
  96. row_pointers[i] = new png_byte[row_bytes];
  97. png_read_image(png_ptr, row_pointers);
  98. if (color_type != PNG_COLOR_TYPE_PALETTE)
  99. {
  100. std::cout << "Unsupported color type" << std::endl;
  101. exit (EXIT_FAILURE);
  102. }
  103. int num_colors;
  104. int num_trans = 0;
  105. png_colorp lpalette;
  106. png_bytep trans;
  107. png_color_16p trans_values;
  108. // Read some more data
  109. png_get_PLTE(png_ptr, info_ptr, &lpalette, &num_colors);
  110. png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values);
  111. // not sure what trans_values stand for
  112. //for (int i = 0; i < num_trans; ++i)
  113. //std::cout << "transcolors: " << trans_values[i] << std::endl;
  114. if (num_trans > 1)
  115. {
  116. std::cout << "Multiple transcolors not supported" << std::endl;
  117. exit (EXIT_FAILURE);
  118. }
  119. else if (num_trans == 1)
  120. m_transcol = trans[0];
  121. else
  122. m_transcol = -1;
  123. for (int i = 0; i < num_trans; i++)
  124. std::cout << "transcolor: " << int(trans[i]) << std::endl;
  125. m_width = pwidth;
  126. m_height = pheight;
  127. m_image.resize (m_width * m_height);
  128. // Convert the png into our internal data structure
  129. for (int y = 0; y < m_height; y++)
  130. {
  131. for (int i = 0; i < row_bytes; i++)
  132. {
  133. m_image[i + (m_width * y)] = row_pointers[y][i];
  134. }
  135. }
  136. assert (num_colors <= 256);
  137. m_palette.resize (256);
  138. for (int i = 0; i < num_colors; ++i)
  139. {
  140. m_palette[i].red = lpalette[i].red;
  141. m_palette[i].green = lpalette[i].green;
  142. m_palette[i].blue = lpalette[i].blue;
  143. }
  144. png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
  145. fclose (fp);
  146. }
  147. ~Image ()
  148. {
  149. }
  150. void write_palette16bit(const std::string& filename)
  151. {
  152. #define RGB5(r,g,b) ((r)|((g)<<5)|((b)<<10))
  153. std::ofstream out(filename.c_str());
  154. for(std::vector<Color>::iterator i = m_palette.begin(); i != m_palette.end(); ++i)
  155. {
  156. unsigned short c = RGB5(i->red/8, i->green/8, i->blue/8);
  157. out.write(reinterpret_cast<char*>(&c), sizeof(unsigned short));
  158. }
  159. }
  160. void write_palette(const std::string& filename)
  161. {
  162. std::ofstream out(filename.c_str());
  163. out.write(reinterpret_cast<char*>(&*m_palette.begin()), m_palette.size());
  164. }
  165. void write_image(const std::string& filename)
  166. {
  167. if (0)
  168. {
  169. // Simple dump of the image data
  170. std::ofstream out(filename.c_str());
  171. out.write(reinterpret_cast<char*>(&*m_image.begin()), m_image.size());
  172. }
  173. else
  174. {
  175. std::cout << "Writing tileset" << std::endl;
  176. std::ofstream out(filename.c_str());
  177. unsigned char* ptr = &*m_image.begin();
  178. int num_tiles = (get_width() * get_height()) / 64;
  179. int pitch = get_width();
  180. int tile_width = get_width()/8;
  181. for(int i = 0; i < num_tiles; ++i)
  182. {
  183. char* tile_start = reinterpret_cast<char*>(ptr + 64*tile_width*(i/tile_width) + 8*(i%tile_width));
  184. for(int y = 0; y < 8; ++y)
  185. {
  186. out.write(tile_start + y*pitch, 8);
  187. }
  188. }
  189. }
  190. }
  191. void set_color (int i, Color c) {
  192. m_palette[i] = c;
  193. }
  194. int get_transcolor () {
  195. return m_transcol;
  196. }
  197. int num_colors () {
  198. return m_palette.size ();
  199. }
  200. int get_width () {
  201. return m_width;
  202. }
  203. int get_height () {
  204. return m_height;
  205. }
  206. };
  207. int main (int argc, char* argv[])
  208. {
  209. if (argc != 3)
  210. {
  211. printf ("Usage: %s INFILE OUTFILE\n", argv[0]);
  212. exit (EXIT_FAILURE);
  213. }
  214. else
  215. {
  216. Image image (argv[1]);
  217. std::cout << image.get_width() << "x" << image.get_height() << std::endl;
  218. std::cout << "writing " << std::string(argv[2]) + "_pal.raw" << std::endl;
  219. std::cout << "writing " << std::string(argv[2]) + "_img.raw" << std::endl;
  220. image.write_palette16bit(std::string(argv[2]) + "_pal.raw");
  221. image.write_image(std::string(argv[2]) + "_img.raw");
  222. }
  223. }
  224. // EOF //