home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD1.iso / GFX / Converter / DC-PGS21.DMS / in.adf / Extras / DevDocs.LHA / DeveloperDocs / examples / gio / bmp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-03  |  7.4 KB  |  330 lines

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