home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD1.iso / GFX / Converter / PHOGEN3.DMS / in.adf / DevDocs.lha / examples / bmp / bmp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-30  |  7.5 KB  |  332 lines

  1. /* 
  2. FILE:            bmp.c
  3. MODULE:            bmp.gio
  4. PROJECT:        photogenics
  5. AUTHOR:            Jolyon Ralph
  6. DATE:            30/3/95
  7. COMMENT:        Example .BMP loader
  8. COPYRIGHT:        © Almathera 1994-5 All Rights Reserved
  9. */
  10.  
  11. #include <exec/types.h>
  12. #include <clib/exec_protos.h>
  13. #include <clib/dos_protos.h>
  14. #include <clib/pgs_protos.h>
  15. #include <dos/dos.h>
  16. #include <pragmas/exec_pragmas.h>
  17. #include <pragmas/dos_pragmas.h>
  18. #include <pragmas/pgs_pragmas.h>
  19. #include <photogenics/gio.h>
  20.  
  21.  
  22. /* first we'll define a structure we need later */
  23.  
  24. struct BMPHeader 
  25. {
  26.     UWORD        id;
  27.     PCLONG    filesize;   // PCLONG is defined in gio.h as == ULONG
  28.     PCWORD    reserved[2];// PCWORD is defined in gio.h as == UWORD
  29.     PCLONG    headersize;
  30.     PCLONG    infosize;
  31.     PCLONG    width;
  32.     PCLONG    depth;
  33.     PCWORD    biplanes;
  34.     PCWORD    bits;
  35.     PCLONG    bicompression;
  36.     PCLONG    bisizeimage;
  37.     PCLONG    bixpelspermeter;
  38.     PCLONG    biyperlpermeter;
  39.     PCLONG    biclrused;
  40.     PCLONG    biclrimportant;
  41. };
  42.  
  43. struct BMPPalEntry 
  44. {
  45.     UBYTE blu;
  46.      UBYTE grn;
  47.     UBYTE    red;
  48.     UBYTE    pad;
  49.  
  50. };
  51.  
  52. /* some macros to swap between Intel and Motorola byte order */
  53.  
  54. #define PCLong2Long(val) ((((val&0xff)<<24)|((val&0xff00)<<8)|
  55.                          ((val&0xff0000)>>8)|((val&0xff000000)>>24)))
  56.  
  57. #define PCWord2Word(val) ((((val&0xff)<<8)|((val&0xff00)>>8)))
  58.  
  59. __asm ULONG GioInfo(void)
  60. {
  61. /* This function returns flags to determine the features of this .GIO 
  62.  
  63.     GIOF_LOADER8        - Because it can load 8-bit (or less) data
  64.     GIOF_LOADER24        - Because it can load 24-bit data
  65.     GIOF_LOADFILE        - Because it reads data from a file
  66.     GIOF_SAVER24        - Because it can save 24-bit data
  67.     GIOF_SAVEFILE        - Because it writes data to a file
  68.     GIOF_EXTENDED        - This is a V1.2 format .GIO
  69. */
  70.     return(GIOF_LOADER8|GIOF_LOADER24|GIOF_LOADFILE|GIOF_SAVER24|GIOF_SAVEFILE|GIOF_EXTENDED);
  71. }
  72.  
  73. __asm ULONG GioExamine(register __a0 struct GIOData *giodata)
  74. {
  75. struct BMPHeader *bmphead;
  76.  
  77. // first we set up flags. Always do this first in GioExamine()
  78.     giodata->Flags = GioInfo();
  79.  
  80. /* 
  81. When we are called (and GIOF_LOADFILE is set in GioInfo())
  82. we are passed the first 64-bytes of the file in giodata->Data.
  83. This is sufficient for most loaders to identify the filetype
  84.  
  85. Let's reference the data as a BMPHeader structure... */
  86.  
  87.     bmphead = (struct BMPHeader *) giodata->Data;
  88.  
  89.  
  90.     if(bmphead->id!=(0x424d))
  91.     {
  92. // it's NOT a .BMP file, let's get out of here!
  93.         giodata->Error = LOAD_WRONGTYPE;
  94.         goto err;
  95.     }
  96.  
  97.  
  98.  
  99. // it IS a .BMP file, let's find out some details... 
  100.  
  101.     giodata->Width             = PCLong2Long(bmphead->width);
  102.     giodata->Height             = PCLong2Long(bmphead->depth);
  103.     giodata->Depth             = PCWord2Word(bmphead->bits);
  104.     giodata->Headerlength     = PCLong2Long(bmphead->headersize);
  105.     giodata->Error = LOAD_OK;  // This means we're all ok to continue.
  106. err:
  107.     return(giodata->Error);
  108.  
  109. }
  110.  
  111. /* giodata contains pointers to several open libraries.
  112. You can reference them simply by using these #defines, you
  113. do not need to open them!
  114.  
  115. Others included are GfxBase, IntuitionBase, AslBase, GadToolsBase,
  116. etc. See the definition of the giodata structure for a full list
  117. (photogenics.h)
  118.  
  119. */
  120.  
  121. #define DOSBase giodata->DOSBase
  122. #define PgsBase giodata->PgsBase
  123.  
  124. __asm ULONG GioRead(register __a0 struct GIOData *giodata)
  125. {
  126. int x,y,r;
  127. UBYTE *bytes,*pal;
  128. ULONG rdsize;
  129. struct BMPPalEntry palentry;
  130.  
  131. // First set the text for the progress bar...
  132.  
  133.     SetProgress("Loading Windows BMP file",0);
  134.  
  135. // Was our source file a 24-bit .BMP file?
  136.     if(giodata->Depth == 24)
  137.     {    
  138.  
  139. // Seek to the right place in the file *IMPORTANT!*
  140.  
  141.         Seek(giodata->Filehandle,giodata->Headerlength+giodata->SkipBytes,
  142.                 OFFSET_BEGINNING);
  143.  
  144.         for(y=giodata->Height-1;y>=0;y--)
  145.         {
  146.             if(!(y%16)) // don't slow down by calling SetProgress too often
  147.             {
  148.                 if(SetProgress(0,100-(y*100/giodata->Height))!=1)
  149.                 {
  150.                     giodata->Error = LOAD_ABORTED;
  151.                     goto err;
  152.                 }
  153.             }
  154.  
  155. //    Get the address of line y of the image data...
  156.  
  157.             bytes=GetLine(giodata,y);
  158.  
  159. // And read the data straight in....
  160.  
  161.             Read(giodata->Filehandle,bytes,giodata->Width*3);
  162.  
  163. // Windows byte order is BGR, we need RGB, so swap them round!
  164.  
  165.             for(x=0;x<giodata->Width;x++)
  166.             { 
  167.                     r=*bytes;
  168.                     *bytes=*(bytes+2);
  169.                     *(bytes+2)=r;
  170.                     bytes+=3;
  171.             }
  172.  
  173. // And we've finished with the memory, so release the line.
  174.             ReleaseLine(giodata,y);
  175.         }
  176.  
  177. // All AOK, get out of here...
  178.         giodata->Error = LOAD_OK;
  179.  
  180.     } else
  181.     {
  182. // Same as before, except first we load a palette...
  183.  
  184.         Seek(giodata->Filehandle,0x36+giodata->SkipBytes,OFFSET_BEGINNING);        
  185.         if(!(pal = giodata->Palette)) 
  186.         {
  187.             giodata->Error=LOAD_WRONGTYPE;
  188.             goto err;
  189.         }
  190.         for(x=0;x<(1<<(giodata->Depth));x++)
  191.         {    
  192.             Read(giodata->Filehandle,&palentry,4);
  193.             *pal++=palentry.red;
  194.             *pal++=palentry.grn;
  195.             *pal++=palentry.blu;
  196.         }
  197.         Seek(giodata->Filehandle,giodata->Headerlength+giodata->SkipBytes,
  198.            OFFSET_BEGINNING);
  199.         switch(giodata->Depth) 
  200.         {
  201.  
  202. // decide how many bytes to read in at a time
  203.  
  204.             case 1:
  205.             rdsize=giodata->Width/8;
  206.             break;
  207.  
  208.             case 4:
  209.             rdsize=giodata->Width/2;
  210.             break;
  211.  
  212.             case 8:
  213.             rdsize=giodata->Width;
  214.             break;
  215.  
  216.             default:
  217.             giodata->Error = LOAD_WRONGTYPE;
  218.             goto err;
  219.         }
  220.         if(rdsize & 0x0003) {rdsize |= 0x0003;rdsize++;}
  221.  
  222.         for(y=giodata->Height-1;y>=0;y--)
  223.         {
  224.             if(!(y%16))
  225.             if(SetProgress(0,100-(y*100/giodata->Height))!=1)
  226.             {
  227.                 giodata->Error = LOAD_ABORTED;
  228.                 goto err;
  229.             }
  230.             bytes = GetLine(giodata,y);
  231.             Read(giodata->Filehandle,bytes,rdsize);
  232.             ReleaseLine(giodata,y);
  233.         }
  234.  
  235.         giodata->Error = LOAD_OK;
  236.  
  237. /* See how simple that was? We didn't have to convert to 24-bit
  238. data at all. All we did was set up the palette, tell Photogenics
  239. how deep the image is, and load the data. If we were loading
  240. planar image data, we'd set the GIOF_PLANAR flag in the 
  241. GioInfo() function, and Photogenics would convert the planar
  242. data (1 to 8 bit or 24-bit) into 24-bit.
  243.  
  244. If you have a bizare format (eg 16-bit hicolour) or if the
  245. bytes are ordered wrong (as in 24-bit BMP above.) then you
  246. will have to do the 24-bit conversion yourself.
  247.  
  248. */
  249.  
  250.     }
  251.  
  252. err:
  253.     return(giodata->Error);
  254. }
  255.  
  256. __asm ULONG GioWrite(register __a0 struct GIOData *giodata)
  257. {
  258. struct BMPHeader header = {0};
  259. UBYTE *peeker;
  260. int x,y,bytewid;
  261. UBYTE r,g,b;
  262.  
  263. /* first make sure it's 24-bit data - it always is at the moment! */
  264.     if(giodata->Depth!=24)
  265.     {
  266.         giodata->Error = LOAD_WRONGTYPE;        // we use LOAD_ for all errors!
  267.         goto err;
  268.     }
  269.  
  270.     SetProgress("Saving Windows BMP file...",0);
  271.  
  272.     bytewid = giodata->Width*3;
  273.     if(bytewid & 0x3) 
  274.     {
  275.         bytewid|=0x3;
  276.         ++bytewid;
  277.     }
  278.     header.id                = 0x424d;
  279.     header.filesize        = PCLong2Long(54 + (bytewid * giodata->Height));
  280.     header.headersize        = PCLong2Long(54);
  281.     header.infosize        = PCLong2Long(0x28L);
  282.     header.width            = PCLong2Long(giodata->Width);
  283.     header.depth            = PCLong2Long(giodata->Height);    
  284.     header.biplanes        = PCWord2Word(1);
  285.     header.bits                = PCWord2Word(24);
  286.     header.bicompression    = 0;
  287.     header.bisizeimage    = PCLong2Long(bytewid*giodata->Height);
  288.  
  289.     Write(giodata->Filehandle,&header,sizeof(struct BMPHeader));
  290.  
  291.     for(y=giodata->Height-1;y>=0;y--)
  292.     {
  293.         if(!(y%16))
  294.         if(SetProgress(0,100-(y*100/giodata->Height))!=1)
  295.         {
  296.             giodata->Error = LOAD_ABORTED;
  297.             goto err;
  298.         }
  299.  
  300.         peeker=GetLine(giodata,y);
  301.         for(x=0;x<giodata->Width;x++)
  302.         {
  303.             r=*peeker++;
  304.             g=*peeker++;    
  305.             b=*peeker++;
  306.             FPutC(giodata->Filehandle,b);
  307.             FPutC(giodata->Filehandle,g);
  308.             FPutC(giodata->Filehandle,r);
  309.         }
  310.         ReleaseLine(giodata,y);
  311.     }
  312.     giodata->Error = LOAD_OK;
  313.  
  314. err:
  315.     return(giodata->Error);
  316. }
  317.  
  318. __asm void GioCleanUp(register __a0 struct GIOData *giodata)
  319. {
  320. /* as of V1.2 this function is not used */
  321. }
  322.  
  323. __asm void GioLoadPrefs(register __a0 struct GIOData *giodata)
  324. {
  325. /* Preferences for load (none needed for .BMP) */
  326. }
  327.  
  328. __asm void GioSavePrefs(register __a0 struct GIOData *giodata)
  329. {
  330. /* Preferences for save (none needed for .BMP) */
  331. }
  332.