a pcd picture is encode in five different sizes: level pixels 8 bit image 24 bit image
base/16 1 128x192 25 kb 74 kb
base/4 2 256x384 99 kb 295 kb
base 3 768x512 394 kb 1200 kb
4*base 4 1536x1024 1600 kb 4800 kb
16*base 5 2048x3072 6300 kb 18900 kb
the first three sub-formats consist of uncoded ycbyr (4:1:1). the last two
sub-formats are encoded in an incremental, but to me unknown way.
therefor i will describe only the first three subtypes:
the image-data of these subtypes start at the respective offsets of 02000h, 0b800h and
30000h. to decode the ycbyr to the more usual rgb-code, three lines of data have to be
read, each consisting of w bytes, where w is the width of the
image-subtype. the first w bytes and the first half of the third w
bytes contain data for the first rgb-line, the second w bytes and the second
half of the third w bytes contain data for a second rgb-line. the exact
decoding is given in the example pascal code below.
the orientation of pcd files is found in the 73rd byte from the start: if
(byte[73] and 63) <> 8 then the orientation is vertical, and you may want to mirror
the image.
if you have any questions or additions, please email me at: [email protected] !
pascal code to decode the first three subtypes of a pcd file.
procedure ycbcr2rgb(y,cb,cr:integer; var
r,g,b:integer);
const c=256;
c11:real= 0.0054980*c;
c12:real= 0.0000000*c;
c13:real= 0.0051681*c;
c21:real= 0.0054980*c;
c22:real=-0.0015446*c;
c23:real=-0.0026325*c;
c31:real= 0.0054980*c;
c32:real= 0.0079533*c;
c33:real= 0.0000000*c;
begin
r:=round(c11*y +c12*(cb-156) +c13*(cr-137));
g:=round(c21*y +c22*(cb-156) +c23*(cr-137));
b:=round(c31*y +c32*(cb-156) +c33*(cr-137));
if r<0 then r:=0;
if g<0 then g:=0;
if b<0 then b:=0;
if r>255 then r:=255;
if g>255 then g:=255;
if b>255 then b:=255;
end;
procedure loadpcd(filename:string);
type buf=array[0..maxlinelen-1] of byte;
buf3=array[0..3*maxlinelen-1] of byte;
var ofs:longint;
infile:file;
y,x,xx:word;
y1,y2,cbcr:buf;
line:buf3;
r,g,b:integer;
function verticalorientation:boolean;
var buf:array[0..127] of byte;
begin
reset(invoer,1);
blockread(invoer,buf,128);
verticalorientation:=(buf[72] and 63)<>8;
end;
begin
assign(infile,filename);
reset(infile,1);
bpp:=24;
case pcdsize of
1: begin
w:=192;
h:=128;
seek(invoer,$2000);
end;
2: begin
w:=384;
h:=256;
seek(invoer,$b800);
end;
3: begin
w:=768;
h:=512;
seek(invoer,$30000);
end;
end;
ofs:=0;
for y:=0 to (h div 2)-1 do
begin
blockread(infile,y1,w);
blockread(infile,y2,w);
blockread(infile,cbcr,w);
xx:=0;
for x:=0 to w-1 do
begin
ycbcr2rgb(y1[x],cbcr[x div 2],cbcr[(w div 2)+(x div 2)],r,g,b);
line[xx]:=b;
line[xx+1]:=g;
line[xx+2]:=r;
inc(xx,3);
end;
{ save your line here ! }
inc(ofs,w*3);
xx:=0;
for x:=0 to w-1 do
begin
ycbcr2rgb(y2[x],cbcr[x div 2],cbcr[(w div 2)+(x div 2)],r,g,b);
line[xx]:=b;
line[xx+1]:=g;
line[xx+2]:=r;
inc(xx,3);
end;
{ save your line here ! }
inc(ofs,w*3);
end;
close(infile);
end;
end;
|