TGA.C 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
  12. */
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <conio.h>
  16. #include <math.h>
  17. #include <string.h>
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <fcntl.h>
  21. #include <io.h>
  22. #include <dos.h>
  23. #include <malloc.h>
  24. #include <ctype.h>
  25. typedef unsigned char BYTE;
  26. typedef unsigned short WORD;
  27. typedef unsigned int DWORD;
  28. typedef struct
  29. {
  30. BYTE Field1;
  31. BYTE Field2;
  32. BYTE DataType ;
  33. BYTE Field41H ;
  34. BYTE Field41L ;
  35. BYTE Field42H ;
  36. BYTE Field42L ;
  37. BYTE Field43 ;
  38. WORD XOrigin ;
  39. WORD YOrigin ;
  40. WORD Width ;
  41. WORD Height ;
  42. BYTE BitsPerPixel;
  43. BYTE Field56 ;
  44. } TGA_FILE_HEADER;
  45. typedef struct {
  46. WORD Width;
  47. WORD Height;
  48. WORD Data[1];
  49. } BITMAP15;
  50. BITMAP15 * ReadInTGA(char * filename )
  51. {
  52. BITMAP15 * NewBitmap;
  53. short row_b,col_b,row_e,col_e;
  54. char *buffer;
  55. TGA_FILE_HEADER imghead;
  56. int infile;
  57. int numread;
  58. short len ;
  59. short row,dcol,col_now,drow;
  60. char quitflag ;
  61. WORD bufindex, value ;
  62. BYTE count;
  63. short tempcnt;
  64. short BufSize, RowsPerRead, BytesPerRow;
  65. short i;
  66. WORD tmpbuf[320];
  67. // Try to open file
  68. infile = open(filename,(O_BINARY|O_RDONLY) ) ;
  69. if (infile==-1) {
  70. printf( "TGAto15BPP: '%s' not found.\n", filename );
  71. return NULL;
  72. }
  73. // Read the image header
  74. numread = read(infile,(char*)&imghead, sizeof(TGA_FILE_HEADER) ) ;
  75. if ( numread != sizeof(TGA_FILE_HEADER) ) {
  76. printf( "TGAto15BPP: Error reading '%s' header.\n", filename );
  77. close(infile);
  78. return NULL;
  79. }
  80. // get the data in header
  81. dcol = imghead.Width;
  82. drow = imghead.Height;
  83. // Assign column,row begin , displacement to input Origion
  84. col_b = imghead.XOrigin ;
  85. row_b = imghead.YOrigin ;
  86. col_b = 0 ;
  87. row_b = 0 ;
  88. // check if orgion overflow
  89. if ( (row_b>320) || (col_b>480) ) {
  90. printf( "TGAto15BPP: Origin overflow reading '%s'.", filename );
  91. close(infile);
  92. return NULL;
  93. }
  94. // Bound the image in maxrow, maxcal
  95. col_e = dcol + col_b - 1 ;
  96. row_e = drow + row_b - 1 ;
  97. if (col_e>320)
  98. col_e = 320 ;
  99. if (row_e>480)
  100. row_e = 480 ;
  101. // check if 16 bits per pixel, now support VIGA16 file only
  102. if (imghead.BitsPerPixel != 16 ) {
  103. printf( "TGAto15BPP: '%s' is not a valid 16bpp TGA file.\n", filename );
  104. close(infile);
  105. return NULL;
  106. }
  107. NewBitmap = (BITMAP15 *)malloc( sizeof(BITMAP15)+((col_e-col_b+1)*(row_e-row_b+1)*3) );
  108. if (NewBitmap == NULL ) {
  109. printf( "TGAto15bpp: Error allocating bitmap memory for '%s'.\n", filename );
  110. return NULL;
  111. }
  112. NewBitmap->Height = row_e - row_b + 1;
  113. NewBitmap->Width = col_e - col_b + 1;
  114. // allocate a buffer as large as possible
  115. BufSize = 1024;
  116. while ( ((buffer=(char *)malloc((size_t)BufSize))==NULL) && (BufSize>=1024) ) {
  117. BufSize -= 1024 ;
  118. }
  119. // check if buffer enough, if not return MEMORY FULL
  120. if (BufSize<1024) {
  121. printf( "TGAto15BPP: Error allocating buffer for '%s'.\n", filename );
  122. close(infile);
  123. free( buffer );
  124. free( NewBitmap);
  125. return NULL;
  126. }
  127. BytesPerRow = dcol * 2 ;
  128. RowsPerRead = BufSize / BytesPerRow ;
  129. // Load image file routines...
  130. if (imghead.DataType == 2) {
  131. // This image file is not compressed
  132. row = row_b ;
  133. while (row <= row_e) {
  134. if ( (row+RowsPerRead) > row_e)
  135. RowsPerRead = row_e - row + 1;
  136. read(infile,buffer,BytesPerRow*RowsPerRead);
  137. bufindex = 0 ;
  138. for (value=0; value<RowsPerRead; value++) {
  139. for (i=col_b; i<=col_e; i++ )
  140. memcpy( &(NewBitmap->Data[ NewBitmap->Width*(NewBitmap->Height-row-1)+i ]), &(buffer[bufindex+2*(i-col_b)]), 2 );
  141. //NewBitmap->Data[ NewBitmap->Width*(NewBitmap->Height-row-1)+i ] = buffer[bufindex+i-col_b];
  142. row++;
  143. bufindex += BytesPerRow ;
  144. } // for
  145. } // while
  146. // free the allocated buffer, close opened file
  147. free(buffer) ;
  148. close(infile);
  149. return NewBitmap;
  150. }
  151. if (imghead.DataType != 10) {
  152. // Not a valid TGA file. Free the allocated buffer, close opened file
  153. printf( "TGAto15BPP: '%s' compression type is invalid.\n", filename );
  154. free(buffer) ;
  155. close(infile);
  156. free( NewBitmap);
  157. return NULL;
  158. }
  159. // init col_now, quitflag to 0,init row to the start row
  160. col_now = 0 ;
  161. row = row_b ;
  162. quitflag = 0 ;
  163. // read a block of data to buffer
  164. numread = read(infile,buffer,BufSize);
  165. while ( (numread>0) && (quitflag==0) ) {
  166. // init bufindex, while loop to decode data
  167. bufindex = 0 ;
  168. while ( (bufindex<numread) && (quitflag==0) ) {
  169. // get the first data in buffer, inc bufindex
  170. count = *(buffer+bufindex) ;
  171. bufindex++;
  172. // check if count a data or a counter
  173. if ( count >= 128 ) {
  174. // if end of buffer, read next block, and continue to decode them
  175. if (bufindex>=numread) {
  176. numread = read(infile,buffer,BufSize) ;
  177. if (numread>0) {
  178. bufindex = 0 ;
  179. memcpy(&value,(buffer+bufindex),2);
  180. bufindex += 2 ;
  181. }
  182. else
  183. quitflag = 1 ;
  184. }
  185. else
  186. if ( (bufindex+1) >= numread ) {
  187. value = *(buffer+bufindex) ;
  188. numread = read(infile,buffer,BufSize) ;
  189. if (numread>0) {
  190. bufindex = 0 ;
  191. value += *(buffer+bufindex) << 8 ;
  192. bufindex++;
  193. }
  194. else
  195. quitflag = 1 ;
  196. }
  197. else {
  198. memcpy(&value,(buffer+bufindex),2);
  199. bufindex += 2 ;
  200. }
  201. // dec count by 127, store data to
  202. // tmpbuf, adjust col_now
  203. count -= 127 ; // 127
  204. while (count>0) {
  205. tmpbuf[col_now] = value ;
  206. col_now++;
  207. count--;
  208. } // while
  209. } // if count
  210. else {
  211. // not counter, inc count, cal tempcnt
  212. count++;
  213. tempcnt = 2*count ;
  214. // check if end of buffer, if yes read next
  215. // block to buffer, continue to decode
  216. if ( (bufindex+tempcnt) >= numread ) {
  217. while ( (bufindex+2)<=numread ) {
  218. memcpy(&tmpbuf[col_now],(buffer+bufindex), 2);
  219. col_now++;
  220. tempcnt -= 2 ;
  221. bufindex += 2 ;
  222. }
  223. if ( bufindex<numread ) {
  224. value = *(buffer+bufindex) ;
  225. numread = read(infile,buffer,BufSize) ;
  226. if (numread>0) {
  227. bufindex = 0 ;
  228. value += *(buffer+bufindex) << 8 ;
  229. tmpbuf[col_now] = value ;
  230. col_now++;
  231. bufindex++;
  232. tempcnt -= 2 ;
  233. }
  234. else
  235. quitflag = 1 ;
  236. }
  237. else
  238. {
  239. numread = read(infile,buffer,BufSize) ;
  240. if (numread>0)
  241. bufindex = 0 ;
  242. else
  243. quitflag = 1 ;
  244. }
  245. if (tempcnt>0)
  246. {
  247. memcpy(&tmpbuf[col_now],(buffer+bufindex), tempcnt) ;
  248. col_now += ( tempcnt / 2) ;
  249. bufindex += tempcnt ;
  250. } // if tempcnt
  251. } // if buffindex
  252. else
  253. {
  254. memcpy(&tmpbuf[col_now],(buffer+bufindex),tempcnt);
  255. bufindex += tempcnt ;
  256. col_now += count;
  257. } // else buffindex
  258. } // else count
  259. // check if tmpbuf enough to be a row, if yes
  260. // output the row to board, inc row
  261. if ( col_now>=dcol )
  262. {
  263. for (i=col_b; i<=col_e; i++ )
  264. NewBitmap->Data[ NewBitmap->Width*(NewBitmap->Height-row-1)+i ] = tmpbuf[i-col_b];
  265. row++;
  266. if (row>row_e)
  267. quitflag = 1 ;
  268. len = col_now - dcol ;
  269. if (len>0)
  270. memcpy(&tmpbuf[0],&tmpbuf[dcol], (2*len) ) ;
  271. col_now = len;
  272. } // if col_now >dcol
  273. } // while bufindex
  274. // read another block to be decoded
  275. numread = read(infile,buffer,BufSize) ;
  276. } // while numread
  277. // if there were some data in tmpbuf, output it
  278. if (col_now>0) {
  279. for (i=col_b; i<=(col_e+col_now); i++ )
  280. NewBitmap->Data[ NewBitmap->Width*(NewBitmap->Height-row-1)+i ] = tmpbuf[i-col_b];
  281. }
  282. // free the allocated buffer, close opened file
  283. free(buffer) ;
  284. close(infile);
  285. return NewBitmap;
  286. }