/* ReadDCTV by Garrick Meeker */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include char *vers = "\0$VER: ReadDCTV 1.0"; char *Copyright = "ReadDCTV v1.0 by Garrick Meeker"; char *usage = "Usage: ReadDCTV dctvfile iff24file"; char *write_err = "Error writing file"; LONG Convert(void); struct IFFHandle *OpenOutfile(void); BOOL WriteRGB(struct IFFHandle *iff24, struct DCTVCvtHandle *cvt); BOOL WriteChunkyLine(struct IFFHandle *iff,UBYTE *chunks,int width); void ConvertPlane(UBYTE planemask, UBYTE *line, int width); void CloseOutfile(struct IFFHandle *iff24); void bye(UBYTE *s, int e); void cleanup(void); struct Library *DCTVBase = NULL; struct Library *GfxBase = NULL; struct Library *IFFParseBase = NULL; struct ILBMInfo ilbm = {0}; LONG error=NULL; UBYTE *infile=NULL; UBYTE *outfile=NULL; UWORD *plane=NULL; BYTE *compressed=NULL; LONG ilbmprops[] = { ID_ILBM, ID_BMHD, ID_ILBM, ID_CMAP, ID_ILBM, ID_CAMG, TAG_DONE }; LONG ilbmstops[] = { ID_ILBM, ID_BODY, TAG_DONE }; void main(int argc, char **argv) { if((argc<3)||(argv[argc-1][0]=='?')) { printf("%s\n%s\n",Copyright,usage); bye("",RETURN_OK); } infile = argv[1]; outfile = argv[2]; if(!(GfxBase = OpenLibrary("graphics.library", 0))) bye("Unable to open graphics.library.\n",RETURN_WARN); if(!(IFFParseBase = OpenLibrary("iffparse.library",0))) bye("Unable to open iffparse.library.\n",RETURN_WARN); if(!(DCTVBase = OpenLibrary("dctv.library",3))) bye("Unable to open dctv.library v3.\n",RETURN_WARN); /* Load image */ ilbm.ParseInfo.propchks = ilbmprops; ilbm.ParseInfo.stopchks = ilbmstops; if(!(ilbm.ParseInfo.iff = AllocIFF())) bye(IFFerr(IFFERR_NOMEM),RETURN_FAIL); if (error = loadbrush(&ilbm,infile)) { printf("Unable to load ilbm \"%s\", ifferr=%s\n",infile,IFFerr(error)); bye("",RETURN_WARN); } error=Convert(); unloadbrush(&ilbm); bye("",error); } /* Convert to 24 bit */ LONG Convert() { struct IFFHandle *iff24 = NULL; struct DCTVCvtHandle *cvt = NULL; if(!(TestDCTVSignature(ilbm.brbitmap))) { puts("This is not a DCTV picture."); return RETURN_WARN; } if (!(cvt = AllocDCTVCvtTags( ilbm.brbitmap, DCTVCVTA_Type, (ULONG)DCTVCVTT_DCTVtoRGB, DCTVCVTA_Width, (ULONG)((ilbm.brbitmap->BytesPerRow)<<3), DCTVCVTA_Height, (ULONG)ilbm.brbitmap->Rows, DCTVCVTA_Flags, (ULONG)((ilbm.camg & LACE) ? DCTVCVTF_Lace : 0), DCTVCVTA_ColorTable, ilbm.colortable, DCTVCVTA_ErrorCode, &error, TAG_END))) { printf("DCTV conversion failed %lu\n",error); error=RETURN_WARN; goto abortconvert; } if (!(plane=(AllocMem(ilbm.brbitmap->BytesPerRow,MEMF_ANY)))) { puts("Out of memory."); error=RETURN_WARN; goto abortconvert; } if (!(compressed=(AllocMem(MaxPackedSize(ilbm.brbitmap->BytesPerRow),MEMF_ANY)))) { puts("Out of memory."); error=RETURN_WARN; goto abortconvert; } if (!(iff24=OpenOutfile())) { puts("Unable to open output file."); error=RETURN_FAIL; goto abortconvert; } while (cvt->DstLineNum < cvt->Height) { /* Break on Ctrl-C */ if (SetSignal(0,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) return RETURN_WARN; CvtDCTVLine(cvt); if(cvt->DstLineNum>0) if(!(WriteRGB(iff24,cvt))) { printf("%s\n",write_err); error=RETURN_FAIL; goto abortconvert; } } if(PopChunk(iff24)) { /* Close BODY chunk */ printf("%s\n",write_err); error=RETURN_FAIL; goto abortconvert; } if(PopChunk(iff24)) { /* Close FORM */ printf("%s\n",write_err); error=RETURN_FAIL; goto abortconvert; } error = RETURN_OK; abortconvert: if(compressed) FreeMem(compressed,MaxPackedSize(ilbm.brbitmap->BytesPerRow)); if(plane) FreeMem(plane,ilbm.brbitmap->BytesPerRow); if(cvt) FreeDCTVCvt(cvt); CloseOutfile(iff24); return error; } /* Open 24-bit IFF */ struct IFFHandle *OpenOutfile() { struct IFFHandle *iff=NULL; BitMapHeader bmhd; if (!(iff = AllocIFF())) return NULL; if (!(iff->iff_Stream=Open(outfile,MODE_NEWFILE))) goto abortopen; InitIFFasDOS(iff); if (OpenIFF(iff,IFFF_WRITE)) goto abortopen; /* Write header */ if (PushChunk(iff,ID_ILBM,ID_FORM,IFFSIZE_UNKNOWN)) goto abortopen; /* Write BMHD */ if (PushChunk(iff,ID_ILBM,ID_BMHD,sizeof(BitMapHeader))) goto abortopen; /* Set BMHD values */ CopyMem(&ilbm.Bmhd,&bmhd,sizeof(bmhd)); bmhd.nPlanes=24; bmhd.masking=mskNone; bmhd.compression=cmpByteRun1; bmhd.reserved1=0; if (WriteChunkBytes(iff,&bmhd,sizeof(bmhd)) != sizeof(bmhd)) goto abortopen; if (PopChunk(iff)) goto abortopen; /* Write BODY header */ if (PushChunk(iff,ID_ILBM,ID_BODY,IFFSIZE_UNKNOWN)) goto abortopen; return iff; abortopen: CloseOutfile(iff); return NULL; } void CloseOutfile(struct IFFHandle *iff) { if(iff) { CloseIFF(iff); if (iff->iff_Stream) Close(iff->iff_Stream); FreeIFF(iff); } } BOOL WriteRGB(struct IFFHandle *iff, struct DCTVCvtHandle *cvt) { if (!(WriteChunkyLine(iff,cvt->Red,cvt->Width)!=cvt->Width)) return FALSE; if (!(WriteChunkyLine(iff,cvt->Green,cvt->Width)!=cvt->Width)) return FALSE; if (!(WriteChunkyLine(iff,cvt->Blue,cvt->Width)!=cvt->Width)) return FALSE; return TRUE; } /* Write one line of a primary color */ BOOL WriteChunkyLine(struct IFFHandle *iff,UBYTE *chunks,int width) { UBYTE i; LONG length; /* Pointers are incremented by packrow() so we use a copy */ BYTE *temp_plane; BYTE *temp_comp; /* Ends when i overflows */ for (i=1; i!=0; i+=i) { temp_plane=(BYTE *)plane; temp_comp=compressed; ConvertPlane(i, chunks, width); length=packrow(&temp_plane,&temp_comp,(LONG)ilbm.brbitmap->BytesPerRow); if (WriteChunkBytes(iff,compressed,length)!=length) return FALSE; } return TRUE; } void ConvertPlane(UBYTE planemask, UBYTE *line, int width) { int i,j,end; UWORD currbit; for (i=0,j=0; i>1) { if (line[i]&planemask) plane[j] |= currbit; } } } void bye(UBYTE *s, int e) { if(s&&(*s)) printf("%s\n",s); cleanup(); exit(e); } void cleanup() { if(ilbm.ParseInfo.iff) FreeIFF(ilbm.ParseInfo.iff); if(IFFParseBase) CloseLibrary(IFFParseBase); if(GfxBase) CloseLibrary(GfxBase); if(DCTVBase) CloseLibrary(DCTVBase); }