Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experiment with instruction level parallelism in pixelsearch1x.c #40

Open
wants to merge 497 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
497 commits
Select commit Hold shift + click to select a range
92cf1da
Design Philosophy
iseahound May 9, 2022
8cd9144
Buffer now supports cropping and showing windows
iseahound May 11, 2022
a1ada4e
Add setter to ImagePutBuffer
iseahound May 11, 2022
50d9cfe
Lift RGB colors to ARGB
iseahound May 11, 2022
222ffff
allow ImagePutBuffer().show to use window edges
iseahound May 11, 2022
c4de443
Update README.md
iseahound May 11, 2022
28f49f5
C source files
iseahound May 12, 2022
02501e8
C source files
iseahound May 12, 2022
f221ac1
Add CPUID function
iseahound May 12, 2022
eef2a0f
comment
iseahound May 12, 2022
b35505d
CPUID only uses 0-31
iseahound May 13, 2022
8c8d2ce
Add pixelsearch with variation
iseahound May 17, 2022
70df42b
C source files
iseahound May 17, 2022
ef0838b
Fix colon : being removed from Drive path
iseahound May 18, 2022
f1f0a25
Use the && short-circuit to simplify ternaries
iseahound May 22, 2022
1998b3d
MimeType typo
iseahound May 22, 2022
7650cb1
Fix put_hex incorrect pointer to GlobalLock
iseahound May 23, 2022
9d732c2
Remove "smart_pointer" type from GdiplusShutdown
iseahound May 23, 2022
df74fcb
Change obj.pBitmap to pic.pBitmap
iseahound May 23, 2022
d1d9225
Remove unused parameter in GdiplusShutdown
iseahound May 23, 2022
8537c07
remove annoying comments from select_
iseahound May 24, 2022
e39f101
WindowProc new thread should be critical
iseahound May 28, 2022
3fb80f4
Fix gdiplus remaining loaded with streams
iseahound Jun 1, 2022
5cdf2d8
Try-Finally to avoid intermediate values
iseahound Jun 1, 2022
255fa3b
some comments
iseahound Jun 1, 2022
00ec0e2
lowercase control flow
iseahound Jun 1, 2022
d721a54
better comment
iseahound Jun 1, 2022
91e5506
Prefix labels with ImagePut
iseahound Jun 1, 2022
33ddb7b
unnecessary double instantiation
iseahound Jun 1, 2022
b31e3c7
Switch case for Destroy()
iseahound Jun 1, 2022
2f91863
Try-finally to avoid intermediate values
iseahound Jun 2, 2022
a6b13dc
v2 Close each window individually
iseahound Jun 14, 2022
9a52b80
DestroyWindow should return 0 in WindowProc
iseahound Jun 14, 2022
485a334
small comment
iseahound Jun 14, 2022
4d0f569
Unused gdip image format line
iseahound Jun 14, 2022
039e24a
Prevent Taskbar Overlay of ImageShow
iseahound Jun 14, 2022
5a59bb6
comment
iseahound Jun 14, 2022
5cf33f6
Change put_dc to be more like put_hbitmap
iseahound Jun 14, 2022
390732a
Animate GIFs
iseahound Jun 14, 2022
144c111
thanks
iseahound Jun 14, 2022
d02df31
Revert NoActivate as default
iseahound Jun 14, 2022
9c32cd3
v1.8
iseahound Jun 14, 2022
cdf5961
comment
iseahound Jun 15, 2022
ea6e91b
Accurate GIF animation delay
iseahound Jun 15, 2022
ee7d820
Accurate GIF animation delay
iseahound Jun 15, 2022
580bade
redundant return
iseahound Jun 16, 2022
17cf3ef
Window Procedures should return
iseahound Jun 16, 2022
8fd8e9c
Refactor gdiplus boilerplate
iseahound Jun 16, 2022
7f11a8c
GIF animations need GDI+ scope
iseahound Jun 16, 2022
a6b7ee8
Add drag and drop functionality to open all images
iseahound Jun 16, 2022
8cf6e34
Load GIF clone to memory immediately
iseahound Jun 16, 2022
42bc201
Fix memory leak when displaying GIFs
iseahound Jun 16, 2022
5bb5b2d
ImageShow is cooler for animated GIFs
iseahound Jun 17, 2022
e848348
update demo
iseahound Jun 17, 2022
bd5c8a3
cute demo
iseahound Jun 17, 2022
0035ad3
v1.8.1
iseahound Jun 17, 2022
d98e451
Validate A_Args length
iseahound Jun 19, 2022
f7fa88f
Shorten URLs
iseahound Jun 19, 2022
0893401
capitalization
iseahound Jun 19, 2022
7cf9326
Improve GIF rendering code
iseahound Jun 19, 2022
796dc4d
Reuse the generated hdc when rendering GIFs
iseahound Jun 19, 2022
2c94324
comments
iseahound Jun 19, 2022
31a514a
disable debug mode
iseahound Jun 19, 2022
fdca7e8
Prettify machine code
iseahound Jun 20, 2022
aa0b695
Avoid GdiplusShutdown error on Reload
iseahound Jun 20, 2022
0b75fde
Combine PixelSearch and PixelSearch2
iseahound Jun 20, 2022
8b99bdf
DirectX screen capture
iseahound Jun 26, 2022
fb16c27
Update README.md
iseahound Jun 27, 2022
4cc0882
OR operator over NOT AND
iseahound Jul 2, 2022
8f00146
Allow set decode & validate to override globals
iseahound Jul 3, 2022
226bc19
C source files
iseahound Jul 17, 2022
9b6cbb5
Update README.md
iseahound Jul 22, 2022
5873a16
Update README.md
iseahound Jul 22, 2022
6767049
Update README.md
iseahound Jul 22, 2022
d631e86
Update README.md
iseahound Jul 23, 2022
b139d8b
Update README.md
iseahound Jul 23, 2022
8404c9d
Update README.md
iseahound Jul 23, 2022
a0fa2c8
Rename ImageTypes to inputs
iseahound Jul 23, 2022
53f8b94
Allow a range of colors to be specified through variation
iseahound Jul 23, 2022
edd77a3
Color channels can be low → high OR high → low
iseahound Jul 23, 2022
a75d5af
lowercase Min and Max
iseahound Jul 23, 2022
2af8a28
Bound variation channels to [0-255]
iseahound Jul 23, 2022
daa8387
Shorten pixelsearch2 assembly by one instruction
iseahound Jul 23, 2022
4678f2d
Standardize base64 → assembly code names
iseahound Jul 24, 2022
a6bb333
add whitespace
iseahound Jul 24, 2022
6285533
Refactor put_buffer to create a global pointer from BitmapBuffer's __…
iseahound Jul 25, 2022
0609b01
C source files
iseahound Jul 25, 2022
a884945
Save() produces a 32-bit ARGB uncompressed bitmap
iseahound Jul 26, 2022
b907d97
Disable complaints that the class is not found due to alphabetical ob…
iseahound Jul 26, 2022
ce060b7
Fixes ImageSearch erroneously creating a buffer from buffer
iseahound Jul 30, 2022
5491bf9
Avoid exporting the pBitmap for buffers
iseahound Jul 30, 2022
1354ff3
Fixes calling bound functions
iseahound Jul 30, 2022
eebfac2
Allow ClipboardAll (no parenthesis) in v2
iseahound Aug 23, 2022
309697f
Remove global variables from ImagePut drag & drop
iseahound Aug 23, 2022
c214d94
place main code at bottom
iseahound Aug 28, 2022
984b0ee
shorten URLs again
iseahound Aug 28, 2022
1d39161
Resolve File before Window
iseahound Aug 30, 2022
116d486
Use Haskey for v1
iseahound Aug 30, 2022
f20f64d
Give monitor numbers higher priority
iseahound Aug 30, 2022
0d19547
ImagePutExplorer()
iseahound Aug 30, 2022
1dd8f45
ImagePutSafeArray()
iseahound Sep 4, 2022
31dea01
considering adding formdata...
iseahound Sep 5, 2022
899484f
Update README.md
iseahound Sep 7, 2022
f5f50b9
Update README.md
iseahound Sep 7, 2022
20ece2c
Interface for FormData (not implemented)
iseahound Sep 16, 2022
718d644
Modify WindowClass to allow optional double clicks
iseahound Oct 5, 2022
b638ac5
Enumerate over colors with a for loop
iseahound Oct 17, 2022
856f26e
Fix crop() for BitmapBuffer
iseahound Nov 5, 2022
55abe4b
Check for image.prototype before image.prototype.__class
iseahound Nov 5, 2022
ba88b4e
ImageSearch now searches more than one row of pixels
iseahound Nov 5, 2022
05a8499
C source files
iseahound Nov 5, 2022
32bbee3
C source files
iseahound Nov 5, 2022
566d171
ImageSearch works with Transcolor
iseahound Nov 5, 2022
1009deb
remove unneeded named function
iseahound Nov 6, 2022
ec058dd
v1.9
iseahound Nov 6, 2022
5d84c60
Add PixelSearchAll
iseahound Dec 17, 2022
bd1116f
ImageSearchAll
iseahound Dec 17, 2022
6ade3ff
Transcolor automatically selects the top-left color
iseahound Dec 20, 2022
109d08b
Colorkey selects the top-left color as default
iseahound Dec 20, 2022
ba5add7
comment wording
iseahound Dec 20, 2022
279a995
Fix parenthesis
iseahound Dec 20, 2022
9b5abd1
sync PixelSearchAll
iseahound Dec 20, 2022
a96e8db
Update README.md
iseahound Dec 20, 2022
ee17a8e
Allow "image" in ImageSearchAll to be magical
iseahound Dec 23, 2022
5e10901
Fix crop() on v1 by removing "new" call
iseahound Jan 21, 2023
7ffeefa
Add simple count* colors function
iseahound Jan 30, 2023
a7494a1
Add Clone() using memcpy
iseahound Jan 30, 2023
00094fe
(v2) Avoid SingleInstance Checks
iseahound Feb 4, 2023
b0aa7e2
Guard against static pToken is unset
iseahound Feb 4, 2023
0ec28af
Remove IsObject checks due to v2-beta.13
iseahound Feb 4, 2023
7f9b5dc
Fix 1st parameter of ImagePutExplorer
iseahound Feb 4, 2023
84042a1
trim backspace
iseahound Feb 4, 2023
5b6ebdc
lowercase hresult
iseahound Feb 4, 2023
4d36be8
Fix Save() failing for 2nd buffer of different size
iseahound Feb 4, 2023
218a847
Streamline NumGet across v1/v2
iseahound Feb 4, 2023
7dccca4
spacing
iseahound Feb 4, 2023
346e1c0
comment
iseahound Feb 5, 2023
ab04e51
Add 3 parameter variation to PixelSearch
iseahound Feb 11, 2023
05952b4
re-add exception
iseahound Feb 11, 2023
ea13e11
right click to close
iseahound Feb 13, 2023
63795c4
Fix GIFs on 32-bit
iseahound Feb 13, 2023
f99ad58
cleanup GIF code
iseahound Feb 13, 2023
c937011
Refactor gifs to use addresses 1-4 of 0-4
iseahound Feb 13, 2023
38e8783
Fix rare bug where the parent window is not correctly identified
iseahound Feb 13, 2023
ea02e39
Add CDecl to every machine code function
iseahound Feb 23, 2023
47b18d4
Add CDecl to ComCall
iseahound Feb 23, 2023
b4a73b2
v1.10
iseahound Mar 2, 2023
e02bdce
rename put_XXX to to_XXX
iseahound Mar 6, 2023
4538df8
reorder window and screenshot
iseahound Mar 26, 2023
914e7a5
Screenshot Windows
iseahound Mar 26, 2023
d69156e
Use WinGetClientPos instead
iseahound Mar 26, 2023
88a41a4
use rect instead of size
iseahound Mar 26, 2023
172d1b7
Throw Error if IsObject branch is exited
iseahound Mar 26, 2023
f36363a
[v2] Change "uint" to hresult. Remove +0 from v1
iseahound Apr 13, 2023
2b70a5a
Catch divide by zero error inside BitmapCrop (negative w&h)
iseahound Apr 27, 2023
4b89b0b
Apply Cropping if and only if all dimensions are valid
iseahound Apr 27, 2023
d1358af
Add upscale && downscale flags
iseahound Apr 27, 2023
13733a9
Fix SetThreadDpiAwarenessContext for Windows 7
iseahound Apr 27, 2023
91e541d
Remove window2 a.k.a. screenshot with ["A"]
iseahound Apr 27, 2023
0b193f9
removed annoying __32 for SetWindowLongPtr
iseahound Apr 28, 2023
b939015
read / write from shared buffers
iseahound Apr 30, 2023
248201a
Use first 8 bytes of FileMapping to store w&h
iseahound Apr 30, 2023
3cdc4a9
Add ImagePutSharedBuffer()
iseahound Apr 30, 2023
a1b0df1
rename
iseahound Apr 30, 2023
f6c8dca
change error message
iseahound Aug 12, 2023
4f909bb
Use a static buffer to store the base64 and allocated pointers
iseahound Sep 4, 2023
3b1cb71
Remove statics holding onto the machine code
iseahound Sep 4, 2023
b8a6a4c
comments for pixelsearch
iseahound Sep 5, 2023
75ea52d
C source files
iseahound Sep 5, 2023
8f65a5b
C source files
iseahound Sep 5, 2023
cea9e37
Refactor PixelSearch
iseahound Sep 5, 2023
4c092fb
reduce line length
iseahound Sep 5, 2023
d4cfcd9
C source files
iseahound Sep 5, 2023
698490b
C source files
iseahound Sep 5, 2023
1b9c9ca
reduce line length again
iseahound Sep 5, 2023
1f982f9
Use SSE2 to increase pixelsearch1 by 100% - 300%
iseahound Sep 6, 2023
0127f32
Use SSE2 to increase pixelsearch1 by 100% - 300%
iseahound Sep 6, 2023
df47d96
Use SSE2 to increase pixelsearch2 by 50% - 100%
iseahound Sep 6, 2023
66dfa67
C source files
iseahound Sep 6, 2023
490748b
C source files
iseahound Sep 7, 2023
44343e1
Fix pixelsearch2 to properly use SSE2 (100-200% speedup)
iseahound Sep 7, 2023
6e38074
Use SSE2 to improve pixelsearch3 (200% speedup)
iseahound Sep 8, 2023
68ab4aa
Refactor WindowProc
iseahound Sep 9, 2023
3044eb0
trailing spaces
iseahound Sep 9, 2023
9a30949
add comment about 64 to 32 bits truncation
iseahound Sep 9, 2023
2c68f0a
Removing some aspects of RegisterSyncCallback seems to work...
iseahound Sep 9, 2023
d259314
Fix instability due to freeing callbacks
iseahound Sep 9, 2023
ee38ebc
Use postmessage to kickoff the animation loop
iseahound Sep 9, 2023
d9c6e62
Use a periodic timer to avoid timer init delay
iseahound Sep 11, 2023
3cfd069
Fix multiple GIFs not playing at the same time
iseahound Sep 11, 2023
7ee795a
sync v1 / v2 compatibility
iseahound Sep 12, 2023
ed9ea70
C source files
iseahound Sep 13, 2023
b44b6e3
comment
iseahound Sep 13, 2023
cd61c12
Clarify condition for GIF delay
iseahound Sep 13, 2023
b555dc0
Set old protect from VirtualProtect to 0
iseahound Sep 15, 2023
408c874
cpuid comment for posterity
iseahound Sep 15, 2023
df1a280
Add check for AVX (not AVX2!)
iseahound Sep 15, 2023
ead7910
Simplify Tooltip Destruction
iseahound Sep 16, 2023
8b676a3
Use Tooltip No. 16
iseahound Sep 16, 2023
2415cc8
C source files
iseahound Sep 17, 2023
ba9da4d
C source files
iseahound Sep 17, 2023
6829268
Avoid recursion limit error in AHK_H
anonymous1184 Sep 17, 2023
e5cf7a8
Merge pull request #31 from anonymous1184/master
iseahound Sep 17, 2023
aceeaed
Simplify PixelSearch3
iseahound Sep 22, 2023
17a92f7
Speedup pixelsearch4
iseahound Sep 22, 2023
27a027f
C source files
iseahound Sep 22, 2023
74c41aa
Refactor PixelSearchAll
iseahound Sep 23, 2023
8f86d7c
rename byte to address
iseahound Sep 23, 2023
257bcca
spacing
iseahound Sep 23, 2023
479febc
finish renaming byte to address
iseahound Sep 23, 2023
349064f
Rename Fix Machine Code
iseahound Sep 23, 2023
fed26e4
Add machine code for PixelSearchAll (not SIMD)
iseahound Sep 23, 2023
472d597
C source files
iseahound Sep 23, 2023
4118962
C source files
iseahound Sep 23, 2023
b84bff2
Implement SSE2 acceleration for PixelSearchAll
iseahound Sep 23, 2023
da471e8
C source files
iseahound Sep 23, 2023
44d046d
C source files
iseahound Sep 23, 2023
63f32cb
Fix pixel inflation; Regenerate machine code and linkes
iseahound Sep 23, 2023
83c8c4f
Fix tooltip dissapprearing!
iseahound Sep 23, 2023
66a59ee
AdjustWindowRectEx uses a bool
iseahound Sep 30, 2023
281ffdb
Add relative to window syntax show(), to_window()
iseahound Oct 3, 2023
1c6c82b
[x, y, w, h, r] where r is a window handle
iseahound Oct 3, 2023
70f3372
Improve ImageSearch
iseahound Oct 5, 2023
42f309b
Add count property
iseahound Oct 6, 2023
9ee8be9
Experiment with ImageSearchAll with tolerance to color variation
wind0204 Dec 14, 2023
57cfafc
Update ImageSearch method of BitmapBuffer
wind0204 Dec 14, 2023
d3c883d
Remove an unnecessary assignment to a variable
wind0204 Dec 14, 2023
dd7e974
Recover the lost work on my wife's windows system
wind0204 Dec 14, 2023
d834c70
Accelerate when the argument variation is 0
wind0204 Dec 14, 2023
05d7a47
Put back the carriage return characters on each line ending
wind0204 Dec 14, 2023
8fd1cc0
As you learn English, the quality of the comments improves
wind0204 Dec 14, 2023
713c809
Fix a bug where random memory location will be touched in focus-deter…
wind0204 Dec 14, 2023
91a0e82
Restore Default Behavior of ImageSearch
iseahound Dec 14, 2023
4976903
Fix ImageSearch2
iseahound Dec 14, 2023
b9f6e19
Fix bug where focus search loop could go out of range
wind0204 Dec 16, 2023
4161cc1
Add files via upload
iseahound Dec 16, 2023
365f9fa
C source files
iseahound Dec 16, 2023
aad765f
Merge pull request #37 from wind0204/pr-fix_bug_where_focus_search_lo…
iseahound Dec 16, 2023
d4e95cf
C source files
iseahound Dec 16, 2023
91c4d4b
C source files
iseahound Dec 16, 2023
714e15a
C source files
iseahound Dec 16, 2023
f20168f
Finalize ImageSearch1
iseahound Dec 16, 2023
c868eb2
Fix bug where the last scanline was skipped
wind0204 Dec 17, 2023
f50b1ba
The previous fix didn't fix, this one does seem to fix it
wind0204 Dec 17, 2023
2aa6843
The prev. commit had a bug of the possibility of reaching off haystack
wind0204 Dec 17, 2023
b27ac85
Merge pull request #38 from wind0204/pr-fix_bug_where_last_scanline_w…
iseahound Dec 17, 2023
a552495
comments: when the faeries dance in the wind
iseahound Dec 25, 2023
346c611
Merge branch 'iseahound:master' into master
wind0204 Jan 1, 2024
a0b9226
Remove an unnecessary conditional jump
wind0204 Jan 2, 2024
86a3c75
The typo in a line of comment "has big a throughput"
wind0204 Jan 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Experiment with ImageSearchAll with tolerance to color variation
wind0204 committed Dec 14, 2023
commit 9ee8be93a264d396a148df65ca26e5e370e4531a
70 changes: 52 additions & 18 deletions ImagePut.ahk
Original file line number Diff line number Diff line change
@@ -2839,6 +2839,12 @@ class ImagePut {
}

ImageSearch(image) {
; FIXME Since I haven't install the GCC libraries for 32bit libraries and build 32bit binary, it won't work on 32-bit systems, Thank you for your understanding!
if ( A_PtrSize == 4 ) {
MsgBox("Since I haven't install the GCC libraries for 32bit libraries and build 32bit binary, it won't work on 32-bit systems, Thank you for your understanding!")
return False
}

; C source code - https://godbolt.org/z/cKxrrT4ss
code := this.Base64Code((A_PtrSize == 4)
? "VYnlV1ZTg+wgi0Uki1UYi30Ui00gD6/Qi3UIix8Pr0UMAcqJXeSLHJeLfQwByItVECtVHIlF7MHnAold4ItdDA+v1ytdGANVCIlV"
@@ -2867,47 +2873,75 @@ class ImagePut {
return [mod(offset, this.width), offset // this.width]
}

ImageSearchAll(image) {
ImageSearchAll(image, variation := 0) {
; FIXME Since I haven't install the GCC libraries for 32bit libraries and build 32bit binary, it won't work on 32-bit systems, Thank you for your understanding!
if ( A_PtrSize == 4 ) {
MsgBox("Since I haven't install the GCC libraries for 32bit libraries and build 32bit binary, it won't work on 32-bit systems, Thank you for your understanding!")
return False
}

; C source code - https://godbolt.org/z/qPodGdP1d
code := this.Base64Code((A_PtrSize == 4)
? "VYnlV1ZTg+wUi0UMi1UYi00IjTyFAAAAAItFECtFHA+vxwNFCIlF6ItFDCnQiUXkjQSVAAAAAIlF7ItF6DnBc2eLRRSLADkBdAmL"
. "RRSAeAMAdVCJyCtFCDHSwfgC93UMOVXkfD4x0otFFInLiVXwi3XwO3UcdDyLVeyJ3gHCiVXgi1XgOdBzFIB4AwB0BosWORB1D4PA"
. "BIPGBOvl/0XwAfvrzIPBBOuSi0UQD6/HA0UIicGDxBSJyFteX13D"
: "QVdBVkFVQVRVV1ZTSIPsGEUx20SLpCSYAAAAi4QkgAAAAESLlCSQAAAASIu8JIgAAABEKeBBD6/BSInLidZMicFNjSyARInIRCnQ"
. "iUQkDEqNBJUAAAAASIkEJEw56XN0iwc5AXQGgH8DAHViSInIMdJMKcBIwfgCQffxOVQkDHxNSIn4Me0x0kQ54nQyTIs8JEGJ7k6N"
. "NLFJAcdMOfhzGIB4AwB0CEWLFkQ5EHUgSIPABEmDxgTr4//CRAHN68lBOfNzB0SJ2EiJDMNB/8NIg8EE64dEidhIg8QYW15fXUFc"
. "QV1BXkFfww==")
: "QVdBVkFVQVRVV1ZTSIPsSIuEJNAAAACLtCTIAAAARImMJKgAAABED7eMJNgAAABIiYwkkAAAAImUJJgAAABMiYQkoAAAAIXAD4Xa"
. "AwAARIuUJMAAAACJ8kSLnCTAAAAAweoCD6+UJMAAAACLjCTAAAAARA+v1kHB6wJIi7wkuAAAAESJ2EgBwkWJ0EiNFJdMAcFIjRyP"
. "SDnaD4MOAwAARIuEJMAAAABB0ehJweACSo0MAkg50XcW6ZMDAAAPH0AASIPCBEg50Q+G1AIAAIB6AwB07UiJ0EgrhCS4AAAAMdJI"
. "wfgC97QkwAAAAGaJVCQwRA+3wg+30InRD6+MJMAAAACJVCQ0TAHBSMHhAkiLhCS4AAAASIu8JKAAAABEi6wkqAAAAEQrrCTAAAAA"
. "iwQIi4wksAAAACnxD6+MJKgAAABIjSyPSDnvD4PtAgAAD6+UJKgAAABJiftFicrHRCQsAAAAAEH32kwBwkiNPJUAAAAAi5QkwAAA"
. "AEiNXwFIiXwkCEiDxwJIiVwkEIucJKgAAABIiXwkIEiNPJUAAAAASYncSIlcJDiLnCTAAAAASSnUjVP/ScHkAkiNHJUAAAAAD7bQ"
. "ZolUJCgPttTB6BAPtsBIiRwkMduJVCQcZolEJCrrFg8fgAAAAABMAxwkMdtJOesPgwoBAABEOet37EiLRCQIQQ+2FAMPt0QkKCnQ"
. "ZkE5wXMKZkQ50A+CyAAAAEiLRCQQQQ+2FAMPt0QkHCnQZkE5wXMKZkQ50A+CpwAAAEiLRCQgQQ+2FAMPt0QkKinQZkE5wXMKZkQ5"
. "0A+ChgAAAEiLhCS4AAAATInaRTH/hfYPhNsAAABMjQQ4STnAdxvpzQAAAA8fRAAASIPABEiDwgRJOcAPhqcAAACAeAMAdOkPtghE"
. "D7YyRCnxZkE5yXMGZkQ50XIwD7ZIAUQPtnIBRCnxZkE5yXMGZkQ50XIYD7ZIAkQPtnICRCnxZkE5yXOpZkQ50XOjSYPDBIPDATHA"
. "O5wkqAAAAA9D2Ek56w+C9v7//4tEJCxIi7QkkAAAAAHASI0EhkiJhCSQAAAASInGi0QkMMHgEAtEJDSJBotEJCxIg8RIW15fXUFc"
. "QV1BXkFfw0GDxwFMAeJEOf4PhSX///+LTCQsOYwkmAAAAHYwTInYSCuEJKAAAABIwfgCSJlI93wkOGYPbsJIi5QkkAAAAGYPOiLA"
. "AY0ECWYP1gSCg0QkLAFJAfsDnCTAAAAA6Uv///9MAcJIOdMPhwH9//9Ii7wkuAAAADHJRTHAMdJmRIlEJDCAfA8DAIlUJDQPhTv9"
. "//+LjCTAAAAAQY1T/0QrlCTAAAAASMHgAkwB0kj32EQp2UiNFJdIweECSPfZSYnQSQHAchXrUWYuDx+EAAAAAABIg+oESTnQcz6A"
. "egMAdPHpr/z//w8fQABBicBBwegQZkSJRCQw6br8///HRCQsAAAAAEiLtCSQAAAA6c/+//9IicrpTf///0gByuug")
;: "QVdBVkFVQVRVV1ZTSIPsGEUx20SLpCSYAAAAi4QkgAAAAESLlCSQAAAASIu8JIgAAABEKeBBD6/BSInLidZMicFNjSyARInIRCnQ"
;. "iUQkDEqNBJUAAAAASIkEJEw56XN0iwc5AXQGgH8DAHViSInIMdJMKcBIwfgCQffxOVQkDHxNSIn4Me0x0kQ54nQyTIs8JEGJ7k6N"
;. "NLFJAcdMOfhzGIB4AwB0CEWLFkQ5EHUgSIPABEmDxgTr4//CRAHN68lBOfNzB0SJ2EiJDMNB/8NIg8EE64dEidhIg8QYW15fXUFc"
;. "QV1BXkFfww==")

; Convert image to a buffer object.
if !(IsObject(image) && ObjHasOwnProp(image, "ptr") && ObjHasOwnProp(image, "size"))
image := ImagePutBuffer(image)

; Check if the object has the coordinates.
coord_focus := ObjHasOwnProp(image, "coord_focus") ? image.coord_focus : 0

; Search for the address of the first matching image.
capacity := 256
result := Buffer(A_PtrSize * capacity)
result := Buffer(2 * 4 * capacity + 4)
count := DllCall(code, "ptr", result, "uint", capacity
, "ptr", this.ptr, "uint", this.width, "uint", this.height
, "ptr", image.ptr, "uint", image.width, "uint", image.height, "cdecl uint")
, "ptr", image.ptr, "uint", image.width, "uint", image.height
, "UInt", coord_focus, "UShort", variation, "cdecl uint")

; If more than 256 results, run the function with the true capacity.
if (count > capacity) {
result.size := A_PtrSize * count
count := DllCall(code, "ptr", result, "uint", capacity
, "ptr", this.ptr, "uint", this.width, "uint", this.height
, "ptr", image.ptr, "uint", image.width, "uint", image.height, "cdecl uint")
}
; Prevent another search for focused pixel
image.coord_focus := NumGet(result, 2*4*count, "UInt")
coord_focus := image.coord_focus

; Check if any matches are found.
if (count = 0)
return False

; If more than 256 results, run the function with the true capacity.
if (count > capacity) {
result.Size := 2 * 4 * count + 4
count := DllCall(code, "ptr", result, "uint", count
, "ptr", this.ptr, "uint", this.width, "uint", this.height
, "ptr", image.ptr, "uint", image.width, "uint", image.height
, "UInt", coord_focus, "UShort", variation, "cdecl uint")
}

; Create an array of [x, y] coordinates.
xys := []
xys.count := count
loop count {
address := NumGet(result, A_PtrSize*(A_Index-1), "ptr")
offset := (address - this.ptr) // 4
xy := [mod(offset, this.width), offset // this.width]
xy := [NumGet(result, 2*4*(A_Index-1), "UInt"),
NumGet(result, 2*4*(A_Index-1) + 4, "UInt")]
xys.push(xy)
}
return xys
156 changes: 156 additions & 0 deletions source/imagesearch2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
__attribute__((ms_abi)) // Tells GCC we want to compile for Windows.
__attribute__ ((target ("sse4.2"))) // According to godbolt.org it doesn't do anything even with
// __builtin_assume_aligned(ptr, 16) and -Ofast -msse4.2.
// You might want to study SIMD instructions and if there is a good instruction to
// take advantage of, go with inline assembly.
unsigned int imagesearch2(unsigned int * restrict result, unsigned int * start, unsigned int width, unsigned int height, unsigned int * s, unsigned int w, unsigned int h, unsigned int coord_focus, unsigned short variation) {
// width, height, start, current, end, color refer to the haystack (main image)
// x, y, w, h, s, c, e, cf refer to the needle (search image)
// The location of the focused pixel
unsigned short x;
unsigned short y;

if ( coord_focus ) {
x = coord_focus >> sizeof(x)*8;
y = coord_focus & 0x0000ffff;
goto focus_determined;
}

// Try to locate the focused pixel in the middle of the sprite
unsigned int * c = s + w/4 + h/4 * w;
unsigned int * last_pixel = s + w + h * w;
while(c < last_pixel) {
for (unsigned int * e = c + w / 2; c < e; c++) {
if ( *((unsigned char *) c + 3) ) {
unsigned int offset = (c - s);
x = offset % w;
y = offset / w;
goto focus_determined;
}
}
c += w / 2;
}

// If every pixel in the middle was transparent
// try to find a non-transparent pixel on the left-hand side.

// This falls into an infinite loop if somehow the sprite doesn't have any
// non-transparent pixel in the leftmost quarter.
if ( *((unsigned char *)(s + x + y * w) + 3) == 0 ) {
unsigned int * c = s + (w/4-1) + (h-1) * w;
while(-1) {
for (unsigned int * e = c - w / 4; c > e; c--) {
if ( *((unsigned char *) c + 3) ) {
unsigned int offset = (c - s);
x = offset % w;
y = offset / w;
goto focus_determined;
}
}
c -= w - w / 4;
}
}

focus_determined:;

// Hide the coordinates of the focused pixel
*(result + 2) = x << sizeof(x)*8 | y;



// Prepare the search.

// The color on the focused pixel
unsigned int cf = *(s + x + y * w);

// We don't need to search in the narrow edge on the right-hand side
unsigned int range_width = width - w;
// Remaining area must be greater than search height
unsigned int range_height = height - h;

unsigned int * current = start;
unsigned int * end = start + width * range_height;

// Start the search.
unsigned int left = 0;
while ( current < end ) {

unsigned int offset = current - start;
//unsigned int left = offset % width;
// TODO Remove the comment below
// I believe div is worse than cmov'ing one constant number.
// The code loses some readability though.
unsigned int top = offset / width; // optimized away

// Checks before subimage loop.

// X-Range Check
if ( left > range_width ) {
current += w - 1;
left = 0;
continue;
}
//

// Focused Pixel
unsigned int * color;
color = current + x + y * width;
for (int b = 0; b < 3; b++) {
unsigned short diff = *((unsigned char *)&cf + b) - *((unsigned char *)color + b);
if ( diff > variation && diff < (unsigned short)(0 - variation) ) {
current++;
left++;
goto next;
}
}

// Subimage loop.
unsigned int * c = s;
color = current;
for (int i = 0; i < h; i++) {
unsigned int * e = c + w;
while (c < e) {
if ( *((unsigned char *) c + 3) ) { // Skip transparent pixels
for (int b = 0; b < 3; b++) {
unsigned short diff = *((unsigned char *) c + b) - *((unsigned char *) color + b);
if ( diff > variation && diff < (unsigned short)(0 - variation) ) {
current++;
left++;
goto next;
}
}
}
c++; // Iterate over the needle image
color++; // Iterate over the haystack image
}
color = color - w + width; // Reset pointer for each scanline
}

// Found a matching image!
*(result) = (current - start) % width;
*(result + 1) = (current - start) / width;
return 1;

next:
if ( left >= width ) {
left = 0;
}
}

// TODO Remove the comment below for clean code
//
// This is how I checked the input data, writing the first few pixels at s or start
// and then ImagePutClipboard and check each pixel's color in GIMP.
//
// It seems loading with ({sprite: fpath}) gives you the right buffer but
// loading with (fpath, transparent_color) gives a buffer with no transparent pixels
// even if the file had pixels with the matching transparent_color.
//
//for ( unsigned int k = 0; k < w*h/2; k++ ) {
// *(result+k) = *(s + k%32);
//}
//return (w*h)/2/2;
//

return 0;
}
164 changes: 164 additions & 0 deletions source/imagesearchall2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
__attribute__((ms_abi)) // Tells GCC we want to compile for Windows.
__attribute__ ((target ("sse4.2"))) // According to godbolt.org it doesn't do anything even with
// __builtin_assume_aligned(ptr, 16) and -Ofast -msse4.2.
// You might want to study SIMD instructions and if there is a good instruction to
// take advantage of, go with inline assembly.
unsigned int imagesearchall2(unsigned int * restrict result, unsigned int capacity, unsigned int * start, unsigned int width, unsigned int height, unsigned int * s, unsigned int w, unsigned int h, unsigned int coord_focus, unsigned short variation ) {
// width, height, start, current, end, color refer to the haystack (main image)
// x, y, w, h, s, c, e, cf refer to the needle (search image)
unsigned int count = 0;

// The location of the focused pixel
unsigned short x;
unsigned short y;

if ( coord_focus ) {
x = coord_focus >> sizeof(x)*8;
y = coord_focus & 0x0000ffff;
goto focus_determined;
}

// Try to locate the focused pixel in the middle of the sprite
unsigned int * c = s + w/4 + h/4 * w;
unsigned int * last_pixel = s + w + h * w;
while(c < last_pixel) {
for (unsigned int * e = c + w / 2; c < e; c++) {
if ( *((unsigned char *) c + 3) ) {
unsigned int offset = (c - s);
x = offset % w;
y = offset / w;
goto focus_determined;
}
}
c += w / 2;
}

// If every pixel in the middle was transparent
// try to find a non-transparent pixel on the left-hand side.

// This falls into an infinite loop if somehow the sprite doesn't have any
// non-transparent pixel in the leftmost quarter.
if ( *((unsigned char *)(s + x + y * w) + 3) == 0 ) {
unsigned int * c = s + (w/4-1) + (h-1) * w;
while(-1) {
for (unsigned int * e = c - w / 4; c > e; c--) {
if ( *((unsigned char *) c + 3) ) {
unsigned int offset = (c - s);
x = offset % w;
y = offset / w;
goto focus_determined;
}
}
c -= w - w / 4;
}
}

focus_determined:;



// Prepare the search.

// The color on the focused pixel
unsigned int cf = *(s + x + y * w);

// We don't need to search in the narrow edge on the right-hand side
unsigned int range_width = width - w;
// Remaining area must be greater than search height
unsigned int range_height = height - h;

unsigned int * current = start;
unsigned int * end = start + width * range_height;

// Start the search.
unsigned int left = 0;
while ( current < end ) {

unsigned int offset = current - start;
//unsigned int left = offset % width;
// TODO Remove the comment below
// I believe div is worse than cmov'ing one constant number.
// The code loses some readability though.
unsigned int top = offset / width; // optimized away

// Checks before subimage loop.

// X-Range Check
if ( left > range_width ) {
current += w - 1;
left = 0;
continue;
}
//

// Focused Pixel
unsigned int * color;
color = current + x + y * width;
for (int b = 0; b < 3; b++) {
unsigned short diff = *((unsigned char *)&cf + b) - *((unsigned char *)color + b);
if ( diff > variation && diff < (unsigned short)(0 - variation) ) {
current++;
left++;
goto next;
}
}

// Subimage loop.
unsigned int * c = s;
color = current;
for (int i = 0; i < h; i++) {
unsigned int * e = c + w;
while (c < e) {
if ( *((unsigned char *) c + 3) ) { // Skip transparent pixels
for (int b = 0; b < 3; b++) {
unsigned short diff = *((unsigned char *) c + b) - *((unsigned char *) color + b);
if ( diff > variation && diff < (unsigned short)(0 - variation) ) {
current++;
left++;
goto next;
}
}
}
c++; // Iterate over the needle image
color++; // Iterate over the haystack image
}
color = color - w + width; // Reset pointer for each scanline
}

// Found a matching image!
if ( count < capacity ) {
*(result + count * 2) = (current - start) % width;
*(result + count * 2 + 1) = (current - start) / width;
}
count++;

// XXX Let us not deal with overlapped matches
current += w;
left += w;

next:
if ( left >= width ) {
left = 0;
}
}

// Hide the coordinates of the focused pixel
*(result + count * 2) = x << sizeof(x)*8 | y;

// TODO Remove the comment below for clean code
//
// This is how I checked the input data, writing the first few pixels at s or start
// and then ImagePutClipboard and check each pixel's color in GIMP.
//
// It seems loading with ({sprite: fpath}) gives you the right buffer but
// loading with (fpath, transparent_color) gives a buffer with no transparent pixels
// even if the file had pixels with the matching transparent_color.
//
//for ( unsigned int k = 0; k < w*h/2; k++ ) {
// *(result+k) = *(s + k%32);
//}
//return (w*h)/2/2;
//

return count;
}