home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2001 October
/
Chip_2001-10_cd1.bin
/
zkuste
/
delphi
/
navody
/
DICOMSRC.ZIP
/
lsjpeg.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
2001-05-31
|
21KB
|
503 lines
unit lsjpeg;
//{$DEFINE MRICRO}
interface
uses dialogs,sysutils,windows;
type
HufRA = record
HufSz,HufCode,HufVal: Integer;
end;
ByteRA = array [1..1] of byte;
Bytep = ^ByteRA;
ByteRA0 = array [0..0] of byte;
Bytep0 = ^ByteRA0;
WordRA = array [1..1] of Word;
Wordp = ^WordRA;
{$IFDEF MRICRO}
SmallIntRA = array [1..1] of SmallInt;
SMallIntp = ^SmallIntRA;
{$ELSE}
SmallIntRA0 = array [0..0] of SmallInt;
SMallIntp0 = ^SmallIntRA0;
{$ENDIF}
{$IFDEF MRICRO}
procedure DecodeJPEG(var infp: file; var lOutSmallRA: SmallIntP; var lImgRAz: ByteP;lOutputSz,lCptPosition,lCptSize: integer; lVerbose: boolean);
{$ELSE}
procedure DecodeJPEG(var infp: file; var lOutSmallRA: SmallIntP0; var lImgRAz: ByteP0;lOutputSz,lCptPosition,lCptSize: integer; lVerbose: boolean);
{$ENDIF}
implementation
{$IFDEF MRICRO}
procedure DecodeJPEG(var infp: file; var lOutSmallRA: SmallIntP; var lImgRAz: ByteP; lOutputSz,lCptPosition,lCptSize: integer; lVerbose: boolean);
{$ELSE}
procedure DecodeJPEG(var infp: file; var lOutSmallRA: SmallIntP0; var lImgRAz: ByteP0;lOutputSz,lCptPosition,lCptSize: integer; lVerbose: boolean);
{$ENDIF}
label
666 {EOF};
var
lRawRA: bytep;
lImgRA: WordP;
lLineStart,lPredicted,lRestartSegmentSz,
lSz,k,Code,Si,lIncX,lIncY,lInc,lPredA,lPredB,lCurrentByteVal,lCurrentBitPos,btS1,btS2, btMarkerType,
DHTnLi,DHTtcth,SOFprecision,lMaxHufSi,lMaxHufVal,SOSpttrans, SOFnf,SOFarrayPos,SOSns,SOSarrayPos,SOSss,SOSse,SOSahal:integer;//byte;
lDecode,lImgStart,lRawSz,lRawPos,lItems,SOFydim, SOFxdim: integer;
DHTLiRA,DHTstartRA: array [0..31] of integer;//byte;
lHufRA: array [0..31] of HufRA;
lSegmentLength,lSegmentEnd,lI: integer;
lImgTypeC3,lHdrOK: boolean;
function ReadBit: integer;
begin
if lCurrentBitPos > 8 then begin
if lCurrentByteVal = $FF then begin
inc(lRawPos);
if (lRawRA[lRawPos] <> 0) {and (lEOFX = 0)} then begin
//while (lRawRA[lRawPos] <> $D9) and (lRawRA[lRawPos] <> 0) do
// inc(lRawPos);
{if (lRawRA[lRawPos] >= $D0) and (lRawRA[lRawPos] <= $D7) then begin
lRestart := lRawPos;
//inc(lRawPos); //restart marker
end;}
{if (lRawRA[lRawPos] = $D9) then begin
//lEOFX := lIncX;
showmessage('end of file');
end;}
//if lRabbi then showmessage(inttostr(lRawPos) )
{
+':'+inttostr(lRawRA[lRawPos+2] )
+':'+inttostr(lRawRA[lRawPos+3] )
+':'+inttostr(lRawRA[lRawPos+4] )
+':'+inttostr(lRawRA[lRawPos+5] )
+':'+inttostr(lRawRA[lRawPos+6] )
+'Data is not zero padded.'+inttostr(lRawPos));;}
end;
(*error checking: significantly slows function
{if (lRawRA[lRawPos] <> 0) then begin
if (lRawRA[lRawPos] = $D9) and (lEOFX=0) then begin
lEOFX := lIncX;
end; { else
showmessage('Data is not zero padded.');
end; }
end; (**)//not 0 padded
end; //$FF = skip a byte
inc(lRawPos);
if lRawPos < lRawSz then //little time penalty for this check
lCurrentByteVal := lRawRA[lRawPos];
result := (lCurrentByteVal shr 7);
lCurrentBitPos := 2;
end else begin
result := 1 and (lCurrentByteVal shr (8-lCurrentBitPos));
inc(lCurrentBitPos);
end;
end; (* *)
(*function ReadBit: byte;
begin
if lCurrentBitPos =1 then begin
if lCurrentByteVal = $FF then begin
inc(lRawPos);
lCurrentByteVal := 0;
if (lRawRA[lRawPos] <> 0) then begin
if (lRawRA[lRawPos] = $D9) and (lEOFX=0) then begin
lEOFX := lIncX;
end; { else
showmessage('Data is not zero padded.');
end; }
end; //not 0 padded
end; //FF
inc(lRawPos);
if lRawPos < lRawSz then
lCurrentByteVal := lRawRA[lRawPos];
result := (lCurrentByteVal shr 7);
end else
result := 1 and (lCurrentByteVal shr (8-lCurrentBitPos));
inc(lCurrentBitPos);
if lCurrentBitPos = 9 then lCurrentBitPos := 1;
end;(**)
function DecodePixelDifference: integer;//qwsmallint;}
var
lInput,lInputbits,lHufVal,lDiff,lI: integer;
begin
lHufVal := 666;
lInput := 0;
lInputBits := 0;
repeat
Inc(lInputBits);
lInput := lInput shl 1 + ReadBit;
if DHTLiRA[lInputBits] <> 0 then begin
for lI := DHTstartRA[lInputBits] to (DHTstartRA[lInputBits]+DHTLiRA[lInputBits]-1) do begin
if (lInput = lHufRA[lI].HufCode) then
lHufVal := lHufRA[lI].HufVal;
end; //check each code
end; //if possible at this length
//a if lInputBits >= lMaxHufSi then//exhausted options
//a lHufVal := lMaxHufVal;
if lInputBits >= lMaxHufSi then//exhausted options
lHufVal := lMaxHufVal;
until (lHufVal < 255){found};
case lHufVal of
0: result:= 0;
1: if ReadBit = 0 then result := -1 else result := 1;
2..15: begin
lDiff := 0;
if ReadBit = 1 then begin //read signbit Positive value
for lI := 1 to (lHufVal - 1) do
lDiff := (lDiff shl 1) + ReadBit;
result := lDiff + (1 shl (lHufval-1));
end else begin
for lI := 1 to (lHufVal - 1) do
lDiff := (lDiff shl 1) + 1 - ReadBit;
result := -(lDiff + (1 shl (lHufval-1)));
//lDiff := -(lDiff);
end;
end;
else {16:} result := 32768;
//else showmessage('Terminal decoder error. HufVal = '+inttostr(lHufVal));//lDiff := -666;
end; //case HuffVal
//result := lDiff;
end;
procedure ReadByte(var lByte: integer);
begin
inc(lRawPos);
lByte := lRawRA[lRawPos];
end;
function ReadWord: word;
var
lbtL1, lbtL2: byte;
begin
inc(lRawPos);
lbtL1 := lRawRA[lRawPos];
inc(lRawPos);
lbtL2 := lRawRA[lRawPos];
result := (256 * lbtL1 + lbtL2)
end;
begin
lRawSz := lCptSize;
lRawPos := 0;
lRestartSegmentSz := 0;
lImgTypeC3 := false;
SOFxdim:= 1;
if lRawSz < 32 then goto 666;
for lInc := 1 to 16 do
DHTstartRA[lInc] := 0;
SOFydim := 1;
SOSpttrans := 0;
lHdrOK := false;
SOFnf := 0;
SOSns := 0;
Seek(infp,lCptPosition);
GetMem( lRawRA, lRawSz);
BlockRead(infp, lRawRA^, lRawSz);
ReadByte(btS1);
ReadByte(btS1);
repeat
repeat
if lRawPos <= lRawSz then ReadByte(btS1);
if btS1 <> $FF then begin
goto 666;
end;
if lRawPos <= lRawSz then ReadByte( btMarkerType);
case btMarkerType of //only process segments with length fields
$0,$1,$D0..$D7,$FF: btMarkerType := 0; //0&FF = fillers, $1=TEM,$D0..D7=resync
end;
until (lRawPos >= lRawSz) or (btMarkerType <> 0);
lSegmentLength := ReadWord;
lSegmentEnd := lRawPos+(lSegmentLength - 2);
if lSegmentEnd > lRawSz then goto 666;
if (btMarkerType = $C3) then
lImgTypeC3 := true;
if lverbose then showmessage( {result+}inttohex(btMarkerType,2){':'+inttostr( lSegmentLength )+'@'+inttostr(positon)+' '});
case btMarkerType of
$0: ; //filler - ignore
$C0..$C3,$C5..$CB,$CD..$CF: begin //read SOF FrameHeader
ReadByte(SOFprecision);
SOFydim := ReadWord;
SOFxdim:= ReadWord;
ReadByte(SOFnf);
if lverbose then Showmessage('[precision:'+inttostr(SOFprecision)+' X*Y:'+inttostr(SOFxdim)+'*'+inttostr(SOFydim)+'nFrames:'+inttostr(SOFnf)+'] ');
if (not lImgTypeC3) or (SOFnf > 1) then begin
showmessage('Unable to extract this file format.');
end;
SOFarrayPos := lRawPos;
lRawPos := (lSegmentEnd);
end; //SOF FrameHeader
$C4: begin //DHT Huffman
if lverbose then showmessage( 'HuffmanLength'+inttostr(lSegmentLength)+':');
ReadByte( DHTtcth);
DHTnLi := 0;
for lInc := 1 to 16 do begin
ReadByte(DHTliRA[lInc]);
DHTnLi := DHTnLi + DHTliRA[lInc];
if DHTliRA[lInc] <> 0 then lMaxHufSi := lInc;
end;
if DHTnLi > 17 then begin
showmessage('Huffman table corrupted.');
goto 666;
end;
lIncY := 0; //frequency
for lInc := 1 to 16 do begin //set the huffman size values
if DHTliRA[lInc]> 0 then begin
DHTstartRA[lInc] := lIncY+1;
for lIncX := 1 to DHTliRA[lInc] do begin
inc(lIncY);
ReadByte(btS1);
lHufRA[lIncY].HufVal := btS1;
lMaxHufVal := btS1;
if (btS1 >= 0) and (btS1 <= 16) then
lHufRA[lIncY].HufSz := lInc
else begin
showmessage('Huffman size array corrupted.');
goto 666;
end; {}
end;
end; //Length of size lInc > 0
end;
K := 1;
Code := 0;
Si := lHufRA[K].HufSz;//HuffSizeRA[1];
repeat
while (Si = lHufRA[K].HufSz) do begin
lHufRA[K].HufCode := Code;
Code := Code + 1;
Inc(K);
end;
if K <= DHTnLi then begin
while lHufRA[K].HufSz > Si do begin
Code := Code Shl 1;
Si := Si + 1;
end; //while Si
end; //K <= 17
until K >= DHTnLi;
lRawPos := (lSegmentEnd);
end; //DHT Huffman
$DD: begin //Define Restart
lRestartSegmentSz := Readword;
lRawPos := (lSegmentEnd);
end;
$DA: begin //read SOS Scan Header
if SOSns > 0 then goto 666; //multiple SOS!
ReadByte(SOSns);
//if Ns = 1 then NOT interleaved, else interleaved: see B.2.3
SOSarrayPos := lRawPos;
if SOSns > 0 then begin
for lInc := 1 to SOSns do begin
ReadByte( btS1); //component identifier 1=Y,2=Cb,3=Cr,4=I,5=Q
ReadByte(btS2); //horizontal and vertical sampling factors
end;
end;
ReadByte(SOSss); //predictor selection B.3
ReadByte( SOSse);
ReadByte( SOSahal); //lower 4bits= pointtransform
SOSpttrans := SOSahal and 16;
if lverbose then Showmessage('[Predictor: '+inttostr(SOSss)+' PointTransform:'+inttostr(SOSahal)+'] ');
lRawPos := (lSegmentEnd);
end; //SOS - Scan Header
else begin //skip marker segment;
lRawPos := (lSegmentEnd);
end;
end; //case markertype
until (lRawPos >= lRawSz) or (btMarkerType = $DA); {hexDA=Start of scan}
lHdrOK := true; //errors goto label 666, so are NOT OK
lImgStart := lRawPos;
666:
if not lHdrOK then begin
showmessage('Unable to read this file - is it really a JPEG image?');
exit;
end;
lItems := SOFxdim*SOFydim;
if SOFPrecision = 8 then
lSz := 1
else
lSz := 2;
if (lImgTypeC3) and ((lItems *lSz) = lOutPutSz) then begin //loss compressed huffman tables
lCurrentByteVal := SOSahal;
if (lRestartSegmentSz > 0) and ((SOFPrecision<> 8) or (SOSss = 7)) then //add restart support if we evr find any samples to test
showmessage('This image may uses restart markers. Please contact the author.');
//z never used lSOI := lRawPos;
//lnRestart := 0;
//if (SOFPrecision<> 8) and (SOSss = 7) then showmessage('ABBA : predictor = 7');
lCurrentByteVal := SOSahal;
//lEOFX := 0;
//lRestart := 0;
lCurrentBitPos := 9; //read in a new byte
//lCurrentBitPos := 1; //read in a new byte
lItems := SOFxdim*SOFydim;
lINc := 0;
lPredicted := 1 shl (SOFPrecision-1-SOSpttrans);
//showmessage(inttostr(lpredicted));
//showmessage(inttostr(SOSss)+'abba'+inttostr(SOFprecision));
if (SOFPrecision<> 8) then begin //start
{$IFDEF MRICRO}
lImgRA := @lOutSmallRA[1];{set to 1 for MRIcro}
{$ELSE}
lImgRA := @lOutSmallRA[0];{set to 1 for MRIcro, else 0}
{$ENDIF}
FillChar(lImgRA^,lItems*sizeof(word), 0); //zero array
for lIncX := 1 to SOFxdim do begin
inc(lInc); //writenext voxel
if lInc > 1 then lPredicted := lImgRA[lInc-1];
lImgRA[lInc] := lPredicted+DecodePixelDifference;
end; //first line: use prev voxel prediction;
if SOFyDim > 1 then
for lIncY := 2 to SOFyDim do begin
inc(lInc); //write next voxel
lPredicted := lImgRA[lInc-SOFxdim];
lImgRA[lInc] := lPredicted+DecodePixelDifference;
if SOSss = 7 then begin
for lIncX := 2 to SOFxdim do begin
inc(lInc); //writenext voxel
lPredA := lImgRA[lInc-1];
lPredB := lImgRA[lInc-SOFxdim];
lPredA := (lPredA+lPredB) shr 1;
lPredicted := lPredA;
lImgRA[lInc] := lPredicted+DecodePixelDifference;
end; //for lIncX
end else begin //SOSss <> 7 -> predictor
for lIncX := 2 to SOFxdim do begin
inc(lInc); //writenext voxel
lPredicted := lImgRA[lInc-1];
lImgRA[lInc] := lPredicted+DecodePixelDifference;
end; //for lIncX
end; //SOSss predictor
(*if lEOFX <> 0 then begin
showmessage('EOF reached prematurely'+inttostr(lRawPos-lSOI)+' X*Y='+inttostr(lEOFX)+'*'+inttostr(lIncY));
goto 127;
end;*)
end; //for lIncY
end else begin //>8bit data; 8 bit follows
{$IFDEF MRICRO}
lInc := 1;
{$ENDIF}
for lIncX := 1 to SOFxdim do begin //write first line
//if lInc > 0 then lPredicted := lImgRAz[lInc-1];
lImgRAz[lInc] := lPredicted+DecodePixelDifference;
inc(lInc); //writenext voxel
lPredicted := lImgRAz[lInc-1];
end; //first line: use prev voxel prediction;
if lRestartSegmentSz = 0 then lSegmentEnd := lItems
else lSegmentEnd := lRestartSegmentSz;
//lLineStart := lInc;
repeat
if lSegmentEnd > lItems then lSegmentEnd := lItems;
lLineStart := (((lInc div SOFxDim)+1)* SOFxDim){-1};
if lInc > (SOFxDim+1) then
lPredicted := 1 shl (SOFPrecision-1-SOSpttrans)
else
lPredicted := lImgRAz[lInc-SOFxdim];
if SOSss = 7 then begin
for lInc := lInc to (lSegmentEnd-1) do begin
lDecode := DecodePixelDifference;
lImgRAz[lInc] := lPredicted+lDecode;
if lInc+1 = lLineStart then begin//newline
lPredicted := lImgRAz[lInc+1-SOFxdim];
lLineStart := lLineStart + SOFxDim;
end else begin
lPredA := lImgRAz[lInc-1];
lPredB := lImgRAz[lInc-SOFxdim];
lPredA := (lPredA+lPredB) shr 1;
lPredicted := lPredA;
// lPredicted := lImgRAz[lInc];
end;
//inc(lInc); //writenext voxel
end;
end else begin //predictor <> 7
for lInc := lInc to (lSegmentEnd-1) do begin
lDecode := DecodePixelDifference;
lImgRAz[lInc] := lPredicted+lDecode;
if lInc+1 = lLineStart then begin//newline
lPredicted := lImgRAz[lInc+1-SOFxdim];
lLineStart := lLineStart + SOFxDim;
end else
lPredicted := lImgRAz[lInc];
//inc(lInc); //writenext voxel
end;
end; //predictor <> 7
if (lSegmentEnd+1) < lItems then begin
dec(lRawPos);
repeat
while (lRawRA[lRawPos] <> 255) do
inc(lRawPos);
inc(lRawPos);
until (lRawRA[lRawPos] >= $D0) and (lRawRA[lRawPos] <= $D7);
lCurrentByteVal := 0; //not FF
lCurrentBitPos := 9; //read in a new byte
end;
lSegmentEnd := lSegmentEnd + lRestartSegmentSz;
until (lRestartSegmentSz < 1) or ((lSegmentEnd-2) > lItems);
(*if SOFyDim > 1 then
for lIncY := 2 to SOFyDim do begin
//for X = 1 use above voxel for predictor, except if Y=1
lPredicted := lImgRAz[lInc-SOFxdim];
lDecode := DecodePixelDifference;
if (lRestart <> 0) then begin
lPredicted := 1 shl (SOFPrecision-1-SOSpttrans);
lCurrentBitPos := 9; //read in a new byte
lRawPos := lRestart;
lDecode := DecodePixelDifference;
lRestart := 0;
inc(lnRestart);
//lRestartRA[lnRestart] := lInc;
end;
lImgRAz[lInc] := lPredicted+lDecode;
inc(lInc); //write next voxel
if SOSss = 7 then begin
for lIncX := 2 to SOFxdim do begin
lPredA := lImgRAz[lInc-1];
lPredB := lImgRAz[lInc-SOFxdim];
lPredA := (lPredA+lPredB) shr 1;
lPredicted := lPredA;
lImgRAz[lInc] := lPredicted+DecodePixelDifference;
inc(lInc); //writenext voxel
end; //for lIncX
end else begin //SOSss <> 7 predictor
lIncX := 1;
while lIncX < SOFXdim do begin
//for lIncX := 2 to SOFxdim do begin
inc(lIncX);
lPredicted := lImgRAz[lInc-1];
lDecode := DecodePixelDifference;
if (lRestart <> 0) then begin
//if lIncX <> 2 then
lPredicted := 1 shl (SOFPrecision-1-SOSpttrans);
//lpredicted := 0;
lCurrentBitPos := 9; //read in a new byte
lRawPos := lRestart;
lDecode := DecodePixelDifference;
lRestart := 0;
dec(lInc);
inc(lnRestart);
//lRestartRA[lnRestart] := lInc;
dec(lIncX);
//showmessage('restart');
end;
lImgRAz[lInc] := lPredicted+lDecode;
//X problem here
inc(lInc); //writenext voxel
end; //for lIncX
end; //SOSss = 7
end; //for lIncY *)
end; //8<>15data type
end; //ImageType C3 lossless HUFffman compressed
(*if lnRestart > 0 then begin
lStr := '';
lSz := 0;
for k := 1 to lnRestart do begin
lStr := lStr + inttostr(lRestartRA[k]-lSz)+':';
lSz := lRestartRA[k];
end;
showmessage(lStr);
end; *)
end;
end.