1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
| unit Unit1;
{$mode objfpc}{$H+}
interface
uses
{$IFDEF LINUX}
BaseUnix, // timespec
Linux, // clock_gettime
{$ENDIF}
LCLtype, LCLintf, Classes, SysUtils, FileUtil, Forms, Controls, Graphics,
Math,
Dialogs, ExtCtrls, StdCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
Image1: TImage;
Image2: TImage;
Panel1: TPanel;
rdg2: TRadioGroup;
rdg1: TRadioGroup;
procedure Button1Click(Sender: TObject);
procedure rdg1SelectionChanged(Sender: TObject);
procedure rdg2SelectionChanged(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
type
TColor2Grayscale = (
c2gAverage,
c2gLightness,
c2gLuminosity
);
TBitmapAccess = (
baScanLine,
baPixels
);
var
c2g: TColor2Grayscale;
ba : TBitmapAccess;
R,G,B: byte;
const
ONE_OVER_MILLION = 1E-6; // micro
ONE_OVER_MILLIER = 1E-3; // milli
{$IFDEF LINUX}
function GetTickCount64: QWord;
var
tp: timespec; // timespec record tv_sec seconds tv_nsec nanoseconds
begin
//clock_gettime(CLOCK_MONOTONIC, @tp); // orig
clock_gettime(CLOCK_MONOTONIC_RAW, @tp);
// multiplier les secondes par 1000 pour pouvoir y ajouter les millisec,
// multiplier les secondes par 1000000 pour pouvoir y ajouter les microsec,
// multiplier les secondes par 1000000000 pour pouvoir y ajouter les nanosec
// du coup le "result" sera le nombre de nsec depuis le démarrage de la machine
Result := (Int64(tp.tv_sec) * 1000000000) + int64(tp.tv_nsec);
end;
{$ENDIF}
function RGBToGray(R, G, B: byte; cg: TColor2Grayscale): TColor;
var
res: Uint;
begin
case cg of
c2gAverage:
res := (R + G + B) div 3;
c2gLightness:
res := ( max(max(R, G), B) + min(min(R, G), B) ) div 2;
c2gLuminosity:
res := round(0.2989*R + 0.5870*G + 0.1141*B); // coeffs from Matlab
else
raise Exception.Create('Unknown Color2Grayscale value');
end;
Result := RGBtoColor(res,res,res);
end;
procedure ColorToGray(aBitmap: Graphics.TBitmap;
cg: TColor2Grayscale;
ba: TBitmapAccess);
var
w, h: UInt;
x: byte;
CurrRow, OffSet: UInt;
pRed, pGreen, pBlue: PByte;
StartTime, StopTime, Delta : QWord;
BW,BH: integer;
begin
{$IFDEF LINUX}
StartTime := GetTickCount64;
{$ENDIF}
BW := aBitmap.Width -1; //Prevent Repeated Calls to TBitMap.Width -- trouvé chez efg
BH := aBitmap.Height-1; //Prevent Repeated Calls to TBitMap.Height
if ba = baPixels then
begin
if aBitmap <> nil then
for h := 0 to BH do
for w := 0 to BW do begin
RedGreenBlue(aBitmap.Canvas.Pixels[w,h], R,G,B);
aBitmap.Canvas.Pixels[w,h] := RGBToGray(R,G,B, cg);
end;
end
else // ba = baScanLine
begin
if aBitmap.PixelFormat <> pf24bit then
raise Exception.Create(
'Not implemented. PixelFormat has to be "pf24bit"');
aBitmap.BeginUpdate();
CurrRow := UInt(aBitmap.RawImage.GetLineStart(0));
OffSet := UInt(aBitmap.RawImage.GetLineStart(1)) - CurrRow;
for h := 0 to BH do
begin
for w := 0 to BW do
begin
pBlue := pByte(CurrRow + w*3);
pGreen := pByte(CurrRow + w*3 + 1);
pRed := pByte(CurrRow + w*3 + 2);
x := RGBToGray(pRed^, pGreen^, pBlue^, cg);
pBlue^ := x;
pGreen^ := x;
pRed^ := x;
end;
inc(CurrRow, OffSet);
end;
aBitmap.EndUpdate();
end;
{$IFDEF LINUX}
StopTime := GetTickCount64;
Delta := StopTime - StartTime;
Form1.Caption := FloatToStr(Delta * ONE_OVER_MILLIER) + ' microsecondes';
{$ENDIF}
end;
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
begin
image1.Picture.Bitmap.LoadFromFile(Application.Location + '150x100x24x72_v2.bmp');
image2.Picture.Bitmap.Assign(image1.Picture.Bitmap);
ColorToGray(image2.Picture.Bitmap, c2g, ba);
end;
procedure TForm1.rdg1SelectionChanged(Sender: TObject);
begin
case rdg1.ItemIndex of
0: c2g := c2gAverage;
1: c2g := c2gLightness;
2: c2g := c2gLuminosity;
end;
end;
procedure TForm1.rdg2SelectionChanged(Sender: TObject);
begin
case rdg2.ItemIndex of
0: ba := baScanLine;
1: ba := baPixels;
end;
end;
end. |
Partager