|
1 | 1 | (******************************************************************************) |
2 | 2 | (* Autostereogram 30.11.2025 *) |
3 | 3 | (* *) |
4 | | -(* Version : 0.01 *) |
| 4 | +(* Version : 0.02 *) |
5 | 5 | (* *) |
6 | 6 | (* Author : Uwe Schächterle (Corpsman) *) |
7 | 7 | (* *) |
|
23 | 23 | (* Known Issues: none *) |
24 | 24 | (* *) |
25 | 25 | (* History : 0.01 - Initial version *) |
| 26 | +(* 0.02 - Load "finished" images for testing via contextmenu *) |
| 27 | +(* ADD: ability to tweak depth image before converting *) |
26 | 28 | (* *) |
27 | 29 | (******************************************************************************) |
28 | 30 | Unit Unit1; |
|
48 | 50 | Image2: TImage; |
49 | 51 | Image3: TImage; |
50 | 52 | Label1: TLabel; |
| 53 | + Label10: TLabel; |
| 54 | + Label11: TLabel; |
| 55 | + Label12: TLabel; |
51 | 56 | Label2: TLabel; |
52 | 57 | Label3: TLabel; |
53 | 58 | Label4: TLabel; |
54 | 59 | Label5: TLabel; |
55 | 60 | Label6: TLabel; |
56 | 61 | Label7: TLabel; |
57 | 62 | Label8: TLabel; |
| 63 | + Label9: TLabel; |
58 | 64 | MenuItem1: TMenuItem; |
| 65 | + MenuItem2: TMenuItem; |
59 | 66 | OpenDialog1: TOpenDialog; |
60 | 67 | PopupMenu1: TPopupMenu; |
61 | 68 | SaveDialog1: TSaveDialog; |
62 | 69 | ScrollBar1: TScrollBar; |
63 | 70 | ScrollBar2: TScrollBar; |
| 71 | + ScrollBar3: TScrollBar; |
| 72 | + ScrollBar4: TScrollBar; |
64 | 73 | Procedure Button1Click(Sender: TObject); |
65 | 74 | Procedure Button2Click(Sender: TObject); |
66 | 75 | Procedure Button3Click(Sender: TObject); |
67 | 76 | Procedure FormCreate(Sender: TObject); |
68 | 77 | Procedure MenuItem1Click(Sender: TObject); |
| 78 | + Procedure MenuItem2Click(Sender: TObject); |
69 | 79 | Procedure ScrollBar1Change(Sender: TObject); |
70 | 80 | Procedure ScrollBar2Change(Sender: TObject); |
| 81 | + Procedure ScrollBar3Change(Sender: TObject); |
| 82 | + Procedure ScrollBar4Change(Sender: TObject); |
71 | 83 | private |
72 | | - Raw: Array Of Array Of Byte; |
| 84 | + Raw: TRawData; |
73 | 85 | initialized: Boolean; |
| 86 | + |
| 87 | + Function BitmapToRawData(Const BM: TBitmap): TRawData; |
74 | 88 | public |
75 | 89 |
|
76 | 90 | End; |
|
84 | 98 |
|
85 | 99 | Uses math, FPImage; |
86 | 100 |
|
| 101 | +Function Map(vmin, vmax, v: Single; rmin, rmax: Single): Single; |
| 102 | +Begin |
| 103 | + If (vmax - vmin = 0) Then Begin |
| 104 | + result := rmin; |
| 105 | + exit; |
| 106 | + End |
| 107 | + Else Begin |
| 108 | + result := ((((v - vmin) * (rmax - rmin)) / (vmax - vmin)) + rmin); |
| 109 | + End; |
| 110 | +End; |
| 111 | + |
87 | 112 | { TForm1 } |
88 | 113 |
|
89 | 114 | Procedure TForm1.Button1Click(Sender: TObject); |
90 | 115 | Begin |
91 | | - // OpenDialog1.FileName := 'Logo_depth.bmp'; |
92 | | - // OpenDialog1.FileName := 'Sphere.bmp'; |
93 | 116 | If OpenDialog1.Execute Then Begin |
94 | 117 | initialized := true; |
95 | 118 | Image1.Picture.LoadFromFile(OpenDialog1.FileName); |
|
115 | 138 | i, j, shift: Integer; |
116 | 139 | pattern_width, pattern_div, idx: integer; |
117 | 140 |
|
| 141 | + minDepth, maxDepth: byte; |
118 | 142 | Begin |
119 | 143 | If Not initialized Then exit; |
120 | 144 |
|
| 145 | + minDepth := ScrollBar3.Position; |
| 146 | + maxDepth := 255 - (100 - ScrollBar4.Position); |
121 | 147 | // 1. Tiefenbild extrahieren |
122 | 148 | tmp_bm := TBitmap.Create; |
123 | 149 | tmp_bm.Assign(Image1.Picture); |
124 | 150 |
|
125 | | - depth_data := Nil; |
126 | | - SetLength(depth_data, tmp_bm.Width, tmp_bm.Height); |
127 | | - tmp_img := tmp_bm.CreateIntfImage; |
128 | | - For i := 0 To tmp_bm.Width - 1 Do |
129 | | - For j := 0 To tmp_bm.Height - 1 Do |
130 | | - depth_data[i, j] := (tmp_img.Colors[i, j].Red Shr 8) And $FF; |
131 | | - tmp_img.Free; |
| 151 | + depth_data := BitmapToRawData(tmp_bm); |
132 | 152 |
|
133 | 153 | // 2. Zielbild daten bestimmen |
134 | 154 | Image_Width := tmp_bm.Width; |
135 | 155 | Image_Height := tmp_bm.Height; |
136 | 156 |
|
| 157 | + // Optionales Nachträgliches "verbiegen" des eingeladenen Tiefenbildes ;) |
| 158 | + If (minDepth <> 1) Or (maxDepth <> 255) Then Begin |
| 159 | + For i := 0 To Image_Width - 1 Do |
| 160 | + For j := 0 To Image_Height - 1 Do Begin |
| 161 | + If depth_data[i, j] <> 0 Then Begin |
| 162 | + depth_data[i, j] := round(Map(1, 255, depth_data[i, j], minDepth, maxDepth)); |
| 163 | + End; |
| 164 | + End; |
| 165 | + End; |
| 166 | + |
137 | 167 | // 3. Pattern erstellen |
138 | 168 | tmp_bm.Free; |
139 | 169 | pattern := Nil; |
|
158 | 188 | End |
159 | 189 | Else Begin |
160 | 190 | // Verschieben der Pixel entsprechend der Tiefeninformationen ;) |
| 191 | +// shift := trunc(map(0, 255, depth_data[i, j], minDepth, maxDepth) / pattern_div); |
161 | 192 | shift := trunc(depth_data[i, j] / pattern_div); |
162 | 193 | idx := i - pattern_width + shift; |
163 | 194 | idx := max(0, min(idx, Image_Width - 1)); |
|
240 | 271 | (* |
241 | 272 | * Magic eye texture generation inspired by: https://github.com/synesthesiam/magicpy |
242 | 273 | *) |
243 | | - caption := 'Magic eye image creator ver. 0.01, by Corpsman, www.Corpsman.de'; |
| 274 | + caption := 'Magic eye image creator ver. 0.02, by Corpsman, www.Corpsman.de'; |
244 | 275 | Randomize; |
245 | 276 | Raw := Nil; |
246 | 277 | initialized := false; |
247 | 278 | ScrollBar2Change(Nil); |
| 279 | + ScrollBar3Change(Nil); |
| 280 | + ScrollBar4Change(Nil); |
248 | 281 | End; |
249 | 282 |
|
250 | 283 | Procedure TForm1.MenuItem1Click(Sender: TObject); |
|
259 | 292 | End; |
260 | 293 | End; |
261 | 294 |
|
| 295 | +Procedure TForm1.MenuItem2Click(Sender: TObject); |
| 296 | +Var |
| 297 | + bm: TBitmap; |
| 298 | + pattern_width: integer; |
| 299 | +Begin |
| 300 | + If OpenDialog1.Execute Then Begin |
| 301 | + bm := TBitmap.Create; |
| 302 | + bm.LoadFromFile(OpenDialog1.FileName); |
| 303 | + Image2.Picture.Assign(bm); |
| 304 | + |
| 305 | + image3.Left := Image2.Left + image2.Width + 15; |
| 306 | + image3.Picture.Assign(bm); |
| 307 | + ScrollBar1.Left := image3.Left; |
| 308 | + ScrollBar1.Width := image2.Width; |
| 309 | + ScrollBar1.Max := image2.Width; |
| 310 | + label4.left := ScrollBar1.Left; |
| 311 | + label5.left := label4.left + label4.Width + 5; |
| 312 | + raw := BitmapToRawData(bm); |
| 313 | + // TODO: mittels Koinzidenztest die Patternwith direkt bestimmen! |
| 314 | + pattern_width := bm.Width Div 10; |
| 315 | + If ScrollBar1.Position = pattern_width Then Begin |
| 316 | + ScrollBar1Change(Nil); |
| 317 | + End |
| 318 | + Else Begin |
| 319 | + ScrollBar1.Position := pattern_width; |
| 320 | + End; |
| 321 | + bm.Free; |
| 322 | + End; |
| 323 | +End; |
| 324 | + |
262 | 325 | Procedure TForm1.ScrollBar1Change(Sender: TObject); |
263 | 326 | Var |
264 | 327 | off, i, j: Integer; |
|
299 | 362 | Button2.Click; |
300 | 363 | End; |
301 | 364 |
|
| 365 | +Procedure TForm1.ScrollBar3Change(Sender: TObject); |
| 366 | +Begin |
| 367 | + Label11.Caption := inttostr(ScrollBar3.Position); |
| 368 | + Button2.Click; |
| 369 | +End; |
| 370 | + |
| 371 | +Procedure TForm1.ScrollBar4Change(Sender: TObject); |
| 372 | +Begin |
| 373 | + Label12.Caption := inttostr(255 - (100 - ScrollBar4.Position)); |
| 374 | + Button2.Click; |
| 375 | +End; |
| 376 | + |
| 377 | +Function TForm1.BitmapToRawData(Const BM: TBitmap): TRawData; |
| 378 | +Var |
| 379 | + i, j: Integer; |
| 380 | + tmp_img: TLazIntfImage; |
| 381 | +Begin |
| 382 | + Result := Nil; |
| 383 | + SetLength(Result, bm.Width, bm.Height); |
| 384 | + tmp_img := bm.CreateIntfImage; |
| 385 | + For i := 0 To bm.Width - 1 Do |
| 386 | + For j := 0 To bm.Height - 1 Do |
| 387 | + Result[i, j] := (tmp_img.Colors[i, j].Red Shr 8) And $FF; |
| 388 | + tmp_img.Free; |
| 389 | + |
| 390 | +End; |
| 391 | + |
302 | 392 | End. |
303 | 393 |
|
0 commit comments