home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / graphics / tiffrea.zip / TIFFREAD.PAS < prev   
Pascal/Delphi Source File  |  1993-06-08  |  14KB  |  546 lines

  1. Program tiffread;
  2.  
  3.  
  4. {Written by Alan B.}
  5.  
  6.  
  7. {$I-,R+}
  8.  
  9. uses  printer,crt,dos,graph;
  10.  
  11. type  binstr     = string[8];
  12.       screenarray= array[1..11000] of byte;
  13.  
  14.       stripinfoptr = ^stripinfo;
  15.       stripinfo    = record
  16.                        size: word;
  17.                        offset: word;
  18.                        stripinfolink: stripinfoptr;
  19.                      end;
  20.       stripobytesptr =^stripobytes;
  21.       stripobytes    = record
  22.                          value: byte;
  23.                          stripobyteslink: stripobytesptr;
  24.                        end;
  25.       lineobytesptr    = ^lineobytes;
  26.       lineobytes       = record
  27.                            bits: byte;
  28.                            lineobyteslink: lineobytesptr;
  29.                          end;
  30.  
  31. var   fin,
  32.       fout                   : file;
  33.       i,j,k,rr               : integer;
  34.       l,m,
  35.       column,
  36.       bytepos                : byte;
  37.       row                    : integer;
  38.       count                  : shortint;
  39.       rownum                 : integer;
  40.       TifFileName            :   String[45];
  41.       dot: boolean;
  42.       rowstir                : integer;
  43.       fentries,
  44.       nexttag,
  45.       nextlength             : word;
  46.       tbyte                  : byte;
  47.       fimagewidth,
  48.       fimagelength,
  49.       fstripoffsetsoffset,
  50.       fstrips,
  51.       fstripbytecountsoffset,
  52.       bytetoread,
  53.       largeststrip           : word;
  54.       first,
  55.       last,
  56.       p                      : stripinfoptr;
  57.       firstbyte,
  58.       lastbyte,
  59.       pbyte                  : stripobytesptr;
  60.       firstline,
  61.       lastline,
  62.       pline                  : lineobytesptr;
  63.       columns                : integer;
  64.       compression            : word;
  65.       regs                   : registers;
  66.       screen                 : ^screenarray;
  67.       header                 : array[1..10] of byte;
  68.       page                   : array[1..8,1..100] of byte;
  69.       printcolumns           : integer;
  70.  
  71.  
  72. {reads a file into the image array}
  73. {assumes StripOffsets start directly after stripbytcounts}
  74. {read down to where stripbytecounts starts}
  75. {fill stripbytecounts with size in bytes of each offset}
  76. {read each strip into linked list}
  77.  
  78.  
  79. procedure Writebytes;
  80. begin
  81. {this displays the contents of the linked list on the printer}
  82.   pbyte:= firstbyte;
  83.   while pbyte^.stripobyteslink <> nil do
  84.     begin
  85.       write(lst,pbyte^.value:3,' ');
  86.       pbyte:= pbyte^.stripobyteslink;
  87.     end;
  88.   writeln(lst);
  89. end;
  90.  
  91. procedure WriteStripInfo;
  92. begin
  93. {this displays the contents of the linked list on the printer}
  94.   p:= first;
  95.   while p <> nil do
  96.     begin
  97.       write(lst,p^.size:3,' ');
  98.       writeln(lst,p^.offset:4,' ');
  99.       p:= p^.stripinfolink;
  100.     end;
  101.   writeln(lst,#12);
  102. end;
  103.  
  104. Procedure SetVMode(newmode:integer);
  105. begin
  106.   FillChar(Regs,SizeOf(regs),0);
  107.   Regs.AX:= newmode;
  108.   Intr($10,Regs);
  109. end;
  110.  
  111. Function BitOn(Position, TestByte:byte):boolean;
  112. var
  113.   bt,
  114.   i:byte;
  115. begin
  116.   bt:= $01;
  117.   bt:= bt shl position;
  118.   biton:= (bt and testbyte) > 0;
  119. end;
  120.  
  121. procedure Pictoprinter(row:integer);
  122. var bytepos,
  123.     j,i,
  124.     pinlabel,
  125.     pin,
  126.     column   : integer;
  127.     trow     : integer;
  128. begin
  129.   write(lst,#27,'A',#8); {8 lines per inch}
  130.   bytepos:=0;
  131.   write(lst,#27,'L',Chr((columns*8) mod 256),chr((columns*8) div 256)); {graphics mode}
  132.   for column:=1 to columns do
  133.   begin
  134.     for bytepos:=0 to 7 do
  135.     begin
  136.       trow:=1;
  137.       pinlabel:=0;
  138.       if not biton(abs(bytepos-7),page[trow][column]) then
  139.         pinlabel:= 128;
  140.       inc(trow);
  141.       if not biton(abs(bytepos-7),page[trow][column]) then
  142.         inc(pinlabel,64);
  143.       inc(trow);
  144.       if not biton(abs(bytepos-7),page[trow][column]) then
  145.         inc(pinlabel,32);
  146.       inc(trow);
  147.       if not biton(abs(bytepos-7),page[trow][column]) then
  148.         inc(pinlabel,16);
  149.       inc(trow);
  150.       if not biton(abs(bytepos-7),page[trow][column]) then
  151.         inc(pinlabel,8);
  152.       inc(trow);
  153.       if not biton(abs(bytepos-7),page[trow][column]) then
  154.         inc(pinlabel,4);
  155.       inc(trow);
  156.       if not biton(abs(bytepos-7),page[trow][column]) then
  157.         inc(pinlabel,2);
  158.       inc(trow);
  159.       if not biton(abs(bytepos-7),page[trow][column]) then
  160.         inc(pinlabel);
  161.       write(lst,char(pinlabel))
  162.     end;
  163.   end;
  164.   write(lst,#13,#10);
  165. end;
  166.  
  167. procedure Pictoscreen(row:integer);
  168.  
  169. var storagebyte : byte;
  170.     i,j,wl,wr,wb,wt,
  171.     column      : integer;
  172.  
  173. procedure SetPixal(xpos,ypos:integer);
  174. begin
  175.   FillChar(Regs,SizeOf(regs),0);
  176.   Regs.ah:= $0c;
  177.   Regs.al:= 1;
  178.   Regs.cx:= xpos;
  179.   Regs.dx:= ypos;
  180.   intr($10,Regs);
  181. end;
  182.  
  183. begin
  184.   column:= 1;
  185.   printcolumns:= 0;
  186.   while pline <> nil do
  187.     begin
  188.       if ((row mod 8) = 0) then
  189.         page[8,column]:= pline^.bits
  190.       else
  191.         page[row mod 8,column]:= pline^.bits;
  192.       for i:= 0 to 7 do
  193.         if biton(i,pline^.bits) then
  194.         begin
  195.           SetPixal((column*8-7)+abs(i-7),row);
  196.           inc(printcolumns)
  197.         end;
  198.       pline:= pline^.lineobyteslink;
  199.       inc(column)
  200.     end;
  201. end;
  202.  
  203.  
  204.  
  205. Procedure GetFileName;
  206.  
  207. Function fileexists(searchfile: string):boolean;
  208. var
  209.   f:   file;
  210.   ok:  boolean;
  211. begin
  212.   assign(f,searchfile);
  213.   (*$I-*)
  214.   reset(f,1);
  215.   (*$I+*)
  216.   ok:= ioresult = 0;
  217.   if not ok then
  218.     fileexists:= false
  219.   else
  220.     begin
  221.       close(f);
  222.       fileexists:= true;
  223.     end;
  224. end;
  225.  
  226. begin
  227.   TifFileName:='____________';
  228.   i:=ParamCount;
  229.   if i>1 then
  230.   begin
  231.     Write(#07,' Invalid Number of Paramaters');
  232.     Halt;
  233.   end
  234.   else
  235.   if i=0 then
  236.   begin
  237.     write('Enter File Name: ');
  238.     ReadLn(tifFileName);
  239.     if Length(tifFileName)=0 then
  240.       Halt;
  241.   end
  242.   else
  243.   begin
  244.     tifFileName:=ParamStr(1);
  245.   end;
  246.   Dot:=False;
  247.   for i:=1 to Length(tifFileName) do
  248.     if tifFileName[i]='.' then
  249.         Dot:=True;
  250.   if Dot=False then
  251.     tifFileName:=tifFileName+'.TIF';
  252.   if not(FileExists(tifFileName)) then
  253.   begin
  254.     Write(#07,'File ',tifFileName,' Not on Disk');
  255.     Halt;
  256.   end;
  257. end;
  258.  
  259.  
  260. Procedure GetFileInfo;
  261. begin
  262.   assign(fin,tiffilename);
  263.   reset(fin,1);
  264.   blockread(fin,header,8);
  265.   writeln('***********');
  266.         {we're assuming the ifd is right after the header}
  267.   blockread(fin,fentries,2);
  268.   for i:=1 to fentries do
  269.     begin
  270.       blockread(fin,nexttag,2);
  271.       case nexttag of
  272.          {i really need a 32 bit unsigned type here. since i dont have
  273.           one file witdth should be limited to 65535}
  274.         256: begin                        {imagewidth}
  275.                blockread(fin,header,6);
  276.                blockread(fin,fimagewidth,2);
  277.                Columns:= (fimagewidth div 8);
  278.                if (fimagewidth mod 8) <> 0 then
  279.                  inc(Columns);
  280. {               writeln('columns: ',columns);}
  281.                blockread(fin,header,2);
  282.              end;
  283.         257:begin                         {imagelength}
  284.               blockread(fin,header,6);
  285.               blockread(fin,fimagelength,2);
  286. {              writeln('rows: ',fimagelength);}
  287.               blockread(fin,header,2);
  288.             end;
  289.         259:begin
  290.               blockread(fin,header,6);
  291.               blockread(fin,Compression,2);
  292.               if compression <> 32773 then
  293.                 begin
  294.                   writeln('I can''t read this. A computer is a terrible thing to waste, isn''t it.');
  295.                   readln;
  296.                   halt;
  297.                 end;
  298.               blockread(fin,header,2);
  299.             end;
  300.         273:begin                         {stripOffsets}
  301.               blockread(fin,header,2);    {read past field type}
  302.               blockread(fin,fstrips,2);      {length}
  303.               writeln('strips: ',fstrips);
  304.               blockread(fin,header,2);
  305.               blockread(fin,fstripoffsetsoffset,2);
  306.               blockread(fin,header,2);
  307.             end;
  308.         279:begin                         {StripByteCounts}
  309.               blockread(fin,header,6);
  310.               blockread(fin,fstripbytecountsoffset,2);
  311.               writeln('stripbytecountoffset: ',fstripbytecountsoffset);
  312.               blockread(fin,header,2);
  313.             end;
  314.         else blockread(fin,header,10);
  315.       end;  {case}
  316.     end; {for i:= 1 to fentries}
  317. end;
  318.  
  319.  
  320.  
  321.  
  322. Procedure GetStripCounts;
  323.  
  324. procedure add(fcount:word);
  325. {we're assuming theres at least 1 byte in the list}
  326. begin
  327.   if first = nil then
  328.     begin
  329.       new(first);
  330.       last:= first;
  331.       first^.size:= fcount;
  332.     end
  333.   else      {the list has already been started so just add to it}
  334.     begin
  335.       new(p);
  336.       p^.size:= fcount;
  337.       last^.stripinfolink:=p;
  338.       last:= p;
  339.     end;
  340. end;
  341.  
  342. begin
  343. {here we're assuming the stripbytecount values will fit in a word}
  344. {this part reads stripbytecounts into the linkedlist}
  345.   first:= nil;
  346.   reset(fin,1);
  347.   seek(fin,fstripbytecountsoffset);
  348.   for i:= 1 to fstrips do
  349.     begin
  350.       blockread(fin,bytetoread,2);
  351.       add(bytetoread);
  352.     end;
  353.   if first <> nil then last^.stripinfolink:= nil;
  354. end;
  355.  
  356.  
  357. Procedure GetStripOffsets;
  358. begin
  359. {this part reads in the strip offsets into the linked list}
  360.   p:= first;
  361.   reset(fin,1);
  362.   seek(fin,fstripoffsetsoffset);
  363.   for i:= 1 to fstrips do
  364.     begin
  365.       blockread(fin,bytetoread,2);
  366.       p^.offset:= bytetoread;
  367.       p:=p^.stripinfolink;
  368.       blockread(fin,bytetoread,2);
  369.     end;
  370. end;
  371.  
  372. procedure DisposeStrip;
  373. var
  374. tpointer:stripobytesptr;
  375. begin
  376.   tpointer:= firstbyte^.stripobyteslink;
  377.   dispose(firstbyte);
  378.   firstbyte:= tpointer;
  379.   while tpointer^.stripobyteslink <> nil do
  380.   begin
  381.     tpointer:= tpointer^.stripobyteslink;
  382.     dispose(firstbyte);
  383.     firstbyte:= tpointer;
  384.   end;
  385.   dispose(tpointer);
  386. end;
  387.  
  388. Procedure ReadAStrip;
  389.  
  390. procedure addbyte(fcount:word);
  391. {we're assuming there's at least 1 byte in the list}
  392. begin
  393.   if firstbyte = nil then
  394.     begin
  395.       new(firstbyte);
  396.       lastbyte:= firstbyte;
  397.       firstbyte^.value:= fcount;
  398.     end
  399.   else      {the list has already been started so just add to it}
  400.     begin
  401.       new(pbyte);
  402.       pbyte^.value:= fcount;
  403.       lastbyte^.stripobyteslink:=pbyte;
  404.       lastbyte:= pbyte;
  405.     end;
  406. end;
  407.  
  408. begin
  409. {this part jumps down to the right place in the file and reads a strip into
  410.  a linked list.  We'll just read in one strip for now.}
  411.  
  412.   firstbyte:= nil;
  413.   reset(fin,1);
  414.   seek(fin,p^.offset);
  415.   for i:= 1 to p^.size + 1 do  {+1 for not / by 8 evenly}
  416.     begin
  417.       blockread(fin,tbyte,1);
  418.       addbyte(tbyte);
  419.     end;
  420.   if firstbyte <> nil then lastbyte^.stripobyteslink:= nil;
  421. end;
  422.  
  423.  
  424. Procedure DecodeStrip;
  425.  
  426. var
  427.   spot     : integer;
  428.  
  429. procedure disposeline;
  430. var
  431. tpointer:lineobytesptr;
  432. begin
  433.   tpointer:= firstline^.lineobyteslink;
  434.   dispose(firstline);
  435.   firstline:= tpointer;
  436.   while tpointer^.lineobyteslink <> nil do
  437.   begin
  438.     tpointer:= tpointer^.lineobyteslink;
  439.     dispose(firstline);
  440.     firstline:= tpointer;
  441.   end;
  442.   dispose(tpointer);
  443. end;
  444.  
  445. procedure ResetPage;
  446. begin
  447.   if firstline <> nil then lastline^.lineobyteslink:= nil;
  448.   pline:= firstline;
  449.   pictoscreen(rownum);
  450.   if ((rownum div 8) >= 1) and ((rownum mod 8) = 0) then
  451.     pictoprinter(rownum);
  452.   inc(rownum);
  453.   disposeline;
  454.   firstline:= nil;
  455.   spot:= 1;
  456. end;
  457.  
  458. procedure addline(fcount:word);
  459. {we're assuming there's at least 1 byte in the list}
  460. begin
  461.   if firstline = nil then
  462.     begin
  463.       new(firstline);
  464.       lastline:= firstline;
  465.       firstline^.bits:= fcount;
  466.     end
  467.   else      {the list has already been started so just add to it}
  468.     begin
  469.       new(pline);
  470.       pline^.bits:= fcount;
  471.       lastline^.lineobyteslink:=pline;
  472.       lastline:= pline;
  473.     end;
  474. end;
  475.  
  476. begin
  477. {now lets try and decode the strip in the linked list}
  478.   firstline:= nil;
  479.   spot:= 1;
  480.   pbyte:= firstbyte;
  481.   while pbyte^.stripobyteslink <> nil do {convert the strip 8 rows per strip}
  482.     begin
  483.       Count:= shortint(pbyte^.value);
  484.       if Count < 0 then    {copy the next byte -n+1 times}
  485.         begin
  486.           pbyte:= pbyte^.stripobyteslink; {point to the byte to copy -n+1 times}
  487.           for i:= 1 to (-Count+1) do
  488.             begin
  489.               addline(pbyte^.value);
  490.               inc(spot);
  491.               if spot > columns then
  492.                 resetpage;
  493.             end;
  494.         end
  495.       else                  {copy the next n+1 bytes literally}
  496.         for i:= 1 to (Count+1) do {no error checking for nil}
  497.           begin
  498.             pbyte:= pbyte^.stripobyteslink; {point the the next literal byte}
  499.             addline(pbyte^.value);
  500.             inc(spot);
  501.             if spot > columns then
  502.               resetpage;
  503.           end;
  504.       pbyte:= pbyte^.stripobyteslink;
  505.     end;
  506. end;
  507.  
  508. var ch:char;
  509. begin
  510.   GetFileName;
  511.   GetFileInfo;
  512.   GetStripCounts;
  513.   GetStripOffsets;
  514.   p:= first;
  515.   SetVMode($10);
  516.   new(screen);
  517.   screen:= ptr($A000,$0000);
  518.   rownum:= 1;
  519.   while p^.stripinfolink <> nil do
  520.     begin
  521.       ReadAStrip;
  522.       DecodeStrip;
  523.       DisposeStrip;
  524.       p:= p^.stripinfolink;
  525.     end;
  526.   close(fin);
  527.   assign(input,'');
  528.   reset(input);
  529.   readln;
  530.   SetVMode($3);
  531.   write(lst,#12,#13);
  532.  
  533.   {enhancements needed
  534.  
  535.   adjust for aspect ratio
  536.   mask out extra stuf at right side when displaying
  537.   add ega support
  538.   add interface
  539.   write direct to memory
  540.   }
  541.  
  542. end.
  543.  
  544.  
  545.  
  546.