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 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
| unit FileHole_MainForm;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.ComCtrls;
type
TForm1 = class(TForm)
btnBuild: TButton;
edWidth: TLabeledEdit;
edHeight: TLabeledEdit;
Image1: TImage;
pcImages: TPageControl;
tsImageOriginale: TTabSheet;
tsImageFilled: TTabSheet;
pnlActionTop: TPanel;
Image2: TImage;
btnFill: TButton;
procedure btnBuildClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure btnFillClick(Sender: TObject);
private
{ Déclarations privées }
public
{ Déclarations publiques }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btnBuildClick(Sender: TObject);
var
X: Integer;
Y: Integer;
Line: PByteArray;
begin
Image1.AutoSize := False;
try
Image1.Picture.Assign(nil);
Image1.Picture.Bitmap.Width := StrToInt(edWidth.Text);
Image1.Picture.Bitmap.Height := StrToInt(edHeight.Text);
Image1.Picture.Bitmap.PixelFormat := pf8bit; // Comme Andnotor pour du 0 à 255
Image1.Picture.Bitmap.Canvas.Lock(); // Delphi n'a pas de BeginUpdate pour le Canvas ???
try
for Y := 0 to Image1.Picture.Bitmap.Height - 1 do
begin
Line := Image1.Picture.Bitmap.ScanLine[Y];
for X := 0 to Image1.Picture.Bitmap.Width - 1 do
begin
if LongBool(Random(4)) then
Line[X] := 254 - Random(6) //Random(High(Byte) - 1) + 1
else
Line[X] := 0;
end;
end;
finally
Image1.Picture.Bitmap.Canvas.Unlock();
end;
finally
Image1.AutoSize := True;
end;
end;
procedure TForm1.btnFillClick(Sender: TObject);
type
TOccurrence = record
Value: Byte;
Counter: Integer;
end;
var
Occurrences: array[1..8] of TOccurrence;
OccurrenceHigh: Integer;
Occurrence: TOccurrence;
function IndexOfOccurrence(B: Byte): Integer;
begin
for Result := Low(Occurrences) to OccurrenceHigh do
if Occurrences[Result].Value = B then
Exit;
Result := -1;
end;
procedure UpdateOccurrence(B: Byte);
var
OccurrenceFound: Integer;
begin
if B > 0 then
begin
OccurrenceFound := IndexOfOccurrence(B);
if OccurrenceFound <= 0 then
begin
Inc(OccurrenceHigh);
Occurrences[OccurrenceHigh].Value := B;
OccurrenceFound := OccurrenceHigh;
end;
Inc(Occurrences[OccurrenceFound].Counter);
if Occurrence.Counter < Occurrences[OccurrenceFound].Counter then
Occurrence := Occurrences[OccurrenceFound];
end;
end;
var
X: Integer;
Y: Integer;
MatrixSource: array[0..2] of PByteArray;
MatrixDestination: array[0..2] of PByteArray;
I: Integer;
begin
Image2.AutoSize := False;
try
Image2.Picture.Assign(nil);
Image2.Picture.Bitmap.Width := Image1.Picture.Bitmap.Width;
Image2.Picture.Bitmap.Height := Image1.Picture.Bitmap.Height;
Image2.Picture.Bitmap.PixelFormat := pf8bit; // Comme Andnotor pour du 0 à 255
Image2.Picture.Bitmap.Canvas.Lock();
try
ZeroMemory(@MatrixSource, SizeOf(MatrixSource));
ZeroMemory(@MatrixDestination, SizeOf(MatrixDestination));
if Image1.Picture.Bitmap.Height >= 2 then
begin
MatrixSource[2] := Image1.Picture.Bitmap.ScanLine[1];
MatrixDestination[2] := Image2.Picture.Bitmap.ScanLine[1];
end;
for Y := 0 to Image1.Picture.Bitmap.Height - 1 do
begin
MatrixSource[1] := Image1.Picture.Bitmap.ScanLine[Y];
// Destination différente de la source, le calcul ne s'influence pas lui-même, cela peut créer des zones incalculables mais c'est d'autant plus intéressant
MatrixDestination[1] := Image2.Picture.Bitmap.ScanLine[Y];
// Altération de l'image d'origine, impact les couleurs calculées seront utilisées pour les calculs suivants
// Move(MatrixSource, MatrixDestination, SizeOf(MatrixDestination));
// Intéressant de générer une matrice séparée, on voit uniquement les zones bouchées
//Move(MatrixSource[1]^, MatrixDestination[1]^, Image1.Picture.Bitmap.Width * SizeOf(Byte));
for X := 0 to Image1.Picture.Bitmap.Width - 1 do
begin
if MatrixSource[1, X] = 0 then
begin
OccurrenceHigh := 0;
ZeroMemory(@Occurrences, SizeOf(Occurrences));
ZeroMemory(@Occurrence, SizeOf(Occurrence));
if Assigned(MatrixSource[0]) then
for I := 0 to 2 do
UpdateOccurrence(MatrixSource[0, I]);
UpdateOccurrence(MatrixSource[1, 0]);
UpdateOccurrence(MatrixSource[1, 2]);
if Assigned(MatrixSource[2]) and (Occurrence.Counter < 4) then
for I := 0 to 2 do
UpdateOccurrence(MatrixSource[2, I]);
if Occurrence.Counter > 1 then
MatrixDestination[1, X] := Occurrence.Value
else
MatrixDestination[1, X] := 255; // Qui favoriser en cas d'égalité ?
end;
end;
for I := 1 to 2 do
begin
MatrixSource[I - 1] := MatrixSource[I];
MatrixDestination[I - 1] := MatrixDestination[I];
end;
if Image1.Picture.Bitmap.Height - 1 = Y then
begin
MatrixSource[2] := nil;
MatrixDestination[2] := nil;
end;
end;
finally
Image2.Picture.Bitmap.Canvas.Unlock();
Image1.Invalidate;
end;
finally
Image2.AutoSize := True;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Randomize();
end;
end. |
Partager