image.cxx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. //// etcpack v2.74
  2. ////
  3. //// NO WARRANTY
  4. ////
  5. //// BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE THE PROGRAM IS PROVIDED
  6. //// "AS IS". ERICSSON MAKES NO REPRESENTATIONS OF ANY KIND, EXTENDS NO
  7. //// WARRANTIES OR CONDITIONS OF ANY KIND; EITHER EXPRESS, IMPLIED OR
  8. //// STATUTORY; INCLUDING, BUT NOT LIMITED TO, EXPRESS, IMPLIED OR
  9. //// STATUTORY WARRANTIES OR CONDITIONS OF TITLE, MERCHANTABILITY,
  10. //// SATISFACTORY QUALITY, SUITABILITY AND FITNESS FOR A PARTICULAR
  11. //// PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
  12. //// PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
  13. //// THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ERICSSON
  14. //// MAKES NO WARRANTY THAT THE MANUFACTURE, SALE, OFFERING FOR SALE,
  15. //// DISTRIBUTION, LEASE, USE OR IMPORTATION UNDER THE LICENSE WILL BE FREE
  16. //// FROM INFRINGEMENT OF PATENTS, COPYRIGHTS OR OTHER INTELLECTUAL
  17. //// PROPERTY RIGHTS OF OTHERS, AND THE VALIDITY OF THE LICENSE IS SUBJECT
  18. //// TO YOUR SOLE RESPONSIBILITY TO MAKE SUCH DETERMINATION AND ACQUIRE
  19. //// SUCH LICENSES AS MAY BE NECESSARY WITH RESPECT TO PATENTS, COPYRIGHT
  20. //// AND OTHER INTELLECTUAL PROPERTY OF THIRD PARTIES.
  21. ////
  22. //// FOR THE AVOIDANCE OF DOUBT THE PROGRAM (I) IS NOT LICENSED FOR; (II)
  23. //// IS NOT DESIGNED FOR OR INTENDED FOR; AND (III) MAY NOT BE USED FOR;
  24. //// ANY MISSION CRITICAL APPLICATIONS SUCH AS, BUT NOT LIMITED TO
  25. //// OPERATION OF NUCLEAR OR HEALTHCARE COMPUTER SYSTEMS AND/OR NETWORKS,
  26. //// AIRCRAFT OR TRAIN CONTROL AND/OR COMMUNICATION SYSTEMS OR ANY OTHER
  27. //// COMPUTER SYSTEMS AND/OR NETWORKS OR CONTROL AND/OR COMMUNICATION
  28. //// SYSTEMS ALL IN WHICH CASE THE FAILURE OF THE PROGRAM COULD LEAD TO
  29. //// DEATH, PERSONAL INJURY, OR SEVERE PHYSICAL, MATERIAL OR ENVIRONMENTAL
  30. //// DAMAGE. YOUR RIGHTS UNDER THIS LICENSE WILL TERMINATE AUTOMATICALLY
  31. //// AND IMMEDIATELY WITHOUT NOTICE IF YOU FAIL TO COMPLY WITH THIS
  32. //// PARAGRAPH.
  33. ////
  34. //// IN NO EVENT WILL ERICSSON, BE LIABLE FOR ANY DAMAGES WHATSOEVER,
  35. //// INCLUDING BUT NOT LIMITED TO PERSONAL INJURY, ANY GENERAL, SPECIAL,
  36. //// INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN
  37. //// CONNECTION WITH THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
  38. //// NOT LIMITED TO LOSS OF PROFITS, BUSINESS INTERUPTIONS, OR ANY OTHER
  39. //// COMMERCIAL DAMAGES OR LOSSES, LOSS OF DATA OR DATA BEING RENDERED
  40. //// INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
  41. //// THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) REGARDLESS OF THE
  42. //// THEORY OF LIABILITY (CONTRACT, TORT OR OTHERWISE), EVEN IF SUCH HOLDER
  43. //// OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  44. ////
  45. //// (C) Ericsson AB 2005-2013. All Rights Reserved.
  46. ////
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #include "image.h"
  51. // Remove warnings for unsafe functions such as strcpy
  52. #pragma warning(disable : 4996)
  53. // Remove warnings for conversions between different time variables
  54. #pragma warning(disable : 4244)
  55. // Removes comments in a .ppm file
  56. // (i.e., lines starting with #)
  57. // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
  58. void removeComments(FILE *f1)
  59. {
  60. int c;
  61. while((c = getc(f1)) == '#')
  62. {
  63. char line[1024];
  64. fgets(line, 1024, f1);
  65. }
  66. ungetc(c, f1);
  67. }
  68. // Removes white spaces in a .ppm file
  69. // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
  70. void removeSpaces(FILE *f1)
  71. {
  72. int c;
  73. c = getc(f1);
  74. while(c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r')
  75. {
  76. c = getc(f1);
  77. }
  78. ungetc(c, f1);
  79. }
  80. // fReadPPM
  81. //
  82. // reads a ppm file with P6 header (meaning binary, as opposed to P5, which is ascII)
  83. // and returns the image in pixels.
  84. //
  85. // The header must look like this:
  86. //
  87. // P6
  88. // # Comments (not necessary)
  89. // width height
  90. // 255
  91. //
  92. // after that follows RGBRGBRGB...
  93. //
  94. // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
  95. bool fReadPPM(char *filename, int &width, int &height, unsigned char *&pixels, int targetbitrate)
  96. {
  97. FILE *f1;
  98. int maximum;
  99. f1 = fopen(filename, "rb");
  100. if(f1)
  101. {
  102. char line[255];
  103. removeSpaces(f1);
  104. removeComments(f1);
  105. removeSpaces(f1);
  106. fscanf(f1, "%s", line);
  107. if(strcmp(line, "P6")!=0)
  108. {
  109. printf("Error: %s is not binary\n");
  110. printf("(Binary .ppm files start with P6).\n");
  111. fclose(f1);
  112. return false;
  113. }
  114. removeSpaces(f1);
  115. removeComments(f1);
  116. removeSpaces(f1);
  117. fscanf(f1, "%d %d", &width, &height);
  118. if( width<=0 || height <=0)
  119. {
  120. printf("Error: width or height negative. File: %s\n",filename);
  121. fclose(f1);
  122. return false;
  123. }
  124. removeSpaces(f1);
  125. removeComments(f1);
  126. removeSpaces(f1);
  127. fscanf(f1, "%d", &maximum);
  128. if( maximum!= 255&&maximum!=(1<<16)-1)
  129. {
  130. printf("Error: Color resolution must be 255. File: %s\n",filename);
  131. fclose(f1);
  132. return false;
  133. }
  134. //printf("maximum is %d\n",maximum);
  135. int bitrate=8;
  136. if(maximum!=255)
  137. bitrate=16;
  138. // We need to remove the newline.
  139. char c = 0;
  140. while(c != '\n')
  141. fscanf(f1, "%c", &c);
  142. unsigned char* readbuffer = (unsigned char*) malloc(3*width*height*bitrate/8);
  143. if(!readbuffer)
  144. {
  145. printf("Error: Could not allocate memory for image. File: %s\n", filename);
  146. fclose(f1);
  147. return false;
  148. }
  149. if(fread(readbuffer, 3*width*height*bitrate/8, 1, f1) != 1)
  150. {
  151. printf("Error: Could not read all pixels. File: %s\n", filename);
  152. free(pixels);
  153. fclose(f1);
  154. return false;
  155. }
  156. // If we have reached this point, we have successfully loaded the image.
  157. //now, convert it to the target bitrate
  158. if(targetbitrate==bitrate)
  159. pixels=readbuffer;
  160. else
  161. {
  162. pixels = (unsigned char*) malloc(3*width*height*targetbitrate/8);
  163. if(targetbitrate<bitrate)
  164. {
  165. //cut least significant bits to go from 16 -> 8 bits..
  166. printf("converting 16 bit input to 8 bits\n");
  167. for(int x=0; x<width; x++)
  168. {
  169. for(int y=0; y<height; y++)
  170. {
  171. for(int c=0; c<3; c++)
  172. {
  173. pixels[3*(x+y*width)+c]=readbuffer[6*(x+y*width)+2*c];
  174. }
  175. }
  176. }
  177. }
  178. else
  179. {
  180. //replicate 8 bits to go from 8 -> 16 bits...
  181. printf("converting 8 bit input to 16 bits\n");
  182. for(int x=0; x<width; x++)
  183. {
  184. for(int y=0; y<height; y++)
  185. {
  186. for(int c=0; c<3; c++)
  187. {
  188. pixels[6*(x+y*width)+2*c]=readbuffer[3*(x+y*width)+c];
  189. pixels[6*(x+y*width)+2*c+1]=readbuffer[3*(x+y*width)+c];
  190. }
  191. }
  192. }
  193. }
  194. free(readbuffer);
  195. }
  196. fclose(f1);
  197. return true;
  198. }
  199. else
  200. {
  201. printf("Error: Coult not open file %s\n", filename);
  202. return false;
  203. }
  204. }
  205. // Write PPM
  206. // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
  207. bool fWritePPM(char *filename, int width, int height, unsigned char *pixels, int bitrate, bool reverse_y)
  208. {
  209. FILE *fsave;
  210. fsave = fopen(filename, "wb");
  211. int max = (1<<bitrate)-1;
  212. int fac = bitrate/8;
  213. if(fsave)
  214. {
  215. int q;
  216. fprintf(fsave, "P6\n%d %d\n%d\n", width, height,max);
  217. for(q = 0; q< height; q++)
  218. {
  219. unsigned char *adr;
  220. if(reverse_y)
  221. adr = pixels+3*width*(height-1-q)*fac;
  222. else
  223. adr = pixels+3*width*q*fac;
  224. fwrite(adr, 3*width*fac, 1, fsave);
  225. }
  226. fclose(fsave);
  227. return true;
  228. }
  229. else
  230. {
  231. printf("Error: Could not open the file %s.\n",filename);
  232. return(false);
  233. }
  234. }
  235. // WritePGM
  236. // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
  237. bool fWritePGM(char *filename, int width, int height, unsigned char *pixels,bool reverse_y, int bitdepth)
  238. {
  239. FILE *f;
  240. f=fopen(filename,"wb");
  241. if(f)
  242. {
  243. int q;
  244. int max = (1<<bitdepth)-1;
  245. fprintf(f,"P5\n%d %d\n%d\n",width,height,max);
  246. if(bitdepth==16)
  247. width*=2; //ugly way of doubling the number of bytes to write, since we write one line at a time..
  248. for(q=0;q<height;q++)
  249. {
  250. unsigned char *adr;
  251. if(reverse_y) adr=pixels+width*(height-1-q);
  252. else adr=pixels+width*q;
  253. fwrite(adr,width,1,f);
  254. }
  255. fclose(f);
  256. return true;
  257. }
  258. else
  259. {
  260. printf("Error: could not open file <%s>.\n",filename);
  261. return false;
  262. }
  263. }
  264. /* reads a ppm file with the P6 header (means raw RGB), puts data into pixel pointer and returns bit depth (8 or 16 bpp) */
  265. /* the header looks like this:
  266. *---------
  267. * P5
  268. * # comments if you want to
  269. * width height
  270. * 255
  271. *---------
  272. * then follows RGBRGBRGBRGBRGB...
  273. */
  274. // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
  275. int fReadPGM(char *filename, int &width, int &height, unsigned char *&pixels, int wantedBitDepth)
  276. {
  277. FILE *f;
  278. int colres;
  279. int bitdepth=8;
  280. f=fopen(filename,"rb");
  281. if(f)
  282. {
  283. char str[100];
  284. removeSpaces(f);
  285. removeComments(f);
  286. removeSpaces(f);
  287. fscanf(f,"%s",str);
  288. if(strcmp(str,"P5")!=0)
  289. {
  290. printf("Error: the alpha image file must be of raw color PGM format,\n");
  291. printf("i.e., it must have P5 in the header. File: %s\n",filename);
  292. fclose(f);
  293. return 0;
  294. }
  295. removeSpaces(f);
  296. removeComments(f);
  297. removeSpaces(f);
  298. fscanf(f,"%d %d",&width,&height);
  299. if(width<=0 || height<=0)
  300. {
  301. printf("Error: width and height of the image must be greater than zero. File: %s\n",filename);
  302. fclose(f);
  303. return 0;
  304. }
  305. removeSpaces(f);
  306. removeComments(f);
  307. removeSpaces(f);
  308. fscanf(f,"%d",&colres);
  309. if(colres!=255&&colres!=65535)
  310. {
  311. printf("Error: color resolution must be 255 or 65535.File: %s\n",filename);
  312. fclose(f);
  313. return 0;
  314. }
  315. if(colres==65535)
  316. bitdepth=16;
  317. /* gotta eat the newline too */
  318. char ch=0;
  319. while(ch!='\n') fscanf(f,"%c",&ch);
  320. pixels=(unsigned char*)malloc(width*height*bitdepth/8);
  321. if(!pixels)
  322. {
  323. printf("Error: could not allocate memory for the pixels of the texture. File: %s\n",filename);
  324. fclose(f);
  325. return 0;
  326. }
  327. if(fread(pixels,width*height*bitdepth/8,1,f)!=1)
  328. {
  329. printf("Error: could not read %d bytes of pixel info. File: %s\n",width*height*bitdepth/8,filename);
  330. free(pixels);
  331. fclose(f);
  332. return 0;
  333. }
  334. fclose(f);
  335. printf("read %d-bit alpha channel",bitdepth);
  336. if(bitdepth!=wantedBitDepth)
  337. {
  338. printf(", converting to %d-bit!",wantedBitDepth);
  339. unsigned char* newpixels = (unsigned char*)malloc(width*height*wantedBitDepth/8);
  340. for(int x=0; x<width; x++)
  341. {
  342. for(int y=0; y<height; y++)
  343. {
  344. if(bitdepth<wantedBitDepth)
  345. {
  346. //do bit-replication to get 2-bytes per pixel
  347. newpixels[2*(x+y*width)]=pixels[x+y*width];
  348. newpixels[2*(x+y*width)+1]=pixels[x+y*width];
  349. }
  350. else
  351. {
  352. //simply truncate the extra data..
  353. newpixels[(x+y*width)]=pixels[2*(x+y*width)];
  354. }
  355. }
  356. }
  357. free(pixels);
  358. pixels=newpixels;
  359. }
  360. printf("\n");
  361. return bitdepth;
  362. }
  363. else
  364. {
  365. printf("Error: could not open %s.\n",filename);
  366. return 0;
  367. }
  368. }
  369. /* writes a .tga file from two arrays --- one RGB array and one alpha-array */
  370. /* */
  371. // NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2012. All Rights Reserved.
  372. bool fWriteTGAfromRGBandA(char *filename, int width, int height, unsigned char *pixelsRGB, unsigned char *pixelsA, bool reverse_y)
  373. {
  374. FILE *f1;
  375. if( (f1 = fopen(filename,"wb")) == NULL)
  376. {
  377. return false;
  378. }
  379. // First write header
  380. unsigned char myByteVal;
  381. short myShortVal;
  382. myByteVal = 0;
  383. fwrite(&myByteVal, 1, 1, f1); // ID field (0)
  384. fwrite(&myByteVal, 1, 1, f1); // Palette? (no=0)
  385. myByteVal = 2;
  386. fwrite(&myByteVal, 1, 1, f1); // Image type (rgb=2)
  387. myShortVal = 0;
  388. fwrite(&myShortVal, 2, 1, f1); // Palette stuff... 0
  389. fwrite(&myShortVal, 2, 1, f1); // Palette stuff... 0
  390. myByteVal = 0;
  391. fwrite(&myByteVal, 1, 1, f1); // Palette stuff... 0
  392. myShortVal = 0;
  393. fwrite(&myShortVal, 2, 1, f1); // x-origin
  394. myShortVal = 0;
  395. fwrite(&myShortVal, 2, 1, f1); // y-origin
  396. myShortVal = width;
  397. fwrite(&myShortVal, 2, 1, f1); // width
  398. myShortVal = height;
  399. fwrite(&myShortVal, 2, 1, f1); // height
  400. myByteVal = 32;
  401. fwrite(&myByteVal, 1, 1, f1); // Bits per pixel = 32
  402. myByteVal = 8;
  403. fwrite(&myByteVal, 1, 1, f1); // flip bits = 8
  404. // Write pixels in BGRA format
  405. if(reverse_y)
  406. {
  407. int xx, yy;
  408. for(yy = height-1; yy>=0; yy--)
  409. {
  410. for(xx = 0; xx<width; xx++)
  411. {
  412. fwrite(&pixelsRGB[3*(yy*width+xx)+2], sizeof(unsigned char), 1, f1); // B
  413. fwrite(&pixelsRGB[3*(yy*width+xx)+1], sizeof(unsigned char), 1, f1); // G
  414. fwrite(&pixelsRGB[3*(yy*width+xx)+0], sizeof(unsigned char), 1, f1); // R
  415. fwrite(&pixelsA[(yy*width+xx)], sizeof(unsigned char), 1, f1); // A
  416. }
  417. }
  418. }
  419. else
  420. {
  421. for(int q = 0; q< width * height; q++)
  422. {
  423. fwrite(&pixelsRGB[3*q+2], sizeof(unsigned char), 1, f1); // B
  424. fwrite(&pixelsRGB[3*q+1], sizeof(unsigned char), 1, f1); // G
  425. fwrite(&pixelsRGB[3*q+0], sizeof(unsigned char), 1, f1); // R
  426. fwrite(&pixelsA[1*q], sizeof(unsigned char), 1, f1); // A
  427. }
  428. }
  429. fclose(f1);
  430. return true;
  431. }