📄 jvqpcx.pas
字号:
// monochrome bitmaps
TPrivateBitmap(Self).FImage := QImage_create(
Header.x1 - Header.x0 + 1, Header.y1 - Header.y0 + 1,
PixelFormatMap[PixelFormat], 1, QImageEndian_BigEndian);
if (Width = 0) or (Height = 0) then
Exit; // nothing to do
BytesPerRasterLine := Header.BytesPerLine * Header.Planes;
Decompressed := TMemoryStream.Create;
try
if (Header.Bpp = 8) and (Header.Planes = 1) then
// do not uncompress the appended (uncompressed) palette
Decompressed.CopyFrom(Stream, Stream.Size - Stream.Position - SizeOf(TPcxPalette256))
else
Decompressed.CopyFrom(Stream, Stream.Size - Stream.Position);
// decompress data stream
if Header.Compressed then
RleDecompress(Decompressed);
if (Header.Bpp = 8) and (Header.Planes = 1) then
// append the uncompressed palette
Decompressed.CopyFrom(Stream, SizeOf(TPcxPalette256));
// create palette (if necessary)
if (Header.Bpp = 1) and (Header.Planes = 1) then
begin
Header.Palette16[1].Red := 255;
Header.Palette16[1].Green := 255;
Header.Palette16[1].Blue := 255;
ReadPalette(Self, 2, @Header.Palette16[0]);
end;
if (Header.Bpp = 1) and (Header.Planes = 4) then
begin
ReadPalette(Self, 16, @Header.Palette16[0]);
end
else
if (Header.Bpp = 8) and (Header.Planes = 1) then
begin
Decompressed.Seek(-SizeOf(TPcxPalette256), soFromEnd);
if Decompressed.Read(Palette256, SizeOf(TPcxPalette256)) <> SizeOf(TPcxPalette256) then
raise EPcxError.CreateRes(@RsEPcxPaletteProblem);
if Palette256.Id = $0C then
ReadPalette(Self, 256, @Palette256.Items[0])
else
raise EPcxError.CreateRes(@RsEPcxPaletteProblem);
end;
Decompressed.Position := 0;
// read data
for Y := 0 to Height - 1 do
begin
ByteLine := ScanLine[Y];
if Decompressed.Read(Buffer, BytesPerRasterLine) <> BytesPerRasterLine then
raise EPcxError.CreateRes(@RsEPcxUnknownFormat);
// write data to the ScanLine
if ((Header.Bpp = 1) and (Header.Planes = 1)) or // 1bit
((Header.Bpp = 8) and (Header.Planes = 1)) then // 8bit
// just copy the data
Move(Buffer[0], ByteLine[0], Header.BytesPerLine)
else
if (Header.Bpp = 8) and (Header.Planes = 3) then // 24bit
begin
Line := Pointer(ByteLine);
Buffer2 := @Buffer[Header.BytesPerLine];
Buffer3 := @Buffer[Header.BytesPerLine * 2];
for X := 0 to Width - 1 do
with Line[X] do
begin
rgbRed := Buffer[X];
rgbGreen := Buffer2[X];
rgbBlue := Buffer3[X];
end;
end
else
if (Header.Bpp = 1) and (Header.Planes = 4) then // 4bit
begin
Buffer2 := @Buffer[Header.BytesPerLine];
Buffer3 := @Buffer[Header.BytesPerLine * 2];
Buffer4 := @Buffer[Header.BytesPerLine * 3];
FillChar(ByteLine[0], Width, 0); // VisualCLX uses pf8bit
for X := 0 to Width - 1 do
begin
b := 0;
ByteNum := X div 8;
BitNum := 7 - (X mod 8);
if (Buffer[ByteNum] shr BitNum) and $1 <> 0 then
b := b or $01;
if (Buffer2[ByteNum] shr BitNum) and $1 <> 0 then
b := b or $02;
if (Buffer3[ByteNum] shr BitNum) and $1 <> 0 then
b := b or $04;
if (Buffer4[ByteNum] shr BitNum) and $1 <> 0 then
b := b or $08;
// VisualCLX does not support pf4bit
ByteLine[X] := ByteLine[X] or b;
end;
end;
end;
finally
Decompressed.Free;
end;
Changed(Self);
end;
procedure TJvPcx.SaveToStream(Stream: TStream);
var
CompressStream: TMemoryStream;
Header: TPcxHeader;
X, Y: Integer;
ByteLine: PByteArray;
Line: PJvRGBArray;
Buffer: array [0..MaxPixelCount - 1] of Byte;
Buffer2, Buffer3, Buffer4: PByteArray; // position in Buffer
Palette256: TPcxPalette256;
BytesPerRasterLine: Integer;
b: Byte;
ByteNum, BitNum: Integer;
begin
ImageNeeded;
FillChar(Header, SizeOf(Header), 0);
Header.Id := $0A;
Header.Version := 5; // = 3.0
Header.Compressed := True;
Header.dpiX := 72;
Header.dpiY := 72;
Header.x1 := Width - 1;
Header.y1 := Height - 1;
Header.PaletteType := 1;
CompressStream := TMemoryStream.Create;
try
// complete header
case PixelFormat of
pf1bit:
begin
Header.Bpp := 1;
Header.Planes := 1;
Header.BytesPerLine := (Width + 7) div 8;
Header.Palette16[1].Red := 255;
Header.Palette16[1].Green := 255;
Header.Palette16[1].Blue := 255;
end;
pf8bit:
begin
if QImage_numColors(GetBitmapImage(Self)) <= 16 then
begin
Header.Bpp := 1;
Header.Planes := 4;
Header.BytesPerLine := (Width + 1) div 2;
end
else
begin
Header.Bpp := 8;
Header.Planes := 1;
Header.BytesPerLine := Width;
end;
end;
pf24bit:
begin
Header.Bpp := 8;
Header.Planes := 3;
Header.BytesPerLine := Width;
end;
end;
// round BytesPerPixel to even
BytesPerRasterLine := Header.BytesPerLine; // save it
if Header.BytesPerLine mod 2 = 1 then
Inc(Header.BytesPerLine);
if (PixelFormat = pf8bit) or (PixelFormat = pf4bit) then
// copy first 16 palette entries into the header (also for pf8bit)
WritePalette(Self, 16, @Header.Palette16[0]);
// write header
Stream.Write(Header, SizeOf(Header));
// compress data
for Y := 0 to Height - 1 do
begin
ByteLine := ScanLine[Y];
case Header.Planes * Header.Bpp of // reduces VisualCLX IFDEFs
1, 8:
begin
if Header.BytesPerLine <> BytesPerRasterLine then
begin
Move(ByteLine[0], Buffer, BytesPerRasterLine);
Buffer[BytesPerRasterLine] := 0;
ByteLine := @Buffer[0];
end;
CompressStream.Write(ByteLine[0], Header.BytesPerLine);
end;
4:
begin
BytesPerRasterLine := Header.BytesPerLine * 4;
Buffer2 := @Buffer[Header.BytesPerLine];
Buffer3 := @Buffer[Header.BytesPerLine * 2];
Buffer4 := @Buffer[Header.BytesPerLine * 3];
FillChar(Buffer[0], BytesPerRasterLine, 0);
for X := 0 to Width - 1 do
begin
b := ByteLine[X];
ByteNum := X div 8;
BitNum := 7 - (X mod 8);
if b and $01 <> 0 then
Buffer[ByteNum] := Buffer[ByteNum] or (1 shl BitNum);
if b and $02 <> 0 then
Buffer2[ByteNum] := Buffer2[ByteNum] or (1 shl BitNum);
if b and $04 <> 0 then
Buffer3[ByteNum] := Buffer3[ByteNum] or (1 shl BitNum);
if b and $08 <> 0 then
Buffer4[ByteNum] := Buffer4[ByteNum] or (1 shl BitNum);
end;
CompressStream.Write(Buffer, BytesPerRasterLine);
end;
24:
begin
Line := ScanLine[Y];
Buffer2 := @Buffer[Header.BytesPerLine];
Buffer3 := @Buffer[Header.BytesPerLine * 2];
for X := 0 to Width - 1 do
begin
with Line[X] do
begin
Buffer[X] := rgbRed;
Buffer2[X] := rgbGreen;
Buffer3[X] := rgbBlue;
end;
end;
CompressStream.Write(Buffer, Header.BytesPerLine * 3);
end;
end;
RleCompressTo(CompressStream, Stream);
CompressStream.Size := 0;
end;
// write palette
if PixelFormat = pf8bit then
begin
Palette256.Id := $0C;
WritePalette(Self, 256, @Palette256.Items[0]);
Stream.Write(Palette256, SizeOf(Palette256));
end;
finally
CompressStream.Free;
end;
end;
initialization
TPicture.RegisterFileFormat(RsPcxExtension, RsPcxFilterName, TJvPcx);
finalization
TPicture.UnregisterGraphicClass(TJvPcx);
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -