mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-17 13:59:29 +02:00
* Apply Merge request !468 (use JPEG out_color_space)
This commit is contained in:
parent
89bcc82843
commit
30e7bfb666
@ -277,6 +277,10 @@ type
|
||||
function ToExpanded(AGammaExpansion: boolean = true): TExpandedPixel;
|
||||
function ToHSLAPixel(AGammaExpansion: boolean = true): THSLAPixel;
|
||||
function ToGSBAPixel(AGammaExpansion: boolean = true): TGSBAPixel;
|
||||
function ToStdRGBA: TStdRGBA;
|
||||
function ToStdHSLA: TStdHSLA;
|
||||
function ToStdHSVA: TStdHSVA;
|
||||
function ToStdCMYK: TStdCMYK;
|
||||
end;
|
||||
|
||||
{ TExpandedPixelHelper }
|
||||
@ -300,11 +304,15 @@ type
|
||||
{ TStdRGBAHelper }
|
||||
|
||||
TStdRGBAHelper = record helper for TStdRGBA
|
||||
function ToFPColor: TFPColor;
|
||||
function ToExpandedPixel: TExpandedPixel;
|
||||
function ToLinearRGBA: TLinearRGBA;
|
||||
function ToStdHSLA: TStdHSLA;
|
||||
function ToStdHSVA: TStdHSVA;
|
||||
function ToStdCMYK: TStdCMYK;
|
||||
{** SamplePrecision = 2^(YCbCrSamplePrecision-1) }
|
||||
function ToYCbCr(const AStd:TYCbCrSTD=YCbCr_JPG; ASamplePrecision:Single=0.5): TYCbCr; overload;
|
||||
function ToYCbCr(LumaRed:Single=0.299; LumaGreen:Single=0.587; LumaBlue:Single=0.114): TYCbCr; overload;
|
||||
end;
|
||||
|
||||
{ TAdobeRGBAHelper }
|
||||
@ -317,6 +325,7 @@ type
|
||||
{ TStdHSLAHelper }
|
||||
|
||||
TStdHSLAHelper = record helper for TStdHSLA
|
||||
function ToFPColor: TFPColor;
|
||||
function ToStdRGBA: TStdRGBA;
|
||||
function ToStdHSVA: TStdHSVA;
|
||||
function ToExpandedPixel: TExpandedPixel;
|
||||
@ -325,6 +334,7 @@ type
|
||||
{ TStdHSVAHelper }
|
||||
|
||||
TStdHSVAHelper = record helper for TStdHSVA
|
||||
function ToFPColor: TFPColor;
|
||||
function ToStdRGBA: TStdRGBA;
|
||||
function ToStdHSLA: TStdHSLA;
|
||||
end;
|
||||
@ -332,6 +342,7 @@ type
|
||||
{ TStdCMYKHelper }
|
||||
|
||||
TStdCMYKHelper = record helper for TStdCMYK
|
||||
function ToFPColor(const AAlpha: Word=$ffff): TFPColor;
|
||||
function ToStdRGBA(AAlpha: Single = 1): TStdRGBA;
|
||||
function ToExpandedPixel: TExpandedPixel;overload;
|
||||
function ToExpandedPixel(AAlpha: word): TExpandedPixel;overload;
|
||||
@ -350,9 +361,6 @@ type
|
||||
function ToXYZA: TXYZA; overload;
|
||||
function ToXYZA(const AReferenceWhite: TXYZReferenceWhite): TXYZA; overload;
|
||||
function ToStdRGBA: TStdRGBA;
|
||||
{** SamplePrecision = 2^(YCbCrSamplePrecision-1) }
|
||||
function ToYCbCr(const AStd:TYCbCrSTD=YCbCr_JPG; ASamplePrecision:Single=0.5): TYCbCr; overload;
|
||||
function ToYCbCr(LumaRed:Single=0.299; LumaGreen:Single=0.587; LumaBlue:Single=0.114): TYCbCr; overload;
|
||||
end;
|
||||
|
||||
{ TXYZAHelper }
|
||||
@ -399,8 +407,8 @@ type
|
||||
|
||||
TYCbCrHelper = record helper for TYCbCr
|
||||
{** SamplePrecision = 2^(YCbCrSamplePrecision-1) }
|
||||
function ToLinearRGBA(const AStd:TYCbCrSTD=YCbCr_JPG; ASamplePrecision:Single=0.5): TLinearRGBA; overload;
|
||||
function ToLinearRGBA(LumaRed:Single=0.299; LumaGreen:Single=0.587; LumaBlue:Single=0.114): TLinearRGBA; overload;
|
||||
function ToStdRGBA(const AStd:TYCbCrSTD=YCbCr_601; ASamplePrecision:Single=0.5): TStdRGBA; overload;
|
||||
function ToStdRGBA(LumaRed:Single=0.299; LumaGreen:Single=0.587; LumaBlue:Single=0.114; ASamplePrecision:Single=0.5): TStdRGBA; overload;
|
||||
end;
|
||||
|
||||
{* How to handle overflow when converting from XYZ }
|
||||
@ -1396,6 +1404,30 @@ begin
|
||||
result.FromFPColor(self, AGammaExpansion);
|
||||
end;
|
||||
|
||||
function TFPColorHelper.ToStdRGBA: TStdRGBA;
|
||||
const oneOver65535 = 1/65535;
|
||||
begin
|
||||
result.red := red * oneOver65535;
|
||||
result.green := green * oneOver65535;
|
||||
result.blue := blue * oneOver65535;
|
||||
result.alpha := alpha * oneOver65535;
|
||||
end;
|
||||
|
||||
function TFPColorHelper.ToStdHSLA: TStdHSLA;
|
||||
begin
|
||||
result :=self.ToStdRGBA.ToStdHSLA;
|
||||
end;
|
||||
|
||||
function TFPColorHelper.ToStdHSVA: TStdHSVA;
|
||||
begin
|
||||
result :=self.ToStdRGBA.ToStdHSVA;
|
||||
end;
|
||||
|
||||
function TFPColorHelper.ToStdCMYK: TStdCMYK;
|
||||
begin
|
||||
result :=self.ToStdRGBA.ToStdCMYK;
|
||||
end;
|
||||
|
||||
{ TExpandedPixelHelper }
|
||||
|
||||
function TExpandedPixelHelper.ToHSLAPixel: THSLAPixel;
|
||||
@ -1470,6 +1502,14 @@ end;
|
||||
|
||||
{ TStdRGBAHelper }
|
||||
|
||||
function TStdRGBAHelper.ToFPColor: TFPColor;
|
||||
begin
|
||||
result.red := ClampInt(round(red * 65535), 0, 65535);
|
||||
result.green := ClampInt(round(green * 65535), 0, 65535);
|
||||
result.blue := ClampInt(round(blue * 65535), 0, 65535);
|
||||
result.alpha := ClampInt(round(alpha * 65535), 0, 65535);
|
||||
end;
|
||||
|
||||
function TStdRGBAHelper.ToExpandedPixel: TExpandedPixel;
|
||||
begin
|
||||
result.red := FPGammaExpansion(self.red);
|
||||
@ -1576,6 +1616,26 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TStdRGBAHelper.ToYCbCr(const AStd: TYCbCrSTD; ASamplePrecision:Single=0.5): TYCbCr;
|
||||
begin
|
||||
with self, YCbCrSTD_Factors[AStd] do
|
||||
begin
|
||||
result.Y := a * red + b * green + c * blue;
|
||||
result.Cb := ((blue - result.Y) / d)+ASamplePrecision;
|
||||
result.Cr := ((red - result.Y) / e)+ASamplePrecision;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TStdRGBAHelper.ToYCbCr(LumaRed: Single; LumaGreen: Single; LumaBlue: Single): TYCbCr;
|
||||
begin
|
||||
with self do
|
||||
begin
|
||||
result.Y := ( LumaRed * red + LumaGreen * green + LumaBlue * blue );
|
||||
result.Cb := ( blue - result.Y ) / ( 2 - 2 * LumaBlue );
|
||||
result.Cr := ( red - result.Y ) / ( 2 - 2 * LumaRed );
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TAdobeRGBAHelper }
|
||||
|
||||
function TAdobeRGBAHelper.ToXYZA: TXYZA;
|
||||
@ -1608,6 +1668,11 @@ end;
|
||||
|
||||
{ TStdHSLAHelper }
|
||||
|
||||
function TStdHSLAHelper.ToFPColor: TFPColor;
|
||||
begin
|
||||
result :=self.ToStdRGBA.ToFPColor;
|
||||
end;
|
||||
|
||||
function TStdHSLAHelper.ToStdRGBA: TStdRGBA;
|
||||
var
|
||||
C, X, M, rp, gp, bp, sp, lp, h360: single;
|
||||
@ -1687,6 +1752,11 @@ end;
|
||||
|
||||
{ TStdHSVAHelper }
|
||||
|
||||
function TStdHSVAHelper.ToFPColor: TFPColor;
|
||||
begin
|
||||
result :=self.ToStdRGBA.ToFPColor;
|
||||
end;
|
||||
|
||||
function TStdHSVAHelper.ToStdRGBA: TStdRGBA;
|
||||
var
|
||||
C, X, M, rp, gp, bp, sp, vp: single;
|
||||
@ -1775,24 +1845,30 @@ end;
|
||||
|
||||
function TStdCMYKHelper.ToExpandedPixel: TExpandedPixel;
|
||||
begin
|
||||
self.ToStdRGBA.ToExpandedPixel;
|
||||
result :=self.ToStdRGBA.ToExpandedPixel;
|
||||
end;
|
||||
|
||||
function TStdCMYKHelper.ToExpandedPixel(AAlpha: word): TExpandedPixel;
|
||||
begin
|
||||
self.ToStdRGBA(AAlpha).ToExpandedPixel;
|
||||
result :=self.ToStdRGBA(AAlpha).ToExpandedPixel;
|
||||
end;
|
||||
|
||||
function TStdCMYKHelper.ToFPColor(const AAlpha: Word): TFPColor;
|
||||
begin
|
||||
result :=self.ToStdRGBA.ToFPColor;
|
||||
result.alpha := AAlpha
|
||||
end;
|
||||
|
||||
{ TLabAHelper }
|
||||
|
||||
function TLabAHelper.ToExpandedPixel: TExpandedPixel;
|
||||
begin
|
||||
self.ToXYZA.ToLinearRGBA.ToExpandedPixel;
|
||||
result :=self.ToXYZA.ToLinearRGBA.ToExpandedPixel;
|
||||
end;
|
||||
|
||||
function TLabAHelper.ToExpandedPixel(const AReferenceWhite: TXYZReferenceWhite): TExpandedPixel;
|
||||
begin
|
||||
self.ToXYZA(AReferenceWhite).ToLinearRGBA(AReferenceWhite).ToExpandedPixel;
|
||||
result :=self.ToXYZA(AReferenceWhite).ToLinearRGBA(AReferenceWhite).ToExpandedPixel;
|
||||
end;
|
||||
|
||||
function TLabAHelper.ToXYZA: TXYZA;
|
||||
@ -1854,22 +1930,25 @@ end;
|
||||
|
||||
{ TYCbCrHelper }
|
||||
|
||||
function TYCbCrHelper.ToLinearRGBA(const AStd: TYCbCrSTD; ASamplePrecision:Single): TLinearRGBA;
|
||||
function TYCbCrHelper.ToStdRGBA(const AStd: TYCbCrSTD; ASamplePrecision:Single): TStdRGBA;
|
||||
begin
|
||||
with self, YCbCrSTD_Factors[AStd] do
|
||||
begin
|
||||
//"analog" Y is in the range 0 to 1 ; Cb and Cr in the range -0.5 to +0.5
|
||||
//"digital" are normalized to 0..255; In 601 Standard values are between 16 and 235 for Y, 16 to 240 for Cb and Cr.
|
||||
|
||||
result.red := Y + e * (Cr-ASamplePrecision);
|
||||
result.green := Y - (a * e / b) * (Cr-ASamplePrecision) - (c * d / b) * (Cb-ASamplePrecision);
|
||||
result.blue := Y + d * (Cb-ASamplePrecision);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TYCbCrHelper.ToLinearRGBA(LumaRed: Single; LumaGreen: Single; LumaBlue: Single): TLinearRGBA;
|
||||
function TYCbCrHelper.ToStdRGBA(LumaRed: Single; LumaGreen: Single; LumaBlue: Single; ASamplePrecision:Single): TStdRGBA;
|
||||
begin
|
||||
with self do
|
||||
begin
|
||||
result.red := Cr * ( 2 - 2 * LumaRed ) + Y;
|
||||
result.blue := Cb * ( 2 - 2 * LumaBlue ) + Y;
|
||||
result.red := (Cr-ASamplePrecision) * ( 2 - 2 * LumaRed ) + Y;
|
||||
result.blue := (Cb-ASamplePrecision) * ( 2 - 2 * LumaBlue ) + Y;
|
||||
result.green := ( Y - LumaBlue * result.blue - LumaRed * result.red ) / LumaGreen;
|
||||
end;
|
||||
end;
|
||||
@ -1933,26 +2012,6 @@ begin
|
||||
result.alpha := self.alpha;
|
||||
end;
|
||||
|
||||
function TLinearRGBAHelper.ToYCbCr(const AStd: TYCbCrSTD; ASamplePrecision:Single=0.5): TYCbCr;
|
||||
begin
|
||||
with self, YCbCrSTD_Factors[AStd] do
|
||||
begin
|
||||
result.Y := a * red + b * green + c * blue;
|
||||
result.Cb := ((blue - result.Y) / d)+ASamplePrecision;
|
||||
result.Cr := ((red - result.Y) / e)+ASamplePrecision;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TLinearRGBAHelper.ToYCbCr(LumaRed: Single; LumaGreen: Single; LumaBlue: Single): TYCbCr;
|
||||
begin
|
||||
with self do
|
||||
begin
|
||||
result.Y := ( LumaRed * red + LumaGreen * green + LumaBlue * blue );
|
||||
result.Cb := ( blue - result.Y ) / ( 2 - 2 * LumaBlue );
|
||||
result.Cr := ( red - result.Y ) / ( 2 - 2 * LumaRed );
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TXYZAHelper }
|
||||
|
||||
function TXYZAHelper.ToLinearRGBA: TLinearRGBA;
|
||||
|
@ -109,6 +109,25 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
uses FPColorSpace;
|
||||
|
||||
type
|
||||
int_Color_Table = array[0..MAXJSAMPLE+1-1] of int;
|
||||
int_table_ptr = ^int_Color_Table;
|
||||
INT32_Color_Table = array[0..MAXJSAMPLE+1-1] of INT32;
|
||||
INT32_table_ptr = ^INT32_Color_Table;
|
||||
my_cconvert_ptr = ^my_color_deconverter;
|
||||
my_color_deconverter = record
|
||||
pub : jpeg_color_deconverter; { public fields }
|
||||
|
||||
{ Private state for YCC^.RGB conversion }
|
||||
Cr_r_tab : int_table_ptr; { => table for Cr to R conversion }
|
||||
Cb_b_tab : int_table_ptr; { => table for Cb to B conversion }
|
||||
Cr_g_tab : INT32_table_ptr; { => table for Cr to G conversion }
|
||||
Cb_g_tab : INT32_table_ptr; { => table for Cb to G conversion }
|
||||
end;
|
||||
|
||||
|
||||
procedure ReadCompleteStreamToStream(SrcStream, DestStream: TStream;
|
||||
StartSize: integer);
|
||||
var
|
||||
@ -353,24 +372,15 @@ var
|
||||
Result.alpha:=alphaOpaque;
|
||||
end;
|
||||
|
||||
function CorrectYCCK(const C: TFPColor): TFPColor;
|
||||
var
|
||||
MinColor: word;
|
||||
begin
|
||||
if C.red<C.green then MinColor:=C.red
|
||||
else MinColor:= C.green;
|
||||
if C.blue<MinColor then MinColor:= C.blue;
|
||||
if MinColor+ C.alpha>$FF then MinColor:=$FF-C.alpha;
|
||||
Result.red:=(C.red-MinColor) shl 8;
|
||||
Result.green:=(C.green-MinColor) shl 8;
|
||||
Result.blue:=(C.blue-MinColor) shl 8;
|
||||
Result.alpha:=alphaOpaque;
|
||||
end;
|
||||
|
||||
|
||||
procedure OutputScanLines();
|
||||
var
|
||||
x: integer;
|
||||
//ycbcr:TYCbCr;
|
||||
cmyk:TStdCMYK;
|
||||
yy,cb,cr :Int;
|
||||
shift_temp : INT32;
|
||||
cconvert : my_cconvert_ptr;
|
||||
|
||||
begin
|
||||
Color.Alpha:=alphaOpaque;
|
||||
y:=0;
|
||||
@ -381,41 +391,68 @@ var
|
||||
ReturnValue:=false;
|
||||
break;
|
||||
end;
|
||||
if (FInfo.jpeg_color_space = JCS_CMYK) then
|
||||
for x:=0 to FInfo.output_width-1 do begin
|
||||
Color.Red:=SampRow^[x*4+0];
|
||||
Color.Green:=SampRow^[x*4+1];
|
||||
Color.Blue:=SampRow^[x*4+2];
|
||||
Color.alpha:=SampRow^[x*4+3];
|
||||
SetPixel(x, y, CorrectCMYK(Color));
|
||||
end
|
||||
|
||||
Case FInfo.out_color_space of
|
||||
JCS_GRAYSCALE :
|
||||
for x:=0 to FInfo.output_width-1 do
|
||||
begin
|
||||
c:= SampRow^[x] shl 8;
|
||||
Color.Red:=c;
|
||||
Color.Green:=c;
|
||||
Color.Blue:=c;
|
||||
SetPixel(x, y, Color);
|
||||
end;
|
||||
JCS_YCbCr :
|
||||
for x:=0 to FInfo.output_width-1 do
|
||||
begin
|
||||
//MaxM: YCbCr is defined per CCIR 601-1
|
||||
// Y (0 to 1.0) and Cb,Cr (-0.5 to 0.5) is normalized to the range 0..MAXJSAMPLE
|
||||
// We have two ways to convert them, the most accurate is to denormalize
|
||||
// the values like the following commented code, or as is and set SamplePrecision to CENTERJSAMPLE
|
||||
// ycbcr.Y :=SampRow^[x*3+0]/256;
|
||||
// ycbcr.Cb :=(SampRow^[x*3+1]-128)/256;
|
||||
// ycbcr.Cr :=(SampRow^[x*3+2]-128)/256;
|
||||
//ycbcr :=TYCbCr.New(SampRow^[x*3+0], SampRow^[x*3+1], SampRow^[x*3+2]);
|
||||
//SetPixel(x, y, ycbcr.ToStdRGBA(YCBCr_601, CENTERJSAMPLE).ToExpandedPixel.ToFPColor(false));
|
||||
|
||||
//Use the same Code of PasJPeg (ycc_rgb_convert function)
|
||||
yy :=SampRow^[x*3+0];
|
||||
cb :=SampRow^[x*3+1];
|
||||
cr :=SampRow^[x*3+2];
|
||||
cconvert :=my_cconvert_ptr(FInfo.cconvert);
|
||||
Color.Red := (FInfo.sample_range_limit^[yy + cconvert^.Cr_r_tab^[cr]]);
|
||||
shift_temp := cconvert^.Cb_g_tab^[cb] + cconvert^.Cr_g_tab^[cr];
|
||||
if shift_temp < 0 then { SHIFT arithmetic RIGHT }
|
||||
Color.Green := (FInfo.sample_range_limit^[yy + int((shift_temp shr 16)
|
||||
or ( (not INT32(0)) shl (32-16)))])
|
||||
else
|
||||
Color.Green := (FInfo.sample_range_limit^[yy + int(shift_temp shr 16)]);
|
||||
|
||||
Color.Blue := (FInfo.sample_range_limit^[yy + cconvert^.Cb_b_tab^[cb]]);
|
||||
|
||||
Color.Red:=Color.Red shl 8;
|
||||
Color.Green:=Color.Green shl 8;
|
||||
Color.Blue:=Color.Blue shl 8;
|
||||
|
||||
SetPixel(x, y, Color);
|
||||
end;
|
||||
JCS_CMYK, JCS_YCCK:
|
||||
for x:=0 to FInfo.output_width-1 do
|
||||
begin
|
||||
//SetPixel(x, y, CorrectCMYK(TFPColor.New(SampRow^[x*4+0], SampRow^[x*4+1], SampRow^[x*4+2], SampRow^[x*4+3])));
|
||||
|
||||
cmyk :=TStdCMYK.New(SampRow^[x*4+0], SampRow^[x*4+1], SampRow^[x*4+2], SampRow^[x*4+3]);
|
||||
SetPixel(x, y, cmyk.ToExpandedPixel.ToFPColor(false));
|
||||
end;
|
||||
else
|
||||
if (FInfo.jpeg_color_space = JCS_YCCK) then
|
||||
for x:=0 to FInfo.output_width-1 do begin
|
||||
Color.Red:=SampRow^[x*4+0];
|
||||
Color.Green:=SampRow^[x*4+1];
|
||||
Color.Blue:=SampRow^[x*4+2];
|
||||
Color.alpha:=SampRow^[x*4+3];
|
||||
SetPixel(x, y, CorrectYCCK(Color));
|
||||
end
|
||||
else
|
||||
if fgrayscale then begin
|
||||
for x:=0 to FInfo.output_width-1 do begin
|
||||
c:= SampRow^[x] shl 8;
|
||||
Color.Red:=c;
|
||||
Color.Green:=c;
|
||||
Color.Blue:=c;
|
||||
SetPixel(x, y, Color);
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
for x:=0 to FInfo.output_width-1 do begin
|
||||
Color.Red:=SampRow^[x*3+0] shl 8;
|
||||
Color.Green:=SampRow^[x*3+1] shl 8;
|
||||
Color.Blue:=SampRow^[x*3+2] shl 8;
|
||||
SetPixel(x, y, Color);
|
||||
end;
|
||||
for x:=0 to FInfo.output_width-1 do begin
|
||||
Color.Red:=SampRow^[x*3+0] shl 8;
|
||||
Color.Green:=SampRow^[x*3+1] shl 8;
|
||||
Color.Blue:=SampRow^[x*3+2] shl 8;
|
||||
SetPixel(x, y, Color);
|
||||
end;
|
||||
end;
|
||||
|
||||
inc(y);
|
||||
end;
|
||||
end;
|
||||
|
@ -1928,7 +1928,8 @@ var
|
||||
//MaxM: Test the difference
|
||||
// result:=CMYKToFPColor(ChannelValues[0],ChannelValues[1],ChannelValues[2],ChannelValues[3]);
|
||||
cmyk :=TStdCMYK.New(ChannelValues[0]/$ffff, ChannelValues[1]/$ffff, ChannelValues[2]/$ffff, ChannelValues[3]/$ffff);
|
||||
result :=cmyk.ToExpandedPixel.ToFPColor(true); //MaxM: in Future we can use GammaCompression
|
||||
result :=cmyk.ToExpandedPixel.ToFPColor(true); //Use of GammaCompression or direct?
|
||||
//result :=cmyk.ToFPColor;
|
||||
end;
|
||||
|
||||
6: // YCBCR: CCIR 601
|
||||
@ -1936,8 +1937,8 @@ var
|
||||
ycbcr :=TYCbCr.New(ChannelValues[0]/$ffff, ChannelValues[1]/$ffff, ChannelValues[2]/$ffff);
|
||||
|
||||
if IFD.YCbCr_LumaRed<>0
|
||||
then result :=ycbcr.ToLinearRGBA(IFD.YCbCr_LumaRed, IFD.YCbCr_LumaGreen, IFD.YCbCr_LumaBlue).ToExpandedPixel.ToFPColor(false)
|
||||
else result :=ycbcr.ToLinearRGBA(YCbCr_601).ToExpandedPixel.ToFPColor(false);
|
||||
then result :=ycbcr.ToStdRGBA(IFD.YCbCr_LumaRed, IFD.YCbCr_LumaGreen, IFD.YCbCr_LumaBlue).ToFPColor
|
||||
else result :=ycbcr.ToStdRGBA(YCbCr_601).ToFPColor;
|
||||
end;
|
||||
|
||||
//8: CIELAB: 1976 CIE L*a*b*
|
||||
|
Loading…
Reference in New Issue
Block a user