TexFile.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * Copyright (C) 2022 The V-Gears Team
  3. *
  4. * This file is part of V-Gears
  5. *
  6. * V-Gears is free software: you can redistribute it and/or modify it under
  7. * terms of the GNU General Public License as published by the Free Software
  8. * Foundation, version 3.0 (GPLv3) of the License.
  9. *
  10. * V-Gears is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include <string>
  16. #include <iostream>
  17. #include <OgreImage.h>
  18. #include <OgreColourValue.h>
  19. #include "TexFile.h"
  20. TexFile::TexFile(std::string path){
  21. File file(path);
  22. Read(file);
  23. }
  24. TexFile::TexFile(File file){
  25. Read(file);
  26. }
  27. void TexFile::Read(File file){
  28. file.SetOffset(0);
  29. version_ = file.readU32LE();
  30. if (version_ != 0x00000001){
  31. std::cout << "[WARNING] Tried to read an invalid TEX file " << file.GetFileName()
  32. << " to png. Version ID: " << version_ << std::endl;
  33. return;
  34. }
  35. unknown_0_ = file.readU32LE();
  36. colour_key_ = file.readU32LE();
  37. unknown_1_ = file.readU32LE();
  38. unknown_2_ = file.readU32LE();
  39. min_bpc_ = file.readU32LE();
  40. max_bpc_ = file.readU32LE();
  41. min_alpha_bits_ = file.readU32LE();
  42. max_alpha_bits_ = file.readU32LE();
  43. min_bpp_ = file.readU32LE();
  44. max_bpp_ = file.readU32LE();
  45. unknown_3_ = file.readU32LE();
  46. palette_count_ = file.readU32LE();
  47. palette_colour_count_ = file.readU32LE();
  48. bit_depth_ = file.readU32LE();
  49. width_ = file.readU32LE();
  50. height_ = file.readU32LE();
  51. pitch_ = file.readU32LE();
  52. unknown_4_ = file.readU32LE();
  53. has_palette_ = file.readU32LE();
  54. bits_per_index_ = file.readU32LE();
  55. indexed_to_8_bit_ = file.readU32LE();
  56. palette_size_ = file.readU32LE();
  57. colours_per_palette_ = file.readU32LE();
  58. run_0_ = file.readU32LE();
  59. bits_per_pixel_ = file.readU32LE();
  60. bytes_per_pixel_ = file.readU32LE();
  61. bits_red_ = file.readU32LE();
  62. bits_green_ = file.readU32LE();
  63. bits_blue_ = file.readU32LE();
  64. bits_alpha_ = file.readU32LE();
  65. bitmask_red_ = file.readU32LE();
  66. bitmask_green_ = file.readU32LE();
  67. bitmask_blue_ = file.readU32LE();
  68. bitmask_alpha_ = file.readU32LE();
  69. shift_red_ = file.readU32LE();
  70. shift_green_ = file.readU32LE();
  71. shift_blue_ = file.readU32LE();
  72. shift_alpha_ = file.readU32LE();
  73. bits_red_2_ = file.readU32LE();
  74. bits_green_2_ = file.readU32LE();
  75. bits_blue_2_ = file.readU32LE();
  76. bits_alpha_2_ = file.readU32LE();
  77. max_red_ = file.readU32LE();
  78. max_green_ = file.readU32LE();
  79. max_blue_ = file.readU32LE();
  80. max_alpha_ = file.readU32LE();
  81. colour_k_array_ = file.readU32LE();
  82. run_1_ = file.readU32LE();
  83. ref_alpha_ = file.readU32LE();
  84. run_2_ = file.readU32LE();
  85. unknown_5_ = file.readU32LE();
  86. palette_index_ = file.readU32LE();
  87. run_3_ = file.readU32LE();
  88. run_4_ = file.readU32LE();
  89. unknown_6_ = file.readU32LE();
  90. unknown_7_ = file.readU32LE();
  91. unknown_8_ = file.readU32LE();
  92. unknown_9_ = file.readU32LE();
  93. if (has_palette_ == 0){
  94. // Non palleted images.
  95. // Skip unused pallete data.
  96. for (int c = 0; c < palette_size_; c ++) file.readU32LE();
  97. // Read 32 byte colours in format BGRA.
  98. for (int p = 0; p < width_ * height_; p ++){
  99. float b = file.readU8() / 255.0f;
  100. float g = file.readU8() / 255.0f;
  101. float r = file.readU8() / 255.0f;
  102. float a = file.readU8() / 255.0f;
  103. Ogre::ColourValue colour(r, g, b, a);
  104. pixel_colour_.push_back(colour);
  105. }
  106. }
  107. else {
  108. // Palleted_images.
  109. palette_count_ = palette_size_ / palette_colour_count_;
  110. // Read palette data.
  111. for (int c = 0; c < palette_count_; c ++){
  112. std::vector<Ogre::ColourValue> palette_colours;
  113. for (int p = 0; p < palette_colour_count_; p ++){
  114. float b = file.readU8() / 255.0f;
  115. float g = file.readU8() / 255.0f;
  116. float r = file.readU8() / 255.0f;
  117. float a = file.readU8() / 255.0f;
  118. Ogre::ColourValue colour(r, g, b, a);
  119. palette_colours.push_back(colour);
  120. }
  121. palettes_.push_back(palette_colours);
  122. }
  123. // Read bytes as references to a palette colour.
  124. for (int p = 0; p < width_ * height_; p ++) pixel_ref_.push_back(file.readU8());
  125. }
  126. }
  127. TexFile::~TexFile(){}
  128. void TexFile::SavePng(
  129. std::string file_name, unsigned int x, unsigned int y, unsigned int w, unsigned int h,
  130. unsigned int palette
  131. ){
  132. if (version_ != 0x00000001){
  133. std::cout << "[WARNING] Tried to convert an invalid TEX file to png. Version ID: " << version_ << std::endl;
  134. return;
  135. }
  136. // TODO: Warn if wrong palette index.
  137. Ogre::Image* image = new Ogre::Image(Ogre::PF_R8G8B8A8_UINT, w, h);
  138. int target_x = 0;
  139. int target_y = 0;
  140. for (int c_y = y; c_y < height_ && c_y < y + h; c_y ++){
  141. for (int c_x = x; c_x < width_ && c_x < x + w; c_x ++){
  142. int i = (width_ * c_y) + c_x;
  143. float r;
  144. float g;
  145. float b;
  146. float a;
  147. if (has_palette_ == 0){
  148. r = pixel_colour_.at(i).r;
  149. g = pixel_colour_.at(i).g;
  150. b = pixel_colour_.at(i).b;
  151. a = pixel_colour_.at(i).a;
  152. }
  153. else{
  154. if (palettes_.at(palette).size() <= pixel_ref_.at(i)){
  155. // If invalid index, use alpha
  156. r = 0;
  157. g = 0;
  158. b = 0;
  159. a = 0;
  160. }
  161. else{
  162. r = palettes_.at(palette).at(pixel_ref_.at(i)).r;
  163. g = palettes_.at(palette).at(pixel_ref_.at(i)).g;
  164. b = palettes_.at(palette).at(pixel_ref_.at(i)).b;
  165. a = palettes_.at(palette).at(pixel_ref_.at(i)).a;
  166. }
  167. }
  168. image->setColourAt(Ogre::ColourValue(r, g, b, a), target_x, target_y, 0);
  169. target_x ++;
  170. if (target_x >= w){
  171. target_y ++;
  172. target_x = 0;
  173. }
  174. }
  175. }
  176. image->save(file_name);
  177. }
  178. void TexFile::SavePng(std::string file_name, unsigned int palette){
  179. //if (invalid_) return;
  180. SavePng(file_name, 0, 0, width_, height_, palette);
  181. }
  182. void TexFile::SavePng(
  183. std::string file_name, unsigned int x1, unsigned int x2, unsigned int y1, unsigned int y2,
  184. unsigned int w1, unsigned int w2, unsigned int h, unsigned int palette
  185. ){
  186. if (version_ != 0x00000001){
  187. std::cout << "[WARNING] Tried to convert an invalid TEX file to png. Version ID: " << version_ << std::endl;
  188. return;
  189. }
  190. // TODO: Warn if wrong palette index.
  191. Ogre::Image* image = new Ogre::Image(Ogre::PF_R8G8B8A8_UINT, w1 + w2, h);
  192. int target_x = 0;
  193. int target_y = 0;
  194. // First image
  195. for (int c_y = y1; c_y < height_ && c_y < y1 + h; c_y ++){
  196. for (int c_x = x1; c_x < width_ && c_x < x1 + w1; c_x ++){
  197. int i = (width_ * c_y) + c_x;
  198. float r;
  199. float g;
  200. float b;
  201. float a;
  202. if (has_palette_ == 0){
  203. r = pixel_colour_.at(i).r;
  204. g = pixel_colour_.at(i).g;
  205. b = pixel_colour_.at(i).b;
  206. a = pixel_colour_.at(i).a;
  207. }
  208. else{
  209. r = palettes_.at(palette).at(pixel_ref_.at(i)).r;
  210. g = palettes_.at(palette).at(pixel_ref_.at(i)).g;
  211. b = palettes_.at(palette).at(pixel_ref_.at(i)).b;
  212. a = palettes_.at(palette).at(pixel_ref_.at(i)).a;
  213. }
  214. image->setColourAt(Ogre::ColourValue(r, g, b, a), target_x, target_y, 0);
  215. target_x ++;
  216. if (target_x >= w1){
  217. target_y ++;
  218. target_x = 0;
  219. }
  220. }
  221. }
  222. target_x = w1;
  223. target_y = 0;
  224. for (int c_y = y2; c_y < height_ && c_y < y2 + h; c_y ++){
  225. for (int c_x = x2; c_x < width_ && c_x < x2 + w2; c_x ++){
  226. int i = (width_ * c_y) + c_x;
  227. float r;
  228. float g;
  229. float b;
  230. float a;
  231. if (has_palette_ == 0){
  232. r = pixel_colour_.at(i).r;
  233. g = pixel_colour_.at(i).g;
  234. b = pixel_colour_.at(i).b;
  235. a = pixel_colour_.at(i).a;
  236. }
  237. else{
  238. r = palettes_.at(palette).at(pixel_ref_.at(i)).r;
  239. g = palettes_.at(palette).at(pixel_ref_.at(i)).g;
  240. b = palettes_.at(palette).at(pixel_ref_.at(i)).b;
  241. a = palettes_.at(palette).at(pixel_ref_.at(i)).a;
  242. }
  243. image->setColourAt(Ogre::ColourValue(r, g, b, a), target_x, target_y, 0);
  244. target_x ++;
  245. if (target_x >= w1 + w2){
  246. target_y ++;
  247. target_x = w1;
  248. }
  249. }
  250. }
  251. image->save(file_name);
  252. }