TIFF
Program TIFFViewer;
Uses Strings,Crt,Dos,VESA;
Const { TIFF sizes }
TIFFByte = 1;
TIFFASCII = 2; { PChar type string }
TIFFShort = 3; { Word }
TIFFLong = 4;
TIFFRational = 5; { 1st Long / 2nd Long }
{ TIFF compression types (2-4 are monochrome only) }
CompNone = 1; { Simple uncompressed image }
CompHuff = 2; { CCITT Group 3, 1-Dimensional Modified Huffman RLE }
CompFax3 = 3;
CompFax4 = 4;
CompLZW = 5; { GIF style LZW compression }
CompWrdL = $8003; { Word aligned image }
CompPakB = $8005; { PackBits RL encoding }
Type PStrip=^TStrip; { we make a list of strips }
TStrip=Record
num : Word; { which strip it is }
loc : LongInt; { location of the strip in the file }
size : LongInt; { size of the strip in bytes }
next : PStrip; { Next strip in list }
End;
PByte=^Byte;
Var Format : Boolean; { True if Intel format, False if Motorola format }
fl : File;
name : Array[0..63] Of Char;
data,tagnum : Word;
offset,maxstp : LongInt;
Strips : PStrip;
width,height : Word;
palette : Array[0..767] Of Byte;
spp,bps,comp : Word; { samples per pixel, bits per sample, compression methold }
photo,ns,rps : Word; { Photometric interpretation, no. of strips, rows per strip }
buf : PByte;
Function GetWord(Var f:File):Word;
Var temp:Word;
Begin
BlockRead(f,temp,2);
If Not(Format) Then temp:=Swap(temp);
GetWord:=temp;
End;
Function GetLong(Var f:File):LongInt;
Var temp:LongInt;
Begin
BlockRead(f,temp,4);
If Not(Format) Then
GetLong:=((temp And $FF000000)Shr 24)+((temp And $FF0000)Shr 8)+
((temp And $FF00)Shl 8)+((temp And $FF)Shl 24)
Else GetLong:=temp;
End;
Function Power(base,index:Word):LongInt;
Var i:Word;
t:LongInt;
Begin
t:=base;
For i:=1 To index-1 Do t:=t*base;
Power:=t;
End;
Function GetStr(slength,foffset:LongInt):String;
Var strng:Array[0..255] Of Char;
curpos:LongInt;
Begin
If slength>256 Then slength:=256;
curpos:=FilePos(fl);
Seek(fl,foffset);
BlockRead(fl,strng,slength);
Seek(fl,curpos);
GetStr:=StrPas(strng);
End;
Function GetRational(foffset:LongInt):Real;
Var n,d,curpos:LongInt;
Begin
curpos:=FilePos(fl);
Seek(fl,foffset);
n:=GetLong(fl);
d:=GetLong(fl);
GetRational:=n/d;
Seek(fl,curpos);
End;
Procedure GetStripOffsets(len,off:LongInt);
Var curpos : LongInt;
i : Word;
temp,last : PStrip;
Begin
curpos:=FilePos(fl);
Seek(fl,off); ns:=len;
For i:=1 To len Do Begin
New(temp);
temp^.num:=i;
temp^.size:=0;
temp^.loc:=GetLong(fl);
temp^.next:=Nil;
If i=1 Then Strips:=temp Else last^.next:=temp;
last:=temp;
End;
Seek(fl,curpos);
End;
Procedure GetStripSize(len,off:LongInt);
Var curpos : LongInt;
i : Word;
temp : PStrip;
Begin
curpos:=FilePos(fl);
Seek(fl,off);
temp:=Strips;
If (temp=Nil)Or(ns<>len) Then Begin
Writeln('Error in TIFF file');
Close(fl);
Halt;
End;
For i:=1 To len Do Begin
temp^.size:=GetLong(fl);
If temp^.size>maxstp Then maxstp:=temp^.size; { Find largest strip }
temp:=temp^.Next;
End;
Seek(fl,curpos);
End;
Procedure GetPalette(len,off:LongInt);
Var curpos : LongInt;
i,j,c : Word;
Begin
curpos:=FilePos(fl);
Seek(fl,off);
c:=(len Div 3)-1;
For i:=0 To 2 Do For j:=0 To c Do
palette[j*3+i]:=GetWord(fl) Shr 10;
{ Convert 48 bit colour to 18 bit VGA colour }
Seek(fl,curpos);
End;
Procedure ShowImage256(buffer:PByte); Assembler;
Var handle,bank,rows,i,dseg,btg,wide : Word;
loc,size : LongInt;
next : Pointer;
Asm
Mov dseg,ds
Mov bank,0
Mov bx,width
Mov wide,bx
Mov ax,VesaMode.Bytes
Sub ax,bx
Mov btg,ax
Mov es,VesaMode.SegA
Xor di,di
Mov ax,$3D00
Mov dx,offset name
Int $21 { Open the file for assembler }
Jc @Ex
Mov handle,ax
Lds si,Strips
Mov ax,[si+2]
Mov loc.Word[0],ax
Mov ax,[si+4]
Mov loc.Word[2],ax
Mov ax,[si+6]
Mov size.Word[0],ax
Mov ax,[si+8]
Mov size.Word[2],ax
Mov ax,[si+10]
Mov next.Word[0],ax
Mov ax,[si+12]
Mov next.Word[2],ax
Mov ds,dseg
Mov i,0
@Bgn: Mov bx,handle
Mov ax,$4200
Mov cx,loc.Word[2]
Mov dx,loc.Word[0]
Int $21 { Seek to image location }
Mov bx,handle
Mov cx,size.Word[0]
Lds si,buffer
Mov dx,si
Mov ah,$3F
Int $21
Push ds
Mov ds,dseg
Mov ax,rps
Mov rows,ax
Cmp comp,1
Pop ds
Je @0S
{ PackBits compressed TIFF }
@1S: Xor dx,dx { Set DX as the width count }
@10: Xor ah,ah { Clear upper byte }
Lodsb { Get "index" byte }
Test al,$80 { See if high bit is set }
Jz @14 { Jump if following is a string }
{ Repeat byte }
Neg al { count = -index }
Inc ax
Mov cx,ax
Add dx,cx
Lodsb { Load data to repeat "index" times }
Mov bx,di
Add bx,cx
Jc @12
@1A: Mov ah,al
Shr cx,1
Jnc @1B
Stosb
@1B: Rep Stosw
Jmp @20
@12: Stosb { Draw byte to screen }
Or di,di { Check to see if line crosses bank }
Jnz @13
Inc bank { Change bank if crossed }
Call @B1
@13: Loop @12 { Store all repeated bytes }
Jmp @20
{ Dump string }
@14: Inc ax { bytes in string = index + 1 }
Mov cx,ax
Add dx,cx
Mov ax,di
Add ax,cx
Jnc @17
@15: Movsb { Transfer string to screen }
Or di,di
Jnz @16 { bank checking }
Inc bank
Call @B1
@16: Loop @15 { Repeat for string }
Jmp @20
@17: Shr cx,1
Jnc @18
Movsb
@18: Rep Movsw
@20: Cmp dx,wide
Jne @10
Add di,btg { Move screen pointer to start of line }
Jnc @23 { Jump if not crossed bank }
Inc bank { Update bank if crossed }
Call @B1
@23: Dec rows { Update line count }
Jnz @1S { Jump to start if not end of the image }
Jmp @NS { Exit if image drawn }
{ Un-compressed TIFF }
@0S: Mov cx,wide
Mov ax,di
Add ax,cx
Jc @03 { Jump if line crosses bank }
Shr cx,1
Jnc @01
Movsb
@01: Rep Movsw { Show line }
Add di,btg
Jnc @02
Inc bank { See if line above is in another bank }
Call @B1
@02: Dec rows
Jnz @0S
Jmp @NS
@03: Movsb
Or di,di
Jnz @05
Inc bank
Call @B1
@05: Loop @03
Add di,btg
Jnc @06
Inc bank
Call @B1
@06: Dec rows
Jnz @0S
@NS: Lds si,next
Mov ax,[si+2]
Mov loc.Word[0],ax
Mov ax,[si+4]
Mov loc.Word[2],ax
Mov ax,[si+6]
Mov size.Word[0],ax
Mov ax,[si+8]
Mov size.Word[2],ax
Mov ax,[si+10]
Mov next.Word[0],ax
Mov ax,[si+12]
Mov next.Word[2],ax
Mov ds,dseg
Inc i
Mov ax,i
Cmp ax,ns
Jne @Bgn
Jmp @Ex
{ Set bank }
@B1: Push ax
Push ds
Mov ds,dseg
Mov al,vesaon
Or al,al
Jz @B3
Push bx
Push dx
Mov dx,bank
Xor bx,bx
Mov ax,64
Mul dx
Div VesaMode.Gran
Mov dx,ax
Push dx
Call VesaMode.WinFunc
Pop dx
Inc bx
Call VesaMode.WinFunc
Pop dx
Pop bx
@B3: Pop ds
Pop ax
RetN
@Ex: Mov bx,handle { Close the file }
Mov ah,$3E
Int $21
End;
Procedure ShowImage16; Assembler;
Asm
End;
Procedure ShowImage;
Var r : Registers;
Begin
SetMode($101);
r.ax:=$1012;
r.bx:=0;
r.cx:=256;
r.dx:=Ofs(palette);
r.es:=Seg(palette);
Intr($10,r); { Set palette }
GetMem(buf,maxstp);
If bps=8 Then ShowImage256(buf) Else
If bps=4 Then ShowImage16;
FreeMem(buf,maxstp);
Sound(660);
Delay(100);
Sound(880);
Delay(50);
Sound(440);
Delay(75);
NoSound;
ReadKey;
SetMode(3);
End;
Procedure ReadTag;
Var tag,typ : Word;
len,off : LongInt;
Begin
tag:=GetWord(fl);
typ:=GetWord(fl);
len:=GetLong(fl);
off:=GetLong(fl);
If (Not Format)And(typ=TIFFByte)And(len=1) Then off:=off Shr 24;
If (Not Format)And(typ=TIFFShort)And(len=1) Then off:=off Shr 16;
Case tag Of
254 : Writeln(tagnum:2,' - New Subfile Type: ',off); { New Subfile type }
255 : Writeln(tagnum:2,' - Old Subfile Type (obsolete): ',off); { Subfile type }
256 : Begin
Writeln(tagnum:2,' - Image width = ',off,' pixels');
width:=off;
End;
257 : Begin
Writeln(tagnum:2,' - Image height = ',off,' pixels');
height:=off;
End;
258 : Begin
Writeln(tagnum:2,' - Bits per sample = ',off);
bps:=off;
End;
259 : Begin
comp:=off;
Case Word(off) Of { Compression }
CompNone : Writeln(tagnum:2,'Non-compressed image, Byte aligned');
CompHuff : Writeln(tagnum:2,'CCITT Group 3 one-dim. mod Huffman run-len enc');
CompFax3 : Writeln(tagnum:2,'Fax compatible CCITT Group 3 compression');
CompFax4 : Writeln(tagnum:2,'Fax compatible CCITT Group 4 compression');
CompLZW : Writeln(tagnum:2,'GIF style LZW compressed image');
CompWrdL : Writeln(tagnum:2,'Non-compressed image, Word aligned');
CompPakB : Writeln(tagnum:2,'MacPaint style PackBits RL image compression');
Else Writeln(tagnum:2,' - Unrecognized image compression');
End;
End;
262 : Begin { Photometric Interpretation }
Write(tagnum:2,' - Photometric Interpretation: ');
photo:=off;
Case off Of
0 : Writeln('MinSampleValue is white, MaxSampleValue is black');
1 : Writeln('MinSampleValue is black, MaxSampleValue is white');
2 : Writeln('RGB');
3 : Writeln('Paletted colour');
4 : Writeln('Transparency mask');
Else Writeln('Unknown');
End;
End;
263 : Writeln(tagnum:2,' - Thresholding (obsolete): ',off);
264 : Writeln(tagnum:2,' - Cell Width (obsolete) = ',off);
265 : Writeln(tagnum:2,' - Cell Length (obsolete) = ',off);
266 : Writeln(tagnum:2,' - Fill Order (obsolete) = ',off);
269 : Writeln(tagnum:2,' - Document name: ',GetStr(len,off));
270 : Writeln(tagnum:2,' - Image description: ',GetStr(len,off));
271 : Writeln(tagnum:2,' - Manufacturer of scanner or whatever: ',GetStr(len,off));
272 : Writeln(tagnum:2,' - Model name of scanner or whatever: ',GetStr(len,off));
273 : Begin { Strip offset }
Writeln(tagnum:2,' - Number of Strip offsets = ',len);
Writeln(' - Location of Strip offsets = ',off);
GetStripOffsets(len,off);
End;
274 : Writeln(tagnum:2,' - Image Orientation (obsolete): ',off); { Orientation }
277 : Begin
Writeln(tagnum:2,' - Samples per pixel = ',off);
spp:=off;
End;
278 : Begin
Writeln(tagnum:2,' - Rows per strip = ',off); { Rows per Strip }
rps:=off;
End;
279 : Begin
Writeln(tagnum:2,' - Bytes per strip offset = ',off); { Bytes per Strip }
GetStripSize(len,off);
End;
{ Minimum Sample Value }
280 : Writeln(tagnum:2,' - Minimum sample value offset (obsolete): ',off);
{ Maximum Sample Value }
281 : Writeln(tagnum:2,' - Maximum sample value offset (obsolete): ',off);
282 : Writeln(tagnum:2,' - X res = ',GetRational(off):1:1,' pixels per Res Unit');
283 : Writeln(tagnum:2,' - Y res = ',GetRational(off):1:1,' pixels per Res Unit');
284 : Begin { Planar configuration }
Write(tagnum:2,' - Planar configuration: ');
Case off Of
1 : Writeln('Samples are contiguous stored');
2 : Writeln('Each of the RGB samples are stored in separate planes');
End;
End;
{ Page name }
285 : Writeln(tagnum:2,' - Page Name: ',GetStr(len,off));
{ X Position }
286 : Writeln(tagnum:2,' - X Position offset (fraction): ',off);
{ Y Position }
287 : Writeln(tagnum:2,' - Y Position offset (fraction): ',off);
{ Free Offsets }
288 : Writeln(tagnum:2,' - Free Offsets (obsolete) = ',off);
{ Free Bytes Count }
289 : Writeln(tagnum:2,' - Free Bytes Count (obsolete) = ',off);
{ Grey response unit }
290 : Writeln(tagnum:2,' - Gray response unit ',Power(10,off));
{ Grey response curve }
291 : Writeln(tagnum:2,' - Gray response curve offset: ',off);
292 : Writeln(tagnum:2,' - Group 3 Options: ',off); { Group 3 Options }
293 : Writeln(tagnum:2,' - Group 4 Options: ',off); { Group 4 Options }
296 : Begin { Resolution Unit }
Write(tagnum:2,' - Resolution Unit: ');
Case off Of
1 : Writeln('No unit of measurement');
2 : Writeln('Inches');
3 : Writeln('Centimetres');
End;
End;
{ Page number }
297 : Writeln(tagnum:2,' - Page Number offset: ',off);
{ Colour response unit }
300 : Writeln(tagnum:2,' - Colour response unit: ',Power(10,off));
{ Colour response curves }
301 : Writeln(tagnum:2,' - Colour response curve offset = ',off);
305 : Writeln(tagnum:2,' - Software that created the image: ',GetStr(len,off));
306 : Writeln(tagnum:2,' - Date & Time image was created: ',GetStr(len,off));
315 : Writeln(tagnum:2,' - Person who created the image: ',GetStr(len,off));
316 : Writeln(tagnum:2,' - Host computer: ',GetStr(len,off));
317 : Writeln(tagnum:2,' - Predictor = ',off);
320 : Begin
Writeln(tagnum:2,' - Palette offset = ',off);
GetPalette(len,off);
End;
Else Writeln(tagnum:2,' - Unrecognized tag: ',tag);
End;
End;
Begin
If ParamCount>0 Then Begin
Strips:=Nil; maxstp:=0;
If Pos('.',ParamStr(1))=0 Then StrPCopy(name,ParamStr(1)+'.TIF')
Else StrPCopy(name,ParamStr(1));
Assign(fl,name);
{$I-}
Reset(fl,1);
{$I+}
If IOResult=0 Then Begin
data:=GetWord(fl);
If data=$4949 Then Format:=True Else
If data=$4D4D Then Format:=False Else Begin
Writeln('File is not a TIFF');
Halt;
End;
If Format Then Writeln('TIFF stored in Intel format')
Else Writeln('TIFF stored in Motorola format');
data:=GetWord(fl);
Writeln('TIFF version ',data/10:1:1);
offset:=GetLong(fl);
Writeln('Tagged fields at offset ',offset,' bytes');
Seek(fl,offset); { Move to "tags" in file }
data:=GetWord(fl);
Writeln(data,' tagged fields in the directory...');
For tagnum:=1 To data Do ReadTag;
If spp=1 Then Begin { Show image if paletted, not true colour }
Writeln;
Writeln('Press a key to view the image');
ReadKey;
ShowImage;
End;
Close(fl);
End Else Writeln('File not found');
End Else Writeln('Usage: TIFFVIEW <filename>');
End.
Оставить комментарий
Комментарии
1.


25 мая 2009, 14:27:26
Чем компилировать прогу на ассемблере????????
2.


22 апреля 2006, 20:46:00
че-ж тут переводить; вот насчет ассемблера, не всегда будет работать
3.
+1 / -0


31 мая 2005, 22:54:05
Здорово! Пока ничего не понял, но все равно - клево. По крайней мере теперь ясен порядок и офсеты заголовков. Открываются возмжности коррекции полученого файла (например: изменить X res & Y res) после того, как одна из многих древних OCX большой растр (x*y >> 10000*5000 pixels) сохраняет только с разрешением 100 dpi, а нужно, к примеру, 300 dpi. Будем колдовать. Спасибо!
Hitler kaputt?
Hitler kaputt?
4.
+1 / -0


28 марта 2005, 00:11:30
Ох... Теперь это все бы еще на С++ перевести... :)
