home *** CD-ROM | disk | FTP | other *** search
- /*
- FILE: bmp.c
- MODULE: bmp.gio
- PROJECT: photogenics
- AUTHOR: Jolyon Ralph
- DATE: 6/3/95
- COMMENT: Example .BMP loader
- COPYRIGHT: © Almathera 1994-6 All Rights Reserved
- */
-
- #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 <pragmas/pgs_pragmas.h>
-
- #include <photogenics/pgs_protos.h>
- #include <photogenics/gio.h>
-
-
- /* first we'll define a structure we need later */
-
- struct BMPHeader
- {
- UWORD id;
- PCLONG filesize; // PCLONG is defined in gio.h as == ULONG
- PCWORD reserved[2];// PCWORD is defined in gio.h as == UWORD
- 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;
-
- };
-
- /* some macros to swap between intel and motorola byte order */
-
- #define PCLong2Long(val) ((((val&0xff)<<24)|((val&0xff00)<<8)|((val&0xff0000)>>8)|((val&0xff000000)>>24)))
- #define PCWord2Word(val) ((((val&0xff)<<8)|((val&0xff00)>>8)))
-
- __asm ULONG GioInfo(void)
- {
- /* This function returns flags to determine the features of this .GIO
-
- GIOF_LOADER8 - Because it can load 8-bit (or less) data
- GIOF_LOADER24 - Because it can load 24-bit data
- GIOF_LOADFILE - Because it reads data from a file
- GIOF_SAVER24 - Because it can save 24-bit data
- GIOF_SAVEFILE - Because it writes data to a file
- GIOF_EXTENDED - This is a V1.2 format .GIO
- */
- return(GIOF_LOADER8|GIOF_LOADER24|GIOF_LOADFILE|GIOF_SAVER24|GIOF_SAVEFILE|GIOF_EXTENDED);
- }
-
- __asm ULONG GioExamine(register __a0 struct GIOData *giodata)
- {
- struct BMPHeader *bmphead;
-
- // first we set up flags. Always do this first in GioExamine()
- giodata->Flags = GioInfo();
-
- /*
- When we are called (and GIOF_LOADFILE is set in GioInfo())
- we are passed the first 64-bytes of the file in giodata->Data.
- This is sufficient for most loaders to identify the filetype
-
- Let's reference the data as a BMPHeader structure... */
-
- bmphead = (struct BMPHeader *) giodata->Data;
-
-
- if(bmphead->id!=(0x424d))
- {
- // it's NOT a .BMP file, let's get out of here!
- giodata->Error = GIO_WRONGTYPE;
- goto err;
- }
-
-
-
- // it IS a .BMP file, let's find out some details...
-
- giodata->Width = PCLong2Long(bmphead->width);
- giodata->Height = PCLong2Long(bmphead->depth);
- giodata->Depth = PCWord2Word(bmphead->bits);
- giodata->Headerlength = PCLong2Long(bmphead->headersize);
- giodata->Error = GIO_OK; // This means we're all ok to continue.
- err:
- return(giodata->Error);
-
- }
-
- /* giodata contains pointers to several open libraries.
- You can reference them simply by using these #defines, you
- do not need to open them!
-
- Others included are GfxBase, IntuitionBase, AslBase, GadToolsBase,
- etc. See the definition of the giodata structure for a full list
- (photogenics.h)
-
- */
-
- #define DOSBase giodata->DOSBase
- #define PgsBase giodata->PgsBase
-
- __asm ULONG GioRead(register __a0 struct GIOData *giodata)
- {
- int x,y,r;
- UBYTE *bytes,*pal;
- ULONG rdsize;
- struct BMPPalEntry palentry;
-
- // First set the text for the progress bar...
-
- SetProgress("Loading Windows BMP file",0);
-
- // Was our source file a 24-bit .BMP file?
- if(giodata->Depth == 24)
- {
-
- // Seek to the right place in the file *IMPORTANT!*
-
- 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 = GIO_ABORTED;
- goto err;
- }
- }
-
- // Get the address of line y of the image data...
-
- bytes=GetLine(giodata,y);
-
- // And read the data straight in....
-
- Read(giodata->Filehandle,bytes,giodata->Width*3);
-
- // Windows byte order is BGR, we need RGB, so swap them round!
-
- for(x=0;x<giodata->Width;x++)
- {
- r=*bytes;
- *bytes=*(bytes+2);
- *(bytes+2)=r;
- bytes+=3;
- }
-
- // And we've finished with the memory, so release the line.
- ReleaseLine(giodata,y);
- }
-
- // All AOK, get out of here...
- giodata->Error = GIO_OK;
-
- } else
- {
- // Same as before, except first we load a palette...
-
- Seek(giodata->Filehandle,0x36+giodata->SkipBytes,OFFSET_BEGINNING);
- if(!(pal = giodata->Palette))
- {
- giodata->Error=GIO_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 = GIO_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 = GIO_ABORTED;
- goto err;
- }
- bytes = GetLine(giodata,y);
- Read(giodata->Filehandle,bytes,rdsize);
- ReleaseLine(giodata,y);
- }
-
- giodata->Error = GIO_OK;
-
- /* See how simple that was? We didn't have to convert to 24-bit
- data at all. All we did was set up the palette, tell Photogenics
- how deep the image is, and load the data. If we were loading
- planar image data, we'd set the GIOF_PLANAR flag in the
- GioInfo() function, and Photogenics would convert the planar
- data (1 to 8 bit or 24-bit) into 24-bit.
-
- If you have a bizare format (eg 16-bit hicolour) or if the
- bytes are ordered wrong (as in 24-bit BMP above.) then you
- will have to do the 24-bit conversion yourself.
-
- */
-
- }
-
- err:
- return(giodata->Error);
- }
-
- __asm ULONG GioWrite(register __a0 struct GIOData *giodata)
- {
- struct BMPHeader header = {0};
- UBYTE *peeker;
- int x,y,bytewid;
- UBYTE r,g,b;
-
- /* first make sure it's 24-bit data - it always is at the moment! */
- if(giodata->Depth!=24)
- {
- giodata->Error = GIO_WRONGTYPE;
- goto err;
- }
-
- SetProgress("Saving Windows BMP file...",0);
-
- 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=giodata->Height-1;y>=0;y--)
- {
- if(!(y%16))
- if(SetProgress(0,100-(y*100/giodata->Height))!=1)
- {
- giodata->Error = GIO_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 = GIO_OK;
-
- err:
- return(giodata->Error);
- }
-
- __asm void GioCleanUp(register __a0 struct GIOData *giodata)
- {
- }
-
- __asm void GioLoadPrefs(register __a0 struct GIOData *giodata)
- {
- /* Preferences for load (none needed for .BMP) */
- }
-
- __asm void GioSavePrefs(register __a0 struct GIOData *giodata)
- {
- /* Preferences for save (none needed for .BMP) */
- }
-