LOADPICT.CPP 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. /*
  2. ** Command & Conquer Red Alert(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program 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. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* $Header: g:/library/wwlib32/file/rcs/loadpict.cpp 1.1 1994/04/20 14:38:08 scott_bowen Exp $ */
  19. /***************************************************************************
  20. ** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
  21. ***************************************************************************
  22. * *
  23. * Project Name : Westwood Library *
  24. * *
  25. * File Name : IFFEXTRA.C *
  26. * *
  27. * Programmer : Joe L. Bostic *
  28. * *
  29. * Start Date : June 11, 1991 *
  30. * *
  31. * Last Update : April 20, 1994 [SKB] *
  32. * *
  33. *-------------------------------------------------------------------------*
  34. * Functions: *
  35. * ILBM_To_Amiga -- Convert ILBM to bitplane Amiga format. *
  36. * ILBM_To_MCGA -- Converts ILBM picture into MCGA format. *
  37. * PBM_To_Amiga -- Converts a PBM picture into Amiga format. *
  38. * Load_Picture -- Loads a picture file (CPS or LBM format). *
  39. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  40. #include "iff.h"
  41. #include "file.h"
  42. #include <wwmem.h> // For Alloc.
  43. #if(IBM)
  44. #include <mem.h>
  45. #endif
  46. // Since we are not currently using AMIGA, this has been put in to
  47. // give us back some code space. If it is needed for a utility,
  48. // this module should be recompiled with that utility and set the
  49. // define to TRUE.
  50. #define MAKE_AMIGA_ART FALSE
  51. /*
  52. ** An IFF picture file can have one of two formats:
  53. ** ILBM - InterLeaved Bit Map
  54. ** PBM - Packed Bit Map
  55. */
  56. typedef enum {
  57. FORM_ILBM,
  58. FORM_PBM
  59. } IFFForm_Type;
  60. /*
  61. ** These are the various chunks that compose an IFF picture file.
  62. */
  63. #define ID_FORM MAKE_ID('F','O','R','M')
  64. #define ID_ILBM MAKE_ID('I','L','B','M')
  65. #define ID_PBM MAKE_ID('P','B','M',' ')
  66. #define ID_CMAP MAKE_ID('C','M','A','P')
  67. #define ID_BODY MAKE_ID('B','O','D','Y')
  68. #define ID_BMHD MAKE_ID('B','M','H','D')
  69. /*
  70. ** The BMHD (Bit Map HeaDer) chunk in an IFF picture file contains the
  71. ** information necessary to extract that picture from the BODY chunk.
  72. ** It also indicates the size and depth of the source art.
  73. */
  74. typedef struct {
  75. unsigned short W, H; // Raster width and height in pixels.
  76. short X, Y; // Pixel postion for this image.
  77. char BPlanes; // Number of bitplanes.
  78. unsigned char Masking; // Masking control byte.
  79. // 0 = No masking.
  80. // 1 = Has a mask.
  81. // 2 = Has transparent color.
  82. // 3 = Lasso.
  83. unsigned char Compression; // Compression method.
  84. // 0 = No compression.
  85. // 1 = Byte run compression.
  86. char pad;
  87. unsigned short Transparent; // Transparent color number.
  88. unsigned char XAspect, // Pixel aspect ratio of source art.
  89. YAspect;
  90. short PageWidth, // Source 'page' size in pixels.
  91. PageHeight;
  92. } BitMapHeader_Type;
  93. /*=========================================================================*/
  94. /* The following PRIVATE functions are in this file: */
  95. /*=========================================================================*/
  96. PRIVATE void __cdecl ILBM_To_MCGA(BufferClass& src, BufferClass& dest, int planes);
  97. PRIVATE void __cdecl ILBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes);
  98. PRIVATE void __cdecl PBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes);
  99. /*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
  100. /***************************************************************************
  101. * ILBM_TO_MCGA -- Converts ILBM picture into MCGA format. *
  102. * *
  103. * This converts an ILBM picture (typical of DPaint LBM files) and *
  104. * converts it to MCGA mode (byte per pixel). This function would be *
  105. * used after the body of an ILBM picture is loaded. Because the *
  106. * number of bitplanes can vary greatly, it is necessary to pass the *
  107. * bitplane count to this function. The size (320 by 200) of the *
  108. * source picture is presumed. *
  109. * *
  110. * INPUT: src - Buffer number for source ILBM picture. *
  111. * *
  112. * dest - Buffer number for place to put MCGA format. *
  113. * *
  114. * planes- The number of bitplanes in the ILBM picture. *
  115. * *
  116. * OUTPUT: none *
  117. * *
  118. * WARNINGS: none *
  119. * *
  120. * HISTORY: *
  121. * 05/16/1991 JLB : Created. *
  122. * 04/20/1994 SKB : Update to 32 bit library and make private. *
  123. *=========================================================================*/
  124. PRIVATE void __cdecl ILBM_To_MCGA(BufferClass& src, BufferClass& dest, int planes)
  125. {
  126. char *source; // Source pointer.
  127. char *destination; // Destination pointer.
  128. int index,j,i; // Working index values.
  129. int bplane; // Bit plane counter.
  130. char bytes[8]; // Byte array holding max bitplanes (8).
  131. char value; // Composed byte(pixel) value.
  132. source = (char *) src.Get_Buffer();
  133. destination = (char *) dest.Get_Buffer();
  134. memset(bytes, '\0', 8); // Makes sure upper bits will be clear.
  135. // Each row is grouped and processed together.
  136. for (index = 0; index < 200 /*bmhd.H*/; index++) {
  137. // Process each line in groups of 8 bytes.
  138. for (j = 0; j < 40 /*(bmhd.W>>3)*/; j++) {
  139. // Get the bitplane bytes.
  140. for (bplane = 0; bplane < planes /*bmhd.BPlanes*/; bplane++) {
  141. bytes[bplane] = *(source + (bplane * 40 /*(bmhd.W>>3)*/));
  142. }
  143. source++;
  144. // Roll the bits out to create 8 pixels (by bytes).
  145. for (i = 0; i < 8; i++) {
  146. // 8 bits per byte.
  147. value = 0;
  148. for (bplane = planes - 1/*bmhd.BPlanes-1*/; bplane >= 0; bplane--) {
  149. value <<= 1; // Make room for next bit.
  150. if (bytes[bplane] & 0x80) value |= 1; // Set the bit.
  151. bytes[bplane] <<= 1;
  152. }
  153. *destination++ = value; // Output the pixel byte.
  154. }
  155. }
  156. // Advance to next scan line.
  157. source += 40 /* (bmhd.W >> 3)*/ * (planes /* bmhd.BPlanes */ - 1);
  158. }
  159. }
  160. /***************************************************************************
  161. * ILBM_TO_AMIGA -- Convert ILBM to bitplane Amiga format. *
  162. * *
  163. * This converts an InterLeaved BitMap picture into Amiga bitplane *
  164. * format (8K per bitplane). The data of an ILBM picture is controlled *
  165. * by the number of bitplanes it contains. The bitplane count is *
  166. * passed into this program. *
  167. * *
  168. * INPUT: src - Buffer number for source ILBM picture data. *
  169. * *
  170. * dest - Buffer number for destination Amiga picture data. *
  171. * *
  172. * planes- The number of bitplanes in the source ILBM data. *
  173. * *
  174. * OUTPUT: none *
  175. * *
  176. * WARNINGS: The amount of data placed into the destination buffer is *
  177. * controlled by the number of bitplanes specified. It is *
  178. * 8000 per bitplane. *
  179. * *
  180. * HISTORY: *
  181. * 05/20/1991 JLB : Created. *
  182. * 04/20/1994 SKB : Update to 32 bit library and make private. *
  183. * 04/20/1994 SKB : #if out for main library. Only used in utils maybe. *
  184. *=========================================================================*/
  185. #if MAKE_AMIGA_ART
  186. PRIVATE void __cdecl ILBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes)
  187. {
  188. int row; // Working row counter.
  189. int bp; // Working bitplane counter.
  190. char *srcptr, // Source buffer pointer.
  191. *dstptr; // Destination buffer pointer.
  192. srcptr = (char *) src.Get_Buffer(); // Source buffer pointer.
  193. dstptr = (char *) dest.Get_Buffer(); // Destination buffer pointer.
  194. for (row = 0; row < 200; row++) {
  195. for (bp = 0; bp < planes; bp++) {
  196. Mem_Copy(srcptr,dstptr+(8000*bp),40);
  197. srcptr += 40;
  198. }
  199. dstptr += 40;
  200. }
  201. }
  202. #endif
  203. /***************************************************************************
  204. * PBM_TO_AMIGA -- Converts a PBM picture into Amiga format. *
  205. * *
  206. * This converts a PBM (Packed Bit Map) MCGA picture into Amiga *
  207. * bitplane format. A PBM picture presumes 8 bitplanes, but this *
  208. * can be controlled by the 'plane' parameter passed in. *
  209. * *
  210. * INPUT: src - Buffer number for the source PBM data. *
  211. * *
  212. * dest - Buffer number to place the Amiga format picture. *
  213. * *
  214. * planes- The number of bitplanes to extract from the PBM source *
  215. * *
  216. * OUTPUT: none *
  217. * *
  218. * WARNINGS: The amount of data placed into the destination buffer is *
  219. * controlled by the number of bitplanes specified. It is *
  220. * 8000 per bitplane. *
  221. * *
  222. * HISTORY: *
  223. * 05/20/1991 JLB : Created. *
  224. * 04/20/1994 SKB : Update to 32 bit library and make private. *
  225. * 04/20/1994 SKB : #if out for main library. Only used in utils maybe. *
  226. *=========================================================================*/
  227. #if MAKE_AMIGA_ART
  228. PRIVATE void __cdecl PBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes)
  229. {
  230. int row, // Working row counter.
  231. col, // Working column (by byte) counter.
  232. bit; // Working bitplane counter.
  233. unsigned char *destptr, // Destination byte pointer.
  234. *srcptr; // Source byte pointer.
  235. unsigned char value; // Working input MCGA pixel number.
  236. destptr = (unsigned char *) dest.Get_Buffer();
  237. srcptr = (unsigned char *) src.Get_Buffer();
  238. memset(destptr, 0, 32000);
  239. memset(destptr+32000, 0, 32000);
  240. for (row = 0; row < 200; row++) {
  241. for (col = 0; col < 320; col++) {
  242. value = *srcptr++;
  243. for (bit = 0; bit < planes; bit++) {
  244. if (value & (0x01 << bit)) {
  245. destptr[(short)((8000L * (long)bit) + (col>>3))] |= 0x80 >> (col & 0x07);
  246. }
  247. }
  248. }
  249. destptr += 40;
  250. }
  251. }
  252. #endif
  253. /***************************************************************************
  254. * LOAD_PICTURE -- Loads a picture file (CPS or LBM format). *
  255. * *
  256. * This loads a picture file into a page buffer. The loaded file will *
  257. * be in MCGA or Amiga mode as requested. Supported source formats *
  258. * are CPS or all forms of IFF dpaint files. *
  259. * *
  260. * INPUT: filename - Source filename. The only files that are *
  261. * processed as IFF are those files that end with *
  262. * ".LBM". *
  263. * *
  264. * loadbuf - Buffer type number for the temporary loading *
  265. * buffer. It will be trashed. *
  266. * *
  267. * destbuf - Buffer type number for the picture to be placed. *
  268. * *
  269. * palette - Palette buffer pointer. If this value is NULL *
  270. * then no palette is loaded. *
  271. * *
  272. * format - Desired destination format. *
  273. * BM_AMIGA - Destination buffer will contain the *
  274. * picture in bitplane format (Amiga). *
  275. * The buffer will contain data equal to *
  276. * 8K times the number of bit planes. *
  277. * *
  278. * BM_MCGA - Destination buffer will contain the *
  279. * picture in MCGA format (byte per pixel).*
  280. * The buffer will be 64K in size. *
  281. * *
  282. * OUTPUT: int number of bitplanes read into the dest buffer *
  283. * *
  284. * WARNINGS: none *
  285. * *
  286. * HISTORY: *
  287. * 05/16/1991 JLB : Created. *
  288. * 05/20/1991 JLB : Handles Amiga and IBM destination formats. *
  289. *=========================================================================*/
  290. int __cdecl Load_Picture(char const *filename, BufferClass& scratchbuf, BufferClass& destbuf, unsigned char *palette, PicturePlaneType format)
  291. {
  292. int fh; // Input file handle.
  293. long ifftype; // Iff form type.
  294. int counter; // Count of the bytes decompressed.
  295. int value; // Working compression code value.
  296. int len; // int sized length value.
  297. int index; // Working index values.
  298. BitMapHeader_Type bmhd; // BMHD chunk data.
  299. IFFForm_Type formtype; // ILBM, PBM.
  300. char *src; // Working source body pointer.
  301. char *dest; // Working destination body pointer.
  302. //len = strlen(filename);
  303. //strupr(filename);
  304. fh = Open_File(filename,READ);
  305. if (fh == WW_ERROR) return(FALSE);
  306. Read_File(fh,&ifftype,4L);
  307. Close_File(fh);
  308. if (ifftype != ID_FORM) {
  309. return((int)Load_Uncompress(filename, scratchbuf, destbuf, palette ) / 8000 ) ;
  310. } else {
  311. fh = Open_Iff_File(filename); // Opens and checks for IFF form.
  312. if (fh == WW_ERROR) return(FALSE);
  313. Read_File(fh, &ifftype, 4L);
  314. if (ifftype == ID_ILBM) {
  315. formtype = FORM_ILBM; // Inter-Leaved Bit Map.
  316. } else {
  317. if (ifftype == ID_PBM) {
  318. formtype = FORM_PBM; // Packed Bit Map.
  319. } else {
  320. return FALSE; // Not a recognizable picture file.
  321. }
  322. }
  323. // Load the BMHD chunk.
  324. if (Read_Iff_Chunk(fh,ID_BMHD,(char*)&bmhd,sizeof(BitMapHeader_Type))) {
  325. #if(IBM)
  326. // Perform necessary IBM conversions to the data.
  327. bmhd.W = Reverse_Short(bmhd.W);
  328. bmhd.H = Reverse_Short(bmhd.H);
  329. bmhd.X = Reverse_Short(bmhd.X);
  330. bmhd.Y = Reverse_Short(bmhd.Y);
  331. // this is a mistake Xaspect and YAspect are char type
  332. // bmhd.XAspect = Reverse_Short(bmhd.XAspect);
  333. // bmhd.YAspect = Reverse_Short(bmhd.YAspect);
  334. value = bmhd.XAspect ;
  335. bmhd.XAspect = bmhd.YAspect ;
  336. bmhd.YAspect = ( unsigned char ) value ;
  337. bmhd.PageWidth = Reverse_Short(bmhd.PageWidth);
  338. bmhd.PageHeight = Reverse_Short(bmhd.PageHeight);
  339. #endif
  340. if (bmhd.Masking > 2) return FALSE; // Don't allow brushes.
  341. if (bmhd.Compression > 1) return FALSE; // Unknown compression.
  342. } else {
  343. return FALSE; // Unable to read the required BMHD chunk.
  344. }
  345. // Load the palette if asked.
  346. if (palette)
  347. {
  348. int pbytes ; // Number of CMAP bytes required.
  349. unsigned char color; // Palette color value.
  350. unsigned char *paletteptr; // Allocated buffer for palette conversions.
  351. unsigned char *source; // Scratch source CMAP data pointer.
  352. unsigned char *dest2; // Scratch destination palette pointer.
  353. // Number of CMAP bytes that are needed.
  354. pbytes = (1 << bmhd.BPlanes) * 3;
  355. // Allocate the temporary palette buffer.
  356. paletteptr = (unsigned char *)Alloc(pbytes, MEM_CLEAR);
  357. source = paletteptr;
  358. dest2 = palette;
  359. // Read in only the bytes that are needed.
  360. pbytes = (int)Read_Iff_Chunk(fh, ID_CMAP, (char *) paletteptr, pbytes);
  361. if (pbytes) {
  362. /*
  363. ** CMAP to machine specific palette conversion code. Conversion
  364. ** goes from CMAP three bytes per color register to the machine
  365. ** specific form.
  366. */
  367. switch(format) {
  368. default:
  369. case BM_MCGA:
  370. // Convert CMAP to IBM MCGA palette form.
  371. for (index = 0; index < pbytes; index++) {
  372. *dest2++ = *source++ >> 2;
  373. }
  374. break;
  375. #if MAKE_AMIGA_ART
  376. case BM_AMIGA:
  377. // Convert CMAP to Amiga nibble packed palette form.
  378. for (index = 0; index < pbytes; index += 3) {
  379. *dest2++ = *(source++) >> 4;
  380. color = (*(source++) & 0xf0);
  381. color += *(source++) >> 4;
  382. *dest2++ = color;
  383. }
  384. break;
  385. #endif
  386. }
  387. }
  388. Free(paletteptr);
  389. }
  390. // Load in BODY chunk.
  391. dest = (char *) scratchbuf.Get_Buffer();
  392. src = (char *) destbuf.Get_Buffer();
  393. if (Read_Iff_Chunk(fh, ID_BODY, src, destbuf.Get_Size()))
  394. {
  395. for (index = 0; index < (short)bmhd.H; index++)
  396. {
  397. /* Height of source */
  398. // Transfer (possibly uncompress) one row of data.
  399. // PBM or ILBM reader. Bytes per row (all bitplanes).
  400. counter = bmhd.BPlanes * (bmhd.W >> 3);
  401. // If there is a mask then there is one more bitplane.
  402. if (bmhd.Masking == 1)
  403. counter += bmhd.W >> 3 ;
  404. if (bmhd.Compression == 1)
  405. {
  406. // The data is compressed.
  407. // Decompress one scanline (all bitplanes) at a time.
  408. while (counter)
  409. {
  410. value = ( signed char ) *src++; // Decompression code.
  411. if (value == -128) continue; // NOOP code.
  412. if (value >= 0)
  413. {
  414. // Copy N+1 bytes.
  415. len = ((short) value) + 1;
  416. // Ignore the masking bitplane.
  417. if ( bmhd.Masking != 1 ||
  418. (bmhd.Masking==1 && counter > ((short)bmhd.W >> 3) ) )
  419. {
  420. memcpy(dest, src, len);
  421. dest += len;
  422. }
  423. counter -= len;
  424. src += len;
  425. }
  426. else
  427. {
  428. // Replicate -N+1 bytes.
  429. len = (-((short) value)) + 1;
  430. value = *src++;
  431. // Ignore the masking bitplane.
  432. if (bmhd.Masking != 1 || (bmhd.Masking==1 && counter > ((short)bmhd.W >> 3)))
  433. {
  434. memset(dest,value,len);
  435. dest += len;
  436. }
  437. counter -= len;
  438. }
  439. }
  440. }
  441. else
  442. {
  443. // Plain data is just copied.
  444. memcpy(dest,src,counter);
  445. dest += counter;
  446. src += counter;
  447. }
  448. }
  449. /*
  450. ** Perform necessary conversions to the data in order to reach
  451. ** the desired format.
  452. */
  453. switch (format) {
  454. default:
  455. case BM_MCGA: // Byte per pixel desired.
  456. if (formtype == FORM_ILBM) {
  457. ILBM_To_MCGA(scratchbuf, destbuf, bmhd.BPlanes);
  458. } else {
  459. Mem_Copy(scratchbuf.Get_Buffer(), destbuf.Get_Buffer(), 64000L);
  460. }
  461. break;
  462. #if MAKE_AMIGA_ART
  463. case BM_AMIGA: // Bitplane format desired.
  464. if (formtype == FORM_ILBM) {
  465. ILBM_To_Amiga(scratchbuf, destbuf, bmhd.BPlanes);
  466. } else {
  467. PBM_To_Amiga(scratchbuf, destbuf, bmhd.BPlanes);
  468. }
  469. break;
  470. #endif
  471. }
  472. }
  473. Close_Iff_File(fh);
  474. }
  475. return((short)bmhd.BPlanes); // Loaded the picture successfully.
  476. }