home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD1.iso / GFX / Misc / OTT-PHT3.DMS / in.adf / devdocs / gio / bmp.c next >
Encoding:
C/C++ Source or Header  |  1994-11-21  |  5.7 KB  |  266 lines

  1. /* example Window BMP loader - (C) Almathera 1994 21/11/94
  2.  
  3. BUGS: does NOT support .DIB/RLE compressed or OS/2 BMP files yet
  4.  
  5. REQUIRES: SAS C V6.50 or higher.
  6.  
  7. */
  8.  
  9.     #include <exec/types.h>
  10.     #include <clib/exec_protos.h>
  11.     #include <clib/dos_protos.h>
  12.     #include <dos/dos.h>
  13.     #include <pragmas/exec_pragmas.h>
  14.     #include <pragmas/dos_pragmas.h>
  15.    #include "pgs_protos.h"
  16.    #include "pgs_pragmas.h"
  17.  
  18.     #include "gio.h"
  19.     #include <stdio.h>
  20.     #include <stdlib.h>
  21.  
  22. struct BMPHeader 
  23. {
  24.     UWORD        id;            // char id[2]
  25.     PCLONG    filesize;
  26.     PCWORD    reserved[2];
  27.     PCLONG    headersize;
  28.     PCLONG    infosize;
  29.     PCLONG    width;
  30.     PCLONG    depth;
  31.     PCWORD    biplanes;
  32.     PCWORD    bits;
  33.     PCLONG    bicompression;
  34.     PCLONG    bisizeimage;
  35.     PCLONG    bixpelspermeter;
  36.     PCLONG    biyperlpermeter;
  37.     PCLONG    biclrused;
  38.     PCLONG    biclrimportant;
  39. };
  40.  
  41. struct BMPPalEntry 
  42. {
  43.     UBYTE blu;
  44.      UBYTE grn;
  45.     UBYTE    red;
  46.     UBYTE    pad;
  47.  
  48. };
  49.  
  50. #define PCLong2Long(val) ((((val&0xff)<<24)|((val&0xff00)<<8)|((val&0xff0000)>>8)|((val&0xff000000)>>24)))
  51. #define PCWord2Word(val) ((((val&0xff)<<8)|((val&0xff00)>>8)))
  52.  
  53. /* prototypes */
  54. __asm ULONG __saveds GioInfo(void);
  55. __asm ULONG __saveds GioExamine(register __a0 struct GIOData *giodata);
  56. __asm ULONG __saveds GioRead(register __a0 struct GIOData *giodata);
  57. __asm ULONG __saveds GioWrite(register __a0 struct GIOData *giodata);
  58. /* end of prototypes */
  59.  
  60.  
  61. __asm ULONG __saveds GioInfo(void)
  62. {
  63. //    return(GIOF_LOADER8|GIOF_LOADER24|GIOF_SAVER8|GIOF_SAVER24|GIOF_LOADFILE|GIOF_SAVEFILE)
  64.     return(GIOF_LOADER8|GIOF_LOADER24|GIOF_LOADFILE|GIOF_SAVER24|GIOF_SAVEFILE);
  65.  
  66. }
  67.  
  68. __asm ULONG __saveds GioExamine(register __a0 struct GIOData *giodata)
  69. {
  70.     struct BMPHeader *bmphead;
  71.     giodata->Flags = GioInfo();
  72.     // examine file and return information on it.
  73.     bmphead = (struct BMPHeader *) giodata->Data;
  74.     
  75.     if(bmphead->id!=(0x424d))
  76.     {
  77.         giodata->Error = LOAD_WRONGTYPE;
  78.         goto err;
  79.     }
  80.     giodata->Width             = PCLong2Long(bmphead->width);
  81.     giodata->Height             = PCLong2Long(bmphead->depth);
  82.     giodata->Depth             = PCWord2Word(bmphead->bits);
  83.     giodata->Headerlength     = PCLong2Long(bmphead->headersize);
  84.  
  85.     giodata->Error = LOAD_OK;
  86. err:
  87.     return(giodata->Error);
  88.  
  89. }
  90.  
  91. #define DOSBase giodata->DOSBase
  92. #define PgsBase giodata->PgsBase
  93.  
  94. __asm ULONG __saveds GioRead(register __a0 struct GIOData *giodata)
  95. {
  96. int x,y,r;
  97. UBYTE *bytes,*pal;
  98. ULONG rdsize;
  99. struct BMPPalEntry palentry;
  100.  
  101.     SetProgress("Loading Windows BMP file",0);
  102.  
  103.     if(giodata->Depth == 24)
  104.     {
  105.         // load in 24-bit data here
  106.  
  107.         Seek(giodata->Filehandle,giodata->Headerlength+giodata->SkipBytes,
  108.                 OFFSET_BEGINNING);
  109.         for(y=giodata->Height-1;y>=0;y--)
  110.         {
  111.             if(!(y%16)) // don't slow down by calling SetProgress too often
  112.             if(SetProgress(0,100-(y*100/giodata->Height))!=1)
  113.             {
  114.                 giodata->Error = LOAD_ABORTED;
  115.                 goto err;
  116.          }
  117.  
  118.             bytes=GetLine(giodata,y);
  119. // here we obtain a pointer to the line bitmap
  120.  
  121.             Read(giodata->Filehandle,bytes,giodata->Width*3);
  122. // we read the data in
  123.  
  124.             for(x=0;x<giodata->Width;x++)
  125.             { // BGR to RGB - swap byte order after load
  126.                     r=*bytes;
  127.                     *bytes=*(bytes+2);
  128.                     *(bytes+2)=r;
  129.                     bytes+=3;
  130.             }
  131. // BMP byte order is different to ours, so we swap them!
  132.  
  133.             ReleaseLine(giodata,y);
  134. // and release the line when we've finished.
  135.  
  136.         }
  137.  
  138.         giodata->Error = LOAD_OK;
  139.         goto err;
  140.  
  141.     } else
  142.     {        // load in 1/4/8-bit data here
  143.         // first decode palette
  144.  
  145.         Seek(giodata->Filehandle,0x36+giodata->SkipBytes,OFFSET_BEGINNING);        
  146.         if(!(pal = giodata->Palette)) 
  147.         {
  148.             giodata->Error=LOAD_WRONGTYPE;
  149.             goto err;
  150.         }
  151.         for(x=0;x<(1<<(giodata->Depth));x++)
  152.         {    
  153.             Read(giodata->Filehandle,&palentry,4);            
  154.             *pal++=palentry.red;
  155.             *pal++=palentry.grn;
  156.             *pal++=palentry.blu;
  157.         }
  158.         Seek(giodata->Filehandle,giodata->Headerlength+giodata->SkipBytes,
  159.            OFFSET_BEGINNING);
  160.         switch(giodata->Depth) 
  161.         {
  162.  
  163.       // decide how many bytes to read in at a time
  164.  
  165.             case 1:
  166.             rdsize=giodata->Width/8;
  167.             break;
  168.  
  169.             case 4:
  170.             rdsize=giodata->Width/2;
  171.             break;
  172.  
  173.             case 8:
  174.             rdsize=giodata->Width;
  175.             break;
  176.  
  177.             default:
  178.             giodata->Error = LOAD_WRONGTYPE;
  179.             goto err;
  180.         }
  181.         if(rdsize & 0x0003) {rdsize |= 0x0003;rdsize++;}
  182.  
  183.         for(y=giodata->Height-1;y>=0;y--)
  184.         {
  185.             if(!(y%16))
  186.             if(SetProgress(0,100-(y*100/giodata->Height))!=1)
  187.             {
  188.                 giodata->Error = LOAD_ABORTED;
  189.                 goto err;
  190.             }
  191.             bytes = GetLine(giodata,y);
  192.             Read(giodata->Filehandle,bytes,rdsize);
  193.             ReleaseLine(giodata,y);
  194.         }
  195.  
  196.         giodata->Error = LOAD_OK;
  197.         goto err;
  198.  
  199.     }
  200.     giodata->Error=LOAD_WRONGTYPE;
  201.  
  202. err:
  203.     return(giodata->Error);
  204. }
  205.  
  206. __asm ULONG __saveds GioWrite(register __a0 struct GIOData *giodata)
  207. {
  208. struct BMPHeader header = {0};
  209. UBYTE *peeker;
  210. int x,y,bytewid;
  211. UBYTE r,g,b;
  212.  
  213.  
  214.     if(giodata->Depth == 24)
  215.     {         // save 24-bit data here
  216.  
  217.         bytewid = giodata->Width*3;
  218.         if(bytewid & 0x3) 
  219.         {    bytewid|=0x3;    ++bytewid;    
  220.         }
  221.         header.id            = 0x424d;
  222.         header.filesize        = PCLong2Long(54 + (bytewid * giodata->Height));
  223.         header.headersize    = PCLong2Long(54);
  224.         header.infosize        = PCLong2Long(0x28L);
  225.         header.width        = PCLong2Long(giodata->Width);
  226.         header.depth        = PCLong2Long(giodata->Height);    
  227.         header.biplanes        = PCWord2Word(1);
  228.         header.bits            = PCWord2Word(24);
  229.         header.bicompression= 0;
  230.         header.bisizeimage    = PCLong2Long(bytewid*giodata->Height);
  231.  
  232.         Write(giodata->Filehandle,&header,sizeof(struct BMPHeader));
  233.  
  234.  
  235.         for(y=0;y<giodata->Height;y++)
  236.         {
  237.             if(!(y%16))
  238.             if(SetProgress(0,y*100/giodata->Height)!=1)
  239.             {
  240.                 giodata->Error = LOAD_ABORTED;
  241.                 goto err;
  242.             }
  243.  
  244.             peeker=GetLine(giodata,y);
  245.             for(x=0;x<giodata->Width;x++)
  246.             {
  247.                 r=*peeker++;
  248.                 g=*peeker++;    
  249.                 b=*peeker++;
  250.                 FPutC(giodata->Filehandle,b);
  251.                 FPutC(giodata->Filehandle,g);
  252.                 FPutC(giodata->Filehandle,r);
  253.             }
  254.             ReleaseLine(giodata,y);
  255.         }
  256.         giodata->Error = LOAD_OK;
  257.  
  258.     } else
  259.     {        // save 8-bit data here
  260.         giodata->Error = LOAD_WRONGTYPE;
  261.     }
  262.  
  263. err:
  264.     return(giodata->Error);
  265. }
  266.