/*========================================================================= ILBM.HPP Author: Gary Liddon @ Watford Created: 30/03/92 Purpose: Crappy ilbm reader Copyright (c) 1992 - 1997 Gary Liddon ===========================================================================*/ /* ----------------------------------------------------------- Includes -------- */ /* Std Lib ------- */ #include <string.h> /* Glib ---- */ #include "gutils.h" /* Local ----- */ #include "ilbm.hpp" #include "iff.hpp" /* Graphics -------- */ /*---------------------------------------------------------------------- Tyepdefs && Defines ------------------- */ /*---------------------------------------------------------------------- Structure defintions -------------------- */ /*---------------------------------------------------------------------- Positional Vars --------------- */ /*---------------------------------------------------------------------- Function Prototypes ------------------- */ /*---------------------------------------------------------------------- Vars ---- */ /*---------------------------------------------------------------------- Data ---- */ /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ nilbm::nilbm(char const *name) : niff(name,ILBM) { if (err_no==NOT_FORM) { if (open(name,PBM)) { err_no=NO_ERROR; } } if (!err_no) starta(); } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ nilbm::nilbm(FILE *fp) : niff(fp,ILBM) { if (err_no==PASSED_ERR) if (mount_form(PBM)) err_no=NO_ERROR; starta(); } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ nilbm::~nilbm() { DiscardCmap(); DiscardBmap(); } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ void nilbm::starta() { cmap=NULL; Bmap=NULL; if (err_no) return; if ((!file_opened) && (!form_mounted)) return; GetBmHeadFromDisk(); if (goto_hunk(CMAP)) cmap=get_hunk(); Bmap=GetBmapFromDisk(); } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ U8 *nilbm::TakeBmap() { U8* Retp=Bmap; Bmap=NULL; return Retp; } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ U8 *nilbm::TakeCmap() { U8* Retp=cmap; cmap=NULL; return Retp; } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ void nilbm::DiscardBmap() { if (Bmap) delete Bmap; Bmap=NULL; } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ void nilbm::DiscardCmap() { if (cmap) delete cmap; cmap=NULL; } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ void nilbm::GetBmHeadFromDisk() { if (goto_hunk(BMHD)) { GetIntelLong(); GetIntelLong(); w=GetIntelWord(); h=GetIntelWord(); GetIntelWord(); GetIntelWord(); planes=fgetc(fp); fgetc(fp); comp=fgetc(fp); rh = h; } } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ U8 *nilbm::GetBmapFromDisk() { U8 *buffa=NULL; U8 *Ptr; if (file_opened) { if (goto_hunk(BODY)) { long temp; fread(&temp,1,sizeof(ULONG),fp); fread(&temp,1,sizeof(ULONG),fp); if (!(buffa=new U8[w*h])) Error(ERR_FATAL,"Allocating ILBM body (%ld)",(long)w*(long)h); U8 *line_buffer; int NormWidth=((w+7)&(0xfff8)); int bwidth=NormWidth/8; if (!(line_buffer=new U8[NormWidth*4])) //MA increased for safety incase of bad encoding return NULL; else { int z,dest; // Init source count for (int line=0;line<(h);line++) { dest=0; // Destination count memset(line_buffer,0,NormWidth); // Clear out buffer if (form_name==PBM) { if (comp) { dest=0; while (dest < w) { s8 val = fgetc(fp); if (val<0) { val=(0-val)+1; U8 ch=fgetc(fp); while (val--) { line_buffer[dest]=ch; dest++; } } else if (val>=0) { val++; while (val--) { line_buffer[dest]=fgetc(fp); dest++; } } } } else { int WidthToRead = GU_AlignVal(w, 2); fread(line_buffer,WidthToRead,1,fp); } } else { for (int p=0;p<planes;p++) { dest=0; if (comp) { while (dest < bwidth) { S8 val = fgetc(fp); Ptr=&line_buffer[dest*8]; if (val<0) { val=(0-val)+1; U8 ch=fgetc(fp); while (val--) { for (z=7;z>=0;z--) *Ptr++ |= ((ch>>(z))&1)<<p; dest++; } } else if (val>=0) { val++; while (val--) { U8 ch=fgetc(fp); for (z=7;z>=0;z--) *Ptr++ |= ((ch>>(z))&1)<<p; dest++; } } } } else { for (int x=0;x<bwidth;x++) { Ptr=&line_buffer[dest*8]; U8 ch=fgetc(fp); for (z=7;z>=0;z--) *Ptr++ |= ((ch>>(z))&1)<<p; dest++; } } } } memcpy(&buffa[line*w],line_buffer,w); } } delete line_buffer; } } return buffa; } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ void nilbm::SavePbm(char *Name,U8 *Palette,U8 *Body,int W,int H) { if (Palette && Body) { IFF_FILE outfile; if (outfile.write(Name) != 0) { int i, j; outfile.form("PBM "); outfile.chunk("BMHD"); outfile.writeword(W); outfile.writeword(H); outfile.writeword(0); // xpos outfile.writeword(0); // ypos outfile.writechar(8); // num-planes outfile.writechar(mskNone); // masking outfile.writechar(cmpNone); // compression outfile.writechar(0); // Pad byte outfile.writeword(0); // Transparent colour outfile.writechar(1); // xAspect outfile.writechar(1); // yAspect outfile.writeword(320); outfile.writeword(200); outfile.endchunk(); if (256) { outfile.chunk("CMAP"); for (i = 0; i < 3*256; i++) outfile.writechar(Palette[i]); outfile.endchunk(); } U8 *ptr; outfile.chunk("BODY"); for (i = 0; i < H; i++) { // Save out a planar scanline ptr = &Body[(long) i * (long) W]; j = W; while (j--) outfile.writechar(*ptr++); if (W&1) { int l = W&1; for (int k=0; k<l; k++) outfile.writechar(0xfe); } } outfile.endchunk(); outfile.endform(); outfile.close(); } else Error(ERR_FATAL,"Error trying to write %s",Name); } else Error(ERR_FATAL,"Image not defined so can't write %s",Name); } /*=========================================================================== end */