Hi,
while converting gray 8bit images to float 32bit and back to gray 8 bit I noted that the intensity values dramatically change:
"in128.bmp" is a grayscale bitmap with pixel values of 128
img.CreateFromFile('in128.bmp');
img.Format:=ifGray8;
img.Format:=ifR32F;
img.Format:=ifGray8;
img.SaveToFile('out.bmp');
Now in the "out.bmp" image the pixel values are only 38.
As this is a bit of a problem for my application, I investigated a bit: The root cause seems to be here:
procedure FloatToGray(NumPixels: LongInt; Src, Dst: PByte; SrcInfo,
DstInfo: PImageFormatInfo);
var
I: LongInt;
PixF: TColorFPRec;
Gray: TColor64Rec;
Alpha: Word;
begin
for I := 0 to NumPixels - 1 do
begin
FloatGetSrcPixel(Src, SrcInfo, PixF);
ClampFloatPixel(PixF);
// alpha is saved from source pixel to Alpha,
// Gray value is computed and set to highest word of Pix64 so
// Pix64.Color contains grayscale value scaled to 64 bits
Alpha := ClampToWord(Round(PixF.A * 65535.0));
Gray.A := ClampToWord(Round((GrayConv.R * PixF.R + GrayConv.G * PixF.G +
GrayConv.B * PixF.B) * 65535.0));
GraySetDstPixel(Dst, DstInfo, Gray, Alpha);
Inc(Src, SrcInfo.BytesPerPixel);
Inc(Dst, DstInfo.BytesPerPixel);
end;
end;
Even the float image is single channel, the RGB-> gray conversion is calculated, reducing the pixel values (there is only intensity in red channel and this gets multiplied with GrayConv.R factor.
I workarounded the behaviour using the following approach (don't know if there are side effects). However now the value after conversion is the same as before:
(sry, you have to scroll down a bit maybe ;) )
procedure FloatToGray(NumPixels: LongInt; Src, Dst: PByte; SrcInfo,
DstInfo: PImageFormatInfo);
var
I: LongInt;
PixF: TColorFPRec;
Gray: TColor64Rec;
Alpha: Word;
begin
for I := 0 to NumPixels - 1 do
begin
FloatGetSrcPixel(Src, SrcInfo, PixF);
ClampFloatPixel(PixF);
// alpha is saved from source pixel to Alpha,
// Gray value is computed and set to highest word of Pix64 so
// Pix64.Color contains grayscale value scaled to 64 bits
Alpha := ClampToWord(Round(PixF.A * 65535.0));
if SrcInfo.ChannelCount =1 then
Gray.A := ClampToWord(Round(PixF.R * 65535.0))
else
Gray.A := ClampToWord(Round((GrayConv.R * PixF.R + GrayConv.G * PixF.G +
GrayConv.B * PixF.B) * 65535.0));
GraySetDstPixel(Dst, DstInfo, Gray, Alpha);
Inc(Src, SrcInfo.BytesPerPixel);
Inc(Dst, DstInfo.BytesPerPixel);
end;
end;
Bye...
Thanks for the report, I'll have a look at this.