| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552 |
- /*
- ** Command & Conquer Red Alert(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /* $Header: g:/library/wwlib32/file/rcs/loadpict.cpp 1.1 1994/04/20 14:38:08 scott_bowen Exp $ */
- /***************************************************************************
- ** 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 **
- ***************************************************************************
- * *
- * Project Name : Westwood Library *
- * *
- * File Name : IFFEXTRA.C *
- * *
- * Programmer : Joe L. Bostic *
- * *
- * Start Date : June 11, 1991 *
- * *
- * Last Update : April 20, 1994 [SKB] *
- * *
- *-------------------------------------------------------------------------*
- * Functions: *
- * ILBM_To_Amiga -- Convert ILBM to bitplane Amiga format. *
- * ILBM_To_MCGA -- Converts ILBM picture into MCGA format. *
- * PBM_To_Amiga -- Converts a PBM picture into Amiga format. *
- * Load_Picture -- Loads a picture file (CPS or LBM format). *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "iff.h"
- #include "file.h"
- #include <wwmem.h> // For Alloc.
- #if(IBM)
- #include <mem.h>
- #endif
- // Since we are not currently using AMIGA, this has been put in to
- // give us back some code space. If it is needed for a utility,
- // this module should be recompiled with that utility and set the
- // define to TRUE.
- #define MAKE_AMIGA_ART FALSE
- /*
- ** An IFF picture file can have one of two formats:
- ** ILBM - InterLeaved Bit Map
- ** PBM - Packed Bit Map
- */
- typedef enum {
- FORM_ILBM,
- FORM_PBM
- } IFFForm_Type;
- /*
- ** These are the various chunks that compose an IFF picture file.
- */
- #define ID_FORM MAKE_ID('F','O','R','M')
- #define ID_ILBM MAKE_ID('I','L','B','M')
- #define ID_PBM MAKE_ID('P','B','M',' ')
- #define ID_CMAP MAKE_ID('C','M','A','P')
- #define ID_BODY MAKE_ID('B','O','D','Y')
- #define ID_BMHD MAKE_ID('B','M','H','D')
- /*
- ** The BMHD (Bit Map HeaDer) chunk in an IFF picture file contains the
- ** information necessary to extract that picture from the BODY chunk.
- ** It also indicates the size and depth of the source art.
- */
- typedef struct {
- unsigned short W, H; // Raster width and height in pixels.
- short X, Y; // Pixel postion for this image.
- char BPlanes; // Number of bitplanes.
- unsigned char Masking; // Masking control byte.
- // 0 = No masking.
- // 1 = Has a mask.
- // 2 = Has transparent color.
- // 3 = Lasso.
- unsigned char Compression; // Compression method.
- // 0 = No compression.
- // 1 = Byte run compression.
- char pad;
- unsigned short Transparent; // Transparent color number.
- unsigned char XAspect, // Pixel aspect ratio of source art.
- YAspect;
- short PageWidth, // Source 'page' size in pixels.
- PageHeight;
- } BitMapHeader_Type;
- /*=========================================================================*/
- /* The following PRIVATE functions are in this file: */
- /*=========================================================================*/
- PRIVATE void __cdecl ILBM_To_MCGA(BufferClass& src, BufferClass& dest, int planes);
- PRIVATE void __cdecl ILBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes);
- PRIVATE void __cdecl PBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes);
- /*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
- /***************************************************************************
- * ILBM_TO_MCGA -- Converts ILBM picture into MCGA format. *
- * *
- * This converts an ILBM picture (typical of DPaint LBM files) and *
- * converts it to MCGA mode (byte per pixel). This function would be *
- * used after the body of an ILBM picture is loaded. Because the *
- * number of bitplanes can vary greatly, it is necessary to pass the *
- * bitplane count to this function. The size (320 by 200) of the *
- * source picture is presumed. *
- * *
- * INPUT: src - Buffer number for source ILBM picture. *
- * *
- * dest - Buffer number for place to put MCGA format. *
- * *
- * planes- The number of bitplanes in the ILBM picture. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 05/16/1991 JLB : Created. *
- * 04/20/1994 SKB : Update to 32 bit library and make private. *
- *=========================================================================*/
- PRIVATE void __cdecl ILBM_To_MCGA(BufferClass& src, BufferClass& dest, int planes)
- {
- char *source; // Source pointer.
- char *destination; // Destination pointer.
- int index,j,i; // Working index values.
- int bplane; // Bit plane counter.
- char bytes[8]; // Byte array holding max bitplanes (8).
- char value; // Composed byte(pixel) value.
- source = (char *) src.Get_Buffer();
- destination = (char *) dest.Get_Buffer();
- memset(bytes, '\0', 8); // Makes sure upper bits will be clear.
- // Each row is grouped and processed together.
- for (index = 0; index < 200 /*bmhd.H*/; index++) {
- // Process each line in groups of 8 bytes.
- for (j = 0; j < 40 /*(bmhd.W>>3)*/; j++) {
- // Get the bitplane bytes.
- for (bplane = 0; bplane < planes /*bmhd.BPlanes*/; bplane++) {
- bytes[bplane] = *(source + (bplane * 40 /*(bmhd.W>>3)*/));
- }
- source++;
- // Roll the bits out to create 8 pixels (by bytes).
- for (i = 0; i < 8; i++) {
- // 8 bits per byte.
- value = 0;
- for (bplane = planes - 1/*bmhd.BPlanes-1*/; bplane >= 0; bplane--) {
- value <<= 1; // Make room for next bit.
- if (bytes[bplane] & 0x80) value |= 1; // Set the bit.
- bytes[bplane] <<= 1;
- }
- *destination++ = value; // Output the pixel byte.
- }
- }
- // Advance to next scan line.
- source += 40 /* (bmhd.W >> 3)*/ * (planes /* bmhd.BPlanes */ - 1);
- }
- }
- /***************************************************************************
- * ILBM_TO_AMIGA -- Convert ILBM to bitplane Amiga format. *
- * *
- * This converts an InterLeaved BitMap picture into Amiga bitplane *
- * format (8K per bitplane). The data of an ILBM picture is controlled *
- * by the number of bitplanes it contains. The bitplane count is *
- * passed into this program. *
- * *
- * INPUT: src - Buffer number for source ILBM picture data. *
- * *
- * dest - Buffer number for destination Amiga picture data. *
- * *
- * planes- The number of bitplanes in the source ILBM data. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: The amount of data placed into the destination buffer is *
- * controlled by the number of bitplanes specified. It is *
- * 8000 per bitplane. *
- * *
- * HISTORY: *
- * 05/20/1991 JLB : Created. *
- * 04/20/1994 SKB : Update to 32 bit library and make private. *
- * 04/20/1994 SKB : #if out for main library. Only used in utils maybe. *
- *=========================================================================*/
- #if MAKE_AMIGA_ART
- PRIVATE void __cdecl ILBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes)
- {
- int row; // Working row counter.
- int bp; // Working bitplane counter.
- char *srcptr, // Source buffer pointer.
- *dstptr; // Destination buffer pointer.
- srcptr = (char *) src.Get_Buffer(); // Source buffer pointer.
- dstptr = (char *) dest.Get_Buffer(); // Destination buffer pointer.
- for (row = 0; row < 200; row++) {
- for (bp = 0; bp < planes; bp++) {
- Mem_Copy(srcptr,dstptr+(8000*bp),40);
- srcptr += 40;
- }
- dstptr += 40;
- }
- }
- #endif
- /***************************************************************************
- * PBM_TO_AMIGA -- Converts a PBM picture into Amiga format. *
- * *
- * This converts a PBM (Packed Bit Map) MCGA picture into Amiga *
- * bitplane format. A PBM picture presumes 8 bitplanes, but this *
- * can be controlled by the 'plane' parameter passed in. *
- * *
- * INPUT: src - Buffer number for the source PBM data. *
- * *
- * dest - Buffer number to place the Amiga format picture. *
- * *
- * planes- The number of bitplanes to extract from the PBM source *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: The amount of data placed into the destination buffer is *
- * controlled by the number of bitplanes specified. It is *
- * 8000 per bitplane. *
- * *
- * HISTORY: *
- * 05/20/1991 JLB : Created. *
- * 04/20/1994 SKB : Update to 32 bit library and make private. *
- * 04/20/1994 SKB : #if out for main library. Only used in utils maybe. *
- *=========================================================================*/
- #if MAKE_AMIGA_ART
- PRIVATE void __cdecl PBM_To_Amiga(BufferClass& src, BufferClass& dest, int planes)
- {
- int row, // Working row counter.
- col, // Working column (by byte) counter.
- bit; // Working bitplane counter.
- unsigned char *destptr, // Destination byte pointer.
- *srcptr; // Source byte pointer.
- unsigned char value; // Working input MCGA pixel number.
- destptr = (unsigned char *) dest.Get_Buffer();
- srcptr = (unsigned char *) src.Get_Buffer();
- memset(destptr, 0, 32000);
- memset(destptr+32000, 0, 32000);
- for (row = 0; row < 200; row++) {
- for (col = 0; col < 320; col++) {
- value = *srcptr++;
- for (bit = 0; bit < planes; bit++) {
- if (value & (0x01 << bit)) {
- destptr[(short)((8000L * (long)bit) + (col>>3))] |= 0x80 >> (col & 0x07);
- }
- }
- }
- destptr += 40;
- }
- }
- #endif
- /***************************************************************************
- * LOAD_PICTURE -- Loads a picture file (CPS or LBM format). *
- * *
- * This loads a picture file into a page buffer. The loaded file will *
- * be in MCGA or Amiga mode as requested. Supported source formats *
- * are CPS or all forms of IFF dpaint files. *
- * *
- * INPUT: filename - Source filename. The only files that are *
- * processed as IFF are those files that end with *
- * ".LBM". *
- * *
- * loadbuf - Buffer type number for the temporary loading *
- * buffer. It will be trashed. *
- * *
- * destbuf - Buffer type number for the picture to be placed. *
- * *
- * palette - Palette buffer pointer. If this value is NULL *
- * then no palette is loaded. *
- * *
- * format - Desired destination format. *
- * BM_AMIGA - Destination buffer will contain the *
- * picture in bitplane format (Amiga). *
- * The buffer will contain data equal to *
- * 8K times the number of bit planes. *
- * *
- * BM_MCGA - Destination buffer will contain the *
- * picture in MCGA format (byte per pixel).*
- * The buffer will be 64K in size. *
- * *
- * OUTPUT: int number of bitplanes read into the dest buffer *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 05/16/1991 JLB : Created. *
- * 05/20/1991 JLB : Handles Amiga and IBM destination formats. *
- *=========================================================================*/
- int __cdecl Load_Picture(char const *filename, BufferClass& scratchbuf, BufferClass& destbuf, unsigned char *palette, PicturePlaneType format)
- {
- int fh; // Input file handle.
- long ifftype; // Iff form type.
- int counter; // Count of the bytes decompressed.
- int value; // Working compression code value.
- int len; // int sized length value.
- int index; // Working index values.
- BitMapHeader_Type bmhd; // BMHD chunk data.
- IFFForm_Type formtype; // ILBM, PBM.
- char *src; // Working source body pointer.
- char *dest; // Working destination body pointer.
- //len = strlen(filename);
- //strupr(filename);
- fh = Open_File(filename,READ);
- if (fh == WW_ERROR) return(FALSE);
- Read_File(fh,&ifftype,4L);
- Close_File(fh);
- if (ifftype != ID_FORM) {
- return((int)Load_Uncompress(filename, scratchbuf, destbuf, palette ) / 8000 ) ;
- } else {
- fh = Open_Iff_File(filename); // Opens and checks for IFF form.
- if (fh == WW_ERROR) return(FALSE);
- Read_File(fh, &ifftype, 4L);
- if (ifftype == ID_ILBM) {
- formtype = FORM_ILBM; // Inter-Leaved Bit Map.
- } else {
- if (ifftype == ID_PBM) {
- formtype = FORM_PBM; // Packed Bit Map.
- } else {
- return FALSE; // Not a recognizable picture file.
- }
- }
- // Load the BMHD chunk.
- if (Read_Iff_Chunk(fh,ID_BMHD,(char*)&bmhd,sizeof(BitMapHeader_Type))) {
- #if(IBM)
- // Perform necessary IBM conversions to the data.
- bmhd.W = Reverse_Short(bmhd.W);
- bmhd.H = Reverse_Short(bmhd.H);
- bmhd.X = Reverse_Short(bmhd.X);
- bmhd.Y = Reverse_Short(bmhd.Y);
- // this is a mistake Xaspect and YAspect are char type
- // bmhd.XAspect = Reverse_Short(bmhd.XAspect);
- // bmhd.YAspect = Reverse_Short(bmhd.YAspect);
- value = bmhd.XAspect ;
- bmhd.XAspect = bmhd.YAspect ;
- bmhd.YAspect = ( unsigned char ) value ;
- bmhd.PageWidth = Reverse_Short(bmhd.PageWidth);
- bmhd.PageHeight = Reverse_Short(bmhd.PageHeight);
- #endif
- if (bmhd.Masking > 2) return FALSE; // Don't allow brushes.
- if (bmhd.Compression > 1) return FALSE; // Unknown compression.
- } else {
- return FALSE; // Unable to read the required BMHD chunk.
- }
- // Load the palette if asked.
- if (palette)
- {
- int pbytes ; // Number of CMAP bytes required.
- unsigned char color; // Palette color value.
- unsigned char *paletteptr; // Allocated buffer for palette conversions.
- unsigned char *source; // Scratch source CMAP data pointer.
- unsigned char *dest2; // Scratch destination palette pointer.
- // Number of CMAP bytes that are needed.
- pbytes = (1 << bmhd.BPlanes) * 3;
- // Allocate the temporary palette buffer.
- paletteptr = (unsigned char *)Alloc(pbytes, MEM_CLEAR);
- source = paletteptr;
- dest2 = palette;
- // Read in only the bytes that are needed.
- pbytes = (int)Read_Iff_Chunk(fh, ID_CMAP, (char *) paletteptr, pbytes);
- if (pbytes) {
- /*
- ** CMAP to machine specific palette conversion code. Conversion
- ** goes from CMAP three bytes per color register to the machine
- ** specific form.
- */
- switch(format) {
- default:
- case BM_MCGA:
- // Convert CMAP to IBM MCGA palette form.
- for (index = 0; index < pbytes; index++) {
- *dest2++ = *source++ >> 2;
- }
- break;
- #if MAKE_AMIGA_ART
- case BM_AMIGA:
- // Convert CMAP to Amiga nibble packed palette form.
- for (index = 0; index < pbytes; index += 3) {
- *dest2++ = *(source++) >> 4;
- color = (*(source++) & 0xf0);
- color += *(source++) >> 4;
- *dest2++ = color;
- }
- break;
- #endif
- }
- }
- Free(paletteptr);
- }
- // Load in BODY chunk.
- dest = (char *) scratchbuf.Get_Buffer();
- src = (char *) destbuf.Get_Buffer();
- if (Read_Iff_Chunk(fh, ID_BODY, src, destbuf.Get_Size()))
- {
- for (index = 0; index < (short)bmhd.H; index++)
- {
- /* Height of source */
- // Transfer (possibly uncompress) one row of data.
- // PBM or ILBM reader. Bytes per row (all bitplanes).
- counter = bmhd.BPlanes * (bmhd.W >> 3);
- // If there is a mask then there is one more bitplane.
- if (bmhd.Masking == 1)
- counter += bmhd.W >> 3 ;
- if (bmhd.Compression == 1)
- {
- // The data is compressed.
- // Decompress one scanline (all bitplanes) at a time.
- while (counter)
- {
- value = ( signed char ) *src++; // Decompression code.
- if (value == -128) continue; // NOOP code.
- if (value >= 0)
- {
- // Copy N+1 bytes.
- len = ((short) value) + 1;
- // Ignore the masking bitplane.
- if ( bmhd.Masking != 1 ||
- (bmhd.Masking==1 && counter > ((short)bmhd.W >> 3) ) )
- {
- memcpy(dest, src, len);
- dest += len;
- }
- counter -= len;
- src += len;
- }
- else
- {
- // Replicate -N+1 bytes.
- len = (-((short) value)) + 1;
- value = *src++;
- // Ignore the masking bitplane.
- if (bmhd.Masking != 1 || (bmhd.Masking==1 && counter > ((short)bmhd.W >> 3)))
- {
- memset(dest,value,len);
- dest += len;
- }
- counter -= len;
- }
- }
- }
- else
- {
- // Plain data is just copied.
- memcpy(dest,src,counter);
- dest += counter;
- src += counter;
- }
- }
- /*
- ** Perform necessary conversions to the data in order to reach
- ** the desired format.
- */
- switch (format) {
- default:
- case BM_MCGA: // Byte per pixel desired.
- if (formtype == FORM_ILBM) {
- ILBM_To_MCGA(scratchbuf, destbuf, bmhd.BPlanes);
- } else {
- Mem_Copy(scratchbuf.Get_Buffer(), destbuf.Get_Buffer(), 64000L);
- }
- break;
- #if MAKE_AMIGA_ART
- case BM_AMIGA: // Bitplane format desired.
- if (formtype == FORM_ILBM) {
- ILBM_To_Amiga(scratchbuf, destbuf, bmhd.BPlanes);
- } else {
- PBM_To_Amiga(scratchbuf, destbuf, bmhd.BPlanes);
- }
- break;
- #endif
- }
- }
- Close_Iff_File(fh);
- }
- return((short)bmhd.BPlanes); // Loaded the picture successfully.
- }
|