home *** CD-ROM | disk | FTP | other *** search
- /* example Window BMP loader - (C) Almathera 1994 21/11/94
-
- BUGS: does NOT support .DIB/RLE compressed or OS/2 BMP files yet
-
- REQUIRES: SAS C V6.50 or higher.
-
- */
-
- #include <exec/types.h>
- #include <clib/exec_protos.h>
- #include <clib/dos_protos.h>
- #include <dos/dos.h>
- #include <pragmas/exec_pragmas.h>
- #include <pragmas/dos_pragmas.h>
- #include "pgs_protos.h"
- #include "pgs_pragmas.h"
-
- #include "gio.h"
- #include <stdio.h>
- #include <stdlib.h>
-
- struct BMPHeader
- {
- UWORD id; // char id[2]
- PCLONG filesize;
- PCWORD reserved[2];
- PCLONG headersize;
- PCLONG infosize;
- PCLONG width;
- PCLONG depth;
- PCWORD biplanes;
- PCWORD bits;
- PCLONG bicompression;
- PCLONG bisizeimage;
- PCLONG bixpelspermeter;
- PCLONG biyperlpermeter;
- PCLONG biclrused;
- PCLONG biclrimportant;
- };
-
- struct BMPPalEntry
- {
- UBYTE blu;
- UBYTE grn;
- UBYTE red;
- UBYTE pad;
-
- };
-
- #define PCLong2Long(val) ((((val&0xff)<<24)|((val&0xff00)<<8)|((val&0xff0000)>>8)|((val&0xff000000)>>24)))
- #define PCWord2Word(val) ((((val&0xff)<<8)|((val&0xff00)>>8)))
-
- /* prototypes */
- __asm ULONG __saveds GioInfo(void);
- __asm ULONG __saveds GioExamine(register __a0 struct GIOData *giodata);
- __asm ULONG __saveds GioRead(register __a0 struct GIOData *giodata);
- __asm ULONG __saveds GioWrite(register __a0 struct GIOData *giodata);
- /* end of prototypes */
-
-
- __asm ULONG __saveds GioInfo(void)
- {
- // return(GIOF_LOADER8|GIOF_LOADER24|GIOF_SAVER8|GIOF_SAVER24|GIOF_LOADFILE|GIOF_SAVEFILE)
- return(GIOF_LOADER8|GIOF_LOADER24|GIOF_LOADFILE|GIOF_SAVER24|GIOF_SAVEFILE);
-
- }
-
- __asm ULONG __saveds GioExamine(register __a0 struct GIOData *giodata)
- {
- struct BMPHeader *bmphead;
- giodata->Flags = GioInfo();
- // examine file and return information on it.
- bmphead = (struct BMPHeader *) giodata->Data;
-
- if(bmphead->id!=(0x424d))
- {
- giodata->Error = LOAD_WRONGTYPE;
- goto err;
- }
- giodata->Width = PCLong2Long(bmphead->width);
- giodata->Height = PCLong2Long(bmphead->depth);
- giodata->Depth = PCWord2Word(bmphead->bits);
- giodata->Headerlength = PCLong2Long(bmphead->headersize);
-
- giodata->Error = LOAD_OK;
- err:
- return(giodata->Error);
-
- }
-
- #define DOSBase giodata->DOSBase
- #define PgsBase giodata->PgsBase
-
- __asm ULONG __saveds GioRead(register __a0 struct GIOData *giodata)
- {
- int x,y,r;
- UBYTE *bytes,*pal;
- ULONG rdsize;
- struct BMPPalEntry palentry;
-
- SetProgress("Loading Windows BMP file",0);
-
- if(giodata->Depth == 24)
- {
- // load in 24-bit data here
-
- Seek(giodata->Filehandle,giodata->Headerlength+giodata->SkipBytes,
- OFFSET_BEGINNING);
- for(y=giodata->Height-1;y>=0;y--)
- {
- if(!(y%16)) // don't slow down by calling SetProgress too often
- if(SetProgress(0,100-(y*100/giodata->Height))!=1)
- {
- giodata->Error = LOAD_ABORTED;
- goto err;
- }
-
- bytes=GetLine(giodata,y);
- // here we obtain a pointer to the line bitmap
-
- Read(giodata->Filehandle,bytes,giodata->Width*3);
- // we read the data in
-
- for(x=0;x<giodata->Width;x++)
- { // BGR to RGB - swap byte order after load
- r=*bytes;
- *bytes=*(bytes+2);
- *(bytes+2)=r;
- bytes+=3;
- }
- // BMP byte order is different to ours, so we swap them!
-
- ReleaseLine(giodata,y);
- // and release the line when we've finished.
-
- }
-
- giodata->Error = LOAD_OK;
- goto err;
-
- } else
- { // load in 1/4/8-bit data here
- // first decode palette
-
- Seek(giodata->Filehandle,0x36+giodata->SkipBytes,OFFSET_BEGINNING);
- if(!(pal = giodata->Palette))
- {
- giodata->Error=LOAD_WRONGTYPE;
- goto err;
- }
- for(x=0;x<(1<<(giodata->Depth));x++)
- {
- Read(giodata->Filehandle,&palentry,4);
- *pal++=palentry.red;
- *pal++=palentry.grn;
- *pal++=palentry.blu;
- }
- Seek(giodata->Filehandle,giodata->Headerlength+giodata->SkipBytes,
- OFFSET_BEGINNING);
- switch(giodata->Depth)
- {
-
- // decide how many bytes to read in at a time
-
- case 1:
- rdsize=giodata->Width/8;
- break;
-
- case 4:
- rdsize=giodata->Width/2;
- break;
-
- case 8:
- rdsize=giodata->Width;
- break;
-
- default:
- giodata->Error = LOAD_WRONGTYPE;
- goto err;
- }
- if(rdsize & 0x0003) {rdsize |= 0x0003;rdsize++;}
-
- for(y=giodata->Height-1;y>=0;y--)
- {
- if(!(y%16))
- if(SetProgress(0,100-(y*100/giodata->Height))!=1)
- {
- giodata->Error = LOAD_ABORTED;
- goto err;
- }
- bytes = GetLine(giodata,y);
- Read(giodata->Filehandle,bytes,rdsize);
- ReleaseLine(giodata,y);
- }
-
- giodata->Error = LOAD_OK;
- goto err;
-
- }
- giodata->Error=LOAD_WRONGTYPE;
-
- err:
- return(giodata->Error);
- }
-
- __asm ULONG __saveds GioWrite(register __a0 struct GIOData *giodata)
- {
- struct BMPHeader header = {0};
- UBYTE *peeker;
- int x,y,bytewid;
- UBYTE r,g,b;
-
-
- if(giodata->Depth == 24)
- { // save 24-bit data here
-
- bytewid = giodata->Width*3;
- if(bytewid & 0x3)
- { bytewid|=0x3; ++bytewid;
- }
- header.id = 0x424d;
- header.filesize = PCLong2Long(54 + (bytewid * giodata->Height));
- header.headersize = PCLong2Long(54);
- header.infosize = PCLong2Long(0x28L);
- header.width = PCLong2Long(giodata->Width);
- header.depth = PCLong2Long(giodata->Height);
- header.biplanes = PCWord2Word(1);
- header.bits = PCWord2Word(24);
- header.bicompression= 0;
- header.bisizeimage = PCLong2Long(bytewid*giodata->Height);
-
- Write(giodata->Filehandle,&header,sizeof(struct BMPHeader));
-
-
- for(y=0;y<giodata->Height;y++)
- {
- if(!(y%16))
- if(SetProgress(0,y*100/giodata->Height)!=1)
- {
- giodata->Error = LOAD_ABORTED;
- goto err;
- }
-
- peeker=GetLine(giodata,y);
- for(x=0;x<giodata->Width;x++)
- {
- r=*peeker++;
- g=*peeker++;
- b=*peeker++;
- FPutC(giodata->Filehandle,b);
- FPutC(giodata->Filehandle,g);
- FPutC(giodata->Filehandle,r);
- }
- ReleaseLine(giodata,y);
- }
- giodata->Error = LOAD_OK;
-
- } else
- { // save 8-bit data here
- giodata->Error = LOAD_WRONGTYPE;
- }
-
- err:
- return(giodata->Error);
- }
-