;The most important chunk in a FORM ILBM is the BMHD (BitMapHeader) chunk
;which describes the size AND compression of the image:
;----------------------------------------------------------

;      'F O R M' Length  'I L B M"B M H D' <- start of BitMapHeader chunk
;0000: 464F524D 00016418 494C424D 424D4844    FORM..d.ILBMBMHD

;                                             Planes Mask
;       Length  WideHigh XorgYorg PlMkCoRe <- Compression Reserved
;0010: 00000014 01400190 00000000 06000100    .....@..........

;                                             Start of C-AMIGA
;      TranAspt PagwPagh 'C A M G' Length  <- View modes chunk
;0020: 00000A0B 01400190 43414D47 00000004    .....@..CAMG....


;      ViewMode 'C M A P' Length   R g b R <- ViewMode 800=HAM | 4=LACE
;0030: 00000804 434D4150 00000030 001000E0    ....CMAP...0....

;       g b R g  b R g b  R g b R  g b R g <- RGB's are For reg0 thru regN
;0040: E0E00000 20000050 30303050 50500030    .... ..P000PPP.0

;       b R g b  R g b R  g b R g  b R g b
;0050: 90805040 70707010 60E02060 E06080D0    ..P@ppp.`. `.`..

;       R g b R  g b R g  b R g b 'B O D Y'
;0060: A0A0A0A0 90E0C0C0 C0D0A000 424F4459    ............BODY

;                                             Compacted
;       Length   Start of body Data        <- (Compression=1 above)
;0070: 000163AC F8000F80 148A5544 2ABDEFFF    ..c.......UD*...
;0080: FFBFF800 0F7FF7FC FF04F85A 77AD5DFE    ...........Zw.].  etc.
;
;Simple CAMG ViewModes:  HIRES=0x8000  LACE=0x4  HAM=0x800  HALFBRITE=0x80
;
;- Release 2 ILBMs may contain a LONGWORD ViewPort ModeID in CAMG -
; ie, the actual ScreenMode
;

;---------------------------------------------------------------

;Curt Esser
;camge@ix.netcom.com
;Last modified Oct 21 199

;this saves a bitmap as a standard uncompressed IFF/ILBM picture file
;needs amigalibs.res

;Parameters:

;Save$        = the full pathname to save the file as

;*BMap        = a pointer to the BitMap to be saved
;               this can be a standard Blitz Bitmap
;               example:  *Bmap=Addr BitMap(0)
;               a NCS bitmap
;               or an OS bitmap

;pixelwidth.w = the actual width of the image to be saved
;               NOTE: This does NOT change the size of the
;                     saved image!  It is only for use by
;                     your viewing software, to prevent
;                     seeing a blank area on the right side
;                     if the image is not an even width

;vMode.l      = the viewmode for the picture
;               you can get this from you screen (see demo below)
;               or see above for how to create your own
;               or simply use 0 for the default Lo-Res no-lace
;               NOTE: This also does NOT affect the saved
;                     image in any way
;                     It simply tells viewing and graphics
;                     editing software the suggested screen
;                     to use for the picture

;palNum.w     = the Blitz palette number to be saved with
;               the picture
;               NOTE: this is NOT optional
;                     You can expect a crash if you don't
;                     supply a valid palette for the image!


; Returns a byte:
; 0 - can't open destination file
; 1 - picture saved successfully
; 2 - not enough space on destination volume

Function.b IFFsave{Save$,*BMap,pixelwidth.w,vMode.l,palNum.w}

*bMap.BitMap=*BMap
rowlen.l=*bMap\BytesPerRow      ;bytes per scan line
bheight.w=*bMap\Rows            ;the height
bdepth.b=*bMap\Depth            ;the depth
colours.w=2^bdepth              ;number of colours in the palette
palettelen.l=colours*3          ;length of palette data
dataLen.l=rowlen*bheight*bdepth ;total bytes of actual image data
nuttin.w=0
nobyte.b=0
headerLen.l=dataLen+60+palettelen

;now we'll check the destination volume

devend.w=0                 ;first we need just the device name
For i = 1 To Len (Save$)
  If Mid$(Save$,i,1)=":"
    devend=i
    i= Len(Save$)
  EndIf
Next

If devend
  dev$=Left$(Save$,devend)
Else
  dev$=""
EndIf

If Instr(dev$,"RAM") OR Instr(dev$,"Ram")  ;needed since the RAM: disk
  avail.l= AvailMem_ (#MEMF_PUBLIC)        ;is ALWAYS full   ;)
Else
  AnalyzeDisk dev$
  avail.l=DiskFree
EndIf

If avail<headerLen+16                      ;OK, we have enough room!
 error.b=2
Else

  Dim *bPlane(8)
  For i = 0 To 7
    *bPlane(i)=*bMap\Planes[i]  ;a pointer to each bitplane
  Next

  If WriteFile(0,Save$)         ;first we write the ILBM header
    FileOutput 0
    Print"FORM"                 ;start of IFF/ILBM header
    WriteMem 0,&headerLen,4     ;total file bytes to follow
    Print"ILBM"                 ;IFF file ID - InterLeavedBitMap image

    Print"BMHD"                 ;start of BitMapHeaDer Chunk
    bmhdLen.l=20                ;length of BMHD chunk data
    WriteMem 0,&bmhdLen,4

    WriteMem 0,&pixelwidth,2    ;pixel width of image
    WriteMem 0,&bheight,2       ;pixel height of image
    WriteMem 0,&nuttin,2        ;Xorg
    WriteMem 0,&nuttin,2        ;Yorg - both are 0 for our purposes
    WriteMem 0,&bdepth,1        ;number of bitplanes
    WriteMem 0,&nobyte,1        ;mask = 0
    WriteMem 0,&nobyte,1        ;compression = 0 (none)
    WriteMem 0,&nobyte,1        ; - reserved -
    WriteMem 0,&nuttin,2        ;transparent colour = 0
    asx.b=22
    asy.b=26
    WriteMem 0,&asx,1           ;aspect ????  I'm not sure...
    WriteMem 0,&asy,1           ;I just stole these from a pic I had
    WriteMem 0,&pixelwidth,2    ;page width
    WriteMem 0,&bheight,2       ;page height

    Print "CAMG"                ;start of CommodoreAMiGa viewmode chunk
    camg.l=4                    ;length of viewmode data
    WriteMem 0,&camg,4
    WriteMem 0,&vMode,4

    Print "CMAP"                ;start of ColourMAP chunk (the palette)
    WriteMem 0,&palettelen,4    ;length of palette data

    PaletteInfo palNum          ;now we store the palette data

    For i = 0 To colours-1      ;3 bytes per colour:
      If CheckAGA
        tempred.b=AGAPalRed(i)
        tempgrn.b=AGAPalGreen(i)
        tempblu.b=AGAPalBlue(i)
      Else
        tempred.b=PalRed(i)*17
        tempgrn.b=PalGreen(i)*17
        tempblu.b=PalBlue(i)*17
      EndIf
      WriteMem 0,&tempred,1     ;the red
      WriteMem 0,&tempgrn,1     ;green
      WriteMem 0,&tempblu,1     ;and blue values
    Next

    Print "BODY"                ;at last!  The actual image data
    WriteMem 0,&dataLen,4       ;length of data to follow

    For y = 0 To bheight-1      ;store the data as "interleaved"
                                ;row 0 from plane 0,
                                ;row 0 from plane 1, etc...
      For plane=0 To bdepth-1
        WriteMem 0,*bPlane(plane),rowlen
        *bPlane(plane)+rowlen
      Next
    Next y

    CloseFile 0                 ;we're done!
    PopOutput
    error.b=1
  Else
    error.b=0
  EndIf

EndIf

Function Return error

End Function
;----------------------------------------------------------

;demo:
;NOTE!  There is no error trapping in this demo!
;make sure your selected file really is an IFF picture!
;turn the Debugger OFF for acurate timing

;IFFsave{Save$,*BMap,pixelwidth.w,vMode.l,palNum.w}

WBStartup
FindScreen 0    ;we need a screen

MaxLen fi$=255  ;for the FileRequesters
MaxLen pa$=255

modeid.l=$8004  ;hi-res laced for the demo

;---------------------------------------------------
;if you have the NCS version of AmigaLibs.res, you can use
;these lines below to get the viewmode of any screen to save
;with the image

;*scr.Screen = Peek.l (Addr Screen(0))

;modeid.l=GetVPModeID_ (*scr\ViewPort) ;get the viewmode of the screen
;---------------------------------------------------



load$=ASLFileRequest$ ("Select IFF pic:",pa$,fi$)

If load$<>""
  ILBMInfo load$
  wd.w=ILBMWidth
  ht.w=ILBMHeight
  dp.w=ILBMDepth
  BitMap 0,wd,ht,dp
  LoadBitMap 0,load$,0  ;load the pic and it's palette
  fi$="test.iff"
  pa$="RAM:"
  save$=ASLFileRequest$("Save as:",pa$,fi$)
  If save$<>""
    ResetTimer
    *ourBmap=Addr BitMap(0)
    result.b=IFFsave{save$,*ourBmap,wd,modeid,0}
  EndIf
  Request "Save took:",Str$(Ticks)+" ticks","OK"
EndIf
End

