/* This file is part of TIFFViewer Copyright (C) 2002-4 Toby Thain, toby@telegraphics.com.au This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "tiffviewer.h" #include "misc.h" #include "scroll.h" extern CTabHandle ctabs[]; void setuppage(WindowRef w,wdata *wd){ if( TIFFSetDirectory(wd->tif,wd->curdir) ){ TIFFGetField(wd->tif,TIFFTAG_IMAGEWIDTH,&wd->width); TIFFGetField(wd->tif,TIFFTAG_IMAGELENGTH,&wd->height); TIFFGetField(wd->tif,TIFFTAG_BITSPERSAMPLE,&wd->bitspersample); TIFFGetField(wd->tif,TIFFTAG_SAMPLESPERPIXEL,&wd->samplesperpixel); TIFFGetField(wd->tif,TIFFTAG_ROWSPERSTRIP,&wd->rowsperstrip); TIFFGetField(wd->tif,TIFFTAG_XRESOLUTION,&wd->xres); TIFFGetField(wd->tif,TIFFTAG_YRESOLUTION,&wd->yres); /* sprintf(s,"[%3d] w=%4d,h=%4d,bps=%d,spp=%d,rps=%d,xres=%g,yres=%g", wd->curdir,wd->width,wd->height,wd->bitspersample, wd->samplesperpixel,wd->rowsperstrip,wd->xres,wd->yres); dbg(s); */ }else bad("TIFFSetDirectory failed"); } void draw(PixMapHandle pm,wdata *wd){ tdata_t buf; tstrip_t strip,curstrip; tsize_t tresult; int i,j,aa,nstrips,outrb,rowinstrip,tifrb,scaledw; int *byteindex,*bitmask,*pixelstep; float row,bit,hstep,vstep; char *baseaddr,*outrow,*inrow; Pattern pat; Rect r; GetQDGlobalsLightGray(&pat); EraseRect(&wd->bounds); if(wd->bitspersample == 1 && wd->samplesperpixel == 1 && TIFFSetDirectory(wd->tif,wd->curdir) ){ baseaddr = GetPixBaseAddr(pm); outrb = GetPixRowBytes(pm); tifrb = (wd->width*wd->bitspersample+7)/8; nstrips = TIFFNumberOfStrips(wd->tif); //sprintf(s,"strips=%d tifrb=%d",nstrips,tifrb); dbg(s); scaledw = wd->aalevel*(wd->bounds.right-wd->bounds.left); vstep = wd->yscale/wd->aalevel; hstep = wd->xscale/wd->aalevel; //aainc = 255/(wd->aalevel*wd->aalevel); byteindex = malloc(sizeof(int)*scaledw); bitmask = malloc(sizeof(int)*scaledw); pixelstep = malloc(sizeof(int)*scaledw); // precompute everything for inner loop for( i=0,bit=0. ; i> ((int)bit%8); pixelstep[i] = i/wd->aalevel; } if(buf = _TIFFmalloc(TIFFStripSize(wd->tif))){ curstrip = -1; row = 0.; for( j=wd->bounds.top,outrow=baseaddr ; jbounds.bottom ; ++j,outrow+=outrb ){ for(aa=wd->aalevel;aa--;){ strip = (int)row / wd->rowsperstrip; rowinstrip = (int)row % wd->rowsperstrip; if(strip != curstrip){ curstrip = strip; //sprintf(s,"reading next strip (%d) @ j=%d row=%g rowinstrip=%d",strip,j,row,rowinstrip); dbg(s); tresult = TIFFReadEncodedStrip(wd->tif,strip,buf,(tsize_t) -1); } if(tresult != -1){ inrow = (char*)buf + rowinstrip*tifrb; for(i=0;ibounds.right,j+1); FillRect(&r,&pat); } row += vstep; } } _TIFFfree(buf); }else bad("Couldn't get memory for image strip."); free(byteindex); free(bitmask); free(pixelstep); }else{ MoveTo(10,50); DrawString("\pOnly 1 bit/pixel supported"); } } void resizewindow(WindowRef w,wdata *wd){ Rect r,rcont,rstruct; BitMap screen; global_wind_rect(w,&rcont); get_struc_bbox(w,&rstruct); GetQDGlobalsScreenBits(&screen); r = screen.bounds; r.left += 2+(rcont.left-rstruct.left); r.top += 2+GetMBarHeight()+(rcont.top-rstruct.top); r.right -= 2+(rstruct.right-rcont.right); r.bottom -= 2+(rstruct.bottom-rcont.bottom); wd->yscale = (float)wd->height / (wd->zoom*(r.bottom - r.top - (SCROLL_BAR_WIDTH-1))); wd->xscale = wd->yscale*(wd->xres/wd->yres); SetRect(&wd->bounds,0,0,wd->width/wd->xscale,wd->height/wd->yscale); r.right = min(r.right,r.left + natural_size(w).h); r.bottom = min(r.bottom,r.top + natural_size(w).v); SetWindowStandardState(w,&r); SetWindowUserState(w,&r); //SetWindowIdealUserState(w,&r); //idealsize = natural_size(w); //ZoomWindowIdeal(w,inZoomOut,&idealsize); MacMoveWindow(w,r.left,r.top,false); SizeWindow(w,r.right-r.left,r.bottom-r.top,true); adjust_scrollers(w,wd->bounds.right,wd->bounds.bottom,wd->hscroll,wd->vscroll); } void redrawwindow(WindowRef w,wdata *wd){ PixMapHandle pm; CGrafPtr gp; GDHandle gd; Rect r; SetCursor(*watch); GetGWorld(&gp,&gd); if(gwFlagErr & UpdateGWorld(&wd->gw,GWDEPTH,&wd->bounds,ctabs[wd->aalevel],NULL,0)) bad("UpdateGWorld failed"); else if(wd->gw && LockPixels(pm = GetGWorldPixMap(wd->gw))){ SetGWorld(wd->gw,0); draw(pm,wd); UnlockPixels(pm); }else bad("No GWorld, or couldn't lock GWorld for drawing"); GetWindowPortBounds(w,&r); r.right -= SCROLL_BAR_WIDTH-1; r.bottom -= SCROLL_BAR_WIDTH-1; #if TARGET_API_MAC_CARBON InvalWindowRect(w,&r); #else SetPortWindowPort(w); InvalRect(&r); #endif SetGWorld(gp,gd); InitCursor(); } OSErr open_doc(FSSpec *fss){ short r; OSErr e = noErr; TIFF *tif; static Rect bounds = {0,0,100,100}; SetCursor(*watch); if( !(e = FSpOpenDF(fss,fsRdPerm,&r)) && (tif = TIFFFdOpen(r,"","r")) ){ WindowRef w = GetNewWindow(WINDOW_ID,NULL,(WindowRef)-1); wdata *wd = (wdata*)malloc(sizeof(wdata)); SetWRefCon(w,(long)wd); SetWTitle(w,fss->name); if(gwFlagErr & NewGWorld(&wd->gw,GWDEPTH,&bounds,NULL,NULL,0)) bad("NewGWorld failed"); wd->hscroll = GetNewControl(SCROLLBAR_ID,w); wd->vscroll = GetNewControl(SCROLLBAR_ID,w); wd->refnum = r; wd->tif = tif; wd->curdir = 0; //first page wd->aalevel = 3; wd->zoom = 1.; wd->dircount = 1; do{ ++wd->dircount; }while(TIFFReadDirectory(tif)); setuppage(w,wd); resizewindow(w,wd); ShowWindow(w); redrawwindow(w,wd); }else bad("open failed"); InitCursor(); return e; } void close_window(WindowRef w){ wdata *wd = (wdata*)GetWRefCon(w); TIFFClose(wd->tif); FSClose(wd->refnum); free(wd); DisposeControl(wd->hscroll); DisposeControl(wd->vscroll); DisposeWindow(w); } void draw_window(WindowRef w,RgnHandle rgn){ wdata *wd = (wdata*)GetWRefCon(w); PixMapHandle pm = GetGWorldPixMap(wd->gw); Rect src,dst,r; if(wd->gw && LockPixels(pm)){ GetWindowPortBounds(w,&dst); dst.right -= SCROLL_BAR_WIDTH-1; dst.bottom -= SCROLL_BAR_WIDTH-1; if(rgn){ GetRegionBounds(rgn,&r); SectRect(&dst,&r,&dst); } src = dst; OffsetRect(&src,GetControlValue(wd->hscroll),GetControlValue(wd->vscroll)); CopyBits((BitMap*)*pm,GetPortBitMapForCopyBits(GetWindowPort(w)),&src,&dst,srcCopy,NULL); UnlockPixels(pm); }else{ EraseRect(&wd->bounds); MoveTo(10,100); DrawString("\pNo GWorld, or LockPixels failed!"); } } Point natural_size(WindowPtr w){ Point pt; wdata *wd = (wdata*)GetWRefCon(w); pt.h = wd->bounds.right + SCROLL_BAR_WIDTH-1; pt.v = wd->bounds.bottom + SCROLL_BAR_WIDTH-1; return pt; } short width_filter(WindowPtr w,short wd){ return max(wd,70); } short height_filter(WindowPtr w,short ht){ return max(ht,70); } void contentclick(WindowRef w,EventRecord *e){ wdata *wd = (wdata*)GetWRefCon(w); ControlPartCode part; ControlRef c; SetPortWindowPort(w); GlobalToLocal(&e->where); if(c = FindControlUnderMouse(e->where,w,&part)) // if(part = FindControl(e->where,w,&c)) do_scroll(e,part,c,wd->hscroll,wd->vscroll); /* else{ p->anchorPt = e->where; p->anchorPt.h += GetCtlValue(p->hScroller); p->anchorPt.v += GetCtlValue(p->vScroller); if(e->modifiers & optionKey) p->tracking = panTracking; else{ p->tracking = dragTracking; if(!p->selected) SetRect(&p->selection,0,0,0,0); drag_pt(p,e->where); p->selected = true; free_menus(); } } */ }