/* * loadpic.c - ILBM loader which runs from the workbench * * Written by Jonathan Hue - if you decide to steal some of this * code (yeah, like anyone would want to), give me credit. */ #include #include #include #include #include #include #include #include #include #include "types.h" #include "ilbm.h" extern struct WBStartup *WBenchMsg; void LoadPic(), ChkRead(), ErrExit(), cleanup(), ReadPic(); int WaitForMouseClick(); struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; extern struct ColorMap *GetColorMap(); extern struct FileLock *Lock(), *CurrentDir(); extern struct Window *OpenWindow(); struct View v; struct ViewPort vp; struct ColorMap *cm; struct BitMap b; BitMapHeader bm; short WinWidth, WinHeight; /* Trust me, you don't want to know what */ struct Preferences prefs; /* I want these for... */ main(argc, argv) int argc; char **argv; { struct WBArg *arg; struct FileLock *lock, *olddir; register int i; if ((GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0)) == NULL) ErrExit("Couldn't open graphics library"); if ((IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 0)) == NULL) ErrExit("Couldn't open graphics library"); WinWidth = GfxBase->NormalDisplayColumns; WinHeight = GfxBase->NormalDisplayRows; GetPrefs(&prefs, sizeof(prefs)); puts("Press Left Mouse Button to Exit"); fflush(stdout); /* stdout should be line buffered */ if (argc > 0) { while (--argc) LoadPic(*++argv); } else { for (i = 1, arg = WBenchMsg->sm_ArgList; i < WBenchMsg->sm_NumArgs; i++) { ++arg; if (arg->wa_Lock == NULL) continue; olddir = CurrentDir(arg->wa_Lock); if ((lock = Lock(arg->wa_Name, SHARED_LOCK)) == NULL) { CurrentDir(olddir); continue; } LoadPic(arg->wa_Name); UnLock(lock); CurrentDir(olddir); } } cleanup(); } void LoadPic(PicName) char *PicName; { register FILE *fp; u_long form, ilbm, id, nbytes, ViewMode = 0; register short i; register u_short *ColorMapPtr, ColorValue; short GotBody = 0, GotHdr = 0, plane; struct View *oldview; struct RasInfo ri; if ((fp = fopen(PicName, "r")) == NULL) { fprintf(stderr, "Couldn't open %s\n", PicName); return; } ChkRead(fp, &form, sizeof(form)); fseek(fp, 4L, 1); ChkRead(fp, &ilbm, sizeof(ilbm)); if ((form != ID_FORM) || (ilbm != ID_ILBM)) ErrExit("Sorry, I can't read this file"); while (1) { ChkRead(fp, &id, sizeof(id)); ChkRead(fp, &nbytes, sizeof(nbytes)); switch(id) { case ID_BMHD: GotHdr++; if (nbytes != sizeof(bm)) ErrExit("Short header length"); ChkRead(fp, &bm, sizeof(bm)); break; case ID_CMAP: cm = GetColorMap(nbytes / 3); ColorMapPtr = (u_short *) cm->ColorTable; for (i = 0; i < nbytes / 3; i++) { ColorValue = (getc(fp) >> 4) << 8; ColorValue |= (getc(fp) >> 4) << 4; ColorValue |= (getc(fp) >> 4); *ColorMapPtr++ = ColorValue; } if (nbytes & 1) getc(fp); break; case ID_CAMG: ChkRead(fp, &ViewMode, sizeof(ViewMode)); break; case ID_BODY: if (!GotHdr) ErrExit("Found BODY before BMHD!!!"); GotBody = 1; break; case ID_GRAB: case ID_DEST: default: fseek(fp, nbytes, 1); break; } if (GotBody) break; } oldview = GfxBase->ActiView; InitView(&v); InitVPort(&vp); v.ViewPort = &vp; InitBitMap(&b, bm.bm_numplanes, bm.bm_width, bm.bm_height); ri.BitMap = &b; ri.RxOffset = 0; ri.RyOffset = 0; vp.DWidth = bm.bm_width; vp.DHeight = bm.bm_height; vp.RasInfo = &ri; vp.ColorMap = cm; for (plane = 0; plane < bm.bm_numplanes; plane++) if ((b.Planes[plane] = (PLANEPTR) AllocRaster(bm.bm_width, bm.bm_height)) == NULL) ErrExit("Couldn't allocate enough screen memory"); if (bm.bm_width > 384) /* should be set */ ViewMode |= HIRES; if (bm.bm_height > 240) ViewMode |= LACE; if (ViewMode & LACE) v.Modes |= LACE; vp.Modes = ViewMode; if (ViewMode & HIRES) /* center */ vp.DxOffset = (640 - bm.bm_width) / 2; else vp.DxOffset = (320 - bm.bm_width) / 2; if (ViewMode & LACE) vp.DyOffset = ((2 * WinHeight) - bm.bm_height) / 2; else vp.DyOffset = ((2 * WinHeight) - bm.bm_height) / 2; MakeVPort(&v, &vp); MrgCop(&v); ReadPic(fp, &bm, &b); LoadView(&v); WaitForMouseClick(); LoadView(oldview); for (i = 0; i < bm.bm_numplanes; i++) { FreeRaster(b.Planes[i], bm.bm_width, bm.bm_height); b.Planes[i] = NULL; } FreeColorMap(cm); cm = NULL; FreeVPortCopLists(&vp); FreeCprList(v.LOFCprList); FreeCprList(v.SHFCprList); } void ReadPic(fp, bmhdr, bm) register FILE *fp; register BitMapHeader *bmhdr; register struct BitMap *bm; { register u_char Pixel, *PixelPtr; register short plane, row, nbytes, count; if (bmhdr->bm_compression == 1) { for (row = 0; row < bmhdr->bm_height; row++) { for (plane = 0; plane < bmhdr->bm_numplanes; plane++) { PixelPtr = bm->Planes[plane] + (row * bm->BytesPerRow); nbytes = bm->BytesPerRow; while (nbytes > 0) { count = (char) getc(fp); /* might be negative */ if (count >= 0) /* copy n+1 literal */ { count++; nbytes -= count; while (count--) *PixelPtr++ = getc(fp); } else if (count >= -127) /* repeat next -n+1 times */ { count = 1 - count; nbytes -= count; Pixel = getc(fp); while (count--) *PixelPtr++ = Pixel; } } } } } else { for (row = 0; row < bmhdr->bm_height; row++) for (plane = 0; plane < bmhdr->bm_numplanes; plane++) ChkRead(fp, bm->Planes[plane] + (row * bm->BytesPerRow), bm->BytesPerRow); } } void ChkRead(fp, buf, nbytes) FILE *fp; char *buf; int nbytes; { if (fread(buf, nbytes, 1, fp) != 1) ErrExit("Short read"); } void ErrExit(s) char *s; { char b[10]; fprintf(stderr, "%s\nPress RETURN", s); gets(b); cleanup(); exit(10); } int WaitForMouseClick() { static struct NewWindow CheeseWhiz = { 0, 0, /* position in upper left */ 0, 0, /* don't init yet */ -1, -1, /* default pens */ MOUSEBUTTONS, BORDERLESS | ACTIVATE, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN }; struct IntuiMessage *message; struct Window *win; CheeseWhiz.Width = WinWidth; CheeseWhiz.Height = WinHeight; if (prefs.LaceWB) CheeseWhiz.Height += WinHeight; if ((win = OpenWindow(&CheeseWhiz)) == NULL) return(-1); Wait(1 << win->UserPort->mp_SigBit); message = (struct IntuiMessage *) GetMsg(win->UserPort); ReplyMsg(message); CloseWindow(win); return(0); } void cleanup() { register short i; if (cm) /* forget about the other bits */ FreeColorMap(cm); for (i = 0; i < bm.bm_numplanes; i++) { if (b.Planes[i]) FreeRaster(b.Planes[i], bm.bm_width, bm.bm_height); } CloseLibrary(GfxBase); CloseLibrary(IntuitionBase); fclose(stdin); fclose(stdout); fclose(stderr); rbrk(); }