📄 graphiccolor.pas
字号:
//----------------------------------------------------------------------------------------------------------------------
function TColorManager.ComponentGammaConvert(Value: Byte): Byte;
begin
Result := FGammaTable[Value];
end;
//----------------------------------------------------------------------------------------------------------------------
function TColorManager.ComponentScaleConvert(Value: Word): Byte;
begin
Result := MulDiv16(Value, 255, 65535);
end;
//----------------------------------------------------------------------------------------------------------------------
function TColorManager.ComponentScaleGammaConvert(Value: Word): Byte;
begin
Result := FGammaTable[MulDiv16(Value, 255, 65535)];
end;
//----------------------------------------------------------------------------------------------------------------------
function TColorManager.ComponentSwapScaleGammaConvert(Value: Word): Byte;
begin
Result := FGammaTable[MulDiv16(Swap(Value), 255, 65535)];
end;
//----------------------------------------------------------------------------------------------------------------------
function TColorManager.ComponentSwapScaleConvert(Value: Word): Byte;
begin
Result := MulDiv16(Swap(Value), 255, 65535);
end;
//----------------------------------------------------------------------------------------------------------------------
function TColorManager.ComponentSwapConvert(Value: Word): Word;
begin
Result := Swap(Value);
end;
//----------------- row conversion routines ----------------------------------------------------------------------------
// Notes: Each method takes parameters for source and target data as well as the count of pixels to work on. This count
// determines the number of pixels in the target buffer. The actual source count may differ for special color
// schemes (like YCbCr) or interlaced lines.
// Mask is a parameter which determines (in a repeative manner) which source pixel should actually be transferred
// to the target buffer. A 1 in the corresponding bit (MSB is leftmost pixel) causes the transfer to happen.
// Usually, this parameter is $FF to transfer all pixels, but for interlaced images (e.g. as in PNG format)
// this will differ to limit pixel transfers. The bit mask only describes which target pixel is to skip. Source
// pixel must be packed.
// Windows DIBs are always byte aligned, so we don't need checks for byte alignments (in target).
procedure TColorManager.RowConvertBGR2BGR(Source: array of Pointer; Target: Pointer; Count: Cardinal; Mask: Byte);
// same as ConvertBGR2RGB but for BGR target schemes
var
SourceR16,
SourceG16,
SourceB16,
SourceA16: PWord;
SourceR8,
SourceG8,
SourceB8,
SourceA8: PByte;
TargetRun16: PBGR16;
TargetRunA16: PBGRA16;
TargetRun8: PBGR;
TargetRunA8: PBGRA;
BitRun: Byte;
Convert8_8: function(Value: Byte): Byte of object;
Convert16_8: function(Value: Word): Byte of object;
Convert16_8Alpha: function(Value: Word): Byte of object;
Convert16_16: function(Value: Word): Word of object;
SourceIncrement,
TargetIncrement: Cardinal;
CopyAlpha: Boolean;
begin
BitRun := $80;
// determine alpha handling once
CopyAlpha := False;
if coAlpha in FSourceOptions then
begin
SourceIncrement := SizeOf(TRGBA);
TargetIncrement := SizeOf(TRGB);
if coAlpha in FTargetOptions then CopyAlpha := True;
end
else
begin
SourceIncrement := SizeOf(TRGB);
if coAlpha in FTargetOptions then TargetIncrement := SizeOf(TRGBA)
else TargetIncrement := SizeOf(TRGB);
end;
// in planar mode source increment is always 1
if Length(Source) > 1 then SourceIncrement := 1;
case FSourceBPS of
8:
begin
if Length(Source) = 1 then
begin
// interleaved mode
SourceB8 := Source[0];
SourceG8 := SourceB8; Inc(SourceG8);
SourceR8 := SourceG8; Inc(SourceR8);
SourceA8 := SourceR8; Inc(SourceA8);
end
else
begin
SourceB8 := Source[0];
SourceG8 := Source[1];
SourceR8 := Source[2];
if coAlpha in FSourceOptions then SourceA8 := Source[3]
else SourceA8 := nil;
end;
case FTargetBPS of
8: // 888 to 888
begin
if coApplyGamma in FTargetOptions then Convert8_8 := ComponentGammaConvert
else Convert8_8 := ComponentNoConvert8;
if CopyAlpha then
begin
TargetRunA8 := Target;
while Count > 0 do
begin
if Boolean(Mask and BitRun) then
begin
TargetRunA8.R := Convert8_8(SourceR8^);
TargetRunA8.G := Convert8_8(SourceG8^);
TargetRunA8.B := Convert8_8(SourceB8^);
// alpha values are never gamma corrected
TargetRunA8.A := SourceA8^;
Inc(SourceB8, SourceIncrement);
Inc(SourceG8, SourceIncrement);
Inc(SourceR8, SourceIncrement);
Inc(SourceA8, SourceIncrement);
end;
asm ROR BYTE PTR [BitRun], 1 end;
Dec(Count);
Inc(TargetRunA8);
end;
end
else
begin
TargetRun8 := Target;
while Count > 0 do
begin
if Boolean(Mask and BitRun) then
begin
TargetRun8.R := Convert8_8(SourceR8^);
TargetRun8.G := Convert8_8(SourceG8^);
TargetRun8.B := Convert8_8(SourceB8^);
Inc(SourceB8, SourceIncrement);
Inc(SourceG8, SourceIncrement);
Inc(SourceR8, SourceIncrement);
end;
asm ROR BYTE PTR [BitRun], 1 end;
Dec(Count);
Inc(PByte(TargetRun8), TargetIncrement);
end;
end;
end;
16: // 888 to 161616
begin
if coApplyGamma in FTargetOptions then Convert8_8 := ComponentGammaConvert
else Convert8_8 := ComponentNoConvert8;
if coNeedByteSwap in FSourceOptions then Convert16_16 := ComponentSwapConvert
else Convert16_16 := ComponentNoConvert16;
if Length(Source) = 1 then
begin
SourceB8 := Source[0];
SourceG8 := SourceB8; Inc(SourceG8);
SourceR8 := SourceG8; Inc(SourceR8);
SourceA8 := SourceR8; Inc(SourceA8);
end
else
begin
SourceB8 := Source[0];
SourceG8 := Source[1];
SourceR8 := Source[2];
if coAlpha in FSourceOptions then SourceA8 := Source[3]
else SourceA8 := nil;
end;
if CopyAlpha then
begin
TargetRunA16 := Target;
while Count > 0 do
begin
if Boolean(Mask and BitRun) then
begin
TargetRunA16.R := Convert16_16(MulDiv16(Convert8_8(SourceR8^), 65535, 255));
TargetRunA16.G := Convert16_16(MulDiv16(Convert8_8(SourceG8^), 65535, 255));
TargetRunA16.B := Convert16_16(MulDiv16(Convert8_8(SourceB8^), 65535, 255));
TargetRunA16.A := Convert16_16(MulDiv16(SourceA8^, 65535, 255));
Inc(SourceB8, SourceIncrement);
Inc(SourceG8, SourceIncrement);
Inc(SourceR8, SourceIncrement);
Inc(SourceA8, SourceIncrement);
end;
asm ROR BYTE PTR [BitRun], 1 end;
Dec(Count);
Inc(TargetRunA16);
end;
end
else
begin
TargetRun16 := Target;
while Count > 0 do
begin
if Boolean(Mask and BitRun) then
begin
TargetRun16.R := Convert16_16(MulDiv16(Convert8_8(SourceR8^), 65535, 255));
TargetRun16.G := Convert16_16(MulDiv16(Convert8_8(SourceG8^), 65535, 255));
TargetRun16.B := Convert16_16(MulDiv16(Convert8_8(SourceB8^), 65535, 255));
Inc(SourceB8, SourceIncrement);
Inc(SourceG8, SourceIncrement);
Inc(SourceR8, SourceIncrement);
end;
asm ROR BYTE PTR [BitRun], 1 end;
Dec(Count);
Inc(PWord(TargetRun16), TargetIncrement);
end;
end;
end;
end;
end;
16:
begin
if Length(Source) = 1 then
begin
SourceB16 := Source[0];
SourceG16 := SourceB16; Inc(SourceG16);
SourceR16 := SourceG16; Inc(SourceR16);
SourceA16 := SourceR16; Inc(SourceA16);
end
else
begin
SourceB16 := Source[0];
SourceG16 := Source[1];
SourceR16 := Source[2];
if coAlpha in FSourceOptions then SourceA16 := Source[3]
else SourceA16 := nil;
end;
case FTargetBPS of
8: // 161616 to 888
begin
if coApplyGamma in FTargetOptions then
begin
if coNeedByteSwap in FSourceOptions then Convert16_8 := ComponentSwapScaleGammaConvert
else Convert16_8 := ComponentScaleGammaConvert;
end
else
begin
if coNeedByteSwap in FSourceOptions then Convert16_8 := ComponentSwapScaleConvert
else Convert16_8 := ComponentScaleConvert;
end;
// since alpha channels are never gamma corrected we need a separate conversion routine
if coNeedByteSwap in FSourceOptions then Convert16_8Alpha := ComponentSwapScaleConvert
else Convert16_8Alpha := ComponentScaleConvert;
if CopyAlpha then
begin
TargetRunA8 := Target;
while Count > 0 do
begin
if Boolean(Mask and BitRun) then
begin
TargetRunA8.R := Convert16_8(SourceR16^);
TargetRunA8.G := Convert16_8(SourceG16^);
TargetRunA8.B := Convert16_8(SourceB16^);
TargetRunA8.A := Convert16_8Alpha(SourceA16^);
Inc(SourceB16, SourceIncrement);
Inc(SourceG16, SourceIncrement);
Inc(SourceR16, SourceIncrement);
Inc(SourceA16, SourceIncrement);
end;
asm ROR BYTE PTR [BitRun], 1 end;
Dec(Count);
Inc(TargetRunA8);
end;
end
else
begin
TargetRun8 := Target;
while Count > 0 do
begin
if Boolean(Mask and BitRun) then
begin
TargetRun8.R := Convert16_8(SourceR16^);
TargetRun8.G := Convert16_8(SourceG16^);
TargetRun8.B := Convert16_8(SourceB16^);
Inc(SourceB16, SourceIncrement);
Inc(SourceG16, SourceIncrement);
Inc(SourceR16, SourceIncrement);
end;
asm ROR BYTE PTR [BitRun], 1 end;
Dec(Count);
Inc(PByte(TargetRun8), TargetIncrement);
end;
end;
end;
16: // 161616 to 161616
begin
// no gamma correction for 16 bit samples yet
if coNeedByteSwap in FSourceOptions then Convert16_16 := ComponentSwapConvert
else Convert16_16 := ComponentNoConvert16;
if Length(Source) = 1 then
begin
SourceB16 := Source[0];
SourceG16 := SourceB16; Inc(SourceG16);
SourceR16 := SourceG16; Inc(SourceR16);
SourceA16 := SourceR16; Inc(SourceA16);
end
else
begin
SourceB16 := Source[0];
SourceG16 := Source[1];
SourceR16 := Source[2];
if coAlpha in FSourceOptions then SourceA16 := Source[3]
else SourceA16 := nil;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -