go-libwebp

Experimental translation from libwebp to Go source.
Log | Files | Refs | README | LICENSE

commit fbd765f1fb8df873b11a1fadc29fb2dbab2ac1fa
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date:   Tue, 25 Jan 2022 10:08:12 +0800

webp: initial working sketch

libwebp.go is generated with gocc and manually fixed up:

1) iterators corrected to use integers as per the C idiom
2) bsearch is implemented (as linear search stub) since it is missing from modernc.org/libc

The sample program executes and generates a webp from a source image.

Follow the happy path and experience the joy of transliterated zombified
raw memory programming in Go!

Signed-off-by: Jack Mordaunt <jackmordaunt.dev@gmail.com>

Diffstat:
ALICENSE | 2++
AREADME.md | 17+++++++++++++++++
Ago.mod | 14++++++++++++++
Ago.sum | 149+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alibwebp.go | 41052+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amain.go | 114+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amegopher.png | 0
Atest.webp | 0
8 files changed, 41348 insertions(+), 0 deletions(-)

diff --git a/LICENSE b/LICENSE @@ -0,0 +1 @@ +Dual: Unlicense/MIT; use at your own risk. +\ No newline at end of file diff --git a/README.md b/README.md @@ -0,0 +1,17 @@ +# go-libwebp + +This is a ccgo translation from [libwebp](https://github.com/webmproject/libwebp/) +in the hope to bring webp codec into Go space. + +`go run . megopher.png` + +Can consume JPEG and PNG images. + +## Notes + +- iterations were manually cleaned up to reflect C idiom of treating integers like booleans + - the cleanup may have been incorrect + - ccgo issue is open to make the translation step correct to avoid needing manual work +- libwebp depends on libc bsearch, which modernc.org/libc doesn't provide; as such an experimental Go implementation is provided (that actually cheats by doing a simple linear search) + - again, this should ideally be upstreamed to ccgo (providing a bsearch) + diff --git a/go.mod b/go.mod @@ -0,0 +1,14 @@ +module git.sr.ht/~jackmordaunt/go-libwebp + +go 1.18 + +require modernc.org/libc v1.14.4 + +require ( + github.com/google/uuid v1.3.0 // indirect + github.com/mattn/go-isatty v0.0.12 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect + golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect + modernc.org/mathutil v1.4.1 // indirect; sindirect + modernc.org/memory v1.0.5 // indirect +) diff --git a/go.sum b/go.sum @@ -0,0 +1,149 @@ +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.20/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.22/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60= +modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw= +modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI= +modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag= +modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw= +modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ= +modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c= +modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo= +modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg= +modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I= +modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs= +modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8= +modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE= +modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk= +modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w= +modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE= +modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8= +modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc= +modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU= +modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE= +modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk= +modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI= +modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE= +modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg= +modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74= +modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU= +modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU= +modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc= +modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM= +modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ= +modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84= +modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ= +modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY= +modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w= +modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU= +modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko= +modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA= +modernc.org/ccgo/v3 v3.13.1/go.mod h1:aBYVOUfIlcSnrsRVU8VRS35y2DIfpgkmVkYZ0tpIXi4= +modernc.org/ccgo/v3 v3.15.9/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0= +modernc.org/ccgo/v3 v3.15.10/go.mod h1:wQKxoFn0ynxMuCLfFD09c8XPUCc8obfchoVR9Cn0fI8= +modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= +modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q= +modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg= +modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M= +modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU= +modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE= +modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso= +modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8= +modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8= +modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I= +modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk= +modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY= +modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE= +modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg= +modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM= +modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg= +modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo= +modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8= +modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ= +modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA= +modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM= +modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg= +modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE= +modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM= +modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU= +modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw= +modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M= +modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18= +modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8= +modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw= +modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0= +modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI= +modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE= +modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY= +modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ= +modernc.org/libc v1.11.98/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c= +modernc.org/libc v1.11.101/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI= +modernc.org/libc v1.12.0/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ= +modernc.org/libc v1.14.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= +modernc.org/libc v1.14.2/go.mod h1:MX1GBLnRLNdvmK9azU9LCxZ5lMyhrbEMK8rG3X/Fe34= +modernc.org/libc v1.14.4 h1:Sw2GDhSQbQF75VKC6RSd5//QH2gj9TgBzjLNZTW6m00= +modernc.org/libc v1.14.4/go.mod h1:GPIvQVOVPizzlqyRX3l756/3ppsAgg1QgPxjr5Q4agQ= +modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= +modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14= +modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= diff --git a/libwebp.go b/libwebp.go @@ -0,0 +1,41052 @@ +package main + +import ( + "math" + "reflect" + "sync/atomic" + "unsafe" + + "modernc.org/libc" + "modernc.org/libc/sys/types" +) + +var _ = math.Pi +var _ reflect.Kind +var _ atomic.Value +var _ unsafe.Pointer +var _ *libc.TLS +var _ types.Size_t + +//------------------------------------------------------------------------------ + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header: WebP decoding parameters and custom IO on buffer +// +// Author: somnath@google.com (Somnath Banerjee) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// VP8 decoder: internal header. +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.21 String handling <string.h> + +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Definitions and macros common to encoding and decoding +// +// Author: Skal (pascal.massimino@gmail.com) + +// intra prediction modes +const ( /* common_dec.h:18:1: */ + B_DC_PRED = 0 // 4x4 modes + B_TM_PRED = 1 + B_VE_PRED = 2 + B_HE_PRED = 3 + B_RD_PRED = 4 + B_VR_PRED = 5 + B_LD_PRED = 6 + B_VL_PRED = 7 + B_HD_PRED = 8 + B_HU_PRED = 9 + NUM_BMODES = 10 // = 10 + + // Luma16 or UV modes + DC_PRED = 0 + V_PRED = 2 + H_PRED = 3 + TM_PRED = 1 + B_PRED = 10 // refined I4x4 mode + NUM_PRED_MODES = 4 + + // special modes + B_DC_PRED_NOTOP = 4 + B_DC_PRED_NOLEFT = 5 + B_DC_PRED_NOTOPLEFT = 6 + NUM_B_DC_MODES = 7 +) + +const ( /* common_dec.h:42:1: */ + MB_FEATURE_TREE_PROBS = 3 + NUM_MB_SEGMENTS = 4 + NUM_REF_LF_DELTAS = 4 + NUM_MODE_LF_DELTAS = 4 // I4x4, ZERO, *, SPLIT + MAX_NUM_PARTITIONS = 8 + // Probabilities + NUM_TYPES = 4 // 0: i16-AC, 1: i16-DC, 2:chroma-AC, 3:i4-AC + NUM_BANDS = 8 + NUM_CTX = 3 + NUM_PROBAS = 11 +) + +const ( /* vp8li_dec.h:28:1: */ + READ_DATA = 0 + READ_HDR = 1 + READ_DIM = 2 +) + +//------------------------------------------------------------------------------ +// WEBP_RESTRICT + +// Declares a pointer with the restrict type qualifier if available. +// This allows code to hint to the compiler that only this pointer references a +// particular object or memory region within the scope of the block in which it +// is declared. This may allow for improved optimizations due to the lack of +// pointer aliasing. See also: +// https://en.cppreference.com/w/c/language/restrict + +//------------------------------------------------------------------------------ +// CPU detection + +// WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp +// files without intrinsics, allowing the corresponding Init() to be called. +// Files containing intrinsics will need to be built targeting the instruction +// set so should succeed on one of the earlier tests. + +// The intrinsics currently cause compiler errors with arm-nacl-gcc and the +// inline assembly would need to be modified for use with Native Client. + +// Note: ARM64 is supported in Visual Studio 2017, but requires the direct +// inclusion of arm64_neon.h; Visual Studio 2019 includes this file in +// arm_neon.h. Compile errors were seen with Visual Studio 2019 16.4 with +// vtbl4_u8(); a fix was made in 16.6. + +// This macro prevents thread_sanitizer from reporting known concurrent writes. + +// Defines an Init + helper function that control multiple initialization of +// function pointers / tables. +// Usage: +// WEBP_DSP_INIT_FUNC(InitFunc) { +// ...function body +// } + +// If 'ptr' is NULL, returns NULL. Otherwise returns 'ptr + off'. +// Prevents undefined behavior sanitizer nullptr-with-nonzero-offset warning. + +// Regularize the definition of WEBP_SWAP_16BIT_CSP (backward compatibility) + +// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__) + +const ( /* dsp.h:251:1: */ + kSSE2 = 0 + kSSE3 = 1 + kSlowSSSE3 = 2 // special feature for slow SSSE3 architectures + kSSE4_1 = 3 + kAVX = 4 + kAVX2 = 5 + kNEON = 6 + kMIPS32 = 7 + kMIPSdspR2 = 8 + kMSA = 9 +) + +//------------------------------------------------------------------------------ +// Filter functions + +const ( /* dsp.h:696:1: */ // Filter types. + WEBP_FILTER_NONE = 0 + WEBP_FILTER_HORIZONTAL = 1 + WEBP_FILTER_VERTICAL = 2 + WEBP_FILTER_GRADIENT = 3 + WEBP_FILTER_LAST = 4 // end marker + WEBP_FILTER_BEST = 5 // meta-types + WEBP_FILTER_FAST = 6 +) + +//------------------------------------------------------------------------------ +// Transform-related functions use din both encoding and decoding. + +// Macros used to create a batch predictor that iteratively uses a +// one-pixel predictor. + +// The predictor is added to the output pixel (which +// is therefore considered as a residual) to get the final prediction. + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// inline YUV<->RGB conversion function +// +// The exact naming is Y'CbCr, following the ITU-R BT.601 standard. +// More information at: https://en.wikipedia.org/wiki/YCbCr +// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16 +// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128 +// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128 +// We use 16bit fixed point operations for RGB->YUV conversion (YUV_FIX). +// +// For the Y'CbCr to RGB conversion, the BT.601 specification reads: +// R = 1.164 * (Y-16) + 1.596 * (V-128) +// G = 1.164 * (Y-16) - 0.813 * (V-128) - 0.391 * (U-128) +// B = 1.164 * (Y-16) + 2.018 * (U-128) +// where Y is in the [16,235] range, and U/V in the [16,240] range. +// +// The fixed-point implementation used here is: +// R = (19077 . y + 26149 . v - 14234) >> 6 +// G = (19077 . y - 6419 . u - 13320 . v + 8708) >> 6 +// B = (19077 . y + 33050 . u - 17685) >> 6 +// where the '.' operator is the mulhi_epu16 variant: +// a . b = ((a << 8) * b) >> 16 +// that preserves 8 bits of fractional precision before final descaling. + +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Low-level API for VP8 decoder +// +// Author: Skal (pascal.massimino@gmail.com) + +//------------------------------------------------------------------------------ +// YUV -> RGB conversion + +const ( /* yuv.h:48:1: */ + YUV_FIX = 16 // fixed-point precision for RGB->YUV + YUV_HALF = 32768 + + YUV_FIX2 = 6 // fixed-point precision for YUV->RGB + YUV_MASK2 = 16383 +) + +// ----------------------------------------------------------------------------- +// Main entry points + +const ( /* backward_references_enc.h:213:1: */ + kLZ77Standard = 1 + kLZ77RLE = 2 + kLZ77Box = 4 +) + +// Alpha related constants. + +// Mux related constants. + +// Maximum chunk payload is such that adding the header and padding won't +// overflow a uint32_t. + +// The maximum allowed limit is 11. + +// ----------------------------------------------------------------------------- +// PixOrCopy + +const ( /* backward_references_enc.h:32:1: */ + kLiteral = 0 + kCacheIdx = 1 + kCopy = 2 + kNone = 3 +) + +//------------------------------------------------------------------------------ + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP encoder: main interface +// +// Author: Skal (pascal.massimino@gmail.com) + +//------------------------------------------------------------------------------ +// Various defines and enums + +// version numbers + +const ( /* vp8i_enc.h:37:1: */ + MAX_LF_LEVELS = 64 // Maximum loop filter level + MAX_VARIABLE_LEVEL = 67 // last (inclusive) level with variable cost + MAX_LEVEL = 2047 +) + +const ( /* vp8i_enc.h:42:1: */ // Rate-distortion optimization levels + RD_OPT_NONE = 0 // no rd-opt + RD_OPT_BASIC = 1 // basic scoring (no trellis) + RD_OPT_TRELLIS = 2 // perform trellis-quant on the final decision only + RD_OPT_TRELLIS_ALL = 3 +) + +//------------------------------------------------------------------------------ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Lossless encoder: internal header. +// +// Author: Vikas Arora (vikaas.arora@gmail.com) + +// src/webp/config.h. Generated from config.h.in by configure. +// src/webp/config.h.in. Generated from configure.ac by autoheader. + +// Define if building universal (internal helper macro) +// #undef AC_APPLE_UNIVERSAL_BUILD + +// Set to 1 if __builtin_bswap16 is available + +// Set to 1 if __builtin_bswap32 is available + +// Set to 1 if __builtin_bswap64 is available + +// Define to 1 if you have the <cpu-features.h> header file. +// #undef HAVE_CPU_FEATURES_H + +// Define to 1 if you have the <dlfcn.h> header file. + +// Define to 1 if you have the <GLUT/glut.h> header file. +// #undef HAVE_GLUT_GLUT_H + +// Define to 1 if you have the <GL/glut.h> header file. +// #undef HAVE_GL_GLUT_H + +// Define to 1 if you have the <inttypes.h> header file. + +// Define to 1 if you have the <OpenGL/glut.h> header file. +// #undef HAVE_OPENGL_GLUT_H + +// Have PTHREAD_PRIO_INHERIT. +// #undef HAVE_PTHREAD_PRIO_INHERIT + +// Define to 1 if you have the <shlwapi.h> header file. +// #undef HAVE_SHLWAPI_H + +// Define to 1 if you have the <stdint.h> header file. + +// Define to 1 if you have the <stdio.h> header file. + +// Define to 1 if you have the <stdlib.h> header file. + +// Define to 1 if you have the <strings.h> header file. + +// Define to 1 if you have the <string.h> header file. + +// Define to 1 if you have the <sys/stat.h> header file. + +// Define to 1 if you have the <sys/types.h> header file. + +// Define to 1 if you have the <unistd.h> header file. + +// Define to 1 if you have the <wincodec.h> header file. +// #undef HAVE_WINCODEC_H + +// Define to 1 if you have the <windows.h> header file. +// #undef HAVE_WINDOWS_H + +// Define to the sub-directory where libtool stores uninstalled libraries. + +// Name of package + +// Define to the address where bug reports for this package should be sent. + +// Define to the full name of this package. + +// Define to the full name and version of this package. + +// Define to the one symbol short name of this package. + +// Define to the home page for this package. + +// Define to the version of this package. + +// Define to necessary symbol if this constant uses a non-standard name on +// your system. +// #undef PTHREAD_CREATE_JOINABLE + +// Define to 1 if all of the C90 standard headers exist (not just the ones +// required in a freestanding environment). This macro is provided for +// backward compatibility; new code need not use it. + +// Version number of package + +// Set to 1 if GIF library is installed +// #undef WEBP_HAVE_GIF + +// Set to 1 if OpenGL is supported +// #undef WEBP_HAVE_GL + +// Set to 1 if JPEG library is installed +// #undef WEBP_HAVE_JPEG + +// Set to 1 if NEON is supported +// #undef WEBP_HAVE_NEON + +// Set to 1 if runtime detection of NEON is enabled +// #undef WEBP_HAVE_NEON_RTCD + +// Set to 1 if PNG library is installed +// #undef WEBP_HAVE_PNG + +// Set to 1 if SDL library is installed +// #undef WEBP_HAVE_SDL + +// Set to 1 if SSE2 is supported +// #undef WEBP_HAVE_SSE2 + +// Set to 1 if SSE4.1 is supported +// #undef WEBP_HAVE_SSE41 + +// Set to 1 if TIFF library is installed +// #undef WEBP_HAVE_TIFF + +// Enable near lossless encoding + +// Undefine this to disable thread support. +// #undef WEBP_USE_THREAD + +// Define WORDS_BIGENDIAN to 1 if your processor stores words with the most +// significant byte first (like Motorola and SPARC, unlike Intel). +// # undef WORDS_BIGENDIAN +// Either WEBP_NEAR_LOSSLESS is defined as 0 in config.h when compiling to +// disable near-lossless, or it is enabled by default. + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +// Models the histograms of literal and distance codes. + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Bit writing and boolean coder +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP encoder: main interface +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header for constants related to WebP file format. +// +// Author: Urvang (urvang@google.com) + +// maximum value of transform_bits_ in VP8LEncoder. + +const ( /* vp8li_enc.h:39:1: */ + kEncoderNone = 0 + kEncoderARGB = 1 + kEncoderNearLossless = 2 + kEncoderPalette = 3 +) + +//------------------------------------------------------------------------------ + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Multi-threaded worker +// +// Author: Skal (pascal.massimino@gmail.com) + +// src/webp/config.h. Generated from config.h.in by configure. +// src/webp/config.h.in. Generated from configure.ac by autoheader. + +// Define if building universal (internal helper macro) +// #undef AC_APPLE_UNIVERSAL_BUILD + +// Set to 1 if __builtin_bswap16 is available + +// Set to 1 if __builtin_bswap32 is available + +// Set to 1 if __builtin_bswap64 is available + +// Define to 1 if you have the <cpu-features.h> header file. +// #undef HAVE_CPU_FEATURES_H + +// Define to 1 if you have the <dlfcn.h> header file. + +// Define to 1 if you have the <GLUT/glut.h> header file. +// #undef HAVE_GLUT_GLUT_H + +// Define to 1 if you have the <GL/glut.h> header file. +// #undef HAVE_GL_GLUT_H + +// Define to 1 if you have the <inttypes.h> header file. + +// Define to 1 if you have the <OpenGL/glut.h> header file. +// #undef HAVE_OPENGL_GLUT_H + +// Have PTHREAD_PRIO_INHERIT. +// #undef HAVE_PTHREAD_PRIO_INHERIT + +// Define to 1 if you have the <shlwapi.h> header file. +// #undef HAVE_SHLWAPI_H + +// Define to 1 if you have the <stdint.h> header file. + +// Define to 1 if you have the <stdio.h> header file. + +// Define to 1 if you have the <stdlib.h> header file. + +// Define to 1 if you have the <strings.h> header file. + +// Define to 1 if you have the <string.h> header file. + +// Define to 1 if you have the <sys/stat.h> header file. + +// Define to 1 if you have the <sys/types.h> header file. + +// Define to 1 if you have the <unistd.h> header file. + +// Define to 1 if you have the <wincodec.h> header file. +// #undef HAVE_WINCODEC_H + +// Define to 1 if you have the <windows.h> header file. +// #undef HAVE_WINDOWS_H + +// Define to the sub-directory where libtool stores uninstalled libraries. + +// Name of package + +// Define to the address where bug reports for this package should be sent. + +// Define to the full name of this package. + +// Define to the full name and version of this package. + +// Define to the one symbol short name of this package. + +// Define to the home page for this package. + +// Define to the version of this package. + +// Define to necessary symbol if this constant uses a non-standard name on +// your system. +// #undef PTHREAD_CREATE_JOINABLE + +// Define to 1 if all of the C90 standard headers exist (not just the ones +// required in a freestanding environment). This macro is provided for +// backward compatibility; new code need not use it. + +// Version number of package + +// Set to 1 if GIF library is installed +// #undef WEBP_HAVE_GIF + +// Set to 1 if OpenGL is supported +// #undef WEBP_HAVE_GL + +// Set to 1 if JPEG library is installed +// #undef WEBP_HAVE_JPEG + +// Set to 1 if NEON is supported +// #undef WEBP_HAVE_NEON + +// Set to 1 if runtime detection of NEON is enabled +// #undef WEBP_HAVE_NEON_RTCD + +// Set to 1 if PNG library is installed +// #undef WEBP_HAVE_PNG + +// Set to 1 if SDL library is installed +// #undef WEBP_HAVE_SDL + +// Set to 1 if SSE2 is supported +// #undef WEBP_HAVE_SSE2 + +// Set to 1 if SSE4.1 is supported +// #undef WEBP_HAVE_SSE41 + +// Set to 1 if TIFF library is installed +// #undef WEBP_HAVE_TIFF + +// Enable near lossless encoding + +// Undefine this to disable thread support. +// #undef WEBP_USE_THREAD + +// Define WORDS_BIGENDIAN to 1 if your processor stores words with the most +// significant byte first (like Motorola and SPARC, unlike Intel). +// # undef WORDS_BIGENDIAN + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// State of the worker thread object +const ( /* thread_utils.h:28:1: */ + NOT_OK = 0 // object is unusable + OK = 1 // ready to work + WORK = 2 +) + +//------------------------------------------------------------------------------ +// Output colorspaces and buffer + +// Colorspaces +// Note: the naming describes the byte-ordering of packed samples in memory. +// For instance, MODE_BGRA relates to samples ordered as B,G,R,A,B,G,R,A,... +// Non-capital names (e.g.:MODE_Argb) relates to pre-multiplied RGB channels. +// RGBA-4444 and RGB-565 colorspaces are represented by following byte-order: +// RGBA-4444: [r3 r2 r1 r0 g3 g2 g1 g0], [b3 b2 b1 b0 a3 a2 a1 a0], ... +// RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ... +// In the case WEBP_SWAP_16BITS_CSP is defined, the bytes are swapped for +// these two modes: +// RGBA-4444: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], ... +// RGB-565: [g2 g1 g0 b4 b3 b2 b1 b0], [r4 r3 r2 r1 r0 g5 g4 g3], ... + +const ( /* decode.h:149:1: */ + MODE_RGB = 0 + MODE_RGBA = 1 + MODE_BGR = 2 + MODE_BGRA = 3 + MODE_ARGB = 4 + MODE_RGBA_4444 = 5 + MODE_RGB_565 = 6 + // RGB-premultiplied transparent modes (alpha value is preserved) + MODE_rgbA = 7 + MODE_bgrA = 8 + MODE_Argb = 9 + MODE_rgbA_4444 = 10 + // YUV modes must come after RGB ones. + MODE_YUV = 11 + MODE_YUVA = 12 // yuv 4:2:0 + MODE_LAST = 13 +) + +//------------------------------------------------------------------------------ +// Enumeration of the status codes + +const ( /* decode.h:234:1: */ + VP8_STATUS_OK = 0 + VP8_STATUS_OUT_OF_MEMORY = 1 + VP8_STATUS_INVALID_PARAM = 2 + VP8_STATUS_BITSTREAM_ERROR = 3 + VP8_STATUS_UNSUPPORTED_FEATURE = 4 + VP8_STATUS_SUSPENDED = 5 + VP8_STATUS_USER_ABORT = 6 + VP8_STATUS_NOT_ENOUGH_DATA = 7 +) + +// Enumerate some predefined settings for WebPConfig, depending on the type +// of source picture. These presets are used when calling WebPConfigPreset(). +const ( /* encode.h:157:1: */ + WEBP_PRESET_DEFAULT = 0 // default preset. + WEBP_PRESET_PICTURE = 1 // digital picture, like portrait, inner shot + WEBP_PRESET_PHOTO = 2 // outdoor photograph, with natural lighting + WEBP_PRESET_DRAWING = 3 // hand or line drawing, with high-contrast details + WEBP_PRESET_ICON = 4 // small-sized colorful images + WEBP_PRESET_TEXT = 5 +) + +// Color spaces. +const ( /* encode.h:267:1: */ + // chroma sampling + WEBP_YUV420 = 0 // 4:2:0 + WEBP_YUV420A = 4 // alpha channel variant + WEBP_CSP_UV_MASK = 3 // bit-mask to get the UV sampling factors + WEBP_CSP_ALPHA_BIT = 4 +) + +// Encoding error conditions. +const ( /* encode.h:276:1: */ + VP8_ENC_OK = 0 + VP8_ENC_ERROR_OUT_OF_MEMORY = 1 // memory error allocating objects + VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY = 2 // memory error while flushing bits + VP8_ENC_ERROR_NULL_PARAMETER = 3 // a pointer parameter is NULL + VP8_ENC_ERROR_INVALID_CONFIGURATION = 4 // configuration is invalid + VP8_ENC_ERROR_BAD_DIMENSION = 5 // picture has invalid width/height + VP8_ENC_ERROR_PARTITION0_OVERFLOW = 6 // partition is bigger than 512k + VP8_ENC_ERROR_PARTITION_OVERFLOW = 7 // partition is bigger than 16M + VP8_ENC_ERROR_BAD_WRITE = 8 // error while flushing bytes + VP8_ENC_ERROR_FILE_TOO_BIG = 9 // file is bigger than 4G + VP8_ENC_ERROR_USER_ABORT = 10 // abort request by user + VP8_ENC_ERROR_LAST = 11 +) + +//------------------------------------------------------------------------------ +// Coding parameters + +// Image characteristics hint for the underlying encoder. +const ( /* encode.h:86:1: */ + WEBP_HINT_DEFAULT = 0 // default preset. + WEBP_HINT_PICTURE = 1 // digital picture, like portrait, inner shot + WEBP_HINT_PHOTO = 2 // outdoor photograph, with natural lighting + WEBP_HINT_GRAPH = 3 // Discrete tone image (graph, map-tile etc). + WEBP_HINT_LAST = 4 +) + +//------------------------------------------------------------------------------ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for building and looking up Huffman trees. +// +// Author: Urvang Joshi (urvang@google.com) + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.2 Diagnostics <assert.h> + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// void assert (int expression); +// +// If NDEBUG is defined, do nothing. +// If not, and EXPRESSION is zero, print an error message and abort. + +// void assert_perror (int errnum); +// +// If NDEBUG is defined, do nothing. If not, and ERRNUM is not zero, print an +// error message with the error text for ERRNUM and abort. +// (This is a GNU extension.) + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header for constants related to WebP file format. +// +// Author: Urvang (urvang@google.com) + +// Create fourcc of the chunk from the chunk tag characters. + +// VP8 related constants. + +// VP8L related constants. +// width and height. + +// to be read is a transform. +// in a bitstream. +const ( /* format_constants.h:55:1: */ + PREDICTOR_TRANSFORM = 0 + CROSS_COLOR_TRANSFORM = 1 + SUBTRACT_GREEN = 2 + COLOR_INDEXING_TRANSFORM = 3 +) + +// VP8X Feature Flags. +const ( /* mux_types.h:32:1: */ + ANIMATION_FLAG = 2 + XMP_FLAG = 4 + EXIF_FLAG = 8 + ALPHA_FLAG = 16 + ICCP_FLAG = 32 + + ALL_VALID_FLAGS = 62 +) + +// Dispose method (animation only). Indicates how the area used by the current +// frame is to be treated before rendering the next frame on the canvas. +const ( /* mux_types.h:44:1: */ + WEBP_MUX_DISPOSE_NONE = 0 // Do not dispose. + WEBP_MUX_DISPOSE_BACKGROUND = 1 +) + +// Blend operation (animation only). Indicates how transparent pixels of the +// current frame are blended with those of the previous canvas. +const ( /* mux_types.h:51:1: */ + WEBP_MUX_BLEND = 0 // Blend. + WEBP_MUX_NO_BLEND = 1 +) + +// Depending on the type of TG_ARG, call an appropriately suffixed +// version of FUNC with arguments (including parentheses) ARGS. +// Suffixed functions may not exist for long double if it has the same +// format as double, or for other types with the same format as float, +// double or long double. The behavior is undefined if the argument +// does not have a real floating type. The definition may use a +// conditional expression, so all suffixed versions of FUNC must +// return the same type (FUNC may include a cast if necessary rather +// than being a single identifier). + +// ISO C99 defines some generic macros which work on any data type. + +// All floating-point numbers can be put in one of these categories. +const ( /* math.h:914:1: */ + FP_NAN = 0 + FP_INFINITE = 1 + FP_ZERO = 2 + FP_SUBNORMAL = 3 + FP_NORMAL = 4 +) + +//------------------------------------------------------------------------------ + +// In append mode, buffer allocations increase as multiples of this value. +// Needs to be a power of 2. + +//------------------------------------------------------------------------------ +// Data structures for memory and states + +// Decoding states. State normally flows as: +// WEBP_HEADER->VP8_HEADER->VP8_PARTS0->VP8_DATA->DONE for a lossy image, and +// WEBP_HEADER->VP8L_HEADER->VP8L_DATA->DONE for a lossless image. +// If there is any error the decoder goes into state ERROR. +const ( /* idec_dec.c:35:1: */ + STATE_WEBP_HEADER = 0 // All the data before that of the VP8/VP8L chunk. + STATE_VP8_HEADER = 1 // The VP8 Frame header (within the VP8 chunk). + STATE_VP8_PARTS0 = 2 + STATE_VP8_DATA = 3 + STATE_VP8L_HEADER = 4 + STATE_VP8L_DATA = 5 + STATE_DONE = 6 + STATE_ERROR = 7 +) + +// Operating state for the MemBuffer +const ( /* idec_dec.c:47:1: */ + MEM_MODE_NONE = 0 + MEM_MODE_APPEND = 1 + MEM_MODE_MAP = 2 +) + +// Coefficient type. +const ( /* quant_enc.c:589:1: */ + TYPE_I16_AC = 0 + TYPE_I16_DC = 1 + TYPE_CHROMA_A = 2 + TYPE_I4_AC = 3 +) + +// ----------------------------------------------------------------------------- +// Five Huffman codes are used at each meta code: +// 1. green + length prefix codes + color cache codes, +// 2. alpha, +// 3. red, +// 4. blue, and, +// 5. distance prefix codes. +const ( /* vp8l_dec.c:41:1: */ + GREEN = 0 + RED = 1 + BLUE = 2 + ALPHA = 3 + DIST = 4 +) + +// ----------------------------------------------------------------------------- +// Palette + +// These five modes are evaluated and their respective entropy is computed. +const ( /* vp8l_enc.c:326:1: */ + kDirect = 0 + kSpatial = 1 + kSubGreen = 2 + kSpatialSubGreen = 3 + kPalette = 4 + kPaletteAndSpatial = 5 + kNumEntropyIx = 6 +) + +const ( /* vp8l_enc.c:336:1: */ + kSortedDefault = 0 + kMinimizeDelta = 1 + kModifiedZeng = 2 + kUnusedPalette = 3 +) + +const ( /* vp8l_enc.c:343:1: */ + kHistoAlpha = 0 + kHistoAlphaPred = 1 + kHistoGreen = 2 + kHistoGreenPred = 3 + kHistoRed = 4 + kHistoRedPred = 5 + kHistoBlue = 6 + kHistoBluePred = 7 + kHistoRedSubGreen = 8 + kHistoRedPredSubGreen = 9 + kHistoBlueSubGreen = 10 + kHistoBluePredSubGreen = 11 + kHistoPalette = 12 + kHistoTotal = 13 +) + +type ptrdiff_t = int64 /* <builtin>:3:26 */ + +type size_t = uint64 /* <builtin>:9:23 */ + +type wchar_t = int32 /* <builtin>:15:24 */ + +// A null pointer constant. + +// XPG requires a few symbols from <sys/wait.h> being defined. +// Definitions of flag bits for `waitpid' et al. +// Copyright (C) 1992-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Bits in the third argument to `waitpid'. + +// Bits in the fourth argument to `waitid'. + +// Definitions of status bits for `wait' et al. +// Copyright (C) 1992-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Everything extant so far uses these same bits. + +// If WIFEXITED(STATUS), the low-order 8 bits of the status. + +// If WIFSIGNALED(STATUS), the terminating signal. + +// If WIFSTOPPED(STATUS), the signal that stopped the child. + +// Nonzero if STATUS indicates normal termination. + +// Nonzero if STATUS indicates termination by a signal. + +// Nonzero if STATUS indicates the child is stopped. + +// Nonzero if STATUS indicates the child continued after a stop. We only +// define this if <bits/waitflags.h> provides the WCONTINUED flag bit. + +// Nonzero if STATUS indicates the child dumped core. + +// Macros for constructing status values. + +// Define the macros <sys/wait.h> also would define this way. + +// _FloatN API tests for enablement. +// Macros to control TS 18661-3 glibc features on x86. +// Copyright (C) 2017-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Defined to 1 if the current compiler invocation provides a +// floating-point type with the IEEE 754 binary128 format, and this +// glibc includes corresponding *f128 interfaces for it. The required +// libgcc support was added some time after the basic compiler +// support, for x86_64 and x86. + +// Defined to 1 if __HAVE_FLOAT128 is 1 and the type is ABI-distinct +// from the default float, double and long double types in this glibc. + +// Defined to 1 if the current compiler invocation provides a +// floating-point type with the right format for _Float64x, and this +// glibc includes corresponding *f64x interfaces for it. + +// Defined to 1 if __HAVE_FLOAT64X is 1 and _Float64x has the format +// of long double. Otherwise, if __HAVE_FLOAT64X is 1, _Float64x has +// the format of _Float128, which must be different from that of long +// double. + +// Defined to concatenate the literal suffix to be used with _Float128 +// types, if __HAVE_FLOAT128 is 1. + +// Defined to a complex binary128 type if __HAVE_FLOAT128 is 1. + +// The remaining of this file provides support for older compilers. + +// The type _Float128 exists only since GCC 7.0. + +// __builtin_huge_valf128 doesn't exist before GCC 7.0. + +// Older GCC has only a subset of built-in functions for _Float128 on +// x86, and __builtin_infq is not usable in static initializers. +// Converting a narrower sNaN to _Float128 produces a quiet NaN, so +// attempts to use _Float128 sNaNs will not work properly with older +// compilers. + +// In math/math.h, __MATH_TG will expand signbit to __builtin_signbit*, +// e.g.: __builtin_signbitf128, before GCC 6. However, there has never +// been a __builtin_signbitf128 in GCC and the type-generic builtin is +// only available since GCC 6. + +// Macros to control TS 18661-3 glibc features where the same +// definitions are appropriate for all platforms. +// Copyright (C) 2017-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Properties of long double type. ldbl-96 version. +// Copyright (C) 2016-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// long double is distinct from double, so there is nothing to +// define here. + +// This header should be included at the bottom of each bits/floatn.h. +// It defines the following macros for each _FloatN and _FloatNx type, +// where the same definitions, or definitions based only on the macros +// in bits/floatn.h, are appropriate for all glibc configurations. + +// Defined to 1 if the current compiler invocation provides a +// floating-point type with the right format for this type, and this +// glibc includes corresponding *fN or *fNx interfaces for it. + +// Defined to 1 if the corresponding __HAVE_<type> macro is 1 and the +// type is the first with its format in the sequence of (the default +// choices for) float, double, long double, _Float16, _Float32, +// _Float64, _Float128, _Float32x, _Float64x, _Float128x for this +// glibc; that is, if functions present once per floating-point format +// rather than once per type are present for this type. +// +// All configurations supported by glibc have _Float32 the same format +// as float, _Float64 and _Float32x the same format as double, the +// _Float64x the same format as either long double or _Float128. No +// configurations support _Float128x or, as of GCC 7, have compiler +// support for a type meeting the requirements for _Float128x. + +// Defined to 1 if the corresponding _FloatN type is not binary compatible +// with the corresponding ISO C type in the current compilation unit as +// opposed to __HAVE_DISTINCT_FLOATN, which indicates the default types built +// in glibc. + +// Defined to 1 if any _FloatN or _FloatNx types that are not +// ABI-distinct are however distinct types at the C language level (so +// for the purposes of __builtin_types_compatible_p and _Generic). + +// Defined to concatenate the literal suffix to be used with _FloatN +// or _FloatNx types, if __HAVE_<type> is 1. The corresponding +// literal suffixes exist since GCC 7, for C only. + +// Defined to a complex type if __HAVE_<type> is 1. + +// The remaining of this file provides support for older compilers. + +// If double, long double and _Float64 all have the same set of +// values, TS 18661-3 requires the usual arithmetic conversions on +// long double and _Float64 to produce _Float64. For this to be the +// case when building with a compiler without a distinct _Float64 +// type, _Float64 must be a typedef for long double, not for +// double. + +// Returned by `div'. +type div_t = struct { + quot int32 + rem int32 +} /* stdlib.h:62:5 */ + +// Returned by `ldiv'. +type ldiv_t = struct { + quot int64 + rem int64 +} /* stdlib.h:70:5 */ + +// Returned by `lldiv'. +type lldiv_t = struct { + quot int64 + rem int64 +} /* stdlib.h:80:5 */ + +// Seconds since the Epoch, visible to user code when time_t is too +// narrow only for consistency with the old way of widening too-narrow +// types. User code should never use __time64_t. + +type u_char = uint8 /* types.h:33:18 */ +type u_short = uint16 /* types.h:34:19 */ +type u_int = uint32 /* types.h:35:17 */ +type u_long = uint64 /* types.h:36:18 */ +type quad_t = int64 /* types.h:37:18 */ +type u_quad_t = uint64 /* types.h:38:20 */ +type fsid_t = struct{ __val [2]int32 } /* types.h:39:18 */ +type loff_t = int64 /* types.h:42:18 */ + +type ino_t = uint64 /* types.h:49:19 */ + +type dev_t = uint64 /* types.h:59:17 */ + +type gid_t = uint32 /* types.h:64:17 */ + +type mode_t = uint32 /* types.h:69:18 */ + +type nlink_t = uint64 /* types.h:74:19 */ + +type uid_t = uint32 /* types.h:79:17 */ + +type off_t = int64 /* types.h:87:19 */ + +type pid_t = int32 /* types.h:97:17 */ + +type id_t = uint32 /* types.h:103:16 */ + +type ssize_t = int64 /* types.h:108:19 */ + +type daddr_t = int32 /* types.h:114:19 */ +type caddr_t = uintptr /* types.h:115:19 */ + +type key_t = int32 /* types.h:121:17 */ + +// bits/types.h -- definitions of __*_t types underlying *_t types. +// Copyright (C) 2002-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Never include this file directly; use <sys/types.h> instead. + +// Returned by `clock'. +type clock_t = int64 /* clock_t.h:7:19 */ + +// bits/types.h -- definitions of __*_t types underlying *_t types. +// Copyright (C) 2002-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Never include this file directly; use <sys/types.h> instead. + +// Clock ID used in clock and timer functions. +type clockid_t = int32 /* clockid_t.h:7:21 */ + +// bits/types.h -- definitions of __*_t types underlying *_t types. +// Copyright (C) 2002-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Never include this file directly; use <sys/types.h> instead. + +// Returned by `time'. +type time_t = int64 /* time_t.h:7:18 */ + +// bits/types.h -- definitions of __*_t types underlying *_t types. +// Copyright (C) 2002-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Never include this file directly; use <sys/types.h> instead. + +// Timer ID returned by `timer_create'. +type timer_t = uintptr /* timer_t.h:7:19 */ + +// Copyright (C) 1989-2021 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. +// +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +// ISO C Standard: 7.17 Common definitions <stddef.h> + +// Any one of these symbols __need_* means that GNU libc +// wants us just to define one data type. So don't define +// the symbols that indicate this file's entire job has been done. + +// This avoids lossage on SunOS but only if stdtypes.h comes first. +// There's no way to win with the other order! Sun lossage. + +// Sequent's header files use _PTRDIFF_T_ in some conflicting way. +// Just ignore it. + +// On VxWorks, <type/vxTypesBase.h> may have defined macros like +// _TYPE_size_t which will typedef size_t. fixincludes patched the +// vxTypesBase.h so that this macro is only defined if _GCC_SIZE_T is +// not defined, and so that defining this macro defines _GCC_SIZE_T. +// If we find that the macros are still defined at this point, we must +// invoke them so that the type is defined as expected. + +// In case nobody has defined these types, but we aren't running under +// GCC 2.00, make sure that __PTRDIFF_TYPE__, __SIZE_TYPE__, and +// __WCHAR_TYPE__ have reasonable values. This can happen if the +// parts of GCC is compiled by an older compiler, that actually +// include gstddef.h, such as collect2. + +// Signed type of difference of two pointers. + +// Define this type if we are doing the whole job, +// or if we want this type in particular. + +// Unsigned type of `sizeof' something. + +// Define this type if we are doing the whole job, +// or if we want this type in particular. + +// Wide character type. +// Locale-writers should change this as necessary to +// be big enough to hold unique values not between 0 and 127, +// and not (wchar_t) -1, for each defined multibyte character. + +// Define this type if we are doing the whole job, +// or if we want this type in particular. + +// A null pointer constant. + +// Old compatibility names for C types. +type ulong = uint64 /* types.h:148:27 */ +type ushort = uint16 /* types.h:149:28 */ +type uint = uint32 /* types.h:150:22 */ + +// These size-specific names are used by some of the inet code. + +// Define intN_t types. +// Copyright (C) 2017-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// bits/types.h -- definitions of __*_t types underlying *_t types. +// Copyright (C) 2002-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Never include this file directly; use <sys/types.h> instead. + +type int8_t = int8 /* stdint-intn.h:24:18 */ +type int16_t = int16 /* stdint-intn.h:25:19 */ +type int32_t = int32 /* stdint-intn.h:26:19 */ +type int64_t = int64 /* stdint-intn.h:27:19 */ + +// These were defined by ISO C without the first `_'. +type u_int8_t = uint8 /* types.h:158:19 */ +type u_int16_t = uint16 /* types.h:159:20 */ +type u_int32_t = uint32 /* types.h:160:20 */ +type u_int64_t = uint64 /* types.h:161:20 */ + +type register_t = int32 /* types.h:164:13 */ + +// A set of signals to be blocked, unblocked, or waited for. +type sigset_t = struct{ __val [16]uint64 } /* sigset_t.h:7:20 */ + +// Get definition of timer specification structures. + +// bits/types.h -- definitions of __*_t types underlying *_t types. +// Copyright (C) 2002-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Never include this file directly; use <sys/types.h> instead. + +// A time value that is accurate to the nearest +// microsecond but also has a range of years. +type timeval = struct { + tv_sec int64 + tv_usec int64 +} /* struct_timeval.h:8:1 */ + +// NB: Include guard matches what <linux/time.h> uses. + +// bits/types.h -- definitions of __*_t types underlying *_t types. +// Copyright (C) 2002-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Never include this file directly; use <sys/types.h> instead. + +// Endian macros for string.h functions +// Copyright (C) 1992-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <http://www.gnu.org/licenses/>. + +// POSIX.1b structure for a time value. This is like a `struct timeval' but +// has nanoseconds instead of microseconds. +type timespec = struct { + tv_sec int64 + tv_nsec int64 +} /* struct_timespec.h:10:1 */ + +type suseconds_t = int64 /* select.h:43:23 */ + +// Some versions of <linux/posix_types.h> define this macros. +// It's easier to assume 8-bit bytes than to get CHAR_BIT. + +// fd_set for select and pselect. +type fd_set = struct{ __fds_bits [16]int64 } /* select.h:70:5 */ + +// Maximum number of file descriptors in `fd_set'. + +// Sometimes the fd_set member is assumed to have this type. +type fd_mask = int64 /* select.h:77:19 */ + +// Define some inlines helping to catch common problems. + +type blksize_t = int64 /* types.h:185:21 */ + +// Types from the Large File Support interface. +type blkcnt_t = int64 /* types.h:205:22 */ // Type to count number of disk blocks. +type fsblkcnt_t = uint64 /* types.h:209:24 */ // Type to count file system blocks. +type fsfilcnt_t = uint64 /* types.h:213:24 */ // Type to count file system inodes. + +// Now add the thread types. +// Declaration of common pthread types for all architectures. +// Copyright (C) 2017-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// For internal mutex and condition variable definitions. +// Common threading primitives definitions for both POSIX and C11. +// Copyright (C) 2017-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Arch-specific definitions. Each architecture must define the following +// macros to define the expected sizes of pthread data types: +// +// __SIZEOF_PTHREAD_ATTR_T - size of pthread_attr_t. +// __SIZEOF_PTHREAD_MUTEX_T - size of pthread_mutex_t. +// __SIZEOF_PTHREAD_MUTEXATTR_T - size of pthread_mutexattr_t. +// __SIZEOF_PTHREAD_COND_T - size of pthread_cond_t. +// __SIZEOF_PTHREAD_CONDATTR_T - size of pthread_condattr_t. +// __SIZEOF_PTHREAD_RWLOCK_T - size of pthread_rwlock_t. +// __SIZEOF_PTHREAD_RWLOCKATTR_T - size of pthread_rwlockattr_t. +// __SIZEOF_PTHREAD_BARRIER_T - size of pthread_barrier_t. +// __SIZEOF_PTHREAD_BARRIERATTR_T - size of pthread_barrierattr_t. +// +// The additional macro defines any constraint for the lock alignment +// inside the thread structures: +// +// __LOCK_ALIGNMENT - for internal lock/futex usage. +// +// Same idea but for the once locking primitive: +// +// __ONCE_ALIGNMENT - for pthread_once_t/once_flag definition. + +// Copyright (C) 2002-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Determine the wordsize from the preprocessor defines. + +// Both x86-64 and x32 use the 64-bit system call interface. + +// Common definition of pthread_mutex_t. + +type __pthread_internal_list = struct { + __prev uintptr + __next uintptr +} /* thread-shared-types.h:49:9 */ + +type __pthread_internal_slist = struct{ __next uintptr } /* thread-shared-types.h:55:9 */ + +// Arch-specific mutex definitions. A generic implementation is provided +// by sysdeps/nptl/bits/struct_mutex.h. If required, an architecture +// can override it by defining: +// +// 1. struct __pthread_mutex_s (used on both pthread_mutex_t and mtx_t +// definition). It should contains at least the internal members +// defined in the generic version. +// +// 2. __LOCK_ALIGNMENT for any extra attribute for internal lock used with +// atomic operations. +// +// 3. The macro __PTHREAD_MUTEX_INITIALIZER used for static initialization. +// It should initialize the mutex internal flag. + +// x86 internal mutex struct definitions. +// Copyright (C) 2019-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <http://www.gnu.org/licenses/>. + +type __pthread_mutex_s = struct { + __lock int32 + __count uint32 + __owner int32 + __nusers uint32 + __kind int32 + __spins int16 + __elision int16 + __list struct { + __prev uintptr + __next uintptr + } +} /* struct_mutex.h:22:1 */ + +// Arch-sepecific read-write lock definitions. A generic implementation is +// provided by struct_rwlock.h. If required, an architecture can override it +// by defining: +// +// 1. struct __pthread_rwlock_arch_t (used on pthread_rwlock_t definition). +// It should contain at least the internal members defined in the +// generic version. +// +// 2. The macro __PTHREAD_RWLOCK_INITIALIZER used for static initialization. +// It should initialize the rwlock internal type. + +// x86 internal rwlock struct definitions. +// Copyright (C) 2019-2021 Free Software Foundation, Inc. +// +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <http://www.gnu.org/licenses/>. + +type __pthread_rwlock_arch_t = struct { + __readers uint32 + __writers uint32 + __wrphase_futex uint32 + __writers_futex uint32 + __pad3 uint32 + __pad4 uint32 + __cur_writer int32 + __shared int32 + __rwelision int8 + __pad1 [7]uint8 + __pad2 uint64 + __flags uint32 + _ [4]byte +} /* struct_rwlock.h:23:1 */ + +// Common definition of pthread_cond_t. + +type __pthread_cond_s = struct { + __0 struct{ __wseq uint64 } + __8 struct{ __g1_start uint64 } + __g_refs [2]uint32 + __g_size [2]uint32 + __g1_orig_size uint32 + __wrefs uint32 + __g_signals [2]uint32 +} /* thread-shared-types.h:92:1 */ + +// Thread identifiers. The structure of the attribute type is not +// exposed on purpose. +type pthread_t = uint64 /* pthreadtypes.h:27:27 */ + +// Data structures for mutex handling. The structure of the attribute +// type is not exposed on purpose. +type pthread_mutexattr_t = struct { + _ [0]uint32 + __size [4]int8 +} /* pthreadtypes.h:36:3 */ + +// Data structure for condition variable handling. The structure of +// the attribute type is not exposed on purpose. +type pthread_condattr_t = struct { + _ [0]uint32 + __size [4]int8 +} /* pthreadtypes.h:45:3 */ + +// Keys for thread-specific data +type pthread_key_t = uint32 /* pthreadtypes.h:49:22 */ + +// Once-only execution +type pthread_once_t = int32 /* pthreadtypes.h:53:30 */ + +type pthread_attr_t1 = struct { + _ [0]uint64 + __size [56]int8 +} /* pthreadtypes.h:56:1 */ + +type pthread_attr_t = pthread_attr_t1 /* pthreadtypes.h:62:30 */ + +type pthread_mutex_t = struct{ __data __pthread_mutex_s } /* pthreadtypes.h:72:3 */ + +type pthread_cond_t = struct{ __data __pthread_cond_s } /* pthreadtypes.h:80:3 */ + +// Data structure for reader-writer lock variable handling. The +// structure of the attribute type is deliberately not exposed. +type pthread_rwlock_t = struct{ __data __pthread_rwlock_arch_t } /* pthreadtypes.h:91:3 */ + +type pthread_rwlockattr_t = struct { + _ [0]uint64 + __size [8]int8 +} /* pthreadtypes.h:97:3 */ + +// POSIX spinlock data type. +type pthread_spinlock_t = int32 /* pthreadtypes.h:103:22 */ + +// POSIX barriers data type. The structure of the type is +// deliberately not exposed. +type pthread_barrier_t = struct { + _ [0]uint64 + __size [32]int8 +} /* pthreadtypes.h:112:3 */ + +type pthread_barrierattr_t = struct { + _ [0]uint32 + __size [4]int8 +} /* pthreadtypes.h:118:3 */ + +// Reentrant versions of the `random' family of functions. +// These functions all use the following data structure to contain +// state, rather than global state variables. + +type random_data = struct { + fptr uintptr + rptr uintptr + state uintptr + rand_type int32 + rand_deg int32 + rand_sep int32 + _ [4]byte + end_ptr uintptr +} /* stdlib.h:423:1 */ + +// Data structure for communication with thread safe versions. This +// type is to be regarded as opaque. It's only exported because users +// have to allocate objects of this type. +type drand48_data = struct { + __x [3]uint16 + __old_x [3]uint16 + __c uint16 + __init uint16 + __a uint64 +} /* stdlib.h:490:1 */ + +// If this symbol has done its job, get rid of it. + +// Unsigned type of `sizeof' something. + +// Define this type if we are doing the whole job, +// or if we want this type in particular. + +// Wide character type. +// Locale-writers should change this as necessary to +// be big enough to hold unique values not between 0 and 127, +// and not (wchar_t) -1, for each defined multibyte character. + +// Define this type if we are doing the whole job, +// or if we want this type in particular. + +// A null pointer constant. + +// Offset of member MEMBER in a struct of type TYPE. + +// Type whose alignment is supported in every context and is at least +// as great as that of any standard type not using alignment +// specifiers. +type max_align_t = struct { + __max_align_ll int64 + __max_align_ld float64 +} /* stddef.h:426:3 */ + +// Copyright (C) 1997-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99: 7.8 Format conversion of integer types <inttypes.h> + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Get the type definitions. +// Copyright (C) 1997-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99: 7.18 Integer types <stdint.h> + +// Handle feature test macros at the start of a header. +// Copyright (C) 2016-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// This header is internal to glibc and should not be included outside +// of glibc headers. Headers including it must define +// __GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION first. This header +// cannot have multiple include guards because ISO C feature test +// macros depend on the definition of the macro when an affected +// header is included, not when the first system header is +// included. + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO/IEC TR 24731-2:2010 defines the __STDC_WANT_LIB_EXT2__ +// macro. + +// ISO/IEC TS 18661-1:2014 defines the __STDC_WANT_IEC_60559_BFP_EXT__ +// macro. Most but not all symbols enabled by that macro in TS +// 18661-1 are enabled unconditionally in C2X; the symbols in Annex F +// still require that macro in C2X. + +// ISO/IEC TS 18661-4:2015 defines the +// __STDC_WANT_IEC_60559_FUNCS_EXT__ macro. Other than the reduction +// functions, the symbols from this TS are enabled unconditionally in +// C2X. + +// ISO/IEC TS 18661-3:2015 defines the +// __STDC_WANT_IEC_60559_TYPES_EXT__ macro. +// bits/types.h -- definitions of __*_t types underlying *_t types. +// Copyright (C) 2002-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Never include this file directly; use <sys/types.h> instead. + +// wchar_t type related definitions. +// Copyright (C) 2000-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// The fallback definitions, for when __WCHAR_MAX__ or __WCHAR_MIN__ +// are not defined, give the right value and type as long as both int +// and wchar_t are 32-bit types. Adding L'\0' to a constant value +// ensures that the type is correct; it is necessary to use (L'\0' + +// 0) rather than just L'\0' so that the type in C++ is the promoted +// version of wchar_t rather than the distinct wchar_t type itself. +// Because wchar_t in preprocessor #if expressions is treated as +// intmax_t or uintmax_t, the expression (L'\0' - 1) would have the +// wrong value for WCHAR_MAX in such expressions and so cannot be used +// to define __WCHAR_MAX in the unsigned case. + +// Determine the wordsize from the preprocessor defines. + +// Both x86-64 and x32 use the 64-bit system call interface. + +// Exact integral types. + +// Signed. +// Define intN_t types. +// Copyright (C) 2017-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Unsigned. +// Define uintN_t types. +// Copyright (C) 2017-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// bits/types.h -- definitions of __*_t types underlying *_t types. +// Copyright (C) 2002-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Never include this file directly; use <sys/types.h> instead. + +type uint8_t = uint8 /* stdint-uintn.h:24:19 */ +type uint16_t = uint16 /* stdint-uintn.h:25:20 */ +type uint32_t = uint32 /* stdint-uintn.h:26:20 */ +type uint64_t = uint64 /* stdint-uintn.h:27:20 */ + +// Small types. + +// Signed. +type int_least8_t = int8 /* stdint.h:43:24 */ +type int_least16_t = int16 /* stdint.h:44:25 */ +type int_least32_t = int32 /* stdint.h:45:25 */ +type int_least64_t = int64 /* stdint.h:46:25 */ + +// Unsigned. +type uint_least8_t = uint8 /* stdint.h:49:25 */ +type uint_least16_t = uint16 /* stdint.h:50:26 */ +type uint_least32_t = uint32 /* stdint.h:51:26 */ +type uint_least64_t = uint64 /* stdint.h:52:26 */ + +// Fast types. + +// Signed. +type int_fast8_t = int8 /* stdint.h:58:22 */ +type int_fast16_t = int64 /* stdint.h:60:19 */ +type int_fast32_t = int64 /* stdint.h:61:19 */ +type int_fast64_t = int64 /* stdint.h:62:19 */ + +// Unsigned. +type uint_fast8_t = uint8 /* stdint.h:71:24 */ +type uint_fast16_t = uint64 /* stdint.h:73:27 */ +type uint_fast32_t = uint64 /* stdint.h:74:27 */ +type uint_fast64_t = uint64 /* stdint.h:75:27 */ + +// Types for `void *' pointers. +type intptr_t = int64 /* stdint.h:87:19 */ +type uintptr_t = uint64 /* stdint.h:90:27 */ + +// Largest integral types. +type intmax_t = int64 /* stdint.h:101:21 */ +type uintmax_t = uint64 /* stdint.h:102:22 */ + +// Macros for printing format specifiers. + +// Decimal notation. + +// Octal notation. + +// Unsigned integers. + +// lowercase hexadecimal notation. + +// UPPERCASE hexadecimal notation. + +// Macros for printing `intmax_t' and `uintmax_t'. + +// Macros for printing `intptr_t' and `uintptr_t'. + +// Macros for scanning format specifiers. + +// Signed decimal notation. + +// Signed decimal notation. + +// Unsigned decimal notation. + +// Octal notation. + +// Hexadecimal notation. + +// Macros for scanning `intmax_t' and `uintmax_t'. + +// Macros for scaning `intptr_t' and `uintptr_t'. + +// We have to define the `uintmax_t' type using `ldiv_t'. +type imaxdiv_t = struct { + quot int64 + rem int64 +} /* inttypes.h:275:5 */ + +// Structure used for on-the-fly rescaling +type rescaler_t = uint32_t /* rescaler_utils.h:29:18 */ // type for side-buffer +type WebPRescaler1 = struct { + x_expand int32 + y_expand int32 + num_channels int32 + fx_scale uint32_t + fy_scale uint32_t + fxy_scale uint32_t + y_accum int32 + y_add int32 + y_sub int32 + x_add int32 + x_sub int32 + src_width int32 + src_height int32 + dst_width int32 + dst_height int32 + src_y int32 + dst_y int32 + _ [4]byte + dst uintptr + dst_stride int32 + _ [4]byte + irow uintptr + frow uintptr +} /* rescaler_utils.h:30:9 */ + +// type for side-buffer +type WebPRescaler = WebPRescaler1 /* rescaler_utils.h:30:29 */ + +// Return true if output is finished +func WebPRescalerOutputDone(tls *libc.TLS, rescaler uintptr) int32 { /* rescaler_utils.h:86:5: */ + return (libc.Bool32((*WebPRescaler)(unsafe.Pointer(rescaler)).dst_y >= (*WebPRescaler)(unsafe.Pointer(rescaler)).dst_height)) +} + +// Return true if there are pending output rows ready. +func WebPRescalerHasPendingOutput(tls *libc.TLS, rescaler uintptr) int32 { /* rescaler_utils.h:92:5: */ + return (libc.Bool32(!(WebPRescalerOutputDone(tls, rescaler) != 0) && ((*WebPRescaler)(unsafe.Pointer(rescaler)).y_accum <= 0))) +} + +//------------------------------------------------------------------------------ + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Low-level API for VP8 decoder +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Main decoding functions for WebP images. +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum VP8StatusCode VP8StatusCode; +// typedef enum WEBP_CSP_MODE WEBP_CSP_MODE; +type WebPRGBABuffer1 = struct { + rgba uintptr + stride int32 + _ [4]byte + size size_t +} /* decode.h:29:9 */ + +//------------------------------------------------------------------------------ + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Low-level API for VP8 decoder +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Main decoding functions for WebP images. +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum VP8StatusCode VP8StatusCode; +// typedef enum WEBP_CSP_MODE WEBP_CSP_MODE; +type WebPRGBABuffer = WebPRGBABuffer1 /* decode.h:29:31 */ +type WebPYUVABuffer1 = struct { + y uintptr + u uintptr + v uintptr + a uintptr + y_stride int32 + u_stride int32 + v_stride int32 + a_stride int32 + y_size size_t + u_size size_t + v_size size_t + a_size size_t +} /* decode.h:30:9 */ + +type WebPYUVABuffer = WebPYUVABuffer1 /* decode.h:30:31 */ +type WebPDecBuffer1 = struct { + colorspace WEBP_CSP_MODE + width int32 + height int32 + is_external_memory int32 + u struct { + RGBA WebPRGBABuffer + _ [56]byte + } + pad [4]uint32_t + private_memory uintptr +} /* decode.h:31:9 */ + +type WebPDecBuffer = WebPDecBuffer1 /* decode.h:31:30 */ +type WebPIDecoder1 = struct { + state_ DecState + _ [4]byte + params_ WebPDecParams + is_lossless_ int32 + _ [4]byte + dec_ uintptr + io_ VP8Io + mem_ MemBuffer + output_ WebPDecBuffer + final_output_ uintptr + chunk_size_ size_t + last_mb_y_ int32 + _ [4]byte +} /* decode.h:32:9 */ + +type WebPBitstreamFeatures1 = struct { + width int32 + height int32 + has_alpha int32 + has_animation int32 + format int32 + pad [5]uint32_t +} /* decode.h:33:9 */ + +type WebPBitstreamFeatures = WebPBitstreamFeatures1 /* decode.h:33:38 */ +type WebPDecoderOptions1 = struct { + bypass_filtering int32 + no_fancy_upsampling int32 + use_cropping int32 + crop_left int32 + crop_top int32 + crop_width int32 + crop_height int32 + use_scaling int32 + scaled_width int32 + scaled_height int32 + use_threads int32 + dithering_strength int32 + flip int32 + alpha_dithering_strength int32 + pad [5]uint32_t +} /* decode.h:34:9 */ + +type WebPDecoderOptions = WebPDecoderOptions1 /* decode.h:34:35 */ +type WebPDecoderConfig1 = struct { + input WebPBitstreamFeatures + output WebPDecBuffer + options WebPDecoderOptions + _ [4]byte +} /* decode.h:35:9 */ + +type WebPDecoderConfig = WebPDecoderConfig1 /* decode.h:35:34 */ + +//------------------------------------------------------------------------------ +// Output colorspaces and buffer + +// Colorspaces +// Note: the naming describes the byte-ordering of packed samples in memory. +// For instance, MODE_BGRA relates to samples ordered as B,G,R,A,B,G,R,A,... +// Non-capital names (e.g.:MODE_Argb) relates to pre-multiplied RGB channels. +// RGBA-4444 and RGB-565 colorspaces are represented by following byte-order: +// RGBA-4444: [r3 r2 r1 r0 g3 g2 g1 g0], [b3 b2 b1 b0 a3 a2 a1 a0], ... +// RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ... +// In the case WEBP_SWAP_16BITS_CSP is defined, the bytes are swapped for +// these two modes: +// RGBA-4444: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], ... +// RGB-565: [g2 g1 g0 b4 b3 b2 b1 b0], [r4 r3 r2 r1 r0 g5 g4 g3], ... + +type WEBP_CSP_MODE = uint32 /* decode.h:162:3 */ + +// Some useful macros: +func WebPIsPremultipliedMode(tls *libc.TLS, mode WEBP_CSP_MODE) int32 { /* decode.h:165:24: */ + return (libc.Bool32((((mode == MODE_rgbA) || (mode == MODE_bgrA)) || (mode == MODE_Argb)) || (mode == MODE_rgbA_4444))) +} + +func WebPIsAlphaMode(tls *libc.TLS, mode WEBP_CSP_MODE) int32 { /* decode.h:170:24: */ + return (libc.Bool32((((((mode == MODE_RGBA) || (mode == MODE_BGRA)) || (mode == MODE_ARGB)) || (mode == MODE_RGBA_4444)) || (mode == MODE_YUVA)) || (WebPIsPremultipliedMode(tls, mode) != 0))) +} + +func WebPIsRGBMode(tls *libc.TLS, mode WEBP_CSP_MODE) int32 { /* decode.h:176:24: */ + return (libc.Bool32(mode < MODE_YUV)) +} + +// Initialize the structure as empty. Must be called before any other use. +// Returns false in case of version mismatch +func WebPInitDecBuffer(tls *libc.TLS, buffer uintptr) int32 { /* decode.h:223:24: */ + return WebPInitDecBufferInternal(tls, buffer, 0x0209) +} + +//------------------------------------------------------------------------------ +// Enumeration of the status codes + +type VP8StatusCode = uint32 /* decode.h:243:3 */ + +// Retrieve features from the bitstream. The *features structure is filled +// with information gathered from the bitstream. +// Returns VP8_STATUS_OK when the features are successfully retrieved. Returns +// VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the +// features from headers. Returns error in other cases. +// Note: The following chunk sequences (before the raw VP8/VP8L data) are +// considered valid by this function: +// RIFF + VP8(L) +// RIFF + VP8X + (optional chunks) + VP8(L) +// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. +// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. +func WebPGetFeatures(tls *libc.TLS, data uintptr, data_size size_t, features uintptr) VP8StatusCode { /* decode.h:437:34: */ + return WebPGetFeaturesInternal(tls, data, data_size, features, + 0x0209) +} + +//------------------------------------------------------------------------------ +// Lower-level API +// +// These functions provide fine-grained control of the decoding process. +// The call flow should resemble: +// +// VP8Io io; +// VP8InitIo(&io); +// io.data = data; +// io.data_size = size; +// /* customize io's functions (setup()/put()/teardown()) if needed. */ +// +// VP8Decoder* dec = VP8New(); +// int ok = VP8Decode(dec, &io); +// if (!ok) printf("Error: %s\n", VP8StatusMessage(dec)); +// VP8Delete(dec); +// return ok; + +// Input / Output +type VP8Io1 = struct { + width int32 + height int32 + mb_y int32 + mb_w int32 + mb_h int32 + _ [4]byte + y uintptr + u uintptr + v uintptr + y_stride int32 + uv_stride int32 + opaque uintptr + put VP8IoPutHook + setup VP8IoSetupHook + teardown VP8IoTeardownHook + fancy_upsampling int32 + _ [4]byte + data_size size_t + data uintptr + bypass_filtering int32 + use_cropping int32 + crop_left int32 + crop_right int32 + crop_top int32 + crop_bottom int32 + use_scaling int32 + scaled_width int32 + scaled_height int32 + _ [4]byte + a uintptr +} /* vp8_dec.h:42:9 */ + +//------------------------------------------------------------------------------ +// Lower-level API +// +// These functions provide fine-grained control of the decoding process. +// The call flow should resemble: +// +// VP8Io io; +// VP8InitIo(&io); +// io.data = data; +// io.data_size = size; +// /* customize io's functions (setup()/put()/teardown()) if needed. */ +// +// VP8Decoder* dec = VP8New(); +// int ok = VP8Decode(dec, &io); +// if (!ok) printf("Error: %s\n", VP8StatusMessage(dec)); +// VP8Delete(dec); +// return ok; + +// Input / Output +type VP8Io = VP8Io1 /* vp8_dec.h:42:22 */ +type VP8IoPutHook = uintptr /* vp8_dec.h:43:13 */ +type VP8IoSetupHook = uintptr /* vp8_dec.h:44:13 */ +type VP8IoTeardownHook = uintptr /* vp8_dec.h:45:14 */ + +// Main decoding object. This is an opaque structure. +type VP8Decoder1 = struct { + status_ VP8StatusCode + ready_ int32 + error_msg_ uintptr + br_ VP8BitReader + frm_hdr_ VP8FrameHeader + pic_hdr_ VP8PictureHeader + filter_hdr_ VP8FilterHeader + segment_hdr_ VP8SegmentHeader + _ [4]byte + worker_ WebPWorker + mt_method_ int32 + cache_id_ int32 + num_caches_ int32 + _ [4]byte + thread_ctx_ VP8ThreadContext + mb_w_ int32 + mb_h_ int32 + tl_mb_x_ int32 + tl_mb_y_ int32 + br_mb_x_ int32 + br_mb_y_ int32 + num_parts_minus_one_ uint32_t + _ [4]byte + parts_ [8]VP8BitReader + dither_ int32 + dithering_rg_ VP8Random + dqm_ [4]VP8QuantMatrix + _ [4]byte + proba_ VP8Proba + use_skip_proba_ int32 + skip_p_ uint8_t + _ [3]byte + intra_t_ uintptr + intra_l_ [4]uint8_t + _ [4]byte + yuv_t_ uintptr + mb_info_ uintptr + f_info_ uintptr + yuv_b_ uintptr + cache_y_ uintptr + cache_u_ uintptr + cache_v_ uintptr + cache_y_stride_ int32 + cache_uv_stride_ int32 + mem_ uintptr + mem_size_ size_t + mb_x_ int32 + mb_y_ int32 + mb_data_ uintptr + filter_type_ int32 + fstrengths_ [4][2]VP8FInfo + _ [4]byte + alph_dec_ uintptr + alpha_data_ uintptr + alpha_data_size_ size_t + is_alpha_decoded_ int32 + _ [4]byte + alpha_plane_mem_ uintptr + alpha_plane_ uintptr + alpha_prev_line_ uintptr + alpha_dithering_ int32 + _ [4]byte +} /* vp8_dec.h:123:9 */ + +// Main decoding object. This is an opaque structure. +type VP8Decoder = VP8Decoder1 /* vp8_dec.h:123:27 */ + +// Must be called to make sure 'io' is initialized properly. +// Returns false in case of version mismatch. Upon such failure, no other +// decoding function should be called (VP8Decode, VP8GetHeaders, ...) +func VP8InitIo(tls *libc.TLS, io uintptr) int32 { /* vp8_dec.h:131:24: */ + return VP8InitIoInternal(tls, io, 0x0209) +} + +//------------------------------------------------------------------------------ +// WebPDecParams: Decoding output parameters. Transient internal object. + +type WebPDecParams1 = struct { + output uintptr + tmp_y uintptr + tmp_u uintptr + tmp_v uintptr + last_y int32 + _ [4]byte + options uintptr + scaler_y uintptr + scaler_u uintptr + scaler_v uintptr + scaler_a uintptr + memory uintptr + emit OutputFunc + emit_alpha OutputAlphaFunc + emit_alpha_row OutputRowFunc +} /* webpi_dec.h:27:9 */ + +//------------------------------------------------------------------------------ +// WebPDecParams: Decoding output parameters. Transient internal object. + +type WebPDecParams = WebPDecParams1 /* webpi_dec.h:27:30 */ +type OutputFunc = uintptr /* webpi_dec.h:28:13 */ +type OutputAlphaFunc = uintptr /* webpi_dec.h:29:13 */ +type OutputRowFunc = uintptr /* webpi_dec.h:31:13 */ + +//------------------------------------------------------------------------------ +// Header parsing helpers + +// Structure storing a description of the RIFF headers. +type WebPHeaderStructure = struct { + data uintptr + data_size size_t + have_all_data int32 + _ [4]byte + offset size_t + alpha_data uintptr + alpha_data_size size_t + compressed_size size_t + riff_size size_t + is_lossless int32 + _ [4]byte +} /* webpi_dec.h:67:3 */ + +//------------------------------------------------------------------------------ + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Spatial prediction using various filters +// +// Author: Urvang (urvang@google.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +// src/webp/config.h. Generated from config.h.in by configure. +// src/webp/config.h.in. Generated from configure.ac by autoheader. + +// Define if building universal (internal helper macro) +// #undef AC_APPLE_UNIVERSAL_BUILD + +// Set to 1 if __builtin_bswap16 is available + +// Set to 1 if __builtin_bswap32 is available + +// Set to 1 if __builtin_bswap64 is available + +// Define to 1 if you have the <cpu-features.h> header file. +// #undef HAVE_CPU_FEATURES_H + +// Define to 1 if you have the <dlfcn.h> header file. + +// Define to 1 if you have the <GLUT/glut.h> header file. +// #undef HAVE_GLUT_GLUT_H + +// Define to 1 if you have the <GL/glut.h> header file. +// #undef HAVE_GL_GLUT_H + +// Define to 1 if you have the <inttypes.h> header file. + +// Define to 1 if you have the <OpenGL/glut.h> header file. +// #undef HAVE_OPENGL_GLUT_H + +// Have PTHREAD_PRIO_INHERIT. +// #undef HAVE_PTHREAD_PRIO_INHERIT + +// Define to 1 if you have the <shlwapi.h> header file. +// #undef HAVE_SHLWAPI_H + +// Define to 1 if you have the <stdint.h> header file. + +// Define to 1 if you have the <stdio.h> header file. + +// Define to 1 if you have the <stdlib.h> header file. + +// Define to 1 if you have the <strings.h> header file. + +// Define to 1 if you have the <string.h> header file. + +// Define to 1 if you have the <sys/stat.h> header file. + +// Define to 1 if you have the <sys/types.h> header file. + +// Define to 1 if you have the <unistd.h> header file. + +// Define to 1 if you have the <wincodec.h> header file. +// #undef HAVE_WINCODEC_H + +// Define to 1 if you have the <windows.h> header file. +// #undef HAVE_WINDOWS_H + +// Define to the sub-directory where libtool stores uninstalled libraries. + +// Name of package + +// Define to the address where bug reports for this package should be sent. + +// Define to the full name of this package. + +// Define to the full name and version of this package. + +// Define to the one symbol short name of this package. + +// Define to the home page for this package. + +// Define to the version of this package. + +// Define to necessary symbol if this constant uses a non-standard name on +// your system. +// #undef PTHREAD_CREATE_JOINABLE + +// Define to 1 if all of the C90 standard headers exist (not just the ones +// required in a freestanding environment). This macro is provided for +// backward compatibility; new code need not use it. + +// Version number of package + +// Set to 1 if GIF library is installed +// #undef WEBP_HAVE_GIF + +// Set to 1 if OpenGL is supported +// #undef WEBP_HAVE_GL + +// Set to 1 if JPEG library is installed +// #undef WEBP_HAVE_JPEG + +// Set to 1 if NEON is supported +// #undef WEBP_HAVE_NEON + +// Set to 1 if runtime detection of NEON is enabled +// #undef WEBP_HAVE_NEON_RTCD + +// Set to 1 if PNG library is installed +// #undef WEBP_HAVE_PNG + +// Set to 1 if SDL library is installed +// #undef WEBP_HAVE_SDL + +// Set to 1 if SSE2 is supported +// #undef WEBP_HAVE_SSE2 + +// Set to 1 if SSE4.1 is supported +// #undef WEBP_HAVE_SSE41 + +// Set to 1 if TIFF library is installed +// #undef WEBP_HAVE_TIFF + +// Enable near lossless encoding + +// Undefine this to disable thread support. +// #undef WEBP_USE_THREAD + +// Define WORDS_BIGENDIAN to 1 if your processor stores words with the most +// significant byte first (like Motorola and SPARC, unlike Intel). +// # undef WORDS_BIGENDIAN + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +//------------------------------------------------------------------------------ +// WEBP_RESTRICT + +// Declares a pointer with the restrict type qualifier if available. +// This allows code to hint to the compiler that only this pointer references a +// particular object or memory region within the scope of the block in which it +// is declared. This may allow for improved optimizations due to the lack of +// pointer aliasing. See also: +// https://en.cppreference.com/w/c/language/restrict + +//------------------------------------------------------------------------------ +// CPU detection + +// WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp +// files without intrinsics, allowing the corresponding Init() to be called. +// Files containing intrinsics will need to be built targeting the instruction +// set so should succeed on one of the earlier tests. + +// The intrinsics currently cause compiler errors with arm-nacl-gcc and the +// inline assembly would need to be modified for use with Native Client. + +// Note: ARM64 is supported in Visual Studio 2017, but requires the direct +// inclusion of arm64_neon.h; Visual Studio 2019 includes this file in +// arm_neon.h. Compile errors were seen with Visual Studio 2019 16.4 with +// vtbl4_u8(); a fix was made in 16.6. + +// This macro prevents thread_sanitizer from reporting known concurrent writes. + +// Defines an Init + helper function that control multiple initialization of +// function pointers / tables. +// Usage: +// WEBP_DSP_INIT_FUNC(InitFunc) { +// ...function body +// } + +// If 'ptr' is NULL, returns NULL. Otherwise returns 'ptr + off'. +// Prevents undefined behavior sanitizer nullptr-with-nonzero-offset warning. + +// Regularize the definition of WEBP_SWAP_16BIT_CSP (backward compatibility) + +// some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__) + +type CPUFeature = uint32 /* dsp.h:262:3 */ +// returns true if the CPU supports the feature. +type VP8CPUInfo = uintptr /* dsp.h:264:13 */ + +//------------------------------------------------------------------------------ +// Init stub generator + +// Defines an init function stub to ensure each module exposes a symbol, +// avoiding a compiler warning. + +//------------------------------------------------------------------------------ +// Encoding + +// Transforms +// VP8Idct: Does one of two inverse transforms. If do_two is set, the transforms +// will be done for (ref, in, dst) and (ref + 4, in + 16, dst + 4). +type VP8Idct = uintptr /* dsp.h:282:14 */ +type VP8Fdct = uintptr /* dsp.h:284:14 */ +type VP8WHT = uintptr /* dsp.h:285:14 */ +// Predictions +// *dst is the destination block. *top and *left can be NULL. +type VP8IntraPreds = uintptr /* dsp.h:292:14 */ +type VP8Intra4Preds = uintptr /* dsp.h:294:14 */ + +type VP8Metric = uintptr /* dsp.h:299:13 */ +type VP8WMetric = uintptr /* dsp.h:301:13 */ + +// Compute the average (DC) of four 4x4 blocks. +// Each sub-4x4 block #i sum is stored in dc[i]. +type VP8MeanMetric = uintptr /* dsp.h:309:14 */ + +type VP8BlockCopy = uintptr /* dsp.h:312:14 */ +// Quantization +type VP8Matrix1 = struct { + q_ [16]uint16_t + iq_ [16]uint16_t + bias_ [16]uint32_t + zthresh_ [16]uint32_t + sharpen_ [16]uint16_t +} /* dsp.h:316:1 */ + +// forward declaration +type VP8QuantizeBlock = uintptr /* dsp.h:317:13 */ +// Same as VP8QuantizeBlock, but quantizes two consecutive blocks. +type VP8Quantize2Blocks = uintptr /* dsp.h:320:13 */ + +// specific to 2nd transform: +type VP8QuantizeBlockWHT = uintptr /* dsp.h:327:13 */ + +// Collect histogram for susceptibility calculation. +type VP8Histogram = struct { + max_value int32 + last_non_zero int32 +} /* dsp.h:339:3 */ +type VP8CHisto = uintptr /* dsp.h:340:14 */ + +type VP8Residual1 = struct { + first int32 + last int32 + coeffs uintptr + coeff_type int32 + _ [4]byte + prob uintptr + stats uintptr + costs CostArrayPtr +} /* dsp.h:359:1 */ + +type VP8SetResidualCoeffsFunc = uintptr /* dsp.h:360:14 */ + +// Cost calculation function. +type VP8GetResidualCostFunc = uintptr /* dsp.h:365:13 */ + +//------------------------------------------------------------------------------ +// SSIM / PSNR utils + +// struct for accumulating statistical moments +type VP8DistoStats = struct { + w uint32_t + xm uint32_t + ym uint32_t + xxm uint32_t + xym uint32_t + yym uint32_t +} /* dsp.h:380:3 */ + +type VP8SSIMGetClippedFunc = uintptr /* dsp.h:388:16 */ // plane dimension + +// This version is called with the guarantee that you can load 8 bytes and +// 8 rows at offset src1 and src2 +type VP8SSIMGetFunc = uintptr /* dsp.h:396:16 */ // with clipping + +type VP8AccumulateSSEFunc = uintptr /* dsp.h:404:18 */ + +//------------------------------------------------------------------------------ +// Decoding + +type VP8DecIdct = uintptr /* dsp.h:415:14 */ +// when doing two transforms, coeffs is actually int16_t[2][16]. +type VP8DecIdct2 = uintptr /* dsp.h:417:14 */ + +// *dst is the destination block, with stride BPS. Boundary samples are +// assumed accessible when needed. +type VP8PredFunc = uintptr /* dsp.h:427:14 */ + +// simple filter (only for luma) +type VP8SimpleFilterFunc = uintptr /* dsp.h:441:14 */ + +// regular filter (on both macroblock edges and inner edges) +type VP8LumaFilterFunc = uintptr /* dsp.h:448:14 */ +type VP8ChromaFilterFunc = uintptr /* dsp.h:450:14 */ + +//------------------------------------------------------------------------------ +// WebP I/O + +// Convert a pair of y/u/v lines together to the output rgb/a colorspace. +// bottom_y can be NULL if only one line of output is needed (at top/bottom). +type WebPUpsampleLinePairFunc = uintptr /* dsp.h:483:14 */ + +// Per-row point-sampling methods. +type WebPSamplerRowFunc = uintptr /* dsp.h:497:14 */ + +// YUV444->RGB converters +type WebPYUV444Converter = uintptr /* dsp.h:515:14 */ + +// Import a row of data and save its contribution in the rescaler. +// 'channel' denotes the channel number to be imported. 'Expand' corresponds to +// the wrk->x_expand case. Otherwise, 'Shrink' is to be used. +type WebPRescalerImportRowFunc = uintptr /* dsp.h:574:14 */ + +// Export one row (starting at x_out position) from rescaler. +// 'Expand' corresponds to the wrk->y_expand case. +// Otherwise 'Shrink' is to be used +type WebPRescalerExportRowFunc = uintptr /* dsp.h:583:14 */ + +//------------------------------------------------------------------------------ +// Filter functions + +type WEBP_FILTER_TYPE = uint32 /* dsp.h:704:3 */ + +type WebPFilterFunc = uintptr /* dsp.h:706:14 */ +// In-place un-filtering. +// Warning! 'prev_line' pointer can be equal to 'cur_line' or 'preds'. +type WebPUnfilterFunc = uintptr /* dsp.h:710:14 */ + +type VP8LDecoder1 = struct { + status_ VP8StatusCode + state_ VP8LDecodeState + io_ uintptr + output_ uintptr + pixels_ uintptr + argb_cache_ uintptr + br_ VP8LBitReader + incremental_ int32 + _ [4]byte + saved_br_ VP8LBitReader + saved_last_pixel_ int32 + width_ int32 + height_ int32 + last_row_ int32 + last_pixel_ int32 + last_out_row_ int32 + hdr_ VP8LMetadata + next_transform_ int32 + _ [4]byte + transforms_ [4]VP8LTransform + transforms_seen_ uint32_t + _ [4]byte + rescaler_memory uintptr + rescaler uintptr +} /* vp8_dec.h:123:9 */ + +// Defined in dec/vp8li.h. + +type ALPHDecoder1 = struct { + width_ int32 + height_ int32 + method_ int32 + filter_ WEBP_FILTER_TYPE + pre_processing_ int32 + _ [4]byte + vp8l_dec_ uintptr + io_ VP8Io + use_8b_decode_ int32 + _ [4]byte + output_ uintptr + prev_line_ uintptr +} /* vp8_dec.h:123:9 */ + +// Defined in dec/vp8li.h. + +type ALPHDecoder = ALPHDecoder1 /* alphai_dec.h:26:28 */ + +// POSIX.1-2008 extended locale interface (see locale.h). +// Definition of locale_t. +// Copyright (C) 2017-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Definition of struct __locale_struct and __locale_t. +// Copyright (C) 1997-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// POSIX.1-2008: the locale_t type, representing a locale context +// (implementation-namespace version). This type should be treated +// as opaque by applications; some details are exposed for the sake of +// efficiency in e.g. ctype functions. + +type __locale_struct = struct { + __locales [13]uintptr + __ctype_b uintptr + __ctype_tolower uintptr + __ctype_toupper uintptr + __names [13]uintptr +} /* __locale_t.h:28:1 */ + +type locale_t = uintptr /* locale_t.h:24:20 */ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Lossless decoder: internal header. +// +// Author: Skal (pascal.massimino@gmail.com) +// Vikas Arora(vikaas.arora@gmail.com) + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.21 String handling <string.h> + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header: WebP decoding parameters and custom IO on buffer +// +// Author: somnath@google.com (Somnath Banerjee) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Boolean decoder +// +// Author: Skal (pascal.massimino@gmail.com) +// Vikas Arora (vikaas.arora@gmail.com) + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.2 Diagnostics <assert.h> + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// void assert (int expression); +// +// If NDEBUG is defined, do nothing. +// If not, and EXPRESSION is zero, print an error message and abort. + +// void assert_perror (int errnum); +// +// If NDEBUG is defined, do nothing. If not, and ERRNUM is not zero, print an +// error message with the error text for ERRNUM and abort. +// (This is a GNU extension.) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Warning! This macro triggers quite some MACRO wizardry around func signature! + +// We'll REMOVE the 'const char label[]' from all signatures and calls (!!): + +// The Boolean decoder needs to maintain infinite precision on the value_ field. +// However, since range_ is only 8bit, we only need an active window of 8 bits +// for value_. Left bits (MSB) gets zeroed and shifted away when value_ falls +// below 128, range_ is updated, and fresh bits read from the bitstream are +// brought in as LSB. To avoid reading the fresh bits one by one (slow), we +// cache BITS of them ahead. The total of (BITS + 8) bits must fit into a +// natural register (with type bit_t). To fetch BITS bits from bitstream we +// use a type lbit_t. +// +// BITS can be any multiple of 8 from 8 to 56 (inclusive). +// Pick values that fit natural register size. + +//------------------------------------------------------------------------------ +// Derived types and constants: +// bit_t = natural register type for storing 'value_' (which is BITS+8 bits) +// range_t = register for 'range_' (which is 8bits only) + +type bit_t = uint64_t /* bit_reader_utils.h:81:18 */ + +type range_t = uint32_t /* bit_reader_utils.h:86:18 */ + +//------------------------------------------------------------------------------ +// Bitreader + +type VP8BitReader1 = struct { + value_ bit_t + range_ range_t + bits_ int32 + buf_ uintptr + buf_end_ uintptr + buf_max_ uintptr + eof_ int32 + _ [4]byte +} /* vp8_dec.h:123:9 */ + +//------------------------------------------------------------------------------ +// Bitreader + +type VP8BitReader = VP8BitReader1 /* bit_reader_utils.h:91:29 */ + +// bit_reader_inl.h will implement the following methods: +// static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob, ...) +// static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v, ...) +// and should be included by the .c files that actually need them. +// This is to avoid recompiling the whole library whenever this file is touched, +// and also allowing platform-specific ad-hoc hacks. + +// ----------------------------------------------------------------------------- +// Bitreader for lossless format + +// maximum number of bits (inclusive) the bit-reader can handle: + +type vp8l_val_t = uint64_t /* bit_reader_utils.h:138:18 */ // right now, this bit-reader can only use 64bit. + +type VP8LBitReader = struct { + val_ vp8l_val_t + buf_ uintptr + len_ size_t + pos_ size_t + bit_pos_ int32 + eos_ int32 +} /* bit_reader_utils.h:147:3 */ + +// Return the prefetched bits, so they can be looked up. +func VP8LPrefetchBits(tls *libc.TLS, br uintptr) uint32_t { /* bit_reader_utils.h:164:29: */ + return (uint32_t((*VP8LBitReader)(unsafe.Pointer(br)).val_ >> ((*VP8LBitReader)(unsafe.Pointer(br)).bit_pos_ & (64 - 1)))) +} + +// Returns true if there was an attempt at reading bit past the end of +// the buffer. Doesn't set br->eos_ flag. +func VP8LIsEndOfStream(tls *libc.TLS, br uintptr) int32 { /* bit_reader_utils.h:170:24: */ + + return (libc.Bool32(((*VP8LBitReader)(unsafe.Pointer(br)).eos_ != 0) || (((*VP8LBitReader)(unsafe.Pointer(br)).pos_ == (*VP8LBitReader)(unsafe.Pointer(br)).len_) && ((*VP8LBitReader)(unsafe.Pointer(br)).bit_pos_ > 64)))) +} + +// For jumping over a number of bits in the bit stream when accessed with +// VP8LPrefetchBits and VP8LFillBitWindow. +// This function does *not* set br->eos_, since it's speed-critical. +// Use with extreme care! +func VP8LSetBitPos(tls *libc.TLS, br uintptr, val int32) { /* bit_reader_utils.h:179:25: */ + (*VP8LBitReader)(unsafe.Pointer(br)).bit_pos_ = val +} + +func VP8LFillBitWindow(tls *libc.TLS, br uintptr) { /* bit_reader_utils.h:186:25: */ + if (*VP8LBitReader)(unsafe.Pointer(br)).bit_pos_ >= 32 { + VP8LDoFillBitWindow(tls, br) + } +} + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Color Cache for WebP Lossless +// +// Authors: Jyrki Alakuijala (jyrki@google.com) +// Urvang Joshi (urvang@google.com) + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.2 Diagnostics <assert.h> + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// void assert (int expression); +// +// If NDEBUG is defined, do nothing. +// If not, and EXPRESSION is zero, print an error message and abort. + +// void assert_perror (int errnum); +// +// If NDEBUG is defined, do nothing. If not, and ERRNUM is not zero, print an +// error message with the error text for ERRNUM and abort. +// (This is a GNU extension.) + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Main color cache struct. +type VP8LColorCache = struct { + colors_ uintptr + hash_shift_ int32 + hash_bits_ int32 +} /* color_cache_utils.h:32:3 */ + +var kHashMul uint32_t = 0x1e35a7bd /* color_cache_utils.h:34:23 */ + +func VP8LHashPix(tls *libc.TLS, argb uint32_t, shift int32) int32 { /* color_cache_utils.h:37:5: */ + return (int32((argb * kHashMul) >> shift)) +} + +func VP8LColorCacheLookup(tls *libc.TLS, cc uintptr, key uint32_t) uint32_t { /* color_cache_utils.h:41:29: */ + + return *(*uint32_t)(unsafe.Pointer((*VP8LColorCache)(unsafe.Pointer(cc)).colors_ + uintptr(key)*4)) +} + +func VP8LColorCacheSet(tls *libc.TLS, cc uintptr, key uint32_t, argb uint32_t) { /* color_cache_utils.h:47:25: */ + + *(*uint32_t)(unsafe.Pointer((*VP8LColorCache)(unsafe.Pointer(cc)).colors_ + uintptr(key)*4)) = argb +} + +func VP8LColorCacheInsert(tls *libc.TLS, cc uintptr, argb uint32_t) { /* color_cache_utils.h:53:25: */ + var key int32 = VP8LHashPix(tls, argb, (*VP8LColorCache)(unsafe.Pointer(cc)).hash_shift_) + *(*uint32_t)(unsafe.Pointer((*VP8LColorCache)(unsafe.Pointer(cc)).colors_ + uintptr(key)*4)) = argb +} + +func VP8LColorCacheGetIndex(tls *libc.TLS, cc uintptr, argb uint32_t) int32 { /* color_cache_utils.h:59:24: */ + return VP8LHashPix(tls, argb, (*VP8LColorCache)(unsafe.Pointer(cc)).hash_shift_) +} + +// Return the key if cc contains argb, and -1 otherwise. +func VP8LColorCacheContains(tls *libc.TLS, cc uintptr, argb uint32_t) int32 { /* color_cache_utils.h:65:24: */ + var key int32 = VP8LHashPix(tls, argb, (*VP8LColorCache)(unsafe.Pointer(cc)).hash_shift_) + if *(*uint32_t)(unsafe.Pointer((*VP8LColorCache)(unsafe.Pointer(cc)).colors_ + uintptr(key)*4)) == argb { + return key + } + return -1 +} + +//------------------------------------------------------------------------------ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for building and looking up Huffman trees. +// +// Author: Urvang Joshi (urvang@google.com) + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.2 Diagnostics <assert.h> + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// void assert (int expression); +// +// If NDEBUG is defined, do nothing. +// If not, and EXPRESSION is zero, print an error message and abort. + +// void assert_perror (int errnum); +// +// If NDEBUG is defined, do nothing. If not, and ERRNUM is not zero, print an +// error message with the error text for ERRNUM and abort. +// (This is a GNU extension.) + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header for constants related to WebP file format. +// +// Author: Urvang (urvang@google.com) + +// Create fourcc of the chunk from the chunk tag characters. + +// VP8 related constants. + +// VP8L related constants. +// width and height. + +// to be read is a transform. +// in a bitstream. +type VP8LImageTransformType = uint32 /* format_constants.h:60:3 */ + +// Alpha related constants. + +// Mux related constants. + +// Maximum chunk payload is such that adding the header and padding won't +// overflow a uint32_t. + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Huffman lookup table entry +type HuffmanCode = struct { + bits uint8_t + _ [1]byte + value uint16_t +} /* huffman_utils.h:36:3 */ + +// long version for holding 32b values +type HuffmanCode32 = struct { + bits int32 + value uint32_t +} /* huffman_utils.h:44:3 */ + +// Huffman table group. +// Includes special handling for the following cases: +// - is_trivial_literal: one common literal base for RED/BLUE/ALPHA (not GREEN) +// - is_trivial_code: only 1 code (no bit is read from bitstream) +// - use_packed_table: few enough literal symbols, so all the bit codes +// can fit into a small look-up table packed_table[] +// The common literal base, if applicable, is stored in 'literal_arb'. +type HTreeGroup1 = struct { + htrees [5]uintptr + is_trivial_literal int32 + literal_arb uint32_t + is_trivial_code int32 + use_packed_table int32 + packed_table [64]HuffmanCode32 +} /* huffman_utils.h:56:9 */ + +// Huffman table group. +// Includes special handling for the following cases: +// - is_trivial_literal: one common literal base for RED/BLUE/ALPHA (not GREEN) +// - is_trivial_code: only 1 code (no bit is read from bitstream) +// - use_packed_table: few enough literal symbols, so all the bit codes +// can fit into a small look-up table packed_table[] +// The common literal base, if applicable, is stored in 'literal_arb'. +type HTreeGroup = HTreeGroup1 /* huffman_utils.h:56:27 */ + +type VP8LDecodeState = uint32 /* vp8li_dec.h:32:3 */ + +type VP8LTransform1 = struct { + type_ VP8LImageTransformType + bits_ int32 + xsize_ int32 + ysize_ int32 + data_ uintptr +} /* vp8_dec.h:123:9 */ + +type VP8LTransform = VP8LTransform1 /* vp8li_dec.h:34:30 */ + +type VP8LMetadata = struct { + color_cache_size_ int32 + _ [4]byte + color_cache_ VP8LColorCache + saved_color_cache_ VP8LColorCache + huffman_mask_ int32 + huffman_subsample_bits_ int32 + huffman_xsize_ int32 + _ [4]byte + huffman_image_ uintptr + num_htree_groups_ int32 + _ [4]byte + htree_groups_ uintptr + huffman_tables_ uintptr +} /* vp8li_dec.h:55:3 */ + +type VP8LDecoder = VP8LDecoder1 /* vp8li_dec.h:57:28 */ + +//------------------------------------------------------------------------------ + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Boolean decoder +// +// Author: Skal (pascal.massimino@gmail.com) +// Vikas Arora (vikaas.arora@gmail.com) + +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Pseudo-random utilities +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.2 Diagnostics <assert.h> + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// void assert (int expression); +// +// If NDEBUG is defined, do nothing. +// If not, and EXPRESSION is zero, print an error message and abort. + +// void assert_perror (int errnum); +// +// If NDEBUG is defined, do nothing. If not, and ERRNUM is not zero, print an +// error message with the error text for ERRNUM and abort. +// (This is a GNU extension.) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +type VP8Random = struct { + index1_ int32 + index2_ int32 + tab_ [55]uint32_t + amp_ int32 +} /* random_utils.h:31:3 */ + +// Returns a centered pseudo-random number with 'num_bits' amplitude. +// (uses D.Knuth's Difference-based random generator). +// 'amp' is in VP8_RANDOM_DITHER_FIX fixed-point precision. +func VP8RandomBits2(tls *libc.TLS, rg uintptr, num_bits int32, amp int32) int32 { /* random_utils.h:39:24: */ + var diff int32 + + diff = (int32(*(*uint32_t)(unsafe.Pointer((rg + 8 /* &.tab_ */) + uintptr((*VP8Random)(unsafe.Pointer(rg)).index1_)*4)) - *(*uint32_t)(unsafe.Pointer((rg + 8 /* &.tab_ */) + uintptr((*VP8Random)(unsafe.Pointer(rg)).index2_)*4)))) + if diff < 0 { + diff = libc.Int32FromUint32(uint32(diff) + (uint32(1) << 31)) + } + *(*uint32_t)(unsafe.Pointer((rg + 8 /* &.tab_ */) + uintptr((*VP8Random)(unsafe.Pointer(rg)).index1_)*4)) = uint32_t(diff) + if libc.PreIncInt32(&(*VP8Random)(unsafe.Pointer(rg)).index1_, 1) == 55 { + (*VP8Random)(unsafe.Pointer(rg)).index1_ = 0 + } + if libc.PreIncInt32(&(*VP8Random)(unsafe.Pointer(rg)).index2_, 1) == 55 { + (*VP8Random)(unsafe.Pointer(rg)).index2_ = 0 + } + // sign-extend, 0-center + diff = ((int32(uint32_t(diff) << 1)) >> (32 - num_bits)) + diff = ((diff * amp) >> 8) // restrict range + diff = diff + (int32(1) << (num_bits - 1)) // shift back to 0.5-center + return diff +} + +func VP8RandomBits(tls *libc.TLS, rg uintptr, num_bits int32) int32 { /* random_utils.h:55:24: */ + return VP8RandomBits2(tls, rg, num_bits, (*VP8Random)(unsafe.Pointer(rg)).amp_) +} + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Multi-threaded worker +// +// Author: Skal (pascal.massimino@gmail.com) + +// src/webp/config.h. Generated from config.h.in by configure. +// src/webp/config.h.in. Generated from configure.ac by autoheader. + +// Define if building universal (internal helper macro) +// #undef AC_APPLE_UNIVERSAL_BUILD + +// Set to 1 if __builtin_bswap16 is available + +// Set to 1 if __builtin_bswap32 is available + +// Set to 1 if __builtin_bswap64 is available + +// Define to 1 if you have the <cpu-features.h> header file. +// #undef HAVE_CPU_FEATURES_H + +// Define to 1 if you have the <dlfcn.h> header file. + +// Define to 1 if you have the <GLUT/glut.h> header file. +// #undef HAVE_GLUT_GLUT_H + +// Define to 1 if you have the <GL/glut.h> header file. +// #undef HAVE_GL_GLUT_H + +// Define to 1 if you have the <inttypes.h> header file. + +// Define to 1 if you have the <OpenGL/glut.h> header file. +// #undef HAVE_OPENGL_GLUT_H + +// Have PTHREAD_PRIO_INHERIT. +// #undef HAVE_PTHREAD_PRIO_INHERIT + +// Define to 1 if you have the <shlwapi.h> header file. +// #undef HAVE_SHLWAPI_H + +// Define to 1 if you have the <stdint.h> header file. + +// Define to 1 if you have the <stdio.h> header file. + +// Define to 1 if you have the <stdlib.h> header file. + +// Define to 1 if you have the <strings.h> header file. + +// Define to 1 if you have the <string.h> header file. + +// Define to 1 if you have the <sys/stat.h> header file. + +// Define to 1 if you have the <sys/types.h> header file. + +// Define to 1 if you have the <unistd.h> header file. + +// Define to 1 if you have the <wincodec.h> header file. +// #undef HAVE_WINCODEC_H + +// Define to 1 if you have the <windows.h> header file. +// #undef HAVE_WINDOWS_H + +// Define to the sub-directory where libtool stores uninstalled libraries. + +// Name of package + +// Define to the address where bug reports for this package should be sent. + +// Define to the full name of this package. + +// Define to the full name and version of this package. + +// Define to the one symbol short name of this package. + +// Define to the home page for this package. + +// Define to the version of this package. + +// Define to necessary symbol if this constant uses a non-standard name on +// your system. +// #undef PTHREAD_CREATE_JOINABLE + +// Define to 1 if all of the C90 standard headers exist (not just the ones +// required in a freestanding environment). This macro is provided for +// backward compatibility; new code need not use it. + +// Version number of package + +// Set to 1 if GIF library is installed +// #undef WEBP_HAVE_GIF + +// Set to 1 if OpenGL is supported +// #undef WEBP_HAVE_GL + +// Set to 1 if JPEG library is installed +// #undef WEBP_HAVE_JPEG + +// Set to 1 if NEON is supported +// #undef WEBP_HAVE_NEON + +// Set to 1 if runtime detection of NEON is enabled +// #undef WEBP_HAVE_NEON_RTCD + +// Set to 1 if PNG library is installed +// #undef WEBP_HAVE_PNG + +// Set to 1 if SDL library is installed +// #undef WEBP_HAVE_SDL + +// Set to 1 if SSE2 is supported +// #undef WEBP_HAVE_SSE2 + +// Set to 1 if SSE4.1 is supported +// #undef WEBP_HAVE_SSE41 + +// Set to 1 if TIFF library is installed +// #undef WEBP_HAVE_TIFF + +// Enable near lossless encoding + +// Undefine this to disable thread support. +// #undef WEBP_USE_THREAD + +// Define WORDS_BIGENDIAN to 1 if your processor stores words with the most +// significant byte first (like Motorola and SPARC, unlike Intel). +// # undef WORDS_BIGENDIAN + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// State of the worker thread object +type WebPWorkerStatus = uint32 /* thread_utils.h:32:3 */ + +// Function to be called by the worker thread. Takes two opaque pointers as +// arguments (data1 and data2), and should return false in case of error. +type WebPWorkerHook = uintptr /* thread_utils.h:36:13 */ + +// Synchronization object used to launch job in the worker thread +type WebPWorker = struct { + impl_ uintptr + status_ WebPWorkerStatus + _ [4]byte + hook WebPWorkerHook + data1 uintptr + data2 uintptr + had_error int32 + _ [4]byte +} /* thread_utils.h:46:3 */ + +// The interface for all thread-worker related functions. All these functions +// must be implemented. +type WebPWorkerInterface = struct { + Init uintptr + Reset uintptr + Sync uintptr + Launch uintptr + Execute uintptr + End uintptr +} /* thread_utils.h:71:3 */ + +//------------------------------------------------------------------------------ + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +//------------------------------------------------------------------------------ +// Various defines and enums + +// version numbers + +// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). +// Constraints are: We need to store one 16x16 block of luma samples (y), +// and two 8x8 chroma blocks (u/v). These are better be 16-bytes aligned, +// in order to be SIMD-friendly. We also need to store the top, left and +// top-left samples (from previously decoded blocks), along with four +// extra top-right samples for luma (intra4x4 prediction only). +// One possible layout is, using 32 * (17 + 9) bytes: +// +// .+------ <- only 1 pixel high +// .|yyyyt. +// .|yyyyt. +// .|yyyyt. +// .|yyyy.. +// .+--.+-- <- only 1 pixel high +// .|uu.|vv +// .|uu.|vv +// +// Every character is a 4x4 block, with legend: +// '.' = unused +// 'y' = y-samples 'u' = u-samples 'v' = u-samples +// '|' = left sample, '-' = top sample, '+' = top-left sample +// 't' = extra top-right sample for 4x4 modes + +// minimal width under which lossy multi-threading is always disabled + +//------------------------------------------------------------------------------ +// Headers + +type VP8FrameHeader = struct { + key_frame_ uint8_t + profile_ uint8_t + show_ uint8_t + _ [1]byte + partition_length_ uint32_t +} /* vp8i_dec.h:75:3 */ + +type VP8PictureHeader = struct { + width_ uint16_t + height_ uint16_t + xscale_ uint8_t + yscale_ uint8_t + colorspace_ uint8_t + clamp_type_ uint8_t +} /* vp8i_dec.h:84:3 */ + +// segment features +type VP8SegmentHeader = struct { + use_segment_ int32 + update_map_ int32 + absolute_delta_ int32 + quantizer_ [4]int8_t + filter_strength_ [4]int8_t +} /* vp8i_dec.h:93:3 */ + +// probas associated to one of the contexts +type VP8ProbaArray = [11]uint8_t /* vp8i_dec.h:96:17 */ + +type VP8BandProbas = struct{ probas_ [3]VP8ProbaArray } /* vp8i_dec.h:100:3 */ + +// Struct collecting all frame-persistent probabilities. +type VP8Proba = struct { + segments_ [3]uint8_t + bands_ [4][8]VP8BandProbas + _ [5]byte + bands_ptr_ [4][17]uintptr +} /* vp8i_dec.h:108:3 */ + +// Filter parameters +type VP8FilterHeader = struct { + simple_ int32 + level_ int32 + sharpness_ int32 + use_lf_delta_ int32 + ref_lf_delta_ [4]int32 + mode_lf_delta_ [4]int32 +} /* vp8i_dec.h:118:3 */ + +//------------------------------------------------------------------------------ +// Informations about the macroblocks. + +type VP8FInfo = struct { + f_limit_ uint8_t + f_ilevel_ uint8_t + f_inner_ uint8_t + hev_thresh_ uint8_t +} /* vp8i_dec.h:128:3 */ + +type VP8MB = struct { + nz_ uint8_t + nz_dc_ uint8_t +} /* vp8i_dec.h:133:3 */ + +// Dequantization matrices +type quant_t = [2]int32 /* vp8i_dec.h:136:13 */ // [DC / AC]. Can be 'uint16_t[2]' too (~slower). +type VP8QuantMatrix = struct { + y1_mat_ quant_t + y2_mat_ quant_t + uv_mat_ quant_t + uv_quant_ int32 + dither_ int32 +} /* vp8i_dec.h:142:3 */ + +// Data needed to reconstruct a macroblock +type VP8MBData = struct { + coeffs_ [384]int16_t + is_i4x4_ uint8_t + imodes_ [16]uint8_t + uvmode_ uint8_t + _ [2]byte + non_zero_y_ uint32_t + non_zero_uv_ uint32_t + dither_ uint8_t + skip_ uint8_t + segment_ uint8_t + _ [1]byte +} /* vp8i_dec.h:162:3 */ + +// Persistent information needed by the parallel processing +type VP8ThreadContext = struct { + id_ int32 + mb_y_ int32 + filter_row_ int32 + _ [4]byte + f_info_ uintptr + mb_data_ uintptr + io_ VP8Io +} /* vp8i_dec.h:172:3 */ + +// Saved top samples, per macroblock. Fits into a cache-line. +type VP8TopSamples = struct { + y [16]uint8_t + u [8]uint8_t + v [8]uint8_t +} /* vp8i_dec.h:177:3 */ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +// src/webp/config.h. Generated from config.h.in by configure. +// src/webp/config.h.in. Generated from configure.ac by autoheader. + +// Define if building universal (internal helper macro) +// #undef AC_APPLE_UNIVERSAL_BUILD + +// Set to 1 if __builtin_bswap16 is available + +// Set to 1 if __builtin_bswap32 is available + +// Set to 1 if __builtin_bswap64 is available + +// Define to 1 if you have the <cpu-features.h> header file. +// #undef HAVE_CPU_FEATURES_H + +// Define to 1 if you have the <dlfcn.h> header file. + +// Define to 1 if you have the <GLUT/glut.h> header file. +// #undef HAVE_GLUT_GLUT_H + +// Define to 1 if you have the <GL/glut.h> header file. +// #undef HAVE_GL_GLUT_H + +// Define to 1 if you have the <inttypes.h> header file. + +// Define to 1 if you have the <OpenGL/glut.h> header file. +// #undef HAVE_OPENGL_GLUT_H + +// Have PTHREAD_PRIO_INHERIT. +// #undef HAVE_PTHREAD_PRIO_INHERIT + +// Define to 1 if you have the <shlwapi.h> header file. +// #undef HAVE_SHLWAPI_H + +// Define to 1 if you have the <stdint.h> header file. + +// Define to 1 if you have the <stdio.h> header file. + +// Define to 1 if you have the <stdlib.h> header file. + +// Define to 1 if you have the <strings.h> header file. + +// Define to 1 if you have the <string.h> header file. + +// Define to 1 if you have the <sys/stat.h> header file. + +// Define to 1 if you have the <sys/types.h> header file. + +// Define to 1 if you have the <unistd.h> header file. + +// Define to 1 if you have the <wincodec.h> header file. +// #undef HAVE_WINCODEC_H + +// Define to 1 if you have the <windows.h> header file. +// #undef HAVE_WINDOWS_H + +// Define to the sub-directory where libtool stores uninstalled libraries. + +// Name of package + +// Define to the address where bug reports for this package should be sent. + +// Define to the full name of this package. + +// Define to the full name and version of this package. + +// Define to the one symbol short name of this package. + +// Define to the home page for this package. + +// Define to the version of this package. + +// Define to necessary symbol if this constant uses a non-standard name on +// your system. +// #undef PTHREAD_CREATE_JOINABLE + +// Define to 1 if all of the C90 standard headers exist (not just the ones +// required in a freestanding environment). This macro is provided for +// backward compatibility; new code need not use it. + +// Version number of package + +// Set to 1 if GIF library is installed +// #undef WEBP_HAVE_GIF + +// Set to 1 if OpenGL is supported +// #undef WEBP_HAVE_GL + +// Set to 1 if JPEG library is installed +// #undef WEBP_HAVE_JPEG + +// Set to 1 if NEON is supported +// #undef WEBP_HAVE_NEON + +// Set to 1 if runtime detection of NEON is enabled +// #undef WEBP_HAVE_NEON_RTCD + +// Set to 1 if PNG library is installed +// #undef WEBP_HAVE_PNG + +// Set to 1 if SDL library is installed +// #undef WEBP_HAVE_SDL + +// Set to 1 if SSE2 is supported +// #undef WEBP_HAVE_SSE2 + +// Set to 1 if SSE4.1 is supported +// #undef WEBP_HAVE_SSE41 + +// Set to 1 if TIFF library is installed +// #undef WEBP_HAVE_TIFF + +// Enable near lossless encoding + +// Undefine this to disable thread support. +// #undef WEBP_USE_THREAD + +// Define WORDS_BIGENDIAN to 1 if your processor stores words with the most +// significant byte first (like Motorola and SPARC, unlike Intel). +// # undef WORDS_BIGENDIAN + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.2 Diagnostics <assert.h> + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// void assert (int expression); +// +// If NDEBUG is defined, do nothing. +// If not, and EXPRESSION is zero, print an error message and abort. + +// void assert_perror (int errnum); +// +// If NDEBUG is defined, do nothing. If not, and ERRNUM is not zero, print an +// error message with the error text for ERRNUM and abort. +// (This is a GNU extension.) + +// Copyright (C) 1992-2021 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. +// +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. +// +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +// This administrivia gets added to the beginning of limits.h +// if the system has its own version of limits.h. + +// We use _GCC_LIMITS_H_ because we want this not to match +// any macros that the system's limits.h uses for its own purposes. + +// Use "..." so that we find syslimits.h only in this same directory. +// syslimits.h stands for the system's own limits.h file. +// If we can use it ok unmodified, then we install this text. +// If fixincludes fixes it, then the fixed version is installed +// instead of this text. + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.10/5.2.4.2.1 Sizes of integer types <limits.h> + +// Handle feature test macros at the start of a header. +// Copyright (C) 2016-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// This header is internal to glibc and should not be included outside +// of glibc headers. Headers including it must define +// __GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION first. This header +// cannot have multiple include guards because ISO C feature test +// macros depend on the definition of the macro when an affected +// header is included, not when the first system header is +// included. + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO/IEC TR 24731-2:2010 defines the __STDC_WANT_LIB_EXT2__ +// macro. + +// ISO/IEC TS 18661-1:2014 defines the __STDC_WANT_IEC_60559_BFP_EXT__ +// macro. Most but not all symbols enabled by that macro in TS +// 18661-1 are enabled unconditionally in C2X; the symbols in Annex F +// still require that macro in C2X. + +// ISO/IEC TS 18661-4:2015 defines the +// __STDC_WANT_IEC_60559_FUNCS_EXT__ macro. Other than the reduction +// functions, the symbols from this TS are enabled unconditionally in +// C2X. + +// ISO/IEC TS 18661-3:2015 defines the +// __STDC_WANT_IEC_60559_TYPES_EXT__ macro. + +// Maximum length of any multibyte character in any locale. +// We define this value here since the gcc header does not define +// the correct value. + +// If we are not using GNU CC we have to define all the symbols ourself. +// Otherwise use gcc's definitions (see below). + +// Get the compiler's limits.h, which defines almost all the ISO constants. +// +// We put this #include_next outside the double inclusion check because +// it should be possible to include this file more than once and still get +// the definitions from gcc's header. + +// The <limits.h> files in some gcc versions don't define LLONG_MIN, +// LLONG_MAX, and ULLONG_MAX. Instead only the values gcc defined for +// ages are available. + +// The integer width macros are not defined by GCC's <limits.h> before +// GCC 7, or if _GNU_SOURCE rather than +// __STDC_WANT_IEC_60559_BFP_EXT__ is used to enable this feature. + +// The macros for _Bool are not defined by GCC's <limits.h> before GCC +// 11, or if _GNU_SOURCE is defined rather than enabling C2x support +// with -std. + +// POSIX adds things to <limits.h>. +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// POSIX Standard: 2.9.2 Minimum Values Added to <limits.h> +// +// Never include this file directly; use <limits.h> instead. + +// Determine the wordsize from the preprocessor defines. + +// Both x86-64 and x32 use the 64-bit system call interface. + +// These are the standard-mandated minimum values. + +// Minimum number of operations in one list I/O call. + +// Minimal number of outstanding asynchronous I/O operations. + +// Maximum length of arguments to `execve', including environment. + +// Maximum simultaneous processes per real user ID. + +// Minimal number of timer expiration overruns. + +// Maximum length of a host name (not including the terminating null) +// as returned from the GETHOSTNAME function. + +// Maximum link count of a file. + +// Maximum length of login name. + +// Number of bytes in a terminal canonical input queue. + +// Number of bytes for which space will be +// available in a terminal input queue. + +// Maximum number of message queues open for a process. + +// Maximum number of supported message priorities. + +// Number of bytes in a filename. + +// Number of simultaneous supplementary group IDs per process. + +// Number of files one process can have open at once. + +// Number of bytes in a pathname. + +// Number of bytes than can be written atomically to a pipe. + +// The number of repeated occurrences of a BRE permitted by the +// REGEXEC and REGCOMP functions when using the interval notation. + +// Minimal number of realtime signals reserved for the application. + +// Number of semaphores a process can have. + +// Maximal value of a semaphore. + +// Number of pending realtime signals. + +// Largest value of a `ssize_t'. + +// Number of streams a process can have open at once. + +// The number of bytes in a symbolic link. + +// The number of symbolic links that can be traversed in the +// resolution of a pathname in the absence of a loop. + +// Number of timer for a process. + +// Maximum number of characters in a tty name. + +// Maximum length of a timezone name (element of `tzname'). + +// Maximum clock resolution in nanoseconds. + +// Get the implementation-specific values for the above. +// Minimum guaranteed maximum values for system limits. Linux version. +// Copyright (C) 1993-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; see the file COPYING.LIB. If +// not, see <https://www.gnu.org/licenses/>. + +// The kernel header pollutes the namespace with the NR_OPEN symbol +// and defines LINK_MAX although filesystems have different maxima. A +// similar thing is true for OPEN_MAX: the limit can be changed at +// runtime and therefore the macro must not be defined. Remove this +// after including the header if necessary. + +// The kernel sources contain a file with all the needed information. +// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note + +// Have to remove NR_OPEN? +// Have to remove LINK_MAX? +// Have to remove OPEN_MAX? +// Have to remove ARG_MAX? + +// The number of data keys per process. +// This is the value this implementation supports. + +// Controlling the iterations of destructors for thread-specific data. +// Number of iterations this implementation does. + +// The number of threads per process. +// We have no predefined limit on the number of threads. + +// Maximum amount by which a process can descrease its asynchronous I/O +// priority level. + +// Minimum size for a thread. We are free to choose a reasonable value. + +// Maximum number of timer expiration overruns. + +// Maximum tty name length. + +// Maximum login name length. This is arbitrary. + +// Maximum host name length. + +// Maximum message queue priority level. + +// Maximum value the semaphore can have. + +// ssize_t is not formally required to be the signed type +// corresponding to size_t, but it is for all configurations supported +// by glibc. + +// This value is a guaranteed minimum maximum. +// The current maximum can be got from `sysconf'. + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Never include this file directly; include <limits.h> instead. + +// The maximum `ibase' and `obase' values allowed by the `bc' utility. + +// The maximum number of elements allowed in an array by the `bc' utility. + +// The maximum `scale' value allowed by the `bc' utility. + +// The maximum length of a string constant accepted by the `bc' utility. + +// The maximum number of weights that can be assigned to an entry of +// the LC_COLLATE `order' keyword in the locale definition file. + +// The maximum number of expressions that can be nested +// within parentheses by the `expr' utility. + +// The maximum length, in bytes, of an input line. + +// The maximum number of repeated occurrences of a regular expression +// permitted when using the interval notation `\{M,N\}'. + +// The maximum number of bytes in a character class name. We have no +// fixed limit, 2048 is a high number. + +// These values are implementation-specific, +// and may vary within the implementation. +// Their precise values can be obtained from sysconf. + +// This value is defined like this in regex.h. + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. +// +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. +// +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +// Number of bits in a `char'. + +// Maximum length of a multibyte character. + +// Minimum and maximum values a `signed char' can hold. + +// Maximum value an `unsigned char' can hold. (Minimum is 0). + +// Minimum and maximum values a `char' can hold. + +// Minimum and maximum values a `signed short int' can hold. + +// Maximum value an `unsigned short int' can hold. (Minimum is 0). + +// Minimum and maximum values a `signed int' can hold. + +// Maximum value an `unsigned int' can hold. (Minimum is 0). + +// Minimum and maximum values a `signed long int' can hold. +// (Same as `int'). + +// Maximum value an `unsigned long int' can hold. (Minimum is 0). + +// Minimum and maximum values a `signed long long int' can hold. + +// Maximum value an `unsigned long long int' can hold. (Minimum is 0). + +// This administrivia gets added to the end of limits.h +// if the system has its own version of limits.h. + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +//------------------------------------------------------------------------------ +// Memory allocation + +// This is the maximum memory amount that libwebp will ever try to allocate. + +func CheckSizeOverflow(tls *libc.TLS, size uint64_t) int32 { /* utils.h:45:24: */ + return (libc.Bool32(size == size)) +} + +//------------------------------------------------------------------------------ +// Alignment + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.21 String handling <string.h> + +// memcpy() is the safe way of moving potentially unaligned 32b memory. +func WebPMemToUint32(tls *libc.TLS, ptr uintptr) uint32_t { /* utils.h:71:29: */ + bp := tls.Alloc(4) + defer tls.Free(4) + + // var A uint32_t at bp, 4 + + libc.Xmemcpy(tls, (bp) /* &A */, ptr, uint64(unsafe.Sizeof(uint32_t(0)))) + return *(*uint32_t)(unsafe.Pointer(bp /* A */)) +} + +func WebPUint32ToMem(tls *libc.TLS, ptr uintptr, val uint32_t) { /* utils.h:76:25: */ + bp := tls.Alloc(4) + defer tls.Free(4) + *(*uint32_t)(unsafe.Pointer(bp)) = val + + libc.Xmemcpy(tls, ptr, (bp) /* &val */, uint64(unsafe.Sizeof(uint32_t(0)))) +} + +//------------------------------------------------------------------------------ +// Reading/writing data. + +// Read 16, 24 or 32 bits stored in little-endian order. +func GetLE16(tls *libc.TLS, data uintptr) int32 { /* utils.h:84:24: */ + return ((int32(*(*uint8_t)(unsafe.Pointer(data))) << 0) | (int32(*(*uint8_t)(unsafe.Pointer(data + 1))) << 8)) +} + +func GetLE24(tls *libc.TLS, data uintptr) int32 { /* utils.h:88:24: */ + return (GetLE16(tls, data) | (int32(*(*uint8_t)(unsafe.Pointer(data + 2))) << 16)) +} + +func GetLE32(tls *libc.TLS, data uintptr) uint32_t { /* utils.h:92:29: */ + return (uint32_t(GetLE16(tls, data)) | (uint32_t(GetLE16(tls, (data+uintptr(2)))) << 16)) +} + +// Store 16, 24 or 32 bits in little-endian order. +func PutLE16(tls *libc.TLS, data uintptr, val int32) { /* utils.h:97:25: */ + + *(*uint8_t)(unsafe.Pointer(data)) = (uint8_t((val >> 0) & 0xff)) + *(*uint8_t)(unsafe.Pointer(data + 1)) = (uint8_t((val >> 8) & 0xff)) +} + +func PutLE24(tls *libc.TLS, data uintptr, val int32) { /* utils.h:103:25: */ + + PutLE16(tls, data, (val & 0xffff)) + *(*uint8_t)(unsafe.Pointer(data + 2)) = (uint8_t((val >> 16) & 0xff)) +} + +func PutLE32(tls *libc.TLS, data uintptr, val uint32_t) { /* utils.h:109:25: */ + PutLE16(tls, data, (int32(val & uint32_t(0xffff)))) + PutLE16(tls, (data + uintptr(2)), (int32(val >> 16))) +} + +// use GNU builtins where available. +// Returns (int)floor(log2(n)). n must be > 0. +func BitsLog2Floor(tls *libc.TLS, n uint32_t) int32 { /* utils.h:118:24: */ + return (31 ^ libc.X__builtin_clz(tls, n)) +} + +//------------------------------------------------------------------------------ +// Pixel copying. + +type WebPPicture1 = struct { + use_argb int32 + colorspace WebPEncCSP + width int32 + height int32 + y uintptr + u uintptr + v uintptr + y_stride int32 + uv_stride int32 + a uintptr + a_stride int32 + pad1 [2]uint32_t + _ [4]byte + argb uintptr + argb_stride int32 + pad2 [3]uint32_t + writer WebPWriterFunction + custom_ptr uintptr + extra_info_type int32 + _ [4]byte + extra_info uintptr + stats uintptr + error_code WebPEncodingError + _ [4]byte + progress_hook WebPProgressHook + user_data uintptr + pad3 [3]uint32_t + _ [4]byte + pad4 uintptr + pad5 uintptr + pad6 [8]uint32_t + memory_ uintptr + memory_argb_ uintptr + pad7 [2]uintptr +} /* encode.h:32:9 */ + +//------------------------------------------------------------------------------ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header for constants related to WebP file format. +// +// Author: Urvang (urvang@google.com) + +//------------------------------------------------------------------------------ +// ALPHDecoder object. + +// Allocates a new alpha decoder instance. +func ALPHNew(tls *libc.TLS) uintptr { /* alpha_dec.c:27:19: */ + var dec uintptr = WebPSafeCalloc(tls, 1, uint64(unsafe.Sizeof(ALPHDecoder{}))) + return dec +} + +// Clears and deallocates an alpha decoder instance. +func ALPHDelete(tls *libc.TLS, dec uintptr) { /* alpha_dec.c:33:13: */ + if dec != (uintptr(0)) { + VP8LDelete(tls, (*ALPHDecoder)(unsafe.Pointer(dec)).vp8l_dec_) + (*ALPHDecoder)(unsafe.Pointer(dec)).vp8l_dec_ = (uintptr(0)) + WebPSafeFree(tls, dec) + } +} + +//------------------------------------------------------------------------------ +// Decoding. + +// Initialize alpha decoding by parsing the alpha header and decoding the image +// header for alpha data stored using lossless compression. +// Returns false in case of error in alpha header (data too short, invalid +// compression method or filter, error in lossless header data etc). +func ALPHInit(tls *libc.TLS, dec uintptr, data uintptr, data_size size_t, src_io uintptr, output uintptr) int32 { /* alpha_dec.c:48:12: */ + var ok int32 = 0 + var alpha_data uintptr = (data + uintptr(1)) + var alpha_data_size size_t = (data_size - uint64(1)) + var rsrv int32 + var io uintptr = (dec + 32 /* &.io_ */) + + VP8FiltersInit(tls) + (*ALPHDecoder)(unsafe.Pointer(dec)).output_ = output + (*ALPHDecoder)(unsafe.Pointer(dec)).width_ = (*VP8Io)(unsafe.Pointer(src_io)).width + (*ALPHDecoder)(unsafe.Pointer(dec)).height_ = (*VP8Io)(unsafe.Pointer(src_io)).height + + if data_size <= uint64(1) { + return 0 + } + + (*ALPHDecoder)(unsafe.Pointer(dec)).method_ = ((int32(*(*uint8_t)(unsafe.Pointer(data))) >> 0) & 0x03) + (*ALPHDecoder)(unsafe.Pointer(dec)).filter_ = (WEBP_FILTER_TYPE((int32(*(*uint8_t)(unsafe.Pointer(data))) >> 2) & 0x03)) + (*ALPHDecoder)(unsafe.Pointer(dec)).pre_processing_ = ((int32(*(*uint8_t)(unsafe.Pointer(data))) >> 4) & 0x03) + rsrv = ((int32(*(*uint8_t)(unsafe.Pointer(data))) >> 6) & 0x03) + if (((((*ALPHDecoder)(unsafe.Pointer(dec)).method_ < 0) || ((*ALPHDecoder)(unsafe.Pointer(dec)).method_ > 1)) || ((*ALPHDecoder)(unsafe.Pointer(dec)).filter_ >= WEBP_FILTER_LAST)) || ((*ALPHDecoder)(unsafe.Pointer(dec)).pre_processing_ > 1)) || (rsrv != 0) { + return 0 + } + + // Copy the necessary parameters from src_io to io + VP8InitIo(tls, io) + WebPInitCustomIo(tls, (uintptr(0)), io) + (*VP8Io)(unsafe.Pointer(io)).opaque = dec + (*VP8Io)(unsafe.Pointer(io)).width = (*VP8Io)(unsafe.Pointer(src_io)).width + (*VP8Io)(unsafe.Pointer(io)).height = (*VP8Io)(unsafe.Pointer(src_io)).height + + (*VP8Io)(unsafe.Pointer(io)).use_cropping = (*VP8Io)(unsafe.Pointer(src_io)).use_cropping + (*VP8Io)(unsafe.Pointer(io)).crop_left = (*VP8Io)(unsafe.Pointer(src_io)).crop_left + (*VP8Io)(unsafe.Pointer(io)).crop_right = (*VP8Io)(unsafe.Pointer(src_io)).crop_right + (*VP8Io)(unsafe.Pointer(io)).crop_top = (*VP8Io)(unsafe.Pointer(src_io)).crop_top + (*VP8Io)(unsafe.Pointer(io)).crop_bottom = (*VP8Io)(unsafe.Pointer(src_io)).crop_bottom + // No need to copy the scaling parameters. + + if (*ALPHDecoder)(unsafe.Pointer(dec)).method_ == 0 { + var alpha_decoded_size size_t = (size_t((*ALPHDecoder)(unsafe.Pointer(dec)).width_ * (*ALPHDecoder)(unsafe.Pointer(dec)).height_)) + ok = (libc.Bool32(alpha_data_size >= alpha_decoded_size)) + } else { + + ok = VP8LDecodeAlphaHeader(tls, dec, alpha_data, alpha_data_size) + } + + return ok +} + +// Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha +// starting from row number 'row'. It assumes that rows up to (row - 1) have +// already been decoded. +// Returns false in case of bitstream error. +func ALPHDecode(tls *libc.TLS, dec uintptr, row int32, num_rows int32) int32 { /* alpha_dec.c:110:12: */ + var alph_dec uintptr = (*VP8Decoder)(unsafe.Pointer(dec)).alph_dec_ + var width int32 = (*ALPHDecoder)(unsafe.Pointer(alph_dec)).width_ + var height int32 = (*ALPHDecoder)(unsafe.Pointer(alph_dec)).io_.crop_bottom + if (*ALPHDecoder)(unsafe.Pointer(alph_dec)).method_ == 0 { + var y int32 + var prev_line uintptr = (*VP8Decoder)(unsafe.Pointer(dec)).alpha_prev_line_ + var deltas uintptr = (((*VP8Decoder)(unsafe.Pointer(dec)).alpha_data_ + uintptr(1)) + uintptr((row * width))) + var dst uintptr = ((*VP8Decoder)(unsafe.Pointer(dec)).alpha_plane_ + uintptr((row * width))) + + if (*ALPHDecoder)(unsafe.Pointer(alph_dec)).filter_ != WEBP_FILTER_NONE { + + for y = 0; y < num_rows; y++ { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPUnfilters[(*ALPHDecoder)(unsafe.Pointer(alph_dec)).filter_]})).f(tls, prev_line, deltas, dst, width) + prev_line = dst + dst += uintptr(width) + deltas += uintptr(width) + } + } else { + for y = 0; y < num_rows; y++ { + libc.Xmemcpy(tls, dst, deltas, (uint64(width) * uint64(unsafe.Sizeof(uint8_t(0))))) + prev_line = dst + dst += uintptr(width) + deltas += uintptr(width) + } + } + (*VP8Decoder)(unsafe.Pointer(dec)).alpha_prev_line_ = prev_line + } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION + + if !(VP8LDecodeAlphaImageStream(tls, alph_dec, (row+num_rows)) != 0) { + return 0 + } + } + + if (row + num_rows) >= height { + (*VP8Decoder)(unsafe.Pointer(dec)).is_alpha_decoded_ = 1 + } + return 1 +} + +func AllocateAlphaPlane(tls *libc.TLS, dec uintptr, io uintptr) int32 { /* alpha_dec.c:150:12: */ + var stride int32 = (*VP8Io)(unsafe.Pointer(io)).width + var height int32 = (*VP8Io)(unsafe.Pointer(io)).crop_bottom + var alpha_size uint64_t = (uint64_t(stride) * uint64_t(height)) + + (*VP8Decoder)(unsafe.Pointer(dec)).alpha_plane_mem_ = WebPSafeMalloc(tls, alpha_size, uint64(unsafe.Sizeof(uint8_t(0)))) + if (*VP8Decoder)(unsafe.Pointer(dec)).alpha_plane_mem_ == (uintptr(0)) { + return 0 + } + (*VP8Decoder)(unsafe.Pointer(dec)).alpha_plane_ = (*VP8Decoder)(unsafe.Pointer(dec)).alpha_plane_mem_ + (*VP8Decoder)(unsafe.Pointer(dec)).alpha_prev_line_ = (uintptr(0)) + return 1 +} + +func WebPDeallocateAlphaMemory(tls *libc.TLS, dec uintptr) { /* alpha_dec.c:165:6: */ + + WebPSafeFree(tls, (*VP8Decoder)(unsafe.Pointer(dec)).alpha_plane_mem_) + (*VP8Decoder)(unsafe.Pointer(dec)).alpha_plane_mem_ = (uintptr(0)) + (*VP8Decoder)(unsafe.Pointer(dec)).alpha_plane_ = (uintptr(0)) + ALPHDelete(tls, (*VP8Decoder)(unsafe.Pointer(dec)).alph_dec_) + (*VP8Decoder)(unsafe.Pointer(dec)).alph_dec_ = (uintptr(0)) +} + +//------------------------------------------------------------------------------ +// Main entry point. + +func VP8DecompressAlphaRows(tls *libc.TLS, dec uintptr, io uintptr, row int32, num_rows int32) uintptr { /* alpha_dec.c:177:14: */ + var width int32 + var height int32 + var alpha uintptr + width = (*VP8Io)(unsafe.Pointer(io)).width + height = (*VP8Io)(unsafe.Pointer(io)).crop_bottom + + if !(((row < 0) || (num_rows <= 0)) || ((row + num_rows) > height)) { + goto __1 + } + return (uintptr(0)) +__1: + ; + + if !(!((*VP8Decoder)(unsafe.Pointer(dec)).is_alpha_decoded_ != 0)) { + goto __2 + } + if !((*VP8Decoder)(unsafe.Pointer(dec)).alph_dec_ == (uintptr(0))) { + goto __3 + } // Initialize decoder. + (*VP8Decoder)(unsafe.Pointer(dec)).alph_dec_ = ALPHNew(tls) + if !((*VP8Decoder)(unsafe.Pointer(dec)).alph_dec_ == (uintptr(0))) { + goto __4 + } + return (uintptr(0)) +__4: + ; + if !(!(AllocateAlphaPlane(tls, dec, io) != 0)) { + goto __5 + } + goto Error +__5: + ; + if !(!(ALPHInit(tls, (*VP8Decoder)(unsafe.Pointer(dec)).alph_dec_, (*VP8Decoder)(unsafe.Pointer(dec)).alpha_data_, (*VP8Decoder)(unsafe.Pointer(dec)).alpha_data_size_, + io, (*VP8Decoder)(unsafe.Pointer(dec)).alpha_plane_) != 0)) { + goto __6 + } + goto Error +__6: + ; + // if we allowed use of alpha dithering, check whether it's needed at all + if !((*ALPHDecoder1)(unsafe.Pointer((*VP8Decoder)(unsafe.Pointer(dec)).alph_dec_)).pre_processing_ != 1) { + goto __7 + } + (*VP8Decoder)(unsafe.Pointer(dec)).alpha_dithering_ = 0 // disable dithering + goto __8 +__7: + num_rows = (height - row) // decode everything in one pass +__8: + ; +__3: + ; + + if !(!(ALPHDecode(tls, dec, row, num_rows) != 0)) { + goto __9 + } + goto Error +__9: + ; + + if !((*VP8Decoder)(unsafe.Pointer(dec)).is_alpha_decoded_ != 0) { + goto __10 + } // finished? + ALPHDelete(tls, (*VP8Decoder)(unsafe.Pointer(dec)).alph_dec_) + (*VP8Decoder)(unsafe.Pointer(dec)).alph_dec_ = (uintptr(0)) + if !((*VP8Decoder)(unsafe.Pointer(dec)).alpha_dithering_ > 0) { + goto __11 + } + alpha = (((*VP8Decoder)(unsafe.Pointer(dec)).alpha_plane_ + uintptr(((*VP8Io)(unsafe.Pointer(io)).crop_top * width))) + + uintptr((*VP8Io)(unsafe.Pointer(io)).crop_left)) + if !(!(WebPDequantizeLevels(tls, alpha, + ((*VP8Io)(unsafe.Pointer(io)).crop_right-(*VP8Io)(unsafe.Pointer(io)).crop_left), + ((*VP8Io)(unsafe.Pointer(io)).crop_bottom-(*VP8Io)(unsafe.Pointer(io)).crop_top), + width, (*VP8Decoder)(unsafe.Pointer(dec)).alpha_dithering_) != 0)) { + goto __12 + } + goto Error +__12: + ; +__11: + ; +__10: + ; +__2: + ; + + // Return a pointer to the current decoded row. + return ((*VP8Decoder)(unsafe.Pointer(dec)).alpha_plane_ + uintptr((row * width))) + +Error: + WebPDeallocateAlphaMemory(tls, dec) + return (uintptr(0)) +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// WebPDecBuffer + +// Number of bytes per pixel for the different color-spaces. +var kModeBpp = [13]uint8_t{ + uint8_t(3), uint8_t(4), uint8_t(3), uint8_t(4), uint8_t(4), uint8_t(2), uint8_t(2), + uint8_t(4), uint8_t(4), uint8_t(4), uint8_t(2), // pre-multiplied modes + uint8_t(1), uint8_t(1)} /* buffer_dec.c:24:22 */ + +// Check that webp_csp_mode is within the bounds of WEBP_CSP_MODE. +// Convert to an integer to handle both the unsigned/signed enum cases +// without the need for casting to remove type limit warnings. +func IsValidColorspace(tls *libc.TLS, webp_csp_mode int32) int32 { /* buffer_dec.c:32:12: */ + return (libc.Bool32((webp_csp_mode >= MODE_RGB) && (webp_csp_mode < MODE_LAST))) +} + +// strictly speaking, the very last (or first, if flipped) row +// doesn't require padding. + +func CheckDecBuffer(tls *libc.TLS, buffer uintptr) VP8StatusCode { /* buffer_dec.c:41:22: */ + var ok int32 = 1 + var mode WEBP_CSP_MODE = (*WebPDecBuffer)(unsafe.Pointer(buffer)).colorspace + var width int32 = (*WebPDecBuffer)(unsafe.Pointer(buffer)).width + var height int32 = (*WebPDecBuffer)(unsafe.Pointer(buffer)).height + if !(IsValidColorspace(tls, int32(mode)) != 0) { + ok = 0 + } else if !(WebPIsRGBMode(tls, mode) != 0) { // YUV checks + var buf uintptr = (buffer + 16 /* &.u */) /* &.YUVA */ + var uv_width int32 = ((width + 1) / 2) + var uv_height int32 = ((height + 1) / 2) + var y_stride int32 = libc.Xabs(tls, (*WebPYUVABuffer)(unsafe.Pointer(buf)).y_stride) + var u_stride int32 = libc.Xabs(tls, (*WebPYUVABuffer)(unsafe.Pointer(buf)).u_stride) + var v_stride int32 = libc.Xabs(tls, (*WebPYUVABuffer)(unsafe.Pointer(buf)).v_stride) + var a_stride int32 = libc.Xabs(tls, (*WebPYUVABuffer)(unsafe.Pointer(buf)).a_stride) + var y_size uint64_t = (((uint64_t(y_stride)) * (uint64_t((height) - 1))) + (uint64_t(width))) + var u_size uint64_t = (((uint64_t(u_stride)) * (uint64_t((uv_height) - 1))) + (uint64_t(uv_width))) + var v_size uint64_t = (((uint64_t(v_stride)) * (uint64_t((uv_height) - 1))) + (uint64_t(uv_width))) + var a_size uint64_t = (((uint64_t(a_stride)) * (uint64_t((height) - 1))) + (uint64_t(width))) + ok = ok & (libc.Bool32(y_size <= (*WebPYUVABuffer)(unsafe.Pointer(buf)).y_size)) + ok = ok & (libc.Bool32(u_size <= (*WebPYUVABuffer)(unsafe.Pointer(buf)).u_size)) + ok = ok & (libc.Bool32(v_size <= (*WebPYUVABuffer)(unsafe.Pointer(buf)).v_size)) + ok = ok & (libc.Bool32(y_stride >= width)) + ok = ok & (libc.Bool32(u_stride >= uv_width)) + ok = ok & (libc.Bool32(v_stride >= uv_width)) + ok = ok & (libc.Bool32((*WebPYUVABuffer)(unsafe.Pointer(buf)).y != (uintptr(0)))) + ok = ok & (libc.Bool32((*WebPYUVABuffer)(unsafe.Pointer(buf)).u != (uintptr(0)))) + ok = ok & (libc.Bool32((*WebPYUVABuffer)(unsafe.Pointer(buf)).v != (uintptr(0)))) + if mode == MODE_YUVA { + ok = ok & (libc.Bool32(a_stride >= width)) + ok = ok & (libc.Bool32(a_size <= (*WebPYUVABuffer)(unsafe.Pointer(buf)).a_size)) + ok = ok & (libc.Bool32((*WebPYUVABuffer)(unsafe.Pointer(buf)).a != (uintptr(0)))) + } + } else { // RGB checks + var buf uintptr = (buffer + 16 /* &.u */) /* &.RGBA */ + var stride int32 = libc.Xabs(tls, (*WebPRGBABuffer)(unsafe.Pointer(buf)).stride) + var size uint64_t = (((uint64_t(stride)) * (uint64_t((height) - 1))) + (uint64_t(width * int32(kModeBpp[mode])))) + ok = ok & (libc.Bool32(size <= (*WebPRGBABuffer)(unsafe.Pointer(buf)).size)) + ok = ok & (libc.Bool32(stride >= (width * int32(kModeBpp[mode])))) + ok = ok & (libc.Bool32((*WebPRGBABuffer)(unsafe.Pointer(buf)).rgba != (uintptr(0)))) + } + if ok != 0 { + return VP8_STATUS_OK + } + return VP8_STATUS_INVALID_PARAM +} + +func AllocateBuffer(tls *libc.TLS, buffer uintptr) VP8StatusCode { /* buffer_dec.c:87:22: */ + var w int32 = (*WebPDecBuffer)(unsafe.Pointer(buffer)).width + var h int32 = (*WebPDecBuffer)(unsafe.Pointer(buffer)).height + var mode WEBP_CSP_MODE = (*WebPDecBuffer)(unsafe.Pointer(buffer)).colorspace + + if ((w <= 0) || (h <= 0)) || !(IsValidColorspace(tls, int32(mode)) != 0) { + return VP8_STATUS_INVALID_PARAM + } + + if ((*WebPDecBuffer)(unsafe.Pointer(buffer)).is_external_memory <= 0) && ((*WebPDecBuffer)(unsafe.Pointer(buffer)).private_memory == (uintptr(0))) { + var output uintptr + var uv_stride int32 = 0 + var a_stride int32 = 0 + var uv_size uint64_t = uint64(0) + var a_size uint64_t = uint64(0) + var total_size uint64_t + // We need memory and it hasn't been allocated yet. + // => initialize output buffer, now that dimensions are known. + var stride int32 + var size uint64_t + + if (uint64(uint64_t(w) * uint64_t(kModeBpp[mode]))) >= (uint64(1) << 31) { + return VP8_STATUS_INVALID_PARAM + } + stride = (w * int32(kModeBpp[mode])) + size = (uint64_t(stride) * uint64_t(h)) + if !(WebPIsRGBMode(tls, mode) != 0) { + uv_stride = ((w + 1) / 2) + uv_size = (uint64_t(uv_stride) * (uint64_t((h + 1) / 2))) + if mode == MODE_YUVA { + a_stride = w + a_size = (uint64_t(a_stride) * uint64_t(h)) + } + } + total_size = ((size + (uint64(2) * uv_size)) + a_size) + + output = WebPSafeMalloc(tls, total_size, uint64(unsafe.Sizeof(uint8_t(0)))) + if output == (uintptr(0)) { + return VP8_STATUS_OUT_OF_MEMORY + } + (*WebPDecBuffer)(unsafe.Pointer(buffer)).private_memory = output + + if !(WebPIsRGBMode(tls, mode) != 0) { // YUVA initialization + var buf uintptr = (buffer + 16 /* &.u */) /* &.YUVA */ + (*WebPYUVABuffer)(unsafe.Pointer(buf)).y = output + (*WebPYUVABuffer)(unsafe.Pointer(buf)).y_stride = stride + (*WebPYUVABuffer)(unsafe.Pointer(buf)).y_size = size + (*WebPYUVABuffer)(unsafe.Pointer(buf)).u = (output + uintptr(size)) + (*WebPYUVABuffer)(unsafe.Pointer(buf)).u_stride = uv_stride + (*WebPYUVABuffer)(unsafe.Pointer(buf)).u_size = uv_size + (*WebPYUVABuffer)(unsafe.Pointer(buf)).v = ((output + uintptr(size)) + uintptr(uv_size)) + (*WebPYUVABuffer)(unsafe.Pointer(buf)).v_stride = uv_stride + (*WebPYUVABuffer)(unsafe.Pointer(buf)).v_size = uv_size + if mode == MODE_YUVA { + (*WebPYUVABuffer)(unsafe.Pointer(buf)).a = ((output + uintptr(size)) + uintptr((uint64(2) * uv_size))) + } + (*WebPYUVABuffer)(unsafe.Pointer(buf)).a_size = a_size + (*WebPYUVABuffer)(unsafe.Pointer(buf)).a_stride = a_stride + } else { // RGBA initialization + var buf uintptr = (buffer + 16 /* &.u */) /* &.RGBA */ + (*WebPRGBABuffer)(unsafe.Pointer(buf)).rgba = output + (*WebPRGBABuffer)(unsafe.Pointer(buf)).stride = stride + (*WebPRGBABuffer)(unsafe.Pointer(buf)).size = size + } + } + return CheckDecBuffer(tls, buffer) +} + +func WebPFlipBuffer(tls *libc.TLS, buffer uintptr) VP8StatusCode { /* buffer_dec.c:152:15: */ + if buffer == (uintptr(0)) { + return VP8_STATUS_INVALID_PARAM + } + if WebPIsRGBMode(tls, (*WebPDecBuffer)(unsafe.Pointer(buffer)).colorspace) != 0 { + var buf uintptr = (buffer + 16 /* &.u */) /* &.RGBA */ + *(*uintptr)(unsafe.Pointer((buf /* &.rgba */))) += (uintptr((int64_t((*WebPDecBuffer)(unsafe.Pointer(buffer)).height - 1)) * int64_t((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride))) + (*WebPRGBABuffer)(unsafe.Pointer(buf)).stride = -(*WebPRGBABuffer)(unsafe.Pointer(buf)).stride + } else { + var buf uintptr = (buffer + 16 /* &.u */) /* &.YUVA */ + var H int64_t = int64_t((*WebPDecBuffer)(unsafe.Pointer(buffer)).height) + *(*uintptr)(unsafe.Pointer((buf /* &.y */))) += (uintptr((H - int64(1)) * int64_t((*WebPYUVABuffer)(unsafe.Pointer(buf)).y_stride))) + (*WebPYUVABuffer)(unsafe.Pointer(buf)).y_stride = -(*WebPYUVABuffer)(unsafe.Pointer(buf)).y_stride + *(*uintptr)(unsafe.Pointer((buf + 8 /* &.u */))) += (uintptr(((H - int64(1)) >> 1) * int64_t((*WebPYUVABuffer)(unsafe.Pointer(buf)).u_stride))) + (*WebPYUVABuffer)(unsafe.Pointer(buf)).u_stride = -(*WebPYUVABuffer)(unsafe.Pointer(buf)).u_stride + *(*uintptr)(unsafe.Pointer((buf + 16 /* &.v */))) += (uintptr(((H - int64(1)) >> 1) * int64_t((*WebPYUVABuffer)(unsafe.Pointer(buf)).v_stride))) + (*WebPYUVABuffer)(unsafe.Pointer(buf)).v_stride = -(*WebPYUVABuffer)(unsafe.Pointer(buf)).v_stride + if (*WebPYUVABuffer)(unsafe.Pointer(buf)).a != (uintptr(0)) { + *(*uintptr)(unsafe.Pointer((buf + 24 /* &.a */))) += (uintptr((H - int64(1)) * int64_t((*WebPYUVABuffer)(unsafe.Pointer(buf)).a_stride))) + (*WebPYUVABuffer)(unsafe.Pointer(buf)).a_stride = -(*WebPYUVABuffer)(unsafe.Pointer(buf)).a_stride + } + } + return VP8_STATUS_OK +} + +func WebPAllocateDecBuffer(tls *libc.TLS, width int32, height int32, options uintptr, buffer uintptr) VP8StatusCode { /* buffer_dec.c:177:15: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var status VP8StatusCode + if ((buffer == (uintptr(0))) || (width <= 0)) || (height <= 0) { + return VP8_STATUS_INVALID_PARAM + } + if options != (uintptr(0)) { // First, apply options if there is any. + if (*WebPDecoderOptions)(unsafe.Pointer(options)).use_cropping != 0 { + var cw int32 = (*WebPDecoderOptions)(unsafe.Pointer(options)).crop_width + var ch int32 = (*WebPDecoderOptions)(unsafe.Pointer(options)).crop_height + var x int32 = ((*WebPDecoderOptions)(unsafe.Pointer(options)).crop_left & libc.CplInt32(1)) + var y int32 = ((*WebPDecoderOptions)(unsafe.Pointer(options)).crop_top & libc.CplInt32(1)) + if !(WebPCheckCropDimensions(tls, width, height, x, y, cw, ch) != 0) { + return VP8_STATUS_INVALID_PARAM // out of frame boundary. + } + width = cw + height = ch + } + + if (*WebPDecoderOptions)(unsafe.Pointer(options)).use_scaling != 0 { + *(*int32)(unsafe.Pointer(bp /* scaled_width */)) = (*WebPDecoderOptions)(unsafe.Pointer(options)).scaled_width + *(*int32)(unsafe.Pointer(bp + 4 /* scaled_height */)) = (*WebPDecoderOptions)(unsafe.Pointer(options)).scaled_height + if !(WebPRescalerGetScaledDimensions(tls, + width, height, (bp) /* &scaled_width */, (bp+4) /* &scaled_height */) != 0) { + return VP8_STATUS_INVALID_PARAM + } + width = *(*int32)(unsafe.Pointer(bp /* scaled_width */)) + height = *(*int32)(unsafe.Pointer(bp + 4 /* scaled_height */)) + } + } + (*WebPDecBuffer)(unsafe.Pointer(buffer)).width = width + (*WebPDecBuffer)(unsafe.Pointer(buffer)).height = height + + // Then, allocate buffer for real. + status = AllocateBuffer(tls, buffer) + if status != VP8_STATUS_OK { + return status + } + + // Use the stride trick if vertical flip is needed. + if (options != (uintptr(0))) && ((*WebPDecoderOptions)(unsafe.Pointer(options)).flip != 0) { + status = WebPFlipBuffer(tls, buffer) + } + return status +} + +//------------------------------------------------------------------------------ +// constructors / destructors + +func WebPInitDecBufferInternal(tls *libc.TLS, buffer uintptr, version int32) int32 { /* buffer_dec.c:229:5: */ + if ((version) >> 8) != (int32((0x0209)) >> 8) { + return 0 // version mismatch + } + if buffer == (uintptr(0)) { + return 0 + } + libc.Xmemset(tls, buffer, 0, uint64(unsafe.Sizeof(WebPDecBuffer{}))) + return 1 +} + +func WebPFreeDecBuffer(tls *libc.TLS, buffer uintptr) { /* buffer_dec.c:238:6: */ + if buffer != (uintptr(0)) { + if (*WebPDecBuffer)(unsafe.Pointer(buffer)).is_external_memory <= 0 { + WebPSafeFree(tls, (*WebPDecBuffer)(unsafe.Pointer(buffer)).private_memory) + } + (*WebPDecBuffer)(unsafe.Pointer(buffer)).private_memory = (uintptr(0)) + } +} + +func WebPCopyDecBuffer(tls *libc.TLS, src uintptr, dst uintptr) { /* buffer_dec.c:247:6: */ + if (src != (uintptr(0))) && (dst != (uintptr(0))) { + *(*WebPDecBuffer)(unsafe.Pointer(dst)) = *(*WebPDecBuffer)(unsafe.Pointer(src)) + if (*WebPDecBuffer)(unsafe.Pointer(src)).private_memory != (uintptr(0)) { + (*WebPDecBuffer)(unsafe.Pointer(dst)).is_external_memory = 1 // dst buffer doesn't own the memory. + (*WebPDecBuffer)(unsafe.Pointer(dst)).private_memory = (uintptr(0)) + } + } +} + +// Copy and transfer ownership from src to dst (beware of parameter order!) +func WebPGrabDecBuffer(tls *libc.TLS, src uintptr, dst uintptr) { /* buffer_dec.c:259:6: */ + if (src != (uintptr(0))) && (dst != (uintptr(0))) { + *(*WebPDecBuffer)(unsafe.Pointer(dst)) = *(*WebPDecBuffer)(unsafe.Pointer(src)) + if (*WebPDecBuffer)(unsafe.Pointer(src)).private_memory != (uintptr(0)) { + (*WebPDecBuffer)(unsafe.Pointer(src)).is_external_memory = 1 // src relinquishes ownership + (*WebPDecBuffer)(unsafe.Pointer(src)).private_memory = (uintptr(0)) + } + } +} + +func WebPCopyDecBufferPixels(tls *libc.TLS, src_buf uintptr, dst_buf uintptr) VP8StatusCode { /* buffer_dec.c:269:15: */ + + (*WebPDecBuffer)(unsafe.Pointer(dst_buf)).width = (*WebPDecBuffer)(unsafe.Pointer(src_buf)).width + (*WebPDecBuffer)(unsafe.Pointer(dst_buf)).height = (*WebPDecBuffer)(unsafe.Pointer(src_buf)).height + if CheckDecBuffer(tls, dst_buf) != VP8_STATUS_OK { + return VP8_STATUS_INVALID_PARAM + } + if WebPIsRGBMode(tls, (*WebPDecBuffer)(unsafe.Pointer(src_buf)).colorspace) != 0 { + var src uintptr = (src_buf + 16 /* &.u */) /* &.RGBA */ + var dst uintptr = (dst_buf + 16 /* &.u */) /* &.RGBA */ + WebPCopyPlane(tls, (*WebPRGBABuffer)(unsafe.Pointer(src)).rgba, (*WebPRGBABuffer)(unsafe.Pointer(src)).stride, (*WebPRGBABuffer)(unsafe.Pointer(dst)).rgba, (*WebPRGBABuffer)(unsafe.Pointer(dst)).stride, + ((*WebPDecBuffer)(unsafe.Pointer(src_buf)).width * int32(kModeBpp[(*WebPDecBuffer)(unsafe.Pointer(src_buf)).colorspace])), + (*WebPDecBuffer)(unsafe.Pointer(src_buf)).height) + } else { + var src uintptr = (src_buf + 16 /* &.u */) /* &.YUVA */ + var dst uintptr = (dst_buf + 16 /* &.u */) /* &.YUVA */ + WebPCopyPlane(tls, (*WebPYUVABuffer)(unsafe.Pointer(src)).y, (*WebPYUVABuffer)(unsafe.Pointer(src)).y_stride, (*WebPYUVABuffer)(unsafe.Pointer(dst)).y, (*WebPYUVABuffer)(unsafe.Pointer(dst)).y_stride, + (*WebPDecBuffer)(unsafe.Pointer(src_buf)).width, (*WebPDecBuffer)(unsafe.Pointer(src_buf)).height) + WebPCopyPlane(tls, (*WebPYUVABuffer)(unsafe.Pointer(src)).u, (*WebPYUVABuffer)(unsafe.Pointer(src)).u_stride, (*WebPYUVABuffer)(unsafe.Pointer(dst)).u, (*WebPYUVABuffer)(unsafe.Pointer(dst)).u_stride, + (((*WebPDecBuffer)(unsafe.Pointer(src_buf)).width + 1) / 2), (((*WebPDecBuffer)(unsafe.Pointer(src_buf)).height + 1) / 2)) + WebPCopyPlane(tls, (*WebPYUVABuffer)(unsafe.Pointer(src)).v, (*WebPYUVABuffer)(unsafe.Pointer(src)).v_stride, (*WebPYUVABuffer)(unsafe.Pointer(dst)).v, (*WebPYUVABuffer)(unsafe.Pointer(dst)).v_stride, + (((*WebPDecBuffer)(unsafe.Pointer(src_buf)).width + 1) / 2), (((*WebPDecBuffer)(unsafe.Pointer(src_buf)).height + 1) / 2)) + if WebPIsAlphaMode(tls, (*WebPDecBuffer)(unsafe.Pointer(src_buf)).colorspace) != 0 { + WebPCopyPlane(tls, (*WebPYUVABuffer)(unsafe.Pointer(src)).a, (*WebPYUVABuffer)(unsafe.Pointer(src)).a_stride, (*WebPYUVABuffer)(unsafe.Pointer(dst)).a, (*WebPYUVABuffer)(unsafe.Pointer(dst)).a_stride, + (*WebPDecBuffer)(unsafe.Pointer(src_buf)).width, (*WebPDecBuffer)(unsafe.Pointer(src_buf)).height) + } + } + return VP8_STATUS_OK +} + +func WebPAvoidSlowMemory(tls *libc.TLS, output uintptr, features uintptr) int32 { /* buffer_dec.c:302:5: */ + + return (libc.Bool32((((*WebPDecBuffer)(unsafe.Pointer(output)).is_external_memory >= 2) && (WebPIsPremultipliedMode(tls, (*WebPDecBuffer)(unsafe.Pointer(output)).colorspace) != 0)) && ((features != (uintptr(0))) && ((*WebPBitstreamFeatures)(unsafe.Pointer(features)).has_alpha != 0)))) +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Main reconstruction function. + +var kScan = [16]uint16_t{ + (uint16_t(0 + (0 * 32))), (uint16_t(4 + (0 * 32))), (uint16_t(8 + (0 * 32))), (uint16_t(12 + (0 * 32))), + (uint16_t(0 + (4 * 32))), (uint16_t(4 + (4 * 32))), (uint16_t(8 + (4 * 32))), (uint16_t(12 + (4 * 32))), + (uint16_t(0 + (8 * 32))), (uint16_t(4 + (8 * 32))), (uint16_t(8 + (8 * 32))), (uint16_t(12 + (8 * 32))), + (uint16_t(0 + (12 * 32))), (uint16_t(4 + (12 * 32))), (uint16_t(8 + (12 * 32))), (uint16_t(12 + (12 * 32))), +} /* frame_dec.c:21:23 */ + +func CheckMode(tls *libc.TLS, mb_x int32, mb_y int32, mode int32) int32 { /* frame_dec.c:28:12: */ + if mode == B_DC_PRED { + if mb_x == 0 { + if mb_y == 0 { + return B_DC_PRED_NOTOPLEFT + } + return B_DC_PRED_NOLEFT + } else { + if mb_y == 0 { + return B_DC_PRED_NOTOP + } + return B_DC_PRED + } + } + return mode +} + +func Copy32b(tls *libc.TLS, dst uintptr, src uintptr) { /* frame_dec.c:39:13: */ + libc.Xmemcpy(tls, dst, src, uint64(4)) +} + +func DoTransform(tls *libc.TLS, bits uint32_t, src uintptr, dst uintptr) { /* frame_dec.c:43:25: */ + switch bits >> 30 { + case uint32_t(3): + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8Transform})).f(tls, src, dst, 0) + break + case uint32_t(2): + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8TransformAC3})).f(tls, src, dst) + break + case uint32_t(1): + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8TransformDC})).f(tls, src, dst) + break + default: + break + } +} + +func DoUVTransform(tls *libc.TLS, bits uint32_t, src uintptr, dst uintptr) { /* frame_dec.c:60:13: */ + if (bits & uint32_t(0xff)) != 0 { // any non-zero coeff at all? + if (bits & uint32_t(0xaa)) != 0 { // any non-zero AC coefficient? + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8TransformUV})).f(tls, src, dst) // note we don't use the AC3 variant for U/V + } else { + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8TransformDCUV})).f(tls, src, dst) + } + } +} + +func ReconstructRow(tls *libc.TLS, dec uintptr, ctx uintptr) { /* frame_dec.c:71:13: */ + var j int32 + var mb_x int32 + var mb_y int32 = (*VP8ThreadContext)(unsafe.Pointer(ctx)).mb_y_ + var cache_id int32 = (*VP8ThreadContext)(unsafe.Pointer(ctx)).id_ + var y_dst uintptr = ((*VP8Decoder)(unsafe.Pointer(dec)).yuv_b_ + uintptr(((32 * 1) + 8))) + var u_dst uintptr = ((*VP8Decoder)(unsafe.Pointer(dec)).yuv_b_ + uintptr(((((32 * 1) + 8) + (32 * 16)) + 32))) + var v_dst uintptr = ((*VP8Decoder)(unsafe.Pointer(dec)).yuv_b_ + uintptr((((((32 * 1) + 8) + (32 * 16)) + 32) + 16))) + + // Initialize left-most block. + for j = 0; j < 16; j++ { + *(*uint8_t)(unsafe.Pointer(y_dst + uintptr(((j * 32) - 1)))) = uint8_t(129) + } + for j = 0; j < 8; j++ { + *(*uint8_t)(unsafe.Pointer(u_dst + uintptr(((j * 32) - 1)))) = uint8_t(129) + *(*uint8_t)(unsafe.Pointer(v_dst + uintptr(((j * 32) - 1)))) = uint8_t(129) + } + + // Init top-left sample on left column too. + if mb_y > 0 { + *(*uint8_t)(unsafe.Pointer(y_dst + libc.UintptrFromInt32((-1 - 32)))) = libc.AssignPtrUint8((u_dst + libc.UintptrFromInt32((-1 - 32))), libc.AssignPtrUint8((v_dst+libc.UintptrFromInt32((-1-32))), uint8_t(129))) + } else { + // we only need to do this init once at block (0,0). + // Afterward, it remains valid for the whole topmost row. + libc.Xmemset(tls, ((y_dst - uintptr(32)) - uintptr(1)), 127, (uint64((16 + 4) + 1))) + libc.Xmemset(tls, ((u_dst - uintptr(32)) - uintptr(1)), 127, (uint64(8 + 1))) + libc.Xmemset(tls, ((v_dst - uintptr(32)) - uintptr(1)), 127, (uint64(8 + 1))) + } + + // Reconstruct one row. + for mb_x = 0; mb_x < (*VP8Decoder)(unsafe.Pointer(dec)).mb_w_; mb_x++ { + var block uintptr = ((*VP8ThreadContext)(unsafe.Pointer(ctx)).mb_data_ + uintptr(mb_x)*800) + + // Rotate in the left samples from previously decoded block. We move four + // pixels at a time for alignment reason, and because of in-loop filter. + if mb_x > 0 { + for j = -1; j < 16; j++ { + Copy32b(tls, (y_dst + uintptr(((j * 32) - 4))), (y_dst + uintptr(((j * 32) + 12)))) + } + for j = -1; j < 8; j++ { + Copy32b(tls, (u_dst + uintptr(((j * 32) - 4))), (u_dst + uintptr(((j * 32) + 4)))) + Copy32b(tls, (v_dst + uintptr(((j * 32) - 4))), (v_dst + uintptr(((j * 32) + 4)))) + } + } + { + // bring top samples into the cache + var top_yuv uintptr = ((*VP8Decoder)(unsafe.Pointer(dec)).yuv_t_ + uintptr(mb_x)*32) + var coeffs uintptr = block /* &.coeffs_ */ + var bits uint32_t = (*VP8MBData)(unsafe.Pointer(block)).non_zero_y_ + var n int32 + + if mb_y > 0 { + libc.Xmemcpy(tls, (y_dst - uintptr(32)), (top_yuv) /* &.y */, uint64(16)) + libc.Xmemcpy(tls, (u_dst - uintptr(32)), ((top_yuv) + 16 /* &.u */), uint64(8)) + libc.Xmemcpy(tls, (v_dst - uintptr(32)), ((top_yuv) + 24 /* &.v */), uint64(8)) + } + + // predict and add residuals + if (*VP8MBData)(unsafe.Pointer(block)).is_i4x4_ != 0 { // 4x4 + var top_right uintptr = ((y_dst - uintptr(32)) + uintptr(16)) + + if mb_y > 0 { + if mb_x >= ((*VP8Decoder)(unsafe.Pointer(dec)).mb_w_ - 1) { // on rightmost border + libc.Xmemset(tls, top_right, int32(*(*uint8_t)(unsafe.Pointer((top_yuv) /* &.y */ + 15))), uint64(unsafe.Sizeof(uint32_t(0)))) + } else { + libc.Xmemcpy(tls, top_right, (top_yuv + 1*32) /* &.y */, uint64(unsafe.Sizeof(uint32_t(0)))) + } + } + // replicate the top-right pixels below + *(*uint32_t)(unsafe.Pointer(top_right + 32*4)) = libc.AssignPtrUint32((top_right + 64*4), libc.AssignPtrUint32((top_right+96*4), *(*uint32_t)(unsafe.Pointer(top_right)))) + + // predict and add residuals for all 4x4 blocks in turn. + n = 0 + __1: + if !(n < 16) { + goto __3 + } + { + var dst uintptr = (y_dst + uintptr(kScan[n])) + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{VP8PredLuma4[*(*uint8_t)(unsafe.Pointer((block + 769 /* &.imodes_ */) + uintptr(n)))]})).f(tls, dst) + DoTransform(tls, bits, (coeffs + uintptr((n*16))*2), dst) + + } + goto __2 + __2: + n++ + bits <<= 2 + goto __1 + goto __3 + __3: + } else { // 16x16 + var pred_func int32 = CheckMode(tls, mb_x, mb_y, int32(*(*uint8_t)(unsafe.Pointer((block + 769 /* &.imodes_ */))))) + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{VP8PredLuma16[pred_func]})).f(tls, y_dst) + if bits != uint32_t(0) { + n = 0 + __4: + if !(n < 16) { + goto __6 + } + { + DoTransform(tls, bits, (coeffs + uintptr((n*16))*2), (y_dst + uintptr(kScan[n]))) + + } + goto __5 + __5: + n++ + bits <<= 2 + goto __4 + goto __6 + __6: + } + } + { + // Chroma + var bits_uv uint32_t = (*VP8MBData)(unsafe.Pointer(block)).non_zero_uv_ + var pred_func int32 = CheckMode(tls, mb_x, mb_y, int32((*VP8MBData)(unsafe.Pointer(block)).uvmode_)) + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{VP8PredChroma8[pred_func]})).f(tls, u_dst) + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{VP8PredChroma8[pred_func]})).f(tls, v_dst) + DoUVTransform(tls, (bits_uv >> 0), (coeffs + uintptr((16*16))*2), u_dst) + DoUVTransform(tls, (bits_uv >> 8), (coeffs + uintptr((20*16))*2), v_dst) + + } + + // stash away top samples for next block + if mb_y < ((*VP8Decoder)(unsafe.Pointer(dec)).mb_h_ - 1) { + libc.Xmemcpy(tls, (top_yuv) /* &.y */, (y_dst + uintptr((15 * 32))), uint64(16)) + libc.Xmemcpy(tls, ((top_yuv) + 16 /* &.u */), (u_dst + uintptr((7 * 32))), uint64(8)) + libc.Xmemcpy(tls, ((top_yuv) + 24 /* &.v */), (v_dst + uintptr((7 * 32))), uint64(8)) + } + + } + // Transfer reconstructed samples from yuv_b_ cache to final destination. + { + var y_offset int32 = ((cache_id * 16) * (*VP8Decoder)(unsafe.Pointer(dec)).cache_y_stride_) + var uv_offset int32 = ((cache_id * 8) * (*VP8Decoder)(unsafe.Pointer(dec)).cache_uv_stride_) + var y_out uintptr = (((*VP8Decoder)(unsafe.Pointer(dec)).cache_y_ + uintptr((mb_x * 16))) + uintptr(y_offset)) + var u_out uintptr = (((*VP8Decoder)(unsafe.Pointer(dec)).cache_u_ + uintptr((mb_x * 8))) + uintptr(uv_offset)) + var v_out uintptr = (((*VP8Decoder)(unsafe.Pointer(dec)).cache_v_ + uintptr((mb_x * 8))) + uintptr(uv_offset)) + for j = 0; j < 16; j++ { + libc.Xmemcpy(tls, (y_out + uintptr((j * (*VP8Decoder)(unsafe.Pointer(dec)).cache_y_stride_))), (y_dst + uintptr((j * 32))), uint64(16)) + } + for j = 0; j < 8; j++ { + libc.Xmemcpy(tls, (u_out + uintptr((j * (*VP8Decoder)(unsafe.Pointer(dec)).cache_uv_stride_))), (u_dst + uintptr((j * 32))), uint64(8)) + libc.Xmemcpy(tls, (v_out + uintptr((j * (*VP8Decoder)(unsafe.Pointer(dec)).cache_uv_stride_))), (v_dst + uintptr((j * 32))), uint64(8)) + } + + } + } +} + +//------------------------------------------------------------------------------ +// Filtering + +// kFilterExtraRows[] = How many extra lines are needed on the MB boundary +// for caching, given a filtering level. +// Simple filter: up to 2 luma samples are read and 1 is written. +// Complex filter: up to 4 luma samples are read and 3 are written. Same for +// U/V, so it's 8 samples total (because of the 2x upsampling). +var kFilterExtraRows = [3]uint8_t{uint8_t(0), uint8_t(2), uint8_t(8)} /* frame_dec.c:201:22 */ + +func DoFilter(tls *libc.TLS, dec uintptr, mb_x int32, mb_y int32) { /* frame_dec.c:203:13: */ + var ctx uintptr = (dec + 216 /* &.thread_ctx_ */) + var cache_id int32 = (*VP8ThreadContext)(unsafe.Pointer(ctx)).id_ + var y_bps int32 = (*VP8Decoder)(unsafe.Pointer(dec)).cache_y_stride_ + var f_info uintptr = ((*VP8ThreadContext)(unsafe.Pointer(ctx)).f_info_ + uintptr(mb_x)*4) + var y_dst uintptr = (((*VP8Decoder)(unsafe.Pointer(dec)).cache_y_ + uintptr(((cache_id * 16) * y_bps))) + uintptr((mb_x * 16))) + var ilevel int32 = int32((*VP8FInfo)(unsafe.Pointer(f_info)).f_ilevel_) + var limit int32 = int32((*VP8FInfo)(unsafe.Pointer(f_info)).f_limit_) + if limit == 0 { + return + } + + if (*VP8Decoder)(unsafe.Pointer(dec)).filter_type_ == 1 { // simple + if mb_x > 0 { + (*struct { + f func(*libc.TLS, uintptr, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8SimpleHFilter16})).f(tls, y_dst, y_bps, (limit + 4)) + } + if (*VP8FInfo)(unsafe.Pointer(f_info)).f_inner_ != 0 { + (*struct { + f func(*libc.TLS, uintptr, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8SimpleHFilter16i})).f(tls, y_dst, y_bps, limit) + } + if mb_y > 0 { + (*struct { + f func(*libc.TLS, uintptr, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8SimpleVFilter16})).f(tls, y_dst, y_bps, (limit + 4)) + } + if (*VP8FInfo)(unsafe.Pointer(f_info)).f_inner_ != 0 { + (*struct { + f func(*libc.TLS, uintptr, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8SimpleVFilter16i})).f(tls, y_dst, y_bps, limit) + } + } else { // complex + var uv_bps int32 = (*VP8Decoder)(unsafe.Pointer(dec)).cache_uv_stride_ + var u_dst uintptr = (((*VP8Decoder)(unsafe.Pointer(dec)).cache_u_ + uintptr(((cache_id * 8) * uv_bps))) + uintptr((mb_x * 8))) + var v_dst uintptr = (((*VP8Decoder)(unsafe.Pointer(dec)).cache_v_ + uintptr(((cache_id * 8) * uv_bps))) + uintptr((mb_x * 8))) + var hev_thresh int32 = int32((*VP8FInfo)(unsafe.Pointer(f_info)).hev_thresh_) + if mb_x > 0 { + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8HFilter16})).f(tls, y_dst, y_bps, (limit + 4), ilevel, hev_thresh) + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8HFilter8})).f(tls, u_dst, v_dst, uv_bps, (limit + 4), ilevel, hev_thresh) + } + if (*VP8FInfo)(unsafe.Pointer(f_info)).f_inner_ != 0 { + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8HFilter16i})).f(tls, y_dst, y_bps, limit, ilevel, hev_thresh) + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8HFilter8i})).f(tls, u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh) + } + if mb_y > 0 { + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8VFilter16})).f(tls, y_dst, y_bps, (limit + 4), ilevel, hev_thresh) + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8VFilter8})).f(tls, u_dst, v_dst, uv_bps, (limit + 4), ilevel, hev_thresh) + } + if (*VP8FInfo)(unsafe.Pointer(f_info)).f_inner_ != 0 { + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8VFilter16i})).f(tls, y_dst, y_bps, limit, ilevel, hev_thresh) + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8VFilter8i})).f(tls, u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh) + } + } +} + +// Filter the decoded macroblock row (if needed) +func FilterRow(tls *libc.TLS, dec uintptr) { /* frame_dec.c:253:13: */ + var mb_x int32 + var mb_y int32 = (*VP8Decoder)(unsafe.Pointer(dec)).thread_ctx_.mb_y_ + + for mb_x = (*VP8Decoder)(unsafe.Pointer(dec)).tl_mb_x_; mb_x < (*VP8Decoder)(unsafe.Pointer(dec)).br_mb_x_; mb_x++ { + DoFilter(tls, dec, mb_x, mb_y) + } +} + +//------------------------------------------------------------------------------ +// Precompute the filtering strength for each segment and each i4x4/i16x16 mode. + +func PrecomputeFilterStrengths(tls *libc.TLS, dec uintptr) { /* frame_dec.c:265:13: */ + if (*VP8Decoder)(unsafe.Pointer(dec)).filter_type_ > 0 { + var s int32 + var hdr uintptr = (dec + 80 /* &.filter_hdr_ */) + for s = 0; s < NUM_MB_SEGMENTS; s++ { + var i4x4 int32 + // First, compute the initial level + var base_level int32 + if (*VP8Decoder)(unsafe.Pointer(dec)).segment_hdr_.use_segment_ != 0 { + base_level = int32(*(*int8_t)(unsafe.Pointer(((dec + 128 /* &.segment_hdr_ */) + 16 /* &.filter_strength_ */) + uintptr(s)))) + if !((*VP8Decoder)(unsafe.Pointer(dec)).segment_hdr_.absolute_delta_ != 0) { + base_level = base_level + ((*VP8FilterHeader)(unsafe.Pointer(hdr)).level_) + } + } else { + base_level = (*VP8FilterHeader)(unsafe.Pointer(hdr)).level_ + } + for i4x4 = 0; i4x4 <= 1; i4x4++ { + var info uintptr = (((dec + 2924 /* &.fstrengths_ */) + uintptr(s)*8) + uintptr(i4x4)*4) + var level int32 = base_level + if (*VP8FilterHeader)(unsafe.Pointer(hdr)).use_lf_delta_ != 0 { + level = level + (*(*int32)(unsafe.Pointer((hdr + 16 /* &.ref_lf_delta_ */)))) + if i4x4 != 0 { + level = level + (*(*int32)(unsafe.Pointer((hdr + 32 /* &.mode_lf_delta_ */)))) + } + } + if level < 0 { + level = 0 + } else { + if level > 63 { + level = 63 + } else { + level = level + } + } + if level > 0 { + var ilevel int32 = level + if (*VP8FilterHeader)(unsafe.Pointer(hdr)).sharpness_ > 0 { + if (*VP8FilterHeader)(unsafe.Pointer(hdr)).sharpness_ > 4 { + ilevel >>= 2 + } else { + ilevel >>= 1 + } + if ilevel > (9 - (*VP8FilterHeader)(unsafe.Pointer(hdr)).sharpness_) { + ilevel = (9 - (*VP8FilterHeader)(unsafe.Pointer(hdr)).sharpness_) + } + } + if ilevel < 1 { + ilevel = 1 + } + (*VP8FInfo)(unsafe.Pointer(info)).f_ilevel_ = uint8_t(ilevel) + (*VP8FInfo)(unsafe.Pointer(info)).f_limit_ = (uint8_t((2 * level) + ilevel)) + (*VP8FInfo)(unsafe.Pointer(info)).hev_thresh_ = func() uint8 { + if level >= 40 { + return uint8(2) + } + return func() uint8 { + if level >= 15 { + return uint8(1) + } + return uint8(0) + }() + }() + } else { + (*VP8FInfo)(unsafe.Pointer(info)).f_limit_ = uint8_t(0) // no filtering + } + (*VP8FInfo)(unsafe.Pointer(info)).f_inner_ = uint8_t(i4x4) + } + } + } +} + +//------------------------------------------------------------------------------ +// Dithering + +// minimal amp that will provide a non-zero dithering effect + +var kQuantToDitherAmp = [12]uint8_t{ + // roughly, it's dqm->uv_mat_[1] + uint8_t(8), uint8_t(7), uint8_t(6), uint8_t(4), uint8_t(4), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), +} /* frame_dec.c:323:22 */ + +func VP8InitDithering(tls *libc.TLS, options uintptr, dec uintptr) { /* frame_dec.c:328:6: */ + + if options != (uintptr(0)) { + var d int32 = (*WebPDecoderOptions)(unsafe.Pointer(options)).dithering_strength + var max_amp int32 = ((int32(1) << 8) - 1) + var f int32 + if d < 0 { + f = 0 + } else { + if d > 100 { + f = max_amp + } else { + f = ((d * max_amp) / 100) + } + } + if f > 0 { + var s int32 + var all_amp int32 = 0 + for s = 0; s < NUM_MB_SEGMENTS; s++ { + var dqm uintptr = ((dec + 1060 /* &.dqm_ */) + uintptr(s)*32) + if (*VP8QuantMatrix)(unsafe.Pointer(dqm)).uv_quant_ < 12 { + var idx int32 + if (*VP8QuantMatrix)(unsafe.Pointer(dqm)).uv_quant_ < 0 { + idx = 0 + } else { + idx = (*VP8QuantMatrix)(unsafe.Pointer(dqm)).uv_quant_ + } + (*VP8QuantMatrix)(unsafe.Pointer(dqm)).dither_ = ((f * int32(kQuantToDitherAmp[idx])) >> 3) + } + all_amp = all_amp | ((*VP8QuantMatrix)(unsafe.Pointer(dqm)).dither_) + } + if all_amp != 0 { + VP8InitRandom(tls, (dec + 828 /* &.dithering_rg_ */), 1.0) + (*VP8Decoder)(unsafe.Pointer(dec)).dither_ = 1 + } + } + // potentially allow alpha dithering + (*VP8Decoder)(unsafe.Pointer(dec)).alpha_dithering_ = (*WebPDecoderOptions)(unsafe.Pointer(options)).alpha_dithering_strength + if (*VP8Decoder)(unsafe.Pointer(dec)).alpha_dithering_ > 100 { + (*VP8Decoder)(unsafe.Pointer(dec)).alpha_dithering_ = 100 + } else if (*VP8Decoder)(unsafe.Pointer(dec)).alpha_dithering_ < 0 { + (*VP8Decoder)(unsafe.Pointer(dec)).alpha_dithering_ = 0 + } + } +} + +// Convert to range: [-2,2] for dither=50, [-4,4] for dither=100 +func Dither8x8(tls *libc.TLS, rg uintptr, dst uintptr, bps int32, amp int32) { /* frame_dec.c:362:13: */ + bp := tls.Alloc(64) + defer tls.Free(64) + + // var dither [64]uint8_t at bp, 64 + + var i int32 + for i = 0; i < (8 * 8); i++ { + *(*uint8_t)(unsafe.Pointer((bp) /* &dither[0] */ + uintptr(i))) = uint8_t(VP8RandomBits2(tls, rg, (7 + 1), amp)) + } + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8DitherCombine8x8})).f(tls, (bp) /* &dither[0] */, dst, bps) +} + +func DitherRow(tls *libc.TLS, dec uintptr) { /* frame_dec.c:371:13: */ + var mb_x int32 + + for mb_x = (*VP8Decoder)(unsafe.Pointer(dec)).tl_mb_x_; mb_x < (*VP8Decoder)(unsafe.Pointer(dec)).br_mb_x_; mb_x++ { + var ctx uintptr = (dec + 216 /* &.thread_ctx_ */) + var data uintptr = ((*VP8ThreadContext)(unsafe.Pointer(ctx)).mb_data_ + uintptr(mb_x)*800) + var cache_id int32 = (*VP8ThreadContext)(unsafe.Pointer(ctx)).id_ + var uv_bps int32 = (*VP8Decoder)(unsafe.Pointer(dec)).cache_uv_stride_ + if int32((*VP8MBData)(unsafe.Pointer(data)).dither_) >= 4 { + var u_dst uintptr = (((*VP8Decoder)(unsafe.Pointer(dec)).cache_u_ + uintptr(((cache_id * 8) * uv_bps))) + uintptr((mb_x * 8))) + var v_dst uintptr = (((*VP8Decoder)(unsafe.Pointer(dec)).cache_v_ + uintptr(((cache_id * 8) * uv_bps))) + uintptr((mb_x * 8))) + Dither8x8(tls, (dec + 828 /* &.dithering_rg_ */), u_dst, uv_bps, int32((*VP8MBData)(unsafe.Pointer(data)).dither_)) + Dither8x8(tls, (dec + 828 /* &.dithering_rg_ */), v_dst, uv_bps, int32((*VP8MBData)(unsafe.Pointer(data)).dither_)) + } + } +} + +//------------------------------------------------------------------------------ +// This function is called after a row of macroblocks is finished decoding. +// It also takes into account the following restrictions: +// * In case of in-loop filtering, we must hold off sending some of the bottom +// pixels as they are yet unfiltered. They will be when the next macroblock +// row is decoded. Meanwhile, we must preserve them by rotating them in the +// cache area. This doesn't hold for the very bottom row of the uncropped +// picture of course. +// * we must clip the remaining pixels against the cropping area. The VP8Io +// struct must have the following fields set correctly before calling put(): + +// Finalize and transmit a complete row. Return false in case of user-abort. +func FinishRow(tls *libc.TLS, arg1 uintptr, arg2 uintptr) int32 { /* frame_dec.c:402:12: */ + var dec uintptr = arg1 + var io uintptr = arg2 + var ok int32 = 1 + var ctx uintptr = (dec + 216 /* &.thread_ctx_ */) + var cache_id int32 = (*VP8ThreadContext)(unsafe.Pointer(ctx)).id_ + var extra_y_rows int32 = int32(kFilterExtraRows[(*VP8Decoder)(unsafe.Pointer(dec)).filter_type_]) + var ysize int32 = (extra_y_rows * (*VP8Decoder)(unsafe.Pointer(dec)).cache_y_stride_) + var uvsize int32 = ((extra_y_rows / 2) * (*VP8Decoder)(unsafe.Pointer(dec)).cache_uv_stride_) + var y_offset int32 = ((cache_id * 16) * (*VP8Decoder)(unsafe.Pointer(dec)).cache_y_stride_) + var uv_offset int32 = ((cache_id * 8) * (*VP8Decoder)(unsafe.Pointer(dec)).cache_uv_stride_) + var ydst uintptr = (((*VP8Decoder)(unsafe.Pointer(dec)).cache_y_ - uintptr(ysize)) + uintptr(y_offset)) + var udst uintptr = (((*VP8Decoder)(unsafe.Pointer(dec)).cache_u_ - uintptr(uvsize)) + uintptr(uv_offset)) + var vdst uintptr = (((*VP8Decoder)(unsafe.Pointer(dec)).cache_v_ - uintptr(uvsize)) + uintptr(uv_offset)) + var mb_y int32 = (*VP8ThreadContext)(unsafe.Pointer(ctx)).mb_y_ + var is_first_row int32 = (libc.Bool32(mb_y == 0)) + var is_last_row int32 = (libc.Bool32(mb_y >= ((*VP8Decoder)(unsafe.Pointer(dec)).br_mb_y_ - 1))) + + if (*VP8Decoder)(unsafe.Pointer(dec)).mt_method_ == 2 { + ReconstructRow(tls, dec, ctx) + } + + if (*VP8ThreadContext)(unsafe.Pointer(ctx)).filter_row_ != 0 { + FilterRow(tls, dec) + } + + if (*VP8Decoder)(unsafe.Pointer(dec)).dither_ != 0 { + DitherRow(tls, dec) + } + + if (*VP8Io)(unsafe.Pointer(io)).put != (uintptr(0)) { + var y_start int32 = ((mb_y) * 16) + var y_end int32 = ((mb_y + 1) * 16) + if !(is_first_row != 0) { + y_start = y_start - (extra_y_rows) + (*VP8Io)(unsafe.Pointer(io)).y = ydst + (*VP8Io)(unsafe.Pointer(io)).u = udst + (*VP8Io)(unsafe.Pointer(io)).v = vdst + } else { + (*VP8Io)(unsafe.Pointer(io)).y = ((*VP8Decoder)(unsafe.Pointer(dec)).cache_y_ + uintptr(y_offset)) + (*VP8Io)(unsafe.Pointer(io)).u = ((*VP8Decoder)(unsafe.Pointer(dec)).cache_u_ + uintptr(uv_offset)) + (*VP8Io)(unsafe.Pointer(io)).v = ((*VP8Decoder)(unsafe.Pointer(dec)).cache_v_ + uintptr(uv_offset)) + } + + if !(is_last_row != 0) { + y_end = y_end - (extra_y_rows) + } + if y_end > (*VP8Io)(unsafe.Pointer(io)).crop_bottom { + y_end = (*VP8Io)(unsafe.Pointer(io)).crop_bottom // make sure we don't overflow on last row. + } + // If dec->alpha_data_ is not NULL, we have some alpha plane present. + (*VP8Io)(unsafe.Pointer(io)).a = (uintptr(0)) + if ((*VP8Decoder)(unsafe.Pointer(dec)).alpha_data_ != (uintptr(0))) && (y_start < y_end) { + (*VP8Io)(unsafe.Pointer(io)).a = VP8DecompressAlphaRows(tls, dec, io, y_start, (y_end - y_start)) + if (*VP8Io)(unsafe.Pointer(io)).a == (uintptr(0)) { + return VP8SetError(tls, dec, VP8_STATUS_BITSTREAM_ERROR, + (ts) /* "Could not decode..." */) + } + } + if y_start < (*VP8Io)(unsafe.Pointer(io)).crop_top { + var delta_y int32 = ((*VP8Io)(unsafe.Pointer(io)).crop_top - y_start) + y_start = (*VP8Io)(unsafe.Pointer(io)).crop_top + + *(*uintptr)(unsafe.Pointer((io + 24 /* &.y */))) += (uintptr((*VP8Decoder)(unsafe.Pointer(dec)).cache_y_stride_ * delta_y)) + *(*uintptr)(unsafe.Pointer((io + 32 /* &.u */))) += (uintptr((*VP8Decoder)(unsafe.Pointer(dec)).cache_uv_stride_ * (delta_y >> 1))) + *(*uintptr)(unsafe.Pointer((io + 40 /* &.v */))) += (uintptr((*VP8Decoder)(unsafe.Pointer(dec)).cache_uv_stride_ * (delta_y >> 1))) + if (*VP8Io)(unsafe.Pointer(io)).a != (uintptr(0)) { + *(*uintptr)(unsafe.Pointer((io + 152 /* &.a */))) += (uintptr((*VP8Io)(unsafe.Pointer(io)).width * delta_y)) + } + } + if y_start < y_end { + *(*uintptr)(unsafe.Pointer((io + 24 /* &.y */))) += (uintptr((*VP8Io)(unsafe.Pointer(io)).crop_left)) + *(*uintptr)(unsafe.Pointer((io + 32 /* &.u */))) += (uintptr((*VP8Io)(unsafe.Pointer(io)).crop_left >> 1)) + *(*uintptr)(unsafe.Pointer((io + 40 /* &.v */))) += (uintptr((*VP8Io)(unsafe.Pointer(io)).crop_left >> 1)) + if (*VP8Io)(unsafe.Pointer(io)).a != (uintptr(0)) { + *(*uintptr)(unsafe.Pointer((io + 152 /* &.a */))) += (uintptr((*VP8Io)(unsafe.Pointer(io)).crop_left)) + } + (*VP8Io)(unsafe.Pointer(io)).mb_y = (y_start - (*VP8Io)(unsafe.Pointer(io)).crop_top) + (*VP8Io)(unsafe.Pointer(io)).mb_w = ((*VP8Io)(unsafe.Pointer(io)).crop_right - (*VP8Io)(unsafe.Pointer(io)).crop_left) + (*VP8Io)(unsafe.Pointer(io)).mb_h = (y_end - y_start) + ok = (*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*VP8Io)(unsafe.Pointer(io)).put})).f(tls, io) + } + } + // rotate top samples if needed + if (cache_id + 1) == (*VP8Decoder)(unsafe.Pointer(dec)).num_caches_ { + if !(is_last_row != 0) { + libc.Xmemcpy(tls, ((*VP8Decoder)(unsafe.Pointer(dec)).cache_y_ - uintptr(ysize)), (ydst + uintptr((16 * (*VP8Decoder)(unsafe.Pointer(dec)).cache_y_stride_))), uint64(ysize)) + libc.Xmemcpy(tls, ((*VP8Decoder)(unsafe.Pointer(dec)).cache_u_ - uintptr(uvsize)), (udst + uintptr((8 * (*VP8Decoder)(unsafe.Pointer(dec)).cache_uv_stride_))), uint64(uvsize)) + libc.Xmemcpy(tls, ((*VP8Decoder)(unsafe.Pointer(dec)).cache_v_ - uintptr(uvsize)), (vdst + uintptr((8 * (*VP8Decoder)(unsafe.Pointer(dec)).cache_uv_stride_))), uint64(uvsize)) + } + } + + return ok +} + +//------------------------------------------------------------------------------ + +func VP8ProcessRow(tls *libc.TLS, dec uintptr, io uintptr) int32 { /* frame_dec.c:501:5: */ + var ok int32 = 1 + var ctx uintptr = (dec + 216 /* &.thread_ctx_ */) + var filter_row int32 = (libc.Bool32((((*VP8Decoder)(unsafe.Pointer(dec)).filter_type_ > 0) && ((*VP8Decoder)(unsafe.Pointer(dec)).mb_y_ >= (*VP8Decoder)(unsafe.Pointer(dec)).tl_mb_y_)) && ((*VP8Decoder)(unsafe.Pointer(dec)).mb_y_ <= (*VP8Decoder)(unsafe.Pointer(dec)).br_mb_y_))) + if (*VP8Decoder)(unsafe.Pointer(dec)).mt_method_ == 0 { + // ctx->id_ and ctx->f_info_ are already set + (*VP8ThreadContext)(unsafe.Pointer(ctx)).mb_y_ = (*VP8Decoder)(unsafe.Pointer(dec)).mb_y_ + (*VP8ThreadContext)(unsafe.Pointer(ctx)).filter_row_ = filter_row + ReconstructRow(tls, dec, ctx) + ok = FinishRow(tls, dec, io) + } else { + var worker uintptr = (dec + 152 /* &.worker_ */) + // Finish previous job *before* updating context + ok = ok & ((*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(WebPGetWorkerInterface(tls))).Sync})).f(tls, worker)) + + if ok != 0 { // spawn a new deblocking/output job + (*VP8ThreadContext)(unsafe.Pointer(ctx)).io_ = *(*VP8Io)(unsafe.Pointer(io)) + (*VP8ThreadContext)(unsafe.Pointer(ctx)).id_ = (*VP8Decoder)(unsafe.Pointer(dec)).cache_id_ + (*VP8ThreadContext)(unsafe.Pointer(ctx)).mb_y_ = (*VP8Decoder)(unsafe.Pointer(dec)).mb_y_ + (*VP8ThreadContext)(unsafe.Pointer(ctx)).filter_row_ = filter_row + if (*VP8Decoder)(unsafe.Pointer(dec)).mt_method_ == 2 { // swap macroblock data + var tmp uintptr = (*VP8ThreadContext)(unsafe.Pointer(ctx)).mb_data_ + (*VP8ThreadContext)(unsafe.Pointer(ctx)).mb_data_ = (*VP8Decoder)(unsafe.Pointer(dec)).mb_data_ + (*VP8Decoder)(unsafe.Pointer(dec)).mb_data_ = tmp + } else { + // perform reconstruction directly in main thread + ReconstructRow(tls, dec, ctx) + } + if filter_row != 0 { // swap filter info + var tmp uintptr = (*VP8ThreadContext)(unsafe.Pointer(ctx)).f_info_ + (*VP8ThreadContext)(unsafe.Pointer(ctx)).f_info_ = (*VP8Decoder)(unsafe.Pointer(dec)).f_info_ + (*VP8Decoder)(unsafe.Pointer(dec)).f_info_ = tmp + } + // (reconstruct)+filter in parallel + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(WebPGetWorkerInterface(tls))).Launch})).f(tls, worker) + if libc.PreIncInt32(&(*VP8Decoder)(unsafe.Pointer(dec)).cache_id_, 1) == (*VP8Decoder)(unsafe.Pointer(dec)).num_caches_ { + (*VP8Decoder)(unsafe.Pointer(dec)).cache_id_ = 0 + } + } + } + return ok +} + +//------------------------------------------------------------------------------ +// Finish setting up the decoding parameter once user's setup() is called. + +func VP8EnterCritical(tls *libc.TLS, dec uintptr, io uintptr) VP8StatusCode { /* frame_dec.c:549:15: */ + // Call setup() first. This may trigger additional decoding features on 'io'. + // Note: Afterward, we must call teardown() no matter what. + if ((*VP8Io)(unsafe.Pointer(io)).setup != (uintptr(0))) && !((*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*VP8Io)(unsafe.Pointer(io)).setup})).f(tls, io) != 0) { + VP8SetError(tls, dec, VP8_STATUS_USER_ABORT, (ts + 29) /* "Frame setup fail..." */) + return (*VP8Decoder)(unsafe.Pointer(dec)).status_ + } + + // Disable filtering per user request + if (*VP8Io)(unsafe.Pointer(io)).bypass_filtering != 0 { + (*VP8Decoder)(unsafe.Pointer(dec)).filter_type_ = 0 + } + + // Define the area where we can skip in-loop filtering, in case of cropping. + // + // 'Simple' filter reads two luma samples outside of the macroblock + // and filters one. It doesn't filter the chroma samples. Hence, we can + // avoid doing the in-loop filtering before crop_top/crop_left position. + // For the 'Complex' filter, 3 samples are read and up to 3 are filtered. + // Means: there's a dependency chain that goes all the way up to the + // top-left corner of the picture (MB #0). We must filter all the previous + // macroblocks. + { + var extra_pixels int32 = int32(kFilterExtraRows[(*VP8Decoder)(unsafe.Pointer(dec)).filter_type_]) + if (*VP8Decoder)(unsafe.Pointer(dec)).filter_type_ == 2 { + // For complex filter, we need to preserve the dependency chain. + (*VP8Decoder)(unsafe.Pointer(dec)).tl_mb_x_ = 0 + (*VP8Decoder)(unsafe.Pointer(dec)).tl_mb_y_ = 0 + } else { + // For simple filter, we can filter only the cropped region. + // We include 'extra_pixels' on the other side of the boundary, since + // vertical or horizontal filtering of the previous macroblock can + // modify some abutting pixels. + (*VP8Decoder)(unsafe.Pointer(dec)).tl_mb_x_ = (((*VP8Io)(unsafe.Pointer(io)).crop_left - extra_pixels) >> 4) + (*VP8Decoder)(unsafe.Pointer(dec)).tl_mb_y_ = (((*VP8Io)(unsafe.Pointer(io)).crop_top - extra_pixels) >> 4) + if (*VP8Decoder)(unsafe.Pointer(dec)).tl_mb_x_ < 0 { + (*VP8Decoder)(unsafe.Pointer(dec)).tl_mb_x_ = 0 + } + if (*VP8Decoder)(unsafe.Pointer(dec)).tl_mb_y_ < 0 { + (*VP8Decoder)(unsafe.Pointer(dec)).tl_mb_y_ = 0 + } + } + // We need some 'extra' pixels on the right/bottom. + (*VP8Decoder)(unsafe.Pointer(dec)).br_mb_y_ = ((((*VP8Io)(unsafe.Pointer(io)).crop_bottom + 15) + extra_pixels) >> 4) + (*VP8Decoder)(unsafe.Pointer(dec)).br_mb_x_ = ((((*VP8Io)(unsafe.Pointer(io)).crop_right + 15) + extra_pixels) >> 4) + if (*VP8Decoder)(unsafe.Pointer(dec)).br_mb_x_ > (*VP8Decoder)(unsafe.Pointer(dec)).mb_w_ { + (*VP8Decoder)(unsafe.Pointer(dec)).br_mb_x_ = (*VP8Decoder)(unsafe.Pointer(dec)).mb_w_ + } + if (*VP8Decoder)(unsafe.Pointer(dec)).br_mb_y_ > (*VP8Decoder)(unsafe.Pointer(dec)).mb_h_ { + (*VP8Decoder)(unsafe.Pointer(dec)).br_mb_y_ = (*VP8Decoder)(unsafe.Pointer(dec)).mb_h_ + } + + } + PrecomputeFilterStrengths(tls, dec) + return VP8_STATUS_OK +} + +func VP8ExitCritical(tls *libc.TLS, dec uintptr, io uintptr) int32 { /* frame_dec.c:601:5: */ + var ok int32 = 1 + if (*VP8Decoder)(unsafe.Pointer(dec)).mt_method_ > 0 { + ok = (*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(WebPGetWorkerInterface(tls))).Sync})).f(tls, (dec + 152 /* &.worker_ */)) + } + + if (*VP8Io)(unsafe.Pointer(io)).teardown != (uintptr(0)) { + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*VP8Io)(unsafe.Pointer(io)).teardown})).f(tls, io) + } + return ok +} + +//------------------------------------------------------------------------------ +// For multi-threaded decoding we need to use 3 rows of 16 pixels as delay line. +// +// Reason is: the deblocking filter cannot deblock the bottom horizontal edges +// immediately, and needs to wait for first few rows of the next macroblock to +// be decoded. Hence, deblocking is lagging behind by 4 or 8 pixels (depending +// on strength). +// With two threads, the vertical positions of the rows being decoded are: +// Decode: [ 0..15][16..31][32..47][48..63][64..79][... +// Deblock: [ 0..11][12..27][28..43][44..59][... +// If we use two threads and two caches of 16 pixels, the sequence would be: +// Decode: [ 0..15][16..31][ 0..15!!][16..31][ 0..15][... +// Deblock: [ 0..11][12..27!!][-4..11][12..27][... +// The problem occurs during row [12..15!!] that both the decoding and +// deblocking threads are writing simultaneously. +// With 3 cache lines, one get a safe write pattern: +// Decode: [ 0..15][16..31][32..47][ 0..15][16..31][32..47][0.. +// Deblock: [ 0..11][12..27][28..43][-4..11][12..27][28... +// Note that multi-threaded output _without_ deblocking can make use of two +// cache lines of 16 pixels only, since there's no lagging behind. The decoding +// and output process have non-concurrent writing: +// Decode: [ 0..15][16..31][ 0..15][16..31][... +// io->put: [ 0..15][16..31][ 0..15][... + +// Initialize multi/single-thread worker +func InitThreadContext(tls *libc.TLS, dec uintptr) int32 { /* frame_dec.c:641:12: */ + (*VP8Decoder)(unsafe.Pointer(dec)).cache_id_ = 0 + if (*VP8Decoder)(unsafe.Pointer(dec)).mt_method_ > 0 { + var worker uintptr = (dec + 152 /* &.worker_ */) + if !((*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(WebPGetWorkerInterface(tls))).Reset})).f(tls, worker) != 0) { + return VP8SetError(tls, dec, VP8_STATUS_OUT_OF_MEMORY, + (ts + 48) /* "thread initializ..." */) + } + (*WebPWorker)(unsafe.Pointer(worker)).data1 = dec + (*WebPWorker)(unsafe.Pointer(worker)).data2 = ((dec + 216 /* &.thread_ctx_ */) + 32 /* &.io_ */) + (*WebPWorker)(unsafe.Pointer(worker)).hook = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{FinishRow})) + (*VP8Decoder)(unsafe.Pointer(dec)).num_caches_ = func() int32 { + if (*VP8Decoder)(unsafe.Pointer(dec)).filter_type_ > 0 { + return 3 + } + return (3 - 1) + }() + } else { + (*VP8Decoder)(unsafe.Pointer(dec)).num_caches_ = 1 + } + return 1 +} + +func VP8GetThreadMethod(tls *libc.TLS, options uintptr, headers uintptr, width int32, height int32) int32 { /* frame_dec.c:660:5: */ + if (options == (uintptr(0))) || ((*WebPDecoderOptions)(unsafe.Pointer(options)).use_threads == 0) { + return 0 + } + _ = headers + _ = width + _ = height + + return 0 +} + +//------------------------------------------------------------------------------ +// Memory setup + +func AllocateMemory(tls *libc.TLS, dec uintptr) int32 { /* frame_dec.c:682:12: */ + var num_caches int32 = (*VP8Decoder)(unsafe.Pointer(dec)).num_caches_ + var mb_w int32 = (*VP8Decoder)(unsafe.Pointer(dec)).mb_w_ + // Note: we use 'size_t' when there's no overflow risk, uint64_t otherwise. + var intra_pred_mode_size size_t = ((uint64(4 * mb_w)) * uint64(unsafe.Sizeof(uint8_t(0)))) + var top_size size_t = (uint64(unsafe.Sizeof(VP8TopSamples{})) * uint64(mb_w)) + var mb_info_size size_t = ((uint64(mb_w + 1)) * uint64(unsafe.Sizeof(VP8MB{}))) + var f_info_size size_t + if (*VP8Decoder)(unsafe.Pointer(dec)).filter_type_ > 0 { + f_info_size = ((uint64(mb_w * (func() int32 { + if (*VP8Decoder)(unsafe.Pointer(dec)).mt_method_ > 0 { + return 2 + } + return 1 + }()))) * uint64(unsafe.Sizeof(VP8FInfo{}))) + } else { + f_info_size = uint64(0) + } + var yuv_size size_t = ((uint64((32 * 17) + (32 * 9))) * uint64(unsafe.Sizeof(uint8_t(0)))) + var mb_data_size size_t = ((uint64((func() int32 { + if (*VP8Decoder)(unsafe.Pointer(dec)).mt_method_ == 2 { + return 2 + } + return 1 + }()) * mb_w)) * uint64(unsafe.Sizeof(VP8MBData{}))) + var cache_height size_t = (size_t((((16 * num_caches) + + int32(kFilterExtraRows[(*VP8Decoder)(unsafe.Pointer(dec)).filter_type_])) * 3) / 2)) + var cache_size size_t = (top_size * cache_height) + // alpha_size is the only one that scales as width x height. + var alpha_size uint64_t + if (*VP8Decoder)(unsafe.Pointer(dec)).alpha_data_ != (uintptr(0)) { + alpha_size = (uint64_t((*VP8Decoder)(unsafe.Pointer(dec)).pic_hdr_.width_) * uint64_t((*VP8Decoder)(unsafe.Pointer(dec)).pic_hdr_.height_)) + } else { + alpha_size = 0 + } + var needed uint64_t = ((((((((intra_pred_mode_size + + top_size) + mb_info_size) + f_info_size) + + yuv_size) + mb_data_size) + + cache_size) + alpha_size) + uint64(31)) + var mem uintptr + + if !(CheckSizeOverflow(tls, needed) != 0) { + return 0 + } // check for overflow + if needed > (*VP8Decoder)(unsafe.Pointer(dec)).mem_size_ { + WebPSafeFree(tls, (*VP8Decoder)(unsafe.Pointer(dec)).mem_) + (*VP8Decoder)(unsafe.Pointer(dec)).mem_size_ = uint64(0) + (*VP8Decoder)(unsafe.Pointer(dec)).mem_ = WebPSafeMalloc(tls, needed, uint64(unsafe.Sizeof(uint8_t(0)))) + if (*VP8Decoder)(unsafe.Pointer(dec)).mem_ == (uintptr(0)) { + return VP8SetError(tls, dec, VP8_STATUS_OUT_OF_MEMORY, + (ts + 78) /* "no memory during..." */) + } + // down-cast is ok, thanks to WebPSafeMalloc() above. + (*VP8Decoder)(unsafe.Pointer(dec)).mem_size_ = needed + } + + mem = (*VP8Decoder)(unsafe.Pointer(dec)).mem_ + (*VP8Decoder)(unsafe.Pointer(dec)).intra_t_ = mem + mem += uintptr(intra_pred_mode_size) + + (*VP8Decoder)(unsafe.Pointer(dec)).yuv_t_ = mem + mem += uintptr(top_size) + + (*VP8Decoder)(unsafe.Pointer(dec)).mb_info_ = ((mem) + uintptr(1)*2) + mem += uintptr(mb_info_size) + + (*VP8Decoder)(unsafe.Pointer(dec)).f_info_ = func() uintptr { + if f_info_size != 0 { + return mem + } + return (uintptr(0)) + }() + mem += uintptr(f_info_size) + (*VP8Decoder)(unsafe.Pointer(dec)).thread_ctx_.id_ = 0 + (*VP8Decoder)(unsafe.Pointer(dec)).thread_ctx_.f_info_ = (*VP8Decoder)(unsafe.Pointer(dec)).f_info_ + if ((*VP8Decoder)(unsafe.Pointer(dec)).filter_type_ > 0) && ((*VP8Decoder)(unsafe.Pointer(dec)).mt_method_ > 0) { + // secondary cache line. The deblocking process need to make use of the + // filtering strength from previous macroblock row, while the new ones + // are being decoded in parallel. We'll just swap the pointers. + *(*uintptr)(unsafe.Pointer(((dec + 216 /* &.thread_ctx_ */) + 16 /* &.f_info_ */))) += (uintptr(mb_w)) * 4 + } + + mem = (uintptr((uintptr_t((mem)) + uint64(31)) & libc.Uint64FromInt32(libc.CplInt32(31)))) + + (*VP8Decoder)(unsafe.Pointer(dec)).yuv_b_ = mem + mem += uintptr(yuv_size) + + (*VP8Decoder)(unsafe.Pointer(dec)).mb_data_ = mem + (*VP8Decoder)(unsafe.Pointer(dec)).thread_ctx_.mb_data_ = mem + if (*VP8Decoder)(unsafe.Pointer(dec)).mt_method_ == 2 { + *(*uintptr)(unsafe.Pointer(((dec + 216 /* &.thread_ctx_ */) + 24 /* &.mb_data_ */))) += (uintptr(mb_w)) * 800 + } + mem += uintptr(mb_data_size) + + (*VP8Decoder)(unsafe.Pointer(dec)).cache_y_stride_ = (16 * mb_w) + (*VP8Decoder)(unsafe.Pointer(dec)).cache_uv_stride_ = (8 * mb_w) + { + var extra_rows int32 = int32(kFilterExtraRows[(*VP8Decoder)(unsafe.Pointer(dec)).filter_type_]) + var extra_y int32 = (extra_rows * (*VP8Decoder)(unsafe.Pointer(dec)).cache_y_stride_) + var extra_uv int32 = ((extra_rows / 2) * (*VP8Decoder)(unsafe.Pointer(dec)).cache_uv_stride_) + (*VP8Decoder)(unsafe.Pointer(dec)).cache_y_ = (mem + uintptr(extra_y)) + (*VP8Decoder)(unsafe.Pointer(dec)).cache_u_ = (((*VP8Decoder)(unsafe.Pointer(dec)).cache_y_ + + uintptr(((16 * num_caches) * (*VP8Decoder)(unsafe.Pointer(dec)).cache_y_stride_))) + uintptr(extra_uv)) + (*VP8Decoder)(unsafe.Pointer(dec)).cache_v_ = (((*VP8Decoder)(unsafe.Pointer(dec)).cache_u_ + + uintptr(((8 * num_caches) * (*VP8Decoder)(unsafe.Pointer(dec)).cache_uv_stride_))) + uintptr(extra_uv)) + (*VP8Decoder)(unsafe.Pointer(dec)).cache_id_ = 0 + + } + mem += uintptr(cache_size) + + // alpha plane + (*VP8Decoder)(unsafe.Pointer(dec)).alpha_plane_ = func() uintptr { + if alpha_size != 0 { + return mem + } + return (uintptr(0)) + }() + mem += uintptr(alpha_size) + + // note: left/top-info is initialized once for all. + libc.Xmemset(tls, ((*VP8Decoder)(unsafe.Pointer(dec)).mb_info_ - uintptr(1)*2), 0, mb_info_size) + VP8InitScanline(tls, dec) // initialize left too. + + // initialize top + libc.Xmemset(tls, (*VP8Decoder)(unsafe.Pointer(dec)).intra_t_, B_DC_PRED, intra_pred_mode_size) + + return 1 +} + +func InitIo(tls *libc.TLS, dec uintptr, io uintptr) { /* frame_dec.c:784:13: */ + // prepare 'io' + (*VP8Io)(unsafe.Pointer(io)).mb_y = 0 + (*VP8Io)(unsafe.Pointer(io)).y = (*VP8Decoder)(unsafe.Pointer(dec)).cache_y_ + (*VP8Io)(unsafe.Pointer(io)).u = (*VP8Decoder)(unsafe.Pointer(dec)).cache_u_ + (*VP8Io)(unsafe.Pointer(io)).v = (*VP8Decoder)(unsafe.Pointer(dec)).cache_v_ + (*VP8Io)(unsafe.Pointer(io)).y_stride = (*VP8Decoder)(unsafe.Pointer(dec)).cache_y_stride_ + (*VP8Io)(unsafe.Pointer(io)).uv_stride = (*VP8Decoder)(unsafe.Pointer(dec)).cache_uv_stride_ + (*VP8Io)(unsafe.Pointer(io)).a = (uintptr(0)) +} + +func VP8InitFrame(tls *libc.TLS, dec uintptr, io uintptr) int32 { /* frame_dec.c:795:5: */ + if !(InitThreadContext(tls, dec) != 0) { + return 0 + } // call first. Sets dec->num_caches_. + if !(AllocateMemory(tls, dec) != 0) { + return 0 + } + InitIo(tls, dec, io) + VP8DspInit(tls) // Init critical function pointers and look-up tables. + return 1 +} + +//------------------------------------------------------------------------------ + +type WebPIDecoder = WebPIDecoder1 /* decode.h:32:29 */ + +//------------------------------------------------------------------------------ + +// In append mode, buffer allocations increase as multiples of this value. +// Needs to be a power of 2. + +//------------------------------------------------------------------------------ +// Data structures for memory and states + +// Decoding states. State normally flows as: +// WEBP_HEADER->VP8_HEADER->VP8_PARTS0->VP8_DATA->DONE for a lossy image, and +// WEBP_HEADER->VP8L_HEADER->VP8L_DATA->DONE for a lossless image. +// If there is any error the decoder goes into state ERROR. +type DecState = uint32 /* idec_dec.c:44:3 */ + +// Operating state for the MemBuffer +type MemBufferMode = uint32 /* idec_dec.c:51:3 */ + +// storage for partition #0 and partial data (in a rolling fashion) +type MemBuffer = struct { + mode_ MemBufferMode + _ [4]byte + start_ size_t + end_ size_t + buf_size_ size_t + buf_ uintptr + part0_size_ size_t + part0_buf_ uintptr +} /* idec_dec.c:63:3 */ + +// MB context to restore in case VP8DecodeMB() fails +type MBContext = struct { + left_ VP8MB + info_ VP8MB + _ [4]byte + token_br_ VP8BitReader +} /* idec_dec.c:86:3 */ + +//------------------------------------------------------------------------------ +// MemBuffer: incoming data handling + +func MemDataSize(tls *libc.TLS, mem uintptr) size_t { /* idec_dec.c:91:27: */ + return ((*MemBuffer)(unsafe.Pointer(mem)).end_ - (*MemBuffer)(unsafe.Pointer(mem)).start_) +} + +// Check if we need to preserve the compressed alpha data, as it may not have +// been decoded yet. +func NeedCompressedAlpha(tls *libc.TLS, idec uintptr) int32 { /* idec_dec.c:97:12: */ + if (*WebPIDecoder)(unsafe.Pointer(idec)).state_ == STATE_WEBP_HEADER { + // We haven't parsed the headers yet, so we don't know whether the image is + // lossy or lossless. This also means that we haven't parsed the ALPH chunk. + return 0 + } + if (*WebPIDecoder)(unsafe.Pointer(idec)).is_lossless_ != 0 { + return 0 // ALPH chunk is not present for lossless images. + } else { + var dec uintptr = (*WebPIDecoder)(unsafe.Pointer(idec)).dec_ + // Must be true as idec->state_ != STATE_WEBP_HEADER. + return (libc.Bool32(((*VP8Decoder)(unsafe.Pointer(dec)).alpha_data_ != (uintptr(0))) && !((*VP8Decoder)(unsafe.Pointer(dec)).is_alpha_decoded_ != 0))) + } + return int32(0) +} + +func DoRemap(tls *libc.TLS, idec uintptr, offset ptrdiff_t) { /* idec_dec.c:112:13: */ + var mem uintptr = (idec + 296 /* &.mem_ */) + var new_base uintptr = ((*MemBuffer)(unsafe.Pointer(mem)).buf_ + uintptr((*MemBuffer)(unsafe.Pointer(mem)).start_)) + // note: for VP8, setting up idec->io_ is only really needed at the beginning + // of the decoding, till partition #0 is complete. + (*WebPIDecoder)(unsafe.Pointer(idec)).io_.data = new_base + (*WebPIDecoder)(unsafe.Pointer(idec)).io_.data_size = MemDataSize(tls, mem) + + if (*WebPIDecoder)(unsafe.Pointer(idec)).dec_ != (uintptr(0)) { + if !((*WebPIDecoder)(unsafe.Pointer(idec)).is_lossless_ != 0) { + var dec uintptr = (*WebPIDecoder)(unsafe.Pointer(idec)).dec_ + var last_part uint32_t = (*VP8Decoder)(unsafe.Pointer(dec)).num_parts_minus_one_ + if offset != int64(0) { + var p uint32_t + for p = uint32_t(0); p <= last_part; p++ { + VP8RemapBitReader(tls, ((dec + 440 /* &.parts_ */) + uintptr(p)*48), offset) + } + // Remap partition #0 data pointer to new offset, but only in MAP + // mode (in APPEND mode, partition #0 is copied into a fixed memory). + if (*MemBuffer)(unsafe.Pointer(mem)).mode_ == MEM_MODE_MAP { + VP8RemapBitReader(tls, (dec + 16 /* &.br_ */), offset) + } + } + { + var last_start uintptr = (*VP8BitReader)(unsafe.Pointer((dec + 440 /* &.parts_ */) + uintptr(last_part)*48)).buf_ + VP8BitReaderSetBuffer(tls, ((dec + 440 /* &.parts_ */) + uintptr(last_part)*48), last_start, + (uint64(((int64((*MemBuffer)(unsafe.Pointer(mem)).buf_ + uintptr((*MemBuffer)(unsafe.Pointer(mem)).end_))) - int64(last_start)) / 1))) + + } + if NeedCompressedAlpha(tls, idec) != 0 { + var alph_dec uintptr = (*VP8Decoder)(unsafe.Pointer(dec)).alph_dec_ + *(*uintptr)(unsafe.Pointer((dec + 2968 /* &.alpha_data_ */))) += (uintptr(offset)) + if (alph_dec != (uintptr(0))) && ((*ALPHDecoder)(unsafe.Pointer(alph_dec)).vp8l_dec_ != (uintptr(0))) { + if (*ALPHDecoder)(unsafe.Pointer(alph_dec)).method_ == 1 { + var alph_vp8l_dec uintptr = (*ALPHDecoder)(unsafe.Pointer(alph_dec)).vp8l_dec_ + + VP8LBitReaderSetBuffer(tls, (alph_vp8l_dec + 40 /* &.br_ */), + ((*VP8Decoder)(unsafe.Pointer(dec)).alpha_data_ + uintptr(1)), + ((*VP8Decoder)(unsafe.Pointer(dec)).alpha_data_size_ - uint64(1))) + } else { // alph_dec->method_ == ALPHA_NO_COMPRESSION + // Nothing special to do in this case. + } + } + } + } else { // Resize lossless bitreader + var dec uintptr = (*WebPIDecoder)(unsafe.Pointer(idec)).dec_ + VP8LBitReaderSetBuffer(tls, (dec + 40 /* &.br_ */), new_base, MemDataSize(tls, mem)) + } + } +} + +// Appends data to the end of MemBuffer->buf_. It expands the allocated memory +// size if required and also updates VP8BitReader's if new memory is allocated. +func AppendToMemBuffer(tls *libc.TLS, idec uintptr, data uintptr, data_size size_t) int32 { /* idec_dec.c:164:12: */ + var dec uintptr = (*WebPIDecoder)(unsafe.Pointer(idec)).dec_ + var mem uintptr = (idec + 296 /* &.mem_ */) + var need_compressed_alpha int32 = NeedCompressedAlpha(tls, idec) + var old_start uintptr + if (*MemBuffer)(unsafe.Pointer(mem)).buf_ == (uintptr(0)) { + old_start = (uintptr(0)) + } else { + old_start = ((*MemBuffer)(unsafe.Pointer(mem)).buf_ + uintptr((*MemBuffer)(unsafe.Pointer(mem)).start_)) + } + var old_base uintptr + if need_compressed_alpha != 0 { + old_base = (*VP8Decoder)(unsafe.Pointer(dec)).alpha_data_ + } else { + old_base = old_start + } + + if data_size > (uint64((libc.CplUint32(0) - uint32(8)) - uint32(1))) { + // security safeguard: trying to allocate more than what the format + // allows for a chunk should be considered a smoke smell. + return 0 + } + + if ((*MemBuffer)(unsafe.Pointer(mem)).end_ + data_size) > (*MemBuffer)(unsafe.Pointer(mem)).buf_size_ { // Need some free memory + var new_mem_start size_t = (size_t((int64(old_start) - int64(old_base)) / 1)) + var current_size size_t = (MemDataSize(tls, mem) + new_mem_start) + var new_size uint64_t = (current_size + data_size) + var extra_size uint64_t = (((new_size + uint64(4096)) - uint64(1)) & libc.Uint64FromInt32(libc.CplInt32((4096 - 1)))) + var new_buf uintptr = WebPSafeMalloc(tls, extra_size, uint64(unsafe.Sizeof(uint8_t(0)))) + if new_buf == (uintptr(0)) { + return 0 + } + if old_base != (uintptr(0)) { + libc.Xmemcpy(tls, new_buf, old_base, current_size) + } + WebPSafeFree(tls, (*MemBuffer)(unsafe.Pointer(mem)).buf_) + (*MemBuffer)(unsafe.Pointer(mem)).buf_ = new_buf + (*MemBuffer)(unsafe.Pointer(mem)).buf_size_ = extra_size + (*MemBuffer)(unsafe.Pointer(mem)).start_ = new_mem_start + (*MemBuffer)(unsafe.Pointer(mem)).end_ = current_size + } + + libc.Xmemcpy(tls, ((*MemBuffer)(unsafe.Pointer(mem)).buf_ + uintptr((*MemBuffer)(unsafe.Pointer(mem)).end_)), data, data_size) + *(*size_t)(unsafe.Pointer((mem + 16 /* &.end_ */))) += (data_size) + + DoRemap(tls, idec, (((int64((*MemBuffer)(unsafe.Pointer(mem)).buf_ + uintptr((*MemBuffer)(unsafe.Pointer(mem)).start_))) - int64(old_start)) / 1)) + return 1 +} + +func RemapMemBuffer(tls *libc.TLS, idec uintptr, data uintptr, data_size size_t) int32 { /* idec_dec.c:206:12: */ + var mem uintptr = (idec + 296 /* &.mem_ */) + var old_buf uintptr = (*MemBuffer)(unsafe.Pointer(mem)).buf_ + var old_start uintptr + if old_buf == (uintptr(0)) { + old_start = (uintptr(0)) + } else { + old_start = (old_buf + uintptr((*MemBuffer)(unsafe.Pointer(mem)).start_)) + } + + if data_size < (*MemBuffer)(unsafe.Pointer(mem)).buf_size_ { + return 0 + } // can't remap to a shorter buffer! + + (*MemBuffer)(unsafe.Pointer(mem)).buf_ = data + (*MemBuffer)(unsafe.Pointer(mem)).end_ = libc.AssignPtrUint64((mem + 24 /* &.buf_size_ */), data_size) + + DoRemap(tls, idec, (((int64((*MemBuffer)(unsafe.Pointer(mem)).buf_ + uintptr((*MemBuffer)(unsafe.Pointer(mem)).start_))) - int64(old_start)) / 1)) + return 1 +} + +func InitMemBuffer(tls *libc.TLS, mem uintptr) { /* idec_dec.c:224:13: */ + (*MemBuffer)(unsafe.Pointer(mem)).mode_ = MEM_MODE_NONE + (*MemBuffer)(unsafe.Pointer(mem)).buf_ = (uintptr(0)) + (*MemBuffer)(unsafe.Pointer(mem)).buf_size_ = uint64(0) + (*MemBuffer)(unsafe.Pointer(mem)).part0_buf_ = (uintptr(0)) + (*MemBuffer)(unsafe.Pointer(mem)).part0_size_ = uint64(0) +} + +func ClearMemBuffer(tls *libc.TLS, mem uintptr) { /* idec_dec.c:232:13: */ + + if (*MemBuffer)(unsafe.Pointer(mem)).mode_ == MEM_MODE_APPEND { + WebPSafeFree(tls, (*MemBuffer)(unsafe.Pointer(mem)).buf_) + WebPSafeFree(tls, (*MemBuffer)(unsafe.Pointer(mem)).part0_buf_) + } +} + +func CheckMemBufferMode(tls *libc.TLS, mem uintptr, expected MemBufferMode) int32 { /* idec_dec.c:240:12: */ + if (*MemBuffer)(unsafe.Pointer(mem)).mode_ == MEM_MODE_NONE { + (*MemBuffer)(unsafe.Pointer(mem)).mode_ = expected // switch to the expected mode + } else if (*MemBuffer)(unsafe.Pointer(mem)).mode_ != expected { + return 0 // we mixed the modes => error + } + // mode is ok + return 1 +} + +// To be called last. +func FinishDecoding(tls *libc.TLS, idec uintptr) VP8StatusCode { /* idec_dec.c:251:22: */ + var options uintptr = (*WebPIDecoder)(unsafe.Pointer(idec)).params_.options + var output uintptr = (*WebPIDecoder)(unsafe.Pointer(idec)).params_.output + + (*WebPIDecoder)(unsafe.Pointer(idec)).state_ = STATE_DONE + if (options != (uintptr(0))) && ((*WebPDecoderOptions)(unsafe.Pointer(options)).flip != 0) { + var status VP8StatusCode = WebPFlipBuffer(tls, output) + if status != VP8_STATUS_OK { + return status + } + } + if (*WebPIDecoder)(unsafe.Pointer(idec)).final_output_ != (uintptr(0)) { + WebPCopyDecBufferPixels(tls, output, (*WebPIDecoder)(unsafe.Pointer(idec)).final_output_) // do the slow-copy + WebPFreeDecBuffer(tls, (idec + 352 /* &.output_ */)) + *(*WebPDecBuffer)(unsafe.Pointer(output)) = *(*WebPDecBuffer)(unsafe.Pointer((*WebPIDecoder)(unsafe.Pointer(idec)).final_output_)) + (*WebPIDecoder)(unsafe.Pointer(idec)).final_output_ = (uintptr(0)) + } + return VP8_STATUS_OK +} + +//------------------------------------------------------------------------------ +// Macroblock-decoding contexts + +func SaveContext(tls *libc.TLS, dec uintptr, token_br uintptr, context uintptr) { /* idec_dec.c:272:13: */ + (*MBContext)(unsafe.Pointer(context)).left_ = *(*VP8MB)(unsafe.Pointer((*VP8Decoder)(unsafe.Pointer(dec)).mb_info_ + libc.UintptrFromInt32(-1)*2)) + (*MBContext)(unsafe.Pointer(context)).info_ = *(*VP8MB)(unsafe.Pointer((*VP8Decoder)(unsafe.Pointer(dec)).mb_info_ + uintptr((*VP8Decoder)(unsafe.Pointer(dec)).mb_x_)*2)) + (*MBContext)(unsafe.Pointer(context)).token_br_ = *(*VP8BitReader)(unsafe.Pointer(token_br)) +} + +func RestoreContext(tls *libc.TLS, context uintptr, dec uintptr, token_br uintptr) { /* idec_dec.c:279:13: */ + *(*VP8MB)(unsafe.Pointer((*VP8Decoder)(unsafe.Pointer(dec)).mb_info_ + libc.UintptrFromInt32(-1)*2)) = (*MBContext)(unsafe.Pointer(context)).left_ + *(*VP8MB)(unsafe.Pointer((*VP8Decoder)(unsafe.Pointer(dec)).mb_info_ + uintptr((*VP8Decoder)(unsafe.Pointer(dec)).mb_x_)*2)) = (*MBContext)(unsafe.Pointer(context)).info_ + *(*VP8BitReader)(unsafe.Pointer(token_br)) = (*MBContext)(unsafe.Pointer(context)).token_br_ +} + +//------------------------------------------------------------------------------ + +func IDecError(tls *libc.TLS, idec uintptr, error VP8StatusCode) VP8StatusCode { /* idec_dec.c:288:22: */ + if (*WebPIDecoder)(unsafe.Pointer(idec)).state_ == STATE_VP8_DATA { + // Synchronize the thread, clean-up and check for errors. + VP8ExitCritical(tls, (*WebPIDecoder)(unsafe.Pointer(idec)).dec_, (idec + 136 /* &.io_ */)) + } + (*WebPIDecoder)(unsafe.Pointer(idec)).state_ = STATE_ERROR + return error +} + +func ChangeState(tls *libc.TLS, idec uintptr, new_state DecState, consumed_bytes size_t) { /* idec_dec.c:297:13: */ + var mem uintptr = (idec + 296 /* &.mem_ */) + (*WebPIDecoder)(unsafe.Pointer(idec)).state_ = new_state + *(*size_t)(unsafe.Pointer((mem + 8 /* &.start_ */))) += (consumed_bytes) + + (*WebPIDecoder)(unsafe.Pointer(idec)).io_.data = ((*MemBuffer)(unsafe.Pointer(mem)).buf_ + uintptr((*MemBuffer)(unsafe.Pointer(mem)).start_)) + (*WebPIDecoder)(unsafe.Pointer(idec)).io_.data_size = MemDataSize(tls, mem) +} + +// Headers +func DecodeWebPHeaders(tls *libc.TLS, idec uintptr) VP8StatusCode { /* idec_dec.c:308:22: */ + bp := tls.Alloc(72) + defer tls.Free(72) + + var mem uintptr = (idec + 296 /* &.mem_ */) + var data uintptr = ((*MemBuffer)(unsafe.Pointer(mem)).buf_ + uintptr((*MemBuffer)(unsafe.Pointer(mem)).start_)) + var curr_size size_t = MemDataSize(tls, mem) + var status VP8StatusCode + // var headers WebPHeaderStructure at bp, 72 + + (*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).data = data + (*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).data_size = curr_size + (*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).have_all_data = 0 + status = WebPParseHeaders(tls, (bp) /* &headers */) + if status == VP8_STATUS_NOT_ENOUGH_DATA { + return VP8_STATUS_SUSPENDED // We haven't found a VP8 chunk yet. + } else if status != VP8_STATUS_OK { + return IDecError(tls, idec, status) + } + + (*WebPIDecoder)(unsafe.Pointer(idec)).chunk_size_ = (*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).compressed_size + (*WebPIDecoder)(unsafe.Pointer(idec)).is_lossless_ = (*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).is_lossless + if !((*WebPIDecoder)(unsafe.Pointer(idec)).is_lossless_ != 0) { + var dec uintptr = VP8New(tls) + if dec == (uintptr(0)) { + return VP8_STATUS_OUT_OF_MEMORY + } + (*WebPIDecoder)(unsafe.Pointer(idec)).dec_ = dec + (*VP8Decoder)(unsafe.Pointer(dec)).alpha_data_ = (*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).alpha_data + (*VP8Decoder)(unsafe.Pointer(dec)).alpha_data_size_ = (*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).alpha_data_size + ChangeState(tls, idec, STATE_VP8_HEADER, (*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).offset) + } else { + var dec uintptr = VP8LNew(tls) + if dec == (uintptr(0)) { + return VP8_STATUS_OUT_OF_MEMORY + } + (*WebPIDecoder)(unsafe.Pointer(idec)).dec_ = dec + ChangeState(tls, idec, STATE_VP8L_HEADER, (*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).offset) + } + return VP8_STATUS_OK +} + +func DecodeVP8FrameHeader(tls *libc.TLS, idec uintptr) VP8StatusCode { /* idec_dec.c:347:22: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var data uintptr = ((*WebPIDecoder)(unsafe.Pointer(idec)).mem_.buf_ + uintptr((*WebPIDecoder)(unsafe.Pointer(idec)).mem_.start_)) + var curr_size size_t = MemDataSize(tls, (idec + 296 /* &.mem_ */)) + // var width int32 at bp, 4 + + // var height int32 at bp+4, 4 + + var bits uint32_t + + if curr_size < uint64(10) { + // Not enough data bytes to extract VP8 Frame Header. + return VP8_STATUS_SUSPENDED + } + if !(VP8GetInfo(tls, data, curr_size, (*WebPIDecoder)(unsafe.Pointer(idec)).chunk_size_, (bp) /* &width */, (bp+4) /* &height */) != 0) { + return IDecError(tls, idec, VP8_STATUS_BITSTREAM_ERROR) + } + + bits = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(data))) | (int32(*(*uint8_t)(unsafe.Pointer(data + 1))) << 8)) | (int32(*(*uint8_t)(unsafe.Pointer(data + 2))) << 16))) + (*WebPIDecoder)(unsafe.Pointer(idec)).mem_.part0_size_ = (size_t((bits >> 5) + uint32_t(10))) + + (*WebPIDecoder)(unsafe.Pointer(idec)).io_.data = data + (*WebPIDecoder)(unsafe.Pointer(idec)).io_.data_size = curr_size + (*WebPIDecoder)(unsafe.Pointer(idec)).state_ = STATE_VP8_PARTS0 + return VP8_STATUS_OK +} + +// Partition #0 +func CopyParts0Data(tls *libc.TLS, idec uintptr) VP8StatusCode { /* idec_dec.c:371:22: */ + var dec uintptr = (*WebPIDecoder)(unsafe.Pointer(idec)).dec_ + var br uintptr = (dec + 16 /* &.br_ */) + var part_size size_t = (size_t((int64((*VP8BitReader)(unsafe.Pointer(br)).buf_end_) - int64((*VP8BitReader)(unsafe.Pointer(br)).buf_)) / 1)) + var mem uintptr = (idec + 296 /* &.mem_ */) + + // the following is a format limitation, no need for runtime check: + + if part_size == uint64(0) { // can't have zero-size partition #0 + return VP8_STATUS_BITSTREAM_ERROR + } + if (*MemBuffer)(unsafe.Pointer(mem)).mode_ == MEM_MODE_APPEND { + // We copy and grab ownership of the partition #0 data. + var part0_buf uintptr = WebPSafeMalloc(tls, 1, part_size) + if part0_buf == (uintptr(0)) { + return VP8_STATUS_OUT_OF_MEMORY + } + libc.Xmemcpy(tls, part0_buf, (*VP8BitReader)(unsafe.Pointer(br)).buf_, part_size) + (*MemBuffer)(unsafe.Pointer(mem)).part0_buf_ = part0_buf + VP8BitReaderSetBuffer(tls, br, part0_buf, part_size) + } else { + // Else: just keep pointers to the partition #0's data in dec_->br_. + } + *(*size_t)(unsafe.Pointer((mem + 8 /* &.start_ */))) += (part_size) + return VP8_STATUS_OK +} + +func DecodePartition0(tls *libc.TLS, idec uintptr) VP8StatusCode { /* idec_dec.c:399:22: */ + var dec uintptr = (*WebPIDecoder)(unsafe.Pointer(idec)).dec_ + var io uintptr = (idec + 136 /* &.io_ */) + var params uintptr = (idec + 8 /* &.params_ */) + var output uintptr = (*WebPDecParams)(unsafe.Pointer(params)).output + + // Wait till we have enough data for the whole partition #0 + if MemDataSize(tls, (idec+296 /* &.mem_ */)) < (*WebPIDecoder)(unsafe.Pointer(idec)).mem_.part0_size_ { + return VP8_STATUS_SUSPENDED + } + + if !(VP8GetHeaders(tls, dec, io) != 0) { + var status VP8StatusCode = (*VP8Decoder)(unsafe.Pointer(dec)).status_ + if (status == VP8_STATUS_SUSPENDED) || (status == VP8_STATUS_NOT_ENOUGH_DATA) { + // treating NOT_ENOUGH_DATA as SUSPENDED state + return VP8_STATUS_SUSPENDED + } + return IDecError(tls, idec, status) + } + + // Allocate/Verify output buffer now + (*VP8Decoder)(unsafe.Pointer(dec)).status_ = WebPAllocateDecBuffer(tls, (*VP8Io)(unsafe.Pointer(io)).width, (*VP8Io)(unsafe.Pointer(io)).height, (*WebPDecParams)(unsafe.Pointer(params)).options, + output) + if (*VP8Decoder)(unsafe.Pointer(dec)).status_ != VP8_STATUS_OK { + return IDecError(tls, idec, (*VP8Decoder)(unsafe.Pointer(dec)).status_) + } + // This change must be done before calling VP8InitFrame() + (*VP8Decoder)(unsafe.Pointer(dec)).mt_method_ = VP8GetThreadMethod(tls, (*WebPDecParams)(unsafe.Pointer(params)).options, (uintptr(0)), + (*VP8Io)(unsafe.Pointer(io)).width, (*VP8Io)(unsafe.Pointer(io)).height) + VP8InitDithering(tls, (*WebPDecParams)(unsafe.Pointer(params)).options, dec) + + (*VP8Decoder)(unsafe.Pointer(dec)).status_ = CopyParts0Data(tls, idec) + if (*VP8Decoder)(unsafe.Pointer(dec)).status_ != VP8_STATUS_OK { + return IDecError(tls, idec, (*VP8Decoder)(unsafe.Pointer(dec)).status_) + } + + // Finish setting up the decoding parameters. Will call io->setup(). + if VP8EnterCritical(tls, dec, io) != VP8_STATUS_OK { + return IDecError(tls, idec, (*VP8Decoder)(unsafe.Pointer(dec)).status_) + } + + // Note: past this point, teardown() must always be called + // in case of error. + (*WebPIDecoder)(unsafe.Pointer(idec)).state_ = STATE_VP8_DATA + // Allocate memory and prepare everything. + if !(VP8InitFrame(tls, dec, io) != 0) { + return IDecError(tls, idec, (*VP8Decoder)(unsafe.Pointer(dec)).status_) + } + return VP8_STATUS_OK +} + +// Remaining partitions +func DecodeRemaining(tls *libc.TLS, idec uintptr) VP8StatusCode { /* idec_dec.c:452:22: */ + bp := tls.Alloc(56) + defer tls.Free(56) + + var dec uintptr = (*WebPIDecoder)(unsafe.Pointer(idec)).dec_ + var io uintptr = (idec + 136 /* &.io_ */) + + // Make sure partition #0 has been read before, to set dec to ready_. + if !((*VP8Decoder)(unsafe.Pointer(dec)).ready_ != 0) { + return IDecError(tls, idec, VP8_STATUS_BITSTREAM_ERROR) + } + for ; (*VP8Decoder)(unsafe.Pointer(dec)).mb_y_ < (*VP8Decoder)(unsafe.Pointer(dec)).mb_h_; (*VP8Decoder)(unsafe.Pointer(dec)).mb_y_++ { + if (*WebPIDecoder)(unsafe.Pointer(idec)).last_mb_y_ != (*VP8Decoder)(unsafe.Pointer(dec)).mb_y_ { + if !(VP8ParseIntraModeRow(tls, (dec+16 /* &.br_ */), dec) != 0) { + // note: normally, error shouldn't occur since we already have the whole + // partition0 available here in DecodeRemaining(). Reaching EOF while + // reading intra modes really means a BITSTREAM_ERROR. + return IDecError(tls, idec, VP8_STATUS_BITSTREAM_ERROR) + } + (*WebPIDecoder)(unsafe.Pointer(idec)).last_mb_y_ = (*VP8Decoder)(unsafe.Pointer(dec)).mb_y_ + } + for ; (*VP8Decoder)(unsafe.Pointer(dec)).mb_x_ < (*VP8Decoder)(unsafe.Pointer(dec)).mb_w_; (*VP8Decoder)(unsafe.Pointer(dec)).mb_x_++ { + var token_br uintptr = ((dec + 440 /* &.parts_ */) + uintptr((uint32_t((*VP8Decoder)(unsafe.Pointer(dec)).mb_y_)&(*VP8Decoder)(unsafe.Pointer(dec)).num_parts_minus_one_))*48) + // var context MBContext at bp, 56 + + SaveContext(tls, dec, token_br, (bp) /* &context */) + if !(VP8DecodeMB(tls, dec, token_br) != 0) { + // We shouldn't fail when MAX_MB data was available + if ((*VP8Decoder)(unsafe.Pointer(dec)).num_parts_minus_one_ == uint32_t(0)) && (MemDataSize(tls, (idec+296 /* &.mem_ */)) > uint64(4096)) { + return IDecError(tls, idec, VP8_STATUS_BITSTREAM_ERROR) + } + // Synchronize the threads. + if (*VP8Decoder)(unsafe.Pointer(dec)).mt_method_ > 0 { + if !((*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(WebPGetWorkerInterface(tls))).Sync})).f(tls, (dec+152 /* &.worker_ */)) != 0) { + return IDecError(tls, idec, VP8_STATUS_BITSTREAM_ERROR) + } + } + RestoreContext(tls, (bp) /* &context */, dec, token_br) + return VP8_STATUS_SUSPENDED + } + // Release buffer only if there is only one partition + if (*VP8Decoder)(unsafe.Pointer(dec)).num_parts_minus_one_ == uint32_t(0) { + (*WebPIDecoder)(unsafe.Pointer(idec)).mem_.start_ = (size_t((int64((*VP8BitReader)(unsafe.Pointer(token_br)).buf_) - int64((*WebPIDecoder)(unsafe.Pointer(idec)).mem_.buf_)) / 1)) + + } + } + VP8InitScanline(tls, dec) // Prepare for next scanline + + // Reconstruct, filter and emit the row. + if !(VP8ProcessRow(tls, dec, io) != 0) { + return IDecError(tls, idec, VP8_STATUS_USER_ABORT) + } + } + // Synchronize the thread and check for errors. + if !(VP8ExitCritical(tls, dec, io) != 0) { + (*WebPIDecoder)(unsafe.Pointer(idec)).state_ = STATE_ERROR // prevent re-entry in IDecError + return IDecError(tls, idec, VP8_STATUS_USER_ABORT) + } + (*VP8Decoder)(unsafe.Pointer(dec)).ready_ = 0 + return FinishDecoding(tls, idec) +} + +func ErrorStatusLossless(tls *libc.TLS, idec uintptr, status VP8StatusCode) VP8StatusCode { /* idec_dec.c:512:22: */ + if (status == VP8_STATUS_SUSPENDED) || (status == VP8_STATUS_NOT_ENOUGH_DATA) { + return VP8_STATUS_SUSPENDED + } + return IDecError(tls, idec, status) +} + +func DecodeVP8LHeader(tls *libc.TLS, idec uintptr) VP8StatusCode { /* idec_dec.c:520:22: */ + var io uintptr = (idec + 136 /* &.io_ */) + var dec uintptr = (*WebPIDecoder)(unsafe.Pointer(idec)).dec_ + var params uintptr = (idec + 8 /* &.params_ */) + var output uintptr = (*WebPDecParams)(unsafe.Pointer(params)).output + var curr_size size_t = MemDataSize(tls, (idec + 296 /* &.mem_ */)) + + // Wait until there's enough data for decoding header. + if curr_size < ((*WebPIDecoder)(unsafe.Pointer(idec)).chunk_size_ >> 3) { + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_SUSPENDED + return ErrorStatusLossless(tls, idec, (*VP8LDecoder)(unsafe.Pointer(dec)).status_) + } + + if !(VP8LDecodeHeader(tls, dec, io) != 0) { + if ((*VP8LDecoder)(unsafe.Pointer(dec)).status_ == VP8_STATUS_BITSTREAM_ERROR) && (curr_size < (*WebPIDecoder)(unsafe.Pointer(idec)).chunk_size_) { + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_SUSPENDED + } + return ErrorStatusLossless(tls, idec, (*VP8LDecoder)(unsafe.Pointer(dec)).status_) + } + // Allocate/verify output buffer now. + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = WebPAllocateDecBuffer(tls, (*VP8Io)(unsafe.Pointer(io)).width, (*VP8Io)(unsafe.Pointer(io)).height, (*WebPDecParams)(unsafe.Pointer(params)).options, + output) + if (*VP8LDecoder)(unsafe.Pointer(dec)).status_ != VP8_STATUS_OK { + return IDecError(tls, idec, (*VP8LDecoder)(unsafe.Pointer(dec)).status_) + } + + (*WebPIDecoder)(unsafe.Pointer(idec)).state_ = STATE_VP8L_DATA + return VP8_STATUS_OK +} + +func DecodeVP8LData(tls *libc.TLS, idec uintptr) VP8StatusCode { /* idec_dec.c:552:22: */ + var dec uintptr = (*WebPIDecoder)(unsafe.Pointer(idec)).dec_ + var curr_size size_t = MemDataSize(tls, (idec + 296 /* &.mem_ */)) + + // Switch to incremental decoding if we don't have all the bytes available. + (*VP8LDecoder)(unsafe.Pointer(dec)).incremental_ = (libc.Bool32(curr_size < (*WebPIDecoder)(unsafe.Pointer(idec)).chunk_size_)) + + if !(VP8LDecodeImage(tls, dec) != 0) { + return ErrorStatusLossless(tls, idec, (*VP8LDecoder)(unsafe.Pointer(dec)).status_) + } + + if (*VP8LDecoder)(unsafe.Pointer(dec)).status_ == VP8_STATUS_SUSPENDED { + return (*VP8LDecoder)(unsafe.Pointer(dec)).status_ + } + return FinishDecoding(tls, idec) +} + +// Main decoding loop +func IDecode(tls *libc.TLS, idec uintptr) VP8StatusCode { /* idec_dec.c:569:22: */ + var status VP8StatusCode = VP8_STATUS_SUSPENDED + + if (*WebPIDecoder)(unsafe.Pointer(idec)).state_ == STATE_WEBP_HEADER { + status = DecodeWebPHeaders(tls, idec) + } else { + if (*WebPIDecoder)(unsafe.Pointer(idec)).dec_ == (uintptr(0)) { + return VP8_STATUS_SUSPENDED // can't continue if we have no decoder. + } + } + if (*WebPIDecoder)(unsafe.Pointer(idec)).state_ == STATE_VP8_HEADER { + status = DecodeVP8FrameHeader(tls, idec) + } + if (*WebPIDecoder)(unsafe.Pointer(idec)).state_ == STATE_VP8_PARTS0 { + status = DecodePartition0(tls, idec) + } + if (*WebPIDecoder)(unsafe.Pointer(idec)).state_ == STATE_VP8_DATA { + var dec uintptr = (*WebPIDecoder)(unsafe.Pointer(idec)).dec_ + if dec == (uintptr(0)) { + return VP8_STATUS_SUSPENDED // can't continue if we have no decoder. + } + status = DecodeRemaining(tls, idec) + } + if (*WebPIDecoder)(unsafe.Pointer(idec)).state_ == STATE_VP8L_HEADER { + status = DecodeVP8LHeader(tls, idec) + } + if (*WebPIDecoder)(unsafe.Pointer(idec)).state_ == STATE_VP8L_DATA { + status = DecodeVP8LData(tls, idec) + } + return status +} + +//------------------------------------------------------------------------------ +// Internal constructor + +func NewDecoder(tls *libc.TLS, output_buffer uintptr, features uintptr) uintptr { /* idec_dec.c:604:20: */ + var idec uintptr = WebPSafeCalloc(tls, 1, uint64(unsafe.Sizeof(WebPIDecoder{}))) + if idec == (uintptr(0)) { + return (uintptr(0)) + } + + (*WebPIDecoder)(unsafe.Pointer(idec)).state_ = STATE_WEBP_HEADER + (*WebPIDecoder)(unsafe.Pointer(idec)).chunk_size_ = uint64(0) + + (*WebPIDecoder)(unsafe.Pointer(idec)).last_mb_y_ = -1 + + InitMemBuffer(tls, (idec + 296 /* &.mem_ */)) + WebPInitDecBuffer(tls, (idec + 352 /* &.output_ */)) + VP8InitIo(tls, (idec + 136 /* &.io_ */)) + + WebPResetDecParams(tls, (idec + 8 /* &.params_ */)) + if (output_buffer == (uintptr(0))) || (WebPAvoidSlowMemory(tls, output_buffer, features) != 0) { + (*WebPIDecoder)(unsafe.Pointer(idec)).params_.output = (idec + 352 /* &.output_ */) + (*WebPIDecoder)(unsafe.Pointer(idec)).final_output_ = output_buffer + if output_buffer != (uintptr(0)) { + (*WebPDecBuffer)(unsafe.Pointer((*WebPIDecoder)(unsafe.Pointer(idec)).params_.output)).colorspace = (*WebPDecBuffer)(unsafe.Pointer(output_buffer)).colorspace + } + } else { + (*WebPIDecoder)(unsafe.Pointer(idec)).params_.output = output_buffer + (*WebPIDecoder)(unsafe.Pointer(idec)).final_output_ = (uintptr(0)) + } + WebPInitCustomIo(tls, (idec + 8 /* &.params_ */), (idec + 136 /* &.io_ */)) // Plug the I/O functions. + + return idec +} + +//------------------------------------------------------------------------------ +// Public functions + +func WebPINewDecoder(tls *libc.TLS, output_buffer uintptr) uintptr { /* idec_dec.c:639:13: */ + return NewDecoder(tls, output_buffer, (uintptr(0))) +} + +func WebPIDecode(tls *libc.TLS, data uintptr, data_size size_t, config uintptr) uintptr { /* idec_dec.c:643:13: */ + bp := tls.Alloc(40) + defer tls.Free(40) + + var idec uintptr + // var tmp_features WebPBitstreamFeatures at bp, 40 + + var features uintptr + if config == (uintptr(0)) { + features = (bp) /* &tmp_features */ + } else { + features = (config /* &.input */) + } + libc.Xmemset(tls, (bp) /* &tmp_features */, 0, uint64(unsafe.Sizeof(WebPBitstreamFeatures{}))) + + // Parse the bitstream's features, if requested: + if (data != (uintptr(0))) && (data_size > uint64(0)) { + if WebPGetFeatures(tls, data, data_size, features) != VP8_STATUS_OK { + return (uintptr(0)) + } + } + + // Create an instance of the incremental decoder + if config != (uintptr(0)) { + idec = NewDecoder(tls, (config + 40 /* &.output */), features) + } else { + idec = NewDecoder(tls, (uintptr(0)), features) + } + if idec == (uintptr(0)) { + return (uintptr(0)) + } + // Finish initialization + if config != (uintptr(0)) { + (*WebPIDecoder)(unsafe.Pointer(idec)).params_.options = (config + 160 /* &.options */) + } + return idec +} + +func WebPIDelete(tls *libc.TLS, idec uintptr) { /* idec_dec.c:671:6: */ + if idec == (uintptr(0)) { + return + } + if (*WebPIDecoder)(unsafe.Pointer(idec)).dec_ != (uintptr(0)) { + if !((*WebPIDecoder)(unsafe.Pointer(idec)).is_lossless_ != 0) { + if (*WebPIDecoder)(unsafe.Pointer(idec)).state_ == STATE_VP8_DATA { + // Synchronize the thread, clean-up and check for errors. + VP8ExitCritical(tls, (*WebPIDecoder)(unsafe.Pointer(idec)).dec_, (idec + 136 /* &.io_ */)) + } + VP8Delete(tls, (*WebPIDecoder)(unsafe.Pointer(idec)).dec_) + } else { + VP8LDelete(tls, (*WebPIDecoder)(unsafe.Pointer(idec)).dec_) + } + } + ClearMemBuffer(tls, (idec + 296 /* &.mem_ */)) + WebPFreeDecBuffer(tls, (idec + 352 /* &.output_ */)) + WebPSafeFree(tls, idec) +} + +//------------------------------------------------------------------------------ +// Wrapper toward WebPINewDecoder + +func WebPINewRGB(tls *libc.TLS, csp WEBP_CSP_MODE, output_buffer uintptr, output_buffer_size size_t, output_stride int32) uintptr { /* idec_dec.c:692:13: */ + var is_external_memory int32 + if output_buffer != (uintptr(0)) { + is_external_memory = 1 + } else { + is_external_memory = 0 + } + var idec uintptr + + if csp >= MODE_YUV { + return (uintptr(0)) + } + if is_external_memory == 0 { // Overwrite parameters to sane values. + output_buffer_size = uint64(0) + output_stride = 0 + } else { // A buffer was passed. Validate the other params. + if (output_stride == 0) || (output_buffer_size == uint64(0)) { + return (uintptr(0)) // invalid parameter. + } + } + idec = WebPINewDecoder(tls, (uintptr(0))) + if idec == (uintptr(0)) { + return (uintptr(0)) + } + (*WebPIDecoder)(unsafe.Pointer(idec)).output_.colorspace = csp + (*WebPIDecoder)(unsafe.Pointer(idec)).output_.is_external_memory = is_external_memory + (*WebPRGBABuffer)(unsafe.Pointer(((idec + 352 /* &.output_ */) + 16 /* &.u */))).rgba = output_buffer + (*WebPRGBABuffer)(unsafe.Pointer(((idec + 352 /* &.output_ */) + 16 /* &.u */))).stride = output_stride + (*WebPRGBABuffer)(unsafe.Pointer(((idec + 352 /* &.output_ */) + 16 /* &.u */))).size = output_buffer_size + return idec +} + +func WebPINewYUVA(tls *libc.TLS, luma uintptr, luma_size size_t, luma_stride int32, u uintptr, u_size size_t, u_stride int32, v uintptr, v_size size_t, v_stride int32, a uintptr, a_size size_t, a_stride int32) uintptr { /* idec_dec.c:716:13: */ + var is_external_memory int32 + if luma != (uintptr(0)) { + is_external_memory = 1 + } else { + is_external_memory = 0 + } + var idec uintptr + var colorspace WEBP_CSP_MODE + + if is_external_memory == 0 { // Overwrite parameters to sane values. + luma_size = libc.AssignUint64(&u_size, libc.AssignUint64(&v_size, libc.AssignUint64(&a_size, uint64(0)))) + luma_stride = libc.AssignInt32(&u_stride, libc.AssignInt32(&v_stride, libc.AssignInt32(&a_stride, 0))) + u = libc.AssignUintptr(&v, libc.AssignUintptr(&a, (uintptr(0)))) + colorspace = MODE_YUVA + } else { // A luma buffer was passed. Validate the other parameters. + if (u == (uintptr(0))) || (v == (uintptr(0))) { + return (uintptr(0)) + } + if ((luma_size == uint64(0)) || (u_size == uint64(0))) || (v_size == uint64(0)) { + return (uintptr(0)) + } + if ((luma_stride == 0) || (u_stride == 0)) || (v_stride == 0) { + return (uintptr(0)) + } + if a != (uintptr(0)) { + if (a_size == uint64(0)) || (a_stride == 0) { + return (uintptr(0)) + } + } + if a == (uintptr(0)) { + colorspace = MODE_YUV + } else { + colorspace = MODE_YUVA + } + } + + idec = WebPINewDecoder(tls, (uintptr(0))) + if idec == (uintptr(0)) { + return (uintptr(0)) + } + + (*WebPIDecoder)(unsafe.Pointer(idec)).output_.colorspace = colorspace + (*WebPIDecoder)(unsafe.Pointer(idec)).output_.is_external_memory = is_external_memory + (*WebPYUVABuffer)(unsafe.Pointer(((idec + 352 /* &.output_ */) + 16 /* &.u */))).y = luma + (*WebPYUVABuffer)(unsafe.Pointer(((idec + 352 /* &.output_ */) + 16 /* &.u */))).y_stride = luma_stride + (*WebPYUVABuffer)(unsafe.Pointer(((idec + 352 /* &.output_ */) + 16 /* &.u */))).y_size = luma_size + (*WebPYUVABuffer)(unsafe.Pointer(((idec + 352 /* &.output_ */) + 16 /* &.u */))).u = u + (*WebPYUVABuffer)(unsafe.Pointer(((idec + 352 /* &.output_ */) + 16 /* &.u */))).u_stride = u_stride + (*WebPYUVABuffer)(unsafe.Pointer(((idec + 352 /* &.output_ */) + 16 /* &.u */))).u_size = u_size + (*WebPYUVABuffer)(unsafe.Pointer(((idec + 352 /* &.output_ */) + 16 /* &.u */))).v = v + (*WebPYUVABuffer)(unsafe.Pointer(((idec + 352 /* &.output_ */) + 16 /* &.u */))).v_stride = v_stride + (*WebPYUVABuffer)(unsafe.Pointer(((idec + 352 /* &.output_ */) + 16 /* &.u */))).v_size = v_size + (*WebPYUVABuffer)(unsafe.Pointer(((idec + 352 /* &.output_ */) + 16 /* &.u */))).a = a + (*WebPYUVABuffer)(unsafe.Pointer(((idec + 352 /* &.output_ */) + 16 /* &.u */))).a_stride = a_stride + (*WebPYUVABuffer)(unsafe.Pointer(((idec + 352 /* &.output_ */) + 16 /* &.u */))).a_size = a_size + return idec +} + +func WebPINewYUV(tls *libc.TLS, luma uintptr, luma_size size_t, luma_stride int32, u uintptr, u_size size_t, u_stride int32, v uintptr, v_size size_t, v_stride int32) uintptr { /* idec_dec.c:759:13: */ + return WebPINewYUVA(tls, luma, luma_size, luma_stride, + u, u_size, u_stride, + v, v_size, v_stride, + (uintptr(0)), uint64(0), 0) +} + +//------------------------------------------------------------------------------ + +func IDecCheckStatus(tls *libc.TLS, idec uintptr) VP8StatusCode { /* idec_dec.c:770:22: */ + + if (*WebPIDecoder)(unsafe.Pointer(idec)).state_ == STATE_ERROR { + return VP8_STATUS_BITSTREAM_ERROR + } + if (*WebPIDecoder)(unsafe.Pointer(idec)).state_ == STATE_DONE { + return VP8_STATUS_OK + } + return VP8_STATUS_SUSPENDED +} + +func WebPIAppend(tls *libc.TLS, idec uintptr, data uintptr, data_size size_t) VP8StatusCode { /* idec_dec.c:781:15: */ + var status VP8StatusCode + if (idec == (uintptr(0))) || (data == (uintptr(0))) { + return VP8_STATUS_INVALID_PARAM + } + status = IDecCheckStatus(tls, idec) + if status != VP8_STATUS_SUSPENDED { + return status + } + // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. + if !(CheckMemBufferMode(tls, (idec+296 /* &.mem_ */), MEM_MODE_APPEND) != 0) { + return VP8_STATUS_INVALID_PARAM + } + // Append data to memory buffer + if !(AppendToMemBuffer(tls, idec, data, data_size) != 0) { + return VP8_STATUS_OUT_OF_MEMORY + } + return IDecode(tls, idec) +} + +func WebPIUpdate(tls *libc.TLS, idec uintptr, data uintptr, data_size size_t) VP8StatusCode { /* idec_dec.c:802:15: */ + var status VP8StatusCode + if (idec == (uintptr(0))) || (data == (uintptr(0))) { + return VP8_STATUS_INVALID_PARAM + } + status = IDecCheckStatus(tls, idec) + if status != VP8_STATUS_SUSPENDED { + return status + } + // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. + if !(CheckMemBufferMode(tls, (idec+296 /* &.mem_ */), MEM_MODE_MAP) != 0) { + return VP8_STATUS_INVALID_PARAM + } + // Make the memory buffer point to the new buffer + if !(RemapMemBuffer(tls, idec, data, data_size) != 0) { + return VP8_STATUS_INVALID_PARAM + } + return IDecode(tls, idec) +} + +//------------------------------------------------------------------------------ + +func GetOutputBuffer(tls *libc.TLS, idec uintptr) uintptr { /* idec_dec.c:825:27: */ + if (idec == (uintptr(0))) || ((*WebPIDecoder)(unsafe.Pointer(idec)).dec_ == (uintptr(0))) { + return (uintptr(0)) + } + if (*WebPIDecoder)(unsafe.Pointer(idec)).state_ <= STATE_VP8_PARTS0 { + return (uintptr(0)) + } + if (*WebPIDecoder)(unsafe.Pointer(idec)).final_output_ != (uintptr(0)) { + return (uintptr(0)) // not yet slow-copied + } + return (*WebPIDecoder)(unsafe.Pointer(idec)).params_.output +} + +func WebPIDecodedArea(tls *libc.TLS, idec uintptr, left uintptr, top uintptr, width uintptr, height uintptr) uintptr { /* idec_dec.c:838:20: */ + var src uintptr = GetOutputBuffer(tls, idec) + if left != (uintptr(0)) { + *(*int32)(unsafe.Pointer(left)) = 0 + } + if top != (uintptr(0)) { + *(*int32)(unsafe.Pointer(top)) = 0 + } + if src != (uintptr(0)) { + if width != (uintptr(0)) { + *(*int32)(unsafe.Pointer(width)) = (*WebPDecBuffer)(unsafe.Pointer(src)).width + } + if height != (uintptr(0)) { + *(*int32)(unsafe.Pointer(height)) = (*WebPIDecoder)(unsafe.Pointer(idec)).params_.last_y + } + } else { + if width != (uintptr(0)) { + *(*int32)(unsafe.Pointer(width)) = 0 + } + if height != (uintptr(0)) { + *(*int32)(unsafe.Pointer(height)) = 0 + } + } + return src +} + +func WebPIDecGetRGB(tls *libc.TLS, idec uintptr, last_y uintptr, width uintptr, height uintptr, stride uintptr) uintptr { /* idec_dec.c:854:8: */ + var src uintptr = GetOutputBuffer(tls, idec) + if src == (uintptr(0)) { + return (uintptr(0)) + } + if (*WebPDecBuffer)(unsafe.Pointer(src)).colorspace >= MODE_YUV { + return (uintptr(0)) + } + + if last_y != (uintptr(0)) { + *(*int32)(unsafe.Pointer(last_y)) = (*WebPIDecoder)(unsafe.Pointer(idec)).params_.last_y + } + if width != (uintptr(0)) { + *(*int32)(unsafe.Pointer(width)) = (*WebPDecBuffer)(unsafe.Pointer(src)).width + } + if height != (uintptr(0)) { + *(*int32)(unsafe.Pointer(height)) = (*WebPDecBuffer)(unsafe.Pointer(src)).height + } + if stride != (uintptr(0)) { + *(*int32)(unsafe.Pointer(stride)) = (*WebPRGBABuffer)(unsafe.Pointer((src + 16 /* &.u */))).stride + } + + return (*WebPRGBABuffer)(unsafe.Pointer((src + 16 /* &.u */))).rgba +} + +func WebPIDecGetYUVA(tls *libc.TLS, idec uintptr, last_y uintptr, u uintptr, v uintptr, a uintptr, width uintptr, height uintptr, stride uintptr, uv_stride uintptr, a_stride uintptr) uintptr { /* idec_dec.c:870:8: */ + var src uintptr = GetOutputBuffer(tls, idec) + if src == (uintptr(0)) { + return (uintptr(0)) + } + if (*WebPDecBuffer)(unsafe.Pointer(src)).colorspace < MODE_YUV { + return (uintptr(0)) + } + + if last_y != (uintptr(0)) { + *(*int32)(unsafe.Pointer(last_y)) = (*WebPIDecoder)(unsafe.Pointer(idec)).params_.last_y + } + if u != (uintptr(0)) { + *(*uintptr)(unsafe.Pointer(u)) = (*WebPYUVABuffer)(unsafe.Pointer((src + 16 /* &.u */))).u + } + if v != (uintptr(0)) { + *(*uintptr)(unsafe.Pointer(v)) = (*WebPYUVABuffer)(unsafe.Pointer((src + 16 /* &.u */))).v + } + if a != (uintptr(0)) { + *(*uintptr)(unsafe.Pointer(a)) = (*WebPYUVABuffer)(unsafe.Pointer((src + 16 /* &.u */))).a + } + if width != (uintptr(0)) { + *(*int32)(unsafe.Pointer(width)) = (*WebPDecBuffer)(unsafe.Pointer(src)).width + } + if height != (uintptr(0)) { + *(*int32)(unsafe.Pointer(height)) = (*WebPDecBuffer)(unsafe.Pointer(src)).height + } + if stride != (uintptr(0)) { + *(*int32)(unsafe.Pointer(stride)) = (*WebPYUVABuffer)(unsafe.Pointer((src + 16 /* &.u */))).y_stride + } + if uv_stride != (uintptr(0)) { + *(*int32)(unsafe.Pointer(uv_stride)) = (*WebPYUVABuffer)(unsafe.Pointer((src + 16 /* &.u */))).u_stride + } + if a_stride != (uintptr(0)) { + *(*int32)(unsafe.Pointer(a_stride)) = (*WebPYUVABuffer)(unsafe.Pointer((src + 16 /* &.u */))).a_stride + } + + return (*WebPYUVABuffer)(unsafe.Pointer((src + 16 /* &.u */))).y +} + +func WebPISetIOHooks(tls *libc.TLS, idec uintptr, put VP8IoPutHook, setup VP8IoSetupHook, teardown VP8IoTeardownHook, user_data uintptr) int32 { /* idec_dec.c:893:5: */ + if (idec == (uintptr(0))) || ((*WebPIDecoder)(unsafe.Pointer(idec)).state_ > STATE_WEBP_HEADER) { + return 0 + } + + (*WebPIDecoder)(unsafe.Pointer(idec)).io_.put = put + (*WebPIDecoder)(unsafe.Pointer(idec)).io_.setup = setup + (*WebPIDecoder)(unsafe.Pointer(idec)).io_.teardown = teardown + (*WebPIDecoder)(unsafe.Pointer(idec)).io_.opaque = user_data + + return 1 +} + +//------------------------------------------------------------------------------ +// slower on x86 by ~7-8%, but bit-exact with the SSE2/NEON version + +func MultHi(tls *libc.TLS, v int32, coeff int32) int32 { /* yuv.h:59:24: */ // _mm_mulhi_epu16 emulation + return ((v * coeff) >> 8) +} + +func VP8Clip8(tls *libc.TLS, v int32) int32 { /* yuv.h:63:24: */ + if (v & libc.CplInt32(YUV_MASK2)) == 0 { + return (v >> YUV_FIX2) + } + if v < 0 { + return 0 + } + return 255 +} + +func VP8YUVToR(tls *libc.TLS, y int32, v int32) int32 { /* yuv.h:67:24: */ + return VP8Clip8(tls, ((MultHi(tls, y, 19077) + MultHi(tls, v, 26149)) - 14234)) +} + +func VP8YUVToG(tls *libc.TLS, y int32, u int32, v int32) int32 { /* yuv.h:71:24: */ + return VP8Clip8(tls, (((MultHi(tls, y, 19077) - MultHi(tls, u, 6419)) - MultHi(tls, v, 13320)) + 8708)) +} + +func VP8YUVToB(tls *libc.TLS, y int32, u int32) int32 { /* yuv.h:75:24: */ + return VP8Clip8(tls, ((MultHi(tls, y, 19077) + MultHi(tls, u, 33050)) - 17685)) +} + +func VP8YuvToRgb(tls *libc.TLS, y int32, u int32, v int32, rgb uintptr) { /* yuv.h:79:25: */ + *(*uint8_t)(unsafe.Pointer(rgb)) = uint8_t(VP8YUVToR(tls, y, v)) + *(*uint8_t)(unsafe.Pointer(rgb + 1)) = uint8_t(VP8YUVToG(tls, y, u, v)) + *(*uint8_t)(unsafe.Pointer(rgb + 2)) = uint8_t(VP8YUVToB(tls, y, u)) +} + +func VP8YuvToBgr(tls *libc.TLS, y int32, u int32, v int32, bgr uintptr) { /* yuv.h:86:25: */ + *(*uint8_t)(unsafe.Pointer(bgr)) = uint8_t(VP8YUVToB(tls, y, u)) + *(*uint8_t)(unsafe.Pointer(bgr + 1)) = uint8_t(VP8YUVToG(tls, y, u, v)) + *(*uint8_t)(unsafe.Pointer(bgr + 2)) = uint8_t(VP8YUVToR(tls, y, v)) +} + +func VP8YuvToRgb565(tls *libc.TLS, y int32, u int32, v int32, rgb uintptr) { /* yuv.h:93:25: */ + var r int32 = VP8YUVToR(tls, y, v) // 5 usable bits + var g int32 = VP8YUVToG(tls, y, u, v) // 6 usable bits + var b int32 = VP8YUVToB(tls, y, u) // 5 usable bits + var rg int32 = ((r & 0xf8) | (g >> 5)) + var gb int32 = (((g << 3) & 0xe0) | (b >> 3)) + *(*uint8_t)(unsafe.Pointer(rgb)) = uint8_t(rg) + *(*uint8_t)(unsafe.Pointer(rgb + 1)) = uint8_t(gb) +} + +func VP8YuvToRgba4444(tls *libc.TLS, y int32, u int32, v int32, argb uintptr) { /* yuv.h:109:25: */ + var r int32 = VP8YUVToR(tls, y, v) // 4 usable bits + var g int32 = VP8YUVToG(tls, y, u, v) // 4 usable bits + var b int32 = VP8YUVToB(tls, y, u) // 4 usable bits + var rg int32 = ((r & 0xf0) | (g >> 4)) + var ba int32 = ((b & 0xf0) | 0x0f) // overwrite the lower 4 bits + *(*uint8_t)(unsafe.Pointer(argb)) = uint8_t(rg) + *(*uint8_t)(unsafe.Pointer(argb + 1)) = uint8_t(ba) +} + +//----------------------------------------------------------------------------- +// Alpha handling variants + +func VP8YuvToArgb(tls *libc.TLS, y uint8_t, u uint8_t, v uint8_t, argb uintptr) { /* yuv.h:128:25: */ + *(*uint8_t)(unsafe.Pointer(argb)) = uint8_t(0xff) + VP8YuvToRgb(tls, int32(y), int32(u), int32(v), (argb + uintptr(1))) +} + +func VP8YuvToBgra(tls *libc.TLS, y uint8_t, u uint8_t, v uint8_t, bgra uintptr) { /* yuv.h:134:25: */ + VP8YuvToBgr(tls, int32(y), int32(u), int32(v), bgra) + *(*uint8_t)(unsafe.Pointer(bgra + 3)) = uint8_t(0xff) +} + +func VP8YuvToRgba(tls *libc.TLS, y uint8_t, u uint8_t, v uint8_t, rgba uintptr) { /* yuv.h:140:25: */ + VP8YuvToRgb(tls, int32(y), int32(u), int32(v), rgba) + *(*uint8_t)(unsafe.Pointer(rgba + 3)) = uint8_t(0xff) +} + +//----------------------------------------------------------------------------- +// SSE2 extra functions (mostly for upsampling_sse2.c) + +//----------------------------------------------------------------------------- +// SSE41 extra functions (mostly for upsampling_sse41.c) + +//------------------------------------------------------------------------------ +// RGB -> YUV conversion + +// Stub functions that can be called with various rounding values: +func VP8ClipUV(tls *libc.TLS, uv int32, rounding int32) int32 { /* yuv.h:186:24: */ + uv = (((uv + rounding) + (int32(128) << (YUV_FIX + 2))) >> (YUV_FIX + 2)) + if (uv & libc.CplInt32(0xff)) == 0 { + return uv + } + if uv < 0 { + return 0 + } + return 255 +} + +func VP8RGBToY(tls *libc.TLS, r int32, g int32, b int32, rounding int32) int32 { /* yuv.h:191:24: */ + var luma int32 = (((16839 * r) + (33059 * g)) + (6420 * b)) + return (((luma + rounding) + (int32(16) << YUV_FIX)) >> YUV_FIX) // no need to clip +} + +func VP8RGBToU(tls *libc.TLS, r int32, g int32, b int32, rounding int32) int32 { /* yuv.h:196:24: */ + var u int32 = (((-9719 * r) - (19081 * g)) + (28800 * b)) + return VP8ClipUV(tls, u, rounding) +} + +func VP8RGBToV(tls *libc.TLS, r int32, g int32, b int32, rounding int32) int32 { /* yuv.h:201:24: */ + var v int32 = (((+28800 * r) - (24116 * g)) - (4684 * b)) + return VP8ClipUV(tls, v, rounding) +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Main YUV<->RGB conversion functions + +func EmitYUV(tls *libc.TLS, io uintptr, p uintptr) int32 { /* io_dec.c:25:12: */ + var output uintptr = (*WebPDecParams)(unsafe.Pointer(p)).output + var buf uintptr = (output + 16 /* &.u */) /* &.YUVA */ + var y_dst uintptr = ((*WebPYUVABuffer)(unsafe.Pointer(buf)).y + uintptr((size_t((*VP8Io)(unsafe.Pointer(io)).mb_y) * size_t((*WebPYUVABuffer)(unsafe.Pointer(buf)).y_stride)))) + var u_dst uintptr = ((*WebPYUVABuffer)(unsafe.Pointer(buf)).u + uintptr(((size_t((*VP8Io)(unsafe.Pointer(io)).mb_y >> 1)) * size_t((*WebPYUVABuffer)(unsafe.Pointer(buf)).u_stride)))) + var v_dst uintptr = ((*WebPYUVABuffer)(unsafe.Pointer(buf)).v + uintptr(((size_t((*VP8Io)(unsafe.Pointer(io)).mb_y >> 1)) * size_t((*WebPYUVABuffer)(unsafe.Pointer(buf)).v_stride)))) + var mb_w int32 = (*VP8Io)(unsafe.Pointer(io)).mb_w + var mb_h int32 = (*VP8Io)(unsafe.Pointer(io)).mb_h + var uv_w int32 = ((mb_w + 1) / 2) + var uv_h int32 = ((mb_h + 1) / 2) + WebPCopyPlane(tls, (*VP8Io)(unsafe.Pointer(io)).y, (*VP8Io)(unsafe.Pointer(io)).y_stride, y_dst, (*WebPYUVABuffer)(unsafe.Pointer(buf)).y_stride, mb_w, mb_h) + WebPCopyPlane(tls, (*VP8Io)(unsafe.Pointer(io)).u, (*VP8Io)(unsafe.Pointer(io)).uv_stride, u_dst, (*WebPYUVABuffer)(unsafe.Pointer(buf)).u_stride, uv_w, uv_h) + WebPCopyPlane(tls, (*VP8Io)(unsafe.Pointer(io)).v, (*VP8Io)(unsafe.Pointer(io)).uv_stride, v_dst, (*WebPYUVABuffer)(unsafe.Pointer(buf)).v_stride, uv_w, uv_h) + return (*VP8Io)(unsafe.Pointer(io)).mb_h +} + +// Point-sampling U/V sampler. +func EmitSampledRGB(tls *libc.TLS, io uintptr, p uintptr) int32 { /* io_dec.c:42:12: */ + var output uintptr = (*WebPDecParams)(unsafe.Pointer(p)).output + var buf uintptr = (output + 16 /* &.u */) /* &.RGBA */ + var dst uintptr = ((*WebPRGBABuffer)(unsafe.Pointer(buf)).rgba + uintptr((size_t((*VP8Io)(unsafe.Pointer(io)).mb_y) * size_t((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride)))) + WebPSamplerProcessPlane(tls, (*VP8Io)(unsafe.Pointer(io)).y, (*VP8Io)(unsafe.Pointer(io)).y_stride, + (*VP8Io)(unsafe.Pointer(io)).u, (*VP8Io)(unsafe.Pointer(io)).v, (*VP8Io)(unsafe.Pointer(io)).uv_stride, + dst, (*WebPRGBABuffer)(unsafe.Pointer(buf)).stride, (*VP8Io)(unsafe.Pointer(io)).mb_w, (*VP8Io)(unsafe.Pointer(io)).mb_h, + WebPSamplers[(*WebPDecBuffer)(unsafe.Pointer(output)).colorspace]) + return (*VP8Io)(unsafe.Pointer(io)).mb_h +} + +//------------------------------------------------------------------------------ +// Fancy upsampling + +func EmitFancyRGB(tls *libc.TLS, io uintptr, p uintptr) int32 { /* io_dec.c:57:12: */ + var num_lines_out int32 = (*VP8Io)(unsafe.Pointer(io)).mb_h // a priori guess + var buf uintptr = ((*WebPDecParams)(unsafe.Pointer(p)).output + 16 /* &.u */) /* &.RGBA */ + var dst uintptr = ((*WebPRGBABuffer)(unsafe.Pointer(buf)).rgba + uintptr((size_t((*VP8Io)(unsafe.Pointer(io)).mb_y) * size_t((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride)))) + var upsample WebPUpsampleLinePairFunc = WebPUpsamplers[(*WebPDecBuffer)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).output)).colorspace] + var cur_y uintptr = (*VP8Io)(unsafe.Pointer(io)).y + var cur_u uintptr = (*VP8Io)(unsafe.Pointer(io)).u + var cur_v uintptr = (*VP8Io)(unsafe.Pointer(io)).v + var top_u uintptr = (*WebPDecParams)(unsafe.Pointer(p)).tmp_u + var top_v uintptr = (*WebPDecParams)(unsafe.Pointer(p)).tmp_v + var y int32 = (*VP8Io)(unsafe.Pointer(io)).mb_y + var y_end int32 = ((*VP8Io)(unsafe.Pointer(io)).mb_y + (*VP8Io)(unsafe.Pointer(io)).mb_h) + var mb_w int32 = (*VP8Io)(unsafe.Pointer(io)).mb_w + var uv_w int32 = ((mb_w + 1) / 2) + + if y == 0 { + // First line is special cased. We mirror the u/v samples at boundary. + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{upsample})).f(tls, cur_y, (uintptr(0)), cur_u, cur_v, cur_u, cur_v, dst, (uintptr(0)), mb_w) + } else { + // We can finish the left-over line from previous call. + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{upsample})).f(tls, (*WebPDecParams)(unsafe.Pointer(p)).tmp_y, cur_y, top_u, top_v, cur_u, cur_v, + (dst - uintptr((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride)), dst, mb_w) + num_lines_out++ + } + // Loop over each output pairs of row. + for ; (y + 2) < y_end; y = y + (2) { + top_u = cur_u + top_v = cur_v + cur_u += uintptr((*VP8Io)(unsafe.Pointer(io)).uv_stride) + cur_v += uintptr((*VP8Io)(unsafe.Pointer(io)).uv_stride) + dst += (uintptr(2 * (*WebPRGBABuffer)(unsafe.Pointer(buf)).stride)) + cur_y += (uintptr(2 * (*VP8Io)(unsafe.Pointer(io)).y_stride)) + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{upsample})).f(tls, (cur_y - uintptr((*VP8Io)(unsafe.Pointer(io)).y_stride)), cur_y, + top_u, top_v, cur_u, cur_v, + (dst - uintptr((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride)), dst, mb_w) + } + // move to last row + cur_y += uintptr((*VP8Io)(unsafe.Pointer(io)).y_stride) + if ((*VP8Io)(unsafe.Pointer(io)).crop_top + y_end) < (*VP8Io)(unsafe.Pointer(io)).crop_bottom { + // Save the unfinished samples for next call (as we're not done yet). + libc.Xmemcpy(tls, (*WebPDecParams)(unsafe.Pointer(p)).tmp_y, cur_y, (uint64(mb_w) * uint64(unsafe.Sizeof(uint8_t(0))))) + libc.Xmemcpy(tls, (*WebPDecParams)(unsafe.Pointer(p)).tmp_u, cur_u, (uint64(uv_w) * uint64(unsafe.Sizeof(uint8_t(0))))) + libc.Xmemcpy(tls, (*WebPDecParams)(unsafe.Pointer(p)).tmp_v, cur_v, (uint64(uv_w) * uint64(unsafe.Sizeof(uint8_t(0))))) + // The fancy upsampler leaves a row unfinished behind + // (except for the very last row) + num_lines_out-- + } else { + // Process the very last row of even-sized picture + if !((y_end & 1) != 0) { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{upsample})).f(tls, cur_y, (uintptr(0)), cur_u, cur_v, cur_u, cur_v, + (dst + uintptr((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride)), (uintptr(0)), mb_w) + } + } + return num_lines_out +} + +//------------------------------------------------------------------------------ + +func FillAlphaPlane(tls *libc.TLS, dst uintptr, w int32, h int32, stride int32) { /* io_dec.c:117:13: */ + var j int32 + for j = 0; j < h; j++ { + libc.Xmemset(tls, dst, 0xff, (uint64(w) * uint64(unsafe.Sizeof(uint8_t(0))))) + dst += uintptr(stride) + } +} + +func EmitAlphaYUV(tls *libc.TLS, io uintptr, p uintptr, expected_num_lines_out int32) int32 { /* io_dec.c:125:12: */ + var alpha uintptr = (*VP8Io)(unsafe.Pointer(io)).a + var buf uintptr = ((*WebPDecParams)(unsafe.Pointer(p)).output + 16 /* &.u */) /* &.YUVA */ + var mb_w int32 = (*VP8Io)(unsafe.Pointer(io)).mb_w + var mb_h int32 = (*VP8Io)(unsafe.Pointer(io)).mb_h + var dst uintptr = ((*WebPYUVABuffer)(unsafe.Pointer(buf)).a + uintptr((size_t((*VP8Io)(unsafe.Pointer(io)).mb_y) * size_t((*WebPYUVABuffer)(unsafe.Pointer(buf)).a_stride)))) + var j int32 + _ = expected_num_lines_out + + if alpha != (uintptr(0)) { + for j = 0; j < mb_h; j++ { + libc.Xmemcpy(tls, dst, alpha, (uint64(mb_w) * uint64(unsafe.Sizeof(uint8_t(0))))) + alpha += uintptr((*VP8Io)(unsafe.Pointer(io)).width) + dst += uintptr((*WebPYUVABuffer)(unsafe.Pointer(buf)).a_stride) + } + } else if (*WebPYUVABuffer)(unsafe.Pointer(buf)).a != (uintptr(0)) { + // the user requested alpha, but there is none, set it to opaque. + FillAlphaPlane(tls, dst, mb_w, mb_h, (*WebPYUVABuffer)(unsafe.Pointer(buf)).a_stride) + } + return 0 +} + +func GetAlphaSourceRow(tls *libc.TLS, io uintptr, alpha uintptr, num_rows uintptr) int32 { /* io_dec.c:148:12: */ + var start_y int32 = (*VP8Io)(unsafe.Pointer(io)).mb_y + *(*int32)(unsafe.Pointer(num_rows)) = (*VP8Io)(unsafe.Pointer(io)).mb_h + + // Compensate for the 1-line delay of the fancy upscaler. + // This is similar to EmitFancyRGB(). + if (*VP8Io)(unsafe.Pointer(io)).fancy_upsampling != 0 { + if start_y == 0 { + // We don't process the last row yet. It'll be done during the next call. + *(*int32)(unsafe.Pointer(num_rows))-- + } else { + start_y-- + // Fortunately, *alpha data is persistent, so we can go back + // one row and finish alpha blending, now that the fancy upscaler + // completed the YUV->RGB interpolation. + *(*uintptr)(unsafe.Pointer(alpha)) -= (uintptr((*VP8Io)(unsafe.Pointer(io)).width)) + } + if (((*VP8Io)(unsafe.Pointer(io)).crop_top + (*VP8Io)(unsafe.Pointer(io)).mb_y) + (*VP8Io)(unsafe.Pointer(io)).mb_h) == (*VP8Io)(unsafe.Pointer(io)).crop_bottom { + // If it's the very last call, we process all the remaining rows! + *(*int32)(unsafe.Pointer(num_rows)) = (((*VP8Io)(unsafe.Pointer(io)).crop_bottom - (*VP8Io)(unsafe.Pointer(io)).crop_top) - start_y) + } + } + return start_y +} + +func EmitAlphaRGB(tls *libc.TLS, io uintptr, p uintptr, expected_num_lines_out int32) int32 { /* io_dec.c:174:12: */ + bp := tls.Alloc(12) + defer tls.Free(12) + + *(*uintptr)(unsafe.Pointer(bp /* alpha */)) = (*VP8Io)(unsafe.Pointer(io)).a + if *(*uintptr)(unsafe.Pointer(bp /* alpha */)) != (uintptr(0)) { + var mb_w int32 = (*VP8Io)(unsafe.Pointer(io)).mb_w + var colorspace WEBP_CSP_MODE = (*WebPDecBuffer)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).output)).colorspace + var alpha_first int32 = (libc.Bool32((colorspace == MODE_ARGB) || (colorspace == MODE_Argb))) + var buf uintptr = ((*WebPDecParams)(unsafe.Pointer(p)).output + 16 /* &.u */) /* &.RGBA */ + // var num_rows int32 at bp+8, 4 + + var start_y size_t = size_t(GetAlphaSourceRow(tls, io, (bp) /* &alpha */, (bp + 8) /* &num_rows */)) + var base_rgba uintptr = ((*WebPRGBABuffer)(unsafe.Pointer(buf)).rgba + uintptr((start_y * size_t((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride)))) + var dst uintptr = (base_rgba + uintptr((func() int32 { + if alpha_first != 0 { + return 0 + } + return 3 + }()))) + var has_alpha int32 = (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, uintptr, int32) int32 + })(unsafe.Pointer(&struct{ uintptr }{WebPDispatchAlpha})).f(tls, *(*uintptr)(unsafe.Pointer(bp /* alpha */)), (*VP8Io)(unsafe.Pointer(io)).width, mb_w, + *(*int32)(unsafe.Pointer(bp + 8 /* num_rows */)), dst, (*WebPRGBABuffer)(unsafe.Pointer(buf)).stride) + _ = expected_num_lines_out + + // has_alpha is true if there's non-trivial alpha to premultiply with. + if (has_alpha != 0) && (WebPIsPremultipliedMode(tls, colorspace) != 0) { + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPApplyAlphaMultiply})).f(tls, base_rgba, alpha_first, + mb_w, *(*int32)(unsafe.Pointer(bp + 8 /* num_rows */)), (*WebPRGBABuffer)(unsafe.Pointer(buf)).stride) + } + } + return 0 +} + +func EmitAlphaRGBA4444(tls *libc.TLS, io uintptr, p uintptr, expected_num_lines_out int32) int32 { /* io_dec.c:200:12: */ + bp := tls.Alloc(12) + defer tls.Free(12) + + *(*uintptr)(unsafe.Pointer(bp /* alpha */)) = (*VP8Io)(unsafe.Pointer(io)).a + if *(*uintptr)(unsafe.Pointer(bp /* alpha */)) != (uintptr(0)) { + var mb_w int32 = (*VP8Io)(unsafe.Pointer(io)).mb_w + var colorspace WEBP_CSP_MODE = (*WebPDecBuffer)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).output)).colorspace + var buf uintptr = ((*WebPDecParams)(unsafe.Pointer(p)).output + 16 /* &.u */) /* &.RGBA */ + // var num_rows int32 at bp+8, 4 + + var start_y size_t = size_t(GetAlphaSourceRow(tls, io, (bp) /* &alpha */, (bp + 8) /* &num_rows */)) + var base_rgba uintptr = ((*WebPRGBABuffer)(unsafe.Pointer(buf)).rgba + uintptr((start_y * size_t((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride)))) + var alpha_dst uintptr = (base_rgba + uintptr(1)) + var alpha_mask uint32_t = uint32_t(0x0f) + var i int32 + var j int32 + for j = 0; j < *(*int32)(unsafe.Pointer(bp + 8 /* num_rows */)); j++ { + for i = 0; i < mb_w; i++ { + // Fill in the alpha value (converted to 4 bits). + var alpha_value uint32_t = (uint32_t(int32(*(*uint8_t)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(bp /* alpha */)) + uintptr(i)))) >> 4)) + *(*uint8_t)(unsafe.Pointer(alpha_dst + uintptr((2 * i)))) = (uint8_t((uint32_t(int32(*(*uint8_t)(unsafe.Pointer(alpha_dst + uintptr((2 * i))))) & 0xf0)) | alpha_value)) + alpha_mask = alpha_mask & (alpha_value) + } + *(*uintptr)(unsafe.Pointer(bp /* alpha */)) += uintptr((*VP8Io)(unsafe.Pointer(io)).width) + alpha_dst += uintptr((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride) + } + _ = expected_num_lines_out + + if (alpha_mask != uint32_t(0x0f)) && (WebPIsPremultipliedMode(tls, colorspace) != 0) { + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPApplyAlphaMultiply4444})).f(tls, base_rgba, mb_w, *(*int32)(unsafe.Pointer(bp + 8 /* num_rows */)), (*WebPRGBABuffer)(unsafe.Pointer(buf)).stride) + } + } + return 0 +} + +//------------------------------------------------------------------------------ +// YUV rescaling (no final RGB conversion needed) + +func Rescale(tls *libc.TLS, src uintptr, src_stride int32, new_lines int32, wrk uintptr) int32 { /* io_dec.c:240:12: */ + var num_lines_out int32 = 0 + for new_lines > 0 { // import new contributions of source rows. + var lines_in int32 = WebPRescalerImport(tls, wrk, new_lines, src, src_stride) + src += (uintptr(lines_in * src_stride)) + new_lines = new_lines - (lines_in) + num_lines_out = num_lines_out + (WebPRescalerExport(tls, wrk)) // emit output row(s) + } + return num_lines_out +} + +func EmitRescaledYUV(tls *libc.TLS, io uintptr, p uintptr) int32 { /* io_dec.c:252:12: */ + var mb_h int32 = (*VP8Io)(unsafe.Pointer(io)).mb_h + var uv_mb_h int32 = ((mb_h + 1) >> 1) + var scaler uintptr = (*WebPDecParams)(unsafe.Pointer(p)).scaler_y + var num_lines_out int32 = 0 + if (WebPIsAlphaMode(tls, (*WebPDecBuffer)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).output)).colorspace) != 0) && ((*VP8Io)(unsafe.Pointer(io)).a != (uintptr(0))) { + // Before rescaling, we premultiply the luma directly into the io->y + // internal buffer. This is OK since these samples are not used for + // intra-prediction (the top samples are saved in cache_y_/u_/v_). + // But we need to cast the const away, though. + WebPMultRows(tls, (*VP8Io)(unsafe.Pointer(io)).y, (*VP8Io)(unsafe.Pointer(io)).y_stride, + (*VP8Io)(unsafe.Pointer(io)).a, (*VP8Io)(unsafe.Pointer(io)).width, (*VP8Io)(unsafe.Pointer(io)).mb_w, mb_h, 0) + } + num_lines_out = Rescale(tls, (*VP8Io)(unsafe.Pointer(io)).y, (*VP8Io)(unsafe.Pointer(io)).y_stride, mb_h, scaler) + Rescale(tls, (*VP8Io)(unsafe.Pointer(io)).u, (*VP8Io)(unsafe.Pointer(io)).uv_stride, uv_mb_h, (*WebPDecParams)(unsafe.Pointer(p)).scaler_u) + Rescale(tls, (*VP8Io)(unsafe.Pointer(io)).v, (*VP8Io)(unsafe.Pointer(io)).uv_stride, uv_mb_h, (*WebPDecParams)(unsafe.Pointer(p)).scaler_v) + return num_lines_out +} + +func EmitRescaledAlphaYUV(tls *libc.TLS, io uintptr, p uintptr, expected_num_lines_out int32) int32 { /* io_dec.c:271:12: */ + var buf uintptr = ((*WebPDecParams)(unsafe.Pointer(p)).output + 16 /* &.u */) /* &.YUVA */ + var dst_a uintptr = ((*WebPYUVABuffer)(unsafe.Pointer(buf)).a + uintptr((size_t((*WebPDecParams)(unsafe.Pointer(p)).last_y) * size_t((*WebPYUVABuffer)(unsafe.Pointer(buf)).a_stride)))) + if (*VP8Io)(unsafe.Pointer(io)).a != (uintptr(0)) { + var dst_y uintptr = ((*WebPYUVABuffer)(unsafe.Pointer(buf)).y + uintptr((size_t((*WebPDecParams)(unsafe.Pointer(p)).last_y) * size_t((*WebPYUVABuffer)(unsafe.Pointer(buf)).y_stride)))) + var num_lines_out int32 = Rescale(tls, (*VP8Io)(unsafe.Pointer(io)).a, (*VP8Io)(unsafe.Pointer(io)).width, (*VP8Io)(unsafe.Pointer(io)).mb_h, (*WebPDecParams)(unsafe.Pointer(p)).scaler_a) + + if num_lines_out > 0 { // unmultiply the Y + WebPMultRows(tls, dst_y, (*WebPYUVABuffer)(unsafe.Pointer(buf)).y_stride, dst_a, (*WebPYUVABuffer)(unsafe.Pointer(buf)).a_stride, + (*WebPRescaler)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).scaler_a)).dst_width, num_lines_out, 1) + } + } else if (*WebPYUVABuffer)(unsafe.Pointer(buf)).a != (uintptr(0)) { + // the user requested alpha, but there is none, set it to opaque. + + FillAlphaPlane(tls, dst_a, (*VP8Io)(unsafe.Pointer(io)).scaled_width, expected_num_lines_out, + (*WebPYUVABuffer)(unsafe.Pointer(buf)).a_stride) + } + return 0 +} + +func InitYUVRescaler(tls *libc.TLS, io uintptr, p uintptr) int32 { /* io_dec.c:292:12: */ + var has_alpha int32 = WebPIsAlphaMode(tls, (*WebPDecBuffer)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).output)).colorspace) + var buf uintptr = ((*WebPDecParams)(unsafe.Pointer(p)).output + 16 /* &.u */) /* &.YUVA */ + var out_width int32 = (*VP8Io)(unsafe.Pointer(io)).scaled_width + var out_height int32 = (*VP8Io)(unsafe.Pointer(io)).scaled_height + var uv_out_width int32 = ((out_width + 1) >> 1) + var uv_out_height int32 = ((out_height + 1) >> 1) + var uv_in_width int32 = (((*VP8Io)(unsafe.Pointer(io)).mb_w + 1) >> 1) + var uv_in_height int32 = (((*VP8Io)(unsafe.Pointer(io)).mb_h + 1) >> 1) + // scratch memory for luma rescaler + var work_size size_t = (uint64(2) * size_t(out_width)) + var uv_work_size size_t = (size_t(2 * uv_out_width)) // and for each u/v ones + var total_size uint64_t + var rescaler_size size_t + var work uintptr + var scalers uintptr + var num_rescalers int32 + if has_alpha != 0 { + num_rescalers = 4 + } else { + num_rescalers = 3 + } + + total_size = ((work_size + (uint64(2) * uv_work_size)) * uint64_t(unsafe.Sizeof(rescaler_t(0)))) + if has_alpha != 0 { + total_size = total_size + (work_size * uint64_t(unsafe.Sizeof(rescaler_t(0)))) + } + rescaler_size = ((uint64(num_rescalers) * uint64(unsafe.Sizeof(WebPRescaler{}))) + uint64(31)) + total_size = total_size + (rescaler_size) + if !(CheckSizeOverflow(tls, total_size) != 0) { + return 0 + } + + (*WebPDecParams)(unsafe.Pointer(p)).memory = WebPSafeMalloc(tls, 1, total_size) + if (*WebPDecParams)(unsafe.Pointer(p)).memory == (uintptr(0)) { + return 0 // memory error + } + work = (*WebPDecParams)(unsafe.Pointer(p)).memory + + scalers = (uintptr((uintptr_t(((work + uintptr(total_size)) - uintptr(rescaler_size))) + uint64(31)) & libc.Uint64FromInt32(libc.CplInt32(31)))) + (*WebPDecParams)(unsafe.Pointer(p)).scaler_y = (scalers) + (*WebPDecParams)(unsafe.Pointer(p)).scaler_u = (scalers + 1*104) + (*WebPDecParams)(unsafe.Pointer(p)).scaler_v = (scalers + 2*104) + (*WebPDecParams)(unsafe.Pointer(p)).scaler_a = func() uintptr { + if has_alpha != 0 { + return (scalers + 3*104) + } + return (uintptr(0)) + }() + + if (!(WebPRescalerInit(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_y, (*VP8Io)(unsafe.Pointer(io)).mb_w, (*VP8Io)(unsafe.Pointer(io)).mb_h, + (*WebPYUVABuffer)(unsafe.Pointer(buf)).y, out_width, out_height, (*WebPYUVABuffer)(unsafe.Pointer(buf)).y_stride, 1, + work) != 0) || !(WebPRescalerInit(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_u, uv_in_width, uv_in_height, + (*WebPYUVABuffer)(unsafe.Pointer(buf)).u, uv_out_width, uv_out_height, (*WebPYUVABuffer)(unsafe.Pointer(buf)).u_stride, 1, + (work+uintptr(work_size)*4)) != 0)) || !(WebPRescalerInit(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_v, uv_in_width, uv_in_height, + (*WebPYUVABuffer)(unsafe.Pointer(buf)).v, uv_out_width, uv_out_height, (*WebPYUVABuffer)(unsafe.Pointer(buf)).v_stride, 1, + ((work+uintptr(work_size)*4)+uintptr(uv_work_size)*4)) != 0) { + return 0 + } + (*WebPDecParams)(unsafe.Pointer(p)).emit = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{EmitRescaledYUV})) + + if has_alpha != 0 { + if !(WebPRescalerInit(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_a, (*VP8Io)(unsafe.Pointer(io)).mb_w, (*VP8Io)(unsafe.Pointer(io)).mb_h, + (*WebPYUVABuffer)(unsafe.Pointer(buf)).a, out_width, out_height, (*WebPYUVABuffer)(unsafe.Pointer(buf)).a_stride, 1, + ((work+uintptr(work_size)*4)+uintptr((uint64(2)*uv_work_size))*4)) != 0) { + return 0 + } + (*WebPDecParams)(unsafe.Pointer(p)).emit_alpha = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + }{EmitRescaledAlphaYUV})) + WebPInitAlphaProcessing(tls) + } + return 1 +} + +//------------------------------------------------------------------------------ +// RGBA rescaling + +func ExportRGB(tls *libc.TLS, p uintptr, y_pos int32) int32 { /* io_dec.c:361:12: */ + var convert WebPYUV444Converter = WebPYUV444Converters[(*WebPDecBuffer)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).output)).colorspace] + var buf uintptr = ((*WebPDecParams)(unsafe.Pointer(p)).output + 16 /* &.u */) /* &.RGBA */ + var dst uintptr = ((*WebPRGBABuffer)(unsafe.Pointer(buf)).rgba + uintptr((size_t(y_pos) * size_t((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride)))) + var num_lines_out int32 = 0 + // For RGB rescaling, because of the YUV420, current scan position + // U/V can be +1/-1 line from the Y one. Hence the double test. + for (WebPRescalerHasPendingOutput(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_y) != 0) && (WebPRescalerHasPendingOutput(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_u) != 0) { + + WebPRescalerExportRow(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_y) + WebPRescalerExportRow(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_u) + WebPRescalerExportRow(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_v) + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{convert})).f(tls, (*WebPRescaler)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).scaler_y)).dst, (*WebPRescaler)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).scaler_u)).dst, (*WebPRescaler)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).scaler_v)).dst, + dst, (*WebPRescaler)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).scaler_y)).dst_width) + dst += uintptr((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride) + num_lines_out++ + } + return num_lines_out +} + +func EmitRescaledRGB(tls *libc.TLS, io uintptr, p uintptr) int32 { /* io_dec.c:384:12: */ + var mb_h int32 = (*VP8Io)(unsafe.Pointer(io)).mb_h + var uv_mb_h int32 = ((mb_h + 1) >> 1) + var j int32 = 0 + var uv_j int32 = 0 + var num_lines_out int32 = 0 + for j < mb_h { + var y_lines_in int32 = WebPRescalerImport(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_y, (mb_h - j), + ((*VP8Io)(unsafe.Pointer(io)).y + uintptr((size_t(j) * size_t((*VP8Io)(unsafe.Pointer(io)).y_stride)))), (*VP8Io)(unsafe.Pointer(io)).y_stride) + j = j + (y_lines_in) + if WebPRescaleNeededLines(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_u, (uv_mb_h-uv_j)) != 0 { + var u_lines_in int32 = WebPRescalerImport(tls, + (*WebPDecParams)(unsafe.Pointer(p)).scaler_u, (uv_mb_h - uv_j), ((*VP8Io)(unsafe.Pointer(io)).u + uintptr((size_t(uv_j) * size_t((*VP8Io)(unsafe.Pointer(io)).uv_stride)))), + (*VP8Io)(unsafe.Pointer(io)).uv_stride) + var v_lines_in int32 = WebPRescalerImport(tls, + (*WebPDecParams)(unsafe.Pointer(p)).scaler_v, (uv_mb_h - uv_j), ((*VP8Io)(unsafe.Pointer(io)).v + uintptr((size_t(uv_j) * size_t((*VP8Io)(unsafe.Pointer(io)).uv_stride)))), + (*VP8Io)(unsafe.Pointer(io)).uv_stride) + _ = v_lines_in + _ = v_lines_in // remove a gcc warning + + uv_j = uv_j + (u_lines_in) + } + num_lines_out = num_lines_out + (ExportRGB(tls, p, ((*WebPDecParams)(unsafe.Pointer(p)).last_y + num_lines_out))) + } + return num_lines_out +} + +func ExportAlpha(tls *libc.TLS, p uintptr, y_pos int32, max_lines_out int32) int32 { /* io_dec.c:410:12: */ + var buf uintptr = ((*WebPDecParams)(unsafe.Pointer(p)).output + 16 /* &.u */) /* &.RGBA */ + var base_rgba uintptr = ((*WebPRGBABuffer)(unsafe.Pointer(buf)).rgba + uintptr((size_t(y_pos) * size_t((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride)))) + var colorspace WEBP_CSP_MODE = (*WebPDecBuffer)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).output)).colorspace + var alpha_first int32 = (libc.Bool32((colorspace == MODE_ARGB) || (colorspace == MODE_Argb))) + var dst uintptr = (base_rgba + uintptr((func() int32 { + if alpha_first != 0 { + return 0 + } + return 3 + }()))) + var num_lines_out int32 = 0 + var is_premult_alpha int32 = WebPIsPremultipliedMode(tls, colorspace) + var non_opaque uint32_t = uint32_t(0) + var width int32 = (*WebPRescaler)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).scaler_a)).dst_width + + for (WebPRescalerHasPendingOutput(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_a) != 0) && (num_lines_out < max_lines_out) { + + WebPRescalerExportRow(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_a) + non_opaque = non_opaque | (uint32_t((*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, uintptr, int32) int32 + })(unsafe.Pointer(&struct{ uintptr }{WebPDispatchAlpha})).f(tls, (*WebPRescaler)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).scaler_a)).dst, 0, width, 1, dst, 0))) + dst += uintptr((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride) + num_lines_out++ + } + if (is_premult_alpha != 0) && (non_opaque != 0) { + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPApplyAlphaMultiply})).f(tls, base_rgba, alpha_first, + width, num_lines_out, (*WebPRGBABuffer)(unsafe.Pointer(buf)).stride) + } + return num_lines_out +} + +func ExportAlphaRGBA4444(tls *libc.TLS, p uintptr, y_pos int32, max_lines_out int32) int32 { /* io_dec.c:437:12: */ + var buf uintptr = ((*WebPDecParams)(unsafe.Pointer(p)).output + 16 /* &.u */) /* &.RGBA */ + var base_rgba uintptr = ((*WebPRGBABuffer)(unsafe.Pointer(buf)).rgba + uintptr((size_t(y_pos) * size_t((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride)))) + var alpha_dst uintptr = (base_rgba + uintptr(1)) + var num_lines_out int32 = 0 + var colorspace WEBP_CSP_MODE = (*WebPDecBuffer)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).output)).colorspace + var width int32 = (*WebPRescaler)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).scaler_a)).dst_width + var is_premult_alpha int32 = WebPIsPremultipliedMode(tls, colorspace) + var alpha_mask uint32_t = uint32_t(0x0f) + + for (WebPRescalerHasPendingOutput(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_a) != 0) && (num_lines_out < max_lines_out) { + var i int32 + + WebPRescalerExportRow(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_a) + for i = 0; i < width; i++ { + // Fill in the alpha value (converted to 4 bits). + var alpha_value uint32_t = (uint32_t(int32(*(*uint8_t)(unsafe.Pointer((*WebPRescaler)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).scaler_a)).dst + uintptr(i)))) >> 4)) + *(*uint8_t)(unsafe.Pointer(alpha_dst + uintptr((2 * i)))) = (uint8_t((uint32_t(int32(*(*uint8_t)(unsafe.Pointer(alpha_dst + uintptr((2 * i))))) & 0xf0)) | alpha_value)) + alpha_mask = alpha_mask & (alpha_value) + } + alpha_dst += uintptr((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride) + num_lines_out++ + } + if (is_premult_alpha != 0) && (alpha_mask != uint32_t(0x0f)) { + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPApplyAlphaMultiply4444})).f(tls, base_rgba, width, num_lines_out, (*WebPRGBABuffer)(unsafe.Pointer(buf)).stride) + } + return num_lines_out +} + +func EmitRescaledAlphaRGB(tls *libc.TLS, io uintptr, p uintptr, expected_num_out_lines int32) int32 { /* io_dec.c:472:12: */ + if (*VP8Io)(unsafe.Pointer(io)).a != (uintptr(0)) { + var scaler uintptr = (*WebPDecParams)(unsafe.Pointer(p)).scaler_a + var lines_left int32 = expected_num_out_lines + var y_end int32 = ((*WebPDecParams)(unsafe.Pointer(p)).last_y + lines_left) + for lines_left > 0 { + var row_offset int64_t = (int64_t((*WebPRescaler)(unsafe.Pointer(scaler)).src_y) - int64_t((*VP8Io)(unsafe.Pointer(io)).mb_y)) + WebPRescalerImport(tls, scaler, (((*VP8Io)(unsafe.Pointer(io)).mb_h + (*VP8Io)(unsafe.Pointer(io)).mb_y) - (*WebPRescaler)(unsafe.Pointer(scaler)).src_y), + ((*VP8Io)(unsafe.Pointer(io)).a + uintptr((row_offset * int64_t((*VP8Io)(unsafe.Pointer(io)).width)))), (*VP8Io)(unsafe.Pointer(io)).width) + lines_left = lines_left - ((*struct { + f func(*libc.TLS, uintptr, int32, int32) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPDecParams)(unsafe.Pointer(p)).emit_alpha_row})).f(tls, p, (y_end - lines_left), lines_left)) + } + } + return 0 +} + +func InitRGBRescaler(tls *libc.TLS, io uintptr, p uintptr) int32 { /* io_dec.c:488:12: */ + var has_alpha int32 = WebPIsAlphaMode(tls, (*WebPDecBuffer)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).output)).colorspace) + var out_width int32 = (*VP8Io)(unsafe.Pointer(io)).scaled_width + var out_height int32 = (*VP8Io)(unsafe.Pointer(io)).scaled_height + var uv_in_width int32 = (((*VP8Io)(unsafe.Pointer(io)).mb_w + 1) >> 1) + var uv_in_height int32 = (((*VP8Io)(unsafe.Pointer(io)).mb_h + 1) >> 1) + // scratch memory for one rescaler + var work_size size_t = (uint64(2) * size_t(out_width)) + var work uintptr // rescalers work area + var tmp uintptr // tmp storage for scaled YUV444 samples before RGB conversion + var tmp_size1 uint64_t + var tmp_size2 uint64_t + var total_size uint64_t + var rescaler_size size_t + var scalers uintptr + var num_rescalers int32 + if has_alpha != 0 { + num_rescalers = 4 + } else { + num_rescalers = 3 + } + + tmp_size1 = (uint64_t(num_rescalers) * work_size) + tmp_size2 = (uint64_t(num_rescalers) * uint64_t(out_width)) + total_size = ((tmp_size1 * uint64_t(unsafe.Sizeof(rescaler_t(0)))) + (tmp_size2 * uint64_t(unsafe.Sizeof(uint8_t(0))))) + rescaler_size = ((uint64(num_rescalers) * uint64(unsafe.Sizeof(WebPRescaler{}))) + uint64(31)) + total_size = total_size + (rescaler_size) + if !(CheckSizeOverflow(tls, total_size) != 0) { + return 0 + } + + (*WebPDecParams)(unsafe.Pointer(p)).memory = WebPSafeMalloc(tls, 1, total_size) + if (*WebPDecParams)(unsafe.Pointer(p)).memory == (uintptr(0)) { + return 0 // memory error + } + work = (*WebPDecParams)(unsafe.Pointer(p)).memory + tmp = (work + uintptr(tmp_size1)*4) + + scalers = (uintptr((uintptr_t(((work + uintptr(total_size)) - uintptr(rescaler_size))) + uint64(31)) & libc.Uint64FromInt32(libc.CplInt32(31)))) + (*WebPDecParams)(unsafe.Pointer(p)).scaler_y = (scalers) + (*WebPDecParams)(unsafe.Pointer(p)).scaler_u = (scalers + 1*104) + (*WebPDecParams)(unsafe.Pointer(p)).scaler_v = (scalers + 2*104) + (*WebPDecParams)(unsafe.Pointer(p)).scaler_a = func() uintptr { + if has_alpha != 0 { + return (scalers + 3*104) + } + return (uintptr(0)) + }() + + if (!(WebPRescalerInit(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_y, (*VP8Io)(unsafe.Pointer(io)).mb_w, (*VP8Io)(unsafe.Pointer(io)).mb_h, + (tmp+uintptr((0*out_width))), out_width, out_height, 0, 1, + (work+uintptr((uint64(0)*work_size))*4)) != 0) || !(WebPRescalerInit(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_u, uv_in_width, uv_in_height, + (tmp+uintptr((1*out_width))), out_width, out_height, 0, 1, + (work+uintptr((uint64(1)*work_size))*4)) != 0)) || !(WebPRescalerInit(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_v, uv_in_width, uv_in_height, + (tmp+uintptr((2*out_width))), out_width, out_height, 0, 1, + (work+uintptr((uint64(2)*work_size))*4)) != 0) { + return 0 + } + (*WebPDecParams)(unsafe.Pointer(p)).emit = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{EmitRescaledRGB})) + WebPInitYUV444Converters(tls) + + if has_alpha != 0 { + if !(WebPRescalerInit(tls, (*WebPDecParams)(unsafe.Pointer(p)).scaler_a, (*VP8Io)(unsafe.Pointer(io)).mb_w, (*VP8Io)(unsafe.Pointer(io)).mb_h, + (tmp+uintptr((3*out_width))), out_width, out_height, 0, 1, + (work+uintptr((uint64(3)*work_size))*4)) != 0) { + return 0 + } + (*WebPDecParams)(unsafe.Pointer(p)).emit_alpha = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + }{EmitRescaledAlphaRGB})) + if ((*WebPDecBuffer)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).output)).colorspace == MODE_RGBA_4444) || ((*WebPDecBuffer)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).output)).colorspace == MODE_rgbA_4444) { + (*WebPDecParams)(unsafe.Pointer(p)).emit_alpha_row = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32) int32 + }{ExportAlphaRGBA4444})) + } else { + (*WebPDecParams)(unsafe.Pointer(p)).emit_alpha_row = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32) int32 + }{ExportAlpha})) + } + WebPInitAlphaProcessing(tls) + } + return 1 +} + +//------------------------------------------------------------------------------ +// Default custom functions + +func CustomSetup(tls *libc.TLS, io uintptr) int32 { /* io_dec.c:563:12: */ + var p uintptr = (*VP8Io)(unsafe.Pointer(io)).opaque + var colorspace WEBP_CSP_MODE = (*WebPDecBuffer)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(p)).output)).colorspace + var is_rgb int32 = WebPIsRGBMode(tls, colorspace) + var is_alpha int32 = WebPIsAlphaMode(tls, colorspace) + + (*WebPDecParams)(unsafe.Pointer(p)).memory = (uintptr(0)) + (*WebPDecParams)(unsafe.Pointer(p)).emit = (uintptr(0)) + (*WebPDecParams)(unsafe.Pointer(p)).emit_alpha = (uintptr(0)) + (*WebPDecParams)(unsafe.Pointer(p)).emit_alpha_row = (uintptr(0)) + if !(WebPIoInitFromOptions(tls, (*WebPDecParams)(unsafe.Pointer(p)).options, io, func() uint32 { + if is_alpha != 0 { + return MODE_YUV + } + return MODE_YUVA + }()) != 0) { + return 0 + } + if (is_alpha != 0) && (WebPIsPremultipliedMode(tls, colorspace) != 0) { + WebPInitUpsamplers(tls) + } + if (*VP8Io)(unsafe.Pointer(io)).use_scaling != 0 { + var ok int32 + if is_rgb != 0 { + ok = InitRGBRescaler(tls, io, p) + } else { + ok = InitYUVRescaler(tls, io, p) + } + if !(ok != 0) { + return 0 // memory error + } + } else { + if is_rgb != 0 { + WebPInitSamplers(tls) + (*WebPDecParams)(unsafe.Pointer(p)).emit = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{EmitSampledRGB})) // default + if (*VP8Io)(unsafe.Pointer(io)).fancy_upsampling != 0 { + var uv_width int32 = (((*VP8Io)(unsafe.Pointer(io)).mb_w + 1) >> 1) + (*WebPDecParams)(unsafe.Pointer(p)).memory = WebPSafeMalloc(tls, 1, (size_t((*VP8Io)(unsafe.Pointer(io)).mb_w + (2 * uv_width)))) + if (*WebPDecParams)(unsafe.Pointer(p)).memory == (uintptr(0)) { + return 0 // memory error. + } + (*WebPDecParams)(unsafe.Pointer(p)).tmp_y = (*WebPDecParams)(unsafe.Pointer(p)).memory + (*WebPDecParams)(unsafe.Pointer(p)).tmp_u = ((*WebPDecParams)(unsafe.Pointer(p)).tmp_y + uintptr((*VP8Io)(unsafe.Pointer(io)).mb_w)) + (*WebPDecParams)(unsafe.Pointer(p)).tmp_v = ((*WebPDecParams)(unsafe.Pointer(p)).tmp_u + uintptr(uv_width)) + (*WebPDecParams)(unsafe.Pointer(p)).emit = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{EmitFancyRGB})) + WebPInitUpsamplers(tls) + } + } else { + (*WebPDecParams)(unsafe.Pointer(p)).emit = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{EmitYUV})) + } + if is_alpha != 0 { // need transparency output + (*WebPDecParams)(unsafe.Pointer(p)).emit_alpha = func() uintptr { + if (colorspace == MODE_RGBA_4444) || (colorspace == MODE_rgbA_4444) { + return *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + }{EmitAlphaRGBA4444})) + } + return func() uintptr { + if is_rgb != 0 { + return *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + }{EmitAlphaRGB})) + } + return *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + }{EmitAlphaYUV})) + }() + }() + if is_rgb != 0 { + WebPInitAlphaProcessing(tls) + } + } + } + + return 1 +} + +//------------------------------------------------------------------------------ + +func CustomPut(tls *libc.TLS, io uintptr) int32 { /* io_dec.c:626:12: */ + var p uintptr = (*VP8Io)(unsafe.Pointer(io)).opaque + var mb_w int32 = (*VP8Io)(unsafe.Pointer(io)).mb_w + var mb_h int32 = (*VP8Io)(unsafe.Pointer(io)).mb_h + var num_lines_out int32 + + if (mb_w <= 0) || (mb_h <= 0) { + return 0 + } + num_lines_out = (*struct { + f func(*libc.TLS, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPDecParams)(unsafe.Pointer(p)).emit})).f(tls, io, p) + if (*WebPDecParams)(unsafe.Pointer(p)).emit_alpha != (uintptr(0)) { + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPDecParams)(unsafe.Pointer(p)).emit_alpha})).f(tls, io, p, num_lines_out) + } + *(*int32)(unsafe.Pointer((p + 32 /* &.last_y */))) += (num_lines_out) + return 1 +} + +//------------------------------------------------------------------------------ + +func CustomTeardown(tls *libc.TLS, io uintptr) { /* io_dec.c:646:13: */ + var p uintptr = (*VP8Io)(unsafe.Pointer(io)).opaque + WebPSafeFree(tls, (*WebPDecParams)(unsafe.Pointer(p)).memory) + (*WebPDecParams)(unsafe.Pointer(p)).memory = (uintptr(0)) +} + +//------------------------------------------------------------------------------ +// Main entry point + +func WebPInitCustomIo(tls *libc.TLS, params uintptr, io uintptr) { /* io_dec.c:655:6: */ + (*VP8Io)(unsafe.Pointer(io)).put = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr) int32 + }{CustomPut})) + (*VP8Io)(unsafe.Pointer(io)).setup = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr) int32 + }{CustomSetup})) + (*VP8Io)(unsafe.Pointer(io)).teardown = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{CustomTeardown})) + (*VP8Io)(unsafe.Pointer(io)).opaque = params +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +func clip(tls *libc.TLS, v int32, M int32) int32 { /* quant_dec.c:16:24: */ + if v < 0 { + return 0 + } + if v > M { + return M + } + return v +} + +// Paragraph 14.1 +var kDcTable = [128]uint8_t{ + uint8_t(4), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(10), uint8_t(10), + uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(14), uint8_t(15), uint8_t(16), uint8_t(17), uint8_t(17), + uint8_t(18), uint8_t(19), uint8_t(20), uint8_t(20), uint8_t(21), uint8_t(21), uint8_t(22), uint8_t(22), + uint8_t(23), uint8_t(23), uint8_t(24), uint8_t(25), uint8_t(25), uint8_t(26), uint8_t(27), uint8_t(28), + uint8_t(29), uint8_t(30), uint8_t(31), uint8_t(32), uint8_t(33), uint8_t(34), uint8_t(35), uint8_t(36), + uint8_t(37), uint8_t(37), uint8_t(38), uint8_t(39), uint8_t(40), uint8_t(41), uint8_t(42), uint8_t(43), + uint8_t(44), uint8_t(45), uint8_t(46), uint8_t(46), uint8_t(47), uint8_t(48), uint8_t(49), uint8_t(50), + uint8_t(51), uint8_t(52), uint8_t(53), uint8_t(54), uint8_t(55), uint8_t(56), uint8_t(57), uint8_t(58), + uint8_t(59), uint8_t(60), uint8_t(61), uint8_t(62), uint8_t(63), uint8_t(64), uint8_t(65), uint8_t(66), + uint8_t(67), uint8_t(68), uint8_t(69), uint8_t(70), uint8_t(71), uint8_t(72), uint8_t(73), uint8_t(74), + uint8_t(75), uint8_t(76), uint8_t(76), uint8_t(77), uint8_t(78), uint8_t(79), uint8_t(80), uint8_t(81), + uint8_t(82), uint8_t(83), uint8_t(84), uint8_t(85), uint8_t(86), uint8_t(87), uint8_t(88), uint8_t(89), + uint8_t(91), uint8_t(93), uint8_t(95), uint8_t(96), uint8_t(98), uint8_t(100), uint8_t(101), uint8_t(102), + uint8_t(104), uint8_t(106), uint8_t(108), uint8_t(110), uint8_t(112), uint8_t(114), uint8_t(116), uint8_t(118), + uint8_t(122), uint8_t(124), uint8_t(126), uint8_t(128), uint8_t(130), uint8_t(132), uint8_t(134), uint8_t(136), + uint8_t(138), uint8_t(140), uint8_t(143), uint8_t(145), uint8_t(148), uint8_t(151), uint8_t(154), uint8_t(157), +} /* quant_dec.c:21:22 */ + +var kAcTable = [128]uint16_t{ + uint16_t(4), uint16_t(5), uint16_t(6), uint16_t(7), uint16_t(8), uint16_t(9), uint16_t(10), uint16_t(11), + uint16_t(12), uint16_t(13), uint16_t(14), uint16_t(15), uint16_t(16), uint16_t(17), uint16_t(18), uint16_t(19), + uint16_t(20), uint16_t(21), uint16_t(22), uint16_t(23), uint16_t(24), uint16_t(25), uint16_t(26), uint16_t(27), + uint16_t(28), uint16_t(29), uint16_t(30), uint16_t(31), uint16_t(32), uint16_t(33), uint16_t(34), uint16_t(35), + uint16_t(36), uint16_t(37), uint16_t(38), uint16_t(39), uint16_t(40), uint16_t(41), uint16_t(42), uint16_t(43), + uint16_t(44), uint16_t(45), uint16_t(46), uint16_t(47), uint16_t(48), uint16_t(49), uint16_t(50), uint16_t(51), + uint16_t(52), uint16_t(53), uint16_t(54), uint16_t(55), uint16_t(56), uint16_t(57), uint16_t(58), uint16_t(60), + uint16_t(62), uint16_t(64), uint16_t(66), uint16_t(68), uint16_t(70), uint16_t(72), uint16_t(74), uint16_t(76), + uint16_t(78), uint16_t(80), uint16_t(82), uint16_t(84), uint16_t(86), uint16_t(88), uint16_t(90), uint16_t(92), + uint16_t(94), uint16_t(96), uint16_t(98), uint16_t(100), uint16_t(102), uint16_t(104), uint16_t(106), uint16_t(108), + uint16_t(110), uint16_t(112), uint16_t(114), uint16_t(116), uint16_t(119), uint16_t(122), uint16_t(125), uint16_t(128), + uint16_t(131), uint16_t(134), uint16_t(137), uint16_t(140), uint16_t(143), uint16_t(146), uint16_t(149), uint16_t(152), + uint16_t(155), uint16_t(158), uint16_t(161), uint16_t(164), uint16_t(167), uint16_t(170), uint16_t(173), uint16_t(177), + uint16_t(181), uint16_t(185), uint16_t(189), uint16_t(193), uint16_t(197), uint16_t(201), uint16_t(205), uint16_t(209), + uint16_t(213), uint16_t(217), uint16_t(221), uint16_t(225), uint16_t(229), uint16_t(234), uint16_t(239), uint16_t(245), + uint16_t(249), uint16_t(254), uint16_t(259), uint16_t(264), uint16_t(269), uint16_t(274), uint16_t(279), uint16_t(284), +} /* quant_dec.c:40:23 */ + +//------------------------------------------------------------------------------ +// Paragraph 9.6 + +func VP8ParseQuant(tls *libc.TLS, dec uintptr) { /* quant_dec.c:62:6: */ + var br uintptr = (dec + 16 /* &.br_ */) + var base_q0 int32 = int32(VP8GetValue(tls, br, 7)) + var dqy1_dc int32 + if VP8GetValue(tls, br, 1) != 0 { + dqy1_dc = VP8GetSignedValue(tls, br, 4) + } else { + dqy1_dc = 0 + } + var dqy2_dc int32 + if VP8GetValue(tls, br, 1) != 0 { + dqy2_dc = VP8GetSignedValue(tls, br, 4) + } else { + dqy2_dc = 0 + } + var dqy2_ac int32 + if VP8GetValue(tls, br, 1) != 0 { + dqy2_ac = VP8GetSignedValue(tls, br, 4) + } else { + dqy2_ac = 0 + } + var dquv_dc int32 + if VP8GetValue(tls, br, 1) != 0 { + dquv_dc = VP8GetSignedValue(tls, br, 4) + } else { + dquv_dc = 0 + } + var dquv_ac int32 + if VP8GetValue(tls, br, 1) != 0 { + dquv_ac = VP8GetSignedValue(tls, br, 4) + } else { + dquv_ac = 0 + } + + var hdr uintptr = (dec + 128 /* &.segment_hdr_ */) + var i int32 + + for i = 0; i < NUM_MB_SEGMENTS; i++ { + var q int32 + if (*VP8SegmentHeader)(unsafe.Pointer(hdr)).use_segment_ != 0 { + q = int32(*(*int8_t)(unsafe.Pointer((hdr + 12 /* &.quantizer_ */) + uintptr(i)))) + if !((*VP8SegmentHeader)(unsafe.Pointer(hdr)).absolute_delta_ != 0) { + q = q + (base_q0) + } + } else { + if i > 0 { + *(*VP8QuantMatrix)(unsafe.Pointer((dec + 1060 /* &.dqm_ */) + uintptr(i)*32)) = *(*VP8QuantMatrix)(unsafe.Pointer((dec + 1060 /* &.dqm_ */))) + continue + } else { + q = base_q0 + } + } + { + var m uintptr = ((dec + 1060 /* &.dqm_ */) + uintptr(i)*32) + *(*int32)(unsafe.Pointer((m /* &.y1_mat_ */))) = int32(kDcTable[clip(tls, (q+dqy1_dc), 127)]) + *(*int32)(unsafe.Pointer((m /* &.y1_mat_ */) + 1*4)) = int32(kAcTable[clip(tls, (q+0), 127)]) + + *(*int32)(unsafe.Pointer((m + 8 /* &.y2_mat_ */))) = (int32(kDcTable[clip(tls, (q+dqy2_dc), 127)]) * 2) + // For all x in [0..284], x*155/100 is bitwise equal to (x*101581) >> 16. + // The smallest precision for that is '(x*6349) >> 12' but 16 is a good + // word size. + *(*int32)(unsafe.Pointer((m + 8 /* &.y2_mat_ */) + 1*4)) = ((int32(kAcTable[clip(tls, (q+dqy2_ac), 127)]) * 101581) >> 16) + if *(*int32)(unsafe.Pointer((m + 8 /* &.y2_mat_ */) + 1*4)) < 8 { + *(*int32)(unsafe.Pointer((m + 8 /* &.y2_mat_ */) + 1*4)) = 8 + } + + *(*int32)(unsafe.Pointer((m + 16 /* &.uv_mat_ */))) = int32(kDcTable[clip(tls, (q+dquv_dc), 117)]) + *(*int32)(unsafe.Pointer((m + 16 /* &.uv_mat_ */) + 1*4)) = int32(kAcTable[clip(tls, (q+dquv_ac), 127)]) + + (*VP8QuantMatrix)(unsafe.Pointer(m)).uv_quant_ = (q + dquv_ac) // for dithering strength evaluation + + } + } +} + +//------------------------------------------------------------------------------ + +func BSwap32(tls *libc.TLS, x uint32_t) uint32_t { /* endian_inl_utils.h:53:29: */ + return libc.X__builtin_bswap32(tls, x) +} + +func BSwap64(tls *libc.TLS, x uint64_t) uint64_t { /* endian_inl_utils.h:76:29: */ + return libc.X__builtin_bswap64(tls, x) +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Derived type lbit_t = natural type for memory I/O + +type lbit_t = uint64_t /* bit_reader_inl_utils.h:38:18 */ + +//------------------------------------------------------------------------------ +// Inlined critical functions + +// makes sure br->value_ has at least BITS bits worth of data +func VP8LoadNewBytes(tls *libc.TLS, br uintptr) { /* bit_reader_inl_utils.h:58:6: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + // Read 'BITS' bits at a time if possible. + if (*VP8BitReader)(unsafe.Pointer(br)).buf_ < (*VP8BitReader)(unsafe.Pointer(br)).buf_max_ { + // convert memory type to register type (with some zero'ing!) + var bits bit_t + // var in_bits lbit_t at bp, 8 + + libc.Xmemcpy(tls, (bp) /* &in_bits */, (*VP8BitReader)(unsafe.Pointer(br)).buf_, uint64(unsafe.Sizeof(lbit_t(0)))) + *(*uintptr)(unsafe.Pointer((br + 16 /* &.buf_ */))) += (uintptr(int32(56) >> 3)) + bits = BSwap64(tls, *(*lbit_t)(unsafe.Pointer(bp /* in_bits */))) + bits >>= (64 - 56) + (*VP8BitReader)(unsafe.Pointer(br)).value_ = (bits | ((*VP8BitReader)(unsafe.Pointer(br)).value_ << 56)) + *(*int32)(unsafe.Pointer((br + 12 /* &.bits_ */))) += (56) + } else { + VP8LoadFinalBytes(tls, br) // no need to be inlined + } +} + +// Read a bit with proba 'prob'. Speed-critical function! +func VP8GetBit(tls *libc.TLS, br uintptr, prob int32) int32 { /* bit_reader_inl_utils.h:107:24: */ + // Don't move this declaration! It makes a big speed difference to store + // 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't + // alter br->range_ value. + var range1 range_t = (*VP8BitReader)(unsafe.Pointer(br)).range_ + if (*VP8BitReader)(unsafe.Pointer(br)).bits_ < 0 { + VP8LoadNewBytes(tls, br) + } + { + var pos int32 = (*VP8BitReader)(unsafe.Pointer(br)).bits_ + var split range_t = ((range1 * range_t(prob)) >> 8) + var value range_t = (range_t((*VP8BitReader)(unsafe.Pointer(br)).value_ >> pos)) + var bit int32 = (libc.Bool32(value > split)) + if bit != 0 { + range1 = range1 - (split) + *(*bit_t)(unsafe.Pointer((br /* &.value_ */))) -= ((bit_t(split + range_t(1))) << pos) + } else { + range1 = (split + range_t(1)) + } + { + var shift int32 = (7 ^ BitsLog2Floor(tls, range1)) + range1 <<= shift + *(*int32)(unsafe.Pointer((br + 12 /* &.bits_ */))) -= (shift) + + } + (*VP8BitReader)(unsafe.Pointer(br)).range_ = (range1 - range_t(1)) + + return bit + + } + return int32(0) +} + +// simplified version of VP8GetBit() for prob=0x80 (note shift is always 1 here) +func VP8GetSigned(tls *libc.TLS, br uintptr, v int32) int32 { /* bit_reader_inl_utils.h:140:5: */ + if (*VP8BitReader)(unsafe.Pointer(br)).bits_ < 0 { + VP8LoadNewBytes(tls, br) + } + { + var pos int32 = (*VP8BitReader)(unsafe.Pointer(br)).bits_ + var split range_t = ((*VP8BitReader)(unsafe.Pointer(br)).range_ >> 1) + var value range_t = (range_t((*VP8BitReader)(unsafe.Pointer(br)).value_ >> pos)) + var mask int32_t = ((int32_t(split - value)) >> 31) // -1 or 0 + *(*int32)(unsafe.Pointer((br + 12 /* &.bits_ */))) -= (1) + *(*range_t)(unsafe.Pointer((br + 8 /* &.range_ */))) += (range_t(mask)) + *(*range_t)(unsafe.Pointer((br + 8 /* &.range_ */))) |= (range_t(1)) + *(*bit_t)(unsafe.Pointer((br /* &.value_ */))) -= ((bit_t((split + range_t(1)) & range_t(mask))) << pos) + + return ((v ^ mask) - mask) + + } + return int32(0) +} + +func VP8GetBitAlt(tls *libc.TLS, br uintptr, prob int32) int32 { /* bit_reader_inl_utils.h:159:24: */ + // Don't move this declaration! It makes a big speed difference to store + // 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't + // alter br->range_ value. + var range1 range_t = (*VP8BitReader)(unsafe.Pointer(br)).range_ + if (*VP8BitReader)(unsafe.Pointer(br)).bits_ < 0 { + VP8LoadNewBytes(tls, br) + } + { + var pos int32 = (*VP8BitReader)(unsafe.Pointer(br)).bits_ + var split range_t = ((range1 * range_t(prob)) >> 8) + var value range_t = (range_t((*VP8BitReader)(unsafe.Pointer(br)).value_ >> pos)) + var bit int32 // Don't use 'const int bit = (value > split);", it's slower. + if value > split { + range1 = range1 - (split + range_t(1)) + *(*bit_t)(unsafe.Pointer((br /* &.value_ */))) -= ((bit_t(split + range_t(1))) << pos) + bit = 1 + } else { + range1 = split + bit = 0 + } + if range1 <= range_t(0x7e) { + var shift int32 = int32(kVP8Log2Range[range1]) + range1 = range_t(kVP8NewRange[range1]) + *(*int32)(unsafe.Pointer((br + 12 /* &.bits_ */))) -= (shift) + } + (*VP8BitReader)(unsafe.Pointer(br)).range_ = range1 + + return bit + + } + return int32(0) +} + +// using a table is ~1-2% slower on ARM. Prefer the coded-tree approach then. + +var kYModesIntra4 = [18]int8_t{ + int8(-B_DC_PRED), int8(1), + int8(-B_TM_PRED), int8(2), + int8(-B_VE_PRED), int8(3), + int8(4), int8(6), + int8(-B_HE_PRED), int8(5), + int8(-B_RD_PRED), int8(-B_VR_PRED), + int8(-B_LD_PRED), int8(7), + int8(-B_VL_PRED), int8(8), + int8(-B_HD_PRED), int8(-B_HU_PRED), +} /* tree_dec.c:27:21 */ + +//------------------------------------------------------------------------------ +// Default probabilities + +// Paragraph 13.5 +var CoeffsProba0 = [4][8][3][11]uint8_t{[8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(253), uint8_t(136), uint8_t(254), uint8_t(255), uint8_t(228), uint8_t(219), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(189), uint8_t(129), uint8_t(242), uint8_t(255), uint8_t(227), uint8_t(213), uint8_t(255), uint8_t(219), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(106), uint8_t(126), uint8_t(227), uint8_t(252), uint8_t(214), uint8_t(209), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(98), uint8_t(248), uint8_t(255), uint8_t(236), uint8_t(226), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(181), uint8_t(133), uint8_t(238), uint8_t(254), uint8_t(221), uint8_t(234), uint8_t(255), uint8_t(154), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(78), uint8_t(134), uint8_t(202), uint8_t(247), uint8_t(198), uint8_t(180), uint8_t(255), uint8_t(219), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(185), uint8_t(249), uint8_t(255), uint8_t(243), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(184), uint8_t(150), uint8_t(247), uint8_t(255), uint8_t(236), uint8_t(224), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(77), uint8_t(110), uint8_t(216), uint8_t(255), uint8_t(236), uint8_t(230), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(101), uint8_t(251), uint8_t(255), uint8_t(241), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(170), uint8_t(139), uint8_t(241), uint8_t(252), uint8_t(236), uint8_t(209), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(37), uint8_t(116), uint8_t(196), uint8_t(243), uint8_t(228), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(204), uint8_t(254), uint8_t(255), uint8_t(245), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(207), uint8_t(160), uint8_t(250), uint8_t(255), uint8_t(238), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(102), uint8_t(103), uint8_t(231), uint8_t(255), uint8_t(211), uint8_t(171), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(152), uint8_t(252), uint8_t(255), uint8_t(240), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(177), uint8_t(135), uint8_t(243), uint8_t(255), uint8_t(234), uint8_t(225), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(80), uint8_t(129), uint8_t(211), uint8_t(255), uint8_t(194), uint8_t(224), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(1), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(246), uint8_t(1), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, +}, + [8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(198), uint8_t(35), uint8_t(237), uint8_t(223), uint8_t(193), uint8_t(187), uint8_t(162), uint8_t(160), uint8_t(145), uint8_t(155), uint8_t(62)}, + [11]uint8_t{uint8_t(131), uint8_t(45), uint8_t(198), uint8_t(221), uint8_t(172), uint8_t(176), uint8_t(220), uint8_t(157), uint8_t(252), uint8_t(221), uint8_t(1)}, + [11]uint8_t{uint8_t(68), uint8_t(47), uint8_t(146), uint8_t(208), uint8_t(149), uint8_t(167), uint8_t(221), uint8_t(162), uint8_t(255), uint8_t(223), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(149), uint8_t(241), uint8_t(255), uint8_t(221), uint8_t(224), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(184), uint8_t(141), uint8_t(234), uint8_t(253), uint8_t(222), uint8_t(220), uint8_t(255), uint8_t(199), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(81), uint8_t(99), uint8_t(181), uint8_t(242), uint8_t(176), uint8_t(190), uint8_t(249), uint8_t(202), uint8_t(255), uint8_t(255), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(129), uint8_t(232), uint8_t(253), uint8_t(214), uint8_t(197), uint8_t(242), uint8_t(196), uint8_t(255), uint8_t(255), uint8_t(128)}, + [11]uint8_t{uint8_t(99), uint8_t(121), uint8_t(210), uint8_t(250), uint8_t(201), uint8_t(198), uint8_t(255), uint8_t(202), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(23), uint8_t(91), uint8_t(163), uint8_t(242), uint8_t(170), uint8_t(187), uint8_t(247), uint8_t(210), uint8_t(255), uint8_t(255), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(200), uint8_t(246), uint8_t(255), uint8_t(234), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(109), uint8_t(178), uint8_t(241), uint8_t(255), uint8_t(231), uint8_t(245), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(44), uint8_t(130), uint8_t(201), uint8_t(253), uint8_t(205), uint8_t(192), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(132), uint8_t(239), uint8_t(251), uint8_t(219), uint8_t(209), uint8_t(255), uint8_t(165), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(94), uint8_t(136), uint8_t(225), uint8_t(251), uint8_t(218), uint8_t(190), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(22), uint8_t(100), uint8_t(174), uint8_t(245), uint8_t(186), uint8_t(161), uint8_t(255), uint8_t(199), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(182), uint8_t(249), uint8_t(255), uint8_t(232), uint8_t(235), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(124), uint8_t(143), uint8_t(241), uint8_t(255), uint8_t(227), uint8_t(234), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(35), uint8_t(77), uint8_t(181), uint8_t(251), uint8_t(193), uint8_t(211), uint8_t(255), uint8_t(205), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(157), uint8_t(247), uint8_t(255), uint8_t(236), uint8_t(231), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(121), uint8_t(141), uint8_t(235), uint8_t(255), uint8_t(225), uint8_t(227), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(45), uint8_t(99), uint8_t(188), uint8_t(251), uint8_t(195), uint8_t(217), uint8_t(255), uint8_t(224), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(1), uint8_t(251), uint8_t(255), uint8_t(213), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(203), uint8_t(1), uint8_t(248), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(137), uint8_t(1), uint8_t(177), uint8_t(255), uint8_t(224), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + }, + [8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(253), uint8_t(9), uint8_t(248), uint8_t(251), uint8_t(207), uint8_t(208), uint8_t(255), uint8_t(192), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(175), uint8_t(13), uint8_t(224), uint8_t(243), uint8_t(193), uint8_t(185), uint8_t(249), uint8_t(198), uint8_t(255), uint8_t(255), uint8_t(128)}, + [11]uint8_t{uint8_t(73), uint8_t(17), uint8_t(171), uint8_t(221), uint8_t(161), uint8_t(179), uint8_t(236), uint8_t(167), uint8_t(255), uint8_t(234), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(95), uint8_t(247), uint8_t(253), uint8_t(212), uint8_t(183), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(239), uint8_t(90), uint8_t(244), uint8_t(250), uint8_t(211), uint8_t(209), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(155), uint8_t(77), uint8_t(195), uint8_t(248), uint8_t(188), uint8_t(195), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(24), uint8_t(239), uint8_t(251), uint8_t(218), uint8_t(219), uint8_t(255), uint8_t(205), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(201), uint8_t(51), uint8_t(219), uint8_t(255), uint8_t(196), uint8_t(186), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(69), uint8_t(46), uint8_t(190), uint8_t(239), uint8_t(201), uint8_t(218), uint8_t(255), uint8_t(228), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(191), uint8_t(251), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(223), uint8_t(165), uint8_t(249), uint8_t(255), uint8_t(213), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(141), uint8_t(124), uint8_t(248), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(16), uint8_t(248), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(190), uint8_t(36), uint8_t(230), uint8_t(255), uint8_t(236), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(149), uint8_t(1), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(226), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(247), uint8_t(192), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(240), uint8_t(128), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(134), uint8_t(252), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(213), uint8_t(62), uint8_t(250), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(55), uint8_t(93), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + }, + [8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(202), uint8_t(24), uint8_t(213), uint8_t(235), uint8_t(186), uint8_t(191), uint8_t(220), uint8_t(160), uint8_t(240), uint8_t(175), uint8_t(255)}, + [11]uint8_t{uint8_t(126), uint8_t(38), uint8_t(182), uint8_t(232), uint8_t(169), uint8_t(184), uint8_t(228), uint8_t(174), uint8_t(255), uint8_t(187), uint8_t(128)}, + [11]uint8_t{uint8_t(61), uint8_t(46), uint8_t(138), uint8_t(219), uint8_t(151), uint8_t(178), uint8_t(240), uint8_t(170), uint8_t(255), uint8_t(216), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(112), uint8_t(230), uint8_t(250), uint8_t(199), uint8_t(191), uint8_t(247), uint8_t(159), uint8_t(255), uint8_t(255), uint8_t(128)}, + [11]uint8_t{uint8_t(166), uint8_t(109), uint8_t(228), uint8_t(252), uint8_t(211), uint8_t(215), uint8_t(255), uint8_t(174), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(39), uint8_t(77), uint8_t(162), uint8_t(232), uint8_t(172), uint8_t(180), uint8_t(245), uint8_t(178), uint8_t(255), uint8_t(255), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(52), uint8_t(220), uint8_t(246), uint8_t(198), uint8_t(199), uint8_t(249), uint8_t(220), uint8_t(255), uint8_t(255), uint8_t(128)}, + [11]uint8_t{uint8_t(124), uint8_t(74), uint8_t(191), uint8_t(243), uint8_t(183), uint8_t(193), uint8_t(250), uint8_t(221), uint8_t(255), uint8_t(255), uint8_t(128)}, + [11]uint8_t{uint8_t(24), uint8_t(71), uint8_t(130), uint8_t(219), uint8_t(154), uint8_t(170), uint8_t(243), uint8_t(182), uint8_t(255), uint8_t(255), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(182), uint8_t(225), uint8_t(249), uint8_t(219), uint8_t(240), uint8_t(255), uint8_t(224), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(149), uint8_t(150), uint8_t(226), uint8_t(252), uint8_t(216), uint8_t(205), uint8_t(255), uint8_t(171), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(28), uint8_t(108), uint8_t(170), uint8_t(242), uint8_t(183), uint8_t(194), uint8_t(254), uint8_t(223), uint8_t(255), uint8_t(255), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(81), uint8_t(230), uint8_t(252), uint8_t(204), uint8_t(203), uint8_t(255), uint8_t(192), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(123), uint8_t(102), uint8_t(209), uint8_t(247), uint8_t(188), uint8_t(196), uint8_t(255), uint8_t(233), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(20), uint8_t(95), uint8_t(153), uint8_t(243), uint8_t(164), uint8_t(173), uint8_t(255), uint8_t(203), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(222), uint8_t(248), uint8_t(255), uint8_t(216), uint8_t(213), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(168), uint8_t(175), uint8_t(246), uint8_t(252), uint8_t(235), uint8_t(205), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(47), uint8_t(116), uint8_t(215), uint8_t(255), uint8_t(211), uint8_t(212), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(121), uint8_t(236), uint8_t(253), uint8_t(212), uint8_t(214), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(141), uint8_t(84), uint8_t(213), uint8_t(252), uint8_t(201), uint8_t(202), uint8_t(255), uint8_t(219), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(42), uint8_t(80), uint8_t(160), uint8_t(240), uint8_t(162), uint8_t(185), uint8_t(255), uint8_t(205), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(1), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(244), uint8_t(1), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(238), uint8_t(1), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + }, +} /* tree_dec.c:45:3 */ + +// Paragraph 11.5 +var kBModesProba = [10][10][9]uint8_t{[10][9]uint8_t{ + [9]uint8_t{uint8_t(231), uint8_t(120), uint8_t(48), uint8_t(89), uint8_t(115), uint8_t(113), uint8_t(120), uint8_t(152), uint8_t(112)}, + [9]uint8_t{uint8_t(152), uint8_t(179), uint8_t(64), uint8_t(126), uint8_t(170), uint8_t(118), uint8_t(46), uint8_t(70), uint8_t(95)}, + [9]uint8_t{uint8_t(175), uint8_t(69), uint8_t(143), uint8_t(80), uint8_t(85), uint8_t(82), uint8_t(72), uint8_t(155), uint8_t(103)}, + [9]uint8_t{uint8_t(56), uint8_t(58), uint8_t(10), uint8_t(171), uint8_t(218), uint8_t(189), uint8_t(17), uint8_t(13), uint8_t(152)}, + [9]uint8_t{uint8_t(114), uint8_t(26), uint8_t(17), uint8_t(163), uint8_t(44), uint8_t(195), uint8_t(21), uint8_t(10), uint8_t(173)}, + [9]uint8_t{uint8_t(121), uint8_t(24), uint8_t(80), uint8_t(195), uint8_t(26), uint8_t(62), uint8_t(44), uint8_t(64), uint8_t(85)}, + [9]uint8_t{uint8_t(144), uint8_t(71), uint8_t(10), uint8_t(38), uint8_t(171), uint8_t(213), uint8_t(144), uint8_t(34), uint8_t(26)}, + [9]uint8_t{uint8_t(170), uint8_t(46), uint8_t(55), uint8_t(19), uint8_t(136), uint8_t(160), uint8_t(33), uint8_t(206), uint8_t(71)}, + [9]uint8_t{uint8_t(63), uint8_t(20), uint8_t(8), uint8_t(114), uint8_t(114), uint8_t(208), uint8_t(12), uint8_t(9), uint8_t(226)}, + [9]uint8_t{uint8_t(81), uint8_t(40), uint8_t(11), uint8_t(96), uint8_t(182), uint8_t(84), uint8_t(29), uint8_t(16), uint8_t(36)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(134), uint8_t(183), uint8_t(89), uint8_t(137), uint8_t(98), uint8_t(101), uint8_t(106), uint8_t(165), uint8_t(148)}, + [9]uint8_t{uint8_t(72), uint8_t(187), uint8_t(100), uint8_t(130), uint8_t(157), uint8_t(111), uint8_t(32), uint8_t(75), uint8_t(80)}, + [9]uint8_t{uint8_t(66), uint8_t(102), uint8_t(167), uint8_t(99), uint8_t(74), uint8_t(62), uint8_t(40), uint8_t(234), uint8_t(128)}, + [9]uint8_t{uint8_t(41), uint8_t(53), uint8_t(9), uint8_t(178), uint8_t(241), uint8_t(141), uint8_t(26), uint8_t(8), uint8_t(107)}, + [9]uint8_t{uint8_t(74), uint8_t(43), uint8_t(26), uint8_t(146), uint8_t(73), uint8_t(166), uint8_t(49), uint8_t(23), uint8_t(157)}, + [9]uint8_t{uint8_t(65), uint8_t(38), uint8_t(105), uint8_t(160), uint8_t(51), uint8_t(52), uint8_t(31), uint8_t(115), uint8_t(128)}, + [9]uint8_t{uint8_t(104), uint8_t(79), uint8_t(12), uint8_t(27), uint8_t(217), uint8_t(255), uint8_t(87), uint8_t(17), uint8_t(7)}, + [9]uint8_t{uint8_t(87), uint8_t(68), uint8_t(71), uint8_t(44), uint8_t(114), uint8_t(51), uint8_t(15), uint8_t(186), uint8_t(23)}, + [9]uint8_t{uint8_t(47), uint8_t(41), uint8_t(14), uint8_t(110), uint8_t(182), uint8_t(183), uint8_t(21), uint8_t(17), uint8_t(194)}, + [9]uint8_t{uint8_t(66), uint8_t(45), uint8_t(25), uint8_t(102), uint8_t(197), uint8_t(189), uint8_t(23), uint8_t(18), uint8_t(22)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(88), uint8_t(88), uint8_t(147), uint8_t(150), uint8_t(42), uint8_t(46), uint8_t(45), uint8_t(196), uint8_t(205)}, + [9]uint8_t{uint8_t(43), uint8_t(97), uint8_t(183), uint8_t(117), uint8_t(85), uint8_t(38), uint8_t(35), uint8_t(179), uint8_t(61)}, + [9]uint8_t{uint8_t(39), uint8_t(53), uint8_t(200), uint8_t(87), uint8_t(26), uint8_t(21), uint8_t(43), uint8_t(232), uint8_t(171)}, + [9]uint8_t{uint8_t(56), uint8_t(34), uint8_t(51), uint8_t(104), uint8_t(114), uint8_t(102), uint8_t(29), uint8_t(93), uint8_t(77)}, + [9]uint8_t{uint8_t(39), uint8_t(28), uint8_t(85), uint8_t(171), uint8_t(58), uint8_t(165), uint8_t(90), uint8_t(98), uint8_t(64)}, + [9]uint8_t{uint8_t(34), uint8_t(22), uint8_t(116), uint8_t(206), uint8_t(23), uint8_t(34), uint8_t(43), uint8_t(166), uint8_t(73)}, + [9]uint8_t{uint8_t(107), uint8_t(54), uint8_t(32), uint8_t(26), uint8_t(51), uint8_t(1), uint8_t(81), uint8_t(43), uint8_t(31)}, + [9]uint8_t{uint8_t(68), uint8_t(25), uint8_t(106), uint8_t(22), uint8_t(64), uint8_t(171), uint8_t(36), uint8_t(225), uint8_t(114)}, + [9]uint8_t{uint8_t(34), uint8_t(19), uint8_t(21), uint8_t(102), uint8_t(132), uint8_t(188), uint8_t(16), uint8_t(76), uint8_t(124)}, + [9]uint8_t{uint8_t(62), uint8_t(18), uint8_t(78), uint8_t(95), uint8_t(85), uint8_t(57), uint8_t(50), uint8_t(48), uint8_t(51)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(193), uint8_t(101), uint8_t(35), uint8_t(159), uint8_t(215), uint8_t(111), uint8_t(89), uint8_t(46), uint8_t(111)}, + [9]uint8_t{uint8_t(60), uint8_t(148), uint8_t(31), uint8_t(172), uint8_t(219), uint8_t(228), uint8_t(21), uint8_t(18), uint8_t(111)}, + [9]uint8_t{uint8_t(112), uint8_t(113), uint8_t(77), uint8_t(85), uint8_t(179), uint8_t(255), uint8_t(38), uint8_t(120), uint8_t(114)}, + [9]uint8_t{uint8_t(40), uint8_t(42), uint8_t(1), uint8_t(196), uint8_t(245), uint8_t(209), uint8_t(10), uint8_t(25), uint8_t(109)}, + [9]uint8_t{uint8_t(88), uint8_t(43), uint8_t(29), uint8_t(140), uint8_t(166), uint8_t(213), uint8_t(37), uint8_t(43), uint8_t(154)}, + [9]uint8_t{uint8_t(61), uint8_t(63), uint8_t(30), uint8_t(155), uint8_t(67), uint8_t(45), uint8_t(68), uint8_t(1), uint8_t(209)}, + [9]uint8_t{uint8_t(100), uint8_t(80), uint8_t(8), uint8_t(43), uint8_t(154), uint8_t(1), uint8_t(51), uint8_t(26), uint8_t(71)}, + [9]uint8_t{uint8_t(142), uint8_t(78), uint8_t(78), uint8_t(16), uint8_t(255), uint8_t(128), uint8_t(34), uint8_t(197), uint8_t(171)}, + [9]uint8_t{uint8_t(41), uint8_t(40), uint8_t(5), uint8_t(102), uint8_t(211), uint8_t(183), uint8_t(4), uint8_t(1), uint8_t(221)}, + [9]uint8_t{uint8_t(51), uint8_t(50), uint8_t(17), uint8_t(168), uint8_t(209), uint8_t(192), uint8_t(23), uint8_t(25), uint8_t(82)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(138), uint8_t(31), uint8_t(36), uint8_t(171), uint8_t(27), uint8_t(166), uint8_t(38), uint8_t(44), uint8_t(229)}, + [9]uint8_t{uint8_t(67), uint8_t(87), uint8_t(58), uint8_t(169), uint8_t(82), uint8_t(115), uint8_t(26), uint8_t(59), uint8_t(179)}, + [9]uint8_t{uint8_t(63), uint8_t(59), uint8_t(90), uint8_t(180), uint8_t(59), uint8_t(166), uint8_t(93), uint8_t(73), uint8_t(154)}, + [9]uint8_t{uint8_t(40), uint8_t(40), uint8_t(21), uint8_t(116), uint8_t(143), uint8_t(209), uint8_t(34), uint8_t(39), uint8_t(175)}, + [9]uint8_t{uint8_t(47), uint8_t(15), uint8_t(16), uint8_t(183), uint8_t(34), uint8_t(223), uint8_t(49), uint8_t(45), uint8_t(183)}, + [9]uint8_t{uint8_t(46), uint8_t(17), uint8_t(33), uint8_t(183), uint8_t(6), uint8_t(98), uint8_t(15), uint8_t(32), uint8_t(183)}, + [9]uint8_t{uint8_t(57), uint8_t(46), uint8_t(22), uint8_t(24), uint8_t(128), uint8_t(1), uint8_t(54), uint8_t(17), uint8_t(37)}, + [9]uint8_t{uint8_t(65), uint8_t(32), uint8_t(73), uint8_t(115), uint8_t(28), uint8_t(128), uint8_t(23), uint8_t(128), uint8_t(205)}, + [9]uint8_t{uint8_t(40), uint8_t(3), uint8_t(9), uint8_t(115), uint8_t(51), uint8_t(192), uint8_t(18), uint8_t(6), uint8_t(223)}, + [9]uint8_t{uint8_t(87), uint8_t(37), uint8_t(9), uint8_t(115), uint8_t(59), uint8_t(77), uint8_t(64), uint8_t(21), uint8_t(47)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(104), uint8_t(55), uint8_t(44), uint8_t(218), uint8_t(9), uint8_t(54), uint8_t(53), uint8_t(130), uint8_t(226)}, + [9]uint8_t{uint8_t(64), uint8_t(90), uint8_t(70), uint8_t(205), uint8_t(40), uint8_t(41), uint8_t(23), uint8_t(26), uint8_t(57)}, + [9]uint8_t{uint8_t(54), uint8_t(57), uint8_t(112), uint8_t(184), uint8_t(5), uint8_t(41), uint8_t(38), uint8_t(166), uint8_t(213)}, + [9]uint8_t{uint8_t(30), uint8_t(34), uint8_t(26), uint8_t(133), uint8_t(152), uint8_t(116), uint8_t(10), uint8_t(32), uint8_t(134)}, + [9]uint8_t{uint8_t(39), uint8_t(19), uint8_t(53), uint8_t(221), uint8_t(26), uint8_t(114), uint8_t(32), uint8_t(73), uint8_t(255)}, + [9]uint8_t{uint8_t(31), uint8_t(9), uint8_t(65), uint8_t(234), uint8_t(2), uint8_t(15), uint8_t(1), uint8_t(118), uint8_t(73)}, + [9]uint8_t{uint8_t(75), uint8_t(32), uint8_t(12), uint8_t(51), uint8_t(192), uint8_t(255), uint8_t(160), uint8_t(43), uint8_t(51)}, + [9]uint8_t{uint8_t(88), uint8_t(31), uint8_t(35), uint8_t(67), uint8_t(102), uint8_t(85), uint8_t(55), uint8_t(186), uint8_t(85)}, + [9]uint8_t{uint8_t(56), uint8_t(21), uint8_t(23), uint8_t(111), uint8_t(59), uint8_t(205), uint8_t(45), uint8_t(37), uint8_t(192)}, + [9]uint8_t{uint8_t(55), uint8_t(38), uint8_t(70), uint8_t(124), uint8_t(73), uint8_t(102), uint8_t(1), uint8_t(34), uint8_t(98)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(125), uint8_t(98), uint8_t(42), uint8_t(88), uint8_t(104), uint8_t(85), uint8_t(117), uint8_t(175), uint8_t(82)}, + [9]uint8_t{uint8_t(95), uint8_t(84), uint8_t(53), uint8_t(89), uint8_t(128), uint8_t(100), uint8_t(113), uint8_t(101), uint8_t(45)}, + [9]uint8_t{uint8_t(75), uint8_t(79), uint8_t(123), uint8_t(47), uint8_t(51), uint8_t(128), uint8_t(81), uint8_t(171), uint8_t(1)}, + [9]uint8_t{uint8_t(57), uint8_t(17), uint8_t(5), uint8_t(71), uint8_t(102), uint8_t(57), uint8_t(53), uint8_t(41), uint8_t(49)}, + [9]uint8_t{uint8_t(38), uint8_t(33), uint8_t(13), uint8_t(121), uint8_t(57), uint8_t(73), uint8_t(26), uint8_t(1), uint8_t(85)}, + [9]uint8_t{uint8_t(41), uint8_t(10), uint8_t(67), uint8_t(138), uint8_t(77), uint8_t(110), uint8_t(90), uint8_t(47), uint8_t(114)}, + [9]uint8_t{uint8_t(115), uint8_t(21), uint8_t(2), uint8_t(10), uint8_t(102), uint8_t(255), uint8_t(166), uint8_t(23), uint8_t(6)}, + [9]uint8_t{uint8_t(101), uint8_t(29), uint8_t(16), uint8_t(10), uint8_t(85), uint8_t(128), uint8_t(101), uint8_t(196), uint8_t(26)}, + [9]uint8_t{uint8_t(57), uint8_t(18), uint8_t(10), uint8_t(102), uint8_t(102), uint8_t(213), uint8_t(34), uint8_t(20), uint8_t(43)}, + [9]uint8_t{uint8_t(117), uint8_t(20), uint8_t(15), uint8_t(36), uint8_t(163), uint8_t(128), uint8_t(68), uint8_t(1), uint8_t(26)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(102), uint8_t(61), uint8_t(71), uint8_t(37), uint8_t(34), uint8_t(53), uint8_t(31), uint8_t(243), uint8_t(192)}, + [9]uint8_t{uint8_t(69), uint8_t(60), uint8_t(71), uint8_t(38), uint8_t(73), uint8_t(119), uint8_t(28), uint8_t(222), uint8_t(37)}, + [9]uint8_t{uint8_t(68), uint8_t(45), uint8_t(128), uint8_t(34), uint8_t(1), uint8_t(47), uint8_t(11), uint8_t(245), uint8_t(171)}, + [9]uint8_t{uint8_t(62), uint8_t(17), uint8_t(19), uint8_t(70), uint8_t(146), uint8_t(85), uint8_t(55), uint8_t(62), uint8_t(70)}, + [9]uint8_t{uint8_t(37), uint8_t(43), uint8_t(37), uint8_t(154), uint8_t(100), uint8_t(163), uint8_t(85), uint8_t(160), uint8_t(1)}, + [9]uint8_t{uint8_t(63), uint8_t(9), uint8_t(92), uint8_t(136), uint8_t(28), uint8_t(64), uint8_t(32), uint8_t(201), uint8_t(85)}, + [9]uint8_t{uint8_t(75), uint8_t(15), uint8_t(9), uint8_t(9), uint8_t(64), uint8_t(255), uint8_t(184), uint8_t(119), uint8_t(16)}, + [9]uint8_t{uint8_t(86), uint8_t(6), uint8_t(28), uint8_t(5), uint8_t(64), uint8_t(255), uint8_t(25), uint8_t(248), uint8_t(1)}, + [9]uint8_t{uint8_t(56), uint8_t(8), uint8_t(17), uint8_t(132), uint8_t(137), uint8_t(255), uint8_t(55), uint8_t(116), uint8_t(128)}, + [9]uint8_t{uint8_t(58), uint8_t(15), uint8_t(20), uint8_t(82), uint8_t(135), uint8_t(57), uint8_t(26), uint8_t(121), uint8_t(40)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(164), uint8_t(50), uint8_t(31), uint8_t(137), uint8_t(154), uint8_t(133), uint8_t(25), uint8_t(35), uint8_t(218)}, + [9]uint8_t{uint8_t(51), uint8_t(103), uint8_t(44), uint8_t(131), uint8_t(131), uint8_t(123), uint8_t(31), uint8_t(6), uint8_t(158)}, + [9]uint8_t{uint8_t(86), uint8_t(40), uint8_t(64), uint8_t(135), uint8_t(148), uint8_t(224), uint8_t(45), uint8_t(183), uint8_t(128)}, + [9]uint8_t{uint8_t(22), uint8_t(26), uint8_t(17), uint8_t(131), uint8_t(240), uint8_t(154), uint8_t(14), uint8_t(1), uint8_t(209)}, + [9]uint8_t{uint8_t(45), uint8_t(16), uint8_t(21), uint8_t(91), uint8_t(64), uint8_t(222), uint8_t(7), uint8_t(1), uint8_t(197)}, + [9]uint8_t{uint8_t(56), uint8_t(21), uint8_t(39), uint8_t(155), uint8_t(60), uint8_t(138), uint8_t(23), uint8_t(102), uint8_t(213)}, + [9]uint8_t{uint8_t(83), uint8_t(12), uint8_t(13), uint8_t(54), uint8_t(192), uint8_t(255), uint8_t(68), uint8_t(47), uint8_t(28)}, + [9]uint8_t{uint8_t(85), uint8_t(26), uint8_t(85), uint8_t(85), uint8_t(128), uint8_t(128), uint8_t(32), uint8_t(146), uint8_t(171)}, + [9]uint8_t{uint8_t(18), uint8_t(11), uint8_t(7), uint8_t(63), uint8_t(144), uint8_t(171), uint8_t(4), uint8_t(4), uint8_t(246)}, + [9]uint8_t{uint8_t(35), uint8_t(27), uint8_t(10), uint8_t(146), uint8_t(174), uint8_t(171), uint8_t(12), uint8_t(26), uint8_t(128)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(190), uint8_t(80), uint8_t(35), uint8_t(99), uint8_t(180), uint8_t(80), uint8_t(126), uint8_t(54), uint8_t(45)}, + [9]uint8_t{uint8_t(85), uint8_t(126), uint8_t(47), uint8_t(87), uint8_t(176), uint8_t(51), uint8_t(41), uint8_t(20), uint8_t(32)}, + [9]uint8_t{uint8_t(101), uint8_t(75), uint8_t(128), uint8_t(139), uint8_t(118), uint8_t(146), uint8_t(116), uint8_t(128), uint8_t(85)}, + [9]uint8_t{uint8_t(56), uint8_t(41), uint8_t(15), uint8_t(176), uint8_t(236), uint8_t(85), uint8_t(37), uint8_t(9), uint8_t(62)}, + [9]uint8_t{uint8_t(71), uint8_t(30), uint8_t(17), uint8_t(119), uint8_t(118), uint8_t(255), uint8_t(17), uint8_t(18), uint8_t(138)}, + [9]uint8_t{uint8_t(101), uint8_t(38), uint8_t(60), uint8_t(138), uint8_t(55), uint8_t(70), uint8_t(43), uint8_t(26), uint8_t(142)}, + [9]uint8_t{uint8_t(146), uint8_t(36), uint8_t(19), uint8_t(30), uint8_t(171), uint8_t(255), uint8_t(97), uint8_t(27), uint8_t(20)}, + [9]uint8_t{uint8_t(138), uint8_t(45), uint8_t(61), uint8_t(62), uint8_t(219), uint8_t(1), uint8_t(81), uint8_t(188), uint8_t(64)}, + [9]uint8_t{uint8_t(32), uint8_t(41), uint8_t(20), uint8_t(117), uint8_t(151), uint8_t(142), uint8_t(20), uint8_t(21), uint8_t(163)}, + [9]uint8_t{uint8_t(112), uint8_t(19), uint8_t(12), uint8_t(61), uint8_t(195), uint8_t(128), uint8_t(48), uint8_t(4), uint8_t(24)}}} /* tree_dec.c:181:22 */ + +func VP8ResetProba(tls *libc.TLS, proba uintptr) { /* tree_dec.c:284:6: */ + libc.Xmemset(tls, (proba /* &.segments_ */), int32(255), uint64(unsafe.Sizeof([3]uint8_t{}))) + // proba->bands_[][] is initialized later +} + +func ParseIntraMode(tls *libc.TLS, br uintptr, dec uintptr, mb_x int32) { /* tree_dec.c:289:13: */ + var top uintptr = ((*VP8Decoder)(unsafe.Pointer(dec)).intra_t_ + uintptr((4 * mb_x))) + var left uintptr = dec + 2816 /* &.intra_l_ */ + var block uintptr = ((*VP8Decoder)(unsafe.Pointer(dec)).mb_data_ + uintptr(mb_x)*800) + + // Note: we don't save segment map (yet), as we don't expect + // to decode more than 1 keyframe. + if (*VP8Decoder)(unsafe.Pointer(dec)).segment_hdr_.update_map_ != 0 { + // Hardcoded tree parsing + (*VP8MBData)(unsafe.Pointer(block)).segment_ = func() uint8 { + if !(VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer((dec + 1192 /* &.proba_ */) /* &.segments_ */)))) != 0) { + return uint8(VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer((dec + 1192 /* &.proba_ */) /* &.segments_ */ + 1))))) + } + return (uint8(VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer((dec + 1192 /* &.proba_ */) /* &.segments_ */ + 2)))) + 2)) + }() + } else { + (*VP8MBData)(unsafe.Pointer(block)).segment_ = uint8_t(0) // default for intra + } + if (*VP8Decoder)(unsafe.Pointer(dec)).use_skip_proba_ != 0 { + (*VP8MBData)(unsafe.Pointer(block)).skip_ = uint8_t(VP8GetBit(tls, br, int32((*VP8Decoder)(unsafe.Pointer(dec)).skip_p_))) + } + + (*VP8MBData)(unsafe.Pointer(block)).is_i4x4_ = libc.BoolUint8(!(VP8GetBit(tls, br, 145) != 0)) + if !(int32((*VP8MBData)(unsafe.Pointer(block)).is_i4x4_) != 0) { + // Hardcoded 16x16 intra-mode decision tree. + var ymode int32 + if VP8GetBit(tls, br, 156) != 0 { + ymode = (func() int32 { + if VP8GetBit(tls, br, 128) != 0 { + return TM_PRED + } + return H_PRED + }()) + } else { + ymode = (func() int32 { + if VP8GetBit(tls, br, 163) != 0 { + return V_PRED + } + return DC_PRED + }()) + } + *(*uint8_t)(unsafe.Pointer((block + 769 /* &.imodes_ */))) = uint8_t(ymode) + libc.Xmemset(tls, top, ymode, (uint64(4) * uint64(unsafe.Sizeof(uint8_t(0))))) + libc.Xmemset(tls, left, ymode, (uint64(4) * uint64(unsafe.Sizeof(uint8_t(0))))) + } else { + var modes uintptr = block + 769 /* &.imodes_ */ + var y int32 + for y = 0; y < 4; y++ { + var ymode int32 = int32(*(*uint8_t)(unsafe.Pointer(left + uintptr(y)))) + var x int32 + for x = 0; x < 4; x++ { + var prob uintptr = ((uintptr(unsafe.Pointer(&kBModesProba)) + uintptr(*(*uint8_t)(unsafe.Pointer(top + uintptr(x))))*90) + uintptr(ymode)*9) + // Generic tree-parsing + var i int32 = int32(kYModesIntra4[VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer(prob))))]) + for i > 0 { + i = int32(kYModesIntra4[((2 * i) + VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer(prob + uintptr(i))))))]) + } + ymode = -i + *(*uint8_t)(unsafe.Pointer(top + uintptr(x))) = uint8_t(ymode) + } + libc.Xmemcpy(tls, modes, top, (uint64(4) * uint64(unsafe.Sizeof(uint8_t(0))))) + modes += uintptr(4) + *(*uint8_t)(unsafe.Pointer(left + uintptr(y))) = uint8_t(ymode) + } + } + // Hardcoded UVMode decision tree + (*VP8MBData)(unsafe.Pointer(block)).uvmode_ = func() uint8 { + if !(VP8GetBit(tls, br, 142) != 0) { + return DC_PRED + } + return func() uint8 { + if !(VP8GetBit(tls, br, 114) != 0) { + return V_PRED + } + return func() uint8 { + if VP8GetBit(tls, br, 183) != 0 { + return TM_PRED + } + return H_PRED + }() + }() + }() +} + +func VP8ParseIntraModeRow(tls *libc.TLS, br uintptr, dec uintptr) int32 { /* tree_dec.c:360:5: */ + var mb_x int32 + for mb_x = 0; mb_x < (*VP8Decoder)(unsafe.Pointer(dec)).mb_w_; mb_x++ { + ParseIntraMode(tls, br, dec, mb_x) + } + return libc.BoolInt32(!((*VP8Decoder)(unsafe.Pointer(dec)).br_.eof_ != 0)) +} + +//------------------------------------------------------------------------------ +// Paragraph 13 + +var CoeffsUpdateProba = [4][8][3][11]uint8_t{[8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(176), uint8_t(246), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(223), uint8_t(241), uint8_t(252), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(249), uint8_t(253), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(244), uint8_t(252), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(234), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(246), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(239), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(248), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(251), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(251), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(253), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(250), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, +}, + [8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(217), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(225), uint8_t(252), uint8_t(241), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(234), uint8_t(250), uint8_t(241), uint8_t(250), uint8_t(253), uint8_t(255), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(223), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(238), uint8_t(253), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(248), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(249), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(247), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(252), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(250), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + }, + [8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(186), uint8_t(251), uint8_t(250), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(234), uint8_t(251), uint8_t(244), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(251), uint8_t(251), uint8_t(243), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(236), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(251), uint8_t(253), uint8_t(253), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + }, + [8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(248), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(250), uint8_t(254), uint8_t(252), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(248), uint8_t(254), uint8_t(249), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(253), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(246), uint8_t(253), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(252), uint8_t(254), uint8_t(251), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(252), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(248), uint8_t(254), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(253), uint8_t(255), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(251), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(245), uint8_t(251), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(253), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(251), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(252), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(252), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(249), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(250), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + }, +} /* tree_dec.c:372:5 */ + +// Paragraph 9.9 + +var kBands = [17]uint8_t{ + uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(6), uint8_t(4), uint8_t(5), uint8_t(6), uint8_t(6), uint8_t(6), uint8_t(6), uint8_t(6), uint8_t(6), uint8_t(6), uint8_t(6), uint8_t(7), + uint8_t(0), // extra entry as sentinel +} /* tree_dec.c:509:22 */ + +func VP8ParseProba(tls *libc.TLS, br uintptr, dec uintptr) { /* tree_dec.c:514:6: */ + var proba uintptr = (dec + 1192 /* &.proba_ */) + var t int32 + var b int32 + var c int32 + var p int32 + for t = 0; t < NUM_TYPES; t++ { + for b = 0; b < NUM_BANDS; b++ { + for c = 0; c < NUM_CTX; c++ { + for p = 0; p < NUM_PROBAS; p++ { + var v int32 + if VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer((((uintptr(unsafe.Pointer(&CoeffsUpdateProba)) + uintptr(t)*264) + uintptr(b)*33) + uintptr(c)*11) + uintptr(p))))) != 0 { + v = int32(VP8GetValue(tls, br, 8)) + } else { + v = int32(*(*uint8_t)(unsafe.Pointer((((uintptr(unsafe.Pointer(&CoeffsProba0)) + uintptr(t)*264) + uintptr(b)*33) + uintptr(c)*11) + uintptr(p)))) + } + *(*uint8_t)(unsafe.Pointer(((((proba + 3 /* &.bands_ */) + uintptr(t)*264) + uintptr(b)*33) /* &.probas_ */ + uintptr(c)*11) + uintptr(p))) = uint8_t(v) + } + } + } + for b = 0; b < (16 + 1); b++ { + *(*uintptr)(unsafe.Pointer(((proba + 1064 /* &.bands_ptr_ */) + uintptr(t)*136) + uintptr(b)*8)) = (((proba + 3 /* &.bands_ */) + uintptr(t)*264) + uintptr(kBands[b])*33) + } + } + (*VP8Decoder)(unsafe.Pointer(dec)).use_skip_proba_ = int32(VP8GetValue(tls, br, 1)) + if (*VP8Decoder)(unsafe.Pointer(dec)).use_skip_proba_ != 0 { + (*VP8Decoder)(unsafe.Pointer(dec)).skip_p_ = uint8_t(VP8GetValue(tls, br, 8)) + } +} + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +//------------------------------------------------------------------------------ + +func WebPGetDecoderVersion(tls *libc.TLS) int32 { /* vp8_dec.c:25:5: */ + return (((int32(1) << 16) | (int32(2) << 8)) | 2) +} + +//------------------------------------------------------------------------------ +// Signature and pointer-to-function for GetCoeffs() variants below. + +type GetCoeffsFunc = uintptr /* vp8_dec.c:32:13 */ +var GetCoeffs GetCoeffsFunc = (uintptr(0)) /* vp8_dec.c:35:31 */ + +//------------------------------------------------------------------------------ +// VP8Decoder + +func SetOk(tls *libc.TLS, dec uintptr) { /* vp8_dec.c:42:13: */ + (*VP8Decoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_OK + (*VP8Decoder)(unsafe.Pointer(dec)).error_msg_ = (ts + 117) /* "OK" */ +} + +func VP8InitIoInternal(tls *libc.TLS, io uintptr, version int32) int32 { /* vp8_dec.c:47:5: */ + if ((version) >> 8) != (int32((0x0209)) >> 8) { + return 0 // mismatch error + } + if io != (uintptr(0)) { + libc.Xmemset(tls, io, 0, uint64(unsafe.Sizeof(VP8Io{}))) + } + return 1 +} + +func VP8New(tls *libc.TLS) uintptr { /* vp8_dec.c:57:11: */ + var dec uintptr = WebPSafeCalloc(tls, 1, uint64(unsafe.Sizeof(VP8Decoder{}))) + if dec != (uintptr(0)) { + SetOk(tls, dec) + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(WebPGetWorkerInterface(tls))).Init})).f(tls, (dec + 152 /* &.worker_ */)) + (*VP8Decoder)(unsafe.Pointer(dec)).ready_ = 0 + (*VP8Decoder)(unsafe.Pointer(dec)).num_parts_minus_one_ = uint32_t(0) + InitGetCoeffs(tls) + } + return dec +} + +func VP8Status(tls *libc.TLS, dec uintptr) VP8StatusCode { /* vp8_dec.c:69:15: */ + if !(dec != 0) { + return VP8_STATUS_INVALID_PARAM + } + return (*VP8Decoder)(unsafe.Pointer(dec)).status_ +} + +func VP8StatusMessage(tls *libc.TLS, dec uintptr) uintptr { /* vp8_dec.c:74:11: */ + if dec == (uintptr(0)) { + return (ts + 120) /* "no object" */ + } + if !(int32((*VP8Decoder)(unsafe.Pointer(dec)).error_msg_) != 0) { + return (ts + 117) /* "OK" */ + } + return (*VP8Decoder)(unsafe.Pointer(dec)).error_msg_ +} + +func VP8Delete(tls *libc.TLS, dec uintptr) { /* vp8_dec.c:80:6: */ + if dec != (uintptr(0)) { + VP8Clear(tls, dec) + WebPSafeFree(tls, dec) + } +} + +func VP8SetError(tls *libc.TLS, dec uintptr, error VP8StatusCode, msg uintptr) int32 { /* vp8_dec.c:87:5: */ + // The oldest error reported takes precedence over the new one. + if (*VP8Decoder)(unsafe.Pointer(dec)).status_ == VP8_STATUS_OK { + (*VP8Decoder)(unsafe.Pointer(dec)).status_ = error + (*VP8Decoder)(unsafe.Pointer(dec)).error_msg_ = msg + (*VP8Decoder)(unsafe.Pointer(dec)).ready_ = 0 + } + return 0 +} + +//------------------------------------------------------------------------------ + +func VP8CheckSignature(tls *libc.TLS, data uintptr, data_size size_t) int32 { /* vp8_dec.c:100:5: */ + return (libc.Bool32((((data_size >= uint64(3)) && (int32(*(*uint8_t)(unsafe.Pointer(data))) == 0x9d)) && (int32(*(*uint8_t)(unsafe.Pointer(data + 1))) == 0x01)) && (int32(*(*uint8_t)(unsafe.Pointer(data + 2))) == 0x2a))) +} + +func VP8GetInfo(tls *libc.TLS, data uintptr, data_size size_t, chunk_size size_t, width uintptr, height uintptr) int32 { /* vp8_dec.c:105:5: */ + if (data == (uintptr(0))) || (data_size < uint64(10)) { + return 0 // not enough data + } + // check signature + if !(VP8CheckSignature(tls, (data+uintptr(3)), (data_size-uint64(3))) != 0) { + return 0 // Wrong signature. + } else { + var bits uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(data))) | (int32(*(*uint8_t)(unsafe.Pointer(data + 1))) << 8)) | (int32(*(*uint8_t)(unsafe.Pointer(data + 2))) << 16))) + var key_frame int32 = libc.BoolInt32(!((bits & uint32_t(1)) != 0)) + var w int32 = (((int32(*(*uint8_t)(unsafe.Pointer(data + 7))) << 8) | int32(*(*uint8_t)(unsafe.Pointer(data + 6)))) & 0x3fff) + var h int32 = (((int32(*(*uint8_t)(unsafe.Pointer(data + 9))) << 8) | int32(*(*uint8_t)(unsafe.Pointer(data + 8)))) & 0x3fff) + + if !(key_frame != 0) { // Not a keyframe. + return 0 + } + + if ((bits >> 1) & uint32_t(7)) > uint32_t(3) { + return 0 // unknown profile + } + if !(((bits >> 4) & uint32_t(1)) != 0) { + return 0 // first frame is invisible! + } + if (size_t(bits >> 5)) >= chunk_size { // partition_length + return 0 // inconsistent size information. + } + if (w == 0) || (h == 0) { + return 0 // We don't support both width and height to be zero. + } + + if width != 0 { + *(*int32)(unsafe.Pointer(width)) = w + } + if height != 0 { + *(*int32)(unsafe.Pointer(height)) = h + } + + return 1 + } + return int32(0) +} + +//------------------------------------------------------------------------------ +// Header parsing + +func ResetSegmentHeader(tls *libc.TLS, hdr uintptr) { /* vp8_dec.c:150:13: */ + + (*VP8SegmentHeader)(unsafe.Pointer(hdr)).use_segment_ = 0 + (*VP8SegmentHeader)(unsafe.Pointer(hdr)).update_map_ = 0 + (*VP8SegmentHeader)(unsafe.Pointer(hdr)).absolute_delta_ = 1 + libc.Xmemset(tls, (hdr + 12 /* &.quantizer_ */), 0, uint64(unsafe.Sizeof([4]int8_t{}))) + libc.Xmemset(tls, (hdr + 16 /* &.filter_strength_ */), 0, uint64(unsafe.Sizeof([4]int8_t{}))) +} + +// Paragraph 9.3 +func ParseSegmentHeader(tls *libc.TLS, br uintptr, hdr uintptr, proba uintptr) int32 { /* vp8_dec.c:160:12: */ + + (*VP8SegmentHeader)(unsafe.Pointer(hdr)).use_segment_ = int32(VP8GetValue(tls, br, 1)) + if (*VP8SegmentHeader)(unsafe.Pointer(hdr)).use_segment_ != 0 { + (*VP8SegmentHeader)(unsafe.Pointer(hdr)).update_map_ = int32(VP8GetValue(tls, br, 1)) + if VP8GetValue(tls, br, 1) != 0 { // update data + var s int32 + (*VP8SegmentHeader)(unsafe.Pointer(hdr)).absolute_delta_ = int32(VP8GetValue(tls, br, 1)) + for s = 0; s < NUM_MB_SEGMENTS; s++ { + *(*int8_t)(unsafe.Pointer((hdr + 12 /* &.quantizer_ */) + uintptr(s))) = func() int8 { + if VP8GetValue(tls, br, 1) != 0 { + return int8(VP8GetSignedValue(tls, br, 7)) + } + return int8(0) + }() + } + for s = 0; s < NUM_MB_SEGMENTS; s++ { + *(*int8_t)(unsafe.Pointer((hdr + 16 /* &.filter_strength_ */) + uintptr(s))) = func() int8 { + if VP8GetValue(tls, br, 1) != 0 { + return int8(VP8GetSignedValue(tls, br, 6)) + } + return int8(0) + }() + } + } + if (*VP8SegmentHeader)(unsafe.Pointer(hdr)).update_map_ != 0 { + var s int32 + for s = 0; s < MB_FEATURE_TREE_PROBS; s++ { + *(*uint8_t)(unsafe.Pointer((proba /* &.segments_ */) + uintptr(s))) = func() uint8 { + if VP8GetValue(tls, br, 1) != 0 { + return uint8(VP8GetValue(tls, br, 8)) + } + return uint8(255) + }() + } + } + } else { + (*VP8SegmentHeader)(unsafe.Pointer(hdr)).update_map_ = 0 + } + return libc.BoolInt32(!((*VP8BitReader)(unsafe.Pointer(br)).eof_ != 0)) +} + +// Paragraph 9.5 +// This function returns VP8_STATUS_SUSPENDED if we don't have all the +// necessary data in 'buf'. +// This case is not necessarily an error (for incremental decoding). +// Still, no bitreader is ever initialized to make it possible to read +// unavailable memory. +// If we don't even have the partitions' sizes, than VP8_STATUS_NOT_ENOUGH_DATA +// is returned, and this is an unrecoverable error. +// If the partitions were positioned ok, VP8_STATUS_OK is returned. +func ParsePartitions(tls *libc.TLS, dec uintptr, buf uintptr, size size_t) VP8StatusCode { /* vp8_dec.c:201:22: */ + var br uintptr = (dec + 16 /* &.br_ */) + var sz uintptr = buf + var buf_end uintptr = (buf + uintptr(size)) + var part_start uintptr + var size_left size_t = size + var last_part size_t + var p size_t + + (*VP8Decoder)(unsafe.Pointer(dec)).num_parts_minus_one_ = (uint32_t((int32(1) << VP8GetValue(tls, br, 2)) - 1)) + last_part = size_t((*VP8Decoder)(unsafe.Pointer(dec)).num_parts_minus_one_) + if size < (uint64(3) * last_part) { + // we can't even read the sizes with sz[]! That's a failure. + return VP8_STATUS_NOT_ENOUGH_DATA + } + part_start = (buf + uintptr((last_part * uint64(3)))) + size_left = size_left - (last_part * uint64(3)) + for p = uint64(0); p < last_part; p++ { + var psize size_t = (size_t((int32(*(*uint8_t)(unsafe.Pointer(sz))) | (int32(*(*uint8_t)(unsafe.Pointer(sz + 1))) << 8)) | (int32(*(*uint8_t)(unsafe.Pointer(sz + 2))) << 16))) + if psize > size_left { + psize = size_left + } + VP8InitBitReader(tls, ((dec + 440 /* &.parts_ */) + uintptr(p)*48), part_start, psize) + part_start += uintptr(psize) + size_left = size_left - (psize) + sz += uintptr(3) + } + VP8InitBitReader(tls, ((dec + 440 /* &.parts_ */) + uintptr(last_part)*48), part_start, size_left) + if part_start < buf_end { + return VP8_STATUS_OK + } + return VP8_STATUS_SUSPENDED // Init is ok, but there's not enough data +} + +// Paragraph 9.4 +func ParseFilterHeader(tls *libc.TLS, br uintptr, dec uintptr) int32 { /* vp8_dec.c:233:12: */ + var hdr uintptr = (dec + 80 /* &.filter_hdr_ */) + (*VP8FilterHeader)(unsafe.Pointer(hdr)).simple_ = int32(VP8GetValue(tls, br, 1)) + (*VP8FilterHeader)(unsafe.Pointer(hdr)).level_ = int32(VP8GetValue(tls, br, 6)) + (*VP8FilterHeader)(unsafe.Pointer(hdr)).sharpness_ = int32(VP8GetValue(tls, br, 3)) + (*VP8FilterHeader)(unsafe.Pointer(hdr)).use_lf_delta_ = int32(VP8GetValue(tls, br, 1)) + if (*VP8FilterHeader)(unsafe.Pointer(hdr)).use_lf_delta_ != 0 { + if VP8GetValue(tls, br, 1) != 0 { // update lf-delta? + var i int32 + for i = 0; i < NUM_REF_LF_DELTAS; i++ { + if VP8GetValue(tls, br, 1) != 0 { + *(*int32)(unsafe.Pointer((hdr + 16 /* &.ref_lf_delta_ */) + uintptr(i)*4)) = VP8GetSignedValue(tls, br, 6) + } + } + for i = 0; i < NUM_MODE_LF_DELTAS; i++ { + if VP8GetValue(tls, br, 1) != 0 { + *(*int32)(unsafe.Pointer((hdr + 32 /* &.mode_lf_delta_ */) + uintptr(i)*4)) = VP8GetSignedValue(tls, br, 6) + } + } + } + } + (*VP8Decoder)(unsafe.Pointer(dec)).filter_type_ = func() int32 { + if (*VP8FilterHeader)(unsafe.Pointer(hdr)).level_ == 0 { + return 0 + } + return func() int32 { + if (*VP8FilterHeader)(unsafe.Pointer(hdr)).simple_ != 0 { + return 1 + } + return 2 + }() + }() + return libc.BoolInt32(!((*VP8BitReader)(unsafe.Pointer(br)).eof_ != 0)) +} + +// Topmost call +func VP8GetHeaders(tls *libc.TLS, dec uintptr, io uintptr) int32 { /* vp8_dec.c:259:5: */ + var buf uintptr + var buf_size size_t + var frm_hdr uintptr + var pic_hdr uintptr + var br uintptr + var status VP8StatusCode + + if dec == (uintptr(0)) { + return 0 + } + SetOk(tls, dec) + if io == (uintptr(0)) { + return VP8SetError(tls, dec, VP8_STATUS_INVALID_PARAM, + (ts + 130) /* "null VP8Io passe..." */) + } + buf = (*VP8Io)(unsafe.Pointer(io)).data + buf_size = (*VP8Io)(unsafe.Pointer(io)).data_size + if buf_size < uint64(4) { + return VP8SetError(tls, dec, VP8_STATUS_NOT_ENOUGH_DATA, + (ts + 167) /* "Truncated header..." */) + } + + // Paragraph 9.1 + { + var bits uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(buf))) | (int32(*(*uint8_t)(unsafe.Pointer(buf + 1))) << 8)) | (int32(*(*uint8_t)(unsafe.Pointer(buf + 2))) << 16))) + frm_hdr = (dec + 64 /* &.frm_hdr_ */) + (*VP8FrameHeader)(unsafe.Pointer(frm_hdr)).key_frame_ = libc.BoolUint8(!((bits & uint32_t(1)) != 0)) + (*VP8FrameHeader)(unsafe.Pointer(frm_hdr)).profile_ = (uint8_t((bits >> 1) & uint32_t(7))) + (*VP8FrameHeader)(unsafe.Pointer(frm_hdr)).show_ = (uint8_t((bits >> 4) & uint32_t(1))) + (*VP8FrameHeader)(unsafe.Pointer(frm_hdr)).partition_length_ = (bits >> 5) + if int32((*VP8FrameHeader)(unsafe.Pointer(frm_hdr)).profile_) > 3 { + return VP8SetError(tls, dec, VP8_STATUS_BITSTREAM_ERROR, + (ts + 185) /* "Incorrect keyfra..." */) + } + if !(int32((*VP8FrameHeader)(unsafe.Pointer(frm_hdr)).show_) != 0) { + return VP8SetError(tls, dec, VP8_STATUS_UNSUPPORTED_FEATURE, + (ts + 216) /* "Frame not displa..." */) + } + buf += uintptr(3) + buf_size = buf_size - (uint64(3)) + + } + + pic_hdr = (dec + 72 /* &.pic_hdr_ */) + if (*VP8FrameHeader)(unsafe.Pointer(frm_hdr)).key_frame_ != 0 { + // Paragraph 9.2 + if buf_size < uint64(7) { + return VP8SetError(tls, dec, VP8_STATUS_NOT_ENOUGH_DATA, + (ts + 239) /* "cannot parse pic..." */) + } + if !(VP8CheckSignature(tls, buf, buf_size) != 0) { + return VP8SetError(tls, dec, VP8_STATUS_BITSTREAM_ERROR, + (ts + 267) /* "Bad code word" */) + } + (*VP8PictureHeader)(unsafe.Pointer(pic_hdr)).width_ = (uint16_t(((int32(*(*uint8_t)(unsafe.Pointer(buf + 4))) << 8) | int32(*(*uint8_t)(unsafe.Pointer(buf + 3)))) & 0x3fff)) + (*VP8PictureHeader)(unsafe.Pointer(pic_hdr)).xscale_ = (uint8_t(int32(*(*uint8_t)(unsafe.Pointer(buf + 4))) >> 6)) // ratio: 1, 5/4 5/3 or 2 + (*VP8PictureHeader)(unsafe.Pointer(pic_hdr)).height_ = (uint16_t(((int32(*(*uint8_t)(unsafe.Pointer(buf + 6))) << 8) | int32(*(*uint8_t)(unsafe.Pointer(buf + 5)))) & 0x3fff)) + (*VP8PictureHeader)(unsafe.Pointer(pic_hdr)).yscale_ = (uint8_t(int32(*(*uint8_t)(unsafe.Pointer(buf + 6))) >> 6)) + buf += uintptr(7) + buf_size = buf_size - (uint64(7)) + + (*VP8Decoder)(unsafe.Pointer(dec)).mb_w_ = ((int32((*VP8PictureHeader)(unsafe.Pointer(pic_hdr)).width_) + 15) >> 4) + (*VP8Decoder)(unsafe.Pointer(dec)).mb_h_ = ((int32((*VP8PictureHeader)(unsafe.Pointer(pic_hdr)).height_) + 15) >> 4) + + // Setup default output area (can be later modified during io->setup()) + (*VP8Io)(unsafe.Pointer(io)).width = int32((*VP8PictureHeader)(unsafe.Pointer(pic_hdr)).width_) + (*VP8Io)(unsafe.Pointer(io)).height = int32((*VP8PictureHeader)(unsafe.Pointer(pic_hdr)).height_) + // IMPORTANT! use some sane dimensions in crop_* and scaled_* fields. + // So they can be used interchangeably without always testing for + // 'use_cropping'. + (*VP8Io)(unsafe.Pointer(io)).use_cropping = 0 + (*VP8Io)(unsafe.Pointer(io)).crop_top = 0 + (*VP8Io)(unsafe.Pointer(io)).crop_left = 0 + (*VP8Io)(unsafe.Pointer(io)).crop_right = (*VP8Io)(unsafe.Pointer(io)).width + (*VP8Io)(unsafe.Pointer(io)).crop_bottom = (*VP8Io)(unsafe.Pointer(io)).height + (*VP8Io)(unsafe.Pointer(io)).use_scaling = 0 + (*VP8Io)(unsafe.Pointer(io)).scaled_width = (*VP8Io)(unsafe.Pointer(io)).width + (*VP8Io)(unsafe.Pointer(io)).scaled_height = (*VP8Io)(unsafe.Pointer(io)).height + + (*VP8Io)(unsafe.Pointer(io)).mb_w = (*VP8Io)(unsafe.Pointer(io)).width // for soundness + (*VP8Io)(unsafe.Pointer(io)).mb_h = (*VP8Io)(unsafe.Pointer(io)).height // ditto + + VP8ResetProba(tls, (dec + 1192 /* &.proba_ */)) + ResetSegmentHeader(tls, (dec + 128 /* &.segment_hdr_ */)) + } + + // Check if we have all the partition #0 available, and initialize dec->br_ + // to read this partition (and this partition only). + if size_t((*VP8FrameHeader)(unsafe.Pointer(frm_hdr)).partition_length_) > buf_size { + return VP8SetError(tls, dec, VP8_STATUS_NOT_ENOUGH_DATA, + (ts + 281) /* "bad partition le..." */) + } + + br = (dec + 16 /* &.br_ */) + VP8InitBitReader(tls, br, buf, uint64((*VP8FrameHeader)(unsafe.Pointer(frm_hdr)).partition_length_)) + buf += uintptr((*VP8FrameHeader)(unsafe.Pointer(frm_hdr)).partition_length_) + buf_size = buf_size - (size_t((*VP8FrameHeader)(unsafe.Pointer(frm_hdr)).partition_length_)) + + if (*VP8FrameHeader)(unsafe.Pointer(frm_hdr)).key_frame_ != 0 { + (*VP8PictureHeader)(unsafe.Pointer(pic_hdr)).colorspace_ = uint8_t(VP8GetValue(tls, br, 1)) + (*VP8PictureHeader)(unsafe.Pointer(pic_hdr)).clamp_type_ = uint8_t(VP8GetValue(tls, br, 1)) + } + if !(ParseSegmentHeader(tls, br, (dec+128 /* &.segment_hdr_ */), (dec+1192 /* &.proba_ */)) != 0) { + return VP8SetError(tls, dec, VP8_STATUS_BITSTREAM_ERROR, + (ts + 302) /* "cannot parse seg..." */) + } + // Filter specs + if !(ParseFilterHeader(tls, br, dec) != 0) { + return VP8SetError(tls, dec, VP8_STATUS_BITSTREAM_ERROR, + (ts + 330) /* "cannot parse fil..." */) + } + status = ParsePartitions(tls, dec, buf, buf_size) + if status != VP8_STATUS_OK { + return VP8SetError(tls, dec, status, (ts + 357) /* "cannot parse par..." */) + } + + // quantizer change + VP8ParseQuant(tls, dec) + + // Frame buffer marking + if !(int32((*VP8FrameHeader)(unsafe.Pointer(frm_hdr)).key_frame_) != 0) { + return VP8SetError(tls, dec, VP8_STATUS_UNSUPPORTED_FEATURE, + (ts + 381) /* "Not a key frame." */) + } + + VP8GetValue(tls, br, 1) // ignore the value of update_proba_ + + VP8ParseProba(tls, br, dec) + + // sanitized state + (*VP8Decoder)(unsafe.Pointer(dec)).ready_ = 1 + return 1 +} + +//------------------------------------------------------------------------------ +// Residual decoding (Paragraph 13.2 / 13.3) + +var kCat3 = [4]uint8_t{uint8_t(173), uint8_t(148), uint8_t(140), uint8_t(0)} /* vp8_dec.c:396:22 */ +var kCat4 = [5]uint8_t{uint8_t(176), uint8_t(155), uint8_t(140), uint8_t(135), uint8_t(0)} /* vp8_dec.c:397:22 */ +var kCat5 = [6]uint8_t{uint8_t(180), uint8_t(157), uint8_t(141), uint8_t(134), uint8_t(130), uint8_t(0)} /* vp8_dec.c:398:22 */ +var kCat6 = [12]uint8_t{uint8_t(254), uint8_t(254), uint8_t(243), uint8_t(230), uint8_t(196), uint8_t(177), uint8_t(153), uint8_t(140), uint8_t(133), uint8_t(130), uint8_t(129), uint8_t(0)} /* vp8_dec.c:399:22 */ +var kCat3456 = [4]uintptr{0, 0, 0, 0} /* vp8_dec.c:401:21 */ +var kZigzag = [16]uint8_t{ + uint8_t(0), uint8_t(1), uint8_t(4), uint8_t(8), uint8_t(5), uint8_t(2), uint8_t(3), uint8_t(6), uint8_t(9), uint8_t(12), uint8_t(13), uint8_t(10), uint8_t(7), uint8_t(11), uint8_t(14), uint8_t(15), +} /* vp8_dec.c:402:22 */ + +// See section 13-2: https://datatracker.ietf.org/doc/html/rfc6386#section-13.2 +func GetLargeValue(tls *libc.TLS, br uintptr, p uintptr) int32 { /* vp8_dec.c:407:12: */ + var v int32 + if !(VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer(p + 3)))) != 0) { + if !(VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer(p + 4)))) != 0) { + v = 2 + } else { + v = (3 + VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer(p + 5))))) + } + } else { + if !(VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer(p + 6)))) != 0) { + if !(VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer(p + 7)))) != 0) { + v = (5 + VP8GetBit(tls, br, 159)) + } else { + v = (7 + (2 * VP8GetBit(tls, br, 165))) + v = v + (VP8GetBit(tls, br, 145)) + } + } else { + var tab uintptr + var bit1 int32 = VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer(p + 8)))) + var bit0 int32 = VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer(p + uintptr((9 + bit1)))))) + var cat int32 = ((2 * bit1) + bit0) + v = 0 + for tab = kCat3456[cat]; *(*uint8_t)(unsafe.Pointer(tab)) != 0; tab++ { + v = v + (v + VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer(tab))))) + } + v = v + (3 + (int32(8) << cat)) + } + } + return v +} + +// Returns the position of the last non-zero coeff plus one +func GetCoeffsFast(tls *libc.TLS, br uintptr, prob uintptr, ctx int32, dq uintptr, n int32, out uintptr) int32 { /* vp8_dec.c:439:12: */ + var p uintptr = (*(*uintptr)(unsafe.Pointer(prob + uintptr(n)*8)) /* &.probas_ */ + uintptr(ctx)*11) + for ; n < 16; n++ { + if !(VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer(p)))) != 0) { + return n // previous coeff was last non-zero coeff + } + for !(VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer(p + 1)))) != 0) { // sequence of zero coeffs + p = (*(*uintptr)(unsafe.Pointer(prob + uintptr(libc.PreIncInt32(&n, 1))*8)) /* &.probas_ */) + if n == 16 { + return 16 + } + } + { // non zero coeff + var p_ctx uintptr = (*(*uintptr)(unsafe.Pointer(prob + uintptr((n+1))*8)) /* &.probas_ */) + var v int32 + if !(VP8GetBit(tls, br, int32(*(*uint8_t)(unsafe.Pointer(p + 2)))) != 0) { + v = 1 + p = (p_ctx + 1*11) + } else { + v = GetLargeValue(tls, br, p) + p = (p_ctx + 2*11) + } + *(*int16_t)(unsafe.Pointer(out + uintptr(kZigzag[n])*2)) = (int16_t(VP8GetSigned(tls, br, v) * *(*int32)(unsafe.Pointer(dq + uintptr((libc.Bool32(n > 0)))*4)))) + + } + } + return 16 +} + +// This version of GetCoeffs() uses VP8GetBitAlt() which is an alternate version +// of VP8GetBitAlt() targeting specific platforms. +func GetCoeffsAlt(tls *libc.TLS, br uintptr, prob uintptr, ctx int32, dq uintptr, n int32, out uintptr) int32 { /* vp8_dec.c:469:12: */ + var p uintptr = (*(*uintptr)(unsafe.Pointer(prob + uintptr(n)*8)) /* &.probas_ */ + uintptr(ctx)*11) + for ; n < 16; n++ { + if !(VP8GetBitAlt(tls, br, int32(*(*uint8_t)(unsafe.Pointer(p)))) != 0) { + return n // previous coeff was last non-zero coeff + } + for !(VP8GetBitAlt(tls, br, int32(*(*uint8_t)(unsafe.Pointer(p + 1)))) != 0) { // sequence of zero coeffs + p = (*(*uintptr)(unsafe.Pointer(prob + uintptr(libc.PreIncInt32(&n, 1))*8)) /* &.probas_ */) + if n == 16 { + return 16 + } + } + { // non zero coeff + var p_ctx uintptr = (*(*uintptr)(unsafe.Pointer(prob + uintptr((n+1))*8)) /* &.probas_ */) + var v int32 + if !(VP8GetBitAlt(tls, br, int32(*(*uint8_t)(unsafe.Pointer(p + 2)))) != 0) { + v = 1 + p = (p_ctx + 1*11) + } else { + v = GetLargeValue(tls, br, p) + p = (p_ctx + 2*11) + } + *(*int16_t)(unsafe.Pointer(out + uintptr(kZigzag[n])*2)) = (int16_t(VP8GetSigned(tls, br, v) * *(*int32)(unsafe.Pointer(dq + uintptr((libc.Bool32(n > 0)))*4)))) + + } + } + return 16 +} + +func InitGetCoeffs(tls *libc.TLS) { /* vp8_dec.c:497:1: */ + for ok := true; ok; ok = (0 != 0) { + if InitGetCoeffs_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + InitGetCoeffs_body(tls) + InitGetCoeffs_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var InitGetCoeffs_body_last_cpuinfo_used VP8CPUInfo = 0 /* vp8_dec.c:497:1 */ + +func InitGetCoeffs_body(tls *libc.TLS) { /* vp8_dec.c:497:1: */ + if (VP8GetCPUInfo != (uintptr(0))) && ((*struct { + f func(*libc.TLS, CPUFeature) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8GetCPUInfo})).f(tls, kSlowSSSE3) != 0) { + GetCoeffs = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr, int32, uintptr) int32 + }{GetCoeffsAlt})) + } else { + GetCoeffs = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr, int32, uintptr) int32 + }{GetCoeffsFast})) + } +} + +func NzCodeBits(tls *libc.TLS, nz_coeffs uint32_t, nz int32, dc_nz int32) uint32_t { /* vp8_dec.c:505:29: */ + nz_coeffs <<= 2 + nz_coeffs = nz_coeffs | (func() uint32 { + if nz > 3 { + return uint32(3) + } + return func() uint32 { + if nz > 1 { + return uint32(2) + } + return uint32(dc_nz) + }() + }()) + return nz_coeffs +} + +func ParseResiduals(tls *libc.TLS, dec uintptr, mb uintptr, token_br uintptr) int32 { /* vp8_dec.c:511:12: */ + bp := tls.Alloc(32) + defer tls.Free(32) + + var bands uintptr = ((dec + 1192 /* &.proba_ */) + 1064 /* &.bands_ptr_ */) + var ac_proba uintptr + var block uintptr = ((*VP8Decoder)(unsafe.Pointer(dec)).mb_data_ + uintptr((*VP8Decoder)(unsafe.Pointer(dec)).mb_x_)*800) + var q uintptr = ((dec + 1060 /* &.dqm_ */) + uintptr((*VP8MBData)(unsafe.Pointer(block)).segment_)*32) + var dst uintptr = block /* &.coeffs_ */ + var left_mb uintptr = ((*VP8Decoder)(unsafe.Pointer(dec)).mb_info_ - uintptr(1)*2) + var tnz uint8_t + var lnz uint8_t + var non_zero_y uint32_t = uint32_t(0) + var non_zero_uv uint32_t = uint32_t(0) + var x int32 + var y int32 + var ch int32 + var out_t_nz uint32_t + var out_l_nz uint32_t + var first int32 + + libc.Xmemset(tls, dst, 0, (uint64(384) * uint64(unsafe.Sizeof(int16_t(0))))) + if !(int32((*VP8MBData)(unsafe.Pointer(block)).is_i4x4_) != 0) { // parse DC + *(*[16]int16_t)(unsafe.Pointer(bp /* dc */)) = [16]int16_t{0: int16(0)} + var ctx int32 = (int32((*VP8MB)(unsafe.Pointer(mb)).nz_dc_) + int32((*VP8MB)(unsafe.Pointer(left_mb)).nz_dc_)) + var nz int32 = (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr, int32, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{GetCoeffs})).f(tls, token_br, (bands + 1*136), ctx, (q + 8 /* &.y2_mat_ */), 0, (bp) /* &dc[0] */) + (*VP8MB)(unsafe.Pointer(mb)).nz_dc_ = libc.AssignPtrUint8((left_mb + 1 /* &.nz_dc_ */), (uint8_t(libc.Bool32(nz > 0)))) + if nz > 1 { // more than just the DC -> perform the full transform + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8TransformWHT})).f(tls, (bp) /* &dc[0] */, dst) + } else { // only DC is non-zero -> inlined simplified transform + var i int32 + var dc0 int32 = ((int32(*(*int16_t)(unsafe.Pointer((bp) /* &dc[0] */))) + 3) >> 3) + for i = 0; i < (16 * 16); i = i + (16) { + *(*int16_t)(unsafe.Pointer(dst + uintptr(i)*2)) = int16_t(dc0) + } + } + first = 1 + ac_proba = (bands) + } else { + first = 0 + ac_proba = (bands + 3*136) + } + + tnz = (uint8_t(int32((*VP8MB)(unsafe.Pointer(mb)).nz_) & 0x0f)) + lnz = (uint8_t(int32((*VP8MB)(unsafe.Pointer(left_mb)).nz_) & 0x0f)) + for y = 0; y < 4; y++ { + var l int32 = (int32(lnz) & 1) + var nz_coeffs uint32_t = uint32_t(0) + for x = 0; x < 4; x++ { + var ctx int32 = (l + (int32(tnz) & 1)) + var nz int32 = (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr, int32, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{GetCoeffs})).f(tls, token_br, ac_proba, ctx, (q /* &.y1_mat_ */), first, dst) + l = (libc.Bool32(nz > first)) + tnz = (uint8_t((int32(tnz) >> 1) | (l << 7))) + nz_coeffs = NzCodeBits(tls, nz_coeffs, nz, (libc.Bool32(int32(*(*int16_t)(unsafe.Pointer(dst))) != 0))) + dst += 2 * (uintptr(16)) + } + tnz >>= 4 + lnz = (uint8_t((int32(lnz) >> 1) | (l << 7))) + non_zero_y = ((non_zero_y << 8) | nz_coeffs) + } + out_t_nz = uint32_t(tnz) + out_l_nz = (uint32_t(int32(lnz) >> 4)) + + for ch = 0; ch < 4; ch = ch + (2) { + var nz_coeffs uint32_t = uint32_t(0) + tnz = (uint8_t(int32((*VP8MB)(unsafe.Pointer(mb)).nz_) >> (4 + ch))) + lnz = (uint8_t(int32((*VP8MB)(unsafe.Pointer(left_mb)).nz_) >> (4 + ch))) + for y = 0; y < 2; y++ { + var l int32 = (int32(lnz) & 1) + for x = 0; x < 2; x++ { + var ctx int32 = (l + (int32(tnz) & 1)) + var nz int32 = (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr, int32, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{GetCoeffs})).f(tls, token_br, (bands + 2*136), ctx, (q + 16 /* &.uv_mat_ */), 0, dst) + l = (libc.Bool32(nz > 0)) + tnz = (uint8_t((int32(tnz) >> 1) | (l << 3))) + nz_coeffs = NzCodeBits(tls, nz_coeffs, nz, (libc.Bool32(int32(*(*int16_t)(unsafe.Pointer(dst))) != 0))) + dst += 2 * (uintptr(16)) + } + tnz >>= 2 + lnz = (uint8_t((int32(lnz) >> 1) | (l << 5))) + } + // Note: we don't really need the per-4x4 details for U/V blocks. + non_zero_uv = non_zero_uv | (nz_coeffs << (4 * ch)) + out_t_nz = out_t_nz | (uint32_t((int32(tnz) << 4) << ch)) + out_l_nz = out_l_nz | (uint32_t((int32(lnz) & 0xf0) << ch)) + } + (*VP8MB)(unsafe.Pointer(mb)).nz_ = uint8_t(out_t_nz) + (*VP8MB)(unsafe.Pointer(left_mb)).nz_ = uint8_t(out_l_nz) + + (*VP8MBData)(unsafe.Pointer(block)).non_zero_y_ = non_zero_y + (*VP8MBData)(unsafe.Pointer(block)).non_zero_uv_ = non_zero_uv + + // We look at the mode-code of each block and check if some blocks have less + // than three non-zero coeffs (code < 2). This is to avoid dithering flat and + // empty blocks. + (*VP8MBData)(unsafe.Pointer(block)).dither_ = func() uint8 { + if (non_zero_uv & uint32_t(0xaaaa)) != 0 { + return uint8(0) + } + return uint8((*VP8QuantMatrix)(unsafe.Pointer(q)).dither_) + }() + + return libc.BoolInt32(!((non_zero_y | non_zero_uv) != 0)) // will be used for further optimization +} + +//------------------------------------------------------------------------------ +// Main loop + +func VP8DecodeMB(tls *libc.TLS, dec uintptr, token_br uintptr) int32 { /* vp8_dec.c:605:5: */ + var left uintptr = ((*VP8Decoder)(unsafe.Pointer(dec)).mb_info_ - uintptr(1)*2) + var mb uintptr = ((*VP8Decoder)(unsafe.Pointer(dec)).mb_info_ + uintptr((*VP8Decoder)(unsafe.Pointer(dec)).mb_x_)*2) + var block uintptr = ((*VP8Decoder)(unsafe.Pointer(dec)).mb_data_ + uintptr((*VP8Decoder)(unsafe.Pointer(dec)).mb_x_)*800) + var skip int32 + if (*VP8Decoder)(unsafe.Pointer(dec)).use_skip_proba_ != 0 { + skip = int32((*VP8MBData)(unsafe.Pointer(block)).skip_) + } else { + skip = 0 + } + + if !(skip != 0) { + skip = ParseResiduals(tls, dec, mb, token_br) + } else { + (*VP8MB)(unsafe.Pointer(left)).nz_ = libc.AssignPtrUint8((mb /* &.nz_ */), uint8_t(0)) + if !(int32((*VP8MBData)(unsafe.Pointer(block)).is_i4x4_) != 0) { + (*VP8MB)(unsafe.Pointer(left)).nz_dc_ = libc.AssignPtrUint8((mb + 1 /* &.nz_dc_ */), uint8_t(0)) + } + (*VP8MBData)(unsafe.Pointer(block)).non_zero_y_ = uint32_t(0) + (*VP8MBData)(unsafe.Pointer(block)).non_zero_uv_ = uint32_t(0) + (*VP8MBData)(unsafe.Pointer(block)).dither_ = uint8_t(0) + } + + if (*VP8Decoder)(unsafe.Pointer(dec)).filter_type_ > 0 { // store filter info + var finfo uintptr = ((*VP8Decoder)(unsafe.Pointer(dec)).f_info_ + uintptr((*VP8Decoder)(unsafe.Pointer(dec)).mb_x_)*4) + *(*VP8FInfo)(unsafe.Pointer(finfo)) = *(*VP8FInfo)(unsafe.Pointer(((dec + 2924 /* &.fstrengths_ */) + uintptr((*VP8MBData)(unsafe.Pointer(block)).segment_)*8) + uintptr((*VP8MBData)(unsafe.Pointer(block)).is_i4x4_)*4)) + *(*uint8_t)(unsafe.Pointer((finfo + 2 /* &.f_inner_ */))) |= uint8_t((libc.BoolInt32(!(skip != 0)))) + } + + return libc.BoolInt32(!((*VP8BitReader)(unsafe.Pointer(token_br)).eof_ != 0)) +} + +func VP8InitScanline(tls *libc.TLS, dec uintptr) { /* vp8_dec.c:632:6: */ + var left uintptr = ((*VP8Decoder)(unsafe.Pointer(dec)).mb_info_ - uintptr(1)*2) + (*VP8MB)(unsafe.Pointer(left)).nz_ = uint8_t(0) + (*VP8MB)(unsafe.Pointer(left)).nz_dc_ = uint8_t(0) + libc.Xmemset(tls, (dec + 2816 /* &.intra_l_ */), B_DC_PRED, uint64(unsafe.Sizeof([4]uint8_t{}))) + (*VP8Decoder)(unsafe.Pointer(dec)).mb_x_ = 0 +} + +func ParseFrame(tls *libc.TLS, dec uintptr, io uintptr) int32 { /* vp8_dec.c:640:12: */ + for (*VP8Decoder)(unsafe.Pointer(dec)).mb_y_ = 0; (*VP8Decoder)(unsafe.Pointer(dec)).mb_y_ < (*VP8Decoder)(unsafe.Pointer(dec)).br_mb_y_; (*VP8Decoder)(unsafe.Pointer(dec)).mb_y_++ { + // Parse bitstream for this row. + var token_br uintptr = ((dec + 440 /* &.parts_ */) + uintptr((uint32_t((*VP8Decoder)(unsafe.Pointer(dec)).mb_y_)&(*VP8Decoder)(unsafe.Pointer(dec)).num_parts_minus_one_))*48) + if !(VP8ParseIntraModeRow(tls, (dec+16 /* &.br_ */), dec) != 0) { + return VP8SetError(tls, dec, VP8_STATUS_NOT_ENOUGH_DATA, + (ts + 398) /* "Premature end-of..." */) + } + for ; (*VP8Decoder)(unsafe.Pointer(dec)).mb_x_ < (*VP8Decoder)(unsafe.Pointer(dec)).mb_w_; (*VP8Decoder)(unsafe.Pointer(dec)).mb_x_++ { + if !(VP8DecodeMB(tls, dec, token_br) != 0) { + return VP8SetError(tls, dec, VP8_STATUS_NOT_ENOUGH_DATA, + (ts + 439) /* "Premature end-of..." */) + } + } + VP8InitScanline(tls, dec) // Prepare for next scanline + + // Reconstruct, filter and emit the row. + if !(VP8ProcessRow(tls, dec, io) != 0) { + return VP8SetError(tls, dec, VP8_STATUS_USER_ABORT, (ts + 474) /* "Output aborted." */) + } + } + if (*VP8Decoder)(unsafe.Pointer(dec)).mt_method_ > 0 { + if !((*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(WebPGetWorkerInterface(tls))).Sync})).f(tls, (dec+152 /* &.worker_ */)) != 0) { + return 0 + } + } + + return 1 +} + +// Main entry point +func VP8Decode(tls *libc.TLS, dec uintptr, io uintptr) int32 { /* vp8_dec.c:670:5: */ + var ok int32 = 0 + if dec == (uintptr(0)) { + return 0 + } + if io == (uintptr(0)) { + return VP8SetError(tls, dec, VP8_STATUS_INVALID_PARAM, + (ts + 490) /* "NULL VP8Io param..." */) + } + + if !((*VP8Decoder)(unsafe.Pointer(dec)).ready_ != 0) { + if !(VP8GetHeaders(tls, dec, io) != 0) { + return 0 + } + } + + // Finish setting up the decoding parameter. Will call io->setup(). + ok = (libc.Bool32(VP8EnterCritical(tls, dec, io) == VP8_STATUS_OK)) + if ok != 0 { // good to go. + // Will allocate memory and prepare everything. + if ok != 0 { + ok = VP8InitFrame(tls, dec, io) + } + + // Main decoding loop + if ok != 0 { + ok = ParseFrame(tls, dec, io) + } + + // Exit. + ok = ok & (VP8ExitCritical(tls, dec, io)) + } + + if !(ok != 0) { + VP8Clear(tls, dec) + return 0 + } + + (*VP8Decoder)(unsafe.Pointer(dec)).ready_ = 0 + return ok +} + +func VP8Clear(tls *libc.TLS, dec uintptr) { /* vp8_dec.c:709:6: */ + if dec == (uintptr(0)) { + return + } + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(WebPGetWorkerInterface(tls))).End})).f(tls, (dec + 152 /* &.worker_ */)) + WebPDeallocateAlphaMemory(tls, dec) + WebPSafeFree(tls, (*VP8Decoder)(unsafe.Pointer(dec)).mem_) + (*VP8Decoder)(unsafe.Pointer(dec)).mem_ = (uintptr(0)) + (*VP8Decoder)(unsafe.Pointer(dec)).mem_size_ = uint64(0) + libc.Xmemset(tls, (dec + 16 /* &.br_ */), 0, uint64(unsafe.Sizeof(VP8BitReader{}))) + (*VP8Decoder)(unsafe.Pointer(dec)).ready_ = 0 +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transforms and color space conversion methods for lossless decoder. +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Main decoding functions for WebP images. +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +// Models the histograms of literal and distance codes. + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.21 String handling <string.h> + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.2 Diagnostics <assert.h> + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// void assert (int expression); +// +// If NDEBUG is defined, do nothing. +// If not, and EXPRESSION is zero, print an error message and abort. + +// void assert_perror (int errnum); +// +// If NDEBUG is defined, do nothing. If not, and ERRNUM is not zero, print an +// error message with the error text for ERRNUM and abort. +// (This is a GNU extension.) + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.20 General utilities <stdlib.h> + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP encoder: main interface +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPImageHint WebPImageHint; +// typedef enum WebPEncCSP WebPEncCSP; +// typedef enum WebPPreset WebPPreset; +// typedef enum WebPEncodingError WebPEncodingError; +type WebPConfig1 = struct { + lossless int32 + quality float32 + method int32 + image_hint WebPImageHint + target_size int32 + target_PSNR float32 + segments int32 + sns_strength int32 + filter_strength int32 + filter_sharpness int32 + filter_type int32 + autofilter int32 + alpha_compression int32 + alpha_filtering int32 + alpha_quality int32 + pass int32 + show_compressed int32 + preprocessing int32 + partitions int32 + partition_limit int32 + emulate_jpeg_size int32 + thread_level int32 + low_memory int32 + near_lossless int32 + exact int32 + use_delta_palette int32 + use_sharp_yuv int32 + qmin int32 + qmax int32 +} /* encode.h:31:9 */ + +//------------------------------------------------------------------------------ + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transforms and color space conversion methods for lossless decoder. +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Main decoding functions for WebP images. +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +// Models the histograms of literal and distance codes. + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.21 String handling <string.h> + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.2 Diagnostics <assert.h> + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// void assert (int expression); +// +// If NDEBUG is defined, do nothing. +// If not, and EXPRESSION is zero, print an error message and abort. + +// void assert_perror (int errnum); +// +// If NDEBUG is defined, do nothing. If not, and ERRNUM is not zero, print an +// error message with the error text for ERRNUM and abort. +// (This is a GNU extension.) + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.20 General utilities <stdlib.h> + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP encoder: main interface +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPImageHint WebPImageHint; +// typedef enum WebPEncCSP WebPEncCSP; +// typedef enum WebPPreset WebPPreset; +// typedef enum WebPEncodingError WebPEncodingError; +type WebPConfig = WebPConfig1 /* encode.h:31:27 */ +type WebPPicture = WebPPicture1 /* encode.h:32:28 */ // main structure for I/O +type WebPAuxStats1 = struct { + coded_size int32 + PSNR [5]float32 + block_count [3]int32 + header_bytes [2]int32 + residual_bytes [3][4]int32 + segment_size [4]int32 + segment_quant [4]int32 + segment_level [4]int32 + alpha_data_size int32 + layer_data_size int32 + lossless_features uint32_t + histogram_bits int32 + transform_bits int32 + cache_bits int32 + palette_size int32 + lossless_size int32 + lossless_hdr_size int32 + lossless_data_size int32 + pad [2]uint32_t +} /* encode.h:32:9 */ + +// main structure for I/O +type WebPAuxStats = WebPAuxStats1 /* encode.h:33:29 */ +type WebPMemoryWriter1 = struct { + mem uintptr + size size_t + max_size size_t + pad [1]uint32_t + _ [4]byte +} /* encode.h:34:9 */ + +type WebPMemoryWriter = WebPMemoryWriter1 /* encode.h:34:33 */ + +//------------------------------------------------------------------------------ +// Coding parameters + +// Image characteristics hint for the underlying encoder. +type WebPImageHint = uint32 /* encode.h:92:3 */ + +// Enumerate some predefined settings for WebPConfig, depending on the type +// of source picture. These presets are used when calling WebPConfigPreset(). +type WebPPreset = uint32 /* encode.h:164:3 */ + +// Should always be called, to initialize a fresh WebPConfig structure before +// modification. Returns false in case of version mismatch. WebPConfigInit() +// must have succeeded before using the 'config' object. +// Note that the default values are lossless=0 and quality=75. +func WebPConfigInit(tls *libc.TLS, config uintptr) int32 { /* encode.h:173:24: */ + return WebPConfigInitInternal(tls, config, WEBP_PRESET_DEFAULT, 75., + 0x020f) +} + +// This function will initialize the configuration according to a predefined +// set of parameters (referred to by 'preset') and a given quality factor. +// This function can be called as a replacement to WebPConfigInit(). Will +// return false in case of error. +func WebPConfigPreset(tls *libc.TLS, config uintptr, preset WebPPreset, quality float32) int32 { /* encode.h:182:24: */ + return WebPConfigInitInternal(tls, config, preset, quality, + 0x020f) +} + +// Signature for output function. Should return true if writing was successful. +// data/data_size is the segment of data to write, and 'picture' is for +// reference (and so one can make use of picture->custom_ptr). +type WebPWriterFunction = uintptr /* encode.h:237:13 */ + +// Progress hook, called from time to time to report progress. It can return +// false to request an abort of the encoding process, or true otherwise if +// everything is OK. +type WebPProgressHook = uintptr /* encode.h:264:13 */ + +// Color spaces. +type WebPEncCSP = uint32 /* encode.h:273:3 */ + +// Encoding error conditions. +type WebPEncodingError = uint32 /* encode.h:289:3 */ + +// Should always be called, to initialize the structure. Returns false in case +// of version mismatch. WebPPictureInit() must have succeeded before using the +// 'picture' object. +// Note that, by default, use_argb is false and colorspace is WEBP_YUV420. +func WebPPictureInit(tls *libc.TLS, picture uintptr) int32 { /* encode.h:373:24: */ + return WebPPictureInitInternal(tls, picture, 0x020f) +} + +type PixOrCopy = struct { + mode uint8_t + _ [1]byte + len uint16_t + argb_or_distance uint32_t +} /* backward_references_enc.h:44:3 */ + +func PixOrCopyCreateCopy(tls *libc.TLS, distance uint32_t, len uint16_t) PixOrCopy { /* backward_references_enc.h:46:30: */ + var retval PixOrCopy + retval.mode = kCopy + retval.argb_or_distance = distance + retval.len = len + return retval +} + +func PixOrCopyCreateCacheIdx(tls *libc.TLS, idx int32) PixOrCopy { /* backward_references_enc.h:55:30: */ + var retval PixOrCopy + + retval.mode = kCacheIdx + retval.argb_or_distance = uint32_t(idx) + retval.len = uint16_t(1) + return retval +} + +func PixOrCopyCreateLiteral(tls *libc.TLS, argb uint32_t) PixOrCopy { /* backward_references_enc.h:65:30: */ + var retval PixOrCopy + retval.mode = kLiteral + retval.argb_or_distance = argb + retval.len = uint16_t(1) + return retval +} + +func PixOrCopyIsLiteral(tls *libc.TLS, p uintptr) int32 { /* backward_references_enc.h:73:24: */ + return (libc.Bool32(int32((*PixOrCopy)(unsafe.Pointer(p)).mode) == kLiteral)) +} + +func PixOrCopyIsCacheIdx(tls *libc.TLS, p uintptr) int32 { /* backward_references_enc.h:77:24: */ + return (libc.Bool32(int32((*PixOrCopy)(unsafe.Pointer(p)).mode) == kCacheIdx)) +} + +func PixOrCopyIsCopy(tls *libc.TLS, p uintptr) int32 { /* backward_references_enc.h:81:24: */ + return (libc.Bool32(int32((*PixOrCopy)(unsafe.Pointer(p)).mode) == kCopy)) +} + +func PixOrCopyLiteral(tls *libc.TLS, p uintptr, component int32) uint32_t { /* backward_references_enc.h:85:29: */ + + return (((*PixOrCopy)(unsafe.Pointer(p)).argb_or_distance >> (component * 8)) & uint32_t(0xff)) +} + +func PixOrCopyLength(tls *libc.TLS, p uintptr) uint32_t { /* backward_references_enc.h:91:29: */ + return uint32_t((*PixOrCopy)(unsafe.Pointer(p)).len) +} + +func PixOrCopyCacheIdx(tls *libc.TLS, p uintptr) uint32_t { /* backward_references_enc.h:95:29: */ + + return (*PixOrCopy)(unsafe.Pointer(p)).argb_or_distance +} + +func PixOrCopyDistance(tls *libc.TLS, p uintptr) uint32_t { /* backward_references_enc.h:101:29: */ + + return (*PixOrCopy)(unsafe.Pointer(p)).argb_or_distance +} + +// ----------------------------------------------------------------------------- +// VP8LHashChain + +// If you change this, you need MAX_LENGTH_BITS + WINDOW_SIZE_BITS <= 32 as it +// is used in VP8LHashChain. +// We want the max value to be attainable and stored in MAX_LENGTH_BITS bits. + +type VP8LHashChain1 = struct { + offset_length_ uintptr + size_ int32 + _ [4]byte +} /* backward_references_enc.h:122:9 */ + +// ----------------------------------------------------------------------------- +// VP8LHashChain + +// If you change this, you need MAX_LENGTH_BITS + WINDOW_SIZE_BITS <= 32 as it +// is used in VP8LHashChain. +// We want the max value to be attainable and stored in MAX_LENGTH_BITS bits. + +type VP8LHashChain = VP8LHashChain1 /* backward_references_enc.h:122:30 */ + +// release memory + +func VP8LHashChainFindOffset(tls *libc.TLS, p uintptr, base_position int32) int32 { /* backward_references_enc.h:143:24: */ + return (int32(*(*uint32_t)(unsafe.Pointer((*VP8LHashChain)(unsafe.Pointer(p)).offset_length_ + uintptr(base_position)*4)) >> 12)) +} + +func VP8LHashChainFindLength(tls *libc.TLS, p uintptr, base_position int32) int32 { /* backward_references_enc.h:148:24: */ + return (int32(*(*uint32_t)(unsafe.Pointer((*VP8LHashChain)(unsafe.Pointer(p)).offset_length_ + uintptr(base_position)*4)) & ((uint32(1) << 12) - uint32(1)))) +} + +func VP8LHashChainFindCopy(tls *libc.TLS, p uintptr, base_position int32, offset_ptr uintptr, length_ptr uintptr) { /* backward_references_enc.h:153:25: */ + *(*int32)(unsafe.Pointer(offset_ptr)) = VP8LHashChainFindOffset(tls, p, base_position) + *(*int32)(unsafe.Pointer(length_ptr)) = VP8LHashChainFindLength(tls, p, base_position) +} + +// ----------------------------------------------------------------------------- +// VP8LBackwardRefs (block-based backward-references storage) + +// maximum number of reference blocks the image will be segmented into + +type PixOrCopyBlock1 = struct { + next_ uintptr + start_ uintptr + size_ int32 + _ [4]byte +} /* backward_references_enc.h:167:9 */ + +// forward declaration +type VP8LBackwardRefs1 = struct { + block_size_ int32 + error_ int32 + refs_ uintptr + tail_ uintptr + free_blocks_ uintptr + last_block_ uintptr +} /* backward_references_enc.h:168:9 */ + +// forward declaration +type VP8LBackwardRefs = VP8LBackwardRefs1 /* backward_references_enc.h:168:33 */ + +// Cursor for iterating on references content +type VP8LRefsCursor = struct { + cur_pos uintptr + cur_block_ uintptr + last_pos_ uintptr +} /* backward_references_enc.h:193:3 */ + +// Returns true if cursor is pointing at a valid position. +func VP8LRefsCursorOk(tls *libc.TLS, c uintptr) int32 { /* backward_references_enc.h:198:24: */ + return (libc.Bool32((*VP8LRefsCursor)(unsafe.Pointer(c)).cur_pos != (uintptr(0)))) +} + +// Move to next position, or NULL. Should not be called if !VP8LRefsCursorOk(). +func VP8LRefsCursorNext(tls *libc.TLS, c uintptr) { /* backward_references_enc.h:204:25: */ + + if libc.PreIncUintptr(&(*VP8LRefsCursor)(unsafe.Pointer(c)).cur_pos, 8) == (*VP8LRefsCursor)(unsafe.Pointer(c)).last_pos_ { + VP8LRefsCursorNextBlock(tls, c) + } +} + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header for constants related to WebP file format. +// +// Author: Urvang (urvang@google.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Not a trivial literal symbol. + +// A simple container for histograms of data. +type VP8LHistogram = struct { + literal_ uintptr + red_ [256]uint32_t + blue_ [256]uint32_t + alpha_ [256]uint32_t + distance_ [40]uint32_t + palette_code_bits_ int32 + trivial_symbol_ uint32_t + bit_cost_ float64 + literal_cost_ float64 + red_cost_ float64 + blue_cost_ float64 + is_used_ [5]uint8_t + _ [3]byte +} /* histogram_enc.h:48:3 */ + +// Collection of histograms with fixed capacity, allocated as one +// big memory chunk. Can be destroyed by calling WebPSafeFree(). +type VP8LHistogramSet = struct { + size int32 + max_size int32 + histograms uintptr +} /* histogram_enc.h:56:3 */ + +func VP8LHistogramNumCodes(tls *libc.TLS, palette_code_bits int32) int32 { /* histogram_enc.h:103:24: */ + return ((256 + 24) + (func() int32 { + if palette_code_bits > 0 { + return (int32(1) << palette_code_bits) + } + return 0 + }())) +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Decoding + +type VP8LPredictorFunc = uintptr /* lossless.h:31:18 */ + +// These Add/Sub function expects upper[-1] and out[-1] to be readable. +type VP8LPredictorAddSubFunc = uintptr /* lossless.h:65:14 */ + +type VP8LProcessDecBlueAndRedFunc = uintptr /* lossless.h:71:14 */ + +type VP8LMultipliers = struct { + green_to_red_ uint8_t + green_to_blue_ uint8_t + red_to_blue_ uint8_t +} /* lossless.h:81:3 */ +type VP8LTransformColorInverseFunc = uintptr /* lossless.h:82:14 */ + +// Color space conversion. +type VP8LConvertFunc = uintptr /* lossless.h:98:14 */ + +type VP8LMapARGBFunc = uintptr /* lossless.h:110:14 */ +type VP8LMapAlphaFunc = uintptr /* lossless.h:114:14 */ + +//------------------------------------------------------------------------------ +// Encoding + +type VP8LProcessEncBlueAndRedFunc = uintptr /* lossless.h:150:14 */ +type VP8LTransformColorFunc = uintptr /* lossless.h:152:14 */ +type VP8LCollectColorBlueTransformsFunc = uintptr /* lossless.h:155:14 */ + +type VP8LCollectColorRedTransformsFunc = uintptr /* lossless.h:161:14 */ + +// ----------------------------------------------------------------------------- +// Huffman-cost related functions. + +type VP8LCostFunc = uintptr /* lossless.h:185:16 */ +type VP8LCostCombinedFunc = uintptr /* lossless.h:186:16 */ +type VP8LCombinedShannonEntropyFunc = uintptr /* lossless.h:188:15 */ + +type VP8LStreaks = struct { + counts [2]int32 + streaks [2][2]int32 +} /* lossless.h:198:3 */ + +type VP8LBitEntropy = struct { + entropy float64 + sum uint32_t + nonzeros int32 + max_val uint32_t + nonzero_code uint32_t +} /* lossless.h:206:3 */ + +// Get the combined symbol bit entropy and Huffman cost stats for the +// distributions 'X' and 'Y'. Those results can then be refined according to +// codec specific heuristics. +type VP8LGetCombinedEntropyUnrefinedFunc = uintptr /* lossless.h:213:14 */ + +// Get the entropy for the distribution 'X'. +type VP8LGetEntropyUnrefinedFunc = uintptr /* lossless.h:219:14 */ + +type VP8LAddVectorFunc = uintptr /* lossless.h:227:14 */ +type VP8LAddVectorEqFunc = uintptr /* lossless.h:230:14 */ + +// ----------------------------------------------------------------------------- +// PrefixEncode() + +type VP8LVectorMismatchFunc = uintptr /* lossless.h:239:13 */ + +type VP8LBundleColorMapFunc = uintptr /* lossless.h:244:14 */ + +//------------------------------------------------------------------------------ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Image transforms and color space conversion methods for lossless decoder. +// +// Authors: Vikas Arora (vikaas.arora@gmail.com) +// Jyrki Alakuijala (jyrki@google.com) +// Vincent Rabaud (vrabaud@google.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +//------------------------------------------------------------------------------ +// Decoding + +// color mapping related functions. +func VP8GetARGBIndex(tls *libc.TLS, idx uint32_t) uint32_t { /* lossless_common.h:31:29: */ + return ((idx >> 8) & uint32_t(0xff)) +} + +func VP8GetAlphaIndex(tls *libc.TLS, idx uint8_t) uint8_t { /* lossless_common.h:35:28: */ + return idx +} + +func VP8GetARGBValue(tls *libc.TLS, val uint32_t) uint32_t { /* lossless_common.h:39:29: */ + return val +} + +func VP8GetAlphaValue(tls *libc.TLS, val uint32_t) uint8_t { /* lossless_common.h:43:28: */ + return (uint8_t((val >> 8) & uint32_t(0xff))) +} + +//------------------------------------------------------------------------------ +// Misc methods. + +// Computes sampled size of 'size' when sampling using 'sampling bits'. +func VP8LSubSampleSize(tls *libc.TLS, size uint32_t, sampling_bits uint32_t) uint32_t { /* lossless_common.h:51:29: */ + return (((size + (uint32_t(int32(1) << sampling_bits))) - uint32_t(1)) >> sampling_bits) +} + +// Converts near lossless quality into max number of bits shaved off. +func VP8LNearLosslessBits(tls *libc.TLS, near_lossless_quality int32) int32 { /* lossless_common.h:57:24: */ + // 100 -> 0 + // 80..99 -> 1 + // 60..79 -> 2 + // 40..59 -> 3 + // 20..39 -> 4 + // 0..19 -> 5 + return (5 - (near_lossless_quality / 20)) +} + +type VP8LFastLog2SlowFunc = uintptr /* lossless_common.h:80:15 */ + +func VP8LFastLog2(tls *libc.TLS, v uint32_t) float32 { /* lossless_common.h:85:26: */ + if v < uint32_t(256) { + return kLog2Table[v] + } + return (*struct { + f func(*libc.TLS, uint32_t) float32 + })(unsafe.Pointer(&struct{ uintptr }{VP8LFastLog2Slow})).f(tls, v) +} + +// Fast calculation of v * log2(v) for integer input. +func VP8LFastSLog2(tls *libc.TLS, v uint32_t) float32 { /* lossless_common.h:89:26: */ + if v < uint32_t(256) { + return kSLog2Table[v] + } + return (*struct { + f func(*libc.TLS, uint32_t) float32 + })(unsafe.Pointer(&struct{ uintptr }{VP8LFastSLog2Slow})).f(tls, v) +} + +// ----------------------------------------------------------------------------- +// PrefixEncode() + +// Splitting of distance and length codes into prefixes and +// extra bits. The prefixes are encoded with an entropy code +// while the extra bits are stored just as normal bits. +func VP8LPrefixEncodeBitsNoLUT(tls *libc.TLS, distance int32, code uintptr, extra_bits uintptr) { /* lossless_common.h:99:25: */ + var highest_bit int32 = BitsLog2Floor(tls, uint32(libc.PreDecInt32(&distance, 1))) + var second_highest_bit int32 = ((distance >> (highest_bit - 1)) & 1) + *(*int32)(unsafe.Pointer(extra_bits)) = (highest_bit - 1) + *(*int32)(unsafe.Pointer(code)) = ((2 * highest_bit) + second_highest_bit) +} + +func VP8LPrefixEncodeNoLUT(tls *libc.TLS, distance int32, code uintptr, extra_bits uintptr, extra_bits_value uintptr) { /* lossless_common.h:107:25: */ + var highest_bit int32 = BitsLog2Floor(tls, uint32(libc.PreDecInt32(&distance, 1))) + var second_highest_bit int32 = ((distance >> (highest_bit - 1)) & 1) + *(*int32)(unsafe.Pointer(extra_bits)) = (highest_bit - 1) + *(*int32)(unsafe.Pointer(extra_bits_value)) = (distance & ((int32(1) << *(*int32)(unsafe.Pointer(extra_bits))) - 1)) + *(*int32)(unsafe.Pointer(code)) = ((2 * highest_bit) + second_highest_bit) +} + +type VP8LPrefixCode = struct { + code_ int8_t + extra_bits_ int8_t +} /* lossless_common.h:121:3 */ + +func VP8LPrefixEncodeBits(tls *libc.TLS, distance int32, code uintptr, extra_bits uintptr) { /* lossless_common.h:126:25: */ + if distance < 512 { + var prefix_code = kPrefixEncodeCode[distance] + *(*int32)(unsafe.Pointer(code)) = int32(prefix_code.code_) + *(*int32)(unsafe.Pointer(extra_bits)) = int32(prefix_code.extra_bits_) + } else { + VP8LPrefixEncodeBitsNoLUT(tls, distance, code, extra_bits) + } +} + +func VP8LPrefixEncode(tls *libc.TLS, distance int32, code uintptr, extra_bits uintptr, extra_bits_value uintptr) { /* lossless_common.h:137:25: */ + if distance < 512 { + var prefix_code = kPrefixEncodeCode[distance] + *(*int32)(unsafe.Pointer(code)) = int32(prefix_code.code_) + *(*int32)(unsafe.Pointer(extra_bits)) = int32(prefix_code.extra_bits_) + *(*int32)(unsafe.Pointer(extra_bits_value)) = int32(kPrefixEncodeExtraBitsValue[distance]) + } else { + VP8LPrefixEncodeNoLUT(tls, distance, code, extra_bits, extra_bits_value) + } +} + +// Sum of each component, mod 256. +func VP8LAddPixels(tls *libc.TLS, a uint32_t, b uint32_t) uint32_t { /* lossless_common.h:152:10: */ + var alpha_and_green uint32_t = ((a & 0xff00ff00) + (b & 0xff00ff00)) + var red_and_blue uint32_t = ((a & 0x00ff00ff) + (b & 0x00ff00ff)) + return ((alpha_and_green & 0xff00ff00) | (red_and_blue & 0x00ff00ff)) +} + +// Difference of each component, mod 256. +func VP8LSubPixels(tls *libc.TLS, a uint32_t, b uint32_t) uint32_t { /* lossless_common.h:160:10: */ + var alpha_and_green uint32_t = ((0x00ff00ff + (a & 0xff00ff00)) - (b & 0xff00ff00)) + var red_and_blue uint32_t = ((0xff00ff00 + (a & 0x00ff00ff)) - (b & 0x00ff00ff)) + return ((alpha_and_green & 0xff00ff00) | (red_and_blue & 0x00ff00ff)) +} + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Utilities for building and looking up Huffman trees. +// +// Author: Urvang Joshi (urvang@google.com) + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +var kCodeLengthLiterals int32 = 16 /* vp8l_dec.c:29:18 */ +var kCodeLengthRepeatCode int32 = 16 /* vp8l_dec.c:30:18 */ +var kCodeLengthExtraBits = [3]uint8_t{uint8_t(2), uint8_t(3), uint8_t(7)} /* vp8l_dec.c:31:22 */ +var kCodeLengthRepeatOffsets = [3]uint8_t{uint8_t(3), uint8_t(3), uint8_t(11)} /* vp8l_dec.c:32:22 */ + +// ----------------------------------------------------------------------------- +// Five Huffman codes are used at each meta code: +// 1. green + length prefix codes + color cache codes, +// 2. alpha, +// 3. red, +// 4. blue, and, +// 5. distance prefix codes. +type HuffIndex = uint32 /* vp8l_dec.c:47:3 */ + +var kAlphabetSize = [5]uint16_t{ + (uint16_t(256 + 24)), + uint16_t(256), uint16_t(256), uint16_t(256), + uint16_t(40), +} /* vp8l_dec.c:49:23 */ + +var kLiteralMap = [5]uint8_t{ + uint8_t(0), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(0), +} /* vp8l_dec.c:55:22 */ + +var kCodeLengthCodeOrder = [19]uint8_t{ + uint8_t(17), uint8_t(18), uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(4), uint8_t(5), uint8_t(16), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(10), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(14), uint8_t(15), +} /* vp8l_dec.c:60:22 */ + +var kCodeToPlane = [120]uint8_t{ + uint8_t(0x18), uint8_t(0x07), uint8_t(0x17), uint8_t(0x19), uint8_t(0x28), uint8_t(0x06), uint8_t(0x27), uint8_t(0x29), uint8_t(0x16), uint8_t(0x1a), + uint8_t(0x26), uint8_t(0x2a), uint8_t(0x38), uint8_t(0x05), uint8_t(0x37), uint8_t(0x39), uint8_t(0x15), uint8_t(0x1b), uint8_t(0x36), uint8_t(0x3a), + uint8_t(0x25), uint8_t(0x2b), uint8_t(0x48), uint8_t(0x04), uint8_t(0x47), uint8_t(0x49), uint8_t(0x14), uint8_t(0x1c), uint8_t(0x35), uint8_t(0x3b), + uint8_t(0x46), uint8_t(0x4a), uint8_t(0x24), uint8_t(0x2c), uint8_t(0x58), uint8_t(0x45), uint8_t(0x4b), uint8_t(0x34), uint8_t(0x3c), uint8_t(0x03), + uint8_t(0x57), uint8_t(0x59), uint8_t(0x13), uint8_t(0x1d), uint8_t(0x56), uint8_t(0x5a), uint8_t(0x23), uint8_t(0x2d), uint8_t(0x44), uint8_t(0x4c), + uint8_t(0x55), uint8_t(0x5b), uint8_t(0x33), uint8_t(0x3d), uint8_t(0x68), uint8_t(0x02), uint8_t(0x67), uint8_t(0x69), uint8_t(0x12), uint8_t(0x1e), + uint8_t(0x66), uint8_t(0x6a), uint8_t(0x22), uint8_t(0x2e), uint8_t(0x54), uint8_t(0x5c), uint8_t(0x43), uint8_t(0x4d), uint8_t(0x65), uint8_t(0x6b), + uint8_t(0x32), uint8_t(0x3e), uint8_t(0x78), uint8_t(0x01), uint8_t(0x77), uint8_t(0x79), uint8_t(0x53), uint8_t(0x5d), uint8_t(0x11), uint8_t(0x1f), + uint8_t(0x64), uint8_t(0x6c), uint8_t(0x42), uint8_t(0x4e), uint8_t(0x76), uint8_t(0x7a), uint8_t(0x21), uint8_t(0x2f), uint8_t(0x75), uint8_t(0x7b), + uint8_t(0x31), uint8_t(0x3f), uint8_t(0x63), uint8_t(0x6d), uint8_t(0x52), uint8_t(0x5e), uint8_t(0x00), uint8_t(0x74), uint8_t(0x7c), uint8_t(0x41), + uint8_t(0x4f), uint8_t(0x10), uint8_t(0x20), uint8_t(0x62), uint8_t(0x6e), uint8_t(0x30), uint8_t(0x73), uint8_t(0x7d), uint8_t(0x51), uint8_t(0x5f), + uint8_t(0x40), uint8_t(0x72), uint8_t(0x7e), uint8_t(0x61), uint8_t(0x6f), uint8_t(0x50), uint8_t(0x71), uint8_t(0x7f), uint8_t(0x60), uint8_t(0x70), +} /* vp8l_dec.c:65:22 */ + +// Memory needed for lookup tables of one Huffman tree group. Red, blue, alpha +// and distance alphabets are constant (256 for red, blue and alpha, 40 for +// distance) and lookup table sizes for them in worst case are 630 and 410 +// respectively. Size of green alphabet depends on color cache size and is equal +// to 256 (green component values) + 24 (length prefix values) +// + color_cache_size (between 0 and 2048). +// All values computed for 8-bit first level lookup with Mark Adler's tool: +// https://github.com/madler/zlib/blob/v1.2.5/examples/enough.c +var kTableSize = [12]uint16_t{ + (uint16_t(((630 * 3) + 410) + 654)), + (uint16_t(((630 * 3) + 410) + 656)), + (uint16_t(((630 * 3) + 410) + 658)), + (uint16_t(((630 * 3) + 410) + 662)), + (uint16_t(((630 * 3) + 410) + 670)), + (uint16_t(((630 * 3) + 410) + 686)), + (uint16_t(((630 * 3) + 410) + 718)), + (uint16_t(((630 * 3) + 410) + 782)), + (uint16_t(((630 * 3) + 410) + 912)), + (uint16_t(((630 * 3) + 410) + 1168)), + (uint16_t(((630 * 3) + 410) + 1680)), + (uint16_t(((630 * 3) + 410) + 2704)), +} /* vp8l_dec.c:89:23 */ + +//------------------------------------------------------------------------------ + +func VP8LCheckSignature(tls *libc.TLS, data uintptr, size size_t) int32 { /* vp8l_dec.c:111:5: */ + return (libc.Bool32(((size >= uint64(5)) && (int32(*(*uint8_t)(unsafe.Pointer(data))) == 0x2f)) && ((int32(*(*uint8_t)(unsafe.Pointer(data + 4))) >> 5) == 0))) // version +} + +func ReadImageInfo(tls *libc.TLS, br uintptr, width uintptr, height uintptr, has_alpha uintptr) int32 { /* vp8l_dec.c:117:12: */ + if VP8LReadBits(tls, br, 8) != uint32_t(0x2f) { + return 0 + } + *(*int32)(unsafe.Pointer(width)) = (int32(VP8LReadBits(tls, br, 14) + uint32_t(1))) + *(*int32)(unsafe.Pointer(height)) = (int32(VP8LReadBits(tls, br, 14) + uint32_t(1))) + *(*int32)(unsafe.Pointer(has_alpha)) = int32(VP8LReadBits(tls, br, 1)) + if VP8LReadBits(tls, br, 3) != uint32_t(0) { + return 0 + } + return libc.BoolInt32(!((*VP8LBitReader)(unsafe.Pointer(br)).eos_ != 0)) +} + +func VP8LGetInfo(tls *libc.TLS, data uintptr, data_size size_t, width uintptr, height uintptr, has_alpha uintptr) int32 { /* vp8l_dec.c:128:5: */ + bp := tls.Alloc(52) + defer tls.Free(52) + + if (data == (uintptr(0))) || (data_size < uint64(5)) { + return 0 // not enough data + } else if !(VP8LCheckSignature(tls, data, data_size) != 0) { + return 0 // bad signature + } else { + // var w int32 at bp+40, 4 + + // var h int32 at bp+44, 4 + + // var a int32 at bp+48, 4 + + // var br VP8LBitReader at bp, 40 + + VP8LInitBitReader(tls, (bp) /* &br */, data, data_size) + if !(ReadImageInfo(tls, (bp) /* &br */, (bp+40) /* &w */, (bp+44) /* &h */, (bp+48) /* &a */) != 0) { + return 0 + } + if width != (uintptr(0)) { + *(*int32)(unsafe.Pointer(width)) = *(*int32)(unsafe.Pointer(bp + 40 /* w */)) + } + if height != (uintptr(0)) { + *(*int32)(unsafe.Pointer(height)) = *(*int32)(unsafe.Pointer(bp + 44 /* h */)) + } + if has_alpha != (uintptr(0)) { + *(*int32)(unsafe.Pointer(has_alpha)) = *(*int32)(unsafe.Pointer(bp + 48 /* a */)) + } + return 1 + } + return int32(0) +} + +//------------------------------------------------------------------------------ + +func GetCopyDistance(tls *libc.TLS, distance_symbol int32, br uintptr) int32 { /* vp8l_dec.c:150:24: */ + var extra_bits int32 + var offset int32 + if distance_symbol < 4 { + return (distance_symbol + 1) + } + extra_bits = ((distance_symbol - 2) >> 1) + offset = ((2 + (distance_symbol & 1)) << extra_bits) + return (int32((uint32_t(offset) + VP8LReadBits(tls, br, extra_bits)) + uint32_t(1))) +} + +func GetCopyLength(tls *libc.TLS, length_symbol int32, br uintptr) int32 { /* vp8l_dec.c:161:24: */ + // Length and distance prefixes are encoded the same way. + return GetCopyDistance(tls, length_symbol, br) +} + +func PlaneCodeToDistance(tls *libc.TLS, xsize int32, plane_code int32) int32 { /* vp8l_dec.c:167:24: */ + if plane_code > 120 { + return (plane_code - 120) + } else { + var dist_code int32 = int32(kCodeToPlane[(plane_code - 1)]) + var yoffset int32 = (dist_code >> 4) + var xoffset int32 = (8 - (dist_code & 0xf)) + var dist int32 = ((yoffset * xsize) + xoffset) + if dist >= 1 { + return dist + } + return 1 // dist<1 can happen if xsize is very small + } + return int32(0) +} + +//------------------------------------------------------------------------------ +// Decodes the next Huffman code from bit-stream. +// FillBitWindow(br) needs to be called at minimum every second call +// to ReadSymbol, in order to pre-fetch enough bits. +func ReadSymbol(tls *libc.TLS, table uintptr, br uintptr) int32 { /* vp8l_dec.c:183:24: */ + var nbits int32 + var val uint32_t = VP8LPrefetchBits(tls, br) + table += 4 * (uintptr(val & (uint32_t((int32(1) << 8) - 1)))) + nbits = (int32((*HuffmanCode)(unsafe.Pointer(table)).bits) - 8) + if nbits > 0 { + VP8LSetBitPos(tls, br, ((*VP8LBitReader)(unsafe.Pointer(br)).bit_pos_ + 8)) + val = VP8LPrefetchBits(tls, br) + table += 4 * (uintptr((*HuffmanCode)(unsafe.Pointer(table)).value)) + table += 4 * (uintptr(val & (uint32_t((int32(1) << nbits) - 1)))) + } + VP8LSetBitPos(tls, br, ((*VP8LBitReader)(unsafe.Pointer(br)).bit_pos_ + int32((*HuffmanCode)(unsafe.Pointer(table)).bits))) + return int32((*HuffmanCode)(unsafe.Pointer(table)).value) +} + +// Reads packed symbol depending on GREEN channel +func ReadPackedSymbols(tls *libc.TLS, group uintptr, br uintptr, dst uintptr) int32 { /* vp8l_dec.c:202:24: */ + var val uint32_t = (VP8LPrefetchBits(tls, br) & ((uint32(1) << 6) - uint32(1))) + var code = *(*HuffmanCode32)(unsafe.Pointer((group + 56 /* &.packed_table */) + uintptr(val)*8)) + + if code.bits < 0x100 { + VP8LSetBitPos(tls, br, ((*VP8LBitReader)(unsafe.Pointer(br)).bit_pos_ + code.bits)) + *(*uint32_t)(unsafe.Pointer(dst)) = code.value + return 0 + } else { + VP8LSetBitPos(tls, br, (((*VP8LBitReader)(unsafe.Pointer(br)).bit_pos_ + code.bits) - 0x100)) + + return int32(code.value) + } + return int32(0) +} + +func AccumulateHCode(tls *libc.TLS, hcode HuffmanCode, shift int32, huff uintptr) int32 { /* vp8l_dec.c:219:12: */ + *(*int32)(unsafe.Pointer((huff /* &.bits */))) += (int32(hcode.bits)) + *(*uint32_t)(unsafe.Pointer((huff + 4 /* &.value */))) |= (uint32_t(hcode.value) << shift) + + return int32(hcode.bits) +} + +func BuildPackedTable(tls *libc.TLS, htree_group uintptr) { /* vp8l_dec.c:227:13: */ + var code uint32_t + for code = uint32_t(0); code < (uint32(1) << 6); code++ { + var bits uint32_t = code + _ = bits + var huff uintptr = ((htree_group + 56 /* &.packed_table */) + uintptr(bits)*8) + var hcode = *(*HuffmanCode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((htree_group /* &.htrees */))) + uintptr(bits)*4)) + if int32(hcode.value) >= 256 { + (*HuffmanCode32)(unsafe.Pointer(huff)).bits = (int32(hcode.bits) + 0x100) + (*HuffmanCode32)(unsafe.Pointer(huff)).value = uint32_t(hcode.value) + } else { + (*HuffmanCode32)(unsafe.Pointer(huff)).bits = 0 + (*HuffmanCode32)(unsafe.Pointer(huff)).value = uint32_t(0) + bits >>= AccumulateHCode(tls, hcode, 8, huff) + bits >>= AccumulateHCode(tls, *(*HuffmanCode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((htree_group /* &.htrees */) + 1*8)) + uintptr(bits)*4)), 16, huff) + bits >>= AccumulateHCode(tls, *(*HuffmanCode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((htree_group /* &.htrees */) + 2*8)) + uintptr(bits)*4)), 0, huff) + bits >>= AccumulateHCode(tls, *(*HuffmanCode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((htree_group /* &.htrees */) + 3*8)) + uintptr(bits)*4)), 24, huff) + _ = bits + } + } +} + +func ReadHuffmanCodeLengths(tls *libc.TLS, dec uintptr, code_length_code_lengths uintptr, num_symbols int32, code_lengths uintptr) int32 { /* vp8l_dec.c:248:12: */ + bp := tls.Alloc(512) + defer tls.Free(512) + + var ok int32 + var br uintptr + var symbol int32 + var max_symbol int32 + var prev_code_len int32 + // var table [128]HuffmanCode at bp, 512 + // use length + var length_nbits int32 + var length int32 + var use_prev int32 + var slot int32 + var extra_bits int32 + var repeat_offset int32 + var repeat int32 + var p uintptr + var code_len int32 + ok = 0 + br = (dec + 40 /* &.br_ */) + prev_code_len = 8 + + if !(!(VP8LBuildHuffmanTable(tls, (bp) /* &table[0] */, 7, + code_length_code_lengths, + 19) != 0)) { + goto __1 + } + goto End +__1: + ; + + if !(VP8LReadBits(tls, br, 1) != 0) { + goto __2 + } // use length + length_nbits = (int32(uint32_t(2) + (uint32_t(2) * VP8LReadBits(tls, br, 3)))) + max_symbol = (int32(uint32_t(2) + VP8LReadBits(tls, br, length_nbits))) + if !(max_symbol > num_symbols) { + goto __4 + } + goto End +__4: + ; + goto __3 +__2: + max_symbol = num_symbols +__3: + ; + + symbol = 0 +__5: + if !(symbol < num_symbols) { + goto __6 + } + if !(libc.PostDecInt32(&max_symbol, 1) == 0) { + goto __7 + } + goto __6 +__7: + ; + VP8LFillBitWindow(tls, br) + p = ((bp) /* &table */ + uintptr((VP8LPrefetchBits(tls, br)&(uint32_t((int32(1)<<7)-1))))*4) + VP8LSetBitPos(tls, br, ((*VP8LBitReader)(unsafe.Pointer(br)).bit_pos_ + int32((*HuffmanCode)(unsafe.Pointer(p)).bits))) + code_len = int32((*HuffmanCode)(unsafe.Pointer(p)).value) + if !(code_len < kCodeLengthLiterals) { + goto __8 + } + *(*int32)(unsafe.Pointer(code_lengths + uintptr(libc.PostIncInt32(&symbol, 1))*4)) = code_len + if !(code_len != 0) { + goto __10 + } + prev_code_len = code_len +__10: + ; + goto __9 +__8: + use_prev = (libc.Bool32(code_len == kCodeLengthRepeatCode)) + slot = (code_len - kCodeLengthLiterals) + extra_bits = int32(kCodeLengthExtraBits[slot]) + repeat_offset = int32(kCodeLengthRepeatOffsets[slot]) + repeat = (int32(VP8LReadBits(tls, br, extra_bits) + uint32_t(repeat_offset))) + if !((symbol + repeat) > num_symbols) { + goto __11 + } + goto End + goto __12 +__11: + if use_prev != 0 { + length = prev_code_len + } else { + length = 0 + } +__13: + if !(libc.PostDecInt32(&repeat, 1) > 0) { + goto __14 + } + *(*int32)(unsafe.Pointer(code_lengths + uintptr(libc.PostIncInt32(&symbol, 1))*4)) = length + goto __13 +__14: + ; +__12: + ; +__9: + ; + goto __5 +__6: + ; + ok = 1 + +End: + if !(!(ok != 0)) { + goto __15 + } + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_BITSTREAM_ERROR +__15: + ; + return ok +} + +// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman +// tree. +func ReadHuffmanCode(tls *libc.TLS, alphabet_size int32, dec uintptr, code_lengths uintptr, table uintptr) int32 { /* vp8l_dec.c:309:12: */ + bp := tls.Alloc(76) + defer tls.Free(76) + + var ok int32 = 0 + var size int32 = 0 + var br uintptr = (dec + 40 /* &.br_ */) + var simple_code int32 = int32(VP8LReadBits(tls, br, 1)) + + libc.Xmemset(tls, code_lengths, 0, (uint64(alphabet_size) * uint64(unsafe.Sizeof(int32(0))))) + + if simple_code != 0 { // Read symbols, codes & code lengths directly. + var num_symbols int32 = (int32(VP8LReadBits(tls, br, 1) + uint32_t(1))) + var first_symbol_len_code int32 = int32(VP8LReadBits(tls, br, 1)) + // The first code is either 1 bit or 8 bit code. + var symbol int32 = int32(VP8LReadBits(tls, br, func() int32 { + if first_symbol_len_code == 0 { + return 1 + } + return 8 + }())) + *(*int32)(unsafe.Pointer(code_lengths + uintptr(symbol)*4)) = 1 + // The second code (if present), is always 8 bit long. + if num_symbols == 2 { + symbol = int32(VP8LReadBits(tls, br, 8)) + *(*int32)(unsafe.Pointer(code_lengths + uintptr(symbol)*4)) = 1 + } + ok = 1 + } else { // Decode Huffman-coded code lengths. + var i int32 + *(*[19]int32)(unsafe.Pointer(bp /* code_length_code_lengths */)) = [19]int32{0: 0} + var num_codes int32 = (int32(VP8LReadBits(tls, br, 4) + uint32_t(4))) + if num_codes > 19 { + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_BITSTREAM_ERROR + return 0 + } + + for i = 0; i < num_codes; i++ { + *(*int32)(unsafe.Pointer((bp) /* &code_length_code_lengths[0] */ + uintptr(kCodeLengthCodeOrder[i])*4)) = int32(VP8LReadBits(tls, br, 3)) + } + ok = ReadHuffmanCodeLengths(tls, dec, (bp) /* &code_length_code_lengths[0] */, alphabet_size, + code_lengths) + } + + ok = (libc.Bool32((ok != 0) && !((*VP8LBitReader)(unsafe.Pointer(br)).eos_ != 0))) + if ok != 0 { + size = VP8LBuildHuffmanTable(tls, table, 8, + code_lengths, alphabet_size) + } + if !(ok != 0) || (size == 0) { + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_BITSTREAM_ERROR + return 0 + } + return size +} + +func ReadHuffmanCodes(tls *libc.TLS, dec uintptr, xsize int32, ysize int32, color_cache_bits int32, allow_recursion int32) int32 { /* vp8l_dec.c:358:12: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var i int32 + var j int32 + var br uintptr + var hdr uintptr + // var huffman_image uintptr at bp, 8 + + var htree_groups uintptr + var huffman_tables uintptr + var huffman_table uintptr + var num_htree_groups int32 + var num_htree_groups_max int32 + var max_alphabet_size int32 + var code_lengths uintptr + var table_size int32 + var mapping uintptr + var ok int32 + // The huffman data is stored in red and green bytes. + var group int32 + // Get the current mapping for the group and remap the Huffman image. + var mapped_group uintptr + // use meta Huffman codes. + var huffman_precision int32 + var huffman_xsize int32 + var huffman_ysize int32 + var huffman_pixs int32 + var alphabet_size int32 + var alphabet_size1 int32 + var local_max_bits int32 + var k int32 + var alphabet_size2 int32 + var red int32 + var blue int32 + var alpha int32 + var htree_group uintptr + var htrees uintptr + var size int32 + var total_size int32 + var is_trivial_literal int32 + var max_bits int32 + br = (dec + 40 /* &.br_ */) + hdr = (dec + 152 /* &.hdr_ */) + *(*uintptr)(unsafe.Pointer(bp /* huffman_image */)) = (uintptr(0)) + htree_groups = (uintptr(0)) + huffman_tables = (uintptr(0)) + huffman_table = (uintptr(0)) + num_htree_groups = 1 + num_htree_groups_max = 1 + max_alphabet_size = 0 + code_lengths = (uintptr(0)) + table_size = int32(kTableSize[color_cache_bits]) + mapping = (uintptr(0)) + ok = 0 + + if !((allow_recursion != 0) && (VP8LReadBits(tls, br, 1) != 0)) { + goto __1 + } + // use meta Huffman codes. + huffman_precision = (int32(VP8LReadBits(tls, br, 3) + uint32_t(2))) + huffman_xsize = int32(VP8LSubSampleSize(tls, uint32(xsize), uint32(huffman_precision))) + huffman_ysize = int32(VP8LSubSampleSize(tls, uint32(ysize), uint32(huffman_precision))) + huffman_pixs = (huffman_xsize * huffman_ysize) + if !(!(DecodeImageStream(tls, huffman_xsize, huffman_ysize, 0, dec, + (bp) /* &huffman_image */) != 0)) { + goto __2 + } + goto Error +__2: + ; + (*VP8LMetadata)(unsafe.Pointer(hdr)).huffman_subsample_bits_ = huffman_precision + i = 0 +__3: + if !(i < huffman_pixs) { + goto __5 + } + // The huffman data is stored in red and green bytes. + group = (int32((*(*uint32_t)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(bp /* huffman_image */)) + uintptr(i)*4)) >> 8) & uint32_t(0xffff))) + *(*uint32_t)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(bp /* huffman_image */)) + uintptr(i)*4)) = uint32_t(group) + if !(group >= num_htree_groups_max) { + goto __6 + } + num_htree_groups_max = (group + 1) +__6: + ; + goto __4 +__4: + i++ + goto __3 + goto __5 +__5: + ; + // Check the validity of num_htree_groups_max. If it seems too big, use a + // smaller value for later. This will prevent big memory allocations to end + // up with a bad bitstream anyway. + // The value of 1000 is totally arbitrary. We know that num_htree_groups_max + // is smaller than (1 << 16) and should be smaller than the number of pixels + // (though the format allows it to be bigger). + if !((num_htree_groups_max > 1000) || (num_htree_groups_max > (xsize * ysize))) { + goto __7 + } + // Create a mapping from the used indices to the minimal set of used + // values [0, num_htree_groups) + mapping = WebPSafeMalloc(tls, uint64(num_htree_groups_max), uint64(unsafe.Sizeof(int32(0)))) + if !(mapping == (uintptr(0))) { + goto __9 + } + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_OUT_OF_MEMORY + goto Error +__9: + ; + // -1 means a value is unmapped, and therefore unused in the Huffman + // image. + libc.Xmemset(tls, mapping, 0xff, (uint64(num_htree_groups_max) * uint64(unsafe.Sizeof(int32(0))))) + num_htree_groups = 0 + i = 0 +__10: + if !(i < huffman_pixs) { + goto __12 + } + // Get the current mapping for the group and remap the Huffman image. + mapped_group = (mapping + uintptr(*(*uint32_t)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(bp /* huffman_image */)) + uintptr(i)*4)))*4) + if !(*(*int32)(unsafe.Pointer(mapped_group)) == -1) { + goto __13 + } + *(*int32)(unsafe.Pointer(mapped_group)) = libc.PostIncInt32(&num_htree_groups, 1) +__13: + ; + *(*uint32_t)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(bp /* huffman_image */)) + uintptr(i)*4)) = uint32_t(*(*int32)(unsafe.Pointer(mapped_group))) + goto __11 +__11: + i++ + goto __10 + goto __12 +__12: + ; + goto __8 +__7: + num_htree_groups = num_htree_groups_max +__8: + ; +__1: + ; + + if !((*VP8LBitReader)(unsafe.Pointer(br)).eos_ != 0) { + goto __14 + } + goto Error +__14: + ; + + // Find maximum alphabet size for the htree group. + j = 0 +__15: + if !(j < 5) { + goto __17 + } + alphabet_size = int32(kAlphabetSize[j]) + if !((j == 0) && (color_cache_bits > 0)) { + goto __18 + } + alphabet_size = alphabet_size + (int32(1) << color_cache_bits) +__18: + ; + if !(max_alphabet_size < alphabet_size) { + goto __19 + } + max_alphabet_size = alphabet_size +__19: + ; + goto __16 +__16: + j++ + goto __15 + goto __17 +__17: + ; + + code_lengths = WebPSafeCalloc(tls, uint64_t(max_alphabet_size), + uint64(unsafe.Sizeof(int32(0)))) + huffman_tables = WebPSafeMalloc(tls, (uint64(num_htree_groups * table_size)), + uint64(unsafe.Sizeof(HuffmanCode{}))) + htree_groups = VP8LHtreeGroupsNew(tls, num_htree_groups) + + if !(((htree_groups == (uintptr(0))) || (code_lengths == (uintptr(0)))) || (huffman_tables == (uintptr(0)))) { + goto __20 + } + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_OUT_OF_MEMORY + goto Error +__20: + ; + + huffman_table = huffman_tables + i = 0 +__21: + if !(i < num_htree_groups_max) { + goto __23 + } + // If the index "i" is unused in the Huffman image, just make sure the + // coefficients are valid but do not store them. + if !((mapping != (uintptr(0))) && (*(*int32)(unsafe.Pointer(mapping + uintptr(i)*4)) == -1)) { + goto __24 + } + j = 0 +__26: + if !(j < 5) { + goto __28 + } + alphabet_size1 = int32(kAlphabetSize[j]) + if !((j == 0) && (color_cache_bits > 0)) { + goto __29 + } + alphabet_size1 = alphabet_size1 + (int32(1) << color_cache_bits) +__29: + ; + // Passing in NULL so that nothing gets filled. + if !(!(ReadHuffmanCode(tls, alphabet_size1, dec, code_lengths, (uintptr(0))) != 0)) { + goto __30 + } + goto Error +__30: + ; + goto __27 +__27: + j++ + goto __26 + goto __28 +__28: + ; + goto __25 +__24: + htree_group = + (htree_groups + uintptr(func() int32 { + if mapping == (uintptr(0)) { + return i + } + return *(*int32)(unsafe.Pointer(mapping + uintptr(i)*4)) + }())*568) + htrees = htree_group /* &.htrees */ + total_size = 0 + is_trivial_literal = 1 + max_bits = 0 + j = 0 +__31: + if !(j < 5) { + goto __33 + } + alphabet_size2 = int32(kAlphabetSize[j]) + *(*uintptr)(unsafe.Pointer(htrees + uintptr(j)*8)) = huffman_table + if !((j == 0) && (color_cache_bits > 0)) { + goto __34 + } + alphabet_size2 = alphabet_size2 + (int32(1) << color_cache_bits) +__34: + ; + size = ReadHuffmanCode(tls, alphabet_size2, dec, code_lengths, huffman_table) + if !(size == 0) { + goto __35 + } + goto Error +__35: + ; + if !((is_trivial_literal != 0) && (int32(kLiteralMap[j]) == 1)) { + goto __36 + } + is_trivial_literal = (libc.Bool32(int32((*HuffmanCode)(unsafe.Pointer(huffman_table)).bits) == 0)) +__36: + ; + total_size = total_size + (int32((*HuffmanCode)(unsafe.Pointer(huffman_table)).bits)) + huffman_table += 4 * (uintptr(size)) + if !(j <= ALPHA) { + goto __37 + } + local_max_bits = *(*int32)(unsafe.Pointer(code_lengths)) + k = 1 +__38: + if !(k < alphabet_size2) { + goto __40 + } + if !(*(*int32)(unsafe.Pointer(code_lengths + uintptr(k)*4)) > local_max_bits) { + goto __41 + } + local_max_bits = *(*int32)(unsafe.Pointer(code_lengths + uintptr(k)*4)) +__41: + ; + goto __39 +__39: + k++ + goto __38 + goto __40 +__40: + ; + max_bits = max_bits + (local_max_bits) +__37: + ; + goto __32 +__32: + j++ + goto __31 + goto __33 +__33: + ; + (*HTreeGroup)(unsafe.Pointer(htree_group)).is_trivial_literal = is_trivial_literal + (*HTreeGroup)(unsafe.Pointer(htree_group)).is_trivial_code = 0 + if !(is_trivial_literal != 0) { + goto __42 + } + red = int32((*HuffmanCode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(htrees + 1*8)))).value) + blue = int32((*HuffmanCode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(htrees + 2*8)))).value) + alpha = int32((*HuffmanCode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(htrees + 3*8)))).value) + (*HTreeGroup)(unsafe.Pointer(htree_group)).literal_arb = (((uint32_t(alpha) << 24) | (uint32_t(red << 16))) | uint32_t(blue)) + if !((total_size == 0) && (int32((*HuffmanCode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(htrees)))).value) < 256)) { + goto __43 + } + (*HTreeGroup)(unsafe.Pointer(htree_group)).is_trivial_code = 1 + *(*uint32_t)(unsafe.Pointer((htree_group + 44 /* &.literal_arb */))) |= (uint32_t(int32((*HuffmanCode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(htrees)))).value) << 8)) +__43: + ; +__42: + ; + (*HTreeGroup)(unsafe.Pointer(htree_group)).use_packed_table = (libc.Bool32(!((*HTreeGroup)(unsafe.Pointer(htree_group)).is_trivial_code != 0) && (max_bits < 6))) + if !((*HTreeGroup)(unsafe.Pointer(htree_group)).use_packed_table != 0) { + goto __44 + } + BuildPackedTable(tls, htree_group) +__44: + ; +__25: + ; + goto __22 +__22: + i++ + goto __21 + goto __23 +__23: + ; + ok = 1 + + // All OK. Finalize pointers. + (*VP8LMetadata)(unsafe.Pointer(hdr)).huffman_image_ = *(*uintptr)(unsafe.Pointer(bp /* huffman_image */)) + (*VP8LMetadata)(unsafe.Pointer(hdr)).num_htree_groups_ = num_htree_groups + (*VP8LMetadata)(unsafe.Pointer(hdr)).htree_groups_ = htree_groups + (*VP8LMetadata)(unsafe.Pointer(hdr)).huffman_tables_ = huffman_tables + +Error: + WebPSafeFree(tls, code_lengths) + WebPSafeFree(tls, mapping) + if !(!(ok != 0)) { + goto __45 + } + WebPSafeFree(tls, *(*uintptr)(unsafe.Pointer(bp /* huffman_image */))) + WebPSafeFree(tls, huffman_tables) + VP8LHtreeGroupsFree(tls, htree_groups) +__45: + ; + return ok +} + +//------------------------------------------------------------------------------ +// Scaling. + +func AllocateAndInitRescaler(tls *libc.TLS, dec uintptr, io uintptr) int32 { /* vp8l_dec.c:535:12: */ + var num_channels int32 = 4 + var in_width int32 = (*VP8Io)(unsafe.Pointer(io)).mb_w + var out_width int32 = (*VP8Io)(unsafe.Pointer(io)).scaled_width + var in_height int32 = (*VP8Io)(unsafe.Pointer(io)).mb_h + var out_height int32 = (*VP8Io)(unsafe.Pointer(io)).scaled_height + var work_size uint64_t = ((uint64_t(2 * num_channels)) * uint64_t(out_width)) + var work uintptr // Rescaler work area. + var scaled_data_size uint64_t = uint64_t(out_width) + var scaled_data uintptr // Temporary storage for scaled BGRA data. + var memory_size uint64_t = ((uint64(unsafe.Sizeof(WebPRescaler{})) + (work_size * uint64_t(unsafe.Sizeof(rescaler_t(0))))) + (scaled_data_size * uint64_t(unsafe.Sizeof(uint32_t(0))))) + var memory uintptr = WebPSafeMalloc(tls, memory_size, uint64(unsafe.Sizeof(uint8_t(0)))) + if memory == (uintptr(0)) { + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_OUT_OF_MEMORY + return 0 + } + + (*VP8LDecoder)(unsafe.Pointer(dec)).rescaler_memory = memory + + (*VP8LDecoder)(unsafe.Pointer(dec)).rescaler = memory + memory += uintptr(unsafe.Sizeof(WebPRescaler{})) + work = memory + memory += (uintptr(work_size * uint64_t(unsafe.Sizeof(rescaler_t(0))))) + scaled_data = memory + + if !(WebPRescalerInit(tls, (*VP8LDecoder)(unsafe.Pointer(dec)).rescaler, in_width, in_height, + scaled_data, out_width, out_height, + 0, num_channels, work) != 0) { + return 0 + } + return 1 +} + +//------------------------------------------------------------------------------ +// Export to ARGB + +// We have special "export" function since we need to convert from BGRA +func Export(tls *libc.TLS, rescaler uintptr, colorspace WEBP_CSP_MODE, rgba_stride int32, rgba uintptr) int32 { /* vp8l_dec.c:577:12: */ + var src uintptr = (*WebPRescaler)(unsafe.Pointer(rescaler)).dst + var dst uintptr = rgba + var dst_width int32 = (*WebPRescaler)(unsafe.Pointer(rescaler)).dst_width + var num_lines_out int32 = 0 + for WebPRescalerHasPendingOutput(tls, rescaler) != 0 { + WebPRescalerExportRow(tls, rescaler) + (*struct { + f func(*libc.TLS, uintptr, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPMultARGBRow})).f(tls, src, dst_width, 1) + VP8LConvertFromBGRA(tls, src, dst_width, colorspace, dst) + dst += uintptr(rgba_stride) + num_lines_out++ + } + return num_lines_out +} + +// Emit scaled rows. +func EmitRescaledRowsRGBA(tls *libc.TLS, dec uintptr, in uintptr, in_stride int32, mb_h int32, out uintptr, out_stride int32) int32 { /* vp8l_dec.c:594:12: */ + var colorspace WEBP_CSP_MODE = (*WebPDecBuffer)(unsafe.Pointer((*VP8LDecoder)(unsafe.Pointer(dec)).output_)).colorspace + var num_lines_in int32 = 0 + var num_lines_out int32 = 0 + for num_lines_in < mb_h { + var row_in uintptr = (in + uintptr((uint64_t(num_lines_in) * uint64_t(in_stride)))) + var row_out uintptr = (out + uintptr((uint64_t(num_lines_out) * uint64_t(out_stride)))) + var lines_left int32 = (mb_h - num_lines_in) + var needed_lines int32 = WebPRescaleNeededLines(tls, (*VP8LDecoder)(unsafe.Pointer(dec)).rescaler, lines_left) + var lines_imported int32 + + WebPMultARGBRows(tls, row_in, in_stride, + (*WebPRescaler)(unsafe.Pointer((*VP8LDecoder)(unsafe.Pointer(dec)).rescaler)).src_width, needed_lines, 0) + lines_imported = WebPRescalerImport(tls, (*VP8LDecoder)(unsafe.Pointer(dec)).rescaler, lines_left, row_in, in_stride) + + num_lines_in = num_lines_in + (lines_imported) + num_lines_out = num_lines_out + (Export(tls, (*VP8LDecoder)(unsafe.Pointer(dec)).rescaler, colorspace, out_stride, row_out)) + } + return num_lines_out +} + +// Emit rows without any scaling. +func EmitRows(tls *libc.TLS, colorspace WEBP_CSP_MODE, row_in uintptr, in_stride int32, mb_w int32, mb_h int32, out uintptr, out_stride int32) int32 { /* vp8l_dec.c:621:12: */ + var lines int32 = mb_h + var row_out uintptr = out + for libc.PostDecInt32(&lines, 1) > 0 { + VP8LConvertFromBGRA(tls, row_in, mb_w, colorspace, row_out) + row_in += uintptr(in_stride) + row_out += uintptr(out_stride) + } + return mb_h // Num rows out == num rows in. +} + +//------------------------------------------------------------------------------ +// Export to YUVA + +func ConvertToYUVA(tls *libc.TLS, src uintptr, width int32, y_pos int32, output uintptr) { /* vp8l_dec.c:638:13: */ + var buf uintptr = (output + 16 /* &.u */) /* &.YUVA */ + + // first, the luma plane + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPConvertARGBToY})).f(tls, src, ((*WebPYUVABuffer)(unsafe.Pointer(buf)).y + uintptr((y_pos * (*WebPYUVABuffer)(unsafe.Pointer(buf)).y_stride))), width) + + // then U/V planes + { + var u uintptr = ((*WebPYUVABuffer)(unsafe.Pointer(buf)).u + uintptr(((y_pos >> 1) * (*WebPYUVABuffer)(unsafe.Pointer(buf)).u_stride))) + var v uintptr = ((*WebPYUVABuffer)(unsafe.Pointer(buf)).v + uintptr(((y_pos >> 1) * (*WebPYUVABuffer)(unsafe.Pointer(buf)).v_stride))) + // even lines: store values + // odd lines: average with previous values + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPConvertARGBToUV})).f(tls, src, u, v, width, libc.BoolInt32(!((y_pos & 1) != 0))) + + } + // Lastly, store alpha if needed. + if (*WebPYUVABuffer)(unsafe.Pointer(buf)).a != (uintptr(0)) { + var a uintptr = ((*WebPYUVABuffer)(unsafe.Pointer(buf)).a + uintptr((y_pos * (*WebPYUVABuffer)(unsafe.Pointer(buf)).a_stride))) + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, uintptr, int32) int32 + })(unsafe.Pointer(&struct{ uintptr }{WebPExtractAlpha})).f(tls, (src + uintptr(3)), 0, width, 1, a, 0) + } +} + +func ExportYUVA(tls *libc.TLS, dec uintptr, y_pos int32) int32 { /* vp8l_dec.c:664:12: */ + var rescaler uintptr = (*VP8LDecoder)(unsafe.Pointer(dec)).rescaler + var src uintptr = (*WebPRescaler)(unsafe.Pointer(rescaler)).dst + var dst_width int32 = (*WebPRescaler)(unsafe.Pointer(rescaler)).dst_width + var num_lines_out int32 = 0 + for WebPRescalerHasPendingOutput(tls, rescaler) != 0 { + WebPRescalerExportRow(tls, rescaler) + (*struct { + f func(*libc.TLS, uintptr, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPMultARGBRow})).f(tls, src, dst_width, 1) + ConvertToYUVA(tls, src, dst_width, y_pos, (*VP8LDecoder)(unsafe.Pointer(dec)).output_) + y_pos++ + num_lines_out++ + } + return num_lines_out +} + +func EmitRescaledRowsYUVA(tls *libc.TLS, dec uintptr, in uintptr, in_stride int32, mb_h int32) int32 { /* vp8l_dec.c:679:12: */ + var num_lines_in int32 = 0 + var y_pos int32 = (*VP8LDecoder)(unsafe.Pointer(dec)).last_out_row_ + for num_lines_in < mb_h { + var lines_left int32 = (mb_h - num_lines_in) + var needed_lines int32 = WebPRescaleNeededLines(tls, (*VP8LDecoder)(unsafe.Pointer(dec)).rescaler, lines_left) + var lines_imported int32 + WebPMultARGBRows(tls, in, in_stride, (*WebPRescaler)(unsafe.Pointer((*VP8LDecoder)(unsafe.Pointer(dec)).rescaler)).src_width, needed_lines, 0) + lines_imported = WebPRescalerImport(tls, (*VP8LDecoder)(unsafe.Pointer(dec)).rescaler, lines_left, in, in_stride) + + num_lines_in = num_lines_in + (lines_imported) + in += (uintptr(needed_lines * in_stride)) + y_pos = y_pos + (ExportYUVA(tls, dec, y_pos)) + } + return y_pos +} + +func EmitRowsYUVA(tls *libc.TLS, dec uintptr, in uintptr, in_stride int32, mb_w int32, num_rows int32) int32 { /* vp8l_dec.c:698:12: */ + var y_pos int32 = (*VP8LDecoder)(unsafe.Pointer(dec)).last_out_row_ + for libc.PostDecInt32(&num_rows, 1) > 0 { + ConvertToYUVA(tls, in, mb_w, y_pos, (*VP8LDecoder)(unsafe.Pointer(dec)).output_) + in += uintptr(in_stride) + y_pos++ + } + return y_pos +} + +//------------------------------------------------------------------------------ +// Cropping. + +// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and +// crop options. Also updates the input data pointer, so that it points to the +// start of the cropped window. Note that pixels are in ARGB format even if +// 'in_data' is uint8_t*. +// Returns true if the crop window is not empty. +func SetCropWindow(tls *libc.TLS, io uintptr, y_start int32, y_end int32, in_data uintptr, pixel_stride int32) int32 { /* vp8l_dec.c:718:12: */ + + if y_end > (*VP8Io)(unsafe.Pointer(io)).crop_bottom { + y_end = (*VP8Io)(unsafe.Pointer(io)).crop_bottom // make sure we don't overflow on last row. + } + if y_start < (*VP8Io)(unsafe.Pointer(io)).crop_top { + var delta int32 = ((*VP8Io)(unsafe.Pointer(io)).crop_top - y_start) + y_start = (*VP8Io)(unsafe.Pointer(io)).crop_top + *(*uintptr)(unsafe.Pointer(in_data)) += (uintptr(delta * pixel_stride)) + } + if y_start >= y_end { + return 0 + } // Crop window is empty. + + *(*uintptr)(unsafe.Pointer(in_data)) += (uintptr(uint64((*VP8Io)(unsafe.Pointer(io)).crop_left) * uint64(unsafe.Sizeof(uint32_t(0))))) + + (*VP8Io)(unsafe.Pointer(io)).mb_y = (y_start - (*VP8Io)(unsafe.Pointer(io)).crop_top) + (*VP8Io)(unsafe.Pointer(io)).mb_w = ((*VP8Io)(unsafe.Pointer(io)).crop_right - (*VP8Io)(unsafe.Pointer(io)).crop_left) + (*VP8Io)(unsafe.Pointer(io)).mb_h = (y_end - y_start) + return 1 // Non-empty crop window. +} + +//------------------------------------------------------------------------------ + +func GetMetaIndex(tls *libc.TLS, image uintptr, xsize int32, bits int32, x int32, y int32) int32 { /* vp8l_dec.c:742:24: */ + if bits == 0 { + return 0 + } + return int32(*(*uint32_t)(unsafe.Pointer(image + uintptr(((xsize*(y>>bits))+(x>>bits)))*4))) +} + +func GetHtreeGroupForPos(tls *libc.TLS, hdr uintptr, x int32, y int32) uintptr { /* vp8l_dec.c:748:30: */ + var meta_index int32 = GetMetaIndex(tls, (*VP8LMetadata)(unsafe.Pointer(hdr)).huffman_image_, (*VP8LMetadata)(unsafe.Pointer(hdr)).huffman_xsize_, + (*VP8LMetadata)(unsafe.Pointer(hdr)).huffman_subsample_bits_, x, y) + + return ((*VP8LMetadata)(unsafe.Pointer(hdr)).htree_groups_ + uintptr(meta_index)*568) +} + +//------------------------------------------------------------------------------ +// Main loop, with custom row-processing function + +type ProcessRowsFunc = uintptr /* vp8l_dec.c:759:14 */ + +func ApplyInverseTransforms(tls *libc.TLS, dec uintptr, start_row int32, num_rows int32, rows uintptr) { /* vp8l_dec.c:761:13: */ + var n int32 = (*VP8LDecoder)(unsafe.Pointer(dec)).next_transform_ + var cache_pixs int32 = ((*VP8LDecoder)(unsafe.Pointer(dec)).width_ * num_rows) + var end_row int32 = (start_row + num_rows) + var rows_in uintptr = rows + var rows_out uintptr = (*VP8LDecoder)(unsafe.Pointer(dec)).argb_cache_ + + // Inverse transforms. + for libc.PostDecInt32(&n, 1) > 0 { + var transform uintptr = ((dec + 248 /* &.transforms_ */) + uintptr(n)*24) + VP8LInverseTransform(tls, transform, start_row, end_row, rows_in, rows_out) + rows_in = rows_out + } + if rows_in != rows_out { + // No transform called, hence just copy. + libc.Xmemcpy(tls, rows_out, rows_in, (uint64(cache_pixs) * uint64(unsafe.Sizeof(uint32_t(0))))) + } +} + +// Processes (transforms, scales & color-converts) the rows decoded after the +// last call. +func ProcessRows(tls *libc.TLS, dec uintptr, row int32) { /* vp8l_dec.c:784:13: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var rows uintptr = ((*VP8LDecoder)(unsafe.Pointer(dec)).pixels_ + uintptr(((*VP8LDecoder)(unsafe.Pointer(dec)).width_*(*VP8LDecoder)(unsafe.Pointer(dec)).last_row_))*4) + var num_rows int32 = (row - (*VP8LDecoder)(unsafe.Pointer(dec)).last_row_) + + // We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size + // of argb_cache_), but we currently don't need more than that. + + if num_rows > 0 { // Emit output. + var io uintptr = (*VP8LDecoder)(unsafe.Pointer(dec)).io_ + *(*uintptr)(unsafe.Pointer(bp /* rows_data */)) = (*VP8LDecoder)(unsafe.Pointer(dec)).argb_cache_ + var in_stride int32 = (int32(uint64((*VP8Io)(unsafe.Pointer(io)).width) * uint64(unsafe.Sizeof(uint32_t(0))))) // in unit of RGBA + ApplyInverseTransforms(tls, dec, (*VP8LDecoder)(unsafe.Pointer(dec)).last_row_, num_rows, rows) + if !(SetCropWindow(tls, io, (*VP8LDecoder)(unsafe.Pointer(dec)).last_row_, row, (bp) /* &rows_data */, in_stride) != 0) { + // Nothing to output (this time). + } else { + var output uintptr = (*VP8LDecoder)(unsafe.Pointer(dec)).output_ + if WebPIsRGBMode(tls, (*WebPDecBuffer)(unsafe.Pointer(output)).colorspace) != 0 { // convert to RGBA + var buf uintptr = (output + 16 /* &.u */) /* &.RGBA */ + var rgba uintptr = ((*WebPRGBABuffer)(unsafe.Pointer(buf)).rgba + uintptr((int64_t((*VP8LDecoder)(unsafe.Pointer(dec)).last_out_row_) * int64_t((*WebPRGBABuffer)(unsafe.Pointer(buf)).stride)))) + var num_rows_out int32 + if (*VP8Io)(unsafe.Pointer(io)).use_scaling != 0 { + num_rows_out = EmitRescaledRowsRGBA(tls, dec, *(*uintptr)(unsafe.Pointer(bp /* rows_data */)), in_stride, (*VP8Io)(unsafe.Pointer(io)).mb_h, + rgba, (*WebPRGBABuffer)(unsafe.Pointer(buf)).stride) + } else { + num_rows_out = EmitRows(tls, (*WebPDecBuffer)(unsafe.Pointer(output)).colorspace, *(*uintptr)(unsafe.Pointer(bp /* rows_data */)), in_stride, + (*VP8Io)(unsafe.Pointer(io)).mb_w, (*VP8Io)(unsafe.Pointer(io)).mb_h, rgba, (*WebPRGBABuffer)(unsafe.Pointer(buf)).stride) + } + // Update 'last_out_row_'. + *(*int32)(unsafe.Pointer((dec + 148 /* &.last_out_row_ */))) += (num_rows_out) + } else { // convert to YUVA + (*VP8LDecoder)(unsafe.Pointer(dec)).last_out_row_ = func() int32 { + if (*VP8Io)(unsafe.Pointer(io)).use_scaling != 0 { + return EmitRescaledRowsYUVA(tls, dec, *(*uintptr)(unsafe.Pointer(bp /* rows_data */)), in_stride, (*VP8Io)(unsafe.Pointer(io)).mb_h) + } + return EmitRowsYUVA(tls, dec, *(*uintptr)(unsafe.Pointer(bp /* rows_data */)), in_stride, (*VP8Io)(unsafe.Pointer(io)).mb_w, (*VP8Io)(unsafe.Pointer(io)).mb_h) + }() + } + + } + } + + // Update 'last_row_'. + (*VP8LDecoder)(unsafe.Pointer(dec)).last_row_ = row + +} + +// Row-processing for the special case when alpha data contains only one +// transform (color indexing), and trivial non-green literals. +func Is8bOptimizable(tls *libc.TLS, hdr uintptr) int32 { /* vp8l_dec.c:831:12: */ + var i int32 + if (*VP8LMetadata)(unsafe.Pointer(hdr)).color_cache_size_ > 0 { + return 0 + } + // When the Huffman tree contains only one symbol, we can skip the + // call to ReadSymbol() for red/blue/alpha channels. + for i = 0; i < (*VP8LMetadata)(unsafe.Pointer(hdr)).num_htree_groups_; i++ { + var htrees uintptr = ((*VP8LMetadata)(unsafe.Pointer(hdr)).htree_groups_ + uintptr(i)*568) /* &.htrees */ + if int32((*HuffmanCode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(htrees + 1*8)))).bits) > 0 { + return 0 + } + if int32((*HuffmanCode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(htrees + 2*8)))).bits) > 0 { + return 0 + } + if int32((*HuffmanCode)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(htrees + 3*8)))).bits) > 0 { + return 0 + } + } + return 1 +} + +func AlphaApplyFilter(tls *libc.TLS, alph_dec uintptr, first_row int32, last_row int32, out uintptr, stride int32) { /* vp8l_dec.c:845:13: */ + if (*ALPHDecoder)(unsafe.Pointer(alph_dec)).filter_ != WEBP_FILTER_NONE { + var y int32 + var prev_line uintptr = (*ALPHDecoder)(unsafe.Pointer(alph_dec)).prev_line_ + + for y = first_row; y < last_row; y++ { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPUnfilters[(*ALPHDecoder)(unsafe.Pointer(alph_dec)).filter_]})).f(tls, prev_line, out, out, stride) + prev_line = out + out += uintptr(stride) + } + (*ALPHDecoder)(unsafe.Pointer(alph_dec)).prev_line_ = prev_line + } +} + +func ExtractPalettedAlphaRows(tls *libc.TLS, dec uintptr, last_row int32) { /* vp8l_dec.c:861:13: */ + // For vertical and gradient filtering, we need to decode the part above the + // crop_top row, in order to have the correct spatial predictors. + var alph_dec uintptr = (*VP8Io)(unsafe.Pointer((*VP8LDecoder)(unsafe.Pointer(dec)).io_)).opaque + var top_row int32 + if ((*ALPHDecoder)(unsafe.Pointer(alph_dec)).filter_ == WEBP_FILTER_NONE) || ((*ALPHDecoder)(unsafe.Pointer(alph_dec)).filter_ == WEBP_FILTER_HORIZONTAL) { + top_row = (*VP8Io)(unsafe.Pointer((*VP8LDecoder)(unsafe.Pointer(dec)).io_)).crop_top + } else { + top_row = (*VP8LDecoder)(unsafe.Pointer(dec)).last_row_ + } + var first_row int32 + if (*VP8LDecoder)(unsafe.Pointer(dec)).last_row_ < top_row { + first_row = top_row + } else { + first_row = (*VP8LDecoder)(unsafe.Pointer(dec)).last_row_ + } + + if last_row > first_row { + // Special method for paletted alpha data. We only process the cropped area. + var width int32 = (*VP8Io)(unsafe.Pointer((*VP8LDecoder)(unsafe.Pointer(dec)).io_)).width + var out uintptr = ((*ALPHDecoder)(unsafe.Pointer(alph_dec)).output_ + uintptr((width * first_row))) + var in uintptr = ((*VP8LDecoder)(unsafe.Pointer(dec)).pixels_ + uintptr(((*VP8LDecoder)(unsafe.Pointer(dec)).width_ * first_row))) + var transform uintptr = (dec + 248 /* &.transforms_ */) + + VP8LColorIndexInverseTransformAlpha(tls, transform, first_row, last_row, + in, out) + AlphaApplyFilter(tls, alph_dec, first_row, last_row, out, width) + } + (*VP8LDecoder)(unsafe.Pointer(dec)).last_row_ = libc.AssignPtrInt32((dec + 148 /* &.last_out_row_ */), last_row) +} + +//------------------------------------------------------------------------------ +// Helper functions for fast pattern copy (8b and 32b) + +// cyclic rotation of pattern word +func Rotate8b(tls *libc.TLS, V uint32_t) uint32_t { /* vp8l_dec.c:891:29: */ + return (((V & 0xff) << 24) | (V >> 8)) +} + +// copy 1, 2 or 4-bytes pattern +func CopySmallPattern8b(tls *libc.TLS, src uintptr, dst uintptr, length int32, pattern uint32_t) { /* vp8l_dec.c:900:25: */ + var i int32 + // align 'dst' to 4-bytes boundary. Adjust the pattern along the way. + for (uintptr_t(dst) & uint64(3)) != 0 { + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&src, 1))) + pattern = Rotate8b(tls, pattern) + length-- + } + // Copy the pattern 4 bytes at a time. + for i = 0; i < (length >> 2); i++ { + *(*uint32_t)(unsafe.Pointer((dst) + uintptr(i)*4)) = pattern + } + // Finish with left-overs. 'pattern' is still correctly positioned, + // so no Rotate8b() call is needed. + for i <<= 2; i < length; i++ { + *(*uint8_t)(unsafe.Pointer(dst + uintptr(i))) = *(*uint8_t)(unsafe.Pointer(src + uintptr(i))) + } +} + +func CopyBlock8b(tls *libc.TLS, dst uintptr, dist int32, length int32) { /* vp8l_dec.c:920:25: */ + bp := tls.Alloc(4) + defer tls.Free(4) + + var src uintptr + // var pattern uint32_t at bp, 4 + + var i int32 + src = (dst - uintptr(dist)) + if !(length >= 8) { + goto __1 + } + *(*uint32_t)(unsafe.Pointer(bp /* pattern */)) = uint32_t(0) + switch dist { + case 1: + goto __3 + case 2: + goto __4 + case 4: + goto __5 + default: + goto __6 + } + goto __2 +__3: + *(*uint32_t)(unsafe.Pointer(bp /* pattern */)) = uint32_t(*(*uint8_t)(unsafe.Pointer(src))) + *(*uint32_t)(unsafe.Pointer(bp /* pattern */)) = (0x01010101 * *(*uint32_t)(unsafe.Pointer(bp /* pattern */))) + goto __2 +__4: + libc.Xmemcpy(tls, (bp) /* &pattern */, src, uint64(unsafe.Sizeof(uint16_t(0)))) + *(*uint32_t)(unsafe.Pointer(bp /* pattern */)) = (0x00010001 * *(*uint32_t)(unsafe.Pointer(bp /* pattern */))) + goto __2 +__5: + libc.Xmemcpy(tls, (bp) /* &pattern */, src, uint64(unsafe.Sizeof(uint32_t(0)))) + goto __2 +__6: + goto Copy +__2: + ; + CopySmallPattern8b(tls, src, dst, length, *(*uint32_t)(unsafe.Pointer(bp /* pattern */))) + return +__1: + ; +Copy: + if !(dist >= length) { + goto __7 + } // no overlap -> use memcpy() + libc.Xmemcpy(tls, dst, src, (uint64(length) * uint64(unsafe.Sizeof(uint8_t(0))))) + goto __8 +__7: + i = 0 +__9: + if !(i < length) { + goto __11 + } + *(*uint8_t)(unsafe.Pointer(dst + uintptr(i))) = *(*uint8_t)(unsafe.Pointer(src + uintptr(i))) + goto __10 +__10: + i++ + goto __9 + goto __11 +__11: + ; +__8: +} + +// copy pattern of 1 or 2 uint32_t's +func CopySmallPattern32b(tls *libc.TLS, src uintptr, dst uintptr, length int32, pattern uint64_t) { /* vp8l_dec.c:969:25: */ + var i int32 + if (uintptr_t(dst) & uint64(4)) != 0 { // Align 'dst' to 8-bytes boundary. + *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 4))) = *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&src, 4))) + pattern = ((pattern >> 32) | (pattern << 32)) + length-- + } + + for i = 0; i < (length >> 1); i++ { + *(*uint64_t)(unsafe.Pointer((dst) + uintptr(i)*8)) = pattern // Copy the pattern 8 bytes at a time. + } + if (length & 1) != 0 { // Finish with left-over. + *(*uint32_t)(unsafe.Pointer(dst + uintptr((i<<1))*4)) = *(*uint32_t)(unsafe.Pointer(src + uintptr((i<<1))*4)) + } +} + +func CopyBlock32b(tls *libc.TLS, dst uintptr, dist int32, length int32) { /* vp8l_dec.c:987:25: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var src uintptr = (dst - uintptr(dist)*4) + if ((dist <= 2) && (length >= 4)) && ((uintptr_t(dst) & uint64(3)) == uint64(0)) { + // var pattern uint64_t at bp, 8 + + if dist == 1 { + *(*uint64_t)(unsafe.Pointer(bp /* pattern */)) = uint64_t(*(*uint32_t)(unsafe.Pointer(src))) + *(*uint64_t)(unsafe.Pointer(bp /* pattern */)) |= (*(*uint64_t)(unsafe.Pointer(bp /* pattern */)) << 32) + } else { + libc.Xmemcpy(tls, (bp) /* &pattern */, src, uint64(unsafe.Sizeof(uint64_t(0)))) + } + CopySmallPattern32b(tls, src, dst, length, *(*uint64_t)(unsafe.Pointer(bp /* pattern */))) + } else if dist >= length { // no overlap + libc.Xmemcpy(tls, dst, src, (uint64(length) * uint64(unsafe.Sizeof(uint32_t(0))))) + } else { + var i int32 + for i = 0; i < length; i++ { + *(*uint32_t)(unsafe.Pointer(dst + uintptr(i)*4)) = *(*uint32_t)(unsafe.Pointer(src + uintptr(i)*4)) + } + } +} + +//------------------------------------------------------------------------------ + +func DecodeAlphaData(tls *libc.TLS, dec uintptr, data uintptr, width int32, height int32, last_row int32) int32 { /* vp8l_dec.c:1009:12: */ + var ok int32 + var row int32 + var col int32 + var br uintptr + var hdr uintptr + var pos int32 // current position + var end int32 // End of data + var last int32 // Last pixel to decode + var len_code_limit int32 + var mask int32 + var htree_group uintptr // Backward reference + var dist_code int32 + var dist int32 + var length_sym int32 + var length int32 + var dist_symbol int32 + var code int32 + ok = 1 + row = ((*VP8LDecoder)(unsafe.Pointer(dec)).last_pixel_ / width) + col = ((*VP8LDecoder)(unsafe.Pointer(dec)).last_pixel_ % width) + br = (dec + 40 /* &.br_ */) + hdr = (dec + 152 /* &.hdr_ */) + pos = (*VP8LDecoder)(unsafe.Pointer(dec)).last_pixel_ + end = (width * height) + last = (width * last_row) + len_code_limit = (256 + 24) + mask = (*VP8LMetadata)(unsafe.Pointer(hdr)).huffman_mask_ + if pos < last { + htree_group = GetHtreeGroupForPos(tls, hdr, col, row) + } else { + htree_group = (uintptr(0)) + } + +__1: + if !(!((*VP8LBitReader)(unsafe.Pointer(br)).eos_ != 0) && (pos < last)) { + goto __2 + } + // Only update when changing tile. + if !((col & mask) == 0) { + goto __3 + } + htree_group = GetHtreeGroupForPos(tls, hdr, col, row) +__3: + ; + + VP8LFillBitWindow(tls, br) + code = ReadSymbol(tls, *(*uintptr)(unsafe.Pointer((htree_group /* &.htrees */))), br) + if !(code < 256) { + goto __4 + } // Literal + *(*uint8_t)(unsafe.Pointer(data + uintptr(pos))) = uint8_t(code) + pos++ + col++ + if !(col >= width) { + goto __6 + } + col = 0 + row++ + if !((row <= last_row) && ((row % 16) == 0)) { + goto __7 + } + ExtractPalettedAlphaRows(tls, dec, row) +__7: + ; +__6: + ; + goto __5 +__4: + if !(code < len_code_limit) { + goto __8 + } + length_sym = (code - 256) + length = GetCopyLength(tls, length_sym, br) + dist_symbol = ReadSymbol(tls, *(*uintptr)(unsafe.Pointer((htree_group /* &.htrees */) + 4*8)), br) + VP8LFillBitWindow(tls, br) + dist_code = GetCopyDistance(tls, dist_symbol, br) + dist = PlaneCodeToDistance(tls, width, dist_code) + if !((pos >= dist) && ((end - pos) >= length)) { + goto __10 + } + CopyBlock8b(tls, (data + uintptr(pos)), dist, length) + goto __11 +__10: + ok = 0 + goto End +__11: + ; + pos = pos + (length) + col = col + (length) +__12: + if !(col >= width) { + goto __13 + } + col = col - (width) + row++ + if !((row <= last_row) && ((row % 16) == 0)) { + goto __14 + } + ExtractPalettedAlphaRows(tls, dec, row) +__14: + ; + goto __12 +__13: + ; + if !((pos < last) && ((col & mask) != 0)) { + goto __15 + } + htree_group = GetHtreeGroupForPos(tls, hdr, col, row) +__15: + ; + goto __9 +__8: // Not reached + ok = 0 + goto End +__9: + ; +__5: + ; + (*VP8LBitReader)(unsafe.Pointer(br)).eos_ = VP8LIsEndOfStream(tls, br) + goto __1 +__2: + ; + // Process the remaining rows corresponding to last row-block. + ExtractPalettedAlphaRows(tls, dec, func() int32 { + if row > last_row { + return last_row + } + return row + }()) + +End: + (*VP8LBitReader)(unsafe.Pointer(br)).eos_ = VP8LIsEndOfStream(tls, br) + if !(!(ok != 0) || (((*VP8LBitReader)(unsafe.Pointer(br)).eos_ != 0) && (pos < end))) { + goto __16 + } + ok = 0 + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = func() uint32 { + if (*VP8LBitReader)(unsafe.Pointer(br)).eos_ != 0 { + return VP8_STATUS_SUSPENDED + } + return VP8_STATUS_BITSTREAM_ERROR + }() + goto __17 +__16: + (*VP8LDecoder)(unsafe.Pointer(dec)).last_pixel_ = pos +__17: + ; + return ok +} + +func SaveState(tls *libc.TLS, dec uintptr, last_pixel int32) { /* vp8l_dec.c:1094:13: */ + + (*VP8LDecoder)(unsafe.Pointer(dec)).saved_br_ = (*VP8LDecoder)(unsafe.Pointer(dec)).br_ + (*VP8LDecoder)(unsafe.Pointer(dec)).saved_last_pixel_ = last_pixel + if (*VP8LDecoder)(unsafe.Pointer(dec)).hdr_.color_cache_size_ > 0 { + VP8LColorCacheCopy(tls, ((dec + 152 /* &.hdr_ */) + 8 /* &.color_cache_ */), ((dec + 152 /* &.hdr_ */) + 24 /* &.saved_color_cache_ */)) + } +} + +func RestoreState(tls *libc.TLS, dec uintptr) { /* vp8l_dec.c:1103:13: */ + + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_SUSPENDED + (*VP8LDecoder)(unsafe.Pointer(dec)).br_ = (*VP8LDecoder)(unsafe.Pointer(dec)).saved_br_ + (*VP8LDecoder)(unsafe.Pointer(dec)).last_pixel_ = (*VP8LDecoder)(unsafe.Pointer(dec)).saved_last_pixel_ + if (*VP8LDecoder)(unsafe.Pointer(dec)).hdr_.color_cache_size_ > 0 { + VP8LColorCacheCopy(tls, ((dec + 152 /* &.hdr_ */) + 24 /* &.saved_color_cache_ */), ((dec + 152 /* &.hdr_ */) + 8 /* &.color_cache_ */)) + } +} + +func DecodeImageData(tls *libc.TLS, dec uintptr, data uintptr, width int32, height int32, last_row int32, process_func ProcessRowsFunc) int32 { /* vp8l_dec.c:1114:12: */ + var row int32 + var col int32 + var br uintptr + var hdr uintptr + var src uintptr + var last_cached uintptr + var src_end uintptr // End of data + var src_last uintptr // Last pixel to decode + var len_code_limit int32 + var color_cache_limit int32 + var next_sync_row int32 + var color_cache uintptr + var mask int32 + var htree_group uintptr + var red int32 + var blue int32 + var alpha int32 // Backward reference + var dist_code int32 + var dist int32 + var length_sym int32 + var length int32 + var dist_symbol int32 // Color cache + var key int32 + var code int32 + row = ((*VP8LDecoder)(unsafe.Pointer(dec)).last_pixel_ / width) + col = ((*VP8LDecoder)(unsafe.Pointer(dec)).last_pixel_ % width) + br = (dec + 40 /* &.br_ */) + hdr = (dec + 152 /* &.hdr_ */) + src = (data + uintptr((*VP8LDecoder)(unsafe.Pointer(dec)).last_pixel_)*4) + last_cached = src + src_end = (data + uintptr((width*height))*4) + src_last = (data + uintptr((width*last_row))*4) + len_code_limit = (256 + 24) + color_cache_limit = (len_code_limit + (*VP8LMetadata)(unsafe.Pointer(hdr)).color_cache_size_) + if (*VP8LDecoder)(unsafe.Pointer(dec)).incremental_ != 0 { + next_sync_row = row + } else { + next_sync_row = (int32(1) << 24) + } + if (*VP8LMetadata)(unsafe.Pointer(hdr)).color_cache_size_ > 0 { + color_cache = (hdr + 8 /* &.color_cache_ */) + } else { + color_cache = (uintptr(0)) + } + mask = (*VP8LMetadata)(unsafe.Pointer(hdr)).huffman_mask_ + if src < src_last { + htree_group = GetHtreeGroupForPos(tls, hdr, col, row) + } else { + htree_group = (uintptr(0)) + } + +__1: + if !(src < src_last) { + goto __2 + } + if !(row >= next_sync_row) { + goto __3 + } + SaveState(tls, dec, (int32((int64(src) - int64(data)) / 4))) + next_sync_row = (row + 8) +__3: + ; + // Only update when changing tile. Note we could use this test: + // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed + // but that's actually slower and needs storing the previous col/row. + if !((col & mask) == 0) { + goto __4 + } + htree_group = GetHtreeGroupForPos(tls, hdr, col, row) +__4: + ; + + if !((*HTreeGroup)(unsafe.Pointer(htree_group)).is_trivial_code != 0) { + goto __5 + } + *(*uint32_t)(unsafe.Pointer(src)) = (*HTreeGroup)(unsafe.Pointer(htree_group)).literal_arb + goto AdvanceByOne +__5: + ; + VP8LFillBitWindow(tls, br) + if !((*HTreeGroup)(unsafe.Pointer(htree_group)).use_packed_table != 0) { + goto __6 + } + code = ReadPackedSymbols(tls, htree_group, br, src) + if !(VP8LIsEndOfStream(tls, br) != 0) { + goto __8 + } + goto __2 +__8: + ; + if !(code == 0) { + goto __9 + } + goto AdvanceByOne +__9: + ; + goto __7 +__6: + code = ReadSymbol(tls, *(*uintptr)(unsafe.Pointer((htree_group /* &.htrees */))), br) +__7: + ; + if !(VP8LIsEndOfStream(tls, br) != 0) { + goto __10 + } + goto __2 +__10: + ; + if !(code < 256) { + goto __11 + } // Literal + if !((*HTreeGroup)(unsafe.Pointer(htree_group)).is_trivial_literal != 0) { + goto __13 + } + *(*uint32_t)(unsafe.Pointer(src)) = ((*HTreeGroup)(unsafe.Pointer(htree_group)).literal_arb | (uint32_t(code << 8))) + goto __14 +__13: + red = ReadSymbol(tls, *(*uintptr)(unsafe.Pointer((htree_group /* &.htrees */) + 1*8)), br) + VP8LFillBitWindow(tls, br) + blue = ReadSymbol(tls, *(*uintptr)(unsafe.Pointer((htree_group /* &.htrees */) + 2*8)), br) + alpha = ReadSymbol(tls, *(*uintptr)(unsafe.Pointer((htree_group /* &.htrees */) + 3*8)), br) + if !(VP8LIsEndOfStream(tls, br) != 0) { + goto __15 + } + goto __2 +__15: + ; + *(*uint32_t)(unsafe.Pointer(src)) = ((((uint32_t(alpha) << 24) | (uint32_t(red << 16))) | (uint32_t(code << 8))) | uint32_t(blue)) +__14: + ; +AdvanceByOne: + src += 4 + col++ + if !(col >= width) { + goto __16 + } + col = 0 + row++ + if !(process_func != (uintptr(0))) { + goto __17 + } + if !((row <= last_row) && ((row % 16) == 0)) { + goto __18 + } + (*struct { + f func(*libc.TLS, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{process_func})).f(tls, dec, row) +__18: + ; +__17: + ; + if !(color_cache != (uintptr(0))) { + goto __19 + } +__20: + if !(last_cached < src) { + goto __21 + } + VP8LColorCacheInsert(tls, color_cache, *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&last_cached, 4)))) + goto __20 +__21: + ; +__19: + ; +__16: + ; + goto __12 +__11: + if !(code < len_code_limit) { + goto __22 + } + length_sym = (code - 256) + length = GetCopyLength(tls, length_sym, br) + dist_symbol = ReadSymbol(tls, *(*uintptr)(unsafe.Pointer((htree_group /* &.htrees */) + 4*8)), br) + VP8LFillBitWindow(tls, br) + dist_code = GetCopyDistance(tls, dist_symbol, br) + dist = PlaneCodeToDistance(tls, width, dist_code) + + if !(VP8LIsEndOfStream(tls, br) != 0) { + goto __24 + } + goto __2 +__24: + ; + if !((((int64(src) - int64(data)) / 4) < ptrdiff_t(dist)) || (((int64(src_end) - int64(src)) / 4) < ptrdiff_t(length))) { + goto __25 + } + goto Error + goto __26 +__25: + CopyBlock32b(tls, src, dist, length) +__26: + ; + src += 4 * (uintptr(length)) + col = col + (length) +__27: + if !(col >= width) { + goto __28 + } + col = col - (width) + row++ + if !(process_func != (uintptr(0))) { + goto __29 + } + if !((row <= last_row) && ((row % 16) == 0)) { + goto __30 + } + (*struct { + f func(*libc.TLS, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{process_func})).f(tls, dec, row) +__30: + ; +__29: + ; + goto __27 +__28: + ; + // Because of the check done above (before 'src' was incremented by + // 'length'), the following holds true. + + if !((col & mask) != 0) { + goto __31 + } + htree_group = GetHtreeGroupForPos(tls, hdr, col, row) +__31: + ; + if !(color_cache != (uintptr(0))) { + goto __32 + } +__33: + if !(last_cached < src) { + goto __34 + } + VP8LColorCacheInsert(tls, color_cache, *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&last_cached, 4)))) + goto __33 +__34: + ; +__32: + ; + goto __23 +__22: + if !(code < color_cache_limit) { + goto __35 + } // Color cache + key = (code - len_code_limit) + +__37: + if !(last_cached < src) { + goto __38 + } + VP8LColorCacheInsert(tls, color_cache, *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&last_cached, 4)))) + goto __37 +__38: + ; + *(*uint32_t)(unsafe.Pointer(src)) = VP8LColorCacheLookup(tls, color_cache, uint32(key)) + goto AdvanceByOne + goto __36 +__35: // Not reached + goto Error +__36: + ; +__23: + ; +__12: + ; + goto __1 +__2: + ; + + (*VP8LBitReader)(unsafe.Pointer(br)).eos_ = VP8LIsEndOfStream(tls, br) + if !((((*VP8LDecoder)(unsafe.Pointer(dec)).incremental_ != 0) && ((*VP8LBitReader)(unsafe.Pointer(br)).eos_ != 0)) && (src < src_end)) { + goto __39 + } + RestoreState(tls, dec) + goto __40 +__39: + if !(!((*VP8LBitReader)(unsafe.Pointer(br)).eos_ != 0)) { + goto __41 + } + // Process the remaining rows corresponding to last row-block. + if !(process_func != (uintptr(0))) { + goto __43 + } + (*struct { + f func(*libc.TLS, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{process_func})).f(tls, dec, func() int32 { + if row > last_row { + return last_row + } + return row + }()) +__43: + ; + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_OK + (*VP8LDecoder)(unsafe.Pointer(dec)).last_pixel_ = (int32((int64(src) - int64(data)) / 4)) // end-of-scan marker + goto __42 +__41: + // if not incremental, and we are past the end of buffer (eos_=1), then this + // is a real bitstream error. + goto Error +__42: + ; +__40: + ; + return 1 + +Error: + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_BITSTREAM_ERROR + return 0 +} + +// ----------------------------------------------------------------------------- +// VP8LTransform + +func ClearTransform(tls *libc.TLS, transform uintptr) { /* vp8l_dec.c:1264:13: */ + WebPSafeFree(tls, (*VP8LTransform)(unsafe.Pointer(transform)).data_) + (*VP8LTransform)(unsafe.Pointer(transform)).data_ = (uintptr(0)) +} + +// For security reason, we need to remap the color map to span +// the total possible bundled values, and not just the num_colors. +func ExpandColorMap(tls *libc.TLS, num_colors int32, transform uintptr) int32 { /* vp8l_dec.c:1271:12: */ + var i int32 + var final_num_colors int32 = (int32(1) << (int32(8) >> (*VP8LTransform)(unsafe.Pointer(transform)).bits_)) + var new_color_map uintptr = WebPSafeMalloc(tls, uint64_t(final_num_colors), + uint64(unsafe.Sizeof(uint32_t(0)))) + if new_color_map == (uintptr(0)) { + return 0 + } else { + var data uintptr = (*VP8LTransform)(unsafe.Pointer(transform)).data_ + var new_data uintptr = new_color_map + *(*uint32_t)(unsafe.Pointer(new_color_map)) = *(*uint32_t)(unsafe.Pointer((*VP8LTransform)(unsafe.Pointer(transform)).data_)) + for i = 4; i < (4 * num_colors); i++ { + // Equivalent to AddPixelEq(), on a byte-basis. + *(*uint8_t)(unsafe.Pointer(new_data + uintptr(i))) = (uint8_t((int32(*(*uint8_t)(unsafe.Pointer(data + uintptr(i)))) + int32(*(*uint8_t)(unsafe.Pointer(new_data + uintptr((i - 4)))))) & 0xff)) + } + for ; i < (4 * final_num_colors); i++ { + *(*uint8_t)(unsafe.Pointer(new_data + uintptr(i))) = uint8_t(0) // black tail. + } + WebPSafeFree(tls, (*VP8LTransform)(unsafe.Pointer(transform)).data_) + (*VP8LTransform)(unsafe.Pointer(transform)).data_ = new_color_map + } + return 1 +} + +func ReadTransform(tls *libc.TLS, xsize uintptr, ysize uintptr, dec uintptr) int32 { /* vp8l_dec.c:1296:12: */ + var ok int32 = 1 + var br uintptr = (dec + 40 /* &.br_ */) + var transform uintptr = ((dec + 248 /* &.transforms_ */) + uintptr((*VP8LDecoder)(unsafe.Pointer(dec)).next_transform_)*24) + var type1 VP8LImageTransformType = VP8LReadBits(tls, br, 2) + + // Each transform type can only be present once in the stream. + if ((*VP8LDecoder)(unsafe.Pointer(dec)).transforms_seen_ & (uint32(1) << type1)) != 0 { + return 0 // Already there, let's not accept the second same transform. + } + *(*uint32_t)(unsafe.Pointer((dec + 344 /* &.transforms_seen_ */))) |= (uint32(1) << type1) + + (*VP8LTransform)(unsafe.Pointer(transform)).type_ = type1 + (*VP8LTransform)(unsafe.Pointer(transform)).xsize_ = *(*int32)(unsafe.Pointer(xsize)) + (*VP8LTransform)(unsafe.Pointer(transform)).ysize_ = *(*int32)(unsafe.Pointer(ysize)) + (*VP8LTransform)(unsafe.Pointer(transform)).data_ = (uintptr(0)) + (*VP8LDecoder)(unsafe.Pointer(dec)).next_transform_++ + + switch type1 { + case PREDICTOR_TRANSFORM: + fallthrough + case CROSS_COLOR_TRANSFORM: + (*VP8LTransform)(unsafe.Pointer(transform)).bits_ = (int32(VP8LReadBits(tls, br, 3) + uint32_t(2))) + ok = DecodeImageStream(tls, int32(VP8LSubSampleSize(tls, uint32((*VP8LTransform)(unsafe.Pointer(transform)).xsize_), + uint32((*VP8LTransform)(unsafe.Pointer(transform)).bits_))), + int32(VP8LSubSampleSize(tls, uint32((*VP8LTransform)(unsafe.Pointer(transform)).ysize_), + uint32((*VP8LTransform)(unsafe.Pointer(transform)).bits_))), + 0, dec, (transform + 16 /* &.data_ */)) + break + case COLOR_INDEXING_TRANSFORM: + { + var num_colors int32 = (int32(VP8LReadBits(tls, br, 8) + uint32_t(1))) + var bits int32 + if num_colors > 16 { + bits = 0 + } else { + if num_colors > 4 { + bits = 1 + } else { + if num_colors > 2 { + bits = 2 + } else { + bits = 3 + } + } + } + *(*int32)(unsafe.Pointer(xsize)) = int32(VP8LSubSampleSize(tls, uint32((*VP8LTransform)(unsafe.Pointer(transform)).xsize_), uint32(bits))) + (*VP8LTransform)(unsafe.Pointer(transform)).bits_ = bits + ok = DecodeImageStream(tls, num_colors, 1, 0, dec, (transform + 16 /* &.data_ */)) + ok = (libc.Bool32((ok != 0) && (ExpandColorMap(tls, num_colors, transform) != 0))) + break + + } + case SUBTRACT_GREEN: + break + default: + // can't happen + break + } + + return ok +} + +// ----------------------------------------------------------------------------- +// VP8LMetadata + +func InitMetadata(tls *libc.TLS, hdr uintptr) { /* vp8l_dec.c:1352:13: */ + + libc.Xmemset(tls, hdr, 0, uint64(unsafe.Sizeof(VP8LMetadata{}))) +} + +func ClearMetadata(tls *libc.TLS, hdr uintptr) { /* vp8l_dec.c:1357:13: */ + + WebPSafeFree(tls, (*VP8LMetadata)(unsafe.Pointer(hdr)).huffman_image_) + WebPSafeFree(tls, (*VP8LMetadata)(unsafe.Pointer(hdr)).huffman_tables_) + VP8LHtreeGroupsFree(tls, (*VP8LMetadata)(unsafe.Pointer(hdr)).htree_groups_) + VP8LColorCacheClear(tls, (hdr + 8 /* &.color_cache_ */)) + VP8LColorCacheClear(tls, (hdr + 24 /* &.saved_color_cache_ */)) + InitMetadata(tls, hdr) +} + +// ----------------------------------------------------------------------------- +// VP8LDecoder + +func VP8LNew(tls *libc.TLS) uintptr { /* vp8l_dec.c:1371:12: */ + var dec uintptr = WebPSafeCalloc(tls, 1, uint64(unsafe.Sizeof(VP8LDecoder{}))) + if dec == (uintptr(0)) { + return (uintptr(0)) + } + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_OK + (*VP8LDecoder)(unsafe.Pointer(dec)).state_ = READ_DIM + + VP8LDspInit(tls) // Init critical function pointers. + + return dec +} + +func VP8LClear(tls *libc.TLS, dec uintptr) { /* vp8l_dec.c:1382:6: */ + var i int32 + if dec == (uintptr(0)) { + return + } + ClearMetadata(tls, (dec + 152 /* &.hdr_ */)) + + WebPSafeFree(tls, (*VP8LDecoder)(unsafe.Pointer(dec)).pixels_) + (*VP8LDecoder)(unsafe.Pointer(dec)).pixels_ = (uintptr(0)) + for i = 0; i < (*VP8LDecoder)(unsafe.Pointer(dec)).next_transform_; i++ { + ClearTransform(tls, ((dec + 248 /* &.transforms_ */) + uintptr(i)*24)) + } + (*VP8LDecoder)(unsafe.Pointer(dec)).next_transform_ = 0 + (*VP8LDecoder)(unsafe.Pointer(dec)).transforms_seen_ = uint32_t(0) + + WebPSafeFree(tls, (*VP8LDecoder)(unsafe.Pointer(dec)).rescaler_memory) + (*VP8LDecoder)(unsafe.Pointer(dec)).rescaler_memory = (uintptr(0)) + + (*VP8LDecoder)(unsafe.Pointer(dec)).output_ = (uintptr(0)) // leave no trace behind +} + +func VP8LDelete(tls *libc.TLS, dec uintptr) { /* vp8l_dec.c:1401:6: */ + if dec != (uintptr(0)) { + VP8LClear(tls, dec) + WebPSafeFree(tls, dec) + } +} + +func UpdateDecoder(tls *libc.TLS, dec uintptr, width int32, height int32) { /* vp8l_dec.c:1408:13: */ + var hdr uintptr = (dec + 152 /* &.hdr_ */) + var num_bits int32 = (*VP8LMetadata)(unsafe.Pointer(hdr)).huffman_subsample_bits_ + (*VP8LDecoder)(unsafe.Pointer(dec)).width_ = width + (*VP8LDecoder)(unsafe.Pointer(dec)).height_ = height + + (*VP8LMetadata)(unsafe.Pointer(hdr)).huffman_xsize_ = int32(VP8LSubSampleSize(tls, uint32(width), uint32(num_bits))) + (*VP8LMetadata)(unsafe.Pointer(hdr)).huffman_mask_ = func() int32 { + if num_bits == 0 { + return libc.CplInt32(0) + } + return ((int32(1) << num_bits) - 1) + }() +} + +func DecodeImageStream(tls *libc.TLS, xsize int32, ysize int32, is_level0 int32, dec uintptr, decoded_data uintptr) int32 { /* vp8l_dec.c:1418:12: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var ok int32 + // var transform_xsize int32 at bp, 4 + + // var transform_ysize int32 at bp+4, 4 + + var br uintptr + var hdr uintptr + var data uintptr + var color_cache_bits int32 + var total_size uint64_t + ok = 1 + *(*int32)(unsafe.Pointer(bp /* transform_xsize */)) = xsize + *(*int32)(unsafe.Pointer(bp + 4 /* transform_ysize */)) = ysize + br = (dec + 40 /* &.br_ */) + hdr = (dec + 152 /* &.hdr_ */) + data = (uintptr(0)) + color_cache_bits = 0 + + // Read the transforms (may recurse). + if !(is_level0 != 0) { + goto __1 + } +__2: + if !((ok != 0) && (VP8LReadBits(tls, br, 1) != 0)) { + goto __3 + } + ok = ReadTransform(tls, (bp) /* &transform_xsize */, (bp + 4) /* &transform_ysize */, dec) + goto __2 +__3: + ; +__1: + ; + + // Color cache + if !((ok != 0) && (VP8LReadBits(tls, br, 1) != 0)) { + goto __4 + } + color_cache_bits = int32(VP8LReadBits(tls, br, 4)) + ok = (libc.Bool32((color_cache_bits >= 1) && (color_cache_bits <= 11))) + if !(!(ok != 0)) { + goto __5 + } + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_BITSTREAM_ERROR + goto End +__5: + ; +__4: + ; + + // Read the Huffman codes (may recurse). + ok = (libc.Bool32((ok != 0) && (ReadHuffmanCodes(tls, dec, *(*int32)(unsafe.Pointer(bp /* transform_xsize */)), *(*int32)(unsafe.Pointer(bp + 4 /* transform_ysize */)), + color_cache_bits, is_level0) != 0))) + if !(!(ok != 0)) { + goto __6 + } + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_BITSTREAM_ERROR + goto End +__6: + ; + + // Finish setting up the color-cache + if !(color_cache_bits > 0) { + goto __7 + } + (*VP8LMetadata)(unsafe.Pointer(hdr)).color_cache_size_ = (int32(1) << color_cache_bits) + if !(!(VP8LColorCacheInit(tls, (hdr+8 /* &.color_cache_ */), color_cache_bits) != 0)) { + goto __9 + } + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_OUT_OF_MEMORY + ok = 0 + goto End +__9: + ; + goto __8 +__7: + (*VP8LMetadata)(unsafe.Pointer(hdr)).color_cache_size_ = 0 +__8: + ; + UpdateDecoder(tls, dec, *(*int32)(unsafe.Pointer(bp /* transform_xsize */)), *(*int32)(unsafe.Pointer(bp + 4 /* transform_ysize */))) + + if !(is_level0 != 0) { + goto __10 + } // level 0 complete + (*VP8LDecoder)(unsafe.Pointer(dec)).state_ = READ_HDR + goto End +__10: + ; + + total_size = (uint64_t(*(*int32)(unsafe.Pointer(bp /* transform_xsize */))) * uint64_t(*(*int32)(unsafe.Pointer(bp + 4 /* transform_ysize */)))) + data = WebPSafeMalloc(tls, total_size, uint64(unsafe.Sizeof(uint32_t(0)))) + if !(data == (uintptr(0))) { + goto __11 + } + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_OUT_OF_MEMORY + ok = 0 + goto End +__11: + ; + + // Use the Huffman trees to decode the LZ77 encoded data. + ok = DecodeImageData(tls, dec, data, *(*int32)(unsafe.Pointer(bp /* transform_xsize */)), *(*int32)(unsafe.Pointer(bp + 4 /* transform_ysize */)), + *(*int32)(unsafe.Pointer(bp + 4 /* transform_ysize */)), (uintptr(0))) + ok = (libc.Bool32((ok != 0) && !((*VP8LBitReader)(unsafe.Pointer(br)).eos_ != 0))) + +End: + if !(!(ok != 0)) { + goto __12 + } + WebPSafeFree(tls, data) + ClearMetadata(tls, hdr) + goto __13 +__12: + if !(decoded_data != (uintptr(0))) { + goto __14 + } + *(*uintptr)(unsafe.Pointer(decoded_data)) = data + goto __15 +__14: + // We allocate image data in this function only for transforms. At level 0 + // (that is: not the transforms), we shouldn't have allocated anything. + ; + +__15: + ; + (*VP8LDecoder)(unsafe.Pointer(dec)).last_pixel_ = 0 // Reset for future DECODE_DATA_FUNC() calls. + if !(!(is_level0 != 0)) { + goto __16 + } + ClearMetadata(tls, hdr) +__16: + ; // Clean up temporary data behind. +__13: + ; + return ok +} + +//------------------------------------------------------------------------------ +// Allocate internal buffers dec->pixels_ and dec->argb_cache_. +func AllocateInternalBuffers32b(tls *libc.TLS, dec uintptr, final_width int32) int32 { /* vp8l_dec.c:1509:12: */ + var num_pixels uint64_t = (uint64_t((*VP8LDecoder)(unsafe.Pointer(dec)).width_) * uint64_t((*VP8LDecoder)(unsafe.Pointer(dec)).height_)) + // Scratch buffer corresponding to top-prediction row for transforming the + // first row in the row-blocks. Not needed for paletted alpha. + var cache_top_pixels uint64_t = uint64_t(uint16_t(final_width)) + // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha. + var cache_pixels uint64_t = (uint64_t(final_width) * uint64(16)) + var total_num_pixels uint64_t = ((num_pixels + cache_top_pixels) + cache_pixels) + + (*VP8LDecoder)(unsafe.Pointer(dec)).pixels_ = WebPSafeMalloc(tls, total_num_pixels, uint64(unsafe.Sizeof(uint32_t(0)))) + if (*VP8LDecoder)(unsafe.Pointer(dec)).pixels_ == (uintptr(0)) { + (*VP8LDecoder)(unsafe.Pointer(dec)).argb_cache_ = (uintptr(0)) // for soundness + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_OUT_OF_MEMORY + return 0 + } + (*VP8LDecoder)(unsafe.Pointer(dec)).argb_cache_ = (((*VP8LDecoder)(unsafe.Pointer(dec)).pixels_ + uintptr(num_pixels)*4) + uintptr(cache_top_pixels)*4) + return 1 +} + +func AllocateInternalBuffers8b(tls *libc.TLS, dec uintptr) int32 { /* vp8l_dec.c:1530:12: */ + var total_num_pixels uint64_t = (uint64_t((*VP8LDecoder)(unsafe.Pointer(dec)).width_) * uint64_t((*VP8LDecoder)(unsafe.Pointer(dec)).height_)) + (*VP8LDecoder)(unsafe.Pointer(dec)).argb_cache_ = (uintptr(0)) // for soundness + (*VP8LDecoder)(unsafe.Pointer(dec)).pixels_ = WebPSafeMalloc(tls, total_num_pixels, uint64(unsafe.Sizeof(uint8_t(0)))) + if (*VP8LDecoder)(unsafe.Pointer(dec)).pixels_ == (uintptr(0)) { + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_OUT_OF_MEMORY + return 0 + } + return 1 +} + +//------------------------------------------------------------------------------ + +// Special row-processing that only stores the alpha data. +func ExtractAlphaRows(tls *libc.TLS, dec uintptr, last_row int32) { /* vp8l_dec.c:1544:13: */ + var cur_row int32 = (*VP8LDecoder)(unsafe.Pointer(dec)).last_row_ + var num_rows int32 = (last_row - cur_row) + var in uintptr = ((*VP8LDecoder)(unsafe.Pointer(dec)).pixels_ + uintptr(((*VP8LDecoder)(unsafe.Pointer(dec)).width_*cur_row))*4) + + for num_rows > 0 { + var num_rows_to_process int32 + if num_rows > 16 { + num_rows_to_process = 16 + } else { + num_rows_to_process = num_rows + } + // Extract alpha (which is stored in the green plane). + var alph_dec uintptr = (*VP8Io)(unsafe.Pointer((*VP8LDecoder)(unsafe.Pointer(dec)).io_)).opaque + var output uintptr = (*ALPHDecoder)(unsafe.Pointer(alph_dec)).output_ + var width int32 = (*VP8Io)(unsafe.Pointer((*VP8LDecoder)(unsafe.Pointer(dec)).io_)).width // the final width (!= dec->width_) + var cache_pixs int32 = (width * num_rows_to_process) + var dst uintptr = (output + uintptr((width * cur_row))) + var src uintptr = (*VP8LDecoder)(unsafe.Pointer(dec)).argb_cache_ + ApplyInverseTransforms(tls, dec, cur_row, num_rows_to_process, in) + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPExtractGreen})).f(tls, src, dst, cache_pixs) + AlphaApplyFilter(tls, alph_dec, + cur_row, (cur_row + num_rows_to_process), dst, width) + num_rows = num_rows - (num_rows_to_process) + in += 4 * (uintptr(num_rows_to_process * (*VP8LDecoder)(unsafe.Pointer(dec)).width_)) + cur_row = cur_row + (num_rows_to_process) + } + + (*VP8LDecoder)(unsafe.Pointer(dec)).last_row_ = libc.AssignPtrInt32((dec + 148 /* &.last_out_row_ */), last_row) +} + +func VP8LDecodeAlphaHeader(tls *libc.TLS, alph_dec uintptr, data uintptr, data_size size_t) int32 { /* vp8l_dec.c:1572:5: */ + var ok int32 + var dec uintptr + ok = 0 + dec = VP8LNew(tls) + + if !(dec == (uintptr(0))) { + goto __1 + } + return 0 +__1: + ; + + (*VP8LDecoder)(unsafe.Pointer(dec)).width_ = (*ALPHDecoder)(unsafe.Pointer(alph_dec)).width_ + (*VP8LDecoder)(unsafe.Pointer(dec)).height_ = (*ALPHDecoder)(unsafe.Pointer(alph_dec)).height_ + (*VP8LDecoder)(unsafe.Pointer(dec)).io_ = (alph_dec + 32 /* &.io_ */) + (*VP8Io)(unsafe.Pointer((*VP8LDecoder)(unsafe.Pointer(dec)).io_)).opaque = alph_dec + (*VP8Io)(unsafe.Pointer((*VP8LDecoder)(unsafe.Pointer(dec)).io_)).width = (*ALPHDecoder)(unsafe.Pointer(alph_dec)).width_ + (*VP8Io)(unsafe.Pointer((*VP8LDecoder)(unsafe.Pointer(dec)).io_)).height = (*ALPHDecoder)(unsafe.Pointer(alph_dec)).height_ + + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_OK + VP8LInitBitReader(tls, (dec + 40 /* &.br_ */), data, data_size) + + if !(!(DecodeImageStream(tls, (*ALPHDecoder)(unsafe.Pointer(alph_dec)).width_, (*ALPHDecoder)(unsafe.Pointer(alph_dec)).height_, 1, dec, (uintptr(0))) != 0)) { + goto __2 + } + goto Err +__2: + ; + + // Special case: if alpha data uses only the color indexing transform and + // doesn't use color cache (a frequent case), we will use DecodeAlphaData() + // method that only needs allocation of 1 byte per pixel (alpha channel). + if !((((*VP8LDecoder)(unsafe.Pointer(dec)).next_transform_ == 1) && ((*VP8LTransform)(unsafe.Pointer((dec + 248 /* &.transforms_ */))).type_ == COLOR_INDEXING_TRANSFORM)) && (Is8bOptimizable(tls, (dec+152 /* &.hdr_ */)) != 0)) { + goto __3 + } + (*ALPHDecoder)(unsafe.Pointer(alph_dec)).use_8b_decode_ = 1 + ok = AllocateInternalBuffers8b(tls, dec) + goto __4 +__3: + // Allocate internal buffers (note that dec->width_ may have changed here). + (*ALPHDecoder)(unsafe.Pointer(alph_dec)).use_8b_decode_ = 0 + ok = AllocateInternalBuffers32b(tls, dec, (*ALPHDecoder)(unsafe.Pointer(alph_dec)).width_) +__4: + ; + + if !(!(ok != 0)) { + goto __5 + } + goto Err +__5: + ; + + // Only set here, once we are sure it is valid (to avoid thread races). + (*ALPHDecoder)(unsafe.Pointer(alph_dec)).vp8l_dec_ = dec + return 1 + +Err: + VP8LDelete(tls, dec) + return 0 +} + +func VP8LDecodeAlphaImageStream(tls *libc.TLS, alph_dec uintptr, last_row int32) int32 { /* vp8l_dec.c:1620:5: */ + var dec uintptr = (*ALPHDecoder)(unsafe.Pointer(alph_dec)).vp8l_dec_ + + if (*VP8LDecoder)(unsafe.Pointer(dec)).last_row_ >= last_row { + return 1 // done + } + + if !((*ALPHDecoder)(unsafe.Pointer(alph_dec)).use_8b_decode_ != 0) { + WebPInitAlphaProcessing(tls) + } + + // Decode (with special row processing). + if (*ALPHDecoder)(unsafe.Pointer(alph_dec)).use_8b_decode_ != 0 { + return DecodeAlphaData(tls, dec, (*VP8LDecoder)(unsafe.Pointer(dec)).pixels_, (*VP8LDecoder)(unsafe.Pointer(dec)).width_, (*VP8LDecoder)(unsafe.Pointer(dec)).height_, + last_row) + } + return DecodeImageData(tls, dec, (*VP8LDecoder)(unsafe.Pointer(dec)).pixels_, (*VP8LDecoder)(unsafe.Pointer(dec)).width_, (*VP8LDecoder)(unsafe.Pointer(dec)).height_, + last_row, *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32) + }{ExtractAlphaRows}))) +} + +//------------------------------------------------------------------------------ + +func VP8LDecodeHeader(tls *libc.TLS, dec uintptr, io uintptr) int32 { /* vp8l_dec.c:1641:5: */ + bp := tls.Alloc(12) + defer tls.Free(12) + + // var width int32 at bp, 4 + + // var height int32 at bp+4, 4 + + // var has_alpha int32 at bp+8, 4 + + if !(dec == (uintptr(0))) { + goto __1 + } + return 0 +__1: + ; + if !(io == (uintptr(0))) { + goto __2 + } + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_INVALID_PARAM + return 0 +__2: + ; + + (*VP8LDecoder)(unsafe.Pointer(dec)).io_ = io + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_OK + VP8LInitBitReader(tls, (dec + 40 /* &.br_ */), (*VP8Io)(unsafe.Pointer(io)).data, (*VP8Io)(unsafe.Pointer(io)).data_size) + if !(!(ReadImageInfo(tls, (dec+40 /* &.br_ */), (bp) /* &width */, (bp+4) /* &height */, (bp+8) /* &has_alpha */) != 0)) { + goto __3 + } + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_BITSTREAM_ERROR + goto Error +__3: + ; + (*VP8LDecoder)(unsafe.Pointer(dec)).state_ = READ_DIM + (*VP8Io)(unsafe.Pointer(io)).width = *(*int32)(unsafe.Pointer(bp /* width */)) + (*VP8Io)(unsafe.Pointer(io)).height = *(*int32)(unsafe.Pointer(bp + 4 /* height */)) + + if !(!(DecodeImageStream(tls, *(*int32)(unsafe.Pointer(bp /* width */)), *(*int32)(unsafe.Pointer(bp + 4 /* height */)), 1, dec, (uintptr(0))) != 0)) { + goto __4 + } + goto Error +__4: + ; + return 1 + +Error: + VP8LClear(tls, dec) + + return 0 +} + +func VP8LDecodeImage(tls *libc.TLS, dec uintptr) int32 { /* vp8l_dec.c:1670:5: */ + var io uintptr + var params uintptr + io = (uintptr(0)) + params = (uintptr(0)) + + if !(dec == (uintptr(0))) { + goto __1 + } + return 0 +__1: + ; + + io = (*VP8LDecoder)(unsafe.Pointer(dec)).io_ + + params = (*VP8Io)(unsafe.Pointer(io)).opaque + + // Initialization. + if !((*VP8LDecoder)(unsafe.Pointer(dec)).state_ != READ_DATA) { + goto __2 + } + (*VP8LDecoder)(unsafe.Pointer(dec)).output_ = (*WebPDecParams)(unsafe.Pointer(params)).output + + if !(!(WebPIoInitFromOptions(tls, (*WebPDecParams)(unsafe.Pointer(params)).options, io, MODE_BGRA) != 0)) { + goto __3 + } + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_INVALID_PARAM + goto Err +__3: + ; + + if !(!(AllocateInternalBuffers32b(tls, dec, (*VP8Io)(unsafe.Pointer(io)).width) != 0)) { + goto __4 + } + goto Err +__4: + ; + + if !(((*VP8Io)(unsafe.Pointer(io)).use_scaling != 0) && !(AllocateAndInitRescaler(tls, dec, io) != 0)) { + goto __5 + } + goto Err +__5: + ; + if !(((*VP8Io)(unsafe.Pointer(io)).use_scaling != 0) || (WebPIsPremultipliedMode(tls, (*WebPDecBuffer)(unsafe.Pointer((*VP8LDecoder)(unsafe.Pointer(dec)).output_)).colorspace) != 0)) { + goto __6 + } + // need the alpha-multiply functions for premultiplied output or rescaling + WebPInitAlphaProcessing(tls) +__6: + ; + + if !(!(WebPIsRGBMode(tls, (*WebPDecBuffer)(unsafe.Pointer((*VP8LDecoder)(unsafe.Pointer(dec)).output_)).colorspace) != 0)) { + goto __7 + } + WebPInitConvertARGBToYUV(tls) + if !((*WebPYUVABuffer)(unsafe.Pointer(((*VP8LDecoder)(unsafe.Pointer(dec)).output_ + 16 /* &.u */))).a != (uintptr(0))) { + goto __8 + } + WebPInitAlphaProcessing(tls) +__8: + ; +__7: + ; + if !((*VP8LDecoder)(unsafe.Pointer(dec)).incremental_ != 0) { + goto __9 + } + if !(((*VP8LDecoder)(unsafe.Pointer(dec)).hdr_.color_cache_size_ > 0) && ((*VP8LDecoder)(unsafe.Pointer(dec)).hdr_.saved_color_cache_.colors_ == (uintptr(0)))) { + goto __10 + } + if !(!(VP8LColorCacheInit(tls, ((dec+152 /* &.hdr_ */)+24 /* &.saved_color_cache_ */), + (*VP8LDecoder)(unsafe.Pointer(dec)).hdr_.color_cache_.hash_bits_) != 0)) { + goto __11 + } + (*VP8LDecoder)(unsafe.Pointer(dec)).status_ = VP8_STATUS_OUT_OF_MEMORY + goto Err +__11: + ; +__10: + ; +__9: + ; + (*VP8LDecoder)(unsafe.Pointer(dec)).state_ = READ_DATA +__2: + ; + + // Decode. + if !(!(DecodeImageData(tls, dec, (*VP8LDecoder)(unsafe.Pointer(dec)).pixels_, (*VP8LDecoder)(unsafe.Pointer(dec)).width_, (*VP8LDecoder)(unsafe.Pointer(dec)).height_, + (*VP8Io)(unsafe.Pointer(io)).crop_bottom, *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32) + }{ProcessRows}))) != 0)) { + goto __12 + } + goto Err +__12: + ; + + (*WebPDecParams)(unsafe.Pointer(params)).last_y = (*VP8LDecoder)(unsafe.Pointer(dec)).last_out_row_ + return 1 + +Err: + VP8LClear(tls, dec) + + return 0 +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Data-types common to the mux and demux libraries. +// +// Author: Urvang (urvang@google.com) + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.21 String handling <string.h> + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPFeatureFlags WebPFeatureFlags; +// typedef enum WebPMuxAnimDispose WebPMuxAnimDispose; +// typedef enum WebPMuxAnimBlend WebPMuxAnimBlend; +type WebPData1 = struct { + bytes uintptr + size size_t +} /* mux_types.h:29:9 */ + +//------------------------------------------------------------------------------ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Data-types common to the mux and demux libraries. +// +// Author: Urvang (urvang@google.com) + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.21 String handling <string.h> + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Note: forward declaring enumerations is not allowed in (strict) C and C++, +// the types are left here for reference. +// typedef enum WebPFeatureFlags WebPFeatureFlags; +// typedef enum WebPMuxAnimDispose WebPMuxAnimDispose; +// typedef enum WebPMuxAnimBlend WebPMuxAnimBlend; +type WebPData = WebPData1 /* mux_types.h:29:25 */ + +// VP8X Feature Flags. +type WebPFeatureFlags = uint32 /* mux_types.h:40:3 */ + +// Dispose method (animation only). Indicates how the area used by the current +// frame is to be treated before rendering the next frame on the canvas. +type WebPMuxAnimDispose = uint32 /* mux_types.h:47:3 */ + +// Blend operation (animation only). Indicates how transparent pixels of the +// current frame are blended with those of the previous canvas. +type WebPMuxAnimBlend = uint32 /* mux_types.h:54:3 */ + +// Initializes the contents of the 'webp_data' object with default values. +func WebPDataInit(tls *libc.TLS, webp_data uintptr) { /* mux_types.h:65:25: */ + if webp_data != (uintptr(0)) { + libc.Xmemset(tls, webp_data, 0, uint64(unsafe.Sizeof(WebPData{}))) + } +} + +//------------------------------------------------------------------------------ +// RIFF layout is: +// Offset tag +// 0...3 "RIFF" 4-byte tag +// 4...7 size of image data (including metadata) starting at offset 8 +// 8...11 "WEBP" our form-type signature +// The RIFF container (12 bytes) is followed by appropriate chunks: +// 12..15 "VP8 ": 4-bytes tags, signaling the use of VP8 video format +// 16..19 size of the raw VP8 image data, starting at offset 20 +// 20.... the VP8 bytes +// Or, +// 12..15 "VP8L": 4-bytes tags, signaling the use of VP8L lossless format +// 16..19 size of the raw VP8L image data, starting at offset 20 +// 20.... the VP8L bytes +// Or, +// 12..15 "VP8X": 4-bytes tags, describing the extended-VP8 chunk. +// 16..19 size of the VP8X chunk starting at offset 20. +// 20..23 VP8X flags bit-map corresponding to the chunk-types present. +// 24..26 Width of the Canvas Image. +// 27..29 Height of the Canvas Image. +// There can be extra chunks after the "VP8X" chunk (ICCP, ANMF, VP8, VP8L, +// XMP, EXIF ...) +// All sizes are in little-endian order. +// Note: chunk data size must be padded to multiple of 2 when written. + +// Validates the RIFF container (if detected) and skips over it. +// If a RIFF container is detected, returns: +// VP8_STATUS_BITSTREAM_ERROR for invalid header, +// VP8_STATUS_NOT_ENOUGH_DATA for truncated data if have_all_data is true, +// and VP8_STATUS_OK otherwise. +// In case there are not enough bytes (partial RIFF container), return 0 for +// *riff_size. Else return the RIFF size extracted from the header. +func ParseRIFF(tls *libc.TLS, data uintptr, data_size uintptr, have_all_data int32, riff_size uintptr) VP8StatusCode { /* webp_dec.c:54:22: */ + + *(*size_t)(unsafe.Pointer(riff_size)) = uint64(0) // Default: no RIFF present. + if (*(*size_t)(unsafe.Pointer(data_size)) >= uint64(12)) && !(libc.Xmemcmp(tls, *(*uintptr)(unsafe.Pointer(data)), (ts+527) /* "RIFF" */, uint64(4)) != 0) { + if libc.Xmemcmp(tls, (*(*uintptr)(unsafe.Pointer(data))+uintptr(8)), (ts+532) /* "WEBP" */, uint64(4)) != 0 { + return VP8_STATUS_BITSTREAM_ERROR // Wrong image file signature. + } else { + var size uint32_t = GetLE32(tls, (*(*uintptr)(unsafe.Pointer(data)) + uintptr(4))) + // Check that we have at least one chunk (i.e "WEBP" + "VP8?nnnn"). + if size < (uint32_t(4 + 8)) { + return VP8_STATUS_BITSTREAM_ERROR + } + if size > ((libc.CplUint32(0) - uint32(8)) - uint32(1)) { + return VP8_STATUS_BITSTREAM_ERROR + } + if (have_all_data != 0) && (size_t(size) > (*(*size_t)(unsafe.Pointer(data_size)) - uint64(8))) { + return VP8_STATUS_NOT_ENOUGH_DATA // Truncated bitstream. + } + // We have a RIFF container. Skip it. + *(*size_t)(unsafe.Pointer(riff_size)) = size_t(size) + *(*uintptr)(unsafe.Pointer(data)) += (uintptr(12)) + *(*size_t)(unsafe.Pointer(data_size)) -= (uint64(12)) + } + } + return VP8_STATUS_OK +} + +// Validates the VP8X header and skips over it. +// Returns VP8_STATUS_BITSTREAM_ERROR for invalid VP8X header, +// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and +// VP8_STATUS_OK otherwise. +// If a VP8X chunk is found, found_vp8x is set to true and *width_ptr, +// *height_ptr and *flags_ptr are set to the corresponding values extracted +// from the VP8X chunk. +func ParseVP8X(tls *libc.TLS, data uintptr, data_size uintptr, found_vp8x uintptr, width_ptr uintptr, height_ptr uintptr, flags_ptr uintptr) VP8StatusCode { /* webp_dec.c:93:22: */ + var vp8x_size uint32_t = (uint32_t(8 + 10)) + + *(*int32)(unsafe.Pointer(found_vp8x)) = 0 + + if *(*size_t)(unsafe.Pointer(data_size)) < uint64(8) { + return VP8_STATUS_NOT_ENOUGH_DATA // Insufficient data. + } + + if !(libc.Xmemcmp(tls, *(*uintptr)(unsafe.Pointer(data)), (ts+537) /* "VP8X" */, uint64(4)) != 0) { + var width int32 + var height int32 + var flags uint32_t + var chunk_size uint32_t = GetLE32(tls, (*(*uintptr)(unsafe.Pointer(data)) + uintptr(4))) + if chunk_size != uint32_t(10) { + return VP8_STATUS_BITSTREAM_ERROR // Wrong chunk size. + } + + // Verify if enough data is available to validate the VP8X chunk. + if *(*size_t)(unsafe.Pointer(data_size)) < size_t(vp8x_size) { + return VP8_STATUS_NOT_ENOUGH_DATA // Insufficient data. + } + flags = GetLE32(tls, (*(*uintptr)(unsafe.Pointer(data)) + uintptr(8))) + width = (1 + GetLE24(tls, (*(*uintptr)(unsafe.Pointer(data))+uintptr(12)))) + height = (1 + GetLE24(tls, (*(*uintptr)(unsafe.Pointer(data))+uintptr(15)))) + if (uint64(uint64_t(width) * uint64_t(height))) >= (uint64(1) << 32) { + return VP8_STATUS_BITSTREAM_ERROR // image is too large + } + + if flags_ptr != (uintptr(0)) { + *(*uint32_t)(unsafe.Pointer(flags_ptr)) = flags + } + if width_ptr != (uintptr(0)) { + *(*int32)(unsafe.Pointer(width_ptr)) = width + } + if height_ptr != (uintptr(0)) { + *(*int32)(unsafe.Pointer(height_ptr)) = height + } + // Skip over VP8X header bytes. + *(*uintptr)(unsafe.Pointer(data)) += (uintptr(vp8x_size)) + *(*size_t)(unsafe.Pointer(data_size)) -= (size_t(vp8x_size)) + *(*int32)(unsafe.Pointer(found_vp8x)) = 1 + } + return VP8_STATUS_OK +} + +// Skips to the next VP8/VP8L chunk header in the data given the size of the +// RIFF chunk 'riff_size'. +// Returns VP8_STATUS_BITSTREAM_ERROR if any invalid chunk size is encountered, +// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and +// VP8_STATUS_OK otherwise. +// If an alpha chunk is found, *alpha_data and *alpha_size are set +// appropriately. +func ParseOptionalChunks(tls *libc.TLS, data uintptr, data_size uintptr, riff_size size_t, alpha_data uintptr, alpha_size uintptr) VP8StatusCode { /* webp_dec.c:146:22: */ + var buf uintptr + var buf_size size_t + var total_size uint32_t = (uint32_t((4 + 8) + 10)) // data. + + buf = *(*uintptr)(unsafe.Pointer(data)) + buf_size = *(*size_t)(unsafe.Pointer(data_size)) + + *(*uintptr)(unsafe.Pointer(alpha_data)) = (uintptr(0)) + *(*size_t)(unsafe.Pointer(alpha_size)) = uint64(0) + + for 1 != 0 { + var chunk_size uint32_t + var disk_chunk_size uint32_t // chunk_size with padding + + *(*uintptr)(unsafe.Pointer(data)) = buf + *(*size_t)(unsafe.Pointer(data_size)) = buf_size + + if buf_size < uint64(8) { // Insufficient data. + return VP8_STATUS_NOT_ENOUGH_DATA + } + + chunk_size = GetLE32(tls, (buf + uintptr(4))) + if chunk_size > ((libc.CplUint32(0) - uint32(8)) - uint32(1)) { + return VP8_STATUS_BITSTREAM_ERROR // Not a valid chunk size. + } + // For odd-sized chunk-payload, there's one byte padding at the end. + disk_chunk_size = (((uint32_t(8) + chunk_size) + uint32_t(1)) & libc.Uint32FromInt32(libc.CplInt32(1))) + total_size = total_size + (disk_chunk_size) + + // Check that total bytes skipped so far does not exceed riff_size. + if (riff_size > uint64(0)) && (size_t(total_size) > riff_size) { + return VP8_STATUS_BITSTREAM_ERROR // Not a valid chunk size. + } + + // Start of a (possibly incomplete) VP8/VP8L chunk implies that we have + // parsed all the optional chunks. + // Note: This check must occur before the check 'buf_size < disk_chunk_size' + // below to allow incomplete VP8/VP8L chunks. + if !(libc.Xmemcmp(tls, buf, (ts+542) /* "VP8 " */, uint64(4)) != 0) || !(libc.Xmemcmp(tls, buf, (ts+547) /* "VP8L" */, uint64(4)) != 0) { + return VP8_STATUS_OK + } + + if buf_size < size_t(disk_chunk_size) { // Insufficient data. + return VP8_STATUS_NOT_ENOUGH_DATA + } + + if !(libc.Xmemcmp(tls, buf, (ts+552) /* "ALPH" */, uint64(4)) != 0) { // A valid ALPH header. + *(*uintptr)(unsafe.Pointer(alpha_data)) = (buf + uintptr(8)) + *(*size_t)(unsafe.Pointer(alpha_size)) = size_t(chunk_size) + } + + // We have a full and valid chunk; skip it. + buf += uintptr(disk_chunk_size) + buf_size = buf_size - (size_t(disk_chunk_size)) + } + return VP8StatusCode(0) +} + +// Validates the VP8/VP8L Header ("VP8 nnnn" or "VP8L nnnn") and skips over it. +// Returns VP8_STATUS_BITSTREAM_ERROR for invalid (chunk larger than +// riff_size) VP8/VP8L header, +// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and +// VP8_STATUS_OK otherwise. +// If a VP8/VP8L chunk is found, *chunk_size is set to the total number of bytes +// extracted from the VP8/VP8L chunk header. +// The flag '*is_lossless' is set to 1 in case of VP8L chunk / raw VP8L data. +func ParseVP8Header(tls *libc.TLS, data_ptr uintptr, data_size uintptr, have_all_data int32, riff_size size_t, chunk_size uintptr, is_lossless uintptr) VP8StatusCode { /* webp_dec.c:222:22: */ + var data uintptr = *(*uintptr)(unsafe.Pointer(data_ptr)) + var is_vp8 int32 = libc.BoolInt32(!(libc.Xmemcmp(tls, data, (ts+542) /* "VP8 " */, uint64(4)) != 0)) + var is_vp8l int32 = libc.BoolInt32(!(libc.Xmemcmp(tls, data, (ts+547) /* "VP8L" */, uint64(4)) != 0)) + var minimal_size uint32_t = (uint32_t(4 + 8)) // "WEBP" + "VP8 nnnn" OR + // "WEBP" + "VP8Lnnnn" + + if *(*size_t)(unsafe.Pointer(data_size)) < uint64(8) { + return VP8_STATUS_NOT_ENOUGH_DATA // Insufficient data. + } + + if (is_vp8 != 0) || (is_vp8l != 0) { + // Bitstream contains VP8/VP8L header. + var size uint32_t = GetLE32(tls, (data + uintptr(4))) + if (riff_size >= size_t(minimal_size)) && (size_t(size) > (riff_size - size_t(minimal_size))) { + return VP8_STATUS_BITSTREAM_ERROR // Inconsistent size information. + } + if (have_all_data != 0) && (size_t(size) > (*(*size_t)(unsafe.Pointer(data_size)) - uint64(8))) { + return VP8_STATUS_NOT_ENOUGH_DATA // Truncated bitstream. + } + // Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header. + *(*size_t)(unsafe.Pointer(chunk_size)) = size_t(size) + *(*uintptr)(unsafe.Pointer(data_ptr)) += (uintptr(8)) + *(*size_t)(unsafe.Pointer(data_size)) -= (uint64(8)) + *(*int32)(unsafe.Pointer(is_lossless)) = is_vp8l + } else { + // Raw VP8/VP8L bitstream (no header). + *(*int32)(unsafe.Pointer(is_lossless)) = VP8LCheckSignature(tls, data, *(*size_t)(unsafe.Pointer(data_size))) + *(*size_t)(unsafe.Pointer(chunk_size)) = *(*size_t)(unsafe.Pointer(data_size)) + } + + return VP8_STATUS_OK +} + +//------------------------------------------------------------------------------ + +// Fetch '*width', '*height', '*has_alpha' and fill out 'headers' based on +// 'data'. All the output parameters may be NULL. If 'headers' is NULL only the +// minimal amount will be read to fetch the remaining parameters. +// If 'headers' is non-NULL this function will attempt to locate both alpha +// data (with or without a VP8X chunk) and the bitstream chunk (VP8/VP8L). +// Note: The following chunk sequences (before the raw VP8/VP8L data) are +// considered valid by this function: +// RIFF + VP8(L) +// RIFF + VP8X + (optional chunks) + VP8(L) +// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. +// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. +func ParseHeadersInternal(tls *libc.TLS, data uintptr, data_size size_t, width uintptr, height uintptr, has_alpha uintptr, has_animation uintptr, format uintptr, headers uintptr) VP8StatusCode { /* webp_dec.c:277:22: */ + bp := tls.Alloc(112) + defer tls.Free(112) + *(*uintptr)(unsafe.Pointer(bp + 72)) = data + *(*size_t)(unsafe.Pointer(bp + 80)) = data_size + + // var canvas_width int32 at bp+92, 4 + + // var canvas_height int32 at bp+96, 4 + + // var image_width int32 at bp+104, 4 + + // var image_height int32 at bp+108, 4 + + var found_riff int32 + // var found_vp8x int32 at bp+88, 4 + + var animation_present int32 + var have_all_data int32 + var status VP8StatusCode + // var hdrs WebPHeaderStructure at bp, 72 + + // var flags uint32_t at bp+100, 4 + *(*int32)(unsafe.Pointer(bp + 92 /* canvas_width */)) = 0 + *(*int32)(unsafe.Pointer(bp + 96 /* canvas_height */)) = 0 + *(*int32)(unsafe.Pointer(bp + 104 /* image_width */)) = 0 + *(*int32)(unsafe.Pointer(bp + 108 /* image_height */)) = 0 + found_riff = 0 + *(*int32)(unsafe.Pointer(bp + 88 /* found_vp8x */)) = 0 + animation_present = 0 + if headers != (uintptr(0)) { + have_all_data = (*WebPHeaderStructure)(unsafe.Pointer(headers)).have_all_data + } else { + have_all_data = 0 + } + + if !((*(*uintptr)(unsafe.Pointer(bp + 72 /* data */)) == (uintptr(0))) || (*(*size_t)(unsafe.Pointer(bp + 80 /* data_size */)) < uint64(12))) { + goto __1 + } + return VP8_STATUS_NOT_ENOUGH_DATA +__1: + ; + libc.Xmemset(tls, (bp) /* &hdrs */, 0, uint64(unsafe.Sizeof(WebPHeaderStructure{}))) + (*WebPHeaderStructure)(unsafe.Pointer(bp /* &hdrs */)).data = *(*uintptr)(unsafe.Pointer(bp + 72 /* data */)) + (*WebPHeaderStructure)(unsafe.Pointer(bp /* &hdrs */)).data_size = *(*size_t)(unsafe.Pointer(bp + 80 /* data_size */)) + + // Skip over RIFF header. + status = ParseRIFF(tls, (bp + 72) /* &data */, (bp + 80) /* &data_size */, have_all_data, ((bp) /* &hdrs */ + 56 /* &.riff_size */)) + if !(status != VP8_STATUS_OK) { + goto __2 + } + return status // Wrong RIFF header / insufficient data. +__2: + ; + found_riff = (libc.Bool32((*WebPHeaderStructure)(unsafe.Pointer(bp /* &hdrs */)).riff_size > uint64(0))) + + // Skip over VP8X. + + *(*uint32_t)(unsafe.Pointer(bp + 100 /* flags */)) = uint32_t(0) + status = ParseVP8X(tls, (bp + 72) /* &data */, (bp + 80) /* &data_size */, (bp + 88), /* &found_vp8x */ + (bp + 92) /* &canvas_width */, (bp + 96) /* &canvas_height */, (bp + 100) /* &flags */) + if !(status != VP8_STATUS_OK) { + goto __3 + } + return status // Wrong VP8X / insufficient data. +__3: + ; + animation_present = libc.BoolInt32(!(!((*(*uint32_t)(unsafe.Pointer(bp + 100 /* flags */)) & ANIMATION_FLAG) != 0))) + if !(!(found_riff != 0) && (*(*int32)(unsafe.Pointer(bp + 88 /* found_vp8x */)) != 0)) { + goto __4 + } + // Note: This restriction may be removed in the future, if it becomes + // necessary to send VP8X chunk to the decoder. + return VP8_STATUS_BITSTREAM_ERROR +__4: + ; + if !(has_alpha != (uintptr(0))) { + goto __5 + } + *(*int32)(unsafe.Pointer(has_alpha)) = libc.BoolInt32(!(!((*(*uint32_t)(unsafe.Pointer(bp + 100 /* flags */)) & ALPHA_FLAG) != 0))) +__5: + ; + if !(has_animation != (uintptr(0))) { + goto __6 + } + *(*int32)(unsafe.Pointer(has_animation)) = animation_present +__6: + ; + if !(format != (uintptr(0))) { + goto __7 + } + *(*int32)(unsafe.Pointer(format)) = 0 +__7: + ; // default = undefined + + *(*int32)(unsafe.Pointer(bp + 104 /* image_width */)) = *(*int32)(unsafe.Pointer(bp + 92 /* canvas_width */)) + *(*int32)(unsafe.Pointer(bp + 108 /* image_height */)) = *(*int32)(unsafe.Pointer(bp + 96 /* canvas_height */)) + if !(((*(*int32)(unsafe.Pointer(bp + 88 /* found_vp8x */)) != 0) && (animation_present != 0)) && (headers == (uintptr(0)))) { + goto __8 + } + status = VP8_STATUS_OK + goto ReturnWidthHeight // Just return features from VP8X header. +__8: + ; + + if !(*(*size_t)(unsafe.Pointer(bp + 80 /* data_size */)) < uint64(4)) { + goto __9 + } + status = VP8_STATUS_NOT_ENOUGH_DATA + goto ReturnWidthHeight +__9: + ; + + // Skip over optional chunks if data started with "RIFF + VP8X" or "ALPH". + if !(((found_riff != 0) && (*(*int32)(unsafe.Pointer(bp + 88 /* found_vp8x */)) != 0)) || ((!(found_riff != 0) && !(*(*int32)(unsafe.Pointer(bp + 88 /* found_vp8x */)) != 0)) && !(libc.Xmemcmp(tls, *(*uintptr)(unsafe.Pointer(bp + 72 /* data */)), (ts+552) /* "ALPH" */, uint64(4)) != 0))) { + goto __10 + } + status = ParseOptionalChunks(tls, (bp + 72) /* &data */, (bp + 80) /* &data_size */, (*WebPHeaderStructure)(unsafe.Pointer(bp /* &hdrs */)).riff_size, + ((bp) /* &hdrs */ + 32 /* &.alpha_data */), ((bp) /* &hdrs */ + 40 /* &.alpha_data_size */)) + if !(status != VP8_STATUS_OK) { + goto __11 + } + goto ReturnWidthHeight // Invalid chunk size / insufficient data. +__11: + ; +__10: + ; + + // Skip over VP8/VP8L header. + status = ParseVP8Header(tls, (bp + 72) /* &data */, (bp + 80) /* &data_size */, have_all_data, (*WebPHeaderStructure)(unsafe.Pointer(bp /* &hdrs */)).riff_size, + ((bp) /* &hdrs */ + 48 /* &.compressed_size */), ((bp) /* &hdrs */ + 64 /* &.is_lossless */)) + if !(status != VP8_STATUS_OK) { + goto __12 + } + goto ReturnWidthHeight // Wrong VP8/VP8L chunk-header / insufficient data. +__12: + ; + if !((*WebPHeaderStructure)(unsafe.Pointer(bp /* &hdrs */)).compressed_size > (uint64((libc.CplUint32(0) - uint32(8)) - uint32(1)))) { + goto __13 + } + return VP8_STATUS_BITSTREAM_ERROR +__13: + ; + + if !((format != (uintptr(0))) && !(animation_present != 0)) { + goto __14 + } + *(*int32)(unsafe.Pointer(format)) = func() int32 { + if (*WebPHeaderStructure)(unsafe.Pointer(bp /* &hdrs */)).is_lossless != 0 { + return 2 + } + return 1 + }() +__14: + ; + + if !(!((*WebPHeaderStructure)(unsafe.Pointer(bp /* &hdrs */)).is_lossless != 0)) { + goto __15 + } + if !(*(*size_t)(unsafe.Pointer(bp + 80 /* data_size */)) < uint64(10)) { + goto __17 + } + status = VP8_STATUS_NOT_ENOUGH_DATA + goto ReturnWidthHeight +__17: + ; + // Validates raw VP8 data. + if !(!(VP8GetInfo(tls, *(*uintptr)(unsafe.Pointer(bp + 72 /* data */)), *(*size_t)(unsafe.Pointer(bp + 80 /* data_size */)), uint64(uint32_t((*WebPHeaderStructure)(unsafe.Pointer(bp /* &hdrs */)).compressed_size)), + (bp+104) /* &image_width */, (bp+108) /* &image_height */) != 0)) { + goto __18 + } + return VP8_STATUS_BITSTREAM_ERROR +__18: + ; + goto __16 +__15: + if !(*(*size_t)(unsafe.Pointer(bp + 80 /* data_size */)) < uint64(5)) { + goto __19 + } + status = VP8_STATUS_NOT_ENOUGH_DATA + goto ReturnWidthHeight +__19: + ; + // Validates raw VP8L data. + if !(!(VP8LGetInfo(tls, *(*uintptr)(unsafe.Pointer(bp + 72 /* data */)), *(*size_t)(unsafe.Pointer(bp + 80 /* data_size */)), (bp+104) /* &image_width */, (bp+108) /* &image_height */, has_alpha) != 0)) { + goto __20 + } + return VP8_STATUS_BITSTREAM_ERROR +__20: + ; +__16: + ; + // Validates image size coherency. + if !(*(*int32)(unsafe.Pointer(bp + 88 /* found_vp8x */)) != 0) { + goto __21 + } + if !((*(*int32)(unsafe.Pointer(bp + 92 /* canvas_width */)) != *(*int32)(unsafe.Pointer(bp + 104 /* image_width */))) || (*(*int32)(unsafe.Pointer(bp + 96 /* canvas_height */)) != *(*int32)(unsafe.Pointer(bp + 108 /* image_height */)))) { + goto __22 + } + return VP8_STATUS_BITSTREAM_ERROR +__22: + ; +__21: + ; + if !(headers != (uintptr(0))) { + goto __23 + } + *(*WebPHeaderStructure)(unsafe.Pointer(headers)) = *(*WebPHeaderStructure)(unsafe.Pointer(bp /* hdrs */)) + (*WebPHeaderStructure)(unsafe.Pointer(headers)).offset = (size_t((int64(*(*uintptr)(unsafe.Pointer(bp + 72 /* data */))) - int64((*WebPHeaderStructure)(unsafe.Pointer(headers)).data)) / 1)) + +__23: + ; +ReturnWidthHeight: + if !((status == VP8_STATUS_OK) || (((status == VP8_STATUS_NOT_ENOUGH_DATA) && (*(*int32)(unsafe.Pointer(bp + 88 /* found_vp8x */)) != 0)) && (headers == (uintptr(0))))) { + goto __24 + } + if !(has_alpha != (uintptr(0))) { + goto __26 + } + // If the data did not contain a VP8X/VP8L chunk the only definitive way + // to set this is by looking for alpha data (from an ALPH chunk). + *(*int32)(unsafe.Pointer(has_alpha)) |= (libc.Bool32((*WebPHeaderStructure)(unsafe.Pointer(bp /* &hdrs */)).alpha_data != (uintptr(0)))) +__26: + ; + if !(width != (uintptr(0))) { + goto __27 + } + *(*int32)(unsafe.Pointer(width)) = *(*int32)(unsafe.Pointer(bp + 104 /* image_width */)) +__27: + ; + if !(height != (uintptr(0))) { + goto __28 + } + *(*int32)(unsafe.Pointer(height)) = *(*int32)(unsafe.Pointer(bp + 108 /* image_height */)) +__28: + ; + return VP8_STATUS_OK + goto __25 +__24: + return status +__25: + ; + return VP8StatusCode(0) +} + +func WebPParseHeaders(tls *libc.TLS, headers uintptr) VP8StatusCode { /* webp_dec.c:414:15: */ + bp := tls.Alloc(4) + defer tls.Free(4) + + // status is marked volatile as a workaround for a clang-3.8 (aarch64) bug + var status VP8StatusCode + *(*int32)(unsafe.Pointer(bp /* has_animation */)) = 0 + + // fill out headers, ignore width/height/has_alpha. + status = ParseHeadersInternal(tls, (*WebPHeaderStructure)(unsafe.Pointer(headers)).data, (*WebPHeaderStructure)(unsafe.Pointer(headers)).data_size, + (uintptr(0)), (uintptr(0)), (uintptr(0)), (bp), /* &has_animation */ + (uintptr(0)), headers) + if (status == VP8_STATUS_OK) || (status == VP8_STATUS_NOT_ENOUGH_DATA) { + // The WebPDemux API + libwebp can be used to decode individual + // uncomposited frames or the WebPAnimDecoder can be used to fully + // reconstruct them (see webp/demux.h). + if *(*int32)(unsafe.Pointer(bp /* has_animation */)) != 0 { + status = VP8_STATUS_UNSUPPORTED_FEATURE + } + } + return status +} + +//------------------------------------------------------------------------------ +// WebPDecParams + +func WebPResetDecParams(tls *libc.TLS, params uintptr) { /* webp_dec.c:437:6: */ + if params != (uintptr(0)) { + libc.Xmemset(tls, params, 0, uint64(unsafe.Sizeof(WebPDecParams{}))) + } +} + +//------------------------------------------------------------------------------ +// "Into" decoding variants + +// Main flow +func DecodeInto(tls *libc.TLS, data uintptr, data_size size_t, params uintptr) VP8StatusCode { /* webp_dec.c:447:22: */ + bp := tls.Alloc(232) + defer tls.Free(232) + + var status VP8StatusCode + // var io VP8Io at bp+72, 160 + + // var headers WebPHeaderStructure at bp, 72 + + (*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).data = data + (*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).data_size = data_size + (*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).have_all_data = 1 + status = WebPParseHeaders(tls, (bp) /* &headers */) // Process Pre-VP8 chunks. + if status != VP8_STATUS_OK { + return status + } + + VP8InitIo(tls, (bp + 72) /* &io */) + (*VP8Io)(unsafe.Pointer(bp + 72 /* &io */)).data = ((*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).data + uintptr((*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).offset)) + (*VP8Io)(unsafe.Pointer(bp + 72 /* &io */)).data_size = ((*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).data_size - (*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).offset) + WebPInitCustomIo(tls, params, (bp + 72) /* &io */) // Plug the I/O functions. + + if !((*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).is_lossless != 0) { + var dec uintptr = VP8New(tls) + if dec == (uintptr(0)) { + return VP8_STATUS_OUT_OF_MEMORY + } + (*VP8Decoder)(unsafe.Pointer(dec)).alpha_data_ = (*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).alpha_data + (*VP8Decoder)(unsafe.Pointer(dec)).alpha_data_size_ = (*WebPHeaderStructure)(unsafe.Pointer(bp /* &headers */)).alpha_data_size + + // Decode bitstream header, update io->width/io->height. + if !(VP8GetHeaders(tls, dec, (bp+72) /* &io */) != 0) { + status = (*VP8Decoder)(unsafe.Pointer(dec)).status_ // An error occurred. Grab error status. + } else { + // Allocate/check output buffers. + status = WebPAllocateDecBuffer(tls, (*VP8Io)(unsafe.Pointer(bp+72 /* &io */)).width, (*VP8Io)(unsafe.Pointer(bp+72 /* &io */)).height, (*WebPDecParams)(unsafe.Pointer(params)).options, + (*WebPDecParams)(unsafe.Pointer(params)).output) + if status == VP8_STATUS_OK { // Decode + // This change must be done before calling VP8Decode() + (*VP8Decoder)(unsafe.Pointer(dec)).mt_method_ = VP8GetThreadMethod(tls, (*WebPDecParams)(unsafe.Pointer(params)).options, (bp), /* &headers */ + (*VP8Io)(unsafe.Pointer(bp+72 /* &io */)).width, (*VP8Io)(unsafe.Pointer(bp+72 /* &io */)).height) + VP8InitDithering(tls, (*WebPDecParams)(unsafe.Pointer(params)).options, dec) + if !(VP8Decode(tls, dec, (bp+72) /* &io */) != 0) { + status = (*VP8Decoder)(unsafe.Pointer(dec)).status_ + } + } + } + VP8Delete(tls, dec) + } else { + var dec uintptr = VP8LNew(tls) + if dec == (uintptr(0)) { + return VP8_STATUS_OUT_OF_MEMORY + } + if !(VP8LDecodeHeader(tls, dec, (bp+72) /* &io */) != 0) { + status = (*VP8LDecoder)(unsafe.Pointer(dec)).status_ // An error occurred. Grab error status. + } else { + // Allocate/check output buffers. + status = WebPAllocateDecBuffer(tls, (*VP8Io)(unsafe.Pointer(bp+72 /* &io */)).width, (*VP8Io)(unsafe.Pointer(bp+72 /* &io */)).height, (*WebPDecParams)(unsafe.Pointer(params)).options, + (*WebPDecParams)(unsafe.Pointer(params)).output) + if status == VP8_STATUS_OK { // Decode + if !(VP8LDecodeImage(tls, dec) != 0) { + status = (*VP8LDecoder)(unsafe.Pointer(dec)).status_ + } + } + } + VP8LDelete(tls, dec) + } + + if status != VP8_STATUS_OK { + WebPFreeDecBuffer(tls, (*WebPDecParams)(unsafe.Pointer(params)).output) + } else { + if ((*WebPDecParams)(unsafe.Pointer(params)).options != (uintptr(0))) && ((*WebPDecoderOptions)(unsafe.Pointer((*WebPDecParams)(unsafe.Pointer(params)).options)).flip != 0) { + // This restores the original stride values if options->flip was used + // during the call to WebPAllocateDecBuffer above. + status = WebPFlipBuffer(tls, (*WebPDecParams)(unsafe.Pointer(params)).output) + } + } + return status +} + +// Helpers +func DecodeIntoRGBABuffer(tls *libc.TLS, colorspace WEBP_CSP_MODE, data uintptr, data_size size_t, rgba uintptr, stride int32, size size_t) uintptr { /* webp_dec.c:526:15: */ + bp := tls.Alloc(232) + defer tls.Free(232) + + // var params WebPDecParams at bp+120, 112 + + // var buf WebPDecBuffer at bp, 120 + + if rgba == (uintptr(0)) { + return (uintptr(0)) + } + WebPInitDecBuffer(tls, (bp) /* &buf */) + WebPResetDecParams(tls, (bp + 120) /* &params */) + (*WebPDecParams)(unsafe.Pointer(bp + 120 /* &params */)).output = (bp) /* &buf */ + (*WebPDecBuffer)(unsafe.Pointer(bp /* &buf */)).colorspace = colorspace + (*WebPRGBABuffer)(unsafe.Pointer(((bp) /* &buf */ + 16 /* &.u */))).rgba = rgba + (*WebPRGBABuffer)(unsafe.Pointer(((bp) /* &buf */ + 16 /* &.u */))).stride = stride + (*WebPRGBABuffer)(unsafe.Pointer(((bp) /* &buf */ + 16 /* &.u */))).size = size + (*WebPDecBuffer)(unsafe.Pointer(bp /* &buf */)).is_external_memory = 1 + if DecodeInto(tls, data, data_size, (bp+120) /* &params */) != VP8_STATUS_OK { + return (uintptr(0)) + } + return rgba +} + +func WebPDecodeRGBInto(tls *libc.TLS, data uintptr, data_size size_t, output uintptr, size size_t, stride int32) uintptr { /* webp_dec.c:550:8: */ + return DecodeIntoRGBABuffer(tls, MODE_RGB, data, data_size, output, stride, size) +} + +func WebPDecodeRGBAInto(tls *libc.TLS, data uintptr, data_size size_t, output uintptr, size size_t, stride int32) uintptr { /* webp_dec.c:555:8: */ + return DecodeIntoRGBABuffer(tls, MODE_RGBA, data, data_size, output, stride, size) +} + +func WebPDecodeARGBInto(tls *libc.TLS, data uintptr, data_size size_t, output uintptr, size size_t, stride int32) uintptr { /* webp_dec.c:560:8: */ + return DecodeIntoRGBABuffer(tls, MODE_ARGB, data, data_size, output, stride, size) +} + +func WebPDecodeBGRInto(tls *libc.TLS, data uintptr, data_size size_t, output uintptr, size size_t, stride int32) uintptr { /* webp_dec.c:565:8: */ + return DecodeIntoRGBABuffer(tls, MODE_BGR, data, data_size, output, stride, size) +} + +func WebPDecodeBGRAInto(tls *libc.TLS, data uintptr, data_size size_t, output uintptr, size size_t, stride int32) uintptr { /* webp_dec.c:570:8: */ + return DecodeIntoRGBABuffer(tls, MODE_BGRA, data, data_size, output, stride, size) +} + +func WebPDecodeYUVInto(tls *libc.TLS, data uintptr, data_size size_t, luma uintptr, luma_size size_t, luma_stride int32, u uintptr, u_size size_t, u_stride int32, v uintptr, v_size size_t, v_stride int32) uintptr { /* webp_dec.c:575:8: */ + bp := tls.Alloc(232) + defer tls.Free(232) + + // var params WebPDecParams at bp+120, 112 + + // var output WebPDecBuffer at bp, 120 + + if luma == (uintptr(0)) { + return (uintptr(0)) + } + WebPInitDecBuffer(tls, (bp) /* &output */) + WebPResetDecParams(tls, (bp + 120) /* &params */) + (*WebPDecParams)(unsafe.Pointer(bp + 120 /* &params */)).output = (bp) /* &output */ + (*WebPDecBuffer)(unsafe.Pointer(bp /* &output */)).colorspace = MODE_YUV + (*WebPYUVABuffer)(unsafe.Pointer(((bp) /* &output */ + 16 /* &.u */))).y = luma + (*WebPYUVABuffer)(unsafe.Pointer(((bp) /* &output */ + 16 /* &.u */))).y_stride = luma_stride + (*WebPYUVABuffer)(unsafe.Pointer(((bp) /* &output */ + 16 /* &.u */))).y_size = luma_size + (*WebPYUVABuffer)(unsafe.Pointer(((bp) /* &output */ + 16 /* &.u */))).u = u + (*WebPYUVABuffer)(unsafe.Pointer(((bp) /* &output */ + 16 /* &.u */))).u_stride = u_stride + (*WebPYUVABuffer)(unsafe.Pointer(((bp) /* &output */ + 16 /* &.u */))).u_size = u_size + (*WebPYUVABuffer)(unsafe.Pointer(((bp) /* &output */ + 16 /* &.u */))).v = v + (*WebPYUVABuffer)(unsafe.Pointer(((bp) /* &output */ + 16 /* &.u */))).v_stride = v_stride + (*WebPYUVABuffer)(unsafe.Pointer(((bp) /* &output */ + 16 /* &.u */))).v_size = v_size + (*WebPDecBuffer)(unsafe.Pointer(bp /* &output */)).is_external_memory = 1 + if DecodeInto(tls, data, data_size, (bp+120) /* &params */) != VP8_STATUS_OK { + return (uintptr(0)) + } + return luma +} + +//------------------------------------------------------------------------------ + +func Decode(tls *libc.TLS, mode WEBP_CSP_MODE, data uintptr, data_size size_t, width uintptr, height uintptr, keep_info uintptr) uintptr { /* webp_dec.c:604:15: */ + bp := tls.Alloc(232) + defer tls.Free(232) + + // var params WebPDecParams at bp+120, 112 + + // var output WebPDecBuffer at bp, 120 + + WebPInitDecBuffer(tls, (bp) /* &output */) + WebPResetDecParams(tls, (bp + 120) /* &params */) + (*WebPDecParams)(unsafe.Pointer(bp + 120 /* &params */)).output = (bp) /* &output */ + (*WebPDecBuffer)(unsafe.Pointer(bp /* &output */)).colorspace = mode + + // Retrieve (and report back) the required dimensions from bitstream. + if !(WebPGetInfo(tls, data, data_size, ((bp) /* &output */ +4 /* &.width */), ((bp) /* &output */ +8 /* &.height */)) != 0) { + return (uintptr(0)) + } + if width != (uintptr(0)) { + *(*int32)(unsafe.Pointer(width)) = (*WebPDecBuffer)(unsafe.Pointer(bp /* &output */)).width + } + if height != (uintptr(0)) { + *(*int32)(unsafe.Pointer(height)) = (*WebPDecBuffer)(unsafe.Pointer(bp /* &output */)).height + } + + // Decode + if DecodeInto(tls, data, data_size, (bp+120) /* &params */) != VP8_STATUS_OK { + return (uintptr(0)) + } + if keep_info != (uintptr(0)) { // keep track of the side-info + WebPCopyDecBuffer(tls, (bp) /* &output */, keep_info) + } + // return decoded samples (don't clear 'output'!) + if WebPIsRGBMode(tls, mode) != 0 { + return (*WebPRGBABuffer)(unsafe.Pointer(((bp) /* &output */ + 16 /* &.u */))).rgba + } + return (*WebPYUVABuffer)(unsafe.Pointer(((bp) /* &output */ + 16 /* &.u */))).y +} + +func WebPDecodeRGB(tls *libc.TLS, data uintptr, data_size size_t, width uintptr, height uintptr) uintptr { /* webp_dec.c:633:8: */ + return Decode(tls, MODE_RGB, data, data_size, width, height, (uintptr(0))) +} + +func WebPDecodeRGBA(tls *libc.TLS, data uintptr, data_size size_t, width uintptr, height uintptr) uintptr { /* webp_dec.c:638:8: */ + return Decode(tls, MODE_RGBA, data, data_size, width, height, (uintptr(0))) +} + +func WebPDecodeARGB(tls *libc.TLS, data uintptr, data_size size_t, width uintptr, height uintptr) uintptr { /* webp_dec.c:643:8: */ + return Decode(tls, MODE_ARGB, data, data_size, width, height, (uintptr(0))) +} + +func WebPDecodeBGR(tls *libc.TLS, data uintptr, data_size size_t, width uintptr, height uintptr) uintptr { /* webp_dec.c:648:8: */ + return Decode(tls, MODE_BGR, data, data_size, width, height, (uintptr(0))) +} + +func WebPDecodeBGRA(tls *libc.TLS, data uintptr, data_size size_t, width uintptr, height uintptr) uintptr { /* webp_dec.c:653:8: */ + return Decode(tls, MODE_BGRA, data, data_size, width, height, (uintptr(0))) +} + +func WebPDecodeYUV(tls *libc.TLS, data uintptr, data_size size_t, width uintptr, height uintptr, u uintptr, v uintptr, stride uintptr, uv_stride uintptr) uintptr { /* webp_dec.c:658:8: */ + bp := tls.Alloc(120) + defer tls.Free(120) + + // var output WebPDecBuffer at bp, 120 + // only to preserve the side-infos + var out uintptr = Decode(tls, MODE_YUV, data, data_size, + width, height, (bp) /* &output */) + + if out != (uintptr(0)) { + var buf uintptr = ((bp) /* &output */ + 16 /* &.u */) /* &.YUVA */ + *(*uintptr)(unsafe.Pointer(u)) = (*WebPYUVABuffer)(unsafe.Pointer(buf)).u + *(*uintptr)(unsafe.Pointer(v)) = (*WebPYUVABuffer)(unsafe.Pointer(buf)).v + *(*int32)(unsafe.Pointer(stride)) = (*WebPYUVABuffer)(unsafe.Pointer(buf)).y_stride + *(*int32)(unsafe.Pointer(uv_stride)) = (*WebPYUVABuffer)(unsafe.Pointer(buf)).u_stride + + } + return out +} + +func DefaultFeatures(tls *libc.TLS, features uintptr) { /* webp_dec.c:676:13: */ + + libc.Xmemset(tls, features, 0, uint64(unsafe.Sizeof(WebPBitstreamFeatures{}))) +} + +func GetFeatures(tls *libc.TLS, data uintptr, data_size size_t, features uintptr) VP8StatusCode { /* webp_dec.c:681:22: */ + if (features == (uintptr(0))) || (data == (uintptr(0))) { + return VP8_STATUS_INVALID_PARAM + } + DefaultFeatures(tls, features) + + // Only parse enough of the data to retrieve the features. + return ParseHeadersInternal(tls, data, data_size, + (features /* &.width */), (features + 4 /* &.height */), + (features + 8 /* &.has_alpha */), (features + 12 /* &.has_animation */), + (features + 16 /* &.format */), (uintptr(0))) +} + +//------------------------------------------------------------------------------ +// WebPGetInfo() + +func WebPGetInfo(tls *libc.TLS, data uintptr, data_size size_t, width uintptr, height uintptr) int32 { /* webp_dec.c:698:5: */ + bp := tls.Alloc(40) + defer tls.Free(40) + + // var features WebPBitstreamFeatures at bp, 40 + + if GetFeatures(tls, data, data_size, (bp) /* &features */) != VP8_STATUS_OK { + return 0 + } + + if width != (uintptr(0)) { + *(*int32)(unsafe.Pointer(width)) = (*WebPBitstreamFeatures)(unsafe.Pointer(bp /* &features */)).width + } + if height != (uintptr(0)) { + *(*int32)(unsafe.Pointer(height)) = (*WebPBitstreamFeatures)(unsafe.Pointer(bp /* &features */)).height + } + + return 1 +} + +//------------------------------------------------------------------------------ +// Advance decoding API + +func WebPInitDecoderConfigInternal(tls *libc.TLS, config uintptr, version int32) int32 { /* webp_dec.c:719:5: */ + if ((version) >> 8) != (int32((0x0209)) >> 8) { + return 0 // version mismatch + } + if config == (uintptr(0)) { + return 0 + } + libc.Xmemset(tls, config, 0, uint64(unsafe.Sizeof(WebPDecoderConfig{}))) + DefaultFeatures(tls, (config /* &.input */)) + WebPInitDecBuffer(tls, (config + 40 /* &.output */)) + return 1 +} + +func WebPGetFeaturesInternal(tls *libc.TLS, data uintptr, data_size size_t, features uintptr, version int32) VP8StatusCode { /* webp_dec.c:733:15: */ + if ((version) >> 8) != (int32((0x0209)) >> 8) { + return VP8_STATUS_INVALID_PARAM // version mismatch + } + if features == (uintptr(0)) { + return VP8_STATUS_INVALID_PARAM + } + return GetFeatures(tls, data, data_size, features) +} + +func WebPDecode(tls *libc.TLS, data uintptr, data_size size_t, config uintptr) VP8StatusCode { /* webp_dec.c:745:15: */ + bp := tls.Alloc(232) + defer tls.Free(232) + + // var params WebPDecParams at bp, 112 + + var status VP8StatusCode + + if config == (uintptr(0)) { + return VP8_STATUS_INVALID_PARAM + } + + status = GetFeatures(tls, data, data_size, (config /* &.input */)) + if status != VP8_STATUS_OK { + if status == VP8_STATUS_NOT_ENOUGH_DATA { + return VP8_STATUS_BITSTREAM_ERROR // Not-enough-data treated as error. + } + return status + } + + WebPResetDecParams(tls, (bp) /* &params */) + (*WebPDecParams)(unsafe.Pointer(bp /* &params */)).options = (config + 160 /* &.options */) + (*WebPDecParams)(unsafe.Pointer(bp /* &params */)).output = (config + 40 /* &.output */) + if WebPAvoidSlowMemory(tls, (*WebPDecParams)(unsafe.Pointer(bp /* &params */)).output, (config /* &.input */)) != 0 { + // decoding to slow memory: use a temporary in-mem buffer to decode into. + // var in_mem_buffer WebPDecBuffer at bp+112, 120 + + WebPInitDecBuffer(tls, (bp + 112) /* &in_mem_buffer */) + (*WebPDecBuffer)(unsafe.Pointer(bp + 112 /* &in_mem_buffer */)).colorspace = (*WebPDecoderConfig)(unsafe.Pointer(config)).output.colorspace + (*WebPDecBuffer)(unsafe.Pointer(bp + 112 /* &in_mem_buffer */)).width = (*WebPDecoderConfig)(unsafe.Pointer(config)).input.width + (*WebPDecBuffer)(unsafe.Pointer(bp + 112 /* &in_mem_buffer */)).height = (*WebPDecoderConfig)(unsafe.Pointer(config)).input.height + (*WebPDecParams)(unsafe.Pointer(bp /* &params */)).output = (bp + 112) /* &in_mem_buffer */ + status = DecodeInto(tls, data, data_size, (bp) /* &params */) + if status == VP8_STATUS_OK { // do the slow-copy + status = WebPCopyDecBufferPixels(tls, (bp + 112) /* &in_mem_buffer */, (config + 40 /* &.output */)) + } + WebPFreeDecBuffer(tls, (bp + 112) /* &in_mem_buffer */) + } else { + status = DecodeInto(tls, data, data_size, (bp) /* &params */) + } + + return status +} + +//------------------------------------------------------------------------------ +// Cropping and rescaling. + +func WebPCheckCropDimensions(tls *libc.TLS, image_width int32, image_height int32, x int32, y int32, w int32, h int32) int32 { /* webp_dec.c:788:5: */ + return libc.BoolInt32(!((((((((((x < 0) || (y < 0)) || (w <= 0)) || (h <= 0)) || (x >= image_width)) || (w > image_width)) || (w > (image_width - x))) || (y >= image_height)) || (h > image_height)) || (h > (image_height - y)))) +} + +func WebPIoInitFromOptions(tls *libc.TLS, options uintptr, io uintptr, src_colorspace WEBP_CSP_MODE) int32 { /* webp_dec.c:795:5: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var W int32 = (*VP8Io)(unsafe.Pointer(io)).width + var H int32 = (*VP8Io)(unsafe.Pointer(io)).height + var x int32 = 0 + var y int32 = 0 + var w int32 = W + var h int32 = H + + // Cropping + (*VP8Io)(unsafe.Pointer(io)).use_cropping = (libc.Bool32((options != (uintptr(0))) && ((*WebPDecoderOptions)(unsafe.Pointer(options)).use_cropping != 0))) + if (*VP8Io)(unsafe.Pointer(io)).use_cropping != 0 { + w = (*WebPDecoderOptions)(unsafe.Pointer(options)).crop_width + h = (*WebPDecoderOptions)(unsafe.Pointer(options)).crop_height + x = (*WebPDecoderOptions)(unsafe.Pointer(options)).crop_left + y = (*WebPDecoderOptions)(unsafe.Pointer(options)).crop_top + if !(WebPIsRGBMode(tls, src_colorspace) != 0) { // only snap for YUV420 + x = x & (libc.CplInt32(1)) + y = y & (libc.CplInt32(1)) + } + if !(WebPCheckCropDimensions(tls, W, H, x, y, w, h) != 0) { + return 0 // out of frame boundary error + } + } + (*VP8Io)(unsafe.Pointer(io)).crop_left = x + (*VP8Io)(unsafe.Pointer(io)).crop_top = y + (*VP8Io)(unsafe.Pointer(io)).crop_right = (x + w) + (*VP8Io)(unsafe.Pointer(io)).crop_bottom = (y + h) + (*VP8Io)(unsafe.Pointer(io)).mb_w = w + (*VP8Io)(unsafe.Pointer(io)).mb_h = h + + // Scaling + (*VP8Io)(unsafe.Pointer(io)).use_scaling = (libc.Bool32((options != (uintptr(0))) && ((*WebPDecoderOptions)(unsafe.Pointer(options)).use_scaling != 0))) + if (*VP8Io)(unsafe.Pointer(io)).use_scaling != 0 { + *(*int32)(unsafe.Pointer(bp /* scaled_width */)) = (*WebPDecoderOptions)(unsafe.Pointer(options)).scaled_width + *(*int32)(unsafe.Pointer(bp + 4 /* scaled_height */)) = (*WebPDecoderOptions)(unsafe.Pointer(options)).scaled_height + if !(WebPRescalerGetScaledDimensions(tls, w, h, (bp) /* &scaled_width */, (bp+4) /* &scaled_height */) != 0) { + return 0 + } + (*VP8Io)(unsafe.Pointer(io)).scaled_width = *(*int32)(unsafe.Pointer(bp /* scaled_width */)) + (*VP8Io)(unsafe.Pointer(io)).scaled_height = *(*int32)(unsafe.Pointer(bp + 4 /* scaled_height */)) + } + + // Filter + (*VP8Io)(unsafe.Pointer(io)).bypass_filtering = (libc.Bool32((options != (uintptr(0))) && ((*WebPDecoderOptions)(unsafe.Pointer(options)).bypass_filtering != 0))) + + // Fancy upsampler + (*VP8Io)(unsafe.Pointer(io)).fancy_upsampling = (libc.Bool32((options == (uintptr(0))) || (!((*WebPDecoderOptions)(unsafe.Pointer(options)).no_fancy_upsampling != 0)))) + + if (*VP8Io)(unsafe.Pointer(io)).use_scaling != 0 { + // disable filter (only for large downscaling ratio). + *(*int32)(unsafe.Pointer((io + 112 /* &.bypass_filtering */))) |= (libc.Bool32(((*VP8Io)(unsafe.Pointer(io)).scaled_width < ((W * 3) / 4)) && ((*VP8Io)(unsafe.Pointer(io)).scaled_height < ((H * 3) / 4)))) + (*VP8Io)(unsafe.Pointer(io)).fancy_upsampling = 0 + } + return 1 +} + +//------------------------------------------------------------------------------ + +// Tables can be faster on some platform but incur some extra binary size (~2k). + +// ----------------------------------------------------------------------------- + +func Mult(tls *libc.TLS, x uint8_t, mult uint32_t) uint32_t { /* alpha_processing.c:29:17: */ + var v uint32_t = (((uint32_t(x) * mult) + (uint32((uint32(1) << 24)) >> 1)) >> 24) + // <- 24bit precision is enough to ensure that. + return v +} + +func GetScale(tls *libc.TLS, a uint32_t, inverse int32) uint32_t { /* alpha_processing.c:134:29: */ + if inverse != 0 { + return ((uint32(255) << 24) / a) + } + return (a * ((uint32(1) << 24) / 255)) +} + +func WebPMultARGBRow_C(tls *libc.TLS, ptr uintptr, width int32, inverse int32) { /* alpha_processing.c:140:6: */ + var x int32 + for x = 0; x < width; x++ { + var argb uint32_t = *(*uint32_t)(unsafe.Pointer(ptr + uintptr(x)*4)) + if argb < 0xff000000 { // alpha < 255 + if argb <= 0x00ffffff { // alpha == 0 + *(*uint32_t)(unsafe.Pointer(ptr + uintptr(x)*4)) = uint32_t(0) + } else { + var alpha uint32_t = ((argb >> 24) & uint32_t(0xff)) + var scale uint32_t = GetScale(tls, alpha, inverse) + var out uint32_t = (argb & 0xff000000) + out = out | (Mult(tls, (uint8(argb>>0)), scale) << 0) + out = out | (Mult(tls, (uint8(argb>>8)), scale) << 8) + out = out | (Mult(tls, (uint8(argb>>16)), scale) << 16) + *(*uint32_t)(unsafe.Pointer(ptr + uintptr(x)*4)) = out + } + } + } +} + +func WebPMultRow_C(tls *libc.TLS, ptr uintptr, alpha uintptr, width int32, inverse int32) { /* alpha_processing.c:160:6: */ + var x int32 + for x = 0; x < width; x++ { + var a uint32_t = uint32_t(*(*uint8_t)(unsafe.Pointer(alpha + uintptr(x)))) + if a != uint32_t(255) { + if a == uint32_t(0) { + *(*uint8_t)(unsafe.Pointer(ptr + uintptr(x))) = uint8_t(0) + } else { + var scale uint32_t = GetScale(tls, a, inverse) + *(*uint8_t)(unsafe.Pointer(ptr + uintptr(x))) = uint8_t(Mult(tls, *(*uint8_t)(unsafe.Pointer(ptr + uintptr(x))), scale)) + } + } + } +} + +var WebPMultARGBRow uintptr /* alpha_processing.c:181:6: */ +var WebPMultRow uintptr /* alpha_processing.c:182:6: */ + +//------------------------------------------------------------------------------ +// Generic per-plane calls + +func WebPMultARGBRows(tls *libc.TLS, ptr uintptr, stride int32, width int32, num_rows int32, inverse int32) { /* alpha_processing.c:189:6: */ + var n int32 + for n = 0; n < num_rows; n++ { + (*struct { + f func(*libc.TLS, uintptr, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPMultARGBRow})).f(tls, ptr, width, inverse) + ptr += uintptr(stride) + } +} + +func WebPMultRows(tls *libc.TLS, ptr uintptr, stride int32, alpha uintptr, alpha_stride int32, width int32, num_rows int32, inverse int32) { /* alpha_processing.c:198:6: */ + var n int32 + for n = 0; n < num_rows; n++ { + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPMultRow})).f(tls, ptr, alpha, width, inverse) + ptr += uintptr(stride) + alpha += uintptr(alpha_stride) + } +} + +//------------------------------------------------------------------------------ +// Premultiplied modes + +// non dithered-modes + +// (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.) +// for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5), +// one can use instead: (x * a * 65793 + (1 << 23)) >> 24 + +func ApplyAlphaMultiply_C(tls *libc.TLS, rgba uintptr, alpha_first int32, w int32, h int32, stride int32) { /* alpha_processing.c:226:13: */ + for libc.PostDecInt32(&h, 1) > 0 { + var rgb uintptr = (rgba + uintptr((func() int32 { + if alpha_first != 0 { + return 1 + } + return 0 + }()))) + var alpha uintptr = (rgba + uintptr((func() int32 { + if alpha_first != 0 { + return 0 + } + return 3 + }()))) + var i int32 + for i = 0; i < w; i++ { + var a uint32_t = uint32_t(*(*uint8_t)(unsafe.Pointer(alpha + uintptr((4 * i))))) + if a != uint32_t(0xff) { + var mult uint32_t = ((a) * 32897) + *(*uint8_t)(unsafe.Pointer(rgb + uintptr(((4 * i) + 0)))) = (uint8_t(((uint32_t(*(*uint8_t)(unsafe.Pointer(rgb + uintptr(((4 * i) + 0)))))) * (mult)) >> 23)) + *(*uint8_t)(unsafe.Pointer(rgb + uintptr(((4 * i) + 1)))) = (uint8_t(((uint32_t(*(*uint8_t)(unsafe.Pointer(rgb + uintptr(((4 * i) + 1)))))) * (mult)) >> 23)) + *(*uint8_t)(unsafe.Pointer(rgb + uintptr(((4 * i) + 2)))) = (uint8_t(((uint32_t(*(*uint8_t)(unsafe.Pointer(rgb + uintptr(((4 * i) + 2)))))) * (mult)) >> 23)) + } + } + rgba += uintptr(stride) + } +} + +// rgbA4444 + +func dither_hi(tls *libc.TLS, x uint8_t) uint8_t { /* alpha_processing.c:252:28: */ + return (uint8_t((int32(x) & 0xf0) | (int32(x) >> 4))) +} + +func dither_lo(tls *libc.TLS, x uint8_t) uint8_t { /* alpha_processing.c:256:28: */ + return (uint8_t((int32(x) & 0x0f) | (int32(x) << 4))) +} + +func multiply(tls *libc.TLS, x uint8_t, m uint32_t) uint8_t { /* alpha_processing.c:260:28: */ + return (uint8_t((uint32_t(x) * m) >> 16)) +} + +func ApplyAlphaMultiply4444_C(tls *libc.TLS, rgba4444 uintptr, w int32, h int32, stride int32, rg_byte_pos int32) { /* alpha_processing.c:264:25: */ + for libc.PostDecInt32(&h, 1) > 0 { + var i int32 + for i = 0; i < w; i++ { + var rg uint32_t = uint32_t(*(*uint8_t)(unsafe.Pointer(rgba4444 + uintptr(((2 * i) + rg_byte_pos))))) + var ba uint32_t = uint32_t(*(*uint8_t)(unsafe.Pointer(rgba4444 + uintptr(((2 * i) + (rg_byte_pos ^ 1)))))) + var a uint8_t = (uint8_t(ba & uint32_t(0x0f))) + var mult uint32_t = (uint32_t((int32(a)) * 0x1111)) + var r uint8_t = multiply(tls, dither_hi(tls, uint8(rg)), mult) + var g uint8_t = multiply(tls, dither_lo(tls, uint8(rg)), mult) + var b uint8_t = multiply(tls, dither_hi(tls, uint8(ba)), mult) + *(*uint8_t)(unsafe.Pointer(rgba4444 + uintptr(((2 * i) + rg_byte_pos)))) = (uint8_t((int32(r) & 0xf0) | ((int32(g) >> 4) & 0x0f))) + *(*uint8_t)(unsafe.Pointer(rgba4444 + uintptr(((2 * i) + (rg_byte_pos ^ 1))))) = (uint8_t((int32(b) & 0xf0) | int32(a))) + } + rgba4444 += uintptr(stride) + } +} + +func ApplyAlphaMultiply_16b_C(tls *libc.TLS, rgba4444 uintptr, w int32, h int32, stride int32) { /* alpha_processing.c:285:13: */ + ApplyAlphaMultiply4444_C(tls, rgba4444, w, h, stride, 0) +} + +func DispatchAlpha_C(tls *libc.TLS, alpha uintptr, alpha_stride int32, width int32, height int32, dst uintptr, dst_stride int32) int32 { /* alpha_processing.c:295:12: */ + var alpha_mask uint32_t = uint32_t(0xff) + var i int32 + var j int32 + + for j = 0; j < height; j++ { + for i = 0; i < width; i++ { + var alpha_value uint32_t = uint32_t(*(*uint8_t)(unsafe.Pointer(alpha + uintptr(i)))) + *(*uint8_t)(unsafe.Pointer(dst + uintptr((4 * i)))) = uint8_t(alpha_value) + alpha_mask = alpha_mask & (alpha_value) + } + alpha += uintptr(alpha_stride) + dst += uintptr(dst_stride) + } + + return (libc.Bool32(alpha_mask != uint32_t(0xff))) +} + +func DispatchAlphaToGreen_C(tls *libc.TLS, alpha uintptr, alpha_stride int32, width int32, height int32, dst uintptr, dst_stride int32) { /* alpha_processing.c:314:13: */ + var i int32 + var j int32 + for j = 0; j < height; j++ { + for i = 0; i < width; i++ { + *(*uint32_t)(unsafe.Pointer(dst + uintptr(i)*4)) = (uint32_t(int32(*(*uint8_t)(unsafe.Pointer(alpha + uintptr(i)))) << 8)) // leave A/R/B channels zero'd. + } + alpha += uintptr(alpha_stride) + dst += 4 * (uintptr(dst_stride)) + } +} + +func ExtractAlpha_C(tls *libc.TLS, argb uintptr, argb_stride int32, width int32, height int32, alpha uintptr, alpha_stride int32) int32 { /* alpha_processing.c:328:12: */ + var alpha_mask uint8_t = uint8_t(0xff) + var i int32 + var j int32 + + for j = 0; j < height; j++ { + for i = 0; i < width; i++ { + var alpha_value uint8_t = *(*uint8_t)(unsafe.Pointer(argb + uintptr((4 * i)))) + *(*uint8_t)(unsafe.Pointer(alpha + uintptr(i))) = alpha_value + alpha_mask = uint8_t(int32(alpha_mask) & (int32(alpha_value))) + } + argb += uintptr(argb_stride) + alpha += uintptr(alpha_stride) + } + return (libc.Bool32(int32(alpha_mask) == 0xff)) +} + +func ExtractGreen_C(tls *libc.TLS, argb uintptr, alpha uintptr, size int32) { /* alpha_processing.c:346:13: */ + var i int32 + for i = 0; i < size; i++ { + *(*uint8_t)(unsafe.Pointer(alpha + uintptr(i))) = (uint8_t(*(*uint32_t)(unsafe.Pointer(argb + uintptr(i)*4)) >> 8)) + } +} + +//------------------------------------------------------------------------------ + +func HasAlpha8b_C(tls *libc.TLS, src uintptr, length int32) int32 { /* alpha_processing.c:355:12: */ + for libc.PostDecInt32(&length, 1) > 0 { + if int32(*(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&src, 1)))) != 0xff { + return 1 + } + } + return 0 +} + +func HasAlpha32b_C(tls *libc.TLS, src uintptr, length int32) int32 { /* alpha_processing.c:360:12: */ + var x int32 + for x = 0; libc.PostDecInt32(&length, 1) > 0; x = x + (4) { + if int32(*(*uint8_t)(unsafe.Pointer(src + uintptr(x)))) != 0xff { + return 1 + } + } + return 0 +} + +func AlphaReplace_C(tls *libc.TLS, src uintptr, length int32, color uint32_t) { /* alpha_processing.c:366:13: */ + var x int32 + for x = 0; x < length; x++ { + if (*(*uint32_t)(unsafe.Pointer(src + uintptr(x)*4)) >> 24) == uint32_t(0) { + *(*uint32_t)(unsafe.Pointer(src + uintptr(x)*4)) = color + } + } +} + +//------------------------------------------------------------------------------ +// Simple channel manipulations. + +func MakeARGB32(tls *libc.TLS, a int32, r int32, g int32, b int32) uint32_t { /* alpha_processing.c:374:29: */ + return ((((uint32_t(a) << 24) | (uint32_t(r << 16))) | (uint32_t(g << 8))) | uint32_t(b)) +} + +func PackRGB_C(tls *libc.TLS, r uintptr, g uintptr, b uintptr, len int32, step int32, out uintptr) { /* alpha_processing.c:391:13: */ + var i int32 + var offset int32 = 0 + for i = 0; i < len; i++ { + *(*uint32_t)(unsafe.Pointer(out + uintptr(i)*4)) = MakeARGB32(tls, 0xff, int32(*(*uint8_t)(unsafe.Pointer(r + uintptr(offset)))), int32(*(*uint8_t)(unsafe.Pointer(g + uintptr(offset)))), int32(*(*uint8_t)(unsafe.Pointer(b + uintptr(offset))))) + offset = offset + (step) + } +} + +var WebPApplyAlphaMultiply uintptr /* alpha_processing.c:402:6: */ +var WebPApplyAlphaMultiply4444 uintptr /* alpha_processing.c:403:6: */ +var WebPDispatchAlpha uintptr /* alpha_processing.c:404:5: */ +var WebPDispatchAlphaToGreen uintptr /* alpha_processing.c:406:6: */ +var WebPExtractAlpha uintptr /* alpha_processing.c:408:5: */ +var WebPExtractGreen uintptr /* alpha_processing.c:410:6: */ +var WebPPackRGB uintptr /* alpha_processing.c:416:6: */ + +var WebPHasAlpha8b uintptr /* alpha_processing.c:421:5: */ +var WebPHasAlpha32b uintptr /* alpha_processing.c:422:5: */ +var WebPAlphaReplace uintptr /* alpha_processing.c:423:6: */ + +func WebPInitAlphaProcessing(tls *libc.TLS) { /* alpha_processing.c:433:1: */ + for ok := true; ok; ok = (0 != 0) { + if WebPInitAlphaProcessing_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + WebPInitAlphaProcessing_body(tls) + WebPInitAlphaProcessing_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var WebPInitAlphaProcessing_body_last_cpuinfo_used VP8CPUInfo = 0 /* alpha_processing.c:433:1 */ + +func WebPInitAlphaProcessing_body(tls *libc.TLS) { /* alpha_processing.c:433:1: */ + WebPMultARGBRow = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32) + }{WebPMultARGBRow_C})) + WebPMultRow = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, int32) + }{WebPMultRow_C})) + WebPApplyAlphaMultiply4444 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32, int32) + }{ApplyAlphaMultiply_16b_C})) + + WebPPackRGB = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32, int32, uintptr) + }{PackRGB_C})) + WebPApplyAlphaMultiply = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + }{ApplyAlphaMultiply_C})) + WebPDispatchAlpha = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32, int32, uintptr, int32) int32 + }{DispatchAlpha_C})) + WebPDispatchAlphaToGreen = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32, int32, uintptr, int32) + }{DispatchAlphaToGreen_C})) + WebPExtractAlpha = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32, int32, uintptr, int32) int32 + }{ExtractAlpha_C})) + WebPExtractGreen = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) + }{ExtractGreen_C})) + + WebPHasAlpha8b = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32) int32 + }{HasAlpha8b_C})) + WebPHasAlpha32b = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32) int32 + }{HasAlpha32b_C})) + WebPAlphaReplace = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, uint32_t) + }{AlphaReplace_C})) + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if VP8GetCPUInfo != (uintptr(0)) { + } + +} + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Bit writing and boolean coder +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +//------------------------------------------------------------------------------ +// Bit-writing + +type VP8BitWriter1 = struct { + range_ int32_t + value_ int32_t + run_ int32 + nb_bits_ int32 + buf_ uintptr + pos_ size_t + max_pos_ size_t + error_ int32 + _ [4]byte +} /* bit_writer_utils.h:26:9 */ + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Bit writing and boolean coder +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +//------------------------------------------------------------------------------ +// Bit-writing + +type VP8BitWriter = VP8BitWriter1 /* bit_writer_utils.h:26:29 */ + +// return approximate write position (in bits) +func VP8BitWriterPos(tls *libc.TLS, bw uintptr) uint64_t { /* bit_writer_utils.h:56:29: */ + var nb_bits uint64_t = (uint64_t(8 + (*VP8BitWriter)(unsafe.Pointer(bw)).nb_bits_)) // bw->nb_bits_ is <= 0, note + return ((((*VP8BitWriter)(unsafe.Pointer(bw)).pos_ + size_t((*VP8BitWriter)(unsafe.Pointer(bw)).run_)) * uint64(8)) + nb_bits) +} + +// Returns a pointer to the internal buffer. +func VP8BitWriterBuf(tls *libc.TLS, bw uintptr) uintptr { /* bit_writer_utils.h:62:27: */ + return (*VP8BitWriter)(unsafe.Pointer(bw)).buf_ +} + +// Returns the size of the internal buffer. +func VP8BitWriterSize(tls *libc.TLS, bw uintptr) size_t { /* bit_writer_utils.h:66:27: */ + return (*VP8BitWriter)(unsafe.Pointer(bw)).pos_ +} + +//------------------------------------------------------------------------------ +// VP8LBitWriter + +type vp8l_atype_t = uint64_t /* bit_writer_utils.h:74:18 */ // accumulator type +type vp8l_wtype_t = uint32_t /* bit_writer_utils.h:75:18 */ // writing type + +type VP8LBitWriter = struct { + bits_ vp8l_atype_t + used_ int32 + _ [4]byte + buf_ uintptr + cur_ uintptr + end_ uintptr + error_ int32 + _ [4]byte +} /* bit_writer_utils.h:101:3 */ + +func VP8LBitWriterNumBytes(tls *libc.TLS, bw uintptr) size_t { /* bit_writer_utils.h:103:27: */ + return (size_t(((int64((*VP8LBitWriter)(unsafe.Pointer(bw)).cur_) - int64((*VP8LBitWriter)(unsafe.Pointer(bw)).buf_)) / 1) + (int64(((*VP8LBitWriter)(unsafe.Pointer(bw)).used_ + 7) >> 3)))) +} + +// This function writes bits into bytes in increasing addresses (little endian), +// and within a byte least-significant-bit first. +// This function can write up to 32 bits in one go, but VP8LBitReader can only +// read 24 bits max (VP8L_MAX_NUM_BIT_READ). +// VP8LBitWriter's error_ flag is set in case of memory allocation error. +func VP8LPutBits(tls *libc.TLS, bw uintptr, bits uint32_t, n_bits int32) { /* bit_writer_utils.h:133:25: */ + if uint64(unsafe.Sizeof(vp8l_wtype_t(0))) == uint64(4) { + if n_bits > 0 { + if (*VP8LBitWriter)(unsafe.Pointer(bw)).used_ >= 32 { + VP8LPutBitsFlushBits(tls, bw) + } + *(*vp8l_atype_t)(unsafe.Pointer((bw /* &.bits_ */))) |= (vp8l_atype_t(bits) << (*VP8LBitWriter)(unsafe.Pointer(bw)).used_) + *(*int32)(unsafe.Pointer((bw + 8 /* &.used_ */))) += (n_bits) + } + } else { + VP8LPutBitsInternal(tls, bw, bits, n_bits) + } +} + +type VP8RDLevel = uint32 /* vp8i_enc.h:47:3 */ + +// Layout of prediction blocks +// intra 16x16 +// chroma 8x8, two U/V blocks side by side (hence: 16x8 each) +// intra 4x4 + +type score_t = int64_t /* vp8i_enc.h:107:17 */ + +// type used for scores, rate, distortion +// Note that MAX_COST is not the maximum allowed by sizeof(score_t), +// in order to allow overflowing computations. + +// Fun fact: this is the _only_ line where we're actually being lossy and +// discarding bits. +func QUANTDIV(tls *libc.TLS, n uint32_t, iQ uint32_t, B uint32_t) int32 { /* vp8i_enc.h:116:24: */ + return (int32(((n * iQ) + B) >> 17)) +} + +// Uncomment the following to remove token-buffer code: +// #define DISABLE_TOKEN_BUFFER + +// quality below which error-diffusion is enabled + +//------------------------------------------------------------------------------ +// Headers + +type proba_t = uint32_t /* vp8i_enc.h:129:18 */ // 16b + 16b +type ProbaArray = [3][11]uint8_t /* vp8i_enc.h:130:17 */ +type StatsArray = [3][11]proba_t /* vp8i_enc.h:131:17 */ +type CostArray = [3][68]uint16_t /* vp8i_enc.h:132:18 */ +type CostArrayPtr = uintptr /* vp8i_enc.h:133:23 */ // for easy casting +type CostArrayMap = [16][3]uintptr /* vp8i_enc.h:134:23 */ +type LFStats = [4][64]float64 /* vp8i_enc.h:135:16 */ // filter stats + +type VP8Encoder1 = struct { + config_ uintptr + pic_ uintptr + filter_hdr_ VP8EncFilterHeader + segment_hdr_ VP8EncSegmentHeader + profile_ int32 + mb_w_ int32 + mb_h_ int32 + preds_w_ int32 + num_parts_ int32 + bw_ VP8BitWriter + parts_ [8]VP8BitWriter + tokens_ VP8TBuffer + percent_ int32 + has_alpha_ int32 + alpha_data_ uintptr + alpha_data_size_ uint32_t + _ [4]byte + alpha_worker_ WebPWorker + dqm_ [4]VP8SegmentInfo + base_quant_ int32 + alpha_ int32 + uv_alpha_ int32 + dq_y1_dc_ int32 + dq_y2_dc_ int32 + dq_y2_ac_ int32 + dq_uv_dc_ int32 + dq_uv_ac_ int32 + proba_ VP8EncProba + sse_ [4]uint64_t + sse_count_ uint64_t + coded_size_ int32 + residual_bytes_ [3][4]int32 + block_count_ [3]int32 + method_ int32 + rd_opt_level_ VP8RDLevel + max_i4_header_bits_ int32 + mb_header_limit_ int32 + thread_level_ int32 + do_search_ int32 + use_tokens_ int32 + _ [4]byte + mb_info_ uintptr + preds_ uintptr + nz_ uintptr + y_top_ uintptr + uv_top_ uintptr + lf_stats_ uintptr + top_derr_ uintptr +} /* vp8i_enc.h:137:9 */ + +// filter stats + +type VP8Encoder = VP8Encoder1 /* vp8i_enc.h:137:27 */ + +// segment features +type VP8EncSegmentHeader = struct { + num_segments_ int32 + update_map_ int32 + size_ int32 +} /* vp8i_enc.h:145:3 */ + +// Struct collecting all frame-persistent probabilities. +type VP8EncProba = struct { + segments_ [3]uint8_t + skip_proba_ uint8_t + coeffs_ [4][8]ProbaArray + stats_ [4][8]StatsArray + level_cost_ [4][8]CostArray + _ [4]byte + remapped_costs_ [4]CostArrayMap + dirty_ int32 + use_skip_proba_ int32 + nb_skip_ int32 + _ [4]byte +} /* vp8i_enc.h:158:3 */ + +// Filter parameters. Not actually used in the code (we don't perform +// the in-loop filtering), but filled from user's config +type VP8EncFilterHeader = struct { + simple_ int32 + level_ int32 + sharpness_ int32 + i4x4_lf_delta_ int32 +} /* vp8i_enc.h:167:3 */ + +//------------------------------------------------------------------------------ +// Informations about the macroblocks. + +type VP8MBInfo = struct { + _ [0]uint32 + type_ uint8 /* unsigned type_: 2, unsigned uv_mode_: 2, unsigned skip_: 1, unsigned segment_: 2 */ + _ [1]byte + alpha_ uint8_t + _ [1]byte +} /* vp8i_enc.h:179:3 */ + +type VP8Matrix = VP8Matrix1 /* vp8i_enc.h:187:3 */ + +type VP8SegmentInfo = struct { + y1_ VP8Matrix + y2_ VP8Matrix + uv_ VP8Matrix + alpha_ int32 + beta_ int32 + quant_ int32 + fstrength_ int32 + max_edge_ int32 + min_disto_ int32 + lambda_i16_ int32 + lambda_i4_ int32 + lambda_uv_ int32 + lambda_mode_ int32 + lambda_trellis_ int32 + tlambda_ int32 + lambda_trellis_i16_ int32 + lambda_trellis_i4_ int32 + lambda_trellis_uv_ int32 + _ [4]byte + i4_penalty_ score_t +} /* vp8i_enc.h:205:3 */ + +type DError = [2][2]int8_t /* vp8i_enc.h:207:16 */ + +// Handy transient struct to accumulate score and info during RD-optimization +// and mode evaluation. +type VP8ModeScore = struct { + D score_t + SD score_t + H score_t + R score_t + score score_t + y_dc_levels [16]int16_t + y_ac_levels [16][16]int16_t + uv_levels [8][16]int16_t + mode_i16 int32 + modes_i4 [16]uint8_t + mode_uv int32 + nz uint32_t + derr [2][3]int8_t + _ [6]byte +} /* vp8i_enc.h:222:3 */ + +// Iterator structure to iterate through macroblocks, pointing to the +// right neighbouring data (samples, predictions, contexts, ...) +type VP8EncIterator = struct { + x_ int32 + y_ int32 + yuv_in_ uintptr + yuv_out_ uintptr + yuv_out2_ uintptr + yuv_p_ uintptr + enc_ uintptr + mb_ uintptr + bw_ uintptr + preds_ uintptr + nz_ uintptr + i4_boundary_ [37]uint8_t + _ [3]byte + i4_top_ uintptr + i4_ int32 + top_nz_ [9]int32 + left_nz_ [9]int32 + _ [4]byte + bit_count_ [4][3]uint64_t + luma_bits_ uint64_t + uv_bits_ uint64_t + lf_stats_ uintptr + do_trellis_ int32 + count_down_ int32 + count_down0_ int32 + percent0_ int32 + left_derr_ DError + _ [4]byte + top_derr_ uintptr + y_left_ uintptr + u_left_ uintptr + v_left_ uintptr + y_top_ uintptr + uv_top_ uintptr + yuv_left_mem_ [88]uint8_t + yuv_mem_ [3359]uint8_t + _ [1]byte +} /* vp8i_enc.h:265:3 */ + +//------------------------------------------------------------------------------ +// Paginated token buffer + +type VP8Tokens1 = struct{ next_ uintptr } /* vp8i_enc.h:310:9 */ + +// struct details in token.c + +type VP8TBuffer = struct { + pages_ uintptr + last_page_ uintptr + tokens_ uintptr + left_ int32 + page_size_ int32 + error_ int32 + _ [4]byte +} /* vp8i_enc.h:321:3 */ + +//------------------------------------------------------------------------------ + +// On-the-fly info about the current set of residuals. Handy to avoid +// passing zillions of params. +type VP8Residual = VP8Residual1 /* cost_enc.h:27:28 */ + +// Record proba context used. +func VP8RecordStats(tls *libc.TLS, bit int32, stats uintptr) int32 { /* cost_enc.h:45:24: */ + var p proba_t = *(*proba_t)(unsafe.Pointer(stats)) + // An overflow is inbound. Note we handle this at 0xfffe0000u instead of + // 0xffff0000u to make sure p + 1u does not overflow. + if p >= 0xfffe0000 { + p = (((p + 1) >> 1) & 0x7fff7fff) // -> divide the stats by 2. + } + // record bit count (lower 16 bits) and increment total count (upper 16 bits). + p = p + (0x00010000 + uint32(bit)) + *(*proba_t)(unsafe.Pointer(stats)) = p + return bit +} + +// Cost of coding one event with probability 'proba'. +func VP8BitCost(tls *libc.TLS, bit int32, proba uint8_t) int32 { /* cost_enc.h:59:24: */ + if !(bit != 0) { + return int32(VP8EntropyCost[proba]) + } + return int32(VP8EntropyCost[(255 - int32(proba))]) +} + +func VP8LevelCost(tls *libc.TLS, table uintptr, level int32) int32 { /* cost_enc.h:66:24: */ + return (int32(VP8LevelFixedCosts[level]) + + int32(*(*uint16_t)(unsafe.Pointer(table + uintptr(func() int32 { + if level > MAX_VARIABLE_LEVEL { + return MAX_VARIABLE_LEVEL + } + return level + }())*2)))) +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Boolean-cost cost table + +var VP8EntropyCost = [256]uint16_t{ + uint16_t(1792), uint16_t(1792), uint16_t(1792), uint16_t(1536), uint16_t(1536), uint16_t(1408), uint16_t(1366), uint16_t(1280), uint16_t(1280), uint16_t(1216), + uint16_t(1178), uint16_t(1152), uint16_t(1110), uint16_t(1076), uint16_t(1061), uint16_t(1024), uint16_t(1024), uint16_t(992), uint16_t(968), uint16_t(951), + uint16_t(939), uint16_t(911), uint16_t(896), uint16_t(878), uint16_t(871), uint16_t(854), uint16_t(838), uint16_t(820), uint16_t(811), uint16_t(794), + uint16_t(786), uint16_t(768), uint16_t(768), uint16_t(752), uint16_t(740), uint16_t(732), uint16_t(720), uint16_t(709), uint16_t(704), uint16_t(690), + uint16_t(683), uint16_t(672), uint16_t(666), uint16_t(655), uint16_t(647), uint16_t(640), uint16_t(631), uint16_t(622), uint16_t(615), uint16_t(607), + uint16_t(598), uint16_t(592), uint16_t(586), uint16_t(576), uint16_t(572), uint16_t(564), uint16_t(559), uint16_t(555), uint16_t(547), uint16_t(541), + uint16_t(534), uint16_t(528), uint16_t(522), uint16_t(512), uint16_t(512), uint16_t(504), uint16_t(500), uint16_t(494), uint16_t(488), uint16_t(483), + uint16_t(477), uint16_t(473), uint16_t(467), uint16_t(461), uint16_t(458), uint16_t(452), uint16_t(448), uint16_t(443), uint16_t(438), uint16_t(434), + uint16_t(427), uint16_t(424), uint16_t(419), uint16_t(415), uint16_t(410), uint16_t(406), uint16_t(403), uint16_t(399), uint16_t(394), uint16_t(390), + uint16_t(384), uint16_t(384), uint16_t(377), uint16_t(374), uint16_t(370), uint16_t(366), uint16_t(362), uint16_t(359), uint16_t(355), uint16_t(351), + uint16_t(347), uint16_t(342), uint16_t(342), uint16_t(336), uint16_t(333), uint16_t(330), uint16_t(326), uint16_t(323), uint16_t(320), uint16_t(316), + uint16_t(312), uint16_t(308), uint16_t(305), uint16_t(302), uint16_t(299), uint16_t(296), uint16_t(293), uint16_t(288), uint16_t(287), uint16_t(283), + uint16_t(280), uint16_t(277), uint16_t(274), uint16_t(272), uint16_t(268), uint16_t(266), uint16_t(262), uint16_t(256), uint16_t(256), uint16_t(256), + uint16_t(251), uint16_t(248), uint16_t(245), uint16_t(242), uint16_t(240), uint16_t(237), uint16_t(234), uint16_t(232), uint16_t(228), uint16_t(226), + uint16_t(223), uint16_t(221), uint16_t(218), uint16_t(216), uint16_t(214), uint16_t(211), uint16_t(208), uint16_t(205), uint16_t(203), uint16_t(201), + uint16_t(198), uint16_t(196), uint16_t(192), uint16_t(191), uint16_t(188), uint16_t(187), uint16_t(183), uint16_t(181), uint16_t(179), uint16_t(176), + uint16_t(175), uint16_t(171), uint16_t(171), uint16_t(168), uint16_t(165), uint16_t(163), uint16_t(160), uint16_t(159), uint16_t(156), uint16_t(154), + uint16_t(152), uint16_t(150), uint16_t(148), uint16_t(146), uint16_t(144), uint16_t(142), uint16_t(139), uint16_t(138), uint16_t(135), uint16_t(133), + uint16_t(131), uint16_t(128), uint16_t(128), uint16_t(125), uint16_t(123), uint16_t(121), uint16_t(119), uint16_t(117), uint16_t(115), uint16_t(113), + uint16_t(111), uint16_t(110), uint16_t(107), uint16_t(105), uint16_t(103), uint16_t(102), uint16_t(100), uint16_t(98), uint16_t(96), uint16_t(94), + uint16_t(92), uint16_t(91), uint16_t(89), uint16_t(86), uint16_t(86), uint16_t(83), uint16_t(82), uint16_t(80), uint16_t(77), uint16_t(76), + uint16_t(74), uint16_t(73), uint16_t(71), uint16_t(69), uint16_t(67), uint16_t(66), uint16_t(64), uint16_t(63), uint16_t(61), uint16_t(59), + uint16_t(57), uint16_t(55), uint16_t(54), uint16_t(52), uint16_t(51), uint16_t(49), uint16_t(47), uint16_t(46), uint16_t(44), uint16_t(43), + uint16_t(41), uint16_t(40), uint16_t(38), uint16_t(36), uint16_t(35), uint16_t(33), uint16_t(32), uint16_t(30), uint16_t(29), uint16_t(27), + uint16_t(25), uint16_t(24), uint16_t(22), uint16_t(21), uint16_t(19), uint16_t(18), uint16_t(16), uint16_t(15), uint16_t(13), uint16_t(12), + uint16_t(10), uint16_t(9), uint16_t(7), uint16_t(6), uint16_t(4), uint16_t(3), +} /* cost.c:18:16 */ + +//------------------------------------------------------------------------------ +// Level cost tables + +// fixed costs for coding levels, deduce from the coding tree. +// This is only the part that doesn't depend on the probability state. +var VP8LevelFixedCosts = [2048]uint16_t{ + uint16_t(0), uint16_t(256), uint16_t(256), uint16_t(256), uint16_t(256), uint16_t(432), uint16_t(618), uint16_t(630), + uint16_t(731), uint16_t(640), uint16_t(640), uint16_t(828), uint16_t(901), uint16_t(948), uint16_t(1021), uint16_t(1101), + uint16_t(1174), uint16_t(1221), uint16_t(1294), uint16_t(1042), uint16_t(1085), uint16_t(1115), uint16_t(1158), uint16_t(1202), + uint16_t(1245), uint16_t(1275), uint16_t(1318), uint16_t(1337), uint16_t(1380), uint16_t(1410), uint16_t(1453), uint16_t(1497), + uint16_t(1540), uint16_t(1570), uint16_t(1613), uint16_t(1280), uint16_t(1295), uint16_t(1317), uint16_t(1332), uint16_t(1358), + uint16_t(1373), uint16_t(1395), uint16_t(1410), uint16_t(1454), uint16_t(1469), uint16_t(1491), uint16_t(1506), uint16_t(1532), + uint16_t(1547), uint16_t(1569), uint16_t(1584), uint16_t(1601), uint16_t(1616), uint16_t(1638), uint16_t(1653), uint16_t(1679), + uint16_t(1694), uint16_t(1716), uint16_t(1731), uint16_t(1775), uint16_t(1790), uint16_t(1812), uint16_t(1827), uint16_t(1853), + uint16_t(1868), uint16_t(1890), uint16_t(1905), uint16_t(1727), uint16_t(1733), uint16_t(1742), uint16_t(1748), uint16_t(1759), + uint16_t(1765), uint16_t(1774), uint16_t(1780), uint16_t(1800), uint16_t(1806), uint16_t(1815), uint16_t(1821), uint16_t(1832), + uint16_t(1838), uint16_t(1847), uint16_t(1853), uint16_t(1878), uint16_t(1884), uint16_t(1893), uint16_t(1899), uint16_t(1910), + uint16_t(1916), uint16_t(1925), uint16_t(1931), uint16_t(1951), uint16_t(1957), uint16_t(1966), uint16_t(1972), uint16_t(1983), + uint16_t(1989), uint16_t(1998), uint16_t(2004), uint16_t(2027), uint16_t(2033), uint16_t(2042), uint16_t(2048), uint16_t(2059), + uint16_t(2065), uint16_t(2074), uint16_t(2080), uint16_t(2100), uint16_t(2106), uint16_t(2115), uint16_t(2121), uint16_t(2132), + uint16_t(2138), uint16_t(2147), uint16_t(2153), uint16_t(2178), uint16_t(2184), uint16_t(2193), uint16_t(2199), uint16_t(2210), + uint16_t(2216), uint16_t(2225), uint16_t(2231), uint16_t(2251), uint16_t(2257), uint16_t(2266), uint16_t(2272), uint16_t(2283), + uint16_t(2289), uint16_t(2298), uint16_t(2304), uint16_t(2168), uint16_t(2174), uint16_t(2183), uint16_t(2189), uint16_t(2200), + uint16_t(2206), uint16_t(2215), uint16_t(2221), uint16_t(2241), uint16_t(2247), uint16_t(2256), uint16_t(2262), uint16_t(2273), + uint16_t(2279), uint16_t(2288), uint16_t(2294), uint16_t(2319), uint16_t(2325), uint16_t(2334), uint16_t(2340), uint16_t(2351), + uint16_t(2357), uint16_t(2366), uint16_t(2372), uint16_t(2392), uint16_t(2398), uint16_t(2407), uint16_t(2413), uint16_t(2424), + uint16_t(2430), uint16_t(2439), uint16_t(2445), uint16_t(2468), uint16_t(2474), uint16_t(2483), uint16_t(2489), uint16_t(2500), + uint16_t(2506), uint16_t(2515), uint16_t(2521), uint16_t(2541), uint16_t(2547), uint16_t(2556), uint16_t(2562), uint16_t(2573), + uint16_t(2579), uint16_t(2588), uint16_t(2594), uint16_t(2619), uint16_t(2625), uint16_t(2634), uint16_t(2640), uint16_t(2651), + uint16_t(2657), uint16_t(2666), uint16_t(2672), uint16_t(2692), uint16_t(2698), uint16_t(2707), uint16_t(2713), uint16_t(2724), + uint16_t(2730), uint16_t(2739), uint16_t(2745), uint16_t(2540), uint16_t(2546), uint16_t(2555), uint16_t(2561), uint16_t(2572), + uint16_t(2578), uint16_t(2587), uint16_t(2593), uint16_t(2613), uint16_t(2619), uint16_t(2628), uint16_t(2634), uint16_t(2645), + uint16_t(2651), uint16_t(2660), uint16_t(2666), uint16_t(2691), uint16_t(2697), uint16_t(2706), uint16_t(2712), uint16_t(2723), + uint16_t(2729), uint16_t(2738), uint16_t(2744), uint16_t(2764), uint16_t(2770), uint16_t(2779), uint16_t(2785), uint16_t(2796), + uint16_t(2802), uint16_t(2811), uint16_t(2817), uint16_t(2840), uint16_t(2846), uint16_t(2855), uint16_t(2861), uint16_t(2872), + uint16_t(2878), uint16_t(2887), uint16_t(2893), uint16_t(2913), uint16_t(2919), uint16_t(2928), uint16_t(2934), uint16_t(2945), + uint16_t(2951), uint16_t(2960), uint16_t(2966), uint16_t(2991), uint16_t(2997), uint16_t(3006), uint16_t(3012), uint16_t(3023), + uint16_t(3029), uint16_t(3038), uint16_t(3044), uint16_t(3064), uint16_t(3070), uint16_t(3079), uint16_t(3085), uint16_t(3096), + uint16_t(3102), uint16_t(3111), uint16_t(3117), uint16_t(2981), uint16_t(2987), uint16_t(2996), uint16_t(3002), uint16_t(3013), + uint16_t(3019), uint16_t(3028), uint16_t(3034), uint16_t(3054), uint16_t(3060), uint16_t(3069), uint16_t(3075), uint16_t(3086), + uint16_t(3092), uint16_t(3101), uint16_t(3107), uint16_t(3132), uint16_t(3138), uint16_t(3147), uint16_t(3153), uint16_t(3164), + uint16_t(3170), uint16_t(3179), uint16_t(3185), uint16_t(3205), uint16_t(3211), uint16_t(3220), uint16_t(3226), uint16_t(3237), + uint16_t(3243), uint16_t(3252), uint16_t(3258), uint16_t(3281), uint16_t(3287), uint16_t(3296), uint16_t(3302), uint16_t(3313), + uint16_t(3319), uint16_t(3328), uint16_t(3334), uint16_t(3354), uint16_t(3360), uint16_t(3369), uint16_t(3375), uint16_t(3386), + uint16_t(3392), uint16_t(3401), uint16_t(3407), uint16_t(3432), uint16_t(3438), uint16_t(3447), uint16_t(3453), uint16_t(3464), + uint16_t(3470), uint16_t(3479), uint16_t(3485), uint16_t(3505), uint16_t(3511), uint16_t(3520), uint16_t(3526), uint16_t(3537), + uint16_t(3543), uint16_t(3552), uint16_t(3558), uint16_t(2816), uint16_t(2822), uint16_t(2831), uint16_t(2837), uint16_t(2848), + uint16_t(2854), uint16_t(2863), uint16_t(2869), uint16_t(2889), uint16_t(2895), uint16_t(2904), uint16_t(2910), uint16_t(2921), + uint16_t(2927), uint16_t(2936), uint16_t(2942), uint16_t(2967), uint16_t(2973), uint16_t(2982), uint16_t(2988), uint16_t(2999), + uint16_t(3005), uint16_t(3014), uint16_t(3020), uint16_t(3040), uint16_t(3046), uint16_t(3055), uint16_t(3061), uint16_t(3072), + uint16_t(3078), uint16_t(3087), uint16_t(3093), uint16_t(3116), uint16_t(3122), uint16_t(3131), uint16_t(3137), uint16_t(3148), + uint16_t(3154), uint16_t(3163), uint16_t(3169), uint16_t(3189), uint16_t(3195), uint16_t(3204), uint16_t(3210), uint16_t(3221), + uint16_t(3227), uint16_t(3236), uint16_t(3242), uint16_t(3267), uint16_t(3273), uint16_t(3282), uint16_t(3288), uint16_t(3299), + uint16_t(3305), uint16_t(3314), uint16_t(3320), uint16_t(3340), uint16_t(3346), uint16_t(3355), uint16_t(3361), uint16_t(3372), + uint16_t(3378), uint16_t(3387), uint16_t(3393), uint16_t(3257), uint16_t(3263), uint16_t(3272), uint16_t(3278), uint16_t(3289), + uint16_t(3295), uint16_t(3304), uint16_t(3310), uint16_t(3330), uint16_t(3336), uint16_t(3345), uint16_t(3351), uint16_t(3362), + uint16_t(3368), uint16_t(3377), uint16_t(3383), uint16_t(3408), uint16_t(3414), uint16_t(3423), uint16_t(3429), uint16_t(3440), + uint16_t(3446), uint16_t(3455), uint16_t(3461), uint16_t(3481), uint16_t(3487), uint16_t(3496), uint16_t(3502), uint16_t(3513), + uint16_t(3519), uint16_t(3528), uint16_t(3534), uint16_t(3557), uint16_t(3563), uint16_t(3572), uint16_t(3578), uint16_t(3589), + uint16_t(3595), uint16_t(3604), uint16_t(3610), uint16_t(3630), uint16_t(3636), uint16_t(3645), uint16_t(3651), uint16_t(3662), + uint16_t(3668), uint16_t(3677), uint16_t(3683), uint16_t(3708), uint16_t(3714), uint16_t(3723), uint16_t(3729), uint16_t(3740), + uint16_t(3746), uint16_t(3755), uint16_t(3761), uint16_t(3781), uint16_t(3787), uint16_t(3796), uint16_t(3802), uint16_t(3813), + uint16_t(3819), uint16_t(3828), uint16_t(3834), uint16_t(3629), uint16_t(3635), uint16_t(3644), uint16_t(3650), uint16_t(3661), + uint16_t(3667), uint16_t(3676), uint16_t(3682), uint16_t(3702), uint16_t(3708), uint16_t(3717), uint16_t(3723), uint16_t(3734), + uint16_t(3740), uint16_t(3749), uint16_t(3755), uint16_t(3780), uint16_t(3786), uint16_t(3795), uint16_t(3801), uint16_t(3812), + uint16_t(3818), uint16_t(3827), uint16_t(3833), uint16_t(3853), uint16_t(3859), uint16_t(3868), uint16_t(3874), uint16_t(3885), + uint16_t(3891), uint16_t(3900), uint16_t(3906), uint16_t(3929), uint16_t(3935), uint16_t(3944), uint16_t(3950), uint16_t(3961), + uint16_t(3967), uint16_t(3976), uint16_t(3982), uint16_t(4002), uint16_t(4008), uint16_t(4017), uint16_t(4023), uint16_t(4034), + uint16_t(4040), uint16_t(4049), uint16_t(4055), uint16_t(4080), uint16_t(4086), uint16_t(4095), uint16_t(4101), uint16_t(4112), + uint16_t(4118), uint16_t(4127), uint16_t(4133), uint16_t(4153), uint16_t(4159), uint16_t(4168), uint16_t(4174), uint16_t(4185), + uint16_t(4191), uint16_t(4200), uint16_t(4206), uint16_t(4070), uint16_t(4076), uint16_t(4085), uint16_t(4091), uint16_t(4102), + uint16_t(4108), uint16_t(4117), uint16_t(4123), uint16_t(4143), uint16_t(4149), uint16_t(4158), uint16_t(4164), uint16_t(4175), + uint16_t(4181), uint16_t(4190), uint16_t(4196), uint16_t(4221), uint16_t(4227), uint16_t(4236), uint16_t(4242), uint16_t(4253), + uint16_t(4259), uint16_t(4268), uint16_t(4274), uint16_t(4294), uint16_t(4300), uint16_t(4309), uint16_t(4315), uint16_t(4326), + uint16_t(4332), uint16_t(4341), uint16_t(4347), uint16_t(4370), uint16_t(4376), uint16_t(4385), uint16_t(4391), uint16_t(4402), + uint16_t(4408), uint16_t(4417), uint16_t(4423), uint16_t(4443), uint16_t(4449), uint16_t(4458), uint16_t(4464), uint16_t(4475), + uint16_t(4481), uint16_t(4490), uint16_t(4496), uint16_t(4521), uint16_t(4527), uint16_t(4536), uint16_t(4542), uint16_t(4553), + uint16_t(4559), uint16_t(4568), uint16_t(4574), uint16_t(4594), uint16_t(4600), uint16_t(4609), uint16_t(4615), uint16_t(4626), + uint16_t(4632), uint16_t(4641), uint16_t(4647), uint16_t(3515), uint16_t(3521), uint16_t(3530), uint16_t(3536), uint16_t(3547), + uint16_t(3553), uint16_t(3562), uint16_t(3568), uint16_t(3588), uint16_t(3594), uint16_t(3603), uint16_t(3609), uint16_t(3620), + uint16_t(3626), uint16_t(3635), uint16_t(3641), uint16_t(3666), uint16_t(3672), uint16_t(3681), uint16_t(3687), uint16_t(3698), + uint16_t(3704), uint16_t(3713), uint16_t(3719), uint16_t(3739), uint16_t(3745), uint16_t(3754), uint16_t(3760), uint16_t(3771), + uint16_t(3777), uint16_t(3786), uint16_t(3792), uint16_t(3815), uint16_t(3821), uint16_t(3830), uint16_t(3836), uint16_t(3847), + uint16_t(3853), uint16_t(3862), uint16_t(3868), uint16_t(3888), uint16_t(3894), uint16_t(3903), uint16_t(3909), uint16_t(3920), + uint16_t(3926), uint16_t(3935), uint16_t(3941), uint16_t(3966), uint16_t(3972), uint16_t(3981), uint16_t(3987), uint16_t(3998), + uint16_t(4004), uint16_t(4013), uint16_t(4019), uint16_t(4039), uint16_t(4045), uint16_t(4054), uint16_t(4060), uint16_t(4071), + uint16_t(4077), uint16_t(4086), uint16_t(4092), uint16_t(3956), uint16_t(3962), uint16_t(3971), uint16_t(3977), uint16_t(3988), + uint16_t(3994), uint16_t(4003), uint16_t(4009), uint16_t(4029), uint16_t(4035), uint16_t(4044), uint16_t(4050), uint16_t(4061), + uint16_t(4067), uint16_t(4076), uint16_t(4082), uint16_t(4107), uint16_t(4113), uint16_t(4122), uint16_t(4128), uint16_t(4139), + uint16_t(4145), uint16_t(4154), uint16_t(4160), uint16_t(4180), uint16_t(4186), uint16_t(4195), uint16_t(4201), uint16_t(4212), + uint16_t(4218), uint16_t(4227), uint16_t(4233), uint16_t(4256), uint16_t(4262), uint16_t(4271), uint16_t(4277), uint16_t(4288), + uint16_t(4294), uint16_t(4303), uint16_t(4309), uint16_t(4329), uint16_t(4335), uint16_t(4344), uint16_t(4350), uint16_t(4361), + uint16_t(4367), uint16_t(4376), uint16_t(4382), uint16_t(4407), uint16_t(4413), uint16_t(4422), uint16_t(4428), uint16_t(4439), + uint16_t(4445), uint16_t(4454), uint16_t(4460), uint16_t(4480), uint16_t(4486), uint16_t(4495), uint16_t(4501), uint16_t(4512), + uint16_t(4518), uint16_t(4527), uint16_t(4533), uint16_t(4328), uint16_t(4334), uint16_t(4343), uint16_t(4349), uint16_t(4360), + uint16_t(4366), uint16_t(4375), uint16_t(4381), uint16_t(4401), uint16_t(4407), uint16_t(4416), uint16_t(4422), uint16_t(4433), + uint16_t(4439), uint16_t(4448), uint16_t(4454), uint16_t(4479), uint16_t(4485), uint16_t(4494), uint16_t(4500), uint16_t(4511), + uint16_t(4517), uint16_t(4526), uint16_t(4532), uint16_t(4552), uint16_t(4558), uint16_t(4567), uint16_t(4573), uint16_t(4584), + uint16_t(4590), uint16_t(4599), uint16_t(4605), uint16_t(4628), uint16_t(4634), uint16_t(4643), uint16_t(4649), uint16_t(4660), + uint16_t(4666), uint16_t(4675), uint16_t(4681), uint16_t(4701), uint16_t(4707), uint16_t(4716), uint16_t(4722), uint16_t(4733), + uint16_t(4739), uint16_t(4748), uint16_t(4754), uint16_t(4779), uint16_t(4785), uint16_t(4794), uint16_t(4800), uint16_t(4811), + uint16_t(4817), uint16_t(4826), uint16_t(4832), uint16_t(4852), uint16_t(4858), uint16_t(4867), uint16_t(4873), uint16_t(4884), + uint16_t(4890), uint16_t(4899), uint16_t(4905), uint16_t(4769), uint16_t(4775), uint16_t(4784), uint16_t(4790), uint16_t(4801), + uint16_t(4807), uint16_t(4816), uint16_t(4822), uint16_t(4842), uint16_t(4848), uint16_t(4857), uint16_t(4863), uint16_t(4874), + uint16_t(4880), uint16_t(4889), uint16_t(4895), uint16_t(4920), uint16_t(4926), uint16_t(4935), uint16_t(4941), uint16_t(4952), + uint16_t(4958), uint16_t(4967), uint16_t(4973), uint16_t(4993), uint16_t(4999), uint16_t(5008), uint16_t(5014), uint16_t(5025), + uint16_t(5031), uint16_t(5040), uint16_t(5046), uint16_t(5069), uint16_t(5075), uint16_t(5084), uint16_t(5090), uint16_t(5101), + uint16_t(5107), uint16_t(5116), uint16_t(5122), uint16_t(5142), uint16_t(5148), uint16_t(5157), uint16_t(5163), uint16_t(5174), + uint16_t(5180), uint16_t(5189), uint16_t(5195), uint16_t(5220), uint16_t(5226), uint16_t(5235), uint16_t(5241), uint16_t(5252), + uint16_t(5258), uint16_t(5267), uint16_t(5273), uint16_t(5293), uint16_t(5299), uint16_t(5308), uint16_t(5314), uint16_t(5325), + uint16_t(5331), uint16_t(5340), uint16_t(5346), uint16_t(4604), uint16_t(4610), uint16_t(4619), uint16_t(4625), uint16_t(4636), + uint16_t(4642), uint16_t(4651), uint16_t(4657), uint16_t(4677), uint16_t(4683), uint16_t(4692), uint16_t(4698), uint16_t(4709), + uint16_t(4715), uint16_t(4724), uint16_t(4730), uint16_t(4755), uint16_t(4761), uint16_t(4770), uint16_t(4776), uint16_t(4787), + uint16_t(4793), uint16_t(4802), uint16_t(4808), uint16_t(4828), uint16_t(4834), uint16_t(4843), uint16_t(4849), uint16_t(4860), + uint16_t(4866), uint16_t(4875), uint16_t(4881), uint16_t(4904), uint16_t(4910), uint16_t(4919), uint16_t(4925), uint16_t(4936), + uint16_t(4942), uint16_t(4951), uint16_t(4957), uint16_t(4977), uint16_t(4983), uint16_t(4992), uint16_t(4998), uint16_t(5009), + uint16_t(5015), uint16_t(5024), uint16_t(5030), uint16_t(5055), uint16_t(5061), uint16_t(5070), uint16_t(5076), uint16_t(5087), + uint16_t(5093), uint16_t(5102), uint16_t(5108), uint16_t(5128), uint16_t(5134), uint16_t(5143), uint16_t(5149), uint16_t(5160), + uint16_t(5166), uint16_t(5175), uint16_t(5181), uint16_t(5045), uint16_t(5051), uint16_t(5060), uint16_t(5066), uint16_t(5077), + uint16_t(5083), uint16_t(5092), uint16_t(5098), uint16_t(5118), uint16_t(5124), uint16_t(5133), uint16_t(5139), uint16_t(5150), + uint16_t(5156), uint16_t(5165), uint16_t(5171), uint16_t(5196), uint16_t(5202), uint16_t(5211), uint16_t(5217), uint16_t(5228), + uint16_t(5234), uint16_t(5243), uint16_t(5249), uint16_t(5269), uint16_t(5275), uint16_t(5284), uint16_t(5290), uint16_t(5301), + uint16_t(5307), uint16_t(5316), uint16_t(5322), uint16_t(5345), uint16_t(5351), uint16_t(5360), uint16_t(5366), uint16_t(5377), + uint16_t(5383), uint16_t(5392), uint16_t(5398), uint16_t(5418), uint16_t(5424), uint16_t(5433), uint16_t(5439), uint16_t(5450), + uint16_t(5456), uint16_t(5465), uint16_t(5471), uint16_t(5496), uint16_t(5502), uint16_t(5511), uint16_t(5517), uint16_t(5528), + uint16_t(5534), uint16_t(5543), uint16_t(5549), uint16_t(5569), uint16_t(5575), uint16_t(5584), uint16_t(5590), uint16_t(5601), + uint16_t(5607), uint16_t(5616), uint16_t(5622), uint16_t(5417), uint16_t(5423), uint16_t(5432), uint16_t(5438), uint16_t(5449), + uint16_t(5455), uint16_t(5464), uint16_t(5470), uint16_t(5490), uint16_t(5496), uint16_t(5505), uint16_t(5511), uint16_t(5522), + uint16_t(5528), uint16_t(5537), uint16_t(5543), uint16_t(5568), uint16_t(5574), uint16_t(5583), uint16_t(5589), uint16_t(5600), + uint16_t(5606), uint16_t(5615), uint16_t(5621), uint16_t(5641), uint16_t(5647), uint16_t(5656), uint16_t(5662), uint16_t(5673), + uint16_t(5679), uint16_t(5688), uint16_t(5694), uint16_t(5717), uint16_t(5723), uint16_t(5732), uint16_t(5738), uint16_t(5749), + uint16_t(5755), uint16_t(5764), uint16_t(5770), uint16_t(5790), uint16_t(5796), uint16_t(5805), uint16_t(5811), uint16_t(5822), + uint16_t(5828), uint16_t(5837), uint16_t(5843), uint16_t(5868), uint16_t(5874), uint16_t(5883), uint16_t(5889), uint16_t(5900), + uint16_t(5906), uint16_t(5915), uint16_t(5921), uint16_t(5941), uint16_t(5947), uint16_t(5956), uint16_t(5962), uint16_t(5973), + uint16_t(5979), uint16_t(5988), uint16_t(5994), uint16_t(5858), uint16_t(5864), uint16_t(5873), uint16_t(5879), uint16_t(5890), + uint16_t(5896), uint16_t(5905), uint16_t(5911), uint16_t(5931), uint16_t(5937), uint16_t(5946), uint16_t(5952), uint16_t(5963), + uint16_t(5969), uint16_t(5978), uint16_t(5984), uint16_t(6009), uint16_t(6015), uint16_t(6024), uint16_t(6030), uint16_t(6041), + uint16_t(6047), uint16_t(6056), uint16_t(6062), uint16_t(6082), uint16_t(6088), uint16_t(6097), uint16_t(6103), uint16_t(6114), + uint16_t(6120), uint16_t(6129), uint16_t(6135), uint16_t(6158), uint16_t(6164), uint16_t(6173), uint16_t(6179), uint16_t(6190), + uint16_t(6196), uint16_t(6205), uint16_t(6211), uint16_t(6231), uint16_t(6237), uint16_t(6246), uint16_t(6252), uint16_t(6263), + uint16_t(6269), uint16_t(6278), uint16_t(6284), uint16_t(6309), uint16_t(6315), uint16_t(6324), uint16_t(6330), uint16_t(6341), + uint16_t(6347), uint16_t(6356), uint16_t(6362), uint16_t(6382), uint16_t(6388), uint16_t(6397), uint16_t(6403), uint16_t(6414), + uint16_t(6420), uint16_t(6429), uint16_t(6435), uint16_t(3515), uint16_t(3521), uint16_t(3530), uint16_t(3536), uint16_t(3547), + uint16_t(3553), uint16_t(3562), uint16_t(3568), uint16_t(3588), uint16_t(3594), uint16_t(3603), uint16_t(3609), uint16_t(3620), + uint16_t(3626), uint16_t(3635), uint16_t(3641), uint16_t(3666), uint16_t(3672), uint16_t(3681), uint16_t(3687), uint16_t(3698), + uint16_t(3704), uint16_t(3713), uint16_t(3719), uint16_t(3739), uint16_t(3745), uint16_t(3754), uint16_t(3760), uint16_t(3771), + uint16_t(3777), uint16_t(3786), uint16_t(3792), uint16_t(3815), uint16_t(3821), uint16_t(3830), uint16_t(3836), uint16_t(3847), + uint16_t(3853), uint16_t(3862), uint16_t(3868), uint16_t(3888), uint16_t(3894), uint16_t(3903), uint16_t(3909), uint16_t(3920), + uint16_t(3926), uint16_t(3935), uint16_t(3941), uint16_t(3966), uint16_t(3972), uint16_t(3981), uint16_t(3987), uint16_t(3998), + uint16_t(4004), uint16_t(4013), uint16_t(4019), uint16_t(4039), uint16_t(4045), uint16_t(4054), uint16_t(4060), uint16_t(4071), + uint16_t(4077), uint16_t(4086), uint16_t(4092), uint16_t(3956), uint16_t(3962), uint16_t(3971), uint16_t(3977), uint16_t(3988), + uint16_t(3994), uint16_t(4003), uint16_t(4009), uint16_t(4029), uint16_t(4035), uint16_t(4044), uint16_t(4050), uint16_t(4061), + uint16_t(4067), uint16_t(4076), uint16_t(4082), uint16_t(4107), uint16_t(4113), uint16_t(4122), uint16_t(4128), uint16_t(4139), + uint16_t(4145), uint16_t(4154), uint16_t(4160), uint16_t(4180), uint16_t(4186), uint16_t(4195), uint16_t(4201), uint16_t(4212), + uint16_t(4218), uint16_t(4227), uint16_t(4233), uint16_t(4256), uint16_t(4262), uint16_t(4271), uint16_t(4277), uint16_t(4288), + uint16_t(4294), uint16_t(4303), uint16_t(4309), uint16_t(4329), uint16_t(4335), uint16_t(4344), uint16_t(4350), uint16_t(4361), + uint16_t(4367), uint16_t(4376), uint16_t(4382), uint16_t(4407), uint16_t(4413), uint16_t(4422), uint16_t(4428), uint16_t(4439), + uint16_t(4445), uint16_t(4454), uint16_t(4460), uint16_t(4480), uint16_t(4486), uint16_t(4495), uint16_t(4501), uint16_t(4512), + uint16_t(4518), uint16_t(4527), uint16_t(4533), uint16_t(4328), uint16_t(4334), uint16_t(4343), uint16_t(4349), uint16_t(4360), + uint16_t(4366), uint16_t(4375), uint16_t(4381), uint16_t(4401), uint16_t(4407), uint16_t(4416), uint16_t(4422), uint16_t(4433), + uint16_t(4439), uint16_t(4448), uint16_t(4454), uint16_t(4479), uint16_t(4485), uint16_t(4494), uint16_t(4500), uint16_t(4511), + uint16_t(4517), uint16_t(4526), uint16_t(4532), uint16_t(4552), uint16_t(4558), uint16_t(4567), uint16_t(4573), uint16_t(4584), + uint16_t(4590), uint16_t(4599), uint16_t(4605), uint16_t(4628), uint16_t(4634), uint16_t(4643), uint16_t(4649), uint16_t(4660), + uint16_t(4666), uint16_t(4675), uint16_t(4681), uint16_t(4701), uint16_t(4707), uint16_t(4716), uint16_t(4722), uint16_t(4733), + uint16_t(4739), uint16_t(4748), uint16_t(4754), uint16_t(4779), uint16_t(4785), uint16_t(4794), uint16_t(4800), uint16_t(4811), + uint16_t(4817), uint16_t(4826), uint16_t(4832), uint16_t(4852), uint16_t(4858), uint16_t(4867), uint16_t(4873), uint16_t(4884), + uint16_t(4890), uint16_t(4899), uint16_t(4905), uint16_t(4769), uint16_t(4775), uint16_t(4784), uint16_t(4790), uint16_t(4801), + uint16_t(4807), uint16_t(4816), uint16_t(4822), uint16_t(4842), uint16_t(4848), uint16_t(4857), uint16_t(4863), uint16_t(4874), + uint16_t(4880), uint16_t(4889), uint16_t(4895), uint16_t(4920), uint16_t(4926), uint16_t(4935), uint16_t(4941), uint16_t(4952), + uint16_t(4958), uint16_t(4967), uint16_t(4973), uint16_t(4993), uint16_t(4999), uint16_t(5008), uint16_t(5014), uint16_t(5025), + uint16_t(5031), uint16_t(5040), uint16_t(5046), uint16_t(5069), uint16_t(5075), uint16_t(5084), uint16_t(5090), uint16_t(5101), + uint16_t(5107), uint16_t(5116), uint16_t(5122), uint16_t(5142), uint16_t(5148), uint16_t(5157), uint16_t(5163), uint16_t(5174), + uint16_t(5180), uint16_t(5189), uint16_t(5195), uint16_t(5220), uint16_t(5226), uint16_t(5235), uint16_t(5241), uint16_t(5252), + uint16_t(5258), uint16_t(5267), uint16_t(5273), uint16_t(5293), uint16_t(5299), uint16_t(5308), uint16_t(5314), uint16_t(5325), + uint16_t(5331), uint16_t(5340), uint16_t(5346), uint16_t(4604), uint16_t(4610), uint16_t(4619), uint16_t(4625), uint16_t(4636), + uint16_t(4642), uint16_t(4651), uint16_t(4657), uint16_t(4677), uint16_t(4683), uint16_t(4692), uint16_t(4698), uint16_t(4709), + uint16_t(4715), uint16_t(4724), uint16_t(4730), uint16_t(4755), uint16_t(4761), uint16_t(4770), uint16_t(4776), uint16_t(4787), + uint16_t(4793), uint16_t(4802), uint16_t(4808), uint16_t(4828), uint16_t(4834), uint16_t(4843), uint16_t(4849), uint16_t(4860), + uint16_t(4866), uint16_t(4875), uint16_t(4881), uint16_t(4904), uint16_t(4910), uint16_t(4919), uint16_t(4925), uint16_t(4936), + uint16_t(4942), uint16_t(4951), uint16_t(4957), uint16_t(4977), uint16_t(4983), uint16_t(4992), uint16_t(4998), uint16_t(5009), + uint16_t(5015), uint16_t(5024), uint16_t(5030), uint16_t(5055), uint16_t(5061), uint16_t(5070), uint16_t(5076), uint16_t(5087), + uint16_t(5093), uint16_t(5102), uint16_t(5108), uint16_t(5128), uint16_t(5134), uint16_t(5143), uint16_t(5149), uint16_t(5160), + uint16_t(5166), uint16_t(5175), uint16_t(5181), uint16_t(5045), uint16_t(5051), uint16_t(5060), uint16_t(5066), uint16_t(5077), + uint16_t(5083), uint16_t(5092), uint16_t(5098), uint16_t(5118), uint16_t(5124), uint16_t(5133), uint16_t(5139), uint16_t(5150), + uint16_t(5156), uint16_t(5165), uint16_t(5171), uint16_t(5196), uint16_t(5202), uint16_t(5211), uint16_t(5217), uint16_t(5228), + uint16_t(5234), uint16_t(5243), uint16_t(5249), uint16_t(5269), uint16_t(5275), uint16_t(5284), uint16_t(5290), uint16_t(5301), + uint16_t(5307), uint16_t(5316), uint16_t(5322), uint16_t(5345), uint16_t(5351), uint16_t(5360), uint16_t(5366), uint16_t(5377), + uint16_t(5383), uint16_t(5392), uint16_t(5398), uint16_t(5418), uint16_t(5424), uint16_t(5433), uint16_t(5439), uint16_t(5450), + uint16_t(5456), uint16_t(5465), uint16_t(5471), uint16_t(5496), uint16_t(5502), uint16_t(5511), uint16_t(5517), uint16_t(5528), + uint16_t(5534), uint16_t(5543), uint16_t(5549), uint16_t(5569), uint16_t(5575), uint16_t(5584), uint16_t(5590), uint16_t(5601), + uint16_t(5607), uint16_t(5616), uint16_t(5622), uint16_t(5417), uint16_t(5423), uint16_t(5432), uint16_t(5438), uint16_t(5449), + uint16_t(5455), uint16_t(5464), uint16_t(5470), uint16_t(5490), uint16_t(5496), uint16_t(5505), uint16_t(5511), uint16_t(5522), + uint16_t(5528), uint16_t(5537), uint16_t(5543), uint16_t(5568), uint16_t(5574), uint16_t(5583), uint16_t(5589), uint16_t(5600), + uint16_t(5606), uint16_t(5615), uint16_t(5621), uint16_t(5641), uint16_t(5647), uint16_t(5656), uint16_t(5662), uint16_t(5673), + uint16_t(5679), uint16_t(5688), uint16_t(5694), uint16_t(5717), uint16_t(5723), uint16_t(5732), uint16_t(5738), uint16_t(5749), + uint16_t(5755), uint16_t(5764), uint16_t(5770), uint16_t(5790), uint16_t(5796), uint16_t(5805), uint16_t(5811), uint16_t(5822), + uint16_t(5828), uint16_t(5837), uint16_t(5843), uint16_t(5868), uint16_t(5874), uint16_t(5883), uint16_t(5889), uint16_t(5900), + uint16_t(5906), uint16_t(5915), uint16_t(5921), uint16_t(5941), uint16_t(5947), uint16_t(5956), uint16_t(5962), uint16_t(5973), + uint16_t(5979), uint16_t(5988), uint16_t(5994), uint16_t(5858), uint16_t(5864), uint16_t(5873), uint16_t(5879), uint16_t(5890), + uint16_t(5896), uint16_t(5905), uint16_t(5911), uint16_t(5931), uint16_t(5937), uint16_t(5946), uint16_t(5952), uint16_t(5963), + uint16_t(5969), uint16_t(5978), uint16_t(5984), uint16_t(6009), uint16_t(6015), uint16_t(6024), uint16_t(6030), uint16_t(6041), + uint16_t(6047), uint16_t(6056), uint16_t(6062), uint16_t(6082), uint16_t(6088), uint16_t(6097), uint16_t(6103), uint16_t(6114), + uint16_t(6120), uint16_t(6129), uint16_t(6135), uint16_t(6158), uint16_t(6164), uint16_t(6173), uint16_t(6179), uint16_t(6190), + uint16_t(6196), uint16_t(6205), uint16_t(6211), uint16_t(6231), uint16_t(6237), uint16_t(6246), uint16_t(6252), uint16_t(6263), + uint16_t(6269), uint16_t(6278), uint16_t(6284), uint16_t(6309), uint16_t(6315), uint16_t(6324), uint16_t(6330), uint16_t(6341), + uint16_t(6347), uint16_t(6356), uint16_t(6362), uint16_t(6382), uint16_t(6388), uint16_t(6397), uint16_t(6403), uint16_t(6414), + uint16_t(6420), uint16_t(6429), uint16_t(6435), uint16_t(5303), uint16_t(5309), uint16_t(5318), uint16_t(5324), uint16_t(5335), + uint16_t(5341), uint16_t(5350), uint16_t(5356), uint16_t(5376), uint16_t(5382), uint16_t(5391), uint16_t(5397), uint16_t(5408), + uint16_t(5414), uint16_t(5423), uint16_t(5429), uint16_t(5454), uint16_t(5460), uint16_t(5469), uint16_t(5475), uint16_t(5486), + uint16_t(5492), uint16_t(5501), uint16_t(5507), uint16_t(5527), uint16_t(5533), uint16_t(5542), uint16_t(5548), uint16_t(5559), + uint16_t(5565), uint16_t(5574), uint16_t(5580), uint16_t(5603), uint16_t(5609), uint16_t(5618), uint16_t(5624), uint16_t(5635), + uint16_t(5641), uint16_t(5650), uint16_t(5656), uint16_t(5676), uint16_t(5682), uint16_t(5691), uint16_t(5697), uint16_t(5708), + uint16_t(5714), uint16_t(5723), uint16_t(5729), uint16_t(5754), uint16_t(5760), uint16_t(5769), uint16_t(5775), uint16_t(5786), + uint16_t(5792), uint16_t(5801), uint16_t(5807), uint16_t(5827), uint16_t(5833), uint16_t(5842), uint16_t(5848), uint16_t(5859), + uint16_t(5865), uint16_t(5874), uint16_t(5880), uint16_t(5744), uint16_t(5750), uint16_t(5759), uint16_t(5765), uint16_t(5776), + uint16_t(5782), uint16_t(5791), uint16_t(5797), uint16_t(5817), uint16_t(5823), uint16_t(5832), uint16_t(5838), uint16_t(5849), + uint16_t(5855), uint16_t(5864), uint16_t(5870), uint16_t(5895), uint16_t(5901), uint16_t(5910), uint16_t(5916), uint16_t(5927), + uint16_t(5933), uint16_t(5942), uint16_t(5948), uint16_t(5968), uint16_t(5974), uint16_t(5983), uint16_t(5989), uint16_t(6000), + uint16_t(6006), uint16_t(6015), uint16_t(6021), uint16_t(6044), uint16_t(6050), uint16_t(6059), uint16_t(6065), uint16_t(6076), + uint16_t(6082), uint16_t(6091), uint16_t(6097), uint16_t(6117), uint16_t(6123), uint16_t(6132), uint16_t(6138), uint16_t(6149), + uint16_t(6155), uint16_t(6164), uint16_t(6170), uint16_t(6195), uint16_t(6201), uint16_t(6210), uint16_t(6216), uint16_t(6227), + uint16_t(6233), uint16_t(6242), uint16_t(6248), uint16_t(6268), uint16_t(6274), uint16_t(6283), uint16_t(6289), uint16_t(6300), + uint16_t(6306), uint16_t(6315), uint16_t(6321), uint16_t(6116), uint16_t(6122), uint16_t(6131), uint16_t(6137), uint16_t(6148), + uint16_t(6154), uint16_t(6163), uint16_t(6169), uint16_t(6189), uint16_t(6195), uint16_t(6204), uint16_t(6210), uint16_t(6221), + uint16_t(6227), uint16_t(6236), uint16_t(6242), uint16_t(6267), uint16_t(6273), uint16_t(6282), uint16_t(6288), uint16_t(6299), + uint16_t(6305), uint16_t(6314), uint16_t(6320), uint16_t(6340), uint16_t(6346), uint16_t(6355), uint16_t(6361), uint16_t(6372), + uint16_t(6378), uint16_t(6387), uint16_t(6393), uint16_t(6416), uint16_t(6422), uint16_t(6431), uint16_t(6437), uint16_t(6448), + uint16_t(6454), uint16_t(6463), uint16_t(6469), uint16_t(6489), uint16_t(6495), uint16_t(6504), uint16_t(6510), uint16_t(6521), + uint16_t(6527), uint16_t(6536), uint16_t(6542), uint16_t(6567), uint16_t(6573), uint16_t(6582), uint16_t(6588), uint16_t(6599), + uint16_t(6605), uint16_t(6614), uint16_t(6620), uint16_t(6640), uint16_t(6646), uint16_t(6655), uint16_t(6661), uint16_t(6672), + uint16_t(6678), uint16_t(6687), uint16_t(6693), uint16_t(6557), uint16_t(6563), uint16_t(6572), uint16_t(6578), uint16_t(6589), + uint16_t(6595), uint16_t(6604), uint16_t(6610), uint16_t(6630), uint16_t(6636), uint16_t(6645), uint16_t(6651), uint16_t(6662), + uint16_t(6668), uint16_t(6677), uint16_t(6683), uint16_t(6708), uint16_t(6714), uint16_t(6723), uint16_t(6729), uint16_t(6740), + uint16_t(6746), uint16_t(6755), uint16_t(6761), uint16_t(6781), uint16_t(6787), uint16_t(6796), uint16_t(6802), uint16_t(6813), + uint16_t(6819), uint16_t(6828), uint16_t(6834), uint16_t(6857), uint16_t(6863), uint16_t(6872), uint16_t(6878), uint16_t(6889), + uint16_t(6895), uint16_t(6904), uint16_t(6910), uint16_t(6930), uint16_t(6936), uint16_t(6945), uint16_t(6951), uint16_t(6962), + uint16_t(6968), uint16_t(6977), uint16_t(6983), uint16_t(7008), uint16_t(7014), uint16_t(7023), uint16_t(7029), uint16_t(7040), + uint16_t(7046), uint16_t(7055), uint16_t(7061), uint16_t(7081), uint16_t(7087), uint16_t(7096), uint16_t(7102), uint16_t(7113), + uint16_t(7119), uint16_t(7128), uint16_t(7134), uint16_t(6392), uint16_t(6398), uint16_t(6407), uint16_t(6413), uint16_t(6424), + uint16_t(6430), uint16_t(6439), uint16_t(6445), uint16_t(6465), uint16_t(6471), uint16_t(6480), uint16_t(6486), uint16_t(6497), + uint16_t(6503), uint16_t(6512), uint16_t(6518), uint16_t(6543), uint16_t(6549), uint16_t(6558), uint16_t(6564), uint16_t(6575), + uint16_t(6581), uint16_t(6590), uint16_t(6596), uint16_t(6616), uint16_t(6622), uint16_t(6631), uint16_t(6637), uint16_t(6648), + uint16_t(6654), uint16_t(6663), uint16_t(6669), uint16_t(6692), uint16_t(6698), uint16_t(6707), uint16_t(6713), uint16_t(6724), + uint16_t(6730), uint16_t(6739), uint16_t(6745), uint16_t(6765), uint16_t(6771), uint16_t(6780), uint16_t(6786), uint16_t(6797), + uint16_t(6803), uint16_t(6812), uint16_t(6818), uint16_t(6843), uint16_t(6849), uint16_t(6858), uint16_t(6864), uint16_t(6875), + uint16_t(6881), uint16_t(6890), uint16_t(6896), uint16_t(6916), uint16_t(6922), uint16_t(6931), uint16_t(6937), uint16_t(6948), + uint16_t(6954), uint16_t(6963), uint16_t(6969), uint16_t(6833), uint16_t(6839), uint16_t(6848), uint16_t(6854), uint16_t(6865), + uint16_t(6871), uint16_t(6880), uint16_t(6886), uint16_t(6906), uint16_t(6912), uint16_t(6921), uint16_t(6927), uint16_t(6938), + uint16_t(6944), uint16_t(6953), uint16_t(6959), uint16_t(6984), uint16_t(6990), uint16_t(6999), uint16_t(7005), uint16_t(7016), + uint16_t(7022), uint16_t(7031), uint16_t(7037), uint16_t(7057), uint16_t(7063), uint16_t(7072), uint16_t(7078), uint16_t(7089), + uint16_t(7095), uint16_t(7104), uint16_t(7110), uint16_t(7133), uint16_t(7139), uint16_t(7148), uint16_t(7154), uint16_t(7165), + uint16_t(7171), uint16_t(7180), uint16_t(7186), uint16_t(7206), uint16_t(7212), uint16_t(7221), uint16_t(7227), uint16_t(7238), + uint16_t(7244), uint16_t(7253), uint16_t(7259), uint16_t(7284), uint16_t(7290), uint16_t(7299), uint16_t(7305), uint16_t(7316), + uint16_t(7322), uint16_t(7331), uint16_t(7337), uint16_t(7357), uint16_t(7363), uint16_t(7372), uint16_t(7378), uint16_t(7389), + uint16_t(7395), uint16_t(7404), uint16_t(7410), uint16_t(7205), uint16_t(7211), uint16_t(7220), uint16_t(7226), uint16_t(7237), + uint16_t(7243), uint16_t(7252), uint16_t(7258), uint16_t(7278), uint16_t(7284), uint16_t(7293), uint16_t(7299), uint16_t(7310), + uint16_t(7316), uint16_t(7325), uint16_t(7331), uint16_t(7356), uint16_t(7362), uint16_t(7371), uint16_t(7377), uint16_t(7388), + uint16_t(7394), uint16_t(7403), uint16_t(7409), uint16_t(7429), uint16_t(7435), uint16_t(7444), uint16_t(7450), uint16_t(7461), + uint16_t(7467), uint16_t(7476), uint16_t(7482), uint16_t(7505), uint16_t(7511), uint16_t(7520), uint16_t(7526), uint16_t(7537), + uint16_t(7543), uint16_t(7552), uint16_t(7558), uint16_t(7578), uint16_t(7584), uint16_t(7593), uint16_t(7599), uint16_t(7610), + uint16_t(7616), uint16_t(7625), uint16_t(7631), uint16_t(7656), uint16_t(7662), uint16_t(7671), uint16_t(7677), uint16_t(7688), + uint16_t(7694), uint16_t(7703), uint16_t(7709), uint16_t(7729), uint16_t(7735), uint16_t(7744), uint16_t(7750), uint16_t(7761), +} /* cost.c:52:16 */ + +//------------------------------------------------------------------------------ +// Tables for level coding + +var VP8EncBands = [17]uint8_t{ + uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(6), uint8_t(4), uint8_t(5), uint8_t(6), uint8_t(6), uint8_t(6), uint8_t(6), uint8_t(6), uint8_t(6), uint8_t(6), uint8_t(6), uint8_t(7), + uint8_t(0), // sentinel +} /* cost.c:314:15 */ + +//------------------------------------------------------------------------------ +// Mode costs + +func GetResidualCost_C(tls *libc.TLS, ctx0 int32, res uintptr) int32 { /* cost.c:322:12: */ + var n int32 = (*VP8Residual)(unsafe.Pointer(res)).first + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + var p0 int32 = int32(*(*uint8_t)(unsafe.Pointer((((*VP8Residual)(unsafe.Pointer(res)).prob + uintptr(n)*33) + uintptr(ctx0)*11)))) + var costs CostArrayPtr = (*VP8Residual)(unsafe.Pointer(res)).costs + var t uintptr = *(*uintptr)(unsafe.Pointer((costs + uintptr(n)*24) + uintptr(ctx0)*8)) + // bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 + // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll + // be missing during the loop. + var cost int32 + if ctx0 == 0 { + cost = VP8BitCost(tls, 1, uint8(p0)) + } else { + cost = 0 + } + + if (*VP8Residual)(unsafe.Pointer(res)).last < 0 { + return VP8BitCost(tls, 0, uint8(p0)) + } + for ; n < (*VP8Residual)(unsafe.Pointer(res)).last; n++ { + var v int32 = libc.Xabs(tls, int32(*(*int16_t)(unsafe.Pointer((*VP8Residual)(unsafe.Pointer(res)).coeffs + uintptr(n)*2)))) + var ctx int32 + if v >= 2 { + ctx = 2 + } else { + ctx = v + } + cost = cost + (VP8LevelCost(tls, t, v)) + t = *(*uintptr)(unsafe.Pointer((costs + uintptr((n+1))*24) + uintptr(ctx)*8)) + } + // Last coefficient is always non-zero + { + var v int32 = libc.Xabs(tls, int32(*(*int16_t)(unsafe.Pointer((*VP8Residual)(unsafe.Pointer(res)).coeffs + uintptr(n)*2)))) + + cost = cost + (VP8LevelCost(tls, t, v)) + if n < 15 { + var b int32 = int32(VP8EncBands[(n + 1)]) + var ctx int32 + if v == 1 { + ctx = 1 + } else { + ctx = 2 + } + var last_p0 int32 = int32(*(*uint8_t)(unsafe.Pointer((((*VP8Residual)(unsafe.Pointer(res)).prob + uintptr(b)*33) + uintptr(ctx)*11)))) + cost = cost + (VP8BitCost(tls, 0, uint8(last_p0))) + } + + } + return cost +} + +func SetResidualCoeffs_C(tls *libc.TLS, coeffs uintptr, res uintptr) { /* cost.c:357:13: */ + var n int32 + (*VP8Residual)(unsafe.Pointer(res)).last = -1 + + for n = 15; n >= 0; n-- { + if *(*int16_t)(unsafe.Pointer(coeffs + uintptr(n)*2)) != 0 { + (*VP8Residual)(unsafe.Pointer(res)).last = n + break + } + } + (*VP8Residual)(unsafe.Pointer(res)).coeffs = coeffs +} + +//------------------------------------------------------------------------------ +// init function + +var VP8GetResidualCost VP8GetResidualCostFunc /* cost.c:374:24: */ +var VP8SetResidualCoeffs VP8SetResidualCoeffsFunc /* cost.c:375:26: */ + +func VP8EncDspCostInit(tls *libc.TLS) { /* cost.c:382:1: */ + for ok := true; ok; ok = (0 != 0) { + if VP8EncDspCostInit_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + VP8EncDspCostInit_body(tls) + VP8EncDspCostInit_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var VP8EncDspCostInit_body_last_cpuinfo_used VP8CPUInfo = 0 /* cost.c:382:1 */ + +func VP8EncDspCostInit_body(tls *libc.TLS) { /* cost.c:382:1: */ + VP8GetResidualCost = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, int32, uintptr) int32 + }{GetResidualCost_C})) + VP8SetResidualCoeffs = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) + }{SetResidualCoeffs_C})) + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if VP8GetCPUInfo != (uintptr(0)) { + } +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// SSE2 detection. +// + +// apple/darwin gcc-4.0.1 defines __PIC__, but not __pic__ with -fPIC. +func GetCPUInfo(tls *libc.TLS, cpu_info uintptr, info_type int32) { /* cpu.c:52:25: */ + panic(`cpu.c:53:3: assembler statements not supported`) +} + +// NaCl has no support for xgetbv or the raw opcode. +func xgetbv(tls *libc.TLS) uint64_t { /* cpu.c:74:29: */ + var ecx uint32_t = uint32_t(0) + _ = ecx + var eax uint32_t + var edx uint32_t + panic(`cpu.c:78:3: assembler statements not supported`) + return ((uint64_t(edx) << 32) | uint64_t(eax)) +} + +// helper function for run-time detection of slow SSSE3 platforms +func CheckSlowModel(tls *libc.TLS, info int32) int32 { /* cpu.c:106:12: */ + var model uint32_t = (uint32_t(((info & 0xf0000) >> 12) | ((info >> 4) & 0xf))) + var family uint32_t = (uint32_t((info >> 8) & 0xf)) + if family == uint32_t(0x06) { + var i size_t + for i = uint64(0); i < (uint64(unsafe.Sizeof(kSlowModels)) / uint64(unsafe.Sizeof(uint8_t(0)))); i++ { + if model == uint32_t(kSlowModels[i]) { + return 1 + } + } + } + return 0 +} + +var kSlowModels = [6]uint8_t{ + uint8_t(0x37), uint8_t(0x4a), uint8_t(0x4d), // Silvermont Microarchitecture + uint8_t(0x1c), uint8_t(0x26), uint8_t(0x27), // Atom Microarchitecture +} /* cpu.c:110:24 */ + +func x86CPUInfo(tls *libc.TLS, feature CPUFeature) int32 { /* cpu.c:125:12: */ + bp := tls.Alloc(16) + defer tls.Free(16) + + var max_cpuid_value int32 + // var cpu_info [4]int32 at bp, 16 + + var is_intel int32 = 0 + + // get the highest feature value cpuid supports + GetCPUInfo(tls, (bp) /* &cpu_info[0] */, 0) + max_cpuid_value = *(*int32)(unsafe.Pointer((bp) /* &cpu_info[0] */)) + if max_cpuid_value < 1 { + return 0 + } else { + var VENDOR_ID_INTEL_EBX int32 = 0x756e6547 // uneG + var VENDOR_ID_INTEL_EDX int32 = 0x49656e69 // Ieni + var VENDOR_ID_INTEL_ECX int32 = 0x6c65746e // letn + is_intel = (libc.Bool32(((*(*int32)(unsafe.Pointer((bp) /* &cpu_info[0] */ + 1*4)) == VENDOR_ID_INTEL_EBX) && (*(*int32)(unsafe.Pointer((bp) /* &cpu_info[0] */ + 2*4)) == VENDOR_ID_INTEL_ECX)) && (*(*int32)(unsafe.Pointer((bp) /* &cpu_info[0] */ + 3*4)) == VENDOR_ID_INTEL_EDX))) // genuine Intel? + } + + GetCPUInfo(tls, (bp) /* &cpu_info[0] */, 1) + if feature == kSSE2 { + return libc.BoolInt32(!(!((*(*int32)(unsafe.Pointer((bp) /* &cpu_info[0] */ + 3*4)) & (int32(1) << 26)) != 0))) + } + if feature == kSSE3 { + return libc.BoolInt32(!(!((*(*int32)(unsafe.Pointer((bp) /* &cpu_info[0] */ + 2*4)) & (int32(1) << 0)) != 0))) + } + if feature == kSlowSSSE3 { + if (is_intel != 0) && ((*(*int32)(unsafe.Pointer((bp) /* &cpu_info[0] */ + 2*4)) & (int32(1) << 9)) != 0) { // SSSE3? + return CheckSlowModel(tls, *(*int32)(unsafe.Pointer((bp) /* &cpu_info[0] */))) + } + return 0 + } + + if feature == kSSE4_1 { + return libc.BoolInt32(!(!((*(*int32)(unsafe.Pointer((bp) /* &cpu_info[0] */ + 2*4)) & (int32(1) << 19)) != 0))) + } + if feature == kAVX { + // bits 27 (OSXSAVE) & 28 (256-bit AVX) + if (*(*int32)(unsafe.Pointer((bp) /* &cpu_info[0] */ + 2*4)) & 0x18000000) == 0x18000000 { + // XMM state and YMM state enabled by the OS. + return (libc.Bool32((xgetbv(tls) & uint64(0x6)) == uint64(0x6))) + } + } + if feature == kAVX2 { + if (x86CPUInfo(tls, kAVX) != 0) && (max_cpuid_value >= 7) { + GetCPUInfo(tls, (bp) /* &cpu_info[0] */, 7) + return libc.BoolInt32(!(!((*(*int32)(unsafe.Pointer((bp) /* &cpu_info[0] */ + 1*4)) & (int32(1) << 5)) != 0))) + } + } + return 0 +} + +var VP8GetCPUInfo VP8CPUInfo = 0 /* cpu.c:176:12 */ + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +func clip_8b(tls *libc.TLS, v int32) uint8_t { /* dec.c:22:28: */ + if !((v & libc.CplInt32(0xff)) != 0) { + return uint8(v) + } + if v < 0 { + return uint8(0) + } + return uint8(255) +} + +//------------------------------------------------------------------------------ +// Transforms (Paragraph 14.4) + +func TransformOne_C(tls *libc.TLS, in uintptr, dst uintptr) { /* dec.c:44:13: */ + bp := tls.Alloc(64) + defer tls.Free(64) + + // var C [16]int32 at bp, 64 + + var tmp uintptr + var i int32 + tmp = (bp) /* &C[0] */ + for i = 0; i < 4; i++ { // vertical pass + var a int32 = (int32(*(*int16_t)(unsafe.Pointer(in))) + int32(*(*int16_t)(unsafe.Pointer(in + 8*2)))) // [-4096, 4094] + var b int32 = (int32(*(*int16_t)(unsafe.Pointer(in))) - int32(*(*int16_t)(unsafe.Pointer(in + 8*2)))) // [-4095, 4095] + var c int32 = ((((int32(*(*int16_t)(unsafe.Pointer(in + 4*2)))) * 35468) >> 16) - ((((int32(*(*int16_t)(unsafe.Pointer(in + 12*2)))) * 20091) >> 16) + (int32(*(*int16_t)(unsafe.Pointer(in + 12*2)))))) // [-3783, 3783] + var d int32 = (((((int32(*(*int16_t)(unsafe.Pointer(in + 4*2)))) * 20091) >> 16) + (int32(*(*int16_t)(unsafe.Pointer(in + 4*2))))) + (((int32(*(*int16_t)(unsafe.Pointer(in + 12*2)))) * 35468) >> 16)) // [-3785, 3781] + *(*int32)(unsafe.Pointer(tmp)) = (a + d) // [-7881, 7875] + *(*int32)(unsafe.Pointer(tmp + 1*4)) = (b + c) // [-7878, 7878] + *(*int32)(unsafe.Pointer(tmp + 2*4)) = (b - c) // [-7878, 7878] + *(*int32)(unsafe.Pointer(tmp + 3*4)) = (a - d) // [-7877, 7879] + tmp += 4 * (uintptr(4)) + in += 2 + } + // Each pass is expanding the dynamic range by ~3.85 (upper bound). + // The exact value is (2. + (20091 + 35468) / 65536). + // After the second pass, maximum interval is [-3794, 3794], assuming + // an input in [-2048, 2047] interval. We then need to add a dst value + // in the [0, 255] range. + // In the worst case scenario, the input to clip_8b() can be as large as + // [-60713, 60968]. + tmp = (bp) /* &C[0] */ + for i = 0; i < 4; i++ { // horizontal pass + var dc int32 = (*(*int32)(unsafe.Pointer(tmp)) + 4) + var a int32 = (dc + *(*int32)(unsafe.Pointer(tmp + 8*4))) + var b int32 = (dc - *(*int32)(unsafe.Pointer(tmp + 8*4))) + var c int32 = ((((*(*int32)(unsafe.Pointer(tmp + 4*4))) * 35468) >> 16) - ((((*(*int32)(unsafe.Pointer(tmp + 12*4))) * 20091) >> 16) + (*(*int32)(unsafe.Pointer(tmp + 12*4))))) + var d int32 = (((((*(*int32)(unsafe.Pointer(tmp + 4*4))) * 20091) >> 16) + (*(*int32)(unsafe.Pointer(tmp + 4*4)))) + (((*(*int32)(unsafe.Pointer(tmp + 12*4))) * 35468) >> 16)) + *(*uint8_t)(unsafe.Pointer(dst)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst))) + ((a + d) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + 1)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 1))) + ((b + c) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + 2)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 2))) + ((b - c) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + 3)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 3))) + ((a - d) >> 3))) + tmp += 4 + dst += uintptr(32) + } +} + +// Simplified transform when only in[0], in[1] and in[4] are non-zero +func TransformAC3_C(tls *libc.TLS, in uintptr, dst uintptr) { /* dec.c:84:13: */ + var a int32 = (int32(*(*int16_t)(unsafe.Pointer(in))) + 4) + var c4 int32 = (((int32(*(*int16_t)(unsafe.Pointer(in + 4*2)))) * 35468) >> 16) + var d4 int32 = ((((int32(*(*int16_t)(unsafe.Pointer(in + 4*2)))) * 20091) >> 16) + (int32(*(*int16_t)(unsafe.Pointer(in + 4*2))))) + var c1 int32 = (((int32(*(*int16_t)(unsafe.Pointer(in + 1*2)))) * 35468) >> 16) + var d1 int32 = ((((int32(*(*int16_t)(unsafe.Pointer(in + 1*2)))) * 20091) >> 16) + (int32(*(*int16_t)(unsafe.Pointer(in + 1*2))))) + for ok := true; ok; ok = (0 != 0) { + var DC int32 = (a + d4) + *(*uint8_t)(unsafe.Pointer(dst)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst))) + ((DC + (d1)) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + 1)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 1))) + ((DC + (c1)) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + 2)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 2))) + ((DC - (c1)) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + 3)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 3))) + ((DC - (d1)) >> 3))) + } + for ok1 := true; ok1; ok1 = (0 != 0) { + var DC int32 = (a + c4) + *(*uint8_t)(unsafe.Pointer(dst + 32)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 32))) + ((DC + (d1)) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + 33)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 33))) + ((DC + (c1)) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + 34)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 34))) + ((DC - (c1)) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + 35)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 35))) + ((DC - (d1)) >> 3))) + } + for ok2 := true; ok2; ok2 = (0 != 0) { + var DC int32 = (a - c4) + *(*uint8_t)(unsafe.Pointer(dst + 64)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 64))) + ((DC + (d1)) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + 65)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 65))) + ((DC + (c1)) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + 66)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 66))) + ((DC - (c1)) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + 67)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 67))) + ((DC - (d1)) >> 3))) + } + for ok3 := true; ok3; ok3 = (0 != 0) { + var DC int32 = (a - d4) + *(*uint8_t)(unsafe.Pointer(dst + 96)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 96))) + ((DC + (d1)) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + 97)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 97))) + ((DC + (c1)) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + 98)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 98))) + ((DC - (c1)) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + 99)) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + 99))) + ((DC - (d1)) >> 3))) + } +} + +func TransformTwo_C(tls *libc.TLS, in uintptr, dst uintptr, do_two int32) { /* dec.c:99:13: */ + TransformOne_C(tls, in, dst) + if do_two != 0 { + TransformOne_C(tls, (in + uintptr(16)*2), (dst + uintptr(4))) + } +} + +func TransformUV_C(tls *libc.TLS, in uintptr, dst uintptr) { /* dec.c:107:13: */ + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8Transform})).f(tls, (in + uintptr((0*16))*2), dst, 1) + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8Transform})).f(tls, (in + uintptr((2*16))*2), (dst + uintptr((4 * 32))), 1) +} + +func TransformDC_C(tls *libc.TLS, in uintptr, dst uintptr) { /* dec.c:113:13: */ + var DC int32 = (int32(*(*int16_t)(unsafe.Pointer(in))) + 4) + var i int32 + var j int32 + for j = 0; j < 4; j++ { + for i = 0; i < 4; i++ { + *(*uint8_t)(unsafe.Pointer(dst + uintptr(((i) + ((j) * 32))))) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + uintptr(((i) + ((j) * 32)))))) + ((DC) >> 3))) + } + } +} + +func TransformDCUV_C(tls *libc.TLS, in uintptr, dst uintptr) { /* dec.c:124:13: */ + if *(*int16_t)(unsafe.Pointer(in)) != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8TransformDC})).f(tls, (in + uintptr((0*16))*2), dst) + } + if *(*int16_t)(unsafe.Pointer(in + 16*2)) != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8TransformDC})).f(tls, (in + uintptr((1*16))*2), (dst + uintptr(4))) + } + if *(*int16_t)(unsafe.Pointer(in + 32*2)) != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8TransformDC})).f(tls, (in + uintptr((2*16))*2), (dst + uintptr((4 * 32)))) + } + if *(*int16_t)(unsafe.Pointer(in + 48*2)) != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8TransformDC})).f(tls, (in + uintptr((3*16))*2), ((dst + uintptr((4 * 32))) + uintptr(4))) + } +} + +//------------------------------------------------------------------------------ +// Paragraph 14.3 + +func TransformWHT_C(tls *libc.TLS, in uintptr, out uintptr) { /* dec.c:137:13: */ + bp := tls.Alloc(64) + defer tls.Free(64) + + // var tmp [16]int32 at bp, 64 + + var i int32 + for i = 0; i < 4; i++ { + var a0 int32 = (int32(*(*int16_t)(unsafe.Pointer(in + uintptr((0+i))*2))) + int32(*(*int16_t)(unsafe.Pointer(in + uintptr((12+i))*2)))) + var a1 int32 = (int32(*(*int16_t)(unsafe.Pointer(in + uintptr((4+i))*2))) + int32(*(*int16_t)(unsafe.Pointer(in + uintptr((8+i))*2)))) + var a2 int32 = (int32(*(*int16_t)(unsafe.Pointer(in + uintptr((4+i))*2))) - int32(*(*int16_t)(unsafe.Pointer(in + uintptr((8+i))*2)))) + var a3 int32 = (int32(*(*int16_t)(unsafe.Pointer(in + uintptr((0+i))*2))) - int32(*(*int16_t)(unsafe.Pointer(in + uintptr((12+i))*2)))) + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((0+i))*4)) = (a0 + a1) + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((8+i))*4)) = (a0 - a1) + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((4+i))*4)) = (a3 + a2) + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((12+i))*4)) = (a3 - a2) + } + for i = 0; i < 4; i++ { + var dc int32 = (*(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((0+(i*4)))*4)) + 3) // w/ rounder + var a0 int32 = (dc + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((3+(i*4)))*4))) + var a1 int32 = (*(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((1+(i*4)))*4)) + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((2+(i*4)))*4))) + var a2 int32 = (*(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((1+(i*4)))*4)) - *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((2+(i*4)))*4))) + var a3 int32 = (dc - *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((3+(i*4)))*4))) + *(*int16_t)(unsafe.Pointer(out)) = (int16_t((a0 + a1) >> 3)) + *(*int16_t)(unsafe.Pointer(out + 16*2)) = (int16_t((a3 + a2) >> 3)) + *(*int16_t)(unsafe.Pointer(out + 32*2)) = (int16_t((a0 - a1) >> 3)) + *(*int16_t)(unsafe.Pointer(out + 48*2)) = (int16_t((a3 - a2) >> 3)) + out += 2 * (uintptr(64)) + } +} + +var VP8TransformWHT uintptr /* dec.c:165:6: */ + +//------------------------------------------------------------------------------ +// Intra predictions + +func TrueMotion(tls *libc.TLS, dst uintptr, size int32) { /* dec.c:173:25: */ + var top uintptr = (dst - uintptr(32)) + var clip0 uintptr = (VP8kclip1 - uintptr(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-1))))) + var y int32 + for y = 0; y < size; y++ { + var clip uintptr = (clip0 + uintptr(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32(-1))))) + var x int32 + for x = 0; x < size; x++ { + *(*uint8_t)(unsafe.Pointer(dst + uintptr(x))) = *(*uint8_t)(unsafe.Pointer(clip + uintptr(*(*uint8_t)(unsafe.Pointer(top + uintptr(x)))))) + } + dst += uintptr(32) + } +} + +func TM4_C(tls *libc.TLS, dst uintptr) { /* dec.c:186:13: */ + TrueMotion(tls, dst, 4) +} + +func TM8uv_C(tls *libc.TLS, dst uintptr) { /* dec.c:187:13: */ + TrueMotion(tls, dst, 8) +} + +func TM16_C(tls *libc.TLS, dst uintptr) { /* dec.c:188:13: */ + TrueMotion(tls, dst, 16) +} + +//------------------------------------------------------------------------------ +// 16x16 + +func VE16_C(tls *libc.TLS, dst uintptr) { /* dec.c:193:13: */ // vertical + var j int32 + for j = 0; j < 16; j++ { + libc.Xmemcpy(tls, (dst + uintptr((j * 32))), (dst - uintptr(32)), uint64(16)) + } +} + +func HE16_C(tls *libc.TLS, dst uintptr) { /* dec.c:200:13: */ // horizontal + var j int32 + for j = 16; j > 0; j-- { + libc.Xmemset(tls, dst, int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32(-1)))), uint64(16)) + dst += uintptr(32) + } +} + +func Put16(tls *libc.TLS, v int32, dst uintptr) { /* dec.c:208:25: */ + var j int32 + for j = 0; j < 16; j++ { + libc.Xmemset(tls, (dst + uintptr((j * 32))), v, uint64(16)) + } +} + +func DC16_C(tls *libc.TLS, dst uintptr) { /* dec.c:215:13: */ // DC + var DC int32 = 16 + var j int32 + for j = 0; j < 16; j++ { + DC = DC + (int32(*(*uint8_t)(unsafe.Pointer(dst + uintptr((-1 + (j * 32)))))) + int32(*(*uint8_t)(unsafe.Pointer(dst + uintptr((j - 32)))))) + } + Put16(tls, (DC >> 5), dst) +} + +func DC16NoTop_C(tls *libc.TLS, dst uintptr) { /* dec.c:224:13: */ // DC with top samples not available + var DC int32 = 8 + var j int32 + for j = 0; j < 16; j++ { + DC = DC + (int32(*(*uint8_t)(unsafe.Pointer(dst + uintptr((-1 + (j * 32))))))) + } + Put16(tls, (DC >> 4), dst) +} + +func DC16NoLeft_C(tls *libc.TLS, dst uintptr) { /* dec.c:233:13: */ // DC with left samples not available + var DC int32 = 8 + var i int32 + for i = 0; i < 16; i++ { + DC = DC + (int32(*(*uint8_t)(unsafe.Pointer(dst + uintptr((i - 32)))))) + } + Put16(tls, (DC >> 4), dst) +} + +func DC16NoTopLeft_C(tls *libc.TLS, dst uintptr) { /* dec.c:242:13: */ // DC with no top and left samples + Put16(tls, 0x80, dst) +} + +var VP8PredLuma16 [7]VP8PredFunc /* dec.c:247:13: */ + +//------------------------------------------------------------------------------ +// 4x4 + +func VE4_C(tls *libc.TLS, dst uintptr) { /* dec.c:256:13: */ + bp := tls.Alloc(4) + defer tls.Free(4) + // vertical + var top uintptr = (dst - uintptr(32)) + *(*[4]uint8_t)(unsafe.Pointer(bp /* vals */)) = [4]uint8_t{ + (uint8_t(((((int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-1))))) + (2 * (int32(*(*uint8_t)(unsafe.Pointer(top)))))) + (int32(*(*uint8_t)(unsafe.Pointer(top + 1))))) + 2) >> 2)), + (uint8_t(((((int32(*(*uint8_t)(unsafe.Pointer(top)))) + (2 * (int32(*(*uint8_t)(unsafe.Pointer(top + 1)))))) + (int32(*(*uint8_t)(unsafe.Pointer(top + 2))))) + 2) >> 2)), + (uint8_t(((((int32(*(*uint8_t)(unsafe.Pointer(top + 1)))) + (2 * (int32(*(*uint8_t)(unsafe.Pointer(top + 2)))))) + (int32(*(*uint8_t)(unsafe.Pointer(top + 3))))) + 2) >> 2)), + (uint8_t(((((int32(*(*uint8_t)(unsafe.Pointer(top + 2)))) + (2 * (int32(*(*uint8_t)(unsafe.Pointer(top + 3)))))) + (int32(*(*uint8_t)(unsafe.Pointer(top + 4))))) + 2) >> 2)), + } + var i int32 + for i = 0; i < 4; i++ { + libc.Xmemcpy(tls, (dst + uintptr((i * 32))), (bp) /* &vals[0] */, uint64(unsafe.Sizeof([4]uint8_t{}))) + } +} + +func HE4_C(tls *libc.TLS, dst uintptr) { /* dec.c:271:13: */ // horizontal + var A int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((-1 - 32))))) + var B int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32(-1)))) + var C int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + 31))) + var D int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + 63))) + var E int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + 95))) + WebPUint32ToMem(tls, (dst + uintptr((0 * 32))), (0x01010101 * (uint32((uint8_t(((((A) + (2 * (B))) + (C)) + 2) >> 2)))))) + WebPUint32ToMem(tls, (dst + uintptr((1 * 32))), (0x01010101 * (uint32((uint8_t(((((B) + (2 * (C))) + (D)) + 2) >> 2)))))) + WebPUint32ToMem(tls, (dst + uintptr((2 * 32))), (0x01010101 * (uint32((uint8_t(((((C) + (2 * (D))) + (E)) + 2) >> 2)))))) + WebPUint32ToMem(tls, (dst + uintptr((3 * 32))), (0x01010101 * (uint32((uint8_t(((((D) + (2 * (E))) + (E)) + 2) >> 2)))))) +} + +func DC4_C(tls *libc.TLS, dst uintptr) { /* dec.c:284:13: */ // DC + var dc uint32_t = uint32_t(4) + var i int32 + for i = 0; i < 4; i++ { + dc = dc + (uint32_t(int32(*(*uint8_t)(unsafe.Pointer(dst + uintptr((i - 32))))) + int32(*(*uint8_t)(unsafe.Pointer(dst + uintptr((-1 + (i * 32)))))))) + } + dc >>= 3 + for i = 0; i < 4; i++ { + libc.Xmemset(tls, (dst + uintptr((i * 32))), int32(dc), uint64(4)) + } +} + +func RD4_C(tls *libc.TLS, dst uintptr) { /* dec.c:292:13: */ // Down-right + var I int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((-1 + (0 * 32)))))) + var J int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + 31))) + var K int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + 63))) + var L int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + 95))) + var X int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((-1 - 32))))) + var A int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((0 - 32))))) + var B int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((1 - 32))))) + var C int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((2 - 32))))) + var D int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((3 - 32))))) + *(*uint8_t)(unsafe.Pointer(dst + 96)) = (uint8_t(((((J) + (2 * (K))) + (L)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 97)) = libc.AssignPtrUint8((dst + 64), (uint8_t(((((I) + (2 * (J))) + (K)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 98)) = libc.AssignPtrUint8((dst + 65), libc.AssignPtrUint8((dst+32), (uint8_t(((((X)+(2*(I)))+(J))+2)>>2)))) + *(*uint8_t)(unsafe.Pointer(dst + 99)) = libc.AssignPtrUint8((dst + 66), libc.AssignPtrUint8((dst+33), libc.AssignPtrUint8((dst), (uint8_t(((((A)+(2*(X)))+(I))+2)>>2))))) + *(*uint8_t)(unsafe.Pointer(dst + 67)) = libc.AssignPtrUint8((dst + 34), libc.AssignPtrUint8((dst+1), (uint8_t(((((B)+(2*(A)))+(X))+2)>>2)))) + *(*uint8_t)(unsafe.Pointer(dst + 35)) = libc.AssignPtrUint8((dst + 2), (uint8_t(((((C) + (2 * (B))) + (A)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 3)) = (uint8_t(((((D) + (2 * (C))) + (B)) + 2) >> 2)) +} + +func LD4_C(tls *libc.TLS, dst uintptr) { /* dec.c:311:13: */ // Down-Left + var A int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((0 - 32))))) + var B int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((1 - 32))))) + var C int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((2 - 32))))) + var D int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((3 - 32))))) + var E int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((4 - 32))))) + var F int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((5 - 32))))) + var G int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((6 - 32))))) + var H int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((7 - 32))))) + *(*uint8_t)(unsafe.Pointer(dst)) = (uint8_t(((((A) + (2 * (B))) + (C)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 1)) = libc.AssignPtrUint8((dst + 32), (uint8_t(((((B) + (2 * (C))) + (D)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 2)) = libc.AssignPtrUint8((dst + 33), libc.AssignPtrUint8((dst+64), (uint8_t(((((C)+(2*(D)))+(E))+2)>>2)))) + *(*uint8_t)(unsafe.Pointer(dst + 3)) = libc.AssignPtrUint8((dst + 34), libc.AssignPtrUint8((dst+65), libc.AssignPtrUint8((dst+96), (uint8_t(((((D)+(2*(E)))+(F))+2)>>2))))) + *(*uint8_t)(unsafe.Pointer(dst + 35)) = libc.AssignPtrUint8((dst + 66), libc.AssignPtrUint8((dst+97), (uint8_t(((((E)+(2*(F)))+(G))+2)>>2)))) + *(*uint8_t)(unsafe.Pointer(dst + 67)) = libc.AssignPtrUint8((dst + 98), (uint8_t(((((F) + (2 * (G))) + (H)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 99)) = (uint8_t(((((G) + (2 * (H))) + (H)) + 2) >> 2)) +} + +func VR4_C(tls *libc.TLS, dst uintptr) { /* dec.c:330:13: */ // Vertical-Right + var I int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((-1 + (0 * 32)))))) + var J int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + 31))) + var K int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + 63))) + var X int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((-1 - 32))))) + var A int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((0 - 32))))) + var B int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((1 - 32))))) + var C int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((2 - 32))))) + var D int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((3 - 32))))) + *(*uint8_t)(unsafe.Pointer(dst)) = libc.AssignPtrUint8((dst + 65), (uint8_t((((X) + (A)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 1)) = libc.AssignPtrUint8((dst + 66), (uint8_t((((A) + (B)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 2)) = libc.AssignPtrUint8((dst + 67), (uint8_t((((B) + (C)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 3)) = (uint8_t((((C) + (D)) + 1) >> 1)) + + *(*uint8_t)(unsafe.Pointer(dst + 96)) = (uint8_t(((((K) + (2 * (J))) + (I)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 64)) = (uint8_t(((((J) + (2 * (I))) + (X)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 32)) = libc.AssignPtrUint8((dst + 97), (uint8_t(((((I) + (2 * (X))) + (A)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 33)) = libc.AssignPtrUint8((dst + 98), (uint8_t(((((X) + (2 * (A))) + (B)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 34)) = libc.AssignPtrUint8((dst + 99), (uint8_t(((((A) + (2 * (B))) + (C)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 35)) = (uint8_t(((((B) + (2 * (C))) + (D)) + 2) >> 2)) +} + +func VL4_C(tls *libc.TLS, dst uintptr) { /* dec.c:352:13: */ // Vertical-Left + var A int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((0 - 32))))) + var B int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((1 - 32))))) + var C int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((2 - 32))))) + var D int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((3 - 32))))) + var E int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((4 - 32))))) + var F int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((5 - 32))))) + var G int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((6 - 32))))) + var H int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((7 - 32))))) + *(*uint8_t)(unsafe.Pointer(dst)) = (uint8_t((((A) + (B)) + 1) >> 1)) + *(*uint8_t)(unsafe.Pointer(dst + 1)) = libc.AssignPtrUint8((dst + 64), (uint8_t((((B) + (C)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 2)) = libc.AssignPtrUint8((dst + 65), (uint8_t((((C) + (D)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 3)) = libc.AssignPtrUint8((dst + 66), (uint8_t((((D) + (E)) + 1) >> 1))) + + *(*uint8_t)(unsafe.Pointer(dst + 32)) = (uint8_t(((((A) + (2 * (B))) + (C)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 33)) = libc.AssignPtrUint8((dst + 96), (uint8_t(((((B) + (2 * (C))) + (D)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 34)) = libc.AssignPtrUint8((dst + 97), (uint8_t(((((C) + (2 * (D))) + (E)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 35)) = libc.AssignPtrUint8((dst + 98), (uint8_t(((((D) + (2 * (E))) + (F)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 67)) = (uint8_t(((((E) + (2 * (F))) + (G)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 99)) = (uint8_t(((((F) + (2 * (G))) + (H)) + 2) >> 2)) +} + +func HU4_C(tls *libc.TLS, dst uintptr) { /* dec.c:374:13: */ // Horizontal-Up + var I int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((-1 + (0 * 32)))))) + var J int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + 31))) + var K int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + 63))) + var L int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + 95))) + *(*uint8_t)(unsafe.Pointer(dst)) = (uint8_t((((I) + (J)) + 1) >> 1)) + *(*uint8_t)(unsafe.Pointer(dst + 2)) = libc.AssignPtrUint8((dst + 32), (uint8_t((((J) + (K)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 34)) = libc.AssignPtrUint8((dst + 64), (uint8_t((((K) + (L)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 1)) = (uint8_t(((((I) + (2 * (J))) + (K)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 3)) = libc.AssignPtrUint8((dst + 33), (uint8_t(((((J) + (2 * (K))) + (L)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 35)) = libc.AssignPtrUint8((dst + 65), (uint8_t(((((K) + (2 * (L))) + (L)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 67)) = libc.AssignPtrUint8((dst + 66), libc.AssignPtrUint8((dst+96), libc.AssignPtrUint8((dst+97), libc.AssignPtrUint8((dst+98), libc.AssignPtrUint8((dst+99), uint8_t(L)))))) +} + +func HD4_C(tls *libc.TLS, dst uintptr) { /* dec.c:389:13: */ // Horizontal-Down + var I int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((-1 + (0 * 32)))))) + var J int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + 31))) + var K int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + 63))) + var L int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + 95))) + var X int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((-1 - 32))))) + var A int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((0 - 32))))) + var B int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((1 - 32))))) + var C int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32((2 - 32))))) + + *(*uint8_t)(unsafe.Pointer(dst)) = libc.AssignPtrUint8((dst + 34), (uint8_t((((I) + (X)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 32)) = libc.AssignPtrUint8((dst + 66), (uint8_t((((J) + (I)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 64)) = libc.AssignPtrUint8((dst + 98), (uint8_t((((K) + (J)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 96)) = (uint8_t((((L) + (K)) + 1) >> 1)) + + *(*uint8_t)(unsafe.Pointer(dst + 3)) = (uint8_t(((((A) + (2 * (B))) + (C)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 2)) = (uint8_t(((((X) + (2 * (A))) + (B)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 1)) = libc.AssignPtrUint8((dst + 35), (uint8_t(((((I) + (2 * (X))) + (A)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 33)) = libc.AssignPtrUint8((dst + 67), (uint8_t(((((J) + (2 * (I))) + (X)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 65)) = libc.AssignPtrUint8((dst + 99), (uint8_t(((((K) + (2 * (J))) + (I)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 97)) = (uint8_t(((((L) + (2 * (K))) + (J)) + 2) >> 2)) +} + +var VP8PredLuma4 [10]VP8PredFunc /* dec.c:416:13: */ + +//------------------------------------------------------------------------------ +// Chroma + +func VE8uv_C(tls *libc.TLS, dst uintptr) { /* dec.c:422:13: */ // vertical + var j int32 + for j = 0; j < 8; j++ { + libc.Xmemcpy(tls, (dst + uintptr((j * 32))), (dst - uintptr(32)), uint64(8)) + } +} + +func HE8uv_C(tls *libc.TLS, dst uintptr) { /* dec.c:429:13: */ // horizontal + var j int32 + for j = 0; j < 8; j++ { + libc.Xmemset(tls, dst, int32(*(*uint8_t)(unsafe.Pointer(dst + libc.UintptrFromInt32(-1)))), uint64(8)) + dst += uintptr(32) + } +} + +// helper for chroma-DC predictions +func Put8x8uv(tls *libc.TLS, value uint8_t, dst uintptr) { /* dec.c:438:25: */ + var j int32 + for j = 0; j < 8; j++ { + libc.Xmemset(tls, (dst + uintptr((j * 32))), int32(value), uint64(8)) + } +} + +func DC8uv_C(tls *libc.TLS, dst uintptr) { /* dec.c:445:13: */ // DC + var dc0 int32 = 8 + var i int32 + for i = 0; i < 8; i++ { + dc0 = dc0 + (int32(*(*uint8_t)(unsafe.Pointer(dst + uintptr((i - 32))))) + int32(*(*uint8_t)(unsafe.Pointer(dst + uintptr((-1 + (i * 32))))))) + } + Put8x8uv(tls, (uint8(dc0 >> 4)), dst) +} + +func DC8uvNoLeft_C(tls *libc.TLS, dst uintptr) { /* dec.c:454:13: */ // DC with no left samples + var dc0 int32 = 4 + var i int32 + for i = 0; i < 8; i++ { + dc0 = dc0 + (int32(*(*uint8_t)(unsafe.Pointer(dst + uintptr((i - 32)))))) + } + Put8x8uv(tls, (uint8(dc0 >> 3)), dst) +} + +func DC8uvNoTop_C(tls *libc.TLS, dst uintptr) { /* dec.c:463:13: */ // DC with no top samples + var dc0 int32 = 4 + var i int32 + for i = 0; i < 8; i++ { + dc0 = dc0 + (int32(*(*uint8_t)(unsafe.Pointer(dst + uintptr((-1 + (i * 32))))))) + } + Put8x8uv(tls, (uint8(dc0 >> 3)), dst) +} + +func DC8uvNoTopLeft_C(tls *libc.TLS, dst uintptr) { /* dec.c:472:13: */ // DC with nothing + Put8x8uv(tls, uint8(0x80), dst) +} + +var VP8PredChroma8 [7]VP8PredFunc /* dec.c:477:13: */ + +//------------------------------------------------------------------------------ +// Edge filtering functions + +// 4 pixels in, 2 pixels out +func DoFilter2_C(tls *libc.TLS, p uintptr, step int32) { /* dec.c:484:25: */ + var p1 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr((-2 * step))))) + var p0 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(-step)))) + var q0 int32 = int32(*(*uint8_t)(unsafe.Pointer(p))) + var q1 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(step)))) + var a int32 = ((3 * (q0 - p0)) + int32(*(*int8_t)(unsafe.Pointer(VP8ksclip1 + uintptr((p1 - q1)))))) // in [-893,892] + var a1 int32 = int32(*(*int8_t)(unsafe.Pointer(VP8ksclip2 + uintptr(((a + 4) >> 3))))) // in [-16,15] + var a2 int32 = int32(*(*int8_t)(unsafe.Pointer(VP8ksclip2 + uintptr(((a + 3) >> 3))))) + *(*uint8_t)(unsafe.Pointer(p + uintptr(-step))) = *(*uint8_t)(unsafe.Pointer(VP8kclip1 + uintptr((p0 + a2)))) + *(*uint8_t)(unsafe.Pointer(p)) = *(*uint8_t)(unsafe.Pointer(VP8kclip1 + uintptr((q0 - a1)))) +} + +// 4 pixels in, 4 pixels out +func DoFilter4_C(tls *libc.TLS, p uintptr, step int32) { /* dec.c:494:25: */ + var p1 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr((-2 * step))))) + var p0 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(-step)))) + var q0 int32 = int32(*(*uint8_t)(unsafe.Pointer(p))) + var q1 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(step)))) + var a int32 = (3 * (q0 - p0)) + var a1 int32 = int32(*(*int8_t)(unsafe.Pointer(VP8ksclip2 + uintptr(((a + 4) >> 3))))) + var a2 int32 = int32(*(*int8_t)(unsafe.Pointer(VP8ksclip2 + uintptr(((a + 3) >> 3))))) + var a3 int32 = ((a1 + 1) >> 1) + *(*uint8_t)(unsafe.Pointer(p + uintptr((-2 * step)))) = *(*uint8_t)(unsafe.Pointer(VP8kclip1 + uintptr((p1 + a3)))) + *(*uint8_t)(unsafe.Pointer(p + uintptr(-step))) = *(*uint8_t)(unsafe.Pointer(VP8kclip1 + uintptr((p0 + a2)))) + *(*uint8_t)(unsafe.Pointer(p)) = *(*uint8_t)(unsafe.Pointer(VP8kclip1 + uintptr((q0 - a1)))) + *(*uint8_t)(unsafe.Pointer(p + uintptr(step))) = *(*uint8_t)(unsafe.Pointer(VP8kclip1 + uintptr((q1 - a3)))) +} + +// 6 pixels in, 6 pixels out +func DoFilter6_C(tls *libc.TLS, p uintptr, step int32) { /* dec.c:507:25: */ + var p2 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr((-3 * step))))) + var p1 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr((-2 * step))))) + var p0 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(-step)))) + var q0 int32 = int32(*(*uint8_t)(unsafe.Pointer(p))) + var q1 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(step)))) + var q2 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr((2 * step))))) + var a int32 = int32(*(*int8_t)(unsafe.Pointer(VP8ksclip1 + uintptr(((3 * (q0 - p0)) + int32(*(*int8_t)(unsafe.Pointer(VP8ksclip1 + uintptr((p1 - q1)))))))))) + // a is in [-128,127], a1 in [-27,27], a2 in [-18,18] and a3 in [-9,9] + var a1 int32 = (((27 * a) + 63) >> 7) // eq. to ((3 * a + 7) * 9) >> 7 + var a2 int32 = (((18 * a) + 63) >> 7) // eq. to ((2 * a + 7) * 9) >> 7 + var a3 int32 = (((9 * a) + 63) >> 7) // eq. to ((1 * a + 7) * 9) >> 7 + *(*uint8_t)(unsafe.Pointer(p + uintptr((-3 * step)))) = *(*uint8_t)(unsafe.Pointer(VP8kclip1 + uintptr((p2 + a3)))) + *(*uint8_t)(unsafe.Pointer(p + uintptr((-2 * step)))) = *(*uint8_t)(unsafe.Pointer(VP8kclip1 + uintptr((p1 + a2)))) + *(*uint8_t)(unsafe.Pointer(p + uintptr(-step))) = *(*uint8_t)(unsafe.Pointer(VP8kclip1 + uintptr((p0 + a1)))) + *(*uint8_t)(unsafe.Pointer(p)) = *(*uint8_t)(unsafe.Pointer(VP8kclip1 + uintptr((q0 - a1)))) + *(*uint8_t)(unsafe.Pointer(p + uintptr(step))) = *(*uint8_t)(unsafe.Pointer(VP8kclip1 + uintptr((q1 - a2)))) + *(*uint8_t)(unsafe.Pointer(p + uintptr((2 * step)))) = *(*uint8_t)(unsafe.Pointer(VP8kclip1 + uintptr((q2 - a3)))) +} + +func Hev(tls *libc.TLS, p uintptr, step int32, thresh int32) int32 { /* dec.c:523:24: */ + var p1 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr((-2 * step))))) + var p0 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(-step)))) + var q0 int32 = int32(*(*uint8_t)(unsafe.Pointer(p))) + var q1 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(step)))) + return (libc.Bool32((int32(*(*uint8_t)(unsafe.Pointer(VP8kabs0 + uintptr((p1 - p0))))) > thresh) || (int32(*(*uint8_t)(unsafe.Pointer(VP8kabs0 + uintptr((q1 - q0))))) > thresh))) +} + +func NeedsFilter_C(tls *libc.TLS, p uintptr, step int32, t int32) int32 { /* dec.c:530:24: */ + var p1 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr((-2 * step))))) + var p0 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(-step)))) + var q0 int32 = int32(*(*uint8_t)(unsafe.Pointer(p))) + var q1 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(step)))) + return (libc.Bool32(((4 * int32(*(*uint8_t)(unsafe.Pointer(VP8kabs0 + uintptr((p0 - q0)))))) + int32(*(*uint8_t)(unsafe.Pointer(VP8kabs0 + uintptr((p1 - q1)))))) <= t)) +} + +func NeedsFilter2_C(tls *libc.TLS, p uintptr, step int32, t int32, it int32) int32 { /* dec.c:537:24: */ + var p3 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr((-4 * step))))) + var p2 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr((-3 * step))))) + var p1 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr((-2 * step))))) + var p0 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(-step)))) + var q0 int32 = int32(*(*uint8_t)(unsafe.Pointer(p))) + var q1 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(step)))) + var q2 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr((2 * step))))) + var q3 int32 = int32(*(*uint8_t)(unsafe.Pointer(p + uintptr((3 * step))))) + if ((4 * int32(*(*uint8_t)(unsafe.Pointer(VP8kabs0 + uintptr((p0 - q0)))))) + int32(*(*uint8_t)(unsafe.Pointer(VP8kabs0 + uintptr((p1 - q1)))))) > t { + return 0 + } + return (libc.Bool32((((((int32(*(*uint8_t)(unsafe.Pointer(VP8kabs0 + uintptr((p3 - p2))))) <= it) && (int32(*(*uint8_t)(unsafe.Pointer(VP8kabs0 + uintptr((p2 - p1))))) <= it)) && (int32(*(*uint8_t)(unsafe.Pointer(VP8kabs0 + uintptr((p1 - p0))))) <= it)) && (int32(*(*uint8_t)(unsafe.Pointer(VP8kabs0 + uintptr((q3 - q2))))) <= it)) && (int32(*(*uint8_t)(unsafe.Pointer(VP8kabs0 + uintptr((q2 - q1))))) <= it)) && (int32(*(*uint8_t)(unsafe.Pointer(VP8kabs0 + uintptr((q1 - q0))))) <= it))) +} + +//------------------------------------------------------------------------------ +// Simple In-loop filtering (Paragraph 15.2) + +func SimpleVFilter16_C(tls *libc.TLS, p uintptr, stride int32, thresh int32) { /* dec.c:553:13: */ + var i int32 + var thresh2 int32 = ((2 * thresh) + 1) + for i = 0; i < 16; i++ { + if NeedsFilter_C(tls, (p+uintptr(i)), stride, thresh2) != 0 { + DoFilter2_C(tls, (p + uintptr(i)), stride) + } + } +} + +func SimpleHFilter16_C(tls *libc.TLS, p uintptr, stride int32, thresh int32) { /* dec.c:563:13: */ + var i int32 + var thresh2 int32 = ((2 * thresh) + 1) + for i = 0; i < 16; i++ { + if NeedsFilter_C(tls, (p+uintptr((i*stride))), 1, thresh2) != 0 { + DoFilter2_C(tls, (p + uintptr((i * stride))), 1) + } + } +} + +func SimpleVFilter16i_C(tls *libc.TLS, p uintptr, stride int32, thresh int32) { /* dec.c:573:13: */ + var k int32 + for k = 3; k > 0; k-- { + p += (uintptr(4 * stride)) + SimpleVFilter16_C(tls, p, stride, thresh) + } +} + +func SimpleHFilter16i_C(tls *libc.TLS, p uintptr, stride int32, thresh int32) { /* dec.c:581:13: */ + var k int32 + for k = 3; k > 0; k-- { + p += uintptr(4) + SimpleHFilter16_C(tls, p, stride, thresh) + } +} + +//------------------------------------------------------------------------------ +// Complex In-loop filtering (Paragraph 15.3) + +func FilterLoop26_C(tls *libc.TLS, p uintptr, hstride int32, vstride int32, size int32, thresh int32, ithresh int32, hev_thresh int32) { /* dec.c:594:25: */ + var thresh2 int32 = ((2 * thresh) + 1) + for libc.PostDecInt32(&size, 1) > 0 { + if NeedsFilter2_C(tls, p, hstride, thresh2, ithresh) != 0 { + if Hev(tls, p, hstride, hev_thresh) != 0 { + DoFilter2_C(tls, p, hstride) + } else { + DoFilter6_C(tls, p, hstride) + } + } + p += uintptr(vstride) + } +} + +func FilterLoop24_C(tls *libc.TLS, p uintptr, hstride int32, vstride int32, size int32, thresh int32, ithresh int32, hev_thresh int32) { /* dec.c:611:25: */ + var thresh2 int32 = ((2 * thresh) + 1) + for libc.PostDecInt32(&size, 1) > 0 { + if NeedsFilter2_C(tls, p, hstride, thresh2, ithresh) != 0 { + if Hev(tls, p, hstride, hev_thresh) != 0 { + DoFilter2_C(tls, p, hstride) + } else { + DoFilter4_C(tls, p, hstride) + } + } + p += uintptr(vstride) + } +} + +// on macroblock edges +func VFilter16_C(tls *libc.TLS, p uintptr, stride int32, thresh int32, ithresh int32, hev_thresh int32) { /* dec.c:631:13: */ + FilterLoop26_C(tls, p, stride, 1, 16, thresh, ithresh, hev_thresh) +} + +func HFilter16_C(tls *libc.TLS, p uintptr, stride int32, thresh int32, ithresh int32, hev_thresh int32) { /* dec.c:636:13: */ + FilterLoop26_C(tls, p, 1, stride, 16, thresh, ithresh, hev_thresh) +} + +// on three inner edges +func VFilter16i_C(tls *libc.TLS, p uintptr, stride int32, thresh int32, ithresh int32, hev_thresh int32) { /* dec.c:642:13: */ + var k int32 + for k = 3; k > 0; k-- { + p += (uintptr(4 * stride)) + FilterLoop24_C(tls, p, stride, 1, 16, thresh, ithresh, hev_thresh) + } +} + +func HFilter16i_C(tls *libc.TLS, p uintptr, stride int32, thresh int32, ithresh int32, hev_thresh int32) { /* dec.c:653:13: */ + var k int32 + for k = 3; k > 0; k-- { + p += uintptr(4) + FilterLoop24_C(tls, p, 1, stride, 16, thresh, ithresh, hev_thresh) + } +} + +// 8-pixels wide variant, for chroma filtering +func VFilter8_C(tls *libc.TLS, u uintptr, v uintptr, stride int32, thresh int32, ithresh int32, hev_thresh int32) { /* dec.c:665:13: */ + FilterLoop26_C(tls, u, stride, 1, 8, thresh, ithresh, hev_thresh) + FilterLoop26_C(tls, v, stride, 1, 8, thresh, ithresh, hev_thresh) +} + +func HFilter8_C(tls *libc.TLS, u uintptr, v uintptr, stride int32, thresh int32, ithresh int32, hev_thresh int32) { /* dec.c:673:13: */ + FilterLoop26_C(tls, u, 1, stride, 8, thresh, ithresh, hev_thresh) + FilterLoop26_C(tls, v, 1, stride, 8, thresh, ithresh, hev_thresh) +} + +func VFilter8i_C(tls *libc.TLS, u uintptr, v uintptr, stride int32, thresh int32, ithresh int32, hev_thresh int32) { /* dec.c:681:13: */ + FilterLoop24_C(tls, (u + uintptr((4 * stride))), stride, 1, 8, thresh, ithresh, hev_thresh) + FilterLoop24_C(tls, (v + uintptr((4 * stride))), stride, 1, 8, thresh, ithresh, hev_thresh) +} + +func HFilter8i_C(tls *libc.TLS, u uintptr, v uintptr, stride int32, thresh int32, ithresh int32, hev_thresh int32) { /* dec.c:689:13: */ + FilterLoop24_C(tls, (u + uintptr(4)), 1, stride, 8, thresh, ithresh, hev_thresh) + FilterLoop24_C(tls, (v + uintptr(4)), 1, stride, 8, thresh, ithresh, hev_thresh) +} + +//------------------------------------------------------------------------------ + +func DitherCombine8x8_C(tls *libc.TLS, dither uintptr, dst uintptr, dst_stride int32) { /* dec.c:698:13: */ + var i int32 + var j int32 + for j = 0; j < 8; j++ { + for i = 0; i < 8; i++ { + var delta0 int32 = (int32(*(*uint8_t)(unsafe.Pointer(dither + uintptr(i)))) - (int32(1) << 7)) + var delta1 int32 = ((delta0 + (int32(1) << (4 - 1))) >> 4) + *(*uint8_t)(unsafe.Pointer(dst + uintptr(i))) = clip_8b(tls, (int32(*(*uint8_t)(unsafe.Pointer(dst + uintptr(i)))) + delta1)) + } + dst += uintptr(dst_stride) + dither += uintptr(8) + } +} + +//------------------------------------------------------------------------------ + +var VP8Transform VP8DecIdct2 /* dec.c:715:13: */ +var VP8TransformAC3 VP8DecIdct /* dec.c:716:12: */ +var VP8TransformUV VP8DecIdct /* dec.c:717:12: */ +var VP8TransformDC VP8DecIdct /* dec.c:718:12: */ +var VP8TransformDCUV VP8DecIdct /* dec.c:719:12: */ + +var VP8VFilter16 VP8LumaFilterFunc /* dec.c:721:19: */ +var VP8HFilter16 VP8LumaFilterFunc /* dec.c:722:19: */ +var VP8VFilter8 VP8ChromaFilterFunc /* dec.c:723:21: */ +var VP8HFilter8 VP8ChromaFilterFunc /* dec.c:724:21: */ +var VP8VFilter16i VP8LumaFilterFunc /* dec.c:725:19: */ +var VP8HFilter16i VP8LumaFilterFunc /* dec.c:726:19: */ +var VP8VFilter8i VP8ChromaFilterFunc /* dec.c:727:21: */ +var VP8HFilter8i VP8ChromaFilterFunc /* dec.c:728:21: */ +var VP8SimpleVFilter16 VP8SimpleFilterFunc /* dec.c:729:21: */ +var VP8SimpleHFilter16 VP8SimpleFilterFunc /* dec.c:730:21: */ +var VP8SimpleVFilter16i VP8SimpleFilterFunc /* dec.c:731:21: */ +var VP8SimpleHFilter16i VP8SimpleFilterFunc /* dec.c:732:21: */ + +var VP8DitherCombine8x8 uintptr /* dec.c:734:6: */ + +func VP8DspInit(tls *libc.TLS) { /* dec.c:744:1: */ + for ok := true; ok; ok = (0 != 0) { + if VP8DspInit_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + VP8DspInit_body(tls) + VP8DspInit_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var VP8DspInit_body_last_cpuinfo_used VP8CPUInfo = 0 /* dec.c:744:1 */ + +func VP8DspInit_body(tls *libc.TLS) { /* dec.c:744:1: */ + VP8InitClipTables(tls) + + VP8TransformWHT = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) + }{TransformWHT_C})) + VP8Transform = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) + }{TransformTwo_C})) + VP8TransformDC = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) + }{TransformDC_C})) + VP8TransformAC3 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) + }{TransformAC3_C})) + VP8TransformUV = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) + }{TransformUV_C})) + VP8TransformDCUV = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) + }{TransformDCUV_C})) + + VP8VFilter16 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + }{VFilter16_C})) + VP8VFilter16i = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + }{VFilter16i_C})) + VP8HFilter16 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + }{HFilter16_C})) + VP8VFilter8 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, int32, int32, int32) + }{VFilter8_C})) + VP8VFilter8i = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, int32, int32, int32) + }{VFilter8i_C})) + VP8SimpleVFilter16 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32) + }{SimpleVFilter16_C})) + VP8SimpleHFilter16 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32) + }{SimpleHFilter16_C})) + VP8SimpleVFilter16i = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32) + }{SimpleVFilter16i_C})) + VP8SimpleHFilter16i = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32) + }{SimpleHFilter16i_C})) + + VP8HFilter16i = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + }{HFilter16i_C})) + VP8HFilter8 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, int32, int32, int32) + }{HFilter8_C})) + VP8HFilter8i = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, int32, int32, int32) + }{HFilter8i_C})) + + VP8PredLuma4[0] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{DC4_C})) + VP8PredLuma4[1] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{TM4_C})) + VP8PredLuma4[2] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{VE4_C})) + VP8PredLuma4[4] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{RD4_C})) + VP8PredLuma4[6] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{LD4_C})) + + VP8PredLuma4[3] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{HE4_C})) + VP8PredLuma4[5] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{VR4_C})) + VP8PredLuma4[7] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{VL4_C})) + VP8PredLuma4[8] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{HD4_C})) + VP8PredLuma4[9] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{HU4_C})) + + VP8PredLuma16[0] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{DC16_C})) + VP8PredLuma16[1] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{TM16_C})) + VP8PredLuma16[2] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{VE16_C})) + VP8PredLuma16[3] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{HE16_C})) + VP8PredLuma16[4] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{DC16NoTop_C})) + VP8PredLuma16[5] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{DC16NoLeft_C})) + VP8PredLuma16[6] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{DC16NoTopLeft_C})) + + VP8PredChroma8[0] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{DC8uv_C})) + VP8PredChroma8[1] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{TM8uv_C})) + VP8PredChroma8[2] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{VE8uv_C})) + VP8PredChroma8[3] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{HE8uv_C})) + VP8PredChroma8[4] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{DC8uvNoTop_C})) + VP8PredChroma8[5] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{DC8uvNoLeft_C})) + VP8PredChroma8[6] = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{DC8uvNoTopLeft_C})) + + VP8DitherCombine8x8 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) + }{DitherCombine8x8_C})) + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if VP8GetCPUInfo != (uintptr(0)) { + } + +} + +// define to 0 to have run-time table initialization + +var abs0 = [511]uint8_t{ + uint8_t(0xff), uint8_t(0xfe), uint8_t(0xfd), uint8_t(0xfc), uint8_t(0xfb), uint8_t(0xfa), uint8_t(0xf9), uint8_t(0xf8), uint8_t(0xf7), uint8_t(0xf6), uint8_t(0xf5), uint8_t(0xf4), + uint8_t(0xf3), uint8_t(0xf2), uint8_t(0xf1), uint8_t(0xf0), uint8_t(0xef), uint8_t(0xee), uint8_t(0xed), uint8_t(0xec), uint8_t(0xeb), uint8_t(0xea), uint8_t(0xe9), uint8_t(0xe8), + uint8_t(0xe7), uint8_t(0xe6), uint8_t(0xe5), uint8_t(0xe4), uint8_t(0xe3), uint8_t(0xe2), uint8_t(0xe1), uint8_t(0xe0), uint8_t(0xdf), uint8_t(0xde), uint8_t(0xdd), uint8_t(0xdc), + uint8_t(0xdb), uint8_t(0xda), uint8_t(0xd9), uint8_t(0xd8), uint8_t(0xd7), uint8_t(0xd6), uint8_t(0xd5), uint8_t(0xd4), uint8_t(0xd3), uint8_t(0xd2), uint8_t(0xd1), uint8_t(0xd0), + uint8_t(0xcf), uint8_t(0xce), uint8_t(0xcd), uint8_t(0xcc), uint8_t(0xcb), uint8_t(0xca), uint8_t(0xc9), uint8_t(0xc8), uint8_t(0xc7), uint8_t(0xc6), uint8_t(0xc5), uint8_t(0xc4), + uint8_t(0xc3), uint8_t(0xc2), uint8_t(0xc1), uint8_t(0xc0), uint8_t(0xbf), uint8_t(0xbe), uint8_t(0xbd), uint8_t(0xbc), uint8_t(0xbb), uint8_t(0xba), uint8_t(0xb9), uint8_t(0xb8), + uint8_t(0xb7), uint8_t(0xb6), uint8_t(0xb5), uint8_t(0xb4), uint8_t(0xb3), uint8_t(0xb2), uint8_t(0xb1), uint8_t(0xb0), uint8_t(0xaf), uint8_t(0xae), uint8_t(0xad), uint8_t(0xac), + uint8_t(0xab), uint8_t(0xaa), uint8_t(0xa9), uint8_t(0xa8), uint8_t(0xa7), uint8_t(0xa6), uint8_t(0xa5), uint8_t(0xa4), uint8_t(0xa3), uint8_t(0xa2), uint8_t(0xa1), uint8_t(0xa0), + uint8_t(0x9f), uint8_t(0x9e), uint8_t(0x9d), uint8_t(0x9c), uint8_t(0x9b), uint8_t(0x9a), uint8_t(0x99), uint8_t(0x98), uint8_t(0x97), uint8_t(0x96), uint8_t(0x95), uint8_t(0x94), + uint8_t(0x93), uint8_t(0x92), uint8_t(0x91), uint8_t(0x90), uint8_t(0x8f), uint8_t(0x8e), uint8_t(0x8d), uint8_t(0x8c), uint8_t(0x8b), uint8_t(0x8a), uint8_t(0x89), uint8_t(0x88), + uint8_t(0x87), uint8_t(0x86), uint8_t(0x85), uint8_t(0x84), uint8_t(0x83), uint8_t(0x82), uint8_t(0x81), uint8_t(0x80), uint8_t(0x7f), uint8_t(0x7e), uint8_t(0x7d), uint8_t(0x7c), + uint8_t(0x7b), uint8_t(0x7a), uint8_t(0x79), uint8_t(0x78), uint8_t(0x77), uint8_t(0x76), uint8_t(0x75), uint8_t(0x74), uint8_t(0x73), uint8_t(0x72), uint8_t(0x71), uint8_t(0x70), + uint8_t(0x6f), uint8_t(0x6e), uint8_t(0x6d), uint8_t(0x6c), uint8_t(0x6b), uint8_t(0x6a), uint8_t(0x69), uint8_t(0x68), uint8_t(0x67), uint8_t(0x66), uint8_t(0x65), uint8_t(0x64), + uint8_t(0x63), uint8_t(0x62), uint8_t(0x61), uint8_t(0x60), uint8_t(0x5f), uint8_t(0x5e), uint8_t(0x5d), uint8_t(0x5c), uint8_t(0x5b), uint8_t(0x5a), uint8_t(0x59), uint8_t(0x58), + uint8_t(0x57), uint8_t(0x56), uint8_t(0x55), uint8_t(0x54), uint8_t(0x53), uint8_t(0x52), uint8_t(0x51), uint8_t(0x50), uint8_t(0x4f), uint8_t(0x4e), uint8_t(0x4d), uint8_t(0x4c), + uint8_t(0x4b), uint8_t(0x4a), uint8_t(0x49), uint8_t(0x48), uint8_t(0x47), uint8_t(0x46), uint8_t(0x45), uint8_t(0x44), uint8_t(0x43), uint8_t(0x42), uint8_t(0x41), uint8_t(0x40), + uint8_t(0x3f), uint8_t(0x3e), uint8_t(0x3d), uint8_t(0x3c), uint8_t(0x3b), uint8_t(0x3a), uint8_t(0x39), uint8_t(0x38), uint8_t(0x37), uint8_t(0x36), uint8_t(0x35), uint8_t(0x34), + uint8_t(0x33), uint8_t(0x32), uint8_t(0x31), uint8_t(0x30), uint8_t(0x2f), uint8_t(0x2e), uint8_t(0x2d), uint8_t(0x2c), uint8_t(0x2b), uint8_t(0x2a), uint8_t(0x29), uint8_t(0x28), + uint8_t(0x27), uint8_t(0x26), uint8_t(0x25), uint8_t(0x24), uint8_t(0x23), uint8_t(0x22), uint8_t(0x21), uint8_t(0x20), uint8_t(0x1f), uint8_t(0x1e), uint8_t(0x1d), uint8_t(0x1c), + uint8_t(0x1b), uint8_t(0x1a), uint8_t(0x19), uint8_t(0x18), uint8_t(0x17), uint8_t(0x16), uint8_t(0x15), uint8_t(0x14), uint8_t(0x13), uint8_t(0x12), uint8_t(0x11), uint8_t(0x10), + uint8_t(0x0f), uint8_t(0x0e), uint8_t(0x0d), uint8_t(0x0c), uint8_t(0x0b), uint8_t(0x0a), uint8_t(0x09), uint8_t(0x08), uint8_t(0x07), uint8_t(0x06), uint8_t(0x05), uint8_t(0x04), + uint8_t(0x03), uint8_t(0x02), uint8_t(0x01), uint8_t(0x00), uint8_t(0x01), uint8_t(0x02), uint8_t(0x03), uint8_t(0x04), uint8_t(0x05), uint8_t(0x06), uint8_t(0x07), uint8_t(0x08), + uint8_t(0x09), uint8_t(0x0a), uint8_t(0x0b), uint8_t(0x0c), uint8_t(0x0d), uint8_t(0x0e), uint8_t(0x0f), uint8_t(0x10), uint8_t(0x11), uint8_t(0x12), uint8_t(0x13), uint8_t(0x14), + uint8_t(0x15), uint8_t(0x16), uint8_t(0x17), uint8_t(0x18), uint8_t(0x19), uint8_t(0x1a), uint8_t(0x1b), uint8_t(0x1c), uint8_t(0x1d), uint8_t(0x1e), uint8_t(0x1f), uint8_t(0x20), + uint8_t(0x21), uint8_t(0x22), uint8_t(0x23), uint8_t(0x24), uint8_t(0x25), uint8_t(0x26), uint8_t(0x27), uint8_t(0x28), uint8_t(0x29), uint8_t(0x2a), uint8_t(0x2b), uint8_t(0x2c), + uint8_t(0x2d), uint8_t(0x2e), uint8_t(0x2f), uint8_t(0x30), uint8_t(0x31), uint8_t(0x32), uint8_t(0x33), uint8_t(0x34), uint8_t(0x35), uint8_t(0x36), uint8_t(0x37), uint8_t(0x38), + uint8_t(0x39), uint8_t(0x3a), uint8_t(0x3b), uint8_t(0x3c), uint8_t(0x3d), uint8_t(0x3e), uint8_t(0x3f), uint8_t(0x40), uint8_t(0x41), uint8_t(0x42), uint8_t(0x43), uint8_t(0x44), + uint8_t(0x45), uint8_t(0x46), uint8_t(0x47), uint8_t(0x48), uint8_t(0x49), uint8_t(0x4a), uint8_t(0x4b), uint8_t(0x4c), uint8_t(0x4d), uint8_t(0x4e), uint8_t(0x4f), uint8_t(0x50), + uint8_t(0x51), uint8_t(0x52), uint8_t(0x53), uint8_t(0x54), uint8_t(0x55), uint8_t(0x56), uint8_t(0x57), uint8_t(0x58), uint8_t(0x59), uint8_t(0x5a), uint8_t(0x5b), uint8_t(0x5c), + uint8_t(0x5d), uint8_t(0x5e), uint8_t(0x5f), uint8_t(0x60), uint8_t(0x61), uint8_t(0x62), uint8_t(0x63), uint8_t(0x64), uint8_t(0x65), uint8_t(0x66), uint8_t(0x67), uint8_t(0x68), + uint8_t(0x69), uint8_t(0x6a), uint8_t(0x6b), uint8_t(0x6c), uint8_t(0x6d), uint8_t(0x6e), uint8_t(0x6f), uint8_t(0x70), uint8_t(0x71), uint8_t(0x72), uint8_t(0x73), uint8_t(0x74), + uint8_t(0x75), uint8_t(0x76), uint8_t(0x77), uint8_t(0x78), uint8_t(0x79), uint8_t(0x7a), uint8_t(0x7b), uint8_t(0x7c), uint8_t(0x7d), uint8_t(0x7e), uint8_t(0x7f), uint8_t(0x80), + uint8_t(0x81), uint8_t(0x82), uint8_t(0x83), uint8_t(0x84), uint8_t(0x85), uint8_t(0x86), uint8_t(0x87), uint8_t(0x88), uint8_t(0x89), uint8_t(0x8a), uint8_t(0x8b), uint8_t(0x8c), + uint8_t(0x8d), uint8_t(0x8e), uint8_t(0x8f), uint8_t(0x90), uint8_t(0x91), uint8_t(0x92), uint8_t(0x93), uint8_t(0x94), uint8_t(0x95), uint8_t(0x96), uint8_t(0x97), uint8_t(0x98), + uint8_t(0x99), uint8_t(0x9a), uint8_t(0x9b), uint8_t(0x9c), uint8_t(0x9d), uint8_t(0x9e), uint8_t(0x9f), uint8_t(0xa0), uint8_t(0xa1), uint8_t(0xa2), uint8_t(0xa3), uint8_t(0xa4), + uint8_t(0xa5), uint8_t(0xa6), uint8_t(0xa7), uint8_t(0xa8), uint8_t(0xa9), uint8_t(0xaa), uint8_t(0xab), uint8_t(0xac), uint8_t(0xad), uint8_t(0xae), uint8_t(0xaf), uint8_t(0xb0), + uint8_t(0xb1), uint8_t(0xb2), uint8_t(0xb3), uint8_t(0xb4), uint8_t(0xb5), uint8_t(0xb6), uint8_t(0xb7), uint8_t(0xb8), uint8_t(0xb9), uint8_t(0xba), uint8_t(0xbb), uint8_t(0xbc), + uint8_t(0xbd), uint8_t(0xbe), uint8_t(0xbf), uint8_t(0xc0), uint8_t(0xc1), uint8_t(0xc2), uint8_t(0xc3), uint8_t(0xc4), uint8_t(0xc5), uint8_t(0xc6), uint8_t(0xc7), uint8_t(0xc8), + uint8_t(0xc9), uint8_t(0xca), uint8_t(0xcb), uint8_t(0xcc), uint8_t(0xcd), uint8_t(0xce), uint8_t(0xcf), uint8_t(0xd0), uint8_t(0xd1), uint8_t(0xd2), uint8_t(0xd3), uint8_t(0xd4), + uint8_t(0xd5), uint8_t(0xd6), uint8_t(0xd7), uint8_t(0xd8), uint8_t(0xd9), uint8_t(0xda), uint8_t(0xdb), uint8_t(0xdc), uint8_t(0xdd), uint8_t(0xde), uint8_t(0xdf), uint8_t(0xe0), + uint8_t(0xe1), uint8_t(0xe2), uint8_t(0xe3), uint8_t(0xe4), uint8_t(0xe5), uint8_t(0xe6), uint8_t(0xe7), uint8_t(0xe8), uint8_t(0xe9), uint8_t(0xea), uint8_t(0xeb), uint8_t(0xec), + uint8_t(0xed), uint8_t(0xee), uint8_t(0xef), uint8_t(0xf0), uint8_t(0xf1), uint8_t(0xf2), uint8_t(0xf3), uint8_t(0xf4), uint8_t(0xf5), uint8_t(0xf6), uint8_t(0xf7), uint8_t(0xf8), + uint8_t(0xf9), uint8_t(0xfa), uint8_t(0xfb), uint8_t(0xfc), uint8_t(0xfd), uint8_t(0xfe), uint8_t(0xff), +} /* dec_clip_tables.c:23:22 */ + +var sclip1 = [2041]uint8_t{ + 0: uint8_t(0x80), 1: uint8_t(0x80), 2: uint8_t(0x80), 3: uint8_t(0x80), 4: uint8_t(0x80), 5: uint8_t(0x80), 6: uint8_t(0x80), 7: uint8_t(0x80), 8: uint8_t(0x80), 9: uint8_t(0x80), 10: uint8_t(0x80), 11: uint8_t(0x80), + 12: uint8_t(0x80), 13: uint8_t(0x80), 14: uint8_t(0x80), 15: uint8_t(0x80), 16: uint8_t(0x80), 17: uint8_t(0x80), 18: uint8_t(0x80), 19: uint8_t(0x80), 20: uint8_t(0x80), 21: uint8_t(0x80), 22: uint8_t(0x80), 23: uint8_t(0x80), + 24: uint8_t(0x80), 25: uint8_t(0x80), 26: uint8_t(0x80), 27: uint8_t(0x80), 28: uint8_t(0x80), 29: uint8_t(0x80), 30: uint8_t(0x80), 31: uint8_t(0x80), 32: uint8_t(0x80), 33: uint8_t(0x80), 34: uint8_t(0x80), 35: uint8_t(0x80), + 36: uint8_t(0x80), 37: uint8_t(0x80), 38: uint8_t(0x80), 39: uint8_t(0x80), 40: uint8_t(0x80), 41: uint8_t(0x80), 42: uint8_t(0x80), 43: uint8_t(0x80), 44: uint8_t(0x80), 45: uint8_t(0x80), 46: uint8_t(0x80), 47: uint8_t(0x80), + 48: uint8_t(0x80), 49: uint8_t(0x80), 50: uint8_t(0x80), 51: uint8_t(0x80), 52: uint8_t(0x80), 53: uint8_t(0x80), 54: uint8_t(0x80), 55: uint8_t(0x80), 56: uint8_t(0x80), 57: uint8_t(0x80), 58: uint8_t(0x80), 59: uint8_t(0x80), + 60: uint8_t(0x80), 61: uint8_t(0x80), 62: uint8_t(0x80), 63: uint8_t(0x80), 64: uint8_t(0x80), 65: uint8_t(0x80), 66: uint8_t(0x80), 67: uint8_t(0x80), 68: uint8_t(0x80), 69: uint8_t(0x80), 70: uint8_t(0x80), 71: uint8_t(0x80), + 72: uint8_t(0x80), 73: uint8_t(0x80), 74: uint8_t(0x80), 75: uint8_t(0x80), 76: uint8_t(0x80), 77: uint8_t(0x80), 78: uint8_t(0x80), 79: uint8_t(0x80), 80: uint8_t(0x80), 81: uint8_t(0x80), 82: uint8_t(0x80), 83: uint8_t(0x80), + 84: uint8_t(0x80), 85: uint8_t(0x80), 86: uint8_t(0x80), 87: uint8_t(0x80), 88: uint8_t(0x80), 89: uint8_t(0x80), 90: uint8_t(0x80), 91: uint8_t(0x80), 92: uint8_t(0x80), 93: uint8_t(0x80), 94: uint8_t(0x80), 95: uint8_t(0x80), + 96: uint8_t(0x80), 97: uint8_t(0x80), 98: uint8_t(0x80), 99: uint8_t(0x80), 100: uint8_t(0x80), 101: uint8_t(0x80), 102: uint8_t(0x80), 103: uint8_t(0x80), 104: uint8_t(0x80), 105: uint8_t(0x80), 106: uint8_t(0x80), 107: uint8_t(0x80), + 108: uint8_t(0x80), 109: uint8_t(0x80), 110: uint8_t(0x80), 111: uint8_t(0x80), 112: uint8_t(0x80), 113: uint8_t(0x80), 114: uint8_t(0x80), 115: uint8_t(0x80), 116: uint8_t(0x80), 117: uint8_t(0x80), 118: uint8_t(0x80), 119: uint8_t(0x80), + 120: uint8_t(0x80), 121: uint8_t(0x80), 122: uint8_t(0x80), 123: uint8_t(0x80), 124: uint8_t(0x80), 125: uint8_t(0x80), 126: uint8_t(0x80), 127: uint8_t(0x80), 128: uint8_t(0x80), 129: uint8_t(0x80), 130: uint8_t(0x80), 131: uint8_t(0x80), + 132: uint8_t(0x80), 133: uint8_t(0x80), 134: uint8_t(0x80), 135: uint8_t(0x80), 136: uint8_t(0x80), 137: uint8_t(0x80), 138: uint8_t(0x80), 139: uint8_t(0x80), 140: uint8_t(0x80), 141: uint8_t(0x80), 142: uint8_t(0x80), 143: uint8_t(0x80), + 144: uint8_t(0x80), 145: uint8_t(0x80), 146: uint8_t(0x80), 147: uint8_t(0x80), 148: uint8_t(0x80), 149: uint8_t(0x80), 150: uint8_t(0x80), 151: uint8_t(0x80), 152: uint8_t(0x80), 153: uint8_t(0x80), 154: uint8_t(0x80), 155: uint8_t(0x80), + 156: uint8_t(0x80), 157: uint8_t(0x80), 158: uint8_t(0x80), 159: uint8_t(0x80), 160: uint8_t(0x80), 161: uint8_t(0x80), 162: uint8_t(0x80), 163: uint8_t(0x80), 164: uint8_t(0x80), 165: uint8_t(0x80), 166: uint8_t(0x80), 167: uint8_t(0x80), + 168: uint8_t(0x80), 169: uint8_t(0x80), 170: uint8_t(0x80), 171: uint8_t(0x80), 172: uint8_t(0x80), 173: uint8_t(0x80), 174: uint8_t(0x80), 175: uint8_t(0x80), 176: uint8_t(0x80), 177: uint8_t(0x80), 178: uint8_t(0x80), 179: uint8_t(0x80), + 180: uint8_t(0x80), 181: uint8_t(0x80), 182: uint8_t(0x80), 183: uint8_t(0x80), 184: uint8_t(0x80), 185: uint8_t(0x80), 186: uint8_t(0x80), 187: uint8_t(0x80), 188: uint8_t(0x80), 189: uint8_t(0x80), 190: uint8_t(0x80), 191: uint8_t(0x80), + 192: uint8_t(0x80), 193: uint8_t(0x80), 194: uint8_t(0x80), 195: uint8_t(0x80), 196: uint8_t(0x80), 197: uint8_t(0x80), 198: uint8_t(0x80), 199: uint8_t(0x80), 200: uint8_t(0x80), 201: uint8_t(0x80), 202: uint8_t(0x80), 203: uint8_t(0x80), + 204: uint8_t(0x80), 205: uint8_t(0x80), 206: uint8_t(0x80), 207: uint8_t(0x80), 208: uint8_t(0x80), 209: uint8_t(0x80), 210: uint8_t(0x80), 211: uint8_t(0x80), 212: uint8_t(0x80), 213: uint8_t(0x80), 214: uint8_t(0x80), 215: uint8_t(0x80), + 216: uint8_t(0x80), 217: uint8_t(0x80), 218: uint8_t(0x80), 219: uint8_t(0x80), 220: uint8_t(0x80), 221: uint8_t(0x80), 222: uint8_t(0x80), 223: uint8_t(0x80), 224: uint8_t(0x80), 225: uint8_t(0x80), 226: uint8_t(0x80), 227: uint8_t(0x80), + 228: uint8_t(0x80), 229: uint8_t(0x80), 230: uint8_t(0x80), 231: uint8_t(0x80), 232: uint8_t(0x80), 233: uint8_t(0x80), 234: uint8_t(0x80), 235: uint8_t(0x80), 236: uint8_t(0x80), 237: uint8_t(0x80), 238: uint8_t(0x80), 239: uint8_t(0x80), + 240: uint8_t(0x80), 241: uint8_t(0x80), 242: uint8_t(0x80), 243: uint8_t(0x80), 244: uint8_t(0x80), 245: uint8_t(0x80), 246: uint8_t(0x80), 247: uint8_t(0x80), 248: uint8_t(0x80), 249: uint8_t(0x80), 250: uint8_t(0x80), 251: uint8_t(0x80), + 252: uint8_t(0x80), 253: uint8_t(0x80), 254: uint8_t(0x80), 255: uint8_t(0x80), 256: uint8_t(0x80), 257: uint8_t(0x80), 258: uint8_t(0x80), 259: uint8_t(0x80), 260: uint8_t(0x80), 261: uint8_t(0x80), 262: uint8_t(0x80), 263: uint8_t(0x80), + 264: uint8_t(0x80), 265: uint8_t(0x80), 266: uint8_t(0x80), 267: uint8_t(0x80), 268: uint8_t(0x80), 269: uint8_t(0x80), 270: uint8_t(0x80), 271: uint8_t(0x80), 272: uint8_t(0x80), 273: uint8_t(0x80), 274: uint8_t(0x80), 275: uint8_t(0x80), + 276: uint8_t(0x80), 277: uint8_t(0x80), 278: uint8_t(0x80), 279: uint8_t(0x80), 280: uint8_t(0x80), 281: uint8_t(0x80), 282: uint8_t(0x80), 283: uint8_t(0x80), 284: uint8_t(0x80), 285: uint8_t(0x80), 286: uint8_t(0x80), 287: uint8_t(0x80), + 288: uint8_t(0x80), 289: uint8_t(0x80), 290: uint8_t(0x80), 291: uint8_t(0x80), 292: uint8_t(0x80), 293: uint8_t(0x80), 294: uint8_t(0x80), 295: uint8_t(0x80), 296: uint8_t(0x80), 297: uint8_t(0x80), 298: uint8_t(0x80), 299: uint8_t(0x80), + 300: uint8_t(0x80), 301: uint8_t(0x80), 302: uint8_t(0x80), 303: uint8_t(0x80), 304: uint8_t(0x80), 305: uint8_t(0x80), 306: uint8_t(0x80), 307: uint8_t(0x80), 308: uint8_t(0x80), 309: uint8_t(0x80), 310: uint8_t(0x80), 311: uint8_t(0x80), + 312: uint8_t(0x80), 313: uint8_t(0x80), 314: uint8_t(0x80), 315: uint8_t(0x80), 316: uint8_t(0x80), 317: uint8_t(0x80), 318: uint8_t(0x80), 319: uint8_t(0x80), 320: uint8_t(0x80), 321: uint8_t(0x80), 322: uint8_t(0x80), 323: uint8_t(0x80), + 324: uint8_t(0x80), 325: uint8_t(0x80), 326: uint8_t(0x80), 327: uint8_t(0x80), 328: uint8_t(0x80), 329: uint8_t(0x80), 330: uint8_t(0x80), 331: uint8_t(0x80), 332: uint8_t(0x80), 333: uint8_t(0x80), 334: uint8_t(0x80), 335: uint8_t(0x80), + 336: uint8_t(0x80), 337: uint8_t(0x80), 338: uint8_t(0x80), 339: uint8_t(0x80), 340: uint8_t(0x80), 341: uint8_t(0x80), 342: uint8_t(0x80), 343: uint8_t(0x80), 344: uint8_t(0x80), 345: uint8_t(0x80), 346: uint8_t(0x80), 347: uint8_t(0x80), + 348: uint8_t(0x80), 349: uint8_t(0x80), 350: uint8_t(0x80), 351: uint8_t(0x80), 352: uint8_t(0x80), 353: uint8_t(0x80), 354: uint8_t(0x80), 355: uint8_t(0x80), 356: uint8_t(0x80), 357: uint8_t(0x80), 358: uint8_t(0x80), 359: uint8_t(0x80), + 360: uint8_t(0x80), 361: uint8_t(0x80), 362: uint8_t(0x80), 363: uint8_t(0x80), 364: uint8_t(0x80), 365: uint8_t(0x80), 366: uint8_t(0x80), 367: uint8_t(0x80), 368: uint8_t(0x80), 369: uint8_t(0x80), 370: uint8_t(0x80), 371: uint8_t(0x80), + 372: uint8_t(0x80), 373: uint8_t(0x80), 374: uint8_t(0x80), 375: uint8_t(0x80), 376: uint8_t(0x80), 377: uint8_t(0x80), 378: uint8_t(0x80), 379: uint8_t(0x80), 380: uint8_t(0x80), 381: uint8_t(0x80), 382: uint8_t(0x80), 383: uint8_t(0x80), + 384: uint8_t(0x80), 385: uint8_t(0x80), 386: uint8_t(0x80), 387: uint8_t(0x80), 388: uint8_t(0x80), 389: uint8_t(0x80), 390: uint8_t(0x80), 391: uint8_t(0x80), 392: uint8_t(0x80), 393: uint8_t(0x80), 394: uint8_t(0x80), 395: uint8_t(0x80), + 396: uint8_t(0x80), 397: uint8_t(0x80), 398: uint8_t(0x80), 399: uint8_t(0x80), 400: uint8_t(0x80), 401: uint8_t(0x80), 402: uint8_t(0x80), 403: uint8_t(0x80), 404: uint8_t(0x80), 405: uint8_t(0x80), 406: uint8_t(0x80), 407: uint8_t(0x80), + 408: uint8_t(0x80), 409: uint8_t(0x80), 410: uint8_t(0x80), 411: uint8_t(0x80), 412: uint8_t(0x80), 413: uint8_t(0x80), 414: uint8_t(0x80), 415: uint8_t(0x80), 416: uint8_t(0x80), 417: uint8_t(0x80), 418: uint8_t(0x80), 419: uint8_t(0x80), + 420: uint8_t(0x80), 421: uint8_t(0x80), 422: uint8_t(0x80), 423: uint8_t(0x80), 424: uint8_t(0x80), 425: uint8_t(0x80), 426: uint8_t(0x80), 427: uint8_t(0x80), 428: uint8_t(0x80), 429: uint8_t(0x80), 430: uint8_t(0x80), 431: uint8_t(0x80), + 432: uint8_t(0x80), 433: uint8_t(0x80), 434: uint8_t(0x80), 435: uint8_t(0x80), 436: uint8_t(0x80), 437: uint8_t(0x80), 438: uint8_t(0x80), 439: uint8_t(0x80), 440: uint8_t(0x80), 441: uint8_t(0x80), 442: uint8_t(0x80), 443: uint8_t(0x80), + 444: uint8_t(0x80), 445: uint8_t(0x80), 446: uint8_t(0x80), 447: uint8_t(0x80), 448: uint8_t(0x80), 449: uint8_t(0x80), 450: uint8_t(0x80), 451: uint8_t(0x80), 452: uint8_t(0x80), 453: uint8_t(0x80), 454: uint8_t(0x80), 455: uint8_t(0x80), + 456: uint8_t(0x80), 457: uint8_t(0x80), 458: uint8_t(0x80), 459: uint8_t(0x80), 460: uint8_t(0x80), 461: uint8_t(0x80), 462: uint8_t(0x80), 463: uint8_t(0x80), 464: uint8_t(0x80), 465: uint8_t(0x80), 466: uint8_t(0x80), 467: uint8_t(0x80), + 468: uint8_t(0x80), 469: uint8_t(0x80), 470: uint8_t(0x80), 471: uint8_t(0x80), 472: uint8_t(0x80), 473: uint8_t(0x80), 474: uint8_t(0x80), 475: uint8_t(0x80), 476: uint8_t(0x80), 477: uint8_t(0x80), 478: uint8_t(0x80), 479: uint8_t(0x80), + 480: uint8_t(0x80), 481: uint8_t(0x80), 482: uint8_t(0x80), 483: uint8_t(0x80), 484: uint8_t(0x80), 485: uint8_t(0x80), 486: uint8_t(0x80), 487: uint8_t(0x80), 488: uint8_t(0x80), 489: uint8_t(0x80), 490: uint8_t(0x80), 491: uint8_t(0x80), + 492: uint8_t(0x80), 493: uint8_t(0x80), 494: uint8_t(0x80), 495: uint8_t(0x80), 496: uint8_t(0x80), 497: uint8_t(0x80), 498: uint8_t(0x80), 499: uint8_t(0x80), 500: uint8_t(0x80), 501: uint8_t(0x80), 502: uint8_t(0x80), 503: uint8_t(0x80), + 504: uint8_t(0x80), 505: uint8_t(0x80), 506: uint8_t(0x80), 507: uint8_t(0x80), 508: uint8_t(0x80), 509: uint8_t(0x80), 510: uint8_t(0x80), 511: uint8_t(0x80), 512: uint8_t(0x80), 513: uint8_t(0x80), 514: uint8_t(0x80), 515: uint8_t(0x80), + 516: uint8_t(0x80), 517: uint8_t(0x80), 518: uint8_t(0x80), 519: uint8_t(0x80), 520: uint8_t(0x80), 521: uint8_t(0x80), 522: uint8_t(0x80), 523: uint8_t(0x80), 524: uint8_t(0x80), 525: uint8_t(0x80), 526: uint8_t(0x80), 527: uint8_t(0x80), + 528: uint8_t(0x80), 529: uint8_t(0x80), 530: uint8_t(0x80), 531: uint8_t(0x80), 532: uint8_t(0x80), 533: uint8_t(0x80), 534: uint8_t(0x80), 535: uint8_t(0x80), 536: uint8_t(0x80), 537: uint8_t(0x80), 538: uint8_t(0x80), 539: uint8_t(0x80), + 540: uint8_t(0x80), 541: uint8_t(0x80), 542: uint8_t(0x80), 543: uint8_t(0x80), 544: uint8_t(0x80), 545: uint8_t(0x80), 546: uint8_t(0x80), 547: uint8_t(0x80), 548: uint8_t(0x80), 549: uint8_t(0x80), 550: uint8_t(0x80), 551: uint8_t(0x80), + 552: uint8_t(0x80), 553: uint8_t(0x80), 554: uint8_t(0x80), 555: uint8_t(0x80), 556: uint8_t(0x80), 557: uint8_t(0x80), 558: uint8_t(0x80), 559: uint8_t(0x80), 560: uint8_t(0x80), 561: uint8_t(0x80), 562: uint8_t(0x80), 563: uint8_t(0x80), + 564: uint8_t(0x80), 565: uint8_t(0x80), 566: uint8_t(0x80), 567: uint8_t(0x80), 568: uint8_t(0x80), 569: uint8_t(0x80), 570: uint8_t(0x80), 571: uint8_t(0x80), 572: uint8_t(0x80), 573: uint8_t(0x80), 574: uint8_t(0x80), 575: uint8_t(0x80), + 576: uint8_t(0x80), 577: uint8_t(0x80), 578: uint8_t(0x80), 579: uint8_t(0x80), 580: uint8_t(0x80), 581: uint8_t(0x80), 582: uint8_t(0x80), 583: uint8_t(0x80), 584: uint8_t(0x80), 585: uint8_t(0x80), 586: uint8_t(0x80), 587: uint8_t(0x80), + 588: uint8_t(0x80), 589: uint8_t(0x80), 590: uint8_t(0x80), 591: uint8_t(0x80), 592: uint8_t(0x80), 593: uint8_t(0x80), 594: uint8_t(0x80), 595: uint8_t(0x80), 596: uint8_t(0x80), 597: uint8_t(0x80), 598: uint8_t(0x80), 599: uint8_t(0x80), + 600: uint8_t(0x80), 601: uint8_t(0x80), 602: uint8_t(0x80), 603: uint8_t(0x80), 604: uint8_t(0x80), 605: uint8_t(0x80), 606: uint8_t(0x80), 607: uint8_t(0x80), 608: uint8_t(0x80), 609: uint8_t(0x80), 610: uint8_t(0x80), 611: uint8_t(0x80), + 612: uint8_t(0x80), 613: uint8_t(0x80), 614: uint8_t(0x80), 615: uint8_t(0x80), 616: uint8_t(0x80), 617: uint8_t(0x80), 618: uint8_t(0x80), 619: uint8_t(0x80), 620: uint8_t(0x80), 621: uint8_t(0x80), 622: uint8_t(0x80), 623: uint8_t(0x80), + 624: uint8_t(0x80), 625: uint8_t(0x80), 626: uint8_t(0x80), 627: uint8_t(0x80), 628: uint8_t(0x80), 629: uint8_t(0x80), 630: uint8_t(0x80), 631: uint8_t(0x80), 632: uint8_t(0x80), 633: uint8_t(0x80), 634: uint8_t(0x80), 635: uint8_t(0x80), + 636: uint8_t(0x80), 637: uint8_t(0x80), 638: uint8_t(0x80), 639: uint8_t(0x80), 640: uint8_t(0x80), 641: uint8_t(0x80), 642: uint8_t(0x80), 643: uint8_t(0x80), 644: uint8_t(0x80), 645: uint8_t(0x80), 646: uint8_t(0x80), 647: uint8_t(0x80), + 648: uint8_t(0x80), 649: uint8_t(0x80), 650: uint8_t(0x80), 651: uint8_t(0x80), 652: uint8_t(0x80), 653: uint8_t(0x80), 654: uint8_t(0x80), 655: uint8_t(0x80), 656: uint8_t(0x80), 657: uint8_t(0x80), 658: uint8_t(0x80), 659: uint8_t(0x80), + 660: uint8_t(0x80), 661: uint8_t(0x80), 662: uint8_t(0x80), 663: uint8_t(0x80), 664: uint8_t(0x80), 665: uint8_t(0x80), 666: uint8_t(0x80), 667: uint8_t(0x80), 668: uint8_t(0x80), 669: uint8_t(0x80), 670: uint8_t(0x80), 671: uint8_t(0x80), + 672: uint8_t(0x80), 673: uint8_t(0x80), 674: uint8_t(0x80), 675: uint8_t(0x80), 676: uint8_t(0x80), 677: uint8_t(0x80), 678: uint8_t(0x80), 679: uint8_t(0x80), 680: uint8_t(0x80), 681: uint8_t(0x80), 682: uint8_t(0x80), 683: uint8_t(0x80), + 684: uint8_t(0x80), 685: uint8_t(0x80), 686: uint8_t(0x80), 687: uint8_t(0x80), 688: uint8_t(0x80), 689: uint8_t(0x80), 690: uint8_t(0x80), 691: uint8_t(0x80), 692: uint8_t(0x80), 693: uint8_t(0x80), 694: uint8_t(0x80), 695: uint8_t(0x80), + 696: uint8_t(0x80), 697: uint8_t(0x80), 698: uint8_t(0x80), 699: uint8_t(0x80), 700: uint8_t(0x80), 701: uint8_t(0x80), 702: uint8_t(0x80), 703: uint8_t(0x80), 704: uint8_t(0x80), 705: uint8_t(0x80), 706: uint8_t(0x80), 707: uint8_t(0x80), + 708: uint8_t(0x80), 709: uint8_t(0x80), 710: uint8_t(0x80), 711: uint8_t(0x80), 712: uint8_t(0x80), 713: uint8_t(0x80), 714: uint8_t(0x80), 715: uint8_t(0x80), 716: uint8_t(0x80), 717: uint8_t(0x80), 718: uint8_t(0x80), 719: uint8_t(0x80), + 720: uint8_t(0x80), 721: uint8_t(0x80), 722: uint8_t(0x80), 723: uint8_t(0x80), 724: uint8_t(0x80), 725: uint8_t(0x80), 726: uint8_t(0x80), 727: uint8_t(0x80), 728: uint8_t(0x80), 729: uint8_t(0x80), 730: uint8_t(0x80), 731: uint8_t(0x80), + 732: uint8_t(0x80), 733: uint8_t(0x80), 734: uint8_t(0x80), 735: uint8_t(0x80), 736: uint8_t(0x80), 737: uint8_t(0x80), 738: uint8_t(0x80), 739: uint8_t(0x80), 740: uint8_t(0x80), 741: uint8_t(0x80), 742: uint8_t(0x80), 743: uint8_t(0x80), + 744: uint8_t(0x80), 745: uint8_t(0x80), 746: uint8_t(0x80), 747: uint8_t(0x80), 748: uint8_t(0x80), 749: uint8_t(0x80), 750: uint8_t(0x80), 751: uint8_t(0x80), 752: uint8_t(0x80), 753: uint8_t(0x80), 754: uint8_t(0x80), 755: uint8_t(0x80), + 756: uint8_t(0x80), 757: uint8_t(0x80), 758: uint8_t(0x80), 759: uint8_t(0x80), 760: uint8_t(0x80), 761: uint8_t(0x80), 762: uint8_t(0x80), 763: uint8_t(0x80), 764: uint8_t(0x80), 765: uint8_t(0x80), 766: uint8_t(0x80), 767: uint8_t(0x80), + 768: uint8_t(0x80), 769: uint8_t(0x80), 770: uint8_t(0x80), 771: uint8_t(0x80), 772: uint8_t(0x80), 773: uint8_t(0x80), 774: uint8_t(0x80), 775: uint8_t(0x80), 776: uint8_t(0x80), 777: uint8_t(0x80), 778: uint8_t(0x80), 779: uint8_t(0x80), + 780: uint8_t(0x80), 781: uint8_t(0x80), 782: uint8_t(0x80), 783: uint8_t(0x80), 784: uint8_t(0x80), 785: uint8_t(0x80), 786: uint8_t(0x80), 787: uint8_t(0x80), 788: uint8_t(0x80), 789: uint8_t(0x80), 790: uint8_t(0x80), 791: uint8_t(0x80), + 792: uint8_t(0x80), 793: uint8_t(0x80), 794: uint8_t(0x80), 795: uint8_t(0x80), 796: uint8_t(0x80), 797: uint8_t(0x80), 798: uint8_t(0x80), 799: uint8_t(0x80), 800: uint8_t(0x80), 801: uint8_t(0x80), 802: uint8_t(0x80), 803: uint8_t(0x80), + 804: uint8_t(0x80), 805: uint8_t(0x80), 806: uint8_t(0x80), 807: uint8_t(0x80), 808: uint8_t(0x80), 809: uint8_t(0x80), 810: uint8_t(0x80), 811: uint8_t(0x80), 812: uint8_t(0x80), 813: uint8_t(0x80), 814: uint8_t(0x80), 815: uint8_t(0x80), + 816: uint8_t(0x80), 817: uint8_t(0x80), 818: uint8_t(0x80), 819: uint8_t(0x80), 820: uint8_t(0x80), 821: uint8_t(0x80), 822: uint8_t(0x80), 823: uint8_t(0x80), 824: uint8_t(0x80), 825: uint8_t(0x80), 826: uint8_t(0x80), 827: uint8_t(0x80), + 828: uint8_t(0x80), 829: uint8_t(0x80), 830: uint8_t(0x80), 831: uint8_t(0x80), 832: uint8_t(0x80), 833: uint8_t(0x80), 834: uint8_t(0x80), 835: uint8_t(0x80), 836: uint8_t(0x80), 837: uint8_t(0x80), 838: uint8_t(0x80), 839: uint8_t(0x80), + 840: uint8_t(0x80), 841: uint8_t(0x80), 842: uint8_t(0x80), 843: uint8_t(0x80), 844: uint8_t(0x80), 845: uint8_t(0x80), 846: uint8_t(0x80), 847: uint8_t(0x80), 848: uint8_t(0x80), 849: uint8_t(0x80), 850: uint8_t(0x80), 851: uint8_t(0x80), + 852: uint8_t(0x80), 853: uint8_t(0x80), 854: uint8_t(0x80), 855: uint8_t(0x80), 856: uint8_t(0x80), 857: uint8_t(0x80), 858: uint8_t(0x80), 859: uint8_t(0x80), 860: uint8_t(0x80), 861: uint8_t(0x80), 862: uint8_t(0x80), 863: uint8_t(0x80), + 864: uint8_t(0x80), 865: uint8_t(0x80), 866: uint8_t(0x80), 867: uint8_t(0x80), 868: uint8_t(0x80), 869: uint8_t(0x80), 870: uint8_t(0x80), 871: uint8_t(0x80), 872: uint8_t(0x80), 873: uint8_t(0x80), 874: uint8_t(0x80), 875: uint8_t(0x80), + 876: uint8_t(0x80), 877: uint8_t(0x80), 878: uint8_t(0x80), 879: uint8_t(0x80), 880: uint8_t(0x80), 881: uint8_t(0x80), 882: uint8_t(0x80), 883: uint8_t(0x80), 884: uint8_t(0x80), 885: uint8_t(0x80), 886: uint8_t(0x80), 887: uint8_t(0x80), + 888: uint8_t(0x80), 889: uint8_t(0x80), 890: uint8_t(0x80), 891: uint8_t(0x80), 892: uint8_t(0x80), 893: uint8_t(0x81), 894: uint8_t(0x82), 895: uint8_t(0x83), 896: uint8_t(0x84), 897: uint8_t(0x85), 898: uint8_t(0x86), 899: uint8_t(0x87), + 900: uint8_t(0x88), 901: uint8_t(0x89), 902: uint8_t(0x8a), 903: uint8_t(0x8b), 904: uint8_t(0x8c), 905: uint8_t(0x8d), 906: uint8_t(0x8e), 907: uint8_t(0x8f), 908: uint8_t(0x90), 909: uint8_t(0x91), 910: uint8_t(0x92), 911: uint8_t(0x93), + 912: uint8_t(0x94), 913: uint8_t(0x95), 914: uint8_t(0x96), 915: uint8_t(0x97), 916: uint8_t(0x98), 917: uint8_t(0x99), 918: uint8_t(0x9a), 919: uint8_t(0x9b), 920: uint8_t(0x9c), 921: uint8_t(0x9d), 922: uint8_t(0x9e), 923: uint8_t(0x9f), + 924: uint8_t(0xa0), 925: uint8_t(0xa1), 926: uint8_t(0xa2), 927: uint8_t(0xa3), 928: uint8_t(0xa4), 929: uint8_t(0xa5), 930: uint8_t(0xa6), 931: uint8_t(0xa7), 932: uint8_t(0xa8), 933: uint8_t(0xa9), 934: uint8_t(0xaa), 935: uint8_t(0xab), + 936: uint8_t(0xac), 937: uint8_t(0xad), 938: uint8_t(0xae), 939: uint8_t(0xaf), 940: uint8_t(0xb0), 941: uint8_t(0xb1), 942: uint8_t(0xb2), 943: uint8_t(0xb3), 944: uint8_t(0xb4), 945: uint8_t(0xb5), 946: uint8_t(0xb6), 947: uint8_t(0xb7), + 948: uint8_t(0xb8), 949: uint8_t(0xb9), 950: uint8_t(0xba), 951: uint8_t(0xbb), 952: uint8_t(0xbc), 953: uint8_t(0xbd), 954: uint8_t(0xbe), 955: uint8_t(0xbf), 956: uint8_t(0xc0), 957: uint8_t(0xc1), 958: uint8_t(0xc2), 959: uint8_t(0xc3), + 960: uint8_t(0xc4), 961: uint8_t(0xc5), 962: uint8_t(0xc6), 963: uint8_t(0xc7), 964: uint8_t(0xc8), 965: uint8_t(0xc9), 966: uint8_t(0xca), 967: uint8_t(0xcb), 968: uint8_t(0xcc), 969: uint8_t(0xcd), 970: uint8_t(0xce), 971: uint8_t(0xcf), + 972: uint8_t(0xd0), 973: uint8_t(0xd1), 974: uint8_t(0xd2), 975: uint8_t(0xd3), 976: uint8_t(0xd4), 977: uint8_t(0xd5), 978: uint8_t(0xd6), 979: uint8_t(0xd7), 980: uint8_t(0xd8), 981: uint8_t(0xd9), 982: uint8_t(0xda), 983: uint8_t(0xdb), + 984: uint8_t(0xdc), 985: uint8_t(0xdd), 986: uint8_t(0xde), 987: uint8_t(0xdf), 988: uint8_t(0xe0), 989: uint8_t(0xe1), 990: uint8_t(0xe2), 991: uint8_t(0xe3), 992: uint8_t(0xe4), 993: uint8_t(0xe5), 994: uint8_t(0xe6), 995: uint8_t(0xe7), + 996: uint8_t(0xe8), 997: uint8_t(0xe9), 998: uint8_t(0xea), 999: uint8_t(0xeb), 1000: uint8_t(0xec), 1001: uint8_t(0xed), 1002: uint8_t(0xee), 1003: uint8_t(0xef), 1004: uint8_t(0xf0), 1005: uint8_t(0xf1), 1006: uint8_t(0xf2), 1007: uint8_t(0xf3), + 1008: uint8_t(0xf4), 1009: uint8_t(0xf5), 1010: uint8_t(0xf6), 1011: uint8_t(0xf7), 1012: uint8_t(0xf8), 1013: uint8_t(0xf9), 1014: uint8_t(0xfa), 1015: uint8_t(0xfb), 1016: uint8_t(0xfc), 1017: uint8_t(0xfd), 1018: uint8_t(0xfe), 1019: uint8_t(0xff), + 1020: uint8_t(0x00), 1021: uint8_t(0x01), 1022: uint8_t(0x02), 1023: uint8_t(0x03), 1024: uint8_t(0x04), 1025: uint8_t(0x05), 1026: uint8_t(0x06), 1027: uint8_t(0x07), 1028: uint8_t(0x08), 1029: uint8_t(0x09), 1030: uint8_t(0x0a), 1031: uint8_t(0x0b), + 1032: uint8_t(0x0c), 1033: uint8_t(0x0d), 1034: uint8_t(0x0e), 1035: uint8_t(0x0f), 1036: uint8_t(0x10), 1037: uint8_t(0x11), 1038: uint8_t(0x12), 1039: uint8_t(0x13), 1040: uint8_t(0x14), 1041: uint8_t(0x15), 1042: uint8_t(0x16), 1043: uint8_t(0x17), + 1044: uint8_t(0x18), 1045: uint8_t(0x19), 1046: uint8_t(0x1a), 1047: uint8_t(0x1b), 1048: uint8_t(0x1c), 1049: uint8_t(0x1d), 1050: uint8_t(0x1e), 1051: uint8_t(0x1f), 1052: uint8_t(0x20), 1053: uint8_t(0x21), 1054: uint8_t(0x22), 1055: uint8_t(0x23), + 1056: uint8_t(0x24), 1057: uint8_t(0x25), 1058: uint8_t(0x26), 1059: uint8_t(0x27), 1060: uint8_t(0x28), 1061: uint8_t(0x29), 1062: uint8_t(0x2a), 1063: uint8_t(0x2b), 1064: uint8_t(0x2c), 1065: uint8_t(0x2d), 1066: uint8_t(0x2e), 1067: uint8_t(0x2f), + 1068: uint8_t(0x30), 1069: uint8_t(0x31), 1070: uint8_t(0x32), 1071: uint8_t(0x33), 1072: uint8_t(0x34), 1073: uint8_t(0x35), 1074: uint8_t(0x36), 1075: uint8_t(0x37), 1076: uint8_t(0x38), 1077: uint8_t(0x39), 1078: uint8_t(0x3a), 1079: uint8_t(0x3b), + 1080: uint8_t(0x3c), 1081: uint8_t(0x3d), 1082: uint8_t(0x3e), 1083: uint8_t(0x3f), 1084: uint8_t(0x40), 1085: uint8_t(0x41), 1086: uint8_t(0x42), 1087: uint8_t(0x43), 1088: uint8_t(0x44), 1089: uint8_t(0x45), 1090: uint8_t(0x46), 1091: uint8_t(0x47), + 1092: uint8_t(0x48), 1093: uint8_t(0x49), 1094: uint8_t(0x4a), 1095: uint8_t(0x4b), 1096: uint8_t(0x4c), 1097: uint8_t(0x4d), 1098: uint8_t(0x4e), 1099: uint8_t(0x4f), 1100: uint8_t(0x50), 1101: uint8_t(0x51), 1102: uint8_t(0x52), 1103: uint8_t(0x53), + 1104: uint8_t(0x54), 1105: uint8_t(0x55), 1106: uint8_t(0x56), 1107: uint8_t(0x57), 1108: uint8_t(0x58), 1109: uint8_t(0x59), 1110: uint8_t(0x5a), 1111: uint8_t(0x5b), 1112: uint8_t(0x5c), 1113: uint8_t(0x5d), 1114: uint8_t(0x5e), 1115: uint8_t(0x5f), + 1116: uint8_t(0x60), 1117: uint8_t(0x61), 1118: uint8_t(0x62), 1119: uint8_t(0x63), 1120: uint8_t(0x64), 1121: uint8_t(0x65), 1122: uint8_t(0x66), 1123: uint8_t(0x67), 1124: uint8_t(0x68), 1125: uint8_t(0x69), 1126: uint8_t(0x6a), 1127: uint8_t(0x6b), + 1128: uint8_t(0x6c), 1129: uint8_t(0x6d), 1130: uint8_t(0x6e), 1131: uint8_t(0x6f), 1132: uint8_t(0x70), 1133: uint8_t(0x71), 1134: uint8_t(0x72), 1135: uint8_t(0x73), 1136: uint8_t(0x74), 1137: uint8_t(0x75), 1138: uint8_t(0x76), 1139: uint8_t(0x77), + 1140: uint8_t(0x78), 1141: uint8_t(0x79), 1142: uint8_t(0x7a), 1143: uint8_t(0x7b), 1144: uint8_t(0x7c), 1145: uint8_t(0x7d), 1146: uint8_t(0x7e), 1147: uint8_t(0x7f), 1148: uint8_t(0x7f), 1149: uint8_t(0x7f), 1150: uint8_t(0x7f), 1151: uint8_t(0x7f), + 1152: uint8_t(0x7f), 1153: uint8_t(0x7f), 1154: uint8_t(0x7f), 1155: uint8_t(0x7f), 1156: uint8_t(0x7f), 1157: uint8_t(0x7f), 1158: uint8_t(0x7f), 1159: uint8_t(0x7f), 1160: uint8_t(0x7f), 1161: uint8_t(0x7f), 1162: uint8_t(0x7f), 1163: uint8_t(0x7f), + 1164: uint8_t(0x7f), 1165: uint8_t(0x7f), 1166: uint8_t(0x7f), 1167: uint8_t(0x7f), 1168: uint8_t(0x7f), 1169: uint8_t(0x7f), 1170: uint8_t(0x7f), 1171: uint8_t(0x7f), 1172: uint8_t(0x7f), 1173: uint8_t(0x7f), 1174: uint8_t(0x7f), 1175: uint8_t(0x7f), + 1176: uint8_t(0x7f), 1177: uint8_t(0x7f), 1178: uint8_t(0x7f), 1179: uint8_t(0x7f), 1180: uint8_t(0x7f), 1181: uint8_t(0x7f), 1182: uint8_t(0x7f), 1183: uint8_t(0x7f), 1184: uint8_t(0x7f), 1185: uint8_t(0x7f), 1186: uint8_t(0x7f), 1187: uint8_t(0x7f), + 1188: uint8_t(0x7f), 1189: uint8_t(0x7f), 1190: uint8_t(0x7f), 1191: uint8_t(0x7f), 1192: uint8_t(0x7f), 1193: uint8_t(0x7f), 1194: uint8_t(0x7f), 1195: uint8_t(0x7f), 1196: uint8_t(0x7f), 1197: uint8_t(0x7f), 1198: uint8_t(0x7f), 1199: uint8_t(0x7f), + 1200: uint8_t(0x7f), 1201: uint8_t(0x7f), 1202: uint8_t(0x7f), 1203: uint8_t(0x7f), 1204: uint8_t(0x7f), 1205: uint8_t(0x7f), 1206: uint8_t(0x7f), 1207: uint8_t(0x7f), 1208: uint8_t(0x7f), 1209: uint8_t(0x7f), 1210: uint8_t(0x7f), 1211: uint8_t(0x7f), + 1212: uint8_t(0x7f), 1213: uint8_t(0x7f), 1214: uint8_t(0x7f), 1215: uint8_t(0x7f), 1216: uint8_t(0x7f), 1217: uint8_t(0x7f), 1218: uint8_t(0x7f), 1219: uint8_t(0x7f), 1220: uint8_t(0x7f), 1221: uint8_t(0x7f), 1222: uint8_t(0x7f), 1223: uint8_t(0x7f), + 1224: uint8_t(0x7f), 1225: uint8_t(0x7f), 1226: uint8_t(0x7f), 1227: uint8_t(0x7f), 1228: uint8_t(0x7f), 1229: uint8_t(0x7f), 1230: uint8_t(0x7f), 1231: uint8_t(0x7f), 1232: uint8_t(0x7f), 1233: uint8_t(0x7f), 1234: uint8_t(0x7f), 1235: uint8_t(0x7f), + 1236: uint8_t(0x7f), 1237: uint8_t(0x7f), 1238: uint8_t(0x7f), 1239: uint8_t(0x7f), 1240: uint8_t(0x7f), 1241: uint8_t(0x7f), 1242: uint8_t(0x7f), 1243: uint8_t(0x7f), 1244: uint8_t(0x7f), 1245: uint8_t(0x7f), 1246: uint8_t(0x7f), 1247: uint8_t(0x7f), + 1248: uint8_t(0x7f), 1249: uint8_t(0x7f), 1250: uint8_t(0x7f), 1251: uint8_t(0x7f), 1252: uint8_t(0x7f), 1253: uint8_t(0x7f), 1254: uint8_t(0x7f), 1255: uint8_t(0x7f), 1256: uint8_t(0x7f), 1257: uint8_t(0x7f), 1258: uint8_t(0x7f), 1259: uint8_t(0x7f), + 1260: uint8_t(0x7f), 1261: uint8_t(0x7f), 1262: uint8_t(0x7f), 1263: uint8_t(0x7f), 1264: uint8_t(0x7f), 1265: uint8_t(0x7f), 1266: uint8_t(0x7f), 1267: uint8_t(0x7f), 1268: uint8_t(0x7f), 1269: uint8_t(0x7f), 1270: uint8_t(0x7f), 1271: uint8_t(0x7f), + 1272: uint8_t(0x7f), 1273: uint8_t(0x7f), 1274: uint8_t(0x7f), 1275: uint8_t(0x7f), 1276: uint8_t(0x7f), 1277: uint8_t(0x7f), 1278: uint8_t(0x7f), 1279: uint8_t(0x7f), 1280: uint8_t(0x7f), 1281: uint8_t(0x7f), 1282: uint8_t(0x7f), 1283: uint8_t(0x7f), + 1284: uint8_t(0x7f), 1285: uint8_t(0x7f), 1286: uint8_t(0x7f), 1287: uint8_t(0x7f), 1288: uint8_t(0x7f), 1289: uint8_t(0x7f), 1290: uint8_t(0x7f), 1291: uint8_t(0x7f), 1292: uint8_t(0x7f), 1293: uint8_t(0x7f), 1294: uint8_t(0x7f), 1295: uint8_t(0x7f), + 1296: uint8_t(0x7f), 1297: uint8_t(0x7f), 1298: uint8_t(0x7f), 1299: uint8_t(0x7f), 1300: uint8_t(0x7f), 1301: uint8_t(0x7f), 1302: uint8_t(0x7f), 1303: uint8_t(0x7f), 1304: uint8_t(0x7f), 1305: uint8_t(0x7f), 1306: uint8_t(0x7f), 1307: uint8_t(0x7f), + 1308: uint8_t(0x7f), 1309: uint8_t(0x7f), 1310: uint8_t(0x7f), 1311: uint8_t(0x7f), 1312: uint8_t(0x7f), 1313: uint8_t(0x7f), 1314: uint8_t(0x7f), 1315: uint8_t(0x7f), 1316: uint8_t(0x7f), 1317: uint8_t(0x7f), 1318: uint8_t(0x7f), 1319: uint8_t(0x7f), + 1320: uint8_t(0x7f), 1321: uint8_t(0x7f), 1322: uint8_t(0x7f), 1323: uint8_t(0x7f), 1324: uint8_t(0x7f), 1325: uint8_t(0x7f), 1326: uint8_t(0x7f), 1327: uint8_t(0x7f), 1328: uint8_t(0x7f), 1329: uint8_t(0x7f), 1330: uint8_t(0x7f), 1331: uint8_t(0x7f), + 1332: uint8_t(0x7f), 1333: uint8_t(0x7f), 1334: uint8_t(0x7f), 1335: uint8_t(0x7f), 1336: uint8_t(0x7f), 1337: uint8_t(0x7f), 1338: uint8_t(0x7f), 1339: uint8_t(0x7f), 1340: uint8_t(0x7f), 1341: uint8_t(0x7f), 1342: uint8_t(0x7f), 1343: uint8_t(0x7f), + 1344: uint8_t(0x7f), 1345: uint8_t(0x7f), 1346: uint8_t(0x7f), 1347: uint8_t(0x7f), 1348: uint8_t(0x7f), 1349: uint8_t(0x7f), 1350: uint8_t(0x7f), 1351: uint8_t(0x7f), 1352: uint8_t(0x7f), 1353: uint8_t(0x7f), 1354: uint8_t(0x7f), 1355: uint8_t(0x7f), + 1356: uint8_t(0x7f), 1357: uint8_t(0x7f), 1358: uint8_t(0x7f), 1359: uint8_t(0x7f), 1360: uint8_t(0x7f), 1361: uint8_t(0x7f), 1362: uint8_t(0x7f), 1363: uint8_t(0x7f), 1364: uint8_t(0x7f), 1365: uint8_t(0x7f), 1366: uint8_t(0x7f), 1367: uint8_t(0x7f), + 1368: uint8_t(0x7f), 1369: uint8_t(0x7f), 1370: uint8_t(0x7f), 1371: uint8_t(0x7f), 1372: uint8_t(0x7f), 1373: uint8_t(0x7f), 1374: uint8_t(0x7f), 1375: uint8_t(0x7f), 1376: uint8_t(0x7f), 1377: uint8_t(0x7f), 1378: uint8_t(0x7f), 1379: uint8_t(0x7f), + 1380: uint8_t(0x7f), 1381: uint8_t(0x7f), 1382: uint8_t(0x7f), 1383: uint8_t(0x7f), 1384: uint8_t(0x7f), 1385: uint8_t(0x7f), 1386: uint8_t(0x7f), 1387: uint8_t(0x7f), 1388: uint8_t(0x7f), 1389: uint8_t(0x7f), 1390: uint8_t(0x7f), 1391: uint8_t(0x7f), + 1392: uint8_t(0x7f), 1393: uint8_t(0x7f), 1394: uint8_t(0x7f), 1395: uint8_t(0x7f), 1396: uint8_t(0x7f), 1397: uint8_t(0x7f), 1398: uint8_t(0x7f), 1399: uint8_t(0x7f), 1400: uint8_t(0x7f), 1401: uint8_t(0x7f), 1402: uint8_t(0x7f), 1403: uint8_t(0x7f), + 1404: uint8_t(0x7f), 1405: uint8_t(0x7f), 1406: uint8_t(0x7f), 1407: uint8_t(0x7f), 1408: uint8_t(0x7f), 1409: uint8_t(0x7f), 1410: uint8_t(0x7f), 1411: uint8_t(0x7f), 1412: uint8_t(0x7f), 1413: uint8_t(0x7f), 1414: uint8_t(0x7f), 1415: uint8_t(0x7f), + 1416: uint8_t(0x7f), 1417: uint8_t(0x7f), 1418: uint8_t(0x7f), 1419: uint8_t(0x7f), 1420: uint8_t(0x7f), 1421: uint8_t(0x7f), 1422: uint8_t(0x7f), 1423: uint8_t(0x7f), 1424: uint8_t(0x7f), 1425: uint8_t(0x7f), 1426: uint8_t(0x7f), 1427: uint8_t(0x7f), + 1428: uint8_t(0x7f), 1429: uint8_t(0x7f), 1430: uint8_t(0x7f), 1431: uint8_t(0x7f), 1432: uint8_t(0x7f), 1433: uint8_t(0x7f), 1434: uint8_t(0x7f), 1435: uint8_t(0x7f), 1436: uint8_t(0x7f), 1437: uint8_t(0x7f), 1438: uint8_t(0x7f), 1439: uint8_t(0x7f), + 1440: uint8_t(0x7f), 1441: uint8_t(0x7f), 1442: uint8_t(0x7f), 1443: uint8_t(0x7f), 1444: uint8_t(0x7f), 1445: uint8_t(0x7f), 1446: uint8_t(0x7f), 1447: uint8_t(0x7f), 1448: uint8_t(0x7f), 1449: uint8_t(0x7f), 1450: uint8_t(0x7f), 1451: uint8_t(0x7f), + 1452: uint8_t(0x7f), 1453: uint8_t(0x7f), 1454: uint8_t(0x7f), 1455: uint8_t(0x7f), 1456: uint8_t(0x7f), 1457: uint8_t(0x7f), 1458: uint8_t(0x7f), 1459: uint8_t(0x7f), 1460: uint8_t(0x7f), 1461: uint8_t(0x7f), 1462: uint8_t(0x7f), 1463: uint8_t(0x7f), + 1464: uint8_t(0x7f), 1465: uint8_t(0x7f), 1466: uint8_t(0x7f), 1467: uint8_t(0x7f), 1468: uint8_t(0x7f), 1469: uint8_t(0x7f), 1470: uint8_t(0x7f), 1471: uint8_t(0x7f), 1472: uint8_t(0x7f), 1473: uint8_t(0x7f), 1474: uint8_t(0x7f), 1475: uint8_t(0x7f), + 1476: uint8_t(0x7f), 1477: uint8_t(0x7f), 1478: uint8_t(0x7f), 1479: uint8_t(0x7f), 1480: uint8_t(0x7f), 1481: uint8_t(0x7f), 1482: uint8_t(0x7f), 1483: uint8_t(0x7f), 1484: uint8_t(0x7f), 1485: uint8_t(0x7f), 1486: uint8_t(0x7f), 1487: uint8_t(0x7f), + 1488: uint8_t(0x7f), 1489: uint8_t(0x7f), 1490: uint8_t(0x7f), 1491: uint8_t(0x7f), 1492: uint8_t(0x7f), 1493: uint8_t(0x7f), 1494: uint8_t(0x7f), 1495: uint8_t(0x7f), 1496: uint8_t(0x7f), 1497: uint8_t(0x7f), 1498: uint8_t(0x7f), 1499: uint8_t(0x7f), + 1500: uint8_t(0x7f), 1501: uint8_t(0x7f), 1502: uint8_t(0x7f), 1503: uint8_t(0x7f), 1504: uint8_t(0x7f), 1505: uint8_t(0x7f), 1506: uint8_t(0x7f), 1507: uint8_t(0x7f), 1508: uint8_t(0x7f), 1509: uint8_t(0x7f), 1510: uint8_t(0x7f), 1511: uint8_t(0x7f), + 1512: uint8_t(0x7f), 1513: uint8_t(0x7f), 1514: uint8_t(0x7f), 1515: uint8_t(0x7f), 1516: uint8_t(0x7f), 1517: uint8_t(0x7f), 1518: uint8_t(0x7f), 1519: uint8_t(0x7f), 1520: uint8_t(0x7f), 1521: uint8_t(0x7f), 1522: uint8_t(0x7f), 1523: uint8_t(0x7f), + 1524: uint8_t(0x7f), 1525: uint8_t(0x7f), 1526: uint8_t(0x7f), 1527: uint8_t(0x7f), 1528: uint8_t(0x7f), 1529: uint8_t(0x7f), 1530: uint8_t(0x7f), 1531: uint8_t(0x7f), 1532: uint8_t(0x7f), 1533: uint8_t(0x7f), 1534: uint8_t(0x7f), 1535: uint8_t(0x7f), + 1536: uint8_t(0x7f), 1537: uint8_t(0x7f), 1538: uint8_t(0x7f), 1539: uint8_t(0x7f), 1540: uint8_t(0x7f), 1541: uint8_t(0x7f), 1542: uint8_t(0x7f), 1543: uint8_t(0x7f), 1544: uint8_t(0x7f), 1545: uint8_t(0x7f), 1546: uint8_t(0x7f), 1547: uint8_t(0x7f), + 1548: uint8_t(0x7f), 1549: uint8_t(0x7f), 1550: uint8_t(0x7f), 1551: uint8_t(0x7f), 1552: uint8_t(0x7f), 1553: uint8_t(0x7f), 1554: uint8_t(0x7f), 1555: uint8_t(0x7f), 1556: uint8_t(0x7f), 1557: uint8_t(0x7f), 1558: uint8_t(0x7f), 1559: uint8_t(0x7f), + 1560: uint8_t(0x7f), 1561: uint8_t(0x7f), 1562: uint8_t(0x7f), 1563: uint8_t(0x7f), 1564: uint8_t(0x7f), 1565: uint8_t(0x7f), 1566: uint8_t(0x7f), 1567: uint8_t(0x7f), 1568: uint8_t(0x7f), 1569: uint8_t(0x7f), 1570: uint8_t(0x7f), 1571: uint8_t(0x7f), + 1572: uint8_t(0x7f), 1573: uint8_t(0x7f), 1574: uint8_t(0x7f), 1575: uint8_t(0x7f), 1576: uint8_t(0x7f), 1577: uint8_t(0x7f), 1578: uint8_t(0x7f), 1579: uint8_t(0x7f), 1580: uint8_t(0x7f), 1581: uint8_t(0x7f), 1582: uint8_t(0x7f), 1583: uint8_t(0x7f), + 1584: uint8_t(0x7f), 1585: uint8_t(0x7f), 1586: uint8_t(0x7f), 1587: uint8_t(0x7f), 1588: uint8_t(0x7f), 1589: uint8_t(0x7f), 1590: uint8_t(0x7f), 1591: uint8_t(0x7f), 1592: uint8_t(0x7f), 1593: uint8_t(0x7f), 1594: uint8_t(0x7f), 1595: uint8_t(0x7f), + 1596: uint8_t(0x7f), 1597: uint8_t(0x7f), 1598: uint8_t(0x7f), 1599: uint8_t(0x7f), 1600: uint8_t(0x7f), 1601: uint8_t(0x7f), 1602: uint8_t(0x7f), 1603: uint8_t(0x7f), 1604: uint8_t(0x7f), 1605: uint8_t(0x7f), 1606: uint8_t(0x7f), 1607: uint8_t(0x7f), + 1608: uint8_t(0x7f), 1609: uint8_t(0x7f), 1610: uint8_t(0x7f), 1611: uint8_t(0x7f), 1612: uint8_t(0x7f), 1613: uint8_t(0x7f), 1614: uint8_t(0x7f), 1615: uint8_t(0x7f), 1616: uint8_t(0x7f), 1617: uint8_t(0x7f), 1618: uint8_t(0x7f), 1619: uint8_t(0x7f), + 1620: uint8_t(0x7f), 1621: uint8_t(0x7f), 1622: uint8_t(0x7f), 1623: uint8_t(0x7f), 1624: uint8_t(0x7f), 1625: uint8_t(0x7f), 1626: uint8_t(0x7f), 1627: uint8_t(0x7f), 1628: uint8_t(0x7f), 1629: uint8_t(0x7f), 1630: uint8_t(0x7f), 1631: uint8_t(0x7f), + 1632: uint8_t(0x7f), 1633: uint8_t(0x7f), 1634: uint8_t(0x7f), 1635: uint8_t(0x7f), 1636: uint8_t(0x7f), 1637: uint8_t(0x7f), 1638: uint8_t(0x7f), 1639: uint8_t(0x7f), 1640: uint8_t(0x7f), 1641: uint8_t(0x7f), 1642: uint8_t(0x7f), 1643: uint8_t(0x7f), + 1644: uint8_t(0x7f), 1645: uint8_t(0x7f), 1646: uint8_t(0x7f), 1647: uint8_t(0x7f), 1648: uint8_t(0x7f), 1649: uint8_t(0x7f), 1650: uint8_t(0x7f), 1651: uint8_t(0x7f), 1652: uint8_t(0x7f), 1653: uint8_t(0x7f), 1654: uint8_t(0x7f), 1655: uint8_t(0x7f), + 1656: uint8_t(0x7f), 1657: uint8_t(0x7f), 1658: uint8_t(0x7f), 1659: uint8_t(0x7f), 1660: uint8_t(0x7f), 1661: uint8_t(0x7f), 1662: uint8_t(0x7f), 1663: uint8_t(0x7f), 1664: uint8_t(0x7f), 1665: uint8_t(0x7f), 1666: uint8_t(0x7f), 1667: uint8_t(0x7f), + 1668: uint8_t(0x7f), 1669: uint8_t(0x7f), 1670: uint8_t(0x7f), 1671: uint8_t(0x7f), 1672: uint8_t(0x7f), 1673: uint8_t(0x7f), 1674: uint8_t(0x7f), 1675: uint8_t(0x7f), 1676: uint8_t(0x7f), 1677: uint8_t(0x7f), 1678: uint8_t(0x7f), 1679: uint8_t(0x7f), + 1680: uint8_t(0x7f), 1681: uint8_t(0x7f), 1682: uint8_t(0x7f), 1683: uint8_t(0x7f), 1684: uint8_t(0x7f), 1685: uint8_t(0x7f), 1686: uint8_t(0x7f), 1687: uint8_t(0x7f), 1688: uint8_t(0x7f), 1689: uint8_t(0x7f), 1690: uint8_t(0x7f), 1691: uint8_t(0x7f), + 1692: uint8_t(0x7f), 1693: uint8_t(0x7f), 1694: uint8_t(0x7f), 1695: uint8_t(0x7f), 1696: uint8_t(0x7f), 1697: uint8_t(0x7f), 1698: uint8_t(0x7f), 1699: uint8_t(0x7f), 1700: uint8_t(0x7f), 1701: uint8_t(0x7f), 1702: uint8_t(0x7f), 1703: uint8_t(0x7f), + 1704: uint8_t(0x7f), 1705: uint8_t(0x7f), 1706: uint8_t(0x7f), 1707: uint8_t(0x7f), 1708: uint8_t(0x7f), 1709: uint8_t(0x7f), 1710: uint8_t(0x7f), 1711: uint8_t(0x7f), 1712: uint8_t(0x7f), 1713: uint8_t(0x7f), 1714: uint8_t(0x7f), 1715: uint8_t(0x7f), + 1716: uint8_t(0x7f), 1717: uint8_t(0x7f), 1718: uint8_t(0x7f), 1719: uint8_t(0x7f), 1720: uint8_t(0x7f), 1721: uint8_t(0x7f), 1722: uint8_t(0x7f), 1723: uint8_t(0x7f), 1724: uint8_t(0x7f), 1725: uint8_t(0x7f), 1726: uint8_t(0x7f), 1727: uint8_t(0x7f), + 1728: uint8_t(0x7f), 1729: uint8_t(0x7f), 1730: uint8_t(0x7f), 1731: uint8_t(0x7f), 1732: uint8_t(0x7f), 1733: uint8_t(0x7f), 1734: uint8_t(0x7f), 1735: uint8_t(0x7f), 1736: uint8_t(0x7f), 1737: uint8_t(0x7f), 1738: uint8_t(0x7f), 1739: uint8_t(0x7f), + 1740: uint8_t(0x7f), 1741: uint8_t(0x7f), 1742: uint8_t(0x7f), 1743: uint8_t(0x7f), 1744: uint8_t(0x7f), 1745: uint8_t(0x7f), 1746: uint8_t(0x7f), 1747: uint8_t(0x7f), 1748: uint8_t(0x7f), 1749: uint8_t(0x7f), 1750: uint8_t(0x7f), 1751: uint8_t(0x7f), + 1752: uint8_t(0x7f), 1753: uint8_t(0x7f), 1754: uint8_t(0x7f), 1755: uint8_t(0x7f), 1756: uint8_t(0x7f), 1757: uint8_t(0x7f), 1758: uint8_t(0x7f), 1759: uint8_t(0x7f), 1760: uint8_t(0x7f), 1761: uint8_t(0x7f), 1762: uint8_t(0x7f), 1763: uint8_t(0x7f), + 1764: uint8_t(0x7f), 1765: uint8_t(0x7f), 1766: uint8_t(0x7f), 1767: uint8_t(0x7f), 1768: uint8_t(0x7f), 1769: uint8_t(0x7f), 1770: uint8_t(0x7f), 1771: uint8_t(0x7f), 1772: uint8_t(0x7f), 1773: uint8_t(0x7f), 1774: uint8_t(0x7f), 1775: uint8_t(0x7f), + 1776: uint8_t(0x7f), 1777: uint8_t(0x7f), 1778: uint8_t(0x7f), 1779: uint8_t(0x7f), 1780: uint8_t(0x7f), 1781: uint8_t(0x7f), 1782: uint8_t(0x7f), 1783: uint8_t(0x7f), 1784: uint8_t(0x7f), 1785: uint8_t(0x7f), 1786: uint8_t(0x7f), 1787: uint8_t(0x7f), + 1788: uint8_t(0x7f), 1789: uint8_t(0x7f), 1790: uint8_t(0x7f), 1791: uint8_t(0x7f), 1792: uint8_t(0x7f), 1793: uint8_t(0x7f), 1794: uint8_t(0x7f), 1795: uint8_t(0x7f), 1796: uint8_t(0x7f), 1797: uint8_t(0x7f), 1798: uint8_t(0x7f), 1799: uint8_t(0x7f), + 1800: uint8_t(0x7f), 1801: uint8_t(0x7f), 1802: uint8_t(0x7f), 1803: uint8_t(0x7f), 1804: uint8_t(0x7f), 1805: uint8_t(0x7f), 1806: uint8_t(0x7f), 1807: uint8_t(0x7f), 1808: uint8_t(0x7f), 1809: uint8_t(0x7f), 1810: uint8_t(0x7f), 1811: uint8_t(0x7f), + 1812: uint8_t(0x7f), 1813: uint8_t(0x7f), 1814: uint8_t(0x7f), 1815: uint8_t(0x7f), 1816: uint8_t(0x7f), 1817: uint8_t(0x7f), 1818: uint8_t(0x7f), 1819: uint8_t(0x7f), 1820: uint8_t(0x7f), 1821: uint8_t(0x7f), 1822: uint8_t(0x7f), 1823: uint8_t(0x7f), + 1824: uint8_t(0x7f), 1825: uint8_t(0x7f), 1826: uint8_t(0x7f), 1827: uint8_t(0x7f), 1828: uint8_t(0x7f), 1829: uint8_t(0x7f), 1830: uint8_t(0x7f), 1831: uint8_t(0x7f), 1832: uint8_t(0x7f), 1833: uint8_t(0x7f), 1834: uint8_t(0x7f), 1835: uint8_t(0x7f), + 1836: uint8_t(0x7f), 1837: uint8_t(0x7f), 1838: uint8_t(0x7f), 1839: uint8_t(0x7f), 1840: uint8_t(0x7f), 1841: uint8_t(0x7f), 1842: uint8_t(0x7f), 1843: uint8_t(0x7f), 1844: uint8_t(0x7f), 1845: uint8_t(0x7f), 1846: uint8_t(0x7f), 1847: uint8_t(0x7f), + 1848: uint8_t(0x7f), 1849: uint8_t(0x7f), 1850: uint8_t(0x7f), 1851: uint8_t(0x7f), 1852: uint8_t(0x7f), 1853: uint8_t(0x7f), 1854: uint8_t(0x7f), 1855: uint8_t(0x7f), 1856: uint8_t(0x7f), 1857: uint8_t(0x7f), 1858: uint8_t(0x7f), 1859: uint8_t(0x7f), + 1860: uint8_t(0x7f), 1861: uint8_t(0x7f), 1862: uint8_t(0x7f), 1863: uint8_t(0x7f), 1864: uint8_t(0x7f), 1865: uint8_t(0x7f), 1866: uint8_t(0x7f), 1867: uint8_t(0x7f), 1868: uint8_t(0x7f), 1869: uint8_t(0x7f), 1870: uint8_t(0x7f), 1871: uint8_t(0x7f), + 1872: uint8_t(0x7f), 1873: uint8_t(0x7f), 1874: uint8_t(0x7f), 1875: uint8_t(0x7f), 1876: uint8_t(0x7f), 1877: uint8_t(0x7f), 1878: uint8_t(0x7f), 1879: uint8_t(0x7f), 1880: uint8_t(0x7f), 1881: uint8_t(0x7f), 1882: uint8_t(0x7f), 1883: uint8_t(0x7f), + 1884: uint8_t(0x7f), 1885: uint8_t(0x7f), 1886: uint8_t(0x7f), 1887: uint8_t(0x7f), 1888: uint8_t(0x7f), 1889: uint8_t(0x7f), 1890: uint8_t(0x7f), 1891: uint8_t(0x7f), 1892: uint8_t(0x7f), 1893: uint8_t(0x7f), 1894: uint8_t(0x7f), 1895: uint8_t(0x7f), + 1896: uint8_t(0x7f), 1897: uint8_t(0x7f), 1898: uint8_t(0x7f), 1899: uint8_t(0x7f), 1900: uint8_t(0x7f), 1901: uint8_t(0x7f), 1902: uint8_t(0x7f), 1903: uint8_t(0x7f), 1904: uint8_t(0x7f), 1905: uint8_t(0x7f), 1906: uint8_t(0x7f), 1907: uint8_t(0x7f), + 1908: uint8_t(0x7f), 1909: uint8_t(0x7f), 1910: uint8_t(0x7f), 1911: uint8_t(0x7f), 1912: uint8_t(0x7f), 1913: uint8_t(0x7f), 1914: uint8_t(0x7f), 1915: uint8_t(0x7f), 1916: uint8_t(0x7f), 1917: uint8_t(0x7f), 1918: uint8_t(0x7f), 1919: uint8_t(0x7f), + 1920: uint8_t(0x7f), 1921: uint8_t(0x7f), 1922: uint8_t(0x7f), 1923: uint8_t(0x7f), 1924: uint8_t(0x7f), 1925: uint8_t(0x7f), 1926: uint8_t(0x7f), 1927: uint8_t(0x7f), 1928: uint8_t(0x7f), 1929: uint8_t(0x7f), 1930: uint8_t(0x7f), 1931: uint8_t(0x7f), + 1932: uint8_t(0x7f), 1933: uint8_t(0x7f), 1934: uint8_t(0x7f), 1935: uint8_t(0x7f), 1936: uint8_t(0x7f), 1937: uint8_t(0x7f), 1938: uint8_t(0x7f), 1939: uint8_t(0x7f), 1940: uint8_t(0x7f), 1941: uint8_t(0x7f), 1942: uint8_t(0x7f), 1943: uint8_t(0x7f), + 1944: uint8_t(0x7f), 1945: uint8_t(0x7f), 1946: uint8_t(0x7f), 1947: uint8_t(0x7f), 1948: uint8_t(0x7f), 1949: uint8_t(0x7f), 1950: uint8_t(0x7f), 1951: uint8_t(0x7f), 1952: uint8_t(0x7f), 1953: uint8_t(0x7f), 1954: uint8_t(0x7f), 1955: uint8_t(0x7f), + 1956: uint8_t(0x7f), 1957: uint8_t(0x7f), 1958: uint8_t(0x7f), 1959: uint8_t(0x7f), 1960: uint8_t(0x7f), 1961: uint8_t(0x7f), 1962: uint8_t(0x7f), 1963: uint8_t(0x7f), 1964: uint8_t(0x7f), 1965: uint8_t(0x7f), 1966: uint8_t(0x7f), 1967: uint8_t(0x7f), + 1968: uint8_t(0x7f), 1969: uint8_t(0x7f), 1970: uint8_t(0x7f), 1971: uint8_t(0x7f), 1972: uint8_t(0x7f), 1973: uint8_t(0x7f), 1974: uint8_t(0x7f), 1975: uint8_t(0x7f), 1976: uint8_t(0x7f), 1977: uint8_t(0x7f), 1978: uint8_t(0x7f), 1979: uint8_t(0x7f), + 1980: uint8_t(0x7f), 1981: uint8_t(0x7f), 1982: uint8_t(0x7f), 1983: uint8_t(0x7f), 1984: uint8_t(0x7f), 1985: uint8_t(0x7f), 1986: uint8_t(0x7f), 1987: uint8_t(0x7f), 1988: uint8_t(0x7f), 1989: uint8_t(0x7f), 1990: uint8_t(0x7f), 1991: uint8_t(0x7f), + 1992: uint8_t(0x7f), 1993: uint8_t(0x7f), 1994: uint8_t(0x7f), 1995: uint8_t(0x7f), 1996: uint8_t(0x7f), 1997: uint8_t(0x7f), 1998: uint8_t(0x7f), 1999: uint8_t(0x7f), 2000: uint8_t(0x7f), 2001: uint8_t(0x7f), 2002: uint8_t(0x7f), 2003: uint8_t(0x7f), + 2004: uint8_t(0x7f), 2005: uint8_t(0x7f), 2006: uint8_t(0x7f), 2007: uint8_t(0x7f), 2008: uint8_t(0x7f), 2009: uint8_t(0x7f), 2010: uint8_t(0x7f), 2011: uint8_t(0x7f), 2012: uint8_t(0x7f), 2013: uint8_t(0x7f), 2014: uint8_t(0x7f), 2015: uint8_t(0x7f), + 2016: uint8_t(0x7f), 2017: uint8_t(0x7f), 2018: uint8_t(0x7f), 2019: uint8_t(0x7f), 2020: uint8_t(0x7f), 2021: uint8_t(0x7f), 2022: uint8_t(0x7f), 2023: uint8_t(0x7f), 2024: uint8_t(0x7f), 2025: uint8_t(0x7f), 2026: uint8_t(0x7f), 2027: uint8_t(0x7f), + 2028: uint8_t(0x7f), 2029: uint8_t(0x7f), 2030: uint8_t(0x7f), 2031: uint8_t(0x7f), 2032: uint8_t(0x7f), 2033: uint8_t(0x7f), 2034: uint8_t(0x7f), 2035: uint8_t(0x7f), 2036: uint8_t(0x7f), 2037: uint8_t(0x7f), 2038: uint8_t(0x7f), 2039: uint8_t(0x7f), +} /* dec_clip_tables.c:69:22 */ + +var sclip2 = [225]uint8_t{ + 0: uint8_t(0xf0), 1: uint8_t(0xf0), 2: uint8_t(0xf0), 3: uint8_t(0xf0), 4: uint8_t(0xf0), 5: uint8_t(0xf0), 6: uint8_t(0xf0), 7: uint8_t(0xf0), 8: uint8_t(0xf0), 9: uint8_t(0xf0), 10: uint8_t(0xf0), 11: uint8_t(0xf0), + 12: uint8_t(0xf0), 13: uint8_t(0xf0), 14: uint8_t(0xf0), 15: uint8_t(0xf0), 16: uint8_t(0xf0), 17: uint8_t(0xf0), 18: uint8_t(0xf0), 19: uint8_t(0xf0), 20: uint8_t(0xf0), 21: uint8_t(0xf0), 22: uint8_t(0xf0), 23: uint8_t(0xf0), + 24: uint8_t(0xf0), 25: uint8_t(0xf0), 26: uint8_t(0xf0), 27: uint8_t(0xf0), 28: uint8_t(0xf0), 29: uint8_t(0xf0), 30: uint8_t(0xf0), 31: uint8_t(0xf0), 32: uint8_t(0xf0), 33: uint8_t(0xf0), 34: uint8_t(0xf0), 35: uint8_t(0xf0), + 36: uint8_t(0xf0), 37: uint8_t(0xf0), 38: uint8_t(0xf0), 39: uint8_t(0xf0), 40: uint8_t(0xf0), 41: uint8_t(0xf0), 42: uint8_t(0xf0), 43: uint8_t(0xf0), 44: uint8_t(0xf0), 45: uint8_t(0xf0), 46: uint8_t(0xf0), 47: uint8_t(0xf0), + 48: uint8_t(0xf0), 49: uint8_t(0xf0), 50: uint8_t(0xf0), 51: uint8_t(0xf0), 52: uint8_t(0xf0), 53: uint8_t(0xf0), 54: uint8_t(0xf0), 55: uint8_t(0xf0), 56: uint8_t(0xf0), 57: uint8_t(0xf0), 58: uint8_t(0xf0), 59: uint8_t(0xf0), + 60: uint8_t(0xf0), 61: uint8_t(0xf0), 62: uint8_t(0xf0), 63: uint8_t(0xf0), 64: uint8_t(0xf0), 65: uint8_t(0xf0), 66: uint8_t(0xf0), 67: uint8_t(0xf0), 68: uint8_t(0xf0), 69: uint8_t(0xf0), 70: uint8_t(0xf0), 71: uint8_t(0xf0), + 72: uint8_t(0xf0), 73: uint8_t(0xf0), 74: uint8_t(0xf0), 75: uint8_t(0xf0), 76: uint8_t(0xf0), 77: uint8_t(0xf0), 78: uint8_t(0xf0), 79: uint8_t(0xf0), 80: uint8_t(0xf0), 81: uint8_t(0xf0), 82: uint8_t(0xf0), 83: uint8_t(0xf0), + 84: uint8_t(0xf0), 85: uint8_t(0xf0), 86: uint8_t(0xf0), 87: uint8_t(0xf0), 88: uint8_t(0xf0), 89: uint8_t(0xf0), 90: uint8_t(0xf0), 91: uint8_t(0xf0), 92: uint8_t(0xf0), 93: uint8_t(0xf0), 94: uint8_t(0xf0), 95: uint8_t(0xf0), + 96: uint8_t(0xf0), 97: uint8_t(0xf1), 98: uint8_t(0xf2), 99: uint8_t(0xf3), 100: uint8_t(0xf4), 101: uint8_t(0xf5), 102: uint8_t(0xf6), 103: uint8_t(0xf7), 104: uint8_t(0xf8), 105: uint8_t(0xf9), 106: uint8_t(0xfa), 107: uint8_t(0xfb), + 108: uint8_t(0xfc), 109: uint8_t(0xfd), 110: uint8_t(0xfe), 111: uint8_t(0xff), 112: uint8_t(0x00), 113: uint8_t(0x01), 114: uint8_t(0x02), 115: uint8_t(0x03), 116: uint8_t(0x04), 117: uint8_t(0x05), 118: uint8_t(0x06), 119: uint8_t(0x07), + 120: uint8_t(0x08), 121: uint8_t(0x09), 122: uint8_t(0x0a), 123: uint8_t(0x0b), 124: uint8_t(0x0c), 125: uint8_t(0x0d), 126: uint8_t(0x0e), 127: uint8_t(0x0f), 128: uint8_t(0x0f), 129: uint8_t(0x0f), 130: uint8_t(0x0f), 131: uint8_t(0x0f), + 132: uint8_t(0x0f), 133: uint8_t(0x0f), 134: uint8_t(0x0f), 135: uint8_t(0x0f), 136: uint8_t(0x0f), 137: uint8_t(0x0f), 138: uint8_t(0x0f), 139: uint8_t(0x0f), 140: uint8_t(0x0f), 141: uint8_t(0x0f), 142: uint8_t(0x0f), 143: uint8_t(0x0f), + 144: uint8_t(0x0f), 145: uint8_t(0x0f), 146: uint8_t(0x0f), 147: uint8_t(0x0f), 148: uint8_t(0x0f), 149: uint8_t(0x0f), 150: uint8_t(0x0f), 151: uint8_t(0x0f), 152: uint8_t(0x0f), 153: uint8_t(0x0f), 154: uint8_t(0x0f), 155: uint8_t(0x0f), + 156: uint8_t(0x0f), 157: uint8_t(0x0f), 158: uint8_t(0x0f), 159: uint8_t(0x0f), 160: uint8_t(0x0f), 161: uint8_t(0x0f), 162: uint8_t(0x0f), 163: uint8_t(0x0f), 164: uint8_t(0x0f), 165: uint8_t(0x0f), 166: uint8_t(0x0f), 167: uint8_t(0x0f), + 168: uint8_t(0x0f), 169: uint8_t(0x0f), 170: uint8_t(0x0f), 171: uint8_t(0x0f), 172: uint8_t(0x0f), 173: uint8_t(0x0f), 174: uint8_t(0x0f), 175: uint8_t(0x0f), 176: uint8_t(0x0f), 177: uint8_t(0x0f), 178: uint8_t(0x0f), 179: uint8_t(0x0f), + 180: uint8_t(0x0f), 181: uint8_t(0x0f), 182: uint8_t(0x0f), 183: uint8_t(0x0f), 184: uint8_t(0x0f), 185: uint8_t(0x0f), 186: uint8_t(0x0f), 187: uint8_t(0x0f), 188: uint8_t(0x0f), 189: uint8_t(0x0f), 190: uint8_t(0x0f), 191: uint8_t(0x0f), + 192: uint8_t(0x0f), 193: uint8_t(0x0f), 194: uint8_t(0x0f), 195: uint8_t(0x0f), 196: uint8_t(0x0f), 197: uint8_t(0x0f), 198: uint8_t(0x0f), 199: uint8_t(0x0f), 200: uint8_t(0x0f), 201: uint8_t(0x0f), 202: uint8_t(0x0f), 203: uint8_t(0x0f), + 204: uint8_t(0x0f), 205: uint8_t(0x0f), 206: uint8_t(0x0f), 207: uint8_t(0x0f), 208: uint8_t(0x0f), 209: uint8_t(0x0f), 210: uint8_t(0x0f), 211: uint8_t(0x0f), 212: uint8_t(0x0f), 213: uint8_t(0x0f), 214: uint8_t(0x0f), 215: uint8_t(0x0f), + 216: uint8_t(0x0f), 217: uint8_t(0x0f), 218: uint8_t(0x0f), 219: uint8_t(0x0f), 220: uint8_t(0x0f), 221: uint8_t(0x0f), 222: uint8_t(0x0f), 223: uint8_t(0x0f), +} /* dec_clip_tables.c:242:22 */ + +var clip1 = [767]uint8_t{ + 0: uint8_t(0x00), 1: uint8_t(0x00), 2: uint8_t(0x00), 3: uint8_t(0x00), 4: uint8_t(0x00), 5: uint8_t(0x00), 6: uint8_t(0x00), 7: uint8_t(0x00), 8: uint8_t(0x00), 9: uint8_t(0x00), 10: uint8_t(0x00), 11: uint8_t(0x00), + 12: uint8_t(0x00), 13: uint8_t(0x00), 14: uint8_t(0x00), 15: uint8_t(0x00), 16: uint8_t(0x00), 17: uint8_t(0x00), 18: uint8_t(0x00), 19: uint8_t(0x00), 20: uint8_t(0x00), 21: uint8_t(0x00), 22: uint8_t(0x00), 23: uint8_t(0x00), + 24: uint8_t(0x00), 25: uint8_t(0x00), 26: uint8_t(0x00), 27: uint8_t(0x00), 28: uint8_t(0x00), 29: uint8_t(0x00), 30: uint8_t(0x00), 31: uint8_t(0x00), 32: uint8_t(0x00), 33: uint8_t(0x00), 34: uint8_t(0x00), 35: uint8_t(0x00), + 36: uint8_t(0x00), 37: uint8_t(0x00), 38: uint8_t(0x00), 39: uint8_t(0x00), 40: uint8_t(0x00), 41: uint8_t(0x00), 42: uint8_t(0x00), 43: uint8_t(0x00), 44: uint8_t(0x00), 45: uint8_t(0x00), 46: uint8_t(0x00), 47: uint8_t(0x00), + 48: uint8_t(0x00), 49: uint8_t(0x00), 50: uint8_t(0x00), 51: uint8_t(0x00), 52: uint8_t(0x00), 53: uint8_t(0x00), 54: uint8_t(0x00), 55: uint8_t(0x00), 56: uint8_t(0x00), 57: uint8_t(0x00), 58: uint8_t(0x00), 59: uint8_t(0x00), + 60: uint8_t(0x00), 61: uint8_t(0x00), 62: uint8_t(0x00), 63: uint8_t(0x00), 64: uint8_t(0x00), 65: uint8_t(0x00), 66: uint8_t(0x00), 67: uint8_t(0x00), 68: uint8_t(0x00), 69: uint8_t(0x00), 70: uint8_t(0x00), 71: uint8_t(0x00), + 72: uint8_t(0x00), 73: uint8_t(0x00), 74: uint8_t(0x00), 75: uint8_t(0x00), 76: uint8_t(0x00), 77: uint8_t(0x00), 78: uint8_t(0x00), 79: uint8_t(0x00), 80: uint8_t(0x00), 81: uint8_t(0x00), 82: uint8_t(0x00), 83: uint8_t(0x00), + 84: uint8_t(0x00), 85: uint8_t(0x00), 86: uint8_t(0x00), 87: uint8_t(0x00), 88: uint8_t(0x00), 89: uint8_t(0x00), 90: uint8_t(0x00), 91: uint8_t(0x00), 92: uint8_t(0x00), 93: uint8_t(0x00), 94: uint8_t(0x00), 95: uint8_t(0x00), + 96: uint8_t(0x00), 97: uint8_t(0x00), 98: uint8_t(0x00), 99: uint8_t(0x00), 100: uint8_t(0x00), 101: uint8_t(0x00), 102: uint8_t(0x00), 103: uint8_t(0x00), 104: uint8_t(0x00), 105: uint8_t(0x00), 106: uint8_t(0x00), 107: uint8_t(0x00), + 108: uint8_t(0x00), 109: uint8_t(0x00), 110: uint8_t(0x00), 111: uint8_t(0x00), 112: uint8_t(0x00), 113: uint8_t(0x00), 114: uint8_t(0x00), 115: uint8_t(0x00), 116: uint8_t(0x00), 117: uint8_t(0x00), 118: uint8_t(0x00), 119: uint8_t(0x00), + 120: uint8_t(0x00), 121: uint8_t(0x00), 122: uint8_t(0x00), 123: uint8_t(0x00), 124: uint8_t(0x00), 125: uint8_t(0x00), 126: uint8_t(0x00), 127: uint8_t(0x00), 128: uint8_t(0x00), 129: uint8_t(0x00), 130: uint8_t(0x00), 131: uint8_t(0x00), + 132: uint8_t(0x00), 133: uint8_t(0x00), 134: uint8_t(0x00), 135: uint8_t(0x00), 136: uint8_t(0x00), 137: uint8_t(0x00), 138: uint8_t(0x00), 139: uint8_t(0x00), 140: uint8_t(0x00), 141: uint8_t(0x00), 142: uint8_t(0x00), 143: uint8_t(0x00), + 144: uint8_t(0x00), 145: uint8_t(0x00), 146: uint8_t(0x00), 147: uint8_t(0x00), 148: uint8_t(0x00), 149: uint8_t(0x00), 150: uint8_t(0x00), 151: uint8_t(0x00), 152: uint8_t(0x00), 153: uint8_t(0x00), 154: uint8_t(0x00), 155: uint8_t(0x00), + 156: uint8_t(0x00), 157: uint8_t(0x00), 158: uint8_t(0x00), 159: uint8_t(0x00), 160: uint8_t(0x00), 161: uint8_t(0x00), 162: uint8_t(0x00), 163: uint8_t(0x00), 164: uint8_t(0x00), 165: uint8_t(0x00), 166: uint8_t(0x00), 167: uint8_t(0x00), + 168: uint8_t(0x00), 169: uint8_t(0x00), 170: uint8_t(0x00), 171: uint8_t(0x00), 172: uint8_t(0x00), 173: uint8_t(0x00), 174: uint8_t(0x00), 175: uint8_t(0x00), 176: uint8_t(0x00), 177: uint8_t(0x00), 178: uint8_t(0x00), 179: uint8_t(0x00), + 180: uint8_t(0x00), 181: uint8_t(0x00), 182: uint8_t(0x00), 183: uint8_t(0x00), 184: uint8_t(0x00), 185: uint8_t(0x00), 186: uint8_t(0x00), 187: uint8_t(0x00), 188: uint8_t(0x00), 189: uint8_t(0x00), 190: uint8_t(0x00), 191: uint8_t(0x00), + 192: uint8_t(0x00), 193: uint8_t(0x00), 194: uint8_t(0x00), 195: uint8_t(0x00), 196: uint8_t(0x00), 197: uint8_t(0x00), 198: uint8_t(0x00), 199: uint8_t(0x00), 200: uint8_t(0x00), 201: uint8_t(0x00), 202: uint8_t(0x00), 203: uint8_t(0x00), + 204: uint8_t(0x00), 205: uint8_t(0x00), 206: uint8_t(0x00), 207: uint8_t(0x00), 208: uint8_t(0x00), 209: uint8_t(0x00), 210: uint8_t(0x00), 211: uint8_t(0x00), 212: uint8_t(0x00), 213: uint8_t(0x00), 214: uint8_t(0x00), 215: uint8_t(0x00), + 216: uint8_t(0x00), 217: uint8_t(0x00), 218: uint8_t(0x00), 219: uint8_t(0x00), 220: uint8_t(0x00), 221: uint8_t(0x00), 222: uint8_t(0x00), 223: uint8_t(0x00), 224: uint8_t(0x00), 225: uint8_t(0x00), 226: uint8_t(0x00), 227: uint8_t(0x00), + 228: uint8_t(0x00), 229: uint8_t(0x00), 230: uint8_t(0x00), 231: uint8_t(0x00), 232: uint8_t(0x00), 233: uint8_t(0x00), 234: uint8_t(0x00), 235: uint8_t(0x00), 236: uint8_t(0x00), 237: uint8_t(0x00), 238: uint8_t(0x00), 239: uint8_t(0x00), + 240: uint8_t(0x00), 241: uint8_t(0x00), 242: uint8_t(0x00), 243: uint8_t(0x00), 244: uint8_t(0x00), 245: uint8_t(0x00), 246: uint8_t(0x00), 247: uint8_t(0x00), 248: uint8_t(0x00), 249: uint8_t(0x00), 250: uint8_t(0x00), 251: uint8_t(0x00), + 252: uint8_t(0x00), 253: uint8_t(0x00), 254: uint8_t(0x00), 255: uint8_t(0x00), 256: uint8_t(0x01), 257: uint8_t(0x02), 258: uint8_t(0x03), 259: uint8_t(0x04), 260: uint8_t(0x05), 261: uint8_t(0x06), 262: uint8_t(0x07), 263: uint8_t(0x08), + 264: uint8_t(0x09), 265: uint8_t(0x0a), 266: uint8_t(0x0b), 267: uint8_t(0x0c), 268: uint8_t(0x0d), 269: uint8_t(0x0e), 270: uint8_t(0x0f), 271: uint8_t(0x10), 272: uint8_t(0x11), 273: uint8_t(0x12), 274: uint8_t(0x13), 275: uint8_t(0x14), + 276: uint8_t(0x15), 277: uint8_t(0x16), 278: uint8_t(0x17), 279: uint8_t(0x18), 280: uint8_t(0x19), 281: uint8_t(0x1a), 282: uint8_t(0x1b), 283: uint8_t(0x1c), 284: uint8_t(0x1d), 285: uint8_t(0x1e), 286: uint8_t(0x1f), 287: uint8_t(0x20), + 288: uint8_t(0x21), 289: uint8_t(0x22), 290: uint8_t(0x23), 291: uint8_t(0x24), 292: uint8_t(0x25), 293: uint8_t(0x26), 294: uint8_t(0x27), 295: uint8_t(0x28), 296: uint8_t(0x29), 297: uint8_t(0x2a), 298: uint8_t(0x2b), 299: uint8_t(0x2c), + 300: uint8_t(0x2d), 301: uint8_t(0x2e), 302: uint8_t(0x2f), 303: uint8_t(0x30), 304: uint8_t(0x31), 305: uint8_t(0x32), 306: uint8_t(0x33), 307: uint8_t(0x34), 308: uint8_t(0x35), 309: uint8_t(0x36), 310: uint8_t(0x37), 311: uint8_t(0x38), + 312: uint8_t(0x39), 313: uint8_t(0x3a), 314: uint8_t(0x3b), 315: uint8_t(0x3c), 316: uint8_t(0x3d), 317: uint8_t(0x3e), 318: uint8_t(0x3f), 319: uint8_t(0x40), 320: uint8_t(0x41), 321: uint8_t(0x42), 322: uint8_t(0x43), 323: uint8_t(0x44), + 324: uint8_t(0x45), 325: uint8_t(0x46), 326: uint8_t(0x47), 327: uint8_t(0x48), 328: uint8_t(0x49), 329: uint8_t(0x4a), 330: uint8_t(0x4b), 331: uint8_t(0x4c), 332: uint8_t(0x4d), 333: uint8_t(0x4e), 334: uint8_t(0x4f), 335: uint8_t(0x50), + 336: uint8_t(0x51), 337: uint8_t(0x52), 338: uint8_t(0x53), 339: uint8_t(0x54), 340: uint8_t(0x55), 341: uint8_t(0x56), 342: uint8_t(0x57), 343: uint8_t(0x58), 344: uint8_t(0x59), 345: uint8_t(0x5a), 346: uint8_t(0x5b), 347: uint8_t(0x5c), + 348: uint8_t(0x5d), 349: uint8_t(0x5e), 350: uint8_t(0x5f), 351: uint8_t(0x60), 352: uint8_t(0x61), 353: uint8_t(0x62), 354: uint8_t(0x63), 355: uint8_t(0x64), 356: uint8_t(0x65), 357: uint8_t(0x66), 358: uint8_t(0x67), 359: uint8_t(0x68), + 360: uint8_t(0x69), 361: uint8_t(0x6a), 362: uint8_t(0x6b), 363: uint8_t(0x6c), 364: uint8_t(0x6d), 365: uint8_t(0x6e), 366: uint8_t(0x6f), 367: uint8_t(0x70), 368: uint8_t(0x71), 369: uint8_t(0x72), 370: uint8_t(0x73), 371: uint8_t(0x74), + 372: uint8_t(0x75), 373: uint8_t(0x76), 374: uint8_t(0x77), 375: uint8_t(0x78), 376: uint8_t(0x79), 377: uint8_t(0x7a), 378: uint8_t(0x7b), 379: uint8_t(0x7c), 380: uint8_t(0x7d), 381: uint8_t(0x7e), 382: uint8_t(0x7f), 383: uint8_t(0x80), + 384: uint8_t(0x81), 385: uint8_t(0x82), 386: uint8_t(0x83), 387: uint8_t(0x84), 388: uint8_t(0x85), 389: uint8_t(0x86), 390: uint8_t(0x87), 391: uint8_t(0x88), 392: uint8_t(0x89), 393: uint8_t(0x8a), 394: uint8_t(0x8b), 395: uint8_t(0x8c), + 396: uint8_t(0x8d), 397: uint8_t(0x8e), 398: uint8_t(0x8f), 399: uint8_t(0x90), 400: uint8_t(0x91), 401: uint8_t(0x92), 402: uint8_t(0x93), 403: uint8_t(0x94), 404: uint8_t(0x95), 405: uint8_t(0x96), 406: uint8_t(0x97), 407: uint8_t(0x98), + 408: uint8_t(0x99), 409: uint8_t(0x9a), 410: uint8_t(0x9b), 411: uint8_t(0x9c), 412: uint8_t(0x9d), 413: uint8_t(0x9e), 414: uint8_t(0x9f), 415: uint8_t(0xa0), 416: uint8_t(0xa1), 417: uint8_t(0xa2), 418: uint8_t(0xa3), 419: uint8_t(0xa4), + 420: uint8_t(0xa5), 421: uint8_t(0xa6), 422: uint8_t(0xa7), 423: uint8_t(0xa8), 424: uint8_t(0xa9), 425: uint8_t(0xaa), 426: uint8_t(0xab), 427: uint8_t(0xac), 428: uint8_t(0xad), 429: uint8_t(0xae), 430: uint8_t(0xaf), 431: uint8_t(0xb0), + 432: uint8_t(0xb1), 433: uint8_t(0xb2), 434: uint8_t(0xb3), 435: uint8_t(0xb4), 436: uint8_t(0xb5), 437: uint8_t(0xb6), 438: uint8_t(0xb7), 439: uint8_t(0xb8), 440: uint8_t(0xb9), 441: uint8_t(0xba), 442: uint8_t(0xbb), 443: uint8_t(0xbc), + 444: uint8_t(0xbd), 445: uint8_t(0xbe), 446: uint8_t(0xbf), 447: uint8_t(0xc0), 448: uint8_t(0xc1), 449: uint8_t(0xc2), 450: uint8_t(0xc3), 451: uint8_t(0xc4), 452: uint8_t(0xc5), 453: uint8_t(0xc6), 454: uint8_t(0xc7), 455: uint8_t(0xc8), + 456: uint8_t(0xc9), 457: uint8_t(0xca), 458: uint8_t(0xcb), 459: uint8_t(0xcc), 460: uint8_t(0xcd), 461: uint8_t(0xce), 462: uint8_t(0xcf), 463: uint8_t(0xd0), 464: uint8_t(0xd1), 465: uint8_t(0xd2), 466: uint8_t(0xd3), 467: uint8_t(0xd4), + 468: uint8_t(0xd5), 469: uint8_t(0xd6), 470: uint8_t(0xd7), 471: uint8_t(0xd8), 472: uint8_t(0xd9), 473: uint8_t(0xda), 474: uint8_t(0xdb), 475: uint8_t(0xdc), 476: uint8_t(0xdd), 477: uint8_t(0xde), 478: uint8_t(0xdf), 479: uint8_t(0xe0), + 480: uint8_t(0xe1), 481: uint8_t(0xe2), 482: uint8_t(0xe3), 483: uint8_t(0xe4), 484: uint8_t(0xe5), 485: uint8_t(0xe6), 486: uint8_t(0xe7), 487: uint8_t(0xe8), 488: uint8_t(0xe9), 489: uint8_t(0xea), 490: uint8_t(0xeb), 491: uint8_t(0xec), + 492: uint8_t(0xed), 493: uint8_t(0xee), 494: uint8_t(0xef), 495: uint8_t(0xf0), 496: uint8_t(0xf1), 497: uint8_t(0xf2), 498: uint8_t(0xf3), 499: uint8_t(0xf4), 500: uint8_t(0xf5), 501: uint8_t(0xf6), 502: uint8_t(0xf7), 503: uint8_t(0xf8), + 504: uint8_t(0xf9), 505: uint8_t(0xfa), 506: uint8_t(0xfb), 507: uint8_t(0xfc), 508: uint8_t(0xfd), 509: uint8_t(0xfe), 510: uint8_t(0xff), 511: uint8_t(0xff), 512: uint8_t(0xff), 513: uint8_t(0xff), 514: uint8_t(0xff), 515: uint8_t(0xff), + 516: uint8_t(0xff), 517: uint8_t(0xff), 518: uint8_t(0xff), 519: uint8_t(0xff), 520: uint8_t(0xff), 521: uint8_t(0xff), 522: uint8_t(0xff), 523: uint8_t(0xff), 524: uint8_t(0xff), 525: uint8_t(0xff), 526: uint8_t(0xff), 527: uint8_t(0xff), + 528: uint8_t(0xff), 529: uint8_t(0xff), 530: uint8_t(0xff), 531: uint8_t(0xff), 532: uint8_t(0xff), 533: uint8_t(0xff), 534: uint8_t(0xff), 535: uint8_t(0xff), 536: uint8_t(0xff), 537: uint8_t(0xff), 538: uint8_t(0xff), 539: uint8_t(0xff), + 540: uint8_t(0xff), 541: uint8_t(0xff), 542: uint8_t(0xff), 543: uint8_t(0xff), 544: uint8_t(0xff), 545: uint8_t(0xff), 546: uint8_t(0xff), 547: uint8_t(0xff), 548: uint8_t(0xff), 549: uint8_t(0xff), 550: uint8_t(0xff), 551: uint8_t(0xff), + 552: uint8_t(0xff), 553: uint8_t(0xff), 554: uint8_t(0xff), 555: uint8_t(0xff), 556: uint8_t(0xff), 557: uint8_t(0xff), 558: uint8_t(0xff), 559: uint8_t(0xff), 560: uint8_t(0xff), 561: uint8_t(0xff), 562: uint8_t(0xff), 563: uint8_t(0xff), + 564: uint8_t(0xff), 565: uint8_t(0xff), 566: uint8_t(0xff), 567: uint8_t(0xff), 568: uint8_t(0xff), 569: uint8_t(0xff), 570: uint8_t(0xff), 571: uint8_t(0xff), 572: uint8_t(0xff), 573: uint8_t(0xff), 574: uint8_t(0xff), 575: uint8_t(0xff), + 576: uint8_t(0xff), 577: uint8_t(0xff), 578: uint8_t(0xff), 579: uint8_t(0xff), 580: uint8_t(0xff), 581: uint8_t(0xff), 582: uint8_t(0xff), 583: uint8_t(0xff), 584: uint8_t(0xff), 585: uint8_t(0xff), 586: uint8_t(0xff), 587: uint8_t(0xff), + 588: uint8_t(0xff), 589: uint8_t(0xff), 590: uint8_t(0xff), 591: uint8_t(0xff), 592: uint8_t(0xff), 593: uint8_t(0xff), 594: uint8_t(0xff), 595: uint8_t(0xff), 596: uint8_t(0xff), 597: uint8_t(0xff), 598: uint8_t(0xff), 599: uint8_t(0xff), + 600: uint8_t(0xff), 601: uint8_t(0xff), 602: uint8_t(0xff), 603: uint8_t(0xff), 604: uint8_t(0xff), 605: uint8_t(0xff), 606: uint8_t(0xff), 607: uint8_t(0xff), 608: uint8_t(0xff), 609: uint8_t(0xff), 610: uint8_t(0xff), 611: uint8_t(0xff), + 612: uint8_t(0xff), 613: uint8_t(0xff), 614: uint8_t(0xff), 615: uint8_t(0xff), 616: uint8_t(0xff), 617: uint8_t(0xff), 618: uint8_t(0xff), 619: uint8_t(0xff), 620: uint8_t(0xff), 621: uint8_t(0xff), 622: uint8_t(0xff), 623: uint8_t(0xff), + 624: uint8_t(0xff), 625: uint8_t(0xff), 626: uint8_t(0xff), 627: uint8_t(0xff), 628: uint8_t(0xff), 629: uint8_t(0xff), 630: uint8_t(0xff), 631: uint8_t(0xff), 632: uint8_t(0xff), 633: uint8_t(0xff), 634: uint8_t(0xff), 635: uint8_t(0xff), + 636: uint8_t(0xff), 637: uint8_t(0xff), 638: uint8_t(0xff), 639: uint8_t(0xff), 640: uint8_t(0xff), 641: uint8_t(0xff), 642: uint8_t(0xff), 643: uint8_t(0xff), 644: uint8_t(0xff), 645: uint8_t(0xff), 646: uint8_t(0xff), 647: uint8_t(0xff), + 648: uint8_t(0xff), 649: uint8_t(0xff), 650: uint8_t(0xff), 651: uint8_t(0xff), 652: uint8_t(0xff), 653: uint8_t(0xff), 654: uint8_t(0xff), 655: uint8_t(0xff), 656: uint8_t(0xff), 657: uint8_t(0xff), 658: uint8_t(0xff), 659: uint8_t(0xff), + 660: uint8_t(0xff), 661: uint8_t(0xff), 662: uint8_t(0xff), 663: uint8_t(0xff), 664: uint8_t(0xff), 665: uint8_t(0xff), 666: uint8_t(0xff), 667: uint8_t(0xff), 668: uint8_t(0xff), 669: uint8_t(0xff), 670: uint8_t(0xff), 671: uint8_t(0xff), + 672: uint8_t(0xff), 673: uint8_t(0xff), 674: uint8_t(0xff), 675: uint8_t(0xff), 676: uint8_t(0xff), 677: uint8_t(0xff), 678: uint8_t(0xff), 679: uint8_t(0xff), 680: uint8_t(0xff), 681: uint8_t(0xff), 682: uint8_t(0xff), 683: uint8_t(0xff), + 684: uint8_t(0xff), 685: uint8_t(0xff), 686: uint8_t(0xff), 687: uint8_t(0xff), 688: uint8_t(0xff), 689: uint8_t(0xff), 690: uint8_t(0xff), 691: uint8_t(0xff), 692: uint8_t(0xff), 693: uint8_t(0xff), 694: uint8_t(0xff), 695: uint8_t(0xff), + 696: uint8_t(0xff), 697: uint8_t(0xff), 698: uint8_t(0xff), 699: uint8_t(0xff), 700: uint8_t(0xff), 701: uint8_t(0xff), 702: uint8_t(0xff), 703: uint8_t(0xff), 704: uint8_t(0xff), 705: uint8_t(0xff), 706: uint8_t(0xff), 707: uint8_t(0xff), + 708: uint8_t(0xff), 709: uint8_t(0xff), 710: uint8_t(0xff), 711: uint8_t(0xff), 712: uint8_t(0xff), 713: uint8_t(0xff), 714: uint8_t(0xff), 715: uint8_t(0xff), 716: uint8_t(0xff), 717: uint8_t(0xff), 718: uint8_t(0xff), 719: uint8_t(0xff), + 720: uint8_t(0xff), 721: uint8_t(0xff), 722: uint8_t(0xff), 723: uint8_t(0xff), 724: uint8_t(0xff), 725: uint8_t(0xff), 726: uint8_t(0xff), 727: uint8_t(0xff), 728: uint8_t(0xff), 729: uint8_t(0xff), 730: uint8_t(0xff), 731: uint8_t(0xff), + 732: uint8_t(0xff), 733: uint8_t(0xff), 734: uint8_t(0xff), 735: uint8_t(0xff), 736: uint8_t(0xff), 737: uint8_t(0xff), 738: uint8_t(0xff), 739: uint8_t(0xff), 740: uint8_t(0xff), 741: uint8_t(0xff), 742: uint8_t(0xff), 743: uint8_t(0xff), + 744: uint8_t(0xff), 745: uint8_t(0xff), 746: uint8_t(0xff), 747: uint8_t(0xff), 748: uint8_t(0xff), 749: uint8_t(0xff), 750: uint8_t(0xff), 751: uint8_t(0xff), 752: uint8_t(0xff), 753: uint8_t(0xff), 754: uint8_t(0xff), 755: uint8_t(0xff), + 756: uint8_t(0xff), 757: uint8_t(0xff), 758: uint8_t(0xff), 759: uint8_t(0xff), 760: uint8_t(0xff), 761: uint8_t(0xff), 762: uint8_t(0xff), 763: uint8_t(0xff), 764: uint8_t(0xff), 765: uint8_t(0xff), +} /* dec_clip_tables.c:264:22 */ + +var VP8ksclip1 uintptr = 0 /* dec_clip_tables.c:345:13 */ +var VP8ksclip2 uintptr = 0 /* dec_clip_tables.c:346:13 */ +var VP8kclip1 uintptr = 0 /* dec_clip_tables.c:347:14 */ +var VP8kabs0 uintptr = 0 /* dec_clip_tables.c:348:14 */ + +func VP8InitClipTables(tls *libc.TLS) { /* dec_clip_tables.c:350:32: */ +} + +//------------------------------------------------------------------------------ + +func clip_8b1(tls *libc.TLS, v int32) uint8_t { /* enc.c:20:28: */ + if !((v & libc.CplInt32(0xff)) != 0) { + return uint8(v) + } + if v < 0 { + return uint8(0) + } + return uint8(255) +} + +func clip_max(tls *libc.TLS, v int32, max int32) int32 { /* enc.c:25:24: */ + if v > max { + return max + } + return v +} + +//------------------------------------------------------------------------------ +// Compute susceptibility based on DCT-coeff histograms: +// the higher, the "easier" the macroblock is to compress. + +var VP8DspScan = [24]int32{ + // Luma + (0 + (0 * 32)), (4 + (0 * 32)), (8 + (0 * 32)), (12 + (0 * 32)), + (0 + (4 * 32)), (4 + (4 * 32)), (8 + (4 * 32)), (12 + (4 * 32)), + (0 + (8 * 32)), (4 + (8 * 32)), (8 + (8 * 32)), (12 + (8 * 32)), + (0 + (12 * 32)), (4 + (12 * 32)), (8 + (12 * 32)), (12 + (12 * 32)), + + (0 + (0 * 32)), (4 + (0 * 32)), (0 + (4 * 32)), (4 + (4 * 32)), // U + (8 + (0 * 32)), (12 + (0 * 32)), (8 + (4 * 32)), (12 + (4 * 32)), // V +} /* enc.c:34:11 */ + +// general-purpose util function +func VP8SetHistogramData(tls *libc.TLS, distribution uintptr, histo uintptr) { /* enc.c:46:6: */ + var max_value int32 = 0 + var last_non_zero int32 = 1 + var k int32 + for k = 0; k <= 31; k++ { + var value int32 = *(*int32)(unsafe.Pointer(distribution + uintptr(k)*4)) + if value > 0 { + if value > max_value { + max_value = value + } + last_non_zero = k + } + } + (*VP8Histogram)(unsafe.Pointer(histo)).max_value = max_value + (*VP8Histogram)(unsafe.Pointer(histo)).last_non_zero = last_non_zero +} + +func CollectHistogram_C(tls *libc.TLS, ref uintptr, pred uintptr, start_block int32, end_block int32, histo uintptr) { /* enc.c:62:13: */ + bp := tls.Alloc(160) + defer tls.Free(160) + + var j int32 + *(*[32]int32)(unsafe.Pointer(bp + 32 /* distribution */)) = [32]int32{0: 0} + for j = start_block; j < end_block; j++ { + var k int32 + // var out [16]int16_t at bp, 32 + + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8FTransform})).f(tls, (ref + uintptr(VP8DspScan[j])), (pred + uintptr(VP8DspScan[j])), (bp) /* &out[0] */) + + // Convert coefficients to bin. + for k = 0; k < 16; k++ { + var v int32 = (libc.Xabs(tls, int32(*(*int16_t)(unsafe.Pointer((bp) /* &out[0] */ + uintptr(k)*2)))) >> 3) + var clipped_value int32 = clip_max(tls, v, 31) + *(*int32)(unsafe.Pointer((bp + 32) /* &distribution[0] */ + uintptr(clipped_value)*4))++ + } + } + VP8SetHistogramData(tls, (bp + 32) /* &distribution[0] */, histo) +} + +//------------------------------------------------------------------------------ +// run-time tables (~4k) + +var clip11 [766]uint8_t /* enc.c:87:16: */ // clips [-255,510] to [0,255] + +// We declare this variable 'volatile' to prevent instruction reordering +// and make sure it's set to true _last_ (so as to be thread-safe) +var tables_ok int32 = 0 /* enc.c:91:21 */ + +func InitTables(tls *libc.TLS) { /* enc.c:93:39: */ + if !(libc.AtomicLoadInt32(&tables_ok) != 0) { + var i int32 + for i = -255; i <= (255 + 255); i++ { + clip11[(255 + i)] = clip_8b1(tls, i) + } + libc.AtomicStoreInt32(&tables_ok, int32(1)) + } +} + +//------------------------------------------------------------------------------ +// Transforms (Paragraph 14.4) + +var kC1 int32 = (20091 + (int32(1) << 16)) /* enc.c:112:18 */ +var kC2 int32 = 35468 /* enc.c:113:18 */ + +func ITransformOne(tls *libc.TLS, ref uintptr, in uintptr, dst uintptr) { /* enc.c:116:25: */ + bp := tls.Alloc(64) + defer tls.Free(64) + + // var C [16]int32 at bp, 64 + + var tmp uintptr + var i int32 + tmp = (bp) /* &C[0] */ + for i = 0; i < 4; i++ { // vertical pass + var a int32 = (int32(*(*int16_t)(unsafe.Pointer(in))) + int32(*(*int16_t)(unsafe.Pointer(in + 8*2)))) + var b int32 = (int32(*(*int16_t)(unsafe.Pointer(in))) - int32(*(*int16_t)(unsafe.Pointer(in + 8*2)))) + var c int32 = ((((int32(*(*int16_t)(unsafe.Pointer(in + 4*2)))) * (kC2)) >> 16) - (((int32(*(*int16_t)(unsafe.Pointer(in + 12*2)))) * (kC1)) >> 16)) + var d int32 = ((((int32(*(*int16_t)(unsafe.Pointer(in + 4*2)))) * (kC1)) >> 16) + (((int32(*(*int16_t)(unsafe.Pointer(in + 12*2)))) * (kC2)) >> 16)) + *(*int32)(unsafe.Pointer(tmp)) = (a + d) + *(*int32)(unsafe.Pointer(tmp + 1*4)) = (b + c) + *(*int32)(unsafe.Pointer(tmp + 2*4)) = (b - c) + *(*int32)(unsafe.Pointer(tmp + 3*4)) = (a - d) + tmp += 4 * (uintptr(4)) + in += 2 + } + + tmp = (bp) /* &C[0] */ + for i = 0; i < 4; i++ { // horizontal pass + var dc int32 = (*(*int32)(unsafe.Pointer(tmp)) + 4) + var a int32 = (dc + *(*int32)(unsafe.Pointer(tmp + 8*4))) + var b int32 = (dc - *(*int32)(unsafe.Pointer(tmp + 8*4))) + var c int32 = ((((*(*int32)(unsafe.Pointer(tmp + 4*4))) * (kC2)) >> 16) - (((*(*int32)(unsafe.Pointer(tmp + 12*4))) * (kC1)) >> 16)) + var d int32 = ((((*(*int32)(unsafe.Pointer(tmp + 4*4))) * (kC1)) >> 16) + (((*(*int32)(unsafe.Pointer(tmp + 12*4))) * (kC2)) >> 16)) + *(*uint8_t)(unsafe.Pointer(dst + uintptr(((0) + ((i) * 32))))) = clip_8b1(tls, (int32(*(*uint8_t)(unsafe.Pointer(ref + uintptr(((0) + ((i) * 32)))))) + ((a + d) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + uintptr(((1) + ((i) * 32))))) = clip_8b1(tls, (int32(*(*uint8_t)(unsafe.Pointer(ref + uintptr(((1) + ((i) * 32)))))) + ((b + c) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + uintptr(((2) + ((i) * 32))))) = clip_8b1(tls, (int32(*(*uint8_t)(unsafe.Pointer(ref + uintptr(((2) + ((i) * 32)))))) + ((b - c) >> 3))) + *(*uint8_t)(unsafe.Pointer(dst + uintptr(((3) + ((i) * 32))))) = clip_8b1(tls, (int32(*(*uint8_t)(unsafe.Pointer(ref + uintptr(((3) + ((i) * 32)))))) + ((a - d) >> 3))) + tmp += 4 + } +} + +func ITransform_C(tls *libc.TLS, ref uintptr, in uintptr, dst uintptr, do_two int32) { /* enc.c:149:13: */ + ITransformOne(tls, ref, in, dst) + if do_two != 0 { + ITransformOne(tls, (ref + uintptr(4)), (in + uintptr(16)*2), (dst + uintptr(4))) + } +} + +func FTransform_C(tls *libc.TLS, src uintptr, ref uintptr, out uintptr) { /* enc.c:157:13: */ + bp := tls.Alloc(64) + defer tls.Free(64) + + var i int32 + // var tmp [16]int32 at bp, 64 + + i = 0 +__1: + if !(i < 4) { + goto __3 + } + { + var d0 int32 = (int32(*(*uint8_t)(unsafe.Pointer(src))) - int32(*(*uint8_t)(unsafe.Pointer(ref)))) // 9bit dynamic range ([-255,255]) + var d1 int32 = (int32(*(*uint8_t)(unsafe.Pointer(src + 1))) - int32(*(*uint8_t)(unsafe.Pointer(ref + 1)))) + var d2 int32 = (int32(*(*uint8_t)(unsafe.Pointer(src + 2))) - int32(*(*uint8_t)(unsafe.Pointer(ref + 2)))) + var d3 int32 = (int32(*(*uint8_t)(unsafe.Pointer(src + 3))) - int32(*(*uint8_t)(unsafe.Pointer(ref + 3)))) + var a0 int32 = (d0 + d3) // 10b [-510,510] + var a1 int32 = (d1 + d2) + var a2 int32 = (d1 - d2) + var a3 int32 = (d0 - d3) + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((0+(i*4)))*4)) = ((a0 + a1) * 8) // 14b [-8160,8160] + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((1+(i*4)))*4)) = ((((a2 * 2217) + (a3 * 5352)) + 1812) >> 9) // [-7536,7542] + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((2+(i*4)))*4)) = ((a0 - a1) * 8) + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((3+(i*4)))*4)) = ((((a3 * 2217) - (a2 * 5352)) + 937) >> 9) + + } + goto __2 +__2: + i++ + src += uintptr(32) + ref += uintptr(32) + goto __1 + goto __3 +__3: + ; + for i = 0; i < 4; i++ { + var a0 int32 = (*(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((0+i))*4)) + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((12+i))*4))) // 15b + var a1 int32 = (*(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((4+i))*4)) + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((8+i))*4))) + var a2 int32 = (*(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((4+i))*4)) - *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((8+i))*4))) + var a3 int32 = (*(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((0+i))*4)) - *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((12+i))*4))) + *(*int16_t)(unsafe.Pointer(out + uintptr((0+i))*2)) = (int16_t(((a0 + a1) + 7) >> 4)) // 12b + *(*int16_t)(unsafe.Pointer(out + uintptr((4+i))*2)) = (int16_t(((((a2 * 2217) + (a3 * 5352)) + 12000) >> 16) + (libc.Bool32(a3 != 0)))) + *(*int16_t)(unsafe.Pointer(out + uintptr((8+i))*2)) = (int16_t(((a0 - a1) + 7) >> 4)) + *(*int16_t)(unsafe.Pointer(out + uintptr((12+i))*2)) = (int16_t((((a3 * 2217) - (a2 * 5352)) + 51000) >> 16)) + } +} + +func FTransform2_C(tls *libc.TLS, src uintptr, ref uintptr, out uintptr) { /* enc.c:187:13: */ + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8FTransform})).f(tls, src, ref, out) + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8FTransform})).f(tls, (src + uintptr(4)), (ref + uintptr(4)), (out + uintptr(16)*2)) +} + +func FTransformWHT_C(tls *libc.TLS, in uintptr, out uintptr) { /* enc.c:194:13: */ + bp := tls.Alloc(64) + defer tls.Free(64) + + // input is 12b signed + // var tmp [16]int32_t at bp, 64 + + var i int32 + i = 0 +__1: + if !(i < 4) { + goto __3 + } + { + var a0 int32 = (int32(*(*int16_t)(unsafe.Pointer(in))) + int32(*(*int16_t)(unsafe.Pointer(in + 32*2)))) // 13b + var a1 int32 = (int32(*(*int16_t)(unsafe.Pointer(in + 16*2))) + int32(*(*int16_t)(unsafe.Pointer(in + 48*2)))) + var a2 int32 = (int32(*(*int16_t)(unsafe.Pointer(in + 16*2))) - int32(*(*int16_t)(unsafe.Pointer(in + 48*2)))) + var a3 int32 = (int32(*(*int16_t)(unsafe.Pointer(in))) - int32(*(*int16_t)(unsafe.Pointer(in + 32*2)))) + *(*int32_t)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((0+(i*4)))*4)) = (a0 + a1) // 14b + *(*int32_t)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((1+(i*4)))*4)) = (a3 + a2) + *(*int32_t)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((2+(i*4)))*4)) = (a3 - a2) + *(*int32_t)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((3+(i*4)))*4)) = (a0 - a1) + + } + goto __2 +__2: + i++ + in += 2 * (uintptr(64)) + goto __1 + goto __3 +__3: + ; + for i = 0; i < 4; i++ { + var a0 int32 = (*(*int32_t)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((0+i))*4)) + *(*int32_t)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((8+i))*4))) // 15b + var a1 int32 = (*(*int32_t)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((4+i))*4)) + *(*int32_t)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((12+i))*4))) + var a2 int32 = (*(*int32_t)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((4+i))*4)) - *(*int32_t)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((12+i))*4))) + var a3 int32 = (*(*int32_t)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((0+i))*4)) - *(*int32_t)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((8+i))*4))) + var b0 int32 = (a0 + a1) // 16b + var b1 int32 = (a3 + a2) + var b2 int32 = (a3 - a2) + var b3 int32 = (a0 - a1) + *(*int16_t)(unsafe.Pointer(out + uintptr((0+i))*2)) = (int16_t(b0 >> 1)) // 15b + *(*int16_t)(unsafe.Pointer(out + uintptr((4+i))*2)) = (int16_t(b1 >> 1)) + *(*int16_t)(unsafe.Pointer(out + uintptr((8+i))*2)) = (int16_t(b2 >> 1)) + *(*int16_t)(unsafe.Pointer(out + uintptr((12+i))*2)) = (int16_t(b3 >> 1)) + } +} + +//------------------------------------------------------------------------------ +// Intra predictions + +func Fill(tls *libc.TLS, dst uintptr, value int32, size int32) { /* enc.c:231:25: */ + var j int32 + for j = 0; j < size; j++ { + libc.Xmemset(tls, (dst + uintptr((j * 32))), value, uint64(size)) + } +} + +func VerticalPred(tls *libc.TLS, dst uintptr, top uintptr, size int32) { /* enc.c:238:25: */ + var j int32 + if top != (uintptr(0)) { + for j = 0; j < size; j++ { + libc.Xmemcpy(tls, (dst + uintptr((j * 32))), top, uint64(size)) + } + } else { + Fill(tls, dst, 127, size) + } +} + +func HorizontalPred(tls *libc.TLS, dst uintptr, left uintptr, size int32) { /* enc.c:248:25: */ + if left != (uintptr(0)) { + var j int32 + for j = 0; j < size; j++ { + libc.Xmemset(tls, (dst + uintptr((j * 32))), int32(*(*uint8_t)(unsafe.Pointer(left + uintptr(j)))), uint64(size)) + } + } else { + Fill(tls, dst, 129, size) + } +} + +func TrueMotion1(tls *libc.TLS, dst uintptr, left uintptr, top uintptr, size int32) { /* enc.c:260:25: */ + var y int32 + if left != (uintptr(0)) { + if top != (uintptr(0)) { + var clip uintptr = ((uintptr(unsafe.Pointer(&clip11)) + uintptr(255)) - uintptr(*(*uint8_t)(unsafe.Pointer(left + libc.UintptrFromInt32(-1))))) + for y = 0; y < size; y++ { + var clip_table uintptr = (clip + uintptr(*(*uint8_t)(unsafe.Pointer(left + uintptr(y))))) + var x int32 + for x = 0; x < size; x++ { + *(*uint8_t)(unsafe.Pointer(dst + uintptr(x))) = *(*uint8_t)(unsafe.Pointer(clip_table + uintptr(*(*uint8_t)(unsafe.Pointer(top + uintptr(x)))))) + } + dst += uintptr(32) + } + } else { + HorizontalPred(tls, dst, left, size) + } + } else { + // true motion without left samples (hence: with default 129 value) + // is equivalent to VE prediction where you just copy the top samples. + // Note that if top samples are not available, the default value is + // then 129, and not 127 as in the VerticalPred case. + if top != (uintptr(0)) { + VerticalPred(tls, dst, top, size) + } else { + Fill(tls, dst, 129, size) + } + } +} + +func DCMode(tls *libc.TLS, dst uintptr, left uintptr, top uintptr, size int32, round int32, shift int32) { /* enc.c:290:25: */ + var DC int32 = 0 + var j int32 + if top != (uintptr(0)) { + for j = 0; j < size; j++ { + DC = DC + (int32(*(*uint8_t)(unsafe.Pointer(top + uintptr(j))))) + } + if left != (uintptr(0)) { // top and left present + for j = 0; j < size; j++ { + DC = DC + (int32(*(*uint8_t)(unsafe.Pointer(left + uintptr(j))))) + } + } else { // top, but no left + DC = DC + (DC) + } + DC = ((DC + round) >> shift) + } else if left != (uintptr(0)) { // left but no top + for j = 0; j < size; j++ { + DC = DC + (int32(*(*uint8_t)(unsafe.Pointer(left + uintptr(j))))) + } + DC = DC + (DC) + DC = ((DC + round) >> shift) + } else { // no top, no left, nothing. + DC = 0x80 + } + Fill(tls, dst, DC, size) +} + +//------------------------------------------------------------------------------ +// Chroma 8x8 prediction (paragraph 12.2) + +func IntraChromaPreds_C(tls *libc.TLS, dst uintptr, left uintptr, top uintptr) { /* enc.c:316:13: */ + // U block + DCMode(tls, (uintptr(((2 * 16) * 32)) + dst), left, top, 8, 8, 4) + VerticalPred(tls, (uintptr((((2 * 16) * 32) + (8 * 32))) + dst), top, 8) + HorizontalPred(tls, (uintptr(((((2 * 16) * 32) + (8 * 32)) + (1 * 16))) + dst), left, 8) + TrueMotion1(tls, (uintptr((((2 * 16) * 32) + (1 * 16))) + dst), left, top, 8) + // V block + dst += uintptr(8) + if top != (uintptr(0)) { + top += uintptr(8) + } + if left != (uintptr(0)) { + left += uintptr(16) + } + DCMode(tls, (uintptr(((2 * 16) * 32)) + dst), left, top, 8, 8, 4) + VerticalPred(tls, (uintptr((((2 * 16) * 32) + (8 * 32))) + dst), top, 8) + HorizontalPred(tls, (uintptr(((((2 * 16) * 32) + (8 * 32)) + (1 * 16))) + dst), left, 8) + TrueMotion1(tls, (uintptr((((2 * 16) * 32) + (1 * 16))) + dst), left, top, 8) +} + +//------------------------------------------------------------------------------ +// luma 16x16 prediction (paragraph 12.3) + +func Intra16Preds_C(tls *libc.TLS, dst uintptr, left uintptr, top uintptr) { /* enc.c:336:13: */ + DCMode(tls, (uintptr(((0 * 16) * 32)) + dst), left, top, 16, 16, 5) + VerticalPred(tls, (uintptr(((1 * 16) * 32)) + dst), top, 16) + HorizontalPred(tls, (uintptr((((1 * 16) * 32) + 16)) + dst), left, 16) + TrueMotion1(tls, (uintptr((((0 * 16) * 32) + 16)) + dst), left, top, 16) +} + +//------------------------------------------------------------------------------ +// luma 4x4 prediction + +func VE4(tls *libc.TLS, dst uintptr, top uintptr) { /* enc.c:351:13: */ + bp := tls.Alloc(4) + defer tls.Free(4) + // vertical + *(*[4]uint8_t)(unsafe.Pointer(bp /* vals */)) = [4]uint8_t{ + (uint8_t(((((int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-1))))) + (2 * (int32(*(*uint8_t)(unsafe.Pointer(top)))))) + (int32(*(*uint8_t)(unsafe.Pointer(top + 1))))) + 2) >> 2)), + (uint8_t(((((int32(*(*uint8_t)(unsafe.Pointer(top)))) + (2 * (int32(*(*uint8_t)(unsafe.Pointer(top + 1)))))) + (int32(*(*uint8_t)(unsafe.Pointer(top + 2))))) + 2) >> 2)), + (uint8_t(((((int32(*(*uint8_t)(unsafe.Pointer(top + 1)))) + (2 * (int32(*(*uint8_t)(unsafe.Pointer(top + 2)))))) + (int32(*(*uint8_t)(unsafe.Pointer(top + 3))))) + 2) >> 2)), + (uint8_t(((((int32(*(*uint8_t)(unsafe.Pointer(top + 2)))) + (2 * (int32(*(*uint8_t)(unsafe.Pointer(top + 3)))))) + (int32(*(*uint8_t)(unsafe.Pointer(top + 4))))) + 2) >> 2)), + } + var i int32 + for i = 0; i < 4; i++ { + libc.Xmemcpy(tls, (dst + uintptr((i * 32))), (bp) /* &vals[0] */, uint64(4)) + } +} + +func HE4(tls *libc.TLS, dst uintptr, top uintptr) { /* enc.c:364:13: */ // horizontal + var X int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-1)))) + var I int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-2)))) + var J int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-3)))) + var K int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-4)))) + var L int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-5)))) + WebPUint32ToMem(tls, (dst + uintptr((0 * 32))), (0x01010101 * (uint32((uint8_t(((((X) + (2 * (I))) + (J)) + 2) >> 2)))))) + WebPUint32ToMem(tls, (dst + uintptr((1 * 32))), (0x01010101 * (uint32((uint8_t(((((I) + (2 * (J))) + (K)) + 2) >> 2)))))) + WebPUint32ToMem(tls, (dst + uintptr((2 * 32))), (0x01010101 * (uint32((uint8_t(((((J) + (2 * (K))) + (L)) + 2) >> 2)))))) + WebPUint32ToMem(tls, (dst + uintptr((3 * 32))), (0x01010101 * (uint32((uint8_t(((((K) + (2 * (L))) + (L)) + 2) >> 2)))))) +} + +func DC4(tls *libc.TLS, dst uintptr, top uintptr) { /* enc.c:376:13: */ + var dc uint32_t = uint32_t(4) + var i int32 + for i = 0; i < 4; i++ { + dc = dc + (uint32_t(int32(*(*uint8_t)(unsafe.Pointer(top + uintptr(i)))) + int32(*(*uint8_t)(unsafe.Pointer(top + uintptr((-5 + i))))))) + } + Fill(tls, dst, (int32(dc >> 3)), 4) +} + +func RD4(tls *libc.TLS, dst uintptr, top uintptr) { /* enc.c:383:13: */ + var X int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-1)))) + var I int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-2)))) + var J int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-3)))) + var K int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-4)))) + var L int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-5)))) + var A int32 = int32(*(*uint8_t)(unsafe.Pointer(top))) + var B int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 1))) + var C int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 2))) + var D int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 3))) + *(*uint8_t)(unsafe.Pointer(dst + 96)) = (uint8_t(((((J) + (2 * (K))) + (L)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 64)) = libc.AssignPtrUint8((dst + 97), (uint8_t(((((I) + (2 * (J))) + (K)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 32)) = libc.AssignPtrUint8((dst + 65), libc.AssignPtrUint8((dst+98), (uint8_t(((((X)+(2*(I)))+(J))+2)>>2)))) + *(*uint8_t)(unsafe.Pointer(dst)) = libc.AssignPtrUint8((dst + 33), libc.AssignPtrUint8((dst+66), libc.AssignPtrUint8((dst+99), (uint8_t(((((A)+(2*(X)))+(I))+2)>>2))))) + *(*uint8_t)(unsafe.Pointer(dst + 1)) = libc.AssignPtrUint8((dst + 34), libc.AssignPtrUint8((dst+67), (uint8_t(((((B)+(2*(A)))+(X))+2)>>2)))) + *(*uint8_t)(unsafe.Pointer(dst + 2)) = libc.AssignPtrUint8((dst + 35), (uint8_t(((((C) + (2 * (B))) + (A)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 3)) = (uint8_t(((((D) + (2 * (C))) + (B)) + 2) >> 2)) +} + +func LD4(tls *libc.TLS, dst uintptr, top uintptr) { /* enc.c:402:13: */ + var A int32 = int32(*(*uint8_t)(unsafe.Pointer(top))) + var B int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 1))) + var C int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 2))) + var D int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 3))) + var E int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 4))) + var F int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 5))) + var G int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 6))) + var H int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 7))) + *(*uint8_t)(unsafe.Pointer(dst)) = (uint8_t(((((A) + (2 * (B))) + (C)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 1)) = libc.AssignPtrUint8((dst + 32), (uint8_t(((((B) + (2 * (C))) + (D)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 2)) = libc.AssignPtrUint8((dst + 33), libc.AssignPtrUint8((dst+64), (uint8_t(((((C)+(2*(D)))+(E))+2)>>2)))) + *(*uint8_t)(unsafe.Pointer(dst + 3)) = libc.AssignPtrUint8((dst + 34), libc.AssignPtrUint8((dst+65), libc.AssignPtrUint8((dst+96), (uint8_t(((((D)+(2*(E)))+(F))+2)>>2))))) + *(*uint8_t)(unsafe.Pointer(dst + 35)) = libc.AssignPtrUint8((dst + 66), libc.AssignPtrUint8((dst+97), (uint8_t(((((E)+(2*(F)))+(G))+2)>>2)))) + *(*uint8_t)(unsafe.Pointer(dst + 67)) = libc.AssignPtrUint8((dst + 98), (uint8_t(((((F) + (2 * (G))) + (H)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 99)) = (uint8_t(((((G) + (2 * (H))) + (H)) + 2) >> 2)) +} + +func VR4(tls *libc.TLS, dst uintptr, top uintptr) { /* enc.c:420:13: */ + var X int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-1)))) + var I int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-2)))) + var J int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-3)))) + var K int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-4)))) + var A int32 = int32(*(*uint8_t)(unsafe.Pointer(top))) + var B int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 1))) + var C int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 2))) + var D int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 3))) + *(*uint8_t)(unsafe.Pointer(dst)) = libc.AssignPtrUint8((dst + 65), (uint8_t((((X) + (A)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 1)) = libc.AssignPtrUint8((dst + 66), (uint8_t((((A) + (B)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 2)) = libc.AssignPtrUint8((dst + 67), (uint8_t((((B) + (C)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 3)) = (uint8_t((((C) + (D)) + 1) >> 1)) + + *(*uint8_t)(unsafe.Pointer(dst + 96)) = (uint8_t(((((K) + (2 * (J))) + (I)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 64)) = (uint8_t(((((J) + (2 * (I))) + (X)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 32)) = libc.AssignPtrUint8((dst + 97), (uint8_t(((((I) + (2 * (X))) + (A)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 33)) = libc.AssignPtrUint8((dst + 98), (uint8_t(((((X) + (2 * (A))) + (B)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 34)) = libc.AssignPtrUint8((dst + 99), (uint8_t(((((A) + (2 * (B))) + (C)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 35)) = (uint8_t(((((B) + (2 * (C))) + (D)) + 2) >> 2)) +} + +func VL4(tls *libc.TLS, dst uintptr, top uintptr) { /* enc.c:442:13: */ + var A int32 = int32(*(*uint8_t)(unsafe.Pointer(top))) + var B int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 1))) + var C int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 2))) + var D int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 3))) + var E int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 4))) + var F int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 5))) + var G int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 6))) + var H int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 7))) + *(*uint8_t)(unsafe.Pointer(dst)) = (uint8_t((((A) + (B)) + 1) >> 1)) + *(*uint8_t)(unsafe.Pointer(dst + 1)) = libc.AssignPtrUint8((dst + 64), (uint8_t((((B) + (C)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 2)) = libc.AssignPtrUint8((dst + 65), (uint8_t((((C) + (D)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 3)) = libc.AssignPtrUint8((dst + 66), (uint8_t((((D) + (E)) + 1) >> 1))) + + *(*uint8_t)(unsafe.Pointer(dst + 32)) = (uint8_t(((((A) + (2 * (B))) + (C)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 33)) = libc.AssignPtrUint8((dst + 96), (uint8_t(((((B) + (2 * (C))) + (D)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 34)) = libc.AssignPtrUint8((dst + 97), (uint8_t(((((C) + (2 * (D))) + (E)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 35)) = libc.AssignPtrUint8((dst + 98), (uint8_t(((((D) + (2 * (E))) + (F)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 67)) = (uint8_t(((((E) + (2 * (F))) + (G)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 99)) = (uint8_t(((((F) + (2 * (G))) + (H)) + 2) >> 2)) +} + +func HU4(tls *libc.TLS, dst uintptr, top uintptr) { /* enc.c:464:13: */ + var I int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-2)))) + var J int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-3)))) + var K int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-4)))) + var L int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-5)))) + *(*uint8_t)(unsafe.Pointer(dst)) = (uint8_t((((I) + (J)) + 1) >> 1)) + *(*uint8_t)(unsafe.Pointer(dst + 2)) = libc.AssignPtrUint8((dst + 32), (uint8_t((((J) + (K)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 34)) = libc.AssignPtrUint8((dst + 64), (uint8_t((((K) + (L)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 1)) = (uint8_t(((((I) + (2 * (J))) + (K)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 3)) = libc.AssignPtrUint8((dst + 33), (uint8_t(((((J) + (2 * (K))) + (L)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 35)) = libc.AssignPtrUint8((dst + 65), (uint8_t(((((K) + (2 * (L))) + (L)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 67)) = libc.AssignPtrUint8((dst + 66), libc.AssignPtrUint8((dst+96), libc.AssignPtrUint8((dst+97), libc.AssignPtrUint8((dst+98), libc.AssignPtrUint8((dst+99), uint8_t(L)))))) +} + +func HD4(tls *libc.TLS, dst uintptr, top uintptr) { /* enc.c:479:13: */ + var X int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-1)))) + var I int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-2)))) + var J int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-3)))) + var K int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-4)))) + var L int32 = int32(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-5)))) + var A int32 = int32(*(*uint8_t)(unsafe.Pointer(top))) + var B int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 1))) + var C int32 = int32(*(*uint8_t)(unsafe.Pointer(top + 2))) + + *(*uint8_t)(unsafe.Pointer(dst)) = libc.AssignPtrUint8((dst + 34), (uint8_t((((I) + (X)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 32)) = libc.AssignPtrUint8((dst + 66), (uint8_t((((J) + (I)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 64)) = libc.AssignPtrUint8((dst + 98), (uint8_t((((K) + (J)) + 1) >> 1))) + *(*uint8_t)(unsafe.Pointer(dst + 96)) = (uint8_t((((L) + (K)) + 1) >> 1)) + + *(*uint8_t)(unsafe.Pointer(dst + 3)) = (uint8_t(((((A) + (2 * (B))) + (C)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 2)) = (uint8_t(((((X) + (2 * (A))) + (B)) + 2) >> 2)) + *(*uint8_t)(unsafe.Pointer(dst + 1)) = libc.AssignPtrUint8((dst + 35), (uint8_t(((((I) + (2 * (X))) + (A)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 33)) = libc.AssignPtrUint8((dst + 67), (uint8_t(((((J) + (2 * (I))) + (X)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 65)) = libc.AssignPtrUint8((dst + 99), (uint8_t(((((K) + (2 * (J))) + (I)) + 2) >> 2))) + *(*uint8_t)(unsafe.Pointer(dst + 97)) = (uint8_t(((((L) + (2 * (K))) + (J)) + 2) >> 2)) +} + +func TM4(tls *libc.TLS, dst uintptr, top uintptr) { /* enc.c:502:13: */ + var x int32 + var y int32 + var clip uintptr = ((uintptr(unsafe.Pointer(&clip11)) + uintptr(255)) - uintptr(*(*uint8_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-1))))) + for y = 0; y < 4; y++ { + var clip_table uintptr = (clip + uintptr(*(*uint8_t)(unsafe.Pointer(top + uintptr((-2 - y)))))) + for x = 0; x < 4; x++ { + *(*uint8_t)(unsafe.Pointer(dst + uintptr(x))) = *(*uint8_t)(unsafe.Pointer(clip_table + uintptr(*(*uint8_t)(unsafe.Pointer(top + uintptr(x)))))) + } + dst += uintptr(32) + } +} + +// Left samples are top[-5 .. -2], top_left is top[-1], top are +// located at top[0..3], and top right is top[4..7] +func Intra4Preds_C(tls *libc.TLS, dst uintptr, top uintptr) { /* enc.c:520:13: */ + DC4(tls, (uintptr((((3 * 16) * 32) + 0)) + dst), top) + TM4(tls, (uintptr(((((3 * 16) * 32) + 0) + 4)) + dst), top) + VE4(tls, (uintptr(((((3 * 16) * 32) + 0) + 8)) + dst), top) + HE4(tls, (uintptr(((((3 * 16) * 32) + 0) + 12)) + dst), top) + RD4(tls, (uintptr(((((3 * 16) * 32) + 0) + 16)) + dst), top) + VR4(tls, (uintptr(((((3 * 16) * 32) + 0) + 20)) + dst), top) + LD4(tls, (uintptr(((((3 * 16) * 32) + 0) + 24)) + dst), top) + VL4(tls, (uintptr(((((3 * 16) * 32) + 0) + 28)) + dst), top) + HD4(tls, (uintptr((((3 * 16) * 32) + (4 * 32))) + dst), top) + HU4(tls, (uintptr(((((3 * 16) * 32) + (4 * 32)) + 4)) + dst), top) +} + +//------------------------------------------------------------------------------ +// Metric + +func GetSSE(tls *libc.TLS, a uintptr, b uintptr, w int32, h int32) int32 { /* enc.c:537:24: */ + var count int32 = 0 + var y int32 + var x int32 + for y = 0; y < h; y++ { + for x = 0; x < w; x++ { + var diff int32 = (int32(*(*uint8_t)(unsafe.Pointer(a + uintptr(x)))) - int32(*(*uint8_t)(unsafe.Pointer(b + uintptr(x))))) + count = count + (diff * diff) + } + a += uintptr(32) + b += uintptr(32) + } + return count +} + +func SSE16x16_C(tls *libc.TLS, a uintptr, b uintptr) int32 { /* enc.c:552:12: */ + return GetSSE(tls, a, b, 16, 16) +} + +func SSE16x8_C(tls *libc.TLS, a uintptr, b uintptr) int32 { /* enc.c:555:12: */ + return GetSSE(tls, a, b, 16, 8) +} + +func SSE8x8_C(tls *libc.TLS, a uintptr, b uintptr) int32 { /* enc.c:558:12: */ + return GetSSE(tls, a, b, 8, 8) +} + +func SSE4x4_C(tls *libc.TLS, a uintptr, b uintptr) int32 { /* enc.c:561:12: */ + return GetSSE(tls, a, b, 4, 4) +} + +func Mean16x4_C(tls *libc.TLS, ref uintptr, dc uintptr) { /* enc.c:566:13: */ + var k int32 + var x int32 + var y int32 + for k = 0; k < 4; k++ { + var avg uint32_t = uint32_t(0) + for y = 0; y < 4; y++ { + for x = 0; x < 4; x++ { + avg = avg + (uint32_t(*(*uint8_t)(unsafe.Pointer(ref + uintptr((x + (y * 32))))))) + } + } + *(*uint32_t)(unsafe.Pointer(dc + uintptr(k)*4)) = avg + ref += uintptr(4) // go to next 4x4 block. + } +} + +//------------------------------------------------------------------------------ +// Texture distortion +// +// We try to match the spectral content (weighted) between source and +// reconstructed samples. + +// Hadamard transform +// Returns the weighted sum of the absolute value of transformed coefficients. +// w[] contains a row-major 4 by 4 symmetric matrix. +func TTransform(tls *libc.TLS, in uintptr, w uintptr) int32 { /* enc.c:590:12: */ + bp := tls.Alloc(64) + defer tls.Free(64) + + var sum int32 = 0 + // var tmp [16]int32 at bp, 64 + + var i int32 + // horizontal pass + i = 0 +__1: + if !(i < 4) { + goto __3 + } + { + var a0 int32 = (int32(*(*uint8_t)(unsafe.Pointer(in))) + int32(*(*uint8_t)(unsafe.Pointer(in + 2)))) + var a1 int32 = (int32(*(*uint8_t)(unsafe.Pointer(in + 1))) + int32(*(*uint8_t)(unsafe.Pointer(in + 3)))) + var a2 int32 = (int32(*(*uint8_t)(unsafe.Pointer(in + 1))) - int32(*(*uint8_t)(unsafe.Pointer(in + 3)))) + var a3 int32 = (int32(*(*uint8_t)(unsafe.Pointer(in))) - int32(*(*uint8_t)(unsafe.Pointer(in + 2)))) + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((0+(i*4)))*4)) = (a0 + a1) + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((1+(i*4)))*4)) = (a3 + a2) + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((2+(i*4)))*4)) = (a3 - a2) + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((3+(i*4)))*4)) = (a0 - a1) + + } + goto __2 +__2: + i++ + in += uintptr(32) + goto __1 + goto __3 +__3: + ; + // vertical pass + i = 0 +__4: + if !(i < 4) { + goto __6 + } + { + var a0 int32 = (*(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((0+i))*4)) + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((8+i))*4))) + var a1 int32 = (*(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((4+i))*4)) + *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((12+i))*4))) + var a2 int32 = (*(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((4+i))*4)) - *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((12+i))*4))) + var a3 int32 = (*(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((0+i))*4)) - *(*int32)(unsafe.Pointer((bp) /* &tmp[0] */ + uintptr((8+i))*4))) + var b0 int32 = (a0 + a1) + var b1 int32 = (a3 + a2) + var b2 int32 = (a3 - a2) + var b3 int32 = (a0 - a1) + + sum = sum + (int32(*(*uint16_t)(unsafe.Pointer(w))) * libc.Xabs(tls, b0)) + sum = sum + (int32(*(*uint16_t)(unsafe.Pointer(w + 4*2))) * libc.Xabs(tls, b1)) + sum = sum + (int32(*(*uint16_t)(unsafe.Pointer(w + 8*2))) * libc.Xabs(tls, b2)) + sum = sum + (int32(*(*uint16_t)(unsafe.Pointer(w + 12*2))) * libc.Xabs(tls, b3)) + + } + goto __5 +__5: + i++ + w += 2 + goto __4 + goto __6 +__6: + ; + return sum +} + +func Disto4x4_C(tls *libc.TLS, a uintptr, b uintptr, w uintptr) int32 { /* enc.c:624:12: */ + var sum1 int32 = TTransform(tls, a, w) + var sum2 int32 = TTransform(tls, b, w) + return (libc.Xabs(tls, (sum2-sum1)) >> 5) +} + +func Disto16x16_C(tls *libc.TLS, a uintptr, b uintptr, w uintptr) int32 { /* enc.c:631:12: */ + var D int32 = 0 + var x int32 + var y int32 + for y = 0; y < (16 * 32); y = y + (4 * 32) { + for x = 0; x < 16; x = x + (4) { + D = D + (Disto4x4_C(tls, ((a + uintptr(x)) + uintptr(y)), ((b + uintptr(x)) + uintptr(y)), w)) + } + } + return D +} + +//------------------------------------------------------------------------------ +// Quantization +// + +var kZigzag1 = [16]uint8_t{ + uint8_t(0), uint8_t(1), uint8_t(4), uint8_t(8), uint8_t(5), uint8_t(2), uint8_t(3), uint8_t(6), uint8_t(9), uint8_t(12), uint8_t(13), uint8_t(10), uint8_t(7), uint8_t(11), uint8_t(14), uint8_t(15), +} /* enc.c:648:22 */ + +// Simple quantization +func QuantizeBlock_C(tls *libc.TLS, in uintptr, out uintptr, mtx uintptr) int32 { /* enc.c:653:12: */ + var last int32 = -1 + var n int32 + for n = 0; n < 16; n++ { + var j int32 = int32(kZigzag1[n]) + var sign int32 = (libc.Bool32(int32(*(*int16_t)(unsafe.Pointer(in + uintptr(j)*2))) < 0)) + var coeff uint32_t = (uint32_t((func() int32 { + if sign != 0 { + return -int32(*(*int16_t)(unsafe.Pointer(in + uintptr(j)*2))) + } + return int32(*(*int16_t)(unsafe.Pointer(in + uintptr(j)*2))) + }()) + int32(*(*uint16_t)(unsafe.Pointer((mtx + 192 /* &.sharpen_ */) + uintptr(j)*2))))) + if coeff > *(*uint32_t)(unsafe.Pointer((mtx + 128 /* &.zthresh_ */) + uintptr(j)*4)) { + var Q uint32_t = uint32_t(*(*uint16_t)(unsafe.Pointer((mtx /* &.q_ */) + uintptr(j)*2))) + var iQ uint32_t = uint32_t(*(*uint16_t)(unsafe.Pointer((mtx + 32 /* &.iq_ */) + uintptr(j)*2))) + var B uint32_t = *(*uint32_t)(unsafe.Pointer((mtx + 64 /* &.bias_ */) + uintptr(j)*4)) + var level int32 = QUANTDIV(tls, coeff, iQ, B) + if level > MAX_LEVEL { + level = MAX_LEVEL + } + if sign != 0 { + level = -level + } + *(*int16_t)(unsafe.Pointer(in + uintptr(j)*2)) = (int16_t(level * int32(Q))) + *(*int16_t)(unsafe.Pointer(out + uintptr(n)*2)) = int16_t(level) + if level != 0 { + last = n + } + } else { + *(*int16_t)(unsafe.Pointer(out + uintptr(n)*2)) = int16(0) + *(*int16_t)(unsafe.Pointer(in + uintptr(j)*2)) = int16(0) + } + } + return (libc.Bool32(last >= 0)) +} + +func Quantize2Blocks_C(tls *libc.TLS, in uintptr, out uintptr, mtx uintptr) int32 { /* enc.c:680:12: */ + var nz int32 + nz = ((*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8EncQuantizeBlock})).f(tls, (in+uintptr((0*16))*2), (out+uintptr((0*16))*2), mtx) << 0) + nz = nz | ((*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8EncQuantizeBlock})).f(tls, (in+uintptr((1*16))*2), (out+uintptr((1*16))*2), mtx) << 1) + return nz +} + +//------------------------------------------------------------------------------ +// Block copy + +func Copy(tls *libc.TLS, src uintptr, dst uintptr, w int32, h int32) { /* enc.c:692:25: */ + var y int32 + for y = 0; y < h; y++ { + libc.Xmemcpy(tls, dst, src, uint64(w)) + src += uintptr(32) + dst += uintptr(32) + } +} + +func Copy4x4_C(tls *libc.TLS, src uintptr, dst uintptr) { /* enc.c:701:13: */ + Copy(tls, src, dst, 4, 4) +} + +func Copy16x8_C(tls *libc.TLS, src uintptr, dst uintptr) { /* enc.c:705:13: */ + Copy(tls, src, dst, 16, 8) +} + +//------------------------------------------------------------------------------ +// Initialization + +// Speed-critical function pointers. We have to initialize them to the default +// implementations within VP8EncDspInit(). +var VP8CollectHistogram VP8CHisto /* enc.c:714:11: */ +var VP8ITransform VP8Idct /* enc.c:715:9: */ +var VP8FTransform VP8Fdct /* enc.c:716:9: */ +var VP8FTransform2 VP8Fdct /* enc.c:717:9: */ +var VP8FTransformWHT VP8WHT /* enc.c:718:8: */ +var VP8EncPredLuma4 VP8Intra4Preds /* enc.c:719:16: */ +var VP8EncPredLuma16 VP8IntraPreds /* enc.c:720:15: */ +var VP8EncPredChroma8 VP8IntraPreds /* enc.c:721:15: */ +var VP8SSE16x16 VP8Metric /* enc.c:722:11: */ +var VP8SSE8x8 VP8Metric /* enc.c:723:11: */ +var VP8SSE16x8 VP8Metric /* enc.c:724:11: */ +var VP8SSE4x4 VP8Metric /* enc.c:725:11: */ +var VP8TDisto4x4 VP8WMetric /* enc.c:726:12: */ +var VP8TDisto16x16 VP8WMetric /* enc.c:727:12: */ +var VP8Mean16x4 VP8MeanMetric /* enc.c:728:15: */ +var VP8EncQuantizeBlock VP8QuantizeBlock /* enc.c:729:18: */ +var VP8EncQuantize2Blocks VP8Quantize2Blocks /* enc.c:730:20: */ +var VP8EncQuantizeBlockWHT VP8QuantizeBlockWHT /* enc.c:731:21: */ +var VP8Copy4x4 VP8BlockCopy /* enc.c:732:14: */ +var VP8Copy16x8 VP8BlockCopy /* enc.c:733:14: */ + +func VP8EncDspInit(tls *libc.TLS) { /* enc.c:742:1: */ + for ok := true; ok; ok = (0 != 0) { + if VP8EncDspInit_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + VP8EncDspInit_body(tls) + VP8EncDspInit_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var VP8EncDspInit_body_last_cpuinfo_used VP8CPUInfo = 0 /* enc.c:742:1 */ + +func VP8EncDspInit_body(tls *libc.TLS) { /* enc.c:742:1: */ + VP8DspInit(tls) // common inverse transforms + InitTables(tls) + + // default C implementations + VP8ITransform = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + }{ITransform_C})) + VP8FTransform = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) + }{FTransform_C})) + VP8FTransformWHT = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) + }{FTransformWHT_C})) + VP8TDisto4x4 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) int32 + }{Disto4x4_C})) + VP8TDisto16x16 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) int32 + }{Disto16x16_C})) + VP8CollectHistogram = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, int32, uintptr) + }{CollectHistogram_C})) + VP8SSE16x16 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{SSE16x16_C})) + VP8SSE16x8 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{SSE16x8_C})) + VP8SSE8x8 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{SSE8x8_C})) + VP8SSE4x4 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{SSE4x4_C})) + + VP8EncQuantizeBlock = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) int32 + }{QuantizeBlock_C})) + VP8EncQuantize2Blocks = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) int32 + }{Quantize2Blocks_C})) + + VP8FTransform2 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) + }{FTransform2_C})) + VP8EncPredLuma4 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) + }{Intra4Preds_C})) + VP8EncPredLuma16 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) + }{Intra16Preds_C})) + VP8EncPredChroma8 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) + }{IntraChromaPreds_C})) + VP8Mean16x4 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) + }{Mean16x4_C})) + VP8EncQuantizeBlockWHT = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) int32 + }{QuantizeBlock_C})) + VP8Copy4x4 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) + }{Copy4x4_C})) + VP8Copy16x8 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) + }{Copy16x8_C})) + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if VP8GetCPUInfo != (uintptr(0)) { + } + +} + +//------------------------------------------------------------------------------ +// Helpful macro. + +func PredictLine_C(tls *libc.TLS, src uintptr, pred uintptr, dst uintptr, length int32, inverse int32) { /* filters.c:32:25: */ + var i int32 + if inverse != 0 { + for i = 0; i < length; i++ { + *(*uint8_t)(unsafe.Pointer(dst + uintptr(i))) = (uint8_t(int32(*(*uint8_t)(unsafe.Pointer(src + uintptr(i)))) + int32(*(*uint8_t)(unsafe.Pointer(pred + uintptr(i)))))) + } + } else { + for i = 0; i < length; i++ { + *(*uint8_t)(unsafe.Pointer(dst + uintptr(i))) = (uint8_t(int32(*(*uint8_t)(unsafe.Pointer(src + uintptr(i)))) - int32(*(*uint8_t)(unsafe.Pointer(pred + uintptr(i)))))) + } + } +} + +//------------------------------------------------------------------------------ +// Horizontal filter. + +func DoHorizontalFilter_C(tls *libc.TLS, in uintptr, width int32, height int32, stride int32, row int32, num_rows int32, inverse int32, out uintptr) { /* filters.c:45:25: */ + var preds uintptr + var start_offset size_t = (size_t(row * stride)) + var last_row int32 = (row + num_rows) + _ = height + + in += uintptr(start_offset) + out += uintptr(start_offset) + if inverse != 0 { + preds = out + } else { + preds = in + } + + if row == 0 { + // Leftmost pixel is the same as input for topmost scanline. + *(*uint8_t)(unsafe.Pointer(out)) = *(*uint8_t)(unsafe.Pointer(in)) + PredictLine_C(tls, (in + uintptr(1)), preds, (out + uintptr(1)), (width - 1), inverse) + row = 1 + preds += uintptr(stride) + in += uintptr(stride) + out += uintptr(stride) + } + + // Filter line-by-line. + for row < last_row { + // Leftmost pixel is predicted from above. + PredictLine_C(tls, in, (preds - uintptr(stride)), out, 1, inverse) + PredictLine_C(tls, (in + uintptr(1)), preds, (out + uintptr(1)), (width - 1), inverse) + row++ + preds += uintptr(stride) + in += uintptr(stride) + out += uintptr(stride) + } +} + +//------------------------------------------------------------------------------ +// Vertical filter. + +func DoVerticalFilter_C(tls *libc.TLS, in uintptr, width int32, height int32, stride int32, row int32, num_rows int32, inverse int32, out uintptr) { /* filters.c:82:25: */ + var preds uintptr + var start_offset size_t = (size_t(row * stride)) + var last_row int32 = (row + num_rows) + _ = height + + in += uintptr(start_offset) + out += uintptr(start_offset) + if inverse != 0 { + preds = out + } else { + preds = in + } + + if row == 0 { + // Very first top-left pixel is copied. + *(*uint8_t)(unsafe.Pointer(out)) = *(*uint8_t)(unsafe.Pointer(in)) + // Rest of top scan-line is left-predicted. + PredictLine_C(tls, (in + uintptr(1)), preds, (out + uintptr(1)), (width - 1), inverse) + row = 1 + in += uintptr(stride) + out += uintptr(stride) + } else { + // We are starting from in-between. Make sure 'preds' points to prev row. + preds -= uintptr(stride) + } + + // Filter line-by-line. + for row < last_row { + PredictLine_C(tls, in, preds, out, width, inverse) + row++ + preds += uintptr(stride) + in += uintptr(stride) + out += uintptr(stride) + } +} + +//------------------------------------------------------------------------------ +// Gradient filter. + +func GradientPredictor_C(tls *libc.TLS, a uint8_t, b uint8_t, c uint8_t) int32 { /* filters.c:121:24: */ + var g int32 = ((int32(a) + int32(b)) - int32(c)) + if (g & libc.CplInt32(0xff)) == 0 { + return g + } + if g < 0 { + return 0 + } + return 255 // clip to 8bit +} + +func DoGradientFilter_C(tls *libc.TLS, in uintptr, width int32, height int32, stride int32, row int32, num_rows int32, inverse int32, out uintptr) { /* filters.c:127:25: */ + var preds uintptr + var start_offset size_t = (size_t(row * stride)) + var last_row int32 = (row + num_rows) + _ = height + + in += uintptr(start_offset) + out += uintptr(start_offset) + if inverse != 0 { + preds = out + } else { + preds = in + } + + // left prediction for top scan-line + if row == 0 { + *(*uint8_t)(unsafe.Pointer(out)) = *(*uint8_t)(unsafe.Pointer(in)) + PredictLine_C(tls, (in + uintptr(1)), preds, (out + uintptr(1)), (width - 1), inverse) + row = 1 + preds += uintptr(stride) + in += uintptr(stride) + out += uintptr(stride) + } + + // Filter line-by-line. + for row < last_row { + var w int32 + // leftmost pixel: predict from above. + PredictLine_C(tls, in, (preds - uintptr(stride)), out, 1, inverse) + for w = 1; w < width; w++ { + var pred int32 = GradientPredictor_C(tls, *(*uint8_t)(unsafe.Pointer(preds + uintptr((w - 1)))), + *(*uint8_t)(unsafe.Pointer(preds + uintptr((w - stride)))), + *(*uint8_t)(unsafe.Pointer(preds + uintptr(((w - stride) - 1))))) + *(*uint8_t)(unsafe.Pointer(out + uintptr(w))) = (uint8_t(int32(*(*uint8_t)(unsafe.Pointer(in + uintptr(w)))) + (func() int32 { + if inverse != 0 { + return pred + } + return -pred + }()))) + } + row++ + preds += uintptr(stride) + in += uintptr(stride) + out += uintptr(stride) + } +} + +//------------------------------------------------------------------------------ + +func HorizontalFilter_C(tls *libc.TLS, data uintptr, width int32, height int32, stride int32, filtered_data uintptr) { /* filters.c:173:13: */ + DoHorizontalFilter_C(tls, data, width, height, stride, 0, height, 0, + filtered_data) +} + +func VerticalFilter_C(tls *libc.TLS, data uintptr, width int32, height int32, stride int32, filtered_data uintptr) { /* filters.c:179:13: */ + DoVerticalFilter_C(tls, data, width, height, stride, 0, height, 0, filtered_data) +} + +func GradientFilter_C(tls *libc.TLS, data uintptr, width int32, height int32, stride int32, filtered_data uintptr) { /* filters.c:184:13: */ + DoGradientFilter_C(tls, data, width, height, stride, 0, height, 0, filtered_data) +} + +//------------------------------------------------------------------------------ + +func HorizontalUnfilter_C(tls *libc.TLS, prev uintptr, in uintptr, out uintptr, width int32) { /* filters.c:192:13: */ + var pred uint8_t + if prev == (uintptr(0)) { + pred = uint8(0) + } else { + pred = *(*uint8_t)(unsafe.Pointer(prev)) + } + var i int32 + for i = 0; i < width; i++ { + *(*uint8_t)(unsafe.Pointer(out + uintptr(i))) = (uint8_t(int32(pred) + int32(*(*uint8_t)(unsafe.Pointer(in + uintptr(i)))))) + pred = *(*uint8_t)(unsafe.Pointer(out + uintptr(i))) + } +} + +func VerticalUnfilter_C(tls *libc.TLS, prev uintptr, in uintptr, out uintptr, width int32) { /* filters.c:203:13: */ + if prev == (uintptr(0)) { + HorizontalUnfilter_C(tls, (uintptr(0)), in, out, width) + } else { + var i int32 + for i = 0; i < width; i++ { + *(*uint8_t)(unsafe.Pointer(out + uintptr(i))) = (uint8_t(int32(*(*uint8_t)(unsafe.Pointer(prev + uintptr(i)))) + int32(*(*uint8_t)(unsafe.Pointer(in + uintptr(i)))))) + } + } +} + +func GradientUnfilter_C(tls *libc.TLS, prev uintptr, in uintptr, out uintptr, width int32) { /* filters.c:214:13: */ + if prev == (uintptr(0)) { + HorizontalUnfilter_C(tls, (uintptr(0)), in, out, width) + } else { + var top uint8_t = *(*uint8_t)(unsafe.Pointer(prev)) + var top_left uint8_t = top + var left uint8_t = top + var i int32 + for i = 0; i < width; i++ { + top = *(*uint8_t)(unsafe.Pointer(prev + uintptr(i))) // need to read this first, in case prev==out + left = (uint8_t(int32(*(*uint8_t)(unsafe.Pointer(in + uintptr(i)))) + GradientPredictor_C(tls, left, top, top_left))) + top_left = top + *(*uint8_t)(unsafe.Pointer(out + uintptr(i))) = left + } + } +} + +//------------------------------------------------------------------------------ +// Init function + +var WebPFilters [4]WebPFilterFunc /* filters.c:233:16: */ +var WebPUnfilters [4]WebPUnfilterFunc /* filters.c:234:18: */ + +func VP8FiltersInit(tls *libc.TLS) { /* filters.c:241:1: */ + for ok := true; ok; ok = (0 != 0) { + if VP8FiltersInit_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + VP8FiltersInit_body(tls) + VP8FiltersInit_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var VP8FiltersInit_body_last_cpuinfo_used VP8CPUInfo = 0 /* filters.c:241:1 */ + +func VP8FiltersInit_body(tls *libc.TLS) { /* filters.c:241:1: */ + WebPUnfilters[WEBP_FILTER_NONE] = (uintptr(0)) + WebPUnfilters[WEBP_FILTER_HORIZONTAL] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + }{HorizontalUnfilter_C})) + WebPUnfilters[WEBP_FILTER_VERTICAL] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + }{VerticalUnfilter_C})) + WebPUnfilters[WEBP_FILTER_GRADIENT] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + }{GradientUnfilter_C})) + + WebPFilters[WEBP_FILTER_NONE] = (uintptr(0)) + WebPFilters[WEBP_FILTER_HORIZONTAL] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32, int32, uintptr) + }{HorizontalFilter_C})) + WebPFilters[WEBP_FILTER_VERTICAL] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32, int32, uintptr) + }{VerticalFilter_C})) + WebPFilters[WEBP_FILTER_GRADIENT] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32, int32, uintptr) + }{GradientFilter_C})) + + if VP8GetCPUInfo != (uintptr(0)) { + } + +} + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.2 Diagnostics <assert.h> + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// void assert (int expression); +// +// If NDEBUG is defined, do nothing. +// If not, and EXPRESSION is zero, print an error message and abort. + +// void assert_perror (int errnum); +// +// If NDEBUG is defined, do nothing. If not, and ERRNUM is not zero, print an +// error message with the error text for ERRNUM and abort. +// (This is a GNU extension.) + +// Declarations for math functions. +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.12 Mathematics <math.h> + +// Handle feature test macros at the start of a header. +// Copyright (C) 2016-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// This header is internal to glibc and should not be included outside +// of glibc headers. Headers including it must define +// __GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION first. This header +// cannot have multiple include guards because ISO C feature test +// macros depend on the definition of the macro when an affected +// header is included, not when the first system header is +// included. + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO/IEC TR 24731-2:2010 defines the __STDC_WANT_LIB_EXT2__ +// macro. + +// ISO/IEC TS 18661-1:2014 defines the __STDC_WANT_IEC_60559_BFP_EXT__ +// macro. Most but not all symbols enabled by that macro in TS +// 18661-1 are enabled unconditionally in C2X; the symbols in Annex F +// still require that macro in C2X. + +// ISO/IEC TS 18661-4:2015 defines the +// __STDC_WANT_IEC_60559_FUNCS_EXT__ macro. Other than the reduction +// functions, the symbols from this TS are enabled unconditionally in +// C2X. + +// ISO/IEC TS 18661-3:2015 defines the +// __STDC_WANT_IEC_60559_TYPES_EXT__ macro. + +// Get definitions of __intmax_t and __uintmax_t. +// bits/types.h -- definitions of __*_t types underlying *_t types. +// Copyright (C) 2002-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Never include this file directly; use <sys/types.h> instead. + +// Get machine-dependent vector math functions declarations. +// Platform-specific SIMD declarations of math functions. +// Copyright (C) 2014-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Get default empty definitions for simd declarations. +// Empty definitions required for __MATHCALL_VEC unfolding in mathcalls.h. +// Copyright (C) 2014-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Needed definitions could be generated with: +// for func in $(grep __MATHCALL_VEC math/bits/mathcalls.h | sed -r "s|__MATHCALL_VEC.?\(||; s|,.*||"); do +// echo "#define __DECL_SIMD_${func}"; +// echo "#define __DECL_SIMD_${func}f"; +// echo "#define __DECL_SIMD_${func}l"; +// done +// + +// Gather machine dependent type support. +// Macros to control TS 18661-3 glibc features on x86. +// Copyright (C) 2017-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Defined to 1 if the current compiler invocation provides a +// floating-point type with the IEEE 754 binary128 format, and this +// glibc includes corresponding *f128 interfaces for it. The required +// libgcc support was added some time after the basic compiler +// support, for x86_64 and x86. + +// Defined to 1 if __HAVE_FLOAT128 is 1 and the type is ABI-distinct +// from the default float, double and long double types in this glibc. + +// Defined to 1 if the current compiler invocation provides a +// floating-point type with the right format for _Float64x, and this +// glibc includes corresponding *f64x interfaces for it. + +// Defined to 1 if __HAVE_FLOAT64X is 1 and _Float64x has the format +// of long double. Otherwise, if __HAVE_FLOAT64X is 1, _Float64x has +// the format of _Float128, which must be different from that of long +// double. + +// Defined to concatenate the literal suffix to be used with _Float128 +// types, if __HAVE_FLOAT128 is 1. + +// Defined to a complex binary128 type if __HAVE_FLOAT128 is 1. + +// The remaining of this file provides support for older compilers. + +// The type _Float128 exists only since GCC 7.0. + +// __builtin_huge_valf128 doesn't exist before GCC 7.0. + +// Older GCC has only a subset of built-in functions for _Float128 on +// x86, and __builtin_infq is not usable in static initializers. +// Converting a narrower sNaN to _Float128 produces a quiet NaN, so +// attempts to use _Float128 sNaNs will not work properly with older +// compilers. + +// In math/math.h, __MATH_TG will expand signbit to __builtin_signbit*, +// e.g.: __builtin_signbitf128, before GCC 6. However, there has never +// been a __builtin_signbitf128 in GCC and the type-generic builtin is +// only available since GCC 6. + +// Macros to control TS 18661-3 glibc features where the same +// definitions are appropriate for all platforms. +// Copyright (C) 2017-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Properties of long double type. ldbl-96 version. +// Copyright (C) 2016-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// long double is distinct from double, so there is nothing to +// define here. + +// This header should be included at the bottom of each bits/floatn.h. +// It defines the following macros for each _FloatN and _FloatNx type, +// where the same definitions, or definitions based only on the macros +// in bits/floatn.h, are appropriate for all glibc configurations. + +// Defined to 1 if the current compiler invocation provides a +// floating-point type with the right format for this type, and this +// glibc includes corresponding *fN or *fNx interfaces for it. + +// Defined to 1 if the corresponding __HAVE_<type> macro is 1 and the +// type is the first with its format in the sequence of (the default +// choices for) float, double, long double, _Float16, _Float32, +// _Float64, _Float128, _Float32x, _Float64x, _Float128x for this +// glibc; that is, if functions present once per floating-point format +// rather than once per type are present for this type. +// +// All configurations supported by glibc have _Float32 the same format +// as float, _Float64 and _Float32x the same format as double, the +// _Float64x the same format as either long double or _Float128. No +// configurations support _Float128x or, as of GCC 7, have compiler +// support for a type meeting the requirements for _Float128x. + +// Defined to 1 if the corresponding _FloatN type is not binary compatible +// with the corresponding ISO C type in the current compilation unit as +// opposed to __HAVE_DISTINCT_FLOATN, which indicates the default types built +// in glibc. + +// Defined to 1 if any _FloatN or _FloatNx types that are not +// ABI-distinct are however distinct types at the C language level (so +// for the purposes of __builtin_types_compatible_p and _Generic). + +// Defined to concatenate the literal suffix to be used with _FloatN +// or _FloatNx types, if __HAVE_<type> is 1. The corresponding +// literal suffixes exist since GCC 7, for C only. + +// Defined to a complex type if __HAVE_<type> is 1. + +// The remaining of this file provides support for older compilers. + +// If double, long double and _Float64 all have the same set of +// values, TS 18661-3 requires the usual arithmetic conversions on +// long double and _Float64 to produce _Float64. For this to be the +// case when building with a compiler without a distinct _Float64 +// type, _Float64 must be a typedef for long double, not for +// double. + +// Value returned on overflow. With IEEE 754 floating point, this is +// +Infinity, otherwise the largest representable positive value. + +// IEEE positive infinity. + +// IEEE Not A Number. + +// Get __GLIBC_FLT_EVAL_METHOD. +// Define __GLIBC_FLT_EVAL_METHOD. x86 version. +// Copyright (C) 2016-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Define the following typedefs. +// +// float_t floating-point type at least as wide as `float' used +// to evaluate `float' expressions +// double_t floating-point type at least as wide as `double' used +// to evaluate `double' expressions +type float_t = float32 /* math.h:149:15 */ +type double_t = float64 /* math.h:150:16 */ + +//------------------------------------------------------------------------------ +// Transform-related functions use din both encoding and decoding. + +// Macros used to create a batch predictor that iteratively uses a +// one-pixel predictor. + +// The predictor is added to the output pixel (which +// is therefore considered as a residual) to get the final prediction. + +//------------------------------------------------------------------------------ +// Image transforms. + +func Average2(tls *libc.TLS, a0 uint32_t, a1 uint32_t) uint32_t { /* lossless.c:29:29: */ + return ((((a0 ^ a1) & 0xfefefefe) >> 1) + (a0 & a1)) +} + +func Average3(tls *libc.TLS, a0 uint32_t, a1 uint32_t, a2 uint32_t) uint32_t { /* lossless.c:33:29: */ + return Average2(tls, Average2(tls, a0, a2), a1) +} + +func Average4(tls *libc.TLS, a0 uint32_t, a1 uint32_t, a2 uint32_t, a3 uint32_t) uint32_t { /* lossless.c:37:29: */ + return Average2(tls, Average2(tls, a0, a1), Average2(tls, a2, a3)) +} + +func Clip255(tls *libc.TLS, a uint32_t) uint32_t { /* lossless.c:42:29: */ + if a < uint32_t(256) { + return a + } + // return 0, when a is a negative integer. + // return 255, when a is positive. + return (^a >> 24) +} + +func AddSubtractComponentFull(tls *libc.TLS, a int32, b int32, c int32) int32 { /* lossless.c:51:24: */ + return int32(Clip255(tls, (uint32((a + b) - c)))) +} + +func ClampedAddSubtractFull(tls *libc.TLS, c0 uint32_t, c1 uint32_t, c2 uint32_t) uint32_t { /* lossless.c:55:29: */ + var a int32 = AddSubtractComponentFull(tls, (int32(c0 >> 24)), (int32(c1 >> 24)), (int32(c2 >> 24))) + var r int32 = AddSubtractComponentFull(tls, (int32((c0 >> 16) & uint32_t(0xff))), + (int32((c1 >> 16) & uint32_t(0xff))), + (int32((c2 >> 16) & uint32_t(0xff)))) + var g int32 = AddSubtractComponentFull(tls, (int32((c0 >> 8) & uint32_t(0xff))), + (int32((c1 >> 8) & uint32_t(0xff))), + (int32((c2 >> 8) & uint32_t(0xff)))) + var b int32 = AddSubtractComponentFull(tls, (int32(c0 & uint32_t(0xff))), (int32(c1 & uint32_t(0xff))), (int32(c2 & uint32_t(0xff)))) + return ((((uint32_t(a) << 24) | (uint32_t(r << 16))) | (uint32_t(g << 8))) | uint32_t(b)) +} + +func AddSubtractComponentHalf(tls *libc.TLS, a int32, b int32) int32 { /* lossless.c:68:24: */ + return int32(Clip255(tls, (uint32(a + ((a - b) / 2))))) +} + +func ClampedAddSubtractHalf(tls *libc.TLS, c0 uint32_t, c1 uint32_t, c2 uint32_t) uint32_t { /* lossless.c:72:29: */ + var ave uint32_t = Average2(tls, c0, c1) + var a int32 = AddSubtractComponentHalf(tls, (int32(ave >> 24)), (int32(c2 >> 24))) + var r int32 = AddSubtractComponentHalf(tls, (int32((ave >> 16) & uint32_t(0xff))), (int32((c2 >> 16) & uint32_t(0xff)))) + var g int32 = AddSubtractComponentHalf(tls, (int32((ave >> 8) & uint32_t(0xff))), (int32((c2 >> 8) & uint32_t(0xff)))) + var b int32 = AddSubtractComponentHalf(tls, (int32((ave >> 0) & uint32_t(0xff))), (int32((c2 >> 0) & uint32_t(0xff)))) + return ((((uint32_t(a) << 24) | (uint32_t(r << 16))) | (uint32_t(g << 8))) | uint32_t(b)) +} + +// gcc <= 4.9 on ARM generates incorrect code in Select() when Sub3() is +// inlined. + +func Sub3(tls *libc.TLS, a int32, b int32, c int32) int32 { /* lossless.c:90:25: */ + var pb int32 = (b - c) + var pa int32 = (a - c) + return (libc.Xabs(tls, pb) - libc.Xabs(tls, pa)) +} + +func Select(tls *libc.TLS, a uint32_t, b uint32_t, c uint32_t) uint32_t { /* lossless.c:98:29: */ + var pa_minus_pb int32 = (((Sub3(tls, (int32(a>>24)), (int32(b>>24)), (int32(c>>24))) + Sub3(tls, (int32((a>>16)&uint32_t(0xff))), (int32((b>>16)&uint32_t(0xff))), (int32((c>>16)&uint32_t(0xff))))) + Sub3(tls, (int32((a>>8)&uint32_t(0xff))), (int32((b>>8)&uint32_t(0xff))), (int32((c>>8)&uint32_t(0xff))))) + Sub3(tls, (int32((a)&uint32_t(0xff))), (int32((b)&uint32_t(0xff))), (int32((c)&uint32_t(0xff))))) + if pa_minus_pb <= 0 { + return a + } + return b +} + +//------------------------------------------------------------------------------ +// Predictors + +func VP8LPredictor0_C(tls *libc.TLS, left uintptr, top uintptr) uint32_t { /* lossless.c:110:10: */ + _ = top + _ = left + return 0xff000000 +} + +func VP8LPredictor1_C(tls *libc.TLS, left uintptr, top uintptr) uint32_t { /* lossless.c:116:10: */ + _ = top + return *(*uint32_t)(unsafe.Pointer(left)) +} + +func VP8LPredictor2_C(tls *libc.TLS, left uintptr, top uintptr) uint32_t { /* lossless.c:121:10: */ + _ = left + return *(*uint32_t)(unsafe.Pointer(top)) +} + +func VP8LPredictor3_C(tls *libc.TLS, left uintptr, top uintptr) uint32_t { /* lossless.c:126:10: */ + _ = left + return *(*uint32_t)(unsafe.Pointer(top + 1*4)) +} + +func VP8LPredictor4_C(tls *libc.TLS, left uintptr, top uintptr) uint32_t { /* lossless.c:131:10: */ + _ = left + return *(*uint32_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-1)*4)) +} + +func VP8LPredictor5_C(tls *libc.TLS, left uintptr, top uintptr) uint32_t { /* lossless.c:136:10: */ + var pred uint32_t = Average3(tls, *(*uint32_t)(unsafe.Pointer(left)), *(*uint32_t)(unsafe.Pointer(top)), *(*uint32_t)(unsafe.Pointer(top + 1*4))) + return pred +} + +func VP8LPredictor6_C(tls *libc.TLS, left uintptr, top uintptr) uint32_t { /* lossless.c:141:10: */ + var pred uint32_t = Average2(tls, *(*uint32_t)(unsafe.Pointer(left)), *(*uint32_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-1)*4))) + return pred +} + +func VP8LPredictor7_C(tls *libc.TLS, left uintptr, top uintptr) uint32_t { /* lossless.c:146:10: */ + var pred uint32_t = Average2(tls, *(*uint32_t)(unsafe.Pointer(left)), *(*uint32_t)(unsafe.Pointer(top))) + return pred +} + +func VP8LPredictor8_C(tls *libc.TLS, left uintptr, top uintptr) uint32_t { /* lossless.c:151:10: */ + var pred uint32_t = Average2(tls, *(*uint32_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-1)*4)), *(*uint32_t)(unsafe.Pointer(top))) + _ = left + return pred +} + +func VP8LPredictor9_C(tls *libc.TLS, left uintptr, top uintptr) uint32_t { /* lossless.c:157:10: */ + var pred uint32_t = Average2(tls, *(*uint32_t)(unsafe.Pointer(top)), *(*uint32_t)(unsafe.Pointer(top + 1*4))) + _ = left + return pred +} + +func VP8LPredictor10_C(tls *libc.TLS, left uintptr, top uintptr) uint32_t { /* lossless.c:163:10: */ + var pred uint32_t = Average4(tls, *(*uint32_t)(unsafe.Pointer(left)), *(*uint32_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-1)*4)), *(*uint32_t)(unsafe.Pointer(top)), *(*uint32_t)(unsafe.Pointer(top + 1*4))) + return pred +} + +func VP8LPredictor11_C(tls *libc.TLS, left uintptr, top uintptr) uint32_t { /* lossless.c:168:10: */ + var pred uint32_t = Select(tls, *(*uint32_t)(unsafe.Pointer(top)), *(*uint32_t)(unsafe.Pointer(left)), *(*uint32_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-1)*4))) + return pred +} + +func VP8LPredictor12_C(tls *libc.TLS, left uintptr, top uintptr) uint32_t { /* lossless.c:173:10: */ + var pred uint32_t = ClampedAddSubtractFull(tls, *(*uint32_t)(unsafe.Pointer(left)), *(*uint32_t)(unsafe.Pointer(top)), *(*uint32_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-1)*4))) + return pred +} + +func VP8LPredictor13_C(tls *libc.TLS, left uintptr, top uintptr) uint32_t { /* lossless.c:178:10: */ + var pred uint32_t = ClampedAddSubtractHalf(tls, *(*uint32_t)(unsafe.Pointer(left)), *(*uint32_t)(unsafe.Pointer(top)), *(*uint32_t)(unsafe.Pointer(top + libc.UintptrFromInt32(-1)*4))) + return pred +} + +func PredictorAdd0_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless.c:184:13: */ + var x int32 + _ = upper + for x = 0; x < num_pixels; x++ { + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LAddPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), 0xff000000) + } +} + +func PredictorAdd1_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless.c:190:13: */ + var i int32 + var left uint32_t = *(*uint32_t)(unsafe.Pointer(out + libc.UintptrFromInt32(-1)*4)) + _ = upper + for i = 0; i < num_pixels; i++ { + *(*uint32_t)(unsafe.Pointer(out + uintptr(i)*4)) = libc.AssignUint32(&left, VP8LAddPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(i)*4)), left)) + } +} + +func PredictorAdd2_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless.c:199:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor2_C(tls, (out + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LAddPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorAdd3_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless.c:200:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor3_C(tls, (out + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LAddPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorAdd4_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless.c:201:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor4_C(tls, (out + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LAddPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorAdd5_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless.c:202:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor5_C(tls, (out + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LAddPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorAdd6_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless.c:203:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor6_C(tls, (out + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LAddPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorAdd7_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless.c:204:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor7_C(tls, (out + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LAddPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorAdd8_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless.c:205:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor8_C(tls, (out + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LAddPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorAdd9_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless.c:206:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor9_C(tls, (out + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LAddPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorAdd10_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless.c:207:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor10_C(tls, (out + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LAddPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorAdd11_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless.c:208:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor11_C(tls, (out + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LAddPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorAdd12_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless.c:209:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor12_C(tls, (out + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LAddPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorAdd13_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless.c:210:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor13_C(tls, (out + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LAddPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +//------------------------------------------------------------------------------ + +// Inverse prediction. +func PredictorInverseTransform_C(tls *libc.TLS, transform uintptr, y_start int32, y_end int32, in uintptr, out uintptr) { /* lossless.c:215:13: */ + var width int32 = (*VP8LTransform)(unsafe.Pointer(transform)).xsize_ + if y_start == 0 { // First Row follows the L (mode=1) mode. + PredictorAdd0_C(tls, in, (uintptr(0)), 1, out) + PredictorAdd1_C(tls, (in + uintptr(1)*4), (uintptr(0)), (width - 1), (out + uintptr(1)*4)) + in += 4 * (uintptr(width)) + out += 4 * (uintptr(width)) + y_start++ + } + + { + var y int32 = y_start + var tile_width int32 = (int32(1) << (*VP8LTransform)(unsafe.Pointer(transform)).bits_) + var mask int32 = (tile_width - 1) + var tiles_per_row int32 = int32(VP8LSubSampleSize(tls, uint32(width), uint32((*VP8LTransform)(unsafe.Pointer(transform)).bits_))) + var pred_mode_base uintptr = ((*VP8LTransform)(unsafe.Pointer(transform)).data_ + uintptr(((y>>(*VP8LTransform)(unsafe.Pointer(transform)).bits_)*tiles_per_row))*4) + + for y < y_end { + var pred_mode_src uintptr = pred_mode_base + var x int32 = 1 + // First pixel follows the T (mode=2) mode. + PredictorAdd2_C(tls, in, (out - uintptr(width)*4), 1, out) + // .. the rest: + for x < width { + var pred_func VP8LPredictorAddSubFunc = VP8LPredictorsAdd[(((*(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&pred_mode_src, 4)))) >> 8) & uint32_t(0xf))] + var x_end int32 = ((x & ^mask) + tile_width) + if x_end > width { + x_end = width + } + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{pred_func})).f(tls, (in + uintptr(x)*4), ((out + uintptr(x)*4) - uintptr(width)*4), (x_end - x), (out + uintptr(x)*4)) + x = x_end + } + in += 4 * (uintptr(width)) + out += 4 * (uintptr(width)) + y++ + if (y & mask) == 0 { // Use the same mask, since tiles are squares. + pred_mode_base += 4 * (uintptr(tiles_per_row)) + } + } + + } +} + +// Add green to blue and red channels (i.e. perform the inverse transform of +// 'subtract green'). +func VP8LAddGreenToBlueAndRed_C(tls *libc.TLS, src uintptr, num_pixels int32, dst uintptr) { /* lossless.c:261:6: */ + var i int32 + for i = 0; i < num_pixels; i++ { + var argb uint32_t = *(*uint32_t)(unsafe.Pointer(src + uintptr(i)*4)) + var green uint32_t = ((argb >> 8) & uint32_t(0xff)) + var red_blue uint32_t = (argb & 0x00ff00ff) + red_blue = red_blue + ((green << 16) | green) + red_blue = red_blue & (0x00ff00ff) + *(*uint32_t)(unsafe.Pointer(dst + uintptr(i)*4)) = ((argb & 0xff00ff00) | red_blue) + } +} + +func ColorTransformDelta(tls *libc.TLS, color_pred int8_t, color int8_t) int32 { /* lossless.c:274:24: */ + return ((int32(color_pred) * int32(color)) >> 5) +} + +func ColorCodeToMultipliers(tls *libc.TLS, color_code uint32_t, m uintptr) { /* lossless.c:279:25: */ + (*VP8LMultipliers)(unsafe.Pointer(m)).green_to_red_ = (uint8_t((color_code >> 0) & uint32_t(0xff))) + (*VP8LMultipliers)(unsafe.Pointer(m)).green_to_blue_ = (uint8_t((color_code >> 8) & uint32_t(0xff))) + (*VP8LMultipliers)(unsafe.Pointer(m)).red_to_blue_ = (uint8_t((color_code >> 16) & uint32_t(0xff))) +} + +func VP8LTransformColorInverse_C(tls *libc.TLS, m uintptr, src uintptr, num_pixels int32, dst uintptr) { /* lossless.c:286:6: */ + var i int32 + for i = 0; i < num_pixels; i++ { + var argb uint32_t = *(*uint32_t)(unsafe.Pointer(src + uintptr(i)*4)) + var green int8_t = (int8_t(argb >> 8)) + var red uint32_t = (argb >> 16) + var new_red int32 = (int32(red & uint32_t(0xff))) + var new_blue int32 = (int32(argb & uint32_t(0xff))) + new_red = new_red + (ColorTransformDelta(tls, int8((*VP8LMultipliers)(unsafe.Pointer(m)).green_to_red_), green)) + new_red = new_red & (0xff) + new_blue = new_blue + (ColorTransformDelta(tls, int8((*VP8LMultipliers)(unsafe.Pointer(m)).green_to_blue_), green)) + new_blue = new_blue + (ColorTransformDelta(tls, int8((*VP8LMultipliers)(unsafe.Pointer(m)).red_to_blue_), int8_t(new_red))) + new_blue = new_blue & (0xff) + *(*uint32_t)(unsafe.Pointer(dst + uintptr(i)*4)) = (((argb & 0xff00ff00) | (uint32_t(new_red << 16))) | (uint32_t(new_blue))) + } +} + +// Color space inverse transform. +func ColorSpaceInverseTransform_C(tls *libc.TLS, transform uintptr, y_start int32, y_end int32, src uintptr, dst uintptr) { /* lossless.c:306:13: */ + bp := tls.Alloc(3) + defer tls.Free(3) + + var width int32 = (*VP8LTransform)(unsafe.Pointer(transform)).xsize_ + var tile_width int32 = (int32(1) << (*VP8LTransform)(unsafe.Pointer(transform)).bits_) + var mask int32 = (tile_width - 1) + var safe_width int32 = (width & ^mask) + var remaining_width int32 = (width - safe_width) + var tiles_per_row int32 = int32(VP8LSubSampleSize(tls, uint32(width), uint32((*VP8LTransform)(unsafe.Pointer(transform)).bits_))) + var y int32 = y_start + var pred_row uintptr = ((*VP8LTransform)(unsafe.Pointer(transform)).data_ + uintptr(((y>>(*VP8LTransform)(unsafe.Pointer(transform)).bits_)*tiles_per_row))*4) + + for y < y_end { + var pred uintptr = pred_row + *(*VP8LMultipliers)(unsafe.Pointer(bp /* m */)) = VP8LMultipliers{} + var src_safe_end uintptr = (src + uintptr(safe_width)*4) + var src_end uintptr = (src + uintptr(width)*4) + for src < src_safe_end { + ColorCodeToMultipliers(tls, *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&pred, 4))), (bp) /* &m */) + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LTransformColorInverse})).f(tls, (bp) /* &m */, src, tile_width, dst) + src += 4 * (uintptr(tile_width)) + dst += 4 * (uintptr(tile_width)) + } + if src < src_end { // Left-overs using C-version. + ColorCodeToMultipliers(tls, *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&pred, 4))), (bp) /* &m */) + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LTransformColorInverse})).f(tls, (bp) /* &m */, src, remaining_width, dst) + src += 4 * (uintptr(remaining_width)) + dst += 4 * (uintptr(remaining_width)) + } + y++ + if (y & mask) == 0 { + pred_row += 4 * (uintptr(tiles_per_row)) + } + } +} + +// Separate out pixels packed together using pixel-bundling. +// We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t). + +func MapARGB_C(tls *libc.TLS, src uintptr, color_map uintptr, dst uintptr, y_start int32, y_end int32, width int32) { /* lossless.c:384:1: */ + var y int32 + for y = y_start; y < y_end; y++ { + var x int32 + for x = 0; x < width; x++ { + *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 4))) = VP8GetARGBValue(tls, *(*uint32_t)(unsafe.Pointer(color_map + uintptr(VP8GetARGBIndex(tls, *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&src, 4)))))*4))) + } + } +} + +func ColorIndexInverseTransform_C(tls *libc.TLS, transform uintptr, y_start int32, y_end int32, src uintptr, dst uintptr) { /* lossless.c:384:1: */ + var y int32 + var bits_per_pixel int32 = (int32(8) >> (*VP8LTransform)(unsafe.Pointer(transform)).bits_) + var width int32 = (*VP8LTransform)(unsafe.Pointer(transform)).xsize_ + var color_map uintptr = (*VP8LTransform)(unsafe.Pointer(transform)).data_ + if bits_per_pixel < 8 { + var pixels_per_byte int32 = (int32(1) << (*VP8LTransform)(unsafe.Pointer(transform)).bits_) + var count_mask int32 = (pixels_per_byte - 1) + var bit_mask uint32_t = (uint32_t((int32(1) << bits_per_pixel) - 1)) + for y = y_start; y < y_end; y++ { + var packed_pixels uint32_t = uint32_t(0) + var x int32 + for x = 0; x < width; x++ { /* We need to load fresh 'packed_pixels' once every */ /* 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte */ /* is a power of 2, so can just use a mask for that, instead of */ /* decrementing a counter. */ + if (x & count_mask) == 0 { + packed_pixels = VP8GetARGBIndex(tls, *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&src, 4)))) + } + *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 4))) = VP8GetARGBValue(tls, *(*uint32_t)(unsafe.Pointer(color_map + uintptr((packed_pixels&bit_mask))*4))) + packed_pixels >>= bits_per_pixel + } + } + } else { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8LMapColor32b})).f(tls, src, color_map, dst, y_start, y_end, width) + } +} + +func MapAlpha_C(tls *libc.TLS, src uintptr, color_map uintptr, dst uintptr, y_start int32, y_end int32, width int32) { /* lossless.c:386:1: */ + var y int32 + for y = y_start; y < y_end; y++ { + var x int32 + for x = 0; x < width; x++ { + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = VP8GetAlphaValue(tls, *(*uint32_t)(unsafe.Pointer(color_map + uintptr(VP8GetAlphaIndex(tls, *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&src, 1)))))*4))) + } + } +} + +func VP8LColorIndexInverseTransformAlpha(tls *libc.TLS, transform uintptr, y_start int32, y_end int32, src uintptr, dst uintptr) { /* lossless.c:386:1: */ + var y int32 + var bits_per_pixel int32 = (int32(8) >> (*VP8LTransform)(unsafe.Pointer(transform)).bits_) + var width int32 = (*VP8LTransform)(unsafe.Pointer(transform)).xsize_ + var color_map uintptr = (*VP8LTransform)(unsafe.Pointer(transform)).data_ + if bits_per_pixel < 8 { + var pixels_per_byte int32 = (int32(1) << (*VP8LTransform)(unsafe.Pointer(transform)).bits_) + var count_mask int32 = (pixels_per_byte - 1) + var bit_mask uint32_t = (uint32_t((int32(1) << bits_per_pixel) - 1)) + for y = y_start; y < y_end; y++ { + var packed_pixels uint32_t = uint32_t(0) + var x int32 + for x = 0; x < width; x++ { /* We need to load fresh 'packed_pixels' once every */ /* 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte */ /* is a power of 2, so can just use a mask for that, instead of */ /* decrementing a counter. */ + if (x & count_mask) == 0 { + packed_pixels = uint32_t(VP8GetAlphaIndex(tls, *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&src, 1))))) + } + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = VP8GetAlphaValue(tls, *(*uint32_t)(unsafe.Pointer(color_map + uintptr((packed_pixels&bit_mask))*4))) + packed_pixels >>= bits_per_pixel + } + } + } else { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8LMapColor8b})).f(tls, src, color_map, dst, y_start, y_end, width) + } +} + +func VP8LInverseTransform(tls *libc.TLS, transform uintptr, row_start int32, row_end int32, in uintptr, out uintptr) { /* lossless.c:391:6: */ + var width int32 = (*VP8LTransform)(unsafe.Pointer(transform)).xsize_ + + switch (*VP8LTransform)(unsafe.Pointer(transform)).type_ { + case SUBTRACT_GREEN: + (*struct { + f func(*libc.TLS, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LAddGreenToBlueAndRed})).f(tls, in, ((row_end - row_start) * width), out) + break + case PREDICTOR_TRANSFORM: + PredictorInverseTransform_C(tls, transform, row_start, row_end, in, out) + if row_end != (*VP8LTransform)(unsafe.Pointer(transform)).ysize_ { + // The last predicted row in this iteration will be the top-pred row + // for the first row in next iteration. + libc.Xmemcpy(tls, (out - uintptr(width)*4), (out + uintptr((((row_end-row_start)-1)*width))*4), + (uint64(width) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + break + case CROSS_COLOR_TRANSFORM: + ColorSpaceInverseTransform_C(tls, transform, row_start, row_end, in, out) + break + case COLOR_INDEXING_TRANSFORM: + if (in == out) && ((*VP8LTransform)(unsafe.Pointer(transform)).bits_ > 0) { + // Move packed pixels to the end of unpacked region, so that unpacking + // can occur seamlessly. + // Also, note that this is the only transform that applies on + // the effective width of VP8LSubSampleSize(xsize_, bits_). All other + // transforms work on effective width of xsize_. + var out_stride int32 = ((row_end - row_start) * width) + var in_stride int32 = (int32((uint32_t(row_end - row_start)) * VP8LSubSampleSize(tls, uint32((*VP8LTransform)(unsafe.Pointer(transform)).xsize_), uint32((*VP8LTransform)(unsafe.Pointer(transform)).bits_)))) + var src uintptr = ((out + uintptr(out_stride)*4) - uintptr(in_stride)*4) + libc.Xmemmove(tls, src, out, (uint64(in_stride) * uint64(unsafe.Sizeof(uint32_t(0))))) + ColorIndexInverseTransform_C(tls, transform, row_start, row_end, src, out) + } else { + ColorIndexInverseTransform_C(tls, transform, row_start, row_end, in, out) + } + break + } +} + +//------------------------------------------------------------------------------ +// Color space conversion. + +func is_big_endian(tls *libc.TLS) int32 { /* lossless.c:436:12: */ + return (libc.Bool32(int32(*(*uint8_t)(unsafe.Pointer((uintptr(unsafe.Pointer(&tmp)) /* &.b */)))) != 1)) +} + +var tmp = func() (r struct{ w uint16_t }) { + *(*uint16_t)(unsafe.Pointer(uintptr(unsafe.Pointer(&r)) + 0)) = uint16_t(1) + return r +}() /* lossless.c:440:5 */ + +func VP8LConvertBGRAToRGB_C(tls *libc.TLS, src uintptr, num_pixels int32, dst uintptr) { /* lossless.c:444:6: */ + var src_end uintptr = (src + uintptr(num_pixels)*4) + for src < src_end { + var argb uint32_t = *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&src, 4))) + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = (uint8_t((argb >> 16) & uint32_t(0xff))) + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = (uint8_t((argb >> 8) & uint32_t(0xff))) + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = (uint8_t((argb >> 0) & uint32_t(0xff))) + } +} + +func VP8LConvertBGRAToRGBA_C(tls *libc.TLS, src uintptr, num_pixels int32, dst uintptr) { /* lossless.c:455:6: */ + var src_end uintptr = (src + uintptr(num_pixels)*4) + for src < src_end { + var argb uint32_t = *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&src, 4))) + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = (uint8_t((argb >> 16) & uint32_t(0xff))) + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = (uint8_t((argb >> 8) & uint32_t(0xff))) + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = (uint8_t((argb >> 0) & uint32_t(0xff))) + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = (uint8_t((argb >> 24) & uint32_t(0xff))) + } +} + +func VP8LConvertBGRAToRGBA4444_C(tls *libc.TLS, src uintptr, num_pixels int32, dst uintptr) { /* lossless.c:467:6: */ + var src_end uintptr = (src + uintptr(num_pixels)*4) + for src < src_end { + var argb uint32_t = *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&src, 4))) + var rg uint8_t = (uint8_t(((argb >> 16) & uint32_t(0xf0)) | ((argb >> 12) & uint32_t(0xf)))) + var ba uint8_t = (uint8_t(((argb >> 0) & uint32_t(0xf0)) | ((argb >> 28) & uint32_t(0xf)))) + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = rg + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = ba + } +} + +func VP8LConvertBGRAToRGB565_C(tls *libc.TLS, src uintptr, num_pixels int32, dst uintptr) { /* lossless.c:484:6: */ + var src_end uintptr = (src + uintptr(num_pixels)*4) + for src < src_end { + var argb uint32_t = *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&src, 4))) + var rg uint8_t = (uint8_t(((argb >> 16) & uint32_t(0xf8)) | ((argb >> 13) & uint32_t(0x7)))) + var gb uint8_t = (uint8_t(((argb >> 5) & uint32_t(0xe0)) | ((argb >> 3) & uint32_t(0x1f)))) + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = rg + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = gb + } +} + +func VP8LConvertBGRAToBGR_C(tls *libc.TLS, src uintptr, num_pixels int32, dst uintptr) { /* lossless.c:501:6: */ + var src_end uintptr = (src + uintptr(num_pixels)*4) + for src < src_end { + var argb uint32_t = *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&src, 4))) + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = (uint8_t((argb >> 0) & uint32_t(0xff))) + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = (uint8_t((argb >> 8) & uint32_t(0xff))) + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&dst, 1))) = (uint8_t((argb >> 16) & uint32_t(0xff))) + } +} + +func CopyOrSwap(tls *libc.TLS, src uintptr, num_pixels int32, dst uintptr, swap_on_big_endian int32) { /* lossless.c:512:13: */ + if is_big_endian(tls) == swap_on_big_endian { + var src_end uintptr = (src + uintptr(num_pixels)*4) + for src < src_end { + var argb uint32_t = *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&src, 4))) + WebPUint32ToMem(tls, dst, BSwap32(tls, argb)) + dst += uintptr(unsafe.Sizeof(argb)) + } + } else { + libc.Xmemcpy(tls, dst, src, (uint64(num_pixels) * uint64(unsafe.Sizeof(uint32_t(0))))) + } +} + +func VP8LConvertFromBGRA(tls *libc.TLS, in_data uintptr, num_pixels int32, out_colorspace WEBP_CSP_MODE, rgba uintptr) { /* lossless.c:526:6: */ + switch out_colorspace { + case MODE_RGB: + (*struct { + f func(*libc.TLS, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LConvertBGRAToRGB})).f(tls, in_data, num_pixels, rgba) + break + case MODE_RGBA: + (*struct { + f func(*libc.TLS, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LConvertBGRAToRGBA})).f(tls, in_data, num_pixels, rgba) + break + case MODE_rgbA: + (*struct { + f func(*libc.TLS, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LConvertBGRAToRGBA})).f(tls, in_data, num_pixels, rgba) + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPApplyAlphaMultiply})).f(tls, rgba, 0, num_pixels, 1, 0) + break + case MODE_BGR: + (*struct { + f func(*libc.TLS, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LConvertBGRAToBGR})).f(tls, in_data, num_pixels, rgba) + break + case MODE_BGRA: + CopyOrSwap(tls, in_data, num_pixels, rgba, 1) + break + case MODE_bgrA: + CopyOrSwap(tls, in_data, num_pixels, rgba, 1) + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPApplyAlphaMultiply})).f(tls, rgba, 0, num_pixels, 1, 0) + break + case MODE_ARGB: + CopyOrSwap(tls, in_data, num_pixels, rgba, 0) + break + case MODE_Argb: + CopyOrSwap(tls, in_data, num_pixels, rgba, 0) + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPApplyAlphaMultiply})).f(tls, rgba, 1, num_pixels, 1, 0) + break + case MODE_RGBA_4444: + (*struct { + f func(*libc.TLS, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LConvertBGRAToRGBA4444})).f(tls, in_data, num_pixels, rgba) + break + case MODE_rgbA_4444: + (*struct { + f func(*libc.TLS, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LConvertBGRAToRGBA4444})).f(tls, in_data, num_pixels, rgba) + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPApplyAlphaMultiply4444})).f(tls, rgba, num_pixels, 1, 0) + break + case MODE_RGB_565: + (*struct { + f func(*libc.TLS, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LConvertBGRAToRGB565})).f(tls, in_data, num_pixels, rgba) + break + default: + // Code flow should not reach here. + } +} + +//------------------------------------------------------------------------------ + +var VP8LAddGreenToBlueAndRed VP8LProcessDecBlueAndRedFunc /* lossless.c:573:30: */ +var VP8LPredictorsAdd [16]VP8LPredictorAddSubFunc /* lossless.c:574:25: */ +var VP8LPredictors [16]VP8LPredictorFunc /* lossless.c:575:19: */ + +// exposed plain-C implementations +var VP8LPredictorsAdd_C [16]VP8LPredictorAddSubFunc /* lossless.c:578:25: */ + +var VP8LTransformColorInverse VP8LTransformColorInverseFunc /* lossless.c:580:31: */ + +var VP8LConvertBGRAToRGB VP8LConvertFunc /* lossless.c:582:17: */ +var VP8LConvertBGRAToRGBA VP8LConvertFunc /* lossless.c:583:17: */ +var VP8LConvertBGRAToRGBA4444 VP8LConvertFunc /* lossless.c:584:17: */ +var VP8LConvertBGRAToRGB565 VP8LConvertFunc /* lossless.c:585:17: */ +var VP8LConvertBGRAToBGR VP8LConvertFunc /* lossless.c:586:17: */ + +var VP8LMapColor32b VP8LMapARGBFunc /* lossless.c:588:17: */ +var VP8LMapColor8b VP8LMapAlphaFunc /* lossless.c:589:18: */ + +func VP8LDspInit(tls *libc.TLS) { /* lossless.c:616:1: */ + for ok := true; ok; ok = (0 != 0) { + if VP8LDspInit_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + VP8LDspInit_body(tls) + VP8LDspInit_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var VP8LDspInit_body_last_cpuinfo_used VP8CPUInfo = 0 /* lossless.c:616:1 */ + +func VP8LDspInit_body(tls *libc.TLS) { /* lossless.c:616:1: */ + for ok := true; ok; ok = (0 != 0) { + (VP8LPredictors)[0] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor0_C})) + (VP8LPredictors)[1] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor1_C})) + (VP8LPredictors)[2] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor2_C})) + (VP8LPredictors)[3] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor3_C})) + (VP8LPredictors)[4] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor4_C})) + (VP8LPredictors)[5] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor5_C})) + (VP8LPredictors)[6] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor6_C})) + (VP8LPredictors)[7] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor7_C})) + (VP8LPredictors)[8] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor8_C})) + (VP8LPredictors)[9] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor9_C})) + (VP8LPredictors)[10] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor10_C})) + (VP8LPredictors)[11] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor11_C})) + (VP8LPredictors)[12] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor12_C})) + (VP8LPredictors)[13] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor13_C})) + (VP8LPredictors)[14] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor0_C})) /* <- padding security sentinels*/ + (VP8LPredictors)[15] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + }{VP8LPredictor0_C})) + } + for ok1 := true; ok1; ok1 = (0 != 0) { + (VP8LPredictorsAdd)[0] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd0_C})) + (VP8LPredictorsAdd)[1] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd1_C})) + (VP8LPredictorsAdd)[2] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd2_C})) + (VP8LPredictorsAdd)[3] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd3_C})) + (VP8LPredictorsAdd)[4] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd4_C})) + (VP8LPredictorsAdd)[5] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd5_C})) + (VP8LPredictorsAdd)[6] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd6_C})) + (VP8LPredictorsAdd)[7] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd7_C})) + (VP8LPredictorsAdd)[8] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd8_C})) + (VP8LPredictorsAdd)[9] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd9_C})) + (VP8LPredictorsAdd)[10] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd10_C})) + (VP8LPredictorsAdd)[11] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd11_C})) + (VP8LPredictorsAdd)[12] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd12_C})) + (VP8LPredictorsAdd)[13] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd13_C})) + (VP8LPredictorsAdd)[14] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd0_C})) /* <- padding security sentinels*/ + (VP8LPredictorsAdd)[15] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd0_C})) + } + for ok2 := true; ok2; ok2 = (0 != 0) { + (VP8LPredictorsAdd_C)[0] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd0_C})) + (VP8LPredictorsAdd_C)[1] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd1_C})) + (VP8LPredictorsAdd_C)[2] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd2_C})) + (VP8LPredictorsAdd_C)[3] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd3_C})) + (VP8LPredictorsAdd_C)[4] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd4_C})) + (VP8LPredictorsAdd_C)[5] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd5_C})) + (VP8LPredictorsAdd_C)[6] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd6_C})) + (VP8LPredictorsAdd_C)[7] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd7_C})) + (VP8LPredictorsAdd_C)[8] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd8_C})) + (VP8LPredictorsAdd_C)[9] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd9_C})) + (VP8LPredictorsAdd_C)[10] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd10_C})) + (VP8LPredictorsAdd_C)[11] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd11_C})) + (VP8LPredictorsAdd_C)[12] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd12_C})) + (VP8LPredictorsAdd_C)[13] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd13_C})) + (VP8LPredictorsAdd_C)[14] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd0_C})) /* <- padding security sentinels*/ + (VP8LPredictorsAdd_C)[15] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorAdd0_C})) + } + + VP8LAddGreenToBlueAndRed = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, uintptr) + }{VP8LAddGreenToBlueAndRed_C})) + + VP8LTransformColorInverse = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{VP8LTransformColorInverse_C})) + + VP8LConvertBGRAToRGBA = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, uintptr) + }{VP8LConvertBGRAToRGBA_C})) + VP8LConvertBGRAToRGB = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, uintptr) + }{VP8LConvertBGRAToRGB_C})) + VP8LConvertBGRAToBGR = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, uintptr) + }{VP8LConvertBGRAToBGR_C})) + + VP8LConvertBGRAToRGBA4444 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, uintptr) + }{VP8LConvertBGRAToRGBA4444_C})) + VP8LConvertBGRAToRGB565 = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, uintptr) + }{VP8LConvertBGRAToRGB565_C})) + + VP8LMapColor32b = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32, int32, int32) + }{MapARGB_C})) + VP8LMapColor8b = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32, int32, int32) + }{MapAlpha_C})) + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if VP8GetCPUInfo != (uintptr(0)) { + } + +} + +//------------------------------------------------------------------------------ + +// lookup table for small values of log2(int) +var kLog2Table = [256]float32{ + 0.0000000000000000, 0.0000000000000000, + 1.0000000000000000, 1.5849625007211560, + 2.0000000000000000, 2.3219280948873621, + 2.5849625007211560, 2.8073549220576041, + 3.0000000000000000, 3.1699250014423121, + 3.3219280948873621, 3.4594316186372973, + 3.5849625007211560, 3.7004397181410921, + 3.8073549220576041, 3.9068905956085187, + 4.0000000000000000, 4.0874628412503390, + 4.1699250014423121, 4.2479275134435852, + 4.3219280948873626, 4.3923174227787606, + 4.4594316186372973, 4.5235619560570130, + 4.5849625007211560, 4.6438561897747243, + 4.7004397181410917, 4.7548875021634682, + 4.8073549220576037, 4.8579809951275718, + 4.9068905956085187, 4.9541963103868749, + 5.0000000000000000, 5.0443941193584533, + 5.0874628412503390, 5.1292830169449663, + 5.1699250014423121, 5.2094533656289501, + 5.2479275134435852, 5.2854022188622487, + 5.3219280948873626, 5.3575520046180837, + 5.3923174227787606, 5.4262647547020979, + 5.4594316186372973, 5.4918530963296747, + 5.5235619560570130, 5.5545888516776376, + 5.5849625007211560, 5.6147098441152083, + 5.6438561897747243, 5.6724253419714951, + 5.7004397181410917, 5.7279204545631987, + 5.7548875021634682, 5.7813597135246599, + 5.8073549220576037, 5.8328900141647412, + 5.8579809951275718, 5.8826430493618415, + 5.9068905956085187, 5.9307373375628866, + 5.9541963103868749, 5.9772799234999167, + 6.0000000000000000, 6.0223678130284543, + 6.0443941193584533, 6.0660891904577720, + 6.0874628412503390, 6.1085244567781691, + 6.1292830169449663, 6.1497471195046822, + 6.1699250014423121, 6.1898245588800175, + 6.2094533656289501, 6.2288186904958804, + 6.2479275134435852, 6.2667865406949010, + 6.2854022188622487, 6.3037807481771030, + 6.3219280948873626, 6.3398500028846243, + 6.3575520046180837, 6.3750394313469245, + 6.3923174227787606, 6.4093909361377017, + 6.4262647547020979, 6.4429434958487279, + 6.4594316186372973, 6.4757334309663976, + 6.4918530963296747, 6.5077946401986963, + 6.5235619560570130, 6.5391588111080309, + 6.5545888516776376, 6.5698556083309478, + 6.5849625007211560, 6.5999128421871278, + 6.6147098441152083, 6.6293566200796094, + 6.6438561897747243, 6.6582114827517946, + 6.6724253419714951, 6.6865005271832185, + 6.7004397181410917, 6.7142455176661224, + 6.7279204545631987, 6.7414669864011464, + 6.7548875021634682, 6.7681843247769259, + 6.7813597135246599, 6.7944158663501061, + 6.8073549220576037, 6.8201789624151878, + 6.8328900141647412, 6.8454900509443747, + 6.8579809951275718, 6.8703647195834047, + 6.8826430493618415, 6.8948177633079437, + 6.9068905956085187, 6.9188632372745946, + 6.9307373375628866, 6.9425145053392398, + 6.9541963103868749, 6.9657842846620869, + 6.9772799234999167, 6.9886846867721654, + 7.0000000000000000, 7.0112272554232539, + 7.0223678130284543, 7.0334230015374501, + 7.0443941193584533, 7.0552824355011898, + 7.0660891904577720, 7.0768155970508308, + 7.0874628412503390, 7.0980320829605263, + 7.1085244567781691, 7.1189410727235076, + 7.1292830169449663, 7.1395513523987936, + 7.1497471195046822, 7.1598713367783890, + 7.1699250014423121, 7.1799090900149344, + 7.1898245588800175, 7.1996723448363644, + 7.2094533656289501, 7.2191685204621611, + 7.2288186904958804, 7.2384047393250785, + 7.2479275134435852, 7.2573878426926521, + 7.2667865406949010, 7.2761244052742375, + 7.2854022188622487, 7.2946207488916270, + 7.3037807481771030, 7.3128829552843557, + 7.3219280948873626, 7.3309168781146167, + 7.3398500028846243, 7.3487281542310771, + 7.3575520046180837, 7.3663222142458160, + 7.3750394313469245, 7.3837042924740519, + 7.3923174227787606, 7.4008794362821843, + 7.4093909361377017, 7.4178525148858982, + 7.4262647547020979, 7.4346282276367245, + 7.4429434958487279, 7.4512111118323289, + 7.4594316186372973, 7.4676055500829976, + 7.4757334309663976, 7.4838157772642563, + 7.4918530963296747, 7.4998458870832056, + 7.5077946401986963, 7.5156998382840427, + 7.5235619560570130, 7.5313814605163118, + 7.5391588111080309, 7.5468944598876364, + 7.5545888516776376, 7.5622424242210728, + 7.5698556083309478, 7.5774288280357486, + 7.5849625007211560, 7.5924570372680806, + 7.5999128421871278, 7.6073303137496104, + 7.6147098441152083, 7.6220518194563764, + 7.6293566200796094, 7.6366246205436487, + 7.6438561897747243, 7.6510516911789281, + 7.6582114827517946, 7.6653359171851764, + 7.6724253419714951, 7.6794800995054464, + 7.6865005271832185, 7.6934869574993252, + 7.7004397181410917, 7.7073591320808825, + 7.7142455176661224, 7.7210991887071855, + 7.7279204545631987, 7.7347096202258383, + 7.7414669864011464, 7.7481928495894605, + 7.7548875021634682, 7.7615512324444795, + 7.7681843247769259, 7.7747870596011736, + 7.7813597135246599, 7.7879025593914317, + 7.7944158663501061, 7.8008998999203047, + 7.8073549220576037, 7.8137811912170374, + 7.8201789624151878, 7.8265484872909150, + 7.8328900141647412, 7.8392037880969436, + 7.8454900509443747, 7.8517490414160571, + 7.8579809951275718, 7.8641861446542797, + 7.8703647195834047, 7.8765169465649993, + 7.8826430493618415, 7.8887432488982591, + 7.8948177633079437, 7.9008668079807486, + 7.9068905956085187, 7.9128893362299619, + 7.9188632372745946, 7.9248125036057812, + 7.9307373375628866, 7.9366379390025709, + 7.9425145053392398, 7.9483672315846778, + 7.9541963103868749, 7.9600019320680805, + 7.9657842846620869, 7.9715435539507719, + 7.9772799234999167, 7.9829935746943103, + 7.9886846867721654, 7.9943534368588577, +} /* lossless_enc.c:28:13 */ + +var kSLog2Table = [256]float32{ + 0.00000000, 0.00000000, 2.00000000, 4.75488750, + 8.00000000, 11.60964047, 15.50977500, 19.65148445, + 24.00000000, 28.52932501, 33.21928095, 38.05374781, + 43.01955001, 48.10571634, 53.30296891, 58.60335893, + 64.00000000, 69.48686830, 75.05865003, 80.71062276, + 86.43856190, 92.23866588, 98.10749561, 104.04192499, + 110.03910002, 116.09640474, 122.21143267, 128.38196256, + 134.60593782, 140.88144886, 147.20671787, 153.58008562, + 160.00000000, 166.46500594, 172.97373660, 179.52490559, + 186.11730005, 192.74977453, 199.42124551, 206.13068654, + 212.87712380, 219.65963219, 226.47733176, 233.32938445, + 240.21499122, 247.13338933, 254.08384998, 261.06567603, + 268.07820003, 275.12078236, 282.19280949, 289.29369244, + 296.42286534, 303.57978409, 310.76392512, 317.97478424, + 325.21187564, 332.47473081, 339.76289772, 347.07593991, + 354.41343574, 361.77497759, 369.16017124, 376.56863518, + 384.00000000, 391.45390785, 398.93001188, 406.42797576, + 413.94747321, 421.48818752, 429.04981119, 436.63204548, + 444.23460010, 451.85719280, 459.49954906, 467.16140179, + 474.84249102, 482.54256363, 490.26137307, 497.99867911, + 505.75424759, 513.52785023, 521.31926438, 529.12827280, + 536.95466351, 544.79822957, 552.65876890, 560.53608414, + 568.42998244, 576.34027536, 584.26677867, 592.20931226, + 600.16769996, 608.14176943, 616.13135206, 624.13628279, + 632.15640007, 640.19154569, 648.24156472, 656.30630539, + 664.38561898, 672.47935976, 680.58738488, 688.70955430, + 696.84573069, 704.99577935, 713.15956818, 721.33696754, + 729.52785023, 737.73209140, 745.94956849, 754.18016116, + 762.42375127, 770.68022275, 778.94946161, 787.23135586, + 795.52579543, 803.83267219, 812.15187982, 820.48331383, + 828.82687147, 837.18245171, 845.54995518, 853.92928416, + 862.32034249, 870.72303558, 879.13727036, 887.56295522, + 896.00000000, 904.44831595, 912.90781569, 921.37841320, + 929.86002376, 938.35256392, 946.85595152, 955.37010560, + 963.89494641, 972.43039537, 980.97637504, 989.53280911, + 998.09962237, 1006.67674069, 1015.26409097, 1023.86160116, + 1032.46920021, 1041.08681805, 1049.71438560, 1058.35183469, + 1066.99909811, 1075.65610955, 1084.32280357, 1092.99911564, + 1101.68498204, 1110.38033993, 1119.08512727, 1127.79928282, + 1136.52274614, 1145.25545758, 1153.99735821, 1162.74838989, + 1171.50849518, 1180.27761738, 1189.05570047, 1197.84268914, + 1206.63852876, 1215.44316535, 1224.25654560, 1233.07861684, + 1241.90932703, 1250.74862473, 1259.59645914, 1268.45278005, + 1277.31753781, 1286.19068338, 1295.07216828, 1303.96194457, + 1312.85996488, 1321.76618236, 1330.68055071, 1339.60302413, + 1348.53355734, 1357.47210556, 1366.41862452, 1375.37307041, + 1384.33539991, 1393.30557020, 1402.28353887, 1411.26926400, + 1420.26270412, 1429.26381818, 1438.27256558, 1447.28890615, + 1456.31280014, 1465.34420819, 1474.38309138, 1483.42941118, + 1492.48312945, 1501.54420843, 1510.61261078, 1519.68829949, + 1528.77123795, 1537.86138993, 1546.95871952, 1556.06319119, + 1565.17476976, 1574.29342040, 1583.41910860, 1592.55180020, + 1601.69146137, 1610.83805860, 1619.99155871, 1629.15192882, + 1638.31913637, 1647.49314911, 1656.67393509, 1665.86146266, + 1675.05570047, 1684.25661744, 1693.46418280, 1702.67836605, + 1711.89913698, 1721.12646563, 1730.36032233, 1739.60067768, + 1748.84750254, 1758.10076802, 1767.36044551, 1776.62650662, + 1785.89892323, 1795.17766747, 1804.46271172, 1813.75402857, + 1823.05159087, 1832.35537170, 1841.66534438, 1850.98148244, + 1860.30375965, 1869.63214999, 1878.96662767, 1888.30716711, + 1897.65374295, 1907.00633003, 1916.36490342, 1925.72943838, + 1935.09991037, 1944.47629506, 1953.85856831, 1963.24670620, + 1972.64068498, 1982.04048108, 1991.44607117, 2000.85743204, + 2010.27454072, 2019.69737440, 2029.12591044, 2038.56012640, +} /* lossless_enc.c:159:13 */ + +var kPrefixEncodeCode = [512]VP8LPrefixCode{ + VP8LPrefixCode{}, VP8LPrefixCode{}, VP8LPrefixCode{code_: int8(1)}, VP8LPrefixCode{code_: int8(2)}, VP8LPrefixCode{code_: int8(3)}, VP8LPrefixCode{code_: int8(4), extra_bits_: int8(1)}, VP8LPrefixCode{code_: int8(4), extra_bits_: int8(1)}, VP8LPrefixCode{code_: int8(5), extra_bits_: int8(1)}, + VP8LPrefixCode{code_: int8(5), extra_bits_: int8(1)}, VP8LPrefixCode{code_: int8(6), extra_bits_: int8(2)}, VP8LPrefixCode{code_: int8(6), extra_bits_: int8(2)}, VP8LPrefixCode{code_: int8(6), extra_bits_: int8(2)}, VP8LPrefixCode{code_: int8(6), extra_bits_: int8(2)}, VP8LPrefixCode{code_: int8(7), extra_bits_: int8(2)}, VP8LPrefixCode{code_: int8(7), extra_bits_: int8(2)}, VP8LPrefixCode{code_: int8(7), extra_bits_: int8(2)}, + VP8LPrefixCode{code_: int8(7), extra_bits_: int8(2)}, VP8LPrefixCode{code_: int8(8), extra_bits_: int8(3)}, VP8LPrefixCode{code_: int8(8), extra_bits_: int8(3)}, VP8LPrefixCode{code_: int8(8), extra_bits_: int8(3)}, VP8LPrefixCode{code_: int8(8), extra_bits_: int8(3)}, VP8LPrefixCode{code_: int8(8), extra_bits_: int8(3)}, VP8LPrefixCode{code_: int8(8), extra_bits_: int8(3)}, VP8LPrefixCode{code_: int8(8), extra_bits_: int8(3)}, + VP8LPrefixCode{code_: int8(8), extra_bits_: int8(3)}, VP8LPrefixCode{code_: int8(9), extra_bits_: int8(3)}, VP8LPrefixCode{code_: int8(9), extra_bits_: int8(3)}, VP8LPrefixCode{code_: int8(9), extra_bits_: int8(3)}, VP8LPrefixCode{code_: int8(9), extra_bits_: int8(3)}, VP8LPrefixCode{code_: int8(9), extra_bits_: int8(3)}, VP8LPrefixCode{code_: int8(9), extra_bits_: int8(3)}, VP8LPrefixCode{code_: int8(9), extra_bits_: int8(3)}, + VP8LPrefixCode{code_: int8(9), extra_bits_: int8(3)}, VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, + VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, + VP8LPrefixCode{code_: int8(10), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, + VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, + VP8LPrefixCode{code_: int8(11), extra_bits_: int8(4)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, + VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, + VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, + VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, + VP8LPrefixCode{code_: int8(12), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, + VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, + VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, + VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, + VP8LPrefixCode{code_: int8(13), extra_bits_: int8(5)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(14), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, + VP8LPrefixCode{code_: int8(15), extra_bits_: int8(6)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(16), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, + VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, VP8LPrefixCode{code_: int8(17), extra_bits_: int8(7)}, +} /* lossless_enc.c:226:22 */ + +var kPrefixEncodeExtraBitsValue = [512]uint8_t{ + uint8_t(0), uint8_t(0), uint8_t(0), uint8_t(0), uint8_t(0), uint8_t(0), uint8_t(1), uint8_t(0), uint8_t(1), uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), + uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(4), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(4), uint8_t(5), uint8_t(6), uint8_t(7), + uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(4), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(10), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(14), uint8_t(15), + uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(4), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(10), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(14), uint8_t(15), + uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(4), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(10), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(14), uint8_t(15), + uint8_t(16), uint8_t(17), uint8_t(18), uint8_t(19), uint8_t(20), uint8_t(21), uint8_t(22), uint8_t(23), uint8_t(24), uint8_t(25), uint8_t(26), uint8_t(27), uint8_t(28), uint8_t(29), uint8_t(30), uint8_t(31), + uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(4), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(10), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(14), uint8_t(15), + uint8_t(16), uint8_t(17), uint8_t(18), uint8_t(19), uint8_t(20), uint8_t(21), uint8_t(22), uint8_t(23), uint8_t(24), uint8_t(25), uint8_t(26), uint8_t(27), uint8_t(28), uint8_t(29), uint8_t(30), uint8_t(31), + uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(4), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(10), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(14), uint8_t(15), + uint8_t(16), uint8_t(17), uint8_t(18), uint8_t(19), uint8_t(20), uint8_t(21), uint8_t(22), uint8_t(23), uint8_t(24), uint8_t(25), uint8_t(26), uint8_t(27), uint8_t(28), uint8_t(29), uint8_t(30), uint8_t(31), + uint8_t(32), uint8_t(33), uint8_t(34), uint8_t(35), uint8_t(36), uint8_t(37), uint8_t(38), uint8_t(39), uint8_t(40), uint8_t(41), uint8_t(42), uint8_t(43), uint8_t(44), uint8_t(45), uint8_t(46), uint8_t(47), + uint8_t(48), uint8_t(49), uint8_t(50), uint8_t(51), uint8_t(52), uint8_t(53), uint8_t(54), uint8_t(55), uint8_t(56), uint8_t(57), uint8_t(58), uint8_t(59), uint8_t(60), uint8_t(61), uint8_t(62), uint8_t(63), + uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(4), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(10), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(14), uint8_t(15), + uint8_t(16), uint8_t(17), uint8_t(18), uint8_t(19), uint8_t(20), uint8_t(21), uint8_t(22), uint8_t(23), uint8_t(24), uint8_t(25), uint8_t(26), uint8_t(27), uint8_t(28), uint8_t(29), uint8_t(30), uint8_t(31), + uint8_t(32), uint8_t(33), uint8_t(34), uint8_t(35), uint8_t(36), uint8_t(37), uint8_t(38), uint8_t(39), uint8_t(40), uint8_t(41), uint8_t(42), uint8_t(43), uint8_t(44), uint8_t(45), uint8_t(46), uint8_t(47), + uint8_t(48), uint8_t(49), uint8_t(50), uint8_t(51), uint8_t(52), uint8_t(53), uint8_t(54), uint8_t(55), uint8_t(56), uint8_t(57), uint8_t(58), uint8_t(59), uint8_t(60), uint8_t(61), uint8_t(62), uint8_t(63), + uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(4), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(10), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(14), uint8_t(15), + uint8_t(16), uint8_t(17), uint8_t(18), uint8_t(19), uint8_t(20), uint8_t(21), uint8_t(22), uint8_t(23), uint8_t(24), uint8_t(25), uint8_t(26), uint8_t(27), uint8_t(28), uint8_t(29), uint8_t(30), uint8_t(31), + uint8_t(32), uint8_t(33), uint8_t(34), uint8_t(35), uint8_t(36), uint8_t(37), uint8_t(38), uint8_t(39), uint8_t(40), uint8_t(41), uint8_t(42), uint8_t(43), uint8_t(44), uint8_t(45), uint8_t(46), uint8_t(47), + uint8_t(48), uint8_t(49), uint8_t(50), uint8_t(51), uint8_t(52), uint8_t(53), uint8_t(54), uint8_t(55), uint8_t(56), uint8_t(57), uint8_t(58), uint8_t(59), uint8_t(60), uint8_t(61), uint8_t(62), uint8_t(63), + uint8_t(64), uint8_t(65), uint8_t(66), uint8_t(67), uint8_t(68), uint8_t(69), uint8_t(70), uint8_t(71), uint8_t(72), uint8_t(73), uint8_t(74), uint8_t(75), uint8_t(76), uint8_t(77), uint8_t(78), uint8_t(79), + uint8_t(80), uint8_t(81), uint8_t(82), uint8_t(83), uint8_t(84), uint8_t(85), uint8_t(86), uint8_t(87), uint8_t(88), uint8_t(89), uint8_t(90), uint8_t(91), uint8_t(92), uint8_t(93), uint8_t(94), uint8_t(95), + uint8_t(96), uint8_t(97), uint8_t(98), uint8_t(99), uint8_t(100), uint8_t(101), uint8_t(102), uint8_t(103), uint8_t(104), uint8_t(105), uint8_t(106), uint8_t(107), uint8_t(108), uint8_t(109), uint8_t(110), uint8_t(111), + uint8_t(112), uint8_t(113), uint8_t(114), uint8_t(115), uint8_t(116), uint8_t(117), uint8_t(118), uint8_t(119), uint8_t(120), uint8_t(121), uint8_t(122), uint8_t(123), uint8_t(124), uint8_t(125), uint8_t(126), + uint8_t(127), + uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(4), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(10), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(14), uint8_t(15), + uint8_t(16), uint8_t(17), uint8_t(18), uint8_t(19), uint8_t(20), uint8_t(21), uint8_t(22), uint8_t(23), uint8_t(24), uint8_t(25), uint8_t(26), uint8_t(27), uint8_t(28), uint8_t(29), uint8_t(30), uint8_t(31), + uint8_t(32), uint8_t(33), uint8_t(34), uint8_t(35), uint8_t(36), uint8_t(37), uint8_t(38), uint8_t(39), uint8_t(40), uint8_t(41), uint8_t(42), uint8_t(43), uint8_t(44), uint8_t(45), uint8_t(46), uint8_t(47), + uint8_t(48), uint8_t(49), uint8_t(50), uint8_t(51), uint8_t(52), uint8_t(53), uint8_t(54), uint8_t(55), uint8_t(56), uint8_t(57), uint8_t(58), uint8_t(59), uint8_t(60), uint8_t(61), uint8_t(62), uint8_t(63), + uint8_t(64), uint8_t(65), uint8_t(66), uint8_t(67), uint8_t(68), uint8_t(69), uint8_t(70), uint8_t(71), uint8_t(72), uint8_t(73), uint8_t(74), uint8_t(75), uint8_t(76), uint8_t(77), uint8_t(78), uint8_t(79), + uint8_t(80), uint8_t(81), uint8_t(82), uint8_t(83), uint8_t(84), uint8_t(85), uint8_t(86), uint8_t(87), uint8_t(88), uint8_t(89), uint8_t(90), uint8_t(91), uint8_t(92), uint8_t(93), uint8_t(94), uint8_t(95), + uint8_t(96), uint8_t(97), uint8_t(98), uint8_t(99), uint8_t(100), uint8_t(101), uint8_t(102), uint8_t(103), uint8_t(104), uint8_t(105), uint8_t(106), uint8_t(107), uint8_t(108), uint8_t(109), uint8_t(110), uint8_t(111), + uint8_t(112), uint8_t(113), uint8_t(114), uint8_t(115), uint8_t(116), uint8_t(117), uint8_t(118), uint8_t(119), uint8_t(120), uint8_t(121), uint8_t(122), uint8_t(123), uint8_t(124), uint8_t(125), uint8_t(126), +} /* lossless_enc.c:293:15 */ + +func FastSLog2Slow_C(tls *libc.TLS, v uint32_t) float32 { /* lossless_enc.c:329:14: */ + + if v < uint32_t(65536) { + // use clz if available + var log_cnt int32 = (BitsLog2Floor(tls, v) - 7) + var y uint32_t = (uint32_t(int32(1) << log_cnt)) + var correction int32 = 0 + var v_f float32 = float32(v) + var orig_v uint32_t = v + v >>= log_cnt + // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256 + // Xf = floor(Xf) * (1 + (v % y) / v) + // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v) + // The correction factor: log(1 + d) ~ d; for very small d values, so + // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v + // LOG_2_RECIPROCAL ~ 23/16 + correction = (int32((uint32_t(23) * (orig_v & (y - uint32_t(1)))) >> 4)) + return ((v_f * (kLog2Table[v] + float32(log_cnt))) + float32(correction)) + } else { + return (float32((1.44269504088896338700465094007086 * float64(v)) * libc.Xlog(tls, float64(v)))) + } + return float32(0) +} + +func FastLog2Slow_C(tls *libc.TLS, v uint32_t) float32 { /* lossless_enc.c:365:14: */ + + if v < uint32_t(65536) { + // use clz if available + var log_cnt int32 = (BitsLog2Floor(tls, v) - 7) + var y uint32_t = (uint32_t(int32(1) << log_cnt)) + var orig_v uint32_t = v + var log_2 float64 + v >>= log_cnt + log_2 = (float64(kLog2Table[v] + float32(log_cnt))) + if orig_v >= uint32_t(4096) { + // Since the division is still expensive, add this correction factor only + // for large values of 'v'. + var correction int32 = (int32((uint32_t(23) * (orig_v & (y - uint32_t(1)))) >> 4)) + log_2 = log_2 + (float64(correction) / float64(orig_v)) + } + return float32(log_2) + } else { + return (float32(1.44269504088896338700465094007086 * libc.Xlog(tls, float64(v)))) + } + return float32(0) +} + +//------------------------------------------------------------------------------ +// Methods to calculate Entropy (Shannon). + +// Compute the combined Shanon's entropy for distribution {X} and {X+Y} +func CombinedShannonEntropy_C(tls *libc.TLS, X uintptr, Y uintptr) float32 { /* lossless_enc.c:403:14: */ + var i int32 + var retval float64 = 0. + var sumX int32 = 0 + var sumXY int32 = 0 + for i = 0; i < 256; i++ { + var x int32 = *(*int32)(unsafe.Pointer(X + uintptr(i)*4)) + if x != 0 { + var xy int32 = (x + *(*int32)(unsafe.Pointer(Y + uintptr(i)*4))) + sumX = sumX + (x) + retval = retval - (float64(VP8LFastSLog2(tls, uint32(x)))) + sumXY = sumXY + (xy) + retval = retval - (float64(VP8LFastSLog2(tls, uint32(xy)))) + } else if *(*int32)(unsafe.Pointer(Y + uintptr(i)*4)) != 0 { + sumXY = sumXY + (*(*int32)(unsafe.Pointer(Y + uintptr(i)*4))) + retval = retval - (float64(VP8LFastSLog2(tls, uint32(*(*int32)(unsafe.Pointer(Y + uintptr(i)*4)))))) + } + } + retval = retval + (float64(VP8LFastSLog2(tls, uint32(sumX)) + VP8LFastSLog2(tls, uint32(sumXY)))) + return float32(retval) +} + +func VP8LBitEntropyInit(tls *libc.TLS, entropy uintptr) { /* lossless_enc.c:424:6: */ + (*VP8LBitEntropy)(unsafe.Pointer(entropy)).entropy = 0. + (*VP8LBitEntropy)(unsafe.Pointer(entropy)).sum = uint32_t(0) + (*VP8LBitEntropy)(unsafe.Pointer(entropy)).nonzeros = 0 + (*VP8LBitEntropy)(unsafe.Pointer(entropy)).max_val = uint32_t(0) + (*VP8LBitEntropy)(unsafe.Pointer(entropy)).nonzero_code = (0xffffffff) +} + +func VP8LBitsEntropyUnrefined(tls *libc.TLS, array uintptr, n int32, entropy uintptr) { /* lossless_enc.c:432:6: */ + var i int32 + + VP8LBitEntropyInit(tls, entropy) + + for i = 0; i < n; i++ { + if *(*uint32_t)(unsafe.Pointer(array + uintptr(i)*4)) != uint32_t(0) { + *(*uint32_t)(unsafe.Pointer((entropy + 8 /* &.sum */))) += (*(*uint32_t)(unsafe.Pointer(array + uintptr(i)*4))) + (*VP8LBitEntropy)(unsafe.Pointer(entropy)).nonzero_code = uint32_t(i) + (*VP8LBitEntropy)(unsafe.Pointer(entropy)).nonzeros++ + *(*float64)(unsafe.Pointer((entropy /* &.entropy */))) -= (float64(VP8LFastSLog2(tls, *(*uint32_t)(unsafe.Pointer(array + uintptr(i)*4))))) + if (*VP8LBitEntropy)(unsafe.Pointer(entropy)).max_val < *(*uint32_t)(unsafe.Pointer(array + uintptr(i)*4)) { + (*VP8LBitEntropy)(unsafe.Pointer(entropy)).max_val = *(*uint32_t)(unsafe.Pointer(array + uintptr(i)*4)) + } + } + } + *(*float64)(unsafe.Pointer((entropy /* &.entropy */))) += (float64(VP8LFastSLog2(tls, (*VP8LBitEntropy)(unsafe.Pointer(entropy)).sum))) +} + +func GetEntropyUnrefinedHelper(tls *libc.TLS, val uint32_t, i int32, val_prev uintptr, i_prev uintptr, bit_entropy uintptr, stats uintptr) { /* lossless_enc.c:452:25: */ + var streak int32 = (i - *(*int32)(unsafe.Pointer(i_prev))) + + // Gather info for the bit entropy. + if *(*uint32_t)(unsafe.Pointer(val_prev)) != uint32_t(0) { + *(*uint32_t)(unsafe.Pointer((bit_entropy + 8 /* &.sum */))) += ((*(*uint32_t)(unsafe.Pointer(val_prev))) * uint32_t(streak)) + *(*int32)(unsafe.Pointer((bit_entropy + 12 /* &.nonzeros */))) += (streak) + (*VP8LBitEntropy)(unsafe.Pointer(bit_entropy)).nonzero_code = uint32_t(*(*int32)(unsafe.Pointer(i_prev))) + *(*float64)(unsafe.Pointer((bit_entropy /* &.entropy */))) -= (float64(VP8LFastSLog2(tls, *(*uint32_t)(unsafe.Pointer(val_prev))) * float32(streak))) + if (*VP8LBitEntropy)(unsafe.Pointer(bit_entropy)).max_val < *(*uint32_t)(unsafe.Pointer(val_prev)) { + (*VP8LBitEntropy)(unsafe.Pointer(bit_entropy)).max_val = *(*uint32_t)(unsafe.Pointer(val_prev)) + } + } + + // Gather info for the Huffman cost. + *(*int32)(unsafe.Pointer(((stats /* &.counts */) + uintptr((libc.Bool32(*(*uint32_t)(unsafe.Pointer(val_prev)) != uint32_t(0))))*4))) += (libc.Bool32(streak > 3)) + *(*int32)(unsafe.Pointer((((stats + 8 /* &.streaks */) + uintptr((libc.Bool32(*(*uint32_t)(unsafe.Pointer(val_prev)) != uint32_t(0))))*8) + uintptr((libc.Bool32(streak > 3)))*4))) += (streak) + + *(*uint32_t)(unsafe.Pointer(val_prev)) = val + *(*int32)(unsafe.Pointer(i_prev)) = i +} + +func GetEntropyUnrefined_C(tls *libc.TLS, X uintptr, length int32, bit_entropy uintptr, stats uintptr) { /* lossless_enc.c:476:13: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var i int32 + *(*int32)(unsafe.Pointer(bp + 4 /* i_prev */)) = 0 + *(*uint32_t)(unsafe.Pointer(bp /* x_prev */)) = *(*uint32_t)(unsafe.Pointer(X)) + + libc.Xmemset(tls, stats, 0, uint64(unsafe.Sizeof(VP8LStreaks{}))) + VP8LBitEntropyInit(tls, bit_entropy) + + for i = 1; i < length; i++ { + var x uint32_t = *(*uint32_t)(unsafe.Pointer(X + uintptr(i)*4)) + if x != *(*uint32_t)(unsafe.Pointer(bp /* x_prev */)) { + GetEntropyUnrefinedHelper(tls, x, i, (bp) /* &x_prev */, (bp + 4) /* &i_prev */, bit_entropy, stats) + } + } + GetEntropyUnrefinedHelper(tls, uint32(0), i, (bp) /* &x_prev */, (bp + 4) /* &i_prev */, bit_entropy, stats) + + *(*float64)(unsafe.Pointer((bit_entropy /* &.entropy */))) += (float64(VP8LFastSLog2(tls, (*VP8LBitEntropy)(unsafe.Pointer(bit_entropy)).sum))) +} + +func GetCombinedEntropyUnrefined_C(tls *libc.TLS, X uintptr, Y uintptr, length int32, bit_entropy uintptr, stats uintptr) { /* lossless_enc.c:497:13: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var i int32 = 1 + *(*int32)(unsafe.Pointer(bp + 4 /* i_prev */)) = 0 + *(*uint32_t)(unsafe.Pointer(bp /* xy_prev */)) = (*(*uint32_t)(unsafe.Pointer(X)) + *(*uint32_t)(unsafe.Pointer(Y))) + + libc.Xmemset(tls, stats, 0, uint64(unsafe.Sizeof(VP8LStreaks{}))) + VP8LBitEntropyInit(tls, bit_entropy) + + for i = 1; i < length; i++ { + var xy uint32_t = (*(*uint32_t)(unsafe.Pointer(X + uintptr(i)*4)) + *(*uint32_t)(unsafe.Pointer(Y + uintptr(i)*4))) + if xy != *(*uint32_t)(unsafe.Pointer(bp /* xy_prev */)) { + GetEntropyUnrefinedHelper(tls, xy, i, (bp) /* &xy_prev */, (bp + 4) /* &i_prev */, bit_entropy, stats) + } + } + GetEntropyUnrefinedHelper(tls, uint32(0), i, (bp) /* &xy_prev */, (bp + 4) /* &i_prev */, bit_entropy, stats) + + *(*float64)(unsafe.Pointer((bit_entropy /* &.entropy */))) += (float64(VP8LFastSLog2(tls, (*VP8LBitEntropy)(unsafe.Pointer(bit_entropy)).sum))) +} + +//------------------------------------------------------------------------------ + +func VP8LSubtractGreenFromBlueAndRed_C(tls *libc.TLS, argb_data uintptr, num_pixels int32) { /* lossless_enc.c:522:6: */ + var i int32 + for i = 0; i < num_pixels; i++ { + var argb int32 = int32(*(*uint32_t)(unsafe.Pointer(argb_data + uintptr(i)*4))) + var green int32 = ((argb >> 8) & 0xff) + var new_r uint32_t = (uint32_t((((argb >> 16) & 0xff) - green) & 0xff)) + var new_b uint32_t = (uint32_t((((argb >> 0) & 0xff) - green) & 0xff)) + *(*uint32_t)(unsafe.Pointer(argb_data + uintptr(i)*4)) = (((uint32(argb) & 0xff00ff00) | (new_r << 16)) | new_b) + } +} + +func ColorTransformDelta1(tls *libc.TLS, color_pred int8_t, color int8_t) int32 { /* lossless_enc.c:533:24: */ + return ((int32(color_pred) * int32(color)) >> 5) +} + +func U32ToS8(tls *libc.TLS, v uint32_t) int8_t { /* lossless_enc.c:537:27: */ + return (int8_t(v & uint32_t(0xff))) +} + +func VP8LTransformColor_C(tls *libc.TLS, m uintptr, data uintptr, num_pixels int32) { /* lossless_enc.c:541:6: */ + var i int32 + for i = 0; i < num_pixels; i++ { + var argb uint32_t = *(*uint32_t)(unsafe.Pointer(data + uintptr(i)*4)) + var green int8_t = U32ToS8(tls, (argb >> 8)) + var red int8_t = U32ToS8(tls, (argb >> 16)) + var new_red int32 = (int32(red) & 0xff) + var new_blue int32 = (int32(argb & uint32_t(0xff))) + new_red = new_red - (ColorTransformDelta1(tls, int8((*VP8LMultipliers)(unsafe.Pointer(m)).green_to_red_), green)) + new_red = new_red & (0xff) + new_blue = new_blue - (ColorTransformDelta1(tls, int8((*VP8LMultipliers)(unsafe.Pointer(m)).green_to_blue_), green)) + new_blue = new_blue - (ColorTransformDelta1(tls, int8((*VP8LMultipliers)(unsafe.Pointer(m)).red_to_blue_), red)) + new_blue = new_blue & (0xff) + *(*uint32_t)(unsafe.Pointer(data + uintptr(i)*4)) = (((argb & 0xff00ff00) | (uint32_t(new_red << 16))) | (uint32_t(new_blue))) + } +} + +func TransformColorRed(tls *libc.TLS, green_to_red uint8_t, argb uint32_t) uint8_t { /* lossless_enc.c:559:28: */ + var green int8_t = U32ToS8(tls, (argb >> 8)) + var new_red int32 = (int32(argb >> 16)) + new_red = new_red - (ColorTransformDelta1(tls, int8(green_to_red), green)) + return (uint8_t(new_red & 0xff)) +} + +func TransformColorBlue(tls *libc.TLS, green_to_blue uint8_t, red_to_blue uint8_t, argb uint32_t) uint8_t { /* lossless_enc.c:567:28: */ + var green int8_t = U32ToS8(tls, (argb >> 8)) + var red int8_t = U32ToS8(tls, (argb >> 16)) + var new_blue uint8_t = (uint8_t(argb & uint32_t(0xff))) + new_blue = uint8_t(int32(new_blue) - (ColorTransformDelta1(tls, int8(green_to_blue), green))) + new_blue = uint8_t(int32(new_blue) - (ColorTransformDelta1(tls, int8(red_to_blue), red))) + return (uint8_t(int32(new_blue) & 0xff)) +} + +func VP8LCollectColorRedTransforms_C(tls *libc.TLS, argb uintptr, stride int32, tile_width int32, tile_height int32, green_to_red int32, histo uintptr) { /* lossless_enc.c:578:6: */ + for libc.PostDecInt32(&tile_height, 1) > 0 { + var x int32 + for x = 0; x < tile_width; x++ { + *(*int32)(unsafe.Pointer(histo + uintptr(TransformColorRed(tls, uint8_t(green_to_red), *(*uint32_t)(unsafe.Pointer(argb + uintptr(x)*4))))*4))++ + } + argb += 4 * (uintptr(stride)) + } +} + +func VP8LCollectColorBlueTransforms_C(tls *libc.TLS, argb uintptr, stride int32, tile_width int32, tile_height int32, green_to_blue int32, red_to_blue int32, histo uintptr) { /* lossless_enc.c:590:6: */ + for libc.PostDecInt32(&tile_height, 1) > 0 { + var x int32 + for x = 0; x < tile_width; x++ { + *(*int32)(unsafe.Pointer(histo + uintptr(TransformColorBlue(tls, uint8_t(green_to_blue), uint8_t(red_to_blue), + *(*uint32_t)(unsafe.Pointer(argb + uintptr(x)*4))))*4))++ + } + argb += 4 * (uintptr(stride)) + } +} + +//------------------------------------------------------------------------------ + +func VectorMismatch_C(tls *libc.TLS, array1 uintptr, array2 uintptr, length int32) int32 { /* lossless_enc.c:606:12: */ + var match_len int32 = 0 + + for (match_len < length) && (*(*uint32_t)(unsafe.Pointer(array1 + uintptr(match_len)*4)) == *(*uint32_t)(unsafe.Pointer(array2 + uintptr(match_len)*4))) { + match_len++ + } + return match_len +} + +// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel. +func VP8LBundleColorMap_C(tls *libc.TLS, row uintptr, width int32, xbits int32, dst uintptr) { /* lossless_enc.c:617:6: */ + var x int32 + if xbits > 0 { + var bit_depth int32 = (int32(1) << (3 - xbits)) + var mask int32 = ((int32(1) << xbits) - 1) + var code uint32_t = 0xff000000 + for x = 0; x < width; x++ { + var xsub int32 = (x & mask) + if xsub == 0 { + code = 0xff000000 + } + code = code | (uint32_t(int32(*(*uint8_t)(unsafe.Pointer(row + uintptr(x)))) << (8 + (bit_depth * xsub)))) + *(*uint32_t)(unsafe.Pointer(dst + uintptr((x>>xbits))*4)) = code + } + } else { + for x = 0; x < width; x++ { + *(*uint32_t)(unsafe.Pointer(dst + uintptr(x)*4)) = (0xff000000 | (uint32(int32(*(*uint8_t)(unsafe.Pointer(row + uintptr(x)))) << 8))) + } + } +} + +//------------------------------------------------------------------------------ + +func ExtraCost_C(tls *libc.TLS, population uintptr, length int32) float64 { /* lossless_enc.c:639:15: */ + var i int32 + var cost float64 = 0. + for i = 2; i < (length - 2); i++ { + cost = cost + (float64((uint32_t(i >> 1)) * *(*uint32_t)(unsafe.Pointer(population + uintptr((i+2))*4)))) + } + return cost +} + +func ExtraCostCombined_C(tls *libc.TLS, X uintptr, Y uintptr, length int32) float64 { /* lossless_enc.c:646:15: */ + var i int32 + var cost float64 = 0. + for i = 2; i < (length - 2); i++ { + var xy int32 = (int32(*(*uint32_t)(unsafe.Pointer(X + uintptr((i+2))*4)) + *(*uint32_t)(unsafe.Pointer(Y + uintptr((i+2))*4)))) + cost = cost + (float64((i >> 1) * xy)) + } + return cost +} + +//------------------------------------------------------------------------------ + +func AddVector_C(tls *libc.TLS, a uintptr, b uintptr, out uintptr, size int32) { /* lossless_enc.c:659:13: */ + var i int32 + for i = 0; i < size; i++ { + *(*uint32_t)(unsafe.Pointer(out + uintptr(i)*4)) = (*(*uint32_t)(unsafe.Pointer(a + uintptr(i)*4)) + *(*uint32_t)(unsafe.Pointer(b + uintptr(i)*4))) + } +} + +func AddVectorEq_C(tls *libc.TLS, a uintptr, out uintptr, size int32) { /* lossless_enc.c:665:13: */ + var i int32 + for i = 0; i < size; i++ { + *(*uint32_t)(unsafe.Pointer((out + uintptr(i)*4))) += (*(*uint32_t)(unsafe.Pointer(a + uintptr(i)*4))) + } +} + +func VP8LHistogramAdd(tls *libc.TLS, a uintptr, b uintptr, out uintptr) { /* lossless_enc.c:694:6: */ + var i int32 + var literal_size int32 = VP8LHistogramNumCodes(tls, (*VP8LHistogram)(unsafe.Pointer(a)).palette_code_bits_) + + if b != out { + for ok := true; ok; ok = (0 != 0) { + if *(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */))) != 0 { + if *(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */))) != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8LAddVector})).f(tls, (*VP8LHistogram)(unsafe.Pointer(a)).literal_, (*VP8LHistogram)(unsafe.Pointer(b)).literal_, (*VP8LHistogram)(unsafe.Pointer(out)).literal_, (literal_size)) + } else { + libc.Xmemcpy(tls, ((*VP8LHistogram)(unsafe.Pointer(out)).literal_), ((*VP8LHistogram)(unsafe.Pointer(a)).literal_), ((uint64(literal_size)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + } else if *(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */))) != 0 { + libc.Xmemcpy(tls, ((*VP8LHistogram)(unsafe.Pointer(out)).literal_), ((*VP8LHistogram)(unsafe.Pointer(b)).literal_), ((uint64(literal_size)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } else { + libc.Xmemset(tls, ((*VP8LHistogram)(unsafe.Pointer(out)).literal_), 0, ((uint64(literal_size)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + } + for ok1 := true; ok1; ok1 = (0 != 0) { + if *(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */) + 1)) != 0 { + if *(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */) + 1)) != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8LAddVector})).f(tls, (a + 8 /* &.red_ */), (b + 8 /* &.red_ */), (out + 8 /* &.red_ */), (256)) + } else { + libc.Xmemcpy(tls, (out + 8 /* &.red_ */), (a + 8 /* &.red_ */), ((uint64(256)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + } else if *(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */) + 1)) != 0 { + libc.Xmemcpy(tls, (out + 8 /* &.red_ */), (b + 8 /* &.red_ */), ((uint64(256)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } else { + libc.Xmemset(tls, (out + 8 /* &.red_ */), 0, ((uint64(256)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + } + for ok2 := true; ok2; ok2 = (0 != 0) { + if *(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */) + 2)) != 0 { + if *(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */) + 2)) != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8LAddVector})).f(tls, (a + 1032 /* &.blue_ */), (b + 1032 /* &.blue_ */), (out + 1032 /* &.blue_ */), (256)) + } else { + libc.Xmemcpy(tls, (out + 1032 /* &.blue_ */), (a + 1032 /* &.blue_ */), ((uint64(256)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + } else if *(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */) + 2)) != 0 { + libc.Xmemcpy(tls, (out + 1032 /* &.blue_ */), (b + 1032 /* &.blue_ */), ((uint64(256)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } else { + libc.Xmemset(tls, (out + 1032 /* &.blue_ */), 0, ((uint64(256)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + } + for ok3 := true; ok3; ok3 = (0 != 0) { + if *(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */) + 3)) != 0 { + if *(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */) + 3)) != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8LAddVector})).f(tls, (a + 2056 /* &.alpha_ */), (b + 2056 /* &.alpha_ */), (out + 2056 /* &.alpha_ */), (256)) + } else { + libc.Xmemcpy(tls, (out + 2056 /* &.alpha_ */), (a + 2056 /* &.alpha_ */), ((uint64(256)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + } else if *(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */) + 3)) != 0 { + libc.Xmemcpy(tls, (out + 2056 /* &.alpha_ */), (b + 2056 /* &.alpha_ */), ((uint64(256)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } else { + libc.Xmemset(tls, (out + 2056 /* &.alpha_ */), 0, ((uint64(256)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + } + for ok4 := true; ok4; ok4 = (0 != 0) { + if *(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */) + 4)) != 0 { + if *(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */) + 4)) != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8LAddVector})).f(tls, (a + 3080 /* &.distance_ */), (b + 3080 /* &.distance_ */), (out + 3080 /* &.distance_ */), (40)) + } else { + libc.Xmemcpy(tls, (out + 3080 /* &.distance_ */), (a + 3080 /* &.distance_ */), ((uint64(40)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + } else if *(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */) + 4)) != 0 { + libc.Xmemcpy(tls, (out + 3080 /* &.distance_ */), (b + 3080 /* &.distance_ */), ((uint64(40)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } else { + libc.Xmemset(tls, (out + 3080 /* &.distance_ */), 0, ((uint64(40)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + } + for i = 0; i < 5; i++ { + *(*uint8_t)(unsafe.Pointer((out + 3280 /* &.is_used_ */) + uintptr(i))) = (uint8_t(int32(*(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */) + uintptr(i)))) | int32(*(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */) + uintptr(i)))))) + } + } else { + for ok5 := true; ok5; ok5 = (0 != 0) { + if *(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */))) != 0 { + if *(*uint8_t)(unsafe.Pointer((out + 3280 /* &.is_used_ */))) != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8LAddVectorEq})).f(tls, (*VP8LHistogram)(unsafe.Pointer(a)).literal_, (*VP8LHistogram)(unsafe.Pointer(out)).literal_, (literal_size)) + } else { + libc.Xmemcpy(tls, ((*VP8LHistogram)(unsafe.Pointer(out)).literal_), ((*VP8LHistogram)(unsafe.Pointer(a)).literal_), ((uint64(literal_size)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + } + } + for ok6 := true; ok6; ok6 = (0 != 0) { + if *(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */) + 1)) != 0 { + if *(*uint8_t)(unsafe.Pointer((out + 3280 /* &.is_used_ */) + 1)) != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8LAddVectorEq})).f(tls, (a + 8 /* &.red_ */), (out + 8 /* &.red_ */), (256)) + } else { + libc.Xmemcpy(tls, (out + 8 /* &.red_ */), (a + 8 /* &.red_ */), ((uint64(256)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + } + } + for ok7 := true; ok7; ok7 = (0 != 0) { + if *(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */) + 2)) != 0 { + if *(*uint8_t)(unsafe.Pointer((out + 3280 /* &.is_used_ */) + 2)) != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8LAddVectorEq})).f(tls, (a + 1032 /* &.blue_ */), (out + 1032 /* &.blue_ */), (256)) + } else { + libc.Xmemcpy(tls, (out + 1032 /* &.blue_ */), (a + 1032 /* &.blue_ */), ((uint64(256)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + } + } + for ok8 := true; ok8; ok8 = (0 != 0) { + if *(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */) + 3)) != 0 { + if *(*uint8_t)(unsafe.Pointer((out + 3280 /* &.is_used_ */) + 3)) != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8LAddVectorEq})).f(tls, (a + 2056 /* &.alpha_ */), (out + 2056 /* &.alpha_ */), (256)) + } else { + libc.Xmemcpy(tls, (out + 2056 /* &.alpha_ */), (a + 2056 /* &.alpha_ */), ((uint64(256)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + } + } + for ok9 := true; ok9; ok9 = (0 != 0) { + if *(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */) + 4)) != 0 { + if *(*uint8_t)(unsafe.Pointer((out + 3280 /* &.is_used_ */) + 4)) != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8LAddVectorEq})).f(tls, (a + 3080 /* &.distance_ */), (out + 3080 /* &.distance_ */), (40)) + } else { + libc.Xmemcpy(tls, (out + 3080 /* &.distance_ */), (a + 3080 /* &.distance_ */), ((uint64(40)) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + } + } + for i = 0; i < 5; i++ { + *(*uint8_t)(unsafe.Pointer(((out + 3280 /* &.is_used_ */) + uintptr(i)))) |= uint8_t((int32(*(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */) + uintptr(i)))))) + } + } +} + +//------------------------------------------------------------------------------ +// Image transforms. + +func PredictorSub0_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless_enc.c:724:13: */ + var i int32 + for i = 0; i < num_pixels; i++ { + *(*uint32_t)(unsafe.Pointer(out + uintptr(i)*4)) = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(i)*4)), 0xff000000) + } + _ = upper +} + +func PredictorSub1_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless_enc.c:731:13: */ + var i int32 + for i = 0; i < num_pixels; i++ { + *(*uint32_t)(unsafe.Pointer(out + uintptr(i)*4)) = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(i)*4)), *(*uint32_t)(unsafe.Pointer(in + uintptr((i-1))*4))) + } + _ = upper +} + +// It subtracts the prediction from the input pixel and stores the residual +// in the output pixel. + +func PredictorSub2_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless_enc.c:753:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor2_C(tls, (in + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorSub3_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless_enc.c:754:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor3_C(tls, (in + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorSub4_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless_enc.c:755:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor4_C(tls, (in + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorSub5_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless_enc.c:756:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor5_C(tls, (in + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorSub6_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless_enc.c:757:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor6_C(tls, (in + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorSub7_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless_enc.c:758:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor7_C(tls, (in + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorSub8_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless_enc.c:759:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor8_C(tls, (in + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorSub9_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless_enc.c:760:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor9_C(tls, (in + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorSub10_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless_enc.c:761:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor10_C(tls, (in + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorSub11_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless_enc.c:762:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor11_C(tls, (in + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorSub12_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless_enc.c:763:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor12_C(tls, (in + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +func PredictorSub13_C(tls *libc.TLS, in uintptr, upper uintptr, num_pixels int32, out uintptr) { /* lossless_enc.c:764:1: */ + var x int32 + for x = 0; x < num_pixels; x++ { + var pred uint32_t = VP8LPredictor13_C(tls, (in + uintptr((x-1))*4), (upper + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(out + uintptr(x)*4)) = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(in + uintptr(x)*4)), pred) + } +} + +//------------------------------------------------------------------------------ + +var VP8LSubtractGreenFromBlueAndRed VP8LProcessEncBlueAndRedFunc /* lossless_enc.c:768:30: */ + +var VP8LTransformColor VP8LTransformColorFunc /* lossless_enc.c:770:24: */ + +var VP8LCollectColorBlueTransforms VP8LCollectColorBlueTransformsFunc /* lossless_enc.c:772:36: */ +var VP8LCollectColorRedTransforms VP8LCollectColorRedTransformsFunc /* lossless_enc.c:773:35: */ + +var VP8LFastLog2Slow VP8LFastLog2SlowFunc /* lossless_enc.c:775:22: */ +var VP8LFastSLog2Slow VP8LFastLog2SlowFunc /* lossless_enc.c:776:22: */ + +var VP8LExtraCost VP8LCostFunc /* lossless_enc.c:778:14: */ +var VP8LExtraCostCombined VP8LCostCombinedFunc /* lossless_enc.c:779:22: */ +var VP8LCombinedShannonEntropy VP8LCombinedShannonEntropyFunc /* lossless_enc.c:780:32: */ + +var VP8LGetEntropyUnrefined VP8LGetEntropyUnrefinedFunc /* lossless_enc.c:782:29: */ +var VP8LGetCombinedEntropyUnrefined VP8LGetCombinedEntropyUnrefinedFunc /* lossless_enc.c:783:37: */ + +var VP8LAddVector VP8LAddVectorFunc /* lossless_enc.c:785:19: */ +var VP8LAddVectorEq VP8LAddVectorEqFunc /* lossless_enc.c:786:21: */ + +var VP8LVectorMismatch VP8LVectorMismatchFunc /* lossless_enc.c:788:24: */ +var VP8LBundleColorMap VP8LBundleColorMapFunc /* lossless_enc.c:789:24: */ + +var VP8LPredictorsSub [16]VP8LPredictorAddSubFunc /* lossless_enc.c:791:25: */ +var VP8LPredictorsSub_C [16]VP8LPredictorAddSubFunc /* lossless_enc.c:792:25: */ + +func VP8LEncDspInit(tls *libc.TLS) { /* lossless_enc.c:801:1: */ + for ok := true; ok; ok = (0 != 0) { + if VP8LEncDspInit_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + VP8LEncDspInit_body(tls) + VP8LEncDspInit_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var VP8LEncDspInit_body_last_cpuinfo_used VP8CPUInfo = 0 /* lossless_enc.c:801:1 */ + +func VP8LEncDspInit_body(tls *libc.TLS) { /* lossless_enc.c:801:1: */ + VP8LDspInit(tls) + + VP8LSubtractGreenFromBlueAndRed = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32) + }{VP8LSubtractGreenFromBlueAndRed_C})) + + VP8LTransformColor = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) + }{VP8LTransformColor_C})) + + VP8LCollectColorBlueTransforms = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32, int32, uintptr) + }{VP8LCollectColorBlueTransforms_C})) + VP8LCollectColorRedTransforms = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32, uintptr) + }{VP8LCollectColorRedTransforms_C})) + + VP8LFastLog2Slow = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uint32_t) float32 + }{FastLog2Slow_C})) + VP8LFastSLog2Slow = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uint32_t) float32 + }{FastSLog2Slow_C})) + + VP8LExtraCost = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32) float64 + }{ExtraCost_C})) + VP8LExtraCostCombined = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) float64 + }{ExtraCostCombined_C})) + VP8LCombinedShannonEntropy = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) float32 + }{CombinedShannonEntropy_C})) + + VP8LGetEntropyUnrefined = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, uintptr, uintptr) + }{GetEntropyUnrefined_C})) + VP8LGetCombinedEntropyUnrefined = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr, uintptr) + }{GetCombinedEntropyUnrefined_C})) + + VP8LAddVector = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + }{AddVector_C})) + VP8LAddVectorEq = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) + }{AddVectorEq_C})) + + VP8LVectorMismatch = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + }{VectorMismatch_C})) + VP8LBundleColorMap = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, int32, uintptr) + }{VP8LBundleColorMap_C})) + + VP8LPredictorsSub[0] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub0_C})) + VP8LPredictorsSub[1] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub1_C})) + VP8LPredictorsSub[2] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub2_C})) + VP8LPredictorsSub[3] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub3_C})) + VP8LPredictorsSub[4] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub4_C})) + VP8LPredictorsSub[5] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub5_C})) + VP8LPredictorsSub[6] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub6_C})) + VP8LPredictorsSub[7] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub7_C})) + VP8LPredictorsSub[8] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub8_C})) + VP8LPredictorsSub[9] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub9_C})) + VP8LPredictorsSub[10] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub10_C})) + VP8LPredictorsSub[11] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub11_C})) + VP8LPredictorsSub[12] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub12_C})) + VP8LPredictorsSub[13] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub13_C})) + VP8LPredictorsSub[14] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub0_C})) // <- padding security sentinels + VP8LPredictorsSub[15] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub0_C})) + + VP8LPredictorsSub_C[0] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub0_C})) + VP8LPredictorsSub_C[1] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub1_C})) + VP8LPredictorsSub_C[2] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub2_C})) + VP8LPredictorsSub_C[3] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub3_C})) + VP8LPredictorsSub_C[4] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub4_C})) + VP8LPredictorsSub_C[5] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub5_C})) + VP8LPredictorsSub_C[6] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub6_C})) + VP8LPredictorsSub_C[7] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub7_C})) + VP8LPredictorsSub_C[8] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub8_C})) + VP8LPredictorsSub_C[9] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub9_C})) + VP8LPredictorsSub_C[10] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub10_C})) + VP8LPredictorsSub_C[11] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub11_C})) + VP8LPredictorsSub_C[12] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub12_C})) + VP8LPredictorsSub_C[13] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub13_C})) + VP8LPredictorsSub_C[14] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub0_C})) // <- padding security sentinels + VP8LPredictorsSub_C[15] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + }{PredictorSub0_C})) + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if VP8GetCPUInfo != (uintptr(0)) { + } + +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Implementations of critical functions ImportRow / ExportRow + +//------------------------------------------------------------------------------ +// Row import + +func WebPRescalerImportRowExpand_C(tls *libc.TLS, wrk uintptr, src uintptr) { /* rescaler.c:29:6: */ + var x_stride int32 = (*WebPRescaler)(unsafe.Pointer(wrk)).num_channels + var x_out_max int32 = ((*WebPRescaler)(unsafe.Pointer(wrk)).dst_width * (*WebPRescaler)(unsafe.Pointer(wrk)).num_channels) + var channel int32 + + for channel = 0; channel < x_stride; channel++ { + var x_in int32 = channel + var x_out int32 = channel + // simple bilinear interpolation + var accum int32 = (*WebPRescaler)(unsafe.Pointer(wrk)).x_add + var left rescaler_t = rescaler_t(*(*uint8_t)(unsafe.Pointer(src + uintptr(x_in)))) + var right rescaler_t + if (*WebPRescaler)(unsafe.Pointer(wrk)).src_width > 1 { + right = rescaler_t(*(*uint8_t)(unsafe.Pointer(src + uintptr((x_in + x_stride))))) + } else { + right = left + } + x_in = x_in + (x_stride) + for 1 != 0 { + *(*rescaler_t)(unsafe.Pointer((*WebPRescaler)(unsafe.Pointer(wrk)).frow + uintptr(x_out)*4)) = ((right * rescaler_t((*WebPRescaler)(unsafe.Pointer(wrk)).x_add)) + ((left - right) * rescaler_t(accum))) + x_out = x_out + (x_stride) + if x_out >= x_out_max { + break + } + accum = accum - ((*WebPRescaler)(unsafe.Pointer(wrk)).x_sub) + if accum < 0 { + left = right + x_in = x_in + (x_stride) + + right = rescaler_t(*(*uint8_t)(unsafe.Pointer(src + uintptr(x_in)))) + accum = accum + ((*WebPRescaler)(unsafe.Pointer(wrk)).x_add) + } + } + + } +} + +func WebPRescalerImportRowShrink_C(tls *libc.TLS, wrk uintptr, src uintptr) { /* rescaler.c:62:6: */ + var x_stride int32 = (*WebPRescaler)(unsafe.Pointer(wrk)).num_channels + var x_out_max int32 = ((*WebPRescaler)(unsafe.Pointer(wrk)).dst_width * (*WebPRescaler)(unsafe.Pointer(wrk)).num_channels) + var channel int32 + + for channel = 0; channel < x_stride; channel++ { + var x_in int32 = channel + var x_out int32 = channel + var sum uint32_t = uint32_t(0) + var accum int32 = 0 + for x_out < x_out_max { + var base uint32_t = uint32_t(0) + accum = accum + ((*WebPRescaler)(unsafe.Pointer(wrk)).x_add) + for accum > 0 { + accum = accum - ((*WebPRescaler)(unsafe.Pointer(wrk)).x_sub) + + base = uint32_t(*(*uint8_t)(unsafe.Pointer(src + uintptr(x_in)))) + sum = sum + (base) + x_in = x_in + (x_stride) + } + { // Emit next horizontal pixel. + var frac rescaler_t = (base * (uint32_t(-accum))) + *(*rescaler_t)(unsafe.Pointer((*WebPRescaler)(unsafe.Pointer(wrk)).frow + uintptr(x_out)*4)) = ((sum * uint32_t((*WebPRescaler)(unsafe.Pointer(wrk)).x_sub)) - frac) + // fresh fractional start for next pixel + sum = uint32_t((int32(((uint64((uint64_t(frac)) * (uint64_t((*WebPRescaler)(unsafe.Pointer(wrk)).fx_scale)))) + (uint64((uint64(1) << 32)) >> 1)) >> 32))) + + } + x_out = x_out + (x_stride) + } + + } +} + +//------------------------------------------------------------------------------ +// Row export + +func WebPRescalerExportRowExpand_C(tls *libc.TLS, wrk uintptr) { /* rescaler.c:99:6: */ + var x_out int32 + var dst uintptr = (*WebPRescaler)(unsafe.Pointer(wrk)).dst + var irow uintptr = (*WebPRescaler)(unsafe.Pointer(wrk)).irow + var x_out_max int32 = ((*WebPRescaler)(unsafe.Pointer(wrk)).dst_width * (*WebPRescaler)(unsafe.Pointer(wrk)).num_channels) + var frow uintptr = (*WebPRescaler)(unsafe.Pointer(wrk)).frow + + if (*WebPRescaler)(unsafe.Pointer(wrk)).y_accum == 0 { + for x_out = 0; x_out < x_out_max; x_out++ { + var J uint32_t = *(*rescaler_t)(unsafe.Pointer(frow + uintptr(x_out)*4)) + var v int32 = (int32(((uint64((uint64_t(J)) * (uint64_t((*WebPRescaler)(unsafe.Pointer(wrk)).fy_scale)))) + (uint64((uint64(1) << 32)) >> 1)) >> 32)) + *(*uint8_t)(unsafe.Pointer(dst + uintptr(x_out))) = func() uint8 { + if v > 255 { + return uint8(255) + } + return uint8_t(v) + }() + } + } else { + var B uint32_t = (uint32_t(((uint64_t(-(*WebPRescaler)(unsafe.Pointer(wrk)).y_accum)) << 32) / (uint64_t((*WebPRescaler)(unsafe.Pointer(wrk)).y_sub)))) + var A uint32_t = (uint32_t((uint64(1) << 32) - uint64(B))) + for x_out = 0; x_out < x_out_max; x_out++ { + var I uint64_t = ((uint64_t(A) * uint64_t(*(*rescaler_t)(unsafe.Pointer(frow + uintptr(x_out)*4)))) + + (uint64_t(B) * uint64_t(*(*rescaler_t)(unsafe.Pointer(irow + uintptr(x_out)*4))))) + var J uint32_t = (uint32_t((uint64(I) + (uint64((uint64(1) << 32)) >> 1)) >> 32)) + var v int32 = (int32(((uint64((uint64_t(J)) * (uint64_t((*WebPRescaler)(unsafe.Pointer(wrk)).fy_scale)))) + (uint64((uint64(1) << 32)) >> 1)) >> 32)) + *(*uint8_t)(unsafe.Pointer(dst + uintptr(x_out))) = func() uint8 { + if v > 255 { + return uint8(255) + } + return uint8_t(v) + }() + } + } +} + +func WebPRescalerExportRowShrink_C(tls *libc.TLS, wrk uintptr) { /* rescaler.c:128:6: */ + var x_out int32 + var dst uintptr = (*WebPRescaler)(unsafe.Pointer(wrk)).dst + var irow uintptr = (*WebPRescaler)(unsafe.Pointer(wrk)).irow + var x_out_max int32 = ((*WebPRescaler)(unsafe.Pointer(wrk)).dst_width * (*WebPRescaler)(unsafe.Pointer(wrk)).num_channels) + var frow uintptr = (*WebPRescaler)(unsafe.Pointer(wrk)).frow + var yscale uint32_t = ((*WebPRescaler)(unsafe.Pointer(wrk)).fy_scale * (uint32_t(-(*WebPRescaler)(unsafe.Pointer(wrk)).y_accum))) + + if yscale != 0 { + for x_out = 0; x_out < x_out_max; x_out++ { + var frac uint32_t = (uint32_t(((uint64_t(*(*rescaler_t)(unsafe.Pointer(frow + uintptr(x_out)*4)))) * (uint64_t(yscale))) >> 32)) + var v int32 = (int32(((uint64((uint64_t(*(*rescaler_t)(unsafe.Pointer(irow + uintptr(x_out)*4)) - frac)) * (uint64_t((*WebPRescaler)(unsafe.Pointer(wrk)).fxy_scale)))) + (uint64((uint64(1) << 32)) >> 1)) >> 32)) + *(*uint8_t)(unsafe.Pointer(dst + uintptr(x_out))) = func() uint8 { + if v > 255 { + return uint8(255) + } + return uint8_t(v) + }() + *(*rescaler_t)(unsafe.Pointer(irow + uintptr(x_out)*4)) = frac // new fractional start + } + } else { + for x_out = 0; x_out < x_out_max; x_out++ { + var v int32 = (int32(((uint64((uint64_t(*(*rescaler_t)(unsafe.Pointer(irow + uintptr(x_out)*4)))) * (uint64_t((*WebPRescaler)(unsafe.Pointer(wrk)).fxy_scale)))) + (uint64((uint64(1) << 32)) >> 1)) >> 32)) + *(*uint8_t)(unsafe.Pointer(dst + uintptr(x_out))) = func() uint8 { + if v > 255 { + return uint8(255) + } + return uint8_t(v) + }() + *(*rescaler_t)(unsafe.Pointer(irow + uintptr(x_out)*4)) = rescaler_t(0) + } + } +} + +//------------------------------------------------------------------------------ +// Main entry calls + +func WebPRescalerImportRow(tls *libc.TLS, wrk uintptr, src uintptr) { /* rescaler.c:161:6: */ + + if !((*WebPRescaler)(unsafe.Pointer(wrk)).x_expand != 0) { + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{WebPRescalerImportRowShrink})).f(tls, wrk, src) + } else { + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{WebPRescalerImportRowExpand})).f(tls, wrk, src) + } +} + +func WebPRescalerExportRow(tls *libc.TLS, wrk uintptr) { /* rescaler.c:170:6: */ + if (*WebPRescaler)(unsafe.Pointer(wrk)).y_accum <= 0 { + + if (*WebPRescaler)(unsafe.Pointer(wrk)).y_expand != 0 { + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{WebPRescalerExportRowExpand})).f(tls, wrk) + } else if (*WebPRescaler)(unsafe.Pointer(wrk)).fxy_scale != 0 { + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{WebPRescalerExportRowShrink})).f(tls, wrk) + } else { // special case + var i int32 + + for i = 0; i < ((*WebPRescaler)(unsafe.Pointer(wrk)).num_channels * (*WebPRescaler)(unsafe.Pointer(wrk)).dst_width); i++ { + *(*uint8_t)(unsafe.Pointer((*WebPRescaler)(unsafe.Pointer(wrk)).dst + uintptr(i))) = uint8_t(*(*rescaler_t)(unsafe.Pointer((*WebPRescaler)(unsafe.Pointer(wrk)).irow + uintptr(i)*4))) + *(*rescaler_t)(unsafe.Pointer((*WebPRescaler)(unsafe.Pointer(wrk)).irow + uintptr(i)*4)) = rescaler_t(0) + } + } + *(*int32)(unsafe.Pointer((wrk + 24 /* &.y_accum */))) += ((*WebPRescaler)(unsafe.Pointer(wrk)).y_add) + *(*uintptr)(unsafe.Pointer((wrk + 72 /* &.dst */))) += (uintptr((*WebPRescaler)(unsafe.Pointer(wrk)).dst_stride)) + (*WebPRescaler)(unsafe.Pointer(wrk)).dst_y++ + } +} + +//------------------------------------------------------------------------------ + +var WebPRescalerImportRowExpand WebPRescalerImportRowFunc /* rescaler.c:194:27: */ +var WebPRescalerImportRowShrink WebPRescalerImportRowFunc /* rescaler.c:195:27: */ + +var WebPRescalerExportRowExpand WebPRescalerExportRowFunc /* rescaler.c:197:27: */ +var WebPRescalerExportRowShrink WebPRescalerExportRowFunc /* rescaler.c:198:27: */ + +func WebPRescalerDspInit(tls *libc.TLS) { /* rescaler.c:206:1: */ + for ok := true; ok; ok = (0 != 0) { + if WebPRescalerDspInit_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + WebPRescalerDspInit_body(tls) + WebPRescalerDspInit_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var WebPRescalerDspInit_body_last_cpuinfo_used VP8CPUInfo = 0 /* rescaler.c:206:1 */ + +func WebPRescalerDspInit_body(tls *libc.TLS) { /* rescaler.c:206:1: */ + WebPRescalerExportRowExpand = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{WebPRescalerExportRowExpand_C})) + WebPRescalerExportRowShrink = *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{WebPRescalerExportRowShrink_C})) + + WebPRescalerImportRowExpand = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) + }{WebPRescalerImportRowExpand_C})) + WebPRescalerImportRowShrink = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) + }{WebPRescalerImportRowShrink_C})) + + if VP8GetCPUInfo != (uintptr(0)) { + } + +} + +//------------------------------------------------------------------------------ +// SSIM / PSNR + +// hat-shaped filter. Sum of coefficients is equal to 16. +var kWeight = [7]uint32_t{ + uint32_t(1), uint32_t(2), uint32_t(3), uint32_t(4), uint32_t(3), uint32_t(2), uint32_t(1), +} /* ssim.c:25:23 */ +var kWeightSum uint32_t = (uint32_t(16 * 16)) /* ssim.c:28:23 */ + +// sum{kWeight}^2 + +func SSIMCalculation(tls *libc.TLS, stats uintptr, N uint32_t) float64 { /* ssim.c:30:27: */ + var w2 uint32_t = (N * N) + var C1 uint32_t = (uint32_t(20) * w2) + var C2 uint32_t = (uint32_t(60) * w2) + var C3 uint32_t = ((uint32_t(8 * 8)) * w2) // 'dark' limit ~= 6 + var xmxm uint64_t = (uint64_t((*VP8DistoStats)(unsafe.Pointer(stats)).xm) * uint64_t((*VP8DistoStats)(unsafe.Pointer(stats)).xm)) + var ymym uint64_t = (uint64_t((*VP8DistoStats)(unsafe.Pointer(stats)).ym) * uint64_t((*VP8DistoStats)(unsafe.Pointer(stats)).ym)) + if (xmxm + ymym) >= uint64_t(C3) { + var xmym int64_t = (int64_t((*VP8DistoStats)(unsafe.Pointer(stats)).xm) * int64_t((*VP8DistoStats)(unsafe.Pointer(stats)).ym)) + var sxy int64_t = ((int64_t((*VP8DistoStats)(unsafe.Pointer(stats)).xym) * int64_t(N)) - xmym) // can be negative + var sxx uint64_t = ((uint64_t((*VP8DistoStats)(unsafe.Pointer(stats)).xxm) * uint64_t(N)) - xmxm) + var syy uint64_t = ((uint64_t((*VP8DistoStats)(unsafe.Pointer(stats)).yym) * uint64_t(N)) - ymym) + // we descale by 8 to prevent overflow during the fnum/fden multiply. + var num_S uint64_t = (((uint64(2) * (func() uint64 { + if sxy < int64(0) { + return uint64(0) + } + return uint64(sxy) + }())) + uint64_t(C2)) >> 8) + var den_S uint64_t = (((sxx + syy) + uint64_t(C2)) >> 8) + var fnum uint64_t = ((uint64_t((int64(2) * xmym) + int64_t(C1))) * num_S) + var fden uint64_t = (((xmxm + ymym) + uint64_t(C1)) * den_S) + var r float64 = (float64(fnum) / float64(fden)) + + return r + } + return 1. // area is too dark to contribute meaningfully +} + +func VP8SSIMFromStats(tls *libc.TLS, stats uintptr) float64 { /* ssim.c:55:8: */ + return SSIMCalculation(tls, stats, kWeightSum) +} + +func VP8SSIMFromStatsClipped(tls *libc.TLS, stats uintptr) float64 { /* ssim.c:59:8: */ + return SSIMCalculation(tls, stats, (*VP8DistoStats)(unsafe.Pointer(stats)).w) +} + +func SSIMGetClipped_C(tls *libc.TLS, src1 uintptr, stride1 int32, src2 uintptr, stride2 int32, xo int32, yo int32, W int32, H int32) float64 { /* ssim.c:63:15: */ + bp := tls.Alloc(24) + defer tls.Free(24) + + *(*VP8DistoStats)(unsafe.Pointer(bp /* stats */)) = VP8DistoStats{} + var ymin int32 + if (yo - 3) < 0 { + ymin = 0 + } else { + ymin = (yo - 3) + } + var ymax int32 + if (yo + 3) > (H - 1) { + ymax = (H - 1) + } else { + ymax = (yo + 3) + } + var xmin int32 + if (xo - 3) < 0 { + xmin = 0 + } else { + xmin = (xo - 3) + } + var xmax int32 + if (xo + 3) > (W - 1) { + xmax = (W - 1) + } else { + xmax = (xo + 3) + } + var x int32 + var y int32 + src1 += (uintptr(ymin * stride1)) + src2 += (uintptr(ymin * stride2)) + y = ymin +__1: + if !(y <= ymax) { + goto __3 + } + { + for x = xmin; x <= xmax; x++ { + var w uint32_t = (kWeight[((3+x)-xo)] * + kWeight[((3+y)-yo)]) + var s1 uint32_t = uint32_t(*(*uint8_t)(unsafe.Pointer(src1 + uintptr(x)))) + var s2 uint32_t = uint32_t(*(*uint8_t)(unsafe.Pointer(src2 + uintptr(x)))) + *(*uint32_t)(unsafe.Pointer((bp) /* &stats */ /* &.w */)) += (w) + *(*uint32_t)(unsafe.Pointer(((bp) /* &stats */ + 4 /* &.xm */))) += (w * s1) + *(*uint32_t)(unsafe.Pointer(((bp) /* &stats */ + 8 /* &.ym */))) += (w * s2) + *(*uint32_t)(unsafe.Pointer(((bp) /* &stats */ + 12 /* &.xxm */))) += ((w * s1) * s1) + *(*uint32_t)(unsafe.Pointer(((bp) /* &stats */ + 16 /* &.xym */))) += ((w * s1) * s2) + *(*uint32_t)(unsafe.Pointer(((bp) /* &stats */ + 20 /* &.yym */))) += ((w * s2) * s2) + } + + } + goto __2 +__2: + y++ + src1 += uintptr(stride1) + src2 += uintptr(stride2) + goto __1 + goto __3 +__3: + ; + return VP8SSIMFromStatsClipped(tls, (bp) /* &stats */) +} + +func SSIMGet_C(tls *libc.TLS, src1 uintptr, stride1 int32, src2 uintptr, stride2 int32) float64 { /* ssim.c:93:15: */ + bp := tls.Alloc(24) + defer tls.Free(24) + + *(*VP8DistoStats)(unsafe.Pointer(bp /* stats */)) = VP8DistoStats{} + var x int32 + var y int32 + y = 0 +__1: + if !(y <= (2 * 3)) { + goto __3 + } + { + for x = 0; x <= (2 * 3); x++ { + var w uint32_t = (kWeight[x] * kWeight[y]) + var s1 uint32_t = uint32_t(*(*uint8_t)(unsafe.Pointer(src1 + uintptr(x)))) + var s2 uint32_t = uint32_t(*(*uint8_t)(unsafe.Pointer(src2 + uintptr(x)))) + *(*uint32_t)(unsafe.Pointer(((bp) /* &stats */ + 4 /* &.xm */))) += (w * s1) + *(*uint32_t)(unsafe.Pointer(((bp) /* &stats */ + 8 /* &.ym */))) += (w * s2) + *(*uint32_t)(unsafe.Pointer(((bp) /* &stats */ + 12 /* &.xxm */))) += ((w * s1) * s1) + *(*uint32_t)(unsafe.Pointer(((bp) /* &stats */ + 16 /* &.xym */))) += ((w * s1) * s2) + *(*uint32_t)(unsafe.Pointer(((bp) /* &stats */ + 20 /* &.yym */))) += ((w * s2) * s2) + } + + } + goto __2 +__2: + y++ + src1 += uintptr(stride1) + src2 += uintptr(stride2) + goto __1 + goto __3 +__3: + ; + return VP8SSIMFromStats(tls, (bp) /* &stats */) +} + +//------------------------------------------------------------------------------ + +func AccumulateSSE_C(tls *libc.TLS, src1 uintptr, src2 uintptr, len int32) uint32_t { /* ssim.c:117:17: */ + var i int32 + var sse2 uint32_t = uint32_t(0) + // to ensure that accumulation fits within uint32_t + for i = 0; i < len; i++ { + var diff int32_t = (int32(*(*uint8_t)(unsafe.Pointer(src1 + uintptr(i)))) - int32(*(*uint8_t)(unsafe.Pointer(src2 + uintptr(i))))) + sse2 = sse2 + (uint32_t(diff * diff)) + } + return sse2 +} + +//------------------------------------------------------------------------------ + +var VP8SSIMGet VP8SSIMGetFunc /* ssim.c:133:16: */ +var VP8SSIMGetClipped VP8SSIMGetClippedFunc /* ssim.c:134:23: */ +var VP8AccumulateSSE VP8AccumulateSSEFunc /* ssim.c:137:22: */ + +func VP8SSIMDspInit(tls *libc.TLS) { /* ssim.c:142:1: */ + for ok := true; ok; ok = (0 != 0) { + if VP8SSIMDspInit_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + VP8SSIMDspInit_body(tls) + VP8SSIMDspInit_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var VP8SSIMDspInit_body_last_cpuinfo_used VP8CPUInfo = 0 /* ssim.c:142:1 */ + +func VP8SSIMDspInit_body(tls *libc.TLS) { /* ssim.c:142:1: */ + VP8SSIMGetClipped = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32, int32, int32) float64 + }{SSIMGetClipped_C})) + VP8SSIMGet = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, uintptr, int32) float64 + }{SSIMGet_C})) + + VP8AccumulateSSE = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) uint32_t + }{AccumulateSSE_C})) + + if VP8GetCPUInfo != (uintptr(0)) { + } +} + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// ISO C99 Standard: 7.2 Diagnostics <assert.h> + +// Copyright (C) 1991-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// void assert (int expression); +// +// If NDEBUG is defined, do nothing. +// If not, and EXPRESSION is zero, print an error message and abort. + +// void assert_perror (int errnum); +// +// If NDEBUG is defined, do nothing. If not, and ERRNUM is not zero, print an +// error message with the error text for ERRNUM and abort. +// (This is a GNU extension.) + +//------------------------------------------------------------------------------ +// Fancy upsampler + +// Fancy upsampling functions to convert YUV to RGB +var WebPUpsamplers [13]WebPUpsampleLinePairFunc /* upsampling.c:25:26: */ + +// Given samples laid out in a square as: +// [a b] +// [c d] +// we interpolate u/v as: +// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16 +// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 + +// We process u and v together stashed into 32bit (16bit each). + +// All variants implemented. +func UpsampleRgbaLinePair_C(tls *libc.TLS, top_y uintptr, bottom_y uintptr, top_u uintptr, top_v uintptr, cur_u uintptr, cur_v uintptr, top_dst uintptr, bottom_dst uintptr, len int32) { /* upsampling.c:97:1: */ + var x int32 + var last_pixel_pair int32 = ((len - 1) >> 1) + var tl_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(top_u)))) | ((int32(*(*uint8_t)(unsafe.Pointer(top_v)))) << 16))) /* top-left sample */ + var l_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(cur_u)))) | ((int32(*(*uint8_t)(unsafe.Pointer(cur_v)))) << 16))) /* left-sample */ + { + var uv0 uint32_t = ((((uint32_t(3) * tl_uv) + l_uv) + 0x00020002) >> 2) + VP8YuvToRgba(tls, *(*uint8_t)(unsafe.Pointer(top_y)), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), top_dst) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((((uint32_t(3) * l_uv) + tl_uv) + 0x00020002) >> 2) + VP8YuvToRgba(tls, *(*uint8_t)(unsafe.Pointer(bottom_y)), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), bottom_dst) + } + for x = 1; x <= last_pixel_pair; x++ { + var t_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(top_u + uintptr(x))))) | ((int32(*(*uint8_t)(unsafe.Pointer(top_v + uintptr(x))))) << 16))) /* top sample */ + var uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(cur_u + uintptr(x))))) | ((int32(*(*uint8_t)(unsafe.Pointer(cur_v + uintptr(x))))) << 16))) /* sample */ /* precompute invariant values associated with first and second diagonals*/ + var avg uint32_t = ((((tl_uv + t_uv) + l_uv) + uv) + 0x00080008) + var diag_12 uint32_t = ((avg + (uint32_t(2) * (t_uv + l_uv))) >> 3) + var diag_03 uint32_t = ((avg + (uint32_t(2) * (tl_uv + uv))) >> 3) + { + var uv0 uint32_t = ((diag_12 + tl_uv) >> 1) + var uv1 uint32_t = ((diag_03 + t_uv) >> 1) + VP8YuvToRgba(tls, *(*uint8_t)(unsafe.Pointer(top_y + uintptr(((2 * x) - 1)))), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), (top_dst + uintptr((((2 * x) - 1) * (4))))) + VP8YuvToRgba(tls, *(*uint8_t)(unsafe.Pointer(top_y + uintptr(((2 * x) - 0)))), (uint8(uv1 & uint32_t(0xff))), (uint8(uv1 >> 16)), (top_dst + uintptr((((2 * x) - 0) * (4))))) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((diag_03 + l_uv) >> 1) + var uv1 uint32_t = ((diag_12 + uv) >> 1) + VP8YuvToRgba(tls, *(*uint8_t)(unsafe.Pointer(bottom_y + uintptr(((2 * x) - 1)))), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), (bottom_dst + uintptr((((2 * x) - 1) * (4))))) + VP8YuvToRgba(tls, *(*uint8_t)(unsafe.Pointer(bottom_y + uintptr(((2 * x) + 0)))), (uint8(uv1 & uint32_t(0xff))), (uint8(uv1 >> 16)), (bottom_dst + uintptr((((2 * x) + 0) * (4))))) + } + tl_uv = t_uv + l_uv = uv + } + if !((len & 1) != 0) { + { + var uv0 uint32_t = ((((uint32_t(3) * tl_uv) + l_uv) + 0x00020002) >> 2) + VP8YuvToRgba(tls, *(*uint8_t)(unsafe.Pointer(top_y + uintptr((len - 1)))), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), (top_dst + uintptr(((len - 1) * (4))))) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((((uint32_t(3) * l_uv) + tl_uv) + 0x00020002) >> 2) + VP8YuvToRgba(tls, *(*uint8_t)(unsafe.Pointer(bottom_y + uintptr((len - 1)))), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), (bottom_dst + uintptr(((len - 1) * (4))))) + } + } +} + +func UpsampleBgraLinePair_C(tls *libc.TLS, top_y uintptr, bottom_y uintptr, top_u uintptr, top_v uintptr, cur_u uintptr, cur_v uintptr, top_dst uintptr, bottom_dst uintptr, len int32) { /* upsampling.c:98:1: */ + var x int32 + var last_pixel_pair int32 = ((len - 1) >> 1) + var tl_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(top_u)))) | ((int32(*(*uint8_t)(unsafe.Pointer(top_v)))) << 16))) /* top-left sample */ + var l_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(cur_u)))) | ((int32(*(*uint8_t)(unsafe.Pointer(cur_v)))) << 16))) /* left-sample */ + { + var uv0 uint32_t = ((((uint32_t(3) * tl_uv) + l_uv) + 0x00020002) >> 2) + VP8YuvToBgra(tls, *(*uint8_t)(unsafe.Pointer(top_y)), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), top_dst) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((((uint32_t(3) * l_uv) + tl_uv) + 0x00020002) >> 2) + VP8YuvToBgra(tls, *(*uint8_t)(unsafe.Pointer(bottom_y)), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), bottom_dst) + } + for x = 1; x <= last_pixel_pair; x++ { + var t_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(top_u + uintptr(x))))) | ((int32(*(*uint8_t)(unsafe.Pointer(top_v + uintptr(x))))) << 16))) /* top sample */ + var uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(cur_u + uintptr(x))))) | ((int32(*(*uint8_t)(unsafe.Pointer(cur_v + uintptr(x))))) << 16))) /* sample */ /* precompute invariant values associated with first and second diagonals*/ + var avg uint32_t = ((((tl_uv + t_uv) + l_uv) + uv) + 0x00080008) + var diag_12 uint32_t = ((avg + (uint32_t(2) * (t_uv + l_uv))) >> 3) + var diag_03 uint32_t = ((avg + (uint32_t(2) * (tl_uv + uv))) >> 3) + { + var uv0 uint32_t = ((diag_12 + tl_uv) >> 1) + var uv1 uint32_t = ((diag_03 + t_uv) >> 1) + VP8YuvToBgra(tls, *(*uint8_t)(unsafe.Pointer(top_y + uintptr(((2 * x) - 1)))), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), (top_dst + uintptr((((2 * x) - 1) * (4))))) + VP8YuvToBgra(tls, *(*uint8_t)(unsafe.Pointer(top_y + uintptr(((2 * x) - 0)))), (uint8(uv1 & uint32_t(0xff))), (uint8(uv1 >> 16)), (top_dst + uintptr((((2 * x) - 0) * (4))))) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((diag_03 + l_uv) >> 1) + var uv1 uint32_t = ((diag_12 + uv) >> 1) + VP8YuvToBgra(tls, *(*uint8_t)(unsafe.Pointer(bottom_y + uintptr(((2 * x) - 1)))), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), (bottom_dst + uintptr((((2 * x) - 1) * (4))))) + VP8YuvToBgra(tls, *(*uint8_t)(unsafe.Pointer(bottom_y + uintptr(((2 * x) + 0)))), (uint8(uv1 & uint32_t(0xff))), (uint8(uv1 >> 16)), (bottom_dst + uintptr((((2 * x) + 0) * (4))))) + } + tl_uv = t_uv + l_uv = uv + } + if !((len & 1) != 0) { + { + var uv0 uint32_t = ((((uint32_t(3) * tl_uv) + l_uv) + 0x00020002) >> 2) + VP8YuvToBgra(tls, *(*uint8_t)(unsafe.Pointer(top_y + uintptr((len - 1)))), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), (top_dst + uintptr(((len - 1) * (4))))) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((((uint32_t(3) * l_uv) + tl_uv) + 0x00020002) >> 2) + VP8YuvToBgra(tls, *(*uint8_t)(unsafe.Pointer(bottom_y + uintptr((len - 1)))), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), (bottom_dst + uintptr(((len - 1) * (4))))) + } + } +} + +func UpsampleArgbLinePair_C(tls *libc.TLS, top_y uintptr, bottom_y uintptr, top_u uintptr, top_v uintptr, cur_u uintptr, cur_v uintptr, top_dst uintptr, bottom_dst uintptr, len int32) { /* upsampling.c:100:1: */ + var x int32 + var last_pixel_pair int32 = ((len - 1) >> 1) + var tl_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(top_u)))) | ((int32(*(*uint8_t)(unsafe.Pointer(top_v)))) << 16))) /* top-left sample */ + var l_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(cur_u)))) | ((int32(*(*uint8_t)(unsafe.Pointer(cur_v)))) << 16))) /* left-sample */ + { + var uv0 uint32_t = ((((uint32_t(3) * tl_uv) + l_uv) + 0x00020002) >> 2) + VP8YuvToArgb(tls, *(*uint8_t)(unsafe.Pointer(top_y)), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), top_dst) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((((uint32_t(3) * l_uv) + tl_uv) + 0x00020002) >> 2) + VP8YuvToArgb(tls, *(*uint8_t)(unsafe.Pointer(bottom_y)), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), bottom_dst) + } + for x = 1; x <= last_pixel_pair; x++ { + var t_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(top_u + uintptr(x))))) | ((int32(*(*uint8_t)(unsafe.Pointer(top_v + uintptr(x))))) << 16))) /* top sample */ + var uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(cur_u + uintptr(x))))) | ((int32(*(*uint8_t)(unsafe.Pointer(cur_v + uintptr(x))))) << 16))) /* sample */ /* precompute invariant values associated with first and second diagonals*/ + var avg uint32_t = ((((tl_uv + t_uv) + l_uv) + uv) + 0x00080008) + var diag_12 uint32_t = ((avg + (uint32_t(2) * (t_uv + l_uv))) >> 3) + var diag_03 uint32_t = ((avg + (uint32_t(2) * (tl_uv + uv))) >> 3) + { + var uv0 uint32_t = ((diag_12 + tl_uv) >> 1) + var uv1 uint32_t = ((diag_03 + t_uv) >> 1) + VP8YuvToArgb(tls, *(*uint8_t)(unsafe.Pointer(top_y + uintptr(((2 * x) - 1)))), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), (top_dst + uintptr((((2 * x) - 1) * (4))))) + VP8YuvToArgb(tls, *(*uint8_t)(unsafe.Pointer(top_y + uintptr(((2 * x) - 0)))), (uint8(uv1 & uint32_t(0xff))), (uint8(uv1 >> 16)), (top_dst + uintptr((((2 * x) - 0) * (4))))) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((diag_03 + l_uv) >> 1) + var uv1 uint32_t = ((diag_12 + uv) >> 1) + VP8YuvToArgb(tls, *(*uint8_t)(unsafe.Pointer(bottom_y + uintptr(((2 * x) - 1)))), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), (bottom_dst + uintptr((((2 * x) - 1) * (4))))) + VP8YuvToArgb(tls, *(*uint8_t)(unsafe.Pointer(bottom_y + uintptr(((2 * x) + 0)))), (uint8(uv1 & uint32_t(0xff))), (uint8(uv1 >> 16)), (bottom_dst + uintptr((((2 * x) + 0) * (4))))) + } + tl_uv = t_uv + l_uv = uv + } + if !((len & 1) != 0) { + { + var uv0 uint32_t = ((((uint32_t(3) * tl_uv) + l_uv) + 0x00020002) >> 2) + VP8YuvToArgb(tls, *(*uint8_t)(unsafe.Pointer(top_y + uintptr((len - 1)))), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), (top_dst + uintptr(((len - 1) * (4))))) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((((uint32_t(3) * l_uv) + tl_uv) + 0x00020002) >> 2) + VP8YuvToArgb(tls, *(*uint8_t)(unsafe.Pointer(bottom_y + uintptr((len - 1)))), (uint8(uv0 & uint32_t(0xff))), (uint8(uv0 >> 16)), (bottom_dst + uintptr(((len - 1) * (4))))) + } + } +} + +func UpsampleRgbLinePair_C(tls *libc.TLS, top_y uintptr, bottom_y uintptr, top_u uintptr, top_v uintptr, cur_u uintptr, cur_v uintptr, top_dst uintptr, bottom_dst uintptr, len int32) { /* upsampling.c:101:1: */ + var x int32 + var last_pixel_pair int32 = ((len - 1) >> 1) + var tl_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(top_u)))) | ((int32(*(*uint8_t)(unsafe.Pointer(top_v)))) << 16))) /* top-left sample */ + var l_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(cur_u)))) | ((int32(*(*uint8_t)(unsafe.Pointer(cur_v)))) << 16))) /* left-sample */ + { + var uv0 uint32_t = ((((uint32_t(3) * tl_uv) + l_uv) + 0x00020002) >> 2) + VP8YuvToRgb(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), top_dst) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((((uint32_t(3) * l_uv) + tl_uv) + 0x00020002) >> 2) + VP8YuvToRgb(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), bottom_dst) + } + for x = 1; x <= last_pixel_pair; x++ { + var t_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(top_u + uintptr(x))))) | ((int32(*(*uint8_t)(unsafe.Pointer(top_v + uintptr(x))))) << 16))) /* top sample */ + var uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(cur_u + uintptr(x))))) | ((int32(*(*uint8_t)(unsafe.Pointer(cur_v + uintptr(x))))) << 16))) /* sample */ /* precompute invariant values associated with first and second diagonals*/ + var avg uint32_t = ((((tl_uv + t_uv) + l_uv) + uv) + 0x00080008) + var diag_12 uint32_t = ((avg + (uint32_t(2) * (t_uv + l_uv))) >> 3) + var diag_03 uint32_t = ((avg + (uint32_t(2) * (tl_uv + uv))) >> 3) + { + var uv0 uint32_t = ((diag_12 + tl_uv) >> 1) + var uv1 uint32_t = ((diag_03 + t_uv) >> 1) + VP8YuvToRgb(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y + uintptr(((2 * x) - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (top_dst + uintptr((((2 * x) - 1) * (3))))) + VP8YuvToRgb(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y + uintptr(((2 * x) - 0))))), (int32(uv1 & uint32_t(0xff))), (int32(uv1 >> 16)), (top_dst + uintptr((((2 * x) - 0) * (3))))) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((diag_03 + l_uv) >> 1) + var uv1 uint32_t = ((diag_12 + uv) >> 1) + VP8YuvToRgb(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y + uintptr(((2 * x) - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (bottom_dst + uintptr((((2 * x) - 1) * (3))))) + VP8YuvToRgb(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y + uintptr(((2 * x) + 0))))), (int32(uv1 & uint32_t(0xff))), (int32(uv1 >> 16)), (bottom_dst + uintptr((((2 * x) + 0) * (3))))) + } + tl_uv = t_uv + l_uv = uv + } + if !((len & 1) != 0) { + { + var uv0 uint32_t = ((((uint32_t(3) * tl_uv) + l_uv) + 0x00020002) >> 2) + VP8YuvToRgb(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y + uintptr((len - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (top_dst + uintptr(((len - 1) * (3))))) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((((uint32_t(3) * l_uv) + tl_uv) + 0x00020002) >> 2) + VP8YuvToRgb(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y + uintptr((len - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (bottom_dst + uintptr(((len - 1) * (3))))) + } + } +} + +func UpsampleBgrLinePair_C(tls *libc.TLS, top_y uintptr, bottom_y uintptr, top_u uintptr, top_v uintptr, cur_u uintptr, cur_v uintptr, top_dst uintptr, bottom_dst uintptr, len int32) { /* upsampling.c:102:1: */ + var x int32 + var last_pixel_pair int32 = ((len - 1) >> 1) + var tl_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(top_u)))) | ((int32(*(*uint8_t)(unsafe.Pointer(top_v)))) << 16))) /* top-left sample */ + var l_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(cur_u)))) | ((int32(*(*uint8_t)(unsafe.Pointer(cur_v)))) << 16))) /* left-sample */ + { + var uv0 uint32_t = ((((uint32_t(3) * tl_uv) + l_uv) + 0x00020002) >> 2) + VP8YuvToBgr(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), top_dst) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((((uint32_t(3) * l_uv) + tl_uv) + 0x00020002) >> 2) + VP8YuvToBgr(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), bottom_dst) + } + for x = 1; x <= last_pixel_pair; x++ { + var t_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(top_u + uintptr(x))))) | ((int32(*(*uint8_t)(unsafe.Pointer(top_v + uintptr(x))))) << 16))) /* top sample */ + var uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(cur_u + uintptr(x))))) | ((int32(*(*uint8_t)(unsafe.Pointer(cur_v + uintptr(x))))) << 16))) /* sample */ /* precompute invariant values associated with first and second diagonals*/ + var avg uint32_t = ((((tl_uv + t_uv) + l_uv) + uv) + 0x00080008) + var diag_12 uint32_t = ((avg + (uint32_t(2) * (t_uv + l_uv))) >> 3) + var diag_03 uint32_t = ((avg + (uint32_t(2) * (tl_uv + uv))) >> 3) + { + var uv0 uint32_t = ((diag_12 + tl_uv) >> 1) + var uv1 uint32_t = ((diag_03 + t_uv) >> 1) + VP8YuvToBgr(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y + uintptr(((2 * x) - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (top_dst + uintptr((((2 * x) - 1) * (3))))) + VP8YuvToBgr(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y + uintptr(((2 * x) - 0))))), (int32(uv1 & uint32_t(0xff))), (int32(uv1 >> 16)), (top_dst + uintptr((((2 * x) - 0) * (3))))) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((diag_03 + l_uv) >> 1) + var uv1 uint32_t = ((diag_12 + uv) >> 1) + VP8YuvToBgr(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y + uintptr(((2 * x) - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (bottom_dst + uintptr((((2 * x) - 1) * (3))))) + VP8YuvToBgr(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y + uintptr(((2 * x) + 0))))), (int32(uv1 & uint32_t(0xff))), (int32(uv1 >> 16)), (bottom_dst + uintptr((((2 * x) + 0) * (3))))) + } + tl_uv = t_uv + l_uv = uv + } + if !((len & 1) != 0) { + { + var uv0 uint32_t = ((((uint32_t(3) * tl_uv) + l_uv) + 0x00020002) >> 2) + VP8YuvToBgr(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y + uintptr((len - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (top_dst + uintptr(((len - 1) * (3))))) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((((uint32_t(3) * l_uv) + tl_uv) + 0x00020002) >> 2) + VP8YuvToBgr(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y + uintptr((len - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (bottom_dst + uintptr(((len - 1) * (3))))) + } + } +} + +func UpsampleRgba4444LinePair_C(tls *libc.TLS, top_y uintptr, bottom_y uintptr, top_u uintptr, top_v uintptr, cur_u uintptr, cur_v uintptr, top_dst uintptr, bottom_dst uintptr, len int32) { /* upsampling.c:103:1: */ + var x int32 + var last_pixel_pair int32 = ((len - 1) >> 1) + var tl_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(top_u)))) | ((int32(*(*uint8_t)(unsafe.Pointer(top_v)))) << 16))) /* top-left sample */ + var l_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(cur_u)))) | ((int32(*(*uint8_t)(unsafe.Pointer(cur_v)))) << 16))) /* left-sample */ + { + var uv0 uint32_t = ((((uint32_t(3) * tl_uv) + l_uv) + 0x00020002) >> 2) + VP8YuvToRgba4444(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), top_dst) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((((uint32_t(3) * l_uv) + tl_uv) + 0x00020002) >> 2) + VP8YuvToRgba4444(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), bottom_dst) + } + for x = 1; x <= last_pixel_pair; x++ { + var t_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(top_u + uintptr(x))))) | ((int32(*(*uint8_t)(unsafe.Pointer(top_v + uintptr(x))))) << 16))) /* top sample */ + var uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(cur_u + uintptr(x))))) | ((int32(*(*uint8_t)(unsafe.Pointer(cur_v + uintptr(x))))) << 16))) /* sample */ /* precompute invariant values associated with first and second diagonals*/ + var avg uint32_t = ((((tl_uv + t_uv) + l_uv) + uv) + 0x00080008) + var diag_12 uint32_t = ((avg + (uint32_t(2) * (t_uv + l_uv))) >> 3) + var diag_03 uint32_t = ((avg + (uint32_t(2) * (tl_uv + uv))) >> 3) + { + var uv0 uint32_t = ((diag_12 + tl_uv) >> 1) + var uv1 uint32_t = ((diag_03 + t_uv) >> 1) + VP8YuvToRgba4444(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y + uintptr(((2 * x) - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (top_dst + uintptr((((2 * x) - 1) * (2))))) + VP8YuvToRgba4444(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y + uintptr(((2 * x) - 0))))), (int32(uv1 & uint32_t(0xff))), (int32(uv1 >> 16)), (top_dst + uintptr((((2 * x) - 0) * (2))))) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((diag_03 + l_uv) >> 1) + var uv1 uint32_t = ((diag_12 + uv) >> 1) + VP8YuvToRgba4444(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y + uintptr(((2 * x) - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (bottom_dst + uintptr((((2 * x) - 1) * (2))))) + VP8YuvToRgba4444(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y + uintptr(((2 * x) + 0))))), (int32(uv1 & uint32_t(0xff))), (int32(uv1 >> 16)), (bottom_dst + uintptr((((2 * x) + 0) * (2))))) + } + tl_uv = t_uv + l_uv = uv + } + if !((len & 1) != 0) { + { + var uv0 uint32_t = ((((uint32_t(3) * tl_uv) + l_uv) + 0x00020002) >> 2) + VP8YuvToRgba4444(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y + uintptr((len - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (top_dst + uintptr(((len - 1) * (2))))) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((((uint32_t(3) * l_uv) + tl_uv) + 0x00020002) >> 2) + VP8YuvToRgba4444(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y + uintptr((len - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (bottom_dst + uintptr(((len - 1) * (2))))) + } + } +} + +func UpsampleRgb565LinePair_C(tls *libc.TLS, top_y uintptr, bottom_y uintptr, top_u uintptr, top_v uintptr, cur_u uintptr, cur_v uintptr, top_dst uintptr, bottom_dst uintptr, len int32) { /* upsampling.c:104:1: */ + var x int32 + var last_pixel_pair int32 = ((len - 1) >> 1) + var tl_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(top_u)))) | ((int32(*(*uint8_t)(unsafe.Pointer(top_v)))) << 16))) /* top-left sample */ + var l_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(cur_u)))) | ((int32(*(*uint8_t)(unsafe.Pointer(cur_v)))) << 16))) /* left-sample */ + { + var uv0 uint32_t = ((((uint32_t(3) * tl_uv) + l_uv) + 0x00020002) >> 2) + VP8YuvToRgb565(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), top_dst) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((((uint32_t(3) * l_uv) + tl_uv) + 0x00020002) >> 2) + VP8YuvToRgb565(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), bottom_dst) + } + for x = 1; x <= last_pixel_pair; x++ { + var t_uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(top_u + uintptr(x))))) | ((int32(*(*uint8_t)(unsafe.Pointer(top_v + uintptr(x))))) << 16))) /* top sample */ + var uv uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer(cur_u + uintptr(x))))) | ((int32(*(*uint8_t)(unsafe.Pointer(cur_v + uintptr(x))))) << 16))) /* sample */ /* precompute invariant values associated with first and second diagonals*/ + var avg uint32_t = ((((tl_uv + t_uv) + l_uv) + uv) + 0x00080008) + var diag_12 uint32_t = ((avg + (uint32_t(2) * (t_uv + l_uv))) >> 3) + var diag_03 uint32_t = ((avg + (uint32_t(2) * (tl_uv + uv))) >> 3) + { + var uv0 uint32_t = ((diag_12 + tl_uv) >> 1) + var uv1 uint32_t = ((diag_03 + t_uv) >> 1) + VP8YuvToRgb565(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y + uintptr(((2 * x) - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (top_dst + uintptr((((2 * x) - 1) * (2))))) + VP8YuvToRgb565(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y + uintptr(((2 * x) - 0))))), (int32(uv1 & uint32_t(0xff))), (int32(uv1 >> 16)), (top_dst + uintptr((((2 * x) - 0) * (2))))) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((diag_03 + l_uv) >> 1) + var uv1 uint32_t = ((diag_12 + uv) >> 1) + VP8YuvToRgb565(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y + uintptr(((2 * x) - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (bottom_dst + uintptr((((2 * x) - 1) * (2))))) + VP8YuvToRgb565(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y + uintptr(((2 * x) + 0))))), (int32(uv1 & uint32_t(0xff))), (int32(uv1 >> 16)), (bottom_dst + uintptr((((2 * x) + 0) * (2))))) + } + tl_uv = t_uv + l_uv = uv + } + if !((len & 1) != 0) { + { + var uv0 uint32_t = ((((uint32_t(3) * tl_uv) + l_uv) + 0x00020002) >> 2) + VP8YuvToRgb565(tls, int32(*(*uint8_t)(unsafe.Pointer(top_y + uintptr((len - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (top_dst + uintptr(((len - 1) * (2))))) + } + if bottom_y != (uintptr(0)) { + var uv0 uint32_t = ((((uint32_t(3) * l_uv) + tl_uv) + 0x00020002) >> 2) + VP8YuvToRgb565(tls, int32(*(*uint8_t)(unsafe.Pointer(bottom_y + uintptr((len - 1))))), (int32(uv0 & uint32_t(0xff))), (int32(uv0 >> 16)), (bottom_dst + uintptr(((len - 1) * (2))))) + } + } +} + +//------------------------------------------------------------------------------ + +func WebPGetLinePairConverter(tls *libc.TLS, alpha_is_last int32) WebPUpsampleLinePairFunc { /* upsampling.c:168:26: */ + WebPInitUpsamplers(tls) + return WebPUpsamplers[func() int32 { + if alpha_is_last != 0 { + return MODE_BGRA + } + return MODE_ARGB + }()] +} + +func WebPYuv444ToRgba_C(tls *libc.TLS, y uintptr, u uintptr, v uintptr, dst uintptr, len int32) { /* upsampling.c:189:1: */ + var i int32 + for i = 0; i < len; i++ { + VP8YuvToRgba(tls, *(*uint8_t)(unsafe.Pointer(y + uintptr(i))), *(*uint8_t)(unsafe.Pointer(u + uintptr(i))), *(*uint8_t)(unsafe.Pointer(v + uintptr(i))), (dst + uintptr((i * (4))))) + } +} + +func WebPYuv444ToBgra_C(tls *libc.TLS, y uintptr, u uintptr, v uintptr, dst uintptr, len int32) { /* upsampling.c:190:1: */ + var i int32 + for i = 0; i < len; i++ { + VP8YuvToBgra(tls, *(*uint8_t)(unsafe.Pointer(y + uintptr(i))), *(*uint8_t)(unsafe.Pointer(u + uintptr(i))), *(*uint8_t)(unsafe.Pointer(v + uintptr(i))), (dst + uintptr((i * (4))))) + } +} + +func WebPYuv444ToRgb_C(tls *libc.TLS, y uintptr, u uintptr, v uintptr, dst uintptr, len int32) { /* upsampling.c:192:1: */ + var i int32 + for i = 0; i < len; i++ { + VP8YuvToRgb(tls, int32(*(*uint8_t)(unsafe.Pointer(y + uintptr(i)))), int32(*(*uint8_t)(unsafe.Pointer(u + uintptr(i)))), int32(*(*uint8_t)(unsafe.Pointer(v + uintptr(i)))), (dst + uintptr((i * (3))))) + } +} + +func WebPYuv444ToBgr_C(tls *libc.TLS, y uintptr, u uintptr, v uintptr, dst uintptr, len int32) { /* upsampling.c:193:1: */ + var i int32 + for i = 0; i < len; i++ { + VP8YuvToBgr(tls, int32(*(*uint8_t)(unsafe.Pointer(y + uintptr(i)))), int32(*(*uint8_t)(unsafe.Pointer(u + uintptr(i)))), int32(*(*uint8_t)(unsafe.Pointer(v + uintptr(i)))), (dst + uintptr((i * (3))))) + } +} + +func WebPYuv444ToArgb_C(tls *libc.TLS, y uintptr, u uintptr, v uintptr, dst uintptr, len int32) { /* upsampling.c:194:1: */ + var i int32 + for i = 0; i < len; i++ { + VP8YuvToArgb(tls, *(*uint8_t)(unsafe.Pointer(y + uintptr(i))), *(*uint8_t)(unsafe.Pointer(u + uintptr(i))), *(*uint8_t)(unsafe.Pointer(v + uintptr(i))), (dst + uintptr((i * (4))))) + } +} + +func WebPYuv444ToRgba4444_C(tls *libc.TLS, y uintptr, u uintptr, v uintptr, dst uintptr, len int32) { /* upsampling.c:195:1: */ + var i int32 + for i = 0; i < len; i++ { + VP8YuvToRgba4444(tls, int32(*(*uint8_t)(unsafe.Pointer(y + uintptr(i)))), int32(*(*uint8_t)(unsafe.Pointer(u + uintptr(i)))), int32(*(*uint8_t)(unsafe.Pointer(v + uintptr(i)))), (dst + uintptr((i * (2))))) + } +} + +func WebPYuv444ToRgb565_C(tls *libc.TLS, y uintptr, u uintptr, v uintptr, dst uintptr, len int32) { /* upsampling.c:196:1: */ + var i int32 + for i = 0; i < len; i++ { + VP8YuvToRgb565(tls, int32(*(*uint8_t)(unsafe.Pointer(y + uintptr(i)))), int32(*(*uint8_t)(unsafe.Pointer(u + uintptr(i)))), int32(*(*uint8_t)(unsafe.Pointer(v + uintptr(i)))), (dst + uintptr((i * (2))))) + } +} + +var WebPYUV444Converters [13]WebPYUV444Converter /* upsampling.c:216:21: */ + +func WebPInitYUV444Converters(tls *libc.TLS) { /* upsampling.c:222:1: */ + for ok := true; ok; ok = (0 != 0) { + if WebPInitYUV444Converters_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + WebPInitYUV444Converters_body(tls) + WebPInitYUV444Converters_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var WebPInitYUV444Converters_body_last_cpuinfo_used VP8CPUInfo = 0 /* upsampling.c:222:1 */ + +func WebPInitYUV444Converters_body(tls *libc.TLS) { /* upsampling.c:222:1: */ + WebPYUV444Converters[MODE_RGBA] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{WebPYuv444ToRgba_C})) + WebPYUV444Converters[MODE_BGRA] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{WebPYuv444ToBgra_C})) + WebPYUV444Converters[MODE_RGB] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{WebPYuv444ToRgb_C})) + WebPYUV444Converters[MODE_BGR] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{WebPYuv444ToBgr_C})) + WebPYUV444Converters[MODE_ARGB] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{WebPYuv444ToArgb_C})) + WebPYUV444Converters[MODE_RGBA_4444] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{WebPYuv444ToRgba4444_C})) + WebPYUV444Converters[MODE_RGB_565] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{WebPYuv444ToRgb565_C})) + WebPYUV444Converters[MODE_rgbA] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{WebPYuv444ToRgba_C})) + WebPYUV444Converters[MODE_bgrA] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{WebPYuv444ToBgra_C})) + WebPYUV444Converters[MODE_Argb] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{WebPYuv444ToArgb_C})) + WebPYUV444Converters[MODE_rgbA_4444] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{WebPYuv444ToRgba4444_C})) + + if VP8GetCPUInfo != (uintptr(0)) { + } +} + +func WebPInitUpsamplers(tls *libc.TLS) { /* upsampling.c:263:1: */ + for ok := true; ok; ok = (0 != 0) { + if WebPInitUpsamplers_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + WebPInitUpsamplers_body(tls) + WebPInitUpsamplers_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var WebPInitUpsamplers_body_last_cpuinfo_used VP8CPUInfo = 0 /* upsampling.c:263:1 */ + +func WebPInitUpsamplers_body(tls *libc.TLS) { /* upsampling.c:263:1: */ + WebPUpsamplers[MODE_RGBA] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + }{UpsampleRgbaLinePair_C})) + WebPUpsamplers[MODE_BGRA] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + }{UpsampleBgraLinePair_C})) + WebPUpsamplers[MODE_rgbA] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + }{UpsampleRgbaLinePair_C})) + WebPUpsamplers[MODE_bgrA] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + }{UpsampleBgraLinePair_C})) + WebPUpsamplers[MODE_RGB] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + }{UpsampleRgbLinePair_C})) + WebPUpsamplers[MODE_BGR] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + }{UpsampleBgrLinePair_C})) + WebPUpsamplers[MODE_ARGB] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + }{UpsampleArgbLinePair_C})) + WebPUpsamplers[MODE_RGBA_4444] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + }{UpsampleRgba4444LinePair_C})) + WebPUpsamplers[MODE_RGB_565] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + }{UpsampleRgb565LinePair_C})) + WebPUpsamplers[MODE_Argb] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + }{UpsampleArgbLinePair_C})) + WebPUpsamplers[MODE_rgbA_4444] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + }{UpsampleRgba4444LinePair_C})) + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if VP8GetCPUInfo != (uintptr(0)) { + } + +} + +//------------------------------------------------------------------------------ + +// Floating-point inline functions for stdlib.h. +// Copyright (C) 2012-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +// Define some macros helping to catch buffer overflows. + +// Macros to control TS 18661-3 glibc features on x86. +// Copyright (C) 2017-2021 Free Software Foundation, Inc. +// This file is part of the GNU C Library. +// +// The GNU C Library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// The GNU C Library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with the GNU C Library; if not, see +// <https://www.gnu.org/licenses/>. + +//----------------------------------------------------------------------------- +// Plain-C version + +// All variants implemented. +func YuvToRgbRow(tls *libc.TLS, y uintptr, u uintptr, v uintptr, dst uintptr, len int32) { /* yuv.c:41:1: */ + var end uintptr = (dst + uintptr(((len & libc.CplInt32(1)) * (3)))) + for dst != end { + VP8YuvToRgb(tls, int32(*(*uint8_t)(unsafe.Pointer(y))), int32(*(*uint8_t)(unsafe.Pointer(u))), int32(*(*uint8_t)(unsafe.Pointer(v))), dst) + VP8YuvToRgb(tls, int32(*(*uint8_t)(unsafe.Pointer(y + 1))), int32(*(*uint8_t)(unsafe.Pointer(u))), int32(*(*uint8_t)(unsafe.Pointer(v))), (dst + uintptr((3)))) + y += uintptr(2) + u++ + v++ + dst += (uintptr(2 * (3))) + } + if (len & 1) != 0 { + VP8YuvToRgb(tls, int32(*(*uint8_t)(unsafe.Pointer(y))), int32(*(*uint8_t)(unsafe.Pointer(u))), int32(*(*uint8_t)(unsafe.Pointer(v))), dst) + } +} + +func YuvToBgrRow(tls *libc.TLS, y uintptr, u uintptr, v uintptr, dst uintptr, len int32) { /* yuv.c:42:1: */ + var end uintptr = (dst + uintptr(((len & libc.CplInt32(1)) * (3)))) + for dst != end { + VP8YuvToBgr(tls, int32(*(*uint8_t)(unsafe.Pointer(y))), int32(*(*uint8_t)(unsafe.Pointer(u))), int32(*(*uint8_t)(unsafe.Pointer(v))), dst) + VP8YuvToBgr(tls, int32(*(*uint8_t)(unsafe.Pointer(y + 1))), int32(*(*uint8_t)(unsafe.Pointer(u))), int32(*(*uint8_t)(unsafe.Pointer(v))), (dst + uintptr((3)))) + y += uintptr(2) + u++ + v++ + dst += (uintptr(2 * (3))) + } + if (len & 1) != 0 { + VP8YuvToBgr(tls, int32(*(*uint8_t)(unsafe.Pointer(y))), int32(*(*uint8_t)(unsafe.Pointer(u))), int32(*(*uint8_t)(unsafe.Pointer(v))), dst) + } +} + +func YuvToRgbaRow(tls *libc.TLS, y uintptr, u uintptr, v uintptr, dst uintptr, len int32) { /* yuv.c:43:1: */ + var end uintptr = (dst + uintptr(((len & libc.CplInt32(1)) * (4)))) + for dst != end { + VP8YuvToRgba(tls, *(*uint8_t)(unsafe.Pointer(y)), *(*uint8_t)(unsafe.Pointer(u)), *(*uint8_t)(unsafe.Pointer(v)), dst) + VP8YuvToRgba(tls, *(*uint8_t)(unsafe.Pointer(y + 1)), *(*uint8_t)(unsafe.Pointer(u)), *(*uint8_t)(unsafe.Pointer(v)), (dst + uintptr((4)))) + y += uintptr(2) + u++ + v++ + dst += (uintptr(2 * (4))) + } + if (len & 1) != 0 { + VP8YuvToRgba(tls, *(*uint8_t)(unsafe.Pointer(y)), *(*uint8_t)(unsafe.Pointer(u)), *(*uint8_t)(unsafe.Pointer(v)), dst) + } +} + +func YuvToBgraRow(tls *libc.TLS, y uintptr, u uintptr, v uintptr, dst uintptr, len int32) { /* yuv.c:44:1: */ + var end uintptr = (dst + uintptr(((len & libc.CplInt32(1)) * (4)))) + for dst != end { + VP8YuvToBgra(tls, *(*uint8_t)(unsafe.Pointer(y)), *(*uint8_t)(unsafe.Pointer(u)), *(*uint8_t)(unsafe.Pointer(v)), dst) + VP8YuvToBgra(tls, *(*uint8_t)(unsafe.Pointer(y + 1)), *(*uint8_t)(unsafe.Pointer(u)), *(*uint8_t)(unsafe.Pointer(v)), (dst + uintptr((4)))) + y += uintptr(2) + u++ + v++ + dst += (uintptr(2 * (4))) + } + if (len & 1) != 0 { + VP8YuvToBgra(tls, *(*uint8_t)(unsafe.Pointer(y)), *(*uint8_t)(unsafe.Pointer(u)), *(*uint8_t)(unsafe.Pointer(v)), dst) + } +} + +func YuvToArgbRow(tls *libc.TLS, y uintptr, u uintptr, v uintptr, dst uintptr, len int32) { /* yuv.c:45:1: */ + var end uintptr = (dst + uintptr(((len & libc.CplInt32(1)) * (4)))) + for dst != end { + VP8YuvToArgb(tls, *(*uint8_t)(unsafe.Pointer(y)), *(*uint8_t)(unsafe.Pointer(u)), *(*uint8_t)(unsafe.Pointer(v)), dst) + VP8YuvToArgb(tls, *(*uint8_t)(unsafe.Pointer(y + 1)), *(*uint8_t)(unsafe.Pointer(u)), *(*uint8_t)(unsafe.Pointer(v)), (dst + uintptr((4)))) + y += uintptr(2) + u++ + v++ + dst += (uintptr(2 * (4))) + } + if (len & 1) != 0 { + VP8YuvToArgb(tls, *(*uint8_t)(unsafe.Pointer(y)), *(*uint8_t)(unsafe.Pointer(u)), *(*uint8_t)(unsafe.Pointer(v)), dst) + } +} + +func YuvToRgba4444Row(tls *libc.TLS, y uintptr, u uintptr, v uintptr, dst uintptr, len int32) { /* yuv.c:46:1: */ + var end uintptr = (dst + uintptr(((len & libc.CplInt32(1)) * (2)))) + for dst != end { + VP8YuvToRgba4444(tls, int32(*(*uint8_t)(unsafe.Pointer(y))), int32(*(*uint8_t)(unsafe.Pointer(u))), int32(*(*uint8_t)(unsafe.Pointer(v))), dst) + VP8YuvToRgba4444(tls, int32(*(*uint8_t)(unsafe.Pointer(y + 1))), int32(*(*uint8_t)(unsafe.Pointer(u))), int32(*(*uint8_t)(unsafe.Pointer(v))), (dst + uintptr((2)))) + y += uintptr(2) + u++ + v++ + dst += (uintptr(2 * (2))) + } + if (len & 1) != 0 { + VP8YuvToRgba4444(tls, int32(*(*uint8_t)(unsafe.Pointer(y))), int32(*(*uint8_t)(unsafe.Pointer(u))), int32(*(*uint8_t)(unsafe.Pointer(v))), dst) + } +} + +func YuvToRgb565Row(tls *libc.TLS, y uintptr, u uintptr, v uintptr, dst uintptr, len int32) { /* yuv.c:47:1: */ + var end uintptr = (dst + uintptr(((len & libc.CplInt32(1)) * (2)))) + for dst != end { + VP8YuvToRgb565(tls, int32(*(*uint8_t)(unsafe.Pointer(y))), int32(*(*uint8_t)(unsafe.Pointer(u))), int32(*(*uint8_t)(unsafe.Pointer(v))), dst) + VP8YuvToRgb565(tls, int32(*(*uint8_t)(unsafe.Pointer(y + 1))), int32(*(*uint8_t)(unsafe.Pointer(u))), int32(*(*uint8_t)(unsafe.Pointer(v))), (dst + uintptr((2)))) + y += uintptr(2) + u++ + v++ + dst += (uintptr(2 * (2))) + } + if (len & 1) != 0 { + VP8YuvToRgb565(tls, int32(*(*uint8_t)(unsafe.Pointer(y))), int32(*(*uint8_t)(unsafe.Pointer(u))), int32(*(*uint8_t)(unsafe.Pointer(v))), dst) + } +} + +// Main call for processing a plane with a WebPSamplerRowFunc function: +func WebPSamplerProcessPlane(tls *libc.TLS, y uintptr, y_stride int32, u uintptr, v uintptr, uv_stride int32, dst uintptr, dst_stride int32, width int32, height int32, func1 WebPSamplerRowFunc) { /* yuv.c:52:6: */ + var j int32 + for j = 0; j < height; j++ { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{func1})).f(tls, y, u, v, dst, width) + y += uintptr(y_stride) + if (j & 1) != 0 { + u += uintptr(uv_stride) + v += uintptr(uv_stride) + } + dst += uintptr(dst_stride) + } +} + +//----------------------------------------------------------------------------- +// Main call + +var WebPSamplers [13]WebPSamplerRowFunc /* yuv.c:71:20: */ + +func WebPInitSamplers(tls *libc.TLS) { /* yuv.c:78:1: */ + for ok := true; ok; ok = (0 != 0) { + if WebPInitSamplers_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + WebPInitSamplers_body(tls) + WebPInitSamplers_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var WebPInitSamplers_body_last_cpuinfo_used VP8CPUInfo = 0 /* yuv.c:78:1 */ + +func WebPInitSamplers_body(tls *libc.TLS) { /* yuv.c:78:1: */ + WebPSamplers[MODE_RGB] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{YuvToRgbRow})) + WebPSamplers[MODE_RGBA] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{YuvToRgbaRow})) + WebPSamplers[MODE_BGR] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{YuvToBgrRow})) + WebPSamplers[MODE_BGRA] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{YuvToBgraRow})) + WebPSamplers[MODE_ARGB] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{YuvToArgbRow})) + WebPSamplers[MODE_RGBA_4444] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{YuvToRgba4444Row})) + WebPSamplers[MODE_RGB_565] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{YuvToRgb565Row})) + WebPSamplers[MODE_rgbA] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{YuvToRgbaRow})) + WebPSamplers[MODE_bgrA] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{YuvToBgraRow})) + WebPSamplers[MODE_Argb] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{YuvToArgbRow})) + WebPSamplers[MODE_rgbA_4444] = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, int32) + }{YuvToRgba4444Row})) + + // If defined, use CPUInfo() to overwrite some pointers with faster versions. + if VP8GetCPUInfo != (uintptr(0)) { + } +} + +//----------------------------------------------------------------------------- +// ARGB -> YUV converters + +func ConvertARGBToY_C(tls *libc.TLS, argb uintptr, y uintptr, width int32) { /* yuv.c:119:13: */ + var i int32 + for i = 0; i < width; i++ { + var p uint32_t = *(*uint32_t)(unsafe.Pointer(argb + uintptr(i)*4)) + *(*uint8_t)(unsafe.Pointer(y + uintptr(i))) = uint8_t(VP8RGBToY(tls, (int32((p >> 16) & uint32_t(0xff))), (int32((p >> 8) & uint32_t(0xff))), (int32((p >> 0) & uint32_t(0xff))), + YUV_HALF)) + } +} + +func WebPConvertARGBToUV_C(tls *libc.TLS, argb uintptr, u uintptr, v uintptr, src_width int32, do_store int32) { /* yuv.c:128:6: */ + // No rounding. Last pixel is dealt with separately. + var uv_width int32 = (src_width >> 1) + var i int32 + for i = 0; i < uv_width; i++ { + var v0 uint32_t = *(*uint32_t)(unsafe.Pointer(argb + uintptr(((2*i)+0))*4)) + var v1 uint32_t = *(*uint32_t)(unsafe.Pointer(argb + uintptr(((2*i)+1))*4)) + // VP8RGBToU/V expects four accumulated pixels. Hence we need to + // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less. + var r int32 = (int32(((v0 >> 15) & uint32_t(0x1fe)) + ((v1 >> 15) & uint32_t(0x1fe)))) + var g int32 = (int32(((v0 >> 7) & uint32_t(0x1fe)) + ((v1 >> 7) & uint32_t(0x1fe)))) + var b int32 = (int32(((v0 << 1) & uint32_t(0x1fe)) + ((v1 << 1) & uint32_t(0x1fe)))) + var tmp_u int32 = VP8RGBToU(tls, r, g, b, (int32(YUV_HALF) << 2)) + var tmp_v int32 = VP8RGBToV(tls, r, g, b, (int32(YUV_HALF) << 2)) + if do_store != 0 { + *(*uint8_t)(unsafe.Pointer(u + uintptr(i))) = uint8_t(tmp_u) + *(*uint8_t)(unsafe.Pointer(v + uintptr(i))) = uint8_t(tmp_v) + } else { + // Approximated average-of-four. But it's an acceptable diff. + *(*uint8_t)(unsafe.Pointer(u + uintptr(i))) = (uint8_t(((int32(*(*uint8_t)(unsafe.Pointer(u + uintptr(i)))) + tmp_u) + 1) >> 1)) + *(*uint8_t)(unsafe.Pointer(v + uintptr(i))) = (uint8_t(((int32(*(*uint8_t)(unsafe.Pointer(v + uintptr(i)))) + tmp_v) + 1) >> 1)) + } + } + if (src_width & 1) != 0 { // last pixel + var v0 uint32_t = *(*uint32_t)(unsafe.Pointer(argb + uintptr(((2*i)+0))*4)) + var r int32 = (int32((v0 >> 14) & uint32_t(0x3fc))) + var g int32 = (int32((v0 >> 6) & uint32_t(0x3fc))) + var b int32 = (int32((v0 << 2) & uint32_t(0x3fc))) + var tmp_u int32 = VP8RGBToU(tls, r, g, b, (int32(YUV_HALF) << 2)) + var tmp_v int32 = VP8RGBToV(tls, r, g, b, (int32(YUV_HALF) << 2)) + if do_store != 0 { + *(*uint8_t)(unsafe.Pointer(u + uintptr(i))) = uint8_t(tmp_u) + *(*uint8_t)(unsafe.Pointer(v + uintptr(i))) = uint8_t(tmp_v) + } else { + *(*uint8_t)(unsafe.Pointer(u + uintptr(i))) = (uint8_t(((int32(*(*uint8_t)(unsafe.Pointer(u + uintptr(i)))) + tmp_u) + 1) >> 1)) + *(*uint8_t)(unsafe.Pointer(v + uintptr(i))) = (uint8_t(((int32(*(*uint8_t)(unsafe.Pointer(v + uintptr(i)))) + tmp_v) + 1) >> 1)) + } + } +} + +//----------------------------------------------------------------------------- + +func ConvertRGB24ToY_C(tls *libc.TLS, rgb uintptr, y uintptr, width int32) { /* yuv.c:171:13: */ + var i int32 + i = 0 +__1: + if !(i < width) { + goto __3 + } + { + *(*uint8_t)(unsafe.Pointer(y + uintptr(i))) = uint8_t(VP8RGBToY(tls, int32(*(*uint8_t)(unsafe.Pointer(rgb))), int32(*(*uint8_t)(unsafe.Pointer(rgb + 1))), int32(*(*uint8_t)(unsafe.Pointer(rgb + 2))), YUV_HALF)) + + } + goto __2 +__2: + i++ + rgb += uintptr(3) + goto __1 + goto __3 +__3: +} + +func ConvertBGR24ToY_C(tls *libc.TLS, bgr uintptr, y uintptr, width int32) { /* yuv.c:178:13: */ + var i int32 + i = 0 +__1: + if !(i < width) { + goto __3 + } + { + *(*uint8_t)(unsafe.Pointer(y + uintptr(i))) = uint8_t(VP8RGBToY(tls, int32(*(*uint8_t)(unsafe.Pointer(bgr + 2))), int32(*(*uint8_t)(unsafe.Pointer(bgr + 1))), int32(*(*uint8_t)(unsafe.Pointer(bgr))), YUV_HALF)) + + } + goto __2 +__2: + i++ + bgr += uintptr(3) + goto __1 + goto __3 +__3: +} + +func WebPConvertRGBA32ToUV_C(tls *libc.TLS, rgb uintptr, u uintptr, v uintptr, width int32) { /* yuv.c:185:6: */ + var i int32 + i = 0 +__1: + if !(i < width) { + goto __3 + } + { + var r int32 = int32(*(*uint16_t)(unsafe.Pointer(rgb))) + var g int32 = int32(*(*uint16_t)(unsafe.Pointer(rgb + 1*2))) + var b int32 = int32(*(*uint16_t)(unsafe.Pointer(rgb + 2*2))) + *(*uint8_t)(unsafe.Pointer(u + uintptr(i))) = uint8_t(VP8RGBToU(tls, r, g, b, (int32(YUV_HALF) << 2))) + *(*uint8_t)(unsafe.Pointer(v + uintptr(i))) = uint8_t(VP8RGBToV(tls, r, g, b, (int32(YUV_HALF) << 2))) + + } + goto __2 +__2: + i = i + (1) + rgb += 2 * (uintptr(4)) + goto __1 + goto __3 +__3: +} + +//----------------------------------------------------------------------------- + +func clip_y(tls *libc.TLS, v int32) uint16_t { /* yuv.c:199:17: */ + if v < 0 { + return uint16(0) + } + if v > ((int32(1) << 10) - 1) { + return (uint16((int32(1) << 10) - 1)) + } + return uint16_t(v) +} + +func SharpYUVUpdateY_C(tls *libc.TLS, ref uintptr, src uintptr, dst uintptr, len int32) uint64_t { /* yuv.c:203:17: */ + var diff uint64_t = uint64(0) + var i int32 + for i = 0; i < len; i++ { + var diff_y int32 = (int32(*(*uint16_t)(unsafe.Pointer(ref + uintptr(i)*2))) - int32(*(*uint16_t)(unsafe.Pointer(src + uintptr(i)*2)))) + var new_y int32 = (int32(*(*uint16_t)(unsafe.Pointer(dst + uintptr(i)*2))) + diff_y) + *(*uint16_t)(unsafe.Pointer(dst + uintptr(i)*2)) = clip_y(tls, new_y) + diff = diff + (uint64_t(libc.Xabs(tls, diff_y))) + } + return diff +} + +func SharpYUVUpdateRGB_C(tls *libc.TLS, ref uintptr, src uintptr, dst uintptr, len int32) { /* yuv.c:216:13: */ + var i int32 + for i = 0; i < len; i++ { + var diff_uv int32 = (int32(*(*int16_t)(unsafe.Pointer(ref + uintptr(i)*2))) - int32(*(*int16_t)(unsafe.Pointer(src + uintptr(i)*2)))) + *(*int16_t)(unsafe.Pointer((dst + uintptr(i)*2))) += int16_t((diff_uv)) + } +} + +func SharpYUVFilterRow_C(tls *libc.TLS, A uintptr, B uintptr, len int32, best_y uintptr, out uintptr) { /* yuv.c:225:13: */ + var i int32 + i = 0 +__1: + if !(i < len) { + goto __3 + } + { + var v0 int32 = ((((((int32(*(*int16_t)(unsafe.Pointer(A))) * 9) + (int32(*(*int16_t)(unsafe.Pointer(A + 1*2))) * 3)) + (int32(*(*int16_t)(unsafe.Pointer(B))) * 3)) + int32(*(*int16_t)(unsafe.Pointer(B + 1*2)))) + 8) >> 4) + var v1 int32 = ((((((int32(*(*int16_t)(unsafe.Pointer(A + 1*2))) * 9) + (int32(*(*int16_t)(unsafe.Pointer(A))) * 3)) + (int32(*(*int16_t)(unsafe.Pointer(B + 1*2))) * 3)) + int32(*(*int16_t)(unsafe.Pointer(B)))) + 8) >> 4) + *(*uint16_t)(unsafe.Pointer(out + uintptr(((2*i)+0))*2)) = clip_y(tls, (int32(*(*uint16_t)(unsafe.Pointer(best_y + uintptr(((2*i)+0))*2))) + v0)) + *(*uint16_t)(unsafe.Pointer(out + uintptr(((2*i)+1))*2)) = clip_y(tls, (int32(*(*uint16_t)(unsafe.Pointer(best_y + uintptr(((2*i)+1))*2))) + v1)) + + } + goto __2 +__2: + i++ + A += 2 + B += 2 + goto __1 + goto __3 +__3: +} + +//----------------------------------------------------------------------------- + +var WebPConvertRGB24ToY uintptr /* yuv.c:241:6: */ +var WebPConvertBGR24ToY uintptr /* yuv.c:242:6: */ +var WebPConvertRGBA32ToUV uintptr /* yuv.c:243:6: */ + +var WebPConvertARGBToY uintptr /* yuv.c:246:6: */ +var WebPConvertARGBToUV uintptr /* yuv.c:247:6: */ + +var WebPSharpYUVUpdateY uintptr /* yuv.c:250:10: */ +var WebPSharpYUVUpdateRGB uintptr /* yuv.c:252:6: */ +var WebPSharpYUVFilterRow uintptr /* yuv.c:254:6: */ + +func WebPInitConvertARGBToYUV(tls *libc.TLS) { /* yuv.c:263:1: */ + for ok := true; ok; ok = (0 != 0) { + if WebPInitConvertARGBToYUV_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + WebPInitConvertARGBToYUV_body(tls) + WebPInitConvertARGBToYUV_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var WebPInitConvertARGBToYUV_body_last_cpuinfo_used VP8CPUInfo = 0 /* yuv.c:263:1 */ + +func WebPInitConvertARGBToYUV_body(tls *libc.TLS) { /* yuv.c:263:1: */ + WebPConvertARGBToY = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) + }{ConvertARGBToY_C})) + WebPConvertARGBToUV = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32, int32) + }{WebPConvertARGBToUV_C})) + + WebPConvertRGB24ToY = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) + }{ConvertRGB24ToY_C})) + WebPConvertBGR24ToY = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) + }{ConvertBGR24ToY_C})) + + WebPConvertRGBA32ToUV = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + }{WebPConvertRGBA32ToUV_C})) + + WebPSharpYUVUpdateY = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) uint64_t + }{SharpYUVUpdateY_C})) + WebPSharpYUVUpdateRGB = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + }{SharpYUVUpdateRGB_C})) + WebPSharpYUVFilterRow = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr, uintptr) + }{SharpYUVFilterRow_C})) + + if VP8GetCPUInfo != (uintptr(0)) { + } + +} + +func VP8EncDspCostInitMIPS32(tls *libc.TLS) { /* cost_mips32.c:152:1: */ +} + +func VP8EncDspInitMIPS32(tls *libc.TLS) { /* enc_mips32.c:675:1: */ +} + +func VP8LEncDspInitMIPS32(tls *libc.TLS) { /* lossless_enc_mips32.c:395:1: */ +} + +func VP8EncDspCostInitMIPSdspR2(tls *libc.TLS) { /* cost_mips_dsp_r2.c:105:1: */ +} + +func VP8EncDspInitMIPSdspR2(tls *libc.TLS) { /* enc_mips_dsp_r2.c:1515:1: */ +} + +func VP8LEncDspInitMIPSdspR2(tls *libc.TLS) { /* lossless_enc_mips_dsp_r2.c:279:1: */ +} + +func VP8EncDspInitMSA(tls *libc.TLS) { /* enc_msa.c:894:1: */ +} + +func VP8LEncDspInitMSA(tls *libc.TLS) { /* lossless_enc_msa.c:146:1: */ +} + +func VP8EncDspCostInitNEON(tls *libc.TLS) { /* cost_neon.c:120:1: */ +} + +func VP8EncDspInitNEON(tls *libc.TLS) { /* enc_neon.c:936:1: */ +} + +func VP8LEncDspInitNEON(tls *libc.TLS) { /* lossless_enc_neon.c:142:1: */ +} + +func VP8EncDspCostInitSSE2(tls *libc.TLS) { /* cost_sse2.c:117:1: */ +} + +func VP8EncDspInitSSE2(tls *libc.TLS) { /* enc_sse2.c:1379:1: */ +} + +func VP8LEncDspInitSSE2(tls *libc.TLS) { /* lossless_enc_sse2.c:667:1: */ +} + +func VP8SSIMDspInitSSE2(tls *libc.TLS) { /* ssim_sse2.c:163:1: */ +} + +func VP8EncDspInitSSE41(tls *libc.TLS) { /* enc_sse41.c:337:1: */ +} + +func VP8LEncDspInitSSE41(tls *libc.TLS) { /* lossless_enc_sse41.c:153:1: */ +} + +func VP8DspInitMIPS32(tls *libc.TLS) { /* dec_mips32.c:585:1: */ +} + +func WebPRescalerDspInitMIPS32(tls *libc.TLS) { /* rescaler_mips32.c:293:1: */ +} + +func WebPInitSamplersMIPS32(tls *libc.TLS) { /* yuv_mips32.c:101:1: */ +} + +func WebPInitAlphaProcessingMIPSdspR2(tls *libc.TLS) { /* alpha_processing_mips_dsp_r2.c:226:1: */ +} + +func VP8DspInitMIPSdspR2(tls *libc.TLS) { /* dec_mips_dsp_r2.c:992:1: */ +} + +func VP8FiltersInitMIPSdspR2(tls *libc.TLS) { /* filters_mips_dsp_r2.c:400:1: */ +} + +func VP8LDspInitMIPSdspR2(tls *libc.TLS) { /* lossless_mips_dsp_r2.c:699:1: */ +} + +func WebPRescalerDspInitMIPSdspR2(tls *libc.TLS) { /* rescaler_mips_dsp_r2.c:312:1: */ +} + +func WebPInitYUV444ConvertersMIPSdspR2(tls *libc.TLS) { /* upsampling_mips_dsp_r2.c:285:1: */ +} + +func WebPInitUpsamplersMIPSdspR2(tls *libc.TLS) { /* upsampling_mips_dsp_r2.c:290:1: */ +} + +func WebPInitSamplersMIPSdspR2(tls *libc.TLS) { /* yuv_mips_dsp_r2.c:132:1: */ +} + +func VP8DspInitMSA(tls *libc.TLS) { /* dec_msa.c:1018:1: */ +} + +func VP8FiltersInitMSA(tls *libc.TLS) { /* filters_msa.c:200:1: */ +} + +func VP8LDspInitMSA(tls *libc.TLS) { /* lossless_msa.c:354:1: */ +} + +func WebPRescalerDspInitMSA(tls *libc.TLS) { /* rescaler_msa.c:441:1: */ +} + +func WebPInitUpsamplersMSA(tls *libc.TLS) { /* upsampling_msa.c:687:1: */ +} + +func WebPInitAlphaProcessingNEON(tls *libc.TLS) { /* alpha_processing_neon.c:190:1: */ +} + +func VP8DspInitNEON(tls *libc.TLS) { /* dec_neon.c:1661:1: */ +} + +func VP8FiltersInitNEON(tls *libc.TLS) { /* filters_neon.c:327:1: */ +} + +func VP8LDspInitNEON(tls *libc.TLS) { /* lossless_neon.c:643:1: */ +} + +func WebPRescalerDspInitNEON(tls *libc.TLS) { /* rescaler_neon.c:190:1: */ +} + +func WebPInitUpsamplersNEON(tls *libc.TLS) { /* upsampling_neon.c:284:1: */ +} + +func WebPInitConvertARGBToYUVNEON(tls *libc.TLS) { /* yuv_neon.c:285:1: */ +} + +func WebPInitSharpYUVNEON(tls *libc.TLS) { /* yuv_neon.c:286:1: */ +} + +func WebPInitAlphaProcessingSSE2(tls *libc.TLS) { /* alpha_processing_sse2.c:365:1: */ +} + +func VP8DspInitSSE2(tls *libc.TLS) { /* dec_sse2.c:1225:1: */ +} + +func VP8FiltersInitSSE2(tls *libc.TLS) { /* filters_sse2.c:338:1: */ +} + +func VP8LDspInitSSE2(tls *libc.TLS) { /* lossless_sse2.c:714:1: */ +} + +func WebPRescalerDspInitSSE2(tls *libc.TLS) { /* rescaler_sse2.c:364:1: */ +} + +func WebPInitYUV444ConvertersSSE2(tls *libc.TLS) { /* upsampling_sse2.c:261:1: */ +} + +func WebPInitUpsamplersSSE2(tls *libc.TLS) { /* upsampling_sse2.c:266:1: */ +} + +func WebPInitSamplersSSE2(tls *libc.TLS) { /* yuv_sse2.c:870:1: */ +} + +func WebPInitConvertARGBToYUVSSE2(tls *libc.TLS) { /* yuv_sse2.c:871:1: */ +} + +func WebPInitSharpYUVSSE2(tls *libc.TLS) { /* yuv_sse2.c:872:1: */ +} + +func WebPInitAlphaProcessingSSE41(tls *libc.TLS) { /* alpha_processing_sse41.c:90:1: */ +} + +func VP8DspInitSSE41(tls *libc.TLS) { /* dec_sse41.c:44:1: */ +} + +func VP8LDspInitSSE41(tls *libc.TLS) { /* lossless_sse41.c:130:1: */ +} + +func WebPInitYUV444ConvertersSSE41(tls *libc.TLS) { /* upsampling_sse41.c:233:1: */ +} + +func WebPInitUpsamplersSSE41(tls *libc.TLS) { /* upsampling_sse41.c:238:1: */ +} + +func WebPInitSamplersSSE41(tls *libc.TLS) { /* yuv_sse41.c:610:1: */ +} + +func WebPInitConvertARGBToYUVSSE41(tls *libc.TLS) { /* yuv_sse41.c:611:1: */ +} + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Bit writing and boolean coder +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP encoder: main interface +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header for constants related to WebP file format. +// +// Author: Urvang (urvang@google.com) + +// maximum value of transform_bits_ in VP8LEncoder. + +type VP8LEncoderARGBContent = uint32 /* vp8li_enc.h:44:3 */ + +type VP8LEncoder = struct { + config_ uintptr + pic_ uintptr + argb_ uintptr + argb_content_ VP8LEncoderARGBContent + _ [4]byte + argb_scratch_ uintptr + transform_data_ uintptr + transform_mem_ uintptr + transform_mem_size_ size_t + current_width_ int32 + histo_bits_ int32 + transform_bits_ int32 + cache_bits_ int32 + use_cross_color_ int32 + use_subtract_green_ int32 + use_predict_ int32 + use_palette_ int32 + palette_size_ int32 + palette_ [256]uint32_t + palette_sorted_ [256]uint32_t + _ [4]byte + refs_ [4]VP8LBackwardRefs1 + hash_chain_ VP8LHashChain +} /* vp8li_enc.h:79:3 */ + +//------------------------------------------------------------------------------ + +func EncodeLossless(tls *libc.TLS, data uintptr, width int32, height int32, effort_level int32, use_quality_100 int32, bw uintptr, stats uintptr) int32 { /* alpha_enc.c:49:12: */ + bp := tls.Alloc(372) + defer tls.Free(372) + + var ok int32 = 0 + // var config WebPConfig at bp+256, 116 + + // var picture WebPPicture at bp, 256 + + WebPPictureInit(tls, (bp) /* &picture */) + (*WebPPicture)(unsafe.Pointer(bp /* &picture */)).width = width + (*WebPPicture)(unsafe.Pointer(bp /* &picture */)).height = height + (*WebPPicture)(unsafe.Pointer(bp /* &picture */)).use_argb = 1 + (*WebPPicture)(unsafe.Pointer(bp /* &picture */)).stats = stats + if !(WebPPictureAlloc(tls, (bp) /* &picture */) != 0) { + return 0 + } + + // Transfer the alpha values to the green channel. + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPDispatchAlphaToGreen})).f(tls, data, width, (*WebPPicture)(unsafe.Pointer(bp /* &picture */)).width, (*WebPPicture)(unsafe.Pointer(bp /* &picture */)).height, + (*WebPPicture)(unsafe.Pointer(bp /* &picture */)).argb, (*WebPPicture)(unsafe.Pointer(bp /* &picture */)).argb_stride) + + WebPConfigInit(tls, (bp + 256) /* &config */) + (*WebPConfig)(unsafe.Pointer(bp + 256 /* &config */)).lossless = 1 + // Enable exact, or it would alter RGB values of transparent alpha, which is + // normally OK but not here since we are not encoding the input image but an + // internal encoding-related image containing necessary exact information in + // RGB channels. + (*WebPConfig)(unsafe.Pointer(bp + 256 /* &config */)).exact = 1 + (*WebPConfig)(unsafe.Pointer(bp + 256 /* &config */)).method = effort_level // impact is very small + // Set a low default quality for encoding alpha. Ensure that Alpha quality at + // lower methods (3 and below) is less than the threshold for triggering + // costly 'BackwardReferencesTraceBackwards'. + // If the alpha quality is set to 100 and the method to 6, allow for a high + // lossless quality to trigger the cruncher. + (*WebPConfig)(unsafe.Pointer(bp + 256 /* &config */)).quality = func() float32 { + if (use_quality_100 != 0) && (effort_level == 6) { + return float32(100) + } + return (8. * float32(effort_level)) + }() + + // TODO(urvang): Temporary fix to avoid generating images that trigger + // a decoder bug related to alpha with color cache. + // See: https://code.google.com/p/webp/issues/detail?id=239 + // Need to re-enable this later. + ok = (libc.Bool32(VP8LEncodeStream(tls, (bp+256) /* &config */, (bp) /* &picture */, bw, 0) == VP8_ENC_OK)) + WebPPictureFree(tls, (bp) /* &picture */) + ok = (libc.Bool32((ok != 0) && !((*VP8LBitWriter)(unsafe.Pointer(bw)).error_ != 0))) + if !(ok != 0) { + VP8LBitWriterWipeOut(tls, bw) + return 0 + } + return 1 +} + +// ----------------------------------------------------------------------------- + +// Small struct to hold the result of a filter mode compression attempt. +type FilterTrial = struct { + score size_t + bw VP8BitWriter + stats WebPAuxStats + _ [4]byte +} /* alpha_enc.c:106:3 */ + +// This function always returns an initialized 'bw' object, even upon error. +func EncodeAlphaInternal(tls *libc.TLS, data uintptr, width int32, height int32, method int32, filter int32, reduce_levels int32, effort_level int32, tmp_alpha uintptr, result uintptr) int32 { /* alpha_enc.c:109:12: */ + bp := tls.Alloc(49) + defer tls.Free(49) + + var ok int32 = 0 + var alpha_src uintptr + var filter_func WebPFilterFunc + // var header uint8_t at bp+48, 1 + + var data_size size_t = (size_t(width * height)) + var output uintptr = (uintptr(0)) + var output_size size_t = uint64(0) + // var tmp_bw VP8LBitWriter at bp, 48 + + // as per spec + + filter_func = WebPFilters[filter] + if filter_func != (uintptr(0)) { + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{filter_func})).f(tls, data, width, height, width, tmp_alpha) + alpha_src = tmp_alpha + } else { + alpha_src = data + } + + if method != 0 { + ok = VP8LBitWriterInit(tls, (bp) /* &tmp_bw */, (data_size >> 3)) + ok = (libc.Bool32((ok != 0) && (EncodeLossless(tls, alpha_src, width, height, effort_level, + libc.BoolInt32(!(reduce_levels != 0)), (bp) /* &tmp_bw */, (result+56 /* &.stats */)) != 0))) + if ok != 0 { + output = VP8LBitWriterFinish(tls, (bp) /* &tmp_bw */) + output_size = VP8LBitWriterNumBytes(tls, (bp) /* &tmp_bw */) + if output_size > data_size { + // compressed size is larger than source! Revert to uncompressed mode. + method = 0 + VP8LBitWriterWipeOut(tls, (bp) /* &tmp_bw */) + } + } else { + VP8LBitWriterWipeOut(tls, (bp) /* &tmp_bw */) + return 0 + } + } + + if method == 0 { + output = alpha_src + output_size = data_size + ok = 1 + } + + // Emit final result. + *(*uint8_t)(unsafe.Pointer(bp + 48 /* header */)) = (uint8_t(method | (filter << 2))) + if reduce_levels != 0 { + *(*uint8_t)(unsafe.Pointer(bp + 48 /* header */)) |= uint8_t((int32(1) << 4)) + } + + VP8BitWriterInit(tls, (result + 8 /* &.bw */), (uint64(1) + output_size)) + ok = (libc.Bool32((ok != 0) && (VP8BitWriterAppend(tls, (result+8 /* &.bw */), (bp+48) /* &header */, uint64(1)) != 0))) + ok = (libc.Bool32((ok != 0) && (VP8BitWriterAppend(tls, (result+8 /* &.bw */), output, output_size) != 0))) + + if method != 0 { + VP8LBitWriterWipeOut(tls, (bp) /* &tmp_bw */) + } + ok = (libc.Bool32((ok != 0) && !((*FilterTrial)(unsafe.Pointer(result)).bw.error_ != 0))) + (*FilterTrial)(unsafe.Pointer(result)).score = VP8BitWriterSize(tls, (result + 8 /* &.bw */)) + return ok +} + +// ----------------------------------------------------------------------------- + +func GetNumColors(tls *libc.TLS, data uintptr, width int32, height int32, stride int32) int32 { /* alpha_enc.c:179:12: */ + bp := tls.Alloc(256) + defer tls.Free(256) + + var j int32 + var colors int32 = 0 + *(*[256]uint8_t)(unsafe.Pointer(bp /* color */)) = [256]uint8_t{0: uint8_t(0)} + + for j = 0; j < height; j++ { + var i int32 + var p uintptr = (data + uintptr((j * stride))) + for i = 0; i < width; i++ { + *(*uint8_t)(unsafe.Pointer((bp) /* &color[0] */ + uintptr(*(*uint8_t)(unsafe.Pointer(p + uintptr(i)))))) = uint8_t(1) + } + } + for j = 0; j < 256; j++ { + if int32(*(*uint8_t)(unsafe.Pointer((bp) /* &color[0] */ + uintptr(j)))) > 0 { + colors++ + } + } + return colors +} + +// Given the input 'filter' option, return an OR'd bit-set of filters to try. +func GetFilterMap(tls *libc.TLS, alpha uintptr, width int32, height int32, filter int32, effort_level int32) uint32_t { /* alpha_enc.c:202:17: */ + var bit_map uint32_t = 0 + if filter == WEBP_FILTER_FAST { + // Quick estimate of the best candidate. + var try_filter_none int32 = (libc.Bool32(effort_level > 3)) + var kMinColorsForFilterNone int32 = 16 + var kMaxColorsForFilterNone int32 = 192 + var num_colors int32 = GetNumColors(tls, alpha, width, height, width) + // For low number of colors, NONE yields better compression. + if num_colors <= kMinColorsForFilterNone { + filter = WEBP_FILTER_NONE + } else { + filter = int32(WebPEstimateBestFilter(tls, alpha, width, height, width)) + } + bit_map = bit_map | (uint32_t(int32(1) << filter)) + // For large number of colors, try FILTER_NONE in addition to the best + // filter as well. + if (try_filter_none != 0) || (num_colors > kMaxColorsForFilterNone) { + bit_map = bit_map | (uint32_t(int32(1) << WEBP_FILTER_NONE)) + } + } else if filter == WEBP_FILTER_NONE { + bit_map = (uint32_t(int32(1) << WEBP_FILTER_NONE)) + } else { // WEBP_FILTER_BEST -> try all + bit_map = (uint32_t((int32(1) << WEBP_FILTER_LAST) - 1)) + } + return bit_map +} + +func InitFilterTrial(tls *libc.TLS, score uintptr) { /* alpha_enc.c:229:13: */ + (*FilterTrial)(unsafe.Pointer(score)).score = uint64(libc.CplUint32(0)) + VP8BitWriterInit(tls, (score + 8 /* &.bw */), uint64(0)) +} + +func ApplyFiltersAndEncode(tls *libc.TLS, alpha uintptr, width int32, height int32, data_size size_t, method int32, filter int32, reduce_levels int32, effort_level int32, output uintptr, output_size uintptr, stats uintptr) int32 { /* alpha_enc.c:234:12: */ + bp := tls.Alloc(496) + defer tls.Free(496) + + var ok int32 = 1 + // var best FilterTrial at bp, 248 + + var try_map uint32_t = GetFilterMap(tls, alpha, width, height, filter, effort_level) + InitFilterTrial(tls, (bp) /* &best */) + + if try_map != (uint32_t(int32(1) << WEBP_FILTER_NONE)) { + var filtered_alpha uintptr = WebPSafeMalloc(tls, 1, data_size) + if filtered_alpha == (uintptr(0)) { + return 0 + } + + filter = WEBP_FILTER_NONE + __1: + if !((ok != 0) && (try_map != 0)) { + goto __3 + } + { + if (try_map & uint32_t(1)) != 0 { + // var trial FilterTrial at bp+248, 248 + + ok = EncodeAlphaInternal(tls, alpha, width, height, method, filter, + reduce_levels, effort_level, filtered_alpha, + (bp + 248) /* &trial */) + if (ok != 0) && ((*FilterTrial)(unsafe.Pointer(bp+248 /* &trial */)).score < (*FilterTrial)(unsafe.Pointer(bp /* &best */)).score) { + VP8BitWriterWipeOut(tls, ((bp) /* &best */ + 8 /* &.bw */)) + *(*FilterTrial)(unsafe.Pointer(bp /* best */)) = *(*FilterTrial)(unsafe.Pointer(bp + 248 /* trial */)) + } else { + VP8BitWriterWipeOut(tls, ((bp + 248) /* &trial */ + 8 /* &.bw */)) + } + } + + } + goto __2 + __2: + filter++ + try_map >>= 1 + goto __1 + goto __3 + __3: + ; + WebPSafeFree(tls, filtered_alpha) + } else { + ok = EncodeAlphaInternal(tls, alpha, width, height, method, WEBP_FILTER_NONE, + reduce_levels, effort_level, (uintptr(0)), (bp) /* &best */) + } + if ok != 0 { + if stats != (uintptr(0)) { + (*WebPAuxStats)(unsafe.Pointer(stats)).lossless_features = (*FilterTrial)(unsafe.Pointer(bp /* &best */)).stats.lossless_features + (*WebPAuxStats)(unsafe.Pointer(stats)).histogram_bits = (*FilterTrial)(unsafe.Pointer(bp /* &best */)).stats.histogram_bits + (*WebPAuxStats)(unsafe.Pointer(stats)).transform_bits = (*FilterTrial)(unsafe.Pointer(bp /* &best */)).stats.transform_bits + (*WebPAuxStats)(unsafe.Pointer(stats)).cache_bits = (*FilterTrial)(unsafe.Pointer(bp /* &best */)).stats.cache_bits + (*WebPAuxStats)(unsafe.Pointer(stats)).palette_size = (*FilterTrial)(unsafe.Pointer(bp /* &best */)).stats.palette_size + (*WebPAuxStats)(unsafe.Pointer(stats)).lossless_size = (*FilterTrial)(unsafe.Pointer(bp /* &best */)).stats.lossless_size + (*WebPAuxStats)(unsafe.Pointer(stats)).lossless_hdr_size = (*FilterTrial)(unsafe.Pointer(bp /* &best */)).stats.lossless_hdr_size + (*WebPAuxStats)(unsafe.Pointer(stats)).lossless_data_size = (*FilterTrial)(unsafe.Pointer(bp /* &best */)).stats.lossless_data_size + } + *(*size_t)(unsafe.Pointer(output_size)) = VP8BitWriterSize(tls, ((bp) /* &best */ + 8 /* &.bw */)) + *(*uintptr)(unsafe.Pointer(output)) = VP8BitWriterBuf(tls, ((bp) /* &best */ + 8 /* &.bw */)) + } else { + VP8BitWriterWipeOut(tls, ((bp) /* &best */ + 8 /* &.bw */)) + } + return ok +} + +func EncodeAlpha(tls *libc.TLS, enc uintptr, quality int32, method int32, filter int32, effort_level int32, output uintptr, output_size uintptr) int32 { /* alpha_enc.c:292:12: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var pic uintptr = (*VP8Encoder)(unsafe.Pointer(enc)).pic_ + var width int32 = (*WebPPicture)(unsafe.Pointer(pic)).width + var height int32 = (*WebPPicture)(unsafe.Pointer(pic)).height + + var quant_alpha uintptr = (uintptr(0)) + var data_size size_t = (size_t(width * height)) + *(*uint64_t)(unsafe.Pointer(bp /* sse */)) = uint64(0) + var ok int32 = 1 + var reduce_levels int32 = (libc.Bool32(quality < 100)) + + // quick correctness checks + // as per spec + + if (quality < 0) || (quality > 100) { + return 0 + } + + if (method < 0) || (method > 1) { + return 0 + } + + if method == 0 { + // Don't filter, as filtering will make no impact on compressed size. + filter = WEBP_FILTER_NONE + } + + quant_alpha = WebPSafeMalloc(tls, 1, data_size) + if quant_alpha == (uintptr(0)) { + return 0 + } + + // Extract alpha data (width x height) from raw_data (stride x height). + WebPCopyPlane(tls, (*WebPPicture)(unsafe.Pointer(pic)).a, (*WebPPicture)(unsafe.Pointer(pic)).a_stride, quant_alpha, width, width, height) + + if reduce_levels != 0 { // No Quantization required for 'quality = 100'. + // 16 alpha levels gives quite a low MSE w.r.t original alpha plane hence + // mapped to moderate quality 70. Hence Quality:[0, 70] -> Levels:[2, 16] + // and Quality:]70, 100] -> Levels:]16, 256]. + var alpha_levels int32 + if quality <= 70 { + alpha_levels = (2 + (quality / 5)) + } else { + alpha_levels = (16 + ((quality - 70) * 8)) + } + ok = QuantizeLevels(tls, quant_alpha, width, height, alpha_levels, (bp) /* &sse */) + } + + if ok != 0 { + VP8FiltersInit(tls) + ok = ApplyFiltersAndEncode(tls, quant_alpha, width, height, data_size, method, + filter, reduce_levels, effort_level, output, + output_size, (*WebPPicture)(unsafe.Pointer(pic)).stats) + if (*WebPPicture)(unsafe.Pointer(pic)).stats != (uintptr(0)) { // need stats? + *(*int32)(unsafe.Pointer(((*WebPPicture)(unsafe.Pointer(pic)).stats /* &.coded_size */))) += (int32(*(*size_t)(unsafe.Pointer(output_size)))) + *(*uint64_t)(unsafe.Pointer((enc + 23512 /* &.sse_ */) + 3*8)) = *(*uint64_t)(unsafe.Pointer(bp /* sse */)) + } + } + + WebPSafeFree(tls, quant_alpha) + return ok +} + +//------------------------------------------------------------------------------ +// Main calls + +func CompressAlphaJob(tls *libc.TLS, arg1 uintptr, unused uintptr) int32 { /* alpha_enc.c:364:12: */ + bp := tls.Alloc(16) + defer tls.Free(16) + + var enc uintptr = arg1 + var config uintptr = (*VP8Encoder)(unsafe.Pointer(enc)).config_ + *(*uintptr)(unsafe.Pointer(bp /* alpha_data */)) = (uintptr(0)) + *(*size_t)(unsafe.Pointer(bp + 8 /* alpha_size */)) = uint64(0) + var effort_level int32 = (*WebPConfig)(unsafe.Pointer(config)).method // maps to [0..6] + var filter WEBP_FILTER_TYPE + if (*WebPConfig)(unsafe.Pointer(config)).alpha_filtering == 0 { + filter = WEBP_FILTER_NONE + } else { + if (*WebPConfig)(unsafe.Pointer(config)).alpha_filtering == 1 { + filter = WEBP_FILTER_FAST + } else { + filter = WEBP_FILTER_BEST + } + } + if !(EncodeAlpha(tls, enc, (*WebPConfig)(unsafe.Pointer(config)).alpha_quality, (*WebPConfig)(unsafe.Pointer(config)).alpha_compression, + int32(filter), effort_level, (bp) /* &alpha_data */, (bp+8) /* &alpha_size */) != 0) { + return 0 + } + if *(*size_t)(unsafe.Pointer(bp + 8 /* alpha_size */)) != size_t(uint32_t(*(*size_t)(unsafe.Pointer(bp + 8 /* alpha_size */)))) { // Soundness check. + WebPSafeFree(tls, *(*uintptr)(unsafe.Pointer(bp /* alpha_data */))) + return 0 + } + (*VP8Encoder)(unsafe.Pointer(enc)).alpha_data_size_ = uint32_t(*(*size_t)(unsafe.Pointer(bp + 8 /* alpha_size */))) + (*VP8Encoder)(unsafe.Pointer(enc)).alpha_data_ = *(*uintptr)(unsafe.Pointer(bp /* alpha_data */)) + _ = unused + return 1 +} + +func VP8EncInitAlpha(tls *libc.TLS, enc uintptr) { /* alpha_enc.c:388:6: */ + WebPInitAlphaProcessing(tls) + (*VP8Encoder)(unsafe.Pointer(enc)).has_alpha_ = WebPPictureHasTransparency(tls, (*VP8Encoder)(unsafe.Pointer(enc)).pic_) + (*VP8Encoder)(unsafe.Pointer(enc)).alpha_data_ = (uintptr(0)) + (*VP8Encoder)(unsafe.Pointer(enc)).alpha_data_size_ = uint32_t(0) + if (*VP8Encoder)(unsafe.Pointer(enc)).thread_level_ > 0 { + var worker uintptr = (enc + 560 /* &.alpha_worker_ */) + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(WebPGetWorkerInterface(tls))).Init})).f(tls, worker) + (*WebPWorker)(unsafe.Pointer(worker)).data1 = enc + (*WebPWorker)(unsafe.Pointer(worker)).data2 = (uintptr(0)) + (*WebPWorker)(unsafe.Pointer(worker)).hook = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{CompressAlphaJob})) + } +} + +func VP8EncStartAlpha(tls *libc.TLS, enc uintptr) int32 { /* alpha_enc.c:402:5: */ + if (*VP8Encoder)(unsafe.Pointer(enc)).has_alpha_ != 0 { + if (*VP8Encoder)(unsafe.Pointer(enc)).thread_level_ > 0 { + var worker uintptr = (enc + 560 /* &.alpha_worker_ */) + // Makes sure worker is good to go. + if !((*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(WebPGetWorkerInterface(tls))).Reset})).f(tls, worker) != 0) { + return 0 + } + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(WebPGetWorkerInterface(tls))).Launch})).f(tls, worker) + return 1 + } else { + return CompressAlphaJob(tls, enc, (uintptr(0))) // just do the job right away + } + } + return 1 +} + +func VP8EncFinishAlpha(tls *libc.TLS, enc uintptr) int32 { /* alpha_enc.c:419:5: */ + if (*VP8Encoder)(unsafe.Pointer(enc)).has_alpha_ != 0 { + if (*VP8Encoder)(unsafe.Pointer(enc)).thread_level_ > 0 { + var worker uintptr = (enc + 560 /* &.alpha_worker_ */) + if !((*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(WebPGetWorkerInterface(tls))).Sync})).f(tls, worker) != 0) { + return 0 + } // error + } + } + return WebPReportProgress(tls, (*VP8Encoder)(unsafe.Pointer(enc)).pic_, ((*VP8Encoder)(unsafe.Pointer(enc)).percent_ + 20), (enc + 536 /* &.percent_ */)) +} + +func VP8EncDeleteAlpha(tls *libc.TLS, enc uintptr) int32 { /* alpha_enc.c:429:5: */ + var ok int32 = 1 + if (*VP8Encoder)(unsafe.Pointer(enc)).thread_level_ > 0 { + var worker uintptr = (enc + 560 /* &.alpha_worker_ */) + // finish anything left in flight + ok = (*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(WebPGetWorkerInterface(tls))).Sync})).f(tls, worker) + // still need to end the worker, even if !ok + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(WebPGetWorkerInterface(tls))).End})).f(tls, worker) + } + WebPSafeFree(tls, (*VP8Encoder)(unsafe.Pointer(enc)).alpha_data_) + (*VP8Encoder)(unsafe.Pointer(enc)).alpha_data_ = (uintptr(0)) + (*VP8Encoder)(unsafe.Pointer(enc)).alpha_data_size_ = uint32_t(0) + (*VP8Encoder)(unsafe.Pointer(enc)).has_alpha_ = 0 + return ok +} + +//------------------------------------------------------------------------------ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +//------------------------------------------------------------------------------ +// Smooth the segment map by replacing isolated block by the majority of its +// neighbours. + +func SmoothSegmentMap(tls *libc.TLS, enc uintptr) { /* analysis_enc.c:28:13: */ + bp := tls.Alloc(16) + defer tls.Free(16) + + var n int32 + var x int32 + var y int32 + var w int32 = (*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ + var h int32 = (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_ + var majority_cnt_3_x_3_grid int32 = 5 + var tmp uintptr = WebPSafeMalloc(tls, (uint64(w * h)), uint64(unsafe.Sizeof(uint8_t(0)))) + // no overflow, as per spec + + if tmp == (uintptr(0)) { + return + } + for y = 1; y < (h - 1); y++ { + for x = 1; x < (w - 1); x++ { + *(*[4]int32)(unsafe.Pointer(bp /* cnt */)) = [4]int32{0: 0} + var mb uintptr = ((*VP8Encoder)(unsafe.Pointer(enc)).mb_info_ + uintptr((x+(w*y)))*4) + var majority_seg int32 = (int32(*(*uint8)(unsafe.Pointer(mb /* &.segment_ */)) & 0x60 >> 5)) + // Check the 8 neighbouring segment values. + *(*int32)(unsafe.Pointer((bp) /* &cnt[0] */ + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer((mb + uintptr((-w-1))*4) /* &.segment_ */))&0x60>>5))))*4))++ // top-left + *(*int32)(unsafe.Pointer((bp) /* &cnt[0] */ + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer((mb + uintptr((-w+0))*4) /* &.segment_ */))&0x60>>5))))*4))++ // top + *(*int32)(unsafe.Pointer((bp) /* &cnt[0] */ + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer((mb + uintptr((-w+1))*4) /* &.segment_ */))&0x60>>5))))*4))++ // top-right + *(*int32)(unsafe.Pointer((bp) /* &cnt[0] */ + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer((mb + libc.UintptrFromInt32(-1)*4) /* &.segment_ */))&0x60>>5))))*4))++ // left + *(*int32)(unsafe.Pointer((bp) /* &cnt[0] */ + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer((mb + 1*4) /* &.segment_ */))&0x60>>5))))*4))++ // right + *(*int32)(unsafe.Pointer((bp) /* &cnt[0] */ + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer((mb + uintptr((w-1))*4) /* &.segment_ */))&0x60>>5))))*4))++ // bottom-left + *(*int32)(unsafe.Pointer((bp) /* &cnt[0] */ + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer((mb + uintptr((w+0))*4) /* &.segment_ */))&0x60>>5))))*4))++ // bottom + *(*int32)(unsafe.Pointer((bp) /* &cnt[0] */ + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer((mb + uintptr((w+1))*4) /* &.segment_ */))&0x60>>5))))*4))++ // bottom-right + for n = 0; n < NUM_MB_SEGMENTS; n++ { + if *(*int32)(unsafe.Pointer((bp) /* &cnt[0] */ + uintptr(n)*4)) >= majority_cnt_3_x_3_grid { + majority_seg = n + break + } + } + *(*uint8_t)(unsafe.Pointer(tmp + uintptr((x + (y * w))))) = uint8_t(majority_seg) + } + } + for y = 1; y < (h - 1); y++ { + for x = 1; x < (w - 1); x++ { + var mb uintptr = ((*VP8Encoder)(unsafe.Pointer(enc)).mb_info_ + uintptr((x+(w*y)))*4) + libc.SetBitFieldPtr8Uint32((mb /* &.segment_ */), uint32(*(*uint8_t)(unsafe.Pointer(tmp + uintptr((x + (y * w)))))), 5, 0x60) + } + } + WebPSafeFree(tls, tmp) +} + +//------------------------------------------------------------------------------ +// set segment susceptibility alpha_ / beta_ + +func clip2(tls *libc.TLS, v int32, m int32, M int32) int32 { /* analysis_enc.c:72:24: */ + if v < m { + return m + } + if v > M { + return M + } + return v +} + +func SetSegmentAlphas(tls *libc.TLS, enc uintptr, centers uintptr, mid int32) { /* analysis_enc.c:76:13: */ + var nb int32 = (*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.num_segments_ + var min int32 = *(*int32)(unsafe.Pointer(centers)) + var max int32 = *(*int32)(unsafe.Pointer(centers)) + var n int32 + + if nb > 1 { + for n = 0; n < nb; n++ { + if min > *(*int32)(unsafe.Pointer(centers + uintptr(n)*4)) { + min = *(*int32)(unsafe.Pointer(centers + uintptr(n)*4)) + } + if max < *(*int32)(unsafe.Pointer(centers + uintptr(n)*4)) { + max = *(*int32)(unsafe.Pointer(centers + uintptr(n)*4)) + } + } + } + if max == min { + max = (min + 1) + } + + for n = 0; n < nb; n++ { + var alpha int32 = ((255 * (*(*int32)(unsafe.Pointer(centers + uintptr(n)*4)) - mid)) / (max - min)) + var beta int32 = ((255 * (*(*int32)(unsafe.Pointer(centers + uintptr(n)*4)) - min)) / (max - min)) + (*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */) + uintptr(n)*744)).alpha_ = clip2(tls, alpha, -127, 127) + (*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */) + uintptr(n)*744)).beta_ = clip2(tls, beta, 0, 255) + } +} + +//------------------------------------------------------------------------------ +// Compute susceptibility based on DCT-coeff histograms: +// the higher, the "easier" the macroblock is to compress. + +func FinalAlphaValue(tls *libc.TLS, alpha int32) int32 { /* analysis_enc.c:108:12: */ + alpha = (255 - alpha) + return clip2(tls, alpha, 0, 255) +} + +func GetAlpha(tls *libc.TLS, histo uintptr) int32 { /* analysis_enc.c:113:12: */ + // 'alpha' will later be clipped to [0..MAX_ALPHA] range, clamping outer + // values which happen to be mostly noise. This leaves the maximum precision + // for handling the useful small values which contribute most. + var max_value int32 = (*VP8Histogram)(unsafe.Pointer(histo)).max_value + var last_non_zero int32 = (*VP8Histogram)(unsafe.Pointer(histo)).last_non_zero + var alpha int32 + if max_value > 1 { + alpha = (((2 * 255) * last_non_zero) / max_value) + } else { + alpha = 0 + } + return alpha +} + +func InitHistogram(tls *libc.TLS, histo uintptr) { /* analysis_enc.c:124:13: */ + (*VP8Histogram)(unsafe.Pointer(histo)).max_value = 0 + (*VP8Histogram)(unsafe.Pointer(histo)).last_non_zero = 1 +} + +//------------------------------------------------------------------------------ +// Simplified k-Means, to assign Nb segments based on alpha-histogram + +func AssignSegments(tls *libc.TLS, enc uintptr, alphas uintptr) { /* analysis_enc.c:132:13: */ + bp := tls.Alloc(1072) + defer tls.Free(1072) + + // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an + // explicit check is needed to avoid spurious warning about 'n + 1' exceeding + // array bounds of 'centers' with some compilers (noticed with gcc-4.9). + var nb int32 + if (*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.num_segments_ < NUM_MB_SEGMENTS { + nb = (*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.num_segments_ + } else { + nb = NUM_MB_SEGMENTS + } + // var centers [4]int32 at bp, 16 + + var weighted_average int32 = 0 + // var map1 [256]int32 at bp+48, 1024 + + var a int32 + var n int32 + var k int32 + var min_a int32 = 0 + var max_a int32 = 255 + var range_a int32 + // 'int' type is ok for histo, and won't overflow + // var accum [4]int32 at bp+16, 16 + + // var dist_accum [4]int32 at bp+32, 16 + + // bracket the input + for n = 0; (n <= 255) && (*(*int32)(unsafe.Pointer(alphas + uintptr(n)*4)) == 0); n++ { + } + min_a = n + for n = 255; (n > min_a) && (*(*int32)(unsafe.Pointer(alphas + uintptr(n)*4)) == 0); n-- { + } + max_a = n + range_a = (max_a - min_a) + + // Spread initial centers evenly + k = 0 + n = 1 +__1: + if !(k < nb) { + goto __3 + } + { + + *(*int32)(unsafe.Pointer((bp) /* &centers[0] */ + uintptr(k)*4)) = (min_a + ((n * range_a) / (2 * nb))) + + } + goto __2 +__2: + k++ + n = n + (2) + goto __1 + goto __3 +__3: + ; + + for k = 0; k < 6; k++ { // few iters are enough + var total_weight int32 + var displaced int32 + // Reset stats + for n = 0; n < nb; n++ { + *(*int32)(unsafe.Pointer((bp + 16) /* &accum[0] */ + uintptr(n)*4)) = 0 + *(*int32)(unsafe.Pointer((bp + 32) /* &dist_accum[0] */ + uintptr(n)*4)) = 0 + } + // Assign nearest center for each 'a' + n = 0 // track the nearest center for current 'a' + for a = min_a; a <= max_a; a++ { + if *(*int32)(unsafe.Pointer(alphas + uintptr(a)*4)) != 0 { + for ((n + 1) < nb) && (libc.Xabs(tls, (a-*(*int32)(unsafe.Pointer((bp) /* &centers[0] */ + uintptr((n+1))*4)))) < libc.Xabs(tls, (a-*(*int32)(unsafe.Pointer((bp) /* &centers[0] */ + uintptr(n)*4))))) { + n++ + } + *(*int32)(unsafe.Pointer((bp + 48) /* &map1[0] */ + uintptr(a)*4)) = n + // accumulate contribution into best centroid + *(*int32)(unsafe.Pointer(((bp + 32) /* &dist_accum */ + uintptr(n)*4))) += (a * *(*int32)(unsafe.Pointer(alphas + uintptr(a)*4))) + *(*int32)(unsafe.Pointer(((bp + 16) /* &accum */ + uintptr(n)*4))) += (*(*int32)(unsafe.Pointer(alphas + uintptr(a)*4))) + } + } + // All point are classified. Move the centroids to the + // center of their respective cloud. + displaced = 0 + weighted_average = 0 + total_weight = 0 + for n = 0; n < nb; n++ { + if *(*int32)(unsafe.Pointer((bp + 16) /* &accum[0] */ + uintptr(n)*4)) != 0 { + var new_center int32 = ((*(*int32)(unsafe.Pointer((bp + 32) /* &dist_accum[0] */ + uintptr(n)*4)) + (*(*int32)(unsafe.Pointer((bp + 16) /* &accum[0] */ + uintptr(n)*4)) / 2)) / *(*int32)(unsafe.Pointer((bp + 16) /* &accum[0] */ + uintptr(n)*4))) + displaced = displaced + (libc.Xabs(tls, (*(*int32)(unsafe.Pointer((bp) /* &centers[0] */ + uintptr(n)*4)) - new_center))) + *(*int32)(unsafe.Pointer((bp) /* &centers[0] */ + uintptr(n)*4)) = new_center + weighted_average = weighted_average + (new_center * *(*int32)(unsafe.Pointer((bp + 16) /* &accum[0] */ + uintptr(n)*4))) + total_weight = total_weight + (*(*int32)(unsafe.Pointer((bp + 16) /* &accum[0] */ + uintptr(n)*4))) + } + } + weighted_average = ((weighted_average + (total_weight / 2)) / total_weight) + if displaced < 5 { + break + } // no need to keep on looping... + } + + // Map each original value to the closest centroid + for n = 0; n < ((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ * (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_); n++ { + var mb uintptr = ((*VP8Encoder)(unsafe.Pointer(enc)).mb_info_ + uintptr(n)*4) + var alpha int32 = int32((*VP8MBInfo)(unsafe.Pointer(mb)).alpha_) + libc.SetBitFieldPtr8Uint32((mb /* &.segment_ */), uint32(*(*int32)(unsafe.Pointer((bp + 48) /* &map1[0] */ + uintptr(alpha)*4))), 5, 0x60) + (*VP8MBInfo)(unsafe.Pointer(mb)).alpha_ = uint8_t(*(*int32)(unsafe.Pointer((bp) /* &centers[0] */ + uintptr(*(*int32)(unsafe.Pointer((bp + 48) /* &map1[0] */ + uintptr(alpha)*4)))*4))) // for the record. + } + + if nb > 1 { + var smooth int32 = ((*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).preprocessing & 1) + if smooth != 0 { + SmoothSegmentMap(tls, enc) + } + } + + SetSegmentAlphas(tls, enc, (bp) /* &centers[0] */, weighted_average) // pick some alphas. +} + +//------------------------------------------------------------------------------ +// Macroblock analysis: collect histogram for each mode, deduce the maximal +// susceptibility and set best modes for this macroblock. +// Segment assignment is done later. + +// Number of modes to inspect for alpha_ evaluation. We don't need to test all +// the possible modes during the analysis phase: we risk falling into a local +// optimum, or be subject to boundary effect + +func MBAnalyzeBestIntra16Mode(tls *libc.TLS, it uintptr) int32 { /* analysis_enc.c:230:12: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var max_mode int32 = 2 + var mode int32 + var best_alpha int32 = (-1) + var best_mode int32 = 0 + + VP8MakeLuma16Preds(tls, it) + for mode = 0; mode < max_mode; mode++ { + // var histo VP8Histogram at bp, 8 + + var alpha int32 + + InitHistogram(tls, (bp) /* &histo */) + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8CollectHistogram})).f(tls, ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((0))), + ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_p_ + uintptr(VP8I16ModeOffsets[mode])), + 0, 16, (bp) /* &histo */) + alpha = GetAlpha(tls, (bp) /* &histo */) + if (alpha) > (best_alpha) { + best_alpha = alpha + best_mode = mode + } + } + VP8SetIntra16Mode(tls, it, best_mode) + return best_alpha +} + +func FastMBAnalyze(tls *libc.TLS, it uintptr) int32 { /* analysis_enc.c:255:12: */ + bp := tls.Alloc(80) + defer tls.Free(80) + + // Empirical cut-off value, should be around 16 (~=block size). We use the + // [8-17] range and favor intra4 at high quality, intra16 for low quality. + var q int32 = libc.Int32FromFloat32((*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).enc_)).config_)).quality) + var kThreshold uint32_t = (uint32_t(8 + (((17 - 8) * q) / 100))) + var k int32 + // var dc [16]uint32_t at bp, 64 + + var m uint32_t + var m2 uint32_t + for k = 0; k < 16; k = k + (4) { + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8Mean16x4})).f(tls, (((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((0))) + uintptr((k * 32))), ((bp) /* &dc */ + uintptr(k)*4)) + } + m = uint32_t(0) + m2 = uint32_t(0) + k = 0 + for ; k < 16; k++ { + m = m + (*(*uint32_t)(unsafe.Pointer((bp) /* &dc[0] */ + uintptr(k)*4))) + m2 = m2 + (*(*uint32_t)(unsafe.Pointer((bp) /* &dc[0] */ + uintptr(k)*4)) * *(*uint32_t)(unsafe.Pointer((bp) /* &dc[0] */ + uintptr(k)*4))) + } + if (kThreshold * m2) < (m * m) { + VP8SetIntra16Mode(tls, it, 0) // DC16 + } else { + *(*[16]uint8_t)(unsafe.Pointer(bp + 64 /* modes */)) = [16]uint8_t{0: uint8_t(0)} // DC4 + VP8SetIntra4Mode(tls, it, (bp + 64) /* &modes[0] */) + } + return 0 +} + +func MBAnalyzeBestUVMode(tls *libc.TLS, it uintptr) int32 { /* analysis_enc.c:278:12: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var best_alpha int32 = (-1) + var smallest_alpha int32 = 0 + var best_mode int32 = 0 + var max_mode int32 = 2 + var mode int32 + + VP8MakeChroma8Preds(tls, it) + for mode = 0; mode < max_mode; mode++ { + // var histo VP8Histogram at bp, 8 + + var alpha int32 + InitHistogram(tls, (bp) /* &histo */) + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8CollectHistogram})).f(tls, ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((16))), + ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_p_ + uintptr(VP8UVModeOffsets[mode])), + 16, ((16 + 4) + 4), (bp) /* &histo */) + alpha = GetAlpha(tls, (bp) /* &histo */) + if (alpha) > (best_alpha) { + best_alpha = alpha + } + // The best prediction mode tends to be the one with the smallest alpha. + if (mode == 0) || (alpha < smallest_alpha) { + smallest_alpha = alpha + best_mode = mode + } + } + VP8SetIntraUVMode(tls, it, best_mode) + return best_alpha +} + +func MBAnalyze(tls *libc.TLS, it uintptr, alphas uintptr, alpha uintptr, uv_alpha uintptr) { /* analysis_enc.c:307:13: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var best_alpha int32 + var best_uv_alpha int32 + + VP8SetIntra16Mode(tls, it, 0) // default: Intra16, DC_PRED + VP8SetSkip(tls, it, 0) // not skipped + VP8SetSegment(tls, it, 0) // default segment, spec-wise. + + if (*VP8Encoder)(unsafe.Pointer(enc)).method_ <= 1 { + best_alpha = FastMBAnalyze(tls, it) + } else { + best_alpha = MBAnalyzeBestIntra16Mode(tls, it) + } + best_uv_alpha = MBAnalyzeBestUVMode(tls, it) + + // Final susceptibility mix + best_alpha = ((((3 * best_alpha) + best_uv_alpha) + 2) >> 2) + best_alpha = FinalAlphaValue(tls, best_alpha) + *(*int32)(unsafe.Pointer(alphas + uintptr(best_alpha)*4))++ + (*VP8MBInfo)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_)).alpha_ = uint8_t(best_alpha) // for later remapping. + + // Accumulate for later complexity analysis. + *(*int32)(unsafe.Pointer(alpha)) += (best_alpha) // mixed susceptibility (not just luma) + *(*int32)(unsafe.Pointer(uv_alpha)) += (best_uv_alpha) +} + +func DefaultMBInfo(tls *libc.TLS, mb uintptr) { /* analysis_enc.c:335:13: */ + libc.SetBitFieldPtr8Uint32((mb /* &.type_ */), uint32(1), 0, 0x3) // I16x16 + libc.SetBitFieldPtr8Uint32((mb /* &.uv_mode_ */), uint32(0), 2, 0xc) + libc.SetBitFieldPtr8Uint32((mb /* &.skip_ */), uint32(0), 4, 0x10) // not skipped + libc.SetBitFieldPtr8Uint32((mb /* &.segment_ */), uint32(0), 5, 0x60) // default segment + (*VP8MBInfo)(unsafe.Pointer(mb)).alpha_ = uint8_t(0) +} + +//------------------------------------------------------------------------------ +// Main analysis loop: +// Collect all susceptibilities for each macroblock and record their +// distribution in alphas[]. Segments is assigned a-posteriori, based on +// this histogram. +// We also pick an intra16 prediction mode, which shouldn't be considered +// final except for fast-encode settings. We can also pick some intra4 modes +// and decide intra4/intra16, but that's usually almost always a bad choice at +// this stage. + +func ResetAllMBInfo(tls *libc.TLS, enc uintptr) { /* analysis_enc.c:353:13: */ + var n int32 + for n = 0; n < ((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ * (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_); n++ { + DefaultMBInfo(tls, ((*VP8Encoder)(unsafe.Pointer(enc)).mb_info_ + uintptr(n)*4)) + } + // Default susceptibilities. + (*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */))).alpha_ = 0 + (*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */))).beta_ = 0 + // Note: we can't compute this alpha_ / uv_alpha_ -> set to default value. + (*VP8Encoder)(unsafe.Pointer(enc)).alpha_ = 0 + (*VP8Encoder)(unsafe.Pointer(enc)).uv_alpha_ = 0 + WebPReportProgress(tls, (*VP8Encoder)(unsafe.Pointer(enc)).pic_, ((*VP8Encoder)(unsafe.Pointer(enc)).percent_ + 20), (enc + 536 /* &.percent_ */)) +} + +// struct used to collect job result +type SegmentJob = struct { + worker WebPWorker + alphas [256]int32 + alpha int32 + uv_alpha int32 + it VP8EncIterator + delta_progress int32 + _ [4]byte +} /* analysis_enc.c:374:3 */ + +// main work call +func DoSegmentsJob(tls *libc.TLS, arg1 uintptr, arg2 uintptr) int32 { /* analysis_enc.c:377:12: */ + var job uintptr = arg1 + var it uintptr = arg2 + var ok int32 = 1 + if !(VP8IteratorIsDone(tls, it) != 0) { + var tmp [63]uint8_t + + var scratch uintptr = (uintptr((uintptr_t(libc.Uint64FromUint8(tmp[0])) + uint64(31)) & libc.Uint64FromInt32(libc.CplInt32(31)))) + for ok := int32(1); ok != 1; ok = VP8IteratorNext(tls, it) { + // Let's pretend we have perfect lossless reconstruction. + VP8IteratorImport(tls, it, scratch) + MBAnalyze(tls, it, (job + 48 /* &.alphas */), (job + 1072 /* &.alpha */), (job + 1076 /* &.uv_alpha */)) + ok = VP8IteratorProgress(tls, it, (*SegmentJob)(unsafe.Pointer(job)).delta_progress) + } + } + return ok +} + +func MergeJobs(tls *libc.TLS, src uintptr, dst uintptr) { /* analysis_enc.c:394:13: */ + var i int32 + for i = 0; i <= 255; i++ { + *(*int32)(unsafe.Pointer(((dst + 48 /* &.alphas */) + uintptr(i)*4))) += (*(*int32)(unsafe.Pointer((src + 48 /* &.alphas */) + uintptr(i)*4))) + } + *(*int32)(unsafe.Pointer((dst + 1072 /* &.alpha */))) += ((*SegmentJob)(unsafe.Pointer(src)).alpha) + *(*int32)(unsafe.Pointer((dst + 1076 /* &.uv_alpha */))) += ((*SegmentJob)(unsafe.Pointer(src)).uv_alpha) +} + +// initialize the job struct with some tasks to perform +func InitSegmentJob(tls *libc.TLS, enc uintptr, job uintptr, start_row int32, end_row int32) { /* analysis_enc.c:402:13: */ + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(WebPGetWorkerInterface(tls))).Init})).f(tls, (job /* &.worker */)) + (*SegmentJob)(unsafe.Pointer(job)).worker.data1 = job + (*SegmentJob)(unsafe.Pointer(job)).worker.data2 = (job + 1080 /* &.it */) + (*SegmentJob)(unsafe.Pointer(job)).worker.hook = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{DoSegmentsJob})) + VP8IteratorInit(tls, enc, (job + 1080 /* &.it */)) + VP8IteratorSetRow(tls, (job + 1080 /* &.it */), start_row) + VP8IteratorSetCountDown(tls, (job + 1080 /* &.it */), ((end_row - start_row) * (*VP8Encoder)(unsafe.Pointer(enc)).mb_w_)) + libc.Xmemset(tls, (job + 48 /* &.alphas */), 0, uint64(unsafe.Sizeof([256]int32{}))) + (*SegmentJob)(unsafe.Pointer(job)).alpha = 0 + (*SegmentJob)(unsafe.Pointer(job)).uv_alpha = 0 + // only one of both jobs can record the progress, since we don't + // expect the user's hook to be multi-thread safe + (*SegmentJob)(unsafe.Pointer(job)).delta_progress = func() int32 { + if start_row == 0 { + return 20 + } + return 0 + }() +} + +// main entry point +func VP8EncAnalyze(tls *libc.TLS, enc uintptr) int32 { /* analysis_enc.c:420:5: */ + bp := tls.Alloc(9872) + defer tls.Free(9872) + + var ok int32 = 1 + var do_segments int32 = (libc.Bool32((((*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).emulate_jpeg_size != 0) || ((*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.num_segments_ > 1)) || ((*VP8Encoder)(unsafe.Pointer(enc)).method_ <= 1))) // for method 0 - 1, we need preds_[] to be filled. + if do_segments != 0 { + var last_row int32 = (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_ + // We give a little more than a half work to the main thread. + var split_row int32 = (((9 * last_row) + 15) >> 4) + var total_mb int32 = (last_row * (*VP8Encoder)(unsafe.Pointer(enc)).mb_w_) + var do_mt int32 = 0 + var worker_interface uintptr = WebPGetWorkerInterface(tls) + // var main_job SegmentJob at bp, 4936 + + if do_mt != 0 { + // var side_job SegmentJob at bp+4936, 4936 + + // Note the use of '&' instead of '&&' because we must call the functions + // no matter what. + InitSegmentJob(tls, enc, (bp) /* &main_job */, 0, split_row) + InitSegmentJob(tls, enc, (bp + 4936) /* &side_job */, split_row, last_row) + // we don't need to call Reset() on main_job.worker, since we're calling + // WebPWorkerExecute() on it + ok = ok & ((*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).Reset})).f(tls, (bp + 4936) /* &side_job */ /* &.worker */)) + // launch the two jobs in parallel + if ok != 0 { + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).Launch})).f(tls, (bp + 4936) /* &side_job */ /* &.worker */) + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).Execute})).f(tls, (bp) /* &main_job */ /* &.worker */) + ok = ok & ((*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).Sync})).f(tls, (bp + 4936) /* &side_job */ /* &.worker */)) + ok = ok & ((*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).Sync})).f(tls, (bp) /* &main_job */ /* &.worker */)) + } + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).End})).f(tls, (bp + 4936) /* &side_job */ /* &.worker */) + if ok != 0 { + MergeJobs(tls, (bp + 4936) /* &side_job */, (bp) /* &main_job */) + } // merge results together + } else { + // Even for single-thread case, we use the generic Worker tools. + InitSegmentJob(tls, enc, (bp) /* &main_job */, 0, last_row) + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).Execute})).f(tls, (bp) /* &main_job */ /* &.worker */) + ok = ok & ((*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).Sync})).f(tls, (bp) /* &main_job */ /* &.worker */)) + } + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).End})).f(tls, (bp) /* &main_job */ /* &.worker */) + if ok != 0 { + (*VP8Encoder)(unsafe.Pointer(enc)).alpha_ = ((*SegmentJob)(unsafe.Pointer(bp /* &main_job */)).alpha / total_mb) + (*VP8Encoder)(unsafe.Pointer(enc)).uv_alpha_ = ((*SegmentJob)(unsafe.Pointer(bp /* &main_job */)).uv_alpha / total_mb) + AssignSegments(tls, enc, ((bp) /* &main_job */ + 48 /* &.alphas */)) + } + } else { // Use only one default segment. + ResetAllMBInfo(tls, enc) + } + return ok +} + +type CostModel = struct { + alpha_ [256]float64 + red_ [256]float64 + blue_ [256]float64 + distance_ [40]float64 + literal_ uintptr +} /* backward_references_cost_enc.c:38:3 */ + +func ConvertPopulationCountTableToBitEstimates(tls *libc.TLS, num_symbols int32, population_counts uintptr, output uintptr) { /* backward_references_cost_enc.c:40:13: */ + var sum uint32_t = uint32_t(0) + var nonzeros int32 = 0 + var i int32 + for i = 0; i < num_symbols; i++ { + sum = sum + (*(*uint32_t)(unsafe.Pointer(population_counts + uintptr(i)*4))) + if *(*uint32_t)(unsafe.Pointer(population_counts + uintptr(i)*4)) > uint32_t(0) { + nonzeros++ + } + } + if nonzeros <= 1 { + libc.Xmemset(tls, output, 0, (uint64(num_symbols) * uint64(unsafe.Sizeof(float64(0))))) + } else { + var logsum float64 = float64(VP8LFastLog2(tls, sum)) + for i = 0; i < num_symbols; i++ { + *(*float64)(unsafe.Pointer(output + uintptr(i)*8)) = (logsum - float64(VP8LFastLog2(tls, *(*uint32_t)(unsafe.Pointer(population_counts + uintptr(i)*4))))) + } + } +} + +func CostModelBuild(tls *libc.TLS, m uintptr, xsize int32, cache_bits int32, refs uintptr) int32 { /* backward_references_cost_enc.c:61:12: */ + bp := tls.Alloc(24) + defer tls.Free(24) + + var ok int32 + // var c VP8LRefsCursor at bp, 24 + + var histo uintptr + ok = 0 + *(*VP8LRefsCursor)(unsafe.Pointer(bp /* c */)) = VP8LRefsCursorInit(tls, refs) + histo = VP8LAllocateHistogram(tls, cache_bits) + if !(histo == (uintptr(0))) { + goto __1 + } + goto Error +__1: + ; + + // The following code is similar to VP8LHistogramCreate but converts the + // distance to plane code. + VP8LHistogramInit(tls, histo, cache_bits /*init_arrays=*/, 1) +__2: + if !(VP8LRefsCursorOk(tls, (bp) /* &c */) != 0) { + goto __3 + } + VP8LHistogramAddSinglePixOrCopy(tls, histo, (*VP8LRefsCursor)(unsafe.Pointer(bp /* &c */)).cur_pos, *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, int32, int32) int32 + }{VP8LDistanceToPlaneCode})), + xsize) + VP8LRefsCursorNext(tls, (bp) /* &c */) + goto __2 +__3: + ; + + ConvertPopulationCountTableToBitEstimates(tls, + VP8LHistogramNumCodes(tls, (*VP8LHistogram)(unsafe.Pointer(histo)).palette_code_bits_), + (*VP8LHistogram)(unsafe.Pointer(histo)).literal_, (*CostModel)(unsafe.Pointer(m)).literal_) + ConvertPopulationCountTableToBitEstimates(tls, + 256, (histo + 8 /* &.red_ */), (m + 2048 /* &.red_ */)) + ConvertPopulationCountTableToBitEstimates(tls, + 256, (histo + 1032 /* &.blue_ */), (m + 4096 /* &.blue_ */)) + ConvertPopulationCountTableToBitEstimates(tls, + 256, (histo + 2056 /* &.alpha_ */), (m /* &.alpha_ */)) + ConvertPopulationCountTableToBitEstimates(tls, + 40, (histo + 3080 /* &.distance_ */), (m + 6144 /* &.distance_ */)) + ok = 1 + +Error: + VP8LFreeHistogram(tls, histo) + return ok +} + +func GetLiteralCost(tls *libc.TLS, m uintptr, v uint32_t) float64 { /* backward_references_cost_enc.c:95:27: */ + return (((*(*float64)(unsafe.Pointer((m /* &.alpha_ */) + uintptr((v>>24))*8)) + *(*float64)(unsafe.Pointer((m + 2048 /* &.red_ */) + uintptr(((v>>16)&uint32_t(0xff)))*8))) + *(*float64)(unsafe.Pointer((*CostModel)(unsafe.Pointer(m)).literal_ + uintptr(((v>>8)&uint32_t(0xff)))*8))) + *(*float64)(unsafe.Pointer((m + 4096 /* &.blue_ */) + uintptr((v&uint32_t(0xff)))*8))) +} + +func GetCacheCost(tls *libc.TLS, m uintptr, idx uint32_t) float64 { /* backward_references_cost_enc.c:102:27: */ + var literal_idx int32 = (int32((uint32_t(256 + 24)) + idx)) + return *(*float64)(unsafe.Pointer((*CostModel)(unsafe.Pointer(m)).literal_ + uintptr(literal_idx)*8)) +} + +func GetLengthCost(tls *libc.TLS, m uintptr, length uint32_t) float64 { /* backward_references_cost_enc.c:107:27: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + // var code int32 at bp, 4 + + // var extra_bits int32 at bp+4, 4 + + VP8LPrefixEncodeBits(tls, int32(length), (bp) /* &code */, (bp + 4) /* &extra_bits */) + return (*(*float64)(unsafe.Pointer((*CostModel)(unsafe.Pointer(m)).literal_ + uintptr((256+*(*int32)(unsafe.Pointer(bp /* code */))))*8)) + float64(*(*int32)(unsafe.Pointer(bp + 4 /* extra_bits */)))) +} + +func GetDistanceCost(tls *libc.TLS, m uintptr, distance uint32_t) float64 { /* backward_references_cost_enc.c:114:27: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + // var code int32 at bp, 4 + + // var extra_bits int32 at bp+4, 4 + + VP8LPrefixEncodeBits(tls, int32(distance), (bp) /* &code */, (bp + 4) /* &extra_bits */) + return (*(*float64)(unsafe.Pointer((m + 6144 /* &.distance_ */) + uintptr(*(*int32)(unsafe.Pointer(bp /* code */)))*8)) + float64(*(*int32)(unsafe.Pointer(bp + 4 /* extra_bits */)))) +} + +func AddSingleLiteralWithCostModel(tls *libc.TLS, argb uintptr, hashers uintptr, cost_model uintptr, idx int32, use_color_cache int32, prev_cost float32, cost uintptr, dist_array uintptr) { /* backward_references_cost_enc.c:121:25: */ + var cost_val float64 = float64(prev_cost) + var color uint32_t = *(*uint32_t)(unsafe.Pointer(argb + uintptr(idx)*4)) + var ix int32 + if use_color_cache != 0 { + ix = VP8LColorCacheContains(tls, hashers, color) + } else { + ix = -1 + } + if ix >= 0 { + // use_color_cache is true and hashers contains color + var mul0 float64 = 0.68 + cost_val = cost_val + (GetCacheCost(tls, cost_model, uint32(ix)) * mul0) + } else { + var mul1 float64 = 0.82 + if use_color_cache != 0 { + VP8LColorCacheInsert(tls, hashers, color) + } + cost_val = cost_val + (GetLiteralCost(tls, cost_model, color) * mul1) + } + if float64(*(*float32)(unsafe.Pointer(cost + uintptr(idx)*4))) > cost_val { + *(*float32)(unsafe.Pointer(cost + uintptr(idx)*4)) = float32(cost_val) + *(*uint16_t)(unsafe.Pointer(dist_array + uintptr(idx)*2)) = uint16_t(1) // only one is inserted. + } +} + +// ----------------------------------------------------------------------------- +// CostManager and interval handling + +// Empirical value to avoid high memory consumption but good for performance. + +// To perform backward reference every pixel at index index_ is considered and +// the cost for the MAX_LENGTH following pixels computed. Those following pixels +// at index index_ + k (k from 0 to MAX_LENGTH) have a cost of: +// cost_ = distance cost at index + GetLengthCost(cost_model, k) +// and the minimum value is kept. GetLengthCost(cost_model, k) is cached in an +// array of size MAX_LENGTH. +// Instead of performing MAX_LENGTH comparisons per pixel, we keep track of the +// minimal values using intervals of constant cost. +// An interval is defined by the index_ of the pixel that generated it and +// is only useful in a range of indices from start_ to end_ (exclusive), i.e. +// it contains the minimum value for pixels between start_ and end_. +// Intervals are stored in a linked list and ordered by start_. When a new +// interval has a better value, old intervals are split or removed. There are +// therefore no overlapping intervals. +type CostInterval1 = struct { + cost_ float32 + start_ int32 + end_ int32 + index_ int32 + previous_ uintptr + next_ uintptr +} /* backward_references_cost_enc.c:163:9 */ + +// ----------------------------------------------------------------------------- +// CostManager and interval handling + +// Empirical value to avoid high memory consumption but good for performance. + +// To perform backward reference every pixel at index index_ is considered and +// the cost for the MAX_LENGTH following pixels computed. Those following pixels +// at index index_ + k (k from 0 to MAX_LENGTH) have a cost of: +// cost_ = distance cost at index + GetLengthCost(cost_model, k) +// and the minimum value is kept. GetLengthCost(cost_model, k) is cached in an +// array of size MAX_LENGTH. +// Instead of performing MAX_LENGTH comparisons per pixel, we keep track of the +// minimal values using intervals of constant cost. +// An interval is defined by the index_ of the pixel that generated it and +// is only useful in a range of indices from start_ to end_ (exclusive), i.e. +// it contains the minimum value for pixels between start_ and end_. +// Intervals are stored in a linked list and ordered by start_. When a new +// interval has a better value, old intervals are split or removed. There are +// therefore no overlapping intervals. +type CostInterval = CostInterval1 /* backward_references_cost_enc.c:163:29 */ + +// The GetLengthCost(cost_model, k) are cached in a CostCacheInterval. +type CostCacheInterval = struct { + cost_ float64 + start_ int32 + end_ int32 +} /* backward_references_cost_enc.c:178:3 */ + +// This structure is in charge of managing intervals and costs. +// It caches the different CostCacheInterval, caches the different +// GetLengthCost(cost_model, k) in cost_cache_ and the CostInterval's (whose +// count_ is limited by COST_CACHE_INTERVAL_SIZE_MAX). +type CostManager = struct { + head_ uintptr + count_ int32 + _ [4]byte + cache_intervals_ uintptr + cache_intervals_size_ size_t + cost_cache_ [4095]float64 + costs_ uintptr + dist_array_ uintptr + intervals_ [10]CostInterval + free_intervals_ uintptr + recycled_intervals_ uintptr +} /* backward_references_cost_enc.c:200:3 */ + +func CostIntervalAddToFreeList(tls *libc.TLS, manager uintptr, interval uintptr) { /* backward_references_cost_enc.c:202:13: */ + (*CostInterval)(unsafe.Pointer(interval)).next_ = (*CostManager)(unsafe.Pointer(manager)).free_intervals_ + (*CostManager)(unsafe.Pointer(manager)).free_intervals_ = interval +} + +func CostIntervalIsInFreeList(tls *libc.TLS, manager uintptr, interval uintptr) int32 { /* backward_references_cost_enc.c:208:12: */ + return (libc.Bool32((interval >= (manager + 32808 /* &.intervals_ */)) && (interval <= ((manager + 32808 /* &.intervals_ */) + 9*32)))) +} + +func CostManagerInitFreeList(tls *libc.TLS, manager uintptr) { /* backward_references_cost_enc.c:214:13: */ + var i int32 + (*CostManager)(unsafe.Pointer(manager)).free_intervals_ = (uintptr(0)) + for i = 0; i < 10; i++ { + CostIntervalAddToFreeList(tls, manager, ((manager + 32808 /* &.intervals_ */) + uintptr(i)*32)) + } +} + +func DeleteIntervalList(tls *libc.TLS, manager uintptr, interval uintptr) { /* backward_references_cost_enc.c:222:13: */ + for interval != (uintptr(0)) { + var next uintptr = (*CostInterval)(unsafe.Pointer(interval)).next_ + if !(CostIntervalIsInFreeList(tls, manager, interval) != 0) { + WebPSafeFree(tls, interval) + } // else: do nothing + interval = next + } +} + +func CostManagerClear(tls *libc.TLS, manager uintptr) { /* backward_references_cost_enc.c:233:13: */ + if manager == (uintptr(0)) { + return + } + + WebPSafeFree(tls, (*CostManager)(unsafe.Pointer(manager)).costs_) + WebPSafeFree(tls, (*CostManager)(unsafe.Pointer(manager)).cache_intervals_) + + // Clear the interval lists. + DeleteIntervalList(tls, manager, (*CostManager)(unsafe.Pointer(manager)).head_) + (*CostManager)(unsafe.Pointer(manager)).head_ = (uintptr(0)) + DeleteIntervalList(tls, manager, (*CostManager)(unsafe.Pointer(manager)).recycled_intervals_) + (*CostManager)(unsafe.Pointer(manager)).recycled_intervals_ = (uintptr(0)) + + // Reset pointers, count_ and cache_intervals_size_. + libc.Xmemset(tls, manager, 0, uint64(unsafe.Sizeof(CostManager{}))) + CostManagerInitFreeList(tls, manager) +} + +func CostManagerInit(tls *libc.TLS, manager uintptr, dist_array uintptr, pix_count int32, cost_model uintptr) int32 { /* backward_references_cost_enc.c:250:12: */ + var i int32 + var cost_cache_size int32 + if pix_count > ((int32(1) << 12) - 1) { + cost_cache_size = ((int32(1) << 12) - 1) + } else { + cost_cache_size = pix_count + } + + (*CostManager)(unsafe.Pointer(manager)).costs_ = (uintptr(0)) + (*CostManager)(unsafe.Pointer(manager)).cache_intervals_ = (uintptr(0)) + (*CostManager)(unsafe.Pointer(manager)).head_ = (uintptr(0)) + (*CostManager)(unsafe.Pointer(manager)).recycled_intervals_ = (uintptr(0)) + (*CostManager)(unsafe.Pointer(manager)).count_ = 0 + (*CostManager)(unsafe.Pointer(manager)).dist_array_ = dist_array + CostManagerInitFreeList(tls, manager) + + // Fill in the cost_cache_. + (*CostManager)(unsafe.Pointer(manager)).cache_intervals_size_ = uint64(1) + *(*float64)(unsafe.Pointer((manager + 32 /* &.cost_cache_ */))) = GetLengthCost(tls, cost_model, uint32(0)) + for i = 1; i < cost_cache_size; i++ { + *(*float64)(unsafe.Pointer((manager + 32 /* &.cost_cache_ */) + uintptr(i)*8)) = GetLengthCost(tls, cost_model, uint32(i)) + // Get the number of bound intervals. + if *(*float64)(unsafe.Pointer((manager + 32 /* &.cost_cache_ */) + uintptr(i)*8)) != *(*float64)(unsafe.Pointer((manager + 32 /* &.cost_cache_ */) + uintptr((i-1))*8)) { + (*CostManager)(unsafe.Pointer(manager)).cache_intervals_size_++ + } + } + + // With the current cost model, we usually have below 20 intervals. + // The worst case scenario with a cost model would be if every length has a + // different cost, hence MAX_LENGTH but that is impossible with the current + // implementation that spirals around a pixel. + + (*CostManager)(unsafe.Pointer(manager)).cache_intervals_ = WebPSafeMalloc(tls, + (*CostManager)(unsafe.Pointer(manager)).cache_intervals_size_, uint64(unsafe.Sizeof(CostCacheInterval{}))) + if (*CostManager)(unsafe.Pointer(manager)).cache_intervals_ == (uintptr(0)) { + CostManagerClear(tls, manager) + return 0 + } + + // Fill in the cache_intervals_. + { + var cur uintptr = (*CostManager)(unsafe.Pointer(manager)).cache_intervals_ + + // Consecutive values in cost_cache_ are compared and if a big enough + // difference is found, a new interval is created and bounded. + (*CostCacheInterval)(unsafe.Pointer(cur)).start_ = 0 + (*CostCacheInterval)(unsafe.Pointer(cur)).end_ = 1 + (*CostCacheInterval)(unsafe.Pointer(cur)).cost_ = *(*float64)(unsafe.Pointer((manager + 32 /* &.cost_cache_ */))) + for i = 1; i < cost_cache_size; i++ { + var cost_val float64 = *(*float64)(unsafe.Pointer((manager + 32 /* &.cost_cache_ */) + uintptr(i)*8)) + if cost_val != (*CostCacheInterval)(unsafe.Pointer(cur)).cost_ { + cur += 16 + // Initialize an interval. + (*CostCacheInterval)(unsafe.Pointer(cur)).start_ = i + (*CostCacheInterval)(unsafe.Pointer(cur)).cost_ = cost_val + } + (*CostCacheInterval)(unsafe.Pointer(cur)).end_ = (i + 1) + } + + } + + (*CostManager)(unsafe.Pointer(manager)).costs_ = WebPSafeMalloc(tls, uint64(pix_count), uint64(unsafe.Sizeof(float32(0)))) + if (*CostManager)(unsafe.Pointer(manager)).costs_ == (uintptr(0)) { + CostManagerClear(tls, manager) + return 0 + } + // Set the initial costs_ high for every pixel as we will keep the minimum. + for i = 0; i < pix_count; i++ { + *(*float32)(unsafe.Pointer((*CostManager)(unsafe.Pointer(manager)).costs_ + uintptr(i)*4)) = 1e38 + } + + return 1 +} + +// Given the cost and the position that define an interval, update the cost at +// pixel 'i' if it is smaller than the previously computed value. +func UpdateCost(tls *libc.TLS, manager uintptr, i int32, position int32, cost float32) { /* backward_references_cost_enc.c:321:25: */ + var k int32 = (i - position) + + if *(*float32)(unsafe.Pointer((*CostManager)(unsafe.Pointer(manager)).costs_ + uintptr(i)*4)) > cost { + *(*float32)(unsafe.Pointer((*CostManager)(unsafe.Pointer(manager)).costs_ + uintptr(i)*4)) = cost + *(*uint16_t)(unsafe.Pointer((*CostManager)(unsafe.Pointer(manager)).dist_array_ + uintptr(i)*2)) = (uint16_t(k + 1)) + } +} + +// Given the cost and the position that define an interval, update the cost for +// all the pixels between 'start' and 'end' excluded. +func UpdateCostPerInterval(tls *libc.TLS, manager uintptr, start int32, end int32, position int32, cost float32) { /* backward_references_cost_enc.c:334:25: */ + var i int32 + for i = start; i < end; i++ { + UpdateCost(tls, manager, i, position, cost) + } +} + +// Given two intervals, make 'prev' be the previous one of 'next' in 'manager'. +func ConnectIntervals(tls *libc.TLS, manager uintptr, prev uintptr, next uintptr) { /* backward_references_cost_enc.c:342:25: */ + if prev != (uintptr(0)) { + (*CostInterval)(unsafe.Pointer(prev)).next_ = next + } else { + (*CostManager)(unsafe.Pointer(manager)).head_ = next + } + + if next != (uintptr(0)) { + (*CostInterval)(unsafe.Pointer(next)).previous_ = prev + } +} + +// Pop an interval in the manager. +func PopInterval(tls *libc.TLS, manager uintptr, interval uintptr) { /* backward_references_cost_enc.c:355:25: */ + if interval == (uintptr(0)) { + return + } + + ConnectIntervals(tls, manager, (*CostInterval)(unsafe.Pointer(interval)).previous_, (*CostInterval)(unsafe.Pointer(interval)).next_) + if CostIntervalIsInFreeList(tls, manager, interval) != 0 { + CostIntervalAddToFreeList(tls, manager, interval) + } else { // recycle regularly malloc'd intervals too + (*CostInterval)(unsafe.Pointer(interval)).next_ = (*CostManager)(unsafe.Pointer(manager)).recycled_intervals_ + (*CostManager)(unsafe.Pointer(manager)).recycled_intervals_ = interval + } + (*CostManager)(unsafe.Pointer(manager)).count_-- + +} + +// Update the cost at index i by going over all the stored intervals that +// overlap with i. +// If 'do_clean_intervals' is set to something different than 0, intervals that +// end before 'i' will be popped. +func UpdateCostAtIndex(tls *libc.TLS, manager uintptr, i int32, do_clean_intervals int32) { /* backward_references_cost_enc.c:374:25: */ + var current uintptr = (*CostManager)(unsafe.Pointer(manager)).head_ + + for (current != (uintptr(0))) && ((*CostInterval)(unsafe.Pointer(current)).start_ <= i) { + var next uintptr = (*CostInterval)(unsafe.Pointer(current)).next_ + if (*CostInterval)(unsafe.Pointer(current)).end_ <= i { + if do_clean_intervals != 0 { + // We have an outdated interval, remove it. + PopInterval(tls, manager, current) + } + } else { + UpdateCost(tls, manager, i, (*CostInterval)(unsafe.Pointer(current)).index_, (*CostInterval)(unsafe.Pointer(current)).cost_) + } + current = next + } +} + +// Given a current orphan interval and its previous interval, before +// it was orphaned (which can be NULL), set it at the right place in the list +// of intervals using the start_ ordering and the previous interval as a hint. +func PositionOrphanInterval(tls *libc.TLS, manager uintptr, current uintptr, previous uintptr) { /* backward_references_cost_enc.c:395:25: */ + + if previous == (uintptr(0)) { + previous = (*CostManager)(unsafe.Pointer(manager)).head_ + } + for (previous != (uintptr(0))) && ((*CostInterval)(unsafe.Pointer(current)).start_ < (*CostInterval)(unsafe.Pointer(previous)).start_) { + previous = (*CostInterval)(unsafe.Pointer(previous)).previous_ + } + for ((previous != (uintptr(0))) && ((*CostInterval)(unsafe.Pointer(previous)).next_ != (uintptr(0)))) && ((*CostInterval)(unsafe.Pointer((*CostInterval)(unsafe.Pointer(previous)).next_)).start_ < (*CostInterval)(unsafe.Pointer(current)).start_) { + previous = (*CostInterval)(unsafe.Pointer(previous)).next_ + } + + if previous != (uintptr(0)) { + ConnectIntervals(tls, manager, current, (*CostInterval)(unsafe.Pointer(previous)).next_) + } else { + ConnectIntervals(tls, manager, current, (*CostManager)(unsafe.Pointer(manager)).head_) + } + ConnectIntervals(tls, manager, previous, current) +} + +// Insert an interval in the list contained in the manager by starting at +// interval_in as a hint. The intervals are sorted by start_ value. +func InsertInterval(tls *libc.TLS, manager uintptr, interval_in uintptr, cost float32, position int32, start int32, end int32) { /* backward_references_cost_enc.c:419:25: */ + var interval_new uintptr + + if start >= end { + return + } + if (*CostManager)(unsafe.Pointer(manager)).count_ >= 500 { + // Serialize the interval if we cannot store it. + UpdateCostPerInterval(tls, manager, start, end, position, cost) + return + } + if (*CostManager)(unsafe.Pointer(manager)).free_intervals_ != (uintptr(0)) { + interval_new = (*CostManager)(unsafe.Pointer(manager)).free_intervals_ + (*CostManager)(unsafe.Pointer(manager)).free_intervals_ = (*CostInterval)(unsafe.Pointer(interval_new)).next_ + } else if (*CostManager)(unsafe.Pointer(manager)).recycled_intervals_ != (uintptr(0)) { + interval_new = (*CostManager)(unsafe.Pointer(manager)).recycled_intervals_ + (*CostManager)(unsafe.Pointer(manager)).recycled_intervals_ = (*CostInterval)(unsafe.Pointer(interval_new)).next_ + } else { // malloc for good + interval_new = WebPSafeMalloc(tls, uint64(1), uint64(unsafe.Sizeof(CostInterval{}))) + if interval_new == (uintptr(0)) { + // Write down the interval if we cannot create it. + UpdateCostPerInterval(tls, manager, start, end, position, cost) + return + } + } + + (*CostInterval)(unsafe.Pointer(interval_new)).cost_ = cost + (*CostInterval)(unsafe.Pointer(interval_new)).index_ = position + (*CostInterval)(unsafe.Pointer(interval_new)).start_ = start + (*CostInterval)(unsafe.Pointer(interval_new)).end_ = end + PositionOrphanInterval(tls, manager, interval_new, interval_in) + + (*CostManager)(unsafe.Pointer(manager)).count_++ +} + +// Given a new cost interval defined by its start at position, its length value +// and distance_cost, add its contributions to the previous intervals and costs. +// If handling the interval or one of its subintervals becomes to heavy, its +// contribution is added to the costs right away. +func PushInterval(tls *libc.TLS, manager uintptr, distance_cost float64, position int32, len int32) { /* backward_references_cost_enc.c:459:25: */ + var i size_t + var interval uintptr = (*CostManager)(unsafe.Pointer(manager)).head_ + var interval_next uintptr + var cost_cache_intervals uintptr = (*CostManager)(unsafe.Pointer(manager)).cache_intervals_ + // If the interval is small enough, no need to deal with the heavy + // interval logic, just serialize it right away. This constant is empirical. + var kSkipDistance int32 = 10 + + if len < kSkipDistance { + var j int32 + for j = position; j < (position + len); j++ { + var k int32 = (j - position) + var cost_tmp float32 + + cost_tmp = (float32(distance_cost + *(*float64)(unsafe.Pointer((manager + 32 /* &.cost_cache_ */) + uintptr(k)*8)))) + + if *(*float32)(unsafe.Pointer((*CostManager)(unsafe.Pointer(manager)).costs_ + uintptr(j)*4)) > cost_tmp { + *(*float32)(unsafe.Pointer((*CostManager)(unsafe.Pointer(manager)).costs_ + uintptr(j)*4)) = cost_tmp + *(*uint16_t)(unsafe.Pointer((*CostManager)(unsafe.Pointer(manager)).dist_array_ + uintptr(j)*2)) = (uint16_t(k + 1)) + } + } + return + } + + for i = uint64(0); (i < (*CostManager)(unsafe.Pointer(manager)).cache_intervals_size_) && ((*CostCacheInterval)(unsafe.Pointer(cost_cache_intervals+uintptr(i)*16)).start_ < len); i++ { + // Define the intersection of the ith interval with the new one. + var start int32 = (position + (*CostCacheInterval)(unsafe.Pointer(cost_cache_intervals+uintptr(i)*16)).start_) + var end int32 = (position + (func() int32 { + if (*CostCacheInterval)(unsafe.Pointer(cost_cache_intervals+uintptr(i)*16)).end_ > len { + return len + } + return (*CostCacheInterval)(unsafe.Pointer(cost_cache_intervals + uintptr(i)*16)).end_ + }())) + var cost float32 = (float32(distance_cost + (*CostCacheInterval)(unsafe.Pointer(cost_cache_intervals+uintptr(i)*16)).cost_)) + + for ; (interval != (uintptr(0))) && ((*CostInterval)(unsafe.Pointer(interval)).start_ < end); interval = interval_next { + interval_next = (*CostInterval)(unsafe.Pointer(interval)).next_ + + // Make sure we have some overlap + if start >= (*CostInterval)(unsafe.Pointer(interval)).end_ { + continue + } + + if cost >= (*CostInterval)(unsafe.Pointer(interval)).cost_ { + // When intervals are represented, the lower, the better. + // [**********************************************************[ + // start end + // [----------------------------------[ + // interval->start_ interval->end_ + // If we are worse than what we already have, add whatever we have so + // far up to interval. + var start_new int32 = (*CostInterval)(unsafe.Pointer(interval)).end_ + InsertInterval(tls, manager, interval, cost, position, start, + (*CostInterval)(unsafe.Pointer(interval)).start_) + start = start_new + if start >= end { + break + } + continue + } + + if start <= (*CostInterval)(unsafe.Pointer(interval)).start_ { + if (*CostInterval)(unsafe.Pointer(interval)).end_ <= end { + // [----------------------------------[ + // interval->start_ interval->end_ + // [**************************************************************[ + // start end + // We can safely remove the old interval as it is fully included. + PopInterval(tls, manager, interval) + } else { + // [------------------------------------[ + // interval->start_ interval->end_ + // [*****************************[ + // start end + (*CostInterval)(unsafe.Pointer(interval)).start_ = end + break + } + } else { + if end < (*CostInterval)(unsafe.Pointer(interval)).end_ { + // [--------------------------------------------------------------[ + // interval->start_ interval->end_ + // [*****************************[ + // start end + // We have to split the old interval as it fully contains the new one. + var end_original int32 = (*CostInterval)(unsafe.Pointer(interval)).end_ + (*CostInterval)(unsafe.Pointer(interval)).end_ = start + InsertInterval(tls, manager, interval, (*CostInterval)(unsafe.Pointer(interval)).cost_, (*CostInterval)(unsafe.Pointer(interval)).index_, + end, end_original) + interval = (*CostInterval)(unsafe.Pointer(interval)).next_ + break + } else { + // [------------------------------------[ + // interval->start_ interval->end_ + // [*****************************[ + // start end + (*CostInterval)(unsafe.Pointer(interval)).end_ = start + } + } + } + // Insert the remaining interval from start to end. + InsertInterval(tls, manager, interval, cost, position, start, end) + } +} + +func BackwardReferencesHashChainDistanceOnly(tls *libc.TLS, xsize int32, ysize int32, argb uintptr, cache_bits int32, hash_chain uintptr, refs uintptr, dist_array uintptr) int32 { /* backward_references_cost_enc.c:563:12: */ + bp := tls.Alloc(32) + defer tls.Free(32) + + var i int32 + var ok int32 + var cc_init int32 + var pix_count int32 + var use_color_cache int32 + var literal_array_size size_t + var cost_model_size size_t + var cost_model uintptr + // var hashers VP8LColorCache at bp, 16 + + var cost_manager uintptr + var offset_prev int32 + var len_prev int32 + var offset_cost float64 + var first_offset_is_constant int32 // initialized with 'impossible' value + var reach int32 + var code int32 + // We can only be go further with the same offset if the previous + // length was maxed, hence len_prev == len == MAX_LENGTH. + // TODO(vrabaud), bump i to the end right away (insert cache and + // update cost). + // TODO(vrabaud), check if one of the points in between does not have + // a lower cost. + // Already consider the pixel at "reach" to add intervals that are + // better than whatever we add. + // var offset_j int32 at bp+24, 4 + + // var len_j int32 at bp+28, 4 + + var j int32 + var prev_cost float32 + // var offset int32 at bp+16, 4 + + // var len int32 at bp+20, 4 + ok = 0 + cc_init = 0 + pix_count = (xsize * ysize) + use_color_cache = (libc.Bool32(cache_bits > 0)) + literal_array_size = + (uint64(unsafe.Sizeof(float64(0))) * (uint64((256 + 24) + (func() int32 { + if cache_bits > 0 { + return (int32(1) << cache_bits) + } + return 0 + }())))) + cost_model_size = (uint64(unsafe.Sizeof(CostModel{})) + literal_array_size) + cost_model = + WebPSafeCalloc(tls, 1, cost_model_size) + cost_manager = + WebPSafeMalloc(tls, 1, uint64(unsafe.Sizeof(CostManager{}))) + offset_prev = -1 + len_prev = -1 + offset_cost = float64(-1) + first_offset_is_constant = -1 + reach = 0 + + if !((cost_model == (uintptr(0))) || (cost_manager == (uintptr(0)))) { + goto __1 + } + goto Error +__1: + ; + + (*CostModel)(unsafe.Pointer(cost_model)).literal_ = (cost_model + uintptr(1)*6472) + if !(use_color_cache != 0) { + goto __2 + } + cc_init = VP8LColorCacheInit(tls, (bp) /* &hashers */, cache_bits) + if !(!(cc_init != 0)) { + goto __3 + } + goto Error +__3: + ; +__2: + ; + + if !(!(CostModelBuild(tls, cost_model, xsize, cache_bits, refs) != 0)) { + goto __4 + } + goto Error +__4: + ; + + if !(!(CostManagerInit(tls, cost_manager, dist_array, pix_count, cost_model) != 0)) { + goto __5 + } + goto Error +__5: + ; + + // We loop one pixel at a time, but store all currently best points to + // non-processed locations from this point. + *(*uint16_t)(unsafe.Pointer(dist_array)) = uint16_t(0) + // Add first pixel as literal. + AddSingleLiteralWithCostModel(tls, argb, (bp) /* &hashers */, cost_model, 0, use_color_cache, + 0., (*CostManager)(unsafe.Pointer(cost_manager)).costs_, dist_array) + + i = 1 +__6: + if !(i < pix_count) { + goto __8 + } + prev_cost = *(*float32)(unsafe.Pointer((*CostManager)(unsafe.Pointer(cost_manager)).costs_ + uintptr((i-1))*4)) + VP8LHashChainFindCopy(tls, hash_chain, i, (bp + 16) /* &offset */, (bp + 20) /* &len */) + + // Try adding the pixel as a literal. + AddSingleLiteralWithCostModel(tls, argb, (bp) /* &hashers */, cost_model, i, + use_color_cache, prev_cost, + (*CostManager)(unsafe.Pointer(cost_manager)).costs_, dist_array) + + // If we are dealing with a non-literal. + if !(*(*int32)(unsafe.Pointer(bp + 20 /* len */)) >= 2) { + goto __9 + } + if !(*(*int32)(unsafe.Pointer(bp + 16 /* offset */)) != offset_prev) { + goto __10 + } + code = VP8LDistanceToPlaneCode(tls, xsize, *(*int32)(unsafe.Pointer(bp + 16 /* offset */))) + offset_cost = GetDistanceCost(tls, cost_model, uint32(code)) + first_offset_is_constant = 1 + PushInterval(tls, cost_manager, (float64(prev_cost) + offset_cost), i, *(*int32)(unsafe.Pointer(bp + 20 /* len */))) + goto __11 +__10: + ; + + // Instead of considering all contributions from a pixel i by calling: + // PushInterval(cost_manager, prev_cost + offset_cost, i, len); + // we optimize these contributions in case offset_cost stays the same + // for consecutive pixels. This describes a set of pixels similar to a + // previous set (e.g. constant color regions). + if !(first_offset_is_constant != 0) { + goto __12 + } + reach = (((i - 1) + len_prev) - 1) + first_offset_is_constant = 0 +__12: + ; + + if !(((i + *(*int32)(unsafe.Pointer(bp + 20 /* len */))) - 1) > reach) { + goto __13 + } + *(*int32)(unsafe.Pointer(bp + 28 /* len_j */)) = 0 + + // Figure out the last consecutive pixel within [i, reach + 1] with + // the same offset. + j = i +__14: + if !(j <= reach) { + goto __16 + } + VP8LHashChainFindCopy(tls, hash_chain, (j + 1), (bp + 24) /* &offset_j */, (bp + 28) /* &len_j */) + if !(*(*int32)(unsafe.Pointer(bp + 24 /* offset_j */)) != *(*int32)(unsafe.Pointer(bp + 16 /* offset */))) { + goto __17 + } + VP8LHashChainFindCopy(tls, hash_chain, j, (bp + 24) /* &offset_j */, (bp + 28) /* &len_j */) + goto __16 +__17: + ; + goto __15 +__15: + j++ + goto __14 + goto __16 +__16: + ; + // Update the cost at j - 1 and j. + UpdateCostAtIndex(tls, cost_manager, (j - 1), 0) + UpdateCostAtIndex(tls, cost_manager, j, 0) + + PushInterval(tls, cost_manager, (float64(*(*float32)(unsafe.Pointer((*CostManager)(unsafe.Pointer(cost_manager)).costs_ + uintptr((j-1))*4))) + offset_cost), + j, *(*int32)(unsafe.Pointer(bp + 28 /* len_j */))) + reach = ((j + *(*int32)(unsafe.Pointer(bp + 28 /* len_j */))) - 1) +__13: + ; +__11: + ; +__9: + ; + + UpdateCostAtIndex(tls, cost_manager, i, 1) + offset_prev = *(*int32)(unsafe.Pointer(bp + 16 /* offset */)) + len_prev = *(*int32)(unsafe.Pointer(bp + 20 /* len */)) + goto __7 +__7: + i++ + goto __6 + goto __8 +__8: + ; + + ok = libc.BoolInt32(!((*VP8LBackwardRefs)(unsafe.Pointer(refs)).error_ != 0)) +Error: + if !(cc_init != 0) { + goto __18 + } + VP8LColorCacheClear(tls, (bp) /* &hashers */) +__18: + ; + CostManagerClear(tls, cost_manager) + WebPSafeFree(tls, cost_model) + WebPSafeFree(tls, cost_manager) + return ok +} + +// We pack the path at the end of *dist_array and return +// a pointer to this part of the array. Example: +// dist_array = [1x2xx3x2] => packed [1x2x1232], chosen_path = [1232] +func TraceBackwards(tls *libc.TLS, dist_array uintptr, dist_array_size int32, chosen_path uintptr, chosen_path_size uintptr) { /* backward_references_cost_enc.c:689:13: */ + var path uintptr = (dist_array + uintptr(dist_array_size)*2) + var cur uintptr = ((dist_array + uintptr(dist_array_size)*2) - uintptr(1)*2) + for cur >= dist_array { + var k int32 = int32(*(*uint16_t)(unsafe.Pointer(cur))) + path -= 2 + *(*uint16_t)(unsafe.Pointer(path)) = uint16_t(k) + cur -= 2 * (uintptr(k)) + } + *(*uintptr)(unsafe.Pointer(chosen_path)) = path + *(*int32)(unsafe.Pointer(chosen_path_size)) = (int32(((int64(dist_array + uintptr(dist_array_size)*2)) - int64(path)) / 2)) +} + +func BackwardReferencesHashChainFollowChosenPath(tls *libc.TLS, argb uintptr, cache_bits int32, chosen_path uintptr, chosen_path_size int32, hash_chain uintptr, refs uintptr) int32 { /* backward_references_cost_enc.c:705:12: */ + bp := tls.Alloc(16) + defer tls.Free(16) + + var use_color_cache int32 + var ix int32 + var i int32 + var ok int32 + var cc_init int32 + // var hashers VP8LColorCache at bp, 16 + + var k int32 + var offset int32 + var v PixOrCopy + var idx int32 + var len int32 + use_color_cache = (libc.Bool32(cache_bits > 0)) + i = 0 + ok = 0 + cc_init = 0 + + if !(use_color_cache != 0) { + goto __1 + } + cc_init = VP8LColorCacheInit(tls, (bp) /* &hashers */, cache_bits) + if !(!(cc_init != 0)) { + goto __2 + } + goto Error +__2: + ; +__1: + ; + + VP8LClearBackwardRefs(tls, refs) + ix = 0 +__3: + if !(ix < chosen_path_size) { + goto __5 + } + len = int32(*(*uint16_t)(unsafe.Pointer(chosen_path + uintptr(ix)*2))) + if !(len != 1) { + goto __6 + } + offset = VP8LHashChainFindOffset(tls, hash_chain, i) + VP8LBackwardRefsCursorAdd(tls, refs, PixOrCopyCreateCopy(tls, uint32(offset), uint16(len))) + if !(use_color_cache != 0) { + goto __8 + } + k = 0 +__9: + if !(k < len) { + goto __11 + } + VP8LColorCacheInsert(tls, (bp) /* &hashers */, *(*uint32_t)(unsafe.Pointer(argb + uintptr((i+k))*4))) + goto __10 +__10: + k++ + goto __9 + goto __11 +__11: + ; +__8: + ; + i = i + (len) + goto __7 +__6: + if use_color_cache != 0 { + idx = VP8LColorCacheContains(tls, (bp) /* &hashers */, *(*uint32_t)(unsafe.Pointer(argb + uintptr(i)*4))) + } else { + idx = -1 + } + if !(idx >= 0) { + goto __12 + } + // use_color_cache is true and hashers contains argb[i] + // push pixel as a color cache index + v = PixOrCopyCreateCacheIdx(tls, idx) + goto __13 +__12: + if !(use_color_cache != 0) { + goto __14 + } + VP8LColorCacheInsert(tls, (bp) /* &hashers */, *(*uint32_t)(unsafe.Pointer(argb + uintptr(i)*4))) +__14: + ; + v = PixOrCopyCreateLiteral(tls, *(*uint32_t)(unsafe.Pointer(argb + uintptr(i)*4))) +__13: + ; + VP8LBackwardRefsCursorAdd(tls, refs, v) + i++ +__7: + ; + goto __4 +__4: + ix++ + goto __3 + goto __5 +__5: + ; + ok = libc.BoolInt32(!((*VP8LBackwardRefs)(unsafe.Pointer(refs)).error_ != 0)) +Error: + if !(cc_init != 0) { + goto __15 + } + VP8LColorCacheClear(tls, (bp) /* &hashers */) +__15: + ; + return ok +} + +func VP8LBackwardReferencesTraceBackwards(tls *libc.TLS, xsize int32, ysize int32, argb uintptr, cache_bits int32, hash_chain uintptr, refs_src uintptr, refs_dst uintptr) int32 { /* backward_references_cost_enc.c:761:5: */ + bp := tls.Alloc(12) + defer tls.Free(12) + + var ok int32 + var dist_array_size int32 + // var chosen_path uintptr at bp, 8 + + // var chosen_path_size int32 at bp+8, 4 + + var dist_array uintptr + ok = 0 + dist_array_size = (xsize * ysize) + *(*uintptr)(unsafe.Pointer(bp /* chosen_path */)) = (uintptr(0)) + *(*int32)(unsafe.Pointer(bp + 8 /* chosen_path_size */)) = 0 + dist_array = + WebPSafeMalloc(tls, uint64(dist_array_size), uint64(unsafe.Sizeof(uint16_t(0)))) + + if !(dist_array == (uintptr(0))) { + goto __1 + } + goto Error +__1: + ; + + if !(!(BackwardReferencesHashChainDistanceOnly(tls, + xsize, ysize, argb, cache_bits, hash_chain, refs_src, dist_array) != 0)) { + goto __2 + } + goto Error +__2: + ; + TraceBackwards(tls, dist_array, dist_array_size, (bp) /* &chosen_path */, (bp + 8) /* &chosen_path_size */) + if !(!(BackwardReferencesHashChainFollowChosenPath(tls, + argb, cache_bits, *(*uintptr)(unsafe.Pointer(bp /* chosen_path */)), *(*int32)(unsafe.Pointer(bp + 8 /* chosen_path_size */)), hash_chain, + refs_dst) != 0)) { + goto __3 + } + goto Error +__3: + ; + ok = 1 +Error: + WebPSafeFree(tls, dist_array) + return ok +} + +// ----------------------------------------------------------------------------- +// VP8LBackwardRefs (block-based backward-references storage) + +// maximum number of reference blocks the image will be segmented into + +type PixOrCopyBlock = PixOrCopyBlock1 /* backward_references_enc.h:167:31 */ + +//------------------------------------------------------------------------------ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +// 1M window (4M bytes) minus 120 special codes for short distances. + +// Minimum number of pixels for which it is cheaper to encode a +// distance + length instead of each pixel as a literal. + +// ----------------------------------------------------------------------------- + +var plane_to_code_lut = [128]uint8_t{ + uint8_t(96), uint8_t(73), uint8_t(55), uint8_t(39), uint8_t(23), uint8_t(13), uint8_t(5), uint8_t(1), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), + uint8_t(101), uint8_t(78), uint8_t(58), uint8_t(42), uint8_t(26), uint8_t(16), uint8_t(8), uint8_t(2), uint8_t(0), uint8_t(3), uint8_t(9), uint8_t(17), uint8_t(27), uint8_t(43), uint8_t(59), uint8_t(79), + uint8_t(102), uint8_t(86), uint8_t(62), uint8_t(46), uint8_t(32), uint8_t(20), uint8_t(10), uint8_t(6), uint8_t(4), uint8_t(7), uint8_t(11), uint8_t(21), uint8_t(33), uint8_t(47), uint8_t(63), uint8_t(87), + uint8_t(105), uint8_t(90), uint8_t(70), uint8_t(52), uint8_t(37), uint8_t(28), uint8_t(18), uint8_t(14), uint8_t(12), uint8_t(15), uint8_t(19), uint8_t(29), uint8_t(38), uint8_t(53), uint8_t(71), uint8_t(91), + uint8_t(110), uint8_t(99), uint8_t(82), uint8_t(66), uint8_t(48), uint8_t(35), uint8_t(30), uint8_t(24), uint8_t(22), uint8_t(25), uint8_t(31), uint8_t(36), uint8_t(49), uint8_t(67), uint8_t(83), uint8_t(100), + uint8_t(115), uint8_t(108), uint8_t(94), uint8_t(76), uint8_t(64), uint8_t(50), uint8_t(44), uint8_t(40), uint8_t(34), uint8_t(41), uint8_t(45), uint8_t(51), uint8_t(65), uint8_t(77), uint8_t(95), uint8_t(109), + uint8_t(118), uint8_t(113), uint8_t(103), uint8_t(92), uint8_t(80), uint8_t(68), uint8_t(60), uint8_t(56), uint8_t(54), uint8_t(57), uint8_t(61), uint8_t(69), uint8_t(81), uint8_t(93), uint8_t(104), uint8_t(114), + uint8_t(119), uint8_t(116), uint8_t(111), uint8_t(106), uint8_t(97), uint8_t(88), uint8_t(84), uint8_t(74), uint8_t(72), uint8_t(75), uint8_t(85), uint8_t(89), uint8_t(98), uint8_t(107), uint8_t(112), uint8_t(117), +} /* backward_references_enc.c:38:22 */ + +func VP8LDistanceToPlaneCode(tls *libc.TLS, xsize int32, dist int32) int32 { /* backward_references_enc.c:50:5: */ + var yoffset int32 = (dist / xsize) + var xoffset int32 = (dist - (yoffset * xsize)) + if (xoffset <= 8) && (yoffset < 8) { + return (int32(plane_to_code_lut[(((yoffset*16)+8)-xoffset)]) + 1) + } else if (xoffset > (xsize - 8)) && (yoffset < 7) { + return (int32(plane_to_code_lut[((((yoffset+1)*16)+8)+(xsize-xoffset))]) + 1) + } + return (dist + 120) +} + +// Returns the exact index where array1 and array2 are different. For an index +// inferior or equal to best_len_match, the return value just has to be strictly +// inferior to best_len_match. The current behavior is to return 0 if this index +// is best_len_match, and the index itself otherwise. +// If no two elements are the same, it returns max_limit. +func FindMatchLength(tls *libc.TLS, array1 uintptr, array2 uintptr, best_len_match int32, max_limit int32) int32 { /* backward_references_enc.c:66:24: */ + // Before 'expensive' linear match, check if the two arrays match at the + // current best length index. + if *(*uint32_t)(unsafe.Pointer(array1 + uintptr(best_len_match)*4)) != *(*uint32_t)(unsafe.Pointer(array2 + uintptr(best_len_match)*4)) { + return 0 + } + + return (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8LVectorMismatch})).f(tls, array1, array2, max_limit) +} + +func VP8LClearBackwardRefs(tls *libc.TLS, refs uintptr) { /* backward_references_enc.c:86:6: */ + + if (*VP8LBackwardRefs)(unsafe.Pointer(refs)).tail_ != (uintptr(0)) { + *(*uintptr)(unsafe.Pointer((*VP8LBackwardRefs)(unsafe.Pointer(refs)).tail_)) = (*VP8LBackwardRefs)(unsafe.Pointer(refs)).free_blocks_ // recycle all blocks at once + } + (*VP8LBackwardRefs)(unsafe.Pointer(refs)).free_blocks_ = (*VP8LBackwardRefs)(unsafe.Pointer(refs)).refs_ + (*VP8LBackwardRefs)(unsafe.Pointer(refs)).tail_ = (refs + 8 /* &.refs_ */) + (*VP8LBackwardRefs)(unsafe.Pointer(refs)).last_block_ = (uintptr(0)) + (*VP8LBackwardRefs)(unsafe.Pointer(refs)).refs_ = (uintptr(0)) +} + +func VP8LBackwardRefsClear(tls *libc.TLS, refs uintptr) { /* backward_references_enc.c:97:6: */ + + VP8LClearBackwardRefs(tls, refs) + for (*VP8LBackwardRefs)(unsafe.Pointer(refs)).free_blocks_ != (uintptr(0)) { + var next uintptr = (*PixOrCopyBlock)(unsafe.Pointer((*VP8LBackwardRefs)(unsafe.Pointer(refs)).free_blocks_)).next_ + WebPSafeFree(tls, (*VP8LBackwardRefs)(unsafe.Pointer(refs)).free_blocks_) + (*VP8LBackwardRefs)(unsafe.Pointer(refs)).free_blocks_ = next + } +} + +// Swaps the content of two VP8LBackwardRefs. +func BackwardRefsSwap(tls *libc.TLS, refs1 uintptr, refs2 uintptr) { /* backward_references_enc.c:108:13: */ + var point_to_refs1 int32 = (libc.Bool32(((*VP8LBackwardRefs)(unsafe.Pointer(refs1)).tail_ != (uintptr(0))) && ((*VP8LBackwardRefs)(unsafe.Pointer(refs1)).tail_ == (refs1 + 8 /* &.refs_ */)))) + var point_to_refs2 int32 = (libc.Bool32(((*VP8LBackwardRefs)(unsafe.Pointer(refs2)).tail_ != (uintptr(0))) && ((*VP8LBackwardRefs)(unsafe.Pointer(refs2)).tail_ == (refs2 + 8 /* &.refs_ */)))) + var tmp = *(*VP8LBackwardRefs)(unsafe.Pointer(refs1)) + *(*VP8LBackwardRefs)(unsafe.Pointer(refs1)) = *(*VP8LBackwardRefs)(unsafe.Pointer(refs2)) + *(*VP8LBackwardRefs)(unsafe.Pointer(refs2)) = tmp + if point_to_refs2 != 0 { + (*VP8LBackwardRefs)(unsafe.Pointer(refs1)).tail_ = (refs1 + 8 /* &.refs_ */) + } + if point_to_refs1 != 0 { + (*VP8LBackwardRefs)(unsafe.Pointer(refs2)).tail_ = (refs2 + 8 /* &.refs_ */) + } +} + +func VP8LBackwardRefsInit(tls *libc.TLS, refs uintptr, block_size int32) { /* backward_references_enc.c:121:6: */ + + libc.Xmemset(tls, refs, 0, uint64(unsafe.Sizeof(VP8LBackwardRefs{}))) + (*VP8LBackwardRefs)(unsafe.Pointer(refs)).tail_ = (refs + 8 /* &.refs_ */) + (*VP8LBackwardRefs)(unsafe.Pointer(refs)).block_size_ = func() int32 { + if block_size < 256 { + return 256 + } + return block_size + }() +} + +func VP8LRefsCursorInit(tls *libc.TLS, refs uintptr) VP8LRefsCursor { /* backward_references_enc.c:129:16: */ + var c VP8LRefsCursor + c.cur_block_ = (*VP8LBackwardRefs)(unsafe.Pointer(refs)).refs_ + if (*VP8LBackwardRefs)(unsafe.Pointer(refs)).refs_ != (uintptr(0)) { + c.cur_pos = (*PixOrCopyBlock)(unsafe.Pointer(c.cur_block_)).start_ + c.last_pos_ = (c.cur_pos + uintptr((*PixOrCopyBlock)(unsafe.Pointer(c.cur_block_)).size_)*8) + } else { + c.cur_pos = (uintptr(0)) + c.last_pos_ = (uintptr(0)) + } + return c +} + +func VP8LRefsCursorNextBlock(tls *libc.TLS, c uintptr) { /* backward_references_enc.c:142:6: */ + var b uintptr = (*PixOrCopyBlock)(unsafe.Pointer((*VP8LRefsCursor)(unsafe.Pointer(c)).cur_block_)).next_ + (*VP8LRefsCursor)(unsafe.Pointer(c)).cur_pos = func() uintptr { + if b == (uintptr(0)) { + return (uintptr(0)) + } + return (*PixOrCopyBlock)(unsafe.Pointer(b)).start_ + }() + (*VP8LRefsCursor)(unsafe.Pointer(c)).last_pos_ = func() uintptr { + if b == (uintptr(0)) { + return (uintptr(0)) + } + return ((*PixOrCopyBlock)(unsafe.Pointer(b)).start_ + uintptr((*PixOrCopyBlock)(unsafe.Pointer(b)).size_)*8) + }() + (*VP8LRefsCursor)(unsafe.Pointer(c)).cur_block_ = b +} + +// Create a new block, either from the free list or allocated +func BackwardRefsNewBlock(tls *libc.TLS, refs uintptr) uintptr { /* backward_references_enc.c:150:22: */ + var b uintptr = (*VP8LBackwardRefs)(unsafe.Pointer(refs)).free_blocks_ + if b == (uintptr(0)) { // allocate new memory chunk + var total_size size_t = (uint64(unsafe.Sizeof(PixOrCopyBlock{})) + (uint64((*VP8LBackwardRefs)(unsafe.Pointer(refs)).block_size_) * uint64(unsafe.Sizeof(PixOrCopy{})))) + b = WebPSafeMalloc(tls, 1, total_size) + if b == (uintptr(0)) { + *(*int32)(unsafe.Pointer((refs + 4 /* &.error_ */))) |= (1) + return (uintptr(0)) + } + (*PixOrCopyBlock)(unsafe.Pointer(b)).start_ = (b + uintptr(uint64(unsafe.Sizeof(PixOrCopyBlock{})))) // not always aligned + } else { // recycle from free-list + (*VP8LBackwardRefs)(unsafe.Pointer(refs)).free_blocks_ = (*PixOrCopyBlock)(unsafe.Pointer(b)).next_ + } + *(*uintptr)(unsafe.Pointer((*VP8LBackwardRefs)(unsafe.Pointer(refs)).tail_)) = b + (*VP8LBackwardRefs)(unsafe.Pointer(refs)).tail_ = (b /* &.next_ */) + (*VP8LBackwardRefs)(unsafe.Pointer(refs)).last_block_ = b + (*PixOrCopyBlock)(unsafe.Pointer(b)).next_ = (uintptr(0)) + (*PixOrCopyBlock)(unsafe.Pointer(b)).size_ = 0 + return b +} + +// Return 1 on success, 0 on error. +func BackwardRefsClone(tls *libc.TLS, from uintptr, to uintptr) int32 { /* backward_references_enc.c:173:12: */ + var block_from uintptr = (*VP8LBackwardRefs)(unsafe.Pointer(from)).refs_ + VP8LClearBackwardRefs(tls, to) + for block_from != (uintptr(0)) { + var block_to uintptr = BackwardRefsNewBlock(tls, to) + if block_to == (uintptr(0)) { + return 0 + } + libc.Xmemcpy(tls, (*PixOrCopyBlock)(unsafe.Pointer(block_to)).start_, (*PixOrCopyBlock)(unsafe.Pointer(block_from)).start_, + (uint64((*PixOrCopyBlock)(unsafe.Pointer(block_from)).size_) * uint64(unsafe.Sizeof(PixOrCopy{})))) + (*PixOrCopyBlock)(unsafe.Pointer(block_to)).size_ = (*PixOrCopyBlock)(unsafe.Pointer(block_from)).size_ + block_from = (*PixOrCopyBlock)(unsafe.Pointer(block_from)).next_ + } + return 1 +} + +func VP8LBackwardRefsCursorAdd(tls *libc.TLS, refs uintptr, v PixOrCopy) { /* backward_references_enc.c:190:6: */ + var b uintptr = (*VP8LBackwardRefs)(unsafe.Pointer(refs)).last_block_ + if (b == (uintptr(0))) || ((*PixOrCopyBlock)(unsafe.Pointer(b)).size_ == (*VP8LBackwardRefs)(unsafe.Pointer(refs)).block_size_) { + b = BackwardRefsNewBlock(tls, refs) + if b == (uintptr(0)) { + return + } // refs->error_ is set + } + *(*PixOrCopy)(unsafe.Pointer((*PixOrCopyBlock)(unsafe.Pointer(b)).start_ + uintptr(libc.PostIncInt32(&(*PixOrCopyBlock)(unsafe.Pointer(b)).size_, 1))*8)) = v +} + +// ----------------------------------------------------------------------------- +// Hash chains + +func VP8LHashChainInit(tls *libc.TLS, p uintptr, size int32) int32 { /* backward_references_enc.c:203:5: */ + + (*VP8LHashChain)(unsafe.Pointer(p)).offset_length_ = WebPSafeMalloc(tls, uint64(size), uint64(unsafe.Sizeof(uint32_t(0)))) + if (*VP8LHashChain)(unsafe.Pointer(p)).offset_length_ == (uintptr(0)) { + return 0 + } + (*VP8LHashChain)(unsafe.Pointer(p)).size_ = size + + return 1 +} + +func VP8LHashChainClear(tls *libc.TLS, p uintptr) { /* backward_references_enc.c:215:6: */ + + WebPSafeFree(tls, (*VP8LHashChain)(unsafe.Pointer(p)).offset_length_) + + (*VP8LHashChain)(unsafe.Pointer(p)).size_ = 0 + (*VP8LHashChain)(unsafe.Pointer(p)).offset_length_ = (uintptr(0)) +} + +// ----------------------------------------------------------------------------- + +var kHashMultiplierHi uint32_t = 0xc6a4a793 /* backward_references_enc.c:225:23 */ +var kHashMultiplierLo uint32_t = 0x5bd1e996 /* backward_references_enc.c:226:23 */ + +func GetPixPairHash64(tls *libc.TLS, argb uintptr) uint32_t { /* backward_references_enc.c:229:10: */ + var key uint32_t + key = (*(*uint32_t)(unsafe.Pointer(argb + 1*4)) * kHashMultiplierHi) + key = key + (*(*uint32_t)(unsafe.Pointer(argb)) * kHashMultiplierLo) + key = (key >> (32 - 18)) + return key +} + +// Returns the maximum number of hash chain lookups to do for a +// given compression quality. Return value in range [8, 86]. +func GetMaxItersForQuality(tls *libc.TLS, quality int32) int32 { /* backward_references_enc.c:239:12: */ + return (8 + ((quality * quality) / 128)) +} + +func GetWindowSizeForHashChain(tls *libc.TLS, quality int32, xsize int32) int32 { /* backward_references_enc.c:243:12: */ + var max_window_size int32 + if quality > 75 { + max_window_size = ((int32(1) << 20) - 120) + } else { + if quality > 50 { + max_window_size = (xsize << 8) + } else { + if quality > 25 { + max_window_size = (xsize << 6) + } else { + max_window_size = (xsize << 4) + } + } + } + + if max_window_size > ((int32(1) << 20) - 120) { + return ((int32(1) << 20) - 120) + } + return max_window_size +} + +func MaxFindCopyLength(tls *libc.TLS, len int32) int32 { /* backward_references_enc.c:252:24: */ + if len < ((int32(1) << 12) - 1) { + return len + } + return ((int32(1) << 12) - 1) +} + +func VP8LHashChainFill(tls *libc.TLS, p uintptr, quality int32, argb uintptr, xsize int32, ysize int32, low_effort int32) int32 { /* backward_references_enc.c:256:5: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var size int32 = (xsize * ysize) + var iter_max int32 = GetMaxItersForQuality(tls, quality) + var window_size uint32_t = uint32_t(GetWindowSizeForHashChain(tls, quality, xsize)) + var pos int32 + var argb_comp int32 + var base_position uint32_t + var hash_to_first_index uintptr + // Temporarily use the p->offset_length_ as a hash chain. + var chain uintptr = (*VP8LHashChain)(unsafe.Pointer(p)).offset_length_ + + if size <= 2 { + *(*uint32_t)(unsafe.Pointer((*VP8LHashChain)(unsafe.Pointer(p)).offset_length_)) = libc.AssignPtrUint32(((*VP8LHashChain)(unsafe.Pointer(p)).offset_length_ + uintptr((size-1))*4), uint32_t(0)) + return 1 + } + + hash_to_first_index = WebPSafeMalloc(tls, (uint64(int32(1) << 18)), uint64(unsafe.Sizeof(int32_t(0)))) + if hash_to_first_index == (uintptr(0)) { + return 0 + } + + // Set the int32_t array to -1. + libc.Xmemset(tls, hash_to_first_index, 0xff, ((uint64(int32(1) << 18)) * uint64(unsafe.Sizeof(int32_t(0))))) + // Fill the chain linking pixels with the same hash. + argb_comp = (libc.Bool32(*(*uint32_t)(unsafe.Pointer(argb)) == *(*uint32_t)(unsafe.Pointer(argb + 1*4)))) + for pos = 0; pos < (size - 2); { + var hash_code uint32_t + var argb_comp_next int32 = (libc.Bool32(*(*uint32_t)(unsafe.Pointer(argb + uintptr((pos+1))*4)) == *(*uint32_t)(unsafe.Pointer(argb + uintptr((pos+2))*4)))) + if (argb_comp != 0) && (argb_comp_next != 0) { + // Consecutive pixels with the same color will share the same hash. + // We therefore use a different hash: the color and its repetition + // length. + // var tmp [2]uint32_t at bp, 8 + + var len uint32_t = uint32_t(1) + *(*uint32_t)(unsafe.Pointer((bp) /* &tmp[0] */)) = *(*uint32_t)(unsafe.Pointer(argb + uintptr(pos)*4)) + // Figure out how far the pixels are the same. + // The last pixel has a different 64 bit hash, as its next pixel does + // not have the same color, so we just need to get to the last pixel equal + // to its follower. + for (((pos + int32(len)) + 2) < size) && (*(*uint32_t)(unsafe.Pointer(argb + uintptr(((uint32_t(pos)+len)+uint32_t(2)))*4)) == *(*uint32_t)(unsafe.Pointer(argb + uintptr(pos)*4))) { + len++ + } + if len > (uint32_t((int32(1) << 12) - 1)) { + // Skip the pixels that match for distance=1 and length>MAX_LENGTH + // because they are linked to their predecessor and we automatically + // check that in the main for loop below. Skipping means setting no + // predecessor in the chain, hence -1. + libc.Xmemset(tls, (chain + uintptr(pos)*4), 0xff, ((uint64(len - (uint32_t((int32(1) << 12) - 1)))) * uint64(unsafe.Sizeof(int32_t(0))))) + pos = int32(uint32_t(pos) + (len - (uint32_t((int32(1) << 12) - 1)))) + len = (uint32_t((int32(1) << 12) - 1)) + } + // Process the rest of the hash chain. + for len != 0 { + *(*uint32_t)(unsafe.Pointer((bp) /* &tmp[0] */ + 1*4)) = libc.PostDecUint32(&len, 1) + hash_code = GetPixPairHash64(tls, (bp) /* &tmp[0] */) + *(*int32_t)(unsafe.Pointer(chain + uintptr(pos)*4)) = *(*int32_t)(unsafe.Pointer(hash_to_first_index + uintptr(hash_code)*4)) + *(*int32_t)(unsafe.Pointer(hash_to_first_index + uintptr(hash_code)*4)) = libc.PostIncInt32(&pos, 1) + } + argb_comp = 0 + } else { + // Just move one pixel forward. + hash_code = GetPixPairHash64(tls, (argb + uintptr(pos)*4)) + *(*int32_t)(unsafe.Pointer(chain + uintptr(pos)*4)) = *(*int32_t)(unsafe.Pointer(hash_to_first_index + uintptr(hash_code)*4)) + *(*int32_t)(unsafe.Pointer(hash_to_first_index + uintptr(hash_code)*4)) = libc.PostIncInt32(&pos, 1) + argb_comp = argb_comp_next + } + } + // Process the penultimate pixel. + *(*int32_t)(unsafe.Pointer(chain + uintptr(pos)*4)) = *(*int32_t)(unsafe.Pointer(hash_to_first_index + uintptr(GetPixPairHash64(tls, (argb+uintptr(pos)*4)))*4)) + + WebPSafeFree(tls, hash_to_first_index) + + // Find the best match interval at each pixel, defined by an offset to the + // pixel and a length. The right-most pixel cannot match anything to the right + // (hence a best length of 0) and the left-most pixel nothing to the left + // (hence an offset of 0). + + *(*uint32_t)(unsafe.Pointer((*VP8LHashChain)(unsafe.Pointer(p)).offset_length_)) = libc.AssignPtrUint32(((*VP8LHashChain)(unsafe.Pointer(p)).offset_length_ + uintptr((size-1))*4), uint32_t(0)) + for base_position = (uint32_t(size - 2)); base_position > uint32_t(0); { + var max_len int32 = MaxFindCopyLength(tls, (int32((uint32_t(size - 1)) - base_position))) + var argb_start uintptr = (argb + uintptr(base_position)*4) + var iter int32 = iter_max + var best_length int32 = 0 + var best_distance uint32_t = uint32_t(0) + var best_argb uint32_t + var min_pos int32 + if base_position > window_size { + min_pos = (int32(base_position - window_size)) + } else { + min_pos = 0 + } + var length_max int32 + if max_len < 256 { + length_max = max_len + } else { + length_max = 256 + } + var max_base_position uint32_t + + pos = *(*int32_t)(unsafe.Pointer(chain + uintptr(base_position)*4)) + if !(low_effort != 0) { + var curr_length int32 + // Heuristic: use the comparison with the above line as an initialization. + if base_position >= uint32_t(xsize) { + curr_length = FindMatchLength(tls, (argb_start - uintptr(xsize)*4), argb_start, + best_length, max_len) + if curr_length > best_length { + best_length = curr_length + best_distance = uint32_t(xsize) + } + iter-- + } + // Heuristic: compare to the previous pixel. + curr_length = FindMatchLength(tls, (argb_start - uintptr(1)*4), argb_start, best_length, max_len) + if curr_length > best_length { + best_length = curr_length + best_distance = uint32_t(1) + } + iter-- + // Skip the for loop if we already have the maximum. + if best_length == ((int32(1) << 12) - 1) { + pos = (min_pos - 1) + } + } + best_argb = *(*uint32_t)(unsafe.Pointer(argb_start + uintptr(best_length)*4)) + + for ; (pos >= min_pos) && (libc.PreDecInt32(&iter, 1) != 0); pos = *(*int32_t)(unsafe.Pointer(chain + uintptr(pos)*4)) { + var curr_length int32 + + if *(*uint32_t)(unsafe.Pointer(argb + uintptr((pos+best_length))*4)) != best_argb { + continue + } + + curr_length = (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8LVectorMismatch})).f(tls, (argb + uintptr(pos)*4), argb_start, max_len) + if best_length < curr_length { + best_length = curr_length + best_distance = (base_position - uint32_t(pos)) + best_argb = *(*uint32_t)(unsafe.Pointer(argb_start + uintptr(best_length)*4)) + // Stop if we have reached a good enough length. + if best_length >= length_max { + break + } + } + } + // We have the best match but in case the two intervals continue matching + // to the left, we have the best matches for the left-extended pixels. + max_base_position = base_position + for 1 != 0 { + + *(*uint32_t)(unsafe.Pointer((*VP8LHashChain)(unsafe.Pointer(p)).offset_length_ + uintptr(base_position)*4)) = ((best_distance << 12) | uint32_t(best_length)) + base_position-- + // Stop if we don't have a match or if we are out of bounds. + if (best_distance == uint32_t(0)) || (base_position == uint32_t(0)) { + break + } + // Stop if we cannot extend the matching intervals to the left. + if (base_position < best_distance) || (*(*uint32_t)(unsafe.Pointer(argb + uintptr((base_position-best_distance))*4)) != *(*uint32_t)(unsafe.Pointer(argb + uintptr(base_position)*4))) { + break + } + // Stop if we are matching at its limit because there could be a closer + // matching interval with the same maximum length. Then again, if the + // matching interval is as close as possible (best_distance == 1), we will + // never find anything better so let's continue. + if ((best_length == ((int32(1) << 12) - 1)) && (best_distance != uint32_t(1))) && ((base_position + (uint32_t((int32(1) << 12) - 1))) < max_base_position) { + break + } + if best_length < ((int32(1) << 12) - 1) { + best_length++ + max_base_position = base_position + } + } + } + return 1 +} + +func AddSingleLiteral(tls *libc.TLS, pixel uint32_t, use_color_cache int32, hashers uintptr, refs uintptr) { /* backward_references_enc.c:424:25: */ + var v PixOrCopy + if use_color_cache != 0 { + var key uint32_t = uint32_t(VP8LColorCacheGetIndex(tls, hashers, pixel)) + if VP8LColorCacheLookup(tls, hashers, key) == pixel { + v = PixOrCopyCreateCacheIdx(tls, int32(key)) + } else { + v = PixOrCopyCreateLiteral(tls, pixel) + VP8LColorCacheSet(tls, hashers, key, pixel) + } + } else { + v = PixOrCopyCreateLiteral(tls, pixel) + } + VP8LBackwardRefsCursorAdd(tls, refs, v) +} + +func BackwardReferencesRle(tls *libc.TLS, xsize int32, ysize int32, argb uintptr, cache_bits int32, refs uintptr) int32 { /* backward_references_enc.c:442:12: */ + bp := tls.Alloc(16) + defer tls.Free(16) + + var pix_count int32 = (xsize * ysize) + var i int32 + var k int32 + var use_color_cache int32 = (libc.Bool32(cache_bits > 0)) + // var hashers VP8LColorCache at bp, 16 + + if (use_color_cache != 0) && !(VP8LColorCacheInit(tls, (bp) /* &hashers */, cache_bits) != 0) { + return 0 + } + VP8LClearBackwardRefs(tls, refs) + // Add first pixel as literal. + AddSingleLiteral(tls, *(*uint32_t)(unsafe.Pointer(argb)), use_color_cache, (bp) /* &hashers */, refs) + i = 1 + for i < pix_count { + var max_len int32 = MaxFindCopyLength(tls, (pix_count - i)) + var rle_len int32 = FindMatchLength(tls, (argb + uintptr(i)*4), ((argb + uintptr(i)*4) - uintptr(1)*4), 0, max_len) + var prev_row_len int32 + if i < xsize { + prev_row_len = 0 + } else { + prev_row_len = FindMatchLength(tls, (argb + uintptr(i)*4), ((argb + uintptr(i)*4) - uintptr(xsize)*4), 0, max_len) + } + if (rle_len >= prev_row_len) && (rle_len >= 4) { + VP8LBackwardRefsCursorAdd(tls, refs, PixOrCopyCreateCopy(tls, uint32(1), uint16(rle_len))) + // We don't need to update the color cache here since it is always the + // same pixel being copied, and that does not change the color cache + // state. + i = i + (rle_len) + } else if prev_row_len >= 4 { + VP8LBackwardRefsCursorAdd(tls, refs, PixOrCopyCreateCopy(tls, uint32(xsize), uint16(prev_row_len))) + if use_color_cache != 0 { + for k = 0; k < prev_row_len; k++ { + VP8LColorCacheInsert(tls, (bp) /* &hashers */, *(*uint32_t)(unsafe.Pointer(argb + uintptr((i+k))*4))) + } + } + i = i + (prev_row_len) + } else { + AddSingleLiteral(tls, *(*uint32_t)(unsafe.Pointer(argb + uintptr(i)*4)), use_color_cache, (bp) /* &hashers */, refs) + i++ + } + } + if use_color_cache != 0 { + VP8LColorCacheClear(tls, (bp) /* &hashers */) + } + return libc.BoolInt32(!((*VP8LBackwardRefs)(unsafe.Pointer(refs)).error_ != 0)) +} + +func BackwardReferencesLz77(tls *libc.TLS, xsize int32, ysize int32, argb uintptr, cache_bits int32, hash_chain uintptr, refs uintptr) int32 { /* backward_references_enc.c:485:12: */ + bp := tls.Alloc(24) + defer tls.Free(24) + + var i int32 + var i_last_check int32 + var ok int32 + var cc_init int32 + var use_color_cache int32 + var pix_count int32 + // var hashers VP8LColorCache at bp, 16 + + var len_j int32 + var reach int32 + var len_ini int32 + var max_reach int32 + var j_max int32 + // Alternative#1: Code the pixels starting at 'i' using backward reference. + // var offset int32 at bp+16, 4 + + // var len int32 at bp+20, 4 + + var j int32 + i_last_check = -1 + ok = 0 + cc_init = 0 + use_color_cache = (libc.Bool32(cache_bits > 0)) + pix_count = (xsize * ysize) + + if !(use_color_cache != 0) { + goto __1 + } + cc_init = VP8LColorCacheInit(tls, (bp) /* &hashers */, cache_bits) + if !(!(cc_init != 0)) { + goto __2 + } + goto Error +__2: + ; +__1: + ; + VP8LClearBackwardRefs(tls, refs) + i = 0 +__3: + if !(i < pix_count) { + goto __5 + } + // Alternative#1: Code the pixels starting at 'i' using backward reference. + *(*int32)(unsafe.Pointer(bp + 16 /* offset */)) = 0 + *(*int32)(unsafe.Pointer(bp + 20 /* len */)) = 0 + VP8LHashChainFindCopy(tls, hash_chain, i, (bp + 16) /* &offset */, (bp + 20) /* &len */) + if !(*(*int32)(unsafe.Pointer(bp + 20 /* len */)) >= 4) { + goto __6 + } + len_ini = *(*int32)(unsafe.Pointer(bp + 20 /* len */)) + max_reach = 0 + if (i + len_ini) >= pix_count { + j_max = (pix_count - 1) + } else { + j_max = (i + len_ini) + } + // Only start from what we have not checked already. + if i > i_last_check { + i_last_check = i + } else { + i_last_check = i_last_check + } + // We know the best match for the current pixel but we try to find the + // best matches for the current pixel AND the next one combined. + // The naive method would use the intervals: + // [i,i+len) + [i+len, length of best match at i+len) + // while we check if we can use: + // [i,j) (where j<=i+len) + [j, length of best match at j) + j = (i_last_check + 1) +__8: + if !(j <= j_max) { + goto __10 + } + len_j = VP8LHashChainFindLength(tls, hash_chain, j) + reach = + (j + (func() int32 { + if len_j >= 4 { + return len_j + } + return 1 + }())) // 1 for single literal. + if !(reach > max_reach) { + goto __11 + } + *(*int32)(unsafe.Pointer(bp + 20 /* len */)) = (j - i) + max_reach = reach + if !(max_reach >= pix_count) { + goto __12 + } + goto __10 +__12: + ; +__11: + ; + goto __9 +__9: + j++ + goto __8 + goto __10 +__10: + ; + goto __7 +__6: + *(*int32)(unsafe.Pointer(bp + 20 /* len */)) = 1 +__7: + ; + // Go with literal or backward reference. + + if !(*(*int32)(unsafe.Pointer(bp + 20 /* len */)) == 1) { + goto __13 + } + AddSingleLiteral(tls, *(*uint32_t)(unsafe.Pointer(argb + uintptr(i)*4)), use_color_cache, (bp) /* &hashers */, refs) + goto __14 +__13: + VP8LBackwardRefsCursorAdd(tls, refs, PixOrCopyCreateCopy(tls, uint32(*(*int32)(unsafe.Pointer(bp + 16 /* offset */))), uint16(*(*int32)(unsafe.Pointer(bp + 20 /* len */))))) + if !(use_color_cache != 0) { + goto __15 + } + j = i +__16: + if !(j < (i + *(*int32)(unsafe.Pointer(bp + 20 /* len */)))) { + goto __18 + } + VP8LColorCacheInsert(tls, (bp) /* &hashers */, *(*uint32_t)(unsafe.Pointer(argb + uintptr(j)*4))) + goto __17 +__17: + j++ + goto __16 + goto __18 +__18: + ; +__15: + ; +__14: + ; + i = i + (*(*int32)(unsafe.Pointer(bp + 20 /* len */))) + goto __4 +__4: + ; + goto __3 + goto __5 +__5: + ; + + ok = libc.BoolInt32(!((*VP8LBackwardRefs)(unsafe.Pointer(refs)).error_ != 0)) +Error: + if !(cc_init != 0) { + goto __19 + } + VP8LColorCacheClear(tls, (bp) /* &hashers */) +__19: + ; + return ok +} + +// Compute an LZ77 by forcing matches to happen within a given distance cost. +// We therefore limit the algorithm to the lowest 32 values in the PlaneCode +// definition. +func BackwardReferencesLz77Box(tls *libc.TLS, xsize int32, ysize int32, argb uintptr, cache_bits int32, hash_chain_best uintptr, hash_chain uintptr, refs uintptr) int32 { /* backward_references_enc.c:557:12: */ + bp := tls.Alloc(256) + defer tls.Free(256) + + var i int32 + var pix_count int32 = (xsize * ysize) + var counts uintptr + *(*[32]int32)(unsafe.Pointer(bp /* window_offsets */)) = [32]int32{0: 0} + *(*[32]int32)(unsafe.Pointer(bp + 128 /* window_offsets_new */)) = [32]int32{0: 0} + var window_offsets_size int32 = 0 + var window_offsets_new_size int32 = 0 + var counts_ini uintptr = WebPSafeMalloc(tls, (uint64(xsize * ysize)), uint64(unsafe.Sizeof(uint16_t(0)))) + var best_offset_prev int32 = -1 + var best_length_prev int32 = -1 + if counts_ini == (uintptr(0)) { + return 0 + } + + // counts[i] counts how many times a pixel is repeated starting at position i. + i = (pix_count - 2) + counts = (counts_ini + uintptr(i)*2) + *(*uint16_t)(unsafe.Pointer(counts + 1*2)) = uint16_t(1) +__1: + if !(i >= 0) { + goto __3 + } + { + if *(*uint32_t)(unsafe.Pointer(argb + uintptr(i)*4)) == *(*uint32_t)(unsafe.Pointer(argb + uintptr((i+1))*4)) { + // Max out the counts to MAX_LENGTH. + *(*uint16_t)(unsafe.Pointer(counts)) = (uint16_t(int32(*(*uint16_t)(unsafe.Pointer(counts + 1*2))) + (libc.Bool32(int32(*(*uint16_t)(unsafe.Pointer(counts + 1*2))) != ((int32(1) << 12) - 1))))) + } else { + *(*uint16_t)(unsafe.Pointer(counts)) = uint16_t(1) + } + + } + goto __2 +__2: + i-- + counts -= 2 + goto __1 + goto __3 +__3: + ; + + // Figure out the window offsets around a pixel. They are stored in a + // spiraling order around the pixel as defined by VP8LDistanceToPlaneCode. + { + var x int32 + var y int32 + for y = 0; y <= 6; y++ { + for x = -6; x <= 6; x++ { + var offset int32 = ((y * xsize) + x) + var plane_code int32 + // Ignore offsets that bring us after the pixel. + if offset <= 0 { + continue + } + plane_code = (VP8LDistanceToPlaneCode(tls, xsize, offset) - 1) + if plane_code >= 32 { + continue + } + *(*int32)(unsafe.Pointer((bp) /* &window_offsets[0] */ + uintptr(plane_code)*4)) = offset + } + } + // For narrow images, not all plane codes are reached, so remove those. + for i = 0; i < 32; i++ { + if *(*int32)(unsafe.Pointer((bp) /* &window_offsets[0] */ + uintptr(i)*4)) == 0 { + continue + } + *(*int32)(unsafe.Pointer((bp) /* &window_offsets[0] */ + uintptr(libc.PostIncInt32(&window_offsets_size, 1))*4)) = *(*int32)(unsafe.Pointer((bp) /* &window_offsets[0] */ + uintptr(i)*4)) + } + // Given a pixel P, find the offsets that reach pixels unreachable from P-1 + // with any of the offsets in window_offsets[]. + for i = 0; i < window_offsets_size; i++ { + var j int32 + var is_reachable int32 = 0 + for j = 0; (j < window_offsets_size) && !(is_reachable != 0); j++ { + is_reachable = is_reachable | (libc.Bool32(*(*int32)(unsafe.Pointer((bp) /* &window_offsets[0] */ + uintptr(i)*4)) == (*(*int32)(unsafe.Pointer((bp) /* &window_offsets[0] */ + uintptr(j)*4)) + 1))) + } + if !(is_reachable != 0) { + *(*int32)(unsafe.Pointer((bp + 128) /* &window_offsets_new[0] */ + uintptr(window_offsets_new_size)*4)) = *(*int32)(unsafe.Pointer((bp) /* &window_offsets[0] */ + uintptr(i)*4)) + window_offsets_new_size++ + } + } + + } + + *(*uint32_t)(unsafe.Pointer((*VP8LHashChain)(unsafe.Pointer(hash_chain)).offset_length_)) = uint32_t(0) + for i = 1; i < pix_count; i++ { + var ind int32 + var best_length int32 = VP8LHashChainFindLength(tls, hash_chain_best, i) + var best_offset int32 + var do_compute int32 = 1 + + if best_length >= ((int32(1) << 12) - 1) { + // Do not recompute the best match if we already have a maximal one in the + // window. + best_offset = VP8LHashChainFindOffset(tls, hash_chain_best, i) + for ind = 0; ind < window_offsets_size; ind++ { + if best_offset == *(*int32)(unsafe.Pointer((bp) /* &window_offsets[0] */ + uintptr(ind)*4)) { + do_compute = 0 + break + } + } + } + if do_compute != 0 { + // Figure out if we should use the offset/length from the previous pixel + // as an initial guess and therefore only inspect the offsets in + // window_offsets_new[]. + var use_prev int32 = (libc.Bool32((best_length_prev > 1) && (best_length_prev < ((int32(1) << 12) - 1)))) + var num_ind int32 + if use_prev != 0 { + num_ind = window_offsets_new_size + } else { + num_ind = window_offsets_size + } + if use_prev != 0 { + best_length = (best_length_prev - 1) + } else { + best_length = 0 + } + if use_prev != 0 { + best_offset = best_offset_prev + } else { + best_offset = 0 + } + // Find the longest match in a window around the pixel. + for ind = 0; ind < num_ind; ind++ { + var curr_length int32 = 0 + var j int32 = i + var j_offset int32 + if use_prev != 0 { + j_offset = (i - *(*int32)(unsafe.Pointer((bp + 128) /* &window_offsets_new[0] */ + uintptr(ind)*4))) + } else { + j_offset = (i - *(*int32)(unsafe.Pointer((bp) /* &window_offsets[0] */ + uintptr(ind)*4))) + } + if (j_offset < 0) || (*(*uint32_t)(unsafe.Pointer(argb + uintptr(j_offset)*4)) != *(*uint32_t)(unsafe.Pointer(argb + uintptr(i)*4))) { + continue + } + // The longest match is the sum of how many times each pixel is + // repeated. + for ok := true; ok; ok = (((curr_length <= ((int32(1) << 12) - 1)) && (j < pix_count)) && (*(*uint32_t)(unsafe.Pointer(argb + uintptr(j_offset)*4)) == *(*uint32_t)(unsafe.Pointer(argb + uintptr(j)*4)))) { + var counts_j_offset int32 = int32(*(*uint16_t)(unsafe.Pointer(counts_ini + uintptr(j_offset)*2))) + var counts_j int32 = int32(*(*uint16_t)(unsafe.Pointer(counts_ini + uintptr(j)*2))) + if counts_j_offset != counts_j { + curr_length = curr_length + (func() int32 { + if counts_j_offset < counts_j { + return counts_j_offset + } + return counts_j + }()) + break + } + // The same color is repeated counts_pos times at j_offset and j. + curr_length = curr_length + (counts_j_offset) + j_offset = j_offset + (counts_j_offset) + j = j + (counts_j_offset) + } + if best_length < curr_length { + if use_prev != 0 { + best_offset = *(*int32)(unsafe.Pointer((bp + 128) /* &window_offsets_new[0] */ + uintptr(ind)*4)) + } else { + best_offset = *(*int32)(unsafe.Pointer((bp) /* &window_offsets[0] */ + uintptr(ind)*4)) + } + if curr_length >= ((int32(1) << 12) - 1) { + best_length = ((int32(1) << 12) - 1) + break + } else { + best_length = curr_length + } + } + } + } + + if best_length <= 4 { + *(*uint32_t)(unsafe.Pointer((*VP8LHashChain)(unsafe.Pointer(hash_chain)).offset_length_ + uintptr(i)*4)) = uint32_t(0) + best_offset_prev = 0 + best_length_prev = 0 + } else { + *(*uint32_t)(unsafe.Pointer((*VP8LHashChain)(unsafe.Pointer(hash_chain)).offset_length_ + uintptr(i)*4)) = ((uint32_t(best_offset << 12)) | uint32_t(best_length)) + best_offset_prev = best_offset + best_length_prev = best_length + } + } + *(*uint32_t)(unsafe.Pointer((*VP8LHashChain)(unsafe.Pointer(hash_chain)).offset_length_)) = uint32_t(0) + WebPSafeFree(tls, counts_ini) + + return BackwardReferencesLz77(tls, xsize, ysize, argb, cache_bits, hash_chain, + refs) +} + +// ----------------------------------------------------------------------------- + +func BackwardReferences2DLocality(tls *libc.TLS, xsize int32, refs uintptr) { /* backward_references_enc.c:708:13: */ + bp := tls.Alloc(24) + defer tls.Free(24) + + *(*VP8LRefsCursor)(unsafe.Pointer(bp /* c */)) = VP8LRefsCursorInit(tls, refs) + for VP8LRefsCursorOk(tls, (bp) /* &c */) != 0 { + if PixOrCopyIsCopy(tls, (*VP8LRefsCursor)(unsafe.Pointer(bp /* &c */)).cur_pos) != 0 { + var dist int32 = int32((*PixOrCopy)(unsafe.Pointer((*VP8LRefsCursor)(unsafe.Pointer(bp /* &c */)).cur_pos)).argb_or_distance) + var transformed_dist int32 = VP8LDistanceToPlaneCode(tls, xsize, dist) + (*PixOrCopy)(unsafe.Pointer((*VP8LRefsCursor)(unsafe.Pointer(bp /* &c */)).cur_pos)).argb_or_distance = uint32_t(transformed_dist) + } + VP8LRefsCursorNext(tls, (bp) /* &c */) + } +} + +// Evaluate optimal cache bits for the local color cache. +// The input *best_cache_bits sets the maximum cache bits to use (passing 0 +// implies disabling the local color cache). The local color cache is also +// disabled for the lower (<= 25) quality. +// Returns 0 in case of memory error. +func CalculateBestCacheSize(tls *libc.TLS, argb uintptr, quality int32, refs uintptr, best_cache_bits uintptr) int32 { /* backward_references_enc.c:726:12: */ + bp := tls.Alloc(348) + defer tls.Free(348) + + var i int32 + var cache_bits_max int32 + var entropy_min float64 + // var cc_init [11]int32 at bp+88, 44 + + // var hashers [11]VP8LColorCache at bp+136, 176 + + // var c VP8LRefsCursor at bp+312, 24 + + // var histos [11]uintptr at bp, 88 + + var ok int32 + var pix uint32_t + var a uint32_t + var r uint32_t + var g uint32_t + var b uint32_t + // The keys of the caches can be derived from the longest one. + var key int32 + // Efficiency: insert only if the color changes. + var key1 int32 + // var code int32 at bp+336, 4 + + // var extra_bits int32 at bp+340, 4 + + // var extra_bits_value int32 at bp+344, 4 + + // We should compute the contribution of the (distance,length) + // histograms but those are the same independently from the cache size. + // As those constant contributions are in the end added to the other + // histogram contributions, we can ignore them, except for the length + // prefix that is part of the literal_ histogram. + var len int32 + var argb_prev uint32_t + var v uintptr + var entropy float64 + if quality <= 25 { + cache_bits_max = 0 + } else { + cache_bits_max = *(*int32)(unsafe.Pointer(best_cache_bits)) + } + entropy_min = (1e30) + *(*[11]int32)(unsafe.Pointer(bp + 88 /* cc_init */)) = [11]int32{0: 0} + *(*VP8LRefsCursor)(unsafe.Pointer(bp + 312 /* c */)) = VP8LRefsCursorInit(tls, refs) + *(*[11]uintptr)(unsafe.Pointer(bp /* histos */)) = [11]uintptr{0: (uintptr(0))} + ok = 0 + + if !(cache_bits_max == 0) { + goto __1 + } + *(*int32)(unsafe.Pointer(best_cache_bits)) = 0 + // Local color cache is disabled. + return 1 +__1: + ; + + // Allocate data. + i = 0 +__2: + if !(i <= cache_bits_max) { + goto __4 + } + *(*uintptr)(unsafe.Pointer((bp) /* &histos[0] */ + uintptr(i)*8)) = VP8LAllocateHistogram(tls, i) + if !(*(*uintptr)(unsafe.Pointer((bp) /* &histos[0] */ + uintptr(i)*8)) == (uintptr(0))) { + goto __5 + } + goto Error +__5: + ; + VP8LHistogramInit(tls, *(*uintptr)(unsafe.Pointer((bp) /* &histos[0] */ + uintptr(i)*8)), i /*init_arrays=*/, 1) + if !(i == 0) { + goto __6 + } + goto __3 +__6: + ; + *(*int32)(unsafe.Pointer((bp + 88) /* &cc_init[0] */ + uintptr(i)*4)) = VP8LColorCacheInit(tls, ((bp + 136) /* &hashers */ + uintptr(i)*16), i) + if !(!(*(*int32)(unsafe.Pointer((bp + 88) /* &cc_init[0] */ + uintptr(i)*4)) != 0)) { + goto __7 + } + goto Error +__7: + ; + goto __3 +__3: + i++ + goto __2 + goto __4 +__4: + ; + + // Find the cache_bits giving the lowest entropy. The search is done in a + // brute-force way as the function (entropy w.r.t cache_bits) can be + // anything in practice. +__8: + if !(VP8LRefsCursorOk(tls, (bp+312) /* &c */) != 0) { + goto __9 + } + v = (*VP8LRefsCursor)(unsafe.Pointer(bp + 312 /* &c */)).cur_pos + if !(PixOrCopyIsLiteral(tls, v) != 0) { + goto __10 + } + pix = *(*uint32_t)(unsafe.Pointer(libc.PostIncUintptr(&argb, 4))) + a = ((pix >> 24) & uint32_t(0xff)) + r = ((pix >> 16) & uint32_t(0xff)) + g = ((pix >> 8) & uint32_t(0xff)) + b = ((pix >> 0) & uint32_t(0xff)) + // The keys of the caches can be derived from the longest one. + key = VP8LHashPix(tls, pix, (32 - cache_bits_max)) + // Do not use the color cache for cache_bits = 0. + *(*uint32_t)(unsafe.Pointer((*(*uintptr)(unsafe.Pointer((bp) /* &histos[0] */)) + 1032 /* &.blue_ */) + uintptr(b)*4))++ + *(*uint32_t)(unsafe.Pointer((*VP8LHistogram)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((bp) /* &histos[0] */)))).literal_ + uintptr(g)*4))++ + *(*uint32_t)(unsafe.Pointer((*(*uintptr)(unsafe.Pointer((bp) /* &histos[0] */)) + 8 /* &.red_ */) + uintptr(r)*4))++ + *(*uint32_t)(unsafe.Pointer((*(*uintptr)(unsafe.Pointer((bp) /* &histos[0] */)) + 2056 /* &.alpha_ */) + uintptr(a)*4))++ + // Deal with cache_bits > 0. + i = cache_bits_max +__12: + if !(i >= 1) { + goto __14 + } + if !(VP8LColorCacheLookup(tls, ((bp+136) /* &hashers */ +uintptr(i)*16), uint32(key)) == pix) { + goto __15 + } + *(*uint32_t)(unsafe.Pointer((*VP8LHistogram)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((bp) /* &histos[0] */ + uintptr(i)*8)))).literal_ + uintptr(((256+24)+key))*4))++ + goto __16 +__15: + VP8LColorCacheSet(tls, ((bp + 136) /* &hashers */ + uintptr(i)*16), uint32(key), pix) + *(*uint32_t)(unsafe.Pointer((*(*uintptr)(unsafe.Pointer((bp) /* &histos[0] */ + uintptr(i)*8)) + 1032 /* &.blue_ */) + uintptr(b)*4))++ + *(*uint32_t)(unsafe.Pointer((*VP8LHistogram)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((bp) /* &histos[0] */ + uintptr(i)*8)))).literal_ + uintptr(g)*4))++ + *(*uint32_t)(unsafe.Pointer((*(*uintptr)(unsafe.Pointer((bp) /* &histos[0] */ + uintptr(i)*8)) + 8 /* &.red_ */) + uintptr(r)*4))++ + *(*uint32_t)(unsafe.Pointer((*(*uintptr)(unsafe.Pointer((bp) /* &histos[0] */ + uintptr(i)*8)) + 2056 /* &.alpha_ */) + uintptr(a)*4))++ +__16: + ; + goto __13 +__13: + i-- + key >>= 1 + goto __12 + goto __14 +__14: + ; + goto __11 +__10: + // We should compute the contribution of the (distance,length) + // histograms but those are the same independently from the cache size. + // As those constant contributions are in the end added to the other + // histogram contributions, we can ignore them, except for the length + // prefix that is part of the literal_ histogram. + len = int32(PixOrCopyLength(tls, v)) + argb_prev = (*(*uint32_t)(unsafe.Pointer(argb)) ^ 0xffffffff) + VP8LPrefixEncode(tls, len, (bp + 336) /* &code */, (bp + 340) /* &extra_bits */, (bp + 344) /* &extra_bits_value */) + i = 0 +__17: + if !(i <= cache_bits_max) { + goto __19 + } + *(*uint32_t)(unsafe.Pointer((*VP8LHistogram)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((bp) /* &histos[0] */ + uintptr(i)*8)))).literal_ + uintptr((256+*(*int32)(unsafe.Pointer(bp + 336 /* code */))))*4))++ + goto __18 +__18: + i++ + goto __17 + goto __19 +__19: + ; + // Update the color caches. +__20: + if !(*(*uint32_t)(unsafe.Pointer(argb)) != argb_prev) { + goto __23 + } + // Efficiency: insert only if the color changes. + key1 = VP8LHashPix(tls, *(*uint32_t)(unsafe.Pointer(argb)), (32 - cache_bits_max)) + i = cache_bits_max +__24: + if !(i >= 1) { + goto __26 + } + *(*uint32_t)(unsafe.Pointer((*VP8LColorCache)(unsafe.Pointer((bp+136) /* &hashers */ +uintptr(i)*16)).colors_ + uintptr(key1)*4)) = *(*uint32_t)(unsafe.Pointer(argb)) + goto __25 +__25: + i-- + key1 >>= 1 + goto __24 + goto __26 +__26: + ; + argb_prev = *(*uint32_t)(unsafe.Pointer(argb)) +__23: + ; + argb += 4 + goto __21 +__21: + if libc.PreDecInt32(&len, 1) != 0 { + goto __20 + } + goto __22 +__22: + ; +__11: + ; + VP8LRefsCursorNext(tls, (bp + 312) /* &c */) + goto __8 +__9: + ; + + i = 0 +__27: + if !(i <= cache_bits_max) { + goto __29 + } + entropy = VP8LHistogramEstimateBits(tls, *(*uintptr)(unsafe.Pointer((bp) /* &histos[0] */ + uintptr(i)*8))) + if !((i == 0) || (entropy < entropy_min)) { + goto __30 + } + entropy_min = entropy + *(*int32)(unsafe.Pointer(best_cache_bits)) = i +__30: + ; + goto __28 +__28: + i++ + goto __27 + goto __29 +__29: + ; + ok = 1 +Error: + i = 0 +__31: + if !(i <= cache_bits_max) { + goto __33 + } + if !(*(*int32)(unsafe.Pointer((bp + 88) /* &cc_init[0] */ + uintptr(i)*4)) != 0) { + goto __34 + } + VP8LColorCacheClear(tls, ((bp + 136) /* &hashers */ + uintptr(i)*16)) +__34: + ; + VP8LFreeHistogram(tls, *(*uintptr)(unsafe.Pointer((bp) /* &histos[0] */ + uintptr(i)*8))) + goto __32 +__32: + i++ + goto __31 + goto __33 +__33: + ; + return ok +} + +// Update (in-place) backward references for specified cache_bits. +func BackwardRefsWithLocalCache(tls *libc.TLS, argb uintptr, cache_bits int32, refs uintptr) int32 { /* backward_references_enc.c:832:12: */ + bp := tls.Alloc(40) + defer tls.Free(40) + + var pixel_index int32 = 0 + // var hashers VP8LColorCache at bp, 16 + + *(*VP8LRefsCursor)(unsafe.Pointer(bp + 16 /* c */)) = VP8LRefsCursorInit(tls, refs) + if !(VP8LColorCacheInit(tls, (bp) /* &hashers */, cache_bits) != 0) { + return 0 + } + + for VP8LRefsCursorOk(tls, (bp+16) /* &c */) != 0 { + var v uintptr = (*VP8LRefsCursor)(unsafe.Pointer(bp + 16 /* &c */)).cur_pos + if PixOrCopyIsLiteral(tls, v) != 0 { + var argb_literal uint32_t = (*PixOrCopy)(unsafe.Pointer(v)).argb_or_distance + var ix int32 = VP8LColorCacheContains(tls, (bp) /* &hashers */, argb_literal) + if ix >= 0 { + // hashers contains argb_literal + *(*PixOrCopy)(unsafe.Pointer(v)) = PixOrCopyCreateCacheIdx(tls, ix) + } else { + VP8LColorCacheInsert(tls, (bp) /* &hashers */, argb_literal) + } + pixel_index++ + } else { + // refs was created without local cache, so it can not have cache indexes. + var k int32 + + for k = 0; k < int32((*PixOrCopy)(unsafe.Pointer(v)).len); k++ { + VP8LColorCacheInsert(tls, (bp) /* &hashers */, *(*uint32_t)(unsafe.Pointer(argb + uintptr(libc.PostIncInt32(&pixel_index, 1))*4))) + } + } + VP8LRefsCursorNext(tls, (bp + 16) /* &c */) + } + VP8LColorCacheClear(tls, (bp) /* &hashers */) + return 1 +} + +func GetBackwardReferencesLowEffort(tls *libc.TLS, width int32, height int32, argb uintptr, cache_bits uintptr, hash_chain uintptr, refs_lz77 uintptr) uintptr { /* backward_references_enc.c:866:24: */ + *(*int32)(unsafe.Pointer(cache_bits)) = 0 + if !(BackwardReferencesLz77(tls, width, height, argb, 0, hash_chain, refs_lz77) != 0) { + return (uintptr(0)) + } + BackwardReferences2DLocality(tls, width, refs_lz77) + return refs_lz77 +} + +func GetBackwardReferences(tls *libc.TLS, width int32, height int32, argb uintptr, quality int32, lz77_types_to_try int32, cache_bits_max int32, do_no_cache int32, hash_chain uintptr, refs uintptr, cache_bits_best uintptr) int32 { /* backward_references_enc.c:882:12: */ + bp := tls.Alloc(48) + defer tls.Free(48) + + var histo uintptr + var i int32 + var lz77_type int32 + // Index 0 is for a color cache, index 1 for no cache (if needed). + // var lz77_types_best [2]int32 at bp+40, 8 + + // var bit_costs_best [2]float64 at bp+24, 16 + + // var hash_chain_box VP8LHashChain at bp, 16 + + var refs_tmp uintptr + var status int32 + // var cache_bits int32 at bp+16, 4 + + var res int32 + var bit_cost float64 + var bit_cost_trace float64 + var hash_chain_tmp uintptr + var cache_bits1 int32 + histo = (uintptr(0)) + *(*[2]int32)(unsafe.Pointer(bp + 40 /* lz77_types_best */)) = [2]int32{0, 0} + *(*[2]float64)(unsafe.Pointer(bp + 24 /* bit_costs_best */)) = [2]float64{(1.79769313486231570814527423731704357e+308), (1.79769313486231570814527423731704357e+308)} + refs_tmp = (refs + uintptr(func() int32 { + if do_no_cache != 0 { + return 2 + } + return 1 + }())*40) + status = 0 + libc.Xmemset(tls, (bp) /* &hash_chain_box */, 0, uint64(unsafe.Sizeof(VP8LHashChain{}))) + + histo = VP8LAllocateHistogram(tls, 10) + if !(histo == (uintptr(0))) { + goto __1 + } + goto Error +__1: + ; + + lz77_type = 1 +__2: + if !(lz77_types_to_try != 0) { + goto __4 + } + res = 0 + bit_cost = 0. + if !((lz77_types_to_try & lz77_type) == 0) { + goto __5 + } + goto __3 +__5: + ; + switch lz77_type { + case kLZ77RLE: + goto __7 + case kLZ77Standard: + goto __8 + case kLZ77Box: + goto __9 + default: + goto __10 + } + goto __6 +__7: + res = BackwardReferencesRle(tls, width, height, argb, 0, refs_tmp) + goto __6 +__8: + // Compute LZ77 with no cache (0 bits), as the ideal LZ77 with a color + // cache is not that different in practice. + res = BackwardReferencesLz77(tls, width, height, argb, 0, hash_chain, + refs_tmp) + goto __6 +__9: + if !(!(VP8LHashChainInit(tls, (bp) /* &hash_chain_box */, (width*height)) != 0)) { + goto __11 + } + goto Error +__11: + ; + res = BackwardReferencesLz77Box(tls, width, height, argb, 0, hash_chain, + (bp) /* &hash_chain_box */, refs_tmp) + goto __6 +__10: + ; +__6: + ; + if !(!(res != 0)) { + goto __12 + } + goto Error +__12: + ; + + // Start with the no color cache case. + i = 1 +__13: + if !(i >= 0) { + goto __15 + } + if i == 1 { + *(*int32)(unsafe.Pointer(bp + 16 /* cache_bits */)) = 0 + } else { + *(*int32)(unsafe.Pointer(bp + 16 /* cache_bits */)) = cache_bits_max + } + + if !((i == 1) && !(do_no_cache != 0)) { + goto __16 + } + goto __14 +__16: + ; + + if !(i == 0) { + goto __17 + } + // Try with a color cache. + if !(!(CalculateBestCacheSize(tls, argb, quality, refs_tmp, (bp+16) /* &cache_bits */) != 0)) { + goto __18 + } + goto Error +__18: + ; + if !(*(*int32)(unsafe.Pointer(bp + 16 /* cache_bits */)) > 0) { + goto __19 + } + if !(!(BackwardRefsWithLocalCache(tls, argb, *(*int32)(unsafe.Pointer(bp + 16 /* cache_bits */)), refs_tmp) != 0)) { + goto __20 + } + goto Error +__20: + ; +__19: + ; +__17: + ; + + if !(((i == 0) && (do_no_cache != 0)) && (*(*int32)(unsafe.Pointer(bp + 16 /* cache_bits */)) == 0)) { + goto __21 + } + // No need to re-compute bit_cost as it was computed at i == 1. + goto __22 +__21: + VP8LHistogramCreate(tls, histo, refs_tmp, *(*int32)(unsafe.Pointer(bp + 16 /* cache_bits */))) + bit_cost = VP8LHistogramEstimateBits(tls, histo) +__22: + ; + + if !(bit_cost < *(*float64)(unsafe.Pointer((bp + 24) /* &bit_costs_best[0] */ + uintptr(i)*8))) { + goto __23 + } + if !(i == 1) { + goto __24 + } + // Do not swap as the full cache analysis would have the wrong + // VP8LBackwardRefs to start with. + if !(!(BackwardRefsClone(tls, refs_tmp, (refs+1*40)) != 0)) { + goto __26 + } + goto Error +__26: + ; + goto __25 +__24: + BackwardRefsSwap(tls, refs_tmp, (refs)) +__25: + ; + *(*float64)(unsafe.Pointer((bp + 24) /* &bit_costs_best[0] */ + uintptr(i)*8)) = bit_cost + *(*int32)(unsafe.Pointer((bp + 40) /* &lz77_types_best[0] */ + uintptr(i)*4)) = lz77_type + if !(i == 0) { + goto __27 + } + *(*int32)(unsafe.Pointer(cache_bits_best)) = *(*int32)(unsafe.Pointer(bp + 16 /* cache_bits */)) +__27: + ; +__23: + ; + goto __14 +__14: + i-- + goto __13 + goto __15 +__15: + ; + goto __3 +__3: + lz77_types_to_try = lz77_types_to_try & (^lz77_type) + lz77_type <<= 1 + goto __2 + goto __4 +__4: + ; + + // Improve on simple LZ77 but only for high quality (TraceBackwards is + // costly). + i = 1 +__28: + if !(i >= 0) { + goto __30 + } + if !((i == 1) && !(do_no_cache != 0)) { + goto __31 + } + goto __29 +__31: + ; + if !(((*(*int32)(unsafe.Pointer((bp + 40) /* &lz77_types_best[0] */ + uintptr(i)*4)) == kLZ77Standard) || (*(*int32)(unsafe.Pointer((bp + 40) /* &lz77_types_best[0] */ + uintptr(i)*4)) == kLZ77Box)) && (quality >= 25)) { + goto __32 + } + if *(*int32)(unsafe.Pointer((bp + 40) /* &lz77_types_best[0] */ + uintptr(i)*4)) == kLZ77Standard { + hash_chain_tmp = hash_chain + } else { + hash_chain_tmp = (bp) /* &hash_chain_box */ + } + if i == 1 { + cache_bits1 = 0 + } else { + cache_bits1 = *(*int32)(unsafe.Pointer(cache_bits_best)) + } + if !(VP8LBackwardReferencesTraceBackwards(tls, width, height, argb, cache_bits1, + hash_chain_tmp, (refs+uintptr(i)*40), + refs_tmp) != 0) { + goto __33 + } + VP8LHistogramCreate(tls, histo, refs_tmp, cache_bits1) + bit_cost_trace = VP8LHistogramEstimateBits(tls, histo) + if !(bit_cost_trace < *(*float64)(unsafe.Pointer((bp + 24) /* &bit_costs_best[0] */ + uintptr(i)*8))) { + goto __34 + } + BackwardRefsSwap(tls, refs_tmp, (refs + uintptr(i)*40)) +__34: + ; +__33: + ; +__32: + ; + + BackwardReferences2DLocality(tls, width, (refs + uintptr(i)*40)) + + if !(((i == 1) && (*(*int32)(unsafe.Pointer((bp + 40) /* &lz77_types_best[0] */)) == *(*int32)(unsafe.Pointer((bp + 40) /* &lz77_types_best[0] */ + 1*4)))) && (*(*int32)(unsafe.Pointer(cache_bits_best)) == 0)) { + goto __35 + } + // If the best cache size is 0 and we have the same best LZ77, just copy + // the data over and stop here. + if !(!(BackwardRefsClone(tls, (refs+1*40), (refs)) != 0)) { + goto __36 + } + goto Error +__36: + ; + goto __30 +__35: + ; + goto __29 +__29: + i-- + goto __28 + goto __30 +__30: + ; + status = 1 + +Error: + VP8LHashChainClear(tls, (bp) /* &hash_chain_box */) + VP8LFreeHistogram(tls, histo) + return status +} + +func VP8LGetBackwardReferences(tls *libc.TLS, width int32, height int32, argb uintptr, quality int32, low_effort int32, lz77_types_to_try int32, cache_bits_max int32, do_no_cache int32, hash_chain uintptr, refs uintptr, cache_bits_best uintptr) WebPEncodingError { /* backward_references_enc.c:1009:19: */ + if low_effort != 0 { + var refs_best uintptr + *(*int32)(unsafe.Pointer(cache_bits_best)) = cache_bits_max + refs_best = GetBackwardReferencesLowEffort(tls, + width, height, argb, cache_bits_best, hash_chain, refs) + if refs_best == (uintptr(0)) { + return VP8_ENC_ERROR_OUT_OF_MEMORY + } + // Set it in first position. + BackwardRefsSwap(tls, refs_best, (refs)) + } else { + if !(GetBackwardReferences(tls, width, height, argb, quality, lz77_types_to_try, + cache_bits_max, do_no_cache, hash_chain, refs, + cache_bits_best) != 0) { + return VP8_ENC_ERROR_OUT_OF_MEMORY + } + } + return VP8_ENC_OK +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// WebPConfig +//------------------------------------------------------------------------------ + +func WebPConfigInitInternal(tls *libc.TLS, config uintptr, preset WebPPreset, quality float32, version int32) int32 { /* config_enc.c:24:5: */ + if ((version) >> 8) != (int32((0x020f)) >> 8) { + return 0 // caller/system version mismatch! + } + if config == (uintptr(0)) { + return 0 + } + + (*WebPConfig)(unsafe.Pointer(config)).quality = quality + (*WebPConfig)(unsafe.Pointer(config)).target_size = 0 + (*WebPConfig)(unsafe.Pointer(config)).target_PSNR = 0. + (*WebPConfig)(unsafe.Pointer(config)).method = 4 + (*WebPConfig)(unsafe.Pointer(config)).sns_strength = 50 + (*WebPConfig)(unsafe.Pointer(config)).filter_strength = 60 // mid-filtering + (*WebPConfig)(unsafe.Pointer(config)).filter_sharpness = 0 + (*WebPConfig)(unsafe.Pointer(config)).filter_type = 1 // default: strong (so U/V is filtered too) + (*WebPConfig)(unsafe.Pointer(config)).partitions = 0 + (*WebPConfig)(unsafe.Pointer(config)).segments = 4 + (*WebPConfig)(unsafe.Pointer(config)).pass = 1 + (*WebPConfig)(unsafe.Pointer(config)).qmin = 0 + (*WebPConfig)(unsafe.Pointer(config)).qmax = 100 + (*WebPConfig)(unsafe.Pointer(config)).show_compressed = 0 + (*WebPConfig)(unsafe.Pointer(config)).preprocessing = 0 + (*WebPConfig)(unsafe.Pointer(config)).autofilter = 0 + (*WebPConfig)(unsafe.Pointer(config)).partition_limit = 0 + (*WebPConfig)(unsafe.Pointer(config)).alpha_compression = 1 + (*WebPConfig)(unsafe.Pointer(config)).alpha_filtering = 1 + (*WebPConfig)(unsafe.Pointer(config)).alpha_quality = 100 + (*WebPConfig)(unsafe.Pointer(config)).lossless = 0 + (*WebPConfig)(unsafe.Pointer(config)).exact = 0 + (*WebPConfig)(unsafe.Pointer(config)).image_hint = WEBP_HINT_DEFAULT + (*WebPConfig)(unsafe.Pointer(config)).emulate_jpeg_size = 0 + (*WebPConfig)(unsafe.Pointer(config)).thread_level = 0 + (*WebPConfig)(unsafe.Pointer(config)).low_memory = 0 + (*WebPConfig)(unsafe.Pointer(config)).near_lossless = 100 + (*WebPConfig)(unsafe.Pointer(config)).use_delta_palette = 0 + (*WebPConfig)(unsafe.Pointer(config)).use_sharp_yuv = 0 + + // TODO(skal): tune. + switch preset { + case WEBP_PRESET_PICTURE: + (*WebPConfig)(unsafe.Pointer(config)).sns_strength = 80 + (*WebPConfig)(unsafe.Pointer(config)).filter_sharpness = 4 + (*WebPConfig)(unsafe.Pointer(config)).filter_strength = 35 + *(*int32)(unsafe.Pointer((config + 68 /* &.preprocessing */))) &= (libc.CplInt32(2)) // no dithering + break + case WEBP_PRESET_PHOTO: + (*WebPConfig)(unsafe.Pointer(config)).sns_strength = 80 + (*WebPConfig)(unsafe.Pointer(config)).filter_sharpness = 3 + (*WebPConfig)(unsafe.Pointer(config)).filter_strength = 30 + *(*int32)(unsafe.Pointer((config + 68 /* &.preprocessing */))) |= (2) + break + case WEBP_PRESET_DRAWING: + (*WebPConfig)(unsafe.Pointer(config)).sns_strength = 25 + (*WebPConfig)(unsafe.Pointer(config)).filter_sharpness = 6 + (*WebPConfig)(unsafe.Pointer(config)).filter_strength = 10 + break + case WEBP_PRESET_ICON: + (*WebPConfig)(unsafe.Pointer(config)).sns_strength = 0 + (*WebPConfig)(unsafe.Pointer(config)).filter_strength = 0 // disable filtering to retain sharpness + *(*int32)(unsafe.Pointer((config + 68 /* &.preprocessing */))) &= (libc.CplInt32(2)) // no dithering + break + case WEBP_PRESET_TEXT: + (*WebPConfig)(unsafe.Pointer(config)).sns_strength = 0 + (*WebPConfig)(unsafe.Pointer(config)).filter_strength = 0 // disable filtering to retain sharpness + *(*int32)(unsafe.Pointer((config + 68 /* &.preprocessing */))) &= (libc.CplInt32(2)) // no dithering + (*WebPConfig)(unsafe.Pointer(config)).segments = 2 + break + case WEBP_PRESET_DEFAULT: + fallthrough + default: + break + } + return WebPValidateConfig(tls, config) +} + +func WebPValidateConfig(tls *libc.TLS, config uintptr) int32 { /* config_enc.c:98:5: */ + if config == (uintptr(0)) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).quality < float32(0)) || ((*WebPConfig)(unsafe.Pointer(config)).quality > float32(100)) { + return 0 + } + if (*WebPConfig)(unsafe.Pointer(config)).target_size < 0 { + return 0 + } + if (*WebPConfig)(unsafe.Pointer(config)).target_PSNR < float32(0) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).method < 0) || ((*WebPConfig)(unsafe.Pointer(config)).method > 6) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).segments < 1) || ((*WebPConfig)(unsafe.Pointer(config)).segments > 4) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).sns_strength < 0) || ((*WebPConfig)(unsafe.Pointer(config)).sns_strength > 100) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).filter_strength < 0) || ((*WebPConfig)(unsafe.Pointer(config)).filter_strength > 100) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).filter_sharpness < 0) || ((*WebPConfig)(unsafe.Pointer(config)).filter_sharpness > 7) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).filter_type < 0) || ((*WebPConfig)(unsafe.Pointer(config)).filter_type > 1) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).autofilter < 0) || ((*WebPConfig)(unsafe.Pointer(config)).autofilter > 1) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).pass < 1) || ((*WebPConfig)(unsafe.Pointer(config)).pass > 10) { + return 0 + } + if (((*WebPConfig)(unsafe.Pointer(config)).qmin < 0) || ((*WebPConfig)(unsafe.Pointer(config)).qmax > 100)) || ((*WebPConfig)(unsafe.Pointer(config)).qmin > (*WebPConfig)(unsafe.Pointer(config)).qmax) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).show_compressed < 0) || ((*WebPConfig)(unsafe.Pointer(config)).show_compressed > 1) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).preprocessing < 0) || ((*WebPConfig)(unsafe.Pointer(config)).preprocessing > 7) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).partitions < 0) || ((*WebPConfig)(unsafe.Pointer(config)).partitions > 3) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).partition_limit < 0) || ((*WebPConfig)(unsafe.Pointer(config)).partition_limit > 100) { + return 0 + } + if (*WebPConfig)(unsafe.Pointer(config)).alpha_compression < 0 { + return 0 + } + if (*WebPConfig)(unsafe.Pointer(config)).alpha_filtering < 0 { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).alpha_quality < 0) || ((*WebPConfig)(unsafe.Pointer(config)).alpha_quality > 100) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).lossless < 0) || ((*WebPConfig)(unsafe.Pointer(config)).lossless > 1) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).near_lossless < 0) || ((*WebPConfig)(unsafe.Pointer(config)).near_lossless > 100) { + return 0 + } + if (*WebPConfig)(unsafe.Pointer(config)).image_hint >= WEBP_HINT_LAST { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).emulate_jpeg_size < 0) || ((*WebPConfig)(unsafe.Pointer(config)).emulate_jpeg_size > 1) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).thread_level < 0) || ((*WebPConfig)(unsafe.Pointer(config)).thread_level > 1) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).low_memory < 0) || ((*WebPConfig)(unsafe.Pointer(config)).low_memory > 1) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).exact < 0) || ((*WebPConfig)(unsafe.Pointer(config)).exact > 1) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).use_delta_palette < 0) || ((*WebPConfig)(unsafe.Pointer(config)).use_delta_palette > 1) { + return 0 + } + if ((*WebPConfig)(unsafe.Pointer(config)).use_sharp_yuv < 0) || ((*WebPConfig)(unsafe.Pointer(config)).use_sharp_yuv > 1) { + return 0 + } + + return 1 +} + +//------------------------------------------------------------------------------ + +// Mapping between -z level and -m / -q parameter settings. +var kLosslessPresets = [10]struct { + method_ uint8_t + quality_ uint8_t +}{ + struct { + method_ uint8_t + quality_ uint8_t + }{}, struct { + method_ uint8_t + quality_ uint8_t + }{method_: uint8_t(1), quality_: uint8_t(20)}, struct { + method_ uint8_t + quality_ uint8_t + }{method_: uint8_t(2), quality_: uint8_t(25)}, struct { + method_ uint8_t + quality_ uint8_t + }{method_: uint8_t(3), quality_: uint8_t(30)}, struct { + method_ uint8_t + quality_ uint8_t + }{method_: uint8_t(3), quality_: uint8_t(50)}, + struct { + method_ uint8_t + quality_ uint8_t + }{method_: uint8_t(4), quality_: uint8_t(50)}, struct { + method_ uint8_t + quality_ uint8_t + }{method_: uint8_t(4), quality_: uint8_t(75)}, struct { + method_ uint8_t + quality_ uint8_t + }{method_: uint8_t(4), quality_: uint8_t(90)}, struct { + method_ uint8_t + quality_ uint8_t + }{method_: uint8_t(5), quality_: uint8_t(90)}, struct { + method_ uint8_t + quality_ uint8_t + }{method_: uint8_t(6), quality_: uint8_t(100)}, +} /* config_enc.c:144:3 */ + +func WebPConfigLosslessPreset(tls *libc.TLS, config uintptr, level int32) int32 { /* config_enc.c:149:5: */ + if ((config == (uintptr(0))) || (level < 0)) || (level > 9) { + return 0 + } + (*WebPConfig)(unsafe.Pointer(config)).lossless = 1 + (*WebPConfig)(unsafe.Pointer(config)).method = int32(kLosslessPresets[level].method_) + (*WebPConfig)(unsafe.Pointer(config)).quality = float32(kLosslessPresets[level].quality_) + return 1 +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Level cost tables + +// For each given level, the following table gives the pattern of contexts to +// use for coding it (in [][0]) as well as the bit value to use for each +// context (in [][1]). +var VP8LevelCodes = [67][2]uint16_t{ + [2]uint16_t{uint16_t(0x001), uint16_t(0x000)}, [2]uint16_t{uint16_t(0x007), uint16_t(0x001)}, [2]uint16_t{uint16_t(0x00f), uint16_t(0x005)}, + [2]uint16_t{uint16_t(0x00f), uint16_t(0x00d)}, [2]uint16_t{uint16_t(0x033), uint16_t(0x003)}, [2]uint16_t{uint16_t(0x033), uint16_t(0x003)}, [2]uint16_t{uint16_t(0x033), uint16_t(0x023)}, + [2]uint16_t{uint16_t(0x033), uint16_t(0x023)}, [2]uint16_t{uint16_t(0x033), uint16_t(0x023)}, [2]uint16_t{uint16_t(0x033), uint16_t(0x023)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x013)}, + [2]uint16_t{uint16_t(0x0d3), uint16_t(0x013)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x013)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x013)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x013)}, + [2]uint16_t{uint16_t(0x0d3), uint16_t(0x013)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x013)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x013)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, + [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, + [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, + [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, + [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, [2]uint16_t{uint16_t(0x0d3), uint16_t(0x093)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, + [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, + [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, + [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, + [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, + [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, + [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, + [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, + [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x053)}, [2]uint16_t{uint16_t(0x153), uint16_t(0x153)}, +} /* cost_enc.c:22:16 */ + +func VariableLevelCost(tls *libc.TLS, level int32, probas uintptr) int32 { /* cost_enc.c:42:12: */ + var pattern int32 = int32(*(*uint16_t)(unsafe.Pointer((uintptr(unsafe.Pointer(&VP8LevelCodes)) + uintptr((level-1))*4)))) + var bits int32 = int32(*(*uint16_t)(unsafe.Pointer((uintptr(unsafe.Pointer(&VP8LevelCodes)) + uintptr((level-1))*4) + 1*2))) + var cost int32 = 0 + var i int32 + for i = 2; pattern != 0; i++ { + if (pattern & 1) != 0 { + cost = cost + (VP8BitCost(tls, (bits & 1), *(*uint8_t)(unsafe.Pointer(probas + uintptr(i))))) + } + bits >>= 1 + pattern >>= 1 + } + return cost +} + +//------------------------------------------------------------------------------ +// Pre-calc level costs once for all + +func VP8CalculateLevelCosts(tls *libc.TLS, proba uintptr) { /* cost_enc.c:60:6: */ + var ctype int32 + var band int32 + var ctx int32 + + if !((*VP8EncProba)(unsafe.Pointer(proba)).dirty_ != 0) { + return + } // nothing to do. + + for ctype = 0; ctype < NUM_TYPES; ctype++ { + var n int32 + for band = 0; band < NUM_BANDS; band++ { + for ctx = 0; ctx < NUM_CTX; ctx++ { + var p uintptr = (((proba + 4 /* &.coeffs_ */ + uintptr(ctype)*264) + uintptr(band)*33) + uintptr(ctx)*11) + var table uintptr = (((proba + 5284 /* &.level_cost_ */ + uintptr(ctype)*3264) + uintptr(band)*408) + uintptr(ctx)*136) + var cost0 int32 + if ctx > 0 { + cost0 = VP8BitCost(tls, 1, *(*uint8_t)(unsafe.Pointer(p))) + } else { + cost0 = 0 + } + var cost_base int32 = (VP8BitCost(tls, 1, *(*uint8_t)(unsafe.Pointer(p + 1))) + cost0) + var v int32 + *(*uint16_t)(unsafe.Pointer(table)) = (uint16_t(VP8BitCost(tls, 0, *(*uint8_t)(unsafe.Pointer(p + 1))) + cost0)) + for v = 1; v <= MAX_VARIABLE_LEVEL; v++ { + *(*uint16_t)(unsafe.Pointer(table + uintptr(v)*2)) = (uint16_t(cost_base + VariableLevelCost(tls, v, p))) + } + // Starting at level 67 and up, the variable part of the cost is + // actually constant. + } + } + for n = 0; n < 16; n++ { // replicate bands. We don't need to sentinel. + for ctx = 0; ctx < NUM_CTX; ctx++ { + *(*uintptr)(unsafe.Pointer((((proba + 18344 /* &.remapped_costs_ */) + uintptr(ctype)*384) + uintptr(n)*24) + uintptr(ctx)*8)) = (((proba + 5284 /* &.level_cost_ */ + uintptr(ctype)*3264) + uintptr(VP8EncBands[n])*408) + uintptr(ctx)*136) + } + } + } + (*VP8EncProba)(unsafe.Pointer(proba)).dirty_ = 0 +} + +//------------------------------------------------------------------------------ +// Mode cost tables. + +// These are the fixed probabilities (in the coding trees) turned into bit-cost +// by calling VP8BitCost(). +var VP8FixedCostsUV = [4]uint16_t{uint16_t(302), uint16_t(984), uint16_t(439), uint16_t(642)} /* cost_enc.c:97:16 */ +// note: these values include the fixed VP8BitCost(1, 145) mode selection cost. +var VP8FixedCostsI16 = [4]uint16_t{uint16_t(663), uint16_t(919), uint16_t(872), uint16_t(919)} /* cost_enc.c:99:16 */ +var VP8FixedCostsI4 = [10][10][10]uint16_t{[10][10]uint16_t{ + [10]uint16_t{uint16_t(40), uint16_t(1151), uint16_t(1723), uint16_t(1874), uint16_t(2103), uint16_t(2019), uint16_t(1628), uint16_t(1777), uint16_t(2226), uint16_t(2137)}, + [10]uint16_t{uint16_t(192), uint16_t(469), uint16_t(1296), uint16_t(1308), uint16_t(1849), uint16_t(1794), uint16_t(1781), uint16_t(1703), uint16_t(1713), uint16_t(1522)}, + [10]uint16_t{uint16_t(142), uint16_t(910), uint16_t(762), uint16_t(1684), uint16_t(1849), uint16_t(1576), uint16_t(1460), uint16_t(1305), uint16_t(1801), uint16_t(1657)}, + [10]uint16_t{uint16_t(559), uint16_t(641), uint16_t(1370), uint16_t(421), uint16_t(1182), uint16_t(1569), uint16_t(1612), uint16_t(1725), uint16_t(863), uint16_t(1007)}, + [10]uint16_t{uint16_t(299), uint16_t(1059), uint16_t(1256), uint16_t(1108), uint16_t(636), uint16_t(1068), uint16_t(1581), uint16_t(1883), uint16_t(869), uint16_t(1142)}, + [10]uint16_t{uint16_t(277), uint16_t(1111), uint16_t(707), uint16_t(1362), uint16_t(1089), uint16_t(672), uint16_t(1603), uint16_t(1541), uint16_t(1545), uint16_t(1291)}, + [10]uint16_t{uint16_t(214), uint16_t(781), uint16_t(1609), uint16_t(1303), uint16_t(1632), uint16_t(2229), uint16_t(726), uint16_t(1560), uint16_t(1713), uint16_t(918)}, + [10]uint16_t{uint16_t(152), uint16_t(1037), uint16_t(1046), uint16_t(1759), uint16_t(1983), uint16_t(2174), uint16_t(1358), uint16_t(742), uint16_t(1740), uint16_t(1390)}, + [10]uint16_t{uint16_t(512), uint16_t(1046), uint16_t(1420), uint16_t(753), uint16_t(752), uint16_t(1297), uint16_t(1486), uint16_t(1613), uint16_t(460), uint16_t(1207)}, + [10]uint16_t{uint16_t(424), uint16_t(827), uint16_t(1362), uint16_t(719), uint16_t(1462), uint16_t(1202), uint16_t(1199), uint16_t(1476), uint16_t(1199), uint16_t(538)}}, + [10][10]uint16_t{[10]uint16_t{uint16_t(240), uint16_t(402), uint16_t(1134), uint16_t(1491), uint16_t(1659), uint16_t(1505), uint16_t(1517), uint16_t(1555), uint16_t(1979), uint16_t(2099)}, + [10]uint16_t{uint16_t(467), uint16_t(242), uint16_t(960), uint16_t(1232), uint16_t(1714), uint16_t(1620), uint16_t(1834), uint16_t(1570), uint16_t(1676), uint16_t(1391)}, + [10]uint16_t{uint16_t(500), uint16_t(455), uint16_t(463), uint16_t(1507), uint16_t(1699), uint16_t(1282), uint16_t(1564), uint16_t(982), uint16_t(2114), uint16_t(2114)}, + [10]uint16_t{uint16_t(672), uint16_t(643), uint16_t(1372), uint16_t(331), uint16_t(1589), uint16_t(1667), uint16_t(1453), uint16_t(1938), uint16_t(996), uint16_t(876)}, + [10]uint16_t{uint16_t(458), uint16_t(783), uint16_t(1037), uint16_t(911), uint16_t(738), uint16_t(968), uint16_t(1165), uint16_t(1518), uint16_t(859), uint16_t(1033)}, + [10]uint16_t{uint16_t(504), uint16_t(815), uint16_t(504), uint16_t(1139), uint16_t(1219), uint16_t(719), uint16_t(1506), uint16_t(1085), uint16_t(1268), uint16_t(1268)}, + [10]uint16_t{uint16_t(333), uint16_t(630), uint16_t(1445), uint16_t(1239), uint16_t(1883), uint16_t(3672), uint16_t(799), uint16_t(1548), uint16_t(1865), uint16_t(598)}, + [10]uint16_t{uint16_t(399), uint16_t(644), uint16_t(746), uint16_t(1342), uint16_t(1856), uint16_t(1350), uint16_t(1493), uint16_t(613), uint16_t(1855), uint16_t(1015)}, + [10]uint16_t{uint16_t(622), uint16_t(749), uint16_t(1205), uint16_t(608), uint16_t(1066), uint16_t(1408), uint16_t(1290), uint16_t(1406), uint16_t(546), uint16_t(971)}, + [10]uint16_t{uint16_t(500), uint16_t(753), uint16_t(1041), uint16_t(668), uint16_t(1230), uint16_t(1617), uint16_t(1297), uint16_t(1425), uint16_t(1383), uint16_t(523)}}, + [10][10]uint16_t{[10]uint16_t{uint16_t(394), uint16_t(553), uint16_t(523), uint16_t(1502), uint16_t(1536), uint16_t(981), uint16_t(1608), uint16_t(1142), uint16_t(1666), uint16_t(2181)}, + [10]uint16_t{uint16_t(655), uint16_t(430), uint16_t(375), uint16_t(1411), uint16_t(1861), uint16_t(1220), uint16_t(1677), uint16_t(1135), uint16_t(1978), uint16_t(1553)}, + [10]uint16_t{uint16_t(690), uint16_t(640), uint16_t(245), uint16_t(1954), uint16_t(2070), uint16_t(1194), uint16_t(1528), uint16_t(982), uint16_t(1972), uint16_t(2232)}, + [10]uint16_t{uint16_t(559), uint16_t(834), uint16_t(741), uint16_t(867), uint16_t(1131), uint16_t(980), uint16_t(1225), uint16_t(852), uint16_t(1092), uint16_t(784)}, + [10]uint16_t{uint16_t(690), uint16_t(875), uint16_t(516), uint16_t(959), uint16_t(673), uint16_t(894), uint16_t(1056), uint16_t(1190), uint16_t(1528), uint16_t(1126)}, + [10]uint16_t{uint16_t(740), uint16_t(951), uint16_t(384), uint16_t(1277), uint16_t(1177), uint16_t(492), uint16_t(1579), uint16_t(1155), uint16_t(1846), uint16_t(1513)}, + [10]uint16_t{uint16_t(323), uint16_t(775), uint16_t(1062), uint16_t(1776), uint16_t(3062), uint16_t(1274), uint16_t(813), uint16_t(1188), uint16_t(1372), uint16_t(655)}, + [10]uint16_t{uint16_t(488), uint16_t(971), uint16_t(484), uint16_t(1767), uint16_t(1515), uint16_t(1775), uint16_t(1115), uint16_t(503), uint16_t(1539), uint16_t(1461)}, + [10]uint16_t{uint16_t(740), uint16_t(1006), uint16_t(998), uint16_t(709), uint16_t(851), uint16_t(1230), uint16_t(1337), uint16_t(788), uint16_t(741), uint16_t(721)}, + [10]uint16_t{uint16_t(522), uint16_t(1073), uint16_t(573), uint16_t(1045), uint16_t(1346), uint16_t(887), uint16_t(1046), uint16_t(1146), uint16_t(1203), uint16_t(697)}}, + [10][10]uint16_t{[10]uint16_t{uint16_t(105), uint16_t(864), uint16_t(1442), uint16_t(1009), uint16_t(1934), uint16_t(1840), uint16_t(1519), uint16_t(1920), uint16_t(1673), uint16_t(1579)}, + [10]uint16_t{uint16_t(534), uint16_t(305), uint16_t(1193), uint16_t(683), uint16_t(1388), uint16_t(2164), uint16_t(1802), uint16_t(1894), uint16_t(1264), uint16_t(1170)}, + [10]uint16_t{uint16_t(305), uint16_t(518), uint16_t(877), uint16_t(1108), uint16_t(1426), uint16_t(3215), uint16_t(1425), uint16_t(1064), uint16_t(1320), uint16_t(1242)}, + [10]uint16_t{uint16_t(683), uint16_t(732), uint16_t(1927), uint16_t(257), uint16_t(1493), uint16_t(2048), uint16_t(1858), uint16_t(1552), uint16_t(1055), uint16_t(947)}, + [10]uint16_t{uint16_t(394), uint16_t(814), uint16_t(1024), uint16_t(660), uint16_t(959), uint16_t(1556), uint16_t(1282), uint16_t(1289), uint16_t(893), uint16_t(1047)}, + [10]uint16_t{uint16_t(528), uint16_t(615), uint16_t(996), uint16_t(940), uint16_t(1201), uint16_t(635), uint16_t(1094), uint16_t(2515), uint16_t(803), uint16_t(1358)}, + [10]uint16_t{uint16_t(347), uint16_t(614), uint16_t(1609), uint16_t(1187), uint16_t(3133), uint16_t(1345), uint16_t(1007), uint16_t(1339), uint16_t(1017), uint16_t(667)}, + [10]uint16_t{uint16_t(218), uint16_t(740), uint16_t(878), uint16_t(1605), uint16_t(3650), uint16_t(3650), uint16_t(1345), uint16_t(758), uint16_t(1357), uint16_t(1617)}, + [10]uint16_t{uint16_t(672), uint16_t(750), uint16_t(1541), uint16_t(558), uint16_t(1257), uint16_t(1599), uint16_t(1870), uint16_t(2135), uint16_t(402), uint16_t(1087)}, + [10]uint16_t{uint16_t(592), uint16_t(684), uint16_t(1161), uint16_t(430), uint16_t(1092), uint16_t(1497), uint16_t(1475), uint16_t(1489), uint16_t(1095), uint16_t(822)}}, + [10][10]uint16_t{[10]uint16_t{uint16_t(228), uint16_t(1056), uint16_t(1059), uint16_t(1368), uint16_t(752), uint16_t(982), uint16_t(1512), uint16_t(1518), uint16_t(987), uint16_t(1782)}, + [10]uint16_t{uint16_t(494), uint16_t(514), uint16_t(818), uint16_t(942), uint16_t(965), uint16_t(892), uint16_t(1610), uint16_t(1356), uint16_t(1048), uint16_t(1363)}, + [10]uint16_t{uint16_t(512), uint16_t(648), uint16_t(591), uint16_t(1042), uint16_t(761), uint16_t(991), uint16_t(1196), uint16_t(1454), uint16_t(1309), uint16_t(1463)}, + [10]uint16_t{uint16_t(683), uint16_t(749), uint16_t(1043), uint16_t(676), uint16_t(841), uint16_t(1396), uint16_t(1133), uint16_t(1138), uint16_t(654), uint16_t(939)}, + [10]uint16_t{uint16_t(622), uint16_t(1101), uint16_t(1126), uint16_t(994), uint16_t(361), uint16_t(1077), uint16_t(1203), uint16_t(1318), uint16_t(877), uint16_t(1219)}, + [10]uint16_t{uint16_t(631), uint16_t(1068), uint16_t(857), uint16_t(1650), uint16_t(651), uint16_t(477), uint16_t(1650), uint16_t(1419), uint16_t(828), uint16_t(1170)}, + [10]uint16_t{uint16_t(555), uint16_t(727), uint16_t(1068), uint16_t(1335), uint16_t(3127), uint16_t(1339), uint16_t(820), uint16_t(1331), uint16_t(1077), uint16_t(429)}, + [10]uint16_t{uint16_t(504), uint16_t(879), uint16_t(624), uint16_t(1398), uint16_t(889), uint16_t(889), uint16_t(1392), uint16_t(808), uint16_t(891), uint16_t(1406)}, + [10]uint16_t{uint16_t(683), uint16_t(1602), uint16_t(1289), uint16_t(977), uint16_t(578), uint16_t(983), uint16_t(1280), uint16_t(1708), uint16_t(406), uint16_t(1122)}, + [10]uint16_t{uint16_t(399), uint16_t(865), uint16_t(1433), uint16_t(1070), uint16_t(1072), uint16_t(764), uint16_t(968), uint16_t(1477), uint16_t(1223), uint16_t(678)}}, + [10][10]uint16_t{[10]uint16_t{uint16_t(333), uint16_t(760), uint16_t(935), uint16_t(1638), uint16_t(1010), uint16_t(529), uint16_t(1646), uint16_t(1410), uint16_t(1472), uint16_t(2219)}, + [10]uint16_t{uint16_t(512), uint16_t(494), uint16_t(750), uint16_t(1160), uint16_t(1215), uint16_t(610), uint16_t(1870), uint16_t(1868), uint16_t(1628), uint16_t(1169)}, + [10]uint16_t{uint16_t(572), uint16_t(646), uint16_t(492), uint16_t(1934), uint16_t(1208), uint16_t(603), uint16_t(1580), uint16_t(1099), uint16_t(1398), uint16_t(1995)}, + [10]uint16_t{uint16_t(786), uint16_t(789), uint16_t(942), uint16_t(581), uint16_t(1018), uint16_t(951), uint16_t(1599), uint16_t(1207), uint16_t(731), uint16_t(768)}, + [10]uint16_t{uint16_t(690), uint16_t(1015), uint16_t(672), uint16_t(1078), uint16_t(582), uint16_t(504), uint16_t(1693), uint16_t(1438), uint16_t(1108), uint16_t(2897)}, + [10]uint16_t{uint16_t(768), uint16_t(1267), uint16_t(571), uint16_t(2005), uint16_t(1243), uint16_t(244), uint16_t(2881), uint16_t(1380), uint16_t(1786), uint16_t(1453)}, + [10]uint16_t{uint16_t(452), uint16_t(899), uint16_t(1293), uint16_t(903), uint16_t(1311), uint16_t(3100), uint16_t(465), uint16_t(1311), uint16_t(1319), uint16_t(813)}, + [10]uint16_t{uint16_t(394), uint16_t(927), uint16_t(942), uint16_t(1103), uint16_t(1358), uint16_t(1104), uint16_t(946), uint16_t(593), uint16_t(1363), uint16_t(1109)}, + [10]uint16_t{uint16_t(559), uint16_t(1005), uint16_t(1007), uint16_t(1016), uint16_t(658), uint16_t(1173), uint16_t(1021), uint16_t(1164), uint16_t(623), uint16_t(1028)}, + [10]uint16_t{uint16_t(564), uint16_t(796), uint16_t(632), uint16_t(1005), uint16_t(1014), uint16_t(863), uint16_t(2316), uint16_t(1268), uint16_t(938), uint16_t(764)}}, + [10][10]uint16_t{[10]uint16_t{uint16_t(266), uint16_t(606), uint16_t(1098), uint16_t(1228), uint16_t(1497), uint16_t(1243), uint16_t(948), uint16_t(1030), uint16_t(1734), uint16_t(1461)}, + [10]uint16_t{uint16_t(366), uint16_t(585), uint16_t(901), uint16_t(1060), uint16_t(1407), uint16_t(1247), uint16_t(876), uint16_t(1134), uint16_t(1620), uint16_t(1054)}, + [10]uint16_t{uint16_t(452), uint16_t(565), uint16_t(542), uint16_t(1729), uint16_t(1479), uint16_t(1479), uint16_t(1016), uint16_t(886), uint16_t(2938), uint16_t(1150)}, + [10]uint16_t{uint16_t(555), uint16_t(1088), uint16_t(1533), uint16_t(950), uint16_t(1354), uint16_t(895), uint16_t(834), uint16_t(1019), uint16_t(1021), uint16_t(496)}, + [10]uint16_t{uint16_t(704), uint16_t(815), uint16_t(1193), uint16_t(971), uint16_t(973), uint16_t(640), uint16_t(1217), uint16_t(2214), uint16_t(832), uint16_t(578)}, + [10]uint16_t{uint16_t(672), uint16_t(1245), uint16_t(579), uint16_t(871), uint16_t(875), uint16_t(774), uint16_t(872), uint16_t(1273), uint16_t(1027), uint16_t(949)}, + [10]uint16_t{uint16_t(296), uint16_t(1134), uint16_t(2050), uint16_t(1784), uint16_t(1636), uint16_t(3425), uint16_t(442), uint16_t(1550), uint16_t(2076), uint16_t(722)}, + [10]uint16_t{uint16_t(342), uint16_t(982), uint16_t(1259), uint16_t(1846), uint16_t(1848), uint16_t(1848), uint16_t(622), uint16_t(568), uint16_t(1847), uint16_t(1052)}, + [10]uint16_t{uint16_t(555), uint16_t(1064), uint16_t(1304), uint16_t(828), uint16_t(746), uint16_t(1343), uint16_t(1075), uint16_t(1329), uint16_t(1078), uint16_t(494)}, + [10]uint16_t{uint16_t(288), uint16_t(1167), uint16_t(1285), uint16_t(1174), uint16_t(1639), uint16_t(1639), uint16_t(833), uint16_t(2254), uint16_t(1304), uint16_t(509)}}, + [10][10]uint16_t{[10]uint16_t{uint16_t(342), uint16_t(719), uint16_t(767), uint16_t(1866), uint16_t(1757), uint16_t(1270), uint16_t(1246), uint16_t(550), uint16_t(1746), uint16_t(2151)}, + [10]uint16_t{uint16_t(483), uint16_t(653), uint16_t(694), uint16_t(1509), uint16_t(1459), uint16_t(1410), uint16_t(1218), uint16_t(507), uint16_t(1914), uint16_t(1266)}, + [10]uint16_t{uint16_t(488), uint16_t(757), uint16_t(447), uint16_t(2979), uint16_t(1813), uint16_t(1268), uint16_t(1654), uint16_t(539), uint16_t(1849), uint16_t(2109)}, + [10]uint16_t{uint16_t(522), uint16_t(1097), uint16_t(1085), uint16_t(851), uint16_t(1365), uint16_t(1111), uint16_t(851), uint16_t(901), uint16_t(961), uint16_t(605)}, + [10]uint16_t{uint16_t(709), uint16_t(716), uint16_t(841), uint16_t(728), uint16_t(736), uint16_t(945), uint16_t(941), uint16_t(862), uint16_t(2845), uint16_t(1057)}, + [10]uint16_t{uint16_t(512), uint16_t(1323), uint16_t(500), uint16_t(1336), uint16_t(1083), uint16_t(681), uint16_t(1342), uint16_t(717), uint16_t(1604), uint16_t(1350)}, + [10]uint16_t{uint16_t(452), uint16_t(1155), uint16_t(1372), uint16_t(1900), uint16_t(1501), uint16_t(3290), uint16_t(311), uint16_t(944), uint16_t(1919), uint16_t(922)}, + [10]uint16_t{uint16_t(403), uint16_t(1520), uint16_t(977), uint16_t(2132), uint16_t(1733), uint16_t(3522), uint16_t(1076), uint16_t(276), uint16_t(3335), uint16_t(1547)}, + [10]uint16_t{uint16_t(559), uint16_t(1374), uint16_t(1101), uint16_t(615), uint16_t(673), uint16_t(2462), uint16_t(974), uint16_t(795), uint16_t(984), uint16_t(984)}, + [10]uint16_t{uint16_t(547), uint16_t(1122), uint16_t(1062), uint16_t(812), uint16_t(1410), uint16_t(951), uint16_t(1140), uint16_t(622), uint16_t(1268), uint16_t(651)}}, + [10][10]uint16_t{[10]uint16_t{uint16_t(165), uint16_t(982), uint16_t(1235), uint16_t(938), uint16_t(1334), uint16_t(1366), uint16_t(1659), uint16_t(1578), uint16_t(964), uint16_t(1612)}, + [10]uint16_t{uint16_t(592), uint16_t(422), uint16_t(925), uint16_t(847), uint16_t(1139), uint16_t(1112), uint16_t(1387), uint16_t(2036), uint16_t(861), uint16_t(1041)}, + [10]uint16_t{uint16_t(403), uint16_t(837), uint16_t(732), uint16_t(770), uint16_t(941), uint16_t(1658), uint16_t(1250), uint16_t(809), uint16_t(1407), uint16_t(1407)}, + [10]uint16_t{uint16_t(896), uint16_t(874), uint16_t(1071), uint16_t(381), uint16_t(1568), uint16_t(1722), uint16_t(1437), uint16_t(2192), uint16_t(480), uint16_t(1035)}, + [10]uint16_t{uint16_t(640), uint16_t(1098), uint16_t(1012), uint16_t(1032), uint16_t(684), uint16_t(1382), uint16_t(1581), uint16_t(2106), uint16_t(416), uint16_t(865)}, + [10]uint16_t{uint16_t(559), uint16_t(1005), uint16_t(819), uint16_t(914), uint16_t(710), uint16_t(770), uint16_t(1418), uint16_t(920), uint16_t(838), uint16_t(1435)}, + [10]uint16_t{uint16_t(415), uint16_t(1258), uint16_t(1245), uint16_t(870), uint16_t(1278), uint16_t(3067), uint16_t(770), uint16_t(1021), uint16_t(1287), uint16_t(522)}, + [10]uint16_t{uint16_t(406), uint16_t(990), uint16_t(601), uint16_t(1009), uint16_t(1265), uint16_t(1265), uint16_t(1267), uint16_t(759), uint16_t(1017), uint16_t(1277)}, + [10]uint16_t{uint16_t(968), uint16_t(1182), uint16_t(1329), uint16_t(788), uint16_t(1032), uint16_t(1292), uint16_t(1705), uint16_t(1714), uint16_t(203), uint16_t(1403)}, + [10]uint16_t{uint16_t(732), uint16_t(877), uint16_t(1279), uint16_t(471), uint16_t(901), uint16_t(1161), uint16_t(1545), uint16_t(1294), uint16_t(755), uint16_t(755)}}, + [10][10]uint16_t{[10]uint16_t{uint16_t(111), uint16_t(931), uint16_t(1378), uint16_t(1185), uint16_t(1933), uint16_t(1648), uint16_t(1148), uint16_t(1714), uint16_t(1873), uint16_t(1307)}, + [10]uint16_t{uint16_t(406), uint16_t(414), uint16_t(1030), uint16_t(1023), uint16_t(1910), uint16_t(1404), uint16_t(1313), uint16_t(1647), uint16_t(1509), uint16_t(793)}, + [10]uint16_t{uint16_t(342), uint16_t(640), uint16_t(575), uint16_t(1088), uint16_t(1241), uint16_t(1349), uint16_t(1161), uint16_t(1350), uint16_t(1756), uint16_t(1502)}, + [10]uint16_t{uint16_t(559), uint16_t(766), uint16_t(1185), uint16_t(357), uint16_t(1682), uint16_t(1428), uint16_t(1329), uint16_t(1897), uint16_t(1219), uint16_t(802)}, + [10]uint16_t{uint16_t(473), uint16_t(909), uint16_t(1164), uint16_t(771), uint16_t(719), uint16_t(2508), uint16_t(1427), uint16_t(1432), uint16_t(722), uint16_t(782)}, + [10]uint16_t{uint16_t(342), uint16_t(892), uint16_t(785), uint16_t(1145), uint16_t(1150), uint16_t(794), uint16_t(1296), uint16_t(1550), uint16_t(973), uint16_t(1057)}, + [10]uint16_t{uint16_t(208), uint16_t(1036), uint16_t(1326), uint16_t(1343), uint16_t(1606), uint16_t(3395), uint16_t(815), uint16_t(1455), uint16_t(1618), uint16_t(712)}, + [10]uint16_t{uint16_t(228), uint16_t(928), uint16_t(890), uint16_t(1046), uint16_t(3499), uint16_t(1711), uint16_t(994), uint16_t(829), uint16_t(1720), uint16_t(1318)}, + [10]uint16_t{uint16_t(768), uint16_t(724), uint16_t(1058), uint16_t(636), uint16_t(991), uint16_t(1075), uint16_t(1319), uint16_t(1324), uint16_t(616), uint16_t(825)}, + [10]uint16_t{uint16_t(305), uint16_t(1167), uint16_t(1358), uint16_t(899), uint16_t(1587), uint16_t(1587), uint16_t(987), uint16_t(1988), uint16_t(1332), uint16_t(501)}}} /* cost_enc.c:100:16 */ + +//------------------------------------------------------------------------------ +// helper functions for residuals struct VP8Residual. + +func VP8InitResidual(tls *libc.TLS, first int32, coeff_type int32, enc uintptr, res uintptr) { /* cost_enc.c:206:6: */ + (*VP8Residual)(unsafe.Pointer(res)).coeff_type = coeff_type + (*VP8Residual)(unsafe.Pointer(res)).prob = (((enc + 3616 /* &.proba_ */) + 4 /* &.coeffs_ */) + uintptr(coeff_type)*264) + (*VP8Residual)(unsafe.Pointer(res)).stats = (((enc + 3616 /* &.proba_ */) + 1060 /* &.stats_ */) + uintptr(coeff_type)*1056) + (*VP8Residual)(unsafe.Pointer(res)).costs = (((enc + 3616 /* &.proba_ */) + 18344 /* &.remapped_costs_ */) + uintptr(coeff_type)*384) + (*VP8Residual)(unsafe.Pointer(res)).first = first +} + +//------------------------------------------------------------------------------ +// Mode costs + +func VP8GetCostLuma4(tls *libc.TLS, it uintptr, levels uintptr) int32 { /* cost_enc.c:218:5: */ + bp := tls.Alloc(48) + defer tls.Free(48) + + var x int32 = ((*VP8EncIterator)(unsafe.Pointer(it)).i4_ & 3) + var y int32 = ((*VP8EncIterator)(unsafe.Pointer(it)).i4_ >> 2) + // var res VP8Residual at bp, 48 + + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var R int32 = 0 + var ctx int32 + + VP8InitResidual(tls, 0, 3, enc, (bp) /* &res */) + ctx = (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(x)*4)) + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + uintptr(y)*4))) + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8SetResidualCoeffs})).f(tls, levels, (bp) /* &res */) + R = R + ((*struct { + f func(*libc.TLS, int32, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8GetResidualCost})).f(tls, ctx, (bp) /* &res */)) + return R +} + +func VP8GetCostLuma16(tls *libc.TLS, it uintptr, rd uintptr) int32 { /* cost_enc.c:232:5: */ + bp := tls.Alloc(48) + defer tls.Free(48) + + // var res VP8Residual at bp, 48 + + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var x int32 + var y int32 + var R int32 = 0 + + VP8IteratorNzToBytes(tls, it) // re-import the non-zero context + + // DC + VP8InitResidual(tls, 0, 1, enc, (bp) /* &res */) + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8SetResidualCoeffs})).f(tls, (rd + 40 /* &.y_dc_levels */), (bp) /* &res */) + R = R + ((*struct { + f func(*libc.TLS, int32, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8GetResidualCost})).f(tls, (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + 8*4)) + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + 8*4))), (bp) /* &res */)) + + // AC + VP8InitResidual(tls, 1, 0, enc, (bp) /* &res */) + for y = 0; y < 4; y++ { + for x = 0; x < 4; x++ { + var ctx int32 = (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(x)*4)) + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + uintptr(y)*4))) + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8SetResidualCoeffs})).f(tls, ((rd + 72 /* &.y_ac_levels */) + uintptr((x+(y*4)))*32), (bp) /* &res */) + R = R + ((*struct { + f func(*libc.TLS, int32, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8GetResidualCost})).f(tls, ctx, (bp) /* &res */)) + *(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(x)*4)) = libc.AssignPtrInt32(((it + 168 /* &.left_nz_ */) + uintptr(y)*4), (libc.Bool32((*VP8Residual)(unsafe.Pointer(bp /* &res */)).last >= 0))) + } + } + return R +} + +func VP8GetCostUV(tls *libc.TLS, it uintptr, rd uintptr) int32 { /* cost_enc.c:258:5: */ + bp := tls.Alloc(48) + defer tls.Free(48) + + // var res VP8Residual at bp, 48 + + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var ch int32 + var x int32 + var y int32 + var R int32 = 0 + + VP8IteratorNzToBytes(tls, it) // re-import the non-zero context + + VP8InitResidual(tls, 0, 2, enc, (bp) /* &res */) + for ch = 0; ch <= 2; ch = ch + (2) { + for y = 0; y < 2; y++ { + for x = 0; x < 2; x++ { + var ctx int32 = (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(((4+ch)+x))*4)) + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + uintptr(((4+ch)+y))*4))) + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8SetResidualCoeffs})).f(tls, ((rd + 584 /* &.uv_levels */) + uintptr((((ch*2)+x)+(y*2)))*32), (bp) /* &res */) + R = R + ((*struct { + f func(*libc.TLS, int32, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8GetResidualCost})).f(tls, ctx, (bp) /* &res */)) + *(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(((4+ch)+x))*4)) = libc.AssignPtrInt32(((it + 168 /* &.left_nz_ */) + uintptr(((4+ch)+y))*4), (libc.Bool32((*VP8Residual)(unsafe.Pointer(bp /* &res */)).last >= 0))) + } + } + } + return R +} + +//------------------------------------------------------------------------------ +// Recording of token probabilities. + +// We keep the table-free variant around for reference, in case. + +// Simulate block coding, but only record statistics. +// Note: no need to record the fixed probas. +func VP8RecordCoeffs(tls *libc.TLS, ctx int32, res uintptr) int32 { /* cost_enc.c:289:5: */ + var n int32 = (*VP8Residual)(unsafe.Pointer(res)).first + // should be stats[VP8EncBands[n]], but it's equivalent for n=0 or 1 + var s uintptr = (((*VP8Residual)(unsafe.Pointer(res)).stats + uintptr(n)*132) + uintptr(ctx)*44) + if (*VP8Residual)(unsafe.Pointer(res)).last < 0 { + VP8RecordStats(tls, 0, (s + uintptr(0)*4)) + return 0 + } + for n <= (*VP8Residual)(unsafe.Pointer(res)).last { + var v int32 + VP8RecordStats(tls, 1, (s + uintptr(0)*4)) // order of record doesn't matter + for (libc.AssignInt32(&v, int32(*(*int16_t)(unsafe.Pointer((*VP8Residual)(unsafe.Pointer(res)).coeffs + uintptr(libc.PostIncInt32(&n, 1))*2))))) == 0 { + VP8RecordStats(tls, 0, (s + uintptr(1)*4)) + s = ((*VP8Residual)(unsafe.Pointer(res)).stats + uintptr(VP8EncBands[n])*132) + } + VP8RecordStats(tls, 1, (s + uintptr(1)*4)) + if !(VP8RecordStats(tls, (libc.Bool32(2 < (uint32(v+1)))), (s+uintptr(2)*4)) != 0) { // v = -1 or 1 + s = (((*VP8Residual)(unsafe.Pointer(res)).stats + uintptr(VP8EncBands[n])*132) + 1*44) + } else { + v = libc.Xabs(tls, v) + if v > MAX_VARIABLE_LEVEL { + v = MAX_VARIABLE_LEVEL + } + + { + var bits int32 = int32(*(*uint16_t)(unsafe.Pointer((uintptr(unsafe.Pointer(&VP8LevelCodes)) + uintptr((v-1))*4) + 1*2))) + var pattern int32 = int32(*(*uint16_t)(unsafe.Pointer((uintptr(unsafe.Pointer(&VP8LevelCodes)) + uintptr((v-1))*4)))) + var i int32 + for i = 0; (libc.AssignShrInt32(&pattern, int(1))) != 0; i++ { + var mask int32 = (int32(2) << i) + if (pattern & 1) != 0 { + VP8RecordStats(tls, libc.BoolInt32(!(!((bits & mask) != 0))), ((s + uintptr(3)*4) + uintptr(i)*4)) + } + } + + } + s = (((*VP8Residual)(unsafe.Pointer(res)).stats + uintptr(VP8EncBands[n])*132) + 2*44) + } + } + if n < 16 { + VP8RecordStats(tls, 0, (s + uintptr(0)*4)) + } + return 1 +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +// This table gives, for a given sharpness, the filtering strength to be +// used (at least) in order to filter a given edge step delta. +// This is constructed by brute force inspection: for all delta, we iterate +// over all possible filtering strength / thresh until needs_filter() returns +// true. +var kLevelsFromDelta = [8][64]uint8_t{ + [64]uint8_t{uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(4), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(10), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(14), uint8_t(15), + uint8_t(16), uint8_t(17), uint8_t(18), uint8_t(19), uint8_t(20), uint8_t(21), uint8_t(22), uint8_t(23), uint8_t(24), uint8_t(25), uint8_t(26), uint8_t(27), uint8_t(28), uint8_t(29), uint8_t(30), uint8_t(31), + uint8_t(32), uint8_t(33), uint8_t(34), uint8_t(35), uint8_t(36), uint8_t(37), uint8_t(38), uint8_t(39), uint8_t(40), uint8_t(41), uint8_t(42), uint8_t(43), uint8_t(44), uint8_t(45), uint8_t(46), uint8_t(47), + uint8_t(48), uint8_t(49), uint8_t(50), uint8_t(51), uint8_t(52), uint8_t(53), uint8_t(54), uint8_t(55), uint8_t(56), uint8_t(57), uint8_t(58), uint8_t(59), uint8_t(60), uint8_t(61), uint8_t(62), uint8_t(63)}, + [64]uint8_t{uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(14), uint8_t(15), uint8_t(17), uint8_t(18), + uint8_t(20), uint8_t(21), uint8_t(23), uint8_t(24), uint8_t(26), uint8_t(27), uint8_t(29), uint8_t(30), uint8_t(32), uint8_t(33), uint8_t(35), uint8_t(36), uint8_t(38), uint8_t(39), uint8_t(41), uint8_t(42), + uint8_t(44), uint8_t(45), uint8_t(47), uint8_t(48), uint8_t(50), uint8_t(51), uint8_t(53), uint8_t(54), uint8_t(56), uint8_t(57), uint8_t(59), uint8_t(60), uint8_t(62), uint8_t(63), uint8_t(63), uint8_t(63), + uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63)}, + [64]uint8_t{uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(14), uint8_t(16), uint8_t(17), uint8_t(19), + uint8_t(20), uint8_t(22), uint8_t(23), uint8_t(25), uint8_t(26), uint8_t(28), uint8_t(29), uint8_t(31), uint8_t(32), uint8_t(34), uint8_t(35), uint8_t(37), uint8_t(38), uint8_t(40), uint8_t(41), uint8_t(43), + uint8_t(44), uint8_t(46), uint8_t(47), uint8_t(49), uint8_t(50), uint8_t(52), uint8_t(53), uint8_t(55), uint8_t(56), uint8_t(58), uint8_t(59), uint8_t(61), uint8_t(62), uint8_t(63), uint8_t(63), uint8_t(63), + uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63)}, + [64]uint8_t{uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(15), uint8_t(16), uint8_t(18), uint8_t(19), + uint8_t(21), uint8_t(22), uint8_t(24), uint8_t(25), uint8_t(27), uint8_t(28), uint8_t(30), uint8_t(31), uint8_t(33), uint8_t(34), uint8_t(36), uint8_t(37), uint8_t(39), uint8_t(40), uint8_t(42), uint8_t(43), + uint8_t(45), uint8_t(46), uint8_t(48), uint8_t(49), uint8_t(51), uint8_t(52), uint8_t(54), uint8_t(55), uint8_t(57), uint8_t(58), uint8_t(60), uint8_t(61), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), + uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63)}, + [64]uint8_t{uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(11), uint8_t(12), uint8_t(14), uint8_t(15), uint8_t(17), uint8_t(18), uint8_t(20), + uint8_t(21), uint8_t(23), uint8_t(24), uint8_t(26), uint8_t(27), uint8_t(29), uint8_t(30), uint8_t(32), uint8_t(33), uint8_t(35), uint8_t(36), uint8_t(38), uint8_t(39), uint8_t(41), uint8_t(42), uint8_t(44), + uint8_t(45), uint8_t(47), uint8_t(48), uint8_t(50), uint8_t(51), uint8_t(53), uint8_t(54), uint8_t(56), uint8_t(57), uint8_t(59), uint8_t(60), uint8_t(62), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), + uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63)}, + [64]uint8_t{uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(4), uint8_t(5), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(15), uint8_t(16), uint8_t(17), uint8_t(19), uint8_t(20), + uint8_t(22), uint8_t(23), uint8_t(25), uint8_t(26), uint8_t(28), uint8_t(29), uint8_t(31), uint8_t(32), uint8_t(34), uint8_t(35), uint8_t(37), uint8_t(38), uint8_t(40), uint8_t(41), uint8_t(43), uint8_t(44), + uint8_t(46), uint8_t(47), uint8_t(49), uint8_t(50), uint8_t(52), uint8_t(53), uint8_t(55), uint8_t(56), uint8_t(58), uint8_t(59), uint8_t(61), uint8_t(62), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), + uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63)}, + [64]uint8_t{uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(4), uint8_t(5), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(15), uint8_t(16), uint8_t(18), uint8_t(19), uint8_t(21), + uint8_t(22), uint8_t(24), uint8_t(25), uint8_t(27), uint8_t(28), uint8_t(30), uint8_t(31), uint8_t(33), uint8_t(34), uint8_t(36), uint8_t(37), uint8_t(39), uint8_t(40), uint8_t(42), uint8_t(43), uint8_t(45), + uint8_t(46), uint8_t(48), uint8_t(49), uint8_t(51), uint8_t(52), uint8_t(54), uint8_t(55), uint8_t(57), uint8_t(58), uint8_t(60), uint8_t(61), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), + uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63)}, + [64]uint8_t{uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(4), uint8_t(5), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(11), uint8_t(12), uint8_t(14), uint8_t(15), uint8_t(17), uint8_t(18), uint8_t(20), uint8_t(21), + uint8_t(23), uint8_t(24), uint8_t(26), uint8_t(27), uint8_t(29), uint8_t(30), uint8_t(32), uint8_t(33), uint8_t(35), uint8_t(36), uint8_t(38), uint8_t(39), uint8_t(41), uint8_t(42), uint8_t(44), uint8_t(45), + uint8_t(47), uint8_t(48), uint8_t(50), uint8_t(51), uint8_t(53), uint8_t(54), uint8_t(56), uint8_t(57), uint8_t(59), uint8_t(60), uint8_t(62), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), + uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63), uint8_t(63)}, +} /* filter_enc.c:24:22 */ + +func VP8FilterStrengthFromDelta(tls *libc.TLS, sharpness int32, delta int32) int32 { /* filter_enc.c:59:5: */ + var pos int32 + if delta < 64 { + pos = delta + } else { + pos = (64 - 1) + } + + return int32(*(*uint8_t)(unsafe.Pointer((uintptr(unsafe.Pointer(&kLevelsFromDelta)) + uintptr(sharpness)*64) + uintptr(pos)))) +} + +//------------------------------------------------------------------------------ +// Paragraph 15.4: compute the inner-edge filtering strength + +func GetILevel(tls *libc.TLS, sharpness int32, level int32) int32 { /* filter_enc.c:70:12: */ + if sharpness > 0 { + if sharpness > 4 { + level >>= 2 + } else { + level >>= 1 + } + if level > (9 - sharpness) { + level = (9 - sharpness) + } + } + if level < 1 { + level = 1 + } + return level +} + +func DoFilter1(tls *libc.TLS, it uintptr, level int32) { /* filter_enc.c:85:13: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var ilevel int32 = GetILevel(tls, (*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).filter_sharpness, level) + var limit int32 = ((2 * level) + ilevel) + + var y_dst uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out2_ + uintptr((0))) + var u_dst uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out2_ + uintptr((16))) + var v_dst uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out2_ + uintptr((16 + 8))) + + // copy current block to yuv_out2_ + libc.Xmemcpy(tls, y_dst, (*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_, ((uint64(32 * 16)) * uint64(unsafe.Sizeof(uint8_t(0))))) + + if (*VP8Encoder)(unsafe.Pointer(enc)).filter_hdr_.simple_ == 1 { // simple + (*struct { + f func(*libc.TLS, uintptr, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8SimpleHFilter16i})).f(tls, y_dst, 32, limit) + (*struct { + f func(*libc.TLS, uintptr, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8SimpleVFilter16i})).f(tls, y_dst, 32, limit) + } else { // complex + var hev_thresh int32 + if level >= 40 { + hev_thresh = 2 + } else { + if level >= 15 { + hev_thresh = 1 + } else { + hev_thresh = 0 + } + } + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8HFilter16i})).f(tls, y_dst, 32, limit, ilevel, hev_thresh) + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8HFilter8i})).f(tls, u_dst, v_dst, 32, limit, ilevel, hev_thresh) + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8VFilter16i})).f(tls, y_dst, 32, limit, ilevel, hev_thresh) + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, int32, int32, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8VFilter8i})).f(tls, u_dst, v_dst, 32, limit, ilevel, hev_thresh) + } +} + +//------------------------------------------------------------------------------ +// SSIM metric for one macroblock + +func GetMBSSIM(tls *libc.TLS, yuv1 uintptr, yuv2 uintptr) float64 { /* filter_enc.c:112:15: */ + var x int32 + var y int32 + var sum float64 = 0. + + // compute SSIM in a 10 x 10 window + for y = 3; y < (16 - 3); y++ { + for x = 3; x < (16 - 3); x++ { + sum = sum + ((*struct { + f func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32, int32, int32) float64 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSIMGetClipped})).f(tls, (yuv1 + uintptr((0))), 32, (yuv2 + uintptr((0))), 32, + x, y, 16, 16)) + } + } + for x = 1; x < 7; x++ { + for y = 1; y < 7; y++ { + sum = sum + ((*struct { + f func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32, int32, int32) float64 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSIMGetClipped})).f(tls, (yuv1 + uintptr((16))), 32, (yuv2 + uintptr((16))), 32, + x, y, 8, 8)) + sum = sum + ((*struct { + f func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32, int32, int32) float64 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSIMGetClipped})).f(tls, (yuv1 + uintptr((16 + 8))), 32, (yuv2 + uintptr((16 + 8))), 32, + x, y, 8, 8)) + } + } + return sum +} + +//------------------------------------------------------------------------------ +// Exposed APIs: Encoder should call the following 3 functions to adjust +// loop filter strength + +func VP8InitFilter(tls *libc.TLS, it uintptr) { /* filter_enc.c:140:6: */ + if (*VP8EncIterator)(unsafe.Pointer(it)).lf_stats_ != (uintptr(0)) { + var s int32 + var i int32 + for s = 0; s < NUM_MB_SEGMENTS; s++ { + for i = 0; i < MAX_LF_LEVELS; i++ { + *(*float64)(unsafe.Pointer(((*VP8EncIterator)(unsafe.Pointer(it)).lf_stats_ + uintptr(s)*512) + uintptr(i)*8)) = float64(0) + } + } + VP8SSIMDspInit(tls) + } +} + +func VP8StoreFilterStats(tls *libc.TLS, it uintptr) { /* filter_enc.c:156:6: */ + var d int32 + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var s int32 = (int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.segment_ */)) & 0x60 >> 5)) + var level0 int32 = (*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */) + uintptr(s)*744)).fstrength_ + + // explore +/-quant range of values around level0 + var delta_min int32 = -(*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */) + uintptr(s)*744)).quant_ + var delta_max int32 = (*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */) + uintptr(s)*744)).quant_ + var step_size int32 + if (delta_max - delta_min) >= 4 { + step_size = 4 + } else { + step_size = 1 + } + + if (*VP8EncIterator)(unsafe.Pointer(it)).lf_stats_ == (uintptr(0)) { + return + } + + // NOTE: Currently we are applying filter only across the sublock edges + // There are two reasons for that. + // 1. Applying filter on macro block edges will change the pixels in + // the left and top macro blocks. That will be hard to restore + // 2. Macro Blocks on the bottom and right are not yet compressed. So we + // cannot apply filter on the right and bottom macro block edges. + if ((int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.type_ */)) & 0x3 >> 0)) == 1) && ((uint32(int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.skip_ */)) & 0x10 >> 4))) != 0) { + return + } + + // Always try filter level zero + *(*float64)(unsafe.Pointer(((*VP8EncIterator)(unsafe.Pointer(it)).lf_stats_ + uintptr(s)*512))) += (GetMBSSIM(tls, (*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_, (*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_)) + + for d = delta_min; d <= delta_max; d = d + (step_size) { + var level int32 = (level0 + d) + if (level <= 0) || (level >= MAX_LF_LEVELS) { + continue + } + DoFilter1(tls, it, level) + *(*float64)(unsafe.Pointer((((*VP8EncIterator)(unsafe.Pointer(it)).lf_stats_ + uintptr(s)*512) + uintptr(level)*8))) += (GetMBSSIM(tls, (*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_, (*VP8EncIterator)(unsafe.Pointer(it)).yuv_out2_)) + } +} + +func VP8AdjustFilterStrength(tls *libc.TLS, it uintptr) { /* filter_enc.c:194:6: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + if (*VP8EncIterator)(unsafe.Pointer(it)).lf_stats_ != (uintptr(0)) { + var s int32 + for s = 0; s < NUM_MB_SEGMENTS; s++ { + var i int32 + var best_level int32 = 0 + // Improvement over filter level 0 should be at least 1e-5 (relatively) + var best_v float64 = (1.00001 * *(*float64)(unsafe.Pointer(((*VP8EncIterator)(unsafe.Pointer(it)).lf_stats_ + uintptr(s)*512)))) + for i = 1; i < MAX_LF_LEVELS; i++ { + var v float64 = *(*float64)(unsafe.Pointer(((*VP8EncIterator)(unsafe.Pointer(it)).lf_stats_ + uintptr(s)*512) + uintptr(i)*8)) + if v > best_v { + best_v = v + best_level = i + } + } + (*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */) + uintptr(s)*744)).fstrength_ = best_level + } + return + } + if (*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).filter_strength > 0 { + var max_level int32 = 0 + var s int32 + for s = 0; s < NUM_MB_SEGMENTS; s++ { + var dqm uintptr = ((enc + 608 /* &.dqm_ */) + uintptr(s)*744) + // this '>> 3' accounts for some inverse WHT scaling + var delta int32 = (((*VP8SegmentInfo)(unsafe.Pointer(dqm)).max_edge_ * int32(*(*uint16_t)(unsafe.Pointer((dqm + 224 /* &.y2_ */) /* &.q_ */ + 1*2)))) >> 3) + var level int32 = VP8FilterStrengthFromDelta(tls, (*VP8Encoder)(unsafe.Pointer(enc)).filter_hdr_.sharpness_, delta) + if level > (*VP8SegmentInfo)(unsafe.Pointer(dqm)).fstrength_ { + (*VP8SegmentInfo)(unsafe.Pointer(dqm)).fstrength_ = level + } + if max_level < (*VP8SegmentInfo)(unsafe.Pointer(dqm)).fstrength_ { + max_level = (*VP8SegmentInfo)(unsafe.Pointer(dqm)).fstrength_ + } + } + (*VP8Encoder)(unsafe.Pointer(enc)).filter_hdr_.level_ = max_level + } +} + +// ----------------------------------------------------------------------------- + +// Alpha related constants. + +// Mux related constants. + +// Maximum chunk payload is such that adding the header and padding won't +// overflow a uint32_t. + +//------------------------------------------------------------------------------ +// multi-pass convergence + +// we allow 2k of extra head-room in PARTITION0 limit. + +func Clamp(tls *libc.TLS, v float32, min float32, max float32) float32 { /* frame_enc.c:34:14: */ + if v < min { + return min + } + if v > max { + return max + } + return v +} + +type PassStats = struct { + is_first int32 + dq float32 + q float32 + last_q float32 + qmin float32 + qmax float32 + value float64 + last_value float64 + target float64 + do_size_search int32 + _ [4]byte +} /* frame_enc.c:46:3 */ + +func InitPassStats(tls *libc.TLS, enc uintptr, s uintptr) int32 { /* frame_enc.c:48:12: */ + var target_size uint64_t = uint64_t((*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).target_size) + var do_size_search int32 = (libc.Bool32(target_size != uint64(0))) + var target_PSNR float32 = (*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).target_PSNR + + (*PassStats)(unsafe.Pointer(s)).is_first = 1 + (*PassStats)(unsafe.Pointer(s)).dq = 10. + (*PassStats)(unsafe.Pointer(s)).qmin = (1. * float32((*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).qmin)) + (*PassStats)(unsafe.Pointer(s)).qmax = (1. * float32((*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).qmax)) + (*PassStats)(unsafe.Pointer(s)).q = libc.AssignPtrFloat32((s + 12 /* &.last_q */), Clamp(tls, (*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).quality, (*PassStats)(unsafe.Pointer(s)).qmin, (*PassStats)(unsafe.Pointer(s)).qmax)) + (*PassStats)(unsafe.Pointer(s)).target = func() float64 { + if do_size_search != 0 { + return float64(target_size) + } + return func() float64 { + if float64(target_PSNR) > 0. { + return float64(target_PSNR) + } + return 40. + }() + }() // default, just in case + (*PassStats)(unsafe.Pointer(s)).value = libc.AssignPtrFloat64((s + 32 /* &.last_value */), 0.) + (*PassStats)(unsafe.Pointer(s)).do_size_search = do_size_search + return do_size_search +} + +func ComputeNextQ(tls *libc.TLS, s uintptr) float32 { /* frame_enc.c:66:14: */ + var dq float32 + if (*PassStats)(unsafe.Pointer(s)).is_first != 0 { + if (*PassStats)(unsafe.Pointer(s)).value > (*PassStats)(unsafe.Pointer(s)).target { + dq = -(*PassStats)(unsafe.Pointer(s)).dq + } else { + dq = (*PassStats)(unsafe.Pointer(s)).dq + } + (*PassStats)(unsafe.Pointer(s)).is_first = 0 + } else if (*PassStats)(unsafe.Pointer(s)).value != (*PassStats)(unsafe.Pointer(s)).last_value { + var slope float64 = (((*PassStats)(unsafe.Pointer(s)).target - (*PassStats)(unsafe.Pointer(s)).value) / ((*PassStats)(unsafe.Pointer(s)).last_value - (*PassStats)(unsafe.Pointer(s)).value)) + dq = (float32(slope * (float64((*PassStats)(unsafe.Pointer(s)).last_q - (*PassStats)(unsafe.Pointer(s)).q)))) + } else { + dq = 0. // we're done?! + } + // Limit variable to avoid large swings. + (*PassStats)(unsafe.Pointer(s)).dq = Clamp(tls, dq, -30., 30.) + (*PassStats)(unsafe.Pointer(s)).last_q = (*PassStats)(unsafe.Pointer(s)).q + (*PassStats)(unsafe.Pointer(s)).last_value = (*PassStats)(unsafe.Pointer(s)).value + (*PassStats)(unsafe.Pointer(s)).q = Clamp(tls, ((*PassStats)(unsafe.Pointer(s)).q + (*PassStats)(unsafe.Pointer(s)).dq), (*PassStats)(unsafe.Pointer(s)).qmin, (*PassStats)(unsafe.Pointer(s)).qmax) + return (*PassStats)(unsafe.Pointer(s)).q +} + +//------------------------------------------------------------------------------ +// Tables for level coding + +var VP8Cat3 = [3]uint8_t{uint8_t(173), uint8_t(148), uint8_t(140)} /* frame_enc.c:88:15 */ +var VP8Cat4 = [4]uint8_t{uint8_t(176), uint8_t(155), uint8_t(140), uint8_t(135)} /* frame_enc.c:89:15 */ +var VP8Cat5 = [5]uint8_t{uint8_t(180), uint8_t(157), uint8_t(141), uint8_t(134), uint8_t(130)} /* frame_enc.c:90:15 */ +var VP8Cat6 = [11]uint8_t{uint8_t(254), uint8_t(254), uint8_t(243), uint8_t(230), uint8_t(196), uint8_t(177), uint8_t(153), uint8_t(140), uint8_t(133), uint8_t(130), uint8_t(129)} /* frame_enc.c:91:15 */ + +//------------------------------------------------------------------------------ +// Reset the statistics about: number of skips, token proba, level cost,... + +func ResetStats(tls *libc.TLS, enc uintptr) { /* frame_enc.c:97:13: */ + var proba uintptr = (enc + 3616 /* &.proba_ */) + VP8CalculateLevelCosts(tls, proba) + (*VP8EncProba)(unsafe.Pointer(proba)).nb_skip_ = 0 +} + +//------------------------------------------------------------------------------ +// Skip decision probability + +func CalcSkipProba(tls *libc.TLS, nb uint64_t, total uint64_t) int32 { /* frame_enc.c:108:12: */ + return (func() int32 { + if total != 0 { + return (int32(((total - nb) * uint64(255)) / total)) + } + return 255 + }()) +} + +// Returns the bit-cost for coding the skip probability. +func FinalizeSkipProba(tls *libc.TLS, enc uintptr) int32 { /* frame_enc.c:113:12: */ + var proba uintptr = (enc + 3616 /* &.proba_ */) + var nb_mbs int32 = ((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ * (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_) + var nb_events int32 = (*VP8EncProba)(unsafe.Pointer(proba)).nb_skip_ + var size int32 + (*VP8EncProba)(unsafe.Pointer(proba)).skip_proba_ = uint8_t(CalcSkipProba(tls, uint64(nb_events), uint64(nb_mbs))) + (*VP8EncProba)(unsafe.Pointer(proba)).use_skip_proba_ = (libc.Bool32(int32((*VP8EncProba)(unsafe.Pointer(proba)).skip_proba_) < 250)) + size = 256 // 'use_skip_proba' bit + if (*VP8EncProba)(unsafe.Pointer(proba)).use_skip_proba_ != 0 { + size = size + ((nb_events * VP8BitCost(tls, 1, (*VP8EncProba)(unsafe.Pointer(proba)).skip_proba_)) + + ((nb_mbs - nb_events) * VP8BitCost(tls, 0, (*VP8EncProba)(unsafe.Pointer(proba)).skip_proba_))) + size = size + (8 * 256) // cost of signaling the skip_proba_ itself. + } + return size +} + +// Collect statistics and deduce probabilities for next coding pass. +// Return the total bit-cost for coding the probability updates. +func CalcTokenProba(tls *libc.TLS, nb int32, total int32) int32 { /* frame_enc.c:131:12: */ + + if nb != 0 { + return (255 - ((nb * 255) / total)) + } + return 255 +} + +// Cost of coding 'nb' 1's and 'total-nb' 0's using 'proba' probability. +func BranchCost(tls *libc.TLS, nb int32, total int32, proba int32) int32 { /* frame_enc.c:137:12: */ + return ((nb * VP8BitCost(tls, 1, uint8(proba))) + ((total - nb) * VP8BitCost(tls, 0, uint8(proba)))) +} + +func ResetTokenStats(tls *libc.TLS, enc uintptr) { /* frame_enc.c:141:13: */ + var proba uintptr = (enc + 3616 /* &.proba_ */) + libc.Xmemset(tls, (proba + 1060 /* &.stats_ */), 0, uint64(unsafe.Sizeof([4][8]StatsArray{}))) +} + +func FinalizeTokenProbas(tls *libc.TLS, proba uintptr) int32 { /* frame_enc.c:146:12: */ + var has_changed int32 = 0 + var size int32 = 0 + var t int32 + var b int32 + var c int32 + var p int32 + for t = 0; t < NUM_TYPES; t++ { + for b = 0; b < NUM_BANDS; b++ { + for c = 0; c < NUM_CTX; c++ { + for p = 0; p < NUM_PROBAS; p++ { + var stats proba_t = *(*proba_t)(unsafe.Pointer(((((proba + 1060 /* &.stats_ */) + uintptr(t)*1056) + uintptr(b)*132) + uintptr(c)*44) + uintptr(p)*4)) + var nb int32 = (int32((stats >> 0) & proba_t(0xffff))) + var total int32 = (int32((stats >> 16) & proba_t(0xffff))) + var update_proba int32 = int32(*(*uint8_t)(unsafe.Pointer((((uintptr(unsafe.Pointer(&VP8CoeffsUpdateProba)) + uintptr(t)*264) + uintptr(b)*33) + uintptr(c)*11) + uintptr(p)))) + var old_p int32 = int32(*(*uint8_t)(unsafe.Pointer((((uintptr(unsafe.Pointer(&VP8CoeffsProba0)) + uintptr(t)*264) + uintptr(b)*33) + uintptr(c)*11) + uintptr(p)))) + var new_p int32 = CalcTokenProba(tls, nb, total) + var old_cost int32 = (BranchCost(tls, nb, total, old_p) + + VP8BitCost(tls, 0, uint8(update_proba))) + var new_cost int32 = ((BranchCost(tls, nb, total, new_p) + + VP8BitCost(tls, 1, uint8(update_proba))) + + (8 * 256)) + var use_new_p int32 = (libc.Bool32(old_cost > new_cost)) + size = size + (VP8BitCost(tls, use_new_p, uint8(update_proba))) + if use_new_p != 0 { // only use proba that seem meaningful enough. + *(*uint8_t)(unsafe.Pointer(((((proba + 4 /* &.coeffs_ */) + uintptr(t)*264) + uintptr(b)*33) + uintptr(c)*11) + uintptr(p))) = uint8_t(new_p) + has_changed = has_changed | (libc.Bool32(new_p != old_p)) + size = size + (8 * 256) + } else { + *(*uint8_t)(unsafe.Pointer(((((proba + 4 /* &.coeffs_ */) + uintptr(t)*264) + uintptr(b)*33) + uintptr(c)*11) + uintptr(p))) = uint8_t(old_p) + } + } + } + } + } + (*VP8EncProba)(unsafe.Pointer(proba)).dirty_ = has_changed + return size +} + +//------------------------------------------------------------------------------ +// Finalize Segment probability based on the coding tree + +func GetProba(tls *libc.TLS, a int32, b int32) int32 { /* frame_enc.c:185:12: */ + var total int32 = (a + b) + if total == 0 { + return 255 + } + return (((255 * a) + (total / 2)) / total) // rounded proba +} + +func ResetSegments(tls *libc.TLS, enc uintptr) { /* frame_enc.c:191:13: */ + var n int32 + for n = 0; n < ((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ * (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_); n++ { + libc.SetBitFieldPtr8Uint32(((*VP8Encoder)(unsafe.Pointer(enc)).mb_info_ + uintptr(n)*4) /* &.segment_ */, uint32(0), 5, 0x60) + } +} + +func SetSegmentProbas(tls *libc.TLS, enc uintptr) { /* frame_enc.c:198:13: */ + bp := tls.Alloc(16) + defer tls.Free(16) + + *(*[4]int32)(unsafe.Pointer(bp /* p */)) = [4]int32{0: 0} + var n int32 + + for n = 0; n < ((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ * (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_); n++ { + var mb uintptr = ((*VP8Encoder)(unsafe.Pointer(enc)).mb_info_ + uintptr(n)*4) + *(*int32)(unsafe.Pointer((bp) /* &p[0] */ + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer(mb /* &.segment_ */))&0x60>>5))))*4))++ + } + if (*WebPPicture)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).pic_)).stats != (uintptr(0)) { + for n = 0; n < NUM_MB_SEGMENTS; n++ { + *(*int32)(unsafe.Pointer(((*WebPPicture)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).pic_)).stats + 92 /* &.segment_size */) + uintptr(n)*4)) = *(*int32)(unsafe.Pointer((bp) /* &p[0] */ + uintptr(n)*4)) + } + } + if (*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.num_segments_ > 1 { + var probas uintptr = (enc + 3616 /* &.proba_ */) /* &.segments_ */ + *(*uint8_t)(unsafe.Pointer(probas)) = uint8_t(GetProba(tls, (*(*int32)(unsafe.Pointer((bp) /* &p[0] */)) + *(*int32)(unsafe.Pointer((bp) /* &p[0] */ + 1*4))), (*(*int32)(unsafe.Pointer((bp) /* &p[0] */ + 2*4)) + *(*int32)(unsafe.Pointer((bp) /* &p[0] */ + 3*4))))) + *(*uint8_t)(unsafe.Pointer(probas + 1)) = uint8_t(GetProba(tls, *(*int32)(unsafe.Pointer((bp) /* &p[0] */)), *(*int32)(unsafe.Pointer((bp) /* &p[0] */ + 1*4)))) + *(*uint8_t)(unsafe.Pointer(probas + 2)) = uint8_t(GetProba(tls, *(*int32)(unsafe.Pointer((bp) /* &p[0] */ + 2*4)), *(*int32)(unsafe.Pointer((bp) /* &p[0] */ + 3*4)))) + + (*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.update_map_ = (libc.Bool32(((int32(*(*uint8_t)(unsafe.Pointer(probas))) != 255) || (int32(*(*uint8_t)(unsafe.Pointer(probas + 1))) != 255)) || (int32(*(*uint8_t)(unsafe.Pointer(probas + 2))) != 255))) + if !((*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.update_map_ != 0) { + ResetSegments(tls, enc) + } + (*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.size_ = ((((*(*int32)(unsafe.Pointer((bp) /* &p[0] */)) * (VP8BitCost(tls, 0, *(*uint8_t)(unsafe.Pointer(probas))) + VP8BitCost(tls, 0, *(*uint8_t)(unsafe.Pointer(probas + 1))))) + (*(*int32)(unsafe.Pointer((bp) /* &p[0] */ + 1*4)) * (VP8BitCost(tls, 0, *(*uint8_t)(unsafe.Pointer(probas))) + VP8BitCost(tls, 1, *(*uint8_t)(unsafe.Pointer(probas + 1)))))) + (*(*int32)(unsafe.Pointer((bp) /* &p[0] */ + 2*4)) * (VP8BitCost(tls, 1, *(*uint8_t)(unsafe.Pointer(probas))) + VP8BitCost(tls, 0, *(*uint8_t)(unsafe.Pointer(probas + 2)))))) + (*(*int32)(unsafe.Pointer((bp) /* &p[0] */ + 3*4)) * (VP8BitCost(tls, 1, *(*uint8_t)(unsafe.Pointer(probas))) + VP8BitCost(tls, 1, *(*uint8_t)(unsafe.Pointer(probas + 2)))))) + } else { + (*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.update_map_ = 0 + (*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.size_ = 0 + } +} + +//------------------------------------------------------------------------------ +// Coefficient coding + +func PutCoeffs(tls *libc.TLS, bw uintptr, ctx int32, res uintptr) int32 { /* frame_enc.c:236:12: */ + var n int32 = (*VP8Residual)(unsafe.Pointer(res)).first + // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 + var p uintptr = (((*VP8Residual)(unsafe.Pointer(res)).prob + uintptr(n)*33) + uintptr(ctx)*11) + if !(VP8PutBit(tls, bw, (libc.Bool32((*VP8Residual)(unsafe.Pointer(res)).last >= 0)), int32(*(*uint8_t)(unsafe.Pointer(p)))) != 0) { + return 0 + } + + for n < 16 { + var c int32 = int32(*(*int16_t)(unsafe.Pointer((*VP8Residual)(unsafe.Pointer(res)).coeffs + uintptr(libc.PostIncInt32(&n, 1))*2))) + var sign int32 = (libc.Bool32(c < 0)) + var v int32 + if sign != 0 { + v = -c + } else { + v = c + } + if !(VP8PutBit(tls, bw, (libc.Bool32(v != 0)), int32(*(*uint8_t)(unsafe.Pointer(p + 1)))) != 0) { + p = ((*VP8Residual)(unsafe.Pointer(res)).prob + uintptr(VP8EncBands[n])*33) + continue + } + if !(VP8PutBit(tls, bw, (libc.Bool32(v > 1)), int32(*(*uint8_t)(unsafe.Pointer(p + 2)))) != 0) { + p = (((*VP8Residual)(unsafe.Pointer(res)).prob + uintptr(VP8EncBands[n])*33) + 1*11) + } else { + if !(VP8PutBit(tls, bw, (libc.Bool32(v > 4)), int32(*(*uint8_t)(unsafe.Pointer(p + 3)))) != 0) { + if VP8PutBit(tls, bw, (libc.Bool32(v != 2)), int32(*(*uint8_t)(unsafe.Pointer(p + 4)))) != 0 { + VP8PutBit(tls, bw, (libc.Bool32(v == 4)), int32(*(*uint8_t)(unsafe.Pointer(p + 5)))) + } + } else if !(VP8PutBit(tls, bw, (libc.Bool32(v > 10)), int32(*(*uint8_t)(unsafe.Pointer(p + 6)))) != 0) { + if !(VP8PutBit(tls, bw, (libc.Bool32(v > 6)), int32(*(*uint8_t)(unsafe.Pointer(p + 7)))) != 0) { + VP8PutBit(tls, bw, (libc.Bool32(v == 6)), 159) + } else { + VP8PutBit(tls, bw, (libc.Bool32(v >= 9)), 165) + VP8PutBit(tls, bw, libc.BoolInt32(!((v & 1) != 0)), 145) + } + } else { + var mask int32 + var tab uintptr + if v < (3 + (int32(8) << 1)) { // VP8Cat3 (3b) + VP8PutBit(tls, bw, 0, int32(*(*uint8_t)(unsafe.Pointer(p + 8)))) + VP8PutBit(tls, bw, 0, int32(*(*uint8_t)(unsafe.Pointer(p + 9)))) + v = v - (3 + (int32(8) << 0)) + mask = (int32(1) << 2) + tab = uintptr(unsafe.Pointer(&VP8Cat3)) + } else if v < (3 + (int32(8) << 2)) { // VP8Cat4 (4b) + VP8PutBit(tls, bw, 0, int32(*(*uint8_t)(unsafe.Pointer(p + 8)))) + VP8PutBit(tls, bw, 1, int32(*(*uint8_t)(unsafe.Pointer(p + 9)))) + v = v - (3 + (int32(8) << 1)) + mask = (int32(1) << 3) + tab = uintptr(unsafe.Pointer(&VP8Cat4)) + } else if v < (3 + (int32(8) << 3)) { // VP8Cat5 (5b) + VP8PutBit(tls, bw, 1, int32(*(*uint8_t)(unsafe.Pointer(p + 8)))) + VP8PutBit(tls, bw, 0, int32(*(*uint8_t)(unsafe.Pointer(p + 10)))) + v = v - (3 + (int32(8) << 2)) + mask = (int32(1) << 4) + tab = uintptr(unsafe.Pointer(&VP8Cat5)) + } else { // VP8Cat6 (11b) + VP8PutBit(tls, bw, 1, int32(*(*uint8_t)(unsafe.Pointer(p + 8)))) + VP8PutBit(tls, bw, 1, int32(*(*uint8_t)(unsafe.Pointer(p + 10)))) + v = v - (3 + (int32(8) << 3)) + mask = (int32(1) << 10) + tab = uintptr(unsafe.Pointer(&VP8Cat6)) + } + for mask != 0 { + VP8PutBit(tls, bw, libc.BoolInt32(!(!((v & mask) != 0))), int32(*(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&tab, 1))))) + mask >>= 1 + } + } + p = (((*VP8Residual)(unsafe.Pointer(res)).prob + uintptr(VP8EncBands[n])*33) + 2*11) + } + VP8PutBitUniform(tls, bw, sign) + if (n == 16) || !(VP8PutBit(tls, bw, (libc.Bool32(n <= (*VP8Residual)(unsafe.Pointer(res)).last)), int32(*(*uint8_t)(unsafe.Pointer(p)))) != 0) { + return 1 // EOB + } + } + return 1 +} + +func CodeResiduals(tls *libc.TLS, bw uintptr, it uintptr, rd uintptr) { /* frame_enc.c:309:13: */ + bp := tls.Alloc(48) + defer tls.Free(48) + + var x int32 + var y int32 + var ch int32 + // var res VP8Residual at bp, 48 + + var pos1 uint64_t + var pos2 uint64_t + var pos3 uint64_t + var i16 int32 = (libc.Bool32((int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.type_ */)) & 0x3 >> 0)) == 1)) + var segment int32 = (int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.segment_ */)) & 0x60 >> 5)) + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + + VP8IteratorNzToBytes(tls, it) + + pos1 = VP8BitWriterPos(tls, bw) + if i16 != 0 { + VP8InitResidual(tls, 0, 1, enc, (bp) /* &res */) + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8SetResidualCoeffs})).f(tls, (rd + 40 /* &.y_dc_levels */), (bp) /* &res */) + *(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + 8*4)) = libc.AssignPtrInt32(((it + 168 /* &.left_nz_ */) + 8*4), PutCoeffs(tls, bw, (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + 8*4))+*(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + 8*4))), (bp) /* &res */)) + VP8InitResidual(tls, 1, 0, enc, (bp) /* &res */) + } else { + VP8InitResidual(tls, 0, 3, enc, (bp) /* &res */) + } + + // luma-AC + for y = 0; y < 4; y++ { + for x = 0; x < 4; x++ { + var ctx int32 = (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(x)*4)) + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + uintptr(y)*4))) + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8SetResidualCoeffs})).f(tls, ((rd + 72 /* &.y_ac_levels */) + uintptr((x+(y*4)))*32), (bp) /* &res */) + *(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(x)*4)) = libc.AssignPtrInt32(((it + 168 /* &.left_nz_ */) + uintptr(y)*4), PutCoeffs(tls, bw, ctx, (bp) /* &res */)) + } + } + pos2 = VP8BitWriterPos(tls, bw) + + // U/V + VP8InitResidual(tls, 0, 2, enc, (bp) /* &res */) + for ch = 0; ch <= 2; ch = ch + (2) { + for y = 0; y < 2; y++ { + for x = 0; x < 2; x++ { + var ctx int32 = (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(((4+ch)+x))*4)) + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + uintptr(((4+ch)+y))*4))) + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8SetResidualCoeffs})).f(tls, ((rd + 584 /* &.uv_levels */) + uintptr((((ch*2)+x)+(y*2)))*32), (bp) /* &res */) + *(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(((4+ch)+x))*4)) = libc.AssignPtrInt32(((it + 168 /* &.left_nz_ */) + uintptr(((4+ch)+y))*4), PutCoeffs(tls, bw, ctx, (bp) /* &res */)) + } + } + } + pos3 = VP8BitWriterPos(tls, bw) + (*VP8EncIterator)(unsafe.Pointer(it)).luma_bits_ = (pos2 - pos1) + (*VP8EncIterator)(unsafe.Pointer(it)).uv_bits_ = (pos3 - pos2) + *(*uint64_t)(unsafe.Pointer((((it + 208 /* &.bit_count_ */) + uintptr(segment)*24) + uintptr(i16)*8))) += ((*VP8EncIterator)(unsafe.Pointer(it)).luma_bits_) + *(*uint64_t)(unsafe.Pointer((((it + 208 /* &.bit_count_ */) + uintptr(segment)*24) + 2*8))) += ((*VP8EncIterator)(unsafe.Pointer(it)).uv_bits_) + VP8IteratorBytesToNz(tls, it) +} + +// Same as CodeResiduals, but doesn't actually write anything. +// Instead, it just records the event distribution. +func RecordResiduals(tls *libc.TLS, it uintptr, rd uintptr) { /* frame_enc.c:363:13: */ + bp := tls.Alloc(48) + defer tls.Free(48) + + var x int32 + var y int32 + var ch int32 + // var res VP8Residual at bp, 48 + + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + + VP8IteratorNzToBytes(tls, it) + + if (int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.type_ */)) & 0x3 >> 0)) == 1 { // i16x16 + VP8InitResidual(tls, 0, 1, enc, (bp) /* &res */) + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8SetResidualCoeffs})).f(tls, (rd + 40 /* &.y_dc_levels */), (bp) /* &res */) + *(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + 8*4)) = libc.AssignPtrInt32(((it + 168 /* &.left_nz_ */) + 8*4), VP8RecordCoeffs(tls, (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + 8*4))+*(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + 8*4))), (bp) /* &res */)) + VP8InitResidual(tls, 1, 0, enc, (bp) /* &res */) + } else { + VP8InitResidual(tls, 0, 3, enc, (bp) /* &res */) + } + + // luma-AC + for y = 0; y < 4; y++ { + for x = 0; x < 4; x++ { + var ctx int32 = (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(x)*4)) + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + uintptr(y)*4))) + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8SetResidualCoeffs})).f(tls, ((rd + 72 /* &.y_ac_levels */) + uintptr((x+(y*4)))*32), (bp) /* &res */) + *(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(x)*4)) = libc.AssignPtrInt32(((it + 168 /* &.left_nz_ */) + uintptr(y)*4), VP8RecordCoeffs(tls, ctx, (bp) /* &res */)) + } + } + + // U/V + VP8InitResidual(tls, 0, 2, enc, (bp) /* &res */) + for ch = 0; ch <= 2; ch = ch + (2) { + for y = 0; y < 2; y++ { + for x = 0; x < 2; x++ { + var ctx int32 = (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(((4+ch)+x))*4)) + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + uintptr(((4+ch)+y))*4))) + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8SetResidualCoeffs})).f(tls, ((rd + 584 /* &.uv_levels */) + uintptr((((ch*2)+x)+(y*2)))*32), (bp) /* &res */) + *(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(((4+ch)+x))*4)) = libc.AssignPtrInt32(((it + 168 /* &.left_nz_ */) + uintptr(((4+ch)+y))*4), VP8RecordCoeffs(tls, ctx, (bp) /* &res */)) + } + } + } + + VP8IteratorBytesToNz(tls, it) +} + +//------------------------------------------------------------------------------ +// Token buffer + +func RecordTokens(tls *libc.TLS, it uintptr, rd uintptr, tokens uintptr) int32 { /* frame_enc.c:411:12: */ + bp := tls.Alloc(48) + defer tls.Free(48) + + var x int32 + var y int32 + var ch int32 + // var res VP8Residual at bp, 48 + + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + + VP8IteratorNzToBytes(tls, it) + if (int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.type_ */)) & 0x3 >> 0)) == 1 { // i16x16 + var ctx int32 = (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + 8*4)) + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + 8*4))) + VP8InitResidual(tls, 0, 1, enc, (bp) /* &res */) + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8SetResidualCoeffs})).f(tls, (rd + 40 /* &.y_dc_levels */), (bp) /* &res */) + *(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + 8*4)) = libc.AssignPtrInt32(((it + 168 /* &.left_nz_ */) + 8*4), VP8RecordCoeffTokens(tls, ctx, (bp) /* &res */, tokens)) + VP8InitResidual(tls, 1, 0, enc, (bp) /* &res */) + } else { + VP8InitResidual(tls, 0, 3, enc, (bp) /* &res */) + } + + // luma-AC + for y = 0; y < 4; y++ { + for x = 0; x < 4; x++ { + var ctx int32 = (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(x)*4)) + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + uintptr(y)*4))) + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8SetResidualCoeffs})).f(tls, ((rd + 72 /* &.y_ac_levels */) + uintptr((x+(y*4)))*32), (bp) /* &res */) + *(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(x)*4)) = libc.AssignPtrInt32(((it + 168 /* &.left_nz_ */) + uintptr(y)*4), VP8RecordCoeffTokens(tls, ctx, (bp) /* &res */, tokens)) + } + } + + // U/V + VP8InitResidual(tls, 0, 2, enc, (bp) /* &res */) + for ch = 0; ch <= 2; ch = ch + (2) { + for y = 0; y < 2; y++ { + for x = 0; x < 2; x++ { + var ctx int32 = (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(((4+ch)+x))*4)) + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + uintptr(((4+ch)+y))*4))) + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8SetResidualCoeffs})).f(tls, ((rd + 584 /* &.uv_levels */) + uintptr((((ch*2)+x)+(y*2)))*32), (bp) /* &res */) + *(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(((4+ch)+x))*4)) = libc.AssignPtrInt32(((it + 168 /* &.left_nz_ */) + uintptr(((4+ch)+y))*4), VP8RecordCoeffTokens(tls, ctx, (bp) /* &res */, tokens)) + } + } + } + VP8IteratorBytesToNz(tls, it) + return libc.BoolInt32(!((*VP8TBuffer)(unsafe.Pointer(tokens)).error_ != 0)) +} + +//------------------------------------------------------------------------------ +// ExtraInfo map / Debug function + +func ResetSSE(tls *libc.TLS, enc uintptr) { /* frame_enc.c:472:13: */ + *(*uint64_t)(unsafe.Pointer((enc + 23512 /* &.sse_ */))) = uint64(0) + *(*uint64_t)(unsafe.Pointer((enc + 23512 /* &.sse_ */) + 1*8)) = uint64(0) + *(*uint64_t)(unsafe.Pointer((enc + 23512 /* &.sse_ */) + 2*8)) = uint64(0) + // Note: enc->sse_[3] is managed by alpha.c + (*VP8Encoder)(unsafe.Pointer(enc)).sse_count_ = uint64(0) +} + +func StoreSSE(tls *libc.TLS, it uintptr) { /* frame_enc.c:480:13: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var in uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + var out uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_ + // Note: not totally accurate at boundary. And doesn't include in-loop filter. + *(*uint64_t)(unsafe.Pointer((enc + 23512 /* &.sse_ */))) += (uint64_t((*struct { + f func(*libc.TLS, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSE16x16})).f(tls, (in + uintptr((0))), (out + uintptr((0)))))) + *(*uint64_t)(unsafe.Pointer(((enc + 23512 /* &.sse_ */) + 1*8))) += (uint64_t((*struct { + f func(*libc.TLS, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSE8x8})).f(tls, (in + uintptr((16))), (out + uintptr((16)))))) + *(*uint64_t)(unsafe.Pointer(((enc + 23512 /* &.sse_ */) + 2*8))) += (uint64_t((*struct { + f func(*libc.TLS, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSE8x8})).f(tls, (in + uintptr((16 + 8))), (out + uintptr((16 + 8)))))) + *(*uint64_t)(unsafe.Pointer((enc + 23544 /* &.sse_count_ */))) += (uint64(16 * 16)) +} + +func StoreSideInfo(tls *libc.TLS, it uintptr) { /* frame_enc.c:491:13: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var mb uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).mb_ + var pic uintptr = (*VP8Encoder)(unsafe.Pointer(enc)).pic_ + + if (*WebPPicture)(unsafe.Pointer(pic)).stats != (uintptr(0)) { + StoreSSE(tls, it) + *(*int32)(unsafe.Pointer((enc + 23604 /* &.block_count_ */))) += (libc.Bool32((int32(*(*uint8)(unsafe.Pointer(mb /* &.type_ */)) & 0x3 >> 0)) == 0)) + *(*int32)(unsafe.Pointer(((enc + 23604 /* &.block_count_ */) + 1*4))) += (libc.Bool32((int32(*(*uint8)(unsafe.Pointer(mb /* &.type_ */)) & 0x3 >> 0)) == 1)) + *(*int32)(unsafe.Pointer(((enc + 23604 /* &.block_count_ */) + 2*4))) += (libc.Bool32((int32(*(*uint8)(unsafe.Pointer(mb /* &.skip_ */)) & 0x10 >> 4)) != 0)) + } + + if (*WebPPicture)(unsafe.Pointer(pic)).extra_info != (uintptr(0)) { + var info uintptr = ((*WebPPicture)(unsafe.Pointer(pic)).extra_info + uintptr(((*VP8EncIterator)(unsafe.Pointer(it)).x_ + ((*VP8EncIterator)(unsafe.Pointer(it)).y_ * (*VP8Encoder)(unsafe.Pointer(enc)).mb_w_)))) + switch (*WebPPicture)(unsafe.Pointer(pic)).extra_info_type { + case 1: + *(*uint8_t)(unsafe.Pointer(info)) = (uint8_t(int32(*(*uint8)(unsafe.Pointer(mb /* &.type_ */)) & 0x3 >> 0))) + break + fallthrough + case 2: + *(*uint8_t)(unsafe.Pointer(info)) = (uint8_t(int32(*(*uint8)(unsafe.Pointer(mb /* &.segment_ */)) & 0x60 >> 5))) + break + fallthrough + case 3: + *(*uint8_t)(unsafe.Pointer(info)) = uint8_t((*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */) + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer(mb /* &.segment_ */))&0x60>>5))))*744)).quant_) + break + fallthrough + case 4: + *(*uint8_t)(unsafe.Pointer(info)) = func() uint8 { + if (int32(*(*uint8)(unsafe.Pointer(mb /* &.type_ */)) & 0x3 >> 0)) == 1 { + return *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).preds_)) + } + return uint8(0xff) + }() + break + fallthrough + case 5: + *(*uint8_t)(unsafe.Pointer(info)) = (uint8_t(int32(*(*uint8)(unsafe.Pointer(mb /* &.uv_mode_ */)) & 0xc >> 2))) + break + fallthrough + case 6: + { + var b int32 = (int32((((*VP8EncIterator)(unsafe.Pointer(it)).luma_bits_ + (*VP8EncIterator)(unsafe.Pointer(it)).uv_bits_) + uint64(7)) >> 3)) + *(*uint8_t)(unsafe.Pointer(info)) = func() uint8 { + if b > 255 { + return uint8(255) + } + return uint8(b) + }() + break + + } + fallthrough + case 7: + *(*uint8_t)(unsafe.Pointer(info)) = (*VP8MBInfo)(unsafe.Pointer(mb)).alpha_ + break + fallthrough + default: + *(*uint8_t)(unsafe.Pointer(info)) = uint8_t(0) + break + } + } +} + +func ResetSideInfo(tls *libc.TLS, it uintptr) { /* frame_enc.c:526:13: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var pic uintptr = (*VP8Encoder)(unsafe.Pointer(enc)).pic_ + if (*WebPPicture)(unsafe.Pointer(pic)).stats != (uintptr(0)) { + libc.Xmemset(tls, (enc + 23604 /* &.block_count_ */), 0, uint64(unsafe.Sizeof([3]int32{}))) + } + ResetSSE(tls, enc) +} + +func GetPSNR(tls *libc.TLS, mse uint64_t, size uint64_t) float64 { /* frame_enc.c:554:15: */ + if (mse > uint64(0)) && (size > uint64(0)) { + return (10. * libc.Xlog10(tls, (((float64(255.)*255.)*float64(size))/float64(mse)))) + } + return float64(99) +} + +//------------------------------------------------------------------------------ +// StatLoop(): only collect statistics (number of skips, token usage, ...). +// This is used for deciding optimal probabilities. It also modifies the +// quantizer value if some target (size, PSNR) was specified. + +func SetLoopParams(tls *libc.TLS, enc uintptr, q float32) { /* frame_enc.c:563:13: */ + // Make sure the quality parameter is inside valid bounds + q = Clamp(tls, q, 0., 100.) + + VP8SetSegmentParams(tls, enc, q) // setup segment quantizations and filters + SetSegmentProbas(tls, enc) // compute segment probabilities + + ResetStats(tls, enc) + ResetSSE(tls, enc) +} + +func OneStatPass(tls *libc.TLS, enc uintptr, rd_opt VP8RDLevel, nb_mbs int32, percent_delta int32, s uintptr) uint64_t { /* frame_enc.c:574:17: */ + bp := tls.Alloc(4728) + defer tls.Free(4728) + + // var it VP8EncIterator at bp, 3848 + + var size uint64_t = uint64(0) + var size_p0 uint64_t = uint64(0) + var distortion uint64_t = uint64(0) + var pixel_count uint64_t = (uint64_t(nb_mbs * 384)) + + VP8IteratorInit(tls, enc, (bp) /* &it */) + SetLoopParams(tls, enc, (*PassStats)(unsafe.Pointer(s)).q) + for ok := true; ok; ok = ((VP8IteratorNext(tls, (bp) /* &it */) != 0) && (libc.PreDecInt32(&nb_mbs, 1) > 0)) { + // var info VP8ModeScore at bp+3848, 880 + + VP8IteratorImport(tls, (bp) /* &it */, (uintptr(0))) + if VP8Decimate(tls, (bp) /* &it */, (bp+3848) /* &info */, rd_opt) != 0 { + // Just record the number of skips and act like skip_proba is not used. + (*VP8Encoder)(unsafe.Pointer(enc)).proba_.nb_skip_++ + } + RecordResiduals(tls, (bp) /* &it */, (bp + 3848) /* &info */) + size = size + (uint64_t((*VP8ModeScore)(unsafe.Pointer(bp+3848 /* &info */)).R + (*VP8ModeScore)(unsafe.Pointer(bp+3848 /* &info */)).H)) + size_p0 = size_p0 + (uint64_t((*VP8ModeScore)(unsafe.Pointer(bp + 3848 /* &info */)).H)) + distortion = distortion + (uint64_t((*VP8ModeScore)(unsafe.Pointer(bp + 3848 /* &info */)).D)) + if (percent_delta != 0) && !(VP8IteratorProgress(tls, (bp) /* &it */, percent_delta) != 0) { + return uint64(0) + } + VP8IteratorSaveBoundary(tls, (bp) /* &it */) + } + + size_p0 = size_p0 + (uint64_t((*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.size_)) + if (*PassStats)(unsafe.Pointer(s)).do_size_search != 0 { + size = size + (uint64_t(FinalizeSkipProba(tls, enc))) + size = size + (uint64_t(FinalizeTokenProbas(tls, (enc + 3616 /* &.proba_ */)))) + size = ((((size + size_p0) + uint64(1024)) >> 11) + (uint64((12 + 8) + 10))) + (*PassStats)(unsafe.Pointer(s)).value = float64(size) + } else { + (*PassStats)(unsafe.Pointer(s)).value = GetPSNR(tls, distortion, pixel_count) + } + return size_p0 +} + +func StatLoop(tls *libc.TLS, enc uintptr) int32 { /* frame_enc.c:614:12: */ + bp := tls.Alloc(56) + defer tls.Free(56) + + var method int32 = (*VP8Encoder)(unsafe.Pointer(enc)).method_ + var do_search int32 = (*VP8Encoder)(unsafe.Pointer(enc)).do_search_ + var fast_probe int32 = (libc.Bool32(((method == 0) || (method == 3)) && !(do_search != 0))) + var num_pass_left int32 = (*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).pass + var task_percent int32 = 20 + var percent_per_pass int32 = ((task_percent + (num_pass_left / 2)) / num_pass_left) + var final_percent int32 = ((*VP8Encoder)(unsafe.Pointer(enc)).percent_ + task_percent) + var rd_opt VP8RDLevel + if (method >= 3) || (do_search != 0) { + rd_opt = RD_OPT_BASIC + } else { + rd_opt = RD_OPT_NONE + } + var nb_mbs int32 = ((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ * (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_) + // var stats PassStats at bp, 56 + + InitPassStats(tls, enc, (bp) /* &stats */) + ResetTokenStats(tls, enc) + + // Fast mode: quick analysis pass over few mbs. Better than nothing. + if fast_probe != 0 { + if method == 3 { // we need more stats for method 3 to be reliable. + if nb_mbs > 200 { + nb_mbs = (nb_mbs >> 1) + } else { + nb_mbs = 100 + } + } else { + if nb_mbs > 200 { + nb_mbs = (nb_mbs >> 2) + } else { + nb_mbs = 50 + } + } + } + + for libc.PostDecInt32(&num_pass_left, 1) > 0 { + var is_last_pass int32 = (libc.Bool32(((libc.Xfabs(tls, float64((*PassStats)(unsafe.Pointer(bp /* &stats */)).dq)) <= 0.4) || (num_pass_left == 0)) || ((*VP8Encoder)(unsafe.Pointer(enc)).max_i4_header_bits_ == 0))) + var size_p0 uint64_t = OneStatPass(tls, enc, rd_opt, nb_mbs, percent_per_pass, (bp) /* &stats */) + if size_p0 == uint64(0) { + return 0 + } + if ((*VP8Encoder)(unsafe.Pointer(enc)).max_i4_header_bits_ > 0) && (uint64(size_p0) > (uint64(((uint64(int32(1) << 19)) - 2048)) << 11)) { + num_pass_left++ + libc.AssignShrPtrInt32((enc + 23624 /* &.max_i4_header_bits_ */), int(1)) // strengthen header bit limitation... + continue // ...and start over + } + if is_last_pass != 0 { + break + } + // If no target size: just do several pass without changing 'q' + if do_search != 0 { + ComputeNextQ(tls, (bp) /* &stats */) + if libc.Xfabs(tls, float64((*PassStats)(unsafe.Pointer(bp /* &stats */)).dq)) <= 0.4 { + break + } + } + } + if !(do_search != 0) || !((*PassStats)(unsafe.Pointer(bp /* &stats */)).do_size_search != 0) { + // Need to finalize probas now, since it wasn't done during the search. + FinalizeSkipProba(tls, enc) + FinalizeTokenProbas(tls, (enc + 3616 /* &.proba_ */)) + } + VP8CalculateLevelCosts(tls, (enc + 3616 /* &.proba_ */)) // finalize costs + return WebPReportProgress(tls, (*VP8Encoder)(unsafe.Pointer(enc)).pic_, final_percent, (enc + 536 /* &.percent_ */)) +} + +//------------------------------------------------------------------------------ +// Main loops +// + +var kAverageBytesPerMB = [8]uint8_t{uint8_t(50), uint8_t(24), uint8_t(16), uint8_t(9), uint8_t(7), uint8_t(5), uint8_t(3), uint8_t(2)} /* frame_enc.c:678:22 */ + +func PreLoopInitialize(tls *libc.TLS, enc uintptr) int32 { /* frame_enc.c:680:12: */ + var p int32 + var ok int32 = 1 + var average_bytes_per_MB int32 = int32(kAverageBytesPerMB[((*VP8Encoder)(unsafe.Pointer(enc)).base_quant_ >> 4)]) + var bytes_per_parts int32 = ((((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ * (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_) * average_bytes_per_MB) / (*VP8Encoder)(unsafe.Pointer(enc)).num_parts_) + // Initialize the bit-writers + for p = 0; (ok != 0) && (p < (*VP8Encoder)(unsafe.Pointer(enc)).num_parts_); p++ { + ok = VP8BitWriterInit(tls, ((enc + 112 /* &.parts_ */) + uintptr(p)*48), uint64(bytes_per_parts)) + } + if !(ok != 0) { + VP8EncFreeBitWriters(tls, enc) // malloc error occurred + WebPEncodingSetError(tls, (*VP8Encoder)(unsafe.Pointer(enc)).pic_, VP8_ENC_ERROR_OUT_OF_MEMORY) + } + return ok +} + +func PostLoopFinalize(tls *libc.TLS, it uintptr, ok int32) int32 { /* frame_enc.c:697:12: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + if ok != 0 { // Finalize the partitions, check for extra errors. + var p int32 + for p = 0; p < (*VP8Encoder)(unsafe.Pointer(enc)).num_parts_; p++ { + VP8BitWriterFinish(tls, ((enc + 112 /* &.parts_ */) + uintptr(p)*48)) + ok = ok & (libc.BoolInt32(!((*VP8BitWriter)(unsafe.Pointer((enc+112 /* &.parts_ */)+uintptr(p)*48)).error_ != 0))) + } + } + + if ok != 0 { // All good. Finish up. + if (*WebPPicture)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).pic_)).stats != (uintptr(0)) { // finalize byte counters... + var i int32 + var s int32 + for i = 0; i <= 2; i++ { + for s = 0; s < NUM_MB_SEGMENTS; s++ { + *(*int32)(unsafe.Pointer(((enc + 23556 /* &.residual_bytes_ */) + uintptr(i)*16) + uintptr(s)*4)) = (int32((*(*uint64_t)(unsafe.Pointer(((it + 208 /* &.bit_count_ */) + uintptr(s)*24) + uintptr(i)*8)) + uint64(7)) >> 3)) + } + } + } + VP8AdjustFilterStrength(tls, it) // ...and store filter stats. + } else { + // Something bad happened -> need to do some memory cleanup. + VP8EncFreeBitWriters(tls, enc) + } + return ok +} + +//------------------------------------------------------------------------------ +// VP8EncLoop(): does the final bitstream coding. + +func ResetAfterSkip(tls *libc.TLS, it uintptr) { /* frame_enc.c:729:13: */ + if (int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.type_ */)) & 0x3 >> 0)) == 1 { + *(*uint32_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).nz_)) = uint32_t(0) // reset all predictors + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + 8*4)) = 0 + } else { + *(*uint32_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).nz_)) &= (uint32_t(int32(1) << 24)) // preserve the dc_nz bit + } +} + +func VP8EncLoop(tls *libc.TLS, enc uintptr) int32 { /* frame_enc.c:738:5: */ + bp := tls.Alloc(4728) + defer tls.Free(4728) + + // var it VP8EncIterator at bp, 3848 + + var ok int32 = PreLoopInitialize(tls, enc) + if !(ok != 0) { + return 0 + } + + StatLoop(tls, enc) // stats-collection loop + + VP8IteratorInit(tls, enc, (bp) /* &it */) + VP8InitFilter(tls, (bp) /* &it */) + for ok := int32(1); ok == 1; ok = VP8IteratorNext(tls, (bp) /* &it */) { + // var info VP8ModeScore at bp+3848, 880 + + var dont_use_skip int32 = libc.BoolInt32(!((*VP8Encoder)(unsafe.Pointer(enc)).proba_.use_skip_proba_ != 0)) + var rd_opt VP8RDLevel = (*VP8Encoder)(unsafe.Pointer(enc)).rd_opt_level_ + + VP8IteratorImport(tls, (bp) /* &it */, (uintptr(0))) + // Warning! order is important: first call VP8Decimate() and + // *then* decide how to code the skip decision if there's one. + if !(VP8Decimate(tls, (bp) /* &it */, (bp+3848) /* &info */, rd_opt) != 0) || (dont_use_skip != 0) { + CodeResiduals(tls, (*VP8EncIterator)(unsafe.Pointer(bp /* &it */)).bw_, (bp) /* &it */, (bp + 3848) /* &info */) + } else { // reset predictors after a skip + ResetAfterSkip(tls, (bp) /* &it */) + } + StoreSideInfo(tls, (bp) /* &it */) + VP8StoreFilterStats(tls, (bp) /* &it */) + VP8IteratorExport(tls, (bp) /* &it */) + ok = VP8IteratorProgress(tls, (bp) /* &it */, 20) + VP8IteratorSaveBoundary(tls, (bp) /* &it */) + } + + return PostLoopFinalize(tls, (bp) /* &it */, ok) +} + +//------------------------------------------------------------------------------ +// Single pass using Token Buffer. + +func VP8EncTokenLoop(tls *libc.TLS, enc uintptr) int32 { /* frame_enc.c:777:5: */ + bp := tls.Alloc(4784) + defer tls.Free(4784) + + // Roughly refresh the proba eight times per pass + var max_count int32 = (((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ * (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_) >> 3) + var num_pass_left int32 = (*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).pass + var remaining_progress int32 = 40 // percents + var do_search int32 = (*VP8Encoder)(unsafe.Pointer(enc)).do_search_ + // var it VP8EncIterator at bp+56, 3848 + + var proba uintptr = (enc + 3616 /* &.proba_ */) + var rd_opt VP8RDLevel = (*VP8Encoder)(unsafe.Pointer(enc)).rd_opt_level_ + var pixel_count uint64_t = (uint64_t(((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ * (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_) * 384)) + // var stats PassStats at bp, 56 + + var ok int32 + + InitPassStats(tls, enc, (bp) /* &stats */) + ok = PreLoopInitialize(tls, enc) + if !(ok != 0) { + return 0 + } + + if max_count < 96 { + max_count = 96 + } + + // otherwise, token-buffer won't be useful + + for (ok != 0) && (libc.PostDecInt32(&num_pass_left, 1) > 0) { + var is_last_pass int32 = (libc.Bool32(((libc.Xfabs(tls, float64((*PassStats)(unsafe.Pointer(bp /* &stats */)).dq)) <= 0.4) || (num_pass_left == 0)) || ((*VP8Encoder)(unsafe.Pointer(enc)).max_i4_header_bits_ == 0))) + var size_p0 uint64_t = uint64(0) + var distortion uint64_t = uint64(0) + var cnt int32 = max_count + // The final number of passes is not trivial to know in advance. + var pass_progress int32 = (remaining_progress / (2 + num_pass_left)) + remaining_progress = remaining_progress - (pass_progress) + VP8IteratorInit(tls, enc, (bp + 56) /* &it */) + SetLoopParams(tls, enc, (*PassStats)(unsafe.Pointer(bp /* &stats */)).q) + if is_last_pass != 0 { + ResetTokenStats(tls, enc) + VP8InitFilter(tls, (bp + 56) /* &it */) // don't collect stats until last pass (too costly) + } + VP8TBufferClear(tls, (enc + 496 /* &.tokens_ */)) + for ok := int32(1); ok == 1; ok = VP8IteratorNext(tls, (bp + 56) /* &it */) { + // var info VP8ModeScore at bp+3904, 880 + + VP8IteratorImport(tls, (bp + 56) /* &it */, (uintptr(0))) + if libc.PreDecInt32(&cnt, 1) < 0 { + FinalizeTokenProbas(tls, proba) + VP8CalculateLevelCosts(tls, proba) // refresh cost tables for rd-opt + cnt = max_count + } + VP8Decimate(tls, (bp + 56) /* &it */, (bp + 3904) /* &info */, rd_opt) + ok = RecordTokens(tls, (bp + 56) /* &it */, (bp + 3904) /* &info */, (enc + 496 /* &.tokens_ */)) + if !(ok != 0) { + WebPEncodingSetError(tls, (*VP8Encoder)(unsafe.Pointer(enc)).pic_, VP8_ENC_ERROR_OUT_OF_MEMORY) + break + } + size_p0 = size_p0 + (uint64_t((*VP8ModeScore)(unsafe.Pointer(bp + 3904 /* &info */)).H)) + distortion = distortion + (uint64_t((*VP8ModeScore)(unsafe.Pointer(bp + 3904 /* &info */)).D)) + if is_last_pass != 0 { + StoreSideInfo(tls, (bp + 56) /* &it */) + VP8StoreFilterStats(tls, (bp + 56) /* &it */) + VP8IteratorExport(tls, (bp + 56) /* &it */) + ok = VP8IteratorProgress(tls, (bp + 56) /* &it */, pass_progress) + } + VP8IteratorSaveBoundary(tls, (bp + 56) /* &it */) + } + if !(ok != 0) { + break + } + + size_p0 = size_p0 + (uint64_t((*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.size_)) + if (*PassStats)(unsafe.Pointer(bp /* &stats */)).do_size_search != 0 { + var size uint64_t = uint64_t(FinalizeTokenProbas(tls, (enc + 3616 /* &.proba_ */))) + size = size + (VP8EstimateTokenSize(tls, (enc + 496 /* &.tokens_ */), + proba+4 /* &.coeffs_ */)) + size = (((size + size_p0) + uint64(1024)) >> 11) // -> size in bytes + size = size + (uint64((12 + 8) + 10)) + (*PassStats)(unsafe.Pointer(bp /* &stats */)).value = float64(size) + } else { // compute and store PSNR + (*PassStats)(unsafe.Pointer(bp /* &stats */)).value = GetPSNR(tls, distortion, pixel_count) + } + + if ((*VP8Encoder)(unsafe.Pointer(enc)).max_i4_header_bits_ > 0) && (uint64(size_p0) > (uint64(((uint64(int32(1) << 19)) - 2048)) << 11)) { + num_pass_left++ + libc.AssignShrPtrInt32((enc + 23624 /* &.max_i4_header_bits_ */), int(1)) // strengthen header bit limitation... + if is_last_pass != 0 { + ResetSideInfo(tls, (bp + 56) /* &it */) + } + continue // ...and start over + } + if is_last_pass != 0 { + break // done + } + if do_search != 0 { + ComputeNextQ(tls, (bp) /* &stats */) // Adjust q + } + } + if ok != 0 { + if !((*PassStats)(unsafe.Pointer(bp /* &stats */)).do_size_search != 0) { + FinalizeTokenProbas(tls, (enc + 3616 /* &.proba_ */)) + } + ok = VP8EmitTokens(tls, (enc + 496 /* &.tokens_ */), ((enc + 112 /* &.parts_ */) + uintptr(0)*48), + proba+4 /* &.coeffs_ */, 1) + } + ok = (libc.Bool32((ok != 0) && (WebPReportProgress(tls, (*VP8Encoder)(unsafe.Pointer(enc)).pic_, ((*VP8Encoder)(unsafe.Pointer(enc)).percent_+remaining_progress), + (enc+536 /* &.percent_ */)) != 0))) + return PostLoopFinalize(tls, (bp + 56) /* &it */, ok) +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Transform-related functions use din both encoding and decoding. + +// Macros used to create a batch predictor that iteratively uses a +// one-pixel predictor. + +// The predictor is added to the output pixel (which +// is therefore considered as a residual) to get the final prediction. + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +// Number of partitions for the three dominant (literal, red and blue) symbol +// costs. +// The size of the bin-hash corresponding to the three dominant costs. +// Maximum number of histograms allowed in greedy combining algorithm. + +func HistogramClear(tls *libc.TLS, p uintptr) { /* histogram_enc.c:34:13: */ + var literal uintptr = (*VP8LHistogram)(unsafe.Pointer(p)).literal_ + var cache_bits int32 = (*VP8LHistogram)(unsafe.Pointer(p)).palette_code_bits_ + var histo_size int32 = VP8LGetHistogramSize(tls, cache_bits) + libc.Xmemset(tls, p, 0, uint64(histo_size)) + (*VP8LHistogram)(unsafe.Pointer(p)).palette_code_bits_ = cache_bits + (*VP8LHistogram)(unsafe.Pointer(p)).literal_ = literal +} + +// Swap two histogram pointers. +func HistogramSwap(tls *libc.TLS, A uintptr, B uintptr) { /* histogram_enc.c:44:13: */ + var tmp uintptr = *(*uintptr)(unsafe.Pointer(A)) + *(*uintptr)(unsafe.Pointer(A)) = *(*uintptr)(unsafe.Pointer(B)) + *(*uintptr)(unsafe.Pointer(B)) = tmp +} + +func HistogramCopy(tls *libc.TLS, src uintptr, dst uintptr) { /* histogram_enc.c:50:13: */ + var dst_literal uintptr = (*VP8LHistogram)(unsafe.Pointer(dst)).literal_ + var dst_cache_bits int32 = (*VP8LHistogram)(unsafe.Pointer(dst)).palette_code_bits_ + var literal_size int32 = VP8LHistogramNumCodes(tls, dst_cache_bits) + var histo_size int32 = VP8LGetHistogramSize(tls, dst_cache_bits) + + libc.Xmemcpy(tls, dst, src, uint64(histo_size)) + (*VP8LHistogram)(unsafe.Pointer(dst)).literal_ = dst_literal + libc.Xmemcpy(tls, (*VP8LHistogram)(unsafe.Pointer(dst)).literal_, (*VP8LHistogram)(unsafe.Pointer(src)).literal_, (uint64(literal_size) * uint64(unsafe.Sizeof(uint32_t(0))))) +} + +func VP8LGetHistogramSize(tls *libc.TLS, cache_bits int32) int32 { /* histogram_enc.c:62:5: */ + var literal_size int32 = VP8LHistogramNumCodes(tls, cache_bits) + var total_size size_t = (uint64(unsafe.Sizeof(VP8LHistogram{})) + (uint64(unsafe.Sizeof(int32(0))) * uint64(literal_size))) + + return int32(total_size) +} + +func VP8LFreeHistogram(tls *libc.TLS, histo uintptr) { /* histogram_enc.c:69:6: */ + WebPSafeFree(tls, histo) +} + +func VP8LFreeHistogramSet(tls *libc.TLS, histo uintptr) { /* histogram_enc.c:73:6: */ + WebPSafeFree(tls, histo) +} + +func VP8LHistogramStoreRefs(tls *libc.TLS, refs uintptr, histo uintptr) { /* histogram_enc.c:77:6: */ + bp := tls.Alloc(24) + defer tls.Free(24) + + *(*VP8LRefsCursor)(unsafe.Pointer(bp /* c */)) = VP8LRefsCursorInit(tls, refs) + for VP8LRefsCursorOk(tls, (bp) /* &c */) != 0 { + VP8LHistogramAddSinglePixOrCopy(tls, histo, (*VP8LRefsCursor)(unsafe.Pointer(bp /* &c */)).cur_pos, (uintptr(0)), 0) + VP8LRefsCursorNext(tls, (bp) /* &c */) + } +} + +func VP8LHistogramCreate(tls *libc.TLS, p uintptr, refs uintptr, palette_code_bits int32) { /* histogram_enc.c:86:6: */ + if palette_code_bits >= 0 { + (*VP8LHistogram)(unsafe.Pointer(p)).palette_code_bits_ = palette_code_bits + } + HistogramClear(tls, p) + VP8LHistogramStoreRefs(tls, refs, p) +} + +func VP8LHistogramInit(tls *libc.TLS, p uintptr, palette_code_bits int32, init_arrays int32) { /* histogram_enc.c:96:6: */ + (*VP8LHistogram)(unsafe.Pointer(p)).palette_code_bits_ = palette_code_bits + if init_arrays != 0 { + HistogramClear(tls, p) + } else { + (*VP8LHistogram)(unsafe.Pointer(p)).trivial_symbol_ = uint32_t(0) + (*VP8LHistogram)(unsafe.Pointer(p)).bit_cost_ = 0. + (*VP8LHistogram)(unsafe.Pointer(p)).literal_cost_ = 0. + (*VP8LHistogram)(unsafe.Pointer(p)).red_cost_ = 0. + (*VP8LHistogram)(unsafe.Pointer(p)).blue_cost_ = 0. + libc.Xmemset(tls, (p + 3280 /* &.is_used_ */), 0, uint64(unsafe.Sizeof([5]uint8_t{}))) + } +} + +func VP8LAllocateHistogram(tls *libc.TLS, cache_bits int32) uintptr { /* histogram_enc.c:111:14: */ + var histo uintptr = (uintptr(0)) + var total_size int32 = VP8LGetHistogramSize(tls, cache_bits) + var memory uintptr = WebPSafeMalloc(tls, uint64(total_size), uint64(unsafe.Sizeof(uint8_t(0)))) + if memory == (uintptr(0)) { + return (uintptr(0)) + } + histo = memory + // literal_ won't necessary be aligned. + (*VP8LHistogram)(unsafe.Pointer(histo)).literal_ = (memory + uintptr(uint64(unsafe.Sizeof(VP8LHistogram{})))) + VP8LHistogramInit(tls, histo, cache_bits /*init_arrays=*/, 0) + return histo +} + +// Resets the pointers of the histograms to point to the bit buffer in the set. +func HistogramSetResetPointers(tls *libc.TLS, set uintptr, cache_bits int32) { /* histogram_enc.c:124:13: */ + var i int32 + var histo_size int32 = VP8LGetHistogramSize(tls, cache_bits) + var memory uintptr = ((*VP8LHistogramSet)(unsafe.Pointer(set)).histograms) + memory += (uintptr(uint64((*VP8LHistogramSet)(unsafe.Pointer(set)).max_size) * uint64(unsafe.Sizeof(uintptr(0))))) + for i = 0; i < (*VP8LHistogramSet)(unsafe.Pointer(set)).max_size; i++ { + memory = (uintptr((uintptr_t((memory)) + uint64(31)) & libc.Uint64FromInt32(libc.CplInt32(31)))) + *(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(set)).histograms + uintptr(i)*8)) = memory + // literal_ won't necessary be aligned. + (*VP8LHistogram)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(set)).histograms + uintptr(i)*8)))).literal_ = (memory + uintptr(uint64(unsafe.Sizeof(VP8LHistogram{})))) + memory += uintptr(histo_size) + } +} + +// Returns the total size of the VP8LHistogramSet. +func HistogramSetTotalSize(tls *libc.TLS, size int32, cache_bits int32) size_t { /* histogram_enc.c:140:15: */ + var histo_size int32 = VP8LGetHistogramSize(tls, cache_bits) + return (uint64(unsafe.Sizeof(VP8LHistogramSet{})) + (uint64(size) * ((uint64(unsafe.Sizeof(uintptr(0))) + uint64(histo_size)) + uint64(31)))) +} + +func VP8LAllocateHistogramSet(tls *libc.TLS, size int32, cache_bits int32) uintptr { /* histogram_enc.c:146:17: */ + var i int32 + var set uintptr + var total_size size_t = HistogramSetTotalSize(tls, size, cache_bits) + var memory uintptr = WebPSafeMalloc(tls, total_size, uint64(unsafe.Sizeof(uint8_t(0)))) + if memory == (uintptr(0)) { + return (uintptr(0)) + } + + set = memory + memory += uintptr(unsafe.Sizeof(VP8LHistogramSet{})) + (*VP8LHistogramSet)(unsafe.Pointer(set)).histograms = memory + (*VP8LHistogramSet)(unsafe.Pointer(set)).max_size = size + (*VP8LHistogramSet)(unsafe.Pointer(set)).size = size + HistogramSetResetPointers(tls, set, cache_bits) + for i = 0; i < size; i++ { + VP8LHistogramInit(tls, *(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(set)).histograms + uintptr(i)*8)), cache_bits /*init_arrays=*/, 0) + } + return set +} + +func VP8LHistogramSetClear(tls *libc.TLS, set uintptr) { /* histogram_enc.c:165:6: */ + var i int32 + var cache_bits int32 = (*VP8LHistogram)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(set)).histograms)))).palette_code_bits_ + var size int32 = (*VP8LHistogramSet)(unsafe.Pointer(set)).max_size + var total_size size_t = HistogramSetTotalSize(tls, size, cache_bits) + var memory uintptr = set + + libc.Xmemset(tls, memory, 0, total_size) + memory += uintptr(unsafe.Sizeof(VP8LHistogramSet{})) + (*VP8LHistogramSet)(unsafe.Pointer(set)).histograms = memory + (*VP8LHistogramSet)(unsafe.Pointer(set)).max_size = size + (*VP8LHistogramSet)(unsafe.Pointer(set)).size = size + HistogramSetResetPointers(tls, set, cache_bits) + for i = 0; i < size; i++ { + (*VP8LHistogram)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(set)).histograms + uintptr(i)*8)))).palette_code_bits_ = cache_bits + } +} + +// Removes the histogram 'i' from 'set' by setting it to NULL. +func HistogramSetRemoveHistogram(tls *libc.TLS, set uintptr, i int32, num_used uintptr) { /* histogram_enc.c:184:13: */ + + *(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(set)).histograms + uintptr(i)*8)) = (uintptr(0)) + *(*int32)(unsafe.Pointer(num_used))-- + // If we remove the last valid one, shrink until the next valid one. + if i == ((*VP8LHistogramSet)(unsafe.Pointer(set)).size - 1) { + for ((*VP8LHistogramSet)(unsafe.Pointer(set)).size >= 1) && (*(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(set)).histograms + uintptr(((*VP8LHistogramSet)(unsafe.Pointer(set)).size-1))*8)) == (uintptr(0))) { + (*VP8LHistogramSet)(unsafe.Pointer(set)).size-- + } + } +} + +// ----------------------------------------------------------------------------- + +func VP8LHistogramAddSinglePixOrCopy(tls *libc.TLS, histo uintptr, v uintptr, distance_modifier uintptr, distance_modifier_arg0 int32) { /* histogram_enc.c:199:6: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + if PixOrCopyIsLiteral(tls, v) != 0 { + *(*uint32_t)(unsafe.Pointer((histo + 2056 /* &.alpha_ */) + uintptr(PixOrCopyLiteral(tls, v, 3))*4))++ + *(*uint32_t)(unsafe.Pointer((histo + 8 /* &.red_ */) + uintptr(PixOrCopyLiteral(tls, v, 2))*4))++ + *(*uint32_t)(unsafe.Pointer((*VP8LHistogram)(unsafe.Pointer(histo)).literal_ + uintptr(PixOrCopyLiteral(tls, v, 1))*4))++ + *(*uint32_t)(unsafe.Pointer((histo + 1032 /* &.blue_ */) + uintptr(PixOrCopyLiteral(tls, v, 0))*4))++ + } else if PixOrCopyIsCacheIdx(tls, v) != 0 { + var literal_ix int32 = (int32((uint32_t(256 + 24)) + PixOrCopyCacheIdx(tls, v))) + + *(*uint32_t)(unsafe.Pointer((*VP8LHistogram)(unsafe.Pointer(histo)).literal_ + uintptr(literal_ix)*4))++ + } else { + // var code int32 at bp, 4 + + // var extra_bits int32 at bp+4, 4 + + VP8LPrefixEncodeBits(tls, int32(PixOrCopyLength(tls, v)), (bp) /* &code */, (bp + 4) /* &extra_bits */) + *(*uint32_t)(unsafe.Pointer((*VP8LHistogram)(unsafe.Pointer(histo)).literal_ + uintptr((256+*(*int32)(unsafe.Pointer(bp /* code */))))*4))++ + if distance_modifier == (uintptr(0)) { + VP8LPrefixEncodeBits(tls, int32(PixOrCopyDistance(tls, v)), (bp) /* &code */, (bp + 4) /* &extra_bits */) + } else { + VP8LPrefixEncodeBits(tls, + (*struct { + f func(*libc.TLS, int32, int32) int32 + })(unsafe.Pointer(&struct{ uintptr }{distance_modifier})).f(tls, distance_modifier_arg0, int32(PixOrCopyDistance(tls, v))), + (bp) /* &code */, (bp + 4) /* &extra_bits */) + } + *(*uint32_t)(unsafe.Pointer((histo + 3080 /* &.distance_ */) + uintptr(*(*int32)(unsafe.Pointer(bp /* code */)))*4))++ + } +} + +// ----------------------------------------------------------------------------- +// Entropy-related functions. + +func BitsEntropyRefine(tls *libc.TLS, entropy uintptr) float64 { /* histogram_enc.c:231:27: */ + var mix float64 + if (*VP8LBitEntropy)(unsafe.Pointer(entropy)).nonzeros < 5 { + if (*VP8LBitEntropy)(unsafe.Pointer(entropy)).nonzeros <= 1 { + return float64(0) + } + // Two symbols, they will be 0 and 1 in a Huffman code. + // Let's mix in a bit of entropy to favor good clustering when + // distributions of these are combined. + if (*VP8LBitEntropy)(unsafe.Pointer(entropy)).nonzeros == 2 { + return ((0.99 * float64((*VP8LBitEntropy)(unsafe.Pointer(entropy)).sum)) + (0.01 * (*VP8LBitEntropy)(unsafe.Pointer(entropy)).entropy)) + } + // No matter what the entropy says, we cannot be better than min_limit + // with Huffman coding. I am mixing a bit of entropy into the + // min_limit since it produces much better (~0.5 %) compression results + // perhaps because of better entropy clustering. + if (*VP8LBitEntropy)(unsafe.Pointer(entropy)).nonzeros == 3 { + mix = 0.95 + } else { + mix = 0.7 // nonzeros == 4. + } + } else { + mix = 0.627 + } + + { + var min_limit float64 = (float64((uint32_t(2) * (*VP8LBitEntropy)(unsafe.Pointer(entropy)).sum) - (*VP8LBitEntropy)(unsafe.Pointer(entropy)).max_val)) + min_limit = ((mix * min_limit) + ((1.0 - mix) * (*VP8LBitEntropy)(unsafe.Pointer(entropy)).entropy)) + if (*VP8LBitEntropy)(unsafe.Pointer(entropy)).entropy < min_limit { + return min_limit + } + return (*VP8LBitEntropy)(unsafe.Pointer(entropy)).entropy + + } + return float64(0) +} + +func VP8LBitsEntropy(tls *libc.TLS, array uintptr, n int32) float64 { /* histogram_enc.c:263:8: */ + bp := tls.Alloc(24) + defer tls.Free(24) + + // var entropy VP8LBitEntropy at bp, 24 + + VP8LBitsEntropyUnrefined(tls, array, n, (bp) /* &entropy */) + + return BitsEntropyRefine(tls, (bp) /* &entropy */) +} + +func InitialHuffmanCost(tls *libc.TLS) float64 { /* histogram_enc.c:270:15: */ + return (float64(kHuffmanCodeOfHuffmanCodeSize) - kSmallBias) +} + +var kHuffmanCodeOfHuffmanCodeSize int32 = (19 * 3) /* histogram_enc.c:273:20 */ +var kSmallBias float64 = 9.1 /* histogram_enc.c:274:23 */ + +// Finalize the Huffman cost based on streak numbers and length type (<3 or >=3) +func FinalHuffmanCost(tls *libc.TLS, stats uintptr) float64 { /* histogram_enc.c:279:15: */ + // The constants in this function are experimental and got rounded from + // their original values in 1/8 when switched to 1/1024. + var retval float64 = InitialHuffmanCost(tls) + // Second coefficient: Many zeros in the histogram are covered efficiently + // by a run-length encode. Originally 2/8. + retval = retval + ((float64(*(*int32)(unsafe.Pointer((stats /* &.counts */)))) * 1.5625) + (0.234375 * float64(*(*int32)(unsafe.Pointer((stats + 8 /* &.streaks */) + 1*4))))) + // Second coefficient: Constant values are encoded less efficiently, but still + // RLE'ed. Originally 6/8. + retval = retval + ((float64(*(*int32)(unsafe.Pointer((stats /* &.counts */) + 1*4))) * 2.578125) + (0.703125 * float64(*(*int32)(unsafe.Pointer(((stats + 8 /* &.streaks */) + 1*8) + 1*4))))) + // 0s are usually encoded more efficiently than non-0s. + // Originally 15/8. + retval = retval + (1.796875 * float64(*(*int32)(unsafe.Pointer((stats + 8 /* &.streaks */))))) + // Originally 26/8. + retval = retval + (3.28125 * float64(*(*int32)(unsafe.Pointer(((stats + 8 /* &.streaks */) + 1*8))))) + return retval +} + +// Get the symbol entropy for the distribution 'population'. +// Set 'trivial_sym', if there's only one symbol present in the distribution. +func PopulationCost(tls *libc.TLS, population uintptr, length int32, trivial_sym uintptr, is_used uintptr) float64 { /* histogram_enc.c:299:15: */ + bp := tls.Alloc(48) + defer tls.Free(48) + + // var bit_entropy VP8LBitEntropy at bp, 24 + + // var stats VP8LStreaks at bp+24, 24 + + (*struct { + f func(*libc.TLS, uintptr, int32, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LGetEntropyUnrefined})).f(tls, population, length, (bp) /* &bit_entropy */, (bp + 24) /* &stats */) + if trivial_sym != (uintptr(0)) { + *(*uint32_t)(unsafe.Pointer(trivial_sym)) = func() uint32 { + if (*VP8LBitEntropy)(unsafe.Pointer(bp /* &bit_entropy */)).nonzeros == 1 { + return (*VP8LBitEntropy)(unsafe.Pointer(bp /* &bit_entropy */)).nonzero_code + } + return (0xffffffff) + }() + } + // The histogram is used if there is at least one non-zero streak. + *(*uint8_t)(unsafe.Pointer(is_used)) = (uint8_t(libc.Bool32((*(*int32)(unsafe.Pointer((((bp + 24) /* &stats */ + 8 /* &.streaks */) + 1*8))) != 0) || (*(*int32)(unsafe.Pointer((((bp + 24) /* &stats */ + 8 /* &.streaks */) + 1*8) + 1*4)) != 0)))) + + return (BitsEntropyRefine(tls, (bp) /* &bit_entropy */) + FinalHuffmanCost(tls, (bp+24) /* &stats */)) +} + +// trivial_at_end is 1 if the two histograms only have one element that is +// non-zero: both the zero-th one, or both the last one. +func GetCombinedEntropy(tls *libc.TLS, X uintptr, Y uintptr, length int32, is_X_used int32, is_Y_used int32, trivial_at_end int32) float64 { /* histogram_enc.c:317:27: */ + bp := tls.Alloc(48) + defer tls.Free(48) + + // var stats VP8LStreaks at bp, 24 + + if trivial_at_end != 0 { + // This configuration is due to palettization that transforms an indexed + // pixel into 0xff000000 | (pixel << 8) in VP8LBundleColorMap. + // BitsEntropyRefine is 0 for histograms with only one non-zero value. + // Only FinalHuffmanCost needs to be evaluated. + libc.Xmemset(tls, (bp) /* &stats */, 0, uint64(unsafe.Sizeof(VP8LStreaks{}))) + // Deal with the non-zero value at index 0 or length-1. + *(*int32)(unsafe.Pointer((((bp) /* &stats */ + 8 /* &.streaks */) + 1*8))) = 1 + // Deal with the following/previous zero streak. + *(*int32)(unsafe.Pointer((bp) /* &stats */ /* &.counts */)) = 1 + *(*int32)(unsafe.Pointer(((bp) /* &stats */ + 8 /* &.streaks */) + 1*4)) = (length - 1) + return FinalHuffmanCost(tls, (bp) /* &stats */) + } else { + // var bit_entropy VP8LBitEntropy at bp+24, 24 + + if is_X_used != 0 { + if is_Y_used != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LGetCombinedEntropyUnrefined})).f(tls, X, Y, length, (bp + 24) /* &bit_entropy */, (bp) /* &stats */) + } else { + (*struct { + f func(*libc.TLS, uintptr, int32, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LGetEntropyUnrefined})).f(tls, X, length, (bp + 24) /* &bit_entropy */, (bp) /* &stats */) + } + } else { + if is_Y_used != 0 { + (*struct { + f func(*libc.TLS, uintptr, int32, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LGetEntropyUnrefined})).f(tls, Y, length, (bp + 24) /* &bit_entropy */, (bp) /* &stats */) + } else { + libc.Xmemset(tls, (bp) /* &stats */, 0, uint64(unsafe.Sizeof(VP8LStreaks{}))) + *(*int32)(unsafe.Pointer((bp) /* &stats */ /* &.counts */)) = 1 + *(*int32)(unsafe.Pointer(((bp) /* &stats */ + 8 /* &.streaks */) + uintptr((libc.Bool32(length > 3)))*4)) = length + VP8LBitEntropyInit(tls, (bp + 24) /* &bit_entropy */) + } + } + + return (BitsEntropyRefine(tls, (bp+24) /* &bit_entropy */) + FinalHuffmanCost(tls, (bp) /* &stats */)) + } + return float64(0) +} + +// Estimates the Entropy + Huffman + other block overhead size cost. +func VP8LHistogramEstimateBits(tls *libc.TLS, p uintptr) float64 { /* histogram_enc.c:359:8: */ + return ((((((PopulationCost(tls, (*VP8LHistogram)(unsafe.Pointer(p)).literal_, VP8LHistogramNumCodes(tls, (*VP8LHistogram)(unsafe.Pointer(p)).palette_code_bits_), + (uintptr(0)), (p+3280 /* &.is_used_ */)) + + PopulationCost(tls, (p+8 /* &.red_ */), 256, (uintptr(0)), ((p+3280 /* &.is_used_ */)+1))) + + PopulationCost(tls, (p+1032 /* &.blue_ */), 256, (uintptr(0)), ((p+3280 /* &.is_used_ */)+2))) + + PopulationCost(tls, (p+2056 /* &.alpha_ */), 256, (uintptr(0)), ((p+3280 /* &.is_used_ */)+3))) + + PopulationCost(tls, (p+3080 /* &.distance_ */), 40, (uintptr(0)), ((p+3280 /* &.is_used_ */)+4))) + + (*struct { + f func(*libc.TLS, uintptr, int32) float64 + })(unsafe.Pointer(&struct{ uintptr }{VP8LExtraCost})).f(tls, ((*VP8LHistogram)(unsafe.Pointer(p)).literal_+uintptr(256)*4), 24)) + + (*struct { + f func(*libc.TLS, uintptr, int32) float64 + })(unsafe.Pointer(&struct{ uintptr }{VP8LExtraCost})).f(tls, (p+3080 /* &.distance_ */), 40)) +} + +// ----------------------------------------------------------------------------- +// Various histogram combine/cost-eval functions + +func GetCombinedHistogramEntropy(tls *libc.TLS, a uintptr, b uintptr, cost_threshold float64, cost uintptr) int32 { /* histogram_enc.c:374:12: */ + var palette_code_bits int32 = (*VP8LHistogram)(unsafe.Pointer(a)).palette_code_bits_ + var trivial_at_end int32 = 0 + + *(*float64)(unsafe.Pointer(cost)) += (GetCombinedEntropy(tls, (*VP8LHistogram)(unsafe.Pointer(a)).literal_, (*VP8LHistogram)(unsafe.Pointer(b)).literal_, + VP8LHistogramNumCodes(tls, palette_code_bits), + int32(*(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */)))), int32(*(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */)))), 0)) + *(*float64)(unsafe.Pointer(cost)) += ((*struct { + f func(*libc.TLS, uintptr, uintptr, int32) float64 + })(unsafe.Pointer(&struct{ uintptr }{VP8LExtraCostCombined})).f(tls, ((*VP8LHistogram)(unsafe.Pointer(a)).literal_ + uintptr(256)*4), + ((*VP8LHistogram)(unsafe.Pointer(b)).literal_ + uintptr(256)*4), + 24)) + if *(*float64)(unsafe.Pointer(cost)) > cost_threshold { + return 0 + } + + if ((*VP8LHistogram)(unsafe.Pointer(a)).trivial_symbol_ != (0xffffffff)) && ((*VP8LHistogram)(unsafe.Pointer(a)).trivial_symbol_ == (*VP8LHistogram)(unsafe.Pointer(b)).trivial_symbol_) { + // A, R and B are all 0 or 0xff. + var color_a uint32_t = (((*VP8LHistogram)(unsafe.Pointer(a)).trivial_symbol_ >> 24) & uint32_t(0xff)) + var color_r uint32_t = (((*VP8LHistogram)(unsafe.Pointer(a)).trivial_symbol_ >> 16) & uint32_t(0xff)) + var color_b uint32_t = (((*VP8LHistogram)(unsafe.Pointer(a)).trivial_symbol_ >> 0) & uint32_t(0xff)) + if (((color_a == uint32_t(0)) || (color_a == uint32_t(0xff))) && ((color_r == uint32_t(0)) || (color_r == uint32_t(0xff)))) && ((color_b == uint32_t(0)) || (color_b == uint32_t(0xff))) { + trivial_at_end = 1 + } + } + + *(*float64)(unsafe.Pointer(cost)) += (GetCombinedEntropy(tls, (a + 8 /* &.red_ */), (b + 8 /* &.red_ */), 256, int32(*(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */) + 1))), + int32(*(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */) + 1))), trivial_at_end)) + if *(*float64)(unsafe.Pointer(cost)) > cost_threshold { + return 0 + } + + *(*float64)(unsafe.Pointer(cost)) += (GetCombinedEntropy(tls, (a + 1032 /* &.blue_ */), (b + 1032 /* &.blue_ */), 256, int32(*(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */) + 2))), + int32(*(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */) + 2))), trivial_at_end)) + if *(*float64)(unsafe.Pointer(cost)) > cost_threshold { + return 0 + } + + *(*float64)(unsafe.Pointer(cost)) += (GetCombinedEntropy(tls, (a + 2056 /* &.alpha_ */), (b + 2056 /* &.alpha_ */), 256, + int32(*(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */) + 3))), int32(*(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */) + 3))), trivial_at_end)) + if *(*float64)(unsafe.Pointer(cost)) > cost_threshold { + return 0 + } + + *(*float64)(unsafe.Pointer(cost)) += (GetCombinedEntropy(tls, (a + 3080 /* &.distance_ */), (b + 3080 /* &.distance_ */), 40, + int32(*(*uint8_t)(unsafe.Pointer((a + 3280 /* &.is_used_ */) + 4))), int32(*(*uint8_t)(unsafe.Pointer((b + 3280 /* &.is_used_ */) + 4))), 0)) + *(*float64)(unsafe.Pointer(cost)) += ((*struct { + f func(*libc.TLS, uintptr, uintptr, int32) float64 + })(unsafe.Pointer(&struct{ uintptr }{VP8LExtraCostCombined})).f(tls, (a + 3080 /* &.distance_ */), (b + 3080 /* &.distance_ */), 40)) + if *(*float64)(unsafe.Pointer(cost)) > cost_threshold { + return 0 + } + + return 1 +} + +func HistogramAdd(tls *libc.TLS, a uintptr, b uintptr, out uintptr) { /* histogram_enc.c:427:25: */ + VP8LHistogramAdd(tls, a, b, out) + (*VP8LHistogram)(unsafe.Pointer(out)).trivial_symbol_ = func() uint32 { + if (*VP8LHistogram)(unsafe.Pointer(a)).trivial_symbol_ == (*VP8LHistogram)(unsafe.Pointer(b)).trivial_symbol_ { + return (*VP8LHistogram)(unsafe.Pointer(a)).trivial_symbol_ + } + return (0xffffffff) + }() +} + +// Performs out = a + b, computing the cost C(a+b) - C(a) - C(b) while comparing +// to the threshold value 'cost_threshold'. The score returned is +// Score = C(a+b) - C(a) - C(b), where C(a) + C(b) is known and fixed. +// Since the previous score passed is 'cost_threshold', we only need to compare +// the partial cost against 'cost_threshold + C(a) + C(b)' to possibly bail-out +// early. +func HistogramAddEval(tls *libc.TLS, a uintptr, b uintptr, out uintptr, cost_threshold float64) float64 { /* histogram_enc.c:442:15: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + *(*float64)(unsafe.Pointer(bp /* cost */)) = float64(0) + var sum_cost float64 = ((*VP8LHistogram)(unsafe.Pointer(a)).bit_cost_ + (*VP8LHistogram)(unsafe.Pointer(b)).bit_cost_) + cost_threshold = cost_threshold + (sum_cost) + + if GetCombinedHistogramEntropy(tls, a, b, cost_threshold, (bp) /* &cost */) != 0 { + HistogramAdd(tls, a, b, out) + (*VP8LHistogram)(unsafe.Pointer(out)).bit_cost_ = *(*float64)(unsafe.Pointer(bp /* cost */)) + (*VP8LHistogram)(unsafe.Pointer(out)).palette_code_bits_ = (*VP8LHistogram)(unsafe.Pointer(a)).palette_code_bits_ + } + + return (*(*float64)(unsafe.Pointer(bp /* cost */)) - sum_cost) +} + +// Same as HistogramAddEval(), except that the resulting histogram +// is not stored. Only the cost C(a+b) - C(a) is evaluated. We omit +// the term C(b) which is constant over all the evaluations. +func HistogramAddThresh(tls *libc.TLS, a uintptr, b uintptr, cost_threshold float64) float64 { /* histogram_enc.c:462:15: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + // var cost float64 at bp, 8 + + *(*float64)(unsafe.Pointer(bp /* cost */)) = -(*VP8LHistogram)(unsafe.Pointer(a)).bit_cost_ + GetCombinedHistogramEntropy(tls, a, b, cost_threshold, (bp) /* &cost */) + return *(*float64)(unsafe.Pointer(bp /* cost */)) +} + +// ----------------------------------------------------------------------------- + +// The structure to keep track of cost range for the three dominant entropy +// symbols. +// TODO(skal): Evaluate if float can be used here instead of double for +// representing the entropy costs. +type DominantCostRange = struct { + literal_max_ float64 + literal_min_ float64 + red_max_ float64 + red_min_ float64 + blue_max_ float64 + blue_min_ float64 +} /* histogram_enc.c:485:3 */ + +func DominantCostRangeInit(tls *libc.TLS, c uintptr) { /* histogram_enc.c:487:13: */ + (*DominantCostRange)(unsafe.Pointer(c)).literal_max_ = 0. + (*DominantCostRange)(unsafe.Pointer(c)).literal_min_ = 1.e38 + (*DominantCostRange)(unsafe.Pointer(c)).red_max_ = 0. + (*DominantCostRange)(unsafe.Pointer(c)).red_min_ = 1.e38 + (*DominantCostRange)(unsafe.Pointer(c)).blue_max_ = 0. + (*DominantCostRange)(unsafe.Pointer(c)).blue_min_ = 1.e38 +} + +func UpdateDominantCostRange(tls *libc.TLS, h uintptr, c uintptr) { /* histogram_enc.c:496:13: */ + if (*DominantCostRange)(unsafe.Pointer(c)).literal_max_ < (*VP8LHistogram)(unsafe.Pointer(h)).literal_cost_ { + (*DominantCostRange)(unsafe.Pointer(c)).literal_max_ = (*VP8LHistogram)(unsafe.Pointer(h)).literal_cost_ + } + if (*DominantCostRange)(unsafe.Pointer(c)).literal_min_ > (*VP8LHistogram)(unsafe.Pointer(h)).literal_cost_ { + (*DominantCostRange)(unsafe.Pointer(c)).literal_min_ = (*VP8LHistogram)(unsafe.Pointer(h)).literal_cost_ + } + if (*DominantCostRange)(unsafe.Pointer(c)).red_max_ < (*VP8LHistogram)(unsafe.Pointer(h)).red_cost_ { + (*DominantCostRange)(unsafe.Pointer(c)).red_max_ = (*VP8LHistogram)(unsafe.Pointer(h)).red_cost_ + } + if (*DominantCostRange)(unsafe.Pointer(c)).red_min_ > (*VP8LHistogram)(unsafe.Pointer(h)).red_cost_ { + (*DominantCostRange)(unsafe.Pointer(c)).red_min_ = (*VP8LHistogram)(unsafe.Pointer(h)).red_cost_ + } + if (*DominantCostRange)(unsafe.Pointer(c)).blue_max_ < (*VP8LHistogram)(unsafe.Pointer(h)).blue_cost_ { + (*DominantCostRange)(unsafe.Pointer(c)).blue_max_ = (*VP8LHistogram)(unsafe.Pointer(h)).blue_cost_ + } + if (*DominantCostRange)(unsafe.Pointer(c)).blue_min_ > (*VP8LHistogram)(unsafe.Pointer(h)).blue_cost_ { + (*DominantCostRange)(unsafe.Pointer(c)).blue_min_ = (*VP8LHistogram)(unsafe.Pointer(h)).blue_cost_ + } +} + +func UpdateHistogramCost(tls *libc.TLS, h uintptr) { /* histogram_enc.c:506:13: */ + bp := tls.Alloc(12) + defer tls.Free(12) + + // var alpha_sym uint32_t at bp, 4 + + // var red_sym uint32_t at bp+4, 4 + + // var blue_sym uint32_t at bp+8, 4 + + var alpha_cost float64 = PopulationCost(tls, (h + 2056 /* &.alpha_ */), 256, (bp), /* &alpha_sym */ + ((h + 3280 /* &.is_used_ */) + 3)) + var distance_cost float64 = (PopulationCost(tls, (h+3080 /* &.distance_ */), 40, (uintptr(0)), ((h+3280 /* &.is_used_ */)+4)) + (*struct { + f func(*libc.TLS, uintptr, int32) float64 + })(unsafe.Pointer(&struct{ uintptr }{VP8LExtraCost})).f(tls, (h+3080 /* &.distance_ */), 40)) + var num_codes int32 = VP8LHistogramNumCodes(tls, (*VP8LHistogram)(unsafe.Pointer(h)).palette_code_bits_) + (*VP8LHistogram)(unsafe.Pointer(h)).literal_cost_ = (PopulationCost(tls, (*VP8LHistogram)(unsafe.Pointer(h)).literal_, num_codes, (uintptr(0)), (h+3280 /* &.is_used_ */)) + (*struct { + f func(*libc.TLS, uintptr, int32) float64 + })(unsafe.Pointer(&struct{ uintptr }{VP8LExtraCost})).f(tls, ((*VP8LHistogram)(unsafe.Pointer(h)).literal_+uintptr(256)*4), 24)) + (*VP8LHistogram)(unsafe.Pointer(h)).red_cost_ = PopulationCost(tls, (h + 8 /* &.red_ */), 256, (bp + 4) /* &red_sym */, ((h + 3280 /* &.is_used_ */) + 1)) + (*VP8LHistogram)(unsafe.Pointer(h)).blue_cost_ = PopulationCost(tls, (h + 1032 /* &.blue_ */), 256, (bp + 8) /* &blue_sym */, ((h + 3280 /* &.is_used_ */) + 2)) + (*VP8LHistogram)(unsafe.Pointer(h)).bit_cost_ = (((((*VP8LHistogram)(unsafe.Pointer(h)).literal_cost_ + (*VP8LHistogram)(unsafe.Pointer(h)).red_cost_) + (*VP8LHistogram)(unsafe.Pointer(h)).blue_cost_) + alpha_cost) + distance_cost) + if ((*(*uint32_t)(unsafe.Pointer(bp /* alpha_sym */)) | *(*uint32_t)(unsafe.Pointer(bp + 4 /* red_sym */))) | *(*uint32_t)(unsafe.Pointer(bp + 8 /* blue_sym */))) == (0xffffffff) { + (*VP8LHistogram)(unsafe.Pointer(h)).trivial_symbol_ = (0xffffffff) + } else { + (*VP8LHistogram)(unsafe.Pointer(h)).trivial_symbol_ = (((*(*uint32_t)(unsafe.Pointer(bp /* alpha_sym */)) << 24) | (*(*uint32_t)(unsafe.Pointer(bp + 4 /* red_sym */)) << 16)) | (*(*uint32_t)(unsafe.Pointer(bp + 8 /* blue_sym */)) << 0)) + } +} + +func GetBinIdForEntropy(tls *libc.TLS, min float64, max float64, val float64) int32 { /* histogram_enc.c:532:12: */ + var range1 float64 = (max - min) + if range1 > 0. { + var delta float64 = (val - min) + return (libc.Int32FromFloat64(((float64(float64(4)) - 1e-6) * delta) / range1)) + } else { + return 0 + } + return int32(0) +} + +func GetHistoBinIndex(tls *libc.TLS, h uintptr, c uintptr, low_effort int32) int32 { /* histogram_enc.c:542:12: */ + var bin_id int32 = GetBinIdForEntropy(tls, (*DominantCostRange)(unsafe.Pointer(c)).literal_min_, (*DominantCostRange)(unsafe.Pointer(c)).literal_max_, + (*VP8LHistogram)(unsafe.Pointer(h)).literal_cost_) + + if !(low_effort != 0) { + bin_id = ((bin_id * 4) + + GetBinIdForEntropy(tls, (*DominantCostRange)(unsafe.Pointer(c)).red_min_, (*DominantCostRange)(unsafe.Pointer(c)).red_max_, (*VP8LHistogram)(unsafe.Pointer(h)).red_cost_)) + bin_id = ((bin_id * 4) + + GetBinIdForEntropy(tls, (*DominantCostRange)(unsafe.Pointer(c)).blue_min_, (*DominantCostRange)(unsafe.Pointer(c)).blue_max_, (*VP8LHistogram)(unsafe.Pointer(h)).blue_cost_)) + + } + return bin_id +} + +// Construct the histograms from backward references. +func HistogramBuild(tls *libc.TLS, xsize int32, histo_bits int32, backward_refs uintptr, image_histo uintptr) { /* histogram_enc.c:558:13: */ + bp := tls.Alloc(24) + defer tls.Free(24) + + var x int32 = 0 + var y int32 = 0 + var histo_xsize int32 = int32(VP8LSubSampleSize(tls, uint32(xsize), uint32(histo_bits))) + var histograms uintptr = (*VP8LHistogramSet)(unsafe.Pointer(image_histo)).histograms + *(*VP8LRefsCursor)(unsafe.Pointer(bp /* c */)) = VP8LRefsCursorInit(tls, backward_refs) + + VP8LHistogramSetClear(tls, image_histo) + for VP8LRefsCursorOk(tls, (bp) /* &c */) != 0 { + var v uintptr = (*VP8LRefsCursor)(unsafe.Pointer(bp /* &c */)).cur_pos + var ix int32 = (((y >> histo_bits) * histo_xsize) + (x >> histo_bits)) + VP8LHistogramAddSinglePixOrCopy(tls, *(*uintptr)(unsafe.Pointer(histograms + uintptr(ix)*8)), v, (uintptr(0)), 0) + x = int32(uint32_t(x) + (PixOrCopyLength(tls, v))) + for x >= xsize { + x = x - (xsize) + y++ + } + VP8LRefsCursorNext(tls, (bp) /* &c */) + } +} + +// Copies the histograms and computes its bit_cost. +var kInvalidHistogramSymbol uint16_t = libc.Uint16((libc.Uint16FromInt32(-1))) /* histogram_enc.c:581:23 */ + +func HistogramCopyAndAnalyze(tls *libc.TLS, orig_histo uintptr, image_histo uintptr, num_used uintptr, histogram_symbols uintptr) { /* histogram_enc.c:582:13: */ + bp := tls.Alloc(4) + defer tls.Free(4) + + var i int32 + var cluster_id int32 + *(*int32)(unsafe.Pointer(bp /* num_used_orig */)) = *(*int32)(unsafe.Pointer(num_used)) + var orig_histograms uintptr = (*VP8LHistogramSet)(unsafe.Pointer(orig_histo)).histograms + var histograms uintptr = (*VP8LHistogramSet)(unsafe.Pointer(image_histo)).histograms + + cluster_id = 0 + i = 0 + for ; i < (*VP8LHistogramSet)(unsafe.Pointer(orig_histo)).max_size; i++ { + var histo uintptr = *(*uintptr)(unsafe.Pointer(orig_histograms + uintptr(i)*8)) + UpdateHistogramCost(tls, histo) + + // Skip the histogram if it is completely empty, which can happen for tiles + // with no information (when they are skipped because of LZ77). + if (((!(int32(*(*uint8_t)(unsafe.Pointer((histo + 3280 /* &.is_used_ */)))) != 0) && !(int32(*(*uint8_t)(unsafe.Pointer((histo + 3280 /* &.is_used_ */) + 1))) != 0)) && !(int32(*(*uint8_t)(unsafe.Pointer((histo + 3280 /* &.is_used_ */) + 2))) != 0)) && + !(int32(*(*uint8_t)(unsafe.Pointer((histo + 3280 /* &.is_used_ */) + 3))) != 0)) && !(int32(*(*uint8_t)(unsafe.Pointer((histo + 3280 /* &.is_used_ */) + 4))) != 0) { + // The first histogram is always used. If an histogram is empty, we set + // its id to be the same as the previous one: this will improve + // compressibility for later LZ77. + + HistogramSetRemoveHistogram(tls, image_histo, i, num_used) + HistogramSetRemoveHistogram(tls, orig_histo, i, (bp) /* &num_used_orig */) + *(*uint16_t)(unsafe.Pointer(histogram_symbols + uintptr(i)*2)) = kInvalidHistogramSymbol + } else { + // Copy histograms from orig_histo[] to image_histo[]. + HistogramCopy(tls, histo, *(*uintptr)(unsafe.Pointer(histograms + uintptr(i)*8))) + *(*uint16_t)(unsafe.Pointer(histogram_symbols + uintptr(i)*2)) = uint16_t(libc.PostIncInt32(&cluster_id, 1)) + + } + } +} + +// Partition histograms to different entropy bins for three dominant (literal, +// red and blue) symbol costs and compute the histogram aggregate bit_cost. +func HistogramAnalyzeEntropyBin(tls *libc.TLS, image_histo uintptr, bin_map uintptr, low_effort int32) { /* histogram_enc.c:617:13: */ + bp := tls.Alloc(48) + defer tls.Free(48) + + var i int32 + var histograms uintptr = (*VP8LHistogramSet)(unsafe.Pointer(image_histo)).histograms + var histo_size int32 = (*VP8LHistogramSet)(unsafe.Pointer(image_histo)).size + // var cost_range DominantCostRange at bp, 48 + + DominantCostRangeInit(tls, (bp) /* &cost_range */) + + // Analyze the dominant (literal, red and blue) entropy costs. + for i = 0; i < histo_size; i++ { + if *(*uintptr)(unsafe.Pointer(histograms + uintptr(i)*8)) == (uintptr(0)) { + continue + } + UpdateDominantCostRange(tls, *(*uintptr)(unsafe.Pointer(histograms + uintptr(i)*8)), (bp) /* &cost_range */) + } + + // bin-hash histograms on three of the dominant (literal, red and blue) + // symbol costs and store the resulting bin_id for each histogram. + for i = 0; i < histo_size; i++ { + // bin_map[i] is not set to a special value as its use will later be guarded + // by another (histograms[i] == NULL). + if *(*uintptr)(unsafe.Pointer(histograms + uintptr(i)*8)) == (uintptr(0)) { + continue + } + *(*uint16_t)(unsafe.Pointer(bin_map + uintptr(i)*2)) = uint16_t(GetHistoBinIndex(tls, *(*uintptr)(unsafe.Pointer(histograms + uintptr(i)*8)), (bp) /* &cost_range */, low_effort)) + } +} + +// Merges some histograms with same bin_id together if it's advantageous. +// Sets the remaining histograms to NULL. +func HistogramCombineEntropyBin(tls *libc.TLS, image_histo uintptr, num_used uintptr, clusters uintptr, cluster_mappings uintptr, cur_combo uintptr, bin_map uintptr, num_bins int32, combine_cost_factor float64, low_effort int32) { /* histogram_enc.c:644:13: */ + bp := tls.Alloc(264) + defer tls.Free(264) + *(*uintptr)(unsafe.Pointer(bp + 256)) = cur_combo + + var histograms uintptr = (*VP8LHistogramSet)(unsafe.Pointer(image_histo)).histograms + var idx int32 + // var bin_info [64]struct {first int16_t;num_combine_failures uint16_t;} at bp, 256 + + for idx = 0; idx < num_bins; idx++ { + (*struct { + first int16_t + num_combine_failures uint16_t + })(unsafe.Pointer((bp) /* &bin_info */ + uintptr(idx)*4)).first = int16(-1) + (*struct { + first int16_t + num_combine_failures uint16_t + })(unsafe.Pointer((bp) /* &bin_info */ + uintptr(idx)*4)).num_combine_failures = uint16_t(0) + } + + // By default, a cluster matches itself. + for idx = 0; idx < *(*int32)(unsafe.Pointer(num_used)); idx++ { + *(*uint16_t)(unsafe.Pointer(cluster_mappings + uintptr(idx)*2)) = uint16_t(idx) + } + for idx = 0; idx < (*VP8LHistogramSet)(unsafe.Pointer(image_histo)).size; idx++ { + var bin_id int32 + var first int32 + if *(*uintptr)(unsafe.Pointer(histograms + uintptr(idx)*8)) == (uintptr(0)) { + continue + } + bin_id = int32(*(*uint16_t)(unsafe.Pointer(bin_map + uintptr(idx)*2))) + first = int32((*struct { + first int16_t + num_combine_failures uint16_t + })(unsafe.Pointer((bp) /* &bin_info */ + uintptr(bin_id)*4)).first) + if first == -1 { + (*struct { + first int16_t + num_combine_failures uint16_t + })(unsafe.Pointer((bp) /* &bin_info */ + uintptr(bin_id)*4)).first = int16_t(idx) + } else if low_effort != 0 { + HistogramAdd(tls, *(*uintptr)(unsafe.Pointer(histograms + uintptr(idx)*8)), *(*uintptr)(unsafe.Pointer(histograms + uintptr(first)*8)), *(*uintptr)(unsafe.Pointer(histograms + uintptr(first)*8))) + HistogramSetRemoveHistogram(tls, image_histo, idx, num_used) + *(*uint16_t)(unsafe.Pointer(cluster_mappings + uintptr(*(*uint16_t)(unsafe.Pointer(clusters + uintptr(idx)*2)))*2)) = *(*uint16_t)(unsafe.Pointer(clusters + uintptr(first)*2)) + } else { + // try to merge #idx into #first (both share the same bin_id) + var bit_cost float64 = (*VP8LHistogram)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(histograms + uintptr(idx)*8)))).bit_cost_ + var bit_cost_thresh float64 = (-bit_cost * combine_cost_factor) + var curr_cost_diff float64 = HistogramAddEval(tls, *(*uintptr)(unsafe.Pointer(histograms + uintptr(first)*8)), *(*uintptr)(unsafe.Pointer(histograms + uintptr(idx)*8)), + *(*uintptr)(unsafe.Pointer(bp + 256 /* cur_combo */)), bit_cost_thresh) + if curr_cost_diff < bit_cost_thresh { + // Try to merge two histograms only if the combo is a trivial one or + // the two candidate histograms are already non-trivial. + // For some images, 'try_combine' turns out to be false for a lot of + // histogram pairs. In that case, we fallback to combining + // histograms as usual to avoid increasing the header size. + var try_combine int32 = (libc.Bool32(((*VP8LHistogram)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(bp + 256 /* cur_combo */)))).trivial_symbol_ != (0xffffffff)) || (((*VP8LHistogram)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(histograms + uintptr(idx)*8)))).trivial_symbol_ == (0xffffffff)) && ((*VP8LHistogram)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(histograms + uintptr(first)*8)))).trivial_symbol_ == (0xffffffff))))) + var max_combine_failures int32 = 32 + if (try_combine != 0) || (int32((*struct { + first int16_t + num_combine_failures uint16_t + })(unsafe.Pointer((bp) /* &bin_info */ +uintptr(bin_id)*4)).num_combine_failures) >= max_combine_failures) { + // move the (better) merged histogram to its final slot + HistogramSwap(tls, (bp + 256) /* &cur_combo */, (histograms + uintptr(first)*8)) + HistogramSetRemoveHistogram(tls, image_histo, idx, num_used) + *(*uint16_t)(unsafe.Pointer(cluster_mappings + uintptr(*(*uint16_t)(unsafe.Pointer(clusters + uintptr(idx)*2)))*2)) = *(*uint16_t)(unsafe.Pointer(clusters + uintptr(first)*2)) + } else { + (*struct { + first int16_t + num_combine_failures uint16_t + })(unsafe.Pointer((bp) /* &bin_info */ +uintptr(bin_id)*4)).num_combine_failures++ + } + } + } + } + if low_effort != 0 { + // for low_effort case, update the final cost when everything is merged + for idx = 0; idx < (*VP8LHistogramSet)(unsafe.Pointer(image_histo)).size; idx++ { + if *(*uintptr)(unsafe.Pointer(histograms + uintptr(idx)*8)) == (uintptr(0)) { + continue + } + UpdateHistogramCost(tls, *(*uintptr)(unsafe.Pointer(histograms + uintptr(idx)*8))) + } + } +} + +// Implement a Lehmer random number generator with a multiplicative constant of +// 48271 and a modulo constant of 2^31 - 1. +func MyRand(tls *libc.TLS, seed uintptr) uint32_t { /* histogram_enc.c:721:17: */ + *(*uint32_t)(unsafe.Pointer(seed)) = (uint32_t(((uint64_t(*(*uint32_t)(unsafe.Pointer(seed)))) * uint64(48271)) % uint64(2147483647))) + + return *(*uint32_t)(unsafe.Pointer(seed)) +} + +// ----------------------------------------------------------------------------- +// Histogram pairs priority queue + +// Pair of histograms. Negative idx1 value means that pair is out-of-date. +type HistogramPair = struct { + idx1 int32 + idx2 int32 + cost_diff float64 + cost_combo float64 +} /* histogram_enc.c:736:3 */ + +type HistoQueue = struct { + queue uintptr + size int32 + max_size int32 +} /* histogram_enc.c:742:3 */ + +func HistoQueueInit(tls *libc.TLS, histo_queue uintptr, max_size int32) int32 { /* histogram_enc.c:744:12: */ + (*HistoQueue)(unsafe.Pointer(histo_queue)).size = 0 + (*HistoQueue)(unsafe.Pointer(histo_queue)).max_size = max_size + // We allocate max_size + 1 because the last element at index "size" is + // used as temporary data (and it could be up to max_size). + (*HistoQueue)(unsafe.Pointer(histo_queue)).queue = WebPSafeMalloc(tls, + (uint64((*HistoQueue)(unsafe.Pointer(histo_queue)).max_size + 1)), uint64(unsafe.Sizeof(HistogramPair{}))) + return (libc.Bool32((*HistoQueue)(unsafe.Pointer(histo_queue)).queue != (uintptr(0)))) +} + +func HistoQueueClear(tls *libc.TLS, histo_queue uintptr) { /* histogram_enc.c:754:13: */ + + WebPSafeFree(tls, (*HistoQueue)(unsafe.Pointer(histo_queue)).queue) + (*HistoQueue)(unsafe.Pointer(histo_queue)).size = 0 + (*HistoQueue)(unsafe.Pointer(histo_queue)).max_size = 0 +} + +// Pop a specific pair in the queue by replacing it with the last one +// and shrinking the queue. +func HistoQueuePopPair(tls *libc.TLS, histo_queue uintptr, pair uintptr) { /* histogram_enc.c:763:13: */ + + *(*HistogramPair)(unsafe.Pointer(pair)) = *(*HistogramPair)(unsafe.Pointer((*HistoQueue)(unsafe.Pointer(histo_queue)).queue + uintptr(((*HistoQueue)(unsafe.Pointer(histo_queue)).size-1))*24)) + (*HistoQueue)(unsafe.Pointer(histo_queue)).size-- +} + +// Check whether a pair in the queue should be updated as head or not. +func HistoQueueUpdateHead(tls *libc.TLS, histo_queue uintptr, pair uintptr) { /* histogram_enc.c:773:13: */ + + if (*HistogramPair)(unsafe.Pointer(pair)).cost_diff < (*HistogramPair)(unsafe.Pointer((*HistoQueue)(unsafe.Pointer(histo_queue)).queue)).cost_diff { + // Replace the best pair. + var tmp = *(*HistogramPair)(unsafe.Pointer((*HistoQueue)(unsafe.Pointer(histo_queue)).queue)) + *(*HistogramPair)(unsafe.Pointer((*HistoQueue)(unsafe.Pointer(histo_queue)).queue)) = *(*HistogramPair)(unsafe.Pointer(pair)) + *(*HistogramPair)(unsafe.Pointer(pair)) = tmp + } +} + +// Update the cost diff and combo of a pair of histograms. This needs to be +// called when the the histograms have been merged with a third one. +func HistoQueueUpdatePair(tls *libc.TLS, h1 uintptr, h2 uintptr, threshold float64, pair uintptr) { /* histogram_enc.c:789:13: */ + var sum_cost float64 = ((*VP8LHistogram)(unsafe.Pointer(h1)).bit_cost_ + (*VP8LHistogram)(unsafe.Pointer(h2)).bit_cost_) + (*HistogramPair)(unsafe.Pointer(pair)).cost_combo = 0. + GetCombinedHistogramEntropy(tls, h1, h2, (sum_cost + threshold), (pair + 16 /* &.cost_combo */)) + (*HistogramPair)(unsafe.Pointer(pair)).cost_diff = ((*HistogramPair)(unsafe.Pointer(pair)).cost_combo - sum_cost) +} + +// Create a pair from indices "idx1" and "idx2" provided its cost +// is inferior to "threshold", a negative entropy. +// It returns the cost of the pair, or 0. if it superior to threshold. +func HistoQueuePush(tls *libc.TLS, histo_queue uintptr, histograms uintptr, idx1 int32, idx2 int32, threshold float64) float64 { /* histogram_enc.c:802:15: */ + bp := tls.Alloc(24) + defer tls.Free(24) + + var h1 uintptr + var h2 uintptr + // var pair HistogramPair at bp, 24 + + // Stop here if the queue is full. + if (*HistoQueue)(unsafe.Pointer(histo_queue)).size == (*HistoQueue)(unsafe.Pointer(histo_queue)).max_size { + return 0. + } + + if idx1 > idx2 { + var tmp int32 = idx2 + idx2 = idx1 + idx1 = tmp + } + (*HistogramPair)(unsafe.Pointer(bp /* &pair */)).idx1 = idx1 + (*HistogramPair)(unsafe.Pointer(bp /* &pair */)).idx2 = idx2 + h1 = *(*uintptr)(unsafe.Pointer(histograms + uintptr(idx1)*8)) + h2 = *(*uintptr)(unsafe.Pointer(histograms + uintptr(idx2)*8)) + + HistoQueueUpdatePair(tls, h1, h2, threshold, (bp) /* &pair */) + + // Do not even consider the pair if it does not improve the entropy. + if (*HistogramPair)(unsafe.Pointer(bp /* &pair */)).cost_diff >= threshold { + return 0. + } + + *(*HistogramPair)(unsafe.Pointer((*HistoQueue)(unsafe.Pointer(histo_queue)).queue + uintptr(libc.PostIncInt32(&(*HistoQueue)(unsafe.Pointer(histo_queue)).size, 1))*24)) = *(*HistogramPair)(unsafe.Pointer(bp /* pair */)) + HistoQueueUpdateHead(tls, histo_queue, ((*HistoQueue)(unsafe.Pointer(histo_queue)).queue + uintptr(((*HistoQueue)(unsafe.Pointer(histo_queue)).size-1))*24)) + + return (*HistogramPair)(unsafe.Pointer(bp /* &pair */)).cost_diff +} + +// ----------------------------------------------------------------------------- + +// Combines histograms by continuously choosing the one with the highest cost +// reduction. +func HistogramCombineGreedy(tls *libc.TLS, image_histo uintptr, num_used uintptr) int32 { /* histogram_enc.c:837:12: */ + bp := tls.Alloc(16) + defer tls.Free(16) + + var ok int32 + var image_histo_size int32 + var i int32 + var j int32 + var histograms uintptr + // Priority queue of histogram pairs. + // var histo_queue HistoQueue at bp, 16 + + var p uintptr + var idx1 int32 + var idx2 int32 + ok = 0 + image_histo_size = (*VP8LHistogramSet)(unsafe.Pointer(image_histo)).size + histograms = (*VP8LHistogramSet)(unsafe.Pointer(image_histo)).histograms + + // image_histo_size^2 for the queue size is safe. If you look at + // HistogramCombineGreedy, and imagine that UpdateQueueFront always pushes + // data to the queue, you insert at most: + // - image_histo_size*(image_histo_size-1)/2 (the first two for loops) + // - image_histo_size - 1 in the last for loop at the first iteration of + // the while loop, image_histo_size - 2 at the second iteration ... + // therefore image_histo_size*(image_histo_size-1)/2 overall too + if !(!(HistoQueueInit(tls, (bp) /* &histo_queue */, (image_histo_size*image_histo_size)) != 0)) { + goto __1 + } + goto End +__1: + ; + + i = 0 +__2: + if !(i < image_histo_size) { + goto __4 + } + if !(*(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(image_histo)).histograms + uintptr(i)*8)) == (uintptr(0))) { + goto __5 + } + goto __3 +__5: + ; + j = (i + 1) +__6: + if !(j < image_histo_size) { + goto __8 + } + // Initialize queue. + if !(*(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(image_histo)).histograms + uintptr(j)*8)) == (uintptr(0))) { + goto __9 + } + goto __7 +__9: + ; + HistoQueuePush(tls, (bp) /* &histo_queue */, histograms, i, j, 0.) + goto __7 +__7: + j++ + goto __6 + goto __8 +__8: + ; + goto __3 +__3: + i++ + goto __2 + goto __4 +__4: + ; + +__10: + if !((*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).size > 0) { + goto __11 + } + idx1 = (*HistogramPair)(unsafe.Pointer((*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).queue)).idx1 + idx2 = (*HistogramPair)(unsafe.Pointer((*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).queue)).idx2 + HistogramAdd(tls, *(*uintptr)(unsafe.Pointer(histograms + uintptr(idx2)*8)), *(*uintptr)(unsafe.Pointer(histograms + uintptr(idx1)*8)), *(*uintptr)(unsafe.Pointer(histograms + uintptr(idx1)*8))) + (*VP8LHistogram)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(histograms + uintptr(idx1)*8)))).bit_cost_ = (*HistogramPair)(unsafe.Pointer((*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).queue)).cost_combo + + // Remove merged histogram. + HistogramSetRemoveHistogram(tls, image_histo, idx2, num_used) + + // Remove pairs intersecting the just combined best pair. + i = 0 +__12: + if !(i < (*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).size) { + goto __14 + } + p = ((*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).queue + uintptr(i)*24) + if !(((((*HistogramPair)(unsafe.Pointer(p)).idx1 == idx1) || ((*HistogramPair)(unsafe.Pointer(p)).idx2 == idx1)) || ((*HistogramPair)(unsafe.Pointer(p)).idx1 == idx2)) || ((*HistogramPair)(unsafe.Pointer(p)).idx2 == idx2)) { + goto __15 + } + HistoQueuePopPair(tls, (bp) /* &histo_queue */, p) + goto __16 +__15: + HistoQueueUpdateHead(tls, (bp) /* &histo_queue */, p) + i++ +__16: + ; + goto __13 +__13: + ; + goto __12 + goto __14 +__14: + ; + + // Push new pairs formed with combined histogram to the queue. + i = 0 +__17: + if !(i < (*VP8LHistogramSet)(unsafe.Pointer(image_histo)).size) { + goto __19 + } + if !((i == idx1) || (*(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(image_histo)).histograms + uintptr(i)*8)) == (uintptr(0)))) { + goto __20 + } + goto __18 +__20: + ; + HistoQueuePush(tls, (bp) /* &histo_queue */, (*VP8LHistogramSet)(unsafe.Pointer(image_histo)).histograms, idx1, i, 0.) + goto __18 +__18: + i++ + goto __17 + goto __19 +__19: + ; + goto __10 +__11: + ; + + ok = 1 + +End: + HistoQueueClear(tls, (bp) /* &histo_queue */) + return ok +} + +// Perform histogram aggregation using a stochastic approach. +// 'do_greedy' is set to 1 if a greedy approach needs to be performed +// afterwards, 0 otherwise. +func PairComparison(tls *libc.TLS, idx1 uintptr, idx2 uintptr) int32 { /* histogram_enc.c:904:12: */ + // To be used with bsearch: <0 when *idx1<*idx2, >0 if >, 0 when ==. + return (*(*int32)(unsafe.Pointer(idx1)) - *(*int32)(unsafe.Pointer(idx2))) +} + +func HistogramCombineStochastic(tls *libc.TLS, image_histo uintptr, num_used uintptr, min_cluster_size int32, do_greedy uintptr) int32 { /* histogram_enc.c:908:12: */ + bp := tls.Alloc(24) + defer tls.Free(24) + + var j int32 + var iter int32 + // var seed uint32_t at bp+16, 4 + + var tries_with_no_success int32 + var outer_iters int32 + var num_tries_no_success int32 + var histograms uintptr + // Priority queue of histogram pairs. Its size of 'kHistoQueueSize' + // impacts the quality of the compression and the speed: the smaller the + // faster but the worse for the compression. + // var histo_queue HistoQueue at bp, 16 + + var kHistoQueueSize int32 + var ok int32 + // mapping from an index in image_histo with no NULL histogram to the full + // blown image_histo. + var mappings uintptr + var curr_cost float64 + // Choose two different histograms at random and try to combine them. + var tmp uint32_t + var idx1 uint32_t + var idx2 uint32_t + var tmp1 int32 + var p uintptr + var is_idx1_best int32 + var is_idx2_best int32 + var do_eval int32 + var mapping_index uintptr + var best_cost float64 + var best_idx1 int32 + // var best_idx2 int32 at bp+20, 4 + + var rand_range uint32_t + // (*num_used) / 2 was chosen empirically. Less means faster but worse + // compression. + var num_tries int32 + *(*uint32_t)(unsafe.Pointer(bp + 16 /* seed */)) = uint32_t(1) + tries_with_no_success = 0 + outer_iters = *(*int32)(unsafe.Pointer(num_used)) + num_tries_no_success = (outer_iters / 2) + histograms = (*VP8LHistogramSet)(unsafe.Pointer(image_histo)).histograms + kHistoQueueSize = 9 + ok = 0 + + if !(*(*int32)(unsafe.Pointer(num_used)) < min_cluster_size) { + goto __1 + } + *(*int32)(unsafe.Pointer(do_greedy)) = 1 + return 1 +__1: + ; + + mappings = WebPSafeMalloc(tls, uint64(*(*int32)(unsafe.Pointer(num_used))), uint64(unsafe.Sizeof(int32(0)))) + if !(mappings == (uintptr(0))) { + goto __2 + } + return 0 +__2: + ; + if !(!(HistoQueueInit(tls, (bp) /* &histo_queue */, kHistoQueueSize) != 0)) { + goto __3 + } + goto End +__3: + ; + // Fill the initial mapping. + j = 0 + iter = 0 +__4: + if !(iter < (*VP8LHistogramSet)(unsafe.Pointer(image_histo)).size) { + goto __6 + } + if !(*(*uintptr)(unsafe.Pointer(histograms + uintptr(iter)*8)) == (uintptr(0))) { + goto __7 + } + goto __5 +__7: + ; + *(*int32)(unsafe.Pointer(mappings + uintptr(libc.PostIncInt32(&j, 1))*4)) = iter + goto __5 +__5: + iter++ + goto __4 + goto __6 +__6: + ; + + // Collapse similar histograms in 'image_histo'. + iter = 0 +__8: + if !(((iter < outer_iters) && (*(*int32)(unsafe.Pointer(num_used)) >= min_cluster_size)) && (libc.PreIncInt32(&tries_with_no_success, 1) < num_tries_no_success)) { + goto __10 + } + if (*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).size == 0 { + best_cost = 0. + } else { + best_cost = (*HistogramPair)(unsafe.Pointer((*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).queue)).cost_diff + } + best_idx1 = -1 + *(*int32)(unsafe.Pointer(bp + 20 /* best_idx2 */)) = 1 + rand_range = (uint32_t((*(*int32)(unsafe.Pointer(num_used)) - 1) * (*(*int32)(unsafe.Pointer(num_used))))) + // (*num_used) / 2 was chosen empirically. Less means faster but worse + // compression. + num_tries = ((*(*int32)(unsafe.Pointer(num_used))) / 2) + + // Pick random samples. + j = 0 +__11: + if !((*(*int32)(unsafe.Pointer(num_used)) >= 2) && (j < num_tries)) { + goto __13 + } + // Choose two different histograms at random and try to combine them. + tmp = (MyRand(tls, (bp+16) /* &seed */) % rand_range) + idx1 = (tmp / (uint32_t(*(*int32)(unsafe.Pointer(num_used)) - 1))) + idx2 = (tmp % (uint32_t(*(*int32)(unsafe.Pointer(num_used)) - 1))) + if !(idx2 >= idx1) { + goto __14 + } + idx2++ +__14: + ; + idx1 = uint32_t(*(*int32)(unsafe.Pointer(mappings + uintptr(idx1)*4))) + idx2 = uint32_t(*(*int32)(unsafe.Pointer(mappings + uintptr(idx2)*4))) + + // Calculate cost reduction on combination. + curr_cost = HistoQueuePush(tls, (bp) /* &histo_queue */, histograms, int32(idx1), int32(idx2), best_cost) + if !(curr_cost < float64(0)) { + goto __15 + } // found a better pair? + best_cost = curr_cost + // Empty the queue if we reached full capacity. + if !((*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).size == (*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).max_size) { + goto __16 + } + goto __13 +__16: + ; +__15: + ; + goto __12 +__12: + j++ + goto __11 + goto __13 +__13: + ; + if !((*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).size == 0) { + goto __17 + } + goto __9 +__17: + ; + + // Get the best histograms. + best_idx1 = (*HistogramPair)(unsafe.Pointer((*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).queue)).idx1 + *(*int32)(unsafe.Pointer(bp + 20 /* best_idx2 */)) = (*HistogramPair)(unsafe.Pointer((*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).queue)).idx2 + + // Pop best_idx2 from mappings. + mapping_index = bsearch( + tls, + (bp + 20), /* &best_idx2 */ + mappings, + uint64(*(*int32)(unsafe.Pointer(num_used))), + uint64(unsafe.Sizeof(int32(0))), + // Function pointers are generated by taking a pointer to + // a struct who's first field is that function. + *(*uintptr)(unsafe.Pointer( + &struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{ + PairComparison, + }, + ))) + + libc.Xmemmove(tls, mapping_index, (mapping_index + uintptr(1)*4), (uint64(unsafe.Sizeof(int32(0))) * (uint64(((int64(*(*int32)(unsafe.Pointer(num_used)))) - ((int64(mapping_index) - int64(mappings)) / 4)) - int64(1))))) + // Merge the histograms and remove best_idx2 from the queue. + HistogramAdd(tls, *(*uintptr)(unsafe.Pointer(histograms + uintptr(*(*int32)(unsafe.Pointer(bp + 20 /* best_idx2 */)))*8)), *(*uintptr)(unsafe.Pointer(histograms + uintptr(best_idx1)*8)), + *(*uintptr)(unsafe.Pointer(histograms + uintptr(best_idx1)*8))) + (*VP8LHistogram)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(histograms + uintptr(best_idx1)*8)))).bit_cost_ = (*HistogramPair)(unsafe.Pointer((*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).queue)).cost_combo + HistogramSetRemoveHistogram(tls, image_histo, *(*int32)(unsafe.Pointer(bp + 20 /* best_idx2 */)), num_used) + // Parse the queue and update each pair that deals with best_idx1, + // best_idx2 or image_histo_size. + j = 0 +__18: + if !(j < (*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).size) { + goto __20 + } + p = ((*HistoQueue)(unsafe.Pointer(bp /* &histo_queue */)).queue + uintptr(j)*24) + is_idx1_best = (libc.Bool32(((*HistogramPair)(unsafe.Pointer(p)).idx1 == best_idx1) || ((*HistogramPair)(unsafe.Pointer(p)).idx1 == *(*int32)(unsafe.Pointer(bp + 20 /* best_idx2 */))))) + is_idx2_best = (libc.Bool32(((*HistogramPair)(unsafe.Pointer(p)).idx2 == best_idx1) || ((*HistogramPair)(unsafe.Pointer(p)).idx2 == *(*int32)(unsafe.Pointer(bp + 20 /* best_idx2 */))))) + do_eval = 0 + // The front pair could have been duplicated by a random pick so + // check for it all the time nevertheless. + if !((is_idx1_best != 0) && (is_idx2_best != 0)) { + goto __21 + } + HistoQueuePopPair(tls, (bp) /* &histo_queue */, p) + goto __19 +__21: + ; + // Any pair containing one of the two best indices should only refer to + // best_idx1. Its cost should also be updated. + if !(is_idx1_best != 0) { + goto __22 + } + (*HistogramPair)(unsafe.Pointer(p)).idx1 = best_idx1 + do_eval = 1 + goto __23 +__22: + if !(is_idx2_best != 0) { + goto __24 + } + (*HistogramPair)(unsafe.Pointer(p)).idx2 = best_idx1 + do_eval = 1 +__24: + ; +__23: + ; + // Make sure the index order is respected. + if !((*HistogramPair)(unsafe.Pointer(p)).idx1 > (*HistogramPair)(unsafe.Pointer(p)).idx2) { + goto __25 + } + tmp1 = (*HistogramPair)(unsafe.Pointer(p)).idx2 + (*HistogramPair)(unsafe.Pointer(p)).idx2 = (*HistogramPair)(unsafe.Pointer(p)).idx1 + (*HistogramPair)(unsafe.Pointer(p)).idx1 = tmp1 +__25: + ; + if !(do_eval != 0) { + goto __26 + } + // Re-evaluate the cost of an updated pair. + HistoQueueUpdatePair(tls, *(*uintptr)(unsafe.Pointer(histograms + uintptr((*HistogramPair)(unsafe.Pointer(p)).idx1)*8)), *(*uintptr)(unsafe.Pointer(histograms + uintptr((*HistogramPair)(unsafe.Pointer(p)).idx2)*8)), 0., p) + if !((*HistogramPair)(unsafe.Pointer(p)).cost_diff >= 0.) { + goto __27 + } + HistoQueuePopPair(tls, (bp) /* &histo_queue */, p) + goto __19 +__27: + ; +__26: + ; + HistoQueueUpdateHead(tls, (bp) /* &histo_queue */, p) + j++ + goto __19 +__19: + ; + goto __18 + goto __20 +__20: + ; + tries_with_no_success = 0 + goto __9 +__9: + iter++ + goto __8 + goto __10 +__10: + ; + *(*int32)(unsafe.Pointer(do_greedy)) = (libc.Bool32(*(*int32)(unsafe.Pointer(num_used)) <= min_cluster_size)) + ok = 1 + +End: + HistoQueueClear(tls, (bp) /* &histo_queue */) + WebPSafeFree(tls, mappings) + return ok +} + +// ----------------------------------------------------------------------------- +// Histogram refinement + +// Find the best 'out' histogram for each of the 'in' histograms. +// At call-time, 'out' contains the histograms of the clusters. +// Note: we assume that out[]->bit_cost_ is already up-to-date. +func HistogramRemap(tls *libc.TLS, in uintptr, out uintptr, symbols uintptr) { /* histogram_enc.c:1049:13: */ + var i int32 + var in_histo uintptr = (*VP8LHistogramSet)(unsafe.Pointer(in)).histograms + var out_histo uintptr = (*VP8LHistogramSet)(unsafe.Pointer(out)).histograms + var in_size int32 = (*VP8LHistogramSet)(unsafe.Pointer(out)).max_size + var out_size int32 = (*VP8LHistogramSet)(unsafe.Pointer(out)).size + if out_size > 1 { + for i = 0; i < in_size; i++ { + var best_out int32 = 0 + var best_bits float64 = 1.e38 + var k int32 + if *(*uintptr)(unsafe.Pointer(in_histo + uintptr(i)*8)) == (uintptr(0)) { + // Arbitrarily set to the previous value if unused to help future LZ77. + *(*uint16_t)(unsafe.Pointer(symbols + uintptr(i)*2)) = *(*uint16_t)(unsafe.Pointer(symbols + uintptr((i-1))*2)) + continue + } + for k = 0; k < out_size; k++ { + var cur_bits float64 + cur_bits = HistogramAddThresh(tls, *(*uintptr)(unsafe.Pointer(out_histo + uintptr(k)*8)), *(*uintptr)(unsafe.Pointer(in_histo + uintptr(i)*8)), best_bits) + if (k == 0) || (cur_bits < best_bits) { + best_bits = cur_bits + best_out = k + } + } + *(*uint16_t)(unsafe.Pointer(symbols + uintptr(i)*2)) = uint16_t(best_out) + } + } else { + + for i = 0; i < in_size; i++ { + *(*uint16_t)(unsafe.Pointer(symbols + uintptr(i)*2)) = uint16_t(0) + } + } + + // Recompute each out based on raw and symbols. + VP8LHistogramSetClear(tls, out) + (*VP8LHistogramSet)(unsafe.Pointer(out)).size = out_size + + for i = 0; i < in_size; i++ { + var idx int32 + if *(*uintptr)(unsafe.Pointer(in_histo + uintptr(i)*8)) == (uintptr(0)) { + continue + } + idx = int32(*(*uint16_t)(unsafe.Pointer(symbols + uintptr(i)*2))) + HistogramAdd(tls, *(*uintptr)(unsafe.Pointer(in_histo + uintptr(i)*8)), *(*uintptr)(unsafe.Pointer(out_histo + uintptr(idx)*8)), *(*uintptr)(unsafe.Pointer(out_histo + uintptr(idx)*8))) + } +} + +func GetCombineCostFactor(tls *libc.TLS, histo_size int32, quality int32) float64 { /* histogram_enc.c:1096:15: */ + var combine_cost_factor float64 = 0.16 + if quality < 90 { + if histo_size > 256 { + combine_cost_factor = combine_cost_factor / (2.) + } + if histo_size > 512 { + combine_cost_factor = combine_cost_factor / (2.) + } + if histo_size > 1024 { + combine_cost_factor = combine_cost_factor / (2.) + } + if quality <= 50 { + combine_cost_factor = combine_cost_factor / (2.) + } + } + return combine_cost_factor +} + +// Given a HistogramSet 'set', the mapping of clusters 'cluster_mapping' and the +// current assignment of the cells in 'symbols', merge the clusters and +// assign the smallest possible clusters values. +func OptimizeHistogramSymbols(tls *libc.TLS, set uintptr, cluster_mappings uintptr, num_clusters int32, cluster_mappings_tmp uintptr, symbols uintptr) { /* histogram_enc.c:1110:13: */ + var i int32 + var cluster_max int32 + var do_continue int32 = 1 + // First, assign the lowest cluster to each pixel. + for do_continue != 0 { + do_continue = 0 + for i = 0; i < num_clusters; i++ { + var k int32 + k = int32(*(*uint16_t)(unsafe.Pointer(cluster_mappings + uintptr(i)*2))) + for k != int32(*(*uint16_t)(unsafe.Pointer(cluster_mappings + uintptr(k)*2))) { + *(*uint16_t)(unsafe.Pointer(cluster_mappings + uintptr(k)*2)) = *(*uint16_t)(unsafe.Pointer(cluster_mappings + uintptr(*(*uint16_t)(unsafe.Pointer(cluster_mappings + uintptr(k)*2)))*2)) + k = int32(*(*uint16_t)(unsafe.Pointer(cluster_mappings + uintptr(k)*2))) + } + if k != int32(*(*uint16_t)(unsafe.Pointer(cluster_mappings + uintptr(i)*2))) { + do_continue = 1 + *(*uint16_t)(unsafe.Pointer(cluster_mappings + uintptr(i)*2)) = uint16_t(k) + } + } + } + // Create a mapping from a cluster id to its minimal version. + cluster_max = 0 + libc.Xmemset(tls, cluster_mappings_tmp, 0, + (uint64((*VP8LHistogramSet)(unsafe.Pointer(set)).max_size) * uint64(unsafe.Sizeof(uint16_t(0))))) + + // Re-map the ids. + for i = 0; i < (*VP8LHistogramSet)(unsafe.Pointer(set)).max_size; i++ { + var cluster int32 + if int32(*(*uint16_t)(unsafe.Pointer(symbols + uintptr(i)*2))) == int32(kInvalidHistogramSymbol) { + continue + } + cluster = int32(*(*uint16_t)(unsafe.Pointer(cluster_mappings + uintptr(*(*uint16_t)(unsafe.Pointer(symbols + uintptr(i)*2)))*2))) + + if (cluster > 0) && (int32(*(*uint16_t)(unsafe.Pointer(cluster_mappings_tmp + uintptr(cluster)*2))) == 0) { + cluster_max++ + *(*uint16_t)(unsafe.Pointer(cluster_mappings_tmp + uintptr(cluster)*2)) = uint16_t(cluster_max) + } + *(*uint16_t)(unsafe.Pointer(symbols + uintptr(i)*2)) = *(*uint16_t)(unsafe.Pointer(cluster_mappings_tmp + uintptr(cluster)*2)) + } + + // Make sure all cluster values are used. + cluster_max = 0 + for i = 0; i < (*VP8LHistogramSet)(unsafe.Pointer(set)).max_size; i++ { + if int32(*(*uint16_t)(unsafe.Pointer(symbols + uintptr(i)*2))) == int32(kInvalidHistogramSymbol) { + continue + } + if int32(*(*uint16_t)(unsafe.Pointer(symbols + uintptr(i)*2))) <= cluster_max { + continue + } + cluster_max++ + + } +} + +func RemoveEmptyHistograms(tls *libc.TLS, image_histo uintptr) { /* histogram_enc.c:1161:13: */ + var size uint32_t + var i int32 + i = 0 + size = uint32_t(0) + for ; i < (*VP8LHistogramSet)(unsafe.Pointer(image_histo)).size; i++ { + if *(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(image_histo)).histograms + uintptr(i)*8)) == (uintptr(0)) { + continue + } + *(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(image_histo)).histograms + uintptr(libc.PostIncUint32(&size, 1))*8)) = *(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(image_histo)).histograms + uintptr(i)*8)) + } + (*VP8LHistogramSet)(unsafe.Pointer(image_histo)).size = int32(size) +} + +func VP8LGetHistoImageSymbols(tls *libc.TLS, xsize int32, ysize int32, refs uintptr, quality int32, low_effort int32, histogram_bits int32, cache_bits int32, image_histo uintptr, tmp_histo uintptr, histogram_symbols uintptr) int32 { /* histogram_enc.c:1171:5: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var ok int32 + var histo_xsize int32 + var histo_ysize int32 + var image_histo_raw_size int32 + var orig_histo uintptr + // Don't attempt linear bin-partition heuristic for + // histograms of small sizes (as bin_map will be very sparse) and + // maximum quality q==100 (to preserve the compression gains at that level). + var entropy_combine_num_bins int32 + var entropy_combine int32 + var map_tmp uintptr + var cluster_mappings uintptr + // var num_used int32 at bp, 4 + + var bin_map uintptr + var combine_cost_factor float64 + var num_clusters uint32_t + var x float32 + // cubic ramp between 1 and MAX_HISTO_GREEDY: + var threshold_size int32 + // var do_greedy int32 at bp+4, 4 + ok = 0 + if histogram_bits != 0 { + histo_xsize = int32(VP8LSubSampleSize(tls, uint32(xsize), uint32(histogram_bits))) + } else { + histo_xsize = 1 + } + if histogram_bits != 0 { + histo_ysize = int32(VP8LSubSampleSize(tls, uint32(ysize), uint32(histogram_bits))) + } else { + histo_ysize = 1 + } + image_histo_raw_size = (histo_xsize * histo_ysize) + orig_histo = + VP8LAllocateHistogramSet(tls, image_histo_raw_size, cache_bits) + if low_effort != 0 { + entropy_combine_num_bins = 4 + } else { + entropy_combine_num_bins = ((4 * 4) * 4) + } + map_tmp = + WebPSafeMalloc(tls, (uint64(2 * image_histo_raw_size)), uint64(unsafe.Sizeof(map_tmp))) + cluster_mappings = (map_tmp + uintptr(image_histo_raw_size)*2) + *(*int32)(unsafe.Pointer(bp /* num_used */)) = image_histo_raw_size + if !((orig_histo == (uintptr(0))) || (map_tmp == (uintptr(0)))) { + goto __1 + } + goto Error +__1: + ; + + // Construct the histograms from backward references. + HistogramBuild(tls, xsize, histogram_bits, refs, orig_histo) + // Copies the histograms and computes its bit_cost. + // histogram_symbols is optimized + HistogramCopyAndAnalyze(tls, orig_histo, image_histo, (bp), /* &num_used */ + histogram_symbols) + + entropy_combine = (libc.Bool32((*(*int32)(unsafe.Pointer(bp /* num_used */)) > (entropy_combine_num_bins * 2)) && (quality < 100))) + + if !(entropy_combine != 0) { + goto __2 + } + bin_map = map_tmp + combine_cost_factor = + GetCombineCostFactor(tls, image_histo_raw_size, quality) + num_clusters = uint32_t(*(*int32)(unsafe.Pointer(bp /* num_used */))) + + HistogramAnalyzeEntropyBin(tls, image_histo, bin_map, low_effort) + // Collapse histograms with similar entropy. + HistogramCombineEntropyBin(tls, image_histo, (bp) /* &num_used */, histogram_symbols, + cluster_mappings, tmp_histo, bin_map, + entropy_combine_num_bins, combine_cost_factor, + low_effort) + OptimizeHistogramSymbols(tls, image_histo, cluster_mappings, int32(num_clusters), + map_tmp, histogram_symbols) +__2: + ; + + // Don't combine the histograms using stochastic and greedy heuristics for + // low-effort compression mode. + if !(!(low_effort != 0) || !(entropy_combine != 0)) { + goto __3 + } + x = (float32(quality) / 100.) + // cubic ramp between 1 and MAX_HISTO_GREEDY: + threshold_size = (libc.Int32FromFloat32(float32(1) + (((x * x) * x) * (float32(100 - 1))))) + if !(!(HistogramCombineStochastic(tls, image_histo, (bp) /* &num_used */, threshold_size, + (bp+4) /* &do_greedy */) != 0)) { + goto __4 + } + goto Error +__4: + ; + if !(*(*int32)(unsafe.Pointer(bp + 4 /* do_greedy */)) != 0) { + goto __5 + } + RemoveEmptyHistograms(tls, image_histo) + if !(!(HistogramCombineGreedy(tls, image_histo, (bp) /* &num_used */) != 0)) { + goto __6 + } + goto Error +__6: + ; +__5: + ; +__3: + ; + + // Find the optimal map from original histograms to the final ones. + RemoveEmptyHistograms(tls, image_histo) + HistogramRemap(tls, orig_histo, image_histo, histogram_symbols) + + ok = 1 + +Error: + VP8LFreeHistogramSet(tls, orig_histo) + WebPSafeFree(tls, map_tmp) + return ok +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// VP8Iterator +//------------------------------------------------------------------------------ + +func InitLeft(tls *libc.TLS, it uintptr) { /* iterator_enc.c:22:13: */ + *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).y_left_ + libc.UintptrFromInt32(-1))) = libc.AssignPtrUint8(((*VP8EncIterator)(unsafe.Pointer(it)).u_left_ + libc.UintptrFromInt32(-1)), libc.AssignPtrUint8(((*VP8EncIterator)(unsafe.Pointer(it)).v_left_+libc.UintptrFromInt32(-1)), func() uint8 { + if (*VP8EncIterator)(unsafe.Pointer(it)).y_ > 0 { + return uint8(129) + } + return uint8(127) + }())) + libc.Xmemset(tls, (*VP8EncIterator)(unsafe.Pointer(it)).y_left_, 129, uint64(16)) + libc.Xmemset(tls, (*VP8EncIterator)(unsafe.Pointer(it)).u_left_, 129, uint64(8)) + libc.Xmemset(tls, (*VP8EncIterator)(unsafe.Pointer(it)).v_left_, 129, uint64(8)) + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + 8*4)) = 0 + if (*VP8EncIterator)(unsafe.Pointer(it)).top_derr_ != (uintptr(0)) { + libc.Xmemset(tls, (it + 344 /* &.left_derr_ */), 0, uint64(unsafe.Sizeof(DError{}))) + } +} + +func InitTop(tls *libc.TLS, it uintptr) { /* iterator_enc.c:34:13: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var top_size size_t = (size_t((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ * 16)) + libc.Xmemset(tls, (*VP8Encoder)(unsafe.Pointer(enc)).y_top_, 127, (uint64(2) * top_size)) + libc.Xmemset(tls, (*VP8Encoder)(unsafe.Pointer(enc)).nz_, 0, (uint64((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_) * uint64(unsafe.Sizeof(uint32_t(0))))) + if (*VP8Encoder)(unsafe.Pointer(enc)).top_derr_ != (uintptr(0)) { + libc.Xmemset(tls, (*VP8Encoder)(unsafe.Pointer(enc)).top_derr_, 0, (uint64((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_) * uint64(unsafe.Sizeof(DError{})))) + } +} + +func VP8IteratorSetRow(tls *libc.TLS, it uintptr, y int32) { /* iterator_enc.c:44:6: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + (*VP8EncIterator)(unsafe.Pointer(it)).x_ = 0 + (*VP8EncIterator)(unsafe.Pointer(it)).y_ = y + (*VP8EncIterator)(unsafe.Pointer(it)).bw_ = ((enc + 112 /* &.parts_ */) + uintptr((y&((*VP8Encoder)(unsafe.Pointer(enc)).num_parts_-1)))*48) + (*VP8EncIterator)(unsafe.Pointer(it)).preds_ = ((*VP8Encoder)(unsafe.Pointer(enc)).preds_ + uintptr(((y * 4) * (*VP8Encoder)(unsafe.Pointer(enc)).preds_w_))) + (*VP8EncIterator)(unsafe.Pointer(it)).nz_ = (*VP8Encoder)(unsafe.Pointer(enc)).nz_ + (*VP8EncIterator)(unsafe.Pointer(it)).mb_ = ((*VP8Encoder)(unsafe.Pointer(enc)).mb_info_ + uintptr((y*(*VP8Encoder)(unsafe.Pointer(enc)).mb_w_))*4) + (*VP8EncIterator)(unsafe.Pointer(it)).y_top_ = (*VP8Encoder)(unsafe.Pointer(enc)).y_top_ + (*VP8EncIterator)(unsafe.Pointer(it)).uv_top_ = (*VP8Encoder)(unsafe.Pointer(enc)).uv_top_ + InitLeft(tls, it) +} + +func VP8IteratorReset(tls *libc.TLS, it uintptr) { /* iterator_enc.c:57:6: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + VP8IteratorSetRow(tls, it, 0) + VP8IteratorSetCountDown(tls, it, ((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ * (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_)) // default + InitTop(tls, it) + libc.Xmemset(tls, (it + 208 /* &.bit_count_ */), 0, uint64(unsafe.Sizeof([4][3]uint64_t{}))) + (*VP8EncIterator)(unsafe.Pointer(it)).do_trellis_ = 0 +} + +func VP8IteratorSetCountDown(tls *libc.TLS, it uintptr, count_down int32) { /* iterator_enc.c:66:6: */ + (*VP8EncIterator)(unsafe.Pointer(it)).count_down_ = libc.AssignPtrInt32((it + 336 /* &.count_down0_ */), count_down) +} + +func VP8IteratorIsDone(tls *libc.TLS, it uintptr) int32 { /* iterator_enc.c:70:5: */ + return (libc.Bool32((*VP8EncIterator)(unsafe.Pointer(it)).count_down_ <= 0)) +} + +func VP8IteratorInit(tls *libc.TLS, enc uintptr, it uintptr) { /* iterator_enc.c:74:6: */ + (*VP8EncIterator)(unsafe.Pointer(it)).enc_ = enc + (*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ = (uintptr(((uint64(it + 488 /* &.yuv_mem_ */)) + uint64(31)) & libc.Uint64FromInt32(libc.CplInt32(31)))) + (*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_ = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((32 * 16))) + (*VP8EncIterator)(unsafe.Pointer(it)).yuv_out2_ = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_ + uintptr((32 * 16))) + (*VP8EncIterator)(unsafe.Pointer(it)).yuv_p_ = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out2_ + uintptr((32 * 16))) + (*VP8EncIterator)(unsafe.Pointer(it)).lf_stats_ = (*VP8Encoder)(unsafe.Pointer(enc)).lf_stats_ + (*VP8EncIterator)(unsafe.Pointer(it)).percent0_ = (*VP8Encoder)(unsafe.Pointer(enc)).percent_ + (*VP8EncIterator)(unsafe.Pointer(it)).y_left_ = (uintptr((uintptr_t(((it + 400 /* &.yuv_left_mem_ */) + uintptr(1))) + uint64(31)) & libc.Uint64FromInt32(libc.CplInt32(31)))) + (*VP8EncIterator)(unsafe.Pointer(it)).u_left_ = (((*VP8EncIterator)(unsafe.Pointer(it)).y_left_ + uintptr(16)) + uintptr(16)) + (*VP8EncIterator)(unsafe.Pointer(it)).v_left_ = ((*VP8EncIterator)(unsafe.Pointer(it)).u_left_ + uintptr(16)) + (*VP8EncIterator)(unsafe.Pointer(it)).top_derr_ = (*VP8Encoder)(unsafe.Pointer(enc)).top_derr_ + VP8IteratorReset(tls, it) +} + +func VP8IteratorProgress(tls *libc.TLS, it uintptr, delta int32) int32 { /* iterator_enc.c:89:5: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + if (delta != 0) && ((*WebPPicture)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).pic_)).progress_hook != (uintptr(0))) { + var done int32 = ((*VP8EncIterator)(unsafe.Pointer(it)).count_down0_ - (*VP8EncIterator)(unsafe.Pointer(it)).count_down_) + var percent int32 + if (*VP8EncIterator)(unsafe.Pointer(it)).count_down0_ <= 0 { + percent = (*VP8EncIterator)(unsafe.Pointer(it)).percent0_ + } else { + percent = ((*VP8EncIterator)(unsafe.Pointer(it)).percent0_ + ((delta * done) / (*VP8EncIterator)(unsafe.Pointer(it)).count_down0_)) + } + return WebPReportProgress(tls, (*VP8Encoder)(unsafe.Pointer(enc)).pic_, percent, (enc + 536 /* &.percent_ */)) + } + return 1 +} + +//------------------------------------------------------------------------------ +// Import the source samples into the cache. Takes care of replicating +// boundary pixels if necessary. + +func MinSize(tls *libc.TLS, a int32, b int32) int32 { /* iterator_enc.c:105:24: */ + if a < b { + return a + } + return b +} + +func ImportBlock(tls *libc.TLS, src uintptr, src_stride int32, dst uintptr, w int32, h int32, size int32) { /* iterator_enc.c:107:13: */ + var i int32 + for i = 0; i < h; i++ { + libc.Xmemcpy(tls, dst, src, uint64(w)) + if w < size { + libc.Xmemset(tls, (dst + uintptr(w)), int32(*(*uint8_t)(unsafe.Pointer(dst + uintptr((w - 1))))), (uint64(size - w))) + } + dst += uintptr(32) + src += uintptr(src_stride) + } + for i = h; i < size; i++ { + libc.Xmemcpy(tls, dst, (dst - uintptr(32)), uint64(size)) + dst += uintptr(32) + } +} + +func ImportLine(tls *libc.TLS, src uintptr, src_stride int32, dst uintptr, len int32, total_len int32) { /* iterator_enc.c:124:13: */ + var i int32 + i = 0 +__1: + if !(i < len) { + goto __3 + } + *(*uint8_t)(unsafe.Pointer(dst + uintptr(i))) = *(*uint8_t)(unsafe.Pointer(src)) + goto __2 +__2: + i++ + src += uintptr(src_stride) + goto __1 + goto __3 +__3: + ; + for ; i < total_len; i++ { + *(*uint8_t)(unsafe.Pointer(dst + uintptr(i))) = *(*uint8_t)(unsafe.Pointer(dst + uintptr((len - 1)))) + } +} + +func VP8IteratorImport(tls *libc.TLS, it uintptr, tmp_32 uintptr) { /* iterator_enc.c:131:6: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var x int32 = (*VP8EncIterator)(unsafe.Pointer(it)).x_ + var y int32 = (*VP8EncIterator)(unsafe.Pointer(it)).y_ + var pic uintptr = (*VP8Encoder)(unsafe.Pointer(enc)).pic_ + var ysrc uintptr = ((*WebPPicture)(unsafe.Pointer(pic)).y + uintptr((((y * (*WebPPicture)(unsafe.Pointer(pic)).y_stride) + x) * 16))) + var usrc uintptr = ((*WebPPicture)(unsafe.Pointer(pic)).u + uintptr((((y * (*WebPPicture)(unsafe.Pointer(pic)).uv_stride) + x) * 8))) + var vsrc uintptr = ((*WebPPicture)(unsafe.Pointer(pic)).v + uintptr((((y * (*WebPPicture)(unsafe.Pointer(pic)).uv_stride) + x) * 8))) + var w int32 = MinSize(tls, ((*WebPPicture)(unsafe.Pointer(pic)).width - (x * 16)), 16) + var h int32 = MinSize(tls, ((*WebPPicture)(unsafe.Pointer(pic)).height - (y * 16)), 16) + var uv_w int32 = ((w + 1) >> 1) + var uv_h int32 = ((h + 1) >> 1) + + ImportBlock(tls, ysrc, (*WebPPicture)(unsafe.Pointer(pic)).y_stride, ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((0))), w, h, 16) + ImportBlock(tls, usrc, (*WebPPicture)(unsafe.Pointer(pic)).uv_stride, ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((16))), uv_w, uv_h, 8) + ImportBlock(tls, vsrc, (*WebPPicture)(unsafe.Pointer(pic)).uv_stride, ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((16 + 8))), uv_w, uv_h, 8) + + if tmp_32 == (uintptr(0)) { + return + } + + // Import source (uncompressed) samples into boundary. + if x == 0 { + InitLeft(tls, it) + } else { + if y == 0 { + *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).y_left_ + libc.UintptrFromInt32(-1))) = libc.AssignPtrUint8(((*VP8EncIterator)(unsafe.Pointer(it)).u_left_ + libc.UintptrFromInt32(-1)), libc.AssignPtrUint8(((*VP8EncIterator)(unsafe.Pointer(it)).v_left_+libc.UintptrFromInt32(-1)), uint8_t(127))) + } else { + *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).y_left_ + libc.UintptrFromInt32(-1))) = *(*uint8_t)(unsafe.Pointer(ysrc + uintptr((-1 - (*WebPPicture)(unsafe.Pointer(pic)).y_stride)))) + *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).u_left_ + libc.UintptrFromInt32(-1))) = *(*uint8_t)(unsafe.Pointer(usrc + uintptr((-1 - (*WebPPicture)(unsafe.Pointer(pic)).uv_stride)))) + *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).v_left_ + libc.UintptrFromInt32(-1))) = *(*uint8_t)(unsafe.Pointer(vsrc + uintptr((-1 - (*WebPPicture)(unsafe.Pointer(pic)).uv_stride)))) + } + ImportLine(tls, (ysrc - uintptr(1)), (*WebPPicture)(unsafe.Pointer(pic)).y_stride, (*VP8EncIterator)(unsafe.Pointer(it)).y_left_, h, 16) + ImportLine(tls, (usrc - uintptr(1)), (*WebPPicture)(unsafe.Pointer(pic)).uv_stride, (*VP8EncIterator)(unsafe.Pointer(it)).u_left_, uv_h, 8) + ImportLine(tls, (vsrc - uintptr(1)), (*WebPPicture)(unsafe.Pointer(pic)).uv_stride, (*VP8EncIterator)(unsafe.Pointer(it)).v_left_, uv_h, 8) + } + + (*VP8EncIterator)(unsafe.Pointer(it)).y_top_ = (tmp_32 + uintptr(0)) + (*VP8EncIterator)(unsafe.Pointer(it)).uv_top_ = (tmp_32 + uintptr(16)) + if y == 0 { + libc.Xmemset(tls, tmp_32, 127, (uint64(32) * uint64(unsafe.Sizeof(uint8_t(0))))) + } else { + ImportLine(tls, (ysrc - uintptr((*WebPPicture)(unsafe.Pointer(pic)).y_stride)), 1, tmp_32, w, 16) + ImportLine(tls, (usrc - uintptr((*WebPPicture)(unsafe.Pointer(pic)).uv_stride)), 1, (tmp_32 + uintptr(16)), uv_w, 8) + ImportLine(tls, (vsrc - uintptr((*WebPPicture)(unsafe.Pointer(pic)).uv_stride)), 1, ((tmp_32 + uintptr(16)) + uintptr(8)), uv_w, 8) + } +} + +//------------------------------------------------------------------------------ +// Copy back the compressed samples into user space if requested. + +func ExportBlock(tls *libc.TLS, src uintptr, dst uintptr, dst_stride int32, w int32, h int32) { /* iterator_enc.c:179:13: */ + for libc.PostDecInt32(&h, 1) > 0 { + libc.Xmemcpy(tls, dst, src, uint64(w)) + dst += uintptr(dst_stride) + src += uintptr(32) + } +} + +func VP8IteratorExport(tls *libc.TLS, it uintptr) { /* iterator_enc.c:188:6: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + if (*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).show_compressed != 0 { + var x int32 = (*VP8EncIterator)(unsafe.Pointer(it)).x_ + var y int32 = (*VP8EncIterator)(unsafe.Pointer(it)).y_ + var ysrc uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_ + uintptr((0))) + var usrc uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_ + uintptr((16))) + var vsrc uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_ + uintptr((16 + 8))) + var pic uintptr = (*VP8Encoder)(unsafe.Pointer(enc)).pic_ + var ydst uintptr = ((*WebPPicture)(unsafe.Pointer(pic)).y + uintptr((((y * (*WebPPicture)(unsafe.Pointer(pic)).y_stride) + x) * 16))) + var udst uintptr = ((*WebPPicture)(unsafe.Pointer(pic)).u + uintptr((((y * (*WebPPicture)(unsafe.Pointer(pic)).uv_stride) + x) * 8))) + var vdst uintptr = ((*WebPPicture)(unsafe.Pointer(pic)).v + uintptr((((y * (*WebPPicture)(unsafe.Pointer(pic)).uv_stride) + x) * 8))) + var w int32 = ((*WebPPicture)(unsafe.Pointer(pic)).width - (x * 16)) + var h int32 = ((*WebPPicture)(unsafe.Pointer(pic)).height - (y * 16)) + + if w > 16 { + w = 16 + } + if h > 16 { + h = 16 + } + + // Luma plane + ExportBlock(tls, ysrc, ydst, (*WebPPicture)(unsafe.Pointer(pic)).y_stride, w, h) + + { // U/V planes + var uv_w int32 = ((w + 1) >> 1) + var uv_h int32 = ((h + 1) >> 1) + ExportBlock(tls, usrc, udst, (*WebPPicture)(unsafe.Pointer(pic)).uv_stride, uv_w, uv_h) + ExportBlock(tls, vsrc, vdst, (*WebPPicture)(unsafe.Pointer(pic)).uv_stride, uv_w, uv_h) + + } + } +} + +//------------------------------------------------------------------------------ +// Non-zero contexts setup/teardown + +// Nz bits: +// 0 1 2 3 Y +// 4 5 6 7 +// 8 9 10 11 +// 12 13 14 15 +// 16 17 U +// 18 19 +// 20 21 V +// 22 23 +// 24 DC-intra16 + +// Convert packed context to byte array + +func VP8IteratorNzToBytes(tls *libc.TLS, it uintptr) { /* iterator_enc.c:234:6: */ + var tnz int32 = int32(*(*uint32_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).nz_))) + var lnz int32 = int32(*(*uint32_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).nz_ + libc.UintptrFromInt32(-1)*4))) + var top_nz uintptr = it + 132 /* &.top_nz_ */ + var left_nz uintptr = it + 168 /* &.left_nz_ */ + + // Top-Y + *(*int32)(unsafe.Pointer(top_nz)) = (libc.BoolInt32(!(!(((tnz) & (int32(1) << (12))) != 0)))) + *(*int32)(unsafe.Pointer(top_nz + 1*4)) = (libc.BoolInt32(!(!(((tnz) & (int32(1) << (13))) != 0)))) + *(*int32)(unsafe.Pointer(top_nz + 2*4)) = (libc.BoolInt32(!(!(((tnz) & (int32(1) << (14))) != 0)))) + *(*int32)(unsafe.Pointer(top_nz + 3*4)) = (libc.BoolInt32(!(!(((tnz) & (int32(1) << (15))) != 0)))) + // Top-U + *(*int32)(unsafe.Pointer(top_nz + 4*4)) = (libc.BoolInt32(!(!(((tnz) & (int32(1) << (18))) != 0)))) + *(*int32)(unsafe.Pointer(top_nz + 5*4)) = (libc.BoolInt32(!(!(((tnz) & (int32(1) << (19))) != 0)))) + // Top-V + *(*int32)(unsafe.Pointer(top_nz + 6*4)) = (libc.BoolInt32(!(!(((tnz) & (int32(1) << (22))) != 0)))) + *(*int32)(unsafe.Pointer(top_nz + 7*4)) = (libc.BoolInt32(!(!(((tnz) & (int32(1) << (23))) != 0)))) + // DC + *(*int32)(unsafe.Pointer(top_nz + 8*4)) = (libc.BoolInt32(!(!(((tnz) & (int32(1) << (24))) != 0)))) + + // left-Y + *(*int32)(unsafe.Pointer(left_nz)) = (libc.BoolInt32(!(!(((lnz) & (int32(1) << (3))) != 0)))) + *(*int32)(unsafe.Pointer(left_nz + 1*4)) = (libc.BoolInt32(!(!(((lnz) & (int32(1) << (7))) != 0)))) + *(*int32)(unsafe.Pointer(left_nz + 2*4)) = (libc.BoolInt32(!(!(((lnz) & (int32(1) << (11))) != 0)))) + *(*int32)(unsafe.Pointer(left_nz + 3*4)) = (libc.BoolInt32(!(!(((lnz) & (int32(1) << (15))) != 0)))) + // left-U + *(*int32)(unsafe.Pointer(left_nz + 4*4)) = (libc.BoolInt32(!(!(((lnz) & (int32(1) << (17))) != 0)))) + *(*int32)(unsafe.Pointer(left_nz + 5*4)) = (libc.BoolInt32(!(!(((lnz) & (int32(1) << (19))) != 0)))) + // left-V + *(*int32)(unsafe.Pointer(left_nz + 6*4)) = (libc.BoolInt32(!(!(((lnz) & (int32(1) << (21))) != 0)))) + *(*int32)(unsafe.Pointer(left_nz + 7*4)) = (libc.BoolInt32(!(!(((lnz) & (int32(1) << (23))) != 0)))) + // left-DC is special, iterated separately +} + +func VP8IteratorBytesToNz(tls *libc.TLS, it uintptr) { /* iterator_enc.c:267:6: */ + var nz uint32_t = uint32_t(0) + var top_nz uintptr = it + 132 /* &.top_nz_ */ + var left_nz uintptr = it + 168 /* &.left_nz_ */ + // top + nz = nz | (uint32_t((*(*int32)(unsafe.Pointer(top_nz)) << 12) | (*(*int32)(unsafe.Pointer(top_nz + 1*4)) << 13))) + nz = nz | (uint32_t((*(*int32)(unsafe.Pointer(top_nz + 2*4)) << 14) | (*(*int32)(unsafe.Pointer(top_nz + 3*4)) << 15))) + nz = nz | (uint32_t((*(*int32)(unsafe.Pointer(top_nz + 4*4)) << 18) | (*(*int32)(unsafe.Pointer(top_nz + 5*4)) << 19))) + nz = nz | (uint32_t((*(*int32)(unsafe.Pointer(top_nz + 6*4)) << 22) | (*(*int32)(unsafe.Pointer(top_nz + 7*4)) << 23))) + nz = nz | (uint32_t(*(*int32)(unsafe.Pointer(top_nz + 8*4)) << 24)) // we propagate the _top_ bit, esp. for intra4 + // left + nz = nz | (uint32_t((*(*int32)(unsafe.Pointer(left_nz)) << 3) | (*(*int32)(unsafe.Pointer(left_nz + 1*4)) << 7))) + nz = nz | (uint32_t(*(*int32)(unsafe.Pointer(left_nz + 2*4)) << 11)) + nz = nz | (uint32_t((*(*int32)(unsafe.Pointer(left_nz + 4*4)) << 17) | (*(*int32)(unsafe.Pointer(left_nz + 6*4)) << 21))) + + *(*uint32_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).nz_)) = nz +} + +//------------------------------------------------------------------------------ +// Advance to the next position, doing the bookkeeping. + +func VP8IteratorSaveBoundary(tls *libc.TLS, it uintptr) { /* iterator_enc.c:290:6: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var x int32 = (*VP8EncIterator)(unsafe.Pointer(it)).x_ + var y int32 = (*VP8EncIterator)(unsafe.Pointer(it)).y_ + var ysrc uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_ + uintptr((0))) + var uvsrc uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_ + uintptr((16))) + if x < ((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ - 1) { // left + var i int32 + for i = 0; i < 16; i++ { + *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).y_left_ + uintptr(i))) = *(*uint8_t)(unsafe.Pointer(ysrc + uintptr((15 + (i * 32))))) + } + for i = 0; i < 8; i++ { + *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).u_left_ + uintptr(i))) = *(*uint8_t)(unsafe.Pointer(uvsrc + uintptr((7 + (i * 32))))) + *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).v_left_ + uintptr(i))) = *(*uint8_t)(unsafe.Pointer(uvsrc + uintptr((15 + (i * 32))))) + } + // top-left (before 'top'!) + *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).y_left_ + libc.UintptrFromInt32(-1))) = *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).y_top_ + 15)) + *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).u_left_ + libc.UintptrFromInt32(-1))) = *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).uv_top_ + 7)) + *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).v_left_ + libc.UintptrFromInt32(-1))) = *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).uv_top_ + 15)) + } + if y < ((*VP8Encoder)(unsafe.Pointer(enc)).mb_h_ - 1) { // top + libc.Xmemcpy(tls, (*VP8EncIterator)(unsafe.Pointer(it)).y_top_, (ysrc + uintptr((15 * 32))), uint64(16)) + libc.Xmemcpy(tls, (*VP8EncIterator)(unsafe.Pointer(it)).uv_top_, (uvsrc + uintptr((7 * 32))), (uint64(8 + 8))) + } +} + +func VP8IteratorNext(tls *libc.TLS, it uintptr) int32 { /* iterator_enc.c:315:5: */ + if libc.PreIncInt32(&(*VP8EncIterator)(unsafe.Pointer(it)).x_, 1) == (*VP8Encoder)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).enc_)).mb_w_ { + VP8IteratorSetRow(tls, it, libc.PreIncInt32(&(*VP8EncIterator)(unsafe.Pointer(it)).y_, 1)) + } else { + *(*uintptr)(unsafe.Pointer((it + 64 /* &.preds_ */))) += (uintptr(4)) + *(*uintptr)(unsafe.Pointer((it + 48 /* &.mb_ */))) += (uintptr(1)) * 4 + *(*uintptr)(unsafe.Pointer((it + 72 /* &.nz_ */))) += (uintptr(1)) * 4 + *(*uintptr)(unsafe.Pointer((it + 384 /* &.y_top_ */))) += (uintptr(16)) + *(*uintptr)(unsafe.Pointer((it + 392 /* &.uv_top_ */))) += (uintptr(16)) + } + return (libc.Bool32(0 < libc.PreDecInt32(&(*VP8EncIterator)(unsafe.Pointer(it)).count_down_, 1))) +} + +//------------------------------------------------------------------------------ +// Helper function to set mode properties + +func VP8SetIntra16Mode(tls *libc.TLS, it uintptr, mode int32) { /* iterator_enc.c:331:6: */ + var preds uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).preds_ + var y int32 + for y = 0; y < 4; y++ { + libc.Xmemset(tls, preds, mode, uint64(4)) + preds += uintptr((*VP8Encoder)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).enc_)).preds_w_) + } + libc.SetBitFieldPtr8Uint32(((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.type_ */), uint32(1), 0, 0x3) +} + +func VP8SetIntra4Mode(tls *libc.TLS, it uintptr, modes uintptr) { /* iterator_enc.c:341:6: */ + var preds uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).preds_ + var y int32 + for y = 4; y > 0; y-- { + libc.Xmemcpy(tls, preds, modes, (uint64(4) * uint64(unsafe.Sizeof(uint8_t(0))))) + preds += uintptr((*VP8Encoder)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).enc_)).preds_w_) + modes += uintptr(4) + } + libc.SetBitFieldPtr8Uint32(((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.type_ */), uint32(0), 0, 0x3) +} + +func VP8SetIntraUVMode(tls *libc.TLS, it uintptr, mode int32) { /* iterator_enc.c:352:6: */ + libc.SetBitFieldPtr8Uint32(((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.uv_mode_ */), uint32(mode), 2, 0xc) +} + +func VP8SetSkip(tls *libc.TLS, it uintptr, skip int32) { /* iterator_enc.c:356:6: */ + libc.SetBitFieldPtr8Uint32(((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.skip_ */), uint32(skip), 4, 0x10) +} + +func VP8SetSegment(tls *libc.TLS, it uintptr, segment int32) { /* iterator_enc.c:360:6: */ + libc.SetBitFieldPtr8Uint32(((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.segment_ */), uint32(segment), 5, 0x60) +} + +//------------------------------------------------------------------------------ +// Intra4x4 sub-blocks iteration +// +// We store and update the boundary samples into an array of 37 pixels. They +// are updated as we iterate and reconstructs each intra4x4 blocks in turn. +// The position of the samples has the following snake pattern: +// +// 16|17 18 19 20|21 22 23 24|25 26 27 28|29 30 31 32|33 34 35 36 <- Top-right +// --+-----------+-----------+-----------+-----------+ +// 15| 19| 23| 27| 31| +// 14| 18| 22| 26| 30| +// 13| 17| 21| 25| 29| +// 12|13 14 15 16|17 18 19 20|21 22 23 24|25 26 27 28| +// --+-----------+-----------+-----------+-----------+ +// 11| 15| 19| 23| 27| +// 10| 14| 18| 22| 26| +// 9| 13| 17| 21| 25| +// 8| 9 10 11 12|13 14 15 16|17 18 19 20|21 22 23 24| +// --+-----------+-----------+-----------+-----------+ +// 7| 11| 15| 19| 23| +// 6| 10| 14| 18| 22| +// 5| 9| 13| 17| 21| +// 4| 5 6 7 8| 9 10 11 12|13 14 15 16|17 18 19 20| +// --+-----------+-----------+-----------+-----------+ +// 3| 7| 11| 15| 19| +// 2| 6| 10| 14| 18| +// 1| 5| 9| 13| 17| +// 0| 1 2 3 4| 5 6 7 8| 9 10 11 12|13 14 15 16| +// --+-----------+-----------+-----------+-----------+ + +// Array to record the position of the top sample to pass to the prediction +// functions in dsp.c. +var VP8TopLeftI4 = [16]uint8_t{ + uint8_t(17), uint8_t(21), uint8_t(25), uint8_t(29), + uint8_t(13), uint8_t(17), uint8_t(21), uint8_t(25), + uint8_t(9), uint8_t(13), uint8_t(17), uint8_t(21), + uint8_t(5), uint8_t(9), uint8_t(13), uint8_t(17), +} /* iterator_enc.c:396:22 */ + +func VP8IteratorStartI4(tls *libc.TLS, it uintptr) { /* iterator_enc.c:403:6: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var i int32 + + (*VP8EncIterator)(unsafe.Pointer(it)).i4_ = 0 // first 4x4 sub-block + (*VP8EncIterator)(unsafe.Pointer(it)).i4_top_ = ((it + 80 /* &.i4_boundary_ */) + uintptr(VP8TopLeftI4[0])) + + // Import the boundary samples + for i = 0; i < 17; i++ { // left + *(*uint8_t)(unsafe.Pointer((it + 80 /* &.i4_boundary_ */) + uintptr(i))) = *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).y_left_ + uintptr((15 - i)))) + } + for i = 0; i < 16; i++ { // top + *(*uint8_t)(unsafe.Pointer((it + 80 /* &.i4_boundary_ */) + uintptr((17 + i)))) = *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).y_top_ + uintptr(i))) + } + // top-right samples have a special case on the far right of the picture + if (*VP8EncIterator)(unsafe.Pointer(it)).x_ < ((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ - 1) { + for i = 16; i < (16 + 4); i++ { + *(*uint8_t)(unsafe.Pointer((it + 80 /* &.i4_boundary_ */) + uintptr((17 + i)))) = *(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).y_top_ + uintptr(i))) + } + } else { // else, replicate the last valid pixel four times + for i = 16; i < (16 + 4); i++ { + *(*uint8_t)(unsafe.Pointer((it + 80 /* &.i4_boundary_ */) + uintptr((17 + i)))) = *(*uint8_t)(unsafe.Pointer((it + 80 /* &.i4_boundary_ */) + 32)) + } + } + VP8IteratorNzToBytes(tls, it) // import the non-zero context +} + +func VP8IteratorRotateI4(tls *libc.TLS, it uintptr, yuv_out uintptr) int32 { /* iterator_enc.c:430:5: */ + var blk uintptr = (yuv_out + uintptr(VP8Scan[(*VP8EncIterator)(unsafe.Pointer(it)).i4_])) + var top uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).i4_top_ + var i int32 + + // Update the cache with 7 fresh samples + for i = 0; i <= 3; i++ { + *(*uint8_t)(unsafe.Pointer(top + uintptr((-4 + i)))) = *(*uint8_t)(unsafe.Pointer(blk + uintptr((i + (3 * 32))))) // store future top samples + } + if ((*VP8EncIterator)(unsafe.Pointer(it)).i4_ & 3) != 3 { // if not on the right sub-blocks #3, #7, #11, #15 + for i = 0; i <= 2; i++ { // store future left samples + *(*uint8_t)(unsafe.Pointer(top + uintptr(i))) = *(*uint8_t)(unsafe.Pointer(blk + uintptr((3 + ((2 - i) * 32))))) + } + } else { // else replicate top-right samples, as says the specs. + for i = 0; i <= 3; i++ { + *(*uint8_t)(unsafe.Pointer(top + uintptr(i))) = *(*uint8_t)(unsafe.Pointer(top + uintptr((i + 4)))) + } + } + // move pointers to next sub-block + (*VP8EncIterator)(unsafe.Pointer(it)).i4_++ + if (*VP8EncIterator)(unsafe.Pointer(it)).i4_ == 16 { // we're done + return 0 + } + + (*VP8EncIterator)(unsafe.Pointer(it)).i4_top_ = ((it + 80 /* &.i4_boundary_ */) + uintptr(VP8TopLeftI4[(*VP8EncIterator)(unsafe.Pointer(it)).i4_])) + return 1 +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +// Quantizes the value up or down to a multiple of 1<<bits (or to 255), +// choosing the closer one, resolving ties using bankers' rounding. +func FindClosestDiscretized(tls *libc.TLS, a uint32_t, bits int32) uint32_t { /* near_lossless_enc.c:31:17: */ + var mask uint32_t = ((uint32(1) << bits) - uint32(1)) + var biased uint32_t = ((a + (mask >> 1)) + ((a >> bits) & uint32_t(1))) + + if biased > uint32_t(0xff) { + return uint32_t(0xff) + } + return (biased & ^mask) +} + +// Applies FindClosestDiscretized to all channels of pixel. +func ClosestDiscretizedArgb(tls *libc.TLS, a uint32_t, bits int32) uint32_t { /* near_lossless_enc.c:40:17: */ + return ((((FindClosestDiscretized(tls, (a>>24), bits) << 24) | (FindClosestDiscretized(tls, ((a>>16)&uint32_t(0xff)), bits) << 16)) | (FindClosestDiscretized(tls, ((a>>8)&uint32_t(0xff)), bits) << 8)) | (FindClosestDiscretized(tls, (a & uint32_t(0xff)), bits))) +} + +// Checks if distance between corresponding channel values of pixels a and b +// is within the given limit. +func IsNear(tls *libc.TLS, a uint32_t, b uint32_t, limit int32) int32 { /* near_lossless_enc.c:50:12: */ + var k int32 + for k = 0; k < 4; k++ { + var delta int32 = ((int32((a >> (k * 8)) & uint32_t(0xff))) - (int32((b >> (k * 8)) & uint32_t(0xff)))) + if (delta >= limit) || (delta <= -limit) { + return 0 + } + } + return 1 +} + +func IsSmooth(tls *libc.TLS, prev_row uintptr, curr_row uintptr, next_row uintptr, ix int32, limit int32) int32 { /* near_lossless_enc.c:62:12: */ + // Check that all pixels in 4-connected neighborhood are smooth. + return (libc.Bool32((((IsNear(tls, *(*uint32_t)(unsafe.Pointer(curr_row + uintptr(ix)*4)), *(*uint32_t)(unsafe.Pointer(curr_row + uintptr((ix-1))*4)), limit) != 0) && (IsNear(tls, *(*uint32_t)(unsafe.Pointer(curr_row + uintptr(ix)*4)), *(*uint32_t)(unsafe.Pointer(curr_row + uintptr((ix+1))*4)), limit) != 0)) && (IsNear(tls, *(*uint32_t)(unsafe.Pointer(curr_row + uintptr(ix)*4)), *(*uint32_t)(unsafe.Pointer(prev_row + uintptr(ix)*4)), limit) != 0)) && (IsNear(tls, *(*uint32_t)(unsafe.Pointer(curr_row + uintptr(ix)*4)), *(*uint32_t)(unsafe.Pointer(next_row + uintptr(ix)*4)), limit) != 0))) +} + +// Adjusts pixel values of image with given maximum error. +func NearLossless(tls *libc.TLS, xsize int32, ysize int32, argb_src uintptr, stride int32, limit_bits int32, copy_buffer uintptr, argb_dst uintptr) { /* near_lossless_enc.c:74:13: */ + var x int32 + var y int32 + var limit int32 = (int32(1) << limit_bits) + var prev_row uintptr = copy_buffer + var curr_row uintptr = (prev_row + uintptr(xsize)*4) + var next_row uintptr = (curr_row + uintptr(xsize)*4) + libc.Xmemcpy(tls, curr_row, argb_src, (uint64(xsize) * uint64(unsafe.Sizeof(uint32_t(0))))) + libc.Xmemcpy(tls, next_row, (argb_src + uintptr(stride)*4), (uint64(xsize) * uint64(unsafe.Sizeof(uint32_t(0))))) + + y = 0 +__1: + if !(y < ysize) { + goto __3 + } + { + if (y == 0) || (y == (ysize - 1)) { + libc.Xmemcpy(tls, argb_dst, argb_src, (uint64(xsize) * uint64(unsafe.Sizeof(uint32_t(0))))) + } else { + libc.Xmemcpy(tls, next_row, (argb_src + uintptr(stride)*4), (uint64(xsize) * uint64(unsafe.Sizeof(uint32_t(0))))) + *(*uint32_t)(unsafe.Pointer(argb_dst)) = *(*uint32_t)(unsafe.Pointer(argb_src)) + *(*uint32_t)(unsafe.Pointer(argb_dst + uintptr((xsize-1))*4)) = *(*uint32_t)(unsafe.Pointer(argb_src + uintptr((xsize-1))*4)) + for x = 1; x < (xsize - 1); x++ { + if IsSmooth(tls, prev_row, curr_row, next_row, x, limit) != 0 { + *(*uint32_t)(unsafe.Pointer(argb_dst + uintptr(x)*4)) = *(*uint32_t)(unsafe.Pointer(curr_row + uintptr(x)*4)) + } else { + *(*uint32_t)(unsafe.Pointer(argb_dst + uintptr(x)*4)) = ClosestDiscretizedArgb(tls, *(*uint32_t)(unsafe.Pointer(curr_row + uintptr(x)*4)), limit_bits) + } + } + } + { + // Three-way swap. + var temp uintptr = prev_row + prev_row = curr_row + curr_row = next_row + next_row = temp + + } + + } + goto __2 +__2: + y++ + argb_src += 4 * (uintptr(stride)) + argb_dst += 4 * (uintptr(xsize)) + goto __1 + goto __3 +__3: +} + +func VP8ApplyNearLossless(tls *libc.TLS, picture uintptr, quality int32, argb_dst uintptr) int32 { /* near_lossless_enc.c:110:5: */ + var i int32 + var xsize int32 = (*WebPPicture)(unsafe.Pointer(picture)).width + var ysize int32 = (*WebPPicture)(unsafe.Pointer(picture)).height + var stride int32 = (*WebPPicture)(unsafe.Pointer(picture)).argb_stride + var copy_buffer uintptr = WebPSafeMalloc(tls, (uint64(xsize * 3)), uint64(unsafe.Sizeof(uint32_t(0)))) + var limit_bits int32 = VP8LNearLosslessBits(tls, quality) + + if copy_buffer == (uintptr(0)) { + return 0 + } + // For small icon images, don't attempt to apply near-lossless compression. + if ((xsize < 64) && (ysize < 64)) || (ysize < 3) { + for i = 0; i < ysize; i++ { + libc.Xmemcpy(tls, (argb_dst + uintptr((i*xsize))*4), ((*WebPPicture)(unsafe.Pointer(picture)).argb + uintptr((i*(*WebPPicture)(unsafe.Pointer(picture)).argb_stride))*4), + (uint64(xsize) * uint64(unsafe.Sizeof(uint32_t(0))))) + } + WebPSafeFree(tls, copy_buffer) + return 1 + } + + NearLossless(tls, xsize, ysize, (*WebPPicture)(unsafe.Pointer(picture)).argb, stride, limit_bits, copy_buffer, + argb_dst) + for i = (limit_bits - 1); i != 0; i-- { + NearLossless(tls, xsize, ysize, argb_dst, xsize, i, copy_buffer, argb_dst) + } + WebPSafeFree(tls, copy_buffer) + return 1 +} + +// Uncomment to disable gamma-compression during RGB->U/V averaging + +// If defined, use table to compute x / alpha. + +// uint32_t 0xff000000 is 0x00,00,00,ff in memory + +//------------------------------------------------------------------------------ +// Detection of non-trivial transparency + +// Returns true if alpha[] has non-0xff values. +func CheckNonOpaque(tls *libc.TLS, alpha uintptr, width int32, height int32, x_step int32, y_step int32) int32 { /* picture_csp_enc.c:45:12: */ + if alpha == (uintptr(0)) { + return 0 + } + WebPInitAlphaProcessing(tls) + if x_step == 1 { + for ; libc.PostDecInt32(&height, 1) > 0; alpha += uintptr(y_step) { + if (*struct { + f func(*libc.TLS, uintptr, int32) int32 + })(unsafe.Pointer(&struct{ uintptr }{WebPHasAlpha8b})).f(tls, alpha, width) != 0 { + return 1 + } + } + } else { + for ; libc.PostDecInt32(&height, 1) > 0; alpha += uintptr(y_step) { + if (*struct { + f func(*libc.TLS, uintptr, int32) int32 + })(unsafe.Pointer(&struct{ uintptr }{WebPHasAlpha32b})).f(tls, alpha, width) != 0 { + return 1 + } + } + } + return 0 +} + +// Checking for the presence of non-opaque alpha. +func WebPPictureHasTransparency(tls *libc.TLS, picture uintptr) int32 { /* picture_csp_enc.c:62:5: */ + if picture == (uintptr(0)) { + return 0 + } + if (*WebPPicture)(unsafe.Pointer(picture)).use_argb != 0 { + var alpha_offset int32 = (3 - (0)) + return CheckNonOpaque(tls, ((*WebPPicture)(unsafe.Pointer(picture)).argb + uintptr(alpha_offset)), + (*WebPPicture)(unsafe.Pointer(picture)).width, (*WebPPicture)(unsafe.Pointer(picture)).height, + 4, (int32(uint64((*WebPPicture)(unsafe.Pointer(picture)).argb_stride) * uint64(unsafe.Sizeof(uint32_t(0)))))) + } + return CheckNonOpaque(tls, (*WebPPicture)(unsafe.Pointer(picture)).a, (*WebPPicture)(unsafe.Pointer(picture)).width, (*WebPPicture)(unsafe.Pointer(picture)).height, + 1, (*WebPPicture)(unsafe.Pointer(picture)).a_stride) +} + +//------------------------------------------------------------------------------ +// Code for gamma correction + +// gamma-compensates loss of resolution during chroma subsampling + +var kLinearToGammaTab [33]int32 /* picture_csp_enc.c:88:12: */ +var kGammaToLinearTab [256]uint16_t /* picture_csp_enc.c:89:17: */ +var kGammaTablesOk int32 = 0 /* picture_csp_enc.c:90:21 */ + +func InitGammaTables(tls *libc.TLS) { /* picture_csp_enc.c:93:1: */ + for ok := true; ok; ok = (0 != 0) { + if InitGammaTables_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + InitGammaTables_body(tls) + InitGammaTables_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var InitGammaTables_body_last_cpuinfo_used VP8CPUInfo = 0 /* picture_csp_enc.c:93:1 */ + +func InitGammaTables_body(tls *libc.TLS) { /* picture_csp_enc.c:93:1: */ + if !(libc.AtomicLoadInt32(&kGammaTablesOk) != 0) { + var v int32 + var scale float64 = (float64((float64(int32(1) << 7))) / (float64((int32(1) << 12) - 1))) + var norm float64 = (float64(1.) / 255.) + for v = 0; v <= 255; v++ { + kGammaToLinearTab[v] = (libc.Uint16FromFloat64((libc.Xpow(tls, (norm*float64(v)), 0.80) * (float64((int32(1) << 12) - 1))) + .5)) + } + for v = 0; v <= (int32(1) << (12 - 7)); v++ { + kLinearToGammaTab[v] = (libc.Int32FromFloat64((255. * libc.Xpow(tls, (scale*float64(v)), (float64(1.)/0.80))) + .5)) + } + libc.AtomicStoreInt32(&kGammaTablesOk, int32(1)) + } +} + +func GammaToLinear(tls *libc.TLS, v uint8_t) uint32_t { /* picture_csp_enc.c:109:29: */ + return uint32_t(kGammaToLinearTab[v]) +} + +func Interpolate(tls *libc.TLS, v int32) int32 { /* picture_csp_enc.c:113:24: */ + var tab_pos int32 = (v >> (7 + 2)) // integer part + var x int32 = (v & ((int32((int32(1) << 7)) << 2) - 1)) // fractional part + var v0 int32 = kLinearToGammaTab[tab_pos] + var v1 int32 = kLinearToGammaTab[(tab_pos + 1)] + var y int32 = ((v1 * x) + (v0 * ((int32((int32(1) << 7)) << 2) - x))) // interpolate + + return y +} + +// Convert a linear value 'v' to YUV_FIX+2 fixed-point precision +// U/V value, suitable for RGBToU/V calls. +func LinearToGamma(tls *libc.TLS, base_value uint32_t, shift int32) int32 { /* picture_csp_enc.c:125:24: */ + var y int32 = Interpolate(tls, (int32(base_value << shift))) // final uplifted value + return ((y + (int32((int32(1) << 7)) >> 1)) >> 7) // descale +} + +//------------------------------------------------------------------------------ +// RGB -> YUV conversion + +func RGBToY(tls *libc.TLS, r int32, g int32, b int32, rg uintptr) int32 { /* picture_csp_enc.c:143:12: */ + if rg == (uintptr(0)) { + return VP8RGBToY(tls, r, g, b, YUV_HALF) + } + return VP8RGBToY(tls, r, g, b, VP8RandomBits(tls, rg, YUV_FIX)) +} + +func RGBToU(tls *libc.TLS, r int32, g int32, b int32, rg uintptr) int32 { /* picture_csp_enc.c:148:12: */ + if rg == (uintptr(0)) { + return VP8RGBToU(tls, r, g, b, (int32(YUV_HALF) << 2)) + } + return VP8RGBToU(tls, r, g, b, VP8RandomBits(tls, rg, (YUV_FIX+2))) +} + +func RGBToV(tls *libc.TLS, r int32, g int32, b int32, rg uintptr) int32 { /* picture_csp_enc.c:153:12: */ + if rg == (uintptr(0)) { + return VP8RGBToV(tls, r, g, b, (int32(YUV_HALF) << 2)) + } + return VP8RGBToV(tls, r, g, b, VP8RandomBits(tls, rg, (YUV_FIX+2))) +} + +//------------------------------------------------------------------------------ +// Sharp RGB->YUV conversion + +var kNumIterations int32 = 4 /* picture_csp_enc.c:161:18 */ +var kMinDimensionIterativeConversion int32 = 4 /* picture_csp_enc.c:162:18 */ + +// We could use SFIX=0 and only uint8_t for fixed_y_t, but it produces some +// banding sometimes. Better use extra precision. +type fixed_t = int16_t /* picture_csp_enc.c:167:17 */ // signed type with extra SFIX precision for UV +type fixed_y_t = uint16_t /* picture_csp_enc.c:168:18 */ // unsigned type with extra SFIX precision for W + +// We use tables of different size and precision for the Rec709 / BT2020 +// transfer function. +var kLinearToGammaTabS [34]uint32_t /* picture_csp_enc.c:179:17: */ +var kGammaToLinearTabS [1024]uint32_t /* picture_csp_enc.c:181:17: */ // size scales with Y_FIX +var kGammaTablesSOk int32 = 0 /* picture_csp_enc.c:182:21 */ + +func InitGammaTablesS(tls *libc.TLS) { /* picture_csp_enc.c:185:1: */ + for ok := true; ok; ok = (0 != 0) { + if InitGammaTablesS_body_last_cpuinfo_used == VP8GetCPUInfo { + break + } + InitGammaTablesS_body(tls) + InitGammaTablesS_body_last_cpuinfo_used = VP8GetCPUInfo + } +} + +var InitGammaTablesS_body_last_cpuinfo_used VP8CPUInfo = 0 /* picture_csp_enc.c:185:1 */ + +func InitGammaTablesS_body(tls *libc.TLS) { /* picture_csp_enc.c:185:1: */ + // we use uint32_t intermediate values + if !(libc.AtomicLoadInt32(&kGammaTablesSOk) != 0) { + var v int32 + var norm float64 = (float64(1.) / (float64((int32(256) << 2) - 1))) + var scale float64 = (float64(1.) / (float64(int32(1) << (12 - 7)))) + var a float64 = 0.09929682680944 + var thresh float64 = 0.018053968510807 + var final_scale float64 = (float64(int32(1) << 14)) + for v = 0; v <= ((int32(256) << 2) - 1); v++ { + var g float64 = (norm * float64(v)) + var value float64 + if g <= (thresh * 4.5) { + value = (g / 4.5) + } else { + var a_rec float64 = (1. / (1. + a)) + value = libc.Xpow(tls, (a_rec * (g + a)), (float64(1.) / 0.45)) + } + kGammaToLinearTabS[v] = (libc.Uint32FromFloat64((value * final_scale) + .5)) + } + for v = 0; v <= (int32(1) << (12 - 7)); v++ { + var g float64 = (scale * float64(v)) + var value float64 + if g <= thresh { + value = (4.5 * g) + } else { + value = (((1. + a) * libc.Xpow(tls, g, (float64(1.)/(float64(1.)/0.45)))) - a) + } + // we already incorporate the 1/2 rounding constant here + kLinearToGammaTabS[v] = ((libc.Uint32FromFloat64((float64((int32(256) << 2) - 1)) * value)) + (uint32_t(int32((int32(1) << 14)) >> 1))) + } + // to prevent small rounding errors to cause read-overflow: + kLinearToGammaTabS[((int32(1) << (12 - 7)) + 1)] = kLinearToGammaTabS[(int32(1) << (12 - 7))] + libc.AtomicStoreInt32(&kGammaTablesSOk, int32(1)) + } +} + +// return value has a fixed-point precision of GAMMA_TO_LINEAR_BITS +func GammaToLinearS(tls *libc.TLS, v int32) uint32_t { /* picture_csp_enc.c:224:29: */ + return kGammaToLinearTabS[v] +} + +func LinearToGammaS(tls *libc.TLS, value uint32_t) uint32_t { /* picture_csp_enc.c:228:29: */ + // 'value' is in GAMMA_TO_LINEAR_BITS fractional precision + var v uint32_t = (value * (uint32_t(int32(1) << (12 - 7)))) + var tab_pos uint32_t = (v >> 14) + // fractional part, in GAMMA_TO_LINEAR_BITS fixed-point precision + var x uint32_t = (v - (tab_pos << 14)) // fractional part + // v0 / v1 are in GAMMA_TO_LINEAR_BITS fixed-point precision (range [0..1]) + var v0 uint32_t = kLinearToGammaTabS[(tab_pos + uint32_t(0))] + var v1 uint32_t = kLinearToGammaTabS[(tab_pos + uint32_t(1))] + // Final interpolation. Note that rounding is already included. + var v2 uint32_t = ((v1 - v0) * x) // note: v1 >= v0. + var result uint32_t = (v0 + (v2 >> 14)) + return result +} + +//------------------------------------------------------------------------------ + +func clip_8b2(tls *libc.TLS, v fixed_t) uint8_t { /* picture_csp_enc.c:257:16: */ + if !((int32(v) & libc.CplInt32(0xff)) != 0) { + return uint8_t(v) + } + if int32(v) < 0 { + return uint8(0) + } + return uint8(255) +} + +func clip_y1(tls *libc.TLS, y int32) fixed_y_t { /* picture_csp_enc.c:261:18: */ + if !((y & libc.CplInt32(((int32(256) << 2) - 1))) != 0) { + return fixed_y_t(y) + } + if y < 0 { + return uint16(0) + } + return (uint16((int32(256) << 2) - 1)) +} + +//------------------------------------------------------------------------------ + +func RGBToGray(tls *libc.TLS, r int32, g int32, b int32) int32 { /* picture_csp_enc.c:267:12: */ + var luma int32 = ((((13933 * r) + (46871 * g)) + (4732 * b)) + YUV_HALF) + return (luma >> YUV_FIX) +} + +func ScaleDown(tls *libc.TLS, a int32, b int32, c int32, d int32) uint32_t { /* picture_csp_enc.c:272:17: */ + var A uint32_t = GammaToLinearS(tls, a) + var B uint32_t = GammaToLinearS(tls, b) + var C uint32_t = GammaToLinearS(tls, c) + var D uint32_t = GammaToLinearS(tls, d) + return LinearToGammaS(tls, (((((A + B) + C) + D) + uint32_t(2)) >> 2)) +} + +func UpdateW(tls *libc.TLS, src uintptr, dst uintptr, w int32) { /* picture_csp_enc.c:280:25: */ + var i int32 + for i = 0; i < w; i++ { + var R uint32_t = GammaToLinearS(tls, int32(*(*fixed_y_t)(unsafe.Pointer(src + uintptr(((0*w)+i))*2)))) + var G uint32_t = GammaToLinearS(tls, int32(*(*fixed_y_t)(unsafe.Pointer(src + uintptr(((1*w)+i))*2)))) + var B uint32_t = GammaToLinearS(tls, int32(*(*fixed_y_t)(unsafe.Pointer(src + uintptr(((2*w)+i))*2)))) + var Y uint32_t = uint32_t(RGBToGray(tls, int32(R), int32(G), int32(B))) + *(*fixed_y_t)(unsafe.Pointer(dst + uintptr(i)*2)) = fixed_y_t(LinearToGammaS(tls, Y)) + } +} + +func UpdateChroma(tls *libc.TLS, src1 uintptr, src2 uintptr, dst uintptr, uv_w int32) { /* picture_csp_enc.c:291:13: */ + var i int32 + for i = 0; i < uv_w; i++ { + var r int32 = int32(ScaleDown(tls, int32(*(*fixed_y_t)(unsafe.Pointer(src1 + uintptr(((0*uv_w)+0))*2))), int32(*(*fixed_y_t)(unsafe.Pointer(src1 + uintptr(((0*uv_w)+1))*2))), + int32(*(*fixed_y_t)(unsafe.Pointer(src2 + uintptr(((0*uv_w)+0))*2))), int32(*(*fixed_y_t)(unsafe.Pointer(src2 + uintptr(((0*uv_w)+1))*2))))) + var g int32 = int32(ScaleDown(tls, int32(*(*fixed_y_t)(unsafe.Pointer(src1 + uintptr(((2*uv_w)+0))*2))), int32(*(*fixed_y_t)(unsafe.Pointer(src1 + uintptr(((2*uv_w)+1))*2))), + int32(*(*fixed_y_t)(unsafe.Pointer(src2 + uintptr(((2*uv_w)+0))*2))), int32(*(*fixed_y_t)(unsafe.Pointer(src2 + uintptr(((2*uv_w)+1))*2))))) + var b int32 = int32(ScaleDown(tls, int32(*(*fixed_y_t)(unsafe.Pointer(src1 + uintptr(((4*uv_w)+0))*2))), int32(*(*fixed_y_t)(unsafe.Pointer(src1 + uintptr(((4*uv_w)+1))*2))), + int32(*(*fixed_y_t)(unsafe.Pointer(src2 + uintptr(((4*uv_w)+0))*2))), int32(*(*fixed_y_t)(unsafe.Pointer(src2 + uintptr(((4*uv_w)+1))*2))))) + var W int32 = RGBToGray(tls, r, g, b) + *(*fixed_t)(unsafe.Pointer(dst + uintptr((0*uv_w))*2)) = (fixed_t(r - W)) + *(*fixed_t)(unsafe.Pointer(dst + uintptr((1*uv_w))*2)) = (fixed_t(g - W)) + *(*fixed_t)(unsafe.Pointer(dst + uintptr((2*uv_w))*2)) = (fixed_t(b - W)) + dst += 2 * (uintptr(1)) + src1 += 2 * (uintptr(2)) + src2 += 2 * (uintptr(2)) + } +} + +func StoreGray(tls *libc.TLS, rgb uintptr, y uintptr, w int32) { /* picture_csp_enc.c:311:13: */ + var i int32 + for i = 0; i < w; i++ { + *(*fixed_y_t)(unsafe.Pointer(y + uintptr(i)*2)) = fixed_y_t(RGBToGray(tls, int32(*(*fixed_y_t)(unsafe.Pointer(rgb + uintptr(((0*w)+i))*2))), int32(*(*fixed_y_t)(unsafe.Pointer(rgb + uintptr(((1*w)+i))*2))), int32(*(*fixed_y_t)(unsafe.Pointer(rgb + uintptr(((2*w)+i))*2))))) + } +} + +//------------------------------------------------------------------------------ + +func Filter2(tls *libc.TLS, A int32, B int32, W0 int32) fixed_y_t { /* picture_csp_enc.c:320:30: */ + var v0 int32 = ((((A * 3) + B) + 2) >> 2) + return clip_y1(tls, (v0 + W0)) +} + +//------------------------------------------------------------------------------ + +func UpLift(tls *libc.TLS, a uint8_t) fixed_y_t { /* picture_csp_enc.c:327:30: */ // 8bit -> SFIX + return (fixed_y_t((int32(fixed_y_t(a)) << 2) | (int32((int32(1) << 2)) >> 1))) +} + +func ImportOneRow(tls *libc.TLS, r_ptr uintptr, g_ptr uintptr, b_ptr uintptr, step int32, pic_width int32, dst uintptr) { /* picture_csp_enc.c:331:13: */ + var i int32 + var w int32 = ((pic_width + 1) & libc.CplInt32(1)) + for i = 0; i < pic_width; i++ { + var off int32 = (i * step) + *(*fixed_y_t)(unsafe.Pointer(dst + uintptr((i+(0*w)))*2)) = UpLift(tls, *(*uint8_t)(unsafe.Pointer(r_ptr + uintptr(off)))) + *(*fixed_y_t)(unsafe.Pointer(dst + uintptr((i+(1*w)))*2)) = UpLift(tls, *(*uint8_t)(unsafe.Pointer(g_ptr + uintptr(off)))) + *(*fixed_y_t)(unsafe.Pointer(dst + uintptr((i+(2*w)))*2)) = UpLift(tls, *(*uint8_t)(unsafe.Pointer(b_ptr + uintptr(off)))) + } + if (pic_width & 1) != 0 { // replicate rightmost pixel + *(*fixed_y_t)(unsafe.Pointer(dst + uintptr((pic_width+(0*w)))*2)) = *(*fixed_y_t)(unsafe.Pointer(dst + uintptr(((pic_width+(0*w))-1))*2)) + *(*fixed_y_t)(unsafe.Pointer(dst + uintptr((pic_width+(1*w)))*2)) = *(*fixed_y_t)(unsafe.Pointer(dst + uintptr(((pic_width+(1*w))-1))*2)) + *(*fixed_y_t)(unsafe.Pointer(dst + uintptr((pic_width+(2*w)))*2)) = *(*fixed_y_t)(unsafe.Pointer(dst + uintptr(((pic_width+(2*w))-1))*2)) + } +} + +func InterpolateTwoRows(tls *libc.TLS, best_y uintptr, prev_uv uintptr, cur_uv uintptr, next_uv uintptr, w int32, out1 uintptr, out2 uintptr) { /* picture_csp_enc.c:352:13: */ + var uv_w int32 = (w >> 1) + var len int32 = ((w - 1) >> 1) // length to filter + var k int32 = 3 + for libc.PostDecInt32(&k, 1) > 0 { // process each R/G/B segments in turn + // special boundary case for i==0 + *(*fixed_y_t)(unsafe.Pointer(out1)) = Filter2(tls, int32(*(*fixed_t)(unsafe.Pointer(cur_uv))), int32(*(*fixed_t)(unsafe.Pointer(prev_uv))), int32(*(*fixed_y_t)(unsafe.Pointer(best_y)))) + *(*fixed_y_t)(unsafe.Pointer(out2)) = Filter2(tls, int32(*(*fixed_t)(unsafe.Pointer(cur_uv))), int32(*(*fixed_t)(unsafe.Pointer(next_uv))), int32(*(*fixed_y_t)(unsafe.Pointer(best_y + uintptr(w)*2)))) + + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{WebPSharpYUVFilterRow})).f(tls, cur_uv, prev_uv, len, ((best_y + uintptr(0)*2) + uintptr(1)*2), (out1 + uintptr(1)*2)) + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{WebPSharpYUVFilterRow})).f(tls, cur_uv, next_uv, len, ((best_y + uintptr(w)*2) + uintptr(1)*2), (out2 + uintptr(1)*2)) + + // special boundary case for i == w - 1 when w is even + if !((w & 1) != 0) { + *(*fixed_y_t)(unsafe.Pointer(out1 + uintptr((w-1))*2)) = Filter2(tls, int32(*(*fixed_t)(unsafe.Pointer(cur_uv + uintptr((uv_w-1))*2))), int32(*(*fixed_t)(unsafe.Pointer(prev_uv + uintptr((uv_w-1))*2))), + int32(*(*fixed_y_t)(unsafe.Pointer(best_y + uintptr(((w-1)+0))*2)))) + *(*fixed_y_t)(unsafe.Pointer(out2 + uintptr((w-1))*2)) = Filter2(tls, int32(*(*fixed_t)(unsafe.Pointer(cur_uv + uintptr((uv_w-1))*2))), int32(*(*fixed_t)(unsafe.Pointer(next_uv + uintptr((uv_w-1))*2))), + int32(*(*fixed_y_t)(unsafe.Pointer(best_y + uintptr(((w-1)+w))*2)))) + } + out1 += 2 * (uintptr(w)) + out2 += 2 * (uintptr(w)) + prev_uv += 2 * (uintptr(uv_w)) + cur_uv += 2 * (uintptr(uv_w)) + next_uv += 2 * (uintptr(uv_w)) + } +} + +func ConvertRGBToY(tls *libc.TLS, r int32, g int32, b int32) uint8_t { /* picture_csp_enc.c:385:28: */ + var luma int32 = ((((16839 * r) + (33059 * g)) + (6420 * b)) + (int32(1) << ((YUV_FIX + 2) - 1))) + return clip_8b2(tls, (int16(16 + (luma >> (YUV_FIX + 2))))) +} + +func ConvertRGBToU(tls *libc.TLS, r int32, g int32, b int32) uint8_t { /* picture_csp_enc.c:390:28: */ + var u int32 = ((((-9719 * r) - (19081 * g)) + (28800 * b)) + (int32(1) << ((YUV_FIX + 2) - 1))) + return clip_8b2(tls, (int16(128 + (u >> (YUV_FIX + 2))))) +} + +func ConvertRGBToV(tls *libc.TLS, r int32, g int32, b int32) uint8_t { /* picture_csp_enc.c:395:28: */ + var v int32 = ((((+28800 * r) - (24116 * g)) - (4684 * b)) + (int32(1) << ((YUV_FIX + 2) - 1))) + return clip_8b2(tls, (int16(128 + (v >> (YUV_FIX + 2))))) +} + +func ConvertWRGBToYUV(tls *libc.TLS, best_y uintptr, best_uv uintptr, picture uintptr) int32 { /* picture_csp_enc.c:400:12: */ + var i int32 + var j int32 + var dst_y uintptr = (*WebPPicture)(unsafe.Pointer(picture)).y + var dst_u uintptr = (*WebPPicture)(unsafe.Pointer(picture)).u + var dst_v uintptr = (*WebPPicture)(unsafe.Pointer(picture)).v + var best_uv_base uintptr = best_uv + var w int32 = (((*WebPPicture)(unsafe.Pointer(picture)).width + 1) & libc.CplInt32(1)) + var h int32 = (((*WebPPicture)(unsafe.Pointer(picture)).height + 1) & libc.CplInt32(1)) + var uv_w int32 = (w >> 1) + var uv_h int32 = (h >> 1) + best_uv = best_uv_base + j = 0 + for ; j < (*WebPPicture)(unsafe.Pointer(picture)).height; j++ { + for i = 0; i < (*WebPPicture)(unsafe.Pointer(picture)).width; i++ { + var off int32 = (i >> 1) + var W int32 = int32(*(*fixed_y_t)(unsafe.Pointer(best_y + uintptr(i)*2))) + var r int32 = (int32(*(*fixed_t)(unsafe.Pointer(best_uv + uintptr((off+(0*uv_w)))*2))) + W) + var g int32 = (int32(*(*fixed_t)(unsafe.Pointer(best_uv + uintptr((off+(1*uv_w)))*2))) + W) + var b int32 = (int32(*(*fixed_t)(unsafe.Pointer(best_uv + uintptr((off+(2*uv_w)))*2))) + W) + *(*uint8_t)(unsafe.Pointer(dst_y + uintptr(i))) = ConvertRGBToY(tls, r, g, b) + } + best_y += 2 * (uintptr(w)) + best_uv += 2 * (uintptr(((j & 1) * 3) * uv_w)) + dst_y += uintptr((*WebPPicture)(unsafe.Pointer(picture)).y_stride) + } + best_uv = best_uv_base + j = 0 + for ; j < uv_h; j++ { + for i = 0; i < uv_w; i++ { + var off int32 = i + var r int32 = int32(*(*fixed_t)(unsafe.Pointer(best_uv + uintptr((off+(0*uv_w)))*2))) + var g int32 = int32(*(*fixed_t)(unsafe.Pointer(best_uv + uintptr((off+(1*uv_w)))*2))) + var b int32 = int32(*(*fixed_t)(unsafe.Pointer(best_uv + uintptr((off+(2*uv_w)))*2))) + *(*uint8_t)(unsafe.Pointer(dst_u + uintptr(i))) = ConvertRGBToU(tls, r, g, b) + *(*uint8_t)(unsafe.Pointer(dst_v + uintptr(i))) = ConvertRGBToV(tls, r, g, b) + } + best_uv += 2 * (uintptr(3 * uv_w)) + dst_u += uintptr((*WebPPicture)(unsafe.Pointer(picture)).uv_stride) + dst_v += uintptr((*WebPPicture)(unsafe.Pointer(picture)).uv_stride) + } + return 1 +} + +//------------------------------------------------------------------------------ +// Main function + +func PreprocessARGB(tls *libc.TLS, r_ptr uintptr, g_ptr uintptr, b_ptr uintptr, step int32, rgb_stride int32, picture uintptr) int32 { /* picture_csp_enc.c:445:12: */ + // we expand the right/bottom border if needed + var w int32 + var h int32 + var uv_w int32 + var uv_h int32 + var prev_diff_y_sum uint64_t + var j int32 + var iter int32 + + // TODO(skal): allocate one big memory chunk. But for now, it's easier + // for valgrind debugging to have several chunks. + var tmp_buffer uintptr // scratch + var best_y_base uintptr + var target_y_base uintptr + var best_rgb_y uintptr + var best_uv_base uintptr + var target_uv_base uintptr + var best_rgb_uv uintptr + var best_y uintptr + var target_y uintptr + var best_uv uintptr + var target_uv uintptr + var diff_y_threshold uint64_t + var ok int32 + var is_last_row int32 + var src1 uintptr + var src2 uintptr + var next_uv uintptr + var src11 uintptr + var src21 uintptr + var cur_uv uintptr + var prev_uv uintptr + var diff_y_sum uint64_t + w = (((*WebPPicture)(unsafe.Pointer(picture)).width + 1) & libc.CplInt32(1)) + h = (((*WebPPicture)(unsafe.Pointer(picture)).height + 1) & libc.CplInt32(1)) + uv_w = (w >> 1) + uv_h = (h >> 1) + prev_diff_y_sum = libc.Uint64FromInt32(libc.CplInt32(0)) + tmp_buffer = (WebPSafeMalloc(tls, (uint64((w * 3) * (2))), uint64(unsafe.Sizeof(fixed_y_t(0))))) + best_y_base = (WebPSafeMalloc(tls, (uint64((w) * (h))), uint64(unsafe.Sizeof(fixed_y_t(0))))) + target_y_base = (WebPSafeMalloc(tls, (uint64((w) * (h))), uint64(unsafe.Sizeof(fixed_y_t(0))))) + best_rgb_y = (WebPSafeMalloc(tls, (uint64((w) * (2))), uint64(unsafe.Sizeof(fixed_y_t(0))))) + best_uv_base = (WebPSafeMalloc(tls, (uint64((uv_w * 3) * (uv_h))), uint64(unsafe.Sizeof(fixed_t(0))))) + target_uv_base = (WebPSafeMalloc(tls, (uint64((uv_w * 3) * (uv_h))), uint64(unsafe.Sizeof(fixed_t(0))))) + best_rgb_uv = (WebPSafeMalloc(tls, (uint64((uv_w * 3) * (1))), uint64(unsafe.Sizeof(fixed_t(0))))) + best_y = best_y_base + target_y = target_y_base + best_uv = best_uv_base + target_uv = target_uv_base + diff_y_threshold = (libc.Uint64FromFloat64((3.0 * float64(w)) * float64(h))) + + if !(((((((best_y_base == (uintptr(0))) || (best_uv_base == (uintptr(0)))) || (target_y_base == (uintptr(0)))) || (target_uv_base == (uintptr(0)))) || (best_rgb_y == (uintptr(0)))) || (best_rgb_uv == (uintptr(0)))) || (tmp_buffer == (uintptr(0)))) { + goto __1 + } + ok = WebPEncodingSetError(tls, picture, VP8_ENC_ERROR_OUT_OF_MEMORY) + goto End +__1: + ; + + WebPInitConvertARGBToYUV(tls) + + // Import RGB samples to W/RGB representation. + j = 0 +__2: + if !(j < (*WebPPicture)(unsafe.Pointer(picture)).height) { + goto __4 + } + is_last_row = (libc.Bool32(j == ((*WebPPicture)(unsafe.Pointer(picture)).height - 1))) + src1 = (tmp_buffer + uintptr((0*w))*2) + src2 = (tmp_buffer + uintptr((3*w))*2) + + // prepare two rows of input + ImportOneRow(tls, r_ptr, g_ptr, b_ptr, step, (*WebPPicture)(unsafe.Pointer(picture)).width, src1) + if !(!(is_last_row != 0)) { + goto __5 + } + ImportOneRow(tls, (r_ptr + uintptr(rgb_stride)), (g_ptr + uintptr(rgb_stride)), (b_ptr + uintptr(rgb_stride)), + step, (*WebPPicture)(unsafe.Pointer(picture)).width, src2) + goto __6 +__5: + libc.Xmemcpy(tls, src2, src1, ((uint64(3 * w)) * uint64(unsafe.Sizeof(fixed_y_t(0))))) +__6: + ; + StoreGray(tls, src1, (best_y + uintptr(0)*2), w) + StoreGray(tls, src2, (best_y + uintptr(w)*2), w) + + UpdateW(tls, src1, target_y, w) + UpdateW(tls, src2, (target_y + uintptr(w)*2), w) + UpdateChroma(tls, src1, src2, target_uv, uv_w) + libc.Xmemcpy(tls, best_uv, target_uv, ((uint64(3 * uv_w)) * uint64(unsafe.Sizeof(fixed_t(0))))) + best_y += 2 * (uintptr(2 * w)) + best_uv += 2 * (uintptr(3 * uv_w)) + target_y += 2 * (uintptr(2 * w)) + target_uv += 2 * (uintptr(3 * uv_w)) + r_ptr += (uintptr(2 * rgb_stride)) + g_ptr += (uintptr(2 * rgb_stride)) + b_ptr += (uintptr(2 * rgb_stride)) + goto __3 +__3: + j = j + (2) + goto __2 + goto __4 +__4: + ; + + // Iterate and resolve clipping conflicts. + iter = 0 +__7: + if !(iter < kNumIterations) { + goto __9 + } + cur_uv = best_uv_base + prev_uv = best_uv_base + diff_y_sum = uint64(0) + + best_y = best_y_base + best_uv = best_uv_base + target_y = target_y_base + target_uv = target_uv_base + j = 0 +__10: + if !(j < h) { + goto __12 + } + src11 = (tmp_buffer + uintptr((0*w))*2) + src21 = (tmp_buffer + uintptr((3*w))*2) + + next_uv = (cur_uv + uintptr((func() int32 { + if j < (h - 2) { + return (3 * uv_w) + } + return 0 + }()))*2) + InterpolateTwoRows(tls, best_y, prev_uv, cur_uv, next_uv, w, src11, src21) + prev_uv = cur_uv + cur_uv = next_uv + + UpdateW(tls, src11, (best_rgb_y + uintptr((0*w))*2), w) + UpdateW(tls, src21, (best_rgb_y + uintptr((1*w))*2), w) + UpdateChroma(tls, src11, src21, best_rgb_uv, uv_w) + + // update two rows of Y and one row of RGB + diff_y_sum = diff_y_sum + ((*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) uint64_t + })(unsafe.Pointer(&struct{ uintptr }{WebPSharpYUVUpdateY})).f(tls, target_y, best_rgb_y, best_y, (2 * w))) + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPSharpYUVUpdateRGB})).f(tls, target_uv, best_rgb_uv, best_uv, (3 * uv_w)) + + best_y += 2 * (uintptr(2 * w)) + best_uv += 2 * (uintptr(3 * uv_w)) + target_y += 2 * (uintptr(2 * w)) + target_uv += 2 * (uintptr(3 * uv_w)) + goto __11 +__11: + j = j + (2) + goto __10 + goto __12 +__12: + ; + // test exit condition + if !(iter > 0) { + goto __13 + } + if !(diff_y_sum < diff_y_threshold) { + goto __14 + } + goto __9 +__14: + ; + if !(diff_y_sum > prev_diff_y_sum) { + goto __15 + } + goto __9 +__15: + ; +__13: + ; + prev_diff_y_sum = diff_y_sum + goto __8 +__8: + iter++ + goto __7 + goto __9 +__9: + ; + // final reconstruction + ok = ConvertWRGBToYUV(tls, best_y_base, best_uv_base, picture) + +End: + WebPSafeFree(tls, best_y_base) + WebPSafeFree(tls, best_uv_base) + WebPSafeFree(tls, target_y_base) + WebPSafeFree(tls, target_uv_base) + WebPSafeFree(tls, best_rgb_y) + WebPSafeFree(tls, best_rgb_uv) + WebPSafeFree(tls, tmp_buffer) + return ok +} + +//------------------------------------------------------------------------------ +// "Fast" regular RGB->YUV + +var kAlphaFix int32 = 19 /* picture_csp_enc.c:588:18 */ +// Following table is (1 << kAlphaFix) / a. The (v * kInvAlpha[a]) >> kAlphaFix +// formula is then equal to v / a in most (99.6%) cases. Note that this table +// and constant are adjusted very tightly to fit 32b arithmetic. +// In particular, they use the fact that the operands for 'v / a' are actually +// derived as v = (a0.p0 + a1.p1 + a2.p2 + a3.p3) and a = a0 + a1 + a2 + a3 +// with ai in [0..255] and pi in [0..1<<kGammaFix). The constraint to avoid +// overflow is: kGammaFix + kAlphaFix <= 31. +var kInvAlpha = [1021]uint32_t{ + uint32_t(0), // alpha = 0 + uint32_t(524288), uint32_t(262144), uint32_t(174762), uint32_t(131072), uint32_t(104857), uint32_t(87381), uint32_t(74898), uint32_t(65536), + uint32_t(58254), uint32_t(52428), uint32_t(47662), uint32_t(43690), uint32_t(40329), uint32_t(37449), uint32_t(34952), uint32_t(32768), + uint32_t(30840), uint32_t(29127), uint32_t(27594), uint32_t(26214), uint32_t(24966), uint32_t(23831), uint32_t(22795), uint32_t(21845), + uint32_t(20971), uint32_t(20164), uint32_t(19418), uint32_t(18724), uint32_t(18078), uint32_t(17476), uint32_t(16912), uint32_t(16384), + uint32_t(15887), uint32_t(15420), uint32_t(14979), uint32_t(14563), uint32_t(14169), uint32_t(13797), uint32_t(13443), uint32_t(13107), + uint32_t(12787), uint32_t(12483), uint32_t(12192), uint32_t(11915), uint32_t(11650), uint32_t(11397), uint32_t(11155), uint32_t(10922), + uint32_t(10699), uint32_t(10485), uint32_t(10280), uint32_t(10082), uint32_t(9892), uint32_t(9709), uint32_t(9532), uint32_t(9362), + uint32_t(9198), uint32_t(9039), uint32_t(8886), uint32_t(8738), uint32_t(8594), uint32_t(8456), uint32_t(8322), uint32_t(8192), + uint32_t(8065), uint32_t(7943), uint32_t(7825), uint32_t(7710), uint32_t(7598), uint32_t(7489), uint32_t(7384), uint32_t(7281), + uint32_t(7182), uint32_t(7084), uint32_t(6990), uint32_t(6898), uint32_t(6808), uint32_t(6721), uint32_t(6636), uint32_t(6553), + uint32_t(6472), uint32_t(6393), uint32_t(6316), uint32_t(6241), uint32_t(6168), uint32_t(6096), uint32_t(6026), uint32_t(5957), + uint32_t(5890), uint32_t(5825), uint32_t(5761), uint32_t(5698), uint32_t(5637), uint32_t(5577), uint32_t(5518), uint32_t(5461), + uint32_t(5405), uint32_t(5349), uint32_t(5295), uint32_t(5242), uint32_t(5190), uint32_t(5140), uint32_t(5090), uint32_t(5041), + uint32_t(4993), uint32_t(4946), uint32_t(4899), uint32_t(4854), uint32_t(4809), uint32_t(4766), uint32_t(4723), uint32_t(4681), + uint32_t(4639), uint32_t(4599), uint32_t(4559), uint32_t(4519), uint32_t(4481), uint32_t(4443), uint32_t(4405), uint32_t(4369), + uint32_t(4332), uint32_t(4297), uint32_t(4262), uint32_t(4228), uint32_t(4194), uint32_t(4161), uint32_t(4128), uint32_t(4096), + uint32_t(4064), uint32_t(4032), uint32_t(4002), uint32_t(3971), uint32_t(3942), uint32_t(3912), uint32_t(3883), uint32_t(3855), + uint32_t(3826), uint32_t(3799), uint32_t(3771), uint32_t(3744), uint32_t(3718), uint32_t(3692), uint32_t(3666), uint32_t(3640), + uint32_t(3615), uint32_t(3591), uint32_t(3566), uint32_t(3542), uint32_t(3518), uint32_t(3495), uint32_t(3472), uint32_t(3449), + uint32_t(3426), uint32_t(3404), uint32_t(3382), uint32_t(3360), uint32_t(3339), uint32_t(3318), uint32_t(3297), uint32_t(3276), + uint32_t(3256), uint32_t(3236), uint32_t(3216), uint32_t(3196), uint32_t(3177), uint32_t(3158), uint32_t(3139), uint32_t(3120), + uint32_t(3102), uint32_t(3084), uint32_t(3066), uint32_t(3048), uint32_t(3030), uint32_t(3013), uint32_t(2995), uint32_t(2978), + uint32_t(2962), uint32_t(2945), uint32_t(2928), uint32_t(2912), uint32_t(2896), uint32_t(2880), uint32_t(2864), uint32_t(2849), + uint32_t(2833), uint32_t(2818), uint32_t(2803), uint32_t(2788), uint32_t(2774), uint32_t(2759), uint32_t(2744), uint32_t(2730), + uint32_t(2716), uint32_t(2702), uint32_t(2688), uint32_t(2674), uint32_t(2661), uint32_t(2647), uint32_t(2634), uint32_t(2621), + uint32_t(2608), uint32_t(2595), uint32_t(2582), uint32_t(2570), uint32_t(2557), uint32_t(2545), uint32_t(2532), uint32_t(2520), + uint32_t(2508), uint32_t(2496), uint32_t(2484), uint32_t(2473), uint32_t(2461), uint32_t(2449), uint32_t(2438), uint32_t(2427), + uint32_t(2416), uint32_t(2404), uint32_t(2394), uint32_t(2383), uint32_t(2372), uint32_t(2361), uint32_t(2351), uint32_t(2340), + uint32_t(2330), uint32_t(2319), uint32_t(2309), uint32_t(2299), uint32_t(2289), uint32_t(2279), uint32_t(2269), uint32_t(2259), + uint32_t(2250), uint32_t(2240), uint32_t(2231), uint32_t(2221), uint32_t(2212), uint32_t(2202), uint32_t(2193), uint32_t(2184), + uint32_t(2175), uint32_t(2166), uint32_t(2157), uint32_t(2148), uint32_t(2139), uint32_t(2131), uint32_t(2122), uint32_t(2114), + uint32_t(2105), uint32_t(2097), uint32_t(2088), uint32_t(2080), uint32_t(2072), uint32_t(2064), uint32_t(2056), uint32_t(2048), + uint32_t(2040), uint32_t(2032), uint32_t(2024), uint32_t(2016), uint32_t(2008), uint32_t(2001), uint32_t(1993), uint32_t(1985), + uint32_t(1978), uint32_t(1971), uint32_t(1963), uint32_t(1956), uint32_t(1949), uint32_t(1941), uint32_t(1934), uint32_t(1927), + uint32_t(1920), uint32_t(1913), uint32_t(1906), uint32_t(1899), uint32_t(1892), uint32_t(1885), uint32_t(1879), uint32_t(1872), + uint32_t(1865), uint32_t(1859), uint32_t(1852), uint32_t(1846), uint32_t(1839), uint32_t(1833), uint32_t(1826), uint32_t(1820), + uint32_t(1814), uint32_t(1807), uint32_t(1801), uint32_t(1795), uint32_t(1789), uint32_t(1783), uint32_t(1777), uint32_t(1771), + uint32_t(1765), uint32_t(1759), uint32_t(1753), uint32_t(1747), uint32_t(1741), uint32_t(1736), uint32_t(1730), uint32_t(1724), + uint32_t(1718), uint32_t(1713), uint32_t(1707), uint32_t(1702), uint32_t(1696), uint32_t(1691), uint32_t(1685), uint32_t(1680), + uint32_t(1675), uint32_t(1669), uint32_t(1664), uint32_t(1659), uint32_t(1653), uint32_t(1648), uint32_t(1643), uint32_t(1638), + uint32_t(1633), uint32_t(1628), uint32_t(1623), uint32_t(1618), uint32_t(1613), uint32_t(1608), uint32_t(1603), uint32_t(1598), + uint32_t(1593), uint32_t(1588), uint32_t(1583), uint32_t(1579), uint32_t(1574), uint32_t(1569), uint32_t(1565), uint32_t(1560), + uint32_t(1555), uint32_t(1551), uint32_t(1546), uint32_t(1542), uint32_t(1537), uint32_t(1533), uint32_t(1528), uint32_t(1524), + uint32_t(1519), uint32_t(1515), uint32_t(1510), uint32_t(1506), uint32_t(1502), uint32_t(1497), uint32_t(1493), uint32_t(1489), + uint32_t(1485), uint32_t(1481), uint32_t(1476), uint32_t(1472), uint32_t(1468), uint32_t(1464), uint32_t(1460), uint32_t(1456), + uint32_t(1452), uint32_t(1448), uint32_t(1444), uint32_t(1440), uint32_t(1436), uint32_t(1432), uint32_t(1428), uint32_t(1424), + uint32_t(1420), uint32_t(1416), uint32_t(1413), uint32_t(1409), uint32_t(1405), uint32_t(1401), uint32_t(1398), uint32_t(1394), + uint32_t(1390), uint32_t(1387), uint32_t(1383), uint32_t(1379), uint32_t(1376), uint32_t(1372), uint32_t(1368), uint32_t(1365), + uint32_t(1361), uint32_t(1358), uint32_t(1354), uint32_t(1351), uint32_t(1347), uint32_t(1344), uint32_t(1340), uint32_t(1337), + uint32_t(1334), uint32_t(1330), uint32_t(1327), uint32_t(1323), uint32_t(1320), uint32_t(1317), uint32_t(1314), uint32_t(1310), + uint32_t(1307), uint32_t(1304), uint32_t(1300), uint32_t(1297), uint32_t(1294), uint32_t(1291), uint32_t(1288), uint32_t(1285), + uint32_t(1281), uint32_t(1278), uint32_t(1275), uint32_t(1272), uint32_t(1269), uint32_t(1266), uint32_t(1263), uint32_t(1260), + uint32_t(1257), uint32_t(1254), uint32_t(1251), uint32_t(1248), uint32_t(1245), uint32_t(1242), uint32_t(1239), uint32_t(1236), + uint32_t(1233), uint32_t(1230), uint32_t(1227), uint32_t(1224), uint32_t(1222), uint32_t(1219), uint32_t(1216), uint32_t(1213), + uint32_t(1210), uint32_t(1208), uint32_t(1205), uint32_t(1202), uint32_t(1199), uint32_t(1197), uint32_t(1194), uint32_t(1191), + uint32_t(1188), uint32_t(1186), uint32_t(1183), uint32_t(1180), uint32_t(1178), uint32_t(1175), uint32_t(1172), uint32_t(1170), + uint32_t(1167), uint32_t(1165), uint32_t(1162), uint32_t(1159), uint32_t(1157), uint32_t(1154), uint32_t(1152), uint32_t(1149), + uint32_t(1147), uint32_t(1144), uint32_t(1142), uint32_t(1139), uint32_t(1137), uint32_t(1134), uint32_t(1132), uint32_t(1129), + uint32_t(1127), uint32_t(1125), uint32_t(1122), uint32_t(1120), uint32_t(1117), uint32_t(1115), uint32_t(1113), uint32_t(1110), + uint32_t(1108), uint32_t(1106), uint32_t(1103), uint32_t(1101), uint32_t(1099), uint32_t(1096), uint32_t(1094), uint32_t(1092), + uint32_t(1089), uint32_t(1087), uint32_t(1085), uint32_t(1083), uint32_t(1081), uint32_t(1078), uint32_t(1076), uint32_t(1074), + uint32_t(1072), uint32_t(1069), uint32_t(1067), uint32_t(1065), uint32_t(1063), uint32_t(1061), uint32_t(1059), uint32_t(1057), + uint32_t(1054), uint32_t(1052), uint32_t(1050), uint32_t(1048), uint32_t(1046), uint32_t(1044), uint32_t(1042), uint32_t(1040), + uint32_t(1038), uint32_t(1036), uint32_t(1034), uint32_t(1032), uint32_t(1030), uint32_t(1028), uint32_t(1026), uint32_t(1024), + uint32_t(1022), uint32_t(1020), uint32_t(1018), uint32_t(1016), uint32_t(1014), uint32_t(1012), uint32_t(1010), uint32_t(1008), + uint32_t(1006), uint32_t(1004), uint32_t(1002), uint32_t(1000), uint32_t(998), uint32_t(996), uint32_t(994), uint32_t(992), + uint32_t(991), uint32_t(989), uint32_t(987), uint32_t(985), uint32_t(983), uint32_t(981), uint32_t(979), uint32_t(978), + uint32_t(976), uint32_t(974), uint32_t(972), uint32_t(970), uint32_t(969), uint32_t(967), uint32_t(965), uint32_t(963), + uint32_t(961), uint32_t(960), uint32_t(958), uint32_t(956), uint32_t(954), uint32_t(953), uint32_t(951), uint32_t(949), + uint32_t(948), uint32_t(946), uint32_t(944), uint32_t(942), uint32_t(941), uint32_t(939), uint32_t(937), uint32_t(936), + uint32_t(934), uint32_t(932), uint32_t(931), uint32_t(929), uint32_t(927), uint32_t(926), uint32_t(924), uint32_t(923), + uint32_t(921), uint32_t(919), uint32_t(918), uint32_t(916), uint32_t(914), uint32_t(913), uint32_t(911), uint32_t(910), + uint32_t(908), uint32_t(907), uint32_t(905), uint32_t(903), uint32_t(902), uint32_t(900), uint32_t(899), uint32_t(897), + uint32_t(896), uint32_t(894), uint32_t(893), uint32_t(891), uint32_t(890), uint32_t(888), uint32_t(887), uint32_t(885), + uint32_t(884), uint32_t(882), uint32_t(881), uint32_t(879), uint32_t(878), uint32_t(876), uint32_t(875), uint32_t(873), + uint32_t(872), uint32_t(870), uint32_t(869), uint32_t(868), uint32_t(866), uint32_t(865), uint32_t(863), uint32_t(862), + uint32_t(860), uint32_t(859), uint32_t(858), uint32_t(856), uint32_t(855), uint32_t(853), uint32_t(852), uint32_t(851), + uint32_t(849), uint32_t(848), uint32_t(846), uint32_t(845), uint32_t(844), uint32_t(842), uint32_t(841), uint32_t(840), + uint32_t(838), uint32_t(837), uint32_t(836), uint32_t(834), uint32_t(833), uint32_t(832), uint32_t(830), uint32_t(829), + uint32_t(828), uint32_t(826), uint32_t(825), uint32_t(824), uint32_t(823), uint32_t(821), uint32_t(820), uint32_t(819), + uint32_t(817), uint32_t(816), uint32_t(815), uint32_t(814), uint32_t(812), uint32_t(811), uint32_t(810), uint32_t(809), + uint32_t(807), uint32_t(806), uint32_t(805), uint32_t(804), uint32_t(802), uint32_t(801), uint32_t(800), uint32_t(799), + uint32_t(798), uint32_t(796), uint32_t(795), uint32_t(794), uint32_t(793), uint32_t(791), uint32_t(790), uint32_t(789), + uint32_t(788), uint32_t(787), uint32_t(786), uint32_t(784), uint32_t(783), uint32_t(782), uint32_t(781), uint32_t(780), + uint32_t(779), uint32_t(777), uint32_t(776), uint32_t(775), uint32_t(774), uint32_t(773), uint32_t(772), uint32_t(771), + uint32_t(769), uint32_t(768), uint32_t(767), uint32_t(766), uint32_t(765), uint32_t(764), uint32_t(763), uint32_t(762), + uint32_t(760), uint32_t(759), uint32_t(758), uint32_t(757), uint32_t(756), uint32_t(755), uint32_t(754), uint32_t(753), + uint32_t(752), uint32_t(751), uint32_t(750), uint32_t(748), uint32_t(747), uint32_t(746), uint32_t(745), uint32_t(744), + uint32_t(743), uint32_t(742), uint32_t(741), uint32_t(740), uint32_t(739), uint32_t(738), uint32_t(737), uint32_t(736), + uint32_t(735), uint32_t(734), uint32_t(733), uint32_t(732), uint32_t(731), uint32_t(730), uint32_t(729), uint32_t(728), + uint32_t(727), uint32_t(726), uint32_t(725), uint32_t(724), uint32_t(723), uint32_t(722), uint32_t(721), uint32_t(720), + uint32_t(719), uint32_t(718), uint32_t(717), uint32_t(716), uint32_t(715), uint32_t(714), uint32_t(713), uint32_t(712), + uint32_t(711), uint32_t(710), uint32_t(709), uint32_t(708), uint32_t(707), uint32_t(706), uint32_t(705), uint32_t(704), + uint32_t(703), uint32_t(702), uint32_t(701), uint32_t(700), uint32_t(699), uint32_t(699), uint32_t(698), uint32_t(697), + uint32_t(696), uint32_t(695), uint32_t(694), uint32_t(693), uint32_t(692), uint32_t(691), uint32_t(690), uint32_t(689), + uint32_t(688), uint32_t(688), uint32_t(687), uint32_t(686), uint32_t(685), uint32_t(684), uint32_t(683), uint32_t(682), + uint32_t(681), uint32_t(680), uint32_t(680), uint32_t(679), uint32_t(678), uint32_t(677), uint32_t(676), uint32_t(675), + uint32_t(674), uint32_t(673), uint32_t(673), uint32_t(672), uint32_t(671), uint32_t(670), uint32_t(669), uint32_t(668), + uint32_t(667), uint32_t(667), uint32_t(666), uint32_t(665), uint32_t(664), uint32_t(663), uint32_t(662), uint32_t(661), + uint32_t(661), uint32_t(660), uint32_t(659), uint32_t(658), uint32_t(657), uint32_t(657), uint32_t(656), uint32_t(655), + uint32_t(654), uint32_t(653), uint32_t(652), uint32_t(652), uint32_t(651), uint32_t(650), uint32_t(649), uint32_t(648), + uint32_t(648), uint32_t(647), uint32_t(646), uint32_t(645), uint32_t(644), uint32_t(644), uint32_t(643), uint32_t(642), + uint32_t(641), uint32_t(640), uint32_t(640), uint32_t(639), uint32_t(638), uint32_t(637), uint32_t(637), uint32_t(636), + uint32_t(635), uint32_t(634), uint32_t(633), uint32_t(633), uint32_t(632), uint32_t(631), uint32_t(630), uint32_t(630), + uint32_t(629), uint32_t(628), uint32_t(627), uint32_t(627), uint32_t(626), uint32_t(625), uint32_t(624), uint32_t(624), + uint32_t(623), uint32_t(622), uint32_t(621), uint32_t(621), uint32_t(620), uint32_t(619), uint32_t(618), uint32_t(618), + uint32_t(617), uint32_t(616), uint32_t(616), uint32_t(615), uint32_t(614), uint32_t(613), uint32_t(613), uint32_t(612), + uint32_t(611), uint32_t(611), uint32_t(610), uint32_t(609), uint32_t(608), uint32_t(608), uint32_t(607), uint32_t(606), + uint32_t(606), uint32_t(605), uint32_t(604), uint32_t(604), uint32_t(603), uint32_t(602), uint32_t(601), uint32_t(601), + uint32_t(600), uint32_t(599), uint32_t(599), uint32_t(598), uint32_t(597), uint32_t(597), uint32_t(596), uint32_t(595), + uint32_t(595), uint32_t(594), uint32_t(593), uint32_t(593), uint32_t(592), uint32_t(591), uint32_t(591), uint32_t(590), + uint32_t(589), uint32_t(589), uint32_t(588), uint32_t(587), uint32_t(587), uint32_t(586), uint32_t(585), uint32_t(585), + uint32_t(584), uint32_t(583), uint32_t(583), uint32_t(582), uint32_t(581), uint32_t(581), uint32_t(580), uint32_t(579), + uint32_t(579), uint32_t(578), uint32_t(578), uint32_t(577), uint32_t(576), uint32_t(576), uint32_t(575), uint32_t(574), + uint32_t(574), uint32_t(573), uint32_t(572), uint32_t(572), uint32_t(571), uint32_t(571), uint32_t(570), uint32_t(569), + uint32_t(569), uint32_t(568), uint32_t(568), uint32_t(567), uint32_t(566), uint32_t(566), uint32_t(565), uint32_t(564), + uint32_t(564), uint32_t(563), uint32_t(563), uint32_t(562), uint32_t(561), uint32_t(561), uint32_t(560), uint32_t(560), + uint32_t(559), uint32_t(558), uint32_t(558), uint32_t(557), uint32_t(557), uint32_t(556), uint32_t(555), uint32_t(555), + uint32_t(554), uint32_t(554), uint32_t(553), uint32_t(553), uint32_t(552), uint32_t(551), uint32_t(551), uint32_t(550), + uint32_t(550), uint32_t(549), uint32_t(548), uint32_t(548), uint32_t(547), uint32_t(547), uint32_t(546), uint32_t(546), + uint32_t(545), uint32_t(544), uint32_t(544), uint32_t(543), uint32_t(543), uint32_t(542), uint32_t(542), uint32_t(541), + uint32_t(541), uint32_t(540), uint32_t(539), uint32_t(539), uint32_t(538), uint32_t(538), uint32_t(537), uint32_t(537), + uint32_t(536), uint32_t(536), uint32_t(535), uint32_t(534), uint32_t(534), uint32_t(533), uint32_t(533), uint32_t(532), + uint32_t(532), uint32_t(531), uint32_t(531), uint32_t(530), uint32_t(530), uint32_t(529), uint32_t(529), uint32_t(528), + uint32_t(527), uint32_t(527), uint32_t(526), uint32_t(526), uint32_t(525), uint32_t(525), uint32_t(524), uint32_t(524), + uint32_t(523), uint32_t(523), uint32_t(522), uint32_t(522), uint32_t(521), uint32_t(521), uint32_t(520), uint32_t(520), + uint32_t(519), uint32_t(519), uint32_t(518), uint32_t(518), uint32_t(517), uint32_t(517), uint32_t(516), uint32_t(516), + uint32_t(515), uint32_t(515), uint32_t(514), uint32_t(514), +} /* picture_csp_enc.c:596:23 */ + +// Note that LinearToGamma() expects the values to be premultiplied by 4, +// so we incorporate this factor 4 inside the DIVIDE_BY_ALPHA macro directly. + +func LinearToGammaWeighted(tls *libc.TLS, src uintptr, a_ptr uintptr, total_a uint32_t, step int32, rgb_stride int32) int32 { /* picture_csp_enc.c:738:24: */ + var sum uint32_t = ((((uint32_t(*(*uint8_t)(unsafe.Pointer(a_ptr))) * GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer(src)))) + (uint32_t(*(*uint8_t)(unsafe.Pointer(a_ptr + uintptr(step)))) * GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer(src + uintptr(step)))))) + (uint32_t(*(*uint8_t)(unsafe.Pointer(a_ptr + uintptr(rgb_stride)))) * GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer(src + uintptr(rgb_stride)))))) + (uint32_t(*(*uint8_t)(unsafe.Pointer(a_ptr + uintptr((rgb_stride + step))))) * GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer(src + uintptr((rgb_stride + step))))))) + + return LinearToGamma(tls, (((sum) * kInvAlpha[(total_a)]) >> (kAlphaFix - 2)), 0) +} + +func ConvertRowToY(tls *libc.TLS, r_ptr uintptr, g_ptr uintptr, b_ptr uintptr, step int32, dst_y uintptr, width int32, rg uintptr) { /* picture_csp_enc.c:754:25: */ + var i int32 + var j int32 + i = 0 + j = 0 +__1: + if !(i < width) { + goto __3 + } + { + *(*uint8_t)(unsafe.Pointer(dst_y + uintptr(i))) = uint8_t(RGBToY(tls, int32(*(*uint8_t)(unsafe.Pointer(r_ptr + uintptr(j)))), int32(*(*uint8_t)(unsafe.Pointer(g_ptr + uintptr(j)))), int32(*(*uint8_t)(unsafe.Pointer(b_ptr + uintptr(j)))), rg)) + + } + goto __2 +__2: + i = i + (1) + j = j + (step) + goto __1 + goto __3 +__3: +} + +func AccumulateRGBA(tls *libc.TLS, r_ptr uintptr, g_ptr uintptr, b_ptr uintptr, a_ptr uintptr, rgb_stride int32, dst uintptr, width int32) { /* picture_csp_enc.c:767:25: */ + var i int32 + var j int32 + // we loop over 2x2 blocks and produce one R/G/B/A value for each. + i = 0 + j = 0 +__1: + if !(i < (width >> 1)) { + goto __3 + } + { + var a uint32_t = (uint32_t((int32(*(*uint8_t)(unsafe.Pointer((a_ptr + uintptr(j))))) + int32(*(*uint8_t)(unsafe.Pointer((a_ptr + uintptr(j)) + uintptr(rgb_stride))))) + (int32(*(*uint8_t)(unsafe.Pointer(((a_ptr + uintptr(j)) + uintptr(4))))) + int32(*(*uint8_t)(unsafe.Pointer(((a_ptr + uintptr(j)) + uintptr(4)) + uintptr(rgb_stride))))))) + var r int32 + var g int32 + var b int32 + if (a == (uint32_t(4 * 0xff))) || (a == uint32_t(0)) { + r = LinearToGamma(tls, (((GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((r_ptr + uintptr(j))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((r_ptr + uintptr(j)) + 4)))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((r_ptr + uintptr(j)) + uintptr(rgb_stride))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((r_ptr + uintptr(j)) + uintptr((rgb_stride + (4))))))), 0) + g = LinearToGamma(tls, (((GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((g_ptr + uintptr(j))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((g_ptr + uintptr(j)) + 4)))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((g_ptr + uintptr(j)) + uintptr(rgb_stride))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((g_ptr + uintptr(j)) + uintptr((rgb_stride + (4))))))), 0) + b = LinearToGamma(tls, (((GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((b_ptr + uintptr(j))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((b_ptr + uintptr(j)) + 4)))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((b_ptr + uintptr(j)) + uintptr(rgb_stride))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((b_ptr + uintptr(j)) + uintptr((rgb_stride + (4))))))), 0) + } else { + r = LinearToGammaWeighted(tls, (r_ptr + uintptr(j)), (a_ptr + uintptr(j)), a, 4, rgb_stride) + g = LinearToGammaWeighted(tls, (g_ptr + uintptr(j)), (a_ptr + uintptr(j)), a, 4, rgb_stride) + b = LinearToGammaWeighted(tls, (b_ptr + uintptr(j)), (a_ptr + uintptr(j)), a, 4, rgb_stride) + } + *(*uint16_t)(unsafe.Pointer(dst)) = uint16_t(r) + *(*uint16_t)(unsafe.Pointer(dst + 1*2)) = uint16_t(g) + *(*uint16_t)(unsafe.Pointer(dst + 2*2)) = uint16_t(b) + *(*uint16_t)(unsafe.Pointer(dst + 3*2)) = uint16_t(a) + + } + goto __2 +__2: + i = i + (1) + j = j + (2 * 4) + dst += 2 * (uintptr(4)) + goto __1 + goto __3 +__3: + ; + if (width & 1) != 0 { + var a uint32_t = (2 * (uint32(int32(*(*uint8_t)(unsafe.Pointer((a_ptr + uintptr(j))))) + int32(*(*uint8_t)(unsafe.Pointer((a_ptr + uintptr(j)) + uintptr(rgb_stride))))))) + var r int32 + var g int32 + var b int32 + if (a == (uint32_t(4 * 0xff))) || (a == uint32_t(0)) { + r = LinearToGamma(tls, (GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((r_ptr + uintptr(j))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((r_ptr + uintptr(j)) + uintptr(rgb_stride))))), 1) + g = LinearToGamma(tls, (GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((g_ptr + uintptr(j))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((g_ptr + uintptr(j)) + uintptr(rgb_stride))))), 1) + b = LinearToGamma(tls, (GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((b_ptr + uintptr(j))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((b_ptr + uintptr(j)) + uintptr(rgb_stride))))), 1) + } else { + r = LinearToGammaWeighted(tls, (r_ptr + uintptr(j)), (a_ptr + uintptr(j)), a, 0, rgb_stride) + g = LinearToGammaWeighted(tls, (g_ptr + uintptr(j)), (a_ptr + uintptr(j)), a, 0, rgb_stride) + b = LinearToGammaWeighted(tls, (b_ptr + uintptr(j)), (a_ptr + uintptr(j)), a, 0, rgb_stride) + } + *(*uint16_t)(unsafe.Pointer(dst)) = uint16_t(r) + *(*uint16_t)(unsafe.Pointer(dst + 1*2)) = uint16_t(g) + *(*uint16_t)(unsafe.Pointer(dst + 2*2)) = uint16_t(b) + *(*uint16_t)(unsafe.Pointer(dst + 3*2)) = uint16_t(a) + } +} + +func AccumulateRGB(tls *libc.TLS, r_ptr uintptr, g_ptr uintptr, b_ptr uintptr, step int32, rgb_stride int32, dst uintptr, width int32) { /* picture_csp_enc.c:811:25: */ + var i int32 + var j int32 + i = 0 + j = 0 +__1: + if !(i < (width >> 1)) { + goto __3 + } + { + *(*uint16_t)(unsafe.Pointer(dst)) = uint16_t(LinearToGamma(tls, (((GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((r_ptr + uintptr(j))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((r_ptr + uintptr(j)) + uintptr((step)))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((r_ptr + uintptr(j)) + uintptr(rgb_stride))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((r_ptr + uintptr(j)) + uintptr((rgb_stride + (step))))))), 0)) + *(*uint16_t)(unsafe.Pointer(dst + 1*2)) = uint16_t(LinearToGamma(tls, (((GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((g_ptr + uintptr(j))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((g_ptr + uintptr(j)) + uintptr((step)))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((g_ptr + uintptr(j)) + uintptr(rgb_stride))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((g_ptr + uintptr(j)) + uintptr((rgb_stride + (step))))))), 0)) + *(*uint16_t)(unsafe.Pointer(dst + 2*2)) = uint16_t(LinearToGamma(tls, (((GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((b_ptr + uintptr(j))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((b_ptr + uintptr(j)) + uintptr((step)))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((b_ptr + uintptr(j)) + uintptr(rgb_stride))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((b_ptr + uintptr(j)) + uintptr((rgb_stride + (step))))))), 0)) + + } + goto __2 +__2: + i = i + (1) + j = j + (2 * step) + dst += 2 * (uintptr(4)) + goto __1 + goto __3 +__3: + ; + if (width & 1) != 0 { + *(*uint16_t)(unsafe.Pointer(dst)) = uint16_t(LinearToGamma(tls, (GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((r_ptr + uintptr(j))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((r_ptr + uintptr(j)) + uintptr(rgb_stride))))), 1)) + *(*uint16_t)(unsafe.Pointer(dst + 1*2)) = uint16_t(LinearToGamma(tls, (GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((g_ptr + uintptr(j))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((g_ptr + uintptr(j)) + uintptr(rgb_stride))))), 1)) + *(*uint16_t)(unsafe.Pointer(dst + 2*2)) = uint16_t(LinearToGamma(tls, (GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((b_ptr + uintptr(j))))) + GammaToLinear(tls, *(*uint8_t)(unsafe.Pointer((b_ptr + uintptr(j)) + uintptr(rgb_stride))))), 1)) + } +} + +func ConvertRowsToUV(tls *libc.TLS, rgb uintptr, dst_u uintptr, dst_v uintptr, width int32, rg uintptr) { /* picture_csp_enc.c:829:25: */ + var i int32 + i = 0 +__1: + if !(i < width) { + goto __3 + } + { + var r int32 = int32(*(*uint16_t)(unsafe.Pointer(rgb))) + var g int32 = int32(*(*uint16_t)(unsafe.Pointer(rgb + 1*2))) + var b int32 = int32(*(*uint16_t)(unsafe.Pointer(rgb + 2*2))) + *(*uint8_t)(unsafe.Pointer(dst_u + uintptr(i))) = uint8_t(RGBToU(tls, r, g, b, rg)) + *(*uint8_t)(unsafe.Pointer(dst_v + uintptr(i))) = uint8_t(RGBToV(tls, r, g, b, rg)) + + } + goto __2 +__2: + i = i + (1) + rgb += 2 * (uintptr(4)) + goto __1 + goto __3 +__3: +} + +func ImportYUVAFromRGBA(tls *libc.TLS, r_ptr uintptr, g_ptr uintptr, b_ptr uintptr, a_ptr uintptr, step int32, rgb_stride int32, dithering float32, use_iterative_conversion int32, picture uintptr) int32 { /* picture_csp_enc.c:842:12: */ + bp := tls.Alloc(232) + defer tls.Free(232) + + var y int32 + var width int32 = (*WebPPicture)(unsafe.Pointer(picture)).width + var height int32 = (*WebPPicture)(unsafe.Pointer(picture)).height + var has_alpha int32 = CheckNonOpaque(tls, a_ptr, width, height, step, rgb_stride) + var is_rgb int32 = (libc.Bool32(r_ptr < b_ptr)) // otherwise it's bgr + + (*WebPPicture)(unsafe.Pointer(picture)).colorspace = func() uint32 { + if has_alpha != 0 { + return WEBP_YUV420A + } + return WEBP_YUV420 + }() + (*WebPPicture)(unsafe.Pointer(picture)).use_argb = 0 + + // disable smart conversion if source is too small (overkill). + if (width < kMinDimensionIterativeConversion) || (height < kMinDimensionIterativeConversion) { + use_iterative_conversion = 0 + } + + if !(WebPPictureAllocYUVA(tls, picture, width, height) != 0) { + return 0 + } + if has_alpha != 0 { + + } + + if use_iterative_conversion != 0 { + InitGammaTablesS(tls) + if !(PreprocessARGB(tls, r_ptr, g_ptr, b_ptr, step, rgb_stride, picture) != 0) { + return 0 + } + if has_alpha != 0 { + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, uintptr, int32) int32 + })(unsafe.Pointer(&struct{ uintptr }{WebPExtractAlpha})).f(tls, a_ptr, rgb_stride, width, height, + (*WebPPicture)(unsafe.Pointer(picture)).a, (*WebPPicture)(unsafe.Pointer(picture)).a_stride) + } + } else { + var uv_width int32 = ((width + 1) >> 1) + var use_dsp int32 = (libc.Bool32(step == 3)) // use special function in this case + // temporary storage for accumulated R/G/B values during conversion to U/V + var tmp_rgb uintptr = WebPSafeMalloc(tls, (uint64(4 * uv_width)), uint64(unsafe.Sizeof(uint16_t(0)))) + var dst_y uintptr = (*WebPPicture)(unsafe.Pointer(picture)).y + var dst_u uintptr = (*WebPPicture)(unsafe.Pointer(picture)).u + var dst_v uintptr = (*WebPPicture)(unsafe.Pointer(picture)).v + var dst_a uintptr = (*WebPPicture)(unsafe.Pointer(picture)).a + // var base_rg VP8Random at bp, 232 + + var rg uintptr = (uintptr(0)) + if float64(dithering) > 0. { + VP8InitRandom(tls, (bp) /* &base_rg */, dithering) + rg = (bp) /* &base_rg */ + use_dsp = 0 // can't use dsp in this case + } + WebPInitConvertARGBToYUV(tls) + InitGammaTables(tls) + + if tmp_rgb == (uintptr(0)) { + return 0 + } // malloc error + + // Downsample Y/U/V planes, two rows at a time + for y = 0; y < (height >> 1); y++ { + var rows_have_alpha int32 = has_alpha + if use_dsp != 0 { + if is_rgb != 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPConvertRGB24ToY})).f(tls, r_ptr, dst_y, width) + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPConvertRGB24ToY})).f(tls, (r_ptr + uintptr(rgb_stride)), + (dst_y + uintptr((*WebPPicture)(unsafe.Pointer(picture)).y_stride)), width) + } else { + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPConvertBGR24ToY})).f(tls, b_ptr, dst_y, width) + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPConvertBGR24ToY})).f(tls, (b_ptr + uintptr(rgb_stride)), + (dst_y + uintptr((*WebPPicture)(unsafe.Pointer(picture)).y_stride)), width) + } + } else { + ConvertRowToY(tls, r_ptr, g_ptr, b_ptr, step, dst_y, width, rg) + ConvertRowToY(tls, (r_ptr + uintptr(rgb_stride)), + (g_ptr + uintptr(rgb_stride)), + (b_ptr + uintptr(rgb_stride)), step, + (dst_y + uintptr((*WebPPicture)(unsafe.Pointer(picture)).y_stride)), width, rg) + } + dst_y += (uintptr(2 * (*WebPPicture)(unsafe.Pointer(picture)).y_stride)) + if has_alpha != 0 { + rows_have_alpha = rows_have_alpha & (libc.BoolInt32(!((*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, uintptr, int32) int32 + })(unsafe.Pointer(&struct{ uintptr }{WebPExtractAlpha})).f(tls, a_ptr, rgb_stride, width, 2, + dst_a, (*WebPPicture)(unsafe.Pointer(picture)).a_stride) != 0))) + dst_a += (uintptr(2 * (*WebPPicture)(unsafe.Pointer(picture)).a_stride)) + } + // Collect averaged R/G/B(/A) + if !(rows_have_alpha != 0) { + AccumulateRGB(tls, r_ptr, g_ptr, b_ptr, step, rgb_stride, tmp_rgb, width) + } else { + AccumulateRGBA(tls, r_ptr, g_ptr, b_ptr, a_ptr, rgb_stride, tmp_rgb, width) + } + // Convert to U/V + if rg == (uintptr(0)) { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPConvertRGBA32ToUV})).f(tls, tmp_rgb, dst_u, dst_v, uv_width) + } else { + ConvertRowsToUV(tls, tmp_rgb, dst_u, dst_v, uv_width, rg) + } + dst_u += uintptr((*WebPPicture)(unsafe.Pointer(picture)).uv_stride) + dst_v += uintptr((*WebPPicture)(unsafe.Pointer(picture)).uv_stride) + r_ptr += (uintptr(2 * rgb_stride)) + b_ptr += (uintptr(2 * rgb_stride)) + g_ptr += (uintptr(2 * rgb_stride)) + if has_alpha != 0 { + a_ptr += (uintptr(2 * rgb_stride)) + } + } + if (height & 1) != 0 { // extra last row + var row_has_alpha int32 = has_alpha + if use_dsp != 0 { + if r_ptr < b_ptr { + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPConvertRGB24ToY})).f(tls, r_ptr, dst_y, width) + } else { + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPConvertBGR24ToY})).f(tls, b_ptr, dst_y, width) + } + } else { + ConvertRowToY(tls, r_ptr, g_ptr, b_ptr, step, dst_y, width, rg) + } + if row_has_alpha != 0 { + row_has_alpha = row_has_alpha & (libc.BoolInt32(!((*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, uintptr, int32) int32 + })(unsafe.Pointer(&struct{ uintptr }{WebPExtractAlpha})).f(tls, a_ptr, 0, width, 1, dst_a, 0) != 0))) + } + // Collect averaged R/G/B(/A) + if !(row_has_alpha != 0) { + // Collect averaged R/G/B + AccumulateRGB(tls, r_ptr, g_ptr, b_ptr, step /* rgb_stride = */, 0, + tmp_rgb, width) + } else { + AccumulateRGBA(tls, r_ptr, g_ptr, b_ptr, a_ptr /* rgb_stride = */, 0, + tmp_rgb, width) + } + if rg == (uintptr(0)) { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{WebPConvertRGBA32ToUV})).f(tls, tmp_rgb, dst_u, dst_v, uv_width) + } else { + ConvertRowsToUV(tls, tmp_rgb, dst_u, dst_v, uv_width, rg) + } + } + WebPSafeFree(tls, tmp_rgb) + } + return 1 +} + +//------------------------------------------------------------------------------ +// call for ARGB->YUVA conversion + +func PictureARGBToYUVA(tls *libc.TLS, picture uintptr, colorspace WebPEncCSP, dithering float32, use_iterative_conversion int32) int32 { /* picture_csp_enc.c:995:12: */ + if picture == (uintptr(0)) { + return 0 + } + if (*WebPPicture)(unsafe.Pointer(picture)).argb == (uintptr(0)) { + return WebPEncodingSetError(tls, picture, VP8_ENC_ERROR_NULL_PARAMETER) + } else if (colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420 { + return WebPEncodingSetError(tls, picture, VP8_ENC_ERROR_INVALID_CONFIGURATION) + } else { + var argb uintptr = (*WebPPicture)(unsafe.Pointer(picture)).argb + var a uintptr = (argb + uintptr((3 - (0)))) + var r uintptr = (argb + uintptr((3 - (1)))) + var g uintptr = (argb + uintptr((3 - (2)))) + var b uintptr = (argb + uintptr((3 - (3)))) + + (*WebPPicture)(unsafe.Pointer(picture)).colorspace = WEBP_YUV420 + return ImportYUVAFromRGBA(tls, r, g, b, a, 4, (4 * (*WebPPicture)(unsafe.Pointer(picture)).argb_stride), + dithering, use_iterative_conversion, picture) + } + return int32(0) +} + +func WebPPictureARGBToYUVADithered(tls *libc.TLS, picture uintptr, colorspace WebPEncCSP, dithering float32) int32 { /* picture_csp_enc.c:1015:5: */ + return PictureARGBToYUVA(tls, picture, colorspace, dithering, 0) +} + +func WebPPictureARGBToYUVA(tls *libc.TLS, picture uintptr, colorspace WebPEncCSP) int32 { /* picture_csp_enc.c:1020:5: */ + return PictureARGBToYUVA(tls, picture, colorspace, 0., 0) +} + +func WebPPictureSharpARGBToYUVA(tls *libc.TLS, picture uintptr) int32 { /* picture_csp_enc.c:1024:5: */ + return PictureARGBToYUVA(tls, picture, WEBP_YUV420, 0., 1) +} + +// for backward compatibility +func WebPPictureSmartARGBToYUVA(tls *libc.TLS, picture uintptr) int32 { /* picture_csp_enc.c:1028:5: */ + return WebPPictureSharpARGBToYUVA(tls, picture) +} + +//------------------------------------------------------------------------------ +// call for YUVA -> ARGB conversion + +func WebPPictureYUVAToARGB(tls *libc.TLS, picture uintptr) int32 { /* picture_csp_enc.c:1035:5: */ + if picture == (uintptr(0)) { + return 0 + } + if (((*WebPPicture)(unsafe.Pointer(picture)).y == (uintptr(0))) || ((*WebPPicture)(unsafe.Pointer(picture)).u == (uintptr(0)))) || ((*WebPPicture)(unsafe.Pointer(picture)).v == (uintptr(0))) { + return WebPEncodingSetError(tls, picture, VP8_ENC_ERROR_NULL_PARAMETER) + } + if (((*WebPPicture)(unsafe.Pointer(picture)).colorspace & WEBP_CSP_ALPHA_BIT) != 0) && ((*WebPPicture)(unsafe.Pointer(picture)).a == (uintptr(0))) { + return WebPEncodingSetError(tls, picture, VP8_ENC_ERROR_NULL_PARAMETER) + } + if ((*WebPPicture)(unsafe.Pointer(picture)).colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420 { + return WebPEncodingSetError(tls, picture, VP8_ENC_ERROR_INVALID_CONFIGURATION) + } + // Allocate a new argb buffer (discarding the previous one). + if !(WebPPictureAllocARGB(tls, picture, (*WebPPicture)(unsafe.Pointer(picture)).width, (*WebPPicture)(unsafe.Pointer(picture)).height) != 0) { + return 0 + } + (*WebPPicture)(unsafe.Pointer(picture)).use_argb = 1 + + // Convert + { + var y int32 + var width int32 = (*WebPPicture)(unsafe.Pointer(picture)).width + var height int32 = (*WebPPicture)(unsafe.Pointer(picture)).height + var argb_stride int32 = (4 * (*WebPPicture)(unsafe.Pointer(picture)).argb_stride) + var dst uintptr = (*WebPPicture)(unsafe.Pointer(picture)).argb + var cur_u uintptr = (*WebPPicture)(unsafe.Pointer(picture)).u + var cur_v uintptr = (*WebPPicture)(unsafe.Pointer(picture)).v + var cur_y uintptr = (*WebPPicture)(unsafe.Pointer(picture)).y + var upsample WebPUpsampleLinePairFunc = WebPGetLinePairConverter(tls, (libc.Bool32((3 - (0)) > 0))) + + // First row, with replicated top samples. + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{upsample})).f(tls, cur_y, (uintptr(0)), cur_u, cur_v, cur_u, cur_v, dst, (uintptr(0)), width) + cur_y += uintptr((*WebPPicture)(unsafe.Pointer(picture)).y_stride) + dst += uintptr(argb_stride) + // Center rows. + for y = 1; (y + 1) < height; y = y + (2) { + var top_u uintptr = cur_u + var top_v uintptr = cur_v + cur_u += uintptr((*WebPPicture)(unsafe.Pointer(picture)).uv_stride) + cur_v += uintptr((*WebPPicture)(unsafe.Pointer(picture)).uv_stride) + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{upsample})).f(tls, cur_y, (cur_y + uintptr((*WebPPicture)(unsafe.Pointer(picture)).y_stride)), top_u, top_v, cur_u, cur_v, + dst, (dst + uintptr(argb_stride)), width) + cur_y += (uintptr(2 * (*WebPPicture)(unsafe.Pointer(picture)).y_stride)) + dst += (uintptr(2 * argb_stride)) + } + // Last row (if needed), with replicated bottom samples. + if (height > 1) && !((height & 1) != 0) { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{upsample})).f(tls, cur_y, (uintptr(0)), cur_u, cur_v, cur_u, cur_v, dst, (uintptr(0)), width) + } + // Insert alpha values if needed, in replacement for the default 0xff ones. + if ((*WebPPicture)(unsafe.Pointer(picture)).colorspace & WEBP_CSP_ALPHA_BIT) != 0 { + for y = 0; y < height; y++ { + var argb_dst uintptr = ((*WebPPicture)(unsafe.Pointer(picture)).argb + uintptr((y*(*WebPPicture)(unsafe.Pointer(picture)).argb_stride))*4) + var src uintptr = ((*WebPPicture)(unsafe.Pointer(picture)).a + uintptr((y * (*WebPPicture)(unsafe.Pointer(picture)).a_stride))) + var x int32 + for x = 0; x < width; x++ { + *(*uint32_t)(unsafe.Pointer(argb_dst + uintptr(x)*4)) = ((*(*uint32_t)(unsafe.Pointer(argb_dst + uintptr(x)*4)) & 0x00ffffff) | (uint32_t(*(*uint8_t)(unsafe.Pointer(src + uintptr(x)))) << 24)) + } + } + } + + } + return 1 +} + +//------------------------------------------------------------------------------ +// automatic import / conversion + +func Import(tls *libc.TLS, picture uintptr, rgb uintptr, rgb_stride int32, step int32, swap_rb int32, import_alpha int32) int32 { /* picture_csp_enc.c:1098:12: */ + var y int32 + // swap_rb -> b,g,r,a , !swap_rb -> r,g,b,a + var r_ptr uintptr = (rgb + uintptr((func() int32 { + if swap_rb != 0 { + return 2 + } + return 0 + }()))) + var g_ptr uintptr = (rgb + uintptr(1)) + var b_ptr uintptr = (rgb + uintptr((func() int32 { + if swap_rb != 0 { + return 0 + } + return 2 + }()))) + var width int32 = (*WebPPicture)(unsafe.Pointer(picture)).width + var height int32 = (*WebPPicture)(unsafe.Pointer(picture)).height + + if !((*WebPPicture)(unsafe.Pointer(picture)).use_argb != 0) { + var a_ptr uintptr + if import_alpha != 0 { + a_ptr = (rgb + uintptr(3)) + } else { + a_ptr = (uintptr(0)) + } + return ImportYUVAFromRGBA(tls, r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride, + 0., 0, picture) + } + if !(WebPPictureAlloc(tls, picture) != 0) { + return 0 + } + + VP8LDspInit(tls) + WebPInitAlphaProcessing(tls) + + if import_alpha != 0 { + // dst[] byte order is {a,r,g,b} for big-endian, {b,g,r,a} for little endian + var dst uintptr = (*WebPPicture)(unsafe.Pointer(picture)).argb + var do_copy int32 = (libc.Bool32(((3 - (0)) == 3) && (swap_rb != 0))) + + if do_copy != 0 { + for y = 0; y < height; y++ { + libc.Xmemcpy(tls, dst, rgb, (uint64(width * 4))) + rgb += uintptr(rgb_stride) + dst += 4 * (uintptr((*WebPPicture)(unsafe.Pointer(picture)).argb_stride)) + } + } else { + for y = 0; y < height; y++ { + // RGBA input order. Need to swap R and B. + (*struct { + f func(*libc.TLS, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LConvertBGRAToRGBA})).f(tls, rgb, width, dst) + rgb += uintptr(rgb_stride) + dst += 4 * (uintptr((*WebPPicture)(unsafe.Pointer(picture)).argb_stride)) + } + } + } else { + var dst uintptr = (*WebPPicture)(unsafe.Pointer(picture)).argb + + for y = 0; y < height; y++ { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{WebPPackRGB})).f(tls, r_ptr, g_ptr, b_ptr, width, step, dst) + r_ptr += uintptr(rgb_stride) + g_ptr += uintptr(rgb_stride) + b_ptr += uintptr(rgb_stride) + dst += 4 * (uintptr((*WebPPicture)(unsafe.Pointer(picture)).argb_stride)) + } + } + return 1 +} + +// Public API + +func WebPPictureImportBGR(tls *libc.TLS, picture uintptr, rgb uintptr, rgb_stride int32) int32 { /* picture_csp_enc.c:1165:5: */ + if (picture != (uintptr(0))) && (rgb != (uintptr(0))) { + return Import(tls, picture, rgb, rgb_stride, 3, 1, 0) + } + return 0 +} + +func WebPPictureImportBGRA(tls *libc.TLS, picture uintptr, rgba uintptr, rgba_stride int32) int32 { /* picture_csp_enc.c:1172:5: */ + if (picture != (uintptr(0))) && (rgba != (uintptr(0))) { + return Import(tls, picture, rgba, rgba_stride, 4, 1, 1) + } + return 0 +} + +func WebPPictureImportBGRX(tls *libc.TLS, picture uintptr, rgba uintptr, rgba_stride int32) int32 { /* picture_csp_enc.c:1180:5: */ + if (picture != (uintptr(0))) && (rgba != (uintptr(0))) { + return Import(tls, picture, rgba, rgba_stride, 4, 1, 0) + } + return 0 +} + +func WebPPictureImportRGB(tls *libc.TLS, picture uintptr, rgb uintptr, rgb_stride int32) int32 { /* picture_csp_enc.c:1189:5: */ + if (picture != (uintptr(0))) && (rgb != (uintptr(0))) { + return Import(tls, picture, rgb, rgb_stride, 3, 0, 0) + } + return 0 +} + +func WebPPictureImportRGBA(tls *libc.TLS, picture uintptr, rgba uintptr, rgba_stride int32) int32 { /* picture_csp_enc.c:1196:5: */ + if (picture != (uintptr(0))) && (rgba != (uintptr(0))) { + return Import(tls, picture, rgba, rgba_stride, 4, 0, 1) + } + return 0 +} + +func WebPPictureImportRGBX(tls *libc.TLS, picture uintptr, rgba uintptr, rgba_stride int32) int32 { /* picture_csp_enc.c:1203:5: */ + if (picture != (uintptr(0))) && (rgba != (uintptr(0))) { + return Import(tls, picture, rgba, rgba_stride, 4, 0, 0) + } + return 0 +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Speed-critical functions. +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +//------------------------------------------------------------------------------ +// WebPPicture +//------------------------------------------------------------------------------ + +func DummyWriter(tls *libc.TLS, data uintptr, data_size size_t, picture uintptr) int32 { /* picture_enc.c:25:12: */ + // The following are to prevent 'unused variable' error message. + _ = data + _ = data_size + _ = picture + return 1 +} + +func WebPPictureInitInternal(tls *libc.TLS, picture uintptr, version int32) int32 { /* picture_enc.c:34:5: */ + if ((version) >> 8) != (int32((0x020f)) >> 8) { + return 0 // caller/system version mismatch! + } + if picture != (uintptr(0)) { + libc.Xmemset(tls, picture, 0, uint64(unsafe.Sizeof(WebPPicture{}))) + (*WebPPicture)(unsafe.Pointer(picture)).writer = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, size_t, uintptr) int32 + }{DummyWriter})) + WebPEncodingSetError(tls, picture, VP8_ENC_OK) + } + return 1 +} + +//------------------------------------------------------------------------------ + +func WebPPictureResetBufferARGB(tls *libc.TLS, picture uintptr) { /* picture_enc.c:48:13: */ + (*WebPPicture)(unsafe.Pointer(picture)).memory_argb_ = (uintptr(0)) + (*WebPPicture)(unsafe.Pointer(picture)).argb = (uintptr(0)) + (*WebPPicture)(unsafe.Pointer(picture)).argb_stride = 0 +} + +func WebPPictureResetBufferYUVA(tls *libc.TLS, picture uintptr) { /* picture_enc.c:54:13: */ + (*WebPPicture)(unsafe.Pointer(picture)).memory_ = (uintptr(0)) + (*WebPPicture)(unsafe.Pointer(picture)).y = libc.AssignPtrUintptr((picture + 24 /* &.u */), libc.AssignPtrUintptr((picture+32 /* &.v */), libc.AssignPtrUintptr((picture+48 /* &.a */), (uintptr(0))))) + (*WebPPicture)(unsafe.Pointer(picture)).y_stride = libc.AssignPtrInt32((picture + 44 /* &.uv_stride */), 0) + (*WebPPicture)(unsafe.Pointer(picture)).a_stride = 0 +} + +func WebPPictureResetBuffers(tls *libc.TLS, picture uintptr) { /* picture_enc.c:61:6: */ + WebPPictureResetBufferARGB(tls, picture) + WebPPictureResetBufferYUVA(tls, picture) +} + +func WebPPictureAllocARGB(tls *libc.TLS, picture uintptr, width int32, height int32) int32 { /* picture_enc.c:66:5: */ + var memory uintptr + var argb_size uint64_t = (uint64_t(width) * uint64_t(height)) + + WebPSafeFree(tls, (*WebPPicture)(unsafe.Pointer(picture)).memory_argb_) + WebPPictureResetBufferARGB(tls, picture) + + if (width <= 0) || (height <= 0) { + return WebPEncodingSetError(tls, picture, VP8_ENC_ERROR_BAD_DIMENSION) + } + // allocate a new buffer. + memory = WebPSafeMalloc(tls, (argb_size + uint64(31)), uint64(unsafe.Sizeof(uint32_t(0)))) + if memory == (uintptr(0)) { + return WebPEncodingSetError(tls, picture, VP8_ENC_ERROR_OUT_OF_MEMORY) + } + (*WebPPicture)(unsafe.Pointer(picture)).memory_argb_ = memory + (*WebPPicture)(unsafe.Pointer(picture)).argb = (uintptr((uintptr_t((memory)) + uint64(31)) & libc.Uint64FromInt32(libc.CplInt32(31)))) + (*WebPPicture)(unsafe.Pointer(picture)).argb_stride = width + return 1 +} + +func WebPPictureAllocYUVA(tls *libc.TLS, picture uintptr, width int32, height int32) int32 { /* picture_enc.c:89:5: */ + var uv_csp WebPEncCSP = (WebPEncCSP(int32((*WebPPicture)(unsafe.Pointer(picture)).colorspace) & WEBP_CSP_UV_MASK)) + var has_alpha int32 = (int32((*WebPPicture)(unsafe.Pointer(picture)).colorspace) & WEBP_CSP_ALPHA_BIT) + var y_stride int32 = width + var uv_width int32 = (int32((int64_t(width) + int64(1)) >> 1)) + var uv_height int32 = (int32((int64_t(height) + int64(1)) >> 1)) + var uv_stride int32 = uv_width + var a_width int32 + var a_stride int32 + var y_size uint64_t + var uv_size uint64_t + var a_size uint64_t + var total_size uint64_t + var mem uintptr + _ = mem + + WebPSafeFree(tls, (*WebPPicture)(unsafe.Pointer(picture)).memory_) + WebPPictureResetBufferYUVA(tls, picture) + + if uv_csp != WEBP_YUV420 { + return WebPEncodingSetError(tls, picture, VP8_ENC_ERROR_INVALID_CONFIGURATION) + } + + // alpha + if has_alpha != 0 { + a_width = width + } else { + a_width = 0 + } + a_stride = a_width + y_size = (uint64_t(y_stride) * uint64_t(height)) + uv_size = (uint64_t(uv_stride) * uint64_t(uv_height)) + a_size = (uint64_t(a_stride) * uint64_t(height)) + + total_size = ((y_size + a_size) + (uint64(2) * uv_size)) + + // Security and validation checks + if (((width <= 0) || (height <= 0)) || (uv_width <= 0)) || (uv_height <= 0) { // u/v param error + return WebPEncodingSetError(tls, picture, VP8_ENC_ERROR_BAD_DIMENSION) + } + // allocate a new buffer. + mem = WebPSafeMalloc(tls, total_size, uint64(unsafe.Sizeof(uint8_t(0)))) + if mem == (uintptr(0)) { + return WebPEncodingSetError(tls, picture, VP8_ENC_ERROR_OUT_OF_MEMORY) + } + + // From now on, we're in the clear, we can no longer fail... + (*WebPPicture)(unsafe.Pointer(picture)).memory_ = mem + (*WebPPicture)(unsafe.Pointer(picture)).y_stride = y_stride + (*WebPPicture)(unsafe.Pointer(picture)).uv_stride = uv_stride + (*WebPPicture)(unsafe.Pointer(picture)).a_stride = a_stride + + // TODO(skal): we could align the y/u/v planes and adjust stride. + (*WebPPicture)(unsafe.Pointer(picture)).y = mem + mem += uintptr(y_size) + + (*WebPPicture)(unsafe.Pointer(picture)).u = mem + mem += uintptr(uv_size) + (*WebPPicture)(unsafe.Pointer(picture)).v = mem + mem += uintptr(uv_size) + + if a_size > uint64(0) { + (*WebPPicture)(unsafe.Pointer(picture)).a = mem + mem += uintptr(a_size) + } + _ = mem // makes the static analyzer happy + return 1 +} + +func WebPPictureAlloc(tls *libc.TLS, picture uintptr) int32 { /* picture_enc.c:153:5: */ + if picture != (uintptr(0)) { + var width int32 = (*WebPPicture)(unsafe.Pointer(picture)).width + var height int32 = (*WebPPicture)(unsafe.Pointer(picture)).height + + WebPPictureFree(tls, picture) // erase previous buffer + + if !((*WebPPicture)(unsafe.Pointer(picture)).use_argb != 0) { + return WebPPictureAllocYUVA(tls, picture, width, height) + } else { + return WebPPictureAllocARGB(tls, picture, width, height) + } + } + return 1 +} + +func WebPPictureFree(tls *libc.TLS, picture uintptr) { /* picture_enc.c:169:6: */ + if picture != (uintptr(0)) { + WebPSafeFree(tls, (*WebPPicture)(unsafe.Pointer(picture)).memory_) + WebPSafeFree(tls, (*WebPPicture)(unsafe.Pointer(picture)).memory_argb_) + WebPPictureResetBuffers(tls, picture) + } +} + +//------------------------------------------------------------------------------ +// WebPMemoryWriter: Write-to-memory + +func WebPMemoryWriterInit(tls *libc.TLS, writer uintptr) { /* picture_enc.c:180:6: */ + (*WebPMemoryWriter)(unsafe.Pointer(writer)).mem = (uintptr(0)) + (*WebPMemoryWriter)(unsafe.Pointer(writer)).size = uint64(0) + (*WebPMemoryWriter)(unsafe.Pointer(writer)).max_size = uint64(0) +} + +func WebPMemoryWrite(tls *libc.TLS, data uintptr, data_size size_t, picture uintptr) int32 { /* picture_enc.c:186:5: */ + var w uintptr = (*WebPPicture)(unsafe.Pointer(picture)).custom_ptr + var next_size uint64_t + if w == (uintptr(0)) { + return 1 + } + next_size = ((*WebPMemoryWriter)(unsafe.Pointer(w)).size + data_size) + if next_size > (*WebPMemoryWriter)(unsafe.Pointer(w)).max_size { + var new_mem uintptr + var next_max_size uint64_t = (uint64_t(2 * uint64((*WebPMemoryWriter)(unsafe.Pointer(w)).max_size))) + if next_max_size < next_size { + next_max_size = next_size + } + if uint64(next_max_size) < 8192 { + next_max_size = 8192 + } + new_mem = WebPSafeMalloc(tls, next_max_size, uint64(1)) + if new_mem == (uintptr(0)) { + return 0 + } + if (*WebPMemoryWriter)(unsafe.Pointer(w)).size > uint64(0) { + libc.Xmemcpy(tls, new_mem, (*WebPMemoryWriter)(unsafe.Pointer(w)).mem, (*WebPMemoryWriter)(unsafe.Pointer(w)).size) + } + WebPSafeFree(tls, (*WebPMemoryWriter)(unsafe.Pointer(w)).mem) + (*WebPMemoryWriter)(unsafe.Pointer(w)).mem = new_mem + // down-cast is ok, thanks to WebPSafeMalloc + (*WebPMemoryWriter)(unsafe.Pointer(w)).max_size = next_max_size + } + if data_size > uint64(0) { + libc.Xmemcpy(tls, ((*WebPMemoryWriter)(unsafe.Pointer(w)).mem + uintptr((*WebPMemoryWriter)(unsafe.Pointer(w)).size)), data, data_size) + *(*size_t)(unsafe.Pointer((w + 8 /* &.size */))) += (data_size) + } + return 1 +} + +func WebPMemoryWriterClear(tls *libc.TLS, writer uintptr) { /* picture_enc.c:218:6: */ + if writer != (uintptr(0)) { + WebPSafeFree(tls, (*WebPMemoryWriter)(unsafe.Pointer(writer)).mem) + (*WebPMemoryWriter)(unsafe.Pointer(writer)).mem = (uintptr(0)) + (*WebPMemoryWriter)(unsafe.Pointer(writer)).size = uint64(0) + (*WebPMemoryWriter)(unsafe.Pointer(writer)).max_size = uint64(0) + } +} + +//------------------------------------------------------------------------------ +// Simplest high-level calls: + +type Importer = uintptr /* picture_enc.c:230:13 */ + +func Encode(tls *libc.TLS, rgba uintptr, width int32, height int32, stride int32, import1 Importer, quality_factor float32, lossless int32, output uintptr) size_t { /* picture_enc.c:232:15: */ + bp := tls.Alloc(408) + defer tls.Free(408) + + // var pic WebPPicture at bp+120, 256 + + // var config WebPConfig at bp, 116 + + // var wrt WebPMemoryWriter at bp+376, 32 + + var ok int32 + + if output == (uintptr(0)) { + return uint64(0) + } + + if !(WebPConfigPreset(tls, (bp) /* &config */, WEBP_PRESET_DEFAULT, quality_factor) != 0) || !(WebPPictureInit(tls, (bp+120) /* &pic */) != 0) { + return uint64(0) // shouldn't happen, except if system installation is broken + } + + (*WebPConfig)(unsafe.Pointer(bp /* &config */)).lossless = libc.BoolInt32(!(!(lossless != 0))) + (*WebPPicture)(unsafe.Pointer(bp + 120 /* &pic */)).use_argb = libc.BoolInt32(!(!(lossless != 0))) + (*WebPPicture)(unsafe.Pointer(bp + 120 /* &pic */)).width = width + (*WebPPicture)(unsafe.Pointer(bp + 120 /* &pic */)).height = height + (*WebPPicture)(unsafe.Pointer(bp + 120 /* &pic */)).writer = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, size_t, uintptr) int32 + }{WebPMemoryWrite})) + (*WebPPicture)(unsafe.Pointer(bp + 120 /* &pic */)).custom_ptr = (bp + 376) /* &wrt */ + WebPMemoryWriterInit(tls, (bp + 376) /* &wrt */) + + ok = (libc.Bool32(((*struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + })(unsafe.Pointer(&struct{ uintptr }{import1})).f(tls, (bp+120) /* &pic */, rgba, stride) != 0) && (WebPEncode(tls, (bp) /* &config */, (bp+120) /* &pic */) != 0))) + WebPPictureFree(tls, (bp + 120) /* &pic */) + if !(ok != 0) { + WebPMemoryWriterClear(tls, (bp + 376) /* &wrt */) + *(*uintptr)(unsafe.Pointer(output)) = (uintptr(0)) + return uint64(0) + } + *(*uintptr)(unsafe.Pointer(output)) = (*WebPMemoryWriter)(unsafe.Pointer(bp + 376 /* &wrt */)).mem + return (*WebPMemoryWriter)(unsafe.Pointer(bp + 376 /* &wrt */)).size +} + +func WebPEncodeRGB(tls *libc.TLS, in uintptr, w int32, h int32, bps int32, q float32, out uintptr) size_t { /* picture_enc.c:272:1: */ + return Encode(tls, in, w, h, bps, *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + }{WebPPictureImportRGB})), q, 0, out) +} + +func WebPEncodeRGBA(tls *libc.TLS, in uintptr, w int32, h int32, bps int32, q float32, out uintptr) size_t { /* picture_enc.c:273:1: */ + return Encode(tls, in, w, h, bps, *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + }{WebPPictureImportRGBA})), q, 0, out) +} + +func WebPEncodeBGR(tls *libc.TLS, in uintptr, w int32, h int32, bps int32, q float32, out uintptr) size_t { /* picture_enc.c:275:1: */ + return Encode(tls, in, w, h, bps, *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + }{WebPPictureImportBGR})), q, 0, out) +} + +func WebPEncodeBGRA(tls *libc.TLS, in uintptr, w int32, h int32, bps int32, q float32, out uintptr) size_t { /* picture_enc.c:276:1: */ + return Encode(tls, in, w, h, bps, *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + }{WebPPictureImportBGRA})), q, 0, out) +} + +func WebPEncodeLosslessRGB(tls *libc.TLS, in uintptr, w int32, h int32, bps int32, out uintptr) size_t { /* picture_enc.c:287:1: */ + return Encode(tls, in, w, h, bps, *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + }{WebPPictureImportRGB})), 70., 1, out) +} + +func WebPEncodeLosslessRGBA(tls *libc.TLS, in uintptr, w int32, h int32, bps int32, out uintptr) size_t { /* picture_enc.c:288:1: */ + return Encode(tls, in, w, h, bps, *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + }{WebPPictureImportRGBA})), 70., 1, out) +} + +func WebPEncodeLosslessBGR(tls *libc.TLS, in uintptr, w int32, h int32, bps int32, out uintptr) size_t { /* picture_enc.c:290:1: */ + return Encode(tls, in, w, h, bps, *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + }{WebPPictureImportBGR})), 70., 1, out) +} + +func WebPEncodeLosslessBGRA(tls *libc.TLS, in uintptr, w int32, h int32, bps int32, out uintptr) size_t { /* picture_enc.c:291:1: */ + return Encode(tls, in, w, h, bps, *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr, int32) int32 + }{WebPPictureImportBGRA})), 70., 1, out) +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +type AccumulateFunc = uintptr /* picture_psnr_enc.c:25:16 */ + +//------------------------------------------------------------------------------ +// local-min distortion +// +// For every pixel in the *reference* picture, we search for the local best +// match in the compressed image. This is not a symmetrical measure. + +func AccumulateLSIM(tls *libc.TLS, src uintptr, src_stride int32, ref uintptr, ref_stride int32, w int32, h int32) float64 { /* picture_psnr_enc.c:37:15: */ + var x int32 + var y int32 + var total_sse float64 = 0. + for y = 0; y < h; y++ { + var y_0 int32 + if (y - 2) < 0 { + y_0 = 0 + } else { + y_0 = (y - 2) + } + var y_1 int32 + if ((y + 2) + 1) >= h { + y_1 = h + } else { + y_1 = ((y + 2) + 1) + } + for x = 0; x < w; x++ { + var x_0 int32 + if (x - 2) < 0 { + x_0 = 0 + } else { + x_0 = (x - 2) + } + var x_1 int32 + if ((x + 2) + 1) >= w { + x_1 = w + } else { + x_1 = ((x + 2) + 1) + } + var best_sse float64 = (float64(255.) * 255.) + var value float64 = float64(*(*uint8_t)(unsafe.Pointer(ref + uintptr(((y * ref_stride) + x))))) + var i int32 + var j int32 + for j = y_0; j < y_1; j++ { + var s uintptr = (src + uintptr((j * src_stride))) + for i = x_0; i < x_1; i++ { + var diff float64 = (float64(*(*uint8_t)(unsafe.Pointer(s + uintptr(i)))) - value) + var sse float64 = (diff * diff) + if sse < best_sse { + best_sse = sse + } + } + } + total_sse = total_sse + (best_sse) + } + } + return total_sse +} + +func AccumulateSSE(tls *libc.TLS, src uintptr, src_stride int32, ref uintptr, ref_stride int32, w int32, h int32) float64 { /* picture_psnr_enc.c:66:15: */ + var y int32 + var total_sse float64 = 0. + for y = 0; y < h; y++ { + total_sse = total_sse + (float64((*struct { + f func(*libc.TLS, uintptr, uintptr, int32) uint32_t + })(unsafe.Pointer(&struct{ uintptr }{VP8AccumulateSSE})).f(tls, src, ref, w))) + src += uintptr(src_stride) + ref += uintptr(ref_stride) + } + return total_sse +} + +//------------------------------------------------------------------------------ + +func AccumulateSSIM(tls *libc.TLS, src uintptr, src_stride int32, ref uintptr, ref_stride int32, w int32, h int32) float64 { /* picture_psnr_enc.c:81:15: */ + var w0 int32 + if w < 3 { + w0 = w + } else { + w0 = 3 + } + var w1 int32 = ((w - 3) - 1) + var h0 int32 + if h < 3 { + h0 = h + } else { + h0 = 3 + } + var h1 int32 = ((h - 3) - 1) + var x int32 + var y int32 + var sum float64 = 0. + for y = 0; y < h0; y++ { + for x = 0; x < w; x++ { + sum = sum + ((*struct { + f func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32, int32, int32) float64 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSIMGetClipped})).f(tls, src, src_stride, ref, ref_stride, x, y, w, h)) + } + } + for ; y < h1; y++ { + for x = 0; x < w0; x++ { + sum = sum + ((*struct { + f func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32, int32, int32) float64 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSIMGetClipped})).f(tls, src, src_stride, ref, ref_stride, x, y, w, h)) + } + for ; x < w1; x++ { + var off1 int32 = ((x - 3) + ((y - 3) * src_stride)) + var off2 int32 = ((x - 3) + ((y - 3) * ref_stride)) + sum = sum + ((*struct { + f func(*libc.TLS, uintptr, int32, uintptr, int32) float64 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSIMGet})).f(tls, (src + uintptr(off1)), src_stride, (ref + uintptr(off2)), ref_stride)) + } + for ; x < w; x++ { + sum = sum + ((*struct { + f func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32, int32, int32) float64 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSIMGetClipped})).f(tls, src, src_stride, ref, ref_stride, x, y, w, h)) + } + } + for ; y < h; y++ { + for x = 0; x < w; x++ { + sum = sum + ((*struct { + f func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32, int32, int32) float64 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSIMGetClipped})).f(tls, src, src_stride, ref, ref_stride, x, y, w, h)) + } + } + return sum +} + +//------------------------------------------------------------------------------ +// Distortion + +// Max value returned in case of exact similarity. +var kMinDistortion_dB float64 = 99. /* picture_psnr_enc.c:120:21 */ + +func GetPSNR1(tls *libc.TLS, v float64, size float64) float64 { /* picture_psnr_enc.c:122:15: */ + if (v > 0.) && (size > 0.) { + return (-4.3429448 * libc.Xlog(tls, (v/((size*float64(255))*255.)))) + } + return kMinDistortion_dB +} + +func GetLogSSIM(tls *libc.TLS, v float64, size float64) float64 { /* picture_psnr_enc.c:127:15: */ + if size > 0. { + v = (v / size) + } else { + v = 1. + } + if v < 1. { + return (-10.0 * libc.Xlog10(tls, (1.-v))) + } + return kMinDistortion_dB +} + +func WebPPlaneDistortion(tls *libc.TLS, src uintptr, src_stride size_t, ref uintptr, ref_stride size_t, width int32, height int32, x_step size_t, type1 int32, distortion uintptr, result uintptr) int32 { /* picture_psnr_enc.c:132:5: */ + var allocated uintptr = (uintptr(0)) + var metric AccumulateFunc + if type1 == 0 { + metric = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32) float64 + }{AccumulateSSE})) + } else { + if type1 == 1 { + metric = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32) float64 + }{AccumulateSSIM})) + } else { + metric = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32) float64 + }{AccumulateLSIM})) + } + } + if (((((src == (uintptr(0))) || (ref == (uintptr(0)))) || (src_stride < (x_step * size_t(width)))) || (ref_stride < (x_step * size_t(width)))) || (result == (uintptr(0)))) || (distortion == (uintptr(0))) { + return 0 + } + + VP8SSIMDspInit(tls) + if x_step != uint64(1) { // extract a packed plane if needed + var x int32 + var y int32 + var tmp1 uintptr + var tmp2 uintptr + allocated = WebPSafeMalloc(tls, (uint64((2 * uint64(width)) * uint64(height))), uint64(unsafe.Sizeof(uint8_t(0)))) + if allocated == (uintptr(0)) { + return 0 + } + tmp1 = allocated + tmp2 = (tmp1 + uintptr((size_t(width) * size_t(height)))) + for y = 0; y < height; y++ { + for x = 0; x < width; x++ { + *(*uint8_t)(unsafe.Pointer(tmp1 + uintptr((x + (y * width))))) = *(*uint8_t)(unsafe.Pointer(src + uintptr(((size_t(x) * x_step) + (size_t(y) * src_stride))))) + *(*uint8_t)(unsafe.Pointer(tmp2 + uintptr((x + (y * width))))) = *(*uint8_t)(unsafe.Pointer(ref + uintptr(((size_t(x) * x_step) + (size_t(y) * ref_stride))))) + } + } + src = tmp1 + ref = tmp2 + } + *(*float32)(unsafe.Pointer(distortion)) = float32((*struct { + f func(*libc.TLS, uintptr, int32, uintptr, int32, int32, int32) float64 + })(unsafe.Pointer(&struct{ uintptr }{metric})).f(tls, src, width, ref, width, width, height)) + WebPSafeFree(tls, allocated) + + *(*float32)(unsafe.Pointer(result)) = func() float32 { + if type1 == 1 { + return float32(GetLogSSIM(tls, float64(*(*float32)(unsafe.Pointer(distortion))), (float64(width) * float64(height)))) + } + return float32(GetPSNR1(tls, float64(*(*float32)(unsafe.Pointer(distortion))), (float64(width) * float64(height)))) + }() + return 1 +} + +func WebPPictureDistortion(tls *libc.TLS, src uintptr, ref uintptr, type1 int32, results uintptr) int32 { /* picture_psnr_enc.c:179:5: */ + bp := tls.Alloc(516) + defer tls.Free(516) + + var w int32 + var h int32 + var c int32 + var ok int32 + // var p0 WebPPicture at bp, 256 + + // var p1 WebPPicture at bp+256, 256 + + var total_size float64 + var total_distortion float64 + // var distortion float32 at bp+512, 4 + + var stride0 size_t + var stride1 size_t + // results are reported as BGRA + var offset int32 + ok = 0 + total_size = 0. + total_distortion = 0. + if !(((((src == (uintptr(0))) || (ref == (uintptr(0)))) || ((*WebPPicture)(unsafe.Pointer(src)).width != (*WebPPicture)(unsafe.Pointer(ref)).width)) || ((*WebPPicture)(unsafe.Pointer(src)).height != (*WebPPicture)(unsafe.Pointer(ref)).height)) || (results == (uintptr(0)))) { + goto __1 + } + return 0 +__1: + ; + + VP8SSIMDspInit(tls) + if !(!(WebPPictureInit(tls, (bp) /* &p0 */) != 0) || !(WebPPictureInit(tls, (bp+256) /* &p1 */) != 0)) { + goto __2 + } + return 0 +__2: + ; + w = (*WebPPicture)(unsafe.Pointer(src)).width + h = (*WebPPicture)(unsafe.Pointer(src)).height + if !(!(WebPPictureView(tls, src, 0, 0, w, h, (bp) /* &p0 */) != 0)) { + goto __3 + } + goto Error +__3: + ; + if !(!(WebPPictureView(tls, ref, 0, 0, w, h, (bp+256) /* &p1 */) != 0)) { + goto __4 + } + goto Error +__4: + ; + + // We always measure distortion in ARGB space. + if !(((*WebPPicture)(unsafe.Pointer(bp /* &p0 */)).use_argb == 0) && !(WebPPictureYUVAToARGB(tls, (bp) /* &p0 */) != 0)) { + goto __5 + } + goto Error +__5: + ; + if !(((*WebPPicture)(unsafe.Pointer(bp+256 /* &p1 */)).use_argb == 0) && !(WebPPictureYUVAToARGB(tls, (bp+256) /* &p1 */) != 0)) { + goto __6 + } + goto Error +__6: + ; + c = 0 +__7: + if !(c < 4) { + goto __9 + } + stride0 = (uint64(4) * size_t((*WebPPicture)(unsafe.Pointer(bp /* &p0 */)).argb_stride)) + stride1 = (uint64(4) * size_t((*WebPPicture)(unsafe.Pointer(bp+256 /* &p1 */)).argb_stride)) + // results are reported as BGRA + offset = (c ^ 0) + if !(!(WebPPlaneDistortion(tls, ((*WebPPicture)(unsafe.Pointer(bp /* &p0 */)).argb+uintptr(offset)), stride0, + ((*WebPPicture)(unsafe.Pointer(bp+256 /* &p1 */)).argb+uintptr(offset)), stride1, + w, h, uint64(4), type1, (bp+512) /* &distortion */, (results+uintptr(c)*4)) != 0)) { + goto __10 + } + goto Error +__10: + ; + total_distortion = total_distortion + (float64(*(*float32)(unsafe.Pointer(bp + 512 /* distortion */)))) + total_size = total_size + (float64(w * h)) + goto __8 +__8: + c++ + goto __7 + goto __9 +__9: + ; + + *(*float32)(unsafe.Pointer(results + 4*4)) = func() float32 { + if type1 == 1 { + return float32(GetLogSSIM(tls, total_distortion, total_size)) + } + return float32(GetPSNR1(tls, total_distortion, total_size)) + }() + ok = 1 + +Error: + WebPPictureFree(tls, (bp) /* &p0 */) + WebPPictureFree(tls, (bp + 256) /* &p1 */) + return ok +} + +//------------------------------------------------------------------------------ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +// Grab the 'specs' (writer, *opaque, width, height...) from 'src' and copy them +// into 'dst'. Mark 'dst' as not owning any memory. +func PictureGrabSpecs(tls *libc.TLS, src uintptr, dst uintptr) { /* picture_rescale_enc.c:29:13: */ + + *(*WebPPicture)(unsafe.Pointer(dst)) = *(*WebPPicture)(unsafe.Pointer(src)) + WebPPictureResetBuffers(tls, dst) +} + +//------------------------------------------------------------------------------ + +// Adjust top-left corner to chroma sample position. +func SnapTopLeftPosition(tls *libc.TLS, pic uintptr, left uintptr, top uintptr) { /* picture_rescale_enc.c:39:13: */ + if !((*WebPPicture)(unsafe.Pointer(pic)).use_argb != 0) { + *(*int32)(unsafe.Pointer(left)) &= (libc.CplInt32(1)) + *(*int32)(unsafe.Pointer(top)) &= (libc.CplInt32(1)) + } +} + +// Adjust top-left corner and verify that the sub-rectangle is valid. +func AdjustAndCheckRectangle(tls *libc.TLS, pic uintptr, left uintptr, top uintptr, width int32, height int32) int32 { /* picture_rescale_enc.c:48:12: */ + SnapTopLeftPosition(tls, pic, left, top) + if ((*(*int32)(unsafe.Pointer(left))) < 0) || ((*(*int32)(unsafe.Pointer(top))) < 0) { + return 0 + } + if (width <= 0) || (height <= 0) { + return 0 + } + if ((*(*int32)(unsafe.Pointer(left))) + width) > (*WebPPicture)(unsafe.Pointer(pic)).width { + return 0 + } + if ((*(*int32)(unsafe.Pointer(top))) + height) > (*WebPPicture)(unsafe.Pointer(pic)).height { + return 0 + } + return 1 +} + +func WebPPictureCopy(tls *libc.TLS, src uintptr, dst uintptr) int32 { /* picture_rescale_enc.c:59:5: */ + if (src == (uintptr(0))) || (dst == (uintptr(0))) { + return 0 + } + if src == dst { + return 1 + } + + PictureGrabSpecs(tls, src, dst) + if !(WebPPictureAlloc(tls, dst) != 0) { + return 0 + } + + if !((*WebPPicture)(unsafe.Pointer(src)).use_argb != 0) { + WebPCopyPlane(tls, (*WebPPicture)(unsafe.Pointer(src)).y, (*WebPPicture)(unsafe.Pointer(src)).y_stride, + (*WebPPicture)(unsafe.Pointer(dst)).y, (*WebPPicture)(unsafe.Pointer(dst)).y_stride, (*WebPPicture)(unsafe.Pointer(dst)).width, (*WebPPicture)(unsafe.Pointer(dst)).height) + WebPCopyPlane(tls, (*WebPPicture)(unsafe.Pointer(src)).u, (*WebPPicture)(unsafe.Pointer(src)).uv_stride, (*WebPPicture)(unsafe.Pointer(dst)).u, (*WebPPicture)(unsafe.Pointer(dst)).uv_stride, + ((((*WebPPicture)(unsafe.Pointer(dst)).width) + 1) >> 1), ((((*WebPPicture)(unsafe.Pointer(dst)).height) + 1) >> 1)) + WebPCopyPlane(tls, (*WebPPicture)(unsafe.Pointer(src)).v, (*WebPPicture)(unsafe.Pointer(src)).uv_stride, (*WebPPicture)(unsafe.Pointer(dst)).v, (*WebPPicture)(unsafe.Pointer(dst)).uv_stride, + ((((*WebPPicture)(unsafe.Pointer(dst)).width) + 1) >> 1), ((((*WebPPicture)(unsafe.Pointer(dst)).height) + 1) >> 1)) + if (*WebPPicture)(unsafe.Pointer(dst)).a != (uintptr(0)) { + WebPCopyPlane(tls, (*WebPPicture)(unsafe.Pointer(src)).a, (*WebPPicture)(unsafe.Pointer(src)).a_stride, + (*WebPPicture)(unsafe.Pointer(dst)).a, (*WebPPicture)(unsafe.Pointer(dst)).a_stride, (*WebPPicture)(unsafe.Pointer(dst)).width, (*WebPPicture)(unsafe.Pointer(dst)).height) + } + } else { + WebPCopyPlane(tls, (*WebPPicture)(unsafe.Pointer(src)).argb, (4 * (*WebPPicture)(unsafe.Pointer(src)).argb_stride), + (*WebPPicture)(unsafe.Pointer(dst)).argb, (4 * (*WebPPicture)(unsafe.Pointer(dst)).argb_stride), + (4 * (*WebPPicture)(unsafe.Pointer(dst)).width), (*WebPPicture)(unsafe.Pointer(dst)).height) + } + return 1 +} + +func WebPPictureIsView(tls *libc.TLS, picture uintptr) int32 { /* picture_rescale_enc.c:85:5: */ + if picture == (uintptr(0)) { + return 0 + } + if (*WebPPicture)(unsafe.Pointer(picture)).use_argb != 0 { + return (libc.Bool32((*WebPPicture)(unsafe.Pointer(picture)).memory_argb_ == (uintptr(0)))) + } + return (libc.Bool32((*WebPPicture)(unsafe.Pointer(picture)).memory_ == (uintptr(0)))) +} + +func WebPPictureView(tls *libc.TLS, src uintptr, left int32, top int32, width int32, height int32, dst uintptr) int32 { /* picture_rescale_enc.c:93:5: */ + bp := tls.Alloc(8) + defer tls.Free(8) + *(*int32)(unsafe.Pointer(bp)) = left + *(*int32)(unsafe.Pointer(bp + 4)) = top + + if (src == (uintptr(0))) || (dst == (uintptr(0))) { + return 0 + } + + // verify rectangle position. + if !(AdjustAndCheckRectangle(tls, src, (bp) /* &left */, (bp+4) /* &top */, width, height) != 0) { + return 0 + } + + if src != dst { // beware of aliasing! We don't want to leak 'memory_'. + PictureGrabSpecs(tls, src, dst) + } + (*WebPPicture)(unsafe.Pointer(dst)).width = width + (*WebPPicture)(unsafe.Pointer(dst)).height = height + if !((*WebPPicture)(unsafe.Pointer(src)).use_argb != 0) { + (*WebPPicture)(unsafe.Pointer(dst)).y = (((*WebPPicture)(unsafe.Pointer(src)).y + uintptr((*(*int32)(unsafe.Pointer(bp + 4 /* top */)) * (*WebPPicture)(unsafe.Pointer(src)).y_stride))) + uintptr(*(*int32)(unsafe.Pointer(bp /* left */)))) + (*WebPPicture)(unsafe.Pointer(dst)).u = (((*WebPPicture)(unsafe.Pointer(src)).u + uintptr(((*(*int32)(unsafe.Pointer(bp + 4 /* top */)) >> 1) * (*WebPPicture)(unsafe.Pointer(src)).uv_stride))) + uintptr((*(*int32)(unsafe.Pointer(bp /* left */)) >> 1))) + (*WebPPicture)(unsafe.Pointer(dst)).v = (((*WebPPicture)(unsafe.Pointer(src)).v + uintptr(((*(*int32)(unsafe.Pointer(bp + 4 /* top */)) >> 1) * (*WebPPicture)(unsafe.Pointer(src)).uv_stride))) + uintptr((*(*int32)(unsafe.Pointer(bp /* left */)) >> 1))) + (*WebPPicture)(unsafe.Pointer(dst)).y_stride = (*WebPPicture)(unsafe.Pointer(src)).y_stride + (*WebPPicture)(unsafe.Pointer(dst)).uv_stride = (*WebPPicture)(unsafe.Pointer(src)).uv_stride + if (*WebPPicture)(unsafe.Pointer(src)).a != (uintptr(0)) { + (*WebPPicture)(unsafe.Pointer(dst)).a = (((*WebPPicture)(unsafe.Pointer(src)).a + uintptr((*(*int32)(unsafe.Pointer(bp + 4 /* top */)) * (*WebPPicture)(unsafe.Pointer(src)).a_stride))) + uintptr(*(*int32)(unsafe.Pointer(bp /* left */)))) + (*WebPPicture)(unsafe.Pointer(dst)).a_stride = (*WebPPicture)(unsafe.Pointer(src)).a_stride + } + } else { + (*WebPPicture)(unsafe.Pointer(dst)).argb = (((*WebPPicture)(unsafe.Pointer(src)).argb + uintptr((*(*int32)(unsafe.Pointer(bp + 4 /* top */))*(*WebPPicture)(unsafe.Pointer(src)).argb_stride))*4) + uintptr(*(*int32)(unsafe.Pointer(bp /* left */)))*4) + (*WebPPicture)(unsafe.Pointer(dst)).argb_stride = (*WebPPicture)(unsafe.Pointer(src)).argb_stride + } + return 1 +} + +//------------------------------------------------------------------------------ +// Picture cropping + +func WebPPictureCrop(tls *libc.TLS, pic uintptr, left int32, top int32, width int32, height int32) int32 { /* picture_rescale_enc.c:126:5: */ + bp := tls.Alloc(264) + defer tls.Free(264) + *(*int32)(unsafe.Pointer(bp)) = left + *(*int32)(unsafe.Pointer(bp + 4)) = top + + // var tmp WebPPicture at bp+8, 256 + + if pic == (uintptr(0)) { + return 0 + } + if !(AdjustAndCheckRectangle(tls, pic, (bp) /* &left */, (bp+4) /* &top */, width, height) != 0) { + return 0 + } + + PictureGrabSpecs(tls, pic, (bp + 8) /* &tmp */) + (*WebPPicture)(unsafe.Pointer(bp + 8 /* &tmp */)).width = width + (*WebPPicture)(unsafe.Pointer(bp + 8 /* &tmp */)).height = height + if !(WebPPictureAlloc(tls, (bp+8) /* &tmp */) != 0) { + return 0 + } + + if !((*WebPPicture)(unsafe.Pointer(pic)).use_argb != 0) { + var y_offset int32 = ((*(*int32)(unsafe.Pointer(bp + 4 /* top */)) * (*WebPPicture)(unsafe.Pointer(pic)).y_stride) + *(*int32)(unsafe.Pointer(bp /* left */))) + var uv_offset int32 = (((*(*int32)(unsafe.Pointer(bp + 4 /* top */)) / 2) * (*WebPPicture)(unsafe.Pointer(pic)).uv_stride) + (*(*int32)(unsafe.Pointer(bp /* left */)) / 2)) + WebPCopyPlane(tls, ((*WebPPicture)(unsafe.Pointer(pic)).y + uintptr(y_offset)), (*WebPPicture)(unsafe.Pointer(pic)).y_stride, + (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).y, (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).y_stride, width, height) + WebPCopyPlane(tls, ((*WebPPicture)(unsafe.Pointer(pic)).u + uintptr(uv_offset)), (*WebPPicture)(unsafe.Pointer(pic)).uv_stride, + (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).u, (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).uv_stride, (((width) + 1) >> 1), (((height) + 1) >> 1)) + WebPCopyPlane(tls, ((*WebPPicture)(unsafe.Pointer(pic)).v + uintptr(uv_offset)), (*WebPPicture)(unsafe.Pointer(pic)).uv_stride, + (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).v, (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).uv_stride, (((width) + 1) >> 1), (((height) + 1) >> 1)) + + if (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).a != (uintptr(0)) { + var a_offset int32 = ((*(*int32)(unsafe.Pointer(bp + 4 /* top */)) * (*WebPPicture)(unsafe.Pointer(pic)).a_stride) + *(*int32)(unsafe.Pointer(bp /* left */))) + WebPCopyPlane(tls, ((*WebPPicture)(unsafe.Pointer(pic)).a + uintptr(a_offset)), (*WebPPicture)(unsafe.Pointer(pic)).a_stride, + (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).a, (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).a_stride, width, height) + } + } else { + var src uintptr = (((*WebPPicture)(unsafe.Pointer(pic)).argb + uintptr((*(*int32)(unsafe.Pointer(bp + 4 /* top */))*(*WebPPicture)(unsafe.Pointer(pic)).argb_stride))*4) + uintptr(*(*int32)(unsafe.Pointer(bp /* left */)))*4) + WebPCopyPlane(tls, src, ((*WebPPicture)(unsafe.Pointer(pic)).argb_stride * 4), (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).argb, + ((*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).argb_stride * 4), (width * 4), height) + } + WebPPictureFree(tls, pic) + *(*WebPPicture)(unsafe.Pointer(pic)) = *(*WebPPicture)(unsafe.Pointer(bp + 8 /* tmp */)) + return 1 +} + +//------------------------------------------------------------------------------ +// Simple picture rescaler + +func RescalePlane(tls *libc.TLS, src uintptr, src_width int32, src_height int32, src_stride int32, dst uintptr, dst_width int32, dst_height int32, dst_stride int32, work uintptr, num_channels int32) int32 { /* picture_rescale_enc.c:167:12: */ + bp := tls.Alloc(104) + defer tls.Free(104) + + // var rescaler WebPRescaler at bp, 104 + + var y int32 = 0 + if !(WebPRescalerInit(tls, (bp) /* &rescaler */, src_width, src_height, + dst, dst_width, dst_height, dst_stride, + num_channels, work) != 0) { + return 0 + } + for y < src_height { + y = y + (WebPRescalerImport(tls, (bp) /* &rescaler */, (src_height - y), + (src + uintptr((y * src_stride))), src_stride)) + WebPRescalerExport(tls, (bp) /* &rescaler */) + } + return 1 +} + +func AlphaMultiplyARGB(tls *libc.TLS, pic uintptr, inverse int32) { /* picture_rescale_enc.c:188:13: */ + + WebPMultARGBRows(tls, (*WebPPicture)(unsafe.Pointer(pic)).argb, (int32(uint64((*WebPPicture)(unsafe.Pointer(pic)).argb_stride) * uint64(unsafe.Sizeof(uint32_t(0))))), + (*WebPPicture)(unsafe.Pointer(pic)).width, (*WebPPicture)(unsafe.Pointer(pic)).height, inverse) +} + +func AlphaMultiplyY(tls *libc.TLS, pic uintptr, inverse int32) { /* picture_rescale_enc.c:194:13: */ + if (*WebPPicture)(unsafe.Pointer(pic)).a != (uintptr(0)) { + WebPMultRows(tls, (*WebPPicture)(unsafe.Pointer(pic)).y, (*WebPPicture)(unsafe.Pointer(pic)).y_stride, (*WebPPicture)(unsafe.Pointer(pic)).a, (*WebPPicture)(unsafe.Pointer(pic)).a_stride, + (*WebPPicture)(unsafe.Pointer(pic)).width, (*WebPPicture)(unsafe.Pointer(pic)).height, inverse) + } +} + +func WebPPictureRescale(tls *libc.TLS, pic uintptr, width int32, height int32) int32 { /* picture_rescale_enc.c:201:5: */ + bp := tls.Alloc(264) + defer tls.Free(264) + *(*int32)(unsafe.Pointer(bp)) = width + *(*int32)(unsafe.Pointer(bp + 4)) = height + + // var tmp WebPPicture at bp+8, 256 + + var prev_width int32 + var prev_height int32 + var work uintptr + + if pic == (uintptr(0)) { + return 0 + } + prev_width = (*WebPPicture)(unsafe.Pointer(pic)).width + prev_height = (*WebPPicture)(unsafe.Pointer(pic)).height + if !(WebPRescalerGetScaledDimensions(tls, + prev_width, prev_height, (bp) /* &width */, (bp+4) /* &height */) != 0) { + return 0 + } + + PictureGrabSpecs(tls, pic, (bp + 8) /* &tmp */) + (*WebPPicture)(unsafe.Pointer(bp + 8 /* &tmp */)).width = *(*int32)(unsafe.Pointer(bp /* width */)) + (*WebPPicture)(unsafe.Pointer(bp + 8 /* &tmp */)).height = *(*int32)(unsafe.Pointer(bp + 4 /* height */)) + if !(WebPPictureAlloc(tls, (bp+8) /* &tmp */) != 0) { + return 0 + } + + if !((*WebPPicture)(unsafe.Pointer(pic)).use_argb != 0) { + work = WebPSafeMalloc(tls, (uint64(2 * uint64(*(*int32)(unsafe.Pointer(bp /* width */))))), uint64(unsafe.Sizeof(rescaler_t(0)))) + if work == (uintptr(0)) { + WebPPictureFree(tls, (bp + 8) /* &tmp */) + return 0 + } + // If present, we need to rescale alpha first (for AlphaMultiplyY). + if (*WebPPicture)(unsafe.Pointer(pic)).a != (uintptr(0)) { + WebPInitAlphaProcessing(tls) + if !(RescalePlane(tls, (*WebPPicture)(unsafe.Pointer(pic)).a, prev_width, prev_height, (*WebPPicture)(unsafe.Pointer(pic)).a_stride, + (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).a, *(*int32)(unsafe.Pointer(bp /* width */)), *(*int32)(unsafe.Pointer(bp + 4 /* height */)), (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).a_stride, work, 1) != 0) { + return 0 + } + } + + // We take transparency into account on the luma plane only. That's not + // totally exact blending, but still is a good approximation. + AlphaMultiplyY(tls, pic, 0) + if (!(RescalePlane(tls, (*WebPPicture)(unsafe.Pointer(pic)).y, prev_width, prev_height, (*WebPPicture)(unsafe.Pointer(pic)).y_stride, + (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).y, *(*int32)(unsafe.Pointer(bp /* width */)), *(*int32)(unsafe.Pointer(bp + 4 /* height */)), (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).y_stride, work, 1) != 0) || !(RescalePlane(tls, (*WebPPicture)(unsafe.Pointer(pic)).u, + (((prev_width)+1)>>1), (((prev_height)+1)>>1), (*WebPPicture)(unsafe.Pointer(pic)).uv_stride, + (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).u, + (((*(*int32)(unsafe.Pointer(bp /* width */)))+1)>>1), (((*(*int32)(unsafe.Pointer(bp + 4 /* height */)))+1)>>1), (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).uv_stride, work, 1) != 0)) || !(RescalePlane(tls, (*WebPPicture)(unsafe.Pointer(pic)).v, + (((prev_width)+1)>>1), (((prev_height)+1)>>1), (*WebPPicture)(unsafe.Pointer(pic)).uv_stride, + (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).v, + (((*(*int32)(unsafe.Pointer(bp /* width */)))+1)>>1), (((*(*int32)(unsafe.Pointer(bp + 4 /* height */)))+1)>>1), (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).uv_stride, work, 1) != 0) { + return 0 + } + AlphaMultiplyY(tls, (bp + 8) /* &tmp */, 1) + } else { + work = WebPSafeMalloc(tls, (uint64((2 * uint64(*(*int32)(unsafe.Pointer(bp /* width */)))) * uint64(4))), uint64(unsafe.Sizeof(rescaler_t(0)))) + if work == (uintptr(0)) { + WebPPictureFree(tls, (bp + 8) /* &tmp */) + return 0 + } + // In order to correctly interpolate colors, we need to apply the alpha + // weighting first (black-matting), scale the RGB values, and remove + // the premultiplication afterward (while preserving the alpha channel). + WebPInitAlphaProcessing(tls) + AlphaMultiplyARGB(tls, pic, 0) + if !(RescalePlane(tls, (*WebPPicture)(unsafe.Pointer(pic)).argb, prev_width, prev_height, + ((*WebPPicture)(unsafe.Pointer(pic)).argb_stride*4), + (*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).argb, *(*int32)(unsafe.Pointer(bp /* width */)), *(*int32)(unsafe.Pointer(bp + 4 /* height */)), + ((*WebPPicture)(unsafe.Pointer(bp+8 /* &tmp */)).argb_stride*4), work, 4) != 0) { + return 0 + } + AlphaMultiplyARGB(tls, (bp + 8) /* &tmp */, 1) + } + WebPPictureFree(tls, pic) + WebPSafeFree(tls, work) + *(*WebPPicture)(unsafe.Pointer(pic)) = *(*WebPPicture)(unsafe.Pointer(bp + 8 /* tmp */)) + return 1 +} + +//------------------------------------------------------------------------------ +// Helper: clean up fully transparent area to help compressibility. + +func IsTransparentARGBArea(tls *libc.TLS, ptr uintptr, stride int32, size int32) int32 { /* picture_tools_enc.c:24:12: */ + var y int32 + var x int32 + for y = 0; y < size; y++ { + for x = 0; x < size; x++ { + if (*(*uint32_t)(unsafe.Pointer(ptr + uintptr(x)*4)) & 0xff000000) != 0 { + return 0 + } + } + ptr += 4 * (uintptr(stride)) + } + return 1 +} + +func Flatten(tls *libc.TLS, ptr uintptr, v int32, stride int32, size int32) { /* picture_tools_enc.c:37:13: */ + var y int32 + for y = 0; y < size; y++ { + libc.Xmemset(tls, ptr, v, uint64(size)) + ptr += uintptr(stride) + } +} + +func FlattenARGB(tls *libc.TLS, ptr uintptr, v uint32_t, stride int32, size int32) { /* picture_tools_enc.c:45:13: */ + var x int32 + var y int32 + for y = 0; y < size; y++ { + for x = 0; x < size; x++ { + *(*uint32_t)(unsafe.Pointer(ptr + uintptr(x)*4)) = v + } + ptr += 4 * (uintptr(stride)) + } +} + +// Smoothen the luma components of transparent pixels. Return true if the whole +// block is transparent. +func SmoothenBlock(tls *libc.TLS, a_ptr uintptr, a_stride int32, y_ptr uintptr, y_stride int32, width int32, height int32) int32 { /* picture_tools_enc.c:55:12: */ + var sum int32 = 0 + var count int32 = 0 + var x int32 + var y int32 + var alpha_ptr uintptr = a_ptr + var luma_ptr uintptr = y_ptr + for y = 0; y < height; y++ { + for x = 0; x < width; x++ { + if int32(*(*uint8_t)(unsafe.Pointer(alpha_ptr + uintptr(x)))) != 0 { + count++ + sum = sum + (int32(*(*uint8_t)(unsafe.Pointer(luma_ptr + uintptr(x))))) + } + } + alpha_ptr += uintptr(a_stride) + luma_ptr += uintptr(y_stride) + } + if (count > 0) && (count < (width * height)) { + var avg_u8 uint8_t = (uint8_t(sum / count)) + alpha_ptr = a_ptr + luma_ptr = y_ptr + for y = 0; y < height; y++ { + for x = 0; x < width; x++ { + if int32(*(*uint8_t)(unsafe.Pointer(alpha_ptr + uintptr(x)))) == 0 { + *(*uint8_t)(unsafe.Pointer(luma_ptr + uintptr(x))) = avg_u8 + } + } + alpha_ptr += uintptr(a_stride) + luma_ptr += uintptr(y_stride) + } + } + return (libc.Bool32(count == 0)) +} + +func WebPReplaceTransparentPixels(tls *libc.TLS, pic uintptr, color uint32_t) { /* picture_tools_enc.c:86:6: */ + if (pic != (uintptr(0))) && ((*WebPPicture)(unsafe.Pointer(pic)).use_argb != 0) { + var y int32 = (*WebPPicture)(unsafe.Pointer(pic)).height + var argb uintptr = (*WebPPicture)(unsafe.Pointer(pic)).argb + color = color & (0xffffff) // force alpha=0 + WebPInitAlphaProcessing(tls) + for libc.PostDecInt32(&y, 1) > 0 { + (*struct { + f func(*libc.TLS, uintptr, int32, uint32_t) + })(unsafe.Pointer(&struct{ uintptr }{WebPAlphaReplace})).f(tls, argb, (*WebPPicture)(unsafe.Pointer(pic)).width, color) + argb += 4 * (uintptr((*WebPPicture)(unsafe.Pointer(pic)).argb_stride)) + } + } +} + +func WebPCleanupTransparentArea(tls *libc.TLS, pic uintptr) { /* picture_tools_enc.c:99:6: */ + bp := tls.Alloc(12) + defer tls.Free(12) + + var x int32 + var y int32 + var w int32 + var h int32 + if pic == (uintptr(0)) { + return + } + w = ((*WebPPicture)(unsafe.Pointer(pic)).width / 8) + h = ((*WebPPicture)(unsafe.Pointer(pic)).height / 8) + + // note: we ignore the left-overs on right/bottom, except for SmoothenBlock(). + if (*WebPPicture)(unsafe.Pointer(pic)).use_argb != 0 { + var argb_value uint32_t = uint32_t(0) + for y = 0; y < h; y++ { + var need_reset int32 = 1 + for x = 0; x < w; x++ { + var off int32 = (((y * (*WebPPicture)(unsafe.Pointer(pic)).argb_stride) + x) * 8) + if IsTransparentARGBArea(tls, ((*WebPPicture)(unsafe.Pointer(pic)).argb+uintptr(off)*4), (*WebPPicture)(unsafe.Pointer(pic)).argb_stride, 8) != 0 { + if need_reset != 0 { + argb_value = *(*uint32_t)(unsafe.Pointer((*WebPPicture)(unsafe.Pointer(pic)).argb + uintptr(off)*4)) + need_reset = 0 + } + FlattenARGB(tls, ((*WebPPicture)(unsafe.Pointer(pic)).argb + uintptr(off)*4), argb_value, (*WebPPicture)(unsafe.Pointer(pic)).argb_stride, 8) + } else { + need_reset = 1 + } + } + } + } else { + var width int32 = (*WebPPicture)(unsafe.Pointer(pic)).width + var height int32 = (*WebPPicture)(unsafe.Pointer(pic)).height + var y_stride int32 = (*WebPPicture)(unsafe.Pointer(pic)).y_stride + var uv_stride int32 = (*WebPPicture)(unsafe.Pointer(pic)).uv_stride + var a_stride int32 = (*WebPPicture)(unsafe.Pointer(pic)).a_stride + var y_ptr uintptr = (*WebPPicture)(unsafe.Pointer(pic)).y + var u_ptr uintptr = (*WebPPicture)(unsafe.Pointer(pic)).u + var v_ptr uintptr = (*WebPPicture)(unsafe.Pointer(pic)).v + var a_ptr uintptr = (*WebPPicture)(unsafe.Pointer(pic)).a + *(*[3]int32)(unsafe.Pointer(bp /* values */)) = [3]int32{0: 0} + if (((a_ptr == (uintptr(0))) || (y_ptr == (uintptr(0)))) || (u_ptr == (uintptr(0)))) || (v_ptr == (uintptr(0))) { + return + } + for y = 0; (y + 8) <= height; y = y + (8) { + var need_reset int32 = 1 + for x = 0; (x + 8) <= width; x = x + (8) { + if SmoothenBlock(tls, (a_ptr+uintptr(x)), a_stride, (y_ptr+uintptr(x)), y_stride, + 8, 8) != 0 { + if need_reset != 0 { + *(*int32)(unsafe.Pointer((bp) /* &values[0] */)) = int32(*(*uint8_t)(unsafe.Pointer(y_ptr + uintptr(x)))) + *(*int32)(unsafe.Pointer((bp) /* &values[0] */ + 1*4)) = int32(*(*uint8_t)(unsafe.Pointer(u_ptr + uintptr((x >> 1))))) + *(*int32)(unsafe.Pointer((bp) /* &values[0] */ + 2*4)) = int32(*(*uint8_t)(unsafe.Pointer(v_ptr + uintptr((x >> 1))))) + need_reset = 0 + } + Flatten(tls, (y_ptr + uintptr(x)), *(*int32)(unsafe.Pointer((bp) /* &values[0] */)), y_stride, 8) + Flatten(tls, (u_ptr + uintptr((x >> 1))), *(*int32)(unsafe.Pointer((bp) /* &values[0] */ + 1*4)), uv_stride, (8 / 2)) + Flatten(tls, (v_ptr + uintptr((x >> 1))), *(*int32)(unsafe.Pointer((bp) /* &values[0] */ + 2*4)), uv_stride, (8 / 2)) + } else { + need_reset = 1 + } + } + if x < width { + SmoothenBlock(tls, (a_ptr + uintptr(x)), a_stride, (y_ptr + uintptr(x)), y_stride, + (width - x), 8) + } + a_ptr += (uintptr(8 * a_stride)) + y_ptr += (uintptr(8 * y_stride)) + u_ptr += (uintptr((8 / 2) * uv_stride)) + v_ptr += (uintptr((8 / 2) * uv_stride)) + } + if y < height { + var sub_height int32 = (height - y) + for x = 0; (x + 8) <= width; x = x + (8) { + SmoothenBlock(tls, (a_ptr + uintptr(x)), a_stride, (y_ptr + uintptr(x)), y_stride, + 8, sub_height) + } + if x < width { + SmoothenBlock(tls, (a_ptr + uintptr(x)), a_stride, (y_ptr + uintptr(x)), y_stride, + (width - x), sub_height) + } + } + } +} + +//------------------------------------------------------------------------------ +// Blend color and remove transparency info + +func MakeARGB321(tls *libc.TLS, r int32, g int32, b int32) uint32_t { /* picture_tools_enc.c:189:29: */ + return (((0xff000000 | (uint32(r << 16))) | (uint32(g << 8))) | uint32(b)) +} + +func WebPBlendAlpha(tls *libc.TLS, pic uintptr, background_rgb uint32_t) { /* picture_tools_enc.c:193:6: */ + var red int32 = (int32((background_rgb >> 16) & uint32_t(0xff))) + var green int32 = (int32((background_rgb >> 8) & uint32_t(0xff))) + var blue int32 = (int32((background_rgb >> 0) & uint32_t(0xff))) + var x int32 + var y int32 + if pic == (uintptr(0)) { + return + } + if !((*WebPPicture)(unsafe.Pointer(pic)).use_argb != 0) { + var uv_width int32 = ((*WebPPicture)(unsafe.Pointer(pic)).width >> 1) // omit last pixel during u/v loop + var Y0 int32 = VP8RGBToY(tls, red, green, blue, YUV_HALF) + // VP8RGBToU/V expects the u/v values summed over four pixels + var U0 int32 = VP8RGBToU(tls, (4 * red), (4 * green), (4 * blue), (4 * YUV_HALF)) + var V0 int32 = VP8RGBToV(tls, (4 * red), (4 * green), (4 * blue), (4 * YUV_HALF)) + var has_alpha int32 = (int32((*WebPPicture)(unsafe.Pointer(pic)).colorspace & WEBP_CSP_ALPHA_BIT)) + var y_ptr uintptr = (*WebPPicture)(unsafe.Pointer(pic)).y + var u_ptr uintptr = (*WebPPicture)(unsafe.Pointer(pic)).u + var v_ptr uintptr = (*WebPPicture)(unsafe.Pointer(pic)).v + var a_ptr uintptr = (*WebPPicture)(unsafe.Pointer(pic)).a + if !(has_alpha != 0) || (a_ptr == (uintptr(0))) { + return + } // nothing to do + for y = 0; y < (*WebPPicture)(unsafe.Pointer(pic)).height; y++ { + // Luma blending + for x = 0; x < (*WebPPicture)(unsafe.Pointer(pic)).width; x++ { + var alpha uint8_t = *(*uint8_t)(unsafe.Pointer(a_ptr + uintptr(x))) + if int32(alpha) < 0xff { + *(*uint8_t)(unsafe.Pointer(y_ptr + uintptr(x))) = (uint8_t((((((Y0) * (255 - (int32(alpha)))) + ((int32(*(*uint8_t)(unsafe.Pointer(y_ptr + uintptr(x))))) * (int32(alpha)))) * 0x101) + 256) >> 16)) + } + } + // Chroma blending every even line + if (y & 1) == 0 { + var a_ptr2 uintptr + if (y + 1) == (*WebPPicture)(unsafe.Pointer(pic)).height { + a_ptr2 = a_ptr + } else { + a_ptr2 = (a_ptr + uintptr((*WebPPicture)(unsafe.Pointer(pic)).a_stride)) + } + for x = 0; x < uv_width; x++ { + // Average four alpha values into a single blending weight. + // TODO(skal): might lead to visible contouring. Can we do better? + var alpha uint32_t = (uint32_t(((int32(*(*uint8_t)(unsafe.Pointer(a_ptr + uintptr(((2 * x) + 0))))) + int32(*(*uint8_t)(unsafe.Pointer(a_ptr + uintptr(((2 * x) + 1)))))) + int32(*(*uint8_t)(unsafe.Pointer(a_ptr2 + uintptr(((2 * x) + 0)))))) + int32(*(*uint8_t)(unsafe.Pointer(a_ptr2 + uintptr(((2 * x) + 1))))))) + *(*uint8_t)(unsafe.Pointer(u_ptr + uintptr(x))) = (uint8_t((((((uint32_t(U0)) * (uint32_t(1020) - (alpha))) + ((uint32_t(*(*uint8_t)(unsafe.Pointer(u_ptr + uintptr(x))))) * (alpha))) * uint32_t(0x101)) + uint32_t(1024)) >> 18)) + *(*uint8_t)(unsafe.Pointer(v_ptr + uintptr(x))) = (uint8_t((((((uint32_t(V0)) * (uint32_t(1020) - (alpha))) + ((uint32_t(*(*uint8_t)(unsafe.Pointer(v_ptr + uintptr(x))))) * (alpha))) * uint32_t(0x101)) + uint32_t(1024)) >> 18)) + } + if ((*WebPPicture)(unsafe.Pointer(pic)).width & 1) != 0 { // rightmost pixel + var alpha uint32_t = (uint32_t(2 * (int32(*(*uint8_t)(unsafe.Pointer(a_ptr + uintptr(((2 * x) + 0))))) + int32(*(*uint8_t)(unsafe.Pointer(a_ptr2 + uintptr(((2 * x) + 0)))))))) + *(*uint8_t)(unsafe.Pointer(u_ptr + uintptr(x))) = (uint8_t((((((uint32_t(U0)) * (uint32_t(1020) - (alpha))) + ((uint32_t(*(*uint8_t)(unsafe.Pointer(u_ptr + uintptr(x))))) * (alpha))) * uint32_t(0x101)) + uint32_t(1024)) >> 18)) + *(*uint8_t)(unsafe.Pointer(v_ptr + uintptr(x))) = (uint8_t((((((uint32_t(V0)) * (uint32_t(1020) - (alpha))) + ((uint32_t(*(*uint8_t)(unsafe.Pointer(v_ptr + uintptr(x))))) * (alpha))) * uint32_t(0x101)) + uint32_t(1024)) >> 18)) + } + } else { + u_ptr += uintptr((*WebPPicture)(unsafe.Pointer(pic)).uv_stride) + v_ptr += uintptr((*WebPPicture)(unsafe.Pointer(pic)).uv_stride) + } + libc.Xmemset(tls, a_ptr, 0xff, uint64((*WebPPicture)(unsafe.Pointer(pic)).width)) // reset alpha value to opaque + a_ptr += uintptr((*WebPPicture)(unsafe.Pointer(pic)).a_stride) + y_ptr += uintptr((*WebPPicture)(unsafe.Pointer(pic)).y_stride) + } + } else { + var argb uintptr = (*WebPPicture)(unsafe.Pointer(pic)).argb + var background uint32_t = MakeARGB321(tls, red, green, blue) + for y = 0; y < (*WebPPicture)(unsafe.Pointer(pic)).height; y++ { + for x = 0; x < (*WebPPicture)(unsafe.Pointer(pic)).width; x++ { + var alpha int32 = (int32((*(*uint32_t)(unsafe.Pointer(argb + uintptr(x)*4)) >> 24) & uint32_t(0xff))) + if alpha != 0xff { + if alpha > 0 { + var r int32 = (int32((*(*uint32_t)(unsafe.Pointer(argb + uintptr(x)*4)) >> 16) & uint32_t(0xff))) + var g int32 = (int32((*(*uint32_t)(unsafe.Pointer(argb + uintptr(x)*4)) >> 8) & uint32_t(0xff))) + var b int32 = (int32((*(*uint32_t)(unsafe.Pointer(argb + uintptr(x)*4)) >> 0) & uint32_t(0xff))) + r = ((((((red) * (255 - (alpha))) + ((r) * (alpha))) * 0x101) + 256) >> 16) + g = ((((((green) * (255 - (alpha))) + ((g) * (alpha))) * 0x101) + 256) >> 16) + b = ((((((blue) * (255 - (alpha))) + ((b) * (alpha))) * 0x101) + 256) >> 16) + *(*uint32_t)(unsafe.Pointer(argb + uintptr(x)*4)) = MakeARGB321(tls, r, g, b) + } else { + *(*uint32_t)(unsafe.Pointer(argb + uintptr(x)*4)) = background + } + } + } + argb += 4 * (uintptr((*WebPPicture)(unsafe.Pointer(pic)).argb_stride)) + } + } +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +var kSpatialPredictorBias float32 = 15. /* predictor_enc.c:23:20 */ +var kPredLowEffort int32 = 11 /* predictor_enc.c:24:18 */ +var kMaskAlpha uint32_t = 0xff000000 /* predictor_enc.c:25:23 */ + +// Mostly used to reduce code size + readability +func GetMin(tls *libc.TLS, a int32, b int32) int32 { /* predictor_enc.c:28:24: */ + if a > b { + return b + } + return a +} + +//------------------------------------------------------------------------------ +// Methods to calculate Entropy (Shannon). + +func PredictionCostSpatial(tls *libc.TLS, counts uintptr, weight_0 int32, exp_val float64) float32 { /* predictor_enc.c:33:14: */ + var significant_symbols int32 = (int32(256) >> 4) + var exp_decay_factor float64 = 0.6 + var bits float64 = (float64(weight_0 * *(*int32)(unsafe.Pointer(counts)))) + var i int32 + for i = 1; i < significant_symbols; i++ { + bits = bits + (exp_val * (float64(*(*int32)(unsafe.Pointer(counts + uintptr(i)*4)) + *(*int32)(unsafe.Pointer(counts + uintptr((256-i))*4))))) + exp_val = exp_val * (exp_decay_factor) + } + return (float32(-0.1 * bits)) +} + +func PredictionCostSpatialHistogram(tls *libc.TLS, accumulated uintptr, tile uintptr) float32 { /* predictor_enc.c:46:14: */ + var i int32 + var retval float64 = float64(0) + for i = 0; i < 4; i++ { + var kExpValue float64 = 0.94 + retval = retval + (float64(PredictionCostSpatial(tls, (tile + uintptr(i)*1024), 1, kExpValue))) + retval = retval + (float64((*struct { + f func(*libc.TLS, uintptr, uintptr) float32 + })(unsafe.Pointer(&struct{ uintptr }{VP8LCombinedShannonEntropy})).f(tls, (tile + uintptr(i)*1024), (accumulated + uintptr(i)*1024)))) + } + return float32(retval) +} + +func UpdateHisto(tls *libc.TLS, histo_argb uintptr, argb uint32_t) { /* predictor_enc.c:58:25: */ + *(*int32)(unsafe.Pointer((histo_argb) + uintptr((argb>>24))*4))++ + *(*int32)(unsafe.Pointer((histo_argb + 1*1024) + uintptr(((argb>>16)&uint32_t(0xff)))*4))++ + *(*int32)(unsafe.Pointer((histo_argb + 2*1024) + uintptr(((argb>>8)&uint32_t(0xff)))*4))++ + *(*int32)(unsafe.Pointer((histo_argb + 3*1024) + uintptr((argb&uint32_t(0xff)))*4))++ +} + +//------------------------------------------------------------------------------ +// Spatial transform functions. + +func PredictBatch(tls *libc.TLS, mode int32, x_start int32, y int32, num_pixels int32, current uintptr, upper uintptr, out uintptr) { /* predictor_enc.c:68:25: */ + if x_start == 0 { + if y == 0 { + // ARGB_BLACK. + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LPredictorsSub[0]})).f(tls, current, (uintptr(0)), 1, out) + } else { + // Top one. + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LPredictorsSub[2]})).f(tls, current, upper, 1, out) + } + x_start++ + out += 4 + num_pixels-- + } + if y == 0 { + // Left one. + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LPredictorsSub[1]})).f(tls, (current + uintptr(x_start)*4), (uintptr(0)), num_pixels, out) + } else { + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LPredictorsSub[mode]})).f(tls, (current + uintptr(x_start)*4), (upper + uintptr(x_start)*4), num_pixels, + out) + } +} + +func GetMax(tls *libc.TLS, a int32, b int32) int32 { /* predictor_enc.c:93:24: */ + if a < b { + return b + } + return a +} + +func MaxDiffBetweenPixels(tls *libc.TLS, p1 uint32_t, p2 uint32_t) int32 { /* predictor_enc.c:95:12: */ + var diff_a int32 = libc.Xabs(tls, ((int32(p1 >> 24)) - (int32(p2 >> 24)))) + var diff_r int32 = libc.Xabs(tls, ((int32((p1 >> 16) & uint32_t(0xff))) - (int32((p2 >> 16) & uint32_t(0xff))))) + var diff_g int32 = libc.Xabs(tls, ((int32((p1 >> 8) & uint32_t(0xff))) - (int32((p2 >> 8) & uint32_t(0xff))))) + var diff_b int32 = libc.Xabs(tls, ((int32(p1 & uint32_t(0xff))) - (int32(p2 & uint32_t(0xff))))) + return GetMax(tls, GetMax(tls, diff_a, diff_r), GetMax(tls, diff_g, diff_b)) +} + +func MaxDiffAroundPixel(tls *libc.TLS, current uint32_t, up uint32_t, down uint32_t, left uint32_t, right uint32_t) int32 { /* predictor_enc.c:103:12: */ + var diff_up int32 = MaxDiffBetweenPixels(tls, current, up) + var diff_down int32 = MaxDiffBetweenPixels(tls, current, down) + var diff_left int32 = MaxDiffBetweenPixels(tls, current, left) + var diff_right int32 = MaxDiffBetweenPixels(tls, current, right) + return GetMax(tls, GetMax(tls, diff_up, diff_down), GetMax(tls, diff_left, diff_right)) +} + +func AddGreenToBlueAndRed(tls *libc.TLS, argb uint32_t) uint32_t { /* predictor_enc.c:112:17: */ + var green uint32_t = ((argb >> 8) & uint32_t(0xff)) + var red_blue uint32_t = (argb & 0x00ff00ff) + red_blue = red_blue + ((green << 16) | green) + red_blue = red_blue & (0x00ff00ff) + return ((argb & 0xff00ff00) | red_blue) +} + +func MaxDiffsForRow(tls *libc.TLS, width int32, stride int32, argb uintptr, max_diffs uintptr, used_subtract_green int32) { /* predictor_enc.c:120:13: */ + var current uint32_t + var up uint32_t + var down uint32_t + var left uint32_t + var right uint32_t + var x int32 + if width <= 2 { + return + } + current = *(*uint32_t)(unsafe.Pointer(argb)) + right = *(*uint32_t)(unsafe.Pointer(argb + 1*4)) + if used_subtract_green != 0 { + current = AddGreenToBlueAndRed(tls, current) + right = AddGreenToBlueAndRed(tls, right) + } + // max_diffs[0] and max_diffs[width - 1] are never used. + for x = 1; x < (width - 1); x++ { + up = *(*uint32_t)(unsafe.Pointer(argb + uintptr((-stride+x))*4)) + down = *(*uint32_t)(unsafe.Pointer(argb + uintptr((stride+x))*4)) + left = current + current = right + right = *(*uint32_t)(unsafe.Pointer(argb + uintptr((x+1))*4)) + if used_subtract_green != 0 { + up = AddGreenToBlueAndRed(tls, up) + down = AddGreenToBlueAndRed(tls, down) + right = AddGreenToBlueAndRed(tls, right) + } + *(*uint8_t)(unsafe.Pointer(max_diffs + uintptr(x))) = uint8_t(MaxDiffAroundPixel(tls, current, up, down, left, right)) + } +} + +// Quantize the difference between the actual component value and its prediction +// to a multiple of quantization, working modulo 256, taking care not to cross +// a boundary (inclusive upper limit). +func NearLosslessComponent(tls *libc.TLS, value uint8_t, predict uint8_t, boundary uint8_t, quantization int32) uint8_t { /* predictor_enc.c:150:16: */ + var residual int32 = ((int32(value) - int32(predict)) & 0xff) + var boundary_residual int32 = ((int32(boundary) - int32(predict)) & 0xff) + var lower int32 = (residual & ^(quantization - 1)) + var upper int32 = (lower + quantization) + // Resolve ties towards a value closer to the prediction (i.e. towards lower + // if value comes after prediction and towards upper otherwise). + var bias int32 = (libc.Bool32(((int32(boundary) - int32(value)) & 0xff) < boundary_residual)) + if (residual - lower) < ((upper - residual) + bias) { + // lower is closer to residual than upper. + if (residual > boundary_residual) && (lower <= boundary_residual) { + // Halve quantization step to avoid crossing boundary. This midpoint is + // on the same side of boundary as residual because midpoint >= residual + // (since lower is closer than upper) and residual is above the boundary. + return (uint8_t(lower + (quantization >> 1))) + } + return uint8_t(lower) + } else { + // upper is closer to residual than lower. + if (residual <= boundary_residual) && (upper > boundary_residual) { + // Halve quantization step to avoid crossing boundary. This midpoint is + // on the same side of boundary as residual because midpoint <= residual + // (since upper is closer than lower) and residual is below the boundary. + return (uint8_t(lower + (quantization >> 1))) + } + return (uint8_t(upper & 0xff)) + } + return uint8_t(0) +} + +func NearLosslessDiff(tls *libc.TLS, a uint8_t, b uint8_t) uint8_t { /* predictor_enc.c:180:28: */ + return (uint8_t(((int32(a)) - (int32(b))) & 0xff)) +} + +// Quantize every component of the difference between the actual pixel value and +// its prediction to a multiple of a quantization (a power of 2, not larger than +// max_quantization which is a power of 2, smaller than max_diff). Take care if +// value and predict have undergone subtract green, which means that red and +// blue are represented as offsets from green. +func NearLossless1(tls *libc.TLS, value uint32_t, predict uint32_t, max_quantization int32, max_diff int32, used_subtract_green int32) uint32_t { /* predictor_enc.c:189:17: */ + var quantization int32 + var new_green uint8_t = uint8_t(0) + var green_diff uint8_t = uint8_t(0) + var a uint8_t + var r uint8_t + var g uint8_t + var b uint8_t + if max_diff <= 2 { + return VP8LSubPixels(tls, value, predict) + } + quantization = max_quantization + for quantization >= max_diff { + quantization >>= 1 + } + if ((value >> 24) == uint32_t(0)) || ((value >> 24) == uint32_t(0xff)) { + // Preserve transparency of fully transparent or fully opaque pixels. + a = NearLosslessDiff(tls, (uint8((value >> 24) & uint32_t(0xff))), (uint8((predict >> 24) & uint32_t(0xff)))) + } else { + a = NearLosslessComponent(tls, (uint8(value >> 24)), (uint8(predict >> 24)), uint8(0xff), quantization) + } + g = NearLosslessComponent(tls, (uint8((value >> 8) & uint32_t(0xff))), (uint8((predict >> 8) & uint32_t(0xff))), uint8(0xff), + quantization) + if used_subtract_green != 0 { + // The green offset will be added to red and blue components during decoding + // to obtain the actual red and blue values. + new_green = (uint8_t(((predict >> 8) + uint32_t(g)) & uint32_t(0xff))) + // The amount by which green has been adjusted during quantization. It is + // subtracted from red and blue for compensation, to avoid accumulating two + // quantization errors in them. + green_diff = NearLosslessDiff(tls, new_green, (uint8((value >> 8) & uint32_t(0xff)))) + } + r = NearLosslessComponent(tls, NearLosslessDiff(tls, (uint8((value>>16)&uint32_t(0xff))), green_diff), + (uint8((predict >> 16) & uint32_t(0xff))), (uint8(0xff - int32(new_green))), + quantization) + b = NearLosslessComponent(tls, NearLosslessDiff(tls, (uint8(value&uint32_t(0xff))), green_diff), + (uint8(predict & uint32_t(0xff))), (uint8(0xff - int32(new_green))), quantization) + return ((((uint32_t(a) << 24) | (uint32_t(r) << 16)) | (uint32_t(g) << 8)) | uint32_t(b)) +} + +// Stores the difference between the pixel and its prediction in "out". +// In case of a lossy encoding, updates the source image to avoid propagating +// the deviation further to pixels which depend on the current pixel for their +// predictions. +func GetResidual(tls *libc.TLS, width int32, height int32, upper_row uintptr, current_row uintptr, max_diffs uintptr, mode int32, x_start int32, x_end int32, y int32, max_quantization int32, exact int32, used_subtract_green int32, out uintptr) { /* predictor_enc.c:233:25: */ + if exact != 0 { + PredictBatch(tls, mode, x_start, y, (x_end - x_start), current_row, upper_row, + out) + } else { + var pred_func VP8LPredictorFunc = VP8LPredictors[mode] + var x int32 + for x = x_start; x < x_end; x++ { + var predict uint32_t + var residual uint32_t + if y == 0 { + if x == 0 { + predict = 0xff000000 + } else { + predict = *(*uint32_t)(unsafe.Pointer(current_row + uintptr((x-1))*4)) + } // Left. + } else if x == 0 { + predict = *(*uint32_t)(unsafe.Pointer(upper_row + uintptr(x)*4)) // Top. + } else { + predict = (*struct { + f func(*libc.TLS, uintptr, uintptr) uint32_t + })(unsafe.Pointer(&struct{ uintptr }{pred_func})).f(tls, (current_row + uintptr((x-1))*4), (upper_row + uintptr(x)*4)) + } + if (((((max_quantization == 1) || (mode == 0)) || (y == 0)) || (y == (height - 1))) || (x == 0)) || (x == (width - 1)) { + residual = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(current_row + uintptr(x)*4)), predict) + } else { + residual = NearLossless1(tls, *(*uint32_t)(unsafe.Pointer(current_row + uintptr(x)*4)), predict, max_quantization, + int32(*(*uint8_t)(unsafe.Pointer(max_diffs + uintptr(x)))), used_subtract_green) + // Update the source image. + *(*uint32_t)(unsafe.Pointer(current_row + uintptr(x)*4)) = VP8LAddPixels(tls, predict, residual) + // x is never 0 here so we do not need to update upper_row like below. + } + if (*(*uint32_t)(unsafe.Pointer(current_row + uintptr(x)*4)) & kMaskAlpha) == uint32_t(0) { + // If alpha is 0, cleanup RGB. We can choose the RGB values of the + // residual for best compression. The prediction of alpha itself can be + // non-zero and must be kept though. We choose RGB of the residual to be + // 0. + residual = residual & (kMaskAlpha) + // Update the source image. + *(*uint32_t)(unsafe.Pointer(current_row + uintptr(x)*4)) = (predict & ^kMaskAlpha) + // The prediction for the rightmost pixel in a row uses the leftmost + // pixel + // in that row as its top-right context pixel. Hence if we change the + // leftmost pixel of current_row, the corresponding change must be + // applied + // to upper_row as well where top-right context is being read from. + if (x == 0) && (y != 0) { + *(*uint32_t)(unsafe.Pointer(upper_row + uintptr(width)*4)) = *(*uint32_t)(unsafe.Pointer(current_row)) + } + } + *(*uint32_t)(unsafe.Pointer(out + uintptr((x-x_start))*4)) = residual + } + } +} + +// Returns best predictor and updates the accumulated histogram. +// If max_quantization > 1, assumes that near lossless processing will be +// applied, quantizing residuals to multiples of quantization levels up to +// max_quantization (the actual quantization level depends on smoothness near +// the given pixel). +func GetBestPredictorForTile(tls *libc.TLS, width int32, height int32, tile_x int32, tile_y int32, bits int32, accumulated uintptr, argb_scratch uintptr, argb uintptr, max_quantization int32, exact int32, used_subtract_green int32, modes uintptr) int32 { /* predictor_enc.c:298:12: */ + bp := tls.Alloc(8448) + defer tls.Free(8448) + + var kNumPredModes int32 = 14 + var start_x int32 = (tile_x << bits) + var start_y int32 = (tile_y << bits) + var tile_size int32 = (int32(1) << bits) + var max_y int32 = GetMin(tls, tile_size, (height - start_y)) + var max_x int32 = GetMin(tls, tile_size, (width - start_x)) + // Whether there exist columns just outside the tile. + var have_left int32 = (libc.Bool32(start_x > 0)) + // Position and size of the strip covering the tile and adjacent columns if + // they exist. + var context_start_x int32 = (start_x - have_left) + var context_width int32 = ((max_x + have_left) + (libc.Bool32(max_x < (width - start_x)))) + var tiles_per_row int32 = int32(VP8LSubSampleSize(tls, uint32(width), uint32(bits))) + // Prediction modes of the left and above neighbor tiles. + var left_mode int32 + if tile_x > 0 { + left_mode = (int32((*(*uint32_t)(unsafe.Pointer(modes + uintptr((((tile_y*tiles_per_row)+tile_x)-1))*4)) >> 8) & uint32_t(0xff))) + } else { + left_mode = 0xff + } + var above_mode int32 + if tile_y > 0 { + above_mode = (int32((*(*uint32_t)(unsafe.Pointer(modes + uintptr((((tile_y-1)*tiles_per_row)+tile_x))*4)) >> 8) & uint32_t(0xff))) + } else { + above_mode = 0xff + } + // The width of upper_row and current_row is one pixel larger than image width + // to allow the top right pixel to point to the leftmost pixel of the next row + // when at the right edge. + var upper_row uintptr = argb_scratch + var current_row uintptr = ((upper_row + uintptr(width)*4) + uintptr(1)*4) + var max_diffs uintptr = ((current_row + uintptr(width)*4) + uintptr(1)*4) + var best_diff float32 = (1e30) + var best_mode int32 = 0 + var mode int32 + // var histo_stack_1 [4][256]int32 at bp, 4096 + + // var histo_stack_2 [4][256]int32 at bp+4096, 4096 + + // Need pointers to be able to swap arrays. + var histo_argb uintptr = (bp) /* histo_stack_1 */ + var best_histo uintptr = (bp + 4096) /* histo_stack_2 */ + var i int32 + var j int32 + // var residuals [64]uint32_t at bp+8192, 256 + + for mode = 0; mode < kNumPredModes; mode++ { + var cur_diff float32 + var relative_y int32 + libc.Xmemset(tls, histo_argb, 0, uint64(unsafe.Sizeof([4][256]int32{}))) + if start_y > 0 { + // Read the row above the tile which will become the first upper_row. + // Include a pixel to the left if it exists; include a pixel to the right + // in all cases (wrapping to the leftmost pixel of the next row if it does + // not exist). + libc.Xmemcpy(tls, (current_row + uintptr(context_start_x)*4), + ((argb + uintptr(((start_y-1)*width))*4) + uintptr(context_start_x)*4), + (uint64(unsafe.Sizeof(uint32_t(0))) * (uint64((max_x + have_left) + 1)))) + } + for relative_y = 0; relative_y < max_y; relative_y++ { + var y int32 = (start_y + relative_y) + var relative_x int32 + var tmp uintptr = upper_row + upper_row = current_row + current_row = tmp + // Read current_row. Include a pixel to the left if it exists; include a + // pixel to the right in all cases except at the bottom right corner of + // the image (wrapping to the leftmost pixel of the next row if it does + // not exist in the current row). + libc.Xmemcpy(tls, (current_row + uintptr(context_start_x)*4), + ((argb + uintptr((y*width))*4) + uintptr(context_start_x)*4), + (uint64(unsafe.Sizeof(uint32_t(0))) * (uint64((max_x + have_left) + (libc.Bool32((y + 1) < height)))))) + if ((max_quantization > 1) && (y >= 1)) && ((y + 1) < height) { + MaxDiffsForRow(tls, context_width, width, ((argb + uintptr((y*width))*4) + uintptr(context_start_x)*4), + (max_diffs + uintptr(context_start_x)), used_subtract_green) + } + + GetResidual(tls, width, height, upper_row, current_row, max_diffs, mode, + start_x, (start_x + max_x), y, max_quantization, exact, + used_subtract_green, (bp + 8192) /* &residuals[0] */) + for relative_x = 0; relative_x < max_x; relative_x++ { + UpdateHisto(tls, histo_argb, *(*uint32_t)(unsafe.Pointer((bp + 8192) /* &residuals[0] */ + uintptr(relative_x)*4))) + } + } + cur_diff = PredictionCostSpatialHistogram(tls, + accumulated, histo_argb) + // Favor keeping the areas locally similar. + if mode == left_mode { + cur_diff = cur_diff - (kSpatialPredictorBias) + } + if mode == above_mode { + cur_diff = cur_diff - (kSpatialPredictorBias) + } + + if cur_diff < best_diff { + var tmp uintptr = histo_argb + histo_argb = best_histo + best_histo = tmp + best_diff = cur_diff + best_mode = mode + } + } + + for i = 0; i < 4; i++ { + for j = 0; j < 256; j++ { + *(*int32)(unsafe.Pointer(((accumulated + uintptr(i)*1024) + uintptr(j)*4))) += (*(*int32)(unsafe.Pointer((best_histo + uintptr(i)*1024) + uintptr(j)*4))) + } + } + + return best_mode +} + +// Converts pixels of the image to residuals with respect to predictions. +// If max_quantization > 1, applies near lossless processing, quantizing +// residuals to multiples of quantization levels up to max_quantization +// (the actual quantization level depends on smoothness near the given pixel). +func CopyImageWithPrediction(tls *libc.TLS, width int32, height int32, bits int32, modes uintptr, argb_scratch uintptr, argb uintptr, low_effort int32, max_quantization int32, exact int32, used_subtract_green int32) { /* predictor_enc.c:413:13: */ + var tiles_per_row int32 = int32(VP8LSubSampleSize(tls, uint32(width), uint32(bits))) + // The width of upper_row and current_row is one pixel larger than image width + // to allow the top right pixel to point to the leftmost pixel of the next row + // when at the right edge. + var upper_row uintptr = argb_scratch + var current_row uintptr = ((upper_row + uintptr(width)*4) + uintptr(1)*4) + var current_max_diffs uintptr = ((current_row + uintptr(width)*4) + uintptr(1)*4) + var lower_max_diffs uintptr = (current_max_diffs + uintptr(width)) + var y int32 + + for y = 0; y < height; y++ { + var x int32 + var tmp32 uintptr = upper_row + upper_row = current_row + current_row = tmp32 + libc.Xmemcpy(tls, current_row, (argb + uintptr((y*width))*4), + (uint64(unsafe.Sizeof(uint32_t(0))) * (uint64(width + (libc.Bool32((y + 1) < height)))))) + + if low_effort != 0 { + PredictBatch(tls, kPredLowEffort, 0, y, width, current_row, upper_row, + (argb + uintptr((y*width))*4)) + } else { + if max_quantization > 1 { + // Compute max_diffs for the lower row now, because that needs the + // contents of argb for the current row, which we will overwrite with + // residuals before proceeding with the next row. + var tmp8 uintptr = current_max_diffs + current_max_diffs = lower_max_diffs + lower_max_diffs = tmp8 + if (y + 2) < height { + MaxDiffsForRow(tls, width, width, (argb + uintptr(((y+1)*width))*4), lower_max_diffs, + used_subtract_green) + } + } + for x = 0; x < width; { + var mode int32 = (int32((*(*uint32_t)(unsafe.Pointer(modes + uintptr((((y>>bits)*tiles_per_row)+(x>>bits)))*4)) >> 8) & uint32_t(0xff))) + var x_end int32 = (x + (int32(1) << bits)) + if x_end > width { + x_end = width + } + GetResidual(tls, width, height, upper_row, current_row, current_max_diffs, + mode, x, x_end, y, max_quantization, exact, + used_subtract_green, ((argb + uintptr((y*width))*4) + uintptr(x)*4)) + x = x_end + } + } + } +} + +// Finds the best predictor for each tile, and converts the image to residuals +// with respect to predictions. If near_lossless_quality < 100, applies +// near lossless processing, shaving off more bits of residuals for lower +// qualities. +func VP8LResidualImage(tls *libc.TLS, width int32, height int32, bits int32, low_effort int32, argb uintptr, argb_scratch uintptr, image uintptr, near_lossless_quality int32, exact int32, used_subtract_green int32) { /* predictor_enc.c:475:6: */ + bp := tls.Alloc(4096) + defer tls.Free(4096) + + var tiles_per_row int32 = int32(VP8LSubSampleSize(tls, uint32(width), uint32(bits))) + var tiles_per_col int32 = int32(VP8LSubSampleSize(tls, uint32(height), uint32(bits))) + var tile_y int32 + // var histo [4][256]int32 at bp, 4096 + + var max_quantization int32 = (int32(1) << VP8LNearLosslessBits(tls, near_lossless_quality)) + if low_effort != 0 { + var i int32 + for i = 0; i < (tiles_per_row * tiles_per_col); i++ { + *(*uint32_t)(unsafe.Pointer(image + uintptr(i)*4)) = (0xff000000 | (uint32(kPredLowEffort << 8))) + } + } else { + libc.Xmemset(tls, (bp) /* &histo[0] */, 0, uint64(unsafe.Sizeof([4][256]int32{}))) + for tile_y = 0; tile_y < tiles_per_col; tile_y++ { + var tile_x int32 + for tile_x = 0; tile_x < tiles_per_row; tile_x++ { + var pred int32 = GetBestPredictorForTile(tls, width, height, tile_x, tile_y, + bits, (bp) /* &histo[0] */, argb_scratch, argb, max_quantization, exact, + used_subtract_green, image) + *(*uint32_t)(unsafe.Pointer(image + uintptr(((tile_y*tiles_per_row)+tile_x))*4)) = (0xff000000 | (uint32(pred << 8))) + } + } + } + + CopyImageWithPrediction(tls, width, height, bits, image, argb_scratch, argb, + low_effort, max_quantization, exact, + used_subtract_green) +} + +//------------------------------------------------------------------------------ +// Color transform functions. + +func MultipliersClear(tls *libc.TLS, m uintptr) { /* predictor_enc.c:510:25: */ + (*VP8LMultipliers)(unsafe.Pointer(m)).green_to_red_ = uint8_t(0) + (*VP8LMultipliers)(unsafe.Pointer(m)).green_to_blue_ = uint8_t(0) + (*VP8LMultipliers)(unsafe.Pointer(m)).red_to_blue_ = uint8_t(0) +} + +func ColorCodeToMultipliers1(tls *libc.TLS, color_code uint32_t, m uintptr) { /* predictor_enc.c:516:25: */ + (*VP8LMultipliers)(unsafe.Pointer(m)).green_to_red_ = (uint8_t((color_code >> 0) & uint32_t(0xff))) + (*VP8LMultipliers)(unsafe.Pointer(m)).green_to_blue_ = (uint8_t((color_code >> 8) & uint32_t(0xff))) + (*VP8LMultipliers)(unsafe.Pointer(m)).red_to_blue_ = (uint8_t((color_code >> 16) & uint32_t(0xff))) +} + +func MultipliersToColorCode(tls *libc.TLS, m uintptr) uint32_t { /* predictor_enc.c:523:29: */ + return (((0xff000000 | ((uint32_t((*VP8LMultipliers)(unsafe.Pointer(m)).red_to_blue_)) << 16)) | ((uint32_t((*VP8LMultipliers)(unsafe.Pointer(m)).green_to_blue_)) << 8)) | uint32((*VP8LMultipliers)(unsafe.Pointer(m)).green_to_red_)) +} + +func PredictionCostCrossColor(tls *libc.TLS, accumulated uintptr, counts uintptr) float32 { /* predictor_enc.c:531:14: */ + return ((*struct { + f func(*libc.TLS, uintptr, uintptr) float32 + })(unsafe.Pointer(&struct{ uintptr }{VP8LCombinedShannonEntropy})).f(tls, counts, accumulated) + PredictionCostSpatial(tls, counts, 3, kExpValue)) +} + +var kExpValue float64 = 2.4 /* predictor_enc.c:535:23 */ + +func GetPredictionCostCrossColorRed(tls *libc.TLS, argb uintptr, stride int32, tile_width int32, tile_height int32, prev_x VP8LMultipliers, prev_y VP8LMultipliers, green_to_red int32, accumulated_red_histo uintptr) float32 { /* predictor_enc.c:540:14: */ + bp := tls.Alloc(1024) + defer tls.Free(1024) + + *(*[256]int32)(unsafe.Pointer(bp /* histo */)) = [256]int32{0: 0} + var cur_diff float32 + + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LCollectColorRedTransforms})).f(tls, argb, stride, tile_width, tile_height, + green_to_red, (bp) /* &histo[0] */) + + cur_diff = PredictionCostCrossColor(tls, accumulated_red_histo, (bp) /* &histo[0] */) + if int32(uint8_t(green_to_red)) == int32(prev_x.green_to_red_) { + cur_diff = cur_diff - (float32(3)) // favor keeping the areas locally similar + } + if int32(uint8_t(green_to_red)) == int32(prev_y.green_to_red_) { + cur_diff = cur_diff - (float32(3)) // favor keeping the areas locally similar + } + if green_to_red == 0 { + cur_diff = cur_diff - (float32(3)) + } + return cur_diff +} + +func GetBestGreenToRed(tls *libc.TLS, argb uintptr, stride int32, tile_width int32, tile_height int32, prev_x VP8LMultipliers, prev_y VP8LMultipliers, quality int32, accumulated_red_histo uintptr, best_tx uintptr) { /* predictor_enc.c:563:13: */ + var kMaxIters int32 = (4 + ((7 * quality) >> 8)) // in range [4..6] + var green_to_red_best int32 = 0 + var iter int32 + var offset int32 + var best_diff float32 = GetPredictionCostCrossColorRed(tls, + argb, stride, tile_width, tile_height, prev_x, prev_y, + green_to_red_best, accumulated_red_histo) + for iter = 0; iter < kMaxIters; iter++ { + // ColorTransformDelta is a 3.5 bit fixed point, so 32 is equal to + // one in color computation. Having initial delta here as 1 is sufficient + // to explore the range of (-2, 2). + var delta int32 = (int32(32) >> iter) + // Try a negative and a positive delta from the best known value. + for offset = -delta; offset <= delta; offset = offset + (2 * delta) { + var green_to_red_cur int32 = (offset + green_to_red_best) + var cur_diff float32 = GetPredictionCostCrossColorRed(tls, + argb, stride, tile_width, tile_height, prev_x, prev_y, + green_to_red_cur, accumulated_red_histo) + if cur_diff < best_diff { + best_diff = cur_diff + green_to_red_best = green_to_red_cur + } + } + } + (*VP8LMultipliers)(unsafe.Pointer(best_tx)).green_to_red_ = (uint8_t(green_to_red_best & 0xff)) +} + +func GetPredictionCostCrossColorBlue(tls *libc.TLS, argb uintptr, stride int32, tile_width int32, tile_height int32, prev_x VP8LMultipliers, prev_y VP8LMultipliers, green_to_blue int32, red_to_blue int32, accumulated_blue_histo uintptr) float32 { /* predictor_enc.c:593:14: */ + bp := tls.Alloc(1024) + defer tls.Free(1024) + + *(*[256]int32)(unsafe.Pointer(bp /* histo */)) = [256]int32{0: 0} + var cur_diff float32 + + (*struct { + f func(*libc.TLS, uintptr, int32, int32, int32, int32, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LCollectColorBlueTransforms})).f(tls, argb, stride, tile_width, tile_height, + green_to_blue, red_to_blue, (bp) /* &histo[0] */) + + cur_diff = PredictionCostCrossColor(tls, accumulated_blue_histo, (bp) /* &histo[0] */) + if int32(uint8_t(green_to_blue)) == int32(prev_x.green_to_blue_) { + cur_diff = cur_diff - (float32(3)) // favor keeping the areas locally similar + } + if int32(uint8_t(green_to_blue)) == int32(prev_y.green_to_blue_) { + cur_diff = cur_diff - (float32(3)) // favor keeping the areas locally similar + } + if int32(uint8_t(red_to_blue)) == int32(prev_x.red_to_blue_) { + cur_diff = cur_diff - (float32(3)) // favor keeping the areas locally similar + } + if int32(uint8_t(red_to_blue)) == int32(prev_y.red_to_blue_) { + cur_diff = cur_diff - (float32(3)) // favor keeping the areas locally similar + } + if green_to_blue == 0 { + cur_diff = cur_diff - (float32(3)) + } + if red_to_blue == 0 { + cur_diff = cur_diff - (float32(3)) + } + return cur_diff +} + +func GetBestGreenRedToBlue(tls *libc.TLS, argb uintptr, stride int32, tile_width int32, tile_height int32, prev_x VP8LMultipliers, prev_y VP8LMultipliers, quality int32, accumulated_blue_histo uintptr, best_tx uintptr) { /* predictor_enc.c:627:13: */ + bp := tls.Alloc(23) + defer tls.Free(23) + + *(*[8][2]int8_t)(unsafe.Pointer(bp + 7 /* offset */)) = + [8][2]int8_t{[2]int8_t{int8(0), int8(-1)}, [2]int8_t{int8(0), int8(1)}, [2]int8_t{int8(-1), int8(0)}, [2]int8_t{int8(1), int8(0)}, [2]int8_t{int8(-1), int8(-1)}, [2]int8_t{int8(-1), int8(1)}, [2]int8_t{int8(1), int8(-1)}, [2]int8_t{int8(1), int8(1)}} + *(*[7]int8_t)(unsafe.Pointer(bp /* delta_lut */)) = [7]int8_t{int8(16), int8(16), int8(8), int8(4), int8(2), int8(2), int8(2)} + var iters int32 + if quality < 25 { + iters = 1 + } else { + if quality > 50 { + iters = 7 + } else { + iters = 4 + } + } + var green_to_blue_best int32 = 0 + var red_to_blue_best int32 = 0 + var iter int32 + // Initial value at origin: + var best_diff float32 = GetPredictionCostCrossColorBlue(tls, + argb, stride, tile_width, tile_height, prev_x, prev_y, + green_to_blue_best, red_to_blue_best, accumulated_blue_histo) + for iter = 0; iter < iters; iter++ { + var delta int32 = int32(*(*int8_t)(unsafe.Pointer((bp) /* &delta_lut[0] */ + uintptr(iter)))) + var axis int32 + for axis = 0; axis < 8; axis++ { + var green_to_blue_cur int32 = ((int32(*(*int8_t)(unsafe.Pointer(((bp + 7) /* &offset[0] */ + uintptr(axis)*2)))) * delta) + green_to_blue_best) + var red_to_blue_cur int32 = ((int32(*(*int8_t)(unsafe.Pointer(((bp + 7) /* &offset[0] */ + uintptr(axis)*2) + 1))) * delta) + red_to_blue_best) + var cur_diff float32 = GetPredictionCostCrossColorBlue(tls, + argb, stride, tile_width, tile_height, prev_x, prev_y, + green_to_blue_cur, red_to_blue_cur, accumulated_blue_histo) + if cur_diff < best_diff { + best_diff = cur_diff + green_to_blue_best = green_to_blue_cur + red_to_blue_best = red_to_blue_cur + } + if (quality < 25) && (iter == 4) { + // Only axis aligned diffs for lower quality. + break // next iter. + } + } + if ((delta == 2) && (green_to_blue_best == 0)) && (red_to_blue_best == 0) { + // Further iterations would not help. + break // out of iter-loop. + } + } + (*VP8LMultipliers)(unsafe.Pointer(best_tx)).green_to_blue_ = (uint8_t(green_to_blue_best & 0xff)) + (*VP8LMultipliers)(unsafe.Pointer(best_tx)).red_to_blue_ = (uint8_t(red_to_blue_best & 0xff)) +} + +func GetBestColorTransformForTile(tls *libc.TLS, tile_x int32, tile_y int32, bits int32, prev_x VP8LMultipliers, prev_y VP8LMultipliers, quality int32, xsize int32, ysize int32, accumulated_red_histo uintptr, accumulated_blue_histo uintptr, argb uintptr) VP8LMultipliers { /* predictor_enc.c:675:24: */ + bp := tls.Alloc(3) + defer tls.Free(3) + + var max_tile_size int32 = (int32(1) << bits) + var tile_y_offset int32 = (tile_y * max_tile_size) + var tile_x_offset int32 = (tile_x * max_tile_size) + var all_x_max int32 = GetMin(tls, (tile_x_offset + max_tile_size), xsize) + var all_y_max int32 = GetMin(tls, (tile_y_offset + max_tile_size), ysize) + var tile_width int32 = (all_x_max - tile_x_offset) + var tile_height int32 = (all_y_max - tile_y_offset) + var tile_argb uintptr = ((argb + uintptr((tile_y_offset*xsize))*4) + + uintptr(tile_x_offset)*4) + // var best_tx VP8LMultipliers at bp, 3 + + MultipliersClear(tls, (bp) /* &best_tx */) + + GetBestGreenToRed(tls, tile_argb, xsize, tile_width, tile_height, + prev_x, prev_y, quality, accumulated_red_histo, (bp) /* &best_tx */) + GetBestGreenRedToBlue(tls, tile_argb, xsize, tile_width, tile_height, + prev_x, prev_y, quality, accumulated_blue_histo, + (bp) /* &best_tx */) + return *(*VP8LMultipliers)(unsafe.Pointer(bp /* best_tx */)) +} + +func CopyTileWithColorTransform(tls *libc.TLS, xsize int32, ysize int32, tile_x int32, tile_y int32, max_tile_size int32, color_transform VP8LMultipliers, argb uintptr) { /* predictor_enc.c:703:13: */ + bp := tls.Alloc(3) + defer tls.Free(3) + *(*VP8LMultipliers)(unsafe.Pointer(bp)) = color_transform + + var xscan int32 = GetMin(tls, max_tile_size, (xsize - tile_x)) + var yscan int32 = GetMin(tls, max_tile_size, (ysize - tile_y)) + argb += 4 * (uintptr((tile_y * xsize) + tile_x)) + for libc.PostDecInt32(&yscan, 1) > 0 { + (*struct { + f func(*libc.TLS, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8LTransformColor})).f(tls, (bp) /* &color_transform */, argb, xscan) + argb += 4 * (uintptr(xsize)) + } +} + +func VP8LColorSpaceTransform(tls *libc.TLS, width int32, height int32, bits int32, quality int32, argb uintptr, image uintptr) { /* predictor_enc.c:717:6: */ + bp := tls.Alloc(2056) + defer tls.Free(2056) + + var max_tile_size int32 = (int32(1) << bits) + var tile_xsize int32 = int32(VP8LSubSampleSize(tls, uint32(width), uint32(bits))) + var tile_ysize int32 = int32(VP8LSubSampleSize(tls, uint32(height), uint32(bits))) + *(*[256]int32)(unsafe.Pointer(bp + 8 /* accumulated_red_histo */)) = [256]int32{0: 0} + *(*[256]int32)(unsafe.Pointer(bp + 1032 /* accumulated_blue_histo */)) = [256]int32{0: 0} + var tile_x int32 + var tile_y int32 + // var prev_x VP8LMultipliers at bp+3, 3 + + // var prev_y VP8LMultipliers at bp, 3 + + MultipliersClear(tls, (bp) /* &prev_y */) + MultipliersClear(tls, (bp + 3) /* &prev_x */) + for tile_y = 0; tile_y < tile_ysize; tile_y++ { + for tile_x = 0; tile_x < tile_xsize; tile_x++ { + var y int32 + var tile_x_offset int32 = (tile_x * max_tile_size) + var tile_y_offset int32 = (tile_y * max_tile_size) + var all_x_max int32 = GetMin(tls, (tile_x_offset + max_tile_size), width) + var all_y_max int32 = GetMin(tls, (tile_y_offset + max_tile_size), height) + var offset int32 = ((tile_y * tile_xsize) + tile_x) + if tile_y != 0 { + ColorCodeToMultipliers1(tls, *(*uint32_t)(unsafe.Pointer(image + uintptr((offset-tile_xsize))*4)), (bp) /* &prev_y */) + } + *(*VP8LMultipliers)(unsafe.Pointer(bp + 3 /* prev_x */)) = GetBestColorTransformForTile(tls, tile_x, tile_y, bits, + *(*VP8LMultipliers)(unsafe.Pointer(bp + 3 /* prev_x */)), *(*VP8LMultipliers)(unsafe.Pointer(bp /* prev_y */)), + quality, width, height, + (bp + 8), /* &accumulated_red_histo[0] */ + (bp + 1032), /* &accumulated_blue_histo[0] */ + argb) + *(*uint32_t)(unsafe.Pointer(image + uintptr(offset)*4)) = MultipliersToColorCode(tls, (bp + 3) /* &prev_x */) + CopyTileWithColorTransform(tls, width, height, tile_x_offset, tile_y_offset, + max_tile_size, *(*VP8LMultipliers)(unsafe.Pointer(bp + 3 /* prev_x */)), argb) + + // Gather accumulated histogram data. + for y = tile_y_offset; y < all_y_max; y++ { + var ix int32 = ((y * width) + tile_x_offset) + var ix_end int32 = ((ix + all_x_max) - tile_x_offset) + for ; ix < ix_end; ix++ { + var pix uint32_t = *(*uint32_t)(unsafe.Pointer(argb + uintptr(ix)*4)) + if ((ix >= 2) && (pix == *(*uint32_t)(unsafe.Pointer(argb + uintptr((ix-2))*4)))) && (pix == *(*uint32_t)(unsafe.Pointer(argb + uintptr((ix-1))*4))) { + continue // repeated pixels are handled by backward references + } + if (((ix >= (width + 2)) && (*(*uint32_t)(unsafe.Pointer(argb + uintptr((ix-2))*4)) == *(*uint32_t)(unsafe.Pointer(argb + uintptr(((ix-width)-2))*4)))) && (*(*uint32_t)(unsafe.Pointer(argb + uintptr((ix-1))*4)) == *(*uint32_t)(unsafe.Pointer(argb + uintptr(((ix-width)-1))*4)))) && (pix == *(*uint32_t)(unsafe.Pointer(argb + uintptr((ix-width))*4))) { + continue // repeated pixels are handled by backward references + } + *(*int32)(unsafe.Pointer((bp + 8) /* &accumulated_red_histo[0] */ + uintptr(((pix>>16)&uint32_t(0xff)))*4))++ + *(*int32)(unsafe.Pointer((bp + 1032) /* &accumulated_blue_histo[0] */ + uintptr(((pix>>0)&uint32_t(0xff)))*4))++ + } + } + } + } +} + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +func IsFlat_C(tls *libc.TLS, levels uintptr, num_blocks int32, thresh int32) int32 { /* quant.h:55:24: */ + var score int32 = 0 + for libc.PostDecInt32(&num_blocks, 1) > 0 { // TODO(skal): refine positional scoring? + var i int32 + for i = 1; i < 16; i++ { // omit DC, we're only interested in AC + score = score + (libc.Bool32(int32(*(*int16_t)(unsafe.Pointer(levels + uintptr(i)*2))) != 0)) + if score > thresh { + return 0 + } + } + levels += 2 * (uintptr(16)) + } + return 1 +} + +// !defined(WEBP_HAVE_NEON_RTCD) + +func IsFlatSource16(tls *libc.TLS, src uintptr) int32 { /* quant.h:72:24: */ + bp := tls.Alloc(4) + defer tls.Free(4) + + *(*uint32_t)(unsafe.Pointer(bp /* v */)) = (uint32(*(*uint8_t)(unsafe.Pointer(src))) * 0x01010101) + var i int32 + for i = 0; i < 16; i++ { + if (((libc.Xmemcmp(tls, (src+uintptr(0)), (bp) /* &v */, uint64(4)) != 0) || (libc.Xmemcmp(tls, (src+uintptr(4)), (bp) /* &v */, uint64(4)) != 0)) || (libc.Xmemcmp(tls, (src+uintptr(8)), (bp) /* &v */, uint64(4)) != 0)) || (libc.Xmemcmp(tls, (src+uintptr(12)), (bp) /* &v */, uint64(4)) != 0) { + return 0 + } + src += uintptr(32) + } + return 1 +} + +//------------------------------------------------------------------------------ + +// power-law modulation. Must be strictly less than 1. + +// number of non-zero coeffs below which we consider the block very flat +// (and apply a penalty to complex predictions) + +// #define DEBUG_BLOCK + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +func clip3(tls *libc.TLS, v int32, m int32, M int32) int32 { /* quant_enc.c:126:24: */ + if v < m { + return m + } + if v > M { + return M + } + return v +} + +var kZigzag2 = [16]uint8_t{ + uint8_t(0), uint8_t(1), uint8_t(4), uint8_t(8), uint8_t(5), uint8_t(2), uint8_t(3), uint8_t(6), uint8_t(9), uint8_t(12), uint8_t(13), uint8_t(10), uint8_t(7), uint8_t(11), uint8_t(14), uint8_t(15), +} /* quant_enc.c:130:22 */ + +var kDcTable1 = [128]uint8_t{ + uint8_t(4), uint8_t(5), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(10), uint8_t(10), + uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(14), uint8_t(15), uint8_t(16), uint8_t(17), uint8_t(17), + uint8_t(18), uint8_t(19), uint8_t(20), uint8_t(20), uint8_t(21), uint8_t(21), uint8_t(22), uint8_t(22), + uint8_t(23), uint8_t(23), uint8_t(24), uint8_t(25), uint8_t(25), uint8_t(26), uint8_t(27), uint8_t(28), + uint8_t(29), uint8_t(30), uint8_t(31), uint8_t(32), uint8_t(33), uint8_t(34), uint8_t(35), uint8_t(36), + uint8_t(37), uint8_t(37), uint8_t(38), uint8_t(39), uint8_t(40), uint8_t(41), uint8_t(42), uint8_t(43), + uint8_t(44), uint8_t(45), uint8_t(46), uint8_t(46), uint8_t(47), uint8_t(48), uint8_t(49), uint8_t(50), + uint8_t(51), uint8_t(52), uint8_t(53), uint8_t(54), uint8_t(55), uint8_t(56), uint8_t(57), uint8_t(58), + uint8_t(59), uint8_t(60), uint8_t(61), uint8_t(62), uint8_t(63), uint8_t(64), uint8_t(65), uint8_t(66), + uint8_t(67), uint8_t(68), uint8_t(69), uint8_t(70), uint8_t(71), uint8_t(72), uint8_t(73), uint8_t(74), + uint8_t(75), uint8_t(76), uint8_t(76), uint8_t(77), uint8_t(78), uint8_t(79), uint8_t(80), uint8_t(81), + uint8_t(82), uint8_t(83), uint8_t(84), uint8_t(85), uint8_t(86), uint8_t(87), uint8_t(88), uint8_t(89), + uint8_t(91), uint8_t(93), uint8_t(95), uint8_t(96), uint8_t(98), uint8_t(100), uint8_t(101), uint8_t(102), + uint8_t(104), uint8_t(106), uint8_t(108), uint8_t(110), uint8_t(112), uint8_t(114), uint8_t(116), uint8_t(118), + uint8_t(122), uint8_t(124), uint8_t(126), uint8_t(128), uint8_t(130), uint8_t(132), uint8_t(134), uint8_t(136), + uint8_t(138), uint8_t(140), uint8_t(143), uint8_t(145), uint8_t(148), uint8_t(151), uint8_t(154), uint8_t(157), +} /* quant_enc.c:134:22 */ + +var kAcTable1 = [128]uint16_t{ + uint16_t(4), uint16_t(5), uint16_t(6), uint16_t(7), uint16_t(8), uint16_t(9), uint16_t(10), uint16_t(11), + uint16_t(12), uint16_t(13), uint16_t(14), uint16_t(15), uint16_t(16), uint16_t(17), uint16_t(18), uint16_t(19), + uint16_t(20), uint16_t(21), uint16_t(22), uint16_t(23), uint16_t(24), uint16_t(25), uint16_t(26), uint16_t(27), + uint16_t(28), uint16_t(29), uint16_t(30), uint16_t(31), uint16_t(32), uint16_t(33), uint16_t(34), uint16_t(35), + uint16_t(36), uint16_t(37), uint16_t(38), uint16_t(39), uint16_t(40), uint16_t(41), uint16_t(42), uint16_t(43), + uint16_t(44), uint16_t(45), uint16_t(46), uint16_t(47), uint16_t(48), uint16_t(49), uint16_t(50), uint16_t(51), + uint16_t(52), uint16_t(53), uint16_t(54), uint16_t(55), uint16_t(56), uint16_t(57), uint16_t(58), uint16_t(60), + uint16_t(62), uint16_t(64), uint16_t(66), uint16_t(68), uint16_t(70), uint16_t(72), uint16_t(74), uint16_t(76), + uint16_t(78), uint16_t(80), uint16_t(82), uint16_t(84), uint16_t(86), uint16_t(88), uint16_t(90), uint16_t(92), + uint16_t(94), uint16_t(96), uint16_t(98), uint16_t(100), uint16_t(102), uint16_t(104), uint16_t(106), uint16_t(108), + uint16_t(110), uint16_t(112), uint16_t(114), uint16_t(116), uint16_t(119), uint16_t(122), uint16_t(125), uint16_t(128), + uint16_t(131), uint16_t(134), uint16_t(137), uint16_t(140), uint16_t(143), uint16_t(146), uint16_t(149), uint16_t(152), + uint16_t(155), uint16_t(158), uint16_t(161), uint16_t(164), uint16_t(167), uint16_t(170), uint16_t(173), uint16_t(177), + uint16_t(181), uint16_t(185), uint16_t(189), uint16_t(193), uint16_t(197), uint16_t(201), uint16_t(205), uint16_t(209), + uint16_t(213), uint16_t(217), uint16_t(221), uint16_t(225), uint16_t(229), uint16_t(234), uint16_t(239), uint16_t(245), + uint16_t(249), uint16_t(254), uint16_t(259), uint16_t(264), uint16_t(269), uint16_t(274), uint16_t(279), uint16_t(284), +} /* quant_enc.c:153:23 */ + +var kAcTable2 = [128]uint16_t{ + uint16_t(8), uint16_t(8), uint16_t(9), uint16_t(10), uint16_t(12), uint16_t(13), uint16_t(15), uint16_t(17), + uint16_t(18), uint16_t(20), uint16_t(21), uint16_t(23), uint16_t(24), uint16_t(26), uint16_t(27), uint16_t(29), + uint16_t(31), uint16_t(32), uint16_t(34), uint16_t(35), uint16_t(37), uint16_t(38), uint16_t(40), uint16_t(41), + uint16_t(43), uint16_t(44), uint16_t(46), uint16_t(48), uint16_t(49), uint16_t(51), uint16_t(52), uint16_t(54), + uint16_t(55), uint16_t(57), uint16_t(58), uint16_t(60), uint16_t(62), uint16_t(63), uint16_t(65), uint16_t(66), + uint16_t(68), uint16_t(69), uint16_t(71), uint16_t(72), uint16_t(74), uint16_t(75), uint16_t(77), uint16_t(79), + uint16_t(80), uint16_t(82), uint16_t(83), uint16_t(85), uint16_t(86), uint16_t(88), uint16_t(89), uint16_t(93), + uint16_t(96), uint16_t(99), uint16_t(102), uint16_t(105), uint16_t(108), uint16_t(111), uint16_t(114), uint16_t(117), + uint16_t(120), uint16_t(124), uint16_t(127), uint16_t(130), uint16_t(133), uint16_t(136), uint16_t(139), uint16_t(142), + uint16_t(145), uint16_t(148), uint16_t(151), uint16_t(155), uint16_t(158), uint16_t(161), uint16_t(164), uint16_t(167), + uint16_t(170), uint16_t(173), uint16_t(176), uint16_t(179), uint16_t(184), uint16_t(189), uint16_t(193), uint16_t(198), + uint16_t(203), uint16_t(207), uint16_t(212), uint16_t(217), uint16_t(221), uint16_t(226), uint16_t(230), uint16_t(235), + uint16_t(240), uint16_t(244), uint16_t(249), uint16_t(254), uint16_t(258), uint16_t(263), uint16_t(268), uint16_t(274), + uint16_t(280), uint16_t(286), uint16_t(292), uint16_t(299), uint16_t(305), uint16_t(311), uint16_t(317), uint16_t(323), + uint16_t(330), uint16_t(336), uint16_t(342), uint16_t(348), uint16_t(354), uint16_t(362), uint16_t(370), uint16_t(379), + uint16_t(385), uint16_t(393), uint16_t(401), uint16_t(409), uint16_t(416), uint16_t(424), uint16_t(432), uint16_t(440), +} /* quant_enc.c:172:23 */ + +var kBiasMatrices = [3][2]uint8_t{ // [luma-ac,luma-dc,chroma][dc,ac] + [2]uint8_t{uint8_t(96), uint8_t(110)}, [2]uint8_t{uint8_t(96), uint8_t(108)}, [2]uint8_t{uint8_t(110), uint8_t(115)}, +} /* quant_enc.c:191:22 */ + +// Sharpening by (slightly) raising the hi-frequency coeffs. +// Hack-ish but helpful for mid-bitrate range. Use with care. +var kFreqSharpening = [16]uint8_t{ + uint8_t(0), uint8_t(30), uint8_t(60), uint8_t(90), + uint8_t(30), uint8_t(60), uint8_t(90), uint8_t(90), + uint8_t(60), uint8_t(90), uint8_t(90), uint8_t(90), + uint8_t(90), uint8_t(90), uint8_t(90), uint8_t(90), +} /* quant_enc.c:198:22 */ + +//------------------------------------------------------------------------------ +// Initialize quantization parameters in VP8Matrix + +// Returns the average quantizer +func ExpandMatrix(tls *libc.TLS, m uintptr, type1 int32) int32 { /* quant_enc.c:209:12: */ + var i int32 + var sum int32 + for i = 0; i < 2; i++ { + var is_ac_coeff int32 = (libc.Bool32(i > 0)) + var bias int32 = int32(*(*uint8_t)(unsafe.Pointer((uintptr(unsafe.Pointer(&kBiasMatrices)) + uintptr(type1)*2) + uintptr(is_ac_coeff)))) + *(*uint16_t)(unsafe.Pointer((m + 32 /* &.iq_ */) + uintptr(i)*2)) = (uint16_t((int32(1) << 17) / int32(*(*uint16_t)(unsafe.Pointer((m /* &.q_ */) + uintptr(i)*2))))) + *(*uint32_t)(unsafe.Pointer((m + 64 /* &.bias_ */) + uintptr(i)*4)) = (uint32_t((bias) << (17 - 8))) + // zthresh_ is the exact value such that QUANTDIV(coeff, iQ, B) is: + // * zero if coeff <= zthresh + // * non-zero if coeff > zthresh + *(*uint32_t)(unsafe.Pointer((m + 128 /* &.zthresh_ */) + uintptr(i)*4)) = (((uint32_t((int32(1) << 17) - 1)) - *(*uint32_t)(unsafe.Pointer((m + 64 /* &.bias_ */) + uintptr(i)*4))) / uint32_t(*(*uint16_t)(unsafe.Pointer((m + 32 /* &.iq_ */) + uintptr(i)*2)))) + } + for i = 2; i < 16; i++ { + *(*uint16_t)(unsafe.Pointer((m /* &.q_ */) + uintptr(i)*2)) = *(*uint16_t)(unsafe.Pointer((m /* &.q_ */) + 1*2)) + *(*uint16_t)(unsafe.Pointer((m + 32 /* &.iq_ */) + uintptr(i)*2)) = *(*uint16_t)(unsafe.Pointer((m + 32 /* &.iq_ */) + 1*2)) + *(*uint32_t)(unsafe.Pointer((m + 64 /* &.bias_ */) + uintptr(i)*4)) = *(*uint32_t)(unsafe.Pointer((m + 64 /* &.bias_ */) + 1*4)) + *(*uint32_t)(unsafe.Pointer((m + 128 /* &.zthresh_ */) + uintptr(i)*4)) = *(*uint32_t)(unsafe.Pointer((m + 128 /* &.zthresh_ */) + 1*4)) + } + sum = 0 + i = 0 + for ; i < 16; i++ { + if type1 == 0 { // we only use sharpening for AC luma coeffs + *(*uint16_t)(unsafe.Pointer((m + 192 /* &.sharpen_ */) + uintptr(i)*2)) = (uint16_t((int32(kFreqSharpening[i]) * int32(*(*uint16_t)(unsafe.Pointer((m /* &.q_ */) + uintptr(i)*2)))) >> 11)) + } else { + *(*uint16_t)(unsafe.Pointer((m + 192 /* &.sharpen_ */) + uintptr(i)*2)) = uint16_t(0) + } + sum = sum + (int32(*(*uint16_t)(unsafe.Pointer((m /* &.q_ */) + uintptr(i)*2)))) + } + return ((sum + 8) >> 4) +} + +func CheckLambdaValue(tls *libc.TLS, v uintptr) { /* quant_enc.c:238:13: */ + if *(*int32)(unsafe.Pointer(v)) < 1 { + *(*int32)(unsafe.Pointer(v)) = 1 + } +} + +func SetupMatrices(tls *libc.TLS, enc uintptr) { /* quant_enc.c:240:13: */ + var i int32 + var tlambda_scale int32 + if (*VP8Encoder)(unsafe.Pointer(enc)).method_ >= 4 { + tlambda_scale = (*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).sns_strength + } else { + tlambda_scale = 0 + } + var num_segments int32 = (*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.num_segments_ + for i = 0; i < num_segments; i++ { + var m uintptr = ((enc + 608 /* &.dqm_ */) + uintptr(i)*744) + var q int32 = (*VP8SegmentInfo)(unsafe.Pointer(m)).quant_ + var q_i4 int32 + var q_i16 int32 + var q_uv int32 + *(*uint16_t)(unsafe.Pointer((m /* &.y1_ */) /* &.q_ */)) = uint16_t(kDcTable1[clip3(tls, (q+(*VP8Encoder)(unsafe.Pointer(enc)).dq_y1_dc_), 0, 127)]) + *(*uint16_t)(unsafe.Pointer((m /* &.y1_ */) /* &.q_ */ + 1*2)) = kAcTable1[clip3(tls, q, 0, 127)] + + *(*uint16_t)(unsafe.Pointer((m + 224 /* &.y2_ */) /* &.q_ */)) = (uint16_t(int32(kDcTable1[clip3(tls, (q+(*VP8Encoder)(unsafe.Pointer(enc)).dq_y2_dc_), 0, 127)]) * 2)) + *(*uint16_t)(unsafe.Pointer((m + 224 /* &.y2_ */) /* &.q_ */ + 1*2)) = kAcTable2[clip3(tls, (q+(*VP8Encoder)(unsafe.Pointer(enc)).dq_y2_ac_), 0, 127)] + + *(*uint16_t)(unsafe.Pointer((m + 448 /* &.uv_ */) /* &.q_ */)) = uint16_t(kDcTable1[clip3(tls, (q+(*VP8Encoder)(unsafe.Pointer(enc)).dq_uv_dc_), 0, 117)]) + *(*uint16_t)(unsafe.Pointer((m + 448 /* &.uv_ */) /* &.q_ */ + 1*2)) = kAcTable1[clip3(tls, (q+(*VP8Encoder)(unsafe.Pointer(enc)).dq_uv_ac_), 0, 127)] + + q_i4 = ExpandMatrix(tls, (m /* &.y1_ */), 0) + q_i16 = ExpandMatrix(tls, (m + 224 /* &.y2_ */), 1) + q_uv = ExpandMatrix(tls, (m + 448 /* &.uv_ */), 2) + + (*VP8SegmentInfo)(unsafe.Pointer(m)).lambda_i4_ = (((3 * q_i4) * q_i4) >> 7) + (*VP8SegmentInfo)(unsafe.Pointer(m)).lambda_i16_ = ((3 * q_i16) * q_i16) + (*VP8SegmentInfo)(unsafe.Pointer(m)).lambda_uv_ = (((3 * q_uv) * q_uv) >> 6) + (*VP8SegmentInfo)(unsafe.Pointer(m)).lambda_mode_ = (((1 * q_i4) * q_i4) >> 7) + (*VP8SegmentInfo)(unsafe.Pointer(m)).lambda_trellis_i4_ = (((7 * q_i4) * q_i4) >> 3) + (*VP8SegmentInfo)(unsafe.Pointer(m)).lambda_trellis_i16_ = ((q_i16 * q_i16) >> 2) + (*VP8SegmentInfo)(unsafe.Pointer(m)).lambda_trellis_uv_ = ((q_uv * q_uv) << 1) + (*VP8SegmentInfo)(unsafe.Pointer(m)).tlambda_ = ((tlambda_scale * q_i4) >> 5) + + // none of these constants should be < 1 + CheckLambdaValue(tls, (m + 700 /* &.lambda_i4_ */)) + CheckLambdaValue(tls, (m + 696 /* &.lambda_i16_ */)) + CheckLambdaValue(tls, (m + 704 /* &.lambda_uv_ */)) + CheckLambdaValue(tls, (m + 708 /* &.lambda_mode_ */)) + CheckLambdaValue(tls, (m + 724 /* &.lambda_trellis_i4_ */)) + CheckLambdaValue(tls, (m + 720 /* &.lambda_trellis_i16_ */)) + CheckLambdaValue(tls, (m + 728 /* &.lambda_trellis_uv_ */)) + CheckLambdaValue(tls, (m + 716 /* &.tlambda_ */)) + + (*VP8SegmentInfo)(unsafe.Pointer(m)).min_disto_ = (20 * int32(*(*uint16_t)(unsafe.Pointer((m /* &.y1_ */) /* &.q_ */)))) // quantization-aware min disto + (*VP8SegmentInfo)(unsafe.Pointer(m)).max_edge_ = 0 + + (*VP8SegmentInfo)(unsafe.Pointer(m)).i4_penalty_ = (score_t((1000 * q_i4) * q_i4)) + } +} + +//------------------------------------------------------------------------------ +// Initialize filtering parameters + +// Very small filter-strength values have close to no visual effect. So we can +// save a little decoding-CPU by turning filtering off for these. + +func SetupFilterStrength(tls *libc.TLS, enc uintptr) { /* quant_enc.c:296:13: */ + var i int32 + // level0 is in [0..500]. Using '-f 50' as filter_strength is mid-filtering. + var level0 int32 = (5 * (*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).filter_strength) + for i = 0; i < NUM_MB_SEGMENTS; i++ { + var m uintptr = ((enc + 608 /* &.dqm_ */) + uintptr(i)*744) + // We focus on the quantization of AC coeffs. + var qstep int32 = (int32(kAcTable1[clip3(tls, (*VP8SegmentInfo)(unsafe.Pointer(m)).quant_, 0, 127)]) >> 2) + var base_strength int32 = VP8FilterStrengthFromDelta(tls, (*VP8Encoder)(unsafe.Pointer(enc)).filter_hdr_.sharpness_, qstep) + // Segments with lower complexity ('beta') will be less filtered. + var f int32 = ((base_strength * level0) / (256 + (*VP8SegmentInfo)(unsafe.Pointer(m)).beta_)) + (*VP8SegmentInfo)(unsafe.Pointer(m)).fstrength_ = func() int32 { + if f < 2 { + return 0 + } + return func() int32 { + if f > 63 { + return 63 + } + return f + }() + }() + } + // We record the initial strength (mainly for the case of 1-segment only). + (*VP8Encoder)(unsafe.Pointer(enc)).filter_hdr_.level_ = (*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */))).fstrength_ + (*VP8Encoder)(unsafe.Pointer(enc)).filter_hdr_.simple_ = (libc.Bool32((*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).filter_type == 0)) + (*VP8Encoder)(unsafe.Pointer(enc)).filter_hdr_.sharpness_ = (*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).filter_sharpness +} + +//------------------------------------------------------------------------------ + +// Note: if you change the values below, remember that the max range +// allowed by the syntax for DQ_UV is [-16,16]. + +// We want to emulate jpeg-like behaviour where the expected "good" quality +// is around q=75. Internally, our "good" middle is around c=50. So we +// map accordingly using linear piece-wise function +func QualityToCompression(tls *libc.TLS, c float64) float64 { /* quant_enc.c:326:15: */ + var linear_c float64 + if c < 0.75 { + linear_c = (c * (float64(2.) / 3.)) + } else { + linear_c = ((2. * c) - 1.) + } + // The file size roughly scales as pow(quantizer, 3.). Actually, the + // exponent is somewhere between 2.8 and 3.2, but we're mostly interested + // in the mid-quant range. So we scale the compressibility inversely to + // this power-law: quant ~= compression ^ 1/3. This law holds well for + // low quant. Finer modeling for high-quant would make use of kAcTable[] + // more explicitly. + var v float64 = libc.Xpow(tls, linear_c, (float64(float64(1)) / 3.)) + return v +} + +func QualityToJPEGCompression(tls *libc.TLS, c float64, alpha float64) float64 { /* quant_enc.c:338:15: */ + // We map the complexity 'alpha' and quality setting 'c' to a compression + // exponent empirically matched to the compression curve of libjpeg6b. + // On average, the WebP output size will be roughly similar to that of a + // JPEG file compressed with same quality factor. + var amin float64 = 0.30 + var amax float64 = 0.85 + var exp_min float64 = 0.4 + var exp_max float64 = 0.9 + var slope float64 = ((exp_min - exp_max) / (amax - amin)) + // Linearly interpolate 'expn' from exp_min to exp_max + // in the [amin, amax] range. + var expn float64 + if alpha > amax { + expn = exp_min + } else { + if alpha < amin { + expn = exp_max + } else { + expn = (exp_max + (slope * (alpha - amin))) + } + } + var v float64 = libc.Xpow(tls, c, expn) + return v +} + +func SegmentsAreEquivalent(tls *libc.TLS, S1 uintptr, S2 uintptr) int32 { /* quant_enc.c:357:12: */ + return (libc.Bool32(((*VP8SegmentInfo)(unsafe.Pointer(S1)).quant_ == (*VP8SegmentInfo)(unsafe.Pointer(S2)).quant_) && ((*VP8SegmentInfo)(unsafe.Pointer(S1)).fstrength_ == (*VP8SegmentInfo)(unsafe.Pointer(S2)).fstrength_))) +} + +func SimplifySegments(tls *libc.TLS, enc uintptr) { /* quant_enc.c:362:13: */ + bp := tls.Alloc(16) + defer tls.Free(16) + + *(*[4]int32)(unsafe.Pointer(bp /* map1 */)) = [4]int32{0, 1, 2, 3} + // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an + // explicit check is needed to avoid a spurious warning about 'i' exceeding + // array bounds of 'dqm_' with some compilers (noticed with gcc-4.9). + var num_segments int32 + if (*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.num_segments_ < NUM_MB_SEGMENTS { + num_segments = (*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.num_segments_ + } else { + num_segments = NUM_MB_SEGMENTS + } + var num_final_segments int32 = 1 + var s1 int32 + var s2 int32 + for s1 = 1; s1 < num_segments; s1++ { // find similar segments + var S1 uintptr = ((enc + 608 /* &.dqm_ */) + uintptr(s1)*744) + var found int32 = 0 + // check if we already have similar segment + for s2 = 0; s2 < num_final_segments; s2++ { + var S2 uintptr = ((enc + 608 /* &.dqm_ */) + uintptr(s2)*744) + if SegmentsAreEquivalent(tls, S1, S2) != 0 { + found = 1 + break + } + } + *(*int32)(unsafe.Pointer((bp) /* &map1[0] */ + uintptr(s1)*4)) = s2 + if !(found != 0) { + if num_final_segments != s1 { + *(*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */) + uintptr(num_final_segments)*744)) = *(*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */) + uintptr(s1)*744)) + } + num_final_segments++ + } + } + if num_final_segments < num_segments { // Remap + var i int32 = ((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ * (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_) + for libc.PostDecInt32(&i, 1) > 0 { + libc.SetBitFieldPtr8Uint32(((*VP8Encoder)(unsafe.Pointer(enc)).mb_info_ + uintptr(i)*4) /* &.segment_ */, uint32(*(*int32)(unsafe.Pointer((bp) /* &map1[0] */ + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer(((*VP8Encoder)(unsafe.Pointer(enc)).mb_info_ + uintptr(i)*4) /* &.segment_ */))&0x60>>5))))*4))), 5, 0x60) + } + (*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.num_segments_ = num_final_segments + // Replicate the trailing segment infos (it's mostly cosmetics) + for i = num_final_segments; i < num_segments; i++ { + *(*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */) + uintptr(i)*744)) = *(*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */) + uintptr((num_final_segments-1))*744)) + } + } +} + +func VP8SetSegmentParams(tls *libc.TLS, enc uintptr, quality float32) { /* quant_enc.c:402:6: */ + var i int32 + var dq_uv_ac int32 + var dq_uv_dc int32 + var num_segments int32 = (*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.num_segments_ + var amp float64 = (((0.9 * float64((*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).sns_strength)) / 100.) / 128.) + var Q float64 = (float64(quality) / 100.) + var c_base float64 + if (*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).emulate_jpeg_size != 0 { + c_base = QualityToJPEGCompression(tls, Q, (float64((*VP8Encoder)(unsafe.Pointer(enc)).alpha_) / 255.)) + } else { + c_base = QualityToCompression(tls, Q) + } + for i = 0; i < num_segments; i++ { + // We modulate the base coefficient to accommodate for the quantization + // susceptibility and allow denser segments to be quantized more. + var expn float64 = (1. - (amp * float64((*VP8SegmentInfo)(unsafe.Pointer((enc+608 /* &.dqm_ */)+uintptr(i)*744)).alpha_))) + var c float64 = libc.Xpow(tls, c_base, expn) + var q int32 = (libc.Int32FromFloat64(127. * (1. - c))) + + (*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */) + uintptr(i)*744)).quant_ = clip3(tls, q, 0, 127) + } + + // purely indicative in the bitstream (except for the 1-segment case) + (*VP8Encoder)(unsafe.Pointer(enc)).base_quant_ = (*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */))).quant_ + + // fill-in values for the unused segments (required by the syntax) + for i = num_segments; i < NUM_MB_SEGMENTS; i++ { + (*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */) + uintptr(i)*744)).quant_ = (*VP8Encoder)(unsafe.Pointer(enc)).base_quant_ + } + + // uv_alpha_ is normally spread around ~60. The useful range is + // typically ~30 (quite bad) to ~100 (ok to decimate UV more). + // We map it to the safe maximal range of MAX/MIN_DQ_UV for dq_uv. + dq_uv_ac = ((((*VP8Encoder)(unsafe.Pointer(enc)).uv_alpha_ - 64) * ((6) - (-4))) / + (100 - 30)) + // we rescale by the user-defined strength of adaptation + dq_uv_ac = ((dq_uv_ac * (*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).sns_strength) / 100) + // and make it safe. + dq_uv_ac = clip3(tls, dq_uv_ac, (-4), (6)) + // We also boost the dc-uv-quant a little, based on sns-strength, since + // U/V channels are quite more reactive to high quants (flat DC-blocks + // tend to appear, and are unpleasant). + dq_uv_dc = ((-4 * (*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).sns_strength) / 100) + dq_uv_dc = clip3(tls, dq_uv_dc, -15, 15) // 4bit-signed max allowed + + (*VP8Encoder)(unsafe.Pointer(enc)).dq_y1_dc_ = 0 // TODO(skal): dq-lum + (*VP8Encoder)(unsafe.Pointer(enc)).dq_y2_dc_ = 0 + (*VP8Encoder)(unsafe.Pointer(enc)).dq_y2_ac_ = 0 + (*VP8Encoder)(unsafe.Pointer(enc)).dq_uv_dc_ = dq_uv_dc + (*VP8Encoder)(unsafe.Pointer(enc)).dq_uv_ac_ = dq_uv_ac + + SetupFilterStrength(tls, enc) // initialize segments' filtering, eventually + + if num_segments > 1 { + SimplifySegments(tls, enc) + } + + SetupMatrices(tls, enc) // finalize quantization matrices +} + +//------------------------------------------------------------------------------ +// Form the predictions in cache + +// Must be ordered using {DC_PRED, TM_PRED, V_PRED, H_PRED} as index +var VP8I16ModeOffsets = [4]uint16_t{(uint16_t((0 * 16) * 32)), (uint16_t(((0 * 16) * 32) + 16)), (uint16_t((1 * 16) * 32)), (uint16_t(((1 * 16) * 32) + 16))} /* quant_enc.c:461:16 */ +var VP8UVModeOffsets = [4]uint16_t{(uint16_t((2 * 16) * 32)), (uint16_t(((2 * 16) * 32) + (1 * 16))), (uint16_t(((2 * 16) * 32) + (8 * 32))), (uint16_t((((2 * 16) * 32) + (8 * 32)) + (1 * 16)))} /* quant_enc.c:462:16 */ + +// Must be indexed using {B_DC_PRED -> B_HU_PRED} as index +var VP8I4ModeOffsets = [10]uint16_t{ + (uint16_t(((3 * 16) * 32) + 0)), (uint16_t((((3 * 16) * 32) + 0) + 4)), (uint16_t((((3 * 16) * 32) + 0) + 8)), (uint16_t((((3 * 16) * 32) + 0) + 12)), (uint16_t((((3 * 16) * 32) + 0) + 16)), (uint16_t((((3 * 16) * 32) + 0) + 20)), (uint16_t((((3 * 16) * 32) + 0) + 24)), (uint16_t((((3 * 16) * 32) + 0) + 28)), (uint16_t(((3 * 16) * 32) + (4 * 32))), (uint16_t((((3 * 16) * 32) + (4 * 32)) + 4)), +} /* quant_enc.c:465:16 */ + +func VP8MakeLuma16Preds(tls *libc.TLS, it uintptr) { /* quant_enc.c:469:6: */ + var left uintptr + if (*VP8EncIterator)(unsafe.Pointer(it)).x_ != 0 { + left = (*VP8EncIterator)(unsafe.Pointer(it)).y_left_ + } else { + left = (uintptr(0)) + } + var top uintptr + if (*VP8EncIterator)(unsafe.Pointer(it)).y_ != 0 { + top = (*VP8EncIterator)(unsafe.Pointer(it)).y_top_ + } else { + top = (uintptr(0)) + } + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8EncPredLuma16})).f(tls, (*VP8EncIterator)(unsafe.Pointer(it)).yuv_p_, left, top) +} + +func VP8MakeChroma8Preds(tls *libc.TLS, it uintptr) { /* quant_enc.c:475:6: */ + var left uintptr + if (*VP8EncIterator)(unsafe.Pointer(it)).x_ != 0 { + left = (*VP8EncIterator)(unsafe.Pointer(it)).u_left_ + } else { + left = (uintptr(0)) + } + var top uintptr + if (*VP8EncIterator)(unsafe.Pointer(it)).y_ != 0 { + top = (*VP8EncIterator)(unsafe.Pointer(it)).uv_top_ + } else { + top = (uintptr(0)) + } + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8EncPredChroma8})).f(tls, (*VP8EncIterator)(unsafe.Pointer(it)).yuv_p_, left, top) +} + +func VP8MakeIntra4Preds(tls *libc.TLS, it uintptr) { /* quant_enc.c:481:6: */ + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8EncPredLuma4})).f(tls, (*VP8EncIterator)(unsafe.Pointer(it)).yuv_p_, (*VP8EncIterator)(unsafe.Pointer(it)).i4_top_) +} + +//------------------------------------------------------------------------------ +// Quantize + +// Layout: +// +----+----+ +// |YYYY|UUVV| 0 +// |YYYY|UUVV| 4 +// |YYYY|....| 8 +// |YYYY|....| 12 +// +----+----+ + +var VP8Scan = [16]uint16_t{ // Luma + (uint16_t(0 + (0 * 32))), (uint16_t(4 + (0 * 32))), (uint16_t(8 + (0 * 32))), (uint16_t(12 + (0 * 32))), + (uint16_t(0 + (4 * 32))), (uint16_t(4 + (4 * 32))), (uint16_t(8 + (4 * 32))), (uint16_t(12 + (4 * 32))), + (uint16_t(0 + (8 * 32))), (uint16_t(4 + (8 * 32))), (uint16_t(8 + (8 * 32))), (uint16_t(12 + (8 * 32))), + (uint16_t(0 + (12 * 32))), (uint16_t(4 + (12 * 32))), (uint16_t(8 + (12 * 32))), (uint16_t(12 + (12 * 32))), +} /* quant_enc.c:496:16 */ + +var VP8ScanUV = [8]uint16_t{ + (uint16_t(0 + (0 * 32))), (uint16_t(4 + (0 * 32))), (uint16_t(0 + (4 * 32))), (uint16_t(4 + (4 * 32))), // U + (uint16_t(8 + (0 * 32))), (uint16_t(12 + (0 * 32))), (uint16_t(8 + (4 * 32))), (uint16_t(12 + (4 * 32))), // V +} /* quant_enc.c:503:23 */ + +//------------------------------------------------------------------------------ +// Distortion measurement + +var kWeightY = [16]uint16_t{ + uint16_t(38), uint16_t(32), uint16_t(20), uint16_t(9), uint16_t(32), uint16_t(28), uint16_t(17), uint16_t(7), uint16_t(20), uint16_t(17), uint16_t(10), uint16_t(4), uint16_t(9), uint16_t(7), uint16_t(4), uint16_t(2), +} /* quant_enc.c:511:23 */ + +var kWeightTrellis = [16]uint16_t{ + uint16_t(30), uint16_t(27), uint16_t(19), uint16_t(11), + uint16_t(27), uint16_t(24), uint16_t(17), uint16_t(10), + uint16_t(19), uint16_t(17), uint16_t(12), uint16_t(8), + uint16_t(11), uint16_t(10), uint16_t(8), uint16_t(6), +} /* quant_enc.c:515:23 */ + +// Init/Copy the common fields in score. +func InitScore(tls *libc.TLS, rd uintptr) { /* quant_enc.c:527:13: */ + (*VP8ModeScore)(unsafe.Pointer(rd)).D = int64(0) + (*VP8ModeScore)(unsafe.Pointer(rd)).SD = int64(0) + (*VP8ModeScore)(unsafe.Pointer(rd)).R = int64(0) + (*VP8ModeScore)(unsafe.Pointer(rd)).H = int64(0) + (*VP8ModeScore)(unsafe.Pointer(rd)).nz = uint32_t(0) + (*VP8ModeScore)(unsafe.Pointer(rd)).score = (0x7fffffffffffff) +} + +func CopyScore(tls *libc.TLS, dst uintptr, src uintptr) { /* quant_enc.c:536:13: */ + (*VP8ModeScore)(unsafe.Pointer(dst)).D = (*VP8ModeScore)(unsafe.Pointer(src)).D + (*VP8ModeScore)(unsafe.Pointer(dst)).SD = (*VP8ModeScore)(unsafe.Pointer(src)).SD + (*VP8ModeScore)(unsafe.Pointer(dst)).R = (*VP8ModeScore)(unsafe.Pointer(src)).R + (*VP8ModeScore)(unsafe.Pointer(dst)).H = (*VP8ModeScore)(unsafe.Pointer(src)).H + (*VP8ModeScore)(unsafe.Pointer(dst)).nz = (*VP8ModeScore)(unsafe.Pointer(src)).nz // note that nz is not accumulated, but just copied. + (*VP8ModeScore)(unsafe.Pointer(dst)).score = (*VP8ModeScore)(unsafe.Pointer(src)).score +} + +func AddScore(tls *libc.TLS, dst uintptr, src uintptr) { /* quant_enc.c:545:13: */ + *(*score_t)(unsafe.Pointer((dst /* &.D */))) += ((*VP8ModeScore)(unsafe.Pointer(src)).D) + *(*score_t)(unsafe.Pointer((dst + 8 /* &.SD */))) += ((*VP8ModeScore)(unsafe.Pointer(src)).SD) + *(*score_t)(unsafe.Pointer((dst + 24 /* &.R */))) += ((*VP8ModeScore)(unsafe.Pointer(src)).R) + *(*score_t)(unsafe.Pointer((dst + 16 /* &.H */))) += ((*VP8ModeScore)(unsafe.Pointer(src)).H) + *(*uint32_t)(unsafe.Pointer((dst + 864 /* &.nz */))) |= ((*VP8ModeScore)(unsafe.Pointer(src)).nz) // here, new nz bits are accumulated. + *(*score_t)(unsafe.Pointer((dst + 32 /* &.score */))) += ((*VP8ModeScore)(unsafe.Pointer(src)).score) +} + +//------------------------------------------------------------------------------ +// Performs trellis-optimized quantization. + +// Trellis node +type Node = struct { + prev int8_t + sign int8_t + level int16_t +} /* quant_enc.c:562:3 */ + +// Score state +type ScoreState = struct { + score score_t + costs uintptr +} /* quant_enc.c:568:3 */ + +// If a coefficient was quantized to a value Q (using a neutral bias), +// we test all alternate possibilities between [Q-MIN_DELTA, Q+MAX_DELTA] +// We don't test negative values though. + +func SetRDScore(tls *libc.TLS, lambda int32, rd uintptr) { /* quant_enc.c:579:25: */ + (*VP8ModeScore)(unsafe.Pointer(rd)).score = ((((*VP8ModeScore)(unsafe.Pointer(rd)).R + (*VP8ModeScore)(unsafe.Pointer(rd)).H) * score_t(lambda)) + (int64(256) * ((*VP8ModeScore)(unsafe.Pointer(rd)).D + (*VP8ModeScore)(unsafe.Pointer(rd)).SD))) +} + +func RDScoreTrellis(tls *libc.TLS, lambda int32, rate score_t, distortion score_t) score_t { /* quant_enc.c:583:28: */ + return ((rate * score_t(lambda)) + (int64(256) * distortion)) +} + +func TrellisQuantizeBlock(tls *libc.TLS, enc uintptr, in uintptr, out uintptr, ctx0 int32, coeff_type int32, mtx uintptr, lambda int32) int32 { /* quant_enc.c:591:12: */ + bp := tls.Alloc(204) + defer tls.Free(204) + + var probas uintptr = (((enc + 3616 /* &.proba_ */) + 4 /* &.coeffs_ */) + uintptr(coeff_type)*264) + var costs CostArrayPtr = (((enc + 3616 /* &.proba_ */) + 18344 /* &.remapped_costs_ */) + uintptr(coeff_type)*384) + var first int32 + if coeff_type == TYPE_I16_AC { + first = 1 + } else { + first = 0 + } + // var nodes [16][2]Node at bp+64, 128 + + // var score_states [2][2]ScoreState at bp, 64 + + var ss_cur uintptr = (bp) /* &score_states */ + var ss_prev uintptr = ((bp) /* &score_states */ + 1*32) + *(*[3]int32)(unsafe.Pointer(bp + 192 /* best_path */)) = [3]int32{-1, -1, -1} // store best-last/best-level/best-previous + var best_score score_t + var n int32 + var m int32 + var p int32 + var last int32 + + { + var cost score_t + var thresh int32 = ((int32(*(*uint16_t)(unsafe.Pointer((mtx /* &.q_ */) + 1*2))) * int32(*(*uint16_t)(unsafe.Pointer((mtx /* &.q_ */) + 1*2)))) / 4) + var last_proba int32 = int32(*(*uint8_t)(unsafe.Pointer(((probas + uintptr(VP8EncBands[first])*33) + uintptr(ctx0)*11)))) + + // compute the position of the last interesting coefficient + last = (first - 1) + for n = 15; n >= first; n-- { + var j int32 = int32(kZigzag2[n]) + var err int32 = (int32(*(*int16_t)(unsafe.Pointer(in + uintptr(j)*2))) * int32(*(*int16_t)(unsafe.Pointer(in + uintptr(j)*2)))) + if err > thresh { + last = n + break + } + } + // we don't need to go inspect up to n = 16 coeffs. We can just go up + // to last + 1 (inclusive) without losing much. + if last < 15 { + last++ + } + + // compute 'skip' score. This is the max score one can do. + cost = score_t(VP8BitCost(tls, 0, uint8(last_proba))) + best_score = RDScoreTrellis(tls, lambda, cost, int64(0)) + + // initialize source node. + for m = -0; m <= 1; m++ { + var rate score_t + if ctx0 == 0 { + rate = int64(VP8BitCost(tls, 1, uint8(last_proba))) + } else { + rate = int64(0) + } + (*ScoreState)(unsafe.Pointer(ss_cur + uintptr(m)*16)).score = RDScoreTrellis(tls, lambda, rate, int64(0)) + (*ScoreState)(unsafe.Pointer(ss_cur + uintptr(m)*16)).costs = *(*uintptr)(unsafe.Pointer((costs + uintptr(first)*24) + uintptr(ctx0)*8)) + } + + } + + // traverse trellis. + for n = first; n <= last; n++ { + var j int32 = int32(kZigzag2[n]) + var Q uint32_t = uint32_t(*(*uint16_t)(unsafe.Pointer((mtx /* &.q_ */) + uintptr(j)*2))) + var iQ uint32_t = uint32_t(*(*uint16_t)(unsafe.Pointer((mtx + 32 /* &.iq_ */) + uintptr(j)*2))) + var B uint32_t = (uint32_t(int32((0x00)) << (17 - 8))) // neutral bias + // note: it's important to take sign of the _original_ coeff, + // so we don't have to consider level < 0 afterward. + var sign int32 = (libc.Bool32(int32(*(*int16_t)(unsafe.Pointer(in + uintptr(j)*2))) < 0)) + var coeff0 uint32_t = (uint32_t((func() int32 { + if sign != 0 { + return -int32(*(*int16_t)(unsafe.Pointer(in + uintptr(j)*2))) + } + return int32(*(*int16_t)(unsafe.Pointer(in + uintptr(j)*2))) + }()) + int32(*(*uint16_t)(unsafe.Pointer((mtx + 192 /* &.sharpen_ */) + uintptr(j)*2))))) + var level0 int32 = QUANTDIV(tls, coeff0, iQ, B) + var thresh_level int32 = QUANTDIV(tls, coeff0, iQ, (uint32(int32((0x80)) << (17 - 8)))) + if thresh_level > MAX_LEVEL { + thresh_level = MAX_LEVEL + } + if level0 > MAX_LEVEL { + level0 = MAX_LEVEL + } + + { // Swap current and previous score states + var tmp uintptr = ss_cur + ss_cur = ss_prev + ss_prev = tmp + + } + + // test all alternate level values around level0. + for m = -0; m <= 1; m++ { + var cur uintptr = (((bp + 64) /* &nodes */ + uintptr((n))*8) + uintptr(((m)+0))*4) + var level int32 = (level0 + m) + var ctx int32 + if level > 2 { + ctx = 2 + } else { + ctx = level + } + var band int32 = int32(VP8EncBands[(n + 1)]) + var base_score score_t + var best_cur_score score_t + var best_prev int32 + var cost score_t + var score score_t + + (*ScoreState)(unsafe.Pointer(ss_cur + uintptr(m)*16)).costs = *(*uintptr)(unsafe.Pointer((costs + uintptr((n+1))*24) + uintptr(ctx)*8)) + if (level < 0) || (level > thresh_level) { + (*ScoreState)(unsafe.Pointer(ss_cur + uintptr(m)*16)).score = (0x7fffffffffffff) + // Node is dead. + continue + } + + { + // Compute delta_error = how much coding this level will + // subtract to max_error as distortion. + // Here, distortion = sum of (|coeff_i| - level_i * Q_i)^2 + var new_error int32 = (int32(coeff0 - (uint32_t(level) * Q))) + var delta_error int32 = (int32(uint32_t(kWeightTrellis[j]) * ((uint32_t(new_error * new_error)) - (coeff0 * coeff0)))) + base_score = RDScoreTrellis(tls, lambda, int64(0), int64(delta_error)) + + } + + // Inspect all possible non-dead predecessors. Retain only the best one. + // The base_score is added to all scores so it is only added for the final + // value after the loop. + cost = score_t(VP8LevelCost(tls, (*ScoreState)(unsafe.Pointer(ss_prev)).costs, level)) + best_cur_score = ((*ScoreState)(unsafe.Pointer(ss_prev)).score + RDScoreTrellis(tls, lambda, cost, int64(0))) + best_prev = -0 + for p = (-0 + 1); p <= 1; p++ { + // Dead nodes (with ss_prev[p].score >= MAX_COST) are automatically + // eliminated since their score can't be better than the current best. + cost = score_t(VP8LevelCost(tls, (*ScoreState)(unsafe.Pointer(ss_prev+uintptr(p)*16)).costs, level)) + // Examine node assuming it's a non-terminal one. + score = ((*ScoreState)(unsafe.Pointer(ss_prev+uintptr(p)*16)).score + RDScoreTrellis(tls, lambda, cost, int64(0))) + if score < best_cur_score { + best_cur_score = score + best_prev = p + } + } + best_cur_score = best_cur_score + (base_score) + // Store best finding in current node. + (*Node)(unsafe.Pointer(cur)).sign = int8_t(sign) + (*Node)(unsafe.Pointer(cur)).level = int16_t(level) + (*Node)(unsafe.Pointer(cur)).prev = int8_t(best_prev) + (*ScoreState)(unsafe.Pointer(ss_cur + uintptr(m)*16)).score = best_cur_score + + // Now, record best terminal node (and thus best entry in the graph). + if (level != 0) && (best_cur_score < best_score) { + var last_pos_cost score_t + if n < 15 { + last_pos_cost = int64(VP8BitCost(tls, 0, *(*uint8_t)(unsafe.Pointer(((probas + uintptr(band)*33) + uintptr(ctx)*11))))) + } else { + last_pos_cost = int64(0) + } + var last_pos_score score_t = RDScoreTrellis(tls, lambda, last_pos_cost, int64(0)) + score = (best_cur_score + last_pos_score) + if score < best_score { + best_score = score + *(*int32)(unsafe.Pointer((bp + 192) /* &best_path[0] */)) = n // best eob position + *(*int32)(unsafe.Pointer((bp + 192) /* &best_path[0] */ + 1*4)) = m // best node index + *(*int32)(unsafe.Pointer((bp + 192) /* &best_path[0] */ + 2*4)) = best_prev // best predecessor + } + } + } + } + + // Fresh start + // Beware! We must preserve in[0]/out[0] value for TYPE_I16_AC case. + if coeff_type == TYPE_I16_AC { + libc.Xmemset(tls, (in + uintptr(1)*2), 0, (uint64(15) * uint64(unsafe.Sizeof(int16_t(0))))) + libc.Xmemset(tls, (out + uintptr(1)*2), 0, (uint64(15) * uint64(unsafe.Sizeof(int16_t(0))))) + } else { + libc.Xmemset(tls, in, 0, (uint64(16) * uint64(unsafe.Sizeof(int16_t(0))))) + libc.Xmemset(tls, out, 0, (uint64(16) * uint64(unsafe.Sizeof(int16_t(0))))) + } + if *(*int32)(unsafe.Pointer((bp + 192) /* &best_path[0] */)) == -1 { + return 0 // skip! + } + + { + // Unwind the best path. + // Note: best-prev on terminal node is not necessarily equal to the + // best_prev for non-terminal. So we patch best_path[2] in. + var nz int32 = 0 + var best_node int32 = *(*int32)(unsafe.Pointer((bp + 192) /* &best_path[0] */ + 1*4)) + n = *(*int32)(unsafe.Pointer((bp + 192) /* &best_path[0] */)) + (*Node)(unsafe.Pointer(((bp + 64) /* &nodes */ + uintptr((n))*8) + uintptr(((best_node)+0))*4)).prev = int8_t(*(*int32)(unsafe.Pointer((bp + 192) /* &best_path[0] */ + 2*4))) // force best-prev for terminal + + for ; n >= first; n-- { + var node uintptr = (((bp + 64) /* &nodes */ + uintptr((n))*8) + uintptr(((best_node)+0))*4) + var j int32 = int32(kZigzag2[n]) + *(*int16_t)(unsafe.Pointer(out + uintptr(n)*2)) = func() int16 { + if (*Node)(unsafe.Pointer(node)).sign != 0 { + return int16(-int32((*Node)(unsafe.Pointer(node)).level)) + } + return (*Node)(unsafe.Pointer(node)).level + }() + nz = nz | (int32((*Node)(unsafe.Pointer(node)).level)) + *(*int16_t)(unsafe.Pointer(in + uintptr(j)*2)) = (int16_t(int32(*(*int16_t)(unsafe.Pointer(out + uintptr(n)*2))) * int32(*(*uint16_t)(unsafe.Pointer((mtx /* &.q_ */) + uintptr(j)*2))))) + best_node = int32((*Node)(unsafe.Pointer(node)).prev) + } + return (libc.Bool32(nz != 0)) + + } + return int32(0) +} + +//------------------------------------------------------------------------------ +// Performs: difference, transform, quantize, back-transform, add +// all at once. Output is the reconstructed block in *yuv_out, and the +// quantized levels in *levels. + +func ReconstructIntra16(tls *libc.TLS, it uintptr, rd uintptr, yuv_out uintptr, mode int32) int32 { /* quant_enc.c:770:12: */ + bp := tls.Alloc(544) + defer tls.Free(544) + + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var ref uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_p_ + uintptr(VP8I16ModeOffsets[mode])) + var src uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((0))) + var dqm uintptr = ((enc + 608 /* &.dqm_ */) + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.segment_ */))&0x60>>5))))*744) + var nz int32 = 0 + var n int32 + // var tmp [16][16]int16_t at bp, 512 + + // var dc_tmp [16]int16_t at bp+512, 32 + + for n = 0; n < 16; n = n + (2) { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8FTransform2})).f(tls, (src + uintptr(VP8Scan[n])), (ref + uintptr(VP8Scan[n])), ((bp) /* &tmp[0] */ + uintptr(n)*32)) + } + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8FTransformWHT})).f(tls, (bp) /* &tmp[0] */, (bp + 512) /* &dc_tmp[0] */) + nz = nz | ((*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8EncQuantizeBlockWHT})).f(tls, (bp+512) /* &dc_tmp[0] */, (rd+40 /* &.y_dc_levels */), (dqm+224 /* &.y2_ */)) << 24) + + if (1 != 0) && ((*VP8EncIterator)(unsafe.Pointer(it)).do_trellis_ != 0) { + var x int32 + var y int32 + VP8IteratorNzToBytes(tls, it) + y = 0 + n = 0 + for ; y < 4; y++ { + x = 0 + __1: + if !(x < 4) { + goto __3 + } + { + var ctx int32 = (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(x)*4)) + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + uintptr(y)*4))) + var non_zero int32 = TrellisQuantizeBlock(tls, + enc, ((bp) /* &tmp[0] */ + uintptr(n)*32), ((rd + 72 /* &.y_ac_levels */) + uintptr(n)*32), ctx, TYPE_I16_AC, (dqm /* &.y1_ */), + (*VP8SegmentInfo)(unsafe.Pointer(dqm)).lambda_trellis_i16_) + *(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(x)*4)) = libc.AssignPtrInt32(((it + 168 /* &.left_nz_ */) + uintptr(y)*4), non_zero) + *(*int16_t)(unsafe.Pointer(((rd + 72 /* &.y_ac_levels */) + uintptr(n)*32))) = int16(0) + nz = nz | (non_zero << n) + + } + goto __2 + __2: + x++ + n++ + goto __1 + goto __3 + __3: + } + } else { + for n = 0; n < 16; n = n + (2) { + // Zero-out the first coeff, so that: a) nz is correct below, and + // b) finding 'last' non-zero coeffs in SetResidualCoeffs() is simplified. + *(*int16_t)(unsafe.Pointer(((bp) /* &tmp[0] */ + uintptr(n)*32))) = libc.AssignPtrInt16(((bp) /* &tmp */ + uintptr((n+1))*32), int16(0)) + nz = nz | ((*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8EncQuantize2Blocks})).f(tls, ((bp) /* &tmp[0] */ +uintptr(n)*32), ((rd+72 /* &.y_ac_levels */)+uintptr(n)*32), (dqm /* &.y1_ */)) << n) + + } + } + + // Transform back + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8TransformWHT})).f(tls, (bp + 512) /* &dc_tmp[0] */, (bp) /* &tmp[0] */) + for n = 0; n < 16; n = n + (2) { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8ITransform})).f(tls, (ref + uintptr(VP8Scan[n])), ((bp) /* &tmp[0] */ + uintptr(n)*32), (yuv_out + uintptr(VP8Scan[n])), 1) + } + + return nz +} + +func ReconstructIntra4(tls *libc.TLS, it uintptr, levels uintptr, src uintptr, yuv_out uintptr, mode int32) int32 { /* quant_enc.c:822:12: */ + bp := tls.Alloc(32) + defer tls.Free(32) + + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var ref uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_p_ + uintptr(VP8I4ModeOffsets[mode])) + var dqm uintptr = ((enc + 608 /* &.dqm_ */) + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.segment_ */))&0x60>>5))))*744) + var nz int32 = 0 + // var tmp [16]int16_t at bp, 32 + + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8FTransform})).f(tls, src, ref, (bp) /* &tmp[0] */) + if (1 != 0) && ((*VP8EncIterator)(unsafe.Pointer(it)).do_trellis_ != 0) { + var x int32 = ((*VP8EncIterator)(unsafe.Pointer(it)).i4_ & 3) + var y int32 = ((*VP8EncIterator)(unsafe.Pointer(it)).i4_ >> 2) + var ctx int32 = (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(x)*4)) + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + uintptr(y)*4))) + nz = TrellisQuantizeBlock(tls, enc, (bp) /* &tmp[0] */, levels, ctx, TYPE_I4_AC, (dqm /* &.y1_ */), + (*VP8SegmentInfo)(unsafe.Pointer(dqm)).lambda_trellis_i4_) + } else { + nz = (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8EncQuantizeBlock})).f(tls, (bp) /* &tmp[0] */, levels, (dqm /* &.y1_ */)) + } + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8ITransform})).f(tls, ref, (bp) /* &tmp[0] */, yuv_out, 0) + return nz +} + +//------------------------------------------------------------------------------ +// DC-error diffusion + +// Diffusion weights. We under-correct a bit (15/16th of the error is actually +// diffused) to avoid 'rainbow' chessboard pattern of blocks at q~=0. + +// Quantize as usual, but also compute and return the quantization error. +// Error is already divided by DSHIFT. +func QuantizeSingle(tls *libc.TLS, v uintptr, mtx uintptr) int32 { /* quant_enc.c:858:12: */ + var V int32 = int32(*(*int16_t)(unsafe.Pointer(v))) + var sign int32 = (libc.Bool32(V < 0)) + if sign != 0 { + V = -V + } + if V > int32(*(*uint32_t)(unsafe.Pointer((mtx + 128 /* &.zthresh_ */)))) { + var qV int32 = (QUANTDIV(tls, uint32(V), uint32(*(*uint16_t)(unsafe.Pointer((mtx + 32 /* &.iq_ */)))), *(*uint32_t)(unsafe.Pointer((mtx + 64 /* &.bias_ */)))) * int32(*(*uint16_t)(unsafe.Pointer((mtx /* &.q_ */))))) + var err int32 = (V - qV) + *(*int16_t)(unsafe.Pointer(v)) = func() int16 { + if sign != 0 { + return int16(-qV) + } + return int16(qV) + }() + return ((func() int32 { + if sign != 0 { + return -err + } + return err + }()) >> 1) + } + *(*int16_t)(unsafe.Pointer(v)) = int16(0) + return ((func() int32 { + if sign != 0 { + return -V + } + return V + }()) >> 1) +} + +func CorrectDCValues(tls *libc.TLS, it uintptr, mtx uintptr, tmp uintptr, rd uintptr) { /* quant_enc.c:872:13: */ + // | top[0] | top[1] + // --------+--------+--------- + // left[0] | tmp[0] tmp[1] <-> err0 err1 + // left[1] | tmp[2] tmp[3] err2 err3 + // + // Final errors {err1,err2,err3} are preserved and later restored + // as top[]/left[] on the next block. + var ch int32 + for ch = 0; ch <= 1; ch++ { + var top uintptr = (((*VP8EncIterator)(unsafe.Pointer(it)).top_derr_ + uintptr((*VP8EncIterator)(unsafe.Pointer(it)).x_)*4) + uintptr(ch)*2) + var left uintptr = (it + 344 /* &.left_derr_ */ + uintptr(ch)*2) + var c uintptr = (tmp + uintptr((ch*4))*32) + var err0 int32 + var err1 int32 + var err2 int32 + var err3 int32 + *(*int16_t)(unsafe.Pointer((c))) += int16_t((((7 * int32(*(*int8_t)(unsafe.Pointer(top)))) + (8 * int32(*(*int8_t)(unsafe.Pointer(left))))) >> (4 - 1))) + err0 = QuantizeSingle(tls, (c), mtx) + *(*int16_t)(unsafe.Pointer((c + 1*32))) += int16_t((((7 * int32(*(*int8_t)(unsafe.Pointer(top + 1)))) + (8 * err0)) >> (4 - 1))) + err1 = QuantizeSingle(tls, (c + 1*32), mtx) + *(*int16_t)(unsafe.Pointer((c + 2*32))) += int16_t((((7 * err0) + (8 * int32(*(*int8_t)(unsafe.Pointer(left + 1))))) >> (4 - 1))) + err2 = QuantizeSingle(tls, (c + 2*32), mtx) + *(*int16_t)(unsafe.Pointer((c + 3*32))) += int16_t((((7 * err1) + (8 * err2)) >> (4 - 1))) + err3 = QuantizeSingle(tls, (c + 3*32), mtx) + // error 'err' is bounded by mtx->q_[0] which is 132 at max. Hence + // err >> DSCALE will fit in an int8_t type if DSCALE>=1. + + *(*int8_t)(unsafe.Pointer(((rd + 868 /* &.derr */) + uintptr(ch)*3))) = int8_t(err1) + *(*int8_t)(unsafe.Pointer(((rd + 868 /* &.derr */) + uintptr(ch)*3) + 1)) = int8_t(err2) + *(*int8_t)(unsafe.Pointer(((rd + 868 /* &.derr */) + uintptr(ch)*3) + 2)) = int8_t(err3) + } +} + +func StoreDiffusionErrors(tls *libc.TLS, it uintptr, rd uintptr) { /* quant_enc.c:905:13: */ + var ch int32 + for ch = 0; ch <= 1; ch++ { + var top uintptr = (((*VP8EncIterator)(unsafe.Pointer(it)).top_derr_ + uintptr((*VP8EncIterator)(unsafe.Pointer(it)).x_)*4) + uintptr(ch)*2) + var left uintptr = (it + 344 /* &.left_derr_ */ + uintptr(ch)*2) + *(*int8_t)(unsafe.Pointer(left)) = *(*int8_t)(unsafe.Pointer(((rd + 868 /* &.derr */) + uintptr(ch)*3))) // restore err1 + *(*int8_t)(unsafe.Pointer(left + 1)) = (int8_t((3 * int32(*(*int8_t)(unsafe.Pointer(((rd + 868 /* &.derr */) + uintptr(ch)*3) + 2)))) >> 2)) // ... 3/4th of err3 + *(*int8_t)(unsafe.Pointer(top)) = *(*int8_t)(unsafe.Pointer(((rd + 868 /* &.derr */) + uintptr(ch)*3) + 1)) // ... err2 + *(*int8_t)(unsafe.Pointer(top + 1)) = (int8_t(int32(*(*int8_t)(unsafe.Pointer(((rd + 868 /* &.derr */) + uintptr(ch)*3) + 2))) - int32(*(*int8_t)(unsafe.Pointer(left + 1))))) // ... 1/4th of err3. + } +} + +//------------------------------------------------------------------------------ + +func ReconstructUV(tls *libc.TLS, it uintptr, rd uintptr, yuv_out uintptr, mode int32) int32 { /* quant_enc.c:925:12: */ + bp := tls.Alloc(256) + defer tls.Free(256) + + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var ref uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_p_ + uintptr(VP8UVModeOffsets[mode])) + var src uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((16))) + var dqm uintptr = ((enc + 608 /* &.dqm_ */) + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.segment_ */))&0x60>>5))))*744) + var nz int32 = 0 + var n int32 + // var tmp [8][16]int16_t at bp, 256 + + for n = 0; n < 8; n = n + (2) { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8FTransform2})).f(tls, (src + uintptr(VP8ScanUV[n])), (ref + uintptr(VP8ScanUV[n])), ((bp) /* &tmp[0] */ + uintptr(n)*32)) + } + if (*VP8EncIterator)(unsafe.Pointer(it)).top_derr_ != (uintptr(0)) { + CorrectDCValues(tls, it, (dqm + 448 /* &.uv_ */), (bp) /* &tmp[0] */, rd) + } + + if (0 != 0) && ((*VP8EncIterator)(unsafe.Pointer(it)).do_trellis_ != 0) { + var ch int32 + var x int32 + var y int32 + ch = 0 + n = 0 + for ; ch <= 2; ch = ch + (2) { + for y = 0; y < 2; y++ { + x = 0 + __1: + if !(x < 2) { + goto __3 + } + { + var ctx int32 = (*(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(((4+ch)+x))*4)) + *(*int32)(unsafe.Pointer((it + 168 /* &.left_nz_ */) + uintptr(((4+ch)+y))*4))) + var non_zero int32 = TrellisQuantizeBlock(tls, + enc, ((bp) /* &tmp[0] */ + uintptr(n)*32), ((rd + 584 /* &.uv_levels */) + uintptr(n)*32), ctx, TYPE_CHROMA_A, (dqm + 448 /* &.uv_ */), + (*VP8SegmentInfo)(unsafe.Pointer(dqm)).lambda_trellis_uv_) + *(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(((4+ch)+x))*4)) = libc.AssignPtrInt32(((it + 168 /* &.left_nz_ */) + uintptr(((4+ch)+y))*4), non_zero) + nz = nz | (non_zero << n) + + } + goto __2 + __2: + x++ + n++ + goto __1 + goto __3 + __3: + } + } + } else { + for n = 0; n < 8; n = n + (2) { + nz = nz | ((*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8EncQuantize2Blocks})).f(tls, ((bp) /* &tmp[0] */ +uintptr(n)*32), ((rd+584 /* &.uv_levels */)+uintptr(n)*32), (dqm+448 /* &.uv_ */)) << n) + } + } + + for n = 0; n < 8; n = n + (2) { + (*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8ITransform})).f(tls, (ref + uintptr(VP8ScanUV[n])), ((bp) /* &tmp[0] */ + uintptr(n)*32), (yuv_out + uintptr(VP8ScanUV[n])), 1) + } + return (nz << 16) +} + +//------------------------------------------------------------------------------ +// RD-opt decision. Reconstruct each modes, evalue distortion and bit-cost. +// Pick the mode is lower RD-cost = Rate + lambda * Distortion. + +func StoreMaxDelta(tls *libc.TLS, dqm uintptr, DCs uintptr) { /* quant_enc.c:970:13: */ + // We look at the first three AC coefficients to determine what is the average + // delta between each sub-4x4 block. + var v0 int32 = libc.Xabs(tls, int32(*(*int16_t)(unsafe.Pointer(DCs + 1*2)))) + var v1 int32 = libc.Xabs(tls, int32(*(*int16_t)(unsafe.Pointer(DCs + 2*2)))) + var v2 int32 = libc.Xabs(tls, int32(*(*int16_t)(unsafe.Pointer(DCs + 4*2)))) + var max_v int32 + if v1 > v0 { + max_v = v1 + } else { + max_v = v0 + } + if v2 > max_v { + max_v = v2 + } else { + max_v = max_v + } + if max_v > (*VP8SegmentInfo)(unsafe.Pointer(dqm)).max_edge_ { + (*VP8SegmentInfo)(unsafe.Pointer(dqm)).max_edge_ = max_v + } +} + +func SwapModeScore(tls *libc.TLS, a uintptr, b uintptr) { /* quant_enc.c:981:13: */ + var tmp uintptr = *(*uintptr)(unsafe.Pointer(a)) + *(*uintptr)(unsafe.Pointer(a)) = *(*uintptr)(unsafe.Pointer(b)) + *(*uintptr)(unsafe.Pointer(b)) = tmp +} + +func SwapPtr(tls *libc.TLS, a uintptr, b uintptr) { /* quant_enc.c:987:13: */ + var tmp uintptr = *(*uintptr)(unsafe.Pointer(a)) + *(*uintptr)(unsafe.Pointer(a)) = *(*uintptr)(unsafe.Pointer(b)) + *(*uintptr)(unsafe.Pointer(b)) = tmp +} + +func SwapOut(tls *libc.TLS, it uintptr) { /* quant_enc.c:993:13: */ + SwapPtr(tls, (it + 16 /* &.yuv_out_ */), (it + 24 /* &.yuv_out2_ */)) +} + +func PickBestIntra16(tls *libc.TLS, it uintptr, rd uintptr) { /* quant_enc.c:997:13: */ + bp := tls.Alloc(896) + defer tls.Free(896) + + var kNumBlocks int32 = 16 + var dqm uintptr = (((*VP8EncIterator)(unsafe.Pointer(it)).enc_ + 608 /* &.dqm_ */) + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.segment_ */))&0x60>>5))))*744) + var lambda int32 = (*VP8SegmentInfo)(unsafe.Pointer(dqm)).lambda_i16_ + var tlambda int32 = (*VP8SegmentInfo)(unsafe.Pointer(dqm)).tlambda_ + var src uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((0))) + // var rd_tmp VP8ModeScore at bp, 880 + + *(*uintptr)(unsafe.Pointer(bp + 880 /* rd_cur */)) = (bp) /* &rd_tmp */ + *(*uintptr)(unsafe.Pointer(bp + 888 /* rd_best */)) = rd + var mode int32 + var is_flat int32 = IsFlatSource16(tls, ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((0)))) + + (*VP8ModeScore)(unsafe.Pointer(rd)).mode_i16 = -1 + for mode = 0; mode < NUM_PRED_MODES; mode++ { + var tmp_dst uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out2_ + uintptr((0))) // scratch buffer + (*VP8ModeScore)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(bp + 880 /* rd_cur */)))).mode_i16 = mode + + // Reconstruct + (*VP8ModeScore)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(bp + 880 /* rd_cur */)))).nz = uint32_t(ReconstructIntra16(tls, it, *(*uintptr)(unsafe.Pointer(bp + 880 /* rd_cur */)), tmp_dst, mode)) + + // Measure RD-score + (*VP8ModeScore)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(bp + 880 /* rd_cur */)))).D = score_t((*struct { + f func(*libc.TLS, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSE16x16})).f(tls, src, tmp_dst)) + (*VP8ModeScore)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(bp + 880 /* rd_cur */)))).SD = func() int64 { + if tlambda != 0 { + return (int64((((tlambda) * ((*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8TDisto16x16})).f(tls, src, tmp_dst, uintptr(unsafe.Pointer(&kWeightY))))) + 128) >> 8)) + } + return int64(0) + }() + (*VP8ModeScore)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(bp + 880 /* rd_cur */)))).H = score_t(VP8FixedCostsI16[mode]) + (*VP8ModeScore)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(bp + 880 /* rd_cur */)))).R = score_t(VP8GetCostLuma16(tls, it, *(*uintptr)(unsafe.Pointer(bp + 880 /* rd_cur */)))) + if is_flat != 0 { + // refine the first impression (which was in pixel space) + is_flat = IsFlat_C(tls, (*(*uintptr)(unsafe.Pointer(bp + 880 /* rd_cur */)) + 72 /* &.y_ac_levels */), kNumBlocks, 0) + if is_flat != 0 { + // Block is very flat. We put emphasis on the distortion being very low! + *(*score_t)(unsafe.Pointer((*(*uintptr)(unsafe.Pointer(bp + 880 /* rd_cur */)) /* &.D */))) *= (int64(2)) + *(*score_t)(unsafe.Pointer((*(*uintptr)(unsafe.Pointer(bp + 880 /* rd_cur */)) + 8 /* &.SD */))) *= (int64(2)) + } + } + + // Since we always examine Intra16 first, we can overwrite *rd directly. + SetRDScore(tls, lambda, *(*uintptr)(unsafe.Pointer(bp + 880 /* rd_cur */))) + if (mode == 0) || ((*VP8ModeScore)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(bp + 880 /* rd_cur */)))).score < (*VP8ModeScore)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(bp + 888 /* rd_best */)))).score) { + SwapModeScore(tls, (bp + 880) /* &rd_cur */, (bp + 888) /* &rd_best */) + SwapOut(tls, it) + } + } + if *(*uintptr)(unsafe.Pointer(bp + 888 /* rd_best */)) != rd { + libc.Xmemcpy(tls, rd, *(*uintptr)(unsafe.Pointer(bp + 888 /* rd_best */)), uint64(unsafe.Sizeof(VP8ModeScore{}))) + } + SetRDScore(tls, (*VP8SegmentInfo)(unsafe.Pointer(dqm)).lambda_mode_, rd) // finalize score for mode decision. + VP8SetIntra16Mode(tls, it, (*VP8ModeScore)(unsafe.Pointer(rd)).mode_i16) + + // we have a blocky macroblock (only DCs are non-zero) with fairly high + // distortion, record max delta so we can later adjust the minimal filtering + // strength needed to smooth these blocks out. + if (((*VP8ModeScore)(unsafe.Pointer(rd)).nz & uint32_t(0x100ffff)) == uint32_t(0x1000000)) && ((*VP8ModeScore)(unsafe.Pointer(rd)).D > score_t((*VP8SegmentInfo)(unsafe.Pointer(dqm)).min_disto_)) { + StoreMaxDelta(tls, dqm, (rd + 40 /* &.y_dc_levels */)) + } +} + +//------------------------------------------------------------------------------ + +// return the cost array corresponding to the surrounding prediction modes. +func GetCostModeI4(tls *libc.TLS, it uintptr, modes uintptr) uintptr { /* quant_enc.c:1057:22: */ + var preds_w int32 = (*VP8Encoder)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).enc_)).preds_w_ + var x int32 = ((*VP8EncIterator)(unsafe.Pointer(it)).i4_ & 3) + var y int32 = ((*VP8EncIterator)(unsafe.Pointer(it)).i4_ >> 2) + var left int32 + if x == 0 { + left = int32(*(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).preds_ + uintptr(((y * preds_w) - 1))))) + } else { + left = int32(*(*uint8_t)(unsafe.Pointer(modes + uintptr(((*VP8EncIterator)(unsafe.Pointer(it)).i4_ - 1))))) + } + var top int32 + if y == 0 { + top = int32(*(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).preds_ + uintptr((-preds_w + x))))) + } else { + top = int32(*(*uint8_t)(unsafe.Pointer(modes + uintptr(((*VP8EncIterator)(unsafe.Pointer(it)).i4_ - 4))))) + } + return ((uintptr(unsafe.Pointer(&VP8FixedCostsI4)) + uintptr(top)*200) + uintptr(left)*20) +} + +func PickBestIntra4(tls *libc.TLS, it uintptr, rd uintptr) int32 { /* quant_enc.c:1066:12: */ + bp := tls.Alloc(2688) + defer tls.Free(2688) + + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var dqm uintptr = ((enc + 608 /* &.dqm_ */) + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.segment_ */))&0x60>>5))))*744) + var lambda int32 = (*VP8SegmentInfo)(unsafe.Pointer(dqm)).lambda_i4_ + var tlambda int32 = (*VP8SegmentInfo)(unsafe.Pointer(dqm)).tlambda_ + var src0 uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((0))) + var best_blocks uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out2_ + uintptr((0))) + var total_header_bits int32 = 0 + // var rd_best VP8ModeScore at bp, 880 + + if (*VP8Encoder)(unsafe.Pointer(enc)).max_i4_header_bits_ == 0 { + return 0 + } + + InitScore(tls, (bp) /* &rd_best */) + (*VP8ModeScore)(unsafe.Pointer(bp /* &rd_best */)).H = int64(211) // '211' is the value of VP8BitCost(0, 145) + SetRDScore(tls, (*VP8SegmentInfo)(unsafe.Pointer(dqm)).lambda_mode_, (bp) /* &rd_best */) + VP8IteratorStartI4(tls, it) + for ok := true; ok; ok = (VP8IteratorRotateI4(tls, it, best_blocks) != 0) { + var kNumBlocks int32 = 1 + // var rd_i4 VP8ModeScore at bp+880, 880 + + var mode int32 + var best_mode int32 = -1 + var src uintptr = (src0 + uintptr(VP8Scan[(*VP8EncIterator)(unsafe.Pointer(it)).i4_])) + var mode_costs uintptr = GetCostModeI4(tls, it, (rd + 844 /* &.modes_i4 */)) + *(*uintptr)(unsafe.Pointer(bp + 2680 /* best_block */)) = (best_blocks + uintptr(VP8Scan[(*VP8EncIterator)(unsafe.Pointer(it)).i4_])) + *(*uintptr)(unsafe.Pointer(bp + 2672 /* tmp_dst */)) = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_p_ + uintptr(((((3 * 16) * 32) + (4 * 32)) + 8))) // scratch buffer. + + InitScore(tls, (bp + 880) /* &rd_i4 */) + VP8MakeIntra4Preds(tls, it) + for mode = 0; mode < NUM_BMODES; mode++ { + // var rd_tmp VP8ModeScore at bp+1792, 880 + + // var tmp_levels [16]int16_t at bp+1760, 32 + + // Reconstruct + (*VP8ModeScore)(unsafe.Pointer(bp + 1792 /* &rd_tmp */)).nz = (uint32_t(ReconstructIntra4(tls, it, (bp+1760) /* &tmp_levels[0] */, src, *(*uintptr)(unsafe.Pointer(bp + 2672 /* tmp_dst */)), mode) << (*VP8EncIterator)(unsafe.Pointer(it)).i4_)) + + // Compute RD-score + (*VP8ModeScore)(unsafe.Pointer(bp + 1792 /* &rd_tmp */)).D = score_t((*struct { + f func(*libc.TLS, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSE4x4})).f(tls, src, *(*uintptr)(unsafe.Pointer(bp + 2672 /* tmp_dst */)))) + (*VP8ModeScore)(unsafe.Pointer(bp + 1792 /* &rd_tmp */)).SD = func() int64 { + if tlambda != 0 { + return (int64((((tlambda) * ((*struct { + f func(*libc.TLS, uintptr, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8TDisto4x4})).f(tls, src, *(*uintptr)(unsafe.Pointer(bp + 2672 /* tmp_dst */)), uintptr(unsafe.Pointer(&kWeightY))))) + 128) >> 8)) + } + return int64(0) + }() + (*VP8ModeScore)(unsafe.Pointer(bp + 1792 /* &rd_tmp */)).H = score_t(*(*uint16_t)(unsafe.Pointer(mode_costs + uintptr(mode)*2))) + + // Add flatness penalty, to avoid flat area to be mispredicted + // by a complex mode. + if (mode > 0) && (IsFlat_C(tls, (bp+1760) /* &tmp_levels[0] */, kNumBlocks, 3) != 0) { + (*VP8ModeScore)(unsafe.Pointer(bp + 1792 /* &rd_tmp */)).R = (score_t(140 * kNumBlocks)) + } else { + (*VP8ModeScore)(unsafe.Pointer(bp + 1792 /* &rd_tmp */)).R = int64(0) + } + + // early-out check + SetRDScore(tls, lambda, (bp + 1792) /* &rd_tmp */) + if (best_mode >= 0) && ((*VP8ModeScore)(unsafe.Pointer(bp+1792 /* &rd_tmp */)).score >= (*VP8ModeScore)(unsafe.Pointer(bp+880 /* &rd_i4 */)).score) { + continue + } + + // finish computing score + *(*score_t)(unsafe.Pointer(((bp + 1792) /* &rd_tmp */ + 24 /* &.R */))) += (score_t(VP8GetCostLuma4(tls, it, (bp + 1760) /* &tmp_levels[0] */))) + SetRDScore(tls, lambda, (bp + 1792) /* &rd_tmp */) + + if (best_mode < 0) || ((*VP8ModeScore)(unsafe.Pointer(bp+1792 /* &rd_tmp */)).score < (*VP8ModeScore)(unsafe.Pointer(bp+880 /* &rd_i4 */)).score) { + CopyScore(tls, (bp + 880) /* &rd_i4 */, (bp + 1792) /* &rd_tmp */) + best_mode = mode + SwapPtr(tls, (bp + 2672) /* &tmp_dst */, (bp + 2680) /* &best_block */) + libc.Xmemcpy(tls, (((bp) /* &rd_best */ + 72 /* &.y_ac_levels */) + uintptr((*VP8EncIterator)(unsafe.Pointer(it)).i4_)*32), (bp + 1760), /* &tmp_levels[0] */ + uint64(unsafe.Sizeof([16]int16_t{}))) + } + } + SetRDScore(tls, (*VP8SegmentInfo)(unsafe.Pointer(dqm)).lambda_mode_, (bp + 880) /* &rd_i4 */) + AddScore(tls, (bp) /* &rd_best */, (bp + 880) /* &rd_i4 */) + if (*VP8ModeScore)(unsafe.Pointer(bp /* &rd_best */)).score >= (*VP8ModeScore)(unsafe.Pointer(rd)).score { + return 0 + } + total_header_bits = total_header_bits + (int32((*VP8ModeScore)(unsafe.Pointer(bp + 880 /* &rd_i4 */)).H)) // <- equal to mode_costs[best_mode]; + if total_header_bits > (*VP8Encoder)(unsafe.Pointer(enc)).max_i4_header_bits_ { + return 0 + } + // Copy selected samples if not in the right place already. + if *(*uintptr)(unsafe.Pointer(bp + 2680 /* best_block */)) != (best_blocks + uintptr(VP8Scan[(*VP8EncIterator)(unsafe.Pointer(it)).i4_])) { + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8Copy4x4})).f(tls, *(*uintptr)(unsafe.Pointer(bp + 2680 /* best_block */)), (best_blocks + uintptr(VP8Scan[(*VP8EncIterator)(unsafe.Pointer(it)).i4_]))) + } + *(*uint8_t)(unsafe.Pointer((rd + 844 /* &.modes_i4 */) + uintptr((*VP8EncIterator)(unsafe.Pointer(it)).i4_))) = uint8_t(best_mode) + *(*int32)(unsafe.Pointer((it + 132 /* &.top_nz_ */) + uintptr(((*VP8EncIterator)(unsafe.Pointer(it)).i4_&3))*4)) = libc.AssignPtrInt32(((it + 168 /* &.left_nz_ */) + uintptr(((*VP8EncIterator)(unsafe.Pointer(it)).i4_>>2))*4), (func() int32 { + if (*VP8ModeScore)(unsafe.Pointer(bp+880 /* &rd_i4 */)).nz != 0 { + return 1 + } + return 0 + }())) + } + + // finalize state + CopyScore(tls, rd, (bp) /* &rd_best */) + VP8SetIntra4Mode(tls, it, (rd + 844 /* &.modes_i4 */)) + SwapOut(tls, it) + libc.Xmemcpy(tls, (rd + 72 /* &.y_ac_levels */), ((bp) /* &rd_best */ + 72 /* &.y_ac_levels */), uint64(unsafe.Sizeof([16][16]int16_t{}))) + return 1 // select intra4x4 over intra16x16 +} + +//------------------------------------------------------------------------------ + +func PickBestUV(tls *libc.TLS, it uintptr, rd uintptr) { /* quant_enc.c:1162:13: */ + bp := tls.Alloc(1776) + defer tls.Free(1776) + + var kNumBlocks int32 = 8 + var dqm uintptr = (((*VP8EncIterator)(unsafe.Pointer(it)).enc_ + 608 /* &.dqm_ */) + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.segment_ */))&0x60>>5))))*744) + var lambda int32 = (*VP8SegmentInfo)(unsafe.Pointer(dqm)).lambda_uv_ + var src uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((16))) + *(*uintptr)(unsafe.Pointer(bp + 1768 /* tmp_dst */)) = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out2_ + uintptr((16))) // scratch buffer + var dst0 uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_ + uintptr((16))) + *(*uintptr)(unsafe.Pointer(bp + 1760 /* dst */)) = dst0 + // var rd_best VP8ModeScore at bp, 880 + + var mode int32 + + (*VP8ModeScore)(unsafe.Pointer(rd)).mode_uv = -1 + InitScore(tls, (bp) /* &rd_best */) + for mode = 0; mode < NUM_PRED_MODES; mode++ { + // var rd_uv VP8ModeScore at bp+880, 880 + + // Reconstruct + (*VP8ModeScore)(unsafe.Pointer(bp + 880 /* &rd_uv */)).nz = uint32_t(ReconstructUV(tls, it, (bp + 880) /* &rd_uv */, *(*uintptr)(unsafe.Pointer(bp + 1768 /* tmp_dst */)), mode)) + + // Compute RD-score + (*VP8ModeScore)(unsafe.Pointer(bp + 880 /* &rd_uv */)).D = score_t((*struct { + f func(*libc.TLS, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSE16x8})).f(tls, src, *(*uintptr)(unsafe.Pointer(bp + 1768 /* tmp_dst */)))) + (*VP8ModeScore)(unsafe.Pointer(bp + 880 /* &rd_uv */)).SD = int64(0) // not calling TDisto here: it tends to flatten areas. + (*VP8ModeScore)(unsafe.Pointer(bp + 880 /* &rd_uv */)).H = score_t(VP8FixedCostsUV[mode]) + (*VP8ModeScore)(unsafe.Pointer(bp + 880 /* &rd_uv */)).R = score_t(VP8GetCostUV(tls, it, (bp + 880) /* &rd_uv */)) + if (mode > 0) && (IsFlat_C(tls, ((bp+880) /* &rd_uv */ +584 /* &.uv_levels */), kNumBlocks, 2) != 0) { + *(*score_t)(unsafe.Pointer(((bp + 880) /* &rd_uv */ + 24 /* &.R */))) += (score_t(140 * kNumBlocks)) + } + + SetRDScore(tls, lambda, (bp + 880) /* &rd_uv */) + if (mode == 0) || ((*VP8ModeScore)(unsafe.Pointer(bp+880 /* &rd_uv */)).score < (*VP8ModeScore)(unsafe.Pointer(bp /* &rd_best */)).score) { + CopyScore(tls, (bp) /* &rd_best */, (bp + 880) /* &rd_uv */) + (*VP8ModeScore)(unsafe.Pointer(rd)).mode_uv = mode + libc.Xmemcpy(tls, (rd + 584 /* &.uv_levels */), ((bp + 880) /* &rd_uv */ + 584 /* &.uv_levels */), uint64(unsafe.Sizeof([8][16]int16_t{}))) + if (*VP8EncIterator)(unsafe.Pointer(it)).top_derr_ != (uintptr(0)) { + libc.Xmemcpy(tls, (rd + 868 /* &.derr */), ((bp + 880) /* &rd_uv */ + 868 /* &.derr */), uint64(unsafe.Sizeof([2][3]int8_t{}))) + } + SwapPtr(tls, (bp + 1760) /* &dst */, (bp + 1768) /* &tmp_dst */) + } + } + VP8SetIntraUVMode(tls, it, (*VP8ModeScore)(unsafe.Pointer(rd)).mode_uv) + AddScore(tls, rd, (bp) /* &rd_best */) + if *(*uintptr)(unsafe.Pointer(bp + 1760 /* dst */)) != dst0 { // copy 16x8 block if needed + (*struct { + f func(*libc.TLS, uintptr, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8Copy16x8})).f(tls, *(*uintptr)(unsafe.Pointer(bp + 1760 /* dst */)), dst0) + } + if (*VP8EncIterator)(unsafe.Pointer(it)).top_derr_ != (uintptr(0)) { // store diffusion errors for next block + StoreDiffusionErrors(tls, it, rd) + } +} + +//------------------------------------------------------------------------------ +// Final reconstruction and quantization. + +func SimpleQuantize(tls *libc.TLS, it uintptr, rd uintptr) { /* quant_enc.c:1214:13: */ + var enc uintptr = (*VP8EncIterator)(unsafe.Pointer(it)).enc_ + var is_i16 int32 = (libc.Bool32((int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.type_ */)) & 0x3 >> 0)) == 1)) + var nz int32 = 0 + + if is_i16 != 0 { + nz = ReconstructIntra16(tls, it, rd, ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_ + uintptr((0))), int32(*(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).preds_)))) + } else { + VP8IteratorStartI4(tls, it) + for ok := true; ok; ok = (VP8IteratorRotateI4(tls, it, ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_+uintptr((0)))) != 0) { + var mode int32 = int32(*(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).preds_ + uintptr((((*VP8EncIterator)(unsafe.Pointer(it)).i4_ & 3) + (((*VP8EncIterator)(unsafe.Pointer(it)).i4_ >> 2) * (*VP8Encoder)(unsafe.Pointer(enc)).preds_w_)))))) + var src uintptr = (((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((0))) + uintptr(VP8Scan[(*VP8EncIterator)(unsafe.Pointer(it)).i4_])) + var dst uintptr = (((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_ + uintptr((0))) + uintptr(VP8Scan[(*VP8EncIterator)(unsafe.Pointer(it)).i4_])) + VP8MakeIntra4Preds(tls, it) + nz = nz | (ReconstructIntra4(tls, it, ((rd+72 /* &.y_ac_levels */)+uintptr((*VP8EncIterator)(unsafe.Pointer(it)).i4_)*32), + src, dst, mode) << (*VP8EncIterator)(unsafe.Pointer(it)).i4_) + } + } + + nz = nz | (ReconstructUV(tls, it, rd, ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_ + uintptr((16))), (int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.uv_mode_ */)) & 0xc >> 2)))) + (*VP8ModeScore)(unsafe.Pointer(rd)).nz = uint32_t(nz) +} + +// Refine intra16/intra4 sub-modes based on distortion only (not rate). +func RefineUsingDistortion(tls *libc.TLS, it uintptr, try_both_modes int32, refine_uv_mode int32, rd uintptr) { /* quant_enc.c:1239:13: */ + var best_score score_t = (0x7fffffffffffff) + var nz int32 = 0 + var mode int32 + var is_i16 int32 = (libc.Bool32((try_both_modes != 0) || ((int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.type_ */)) & 0x3 >> 0)) == 1))) + + var dqm uintptr = (((*VP8EncIterator)(unsafe.Pointer(it)).enc_ + 608 /* &.dqm_ */) + uintptr((uint32(int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.segment_ */))&0x60>>5))))*744) + // Some empiric constants, of approximate order of magnitude. + var lambda_d_i16 int32 = 106 + var lambda_d_i4 int32 = 11 + var lambda_d_uv int32 = 120 + var score_i4 score_t = (*VP8SegmentInfo)(unsafe.Pointer(dqm)).i4_penalty_ + var i4_bit_sum score_t = int64(0) + var bit_limit score_t + if try_both_modes != 0 { + bit_limit = int64((*VP8Encoder)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).enc_)).mb_header_limit_) + } else { + bit_limit = (0x7fffffffffffff) + } // no early-out allowed + + if is_i16 != 0 { // First, evaluate Intra16 distortion + var best_mode int32 = -1 + var src uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((0))) + for mode = 0; mode < NUM_PRED_MODES; mode++ { + var ref uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_p_ + uintptr(VP8I16ModeOffsets[mode])) + var score score_t = ((score_t((*struct { + f func(*libc.TLS, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSE16x16})).f(tls, src, ref)) * int64(256)) + + (score_t(int32(VP8FixedCostsI16[mode]) * lambda_d_i16))) + if (mode > 0) && (score_t(VP8FixedCostsI16[mode]) > bit_limit) { + continue + } + + if score < best_score { + best_mode = mode + best_score = score + } + } + if ((*VP8EncIterator)(unsafe.Pointer(it)).x_ == 0) || ((*VP8EncIterator)(unsafe.Pointer(it)).y_ == 0) { + // avoid starting a checkerboard resonance from the border. See bug #432. + if IsFlatSource16(tls, src) != 0 { + if (*VP8EncIterator)(unsafe.Pointer(it)).x_ == 0 { + best_mode = 0 + } else { + best_mode = 2 + } + try_both_modes = 0 // stick to i16 + } + } + VP8SetIntra16Mode(tls, it, best_mode) + // we'll reconstruct later, if i16 mode actually gets selected + } + + // Next, evaluate Intra4 + if (try_both_modes != 0) || !(is_i16 != 0) { + // We don't evaluate the rate here, but just account for it through a + // constant penalty (i4 mode usually needs more bits compared to i16). + is_i16 = 0 + VP8IteratorStartI4(tls, it) + for ok := true; ok; ok = (VP8IteratorRotateI4(tls, it, ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out2_+uintptr((0)))) != 0) { + var best_i4_mode int32 = -1 + var best_i4_score score_t = (0x7fffffffffffff) + var src uintptr = (((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((0))) + uintptr(VP8Scan[(*VP8EncIterator)(unsafe.Pointer(it)).i4_])) + var mode_costs uintptr = GetCostModeI4(tls, it, (rd + 844 /* &.modes_i4 */)) + + VP8MakeIntra4Preds(tls, it) + for mode = 0; mode < NUM_BMODES; mode++ { + var ref uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_p_ + uintptr(VP8I4ModeOffsets[mode])) + var score score_t = (score_t(((*struct { + f func(*libc.TLS, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSE4x4})).f(tls, src, ref) * 256) + + (int32(*(*uint16_t)(unsafe.Pointer(mode_costs + uintptr(mode)*2))) * lambda_d_i4))) + if score < best_i4_score { + best_i4_mode = mode + best_i4_score = score + } + } + i4_bit_sum = i4_bit_sum + (score_t(*(*uint16_t)(unsafe.Pointer(mode_costs + uintptr(best_i4_mode)*2)))) + *(*uint8_t)(unsafe.Pointer((rd + 844 /* &.modes_i4 */) + uintptr((*VP8EncIterator)(unsafe.Pointer(it)).i4_))) = uint8_t(best_i4_mode) + score_i4 = score_i4 + (best_i4_score) + if (score_i4 >= best_score) || (i4_bit_sum > bit_limit) { + // Intra4 won't be better than Intra16. Bail out and pick Intra16. + is_i16 = 1 + break + } else { // reconstruct partial block inside yuv_out2_ buffer + var tmp_dst uintptr = (((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out2_ + uintptr((0))) + uintptr(VP8Scan[(*VP8EncIterator)(unsafe.Pointer(it)).i4_])) + nz = nz | (ReconstructIntra4(tls, it, ((rd+72 /* &.y_ac_levels */)+uintptr((*VP8EncIterator)(unsafe.Pointer(it)).i4_)*32), + src, tmp_dst, best_i4_mode) << (*VP8EncIterator)(unsafe.Pointer(it)).i4_) + } + } + } + + // Final reconstruction, depending on which mode is selected. + if !(is_i16 != 0) { + VP8SetIntra4Mode(tls, it, (rd + 844 /* &.modes_i4 */)) + SwapOut(tls, it) + best_score = score_i4 + } else { + nz = ReconstructIntra16(tls, it, rd, ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_ + uintptr((0))), int32(*(*uint8_t)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).preds_)))) + } + + // ... and UV! + if refine_uv_mode != 0 { + var best_mode int32 = -1 + var best_uv_score score_t = (0x7fffffffffffff) + var src uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_in_ + uintptr((16))) + for mode = 0; mode < NUM_PRED_MODES; mode++ { + var ref uintptr = ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_p_ + uintptr(VP8UVModeOffsets[mode])) + var score score_t = (score_t(((*struct { + f func(*libc.TLS, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{VP8SSE16x8})).f(tls, src, ref) * 256) + + (int32(VP8FixedCostsUV[mode]) * lambda_d_uv))) + if score < best_uv_score { + best_mode = mode + best_uv_score = score + } + } + VP8SetIntraUVMode(tls, it, best_mode) + } + nz = nz | (ReconstructUV(tls, it, rd, ((*VP8EncIterator)(unsafe.Pointer(it)).yuv_out_ + uintptr((16))), (int32(*(*uint8)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).mb_ /* &.uv_mode_ */)) & 0xc >> 2)))) + + (*VP8ModeScore)(unsafe.Pointer(rd)).nz = uint32_t(nz) + (*VP8ModeScore)(unsafe.Pointer(rd)).score = best_score +} + +//------------------------------------------------------------------------------ +// Entry point + +func VP8Decimate(tls *libc.TLS, it uintptr, rd uintptr, rd_opt VP8RDLevel) int32 { /* quant_enc.c:1355:5: */ + var is_skipped int32 + var method int32 = (*VP8Encoder)(unsafe.Pointer((*VP8EncIterator)(unsafe.Pointer(it)).enc_)).method_ + + InitScore(tls, rd) + + // We can perform predictions for Luma16x16 and Chroma8x8 already. + // Luma4x4 predictions needs to be done as-we-go. + VP8MakeLuma16Preds(tls, it) + VP8MakeChroma8Preds(tls, it) + + if rd_opt > RD_OPT_NONE { + (*VP8EncIterator)(unsafe.Pointer(it)).do_trellis_ = (libc.Bool32(rd_opt >= RD_OPT_TRELLIS_ALL)) + PickBestIntra16(tls, it, rd) + if method >= 2 { + PickBestIntra4(tls, it, rd) + } + PickBestUV(tls, it, rd) + if rd_opt == RD_OPT_TRELLIS { // finish off with trellis-optim now + (*VP8EncIterator)(unsafe.Pointer(it)).do_trellis_ = 1 + SimpleQuantize(tls, it, rd) + } + } else { + // At this point we have heuristically decided intra16 / intra4. + // For method >= 2, pick the best intra4/intra16 based on SSE (~tad slower). + // For method <= 1, we don't re-examine the decision but just go ahead with + // quantization/reconstruction. + RefineUsingDistortion(tls, it, (libc.Bool32(method >= 2)), (libc.Bool32(method >= 1)), rd) + } + is_skipped = (libc.Bool32((*VP8ModeScore)(unsafe.Pointer(rd)).nz == uint32_t(0))) + VP8SetSkip(tls, it, is_skipped) + return is_skipped +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Helper functions + +func IsVP8XNeeded(tls *libc.TLS, enc uintptr) int32 { /* syntax_enc.c:24:12: */ + return libc.BoolInt32(!(!((*VP8Encoder)(unsafe.Pointer(enc)).has_alpha_ != 0))) // Currently the only case when VP8X is needed. + // This could change in the future. +} + +func PutPaddingByte(tls *libc.TLS, pic uintptr) int32 { /* syntax_enc.c:29:12: */ + bp := tls.Alloc(1) + defer tls.Free(1) + + *(*[1]uint8_t)(unsafe.Pointer(bp /* pad_byte */)) = [1]uint8_t{uint8_t(0)} + return libc.BoolInt32(!(!((*struct { + f func(*libc.TLS, uintptr, size_t, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPPicture)(unsafe.Pointer(pic)).writer})).f(tls, (bp) /* &pad_byte[0] */, uint64(1), pic) != 0))) +} + +//------------------------------------------------------------------------------ +// Writers for header's various pieces (in order of appearance) + +func PutRIFFHeader(tls *libc.TLS, enc uintptr, riff_size size_t) WebPEncodingError { /* syntax_enc.c:37:26: */ + bp := tls.Alloc(12) + defer tls.Free(12) + + var pic uintptr = (*VP8Encoder)(unsafe.Pointer(enc)).pic_ + *(*[12]uint8_t)(unsafe.Pointer(bp /* riff */)) = [12]uint8_t{ + uint8_t('R'), uint8_t('I'), uint8_t('F'), uint8_t('F'), uint8_t(0), uint8_t(0), uint8_t(0), uint8_t(0), uint8_t('W'), uint8_t('E'), uint8_t('B'), uint8_t('P'), + } + + PutLE32(tls, ((bp) /* &riff[0] */ + uintptr(4)), uint32_t(riff_size)) + if !((*struct { + f func(*libc.TLS, uintptr, size_t, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPPicture)(unsafe.Pointer(pic)).writer})).f(tls, (bp) /* &riff[0] */, uint64(unsafe.Sizeof([12]uint8_t{})), pic) != 0) { + return VP8_ENC_ERROR_BAD_WRITE + } + return VP8_ENC_OK +} + +func PutVP8XHeader(tls *libc.TLS, enc uintptr) WebPEncodingError { /* syntax_enc.c:51:26: */ + bp := tls.Alloc(18) + defer tls.Free(18) + + var pic uintptr = (*VP8Encoder)(unsafe.Pointer(enc)).pic_ + *(*[18]uint8_t)(unsafe.Pointer(bp /* vp8x */)) = [18]uint8_t{ + 0: uint8_t('V'), 1: uint8_t('P'), 2: uint8_t('8'), 3: uint8_t('X'), + } + var flags uint32_t = uint32_t(0) + + if (*VP8Encoder)(unsafe.Pointer(enc)).has_alpha_ != 0 { + flags = flags | (ALPHA_FLAG) + } + + PutLE32(tls, ((bp) /* &vp8x[0] */ + uintptr(4)), uint32(10)) + PutLE32(tls, ((bp) /* &vp8x[0] */ + uintptr(8)), flags) + PutLE24(tls, (((bp) /* &vp8x[0] */ + uintptr(8)) + uintptr(4)), ((*WebPPicture)(unsafe.Pointer(pic)).width - 1)) + PutLE24(tls, (((bp) /* &vp8x[0] */ + uintptr(8)) + uintptr(7)), ((*WebPPicture)(unsafe.Pointer(pic)).height - 1)) + if !((*struct { + f func(*libc.TLS, uintptr, size_t, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPPicture)(unsafe.Pointer(pic)).writer})).f(tls, (bp) /* &vp8x[0] */, uint64(unsafe.Sizeof([18]uint8_t{})), pic) != 0) { + return VP8_ENC_ERROR_BAD_WRITE + } + return VP8_ENC_OK +} + +func PutAlphaChunk(tls *libc.TLS, enc uintptr) WebPEncodingError { /* syntax_enc.c:76:26: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var pic uintptr = (*VP8Encoder)(unsafe.Pointer(enc)).pic_ + *(*[8]uint8_t)(unsafe.Pointer(bp /* alpha_chunk_hdr */)) = [8]uint8_t{ + 0: uint8_t('A'), 1: uint8_t('L'), 2: uint8_t('P'), 3: uint8_t('H'), + } + + // Alpha chunk header. + PutLE32(tls, ((bp) /* &alpha_chunk_hdr[0] */ + uintptr(4)), (*VP8Encoder)(unsafe.Pointer(enc)).alpha_data_size_) + if !((*struct { + f func(*libc.TLS, uintptr, size_t, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPPicture)(unsafe.Pointer(pic)).writer})).f(tls, (bp) /* &alpha_chunk_hdr[0] */, uint64(unsafe.Sizeof([8]uint8_t{})), pic) != 0) { + return VP8_ENC_ERROR_BAD_WRITE + } + + // Alpha chunk data. + if !((*struct { + f func(*libc.TLS, uintptr, size_t, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPPicture)(unsafe.Pointer(pic)).writer})).f(tls, (*VP8Encoder)(unsafe.Pointer(enc)).alpha_data_, uint64((*VP8Encoder)(unsafe.Pointer(enc)).alpha_data_size_), pic) != 0) { + return VP8_ENC_ERROR_BAD_WRITE + } + + // Padding. + if (((*VP8Encoder)(unsafe.Pointer(enc)).alpha_data_size_ & uint32_t(1)) != 0) && !(PutPaddingByte(tls, pic) != 0) { + return VP8_ENC_ERROR_BAD_WRITE + } + return VP8_ENC_OK +} + +func PutVP8Header(tls *libc.TLS, pic uintptr, vp8_size size_t) WebPEncodingError { /* syntax_enc.c:102:26: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + *(*[8]uint8_t)(unsafe.Pointer(bp /* vp8_chunk_hdr */)) = [8]uint8_t{ + 0: uint8_t('V'), 1: uint8_t('P'), 2: uint8_t('8'), 3: uint8_t(' '), + } + + PutLE32(tls, ((bp) /* &vp8_chunk_hdr[0] */ + uintptr(4)), uint32_t(vp8_size)) + if !((*struct { + f func(*libc.TLS, uintptr, size_t, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPPicture)(unsafe.Pointer(pic)).writer})).f(tls, (bp) /* &vp8_chunk_hdr[0] */, uint64(unsafe.Sizeof([8]uint8_t{})), pic) != 0) { + return VP8_ENC_ERROR_BAD_WRITE + } + return VP8_ENC_OK +} + +func PutVP8FrameHeader(tls *libc.TLS, pic uintptr, profile int32, size0 size_t) WebPEncodingError { /* syntax_enc.c:115:26: */ + bp := tls.Alloc(10) + defer tls.Free(10) + + // var vp8_frm_hdr [10]uint8_t at bp, 10 + + var bits uint32_t + + if size0 >= (uint64(int32(1) << 19)) { // partition #0 is too big to fit + return VP8_ENC_ERROR_PARTITION0_OVERFLOW + } + + // Paragraph 9.1. + bits = ((uint32_t((0 | // keyframe (1b) + (profile << 1)) | // profile (3b) + (int32(1) << 4))) | // visible (1b) + (uint32_t(size0) << 5)) // partition length (19b) + *(*uint8_t)(unsafe.Pointer((bp) /* &vp8_frm_hdr[0] */)) = (uint8_t((bits >> 0) & uint32_t(0xff))) + *(*uint8_t)(unsafe.Pointer((bp) /* &vp8_frm_hdr[0] */ + 1)) = (uint8_t((bits >> 8) & uint32_t(0xff))) + *(*uint8_t)(unsafe.Pointer((bp) /* &vp8_frm_hdr[0] */ + 2)) = (uint8_t((bits >> 16) & uint32_t(0xff))) + // signature + *(*uint8_t)(unsafe.Pointer((bp) /* &vp8_frm_hdr[0] */ + 3)) = (uint8_t((int32(0x9d012a) >> 16) & 0xff)) + *(*uint8_t)(unsafe.Pointer((bp) /* &vp8_frm_hdr[0] */ + 4)) = (uint8_t((int32(0x9d012a) >> 8) & 0xff)) + *(*uint8_t)(unsafe.Pointer((bp) /* &vp8_frm_hdr[0] */ + 5)) = (uint8_t((int32(0x9d012a) >> 0) & 0xff)) + // dimensions + *(*uint8_t)(unsafe.Pointer((bp) /* &vp8_frm_hdr[0] */ + 6)) = (uint8_t((*WebPPicture)(unsafe.Pointer(pic)).width & 0xff)) + *(*uint8_t)(unsafe.Pointer((bp) /* &vp8_frm_hdr[0] */ + 7)) = (uint8_t((*WebPPicture)(unsafe.Pointer(pic)).width >> 8)) + *(*uint8_t)(unsafe.Pointer((bp) /* &vp8_frm_hdr[0] */ + 8)) = (uint8_t((*WebPPicture)(unsafe.Pointer(pic)).height & 0xff)) + *(*uint8_t)(unsafe.Pointer((bp) /* &vp8_frm_hdr[0] */ + 9)) = (uint8_t((*WebPPicture)(unsafe.Pointer(pic)).height >> 8)) + + if !((*struct { + f func(*libc.TLS, uintptr, size_t, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPPicture)(unsafe.Pointer(pic)).writer})).f(tls, (bp) /* &vp8_frm_hdr[0] */, uint64(unsafe.Sizeof([10]uint8_t{})), pic) != 0) { + return VP8_ENC_ERROR_BAD_WRITE + } + return VP8_ENC_OK +} + +// WebP Headers. +func PutWebPHeaders(tls *libc.TLS, enc uintptr, size0 size_t, vp8_size size_t, riff_size size_t) int32 { /* syntax_enc.c:149:12: */ + var pic uintptr + var err WebPEncodingError + pic = (*VP8Encoder)(unsafe.Pointer(enc)).pic_ + err = VP8_ENC_OK + + // RIFF header. + err = PutRIFFHeader(tls, enc, riff_size) + if !(err != VP8_ENC_OK) { + goto __1 + } + goto Error +__1: + ; + + // VP8X. + if !(IsVP8XNeeded(tls, enc) != 0) { + goto __2 + } + err = PutVP8XHeader(tls, enc) + if !(err != VP8_ENC_OK) { + goto __3 + } + goto Error +__3: + ; +__2: + ; + + // Alpha. + if !((*VP8Encoder)(unsafe.Pointer(enc)).has_alpha_ != 0) { + goto __4 + } + err = PutAlphaChunk(tls, enc) + if !(err != VP8_ENC_OK) { + goto __5 + } + goto Error +__5: + ; +__4: + ; + + // VP8 header. + err = PutVP8Header(tls, pic, vp8_size) + if !(err != VP8_ENC_OK) { + goto __6 + } + goto Error +__6: + ; + + // VP8 frame header. + err = PutVP8FrameHeader(tls, pic, (*VP8Encoder)(unsafe.Pointer(enc)).profile_, size0) + if !(err != VP8_ENC_OK) { + goto __7 + } + goto Error +__7: + ; + + // All OK. + return 1 + + // Error. +Error: + return WebPEncodingSetError(tls, pic, err) +} + +// Segmentation header +func PutSegmentHeader(tls *libc.TLS, bw uintptr, enc uintptr) { /* syntax_enc.c:187:13: */ + var hdr uintptr = (enc + 32 /* &.segment_hdr_ */) + var proba uintptr = (enc + 3616 /* &.proba_ */) + if VP8PutBitUniform(tls, bw, (libc.Bool32((*VP8EncSegmentHeader)(unsafe.Pointer(hdr)).num_segments_ > 1))) != 0 { + // We always 'update' the quant and filter strength values + var update_data int32 = 1 + var s int32 + VP8PutBitUniform(tls, bw, (*VP8EncSegmentHeader)(unsafe.Pointer(hdr)).update_map_) + if VP8PutBitUniform(tls, bw, update_data) != 0 { + // we always use absolute values, not relative ones + VP8PutBitUniform(tls, bw, 1) // (segment_feature_mode = 1. Paragraph 9.3.) + for s = 0; s < NUM_MB_SEGMENTS; s++ { + VP8PutSignedBits(tls, bw, (*VP8SegmentInfo)(unsafe.Pointer((enc+608 /* &.dqm_ */)+uintptr(s)*744)).quant_, 7) + } + for s = 0; s < NUM_MB_SEGMENTS; s++ { + VP8PutSignedBits(tls, bw, (*VP8SegmentInfo)(unsafe.Pointer((enc+608 /* &.dqm_ */)+uintptr(s)*744)).fstrength_, 6) + } + } + if (*VP8EncSegmentHeader)(unsafe.Pointer(hdr)).update_map_ != 0 { + for s = 0; s < 3; s++ { + if VP8PutBitUniform(tls, bw, (libc.Bool32(uint32(*(*uint8_t)(unsafe.Pointer((proba /* &.segments_ */) + uintptr(s)))) != 255))) != 0 { + VP8PutBits(tls, bw, uint32(*(*uint8_t)(unsafe.Pointer((proba /* &.segments_ */) + uintptr(s)))), 8) + } + } + } + } +} + +// Filtering parameters header +func PutFilterHeader(tls *libc.TLS, bw uintptr, hdr uintptr) { /* syntax_enc.c:217:13: */ + var use_lf_delta int32 = (libc.Bool32((*VP8EncFilterHeader)(unsafe.Pointer(hdr)).i4x4_lf_delta_ != 0)) + VP8PutBitUniform(tls, bw, (*VP8EncFilterHeader)(unsafe.Pointer(hdr)).simple_) + VP8PutBits(tls, bw, uint32((*VP8EncFilterHeader)(unsafe.Pointer(hdr)).level_), 6) + VP8PutBits(tls, bw, uint32((*VP8EncFilterHeader)(unsafe.Pointer(hdr)).sharpness_), 3) + if VP8PutBitUniform(tls, bw, use_lf_delta) != 0 { + // '0' is the default value for i4x4_lf_delta_ at frame #0. + var need_update int32 = (libc.Bool32((*VP8EncFilterHeader)(unsafe.Pointer(hdr)).i4x4_lf_delta_ != 0)) + if VP8PutBitUniform(tls, bw, need_update) != 0 { + // we don't use ref_lf_delta => emit four 0 bits + VP8PutBits(tls, bw, uint32(0), 4) + // we use mode_lf_delta for i4x4 + VP8PutSignedBits(tls, bw, (*VP8EncFilterHeader)(unsafe.Pointer(hdr)).i4x4_lf_delta_, 6) + VP8PutBits(tls, bw, uint32(0), 3) // all others unused + } + } +} + +// Nominal quantization parameters +func PutQuant(tls *libc.TLS, bw uintptr, enc uintptr) { /* syntax_enc.c:237:13: */ + VP8PutBits(tls, bw, uint32((*VP8Encoder)(unsafe.Pointer(enc)).base_quant_), 7) + VP8PutSignedBits(tls, bw, (*VP8Encoder)(unsafe.Pointer(enc)).dq_y1_dc_, 4) + VP8PutSignedBits(tls, bw, (*VP8Encoder)(unsafe.Pointer(enc)).dq_y2_dc_, 4) + VP8PutSignedBits(tls, bw, (*VP8Encoder)(unsafe.Pointer(enc)).dq_y2_ac_, 4) + VP8PutSignedBits(tls, bw, (*VP8Encoder)(unsafe.Pointer(enc)).dq_uv_dc_, 4) + VP8PutSignedBits(tls, bw, (*VP8Encoder)(unsafe.Pointer(enc)).dq_uv_ac_, 4) +} + +// Partition sizes +func EmitPartitionsSize(tls *libc.TLS, enc uintptr, pic uintptr) int32 { /* syntax_enc.c:248:12: */ + bp := tls.Alloc(21) + defer tls.Free(21) + + // var buf [21]uint8_t at bp, 21 + + var p int32 + for p = 0; p < ((*VP8Encoder)(unsafe.Pointer(enc)).num_parts_ - 1); p++ { + var part_size size_t = VP8BitWriterSize(tls, ((enc + 112 /* &.parts_ */) + uintptr(p)*48)) + if part_size >= (uint64(int32(1) << 24)) { + return WebPEncodingSetError(tls, pic, VP8_ENC_ERROR_PARTITION_OVERFLOW) + } + *(*uint8_t)(unsafe.Pointer((bp) /* &buf[0] */ + uintptr(((3 * p) + 0)))) = (uint8_t((part_size >> 0) & uint64(0xff))) + *(*uint8_t)(unsafe.Pointer((bp) /* &buf[0] */ + uintptr(((3 * p) + 1)))) = (uint8_t((part_size >> 8) & uint64(0xff))) + *(*uint8_t)(unsafe.Pointer((bp) /* &buf[0] */ + uintptr(((3 * p) + 2)))) = (uint8_t((part_size >> 16) & uint64(0xff))) + } + if p != 0 { + return (*struct { + f func(*libc.TLS, uintptr, size_t, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPPicture)(unsafe.Pointer(pic)).writer})).f(tls, (bp) /* &buf[0] */, (uint64(3 * p)), pic) + } + return 1 +} + +//------------------------------------------------------------------------------ + +func GeneratePartition0(tls *libc.TLS, enc uintptr) int32 { /* syntax_enc.c:266:12: */ + var bw uintptr = (enc + 64 /* &.bw_ */) + var mb_size int32 = ((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ * (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_) + var pos1 uint64_t + var pos2 uint64_t + var pos3 uint64_t + + pos1 = VP8BitWriterPos(tls, bw) + if !(VP8BitWriterInit(tls, bw, (uint64((mb_size*7)/8))) != 0) { // ~7 bits per macroblock + return WebPEncodingSetError(tls, (*VP8Encoder)(unsafe.Pointer(enc)).pic_, VP8_ENC_ERROR_OUT_OF_MEMORY) + } + VP8PutBitUniform(tls, bw, 0) // colorspace + VP8PutBitUniform(tls, bw, 0) // clamp type + + PutSegmentHeader(tls, bw, enc) + PutFilterHeader(tls, bw, (enc + 16 /* &.filter_hdr_ */)) + VP8PutBits(tls, bw, func() uint32 { + if (*VP8Encoder)(unsafe.Pointer(enc)).num_parts_ == 8 { + return uint32(3) + } + return func() uint32 { + if (*VP8Encoder)(unsafe.Pointer(enc)).num_parts_ == 4 { + return uint32(2) + } + return func() uint32 { + if (*VP8Encoder)(unsafe.Pointer(enc)).num_parts_ == 2 { + return uint32(1) + } + return uint32(0) + }() + }() + }(), 2) + PutQuant(tls, bw, enc) + VP8PutBitUniform(tls, bw, 0) // no proba update + VP8WriteProbas(tls, bw, (enc + 3616 /* &.proba_ */)) + pos2 = VP8BitWriterPos(tls, bw) + VP8CodeIntraModes(tls, enc) + VP8BitWriterFinish(tls, bw) + + pos3 = VP8BitWriterPos(tls, bw) + + if (*WebPPicture)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).pic_)).stats != 0 { + *(*int32)(unsafe.Pointer(((*WebPPicture)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).pic_)).stats + 36 /* &.header_bytes */))) = (int32(((pos2 - pos1) + uint64(7)) >> 3)) + *(*int32)(unsafe.Pointer(((*WebPPicture)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).pic_)).stats + 36 /* &.header_bytes */) + 1*4)) = (int32(((pos3 - pos2) + uint64(7)) >> 3)) + (*WebPAuxStats)(unsafe.Pointer((*WebPPicture)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).pic_)).stats)).alpha_data_size = int32((*VP8Encoder)(unsafe.Pointer(enc)).alpha_data_size_) + } + if (*VP8BitWriter)(unsafe.Pointer(bw)).error_ != 0 { + return WebPEncodingSetError(tls, (*VP8Encoder)(unsafe.Pointer(enc)).pic_, VP8_ENC_ERROR_OUT_OF_MEMORY) + } + return 1 +} + +func VP8EncFreeBitWriters(tls *libc.TLS, enc uintptr) { /* syntax_enc.c:309:6: */ + var p int32 + VP8BitWriterWipeOut(tls, (enc + 64 /* &.bw_ */)) + for p = 0; p < (*VP8Encoder)(unsafe.Pointer(enc)).num_parts_; p++ { + VP8BitWriterWipeOut(tls, ((enc + 112 /* &.parts_ */) + uintptr(p)*48)) + } +} + +func VP8EncWrite(tls *libc.TLS, enc uintptr) int32 { /* syntax_enc.c:317:5: */ + var pic uintptr = (*VP8Encoder)(unsafe.Pointer(enc)).pic_ + var bw uintptr = (enc + 64 /* &.bw_ */) + var task_percent int32 = 19 + var percent_per_part int32 = (task_percent / (*VP8Encoder)(unsafe.Pointer(enc)).num_parts_) + var final_percent int32 = ((*VP8Encoder)(unsafe.Pointer(enc)).percent_ + task_percent) + var ok int32 = 0 + var vp8_size size_t + var pad size_t + var riff_size size_t + var p int32 + + // Partition #0 with header and partition sizes + ok = GeneratePartition0(tls, enc) + if !(ok != 0) { + return 0 + } + + // Compute VP8 size + vp8_size = ((uint64(10) + VP8BitWriterSize(tls, bw)) + (size_t(3 * ((*VP8Encoder)(unsafe.Pointer(enc)).num_parts_ - 1)))) + for p = 0; p < (*VP8Encoder)(unsafe.Pointer(enc)).num_parts_; p++ { + vp8_size = vp8_size + (VP8BitWriterSize(tls, ((enc + 112 /* &.parts_ */) + uintptr(p)*48))) + } + pad = (vp8_size & uint64(1)) + vp8_size = vp8_size + (pad) + + // Compute RIFF size + // At the minimum it is: "WEBPVP8 nnnn" + VP8 data size. + riff_size = ((uint64(4 + 8)) + vp8_size) + if IsVP8XNeeded(tls, enc) != 0 { // Add size for: VP8X header + data. + riff_size = riff_size + (uint64(8 + 10)) + } + if (*VP8Encoder)(unsafe.Pointer(enc)).has_alpha_ != 0 { // Add size for: ALPH header + data. + var padded_alpha_size uint32_t = ((*VP8Encoder)(unsafe.Pointer(enc)).alpha_data_size_ + ((*VP8Encoder)(unsafe.Pointer(enc)).alpha_data_size_ & uint32_t(1))) + riff_size = riff_size + (size_t(uint32_t(8) + padded_alpha_size)) + } + // RIFF size should fit in 32-bits. + if riff_size > uint64(0xfffffffe) { + return WebPEncodingSetError(tls, pic, VP8_ENC_ERROR_FILE_TOO_BIG) + } + + // Emit headers and partition #0 + { + var part0 uintptr = VP8BitWriterBuf(tls, bw) + var size0 size_t = VP8BitWriterSize(tls, bw) + ok = (libc.Bool32((((ok != 0) && (PutWebPHeaders(tls, enc, size0, vp8_size, riff_size) != 0)) && + ((*struct { + f func(*libc.TLS, uintptr, size_t, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPPicture)(unsafe.Pointer(pic)).writer})).f(tls, part0, size0, pic) != 0)) && + (EmitPartitionsSize(tls, enc, pic) != 0))) + VP8BitWriterWipeOut(tls, bw) // will free the internal buffer. + + } + + // Token partitions + for p = 0; p < (*VP8Encoder)(unsafe.Pointer(enc)).num_parts_; p++ { + var buf uintptr = VP8BitWriterBuf(tls, ((enc + 112 /* &.parts_ */) + uintptr(p)*48)) + var size size_t = VP8BitWriterSize(tls, ((enc + 112 /* &.parts_ */) + uintptr(p)*48)) + if size != 0 { + ok = (libc.Bool32((ok != 0) && ((*struct { + f func(*libc.TLS, uintptr, size_t, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPPicture)(unsafe.Pointer(pic)).writer})).f(tls, buf, size, pic) != 0))) + } + VP8BitWriterWipeOut(tls, ((enc + 112 /* &.parts_ */) + uintptr(p)*48)) // will free the internal buffer. + ok = (libc.Bool32((ok != 0) && (WebPReportProgress(tls, pic, ((*VP8Encoder)(unsafe.Pointer(enc)).percent_+percent_per_part), + (enc+536 /* &.percent_ */)) != 0))) + } + + // Padding byte + if (ok != 0) && (pad != 0) { + ok = PutPaddingByte(tls, pic) + } + + (*VP8Encoder)(unsafe.Pointer(enc)).coded_size_ = (int32(uint64(8) + riff_size)) + ok = (libc.Bool32((ok != 0) && (WebPReportProgress(tls, pic, final_percent, (enc+536 /* &.percent_ */)) != 0))) + return ok +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Paginated token buffer + +type VP8Tokens = VP8Tokens1 /* vp8i_enc.h:310:26 */ + +//------------------------------------------------------------------------------ + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// WebP encoder: internal header. +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +// we use pages to reduce the number of memcpy() + +type token_t = uint16_t /* token_enc.c:33:18 */ + +// Token data is located in memory just after the next_ field. +// This macro is used to return their address and hide the trick. + +//------------------------------------------------------------------------------ + +func VP8TBufferInit(tls *libc.TLS, b uintptr, page_size int32) { /* token_enc.c:45:6: */ + (*VP8TBuffer)(unsafe.Pointer(b)).tokens_ = (uintptr(0)) + (*VP8TBuffer)(unsafe.Pointer(b)).pages_ = (uintptr(0)) + (*VP8TBuffer)(unsafe.Pointer(b)).last_page_ = (b /* &.pages_ */) + (*VP8TBuffer)(unsafe.Pointer(b)).left_ = 0 + (*VP8TBuffer)(unsafe.Pointer(b)).page_size_ = func() int32 { + if page_size < 8192 { + return 8192 + } + return page_size + }() + (*VP8TBuffer)(unsafe.Pointer(b)).error_ = 0 +} + +func VP8TBufferClear(tls *libc.TLS, b uintptr) { /* token_enc.c:54:6: */ + if b != (uintptr(0)) { + var p uintptr = (*VP8TBuffer)(unsafe.Pointer(b)).pages_ + for p != (uintptr(0)) { + var next uintptr = (*VP8Tokens)(unsafe.Pointer(p)).next_ + WebPSafeFree(tls, p) + p = next + } + VP8TBufferInit(tls, b, (*VP8TBuffer)(unsafe.Pointer(b)).page_size_) + } +} + +func TBufferNewPage(tls *libc.TLS, b uintptr) int32 { /* token_enc.c:66:12: */ + var page uintptr = (uintptr(0)) + if !((*VP8TBuffer)(unsafe.Pointer(b)).error_ != 0) { + var size size_t = (uint64(unsafe.Sizeof(VP8Tokens{})) + (uint64((*VP8TBuffer)(unsafe.Pointer(b)).page_size_) * uint64(unsafe.Sizeof(token_t(0))))) + page = WebPSafeMalloc(tls, 1, size) + } + if page == (uintptr(0)) { + (*VP8TBuffer)(unsafe.Pointer(b)).error_ = 1 + return 0 + } + (*VP8Tokens)(unsafe.Pointer(page)).next_ = (uintptr(0)) + + *(*uintptr)(unsafe.Pointer((*VP8TBuffer)(unsafe.Pointer(b)).last_page_)) = page + (*VP8TBuffer)(unsafe.Pointer(b)).last_page_ = (page /* &.next_ */) + (*VP8TBuffer)(unsafe.Pointer(b)).left_ = (*VP8TBuffer)(unsafe.Pointer(b)).page_size_ + (*VP8TBuffer)(unsafe.Pointer(b)).tokens_ = ((page) + 1*8) + return 1 +} + +//------------------------------------------------------------------------------ + +func AddToken(tls *libc.TLS, b uintptr, bit uint32_t, proba_idx uint32_t, stats uintptr) uint32_t { /* token_enc.c:90:29: */ + + if ((*VP8TBuffer)(unsafe.Pointer(b)).left_ > 0) || (TBufferNewPage(tls, b) != 0) { + var slot int32 = libc.PreDecInt32(&(*VP8TBuffer)(unsafe.Pointer(b)).left_, 1) + *(*uint16_t)(unsafe.Pointer((*VP8TBuffer)(unsafe.Pointer(b)).tokens_ + uintptr(slot)*2)) = (uint16_t((bit << 15) | proba_idx)) + } + VP8RecordStats(tls, int32(bit), stats) + return bit +} + +func AddConstantToken(tls *libc.TLS, b uintptr, bit uint32_t, proba uint32_t) { /* token_enc.c:103:25: */ + + if ((*VP8TBuffer)(unsafe.Pointer(b)).left_ > 0) || (TBufferNewPage(tls, b) != 0) { + var slot int32 = libc.PreDecInt32(&(*VP8TBuffer)(unsafe.Pointer(b)).left_, 1) + *(*uint16_t)(unsafe.Pointer((*VP8TBuffer)(unsafe.Pointer(b)).tokens_ + uintptr(slot)*2)) = (uint16_t(((bit << 15) | (uint32(1) << 14)) | proba)) + } +} + +func VP8RecordCoeffTokens(tls *libc.TLS, ctx int32, res uintptr, tokens uintptr) int32 { /* token_enc.c:113:5: */ + var coeffs uintptr = (*VP8Residual1)(unsafe.Pointer(res)).coeffs + var coeff_type int32 = (*VP8Residual1)(unsafe.Pointer(res)).coeff_type + var last int32 = (*VP8Residual1)(unsafe.Pointer(res)).last + var n int32 = (*VP8Residual1)(unsafe.Pointer(res)).first + var base_id uint32_t = (uint32_t(NUM_PROBAS * ((ctx) + (NUM_CTX * ((n) + (NUM_BANDS * (coeff_type))))))) + // should be stats[VP8EncBands[n]], but it's equivalent for n=0 or 1 + var s uintptr = (((*VP8Residual1)(unsafe.Pointer(res)).stats + uintptr(n)*132) + uintptr(ctx)*44) + if !(AddToken(tls, tokens, (uint32(libc.Bool32(last >= 0))), (base_id+uint32_t(0)), (s+uintptr(0)*4)) != 0) { + return 0 + } + + for n < 16 { + var c int32 = int32(*(*int16_t)(unsafe.Pointer(coeffs + uintptr(libc.PostIncInt32(&n, 1))*2))) + var sign int32 = (libc.Bool32(c < 0)) + var v uint32_t + if sign != 0 { + v = uint32(-c) + } else { + v = uint32(c) + } + if !(AddToken(tls, tokens, (uint32(libc.Bool32(v != uint32_t(0)))), (base_id+uint32_t(1)), (s+uintptr(1)*4)) != 0) { + base_id = (uint32_t(NUM_PROBAS * ((0) + (NUM_CTX * ((int32(VP8EncBands[n])) + (NUM_BANDS * (coeff_type))))))) // ctx=0 + s = ((*VP8Residual1)(unsafe.Pointer(res)).stats + uintptr(VP8EncBands[n])*132) + continue + } + if !(AddToken(tls, tokens, (uint32(libc.Bool32(v > uint32_t(1)))), (base_id+uint32_t(2)), (s+uintptr(2)*4)) != 0) { + base_id = (uint32_t(NUM_PROBAS * ((1) + (NUM_CTX * ((int32(VP8EncBands[n])) + (NUM_BANDS * (coeff_type))))))) // ctx=1 + s = (((*VP8Residual1)(unsafe.Pointer(res)).stats + uintptr(VP8EncBands[n])*132) + 1*44) + } else { + if !(AddToken(tls, tokens, (uint32(libc.Bool32(v > uint32_t(4)))), (base_id+uint32_t(3)), (s+uintptr(3)*4)) != 0) { + if AddToken(tls, tokens, (uint32(libc.Bool32(v != uint32_t(2)))), (base_id+uint32_t(4)), (s+uintptr(4)*4)) != 0 { + AddToken(tls, tokens, (uint32(libc.Bool32(v == uint32_t(4)))), (base_id + uint32_t(5)), (s + uintptr(5)*4)) + } + } else if !(AddToken(tls, tokens, (uint32(libc.Bool32(v > uint32_t(10)))), (base_id+uint32_t(6)), (s+uintptr(6)*4)) != 0) { + if !(AddToken(tls, tokens, (uint32(libc.Bool32(v > uint32_t(6)))), (base_id+uint32_t(7)), (s+uintptr(7)*4)) != 0) { + AddConstantToken(tls, tokens, (uint32(libc.Bool32(v == uint32_t(6)))), uint32(159)) + } else { + AddConstantToken(tls, tokens, (uint32(libc.Bool32(v >= uint32_t(9)))), uint32(165)) + AddConstantToken(tls, tokens, libc.BoolUint32(!((v & uint32_t(1)) != 0)), uint32(145)) + } + } else { + var mask int32 + var tab uintptr + var residue uint32_t = (v - uint32_t(3)) + if residue < (uint32_t(int32(8) << 1)) { // VP8Cat3 (3b) + AddToken(tls, tokens, uint32(0), (base_id + uint32_t(8)), (s + uintptr(8)*4)) + AddToken(tls, tokens, uint32(0), (base_id + uint32_t(9)), (s + uintptr(9)*4)) + residue = residue - (uint32_t(int32(8) << 0)) + mask = (int32(1) << 2) + tab = uintptr(unsafe.Pointer(&VP8Cat3)) + } else if residue < (uint32_t(int32(8) << 2)) { // VP8Cat4 (4b) + AddToken(tls, tokens, uint32(0), (base_id + uint32_t(8)), (s + uintptr(8)*4)) + AddToken(tls, tokens, uint32(1), (base_id + uint32_t(9)), (s + uintptr(9)*4)) + residue = residue - (uint32_t(int32(8) << 1)) + mask = (int32(1) << 3) + tab = uintptr(unsafe.Pointer(&VP8Cat4)) + } else if residue < (uint32_t(int32(8) << 3)) { // VP8Cat5 (5b) + AddToken(tls, tokens, uint32(1), (base_id + uint32_t(8)), (s + uintptr(8)*4)) + AddToken(tls, tokens, uint32(0), (base_id + uint32_t(10)), (s + uintptr(9)*4)) + residue = residue - (uint32_t(int32(8) << 2)) + mask = (int32(1) << 4) + tab = uintptr(unsafe.Pointer(&VP8Cat5)) + } else { // VP8Cat6 (11b) + AddToken(tls, tokens, uint32(1), (base_id + uint32_t(8)), (s + uintptr(8)*4)) + AddToken(tls, tokens, uint32(1), (base_id + uint32_t(10)), (s + uintptr(9)*4)) + residue = residue - (uint32_t(int32(8) << 3)) + mask = (int32(1) << 10) + tab = uintptr(unsafe.Pointer(&VP8Cat6)) + } + for mask != 0 { + AddConstantToken(tls, tokens, libc.BoolUint32(!(!((residue & uint32_t(mask)) != 0))), uint32(*(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&tab, 1))))) + mask >>= 1 + } + } + base_id = (uint32_t(NUM_PROBAS * ((2) + (NUM_CTX * ((int32(VP8EncBands[n])) + (NUM_BANDS * (coeff_type))))))) // ctx=2 + s = (((*VP8Residual1)(unsafe.Pointer(res)).stats + uintptr(VP8EncBands[n])*132) + 2*44) + } + AddConstantToken(tls, tokens, uint32(sign), uint32(128)) + if (n == 16) || !(AddToken(tls, tokens, (uint32(libc.Bool32(n <= last))), (base_id+uint32_t(0)), (s+uintptr(0)*4)) != 0) { + return 1 // EOB + } + } + return 1 +} + +//------------------------------------------------------------------------------ +// Final coding pass, with known probabilities + +func VP8EmitTokens(tls *libc.TLS, b uintptr, bw uintptr, probas uintptr, final_pass int32) int32 { /* token_enc.c:200:5: */ + var p uintptr = (*VP8TBuffer)(unsafe.Pointer(b)).pages_ + + for p != (uintptr(0)) { + var next uintptr = (*VP8Tokens)(unsafe.Pointer(p)).next_ + var N int32 + if next == (uintptr(0)) { + N = (*VP8TBuffer)(unsafe.Pointer(b)).left_ + } else { + N = 0 + } + var n int32 = (*VP8TBuffer)(unsafe.Pointer(b)).page_size_ + var tokens uintptr = ((p) + 1*8) + for libc.PostDecInt32(&n, 1) > N { + var token token_t = *(*token_t)(unsafe.Pointer(tokens + uintptr(n)*2)) + var bit int32 = ((int32(token) >> 15) & 1) + if (uint32(token) & (uint32(1) << 14)) != 0 { + VP8PutBit(tls, bw, bit, (int32(uint32(token) & 0xff))) // constant proba + } else { + VP8PutBit(tls, bw, bit, int32(*(*uint8_t)(unsafe.Pointer(probas + uintptr((uint32(token) & 0x3fff)))))) + } + } + if final_pass != 0 { + WebPSafeFree(tls, p) + } + p = next + } + if final_pass != 0 { + (*VP8TBuffer)(unsafe.Pointer(b)).pages_ = (uintptr(0)) + } + return 1 +} + +// Size estimation +func VP8EstimateTokenSize(tls *libc.TLS, b uintptr, probas uintptr) size_t { /* token_enc.c:226:8: */ + var size size_t = uint64(0) + var p uintptr = (*VP8TBuffer)(unsafe.Pointer(b)).pages_ + + for p != (uintptr(0)) { + var next uintptr = (*VP8Tokens)(unsafe.Pointer(p)).next_ + var N int32 + if next == (uintptr(0)) { + N = (*VP8TBuffer)(unsafe.Pointer(b)).left_ + } else { + N = 0 + } + var n int32 = (*VP8TBuffer)(unsafe.Pointer(b)).page_size_ + var tokens uintptr = ((p) + 1*8) + for libc.PostDecInt32(&n, 1) > N { + var token token_t = *(*token_t)(unsafe.Pointer(tokens + uintptr(n)*2)) + var bit int32 = (int32(token) & (int32(1) << 15)) + if (uint32(token) & (uint32(1) << 14)) != 0 { + size = size + (size_t(VP8BitCost(tls, bit, (uint8(uint32(token) & 0xff))))) + } else { + size = size + (size_t(VP8BitCost(tls, bit, *(*uint8_t)(unsafe.Pointer(probas + uintptr((uint32(token) & 0x3fff))))))) + } + } + p = next + } + return size +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Default probabilities + +// Paragraph 13.5 +var VP8CoeffsProba0 = [4][8][3][11]uint8_t{[8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(253), uint8_t(136), uint8_t(254), uint8_t(255), uint8_t(228), uint8_t(219), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(189), uint8_t(129), uint8_t(242), uint8_t(255), uint8_t(227), uint8_t(213), uint8_t(255), uint8_t(219), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(106), uint8_t(126), uint8_t(227), uint8_t(252), uint8_t(214), uint8_t(209), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(98), uint8_t(248), uint8_t(255), uint8_t(236), uint8_t(226), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(181), uint8_t(133), uint8_t(238), uint8_t(254), uint8_t(221), uint8_t(234), uint8_t(255), uint8_t(154), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(78), uint8_t(134), uint8_t(202), uint8_t(247), uint8_t(198), uint8_t(180), uint8_t(255), uint8_t(219), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(185), uint8_t(249), uint8_t(255), uint8_t(243), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(184), uint8_t(150), uint8_t(247), uint8_t(255), uint8_t(236), uint8_t(224), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(77), uint8_t(110), uint8_t(216), uint8_t(255), uint8_t(236), uint8_t(230), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(101), uint8_t(251), uint8_t(255), uint8_t(241), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(170), uint8_t(139), uint8_t(241), uint8_t(252), uint8_t(236), uint8_t(209), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(37), uint8_t(116), uint8_t(196), uint8_t(243), uint8_t(228), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(204), uint8_t(254), uint8_t(255), uint8_t(245), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(207), uint8_t(160), uint8_t(250), uint8_t(255), uint8_t(238), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(102), uint8_t(103), uint8_t(231), uint8_t(255), uint8_t(211), uint8_t(171), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(152), uint8_t(252), uint8_t(255), uint8_t(240), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(177), uint8_t(135), uint8_t(243), uint8_t(255), uint8_t(234), uint8_t(225), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(80), uint8_t(129), uint8_t(211), uint8_t(255), uint8_t(194), uint8_t(224), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(1), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(246), uint8_t(1), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, +}, + [8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(198), uint8_t(35), uint8_t(237), uint8_t(223), uint8_t(193), uint8_t(187), uint8_t(162), uint8_t(160), uint8_t(145), uint8_t(155), uint8_t(62)}, + [11]uint8_t{uint8_t(131), uint8_t(45), uint8_t(198), uint8_t(221), uint8_t(172), uint8_t(176), uint8_t(220), uint8_t(157), uint8_t(252), uint8_t(221), uint8_t(1)}, + [11]uint8_t{uint8_t(68), uint8_t(47), uint8_t(146), uint8_t(208), uint8_t(149), uint8_t(167), uint8_t(221), uint8_t(162), uint8_t(255), uint8_t(223), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(149), uint8_t(241), uint8_t(255), uint8_t(221), uint8_t(224), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(184), uint8_t(141), uint8_t(234), uint8_t(253), uint8_t(222), uint8_t(220), uint8_t(255), uint8_t(199), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(81), uint8_t(99), uint8_t(181), uint8_t(242), uint8_t(176), uint8_t(190), uint8_t(249), uint8_t(202), uint8_t(255), uint8_t(255), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(129), uint8_t(232), uint8_t(253), uint8_t(214), uint8_t(197), uint8_t(242), uint8_t(196), uint8_t(255), uint8_t(255), uint8_t(128)}, + [11]uint8_t{uint8_t(99), uint8_t(121), uint8_t(210), uint8_t(250), uint8_t(201), uint8_t(198), uint8_t(255), uint8_t(202), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(23), uint8_t(91), uint8_t(163), uint8_t(242), uint8_t(170), uint8_t(187), uint8_t(247), uint8_t(210), uint8_t(255), uint8_t(255), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(200), uint8_t(246), uint8_t(255), uint8_t(234), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(109), uint8_t(178), uint8_t(241), uint8_t(255), uint8_t(231), uint8_t(245), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(44), uint8_t(130), uint8_t(201), uint8_t(253), uint8_t(205), uint8_t(192), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(132), uint8_t(239), uint8_t(251), uint8_t(219), uint8_t(209), uint8_t(255), uint8_t(165), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(94), uint8_t(136), uint8_t(225), uint8_t(251), uint8_t(218), uint8_t(190), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(22), uint8_t(100), uint8_t(174), uint8_t(245), uint8_t(186), uint8_t(161), uint8_t(255), uint8_t(199), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(182), uint8_t(249), uint8_t(255), uint8_t(232), uint8_t(235), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(124), uint8_t(143), uint8_t(241), uint8_t(255), uint8_t(227), uint8_t(234), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(35), uint8_t(77), uint8_t(181), uint8_t(251), uint8_t(193), uint8_t(211), uint8_t(255), uint8_t(205), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(157), uint8_t(247), uint8_t(255), uint8_t(236), uint8_t(231), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(121), uint8_t(141), uint8_t(235), uint8_t(255), uint8_t(225), uint8_t(227), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(45), uint8_t(99), uint8_t(188), uint8_t(251), uint8_t(195), uint8_t(217), uint8_t(255), uint8_t(224), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(1), uint8_t(251), uint8_t(255), uint8_t(213), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(203), uint8_t(1), uint8_t(248), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(137), uint8_t(1), uint8_t(177), uint8_t(255), uint8_t(224), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + }, + [8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(253), uint8_t(9), uint8_t(248), uint8_t(251), uint8_t(207), uint8_t(208), uint8_t(255), uint8_t(192), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(175), uint8_t(13), uint8_t(224), uint8_t(243), uint8_t(193), uint8_t(185), uint8_t(249), uint8_t(198), uint8_t(255), uint8_t(255), uint8_t(128)}, + [11]uint8_t{uint8_t(73), uint8_t(17), uint8_t(171), uint8_t(221), uint8_t(161), uint8_t(179), uint8_t(236), uint8_t(167), uint8_t(255), uint8_t(234), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(95), uint8_t(247), uint8_t(253), uint8_t(212), uint8_t(183), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(239), uint8_t(90), uint8_t(244), uint8_t(250), uint8_t(211), uint8_t(209), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(155), uint8_t(77), uint8_t(195), uint8_t(248), uint8_t(188), uint8_t(195), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(24), uint8_t(239), uint8_t(251), uint8_t(218), uint8_t(219), uint8_t(255), uint8_t(205), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(201), uint8_t(51), uint8_t(219), uint8_t(255), uint8_t(196), uint8_t(186), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(69), uint8_t(46), uint8_t(190), uint8_t(239), uint8_t(201), uint8_t(218), uint8_t(255), uint8_t(228), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(191), uint8_t(251), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(223), uint8_t(165), uint8_t(249), uint8_t(255), uint8_t(213), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(141), uint8_t(124), uint8_t(248), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(16), uint8_t(248), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(190), uint8_t(36), uint8_t(230), uint8_t(255), uint8_t(236), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(149), uint8_t(1), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(226), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(247), uint8_t(192), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(240), uint8_t(128), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(134), uint8_t(252), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(213), uint8_t(62), uint8_t(250), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(55), uint8_t(93), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + }, + [8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(202), uint8_t(24), uint8_t(213), uint8_t(235), uint8_t(186), uint8_t(191), uint8_t(220), uint8_t(160), uint8_t(240), uint8_t(175), uint8_t(255)}, + [11]uint8_t{uint8_t(126), uint8_t(38), uint8_t(182), uint8_t(232), uint8_t(169), uint8_t(184), uint8_t(228), uint8_t(174), uint8_t(255), uint8_t(187), uint8_t(128)}, + [11]uint8_t{uint8_t(61), uint8_t(46), uint8_t(138), uint8_t(219), uint8_t(151), uint8_t(178), uint8_t(240), uint8_t(170), uint8_t(255), uint8_t(216), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(112), uint8_t(230), uint8_t(250), uint8_t(199), uint8_t(191), uint8_t(247), uint8_t(159), uint8_t(255), uint8_t(255), uint8_t(128)}, + [11]uint8_t{uint8_t(166), uint8_t(109), uint8_t(228), uint8_t(252), uint8_t(211), uint8_t(215), uint8_t(255), uint8_t(174), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(39), uint8_t(77), uint8_t(162), uint8_t(232), uint8_t(172), uint8_t(180), uint8_t(245), uint8_t(178), uint8_t(255), uint8_t(255), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(52), uint8_t(220), uint8_t(246), uint8_t(198), uint8_t(199), uint8_t(249), uint8_t(220), uint8_t(255), uint8_t(255), uint8_t(128)}, + [11]uint8_t{uint8_t(124), uint8_t(74), uint8_t(191), uint8_t(243), uint8_t(183), uint8_t(193), uint8_t(250), uint8_t(221), uint8_t(255), uint8_t(255), uint8_t(128)}, + [11]uint8_t{uint8_t(24), uint8_t(71), uint8_t(130), uint8_t(219), uint8_t(154), uint8_t(170), uint8_t(243), uint8_t(182), uint8_t(255), uint8_t(255), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(182), uint8_t(225), uint8_t(249), uint8_t(219), uint8_t(240), uint8_t(255), uint8_t(224), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(149), uint8_t(150), uint8_t(226), uint8_t(252), uint8_t(216), uint8_t(205), uint8_t(255), uint8_t(171), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(28), uint8_t(108), uint8_t(170), uint8_t(242), uint8_t(183), uint8_t(194), uint8_t(254), uint8_t(223), uint8_t(255), uint8_t(255), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(81), uint8_t(230), uint8_t(252), uint8_t(204), uint8_t(203), uint8_t(255), uint8_t(192), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(123), uint8_t(102), uint8_t(209), uint8_t(247), uint8_t(188), uint8_t(196), uint8_t(255), uint8_t(233), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(20), uint8_t(95), uint8_t(153), uint8_t(243), uint8_t(164), uint8_t(173), uint8_t(255), uint8_t(203), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(222), uint8_t(248), uint8_t(255), uint8_t(216), uint8_t(213), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(168), uint8_t(175), uint8_t(246), uint8_t(252), uint8_t(235), uint8_t(205), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(47), uint8_t(116), uint8_t(215), uint8_t(255), uint8_t(211), uint8_t(212), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(121), uint8_t(236), uint8_t(253), uint8_t(212), uint8_t(214), uint8_t(255), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(141), uint8_t(84), uint8_t(213), uint8_t(252), uint8_t(201), uint8_t(202), uint8_t(255), uint8_t(219), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(42), uint8_t(80), uint8_t(160), uint8_t(240), uint8_t(162), uint8_t(185), uint8_t(255), uint8_t(205), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(1), uint8_t(1), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(244), uint8_t(1), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + [11]uint8_t{uint8_t(238), uint8_t(1), uint8_t(255), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128), uint8_t(128)}, + }, + }, +} /* tree_enc.c:21:3 */ + +func VP8DefaultProbas(tls *libc.TLS, enc uintptr) { /* tree_enc.c:156:6: */ + var probas uintptr = (enc + 3616 /* &.proba_ */) + (*VP8EncProba)(unsafe.Pointer(probas)).use_skip_proba_ = 0 + libc.Xmemset(tls, (probas /* &.segments_ */), int32(255), uint64(unsafe.Sizeof([3]uint8_t{}))) + libc.Xmemcpy(tls, (probas + 4 /* &.coeffs_ */), uintptr(unsafe.Pointer(&VP8CoeffsProba0)), uint64(unsafe.Sizeof(VP8CoeffsProba0))) + // Note: we could hard-code the level_costs_ corresponding to VP8CoeffsProba0, + // but that's ~11k of static data. Better call VP8CalculateLevelCosts() later. + (*VP8EncProba)(unsafe.Pointer(probas)).dirty_ = 1 +} + +// Paragraph 11.5. 900bytes. +var kBModesProba1 = [10][10][9]uint8_t{[10][9]uint8_t{ + [9]uint8_t{uint8_t(231), uint8_t(120), uint8_t(48), uint8_t(89), uint8_t(115), uint8_t(113), uint8_t(120), uint8_t(152), uint8_t(112)}, + [9]uint8_t{uint8_t(152), uint8_t(179), uint8_t(64), uint8_t(126), uint8_t(170), uint8_t(118), uint8_t(46), uint8_t(70), uint8_t(95)}, + [9]uint8_t{uint8_t(175), uint8_t(69), uint8_t(143), uint8_t(80), uint8_t(85), uint8_t(82), uint8_t(72), uint8_t(155), uint8_t(103)}, + [9]uint8_t{uint8_t(56), uint8_t(58), uint8_t(10), uint8_t(171), uint8_t(218), uint8_t(189), uint8_t(17), uint8_t(13), uint8_t(152)}, + [9]uint8_t{uint8_t(114), uint8_t(26), uint8_t(17), uint8_t(163), uint8_t(44), uint8_t(195), uint8_t(21), uint8_t(10), uint8_t(173)}, + [9]uint8_t{uint8_t(121), uint8_t(24), uint8_t(80), uint8_t(195), uint8_t(26), uint8_t(62), uint8_t(44), uint8_t(64), uint8_t(85)}, + [9]uint8_t{uint8_t(144), uint8_t(71), uint8_t(10), uint8_t(38), uint8_t(171), uint8_t(213), uint8_t(144), uint8_t(34), uint8_t(26)}, + [9]uint8_t{uint8_t(170), uint8_t(46), uint8_t(55), uint8_t(19), uint8_t(136), uint8_t(160), uint8_t(33), uint8_t(206), uint8_t(71)}, + [9]uint8_t{uint8_t(63), uint8_t(20), uint8_t(8), uint8_t(114), uint8_t(114), uint8_t(208), uint8_t(12), uint8_t(9), uint8_t(226)}, + [9]uint8_t{uint8_t(81), uint8_t(40), uint8_t(11), uint8_t(96), uint8_t(182), uint8_t(84), uint8_t(29), uint8_t(16), uint8_t(36)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(134), uint8_t(183), uint8_t(89), uint8_t(137), uint8_t(98), uint8_t(101), uint8_t(106), uint8_t(165), uint8_t(148)}, + [9]uint8_t{uint8_t(72), uint8_t(187), uint8_t(100), uint8_t(130), uint8_t(157), uint8_t(111), uint8_t(32), uint8_t(75), uint8_t(80)}, + [9]uint8_t{uint8_t(66), uint8_t(102), uint8_t(167), uint8_t(99), uint8_t(74), uint8_t(62), uint8_t(40), uint8_t(234), uint8_t(128)}, + [9]uint8_t{uint8_t(41), uint8_t(53), uint8_t(9), uint8_t(178), uint8_t(241), uint8_t(141), uint8_t(26), uint8_t(8), uint8_t(107)}, + [9]uint8_t{uint8_t(74), uint8_t(43), uint8_t(26), uint8_t(146), uint8_t(73), uint8_t(166), uint8_t(49), uint8_t(23), uint8_t(157)}, + [9]uint8_t{uint8_t(65), uint8_t(38), uint8_t(105), uint8_t(160), uint8_t(51), uint8_t(52), uint8_t(31), uint8_t(115), uint8_t(128)}, + [9]uint8_t{uint8_t(104), uint8_t(79), uint8_t(12), uint8_t(27), uint8_t(217), uint8_t(255), uint8_t(87), uint8_t(17), uint8_t(7)}, + [9]uint8_t{uint8_t(87), uint8_t(68), uint8_t(71), uint8_t(44), uint8_t(114), uint8_t(51), uint8_t(15), uint8_t(186), uint8_t(23)}, + [9]uint8_t{uint8_t(47), uint8_t(41), uint8_t(14), uint8_t(110), uint8_t(182), uint8_t(183), uint8_t(21), uint8_t(17), uint8_t(194)}, + [9]uint8_t{uint8_t(66), uint8_t(45), uint8_t(25), uint8_t(102), uint8_t(197), uint8_t(189), uint8_t(23), uint8_t(18), uint8_t(22)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(88), uint8_t(88), uint8_t(147), uint8_t(150), uint8_t(42), uint8_t(46), uint8_t(45), uint8_t(196), uint8_t(205)}, + [9]uint8_t{uint8_t(43), uint8_t(97), uint8_t(183), uint8_t(117), uint8_t(85), uint8_t(38), uint8_t(35), uint8_t(179), uint8_t(61)}, + [9]uint8_t{uint8_t(39), uint8_t(53), uint8_t(200), uint8_t(87), uint8_t(26), uint8_t(21), uint8_t(43), uint8_t(232), uint8_t(171)}, + [9]uint8_t{uint8_t(56), uint8_t(34), uint8_t(51), uint8_t(104), uint8_t(114), uint8_t(102), uint8_t(29), uint8_t(93), uint8_t(77)}, + [9]uint8_t{uint8_t(39), uint8_t(28), uint8_t(85), uint8_t(171), uint8_t(58), uint8_t(165), uint8_t(90), uint8_t(98), uint8_t(64)}, + [9]uint8_t{uint8_t(34), uint8_t(22), uint8_t(116), uint8_t(206), uint8_t(23), uint8_t(34), uint8_t(43), uint8_t(166), uint8_t(73)}, + [9]uint8_t{uint8_t(107), uint8_t(54), uint8_t(32), uint8_t(26), uint8_t(51), uint8_t(1), uint8_t(81), uint8_t(43), uint8_t(31)}, + [9]uint8_t{uint8_t(68), uint8_t(25), uint8_t(106), uint8_t(22), uint8_t(64), uint8_t(171), uint8_t(36), uint8_t(225), uint8_t(114)}, + [9]uint8_t{uint8_t(34), uint8_t(19), uint8_t(21), uint8_t(102), uint8_t(132), uint8_t(188), uint8_t(16), uint8_t(76), uint8_t(124)}, + [9]uint8_t{uint8_t(62), uint8_t(18), uint8_t(78), uint8_t(95), uint8_t(85), uint8_t(57), uint8_t(50), uint8_t(48), uint8_t(51)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(193), uint8_t(101), uint8_t(35), uint8_t(159), uint8_t(215), uint8_t(111), uint8_t(89), uint8_t(46), uint8_t(111)}, + [9]uint8_t{uint8_t(60), uint8_t(148), uint8_t(31), uint8_t(172), uint8_t(219), uint8_t(228), uint8_t(21), uint8_t(18), uint8_t(111)}, + [9]uint8_t{uint8_t(112), uint8_t(113), uint8_t(77), uint8_t(85), uint8_t(179), uint8_t(255), uint8_t(38), uint8_t(120), uint8_t(114)}, + [9]uint8_t{uint8_t(40), uint8_t(42), uint8_t(1), uint8_t(196), uint8_t(245), uint8_t(209), uint8_t(10), uint8_t(25), uint8_t(109)}, + [9]uint8_t{uint8_t(88), uint8_t(43), uint8_t(29), uint8_t(140), uint8_t(166), uint8_t(213), uint8_t(37), uint8_t(43), uint8_t(154)}, + [9]uint8_t{uint8_t(61), uint8_t(63), uint8_t(30), uint8_t(155), uint8_t(67), uint8_t(45), uint8_t(68), uint8_t(1), uint8_t(209)}, + [9]uint8_t{uint8_t(100), uint8_t(80), uint8_t(8), uint8_t(43), uint8_t(154), uint8_t(1), uint8_t(51), uint8_t(26), uint8_t(71)}, + [9]uint8_t{uint8_t(142), uint8_t(78), uint8_t(78), uint8_t(16), uint8_t(255), uint8_t(128), uint8_t(34), uint8_t(197), uint8_t(171)}, + [9]uint8_t{uint8_t(41), uint8_t(40), uint8_t(5), uint8_t(102), uint8_t(211), uint8_t(183), uint8_t(4), uint8_t(1), uint8_t(221)}, + [9]uint8_t{uint8_t(51), uint8_t(50), uint8_t(17), uint8_t(168), uint8_t(209), uint8_t(192), uint8_t(23), uint8_t(25), uint8_t(82)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(138), uint8_t(31), uint8_t(36), uint8_t(171), uint8_t(27), uint8_t(166), uint8_t(38), uint8_t(44), uint8_t(229)}, + [9]uint8_t{uint8_t(67), uint8_t(87), uint8_t(58), uint8_t(169), uint8_t(82), uint8_t(115), uint8_t(26), uint8_t(59), uint8_t(179)}, + [9]uint8_t{uint8_t(63), uint8_t(59), uint8_t(90), uint8_t(180), uint8_t(59), uint8_t(166), uint8_t(93), uint8_t(73), uint8_t(154)}, + [9]uint8_t{uint8_t(40), uint8_t(40), uint8_t(21), uint8_t(116), uint8_t(143), uint8_t(209), uint8_t(34), uint8_t(39), uint8_t(175)}, + [9]uint8_t{uint8_t(47), uint8_t(15), uint8_t(16), uint8_t(183), uint8_t(34), uint8_t(223), uint8_t(49), uint8_t(45), uint8_t(183)}, + [9]uint8_t{uint8_t(46), uint8_t(17), uint8_t(33), uint8_t(183), uint8_t(6), uint8_t(98), uint8_t(15), uint8_t(32), uint8_t(183)}, + [9]uint8_t{uint8_t(57), uint8_t(46), uint8_t(22), uint8_t(24), uint8_t(128), uint8_t(1), uint8_t(54), uint8_t(17), uint8_t(37)}, + [9]uint8_t{uint8_t(65), uint8_t(32), uint8_t(73), uint8_t(115), uint8_t(28), uint8_t(128), uint8_t(23), uint8_t(128), uint8_t(205)}, + [9]uint8_t{uint8_t(40), uint8_t(3), uint8_t(9), uint8_t(115), uint8_t(51), uint8_t(192), uint8_t(18), uint8_t(6), uint8_t(223)}, + [9]uint8_t{uint8_t(87), uint8_t(37), uint8_t(9), uint8_t(115), uint8_t(59), uint8_t(77), uint8_t(64), uint8_t(21), uint8_t(47)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(104), uint8_t(55), uint8_t(44), uint8_t(218), uint8_t(9), uint8_t(54), uint8_t(53), uint8_t(130), uint8_t(226)}, + [9]uint8_t{uint8_t(64), uint8_t(90), uint8_t(70), uint8_t(205), uint8_t(40), uint8_t(41), uint8_t(23), uint8_t(26), uint8_t(57)}, + [9]uint8_t{uint8_t(54), uint8_t(57), uint8_t(112), uint8_t(184), uint8_t(5), uint8_t(41), uint8_t(38), uint8_t(166), uint8_t(213)}, + [9]uint8_t{uint8_t(30), uint8_t(34), uint8_t(26), uint8_t(133), uint8_t(152), uint8_t(116), uint8_t(10), uint8_t(32), uint8_t(134)}, + [9]uint8_t{uint8_t(39), uint8_t(19), uint8_t(53), uint8_t(221), uint8_t(26), uint8_t(114), uint8_t(32), uint8_t(73), uint8_t(255)}, + [9]uint8_t{uint8_t(31), uint8_t(9), uint8_t(65), uint8_t(234), uint8_t(2), uint8_t(15), uint8_t(1), uint8_t(118), uint8_t(73)}, + [9]uint8_t{uint8_t(75), uint8_t(32), uint8_t(12), uint8_t(51), uint8_t(192), uint8_t(255), uint8_t(160), uint8_t(43), uint8_t(51)}, + [9]uint8_t{uint8_t(88), uint8_t(31), uint8_t(35), uint8_t(67), uint8_t(102), uint8_t(85), uint8_t(55), uint8_t(186), uint8_t(85)}, + [9]uint8_t{uint8_t(56), uint8_t(21), uint8_t(23), uint8_t(111), uint8_t(59), uint8_t(205), uint8_t(45), uint8_t(37), uint8_t(192)}, + [9]uint8_t{uint8_t(55), uint8_t(38), uint8_t(70), uint8_t(124), uint8_t(73), uint8_t(102), uint8_t(1), uint8_t(34), uint8_t(98)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(125), uint8_t(98), uint8_t(42), uint8_t(88), uint8_t(104), uint8_t(85), uint8_t(117), uint8_t(175), uint8_t(82)}, + [9]uint8_t{uint8_t(95), uint8_t(84), uint8_t(53), uint8_t(89), uint8_t(128), uint8_t(100), uint8_t(113), uint8_t(101), uint8_t(45)}, + [9]uint8_t{uint8_t(75), uint8_t(79), uint8_t(123), uint8_t(47), uint8_t(51), uint8_t(128), uint8_t(81), uint8_t(171), uint8_t(1)}, + [9]uint8_t{uint8_t(57), uint8_t(17), uint8_t(5), uint8_t(71), uint8_t(102), uint8_t(57), uint8_t(53), uint8_t(41), uint8_t(49)}, + [9]uint8_t{uint8_t(38), uint8_t(33), uint8_t(13), uint8_t(121), uint8_t(57), uint8_t(73), uint8_t(26), uint8_t(1), uint8_t(85)}, + [9]uint8_t{uint8_t(41), uint8_t(10), uint8_t(67), uint8_t(138), uint8_t(77), uint8_t(110), uint8_t(90), uint8_t(47), uint8_t(114)}, + [9]uint8_t{uint8_t(115), uint8_t(21), uint8_t(2), uint8_t(10), uint8_t(102), uint8_t(255), uint8_t(166), uint8_t(23), uint8_t(6)}, + [9]uint8_t{uint8_t(101), uint8_t(29), uint8_t(16), uint8_t(10), uint8_t(85), uint8_t(128), uint8_t(101), uint8_t(196), uint8_t(26)}, + [9]uint8_t{uint8_t(57), uint8_t(18), uint8_t(10), uint8_t(102), uint8_t(102), uint8_t(213), uint8_t(34), uint8_t(20), uint8_t(43)}, + [9]uint8_t{uint8_t(117), uint8_t(20), uint8_t(15), uint8_t(36), uint8_t(163), uint8_t(128), uint8_t(68), uint8_t(1), uint8_t(26)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(102), uint8_t(61), uint8_t(71), uint8_t(37), uint8_t(34), uint8_t(53), uint8_t(31), uint8_t(243), uint8_t(192)}, + [9]uint8_t{uint8_t(69), uint8_t(60), uint8_t(71), uint8_t(38), uint8_t(73), uint8_t(119), uint8_t(28), uint8_t(222), uint8_t(37)}, + [9]uint8_t{uint8_t(68), uint8_t(45), uint8_t(128), uint8_t(34), uint8_t(1), uint8_t(47), uint8_t(11), uint8_t(245), uint8_t(171)}, + [9]uint8_t{uint8_t(62), uint8_t(17), uint8_t(19), uint8_t(70), uint8_t(146), uint8_t(85), uint8_t(55), uint8_t(62), uint8_t(70)}, + [9]uint8_t{uint8_t(37), uint8_t(43), uint8_t(37), uint8_t(154), uint8_t(100), uint8_t(163), uint8_t(85), uint8_t(160), uint8_t(1)}, + [9]uint8_t{uint8_t(63), uint8_t(9), uint8_t(92), uint8_t(136), uint8_t(28), uint8_t(64), uint8_t(32), uint8_t(201), uint8_t(85)}, + [9]uint8_t{uint8_t(75), uint8_t(15), uint8_t(9), uint8_t(9), uint8_t(64), uint8_t(255), uint8_t(184), uint8_t(119), uint8_t(16)}, + [9]uint8_t{uint8_t(86), uint8_t(6), uint8_t(28), uint8_t(5), uint8_t(64), uint8_t(255), uint8_t(25), uint8_t(248), uint8_t(1)}, + [9]uint8_t{uint8_t(56), uint8_t(8), uint8_t(17), uint8_t(132), uint8_t(137), uint8_t(255), uint8_t(55), uint8_t(116), uint8_t(128)}, + [9]uint8_t{uint8_t(58), uint8_t(15), uint8_t(20), uint8_t(82), uint8_t(135), uint8_t(57), uint8_t(26), uint8_t(121), uint8_t(40)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(164), uint8_t(50), uint8_t(31), uint8_t(137), uint8_t(154), uint8_t(133), uint8_t(25), uint8_t(35), uint8_t(218)}, + [9]uint8_t{uint8_t(51), uint8_t(103), uint8_t(44), uint8_t(131), uint8_t(131), uint8_t(123), uint8_t(31), uint8_t(6), uint8_t(158)}, + [9]uint8_t{uint8_t(86), uint8_t(40), uint8_t(64), uint8_t(135), uint8_t(148), uint8_t(224), uint8_t(45), uint8_t(183), uint8_t(128)}, + [9]uint8_t{uint8_t(22), uint8_t(26), uint8_t(17), uint8_t(131), uint8_t(240), uint8_t(154), uint8_t(14), uint8_t(1), uint8_t(209)}, + [9]uint8_t{uint8_t(45), uint8_t(16), uint8_t(21), uint8_t(91), uint8_t(64), uint8_t(222), uint8_t(7), uint8_t(1), uint8_t(197)}, + [9]uint8_t{uint8_t(56), uint8_t(21), uint8_t(39), uint8_t(155), uint8_t(60), uint8_t(138), uint8_t(23), uint8_t(102), uint8_t(213)}, + [9]uint8_t{uint8_t(83), uint8_t(12), uint8_t(13), uint8_t(54), uint8_t(192), uint8_t(255), uint8_t(68), uint8_t(47), uint8_t(28)}, + [9]uint8_t{uint8_t(85), uint8_t(26), uint8_t(85), uint8_t(85), uint8_t(128), uint8_t(128), uint8_t(32), uint8_t(146), uint8_t(171)}, + [9]uint8_t{uint8_t(18), uint8_t(11), uint8_t(7), uint8_t(63), uint8_t(144), uint8_t(171), uint8_t(4), uint8_t(4), uint8_t(246)}, + [9]uint8_t{uint8_t(35), uint8_t(27), uint8_t(10), uint8_t(146), uint8_t(174), uint8_t(171), uint8_t(12), uint8_t(26), uint8_t(128)}}, + [10][9]uint8_t{[9]uint8_t{uint8_t(190), uint8_t(80), uint8_t(35), uint8_t(99), uint8_t(180), uint8_t(80), uint8_t(126), uint8_t(54), uint8_t(45)}, + [9]uint8_t{uint8_t(85), uint8_t(126), uint8_t(47), uint8_t(87), uint8_t(176), uint8_t(51), uint8_t(41), uint8_t(20), uint8_t(32)}, + [9]uint8_t{uint8_t(101), uint8_t(75), uint8_t(128), uint8_t(139), uint8_t(118), uint8_t(146), uint8_t(116), uint8_t(128), uint8_t(85)}, + [9]uint8_t{uint8_t(56), uint8_t(41), uint8_t(15), uint8_t(176), uint8_t(236), uint8_t(85), uint8_t(37), uint8_t(9), uint8_t(62)}, + [9]uint8_t{uint8_t(71), uint8_t(30), uint8_t(17), uint8_t(119), uint8_t(118), uint8_t(255), uint8_t(17), uint8_t(18), uint8_t(138)}, + [9]uint8_t{uint8_t(101), uint8_t(38), uint8_t(60), uint8_t(138), uint8_t(55), uint8_t(70), uint8_t(43), uint8_t(26), uint8_t(142)}, + [9]uint8_t{uint8_t(146), uint8_t(36), uint8_t(19), uint8_t(30), uint8_t(171), uint8_t(255), uint8_t(97), uint8_t(27), uint8_t(20)}, + [9]uint8_t{uint8_t(138), uint8_t(45), uint8_t(61), uint8_t(62), uint8_t(219), uint8_t(1), uint8_t(81), uint8_t(188), uint8_t(64)}, + [9]uint8_t{uint8_t(32), uint8_t(41), uint8_t(20), uint8_t(117), uint8_t(151), uint8_t(142), uint8_t(20), uint8_t(21), uint8_t(163)}, + [9]uint8_t{uint8_t(112), uint8_t(19), uint8_t(12), uint8_t(61), uint8_t(195), uint8_t(128), uint8_t(48), uint8_t(4), uint8_t(24)}}} /* tree_enc.c:167:22 */ + +func PutI4Mode(tls *libc.TLS, bw uintptr, mode int32, prob uintptr) int32 { /* tree_enc.c:270:12: */ + if VP8PutBit(tls, bw, (libc.Bool32(mode != B_DC_PRED)), int32(*(*uint8_t)(unsafe.Pointer(prob)))) != 0 { + if VP8PutBit(tls, bw, (libc.Bool32(mode != B_TM_PRED)), int32(*(*uint8_t)(unsafe.Pointer(prob + 1)))) != 0 { + if VP8PutBit(tls, bw, (libc.Bool32(mode != B_VE_PRED)), int32(*(*uint8_t)(unsafe.Pointer(prob + 2)))) != 0 { + if !(VP8PutBit(tls, bw, (libc.Bool32(mode >= B_LD_PRED)), int32(*(*uint8_t)(unsafe.Pointer(prob + 3)))) != 0) { + if VP8PutBit(tls, bw, (libc.Bool32(mode != B_HE_PRED)), int32(*(*uint8_t)(unsafe.Pointer(prob + 4)))) != 0 { + VP8PutBit(tls, bw, (libc.Bool32(mode != B_RD_PRED)), int32(*(*uint8_t)(unsafe.Pointer(prob + 5)))) + } + } else { + if VP8PutBit(tls, bw, (libc.Bool32(mode != B_LD_PRED)), int32(*(*uint8_t)(unsafe.Pointer(prob + 6)))) != 0 { + if VP8PutBit(tls, bw, (libc.Bool32(mode != B_VL_PRED)), int32(*(*uint8_t)(unsafe.Pointer(prob + 7)))) != 0 { + VP8PutBit(tls, bw, (libc.Bool32(mode != B_HD_PRED)), int32(*(*uint8_t)(unsafe.Pointer(prob + 8)))) + } + } + } + } + } + } + return mode +} + +func PutI16Mode(tls *libc.TLS, bw uintptr, mode int32) { /* tree_enc.c:292:13: */ + if VP8PutBit(tls, bw, (libc.Bool32((mode == TM_PRED) || (mode == H_PRED))), 156) != 0 { + VP8PutBit(tls, bw, (libc.Bool32(mode == TM_PRED)), 128) // TM or HE + } else { + VP8PutBit(tls, bw, (libc.Bool32(mode == V_PRED)), 163) // VE or DC + } +} + +func PutUVMode(tls *libc.TLS, bw uintptr, uv_mode int32) { /* tree_enc.c:300:13: */ + if VP8PutBit(tls, bw, (libc.Bool32(uv_mode != DC_PRED)), 142) != 0 { + if VP8PutBit(tls, bw, (libc.Bool32(uv_mode != V_PRED)), 114) != 0 { + VP8PutBit(tls, bw, (libc.Bool32(uv_mode != H_PRED)), 183) // else: TM_PRED + } + } +} + +func PutSegment(tls *libc.TLS, bw uintptr, s int32, p uintptr) { /* tree_enc.c:308:13: */ + if VP8PutBit(tls, bw, (libc.Bool32(s >= 2)), int32(*(*uint8_t)(unsafe.Pointer(p)))) != 0 { + p += uintptr(1) + } + VP8PutBit(tls, bw, (s & 1), int32(*(*uint8_t)(unsafe.Pointer(p + 1)))) +} + +func VP8CodeIntraModes(tls *libc.TLS, enc uintptr) { /* tree_enc.c:313:6: */ + bp := tls.Alloc(3848) + defer tls.Free(3848) + + var bw uintptr = (enc + 64 /* &.bw_ */) + // var it VP8EncIterator at bp, 3848 + + VP8IteratorInit(tls, enc, (bp) /* &it */) + for ok := true; ok; ok = (VP8IteratorNext(tls, (bp) /* &it */) != 0) { + var mb uintptr = (*VP8EncIterator)(unsafe.Pointer(bp /* &it */)).mb_ + var preds uintptr = (*VP8EncIterator)(unsafe.Pointer(bp /* &it */)).preds_ + if (*VP8Encoder)(unsafe.Pointer(enc)).segment_hdr_.update_map_ != 0 { + PutSegment(tls, bw, (int32(*(*uint8)(unsafe.Pointer(mb /* &.segment_ */)) & 0x60 >> 5)), (enc + 3616 /* &.proba_ */) /* &.segments_ */) + } + if (*VP8Encoder)(unsafe.Pointer(enc)).proba_.use_skip_proba_ != 0 { + VP8PutBit(tls, bw, (int32(*(*uint8)(unsafe.Pointer(mb /* &.skip_ */)) & 0x10 >> 4)), int32((*VP8Encoder)(unsafe.Pointer(enc)).proba_.skip_proba_)) + } + if VP8PutBit(tls, bw, (libc.Bool32((int32(*(*uint8)(unsafe.Pointer(mb /* &.type_ */))&0x3>>0)) != 0)), 145) != 0 { // i16x16 + PutI16Mode(tls, bw, int32(*(*uint8_t)(unsafe.Pointer(preds)))) + } else { + var preds_w int32 = (*VP8Encoder)(unsafe.Pointer(enc)).preds_w_ + var top_pred uintptr = (preds - uintptr(preds_w)) + var x int32 + var y int32 + for y = 0; y < 4; y++ { + var left int32 = int32(*(*uint8_t)(unsafe.Pointer(preds + libc.UintptrFromInt32(-1)))) + for x = 0; x < 4; x++ { + var probas uintptr = ((uintptr(unsafe.Pointer(&kBModesProba1)) + uintptr(*(*uint8_t)(unsafe.Pointer(top_pred + uintptr(x))))*90) + uintptr(left)*9) + left = PutI4Mode(tls, bw, int32(*(*uint8_t)(unsafe.Pointer(preds + uintptr(x)))), probas) + } + top_pred = preds + preds += uintptr(preds_w) + } + } + PutUVMode(tls, bw, (int32(*(*uint8)(unsafe.Pointer(mb /* &.uv_mode_ */)) & 0xc >> 2))) + } +} + +//------------------------------------------------------------------------------ +// Paragraph 13 + +var VP8CoeffsUpdateProba = [4][8][3][11]uint8_t{[8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(176), uint8_t(246), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(223), uint8_t(241), uint8_t(252), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(249), uint8_t(253), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(244), uint8_t(252), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(234), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(246), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(239), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(248), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(251), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(251), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(253), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(250), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, +}, + [8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(217), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(225), uint8_t(252), uint8_t(241), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(234), uint8_t(250), uint8_t(241), uint8_t(250), uint8_t(253), uint8_t(255), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(223), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(238), uint8_t(253), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(248), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(249), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(247), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(252), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(250), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + }, + [8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(186), uint8_t(251), uint8_t(250), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(234), uint8_t(251), uint8_t(244), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(251), uint8_t(251), uint8_t(243), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(236), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(251), uint8_t(253), uint8_t(253), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + }, + [8][3][11]uint8_t{ + [3][11]uint8_t{[11]uint8_t{uint8_t(248), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(250), uint8_t(254), uint8_t(252), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(248), uint8_t(254), uint8_t(249), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(253), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(246), uint8_t(253), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(252), uint8_t(254), uint8_t(251), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(252), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(248), uint8_t(254), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(253), uint8_t(255), uint8_t(254), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(251), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(245), uint8_t(251), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(253), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(251), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(252), uint8_t(253), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(252), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(249), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(253), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(250), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + [3][11]uint8_t{[11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(254), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + [11]uint8_t{uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255), uint8_t(255)}, + }, + }, +} /* tree_enc.c:350:5 */ + +func VP8WriteProbas(tls *libc.TLS, bw uintptr, probas uintptr) { /* tree_enc.c:485:6: */ + var t int32 + var b int32 + var c int32 + var p int32 + for t = 0; t < NUM_TYPES; t++ { + for b = 0; b < NUM_BANDS; b++ { + for c = 0; c < NUM_CTX; c++ { + for p = 0; p < NUM_PROBAS; p++ { + var p0 uint8_t = *(*uint8_t)(unsafe.Pointer(((((probas + 4 /* &.coeffs_ */) + uintptr(t)*264) + uintptr(b)*33) + uintptr(c)*11) + uintptr(p))) + var update int32 = (libc.Bool32(int32(p0) != int32(*(*uint8_t)(unsafe.Pointer((((uintptr(unsafe.Pointer(&VP8CoeffsProba0)) + uintptr(t)*264) + uintptr(b)*33) + uintptr(c)*11) + uintptr(p)))))) + if VP8PutBit(tls, bw, update, int32(*(*uint8_t)(unsafe.Pointer((((uintptr(unsafe.Pointer(&VP8CoeffsUpdateProba)) + uintptr(t)*264) + uintptr(b)*33) + uintptr(c)*11) + uintptr(p))))) != 0 { + VP8PutBits(tls, bw, uint32(p0), 8) + } + } + } + } + } + if VP8PutBitUniform(tls, bw, (*VP8EncProba)(unsafe.Pointer(probas)).use_skip_proba_) != 0 { + VP8PutBits(tls, bw, uint32((*VP8EncProba)(unsafe.Pointer(probas)).skip_proba_), 8) + } +} + +//------------------------------------------------------------------------------ +// Transform-related functions use din both encoding and decoding. + +// Macros used to create a batch predictor that iteratively uses a +// one-pixel predictor. + +// The predictor is added to the output pixel (which +// is therefore considered as a residual) to get the final prediction. + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Bit writing and boolean coder +// +// Author: Skal (pascal.massimino@gmail.com) + +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// +// Entropy encoding (Huffman) for webp lossless + +// Copyright 2010 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Common types + memory wrappers +// +// Author: Skal (pascal.massimino@gmail.com) + +// Struct for holding the tree header in coded form. +type HuffmanTreeToken = struct { + code uint8_t + extra_bits uint8_t +} /* huffman_encode_utils.h:27:3 */ + +// Struct to represent the tree codes (depth and bits array). +type HuffmanTreeCode = struct { + num_symbols int32 + _ [4]byte + code_lengths uintptr + codes uintptr +} /* huffman_encode_utils.h:34:3 */ + +// Struct to represent the Huffman tree. +type HuffmanTree = struct { + total_count_ uint32_t + value_ int32 + pool_index_left_ int32 + pool_index_right_ int32 +} /* huffman_encode_utils.h:42:3 */ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header for constants related to WebP file format. +// +// Author: Urvang (urvang@google.com) + +// Maximum number of histogram images (sub-blocks). + +// Palette reordering for smaller sum of deltas (and for smaller storage). + +func PaletteCompareColorsForQsort(tls *libc.TLS, p1 uintptr, p2 uintptr) int32 { /* vp8l_enc.c:34:12: */ + var a uint32_t = WebPMemToUint32(tls, p1) + var b uint32_t = WebPMemToUint32(tls, p2) + + if a < b { + return -1 + } + return 1 +} + +func PaletteComponentDistance(tls *libc.TLS, v uint32_t) uint32_t { /* vp8l_enc.c:41:29: */ + if v <= uint32_t(128) { + return v + } + return (uint32_t(256) - v) +} + +// Computes a value that is related to the entropy created by the +// palette entry diff. +// +// Note that the last & 0xff is a no-operation in the next statement, but +// removed by most compilers and is here only for regularity of the code. +func PaletteColorDistance(tls *libc.TLS, col1 uint32_t, col2 uint32_t) uint32_t { /* vp8l_enc.c:50:29: */ + var diff uint32_t = VP8LSubPixels(tls, col1, col2) + var kMoreWeightForRGBThanForAlpha int32 = 9 + var score uint32_t + score = PaletteComponentDistance(tls, ((diff >> 0) & uint32_t(0xff))) + score = score + (PaletteComponentDistance(tls, ((diff >> 8) & uint32_t(0xff)))) + score = score + (PaletteComponentDistance(tls, ((diff >> 16) & uint32_t(0xff)))) + score = score * (uint32_t(kMoreWeightForRGBThanForAlpha)) + score = score + (PaletteComponentDistance(tls, ((diff >> 24) & uint32_t(0xff)))) + return score +} + +func SwapColor(tls *libc.TLS, col1 uintptr, col2 uintptr) { /* vp8l_enc.c:62:25: */ + var tmp uint32_t = *(*uint32_t)(unsafe.Pointer(col1)) + *(*uint32_t)(unsafe.Pointer(col1)) = *(*uint32_t)(unsafe.Pointer(col2)) + *(*uint32_t)(unsafe.Pointer(col2)) = tmp +} + +func SearchColorNoIdx(tls *libc.TLS, sorted uintptr, color uint32_t, num_colors int32) int32 { /* vp8l_enc.c:68:24: */ + var low int32 = 0 + var hi int32 = num_colors + if *(*uint32_t)(unsafe.Pointer(sorted + uintptr(low)*4)) == color { + return low + } // loop invariant: sorted[low] != color + for 1 != 0 { + var mid int32 = ((low + hi) >> 1) + if *(*uint32_t)(unsafe.Pointer(sorted + uintptr(mid)*4)) == color { + return mid + } else if *(*uint32_t)(unsafe.Pointer(sorted + uintptr(mid)*4)) < color { + low = mid + } else { + hi = mid + } + } + + return 0 +} + +// The palette has been sorted by alpha. This function checks if the other +// components of the palette have a monotonic development with regards to +// position in the palette. If all have monotonic development, there is +// no benefit to re-organize them greedily. A monotonic development +// would be spotted in green-only situations (like lossy alpha) or gray-scale +// images. +func PaletteHasNonMonotonousDeltas(tls *libc.TLS, palette uintptr, num_colors int32) int32 { /* vp8l_enc.c:92:12: */ + var predict uint32_t = uint32_t(0x000000) + var i int32 + var sign_found uint8_t = uint8_t(0x00) + for i = 0; i < num_colors; i++ { + var diff uint32_t = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(palette + uintptr(i)*4)), predict) + var rd uint8_t = (uint8_t((diff >> 16) & uint32_t(0xff))) + var gd uint8_t = (uint8_t((diff >> 8) & uint32_t(0xff))) + var bd uint8_t = (uint8_t((diff >> 0) & uint32_t(0xff))) + if int32(rd) != 0x00 { + sign_found = uint8_t(int32(sign_found) | (func() int32 { + if int32(rd) < 0x80 { + return 1 + } + return 2 + }())) + } + if int32(gd) != 0x00 { + sign_found = uint8_t(int32(sign_found) | (func() int32 { + if int32(gd) < 0x80 { + return 8 + } + return 16 + }())) + } + if int32(bd) != 0x00 { + sign_found = uint8_t(int32(sign_found) | (func() int32 { + if int32(bd) < 0x80 { + return 64 + } + return 128 + }())) + } + predict = *(*uint32_t)(unsafe.Pointer(palette + uintptr(i)*4)) + } + return (libc.Bool32((int32(sign_found) & (int32(sign_found) << 1)) != 0)) // two consequent signs. +} + +func PaletteSortMinimizeDeltas(tls *libc.TLS, palette_sorted uintptr, num_colors int32, palette uintptr) { /* vp8l_enc.c:116:13: */ + var predict uint32_t = uint32_t(0x00000000) + var i int32 + var k int32 + libc.Xmemcpy(tls, palette, palette_sorted, (uint64(num_colors) * uint64(unsafe.Sizeof(uint32_t(0))))) + if !(PaletteHasNonMonotonousDeltas(tls, palette_sorted, num_colors) != 0) { + return + } + // Find greedily always the closest color of the predicted color to minimize + // deltas in the palette. This reduces storage needs since the + // palette is stored with delta encoding. + for i = 0; i < num_colors; i++ { + var best_ix int32 = i + var best_score uint32_t = libc.CplUint32(0) + for k = i; k < num_colors; k++ { + var cur_score uint32_t = PaletteColorDistance(tls, *(*uint32_t)(unsafe.Pointer(palette + uintptr(k)*4)), predict) + if best_score > cur_score { + best_score = cur_score + best_ix = k + } + } + SwapColor(tls, (palette + uintptr(best_ix)*4), (palette + uintptr(i)*4)) + predict = *(*uint32_t)(unsafe.Pointer(palette + uintptr(i)*4)) + } +} + +// Sort palette in increasing order and prepare an inverse mapping array. +func PrepareMapToPalette(tls *libc.TLS, palette uintptr, num_colors uint32_t, sorted uintptr, idx_map uintptr) { /* vp8l_enc.c:141:13: */ + var i uint32_t + libc.Xmemcpy(tls, sorted, palette, (uint64(num_colors) * uint64(unsafe.Sizeof(uint32_t(0))))) + libc.Xqsort(tls, sorted, uint64(num_colors), uint64(unsafe.Sizeof(uint32_t(0))), *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{PaletteCompareColorsForQsort}))) + for i = uint32_t(0); i < num_colors; i++ { + *(*uint32_t)(unsafe.Pointer(idx_map + uintptr(SearchColorNoIdx(tls, sorted, *(*uint32_t)(unsafe.Pointer(palette + uintptr(i)*4)), int32(num_colors)))*4)) = i + } +} + +// ----------------------------------------------------------------------------- +// Modified Zeng method from "A Survey on Palette Reordering +// Methods for Improving the Compression of Color-Indexed Images" by Armando J. +// Pinho and Antonio J. R. Neves. + +// Finds the biggest cooccurrence in the matrix. +func CoOccurrenceFindMax(tls *libc.TLS, cooccurrence uintptr, num_colors uint32_t, c1 uintptr, c2 uintptr) { /* vp8l_enc.c:157:13: */ + // Find the index that is most frequently located adjacent to other + // (different) indexes. + var best_sum uint32_t = 0 + var i uint32_t + var j uint32_t + var best_cooccurrence uint32_t + *(*uint8_t)(unsafe.Pointer(c1)) = uint8(0) + for i = uint32_t(0); i < num_colors; i++ { + var sum uint32_t = uint32_t(0) + for j = uint32_t(0); j < num_colors; j++ { + sum = sum + (*(*uint32_t)(unsafe.Pointer(cooccurrence + uintptr(((i*num_colors)+j))*4))) + } + if sum > best_sum { + best_sum = sum + *(*uint8_t)(unsafe.Pointer(c1)) = uint8_t(i) + } + } + // Find the index that is most frequently found adjacent to *c1. + *(*uint8_t)(unsafe.Pointer(c2)) = uint8(0) + best_cooccurrence = 0 + for i = uint32_t(0); i < num_colors; i++ { + if *(*uint32_t)(unsafe.Pointer(cooccurrence + uintptr(((uint32_t(*(*uint8_t)(unsafe.Pointer(c1)))*num_colors)+i))*4)) > best_cooccurrence { + best_cooccurrence = *(*uint32_t)(unsafe.Pointer(cooccurrence + uintptr(((uint32_t(*(*uint8_t)(unsafe.Pointer(c1)))*num_colors)+i))*4)) + *(*uint8_t)(unsafe.Pointer(c2)) = uint8_t(i) + } + } + +} + +// Builds the cooccurrence matrix +func CoOccurrenceBuild(tls *libc.TLS, pic uintptr, palette uintptr, num_colors uint32_t, cooccurrence uintptr) WebPEncodingError { /* vp8l_enc.c:186:26: */ + bp := tls.Alloc(2048) + defer tls.Free(2048) + + var lines uintptr + var line_top uintptr + var line_current uintptr + var line_tmp uintptr + var x int32 + var y int32 + var src uintptr = (*WebPPicture)(unsafe.Pointer(pic)).argb + var prev_pix uint32_t = ^*(*uint32_t)(unsafe.Pointer(src)) + var prev_idx uint32_t = 0 + *(*[256]uint32_t)(unsafe.Pointer(bp + 1024 /* idx_map */)) = [256]uint32_t{0: uint32_t(0)} + // var palette_sorted [256]uint32_t at bp, 1024 + + lines = WebPSafeMalloc(tls, (uint64(2 * (*WebPPicture)(unsafe.Pointer(pic)).width)), uint64(unsafe.Sizeof(uint32_t(0)))) + if lines == (uintptr(0)) { + return VP8_ENC_ERROR_OUT_OF_MEMORY + } + line_top = (lines) + line_current = (lines + uintptr((*WebPPicture)(unsafe.Pointer(pic)).width)*4) + PrepareMapToPalette(tls, palette, num_colors, (bp) /* &palette_sorted[0] */, (bp + 1024) /* &idx_map[0] */) + for y = 0; y < (*WebPPicture)(unsafe.Pointer(pic)).height; y++ { + for x = 0; x < (*WebPPicture)(unsafe.Pointer(pic)).width; x++ { + var pix uint32_t = *(*uint32_t)(unsafe.Pointer(src + uintptr(x)*4)) + if pix != prev_pix { + prev_idx = *(*uint32_t)(unsafe.Pointer((bp + 1024) /* &idx_map[0] */ + uintptr(SearchColorNoIdx(tls, (bp) /* &palette_sorted[0] */, pix, int32(num_colors)))*4)) + prev_pix = pix + } + *(*uint32_t)(unsafe.Pointer(line_current + uintptr(x)*4)) = prev_idx + // 4-connectivity is what works best as mentioned in "On the relation + // between Memon's and the modified Zeng's palette reordering methods". + if (x > 0) && (prev_idx != *(*uint32_t)(unsafe.Pointer(line_current + uintptr((x-1))*4))) { + var left_idx uint32_t = *(*uint32_t)(unsafe.Pointer(line_current + uintptr((x-1))*4)) + *(*uint32_t)(unsafe.Pointer(cooccurrence + uintptr(((prev_idx*num_colors)+left_idx))*4))++ + *(*uint32_t)(unsafe.Pointer(cooccurrence + uintptr(((left_idx*num_colors)+prev_idx))*4))++ + } + if (y > 0) && (prev_idx != *(*uint32_t)(unsafe.Pointer(line_top + uintptr(x)*4))) { + var top_idx uint32_t = *(*uint32_t)(unsafe.Pointer(line_top + uintptr(x)*4)) + *(*uint32_t)(unsafe.Pointer(cooccurrence + uintptr(((prev_idx*num_colors)+top_idx))*4))++ + *(*uint32_t)(unsafe.Pointer(cooccurrence + uintptr(((top_idx*num_colors)+prev_idx))*4))++ + } + } + line_tmp = line_top + line_top = line_current + line_current = line_tmp + src += 4 * (uintptr((*WebPPicture)(unsafe.Pointer(pic)).argb_stride)) + } + WebPSafeFree(tls, lines) + return VP8_ENC_OK +} + +type Sum = struct { + index uint8_t + _ [3]byte + sum uint32_t +} /* vp8l_enc.c:232:1 */ + +// Implements the modified Zeng method from "A Survey on Palette Reordering +// Methods for Improving the Compression of Color-Indexed Images" by Armando J. +// Pinho and Antonio J. R. Neves. +func PaletteSortModifiedZeng(tls *libc.TLS, pic uintptr, palette_sorted uintptr, num_colors uint32_t, palette uintptr) WebPEncodingError { /* vp8l_enc.c:240:26: */ + bp := tls.Alloc(2304) + defer tls.Free(2304) + + var i uint32_t + var j uint32_t + var ind uint32_t + // var remapping [256]uint8_t at bp, 256 + + var cooccurrence uintptr + // var sums [256]Sum at bp+256, 2048 + + var first uint32_t + var last uint32_t + var num_sums uint32_t + // TODO(vrabaud) check whether one color images should use palette or not. + if num_colors <= uint32_t(1) { + return VP8_ENC_OK + } + // Build the co-occurrence matrix. + cooccurrence = WebPSafeCalloc(tls, (uint64(num_colors * num_colors)), uint64(unsafe.Sizeof(uint32_t(0)))) + if cooccurrence == (uintptr(0)) { + return VP8_ENC_ERROR_OUT_OF_MEMORY + } + if CoOccurrenceBuild(tls, pic, palette_sorted, num_colors, cooccurrence) != VP8_ENC_OK { + WebPSafeFree(tls, cooccurrence) + return VP8_ENC_ERROR_OUT_OF_MEMORY + } + + // Initialize the mapping list with the two best indices. + CoOccurrenceFindMax(tls, cooccurrence, num_colors, (bp) /* &remapping */, ((bp) /* &remapping */ + 1)) + + // We need to append and prepend to the list of remapping. To this end, we + // actually define the next start/end of the list as indices in a vector (with + // a wrap around when the end is reached). + first = uint32_t(0) + last = uint32_t(1) + num_sums = (num_colors - uint32_t(2)) // -2 because we know the first two values + if num_sums > uint32_t(0) { + // Initialize the sums with the first two remappings and find the best one + var best_sum uintptr = (bp + 256) /* &sums */ + (*Sum)(unsafe.Pointer(best_sum)).index = uint8(0) + (*Sum)(unsafe.Pointer(best_sum)).sum = 0 + i = uint32_t(0) + j = uint32_t(0) + for ; i < num_colors; i++ { + if (i == uint32_t(*(*uint8_t)(unsafe.Pointer((bp) /* &remapping[0] */)))) || (i == uint32_t(*(*uint8_t)(unsafe.Pointer((bp) /* &remapping[0] */ + 1)))) { + continue + } + (*Sum)(unsafe.Pointer((bp + 256) /* &sums */ + uintptr(j)*8)).index = uint8_t(i) + (*Sum)(unsafe.Pointer((bp + 256) /* &sums */ + uintptr(j)*8)).sum = (*(*uint32_t)(unsafe.Pointer(cooccurrence + uintptr(((i*num_colors)+uint32_t(*(*uint8_t)(unsafe.Pointer((bp) /* &remapping[0] */)))))*4)) + *(*uint32_t)(unsafe.Pointer(cooccurrence + uintptr(((i*num_colors)+uint32_t(*(*uint8_t)(unsafe.Pointer((bp) /* &remapping[0] */ + 1)))))*4))) + if (*Sum)(unsafe.Pointer((bp+256) /* &sums */ +uintptr(j)*8)).sum > (*Sum)(unsafe.Pointer(best_sum)).sum { + best_sum = ((bp + 256) /* &sums */ + uintptr(j)*8) + } + j++ + } + + for num_sums > uint32_t(0) { + var best_index uint8_t = (*Sum)(unsafe.Pointer(best_sum)).index + // Compute delta to know if we need to prepend or append the best index. + var delta int32_t = 0 + var n int32_t = (int32_t(num_colors - num_sums)) + ind = first + j = uint32_t(0) + for ; ((ind + j) % num_colors) != (last + uint32_t(1)); j++ { + var l_j uint16_t = uint16_t(*(*uint8_t)(unsafe.Pointer((bp) /* &remapping[0] */ + uintptr(((ind + j) % num_colors))))) + delta = delta + (((n - 1) - (2 * int32_t(j))) * int32_t(*(*uint32_t)(unsafe.Pointer(cooccurrence + uintptr(((uint32_t(best_index)*num_colors)+uint32_t(l_j)))*4)))) + } + if delta > 0 { + if first == uint32_t(0) { + first = (num_colors - uint32_t(1)) + } else { + first = (first - uint32_t(1)) + } + *(*uint8_t)(unsafe.Pointer((bp) /* &remapping[0] */ + uintptr(first))) = best_index + } else { + last++ + *(*uint8_t)(unsafe.Pointer((bp) /* &remapping[0] */ + uintptr(last))) = best_index + } + // Remove best_sum from sums. + *(*Sum)(unsafe.Pointer(best_sum)) = *(*Sum)(unsafe.Pointer((bp + 256) /* &sums[0] */ + uintptr((num_sums-uint32_t(1)))*8)) + num_sums-- + // Update all the sums and find the best one. + best_sum = (bp + 256) /* &sums */ + for i = uint32_t(0); i < num_sums; i++ { + *(*uint32_t)(unsafe.Pointer((((bp + 256) /* &sums */ + uintptr(i)*8) + 4 /* &.sum */))) += (*(*uint32_t)(unsafe.Pointer(cooccurrence + uintptr(((uint32_t(best_index)*num_colors)+uint32_t((*Sum)(unsafe.Pointer((bp+256) /* &sums */ +uintptr(i)*8)).index)))*4))) + if (*Sum)(unsafe.Pointer((bp+256) /* &sums */ +uintptr(i)*8)).sum > (*Sum)(unsafe.Pointer(best_sum)).sum { + best_sum = ((bp + 256) /* &sums */ + uintptr(i)*8) + } + } + } + } + + WebPSafeFree(tls, cooccurrence) + + // Re-map the palette. + for i = uint32_t(0); i < num_colors; i++ { + *(*uint32_t)(unsafe.Pointer(palette + uintptr(i)*4)) = *(*uint32_t)(unsafe.Pointer(palette_sorted + uintptr(*(*uint8_t)(unsafe.Pointer((bp) /* &remapping[0] */ + uintptr(((first + i) % num_colors)))))*4)) + } + return VP8_ENC_OK +} + +// ----------------------------------------------------------------------------- +// Palette + +// These five modes are evaluated and their respective entropy is computed. +type EntropyIx = uint32 /* vp8l_enc.c:334:3 */ + +type PaletteSorting = uint32 /* vp8l_enc.c:341:3 */ + +type HistoIx = uint32 /* vp8l_enc.c:358:3 */ + +func AddSingleSubGreen(tls *libc.TLS, p int32, r uintptr, b uintptr) { /* vp8l_enc.c:360:13: */ + var green int32 = (p >> 8) // The upper bits are masked away later. + *(*uint32_t)(unsafe.Pointer(r + uintptr((((p>>16)-green)&0xff))*4))++ + *(*uint32_t)(unsafe.Pointer(b + uintptr((((p>>0)-green)&0xff))*4))++ +} + +func AddSingle(tls *libc.TLS, p uint32_t, a uintptr, r uintptr, g uintptr, b uintptr) { /* vp8l_enc.c:366:13: */ + *(*uint32_t)(unsafe.Pointer(a + uintptr(((p>>24)&uint32_t(0xff)))*4))++ + *(*uint32_t)(unsafe.Pointer(r + uintptr(((p>>16)&uint32_t(0xff)))*4))++ + *(*uint32_t)(unsafe.Pointer(g + uintptr(((p>>8)&uint32_t(0xff)))*4))++ + *(*uint32_t)(unsafe.Pointer(b + uintptr(((p>>0)&uint32_t(0xff)))*4))++ +} + +func HashPix(tls *libc.TLS, pix uint32_t) uint32_t { /* vp8l_enc.c:375:29: */ + // Note that masking with 0xffffffffu is for preventing an + // 'unsigned int overflow' warning. Doesn't impact the compiled code. + return (uint32_t((((uint64(uint64_t(pix) + (uint64_t(pix >> 19)))) * 0x39c5fba7) & uint64(0xffffffff)) >> 24)) +} + +func AnalyzeEntropy(tls *libc.TLS, argb uintptr, width int32, height int32, argb_stride int32, use_palette int32, palette_size int32, transform_bits int32, min_entropy_ix uintptr, red_and_blue_always_zero uintptr) int32 { /* vp8l_enc.c:381:12: */ + bp := tls.Alloc(152) + defer tls.Free(152) + + // Allocate histogram set with cache_bits = 0. + var histo uintptr + + if (use_palette != 0) && (palette_size <= 16) { + // In the case of small palettes, we pack 2, 4 or 8 pixels together. In + // practice, small palettes are better than any other transform. + *(*EntropyIx)(unsafe.Pointer(min_entropy_ix)) = kPalette + *(*int32)(unsafe.Pointer(red_and_blue_always_zero)) = 1 + return 1 + } + histo = WebPSafeCalloc(tls, kHistoTotal, (uint64(unsafe.Sizeof(uint32_t(0))) * uint64(256))) + if histo != (uintptr(0)) { + var i int32 + var x int32 + var y int32 + var prev_row uintptr = (uintptr(0)) + var curr_row uintptr = argb + var pix_prev uint32_t = *(*uint32_t)(unsafe.Pointer(argb)) // Skip the first pixel. + for y = 0; y < height; y++ { + for x = 0; x < width; x++ { + var pix uint32_t = *(*uint32_t)(unsafe.Pointer(curr_row + uintptr(x)*4)) + var pix_diff uint32_t = VP8LSubPixels(tls, pix, pix_prev) + pix_prev = pix + if (pix_diff == uint32_t(0)) || ((prev_row != (uintptr(0))) && (pix == *(*uint32_t)(unsafe.Pointer(prev_row + uintptr(x)*4)))) { + continue + } + AddSingle(tls, pix, + (histo), + (histo + 1024*4), + (histo + 512*4), + (histo + 1536*4)) + AddSingle(tls, pix_diff, + (histo + 256*4), + (histo + 1280*4), + (histo + 768*4), + (histo + 1792*4)) + AddSingleSubGreen(tls, int32(pix), + (histo + 2048*4), + (histo + 2560*4)) + AddSingleSubGreen(tls, int32(pix_diff), + (histo + 2304*4), + (histo + 2816*4)) + { + // Approximate the palette by the entropy of the multiplicative hash. + var hash uint32_t = HashPix(tls, pix) + *(*uint32_t)(unsafe.Pointer(histo + uintptr(((uint32_t(kHistoPalette*256))+hash))*4))++ + + } + } + prev_row = curr_row + curr_row += 4 * (uintptr(argb_stride)) + } + { + // var entropy_comp [13]float64 at bp, 104 + + // var entropy [6]float64 at bp+104, 48 + + var k int32 + var last_mode_to_analyze int32 + if use_palette != 0 { + last_mode_to_analyze = kPalette + } else { + last_mode_to_analyze = kSpatialSubGreen + } + var j int32 + // Let's add one zero to the predicted histograms. The zeros are removed + // too efficiently by the pix_diff == 0 comparison, at least one of the + // zeros is likely to exist. + *(*uint32_t)(unsafe.Pointer(histo + 2304*4))++ + *(*uint32_t)(unsafe.Pointer(histo + 2816*4))++ + *(*uint32_t)(unsafe.Pointer(histo + 1280*4))++ + *(*uint32_t)(unsafe.Pointer(histo + 768*4))++ + *(*uint32_t)(unsafe.Pointer(histo + 1792*4))++ + *(*uint32_t)(unsafe.Pointer(histo + 256*4))++ + + for j = 0; j < kHistoTotal; j++ { + *(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + uintptr(j)*8)) = VP8LBitsEntropy(tls, (histo + uintptr((j*256))*4), 256) + } + *(*float64)(unsafe.Pointer((bp + 104) /* &entropy[0] */)) = (((*(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */)) + *(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + 4*8))) + *(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + 2*8))) + *(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + 6*8))) + *(*float64)(unsafe.Pointer((bp + 104) /* &entropy[0] */ + 1*8)) = (((*(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + 1*8)) + *(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + 5*8))) + *(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + 3*8))) + *(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + 7*8))) + *(*float64)(unsafe.Pointer((bp + 104) /* &entropy[0] */ + 2*8)) = (((*(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */)) + *(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + 8*8))) + *(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + 2*8))) + *(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + 10*8))) + *(*float64)(unsafe.Pointer((bp + 104) /* &entropy[0] */ + 3*8)) = (((*(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + 1*8)) + *(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + 9*8))) + *(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + 3*8))) + *(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + 11*8))) + *(*float64)(unsafe.Pointer((bp + 104) /* &entropy[0] */ + 4*8)) = *(*float64)(unsafe.Pointer((bp) /* &entropy_comp[0] */ + 12*8)) + + // When including transforms, there is an overhead in bits from + // storing them. This overhead is small but matters for small images. + // For spatial, there are 14 transformations. + *(*float64)(unsafe.Pointer(((bp + 104) /* &entropy */ + 1*8))) += (float64((float32(VP8LSubSampleSize(tls, uint32(width), uint32(transform_bits)) * VP8LSubSampleSize(tls, uint32(height), uint32(transform_bits)))) * VP8LFastLog2(tls, uint32(14)))) + // For color transforms: 24 as only 3 channels are considered in a + // ColorTransformElement. + *(*float64)(unsafe.Pointer(((bp + 104) /* &entropy */ + 3*8))) += (float64((float32(VP8LSubSampleSize(tls, uint32(width), uint32(transform_bits)) * VP8LSubSampleSize(tls, uint32(height), uint32(transform_bits)))) * VP8LFastLog2(tls, uint32(24)))) + // For palettes, add the cost of storing the palette. + // We empirically estimate the cost of a compressed entry as 8 bits. + // The palette is differential-coded when compressed hence a much + // lower cost than sizeof(uint32_t)*8. + *(*float64)(unsafe.Pointer(((bp + 104) /* &entropy */ + 4*8))) += (float64(palette_size * 8)) + + *(*EntropyIx)(unsafe.Pointer(min_entropy_ix)) = kDirect + for k = (kDirect + 1); k <= last_mode_to_analyze; k++ { + if *(*float64)(unsafe.Pointer((bp + 104) /* &entropy[0] */ + uintptr(*(*EntropyIx)(unsafe.Pointer(min_entropy_ix)))*8)) > *(*float64)(unsafe.Pointer((bp + 104) /* &entropy[0] */ + uintptr(k)*8)) { + *(*EntropyIx)(unsafe.Pointer(min_entropy_ix)) = EntropyIx(k) + } + } + + *(*int32)(unsafe.Pointer(red_and_blue_always_zero)) = 1 + // Let's check if the histogram of the chosen entropy mode has + // non-zero red and blue values. If all are zero, we can later skip + // the cross color optimization. + { + var red_histo uintptr = (histo + uintptr((256*int32(*(*uint8_t)(unsafe.Pointer((uintptr(unsafe.Pointer(&kHistoPairs)) + uintptr(*(*EntropyIx)(unsafe.Pointer(min_entropy_ix)))*2))))))*4) + var blue_histo uintptr = (histo + uintptr((256*int32(*(*uint8_t)(unsafe.Pointer((uintptr(unsafe.Pointer(&kHistoPairs)) + uintptr(*(*EntropyIx)(unsafe.Pointer(min_entropy_ix)))*2) + 1)))))*4) + for i = 1; i < 256; i++ { + if (*(*uint32_t)(unsafe.Pointer(red_histo + uintptr(i)*4)) | *(*uint32_t)(unsafe.Pointer(blue_histo + uintptr(i)*4))) != uint32_t(0) { + *(*int32)(unsafe.Pointer(red_and_blue_always_zero)) = 0 + break + } + } + + } + + } + WebPSafeFree(tls, histo) + return 1 + } else { + return 0 + } + return int32(0) +} + +var kHistoPairs = [5][2]uint8_t{ + [2]uint8_t{kHistoRed, kHistoBlue}, + [2]uint8_t{kHistoRedPred, kHistoBluePred}, + [2]uint8_t{kHistoRedSubGreen, kHistoBlueSubGreen}, + [2]uint8_t{kHistoRedPredSubGreen, kHistoBluePredSubGreen}, + [2]uint8_t{kHistoRed, kHistoBlue}, +} /* vp8l_enc.c:502:30 */ + +func GetHistoBits(tls *libc.TLS, method int32, use_palette int32, width int32, height int32) int32 { /* vp8l_enc.c:528:12: */ + // Make tile size a function of encoding method (Range: 0 to 6). + var histo_bits int32 = ((func() int32 { + if use_palette != 0 { + return 9 + } + return 7 + }()) - method) + for 1 != 0 { + var huff_image_size int32 = (int32(VP8LSubSampleSize(tls, uint32(width), uint32(histo_bits)) * VP8LSubSampleSize(tls, uint32(height), uint32(histo_bits)))) + if huff_image_size <= 2600 { + break + } + histo_bits++ + } + if histo_bits < 2 { + return 2 + } + if histo_bits > 9 { + return 9 + } + return histo_bits +} + +func GetTransformBits(tls *libc.TLS, method int32, histo_bits int32) int32 { /* vp8l_enc.c:541:12: */ + var max_transform_bits int32 + if method < 4 { + max_transform_bits = 6 + } else { + if method > 4 { + max_transform_bits = 4 + } else { + max_transform_bits = 5 + } + } + var res int32 + if histo_bits > max_transform_bits { + res = max_transform_bits + } else { + res = histo_bits + } + + return res +} + +// Set of parameters to be used in each iteration of the cruncher. +type CrunchSubConfig = struct { + lz77_ int32 + do_no_cache_ int32 +} /* vp8l_enc.c:554:3 */ +type CrunchConfig = struct { + entropy_idx_ int32 + palette_sorting_type_ PaletteSorting + sub_configs_ [2]CrunchSubConfig + sub_configs_size_ int32 +} /* vp8l_enc.c:560:3 */ + +// +2 because we add a palette sorting configuration for kPalette and +// kPaletteAndSpatial. + +func EncoderAnalyze(tls *libc.TLS, enc uintptr, crunch_configs uintptr, crunch_configs_size uintptr, red_and_blue_always_zero uintptr) int32 { /* vp8l_enc.c:566:12: */ + bp := tls.Alloc(4) + defer tls.Free(4) + + var pic uintptr = (*VP8LEncoder)(unsafe.Pointer(enc)).pic_ + var width int32 = (*WebPPicture)(unsafe.Pointer(pic)).width + var height int32 = (*WebPPicture)(unsafe.Pointer(pic)).height + var config uintptr = (*VP8LEncoder)(unsafe.Pointer(enc)).config_ + var method int32 = (*WebPConfig)(unsafe.Pointer(config)).method + var low_effort int32 = (libc.Bool32((*WebPConfig)(unsafe.Pointer(config)).method == 0)) + var i int32 + var use_palette int32 + var n_lz77s int32 + // If set to 0, analyze the cache with the computed cache value. If 1, also + // analyze with no-cache. + var do_no_cache int32 = 0 + + // Check whether a palette is possible. + (*VP8LEncoder)(unsafe.Pointer(enc)).palette_size_ = WebPGetColorPalette(tls, pic, (enc + 1124 /* &.palette_sorted_ */)) + use_palette = (libc.Bool32((*VP8LEncoder)(unsafe.Pointer(enc)).palette_size_ <= 256)) + if !(use_palette != 0) { + (*VP8LEncoder)(unsafe.Pointer(enc)).palette_size_ = 0 + } else { + libc.Xqsort(tls, (enc + 1124 /* &.palette_sorted_ */), uint64((*VP8LEncoder)(unsafe.Pointer(enc)).palette_size_), + uint64(unsafe.Sizeof(uint32_t(0))), *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{PaletteCompareColorsForQsort}))) + } + + // Empirical bit sizes. + (*VP8LEncoder)(unsafe.Pointer(enc)).histo_bits_ = GetHistoBits(tls, method, use_palette, + (*WebPPicture)(unsafe.Pointer(pic)).width, (*WebPPicture)(unsafe.Pointer(pic)).height) + (*VP8LEncoder)(unsafe.Pointer(enc)).transform_bits_ = GetTransformBits(tls, method, (*VP8LEncoder)(unsafe.Pointer(enc)).histo_bits_) + + if low_effort != 0 { + // AnalyzeEntropy is somewhat slow. + (*CrunchConfig)(unsafe.Pointer(crunch_configs)).entropy_idx_ = func() int32 { + if use_palette != 0 { + return kPalette + } + return kSpatialSubGreen + }() + (*CrunchConfig)(unsafe.Pointer(crunch_configs)).palette_sorting_type_ = func() uint32 { + if use_palette != 0 { + return kSortedDefault + } + return kUnusedPalette + }() + n_lz77s = 1 + *(*int32)(unsafe.Pointer(crunch_configs_size)) = 1 + } else { + // var min_entropy_ix EntropyIx at bp, 4 + + // Try out multiple LZ77 on images with few colors. + if ((*VP8LEncoder)(unsafe.Pointer(enc)).palette_size_ > 0) && ((*VP8LEncoder)(unsafe.Pointer(enc)).palette_size_ <= 16) { + n_lz77s = 2 + } else { + n_lz77s = 1 + } + if !(AnalyzeEntropy(tls, (*WebPPicture)(unsafe.Pointer(pic)).argb, width, height, (*WebPPicture)(unsafe.Pointer(pic)).argb_stride, use_palette, + (*VP8LEncoder)(unsafe.Pointer(enc)).palette_size_, (*VP8LEncoder)(unsafe.Pointer(enc)).transform_bits_, + (bp) /* &min_entropy_ix */, red_and_blue_always_zero) != 0) { + return 0 + } + if (method == 6) && ((*WebPConfig)(unsafe.Pointer(config)).quality == float32(100)) { + do_no_cache = 1 + // Go brute force on all transforms. + *(*int32)(unsafe.Pointer(crunch_configs_size)) = 0 + for i = 0; i < kNumEntropyIx; i++ { + // We can only apply kPalette or kPaletteAndSpatial if we can indeed use + // a palette. + if ((i != kPalette) && (i != kPaletteAndSpatial)) || (use_palette != 0) { + + (*CrunchConfig)(unsafe.Pointer(crunch_configs + uintptr((*(*int32)(unsafe.Pointer(crunch_configs_size))))*28)).entropy_idx_ = i + if (use_palette != 0) && ((i == kPalette) || (i == kPaletteAndSpatial)) { + (*CrunchConfig)(unsafe.Pointer(crunch_configs + uintptr((*(*int32)(unsafe.Pointer(crunch_configs_size))))*28)).palette_sorting_type_ = kMinimizeDelta + *(*int32)(unsafe.Pointer(crunch_configs_size))++ + // Also add modified Zeng's method. + (*CrunchConfig)(unsafe.Pointer(crunch_configs + uintptr((*(*int32)(unsafe.Pointer(crunch_configs_size))))*28)).entropy_idx_ = i + (*CrunchConfig)(unsafe.Pointer(crunch_configs + uintptr((*(*int32)(unsafe.Pointer(crunch_configs_size))))*28)).palette_sorting_type_ = kModifiedZeng + } else { + (*CrunchConfig)(unsafe.Pointer(crunch_configs + uintptr((*(*int32)(unsafe.Pointer(crunch_configs_size))))*28)).palette_sorting_type_ = kUnusedPalette + } + *(*int32)(unsafe.Pointer(crunch_configs_size))++ + } + } + } else { + // Only choose the guessed best transform. + *(*int32)(unsafe.Pointer(crunch_configs_size)) = 1 + (*CrunchConfig)(unsafe.Pointer(crunch_configs)).entropy_idx_ = int32(*(*EntropyIx)(unsafe.Pointer(bp /* min_entropy_ix */))) + (*CrunchConfig)(unsafe.Pointer(crunch_configs)).palette_sorting_type_ = func() uint32 { + if use_palette != 0 { + return kMinimizeDelta + } + return kUnusedPalette + }() + if ((*WebPConfig)(unsafe.Pointer(config)).quality >= float32(75)) && (method == 5) { + // Test with and without color cache. + do_no_cache = 1 + // If we have a palette, also check in combination with spatial. + if *(*EntropyIx)(unsafe.Pointer(bp /* min_entropy_ix */)) == kPalette { + *(*int32)(unsafe.Pointer(crunch_configs_size)) = 2 + (*CrunchConfig)(unsafe.Pointer(crunch_configs + 1*28)).entropy_idx_ = kPaletteAndSpatial + (*CrunchConfig)(unsafe.Pointer(crunch_configs + 1*28)).palette_sorting_type_ = kMinimizeDelta + } + } + } + } + // Fill in the different LZ77s. + + for i = 0; i < *(*int32)(unsafe.Pointer(crunch_configs_size)); i++ { + var j int32 + for j = 0; j < n_lz77s; j++ { + + (*CrunchSubConfig)(unsafe.Pointer(((crunch_configs + uintptr(i)*28) + 8 /* &.sub_configs_ */) + uintptr(j)*8)).lz77_ = func() int32 { + if j == 0 { + return (kLZ77Standard | kLZ77RLE) + } + return kLZ77Box + }() + (*CrunchSubConfig)(unsafe.Pointer(((crunch_configs + uintptr(i)*28) + 8 /* &.sub_configs_ */) + uintptr(j)*8)).do_no_cache_ = do_no_cache + } + (*CrunchConfig)(unsafe.Pointer(crunch_configs + uintptr(i)*28)).sub_configs_size_ = n_lz77s + } + return 1 +} + +func EncoderInit(tls *libc.TLS, enc uintptr) int32 { /* vp8l_enc.c:673:12: */ + var pic uintptr = (*VP8LEncoder)(unsafe.Pointer(enc)).pic_ + var width int32 = (*WebPPicture)(unsafe.Pointer(pic)).width + var height int32 = (*WebPPicture)(unsafe.Pointer(pic)).height + var pix_cnt int32 = (width * height) + // we round the block size up, so we're guaranteed to have + // at most MAX_REFS_BLOCK_PER_IMAGE blocks used: + var refs_block_size int32 = (((pix_cnt - 1) / 16) + 1) + var i int32 + if !(VP8LHashChainInit(tls, (enc+2312 /* &.hash_chain_ */), pix_cnt) != 0) { + return 0 + } + + for i = 0; i < 4; i++ { + VP8LBackwardRefsInit(tls, ((enc + 2152 /* &.refs_ */) + uintptr(i)*40), refs_block_size) + } + + return 1 +} + +// Returns false in case of memory error. +func GetHuffBitLengthsAndCodes(tls *libc.TLS, histogram_image uintptr, huffman_codes uintptr) int32 { /* vp8l_enc.c:690:12: */ + var i int32 + var k int32 + var ok int32 + var total_length_size uint64_t + var mem_buf uintptr + var histogram_image_size int32 + var max_num_symbols int32 + var buf_rle uintptr + var huff_tree uintptr + var num_symbols int32 + var histo uintptr + var codes uintptr + var bit_length int32 + var codes1 uintptr + var lengths uintptr + var codes2 uintptr + var histo1 uintptr + ok = 0 + total_length_size = uint64(0) + mem_buf = (uintptr(0)) + histogram_image_size = (*VP8LHistogramSet)(unsafe.Pointer(histogram_image)).size + max_num_symbols = 0 + buf_rle = (uintptr(0)) + huff_tree = (uintptr(0)) + + // Iterate over all histograms and get the aggregate number of codes used. + i = 0 +__1: + if !(i < histogram_image_size) { + goto __3 + } + histo = *(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(histogram_image)).histograms + uintptr(i)*8)) + codes = (huffman_codes + uintptr((5*i))*24) + + k = 0 +__4: + if !(k < 5) { + goto __6 + } + if k == 0 { + num_symbols = VP8LHistogramNumCodes(tls, (*VP8LHistogram)(unsafe.Pointer(histo)).palette_code_bits_) + } else { + if k == 4 { + num_symbols = 40 + } else { + num_symbols = 256 + } + } + (*HuffmanTreeCode)(unsafe.Pointer(codes + uintptr(k)*24)).num_symbols = num_symbols + total_length_size = total_length_size + (uint64_t(num_symbols)) + goto __5 +__5: + k++ + goto __4 + goto __6 +__6: + ; + goto __2 +__2: + i++ + goto __1 + goto __3 +__3: + ; + + // Allocate and Set Huffman codes. + + mem_buf = WebPSafeCalloc(tls, total_length_size, + (uint64(unsafe.Sizeof(uint8_t(0))) + uint64(unsafe.Sizeof(uint16_t(0))))) + if !(mem_buf == (uintptr(0))) { + goto __7 + } + goto End +__7: + ; + + codes1 = mem_buf + lengths = (codes1 + uintptr(total_length_size)*2) + i = 0 +__8: + if !(i < (5 * histogram_image_size)) { + goto __10 + } + bit_length = (*HuffmanTreeCode)(unsafe.Pointer(huffman_codes + uintptr(i)*24)).num_symbols + (*HuffmanTreeCode)(unsafe.Pointer(huffman_codes + uintptr(i)*24)).codes = codes1 + (*HuffmanTreeCode)(unsafe.Pointer(huffman_codes + uintptr(i)*24)).code_lengths = lengths + codes1 += 2 * (uintptr(bit_length)) + lengths += uintptr(bit_length) + if !(max_num_symbols < bit_length) { + goto __11 + } + max_num_symbols = bit_length +__11: + ; + goto __9 +__9: + i++ + goto __8 + goto __10 +__10: + ; + + buf_rle = WebPSafeMalloc(tls, 1, uint64(max_num_symbols)) + huff_tree = WebPSafeMalloc(tls, (uint64(3 * uint64(max_num_symbols))), + uint64(unsafe.Sizeof(HuffmanTree{}))) + if !((buf_rle == (uintptr(0))) || (huff_tree == (uintptr(0)))) { + goto __12 + } + goto End +__12: + ; + + // Create Huffman trees. + i = 0 +__13: + if !(i < histogram_image_size) { + goto __15 + } + codes2 = (huffman_codes + uintptr((5*i))*24) + histo1 = *(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(histogram_image)).histograms + uintptr(i)*8)) + VP8LCreateHuffmanTree(tls, (*VP8LHistogram)(unsafe.Pointer(histo1)).literal_, 15, buf_rle, huff_tree, (codes2 + uintptr(0)*24)) + VP8LCreateHuffmanTree(tls, (histo1 + 8 /* &.red_ */), 15, buf_rle, huff_tree, (codes2 + uintptr(1)*24)) + VP8LCreateHuffmanTree(tls, (histo1 + 1032 /* &.blue_ */), 15, buf_rle, huff_tree, (codes2 + uintptr(2)*24)) + VP8LCreateHuffmanTree(tls, (histo1 + 2056 /* &.alpha_ */), 15, buf_rle, huff_tree, (codes2 + uintptr(3)*24)) + VP8LCreateHuffmanTree(tls, (histo1 + 3080 /* &.distance_ */), 15, buf_rle, huff_tree, (codes2 + uintptr(4)*24)) + goto __14 +__14: + i++ + goto __13 + goto __15 +__15: + ; + ok = 1 +End: + WebPSafeFree(tls, huff_tree) + WebPSafeFree(tls, buf_rle) + if !(!(ok != 0)) { + goto __16 + } + WebPSafeFree(tls, mem_buf) + libc.Xmemset(tls, huffman_codes, 0, ((uint64(5 * histogram_image_size)) * uint64(unsafe.Sizeof(HuffmanTreeCode{})))) +__16: + ; + return ok +} + +func StoreHuffmanTreeOfHuffmanTreeToBitMask(tls *libc.TLS, bw uintptr, code_length_bitdepth uintptr) { /* vp8l_enc.c:764:13: */ + var i int32 + // Throw away trailing zeros: + var codes_to_store int32 = 19 + for ; codes_to_store > 4; codes_to_store-- { + if int32(*(*uint8_t)(unsafe.Pointer(code_length_bitdepth + uintptr(kStorageOrder[(codes_to_store-1)])))) != 0 { + break + } + } + VP8LPutBits(tls, bw, (uint32(codes_to_store - 4)), 4) + for i = 0; i < codes_to_store; i++ { + VP8LPutBits(tls, bw, uint32(*(*uint8_t)(unsafe.Pointer(code_length_bitdepth + uintptr(kStorageOrder[i])))), 3) + } +} + +var kStorageOrder = [19]uint8_t{ + uint8_t(17), uint8_t(18), uint8_t(0), uint8_t(1), uint8_t(2), uint8_t(3), uint8_t(4), uint8_t(5), uint8_t(16), uint8_t(6), uint8_t(7), uint8_t(8), uint8_t(9), uint8_t(10), uint8_t(11), uint8_t(12), uint8_t(13), uint8_t(14), uint8_t(15), +} /* vp8l_enc.c:769:24 */ + +func ClearHuffmanTreeIfOnlyOneSymbol(tls *libc.TLS, huffman_code uintptr) { /* vp8l_enc.c:786:13: */ + var k int32 + var count int32 = 0 + for k = 0; k < (*HuffmanTreeCode)(unsafe.Pointer(huffman_code)).num_symbols; k++ { + if int32(*(*uint8_t)(unsafe.Pointer((*HuffmanTreeCode)(unsafe.Pointer(huffman_code)).code_lengths + uintptr(k)))) != 0 { + count++ + if count > 1 { + return + } + } + } + for k = 0; k < (*HuffmanTreeCode)(unsafe.Pointer(huffman_code)).num_symbols; k++ { + *(*uint8_t)(unsafe.Pointer((*HuffmanTreeCode)(unsafe.Pointer(huffman_code)).code_lengths + uintptr(k))) = uint8_t(0) + *(*uint16_t)(unsafe.Pointer((*HuffmanTreeCode)(unsafe.Pointer(huffman_code)).codes + uintptr(k)*2)) = uint16_t(0) + } +} + +func StoreHuffmanTreeToBitMask(tls *libc.TLS, bw uintptr, tokens uintptr, num_tokens int32, huffman_code uintptr) { /* vp8l_enc.c:802:13: */ + var i int32 + for i = 0; i < num_tokens; i++ { + var ix int32 = int32((*HuffmanTreeToken)(unsafe.Pointer(tokens + uintptr(i)*2)).code) + var extra_bits int32 = int32((*HuffmanTreeToken)(unsafe.Pointer(tokens + uintptr(i)*2)).extra_bits) + VP8LPutBits(tls, bw, uint32(*(*uint16_t)(unsafe.Pointer((*HuffmanTreeCode)(unsafe.Pointer(huffman_code)).codes + uintptr(ix)*2))), int32(*(*uint8_t)(unsafe.Pointer((*HuffmanTreeCode)(unsafe.Pointer(huffman_code)).code_lengths + uintptr(ix))))) + switch ix { + case 16: + VP8LPutBits(tls, bw, uint32(extra_bits), 2) + break + case 17: + VP8LPutBits(tls, bw, uint32(extra_bits), 3) + break + case 18: + VP8LPutBits(tls, bw, uint32(extra_bits), 7) + break + } + } +} + +// 'huff_tree' and 'tokens' are pre-alloacted buffers. +func StoreFullHuffmanCode(tls *libc.TLS, bw uintptr, huff_tree uintptr, tokens uintptr, tree uintptr) { /* vp8l_enc.c:826:13: */ + bp := tls.Alloc(184) + defer tls.Free(184) + + *(*[19]uint8_t)(unsafe.Pointer(bp /* code_length_bitdepth */)) = [19]uint8_t{0: uint8_t(0)} + *(*[19]uint16_t)(unsafe.Pointer(bp + 20 /* code_length_bitdepth_symbols */)) = [19]uint16_t{0: uint16_t(0)} + var max_tokens int32 = (*HuffmanTreeCode)(unsafe.Pointer(tree)).num_symbols + var num_tokens int32 + // var huffman_code HuffmanTreeCode at bp+160, 24 + + (*HuffmanTreeCode)(unsafe.Pointer(bp + 160 /* &huffman_code */)).num_symbols = 19 + (*HuffmanTreeCode)(unsafe.Pointer(bp + 160 /* &huffman_code */)).code_lengths = (bp) /* &code_length_bitdepth[0] */ + (*HuffmanTreeCode)(unsafe.Pointer(bp + 160 /* &huffman_code */)).codes = (bp + 20) /* &code_length_bitdepth_symbols[0] */ + + VP8LPutBits(tls, bw, uint32(0), 1) + num_tokens = VP8LCreateCompressedHuffmanTree(tls, tree, tokens, max_tokens) + { + *(*[19]uint32_t)(unsafe.Pointer(bp + 60 /* histogram */)) = [19]uint32_t{0: uint32_t(0)} + *(*[19]uint8_t)(unsafe.Pointer(bp + 136 /* buf_rle */)) = [19]uint8_t{0: uint8_t(0)} + var i int32 + for i = 0; i < num_tokens; i++ { + *(*uint32_t)(unsafe.Pointer((bp + 60) /* &histogram[0] */ + uintptr((*HuffmanTreeToken)(unsafe.Pointer(tokens+uintptr(i)*2)).code)*4))++ + } + + VP8LCreateHuffmanTree(tls, (bp + 60) /* &histogram[0] */, 7, (bp + 136) /* &buf_rle[0] */, huff_tree, (bp + 160) /* &huffman_code */) + + } + + StoreHuffmanTreeOfHuffmanTreeToBitMask(tls, bw, (bp) /* &code_length_bitdepth[0] */) + ClearHuffmanTreeIfOnlyOneSymbol(tls, (bp + 160) /* &huffman_code */) + { + var trailing_zero_bits int32 = 0 + var trimmed_length int32 = num_tokens + var write_trimmed_length int32 + var length int32 + var i int32 = num_tokens + for libc.PostDecInt32(&i, 1) > 0 { + var ix int32 = int32((*HuffmanTreeToken)(unsafe.Pointer(tokens + uintptr(i)*2)).code) + if ((ix == 0) || (ix == 17)) || (ix == 18) { + trimmed_length-- // discount trailing zeros + trailing_zero_bits = trailing_zero_bits + (int32(*(*uint8_t)(unsafe.Pointer((bp) /* &code_length_bitdepth[0] */ + uintptr(ix))))) + if ix == 17 { + trailing_zero_bits = trailing_zero_bits + (3) + } else if ix == 18 { + trailing_zero_bits = trailing_zero_bits + (7) + } + } else { + break + } + } + write_trimmed_length = (libc.Bool32((trimmed_length > 1) && (trailing_zero_bits > 12))) + if write_trimmed_length != 0 { + length = trimmed_length + } else { + length = num_tokens + } + VP8LPutBits(tls, bw, uint32(write_trimmed_length), 1) + if write_trimmed_length != 0 { + if trimmed_length == 2 { + VP8LPutBits(tls, bw, uint32(0), (3 + 2)) // nbitpairs=1, trimmed_length=2 + } else { + var nbits int32 = BitsLog2Floor(tls, (uint32(trimmed_length - 2))) + var nbitpairs int32 = ((nbits / 2) + 1) + + VP8LPutBits(tls, bw, (uint32(nbitpairs - 1)), 3) + VP8LPutBits(tls, bw, (uint32(trimmed_length - 2)), (nbitpairs * 2)) + } + } + StoreHuffmanTreeToBitMask(tls, bw, tokens, length, (bp + 160) /* &huffman_code */) + + } +} + +// 'huff_tree' and 'tokens' are pre-alloacted buffers. +func StoreHuffmanCode(tls *libc.TLS, bw uintptr, huff_tree uintptr, tokens uintptr, huffman_code uintptr) { /* vp8l_enc.c:894:13: */ + bp := tls.Alloc(8) + defer tls.Free(8) + + var i int32 + var count int32 = 0 + *(*[2]int32)(unsafe.Pointer(bp /* symbols */)) = [2]int32{0, 0} + var kMaxBits int32 = 8 + var kMaxSymbol int32 = (int32(1) << kMaxBits) + + // Check whether it's a small tree. + for i = 0; (i < (*HuffmanTreeCode)(unsafe.Pointer(huffman_code)).num_symbols) && (count < 3); i++ { + if int32(*(*uint8_t)(unsafe.Pointer((*HuffmanTreeCode)(unsafe.Pointer(huffman_code)).code_lengths + uintptr(i)))) != 0 { + if count < 2 { + *(*int32)(unsafe.Pointer((bp) /* &symbols[0] */ + uintptr(count)*4)) = i + } + count++ + } + } + + if count == 0 { // emit minimal tree for empty cases + // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0 + VP8LPutBits(tls, bw, uint32(0x01), 4) + } else if ((count <= 2) && (*(*int32)(unsafe.Pointer((bp) /* &symbols[0] */)) < kMaxSymbol)) && (*(*int32)(unsafe.Pointer((bp) /* &symbols[0] */ + 1*4)) < kMaxSymbol) { + VP8LPutBits(tls, bw, uint32(1), 1) // Small tree marker to encode 1 or 2 symbols. + VP8LPutBits(tls, bw, (uint32(count - 1)), 1) + if *(*int32)(unsafe.Pointer((bp) /* &symbols[0] */)) <= 1 { + VP8LPutBits(tls, bw, uint32(0), 1) // Code bit for small (1 bit) symbol value. + VP8LPutBits(tls, bw, uint32(*(*int32)(unsafe.Pointer((bp) /* &symbols[0] */))), 1) + } else { + VP8LPutBits(tls, bw, uint32(1), 1) + VP8LPutBits(tls, bw, uint32(*(*int32)(unsafe.Pointer((bp) /* &symbols[0] */))), 8) + } + if count == 2 { + VP8LPutBits(tls, bw, uint32(*(*int32)(unsafe.Pointer((bp) /* &symbols[0] */ + 1*4))), 8) + } + } else { + StoreFullHuffmanCode(tls, bw, huff_tree, tokens, huffman_code) + } +} + +func WriteHuffmanCode(tls *libc.TLS, bw uintptr, code uintptr, code_index int32) { /* vp8l_enc.c:933:25: */ + var depth int32 = int32(*(*uint8_t)(unsafe.Pointer((*HuffmanTreeCode)(unsafe.Pointer(code)).code_lengths + uintptr(code_index)))) + var symbol int32 = int32(*(*uint16_t)(unsafe.Pointer((*HuffmanTreeCode)(unsafe.Pointer(code)).codes + uintptr(code_index)*2))) + VP8LPutBits(tls, bw, uint32(symbol), depth) +} + +func WriteHuffmanCodeWithExtraBits(tls *libc.TLS, bw uintptr, code uintptr, code_index int32, bits int32, n_bits int32) { /* vp8l_enc.c:941:25: */ + var depth int32 = int32(*(*uint8_t)(unsafe.Pointer((*HuffmanTreeCode)(unsafe.Pointer(code)).code_lengths + uintptr(code_index)))) + var symbol int32 = int32(*(*uint16_t)(unsafe.Pointer((*HuffmanTreeCode)(unsafe.Pointer(code)).codes + uintptr(code_index)*2))) + VP8LPutBits(tls, bw, (uint32((bits << depth) | symbol)), (depth + n_bits)) +} + +func StoreImageToBitMask(tls *libc.TLS, bw uintptr, width int32, histo_bits int32, refs uintptr, histogram_symbols uintptr, huffman_codes uintptr) WebPEncodingError { /* vp8l_enc.c:952:26: */ + bp := tls.Alloc(36) + defer tls.Free(36) + + var histo_xsize int32 + if histo_bits != 0 { + histo_xsize = int32(VP8LSubSampleSize(tls, uint32(width), uint32(histo_bits))) + } else { + histo_xsize = 1 + } + var tile_mask int32 + if histo_bits == 0 { + tile_mask = 0 + } else { + tile_mask = -(int32(1) << histo_bits) + } + // x and y trace the position in the image. + var x int32 = 0 + var y int32 = 0 + var tile_x int32 = (x & tile_mask) + var tile_y int32 = (y & tile_mask) + var histogram_ix int32 = int32(*(*uint16_t)(unsafe.Pointer(histogram_symbols))) + var codes uintptr = (huffman_codes + uintptr((5*histogram_ix))*24) + *(*VP8LRefsCursor)(unsafe.Pointer(bp /* c */)) = VP8LRefsCursorInit(tls, refs) + for VP8LRefsCursorOk(tls, (bp) /* &c */) != 0 { + var v uintptr = (*VP8LRefsCursor)(unsafe.Pointer(bp /* &c */)).cur_pos + if (tile_x != (x & tile_mask)) || (tile_y != (y & tile_mask)) { + tile_x = (x & tile_mask) + tile_y = (y & tile_mask) + histogram_ix = int32(*(*uint16_t)(unsafe.Pointer(histogram_symbols + uintptr((((y>>histo_bits)*histo_xsize)+(x>>histo_bits)))*2))) + codes = (huffman_codes + uintptr((5*histogram_ix))*24) + } + if PixOrCopyIsLiteral(tls, v) != 0 { + var k int32 + for k = 0; k < 4; k++ { + var code int32 = int32(PixOrCopyLiteral(tls, v, int32(order[k]))) + WriteHuffmanCode(tls, bw, (codes + uintptr(k)*24), code) + } + } else if PixOrCopyIsCacheIdx(tls, v) != 0 { + var code int32 = int32(PixOrCopyCacheIdx(tls, v)) + var literal_ix int32 = ((256 + 24) + code) + WriteHuffmanCode(tls, bw, codes, literal_ix) + } else { + // var bits int32 at bp+32, 4 + + // var n_bits int32 at bp+28, 4 + + // var code int32 at bp+24, 4 + + var distance int32 = int32(PixOrCopyDistance(tls, v)) + VP8LPrefixEncode(tls, int32((*PixOrCopy)(unsafe.Pointer(v)).len), (bp + 24) /* &code */, (bp + 28) /* &n_bits */, (bp + 32) /* &bits */) + WriteHuffmanCodeWithExtraBits(tls, bw, codes, (256 + *(*int32)(unsafe.Pointer(bp + 24 /* code */))), *(*int32)(unsafe.Pointer(bp + 32 /* bits */)), *(*int32)(unsafe.Pointer(bp + 28 /* n_bits */))) + + // Don't write the distance with the extra bits code since + // the distance can be up to 18 bits of extra bits, and the prefix + // 15 bits, totaling to 33, and our PutBits only supports up to 32 bits. + VP8LPrefixEncode(tls, distance, (bp + 24) /* &code */, (bp + 28) /* &n_bits */, (bp + 32) /* &bits */) + WriteHuffmanCode(tls, bw, (codes + uintptr(4)*24), *(*int32)(unsafe.Pointer(bp + 24 /* code */))) + VP8LPutBits(tls, bw, uint32(*(*int32)(unsafe.Pointer(bp + 32 /* bits */))), *(*int32)(unsafe.Pointer(bp + 28 /* n_bits */))) + } + x = int32(uint32_t(x) + (PixOrCopyLength(tls, v))) + for x >= width { + x = x - (width) + y++ + } + VP8LRefsCursorNext(tls, (bp) /* &c */) + } + if (*VP8LBitWriter)(unsafe.Pointer(bw)).error_ != 0 { + return VP8_ENC_ERROR_OUT_OF_MEMORY + } + return VP8_ENC_OK +} + +var order = [4]uint8_t{uint8_t(1), uint8_t(2), uint8_t(0), uint8_t(3)} /* vp8l_enc.c:977:28 */ + +// Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31 +func EncodeImageNoHuffman(tls *libc.TLS, bw uintptr, argb uintptr, hash_chain uintptr, refs_array uintptr, width int32, height int32, quality int32, low_effort int32) WebPEncodingError { /* vp8l_enc.c:1013:26: */ + bp := tls.Alloc(130) + defer tls.Free(130) + + var i int32 + var max_tokens int32 + var err WebPEncodingError + var refs uintptr + var tokens uintptr + // var huffman_codes [5]HuffmanTreeCode at bp+8, 120 + + // var histogram_symbols [1]uint16_t at bp+128, 2 + // only one tree, one symbol + // var cache_bits int32 at bp, 4 + + var histogram_image uintptr + var huff_tree uintptr + var codes uintptr + var codes1 uintptr + max_tokens = 0 + err = VP8_ENC_OK + tokens = (uintptr(0)) + *(*[5]HuffmanTreeCode)(unsafe.Pointer(bp + 8 /* huffman_codes */)) = [5]HuffmanTreeCode{0: HuffmanTreeCode{}} + *(*[1]uint16_t)(unsafe.Pointer(bp + 128 /* histogram_symbols */)) = [1]uint16_t{uint16_t(0)} + *(*int32)(unsafe.Pointer(bp /* cache_bits */)) = 0 + histogram_image = (uintptr(0)) + huff_tree = WebPSafeMalloc(tls, + (3 * uint64(19)), uint64(unsafe.Sizeof(HuffmanTree{}))) + if !(huff_tree == (uintptr(0))) { + goto __1 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY + goto Error +__1: + ; + + // Calculate backward references from ARGB image. + if !(!(VP8LHashChainFill(tls, hash_chain, quality, argb, width, height, + low_effort) != 0)) { + goto __2 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY + goto Error +__2: + ; + err = VP8LGetBackwardReferences(tls, + width, height, argb, quality /*low_effort=*/, 0, (kLZ77Standard | kLZ77RLE), + *(*int32)(unsafe.Pointer(bp /* cache_bits */)) /*do_no_cache=*/, 0, hash_chain, refs_array, (bp) /* &cache_bits */) + if !(err != VP8_ENC_OK) { + goto __3 + } + goto Error +__3: + ; + refs = (refs_array) + histogram_image = VP8LAllocateHistogramSet(tls, 1, *(*int32)(unsafe.Pointer(bp /* cache_bits */))) + if !(histogram_image == (uintptr(0))) { + goto __4 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY + goto Error +__4: + ; + VP8LHistogramSetClear(tls, histogram_image) + + // Build histogram image and symbols from backward references. + VP8LHistogramStoreRefs(tls, refs, *(*uintptr)(unsafe.Pointer((*VP8LHistogramSet)(unsafe.Pointer(histogram_image)).histograms))) + + // Create Huffman bit lengths and codes for each histogram image. + + if !(!(GetHuffBitLengthsAndCodes(tls, histogram_image, (bp+8) /* &huffman_codes[0] */) != 0)) { + goto __5 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY + goto Error +__5: + ; + + // No color cache, no Huffman image. + VP8LPutBits(tls, bw, uint32(0), 1) + + // Find maximum number of symbols for the huffman tree-set. + i = 0 +__6: + if !(i < 5) { + goto __8 + } + codes = ((bp + 8) /* &huffman_codes */ + uintptr(i)*24) + if !(max_tokens < (*HuffmanTreeCode)(unsafe.Pointer(codes)).num_symbols) { + goto __9 + } + max_tokens = (*HuffmanTreeCode)(unsafe.Pointer(codes)).num_symbols +__9: + ; + goto __7 +__7: + i++ + goto __6 + goto __8 +__8: + ; + + tokens = WebPSafeMalloc(tls, uint64(max_tokens), uint64(unsafe.Sizeof(HuffmanTreeToken{}))) + if !(tokens == (uintptr(0))) { + goto __10 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY + goto Error +__10: + ; + + // Store Huffman codes. + i = 0 +__11: + if !(i < 5) { + goto __13 + } + codes1 = ((bp + 8) /* &huffman_codes */ + uintptr(i)*24) + StoreHuffmanCode(tls, bw, huff_tree, tokens, codes1) + ClearHuffmanTreeIfOnlyOneSymbol(tls, codes1) + goto __12 +__12: + i++ + goto __11 + goto __13 +__13: + ; + + // Store actual literals. + err = StoreImageToBitMask(tls, bw, width, 0, refs, (bp + 128), /* &histogram_symbols[0] */ + (bp + 8) /* &huffman_codes[0] */) + +Error: + WebPSafeFree(tls, tokens) + WebPSafeFree(tls, huff_tree) + VP8LFreeHistogramSet(tls, histogram_image) + WebPSafeFree(tls, (*HuffmanTreeCode)(unsafe.Pointer((bp + 8) /* &huffman_codes */)).codes) + return err +} + +func EncodeImageInternal(tls *libc.TLS, bw uintptr, argb uintptr, hash_chain uintptr, refs_array uintptr, width int32, height int32, quality int32, low_effort int32, use_cache int32, config uintptr, cache_bits uintptr, histogram_bits int32, init_byte_position size_t, hdr_size uintptr, data_size uintptr) WebPEncodingError { /* vp8l_enc.c:1097:26: */ + bp := tls.Alloc(120) + defer tls.Free(120) + + var err WebPEncodingError + var histogram_image_xysize uint32_t + var histogram_image uintptr + var tmp_histo uintptr + var histogram_image_size int32 + var bit_array_size size_t + var huff_tree uintptr + var tokens uintptr + var huffman_codes uintptr + var histogram_symbols uintptr + var sub_configs_idx int32 + var cache_bits_init int32 + var write_histogram_image int32 + // var bw_init VP8LBitWriter at bp+72, 48 + + // var bw_best VP8LBitWriter at bp+16, 48 + + var hdr_size_tmp int32 + // var hash_chain_histogram VP8LHashChain at bp, 16 + // histogram image hash chain + var bw_size_best size_t + var symbol_index int32 + var histogram_argb uintptr + var max_index int32 + var i uint32_t + var codes uintptr + var codes1 uintptr + var i1 int32 + var max_tokens int32 + var cache_bits_tmp int32 + var sub_config uintptr + // var cache_bits_best int32 at bp+64, 4 + + var i_cache int32 + err = VP8_ENC_ERROR_OUT_OF_MEMORY + histogram_image_xysize = + (VP8LSubSampleSize(tls, uint32(width), uint32(histogram_bits)) * VP8LSubSampleSize(tls, uint32(height), uint32(histogram_bits))) + histogram_image = (uintptr(0)) + tmp_histo = (uintptr(0)) + histogram_image_size = 0 + bit_array_size = uint64(0) + huff_tree = WebPSafeMalloc(tls, + (3 * uint64(19)), uint64(unsafe.Sizeof(HuffmanTree{}))) + tokens = (uintptr(0)) + huffman_codes = (uintptr(0)) + histogram_symbols = + WebPSafeMalloc(tls, uint64(histogram_image_xysize), + uint64(unsafe.Sizeof(uint16_t(0)))) + *(*VP8LBitWriter)(unsafe.Pointer(bp + 72 /* bw_init */)) = *(*VP8LBitWriter)(unsafe.Pointer(bw)) + bw_size_best = libc.CplUint64(uint64(0)) + + // Make sure we can allocate the different objects. + libc.Xmemset(tls, (bp) /* &hash_chain_histogram */, 0, uint64(unsafe.Sizeof(VP8LHashChain{}))) + if !((((huff_tree == (uintptr(0))) || (histogram_symbols == (uintptr(0)))) || !(VP8LHashChainInit(tls, (bp) /* &hash_chain_histogram */, int32(histogram_image_xysize)) != 0)) || !(VP8LHashChainFill(tls, hash_chain, quality, argb, width, height, + low_effort) != 0)) { + goto __1 + } + goto Error +__1: + ; + if !(use_cache != 0) { + goto __2 + } + // If the value is different from zero, it has been set during the + // palette analysis. + if *(*int32)(unsafe.Pointer(cache_bits)) == 0 { + cache_bits_init = 10 + } else { + cache_bits_init = *(*int32)(unsafe.Pointer(cache_bits)) + } + goto __3 +__2: + cache_bits_init = 0 +__3: + ; + // If several iterations will happen, clone into bw_best. + if !(!(VP8LBitWriterInit(tls, (bp+16) /* &bw_best */, uint64(0)) != 0) || ((((*CrunchConfig)(unsafe.Pointer(config)).sub_configs_size_ > 1) || ((*CrunchSubConfig)(unsafe.Pointer((config + 8 /* &.sub_configs_ */))).do_no_cache_ != 0)) && !(VP8LBitWriterClone(tls, bw, (bp+16) /* &bw_best */) != 0))) { + goto __4 + } + goto Error +__4: + ; + sub_configs_idx = 0 +__5: + if !(sub_configs_idx < (*CrunchConfig)(unsafe.Pointer(config)).sub_configs_size_) { + goto __7 + } + sub_config = + ((config + 8 /* &.sub_configs_ */) + uintptr(sub_configs_idx)*8) + err = VP8LGetBackwardReferences(tls, width, height, argb, quality, low_effort, + (*CrunchSubConfig)(unsafe.Pointer(sub_config)).lz77_, cache_bits_init, + (*CrunchSubConfig)(unsafe.Pointer(sub_config)).do_no_cache_, hash_chain, + (refs_array), (bp + 64) /* &cache_bits_best */) + if !(err != VP8_ENC_OK) { + goto __8 + } + goto Error +__8: + ; + + i_cache = 0 +__9: + if !(i_cache < (func() int32 { + if (*CrunchSubConfig)(unsafe.Pointer(sub_config)).do_no_cache_ != 0 { + return 2 + } + return 1 + }())) { + goto __11 + } + if i_cache == 0 { + cache_bits_tmp = *(*int32)(unsafe.Pointer(bp + 64 /* cache_bits_best */)) + } else { + cache_bits_tmp = 0 + } + // Speed-up: no need to study the no-cache case if it was already studied + // in i_cache == 0. + if !((i_cache == 1) && (*(*int32)(unsafe.Pointer(bp + 64 /* cache_bits_best */)) == 0)) { + goto __12 + } + goto __11 +__12: + ; + + // Reset the bit writer for this iteration. + VP8LBitWriterReset(tls, (bp + 72) /* &bw_init */, bw) + + // Build histogram image and symbols from backward references. + histogram_image = VP8LAllocateHistogramSet(tls, int32(histogram_image_xysize), cache_bits_tmp) + tmp_histo = VP8LAllocateHistogram(tls, cache_bits_tmp) + if !(((histogram_image == (uintptr(0))) || (tmp_histo == (uintptr(0)))) || !(VP8LGetHistoImageSymbols(tls, width, height, (refs_array+uintptr(i_cache)*40), + quality, low_effort, histogram_bits, + cache_bits_tmp, histogram_image, tmp_histo, + histogram_symbols) != 0)) { + goto __13 + } + goto Error +__13: + ; + // Create Huffman bit lengths and codes for each histogram image. + histogram_image_size = (*VP8LHistogramSet)(unsafe.Pointer(histogram_image)).size + bit_array_size = (size_t(5 * histogram_image_size)) + huffman_codes = WebPSafeCalloc(tls, bit_array_size, + uint64(unsafe.Sizeof(HuffmanTreeCode{}))) + // Note: some histogram_image entries may point to tmp_histos[], so the + // latter need to outlive the following call to + // GetHuffBitLengthsAndCodes(). + if !((huffman_codes == (uintptr(0))) || !(GetHuffBitLengthsAndCodes(tls, histogram_image, huffman_codes) != 0)) { + goto __14 + } + goto Error +__14: + ; + // Free combined histograms. + VP8LFreeHistogramSet(tls, histogram_image) + histogram_image = (uintptr(0)) + + // Free scratch histograms. + VP8LFreeHistogram(tls, tmp_histo) + tmp_histo = (uintptr(0)) + + // Color Cache parameters. + if !(cache_bits_tmp > 0) { + goto __15 + } + VP8LPutBits(tls, bw, uint32(1), 1) + VP8LPutBits(tls, bw, uint32(cache_bits_tmp), 4) + goto __16 +__15: + VP8LPutBits(tls, bw, uint32(0), 1) +__16: + ; + + // Huffman image + meta huffman. + write_histogram_image = (libc.Bool32(histogram_image_size > 1)) + VP8LPutBits(tls, bw, uint32(write_histogram_image), 1) + if !(write_histogram_image != 0) { + goto __17 + } + histogram_argb = + WebPSafeMalloc(tls, uint64(histogram_image_xysize), + uint64(unsafe.Sizeof(uint32_t(0)))) + max_index = 0 + if !(histogram_argb == (uintptr(0))) { + goto __18 + } + goto Error +__18: + ; + i = uint32_t(0) +__19: + if !(i < histogram_image_xysize) { + goto __21 + } + symbol_index = (int32(*(*uint16_t)(unsafe.Pointer(histogram_symbols + uintptr(i)*2))) & 0xffff) + *(*uint32_t)(unsafe.Pointer(histogram_argb + uintptr(i)*4)) = (uint32_t(symbol_index << 8)) + if !(symbol_index >= max_index) { + goto __22 + } + max_index = (symbol_index + 1) +__22: + ; + goto __20 +__20: + i++ + goto __19 + goto __21 +__21: + ; + histogram_image_size = max_index + + VP8LPutBits(tls, bw, (uint32(histogram_bits - 2)), 3) + err = EncodeImageNoHuffman(tls, + bw, histogram_argb, (bp) /* &hash_chain_histogram */, (refs_array + 2*40), + int32(VP8LSubSampleSize(tls, uint32(width), uint32(histogram_bits))), + int32(VP8LSubSampleSize(tls, uint32(height), uint32(histogram_bits))), quality, low_effort) + WebPSafeFree(tls, histogram_argb) + if !(err != VP8_ENC_OK) { + goto __23 + } + goto Error +__23: + ; +__17: + ; + + // Store Huffman codes. + + max_tokens = 0 + // Find maximum number of symbols for the huffman tree-set. + i1 = 0 +__24: + if !(i1 < (5 * histogram_image_size)) { + goto __26 + } + codes = (huffman_codes + uintptr(i1)*24) + if !(max_tokens < (*HuffmanTreeCode)(unsafe.Pointer(codes)).num_symbols) { + goto __27 + } + max_tokens = (*HuffmanTreeCode)(unsafe.Pointer(codes)).num_symbols +__27: + ; + goto __25 +__25: + i1++ + goto __24 + goto __26 +__26: + ; + tokens = WebPSafeMalloc(tls, uint64(max_tokens), uint64(unsafe.Sizeof(HuffmanTreeToken{}))) + if !(tokens == (uintptr(0))) { + goto __28 + } + goto Error +__28: + ; + i1 = 0 +__29: + if !(i1 < (5 * histogram_image_size)) { + goto __31 + } + codes1 = (huffman_codes + uintptr(i1)*24) + StoreHuffmanCode(tls, bw, huff_tree, tokens, codes1) + ClearHuffmanTreeIfOnlyOneSymbol(tls, codes1) + goto __30 +__30: + i1++ + goto __29 + goto __31 +__31: + ; + + // Store actual literals. + hdr_size_tmp = (int32(VP8LBitWriterNumBytes(tls, bw) - init_byte_position)) + err = StoreImageToBitMask(tls, bw, width, histogram_bits, (refs_array + uintptr(i_cache)*40), + histogram_symbols, huffman_codes) + if !(err != VP8_ENC_OK) { + goto __32 + } + goto Error +__32: + ; + // Keep track of the smallest image so far. + if !(VP8LBitWriterNumBytes(tls, bw) < bw_size_best) { + goto __33 + } + bw_size_best = VP8LBitWriterNumBytes(tls, bw) + *(*int32)(unsafe.Pointer(cache_bits)) = cache_bits_tmp + *(*int32)(unsafe.Pointer(hdr_size)) = hdr_size_tmp + *(*int32)(unsafe.Pointer(data_size)) = (int32((VP8LBitWriterNumBytes(tls, bw) - init_byte_position) - size_t(*(*int32)(unsafe.Pointer(hdr_size))))) + VP8LBitWriterSwap(tls, bw, (bp + 16) /* &bw_best */) +__33: + ; + WebPSafeFree(tls, tokens) + tokens = (uintptr(0)) + if !(huffman_codes != (uintptr(0))) { + goto __34 + } + WebPSafeFree(tls, (*HuffmanTreeCode)(unsafe.Pointer(huffman_codes)).codes) + WebPSafeFree(tls, huffman_codes) + huffman_codes = (uintptr(0)) +__34: + ; + goto __10 +__10: + i_cache++ + goto __9 + goto __11 +__11: + ; + goto __6 +__6: + sub_configs_idx++ + goto __5 + goto __7 +__7: + ; + VP8LBitWriterSwap(tls, bw, (bp + 16) /* &bw_best */) + err = VP8_ENC_OK + +Error: + WebPSafeFree(tls, tokens) + WebPSafeFree(tls, huff_tree) + VP8LFreeHistogramSet(tls, histogram_image) + VP8LFreeHistogram(tls, tmp_histo) + VP8LHashChainClear(tls, (bp) /* &hash_chain_histogram */) + if !(huffman_codes != (uintptr(0))) { + goto __35 + } + WebPSafeFree(tls, (*HuffmanTreeCode)(unsafe.Pointer(huffman_codes)).codes) + WebPSafeFree(tls, huffman_codes) +__35: + ; + WebPSafeFree(tls, histogram_symbols) + VP8LBitWriterWipeOut(tls, (bp + 16) /* &bw_best */) + return err +} + +// ----------------------------------------------------------------------------- +// Transforms + +func ApplySubtractGreen(tls *libc.TLS, enc uintptr, width int32, height int32, bw uintptr) { /* vp8l_enc.c:1301:13: */ + VP8LPutBits(tls, bw, uint32(1), 1) + VP8LPutBits(tls, bw, SUBTRACT_GREEN, 2) + (*struct { + f func(*libc.TLS, uintptr, int32) + })(unsafe.Pointer(&struct{ uintptr }{VP8LSubtractGreenFromBlueAndRed})).f(tls, (*VP8LEncoder)(unsafe.Pointer(enc)).argb_, (width * height)) +} + +func ApplyPredictFilter(tls *libc.TLS, enc uintptr, width int32, height int32, quality int32, low_effort int32, used_subtract_green int32, bw uintptr) WebPEncodingError { /* vp8l_enc.c:1308:26: */ + var pred_bits int32 = (*VP8LEncoder)(unsafe.Pointer(enc)).transform_bits_ + var transform_width int32 = int32(VP8LSubSampleSize(tls, uint32(width), uint32(pred_bits))) + var transform_height int32 = int32(VP8LSubSampleSize(tls, uint32(height), uint32(pred_bits))) + // we disable near-lossless quantization if palette is used. + var near_lossless_strength int32 + if (*VP8LEncoder)(unsafe.Pointer(enc)).use_palette_ != 0 { + near_lossless_strength = 100 + } else { + near_lossless_strength = (*WebPConfig)(unsafe.Pointer((*VP8LEncoder)(unsafe.Pointer(enc)).config_)).near_lossless + } + + VP8LResidualImage(tls, width, height, pred_bits, low_effort, (*VP8LEncoder)(unsafe.Pointer(enc)).argb_, + (*VP8LEncoder)(unsafe.Pointer(enc)).argb_scratch_, (*VP8LEncoder)(unsafe.Pointer(enc)).transform_data_, + near_lossless_strength, (*WebPConfig)(unsafe.Pointer((*VP8LEncoder)(unsafe.Pointer(enc)).config_)).exact, + used_subtract_green) + VP8LPutBits(tls, bw, uint32(1), 1) + VP8LPutBits(tls, bw, PREDICTOR_TRANSFORM, 2) + + VP8LPutBits(tls, bw, (uint32(pred_bits - 2)), 3) + return EncodeImageNoHuffman(tls, + bw, (*VP8LEncoder)(unsafe.Pointer(enc)).transform_data_, (enc + 2312 /* &.hash_chain_ */), + (enc + 2152 /* &.refs_ */), transform_width, transform_height, + quality, low_effort) +} + +func ApplyCrossColorFilter(tls *libc.TLS, enc uintptr, width int32, height int32, quality int32, low_effort int32, bw uintptr) WebPEncodingError { /* vp8l_enc.c:1334:26: */ + var ccolor_transform_bits int32 = (*VP8LEncoder)(unsafe.Pointer(enc)).transform_bits_ + var transform_width int32 = int32(VP8LSubSampleSize(tls, uint32(width), uint32(ccolor_transform_bits))) + var transform_height int32 = int32(VP8LSubSampleSize(tls, uint32(height), uint32(ccolor_transform_bits))) + + VP8LColorSpaceTransform(tls, width, height, ccolor_transform_bits, quality, + (*VP8LEncoder)(unsafe.Pointer(enc)).argb_, (*VP8LEncoder)(unsafe.Pointer(enc)).transform_data_) + VP8LPutBits(tls, bw, uint32(1), 1) + VP8LPutBits(tls, bw, CROSS_COLOR_TRANSFORM, 2) + + VP8LPutBits(tls, bw, (uint32(ccolor_transform_bits - 2)), 3) + return EncodeImageNoHuffman(tls, + bw, (*VP8LEncoder)(unsafe.Pointer(enc)).transform_data_, (enc + 2312 /* &.hash_chain_ */), + (enc + 2152 /* &.refs_ */), transform_width, transform_height, + quality, low_effort) +} + +// ----------------------------------------------------------------------------- + +func WriteRiffHeader(tls *libc.TLS, pic uintptr, riff_size size_t, vp8l_size size_t) WebPEncodingError { /* vp8l_enc.c:1356:26: */ + bp := tls.Alloc(21) + defer tls.Free(21) + + *(*[21]uint8_t)(unsafe.Pointer(bp /* riff */)) = [21]uint8_t{ + uint8_t('R'), uint8_t('I'), uint8_t('F'), uint8_t('F'), uint8_t(0), uint8_t(0), uint8_t(0), uint8_t(0), uint8_t('W'), uint8_t('E'), uint8_t('B'), uint8_t('P'), + uint8_t('V'), uint8_t('P'), uint8_t('8'), uint8_t('L'), uint8_t(0), uint8_t(0), uint8_t(0), uint8_t(0), uint8_t(0x2f), + } + PutLE32(tls, ((bp) /* &riff[0] */ + uintptr(4)), uint32_t(riff_size)) + PutLE32(tls, (((bp) /* &riff[0] */ + uintptr(12)) + uintptr(4)), uint32_t(vp8l_size)) + if !((*struct { + f func(*libc.TLS, uintptr, size_t, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPPicture)(unsafe.Pointer(pic)).writer})).f(tls, (bp) /* &riff[0] */, uint64(unsafe.Sizeof([21]uint8_t{})), pic) != 0) { + return VP8_ENC_ERROR_BAD_WRITE + } + return VP8_ENC_OK +} + +func WriteImageSize(tls *libc.TLS, pic uintptr, bw uintptr) int32 { /* vp8l_enc.c:1370:12: */ + var width int32 = ((*WebPPicture)(unsafe.Pointer(pic)).width - 1) + var height int32 = ((*WebPPicture)(unsafe.Pointer(pic)).height - 1) + + VP8LPutBits(tls, bw, uint32(width), 14) + VP8LPutBits(tls, bw, uint32(height), 14) + return libc.BoolInt32(!((*VP8LBitWriter)(unsafe.Pointer(bw)).error_ != 0)) +} + +func WriteRealAlphaAndVersion(tls *libc.TLS, bw uintptr, has_alpha int32) int32 { /* vp8l_enc.c:1381:12: */ + VP8LPutBits(tls, bw, uint32(has_alpha), 1) + VP8LPutBits(tls, bw, uint32(0), 3) + return libc.BoolInt32(!((*VP8LBitWriter)(unsafe.Pointer(bw)).error_ != 0)) +} + +func WriteImage(tls *libc.TLS, pic uintptr, bw uintptr, coded_size uintptr) WebPEncodingError { /* vp8l_enc.c:1387:26: */ + bp := tls.Alloc(1) + defer tls.Free(1) + + var err WebPEncodingError + var webpll_data uintptr + var webpll_size size_t + var vp8l_size size_t + var pad size_t + var riff_size size_t + // var pad_byte [1]uint8_t at bp, 1 + err = VP8_ENC_OK + webpll_data = VP8LBitWriterFinish(tls, bw) + webpll_size = VP8LBitWriterNumBytes(tls, bw) + vp8l_size = (uint64(1) + webpll_size) + pad = (vp8l_size & uint64(1)) + riff_size = (((uint64(4 + 8)) + vp8l_size) + pad) + + err = WriteRiffHeader(tls, pic, riff_size, vp8l_size) + if !(err != VP8_ENC_OK) { + goto __1 + } + goto Error +__1: + ; + + if !(!((*struct { + f func(*libc.TLS, uintptr, size_t, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPPicture)(unsafe.Pointer(pic)).writer})).f(tls, webpll_data, webpll_size, pic) != 0)) { + goto __2 + } + err = VP8_ENC_ERROR_BAD_WRITE + goto Error +__2: + ; + + if !(pad != 0) { + goto __3 + } + *(*[1]uint8_t)(unsafe.Pointer(bp /* pad_byte */)) = [1]uint8_t{uint8_t(0)} + if !(!((*struct { + f func(*libc.TLS, uintptr, size_t, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPPicture)(unsafe.Pointer(pic)).writer})).f(tls, (bp) /* &pad_byte[0] */, uint64(1), pic) != 0)) { + goto __4 + } + err = VP8_ENC_ERROR_BAD_WRITE + goto Error +__4: + ; +__3: + ; + *(*size_t)(unsafe.Pointer(coded_size)) = (uint64(8) + riff_size) + return VP8_ENC_OK + +Error: + return err +} + +// ----------------------------------------------------------------------------- + +func ClearTransformBuffer(tls *libc.TLS, enc uintptr) { /* vp8l_enc.c:1421:13: */ + WebPSafeFree(tls, (*VP8LEncoder)(unsafe.Pointer(enc)).transform_mem_) + (*VP8LEncoder)(unsafe.Pointer(enc)).transform_mem_ = (uintptr(0)) + (*VP8LEncoder)(unsafe.Pointer(enc)).transform_mem_size_ = uint64(0) +} + +// Allocates the memory for argb (W x H) buffer, 2 rows of context for +// prediction and transform data. +// Flags influencing the memory allocated: +// enc->transform_bits_ +// enc->use_predict_, enc->use_cross_color_ +func AllocateTransformBuffer(tls *libc.TLS, enc uintptr, width int32, height int32) WebPEncodingError { /* vp8l_enc.c:1432:26: */ + var err WebPEncodingError + var image_size uint64_t + // VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra + // pixel in each, plus 2 regular scanlines of bytes. + // TODO(skal): Clean up by using arithmetic in bytes instead of words. + var argb_scratch_size uint64_t + var transform_data_size uint64_t + var max_alignment_in_words uint64_t + var mem_size uint64_t + var mem uintptr + err = VP8_ENC_OK + image_size = (uint64_t(width * height)) + if (*VP8LEncoder)(unsafe.Pointer(enc)).use_predict_ != 0 { + argb_scratch_size = ((uint64((width + 1) * 2)) + ((((uint64(width * 2)) + uint64(unsafe.Sizeof(uint32_t(0)))) - uint64(1)) / uint64(unsafe.Sizeof(uint32_t(0))))) + } else { + argb_scratch_size = uint64(0) + } + if ((*VP8LEncoder)(unsafe.Pointer(enc)).use_predict_ != 0) || ((*VP8LEncoder)(unsafe.Pointer(enc)).use_cross_color_ != 0) { + transform_data_size = (uint64(VP8LSubSampleSize(tls, uint32(width), uint32((*VP8LEncoder)(unsafe.Pointer(enc)).transform_bits_)) * VP8LSubSampleSize(tls, uint32(height), uint32((*VP8LEncoder)(unsafe.Pointer(enc)).transform_bits_)))) + } else { + transform_data_size = uint64(0) + } + max_alignment_in_words = + (((uint64(31) + uint64(unsafe.Sizeof(uint32_t(0)))) - uint64(1)) / uint64(unsafe.Sizeof(uint32_t(0)))) + mem_size = + ((((image_size + max_alignment_in_words) + argb_scratch_size) + max_alignment_in_words) + transform_data_size) + mem = (*VP8LEncoder)(unsafe.Pointer(enc)).transform_mem_ + if !((mem == (uintptr(0))) || (mem_size > (*VP8LEncoder)(unsafe.Pointer(enc)).transform_mem_size_)) { + goto __1 + } + ClearTransformBuffer(tls, enc) + mem = WebPSafeMalloc(tls, mem_size, uint64(unsafe.Sizeof(uint32_t(0)))) + if !(mem == (uintptr(0))) { + goto __2 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY + goto Error +__2: + ; + (*VP8LEncoder)(unsafe.Pointer(enc)).transform_mem_ = mem + (*VP8LEncoder)(unsafe.Pointer(enc)).transform_mem_size_ = mem_size + (*VP8LEncoder)(unsafe.Pointer(enc)).argb_content_ = kEncoderNone +__1: + ; + (*VP8LEncoder)(unsafe.Pointer(enc)).argb_ = mem + mem = (uintptr((uintptr_t((mem + uintptr(image_size)*4)) + uint64(31)) & libc.Uint64FromInt32(libc.CplInt32(31)))) + (*VP8LEncoder)(unsafe.Pointer(enc)).argb_scratch_ = mem + mem = (uintptr((uintptr_t((mem + uintptr(argb_scratch_size)*4)) + uint64(31)) & libc.Uint64FromInt32(libc.CplInt32(31)))) + (*VP8LEncoder)(unsafe.Pointer(enc)).transform_data_ = mem + + (*VP8LEncoder)(unsafe.Pointer(enc)).current_width_ = width +Error: + return err +} + +func MakeInputImageCopy(tls *libc.TLS, enc uintptr) WebPEncodingError { /* vp8l_enc.c:1478:26: */ + var err WebPEncodingError = VP8_ENC_OK + var picture uintptr = (*VP8LEncoder)(unsafe.Pointer(enc)).pic_ + var width int32 = (*WebPPicture)(unsafe.Pointer(picture)).width + var height int32 = (*WebPPicture)(unsafe.Pointer(picture)).height + + err = AllocateTransformBuffer(tls, enc, width, height) + if err != VP8_ENC_OK { + return err + } + if (*VP8LEncoder)(unsafe.Pointer(enc)).argb_content_ == kEncoderARGB { + return VP8_ENC_OK + } + + { + var dst uintptr = (*VP8LEncoder)(unsafe.Pointer(enc)).argb_ + var src uintptr = (*WebPPicture)(unsafe.Pointer(picture)).argb + var y int32 + for y = 0; y < height; y++ { + libc.Xmemcpy(tls, dst, src, (uint64(width) * uint64(unsafe.Sizeof(uint32_t(0))))) + dst += 4 * (uintptr(width)) + src += 4 * (uintptr((*WebPPicture)(unsafe.Pointer(picture)).argb_stride)) + } + + } + (*VP8LEncoder)(unsafe.Pointer(enc)).argb_content_ = kEncoderARGB + + return VP8_ENC_OK +} + +// ----------------------------------------------------------------------------- + +func SearchColorGreedy(tls *libc.TLS, palette uintptr, palette_size int32, color uint32_t) uint32_t { /* vp8l_enc.c:1507:29: */ + _ = palette_size + + if color == *(*uint32_t)(unsafe.Pointer(palette)) { + return uint32_t(0) + } + if color == *(*uint32_t)(unsafe.Pointer(palette + 1*4)) { + return uint32_t(1) + } + if color == *(*uint32_t)(unsafe.Pointer(palette + 2*4)) { + return uint32_t(2) + } + return uint32_t(3) +} + +func ApplyPaletteHash0(tls *libc.TLS, color uint32_t) uint32_t { /* vp8l_enc.c:1519:29: */ + // Focus on the green color. + return ((color >> 8) & uint32_t(0xff)) +} + +func ApplyPaletteHash1(tls *libc.TLS, color uint32_t) uint32_t { /* vp8l_enc.c:1527:29: */ + // Forget about alpha. + return ((uint32_t((uint64(color & 0x00ffffff)) * 4222244071)) >> (32 - 11)) +} + +func ApplyPaletteHash2(tls *libc.TLS, color uint32_t) uint32_t { /* vp8l_enc.c:1533:29: */ + // Forget about alpha. + return ((uint32_t((uint64(color & 0x00ffffff)) * ((uint64(1) << 31) - uint64(1)))) >> (32 - 11)) +} + +// Use 1 pixel cache for ARGB pixels. + +// Remap argb values in src[] to packed palettes entries in dst[] +// using 'row' as a temporary buffer of size 'width'. +// We assume that all src[] values have a corresponding entry in the palette. +// Note: src[] can be the same as dst[] +func ApplyPalette(tls *libc.TLS, src uintptr, src_stride uint32_t, dst uintptr, dst_stride uint32_t, palette uintptr, palette_size int32, width int32, height int32, xbits int32) WebPEncodingError { /* vp8l_enc.c:1562:26: */ + bp := tls.Alloc(6168) + defer tls.Free(6168) + + // TODO(skal): this tmp buffer is not needed if VP8LBundleColorMap() can be + // made to work in-place. + var tmp_row uintptr = WebPSafeMalloc(tls, uint64(width), uint64(unsafe.Sizeof(uint8_t(0)))) + var x int32 + var y int32 + + if tmp_row == (uintptr(0)) { + return VP8_ENC_ERROR_OUT_OF_MEMORY + } + + if palette_size < 4 { + for ok := true; ok; ok = (0 != 0) { + var prev_pix uint32_t = *(*uint32_t)(unsafe.Pointer(palette)) + var prev_idx uint32_t = uint32_t(0) + for y = 0; y < height; y++ { + for x = 0; x < width; x++ { + var pix uint32_t = *(*uint32_t)(unsafe.Pointer(src + uintptr(x)*4)) + if pix != prev_pix { + prev_idx = SearchColorGreedy(tls, palette, palette_size, pix) + prev_pix = pix + } + *(*uint8_t)(unsafe.Pointer(tmp_row + uintptr(x))) = uint8_t(prev_idx) + } + (*struct { + f func(*libc.TLS, uintptr, int32, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LBundleColorMap})).f(tls, tmp_row, width, xbits, dst) + src += 4 * (uintptr(src_stride)) + dst += 4 * (uintptr(dst_stride)) + } + } + } else { + var i int32 + var j int32 + // var buffer [2048]uint16_t at bp, 4096 + + *(*[3]uintptr)(unsafe.Pointer(bp + 4096 /* hash_functions */)) = [3]uintptr{ + *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uint32_t) uint32_t + }{ApplyPaletteHash0})), *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uint32_t) uint32_t + }{ApplyPaletteHash1})), *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uint32_t) uint32_t + }{ApplyPaletteHash2})), + } + + // Try to find a perfect hash function able to go from a color to an index + // within 1 << PALETTE_INV_SIZE_BITS in order to build a hash map to go + // from color to index in palette. + for i = 0; i < 3; i++ { + var use_LUT int32 = 1 + // Set each element in buffer to max uint16_t. + libc.Xmemset(tls, (bp) /* &buffer[0] */, 0xff, uint64(unsafe.Sizeof([2048]uint16_t{}))) + for j = 0; j < palette_size; j++ { + var ind uint32_t = (*struct { + f func(*libc.TLS, uint32_t) uint32_t + })(unsafe.Pointer(&struct{ uintptr }{*(*uintptr)(unsafe.Pointer((bp + 4096) /* &hash_functions[0] */ + uintptr(i)*8))})).f(tls, *(*uint32_t)(unsafe.Pointer(palette + uintptr(j)*4))) + if uint32(*(*uint16_t)(unsafe.Pointer((bp) /* &buffer[0] */ + uintptr(ind)*2))) != 0xffff { + use_LUT = 0 + break + } else { + *(*uint16_t)(unsafe.Pointer((bp) /* &buffer[0] */ + uintptr(ind)*2)) = uint16_t(j) + } + } + if use_LUT != 0 { + break + } + } + + if i == 0 { + for ok1 := true; ok1; ok1 = (0 != 0) { + var prev_pix uint32_t = *(*uint32_t)(unsafe.Pointer(palette)) + var prev_idx uint32_t = uint32_t(0) + for y = 0; y < height; y++ { + for x = 0; x < width; x++ { + var pix uint32_t = *(*uint32_t)(unsafe.Pointer(src + uintptr(x)*4)) + if pix != prev_pix { + prev_idx = uint32_t(*(*uint16_t)(unsafe.Pointer((bp) /* &buffer[0] */ + uintptr(ApplyPaletteHash0(tls, pix))*2))) + prev_pix = pix + } + *(*uint8_t)(unsafe.Pointer(tmp_row + uintptr(x))) = uint8_t(prev_idx) + } + (*struct { + f func(*libc.TLS, uintptr, int32, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LBundleColorMap})).f(tls, tmp_row, width, xbits, dst) + src += 4 * (uintptr(src_stride)) + dst += 4 * (uintptr(dst_stride)) + } + } + } else if i == 1 { + for ok2 := true; ok2; ok2 = (0 != 0) { + var prev_pix uint32_t = *(*uint32_t)(unsafe.Pointer(palette)) + var prev_idx uint32_t = uint32_t(0) + for y = 0; y < height; y++ { + for x = 0; x < width; x++ { + var pix uint32_t = *(*uint32_t)(unsafe.Pointer(src + uintptr(x)*4)) + if pix != prev_pix { + prev_idx = uint32_t(*(*uint16_t)(unsafe.Pointer((bp) /* &buffer[0] */ + uintptr(ApplyPaletteHash1(tls, pix))*2))) + prev_pix = pix + } + *(*uint8_t)(unsafe.Pointer(tmp_row + uintptr(x))) = uint8_t(prev_idx) + } + (*struct { + f func(*libc.TLS, uintptr, int32, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LBundleColorMap})).f(tls, tmp_row, width, xbits, dst) + src += 4 * (uintptr(src_stride)) + dst += 4 * (uintptr(dst_stride)) + } + } + } else if i == 2 { + for ok3 := true; ok3; ok3 = (0 != 0) { + var prev_pix uint32_t = *(*uint32_t)(unsafe.Pointer(palette)) + var prev_idx uint32_t = uint32_t(0) + for y = 0; y < height; y++ { + for x = 0; x < width; x++ { + var pix uint32_t = *(*uint32_t)(unsafe.Pointer(src + uintptr(x)*4)) + if pix != prev_pix { + prev_idx = uint32_t(*(*uint16_t)(unsafe.Pointer((bp) /* &buffer[0] */ + uintptr(ApplyPaletteHash2(tls, pix))*2))) + prev_pix = pix + } + *(*uint8_t)(unsafe.Pointer(tmp_row + uintptr(x))) = uint8_t(prev_idx) + } + (*struct { + f func(*libc.TLS, uintptr, int32, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LBundleColorMap})).f(tls, tmp_row, width, xbits, dst) + src += 4 * (uintptr(src_stride)) + dst += 4 * (uintptr(dst_stride)) + } + } + } else { + // var idx_map [256]uint32_t at bp+5144, 1024 + + // var palette_sorted [256]uint32_t at bp+4120, 1024 + + PrepareMapToPalette(tls, palette, uint32(palette_size), (bp + 4120) /* &palette_sorted[0] */, (bp + 5144) /* &idx_map[0] */) + for ok4 := true; ok4; ok4 = (0 != 0) { + var prev_pix uint32_t = *(*uint32_t)(unsafe.Pointer(palette)) + var prev_idx uint32_t = uint32_t(0) + for y = 0; y < height; y++ { + for x = 0; x < width; x++ { + var pix uint32_t = *(*uint32_t)(unsafe.Pointer(src + uintptr(x)*4)) + if pix != prev_pix { + prev_idx = *(*uint32_t)(unsafe.Pointer((bp + 5144) /* &idx_map[0] */ + uintptr(SearchColorNoIdx(tls, (bp+4120) /* &palette_sorted[0] */, pix, palette_size))*4)) + prev_pix = pix + } + *(*uint8_t)(unsafe.Pointer(tmp_row + uintptr(x))) = uint8_t(prev_idx) + } + (*struct { + f func(*libc.TLS, uintptr, int32, int32, uintptr) + })(unsafe.Pointer(&struct{ uintptr }{VP8LBundleColorMap})).f(tls, tmp_row, width, xbits, dst) + src += 4 * (uintptr(src_stride)) + dst += 4 * (uintptr(dst_stride)) + } + } + } + } + WebPSafeFree(tls, tmp_row) + return VP8_ENC_OK +} + +// Note: Expects "enc->palette_" to be set properly. +func MapImageFromPalette(tls *libc.TLS, enc uintptr, in_place int32) WebPEncodingError { /* vp8l_enc.c:1624:26: */ + var err WebPEncodingError = VP8_ENC_OK + var pic uintptr = (*VP8LEncoder)(unsafe.Pointer(enc)).pic_ + var width int32 = (*WebPPicture)(unsafe.Pointer(pic)).width + var height int32 = (*WebPPicture)(unsafe.Pointer(pic)).height + var palette uintptr = enc + 100 /* &.palette_ */ + var src uintptr + if in_place != 0 { + src = (*VP8LEncoder)(unsafe.Pointer(enc)).argb_ + } else { + src = (*WebPPicture)(unsafe.Pointer(pic)).argb + } + var src_stride int32 + if in_place != 0 { + src_stride = (*VP8LEncoder)(unsafe.Pointer(enc)).current_width_ + } else { + src_stride = (*WebPPicture)(unsafe.Pointer(pic)).argb_stride + } + var palette_size int32 = (*VP8LEncoder)(unsafe.Pointer(enc)).palette_size_ + var xbits int32 + + // Replace each input pixel by corresponding palette index. + // This is done line by line. + if palette_size <= 4 { + if palette_size <= 2 { + xbits = 3 + } else { + xbits = 2 + } + } else { + if palette_size <= 16 { + xbits = 1 + } else { + xbits = 0 + } + } + + err = AllocateTransformBuffer(tls, enc, int32(VP8LSubSampleSize(tls, uint32(width), uint32(xbits))), height) + if err != VP8_ENC_OK { + return err + } + + err = ApplyPalette(tls, src, uint32(src_stride), + (*VP8LEncoder)(unsafe.Pointer(enc)).argb_, uint32((*VP8LEncoder)(unsafe.Pointer(enc)).current_width_), + palette, palette_size, width, height, xbits) + (*VP8LEncoder)(unsafe.Pointer(enc)).argb_content_ = kEncoderPalette + return err +} + +// Save palette_[] to bitstream. +func EncodePalette(tls *libc.TLS, bw uintptr, low_effort int32, enc uintptr) WebPEncodingError { /* vp8l_enc.c:1655:26: */ + bp := tls.Alloc(1024) + defer tls.Free(1024) + + var i int32 + // var tmp_palette [256]uint32_t at bp, 1024 + + var palette_size int32 = (*VP8LEncoder)(unsafe.Pointer(enc)).palette_size_ + var palette uintptr = enc + 100 /* &.palette_ */ + VP8LPutBits(tls, bw, uint32(1), 1) + VP8LPutBits(tls, bw, COLOR_INDEXING_TRANSFORM, 2) + + VP8LPutBits(tls, bw, (uint32(palette_size - 1)), 8) + for i = (palette_size - 1); i >= 1; i-- { + *(*uint32_t)(unsafe.Pointer((bp) /* &tmp_palette[0] */ + uintptr(i)*4)) = VP8LSubPixels(tls, *(*uint32_t)(unsafe.Pointer(palette + uintptr(i)*4)), *(*uint32_t)(unsafe.Pointer(palette + uintptr((i-1))*4))) + } + *(*uint32_t)(unsafe.Pointer((bp) /* &tmp_palette[0] */)) = *(*uint32_t)(unsafe.Pointer(palette)) + return EncodeImageNoHuffman(tls, bw, (bp) /* &tmp_palette[0] */, (enc + 2312 /* &.hash_chain_ */), + (enc + 2152 /* &.refs_ */), palette_size, 1 /*quality=*/, 20, + low_effort) +} + +// ----------------------------------------------------------------------------- +// VP8LEncoder + +func VP8LEncoderNew(tls *libc.TLS, config uintptr, picture uintptr) uintptr { /* vp8l_enc.c:1677:19: */ + var enc uintptr = WebPSafeCalloc(tls, 1, uint64(unsafe.Sizeof(VP8LEncoder{}))) + if enc == (uintptr(0)) { + WebPEncodingSetError(tls, picture, VP8_ENC_ERROR_OUT_OF_MEMORY) + return (uintptr(0)) + } + (*VP8LEncoder)(unsafe.Pointer(enc)).config_ = config + (*VP8LEncoder)(unsafe.Pointer(enc)).pic_ = picture + (*VP8LEncoder)(unsafe.Pointer(enc)).argb_content_ = kEncoderNone + + VP8LEncDspInit(tls) + + return enc +} + +func VP8LEncoderDelete(tls *libc.TLS, enc uintptr) { /* vp8l_enc.c:1693:13: */ + if enc != (uintptr(0)) { + var i int32 + VP8LHashChainClear(tls, (enc + 2312 /* &.hash_chain_ */)) + for i = 0; i < 4; i++ { + VP8LBackwardRefsClear(tls, ((enc + 2152 /* &.refs_ */) + uintptr(i)*40)) + } + ClearTransformBuffer(tls, enc) + WebPSafeFree(tls, enc) + } +} + +// ----------------------------------------------------------------------------- +// Main call + +type StreamEncodeContext = struct { + config_ uintptr + picture_ uintptr + bw_ uintptr + enc_ uintptr + use_cache_ int32 + crunch_configs_ [8]CrunchConfig + num_crunch_configs_ int32 + red_and_blue_always_zero_ int32 + err_ WebPEncodingError + stats_ uintptr +} /* vp8l_enc.c:1717:3 */ + +func EncodeStreamHook(tls *libc.TLS, input uintptr, data2 uintptr) int32 { /* vp8l_enc.c:1719:12: */ + bp := tls.Alloc(104) + defer tls.Free(104) + + var params uintptr + var config uintptr + var picture uintptr + var bw uintptr + var enc uintptr + var use_cache int32 + var crunch_configs uintptr + var num_crunch_configs int32 + var red_and_blue_always_zero int32 + var stats uintptr + var err WebPEncodingError + var quality int32 + var low_effort int32 + var width int32 + var height int32 + var byte_position size_t + var use_near_lossless int32 + // var hdr_size int32 at bp+48, 4 + + // var data_size int32 at bp+52, 4 + + var use_delta_palette int32 + var idx int32 + var best_size size_t + // var bw_init VP8LBitWriter at bp+56, 48 + + // var bw_best VP8LBitWriter at bp, 48 + + var entropy_idx int32 + params = input + config = (*StreamEncodeContext)(unsafe.Pointer(params)).config_ + picture = (*StreamEncodeContext)(unsafe.Pointer(params)).picture_ + bw = (*StreamEncodeContext)(unsafe.Pointer(params)).bw_ + enc = (*StreamEncodeContext)(unsafe.Pointer(params)).enc_ + use_cache = (*StreamEncodeContext)(unsafe.Pointer(params)).use_cache_ + crunch_configs = params + 36 /* &.crunch_configs_ */ + num_crunch_configs = (*StreamEncodeContext)(unsafe.Pointer(params)).num_crunch_configs_ + red_and_blue_always_zero = (*StreamEncodeContext)(unsafe.Pointer(params)).red_and_blue_always_zero_ + stats = (*StreamEncodeContext)(unsafe.Pointer(params)).stats_ + err = VP8_ENC_OK + quality = libc.Int32FromFloat32((*WebPConfig)(unsafe.Pointer(config)).quality) + low_effort = (libc.Bool32((*WebPConfig)(unsafe.Pointer(config)).method == 0)) + width = (*WebPPicture)(unsafe.Pointer(picture)).width + height = (*WebPPicture)(unsafe.Pointer(picture)).height + byte_position = VP8LBitWriterNumBytes(tls, bw) + use_near_lossless = 0 + *(*int32)(unsafe.Pointer(bp + 48 /* hdr_size */)) = 0 + *(*int32)(unsafe.Pointer(bp + 52 /* data_size */)) = 0 + use_delta_palette = 0 + best_size = libc.CplUint64(uint64(0)) + *(*VP8LBitWriter)(unsafe.Pointer(bp + 56 /* bw_init */)) = *(*VP8LBitWriter)(unsafe.Pointer(bw)) + _ = data2 + + if !(!(VP8LBitWriterInit(tls, (bp) /* &bw_best */, uint64(0)) != 0) || ((num_crunch_configs > 1) && !(VP8LBitWriterClone(tls, bw, (bp) /* &bw_best */) != 0))) { + goto __1 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY + goto Error +__1: + ; + + idx = 0 +__2: + if !(idx < num_crunch_configs) { + goto __4 + } + entropy_idx = (*CrunchConfig)(unsafe.Pointer(crunch_configs + uintptr(idx)*28)).entropy_idx_ + (*VP8LEncoder)(unsafe.Pointer(enc)).use_palette_ = (libc.Bool32((entropy_idx == kPalette) || (entropy_idx == kPaletteAndSpatial))) + (*VP8LEncoder)(unsafe.Pointer(enc)).use_subtract_green_ = (libc.Bool32((entropy_idx == kSubGreen) || (entropy_idx == kSpatialSubGreen))) + (*VP8LEncoder)(unsafe.Pointer(enc)).use_predict_ = (libc.Bool32(((entropy_idx == kSpatial) || (entropy_idx == kSpatialSubGreen)) || (entropy_idx == kPaletteAndSpatial))) + // When using a palette, R/B==0, hence no need to test for cross-color. + if !((low_effort != 0) || ((*VP8LEncoder)(unsafe.Pointer(enc)).use_palette_ != 0)) { + goto __5 + } + (*VP8LEncoder)(unsafe.Pointer(enc)).use_cross_color_ = 0 + goto __6 +__5: + (*VP8LEncoder)(unsafe.Pointer(enc)).use_cross_color_ = func() int32 { + if red_and_blue_always_zero != 0 { + return 0 + } + return (*VP8LEncoder)(unsafe.Pointer(enc)).use_predict_ + }() +__6: + ; + // Reset any parameter in the encoder that is set in the previous iteration. + (*VP8LEncoder)(unsafe.Pointer(enc)).cache_bits_ = 0 + VP8LBackwardRefsClear(tls, (enc + 2152 /* &.refs_ */)) + VP8LBackwardRefsClear(tls, ((enc + 2152 /* &.refs_ */) + 1*40)) + + // Apply near-lossless preprocessing. + use_near_lossless = (libc.Bool32((((*WebPConfig)(unsafe.Pointer(config)).near_lossless < 100) && !((*VP8LEncoder)(unsafe.Pointer(enc)).use_palette_ != 0)) && !((*VP8LEncoder)(unsafe.Pointer(enc)).use_predict_ != 0))) + if !(use_near_lossless != 0) { + goto __7 + } + err = AllocateTransformBuffer(tls, enc, width, height) + if !(err != VP8_ENC_OK) { + goto __9 + } + goto Error +__9: + ; + if !(((*VP8LEncoder)(unsafe.Pointer(enc)).argb_content_ != kEncoderNearLossless) && !(VP8ApplyNearLossless(tls, picture, (*WebPConfig)(unsafe.Pointer(config)).near_lossless, (*VP8LEncoder)(unsafe.Pointer(enc)).argb_) != 0)) { + goto __10 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY + goto Error +__10: + ; + (*VP8LEncoder)(unsafe.Pointer(enc)).argb_content_ = kEncoderNearLossless + goto __8 +__7: + (*VP8LEncoder)(unsafe.Pointer(enc)).argb_content_ = kEncoderNone +__8: + ; + + // Encode palette + if !((*VP8LEncoder)(unsafe.Pointer(enc)).use_palette_ != 0) { + goto __11 + } + if !((*CrunchConfig)(unsafe.Pointer(crunch_configs+uintptr(idx)*28)).palette_sorting_type_ == kSortedDefault) { + goto __12 + } + // Nothing to do, we have already sorted the palette. + libc.Xmemcpy(tls, (enc + 100 /* &.palette_ */), (enc + 1124 /* &.palette_sorted_ */), + (uint64((*VP8LEncoder)(unsafe.Pointer(enc)).palette_size_) * uint64(unsafe.Sizeof(uint32_t(0))))) + goto __13 +__12: + if !((*CrunchConfig)(unsafe.Pointer(crunch_configs+uintptr(idx)*28)).palette_sorting_type_ == kMinimizeDelta) { + goto __14 + } + PaletteSortMinimizeDeltas(tls, (enc + 1124 /* &.palette_sorted_ */), (*VP8LEncoder)(unsafe.Pointer(enc)).palette_size_, + (enc + 100 /* &.palette_ */)) + goto __15 +__14: + ; + err = PaletteSortModifiedZeng(tls, (*VP8LEncoder)(unsafe.Pointer(enc)).pic_, (enc + 1124 /* &.palette_sorted_ */), + uint32((*VP8LEncoder)(unsafe.Pointer(enc)).palette_size_), (enc + 100 /* &.palette_ */)) + if !(err != VP8_ENC_OK) { + goto __16 + } + goto Error +__16: + ; +__15: + ; +__13: + ; + err = EncodePalette(tls, bw, low_effort, enc) + if !(err != VP8_ENC_OK) { + goto __17 + } + goto Error +__17: + ; + err = MapImageFromPalette(tls, enc, use_delta_palette) + if !(err != VP8_ENC_OK) { + goto __18 + } + goto Error +__18: + ; + // If using a color cache, do not have it bigger than the number of + // colors. + if !((use_cache != 0) && ((*VP8LEncoder)(unsafe.Pointer(enc)).palette_size_ < (int32(1) << 10))) { + goto __19 + } + (*VP8LEncoder)(unsafe.Pointer(enc)).cache_bits_ = (BitsLog2Floor(tls, uint32((*VP8LEncoder)(unsafe.Pointer(enc)).palette_size_)) + 1) +__19: + ; +__11: + ; + if !(!(use_delta_palette != 0)) { + goto __20 + } + // In case image is not packed. + if !(((*VP8LEncoder)(unsafe.Pointer(enc)).argb_content_ != kEncoderNearLossless) && ((*VP8LEncoder)(unsafe.Pointer(enc)).argb_content_ != kEncoderPalette)) { + goto __21 + } + err = MakeInputImageCopy(tls, enc) + if !(err != VP8_ENC_OK) { + goto __22 + } + goto Error +__22: + ; +__21: + ; + + // ----------------------------------------------------------------------- + // Apply transforms and write transform data. + + if !((*VP8LEncoder)(unsafe.Pointer(enc)).use_subtract_green_ != 0) { + goto __23 + } + ApplySubtractGreen(tls, enc, (*VP8LEncoder)(unsafe.Pointer(enc)).current_width_, height, bw) +__23: + ; + + if !((*VP8LEncoder)(unsafe.Pointer(enc)).use_predict_ != 0) { + goto __24 + } + err = ApplyPredictFilter(tls, enc, (*VP8LEncoder)(unsafe.Pointer(enc)).current_width_, height, quality, + low_effort, (*VP8LEncoder)(unsafe.Pointer(enc)).use_subtract_green_, bw) + if !(err != VP8_ENC_OK) { + goto __25 + } + goto Error +__25: + ; +__24: + ; + + if !((*VP8LEncoder)(unsafe.Pointer(enc)).use_cross_color_ != 0) { + goto __26 + } + err = ApplyCrossColorFilter(tls, enc, (*VP8LEncoder)(unsafe.Pointer(enc)).current_width_, height, quality, + low_effort, bw) + if !(err != VP8_ENC_OK) { + goto __27 + } + goto Error +__27: + ; +__26: + ; +__20: + ; + + VP8LPutBits(tls, bw, libc.BoolUint32(!(1 != 0)), 1) // No more transforms. + + // ------------------------------------------------------------------------- + // Encode and write the transformed image. + err = EncodeImageInternal(tls, bw, (*VP8LEncoder)(unsafe.Pointer(enc)).argb_, (enc + 2312 /* &.hash_chain_ */), (enc + 2152 /* &.refs_ */), + (*VP8LEncoder)(unsafe.Pointer(enc)).current_width_, height, quality, low_effort, + use_cache, (crunch_configs + uintptr(idx)*28), + (enc + 76 /* &.cache_bits_ */), (*VP8LEncoder)(unsafe.Pointer(enc)).histo_bits_, + byte_position, (bp + 48) /* &hdr_size */, (bp + 52) /* &data_size */) + if !(err != VP8_ENC_OK) { + goto __28 + } + goto Error +__28: + ; + + // If we are better than what we already have. + if !(VP8LBitWriterNumBytes(tls, bw) < best_size) { + goto __29 + } + best_size = VP8LBitWriterNumBytes(tls, bw) + // Store the BitWriter. + VP8LBitWriterSwap(tls, bw, (bp) /* &bw_best */) + // Update the stats. + if !(stats != (uintptr(0))) { + goto __30 + } + (*WebPAuxStats)(unsafe.Pointer(stats)).lossless_features = uint32_t(0) + if !((*VP8LEncoder)(unsafe.Pointer(enc)).use_predict_ != 0) { + goto __31 + } + *(*uint32_t)(unsafe.Pointer((stats + 148 /* &.lossless_features */))) |= (uint32_t(1)) +__31: + ; + if !((*VP8LEncoder)(unsafe.Pointer(enc)).use_cross_color_ != 0) { + goto __32 + } + *(*uint32_t)(unsafe.Pointer((stats + 148 /* &.lossless_features */))) |= (uint32_t(2)) +__32: + ; + if !((*VP8LEncoder)(unsafe.Pointer(enc)).use_subtract_green_ != 0) { + goto __33 + } + *(*uint32_t)(unsafe.Pointer((stats + 148 /* &.lossless_features */))) |= (uint32_t(4)) +__33: + ; + if !((*VP8LEncoder)(unsafe.Pointer(enc)).use_palette_ != 0) { + goto __34 + } + *(*uint32_t)(unsafe.Pointer((stats + 148 /* &.lossless_features */))) |= (uint32_t(8)) +__34: + ; + (*WebPAuxStats)(unsafe.Pointer(stats)).histogram_bits = (*VP8LEncoder)(unsafe.Pointer(enc)).histo_bits_ + (*WebPAuxStats)(unsafe.Pointer(stats)).transform_bits = (*VP8LEncoder)(unsafe.Pointer(enc)).transform_bits_ + (*WebPAuxStats)(unsafe.Pointer(stats)).cache_bits = (*VP8LEncoder)(unsafe.Pointer(enc)).cache_bits_ + (*WebPAuxStats)(unsafe.Pointer(stats)).palette_size = (*VP8LEncoder)(unsafe.Pointer(enc)).palette_size_ + (*WebPAuxStats)(unsafe.Pointer(stats)).lossless_size = (int32(best_size - byte_position)) + (*WebPAuxStats)(unsafe.Pointer(stats)).lossless_hdr_size = *(*int32)(unsafe.Pointer(bp + 48 /* hdr_size */)) + (*WebPAuxStats)(unsafe.Pointer(stats)).lossless_data_size = *(*int32)(unsafe.Pointer(bp + 52 /* data_size */)) +__30: + ; +__29: + ; + // Reset the bit writer for the following iteration if any. + if !(num_crunch_configs > 1) { + goto __35 + } + VP8LBitWriterReset(tls, (bp + 56) /* &bw_init */, bw) +__35: + ; + goto __3 +__3: + idx++ + goto __2 + goto __4 +__4: + ; + VP8LBitWriterSwap(tls, (bp) /* &bw_best */, bw) + +Error: + VP8LBitWriterWipeOut(tls, (bp) /* &bw_best */) + (*StreamEncodeContext)(unsafe.Pointer(params)).err_ = err + // The hook should return false in case of error. + return (libc.Bool32(err == VP8_ENC_OK)) +} + +func VP8LEncodeStream(tls *libc.TLS, config uintptr, picture uintptr, bw_main uintptr, use_cache int32) WebPEncodingError { /* vp8l_enc.c:1896:19: */ + bp := tls.Alloc(1124) + defer tls.Free(1124) + + var err WebPEncodingError + var enc_main uintptr + var enc_side uintptr + // var crunch_configs [8]CrunchConfig at bp, 224 + + // var num_crunch_configs_main int32 at bp+224, 4 + + var num_crunch_configs_side int32 + var idx int32 + // var red_and_blue_always_zero int32 at bp+228, 4 + + // var worker_main WebPWorker at bp+840, 48 + + // var worker_side WebPWorker at bp+888, 48 + + // var params_main StreamEncodeContext at bp+560, 280 + + // var params_side StreamEncodeContext at bp+280, 280 + + // The main thread uses picture->stats, the side thread uses stats_side. + // var stats_side WebPAuxStats at bp+936, 188 + + // var bw_side VP8LBitWriter at bp+232, 48 + + var worker_interface uintptr + var ok_main int32 + // Create the parameters for each worker. + var worker uintptr + var param uintptr + var params_size int32 + // Wait for the second thread. + var ok_side int32 + err = VP8_ENC_OK + enc_main = VP8LEncoderNew(tls, config, picture) + enc_side = (uintptr(0)) + num_crunch_configs_side = 0 + *(*int32)(unsafe.Pointer(bp + 228 /* red_and_blue_always_zero */)) = 0 + worker_interface = WebPGetWorkerInterface(tls) + + // Analyze image (entropy, num_palettes etc) + if !((((enc_main == (uintptr(0))) || !(EncoderAnalyze(tls, enc_main, (bp) /* &crunch_configs[0] */, (bp+224), /* &num_crunch_configs_main */ + (bp+228) /* &red_and_blue_always_zero */) != 0)) || !(EncoderInit(tls, enc_main) != 0)) || !(VP8LBitWriterInit(tls, (bp+232) /* &bw_side */, uint64(0)) != 0)) { + goto __1 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY + goto Error +__1: + ; + + // Split the configs between the main and side threads (if any). + if !((*WebPConfig)(unsafe.Pointer(config)).thread_level > 0) { + goto __2 + } + num_crunch_configs_side = (*(*int32)(unsafe.Pointer(bp + 224 /* num_crunch_configs_main */)) / 2) + idx = 0 +__3: + if !(idx < num_crunch_configs_side) { + goto __5 + } + *(*CrunchConfig)(unsafe.Pointer(((bp + 280) /* &params_side */ + 36 /* &.crunch_configs_ */) + uintptr(idx)*28)) = *(*CrunchConfig)(unsafe.Pointer((bp) /* &crunch_configs[0] */ + uintptr(((*(*int32)(unsafe.Pointer(bp + 224 /* num_crunch_configs_main */))-num_crunch_configs_side)+idx))*28)) + goto __4 +__4: + idx++ + goto __3 + goto __5 +__5: + ; + (*StreamEncodeContext)(unsafe.Pointer(bp + 280 /* &params_side */)).num_crunch_configs_ = num_crunch_configs_side +__2: + ; + *(*int32)(unsafe.Pointer(bp + 224 /* num_crunch_configs_main */)) -= num_crunch_configs_side + idx = 0 +__6: + if !(idx < *(*int32)(unsafe.Pointer(bp + 224 /* num_crunch_configs_main */))) { + goto __8 + } + *(*CrunchConfig)(unsafe.Pointer(((bp + 560) /* &params_main */ + 36 /* &.crunch_configs_ */) + uintptr(idx)*28)) = *(*CrunchConfig)(unsafe.Pointer((bp) /* &crunch_configs[0] */ + uintptr(idx)*28)) + goto __7 +__7: + idx++ + goto __6 + goto __8 +__8: + ; + (*StreamEncodeContext)(unsafe.Pointer(bp + 560 /* &params_main */)).num_crunch_configs_ = *(*int32)(unsafe.Pointer(bp + 224 /* num_crunch_configs_main */)) + + // Fill in the parameters for the thread workers. + + if num_crunch_configs_side > 0 { + params_size = 2 + } else { + params_size = 1 + } + idx = 0 +__9: + if !(idx < params_size) { + goto __11 + } + // Create the parameters for each worker. + if idx == 0 { + worker = (bp + 840) /* &worker_main */ + } else { + worker = (bp + 888) /* &worker_side */ + } + if idx == 0 { + param = (bp + 560) /* &params_main */ + } else { + param = (bp + 280) /* &params_side */ + } + (*StreamEncodeContext)(unsafe.Pointer(param)).config_ = config + (*StreamEncodeContext)(unsafe.Pointer(param)).picture_ = picture + (*StreamEncodeContext)(unsafe.Pointer(param)).use_cache_ = use_cache + (*StreamEncodeContext)(unsafe.Pointer(param)).red_and_blue_always_zero_ = *(*int32)(unsafe.Pointer(bp + 228 /* red_and_blue_always_zero */)) + if !(idx == 0) { + goto __12 + } + (*StreamEncodeContext)(unsafe.Pointer(param)).stats_ = (*WebPPicture)(unsafe.Pointer(picture)).stats + (*StreamEncodeContext)(unsafe.Pointer(param)).bw_ = bw_main + (*StreamEncodeContext)(unsafe.Pointer(param)).enc_ = enc_main + goto __13 +__12: + (*StreamEncodeContext)(unsafe.Pointer(param)).stats_ = func() uintptr { + if (*WebPPicture)(unsafe.Pointer(picture)).stats == (uintptr(0)) { + return (uintptr(0)) + } + return (bp + 936) /* &stats_side */ + }() + // Create a side bit writer. + if !(!(VP8LBitWriterClone(tls, bw_main, (bp+232) /* &bw_side */) != 0)) { + goto __14 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY + goto Error +__14: + ; + (*StreamEncodeContext)(unsafe.Pointer(param)).bw_ = (bp + 232) /* &bw_side */ + // Create a side encoder. + enc_side = VP8LEncoderNew(tls, config, picture) + if !((enc_side == (uintptr(0))) || !(EncoderInit(tls, enc_side) != 0)) { + goto __15 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY + goto Error +__15: + ; + // Copy the values that were computed for the main encoder. + (*VP8LEncoder)(unsafe.Pointer(enc_side)).histo_bits_ = (*VP8LEncoder)(unsafe.Pointer(enc_main)).histo_bits_ + (*VP8LEncoder)(unsafe.Pointer(enc_side)).transform_bits_ = (*VP8LEncoder)(unsafe.Pointer(enc_main)).transform_bits_ + (*VP8LEncoder)(unsafe.Pointer(enc_side)).palette_size_ = (*VP8LEncoder)(unsafe.Pointer(enc_main)).palette_size_ + libc.Xmemcpy(tls, (enc_side + 100 /* &.palette_ */), (enc_main + 100 /* &.palette_ */), + uint64(unsafe.Sizeof([256]uint32_t{}))) + libc.Xmemcpy(tls, (enc_side + 1124 /* &.palette_sorted_ */), (enc_main + 1124 /* &.palette_sorted_ */), + uint64(unsafe.Sizeof([256]uint32_t{}))) + (*StreamEncodeContext)(unsafe.Pointer(param)).enc_ = enc_side +__13: + ; + // Create the workers. + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).Init})).f(tls, worker) + (*WebPWorker)(unsafe.Pointer(worker)).data1 = param + (*WebPWorker)(unsafe.Pointer(worker)).data2 = (uintptr(0)) + (*WebPWorker)(unsafe.Pointer(worker)).hook = *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{EncodeStreamHook})) + goto __10 +__10: + idx++ + goto __9 + goto __11 +__11: + ; + + // Start the second thread if needed. + if !(num_crunch_configs_side != 0) { + goto __16 + } + if !(!((*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).Reset})).f(tls, (bp+888) /* &worker_side */) != 0)) { + goto __17 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY + goto Error +__17: + ; + // This line is here and not in the param initialization above to remove a + // Clang static analyzer warning. + if !((*WebPPicture)(unsafe.Pointer(picture)).stats != (uintptr(0))) { + goto __18 + } + libc.Xmemcpy(tls, (bp + 936) /* &stats_side */, (*WebPPicture)(unsafe.Pointer(picture)).stats, uint64(unsafe.Sizeof(WebPAuxStats{}))) +__18: + ; + // This line is only useful to remove a Clang static analyzer warning. + (*StreamEncodeContext)(unsafe.Pointer(bp + 280 /* &params_side */)).err_ = VP8_ENC_OK + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).Launch})).f(tls, (bp + 888) /* &worker_side */) +__16: + ; + // Execute the main thread. + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).Execute})).f(tls, (bp + 840) /* &worker_main */) + ok_main = (*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).Sync})).f(tls, (bp + 840) /* &worker_main */) + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).End})).f(tls, (bp + 840) /* &worker_main */) + if !(num_crunch_configs_side != 0) { + goto __19 + } + // Wait for the second thread. + ok_side = (*struct { + f func(*libc.TLS, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).Sync})).f(tls, (bp + 888) /* &worker_side */) + (*struct{ f func(*libc.TLS, uintptr) })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorkerInterface)(unsafe.Pointer(worker_interface)).End})).f(tls, (bp + 888) /* &worker_side */) + if !(!(ok_main != 0) || !(ok_side != 0)) { + goto __21 + } + if ok_main != 0 { + err = (*StreamEncodeContext)(unsafe.Pointer(bp + 280 /* &params_side */)).err_ + } else { + err = (*StreamEncodeContext)(unsafe.Pointer(bp + 560 /* &params_main */)).err_ + } + goto Error +__21: + ; + if !(VP8LBitWriterNumBytes(tls, (bp+232) /* &bw_side */) < VP8LBitWriterNumBytes(tls, bw_main)) { + goto __22 + } + VP8LBitWriterSwap(tls, bw_main, (bp + 232) /* &bw_side */) + if !((*WebPPicture)(unsafe.Pointer(picture)).stats != (uintptr(0))) { + goto __23 + } + libc.Xmemcpy(tls, (*WebPPicture)(unsafe.Pointer(picture)).stats, (bp + 936) /* &stats_side */, uint64(unsafe.Sizeof(WebPAuxStats{}))) +__23: + ; +__22: + ; + goto __20 +__19: + if !(!(ok_main != 0)) { + goto __24 + } + err = (*StreamEncodeContext)(unsafe.Pointer(bp + 560 /* &params_main */)).err_ + goto Error +__24: + ; +__20: + ; + +Error: + VP8LBitWriterWipeOut(tls, (bp + 232) /* &bw_side */) + VP8LEncoderDelete(tls, enc_main) + VP8LEncoderDelete(tls, enc_side) + return err +} + +func VP8LEncodeImage(tls *libc.TLS, config uintptr, picture uintptr) int32 { /* vp8l_enc.c:2042:5: */ + bp := tls.Alloc(64) + defer tls.Free(64) + + var width int32 + var height int32 + var has_alpha int32 + // var coded_size size_t at bp+56, 8 + + // var percent int32 at bp+48, 4 + + var initial_size int32 + var err WebPEncodingError + // var bw VP8LBitWriter at bp, 48 + + var stats uintptr + var mb_w int32 + var mb_h int32 + *(*int32)(unsafe.Pointer(bp + 48 /* percent */)) = 0 + err = VP8_ENC_OK + + if !(picture == (uintptr(0))) { + goto __1 + } + return 0 +__1: + ; + + if !((config == (uintptr(0))) || ((*WebPPicture)(unsafe.Pointer(picture)).argb == (uintptr(0)))) { + goto __2 + } + err = VP8_ENC_ERROR_NULL_PARAMETER + WebPEncodingSetError(tls, picture, err) + return 0 +__2: + ; + + width = (*WebPPicture)(unsafe.Pointer(picture)).width + height = (*WebPPicture)(unsafe.Pointer(picture)).height + // Initialize BitWriter with size corresponding to 16 bpp to photo images and + // 8 bpp for graphical images. + if (*WebPConfig)(unsafe.Pointer(config)).image_hint == WEBP_HINT_GRAPH { + initial_size = (width * height) + } else { + initial_size = ((width * height) * 2) + } + if !(!(VP8LBitWriterInit(tls, (bp) /* &bw */, uint64(initial_size)) != 0)) { + goto __3 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY + goto Error +__3: + ; + + if !(!(WebPReportProgress(tls, picture, 1, (bp+48) /* &percent */) != 0)) { + goto __4 + } +UserAbort: + err = VP8_ENC_ERROR_USER_ABORT + goto Error +__4: + ; + // Reset stats (for pure lossless coding) + if !((*WebPPicture)(unsafe.Pointer(picture)).stats != (uintptr(0))) { + goto __5 + } + stats = (*WebPPicture)(unsafe.Pointer(picture)).stats + libc.Xmemset(tls, stats, 0, uint64(unsafe.Sizeof(WebPAuxStats{}))) + *(*float32)(unsafe.Pointer((stats + 4 /* &.PSNR */))) = 99. + *(*float32)(unsafe.Pointer((stats + 4 /* &.PSNR */) + 1*4)) = 99. + *(*float32)(unsafe.Pointer((stats + 4 /* &.PSNR */) + 2*4)) = 99. + *(*float32)(unsafe.Pointer((stats + 4 /* &.PSNR */) + 3*4)) = 99. + *(*float32)(unsafe.Pointer((stats + 4 /* &.PSNR */) + 4*4)) = 99. +__5: + ; + + // Write image size. + if !(!(WriteImageSize(tls, picture, (bp) /* &bw */) != 0)) { + goto __6 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY + goto Error +__6: + ; + + has_alpha = WebPPictureHasTransparency(tls, picture) + // Write the non-trivial Alpha flag and lossless version. + if !(!(WriteRealAlphaAndVersion(tls, (bp) /* &bw */, has_alpha) != 0)) { + goto __7 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY + goto Error +__7: + ; + + if !(!(WebPReportProgress(tls, picture, 5, (bp+48) /* &percent */) != 0)) { + goto __8 + } + goto UserAbort +__8: + ; + + // Encode main image stream. + err = VP8LEncodeStream(tls, config, picture, (bp) /* &bw */, 1) + if !(err != VP8_ENC_OK) { + goto __9 + } + goto Error +__9: + ; + + if !(!(WebPReportProgress(tls, picture, 90, (bp+48) /* &percent */) != 0)) { + goto __10 + } + goto UserAbort +__10: + ; + + // Finish the RIFF chunk. + err = WriteImage(tls, picture, (bp) /* &bw */, (bp + 56) /* &coded_size */) + if !(err != VP8_ENC_OK) { + goto __11 + } + goto Error +__11: + ; + + if !(!(WebPReportProgress(tls, picture, 100, (bp+48) /* &percent */) != 0)) { + goto __12 + } + goto UserAbort +__12: + ; + + // Save size. + if !((*WebPPicture)(unsafe.Pointer(picture)).stats != (uintptr(0))) { + goto __13 + } + *(*int32)(unsafe.Pointer(((*WebPPicture)(unsafe.Pointer(picture)).stats /* &.coded_size */))) += (int32(*(*size_t)(unsafe.Pointer(bp + 56 /* coded_size */)))) + (*WebPAuxStats)(unsafe.Pointer((*WebPPicture)(unsafe.Pointer(picture)).stats)).lossless_size = int32(*(*size_t)(unsafe.Pointer(bp + 56 /* coded_size */))) +__13: + ; + + if !((*WebPPicture)(unsafe.Pointer(picture)).extra_info != (uintptr(0))) { + goto __14 + } + mb_w = ((width + 15) >> 4) + mb_h = ((height + 15) >> 4) + libc.Xmemset(tls, (*WebPPicture)(unsafe.Pointer(picture)).extra_info, 0, ((uint64(mb_w * mb_h)) * uint64(unsafe.Sizeof(uint8_t(0))))) +__14: + ; + +Error: + if !((*VP8LBitWriter)(unsafe.Pointer(bp /* &bw */)).error_ != 0) { + goto __15 + } + err = VP8_ENC_ERROR_OUT_OF_MEMORY +__15: + ; + VP8LBitWriterWipeOut(tls, (bp) /* &bw */) + if !(err != VP8_ENC_OK) { + goto __16 + } + WebPEncodingSetError(tls, picture, err) + return 0 +__16: + ; + return 1 +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +// #define PRINT_MEMORY_INFO + +//------------------------------------------------------------------------------ + +func WebPGetEncoderVersion(tls *libc.TLS) int32 { /* webp_enc.c:32:5: */ + return (((int32(1) << 16) | (int32(2) << 8)) | 2) +} + +//------------------------------------------------------------------------------ +// VP8Encoder +//------------------------------------------------------------------------------ + +func ResetSegmentHeader1(tls *libc.TLS, enc uintptr) { /* webp_enc.c:40:13: */ + var hdr uintptr = (enc + 32 /* &.segment_hdr_ */) + (*VP8EncSegmentHeader)(unsafe.Pointer(hdr)).num_segments_ = (*WebPConfig)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).config_)).segments + (*VP8EncSegmentHeader)(unsafe.Pointer(hdr)).update_map_ = (libc.Bool32((*VP8EncSegmentHeader)(unsafe.Pointer(hdr)).num_segments_ > 1)) + (*VP8EncSegmentHeader)(unsafe.Pointer(hdr)).size_ = 0 +} + +func ResetFilterHeader(tls *libc.TLS, enc uintptr) { /* webp_enc.c:47:13: */ + var hdr uintptr = (enc + 16 /* &.filter_hdr_ */) + (*VP8EncFilterHeader)(unsafe.Pointer(hdr)).simple_ = 1 + (*VP8EncFilterHeader)(unsafe.Pointer(hdr)).level_ = 0 + (*VP8EncFilterHeader)(unsafe.Pointer(hdr)).sharpness_ = 0 + (*VP8EncFilterHeader)(unsafe.Pointer(hdr)).i4x4_lf_delta_ = 0 +} + +func ResetBoundaryPredictions(tls *libc.TLS, enc uintptr) { /* webp_enc.c:55:13: */ + // init boundary values once for all + // Note: actually, initializing the preds_[] is only needed for intra4. + var i int32 + var top uintptr = ((*VP8Encoder)(unsafe.Pointer(enc)).preds_ - uintptr((*VP8Encoder)(unsafe.Pointer(enc)).preds_w_)) + var left uintptr = ((*VP8Encoder)(unsafe.Pointer(enc)).preds_ - uintptr(1)) + for i = -1; i < (4 * (*VP8Encoder)(unsafe.Pointer(enc)).mb_w_); i++ { + *(*uint8_t)(unsafe.Pointer(top + uintptr(i))) = B_DC_PRED + } + for i = 0; i < (4 * (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_); i++ { + *(*uint8_t)(unsafe.Pointer(left + uintptr((i * (*VP8Encoder)(unsafe.Pointer(enc)).preds_w_)))) = B_DC_PRED + } + *(*uint32_t)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).nz_ + libc.UintptrFromInt32(-1)*4)) = uint32_t(0) // constant +} + +// Mapping from config->method_ to coding tools used. +//-------------------+---+---+---+---+---+---+---+ +// Method | 0 | 1 | 2 | 3 |(4)| 5 | 6 | +//-------------------+---+---+---+---+---+---+---+ +// fast probe | x | | | x | | | | +//-------------------+---+---+---+---+---+---+---+ +// dynamic proba | ~ | x | x | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// fast mode analysis|[x]|[x]| | | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// basic rd-opt | | | | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// disto-refine i4/16| x | x | x | | | | | +//-------------------+---+---+---+---+---+---+---+ +// disto-refine uv | | x | x | | | | | +//-------------------+---+---+---+---+---+---+---+ +// rd-opt i4/16 | | | ~ | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// token buffer (opt)| | | | x | x | x | x | +//-------------------+---+---+---+---+---+---+---+ +// Trellis | | | | | | x |Ful| +//-------------------+---+---+---+---+---+---+---+ +// full-SNS | | | | | x | x | x | +//-------------------+---+---+---+---+---+---+---+ + +func MapConfigToTools(tls *libc.TLS, enc uintptr) { /* webp_enc.c:95:13: */ + var config uintptr = (*VP8Encoder)(unsafe.Pointer(enc)).config_ + var method int32 = (*WebPConfig)(unsafe.Pointer(config)).method + var limit int32 = (100 - (*WebPConfig)(unsafe.Pointer(config)).partition_limit) + (*VP8Encoder)(unsafe.Pointer(enc)).method_ = method + (*VP8Encoder)(unsafe.Pointer(enc)).rd_opt_level_ = func() uint32 { + if method >= 6 { + return RD_OPT_TRELLIS_ALL + } + return func() uint32 { + if method >= 5 { + return RD_OPT_TRELLIS + } + return func() uint32 { + if method >= 3 { + return RD_OPT_BASIC + } + return RD_OPT_NONE + }() + }() + }() + (*VP8Encoder)(unsafe.Pointer(enc)).max_i4_header_bits_ = ((((256 * 16) * 16) * (limit * limit)) / (100 * 100)) // ... modulated with a quadratic curve. + + // partition0 = 512k max. + (*VP8Encoder)(unsafe.Pointer(enc)).mb_header_limit_ = (int32((((int64(256) * int64(510)) * int64(8)) * int64(1024)) / (score_t((*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ * (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_)))) + + (*VP8Encoder)(unsafe.Pointer(enc)).thread_level_ = (*WebPConfig)(unsafe.Pointer(config)).thread_level + + (*VP8Encoder)(unsafe.Pointer(enc)).do_search_ = (libc.Bool32(((*WebPConfig)(unsafe.Pointer(config)).target_size > 0) || ((*WebPConfig)(unsafe.Pointer(config)).target_PSNR > float32(0)))) + if !((*WebPConfig)(unsafe.Pointer(config)).low_memory != 0) { + (*VP8Encoder)(unsafe.Pointer(enc)).use_tokens_ = (libc.Bool32((*VP8Encoder)(unsafe.Pointer(enc)).rd_opt_level_ >= RD_OPT_BASIC)) // need rd stats + if (*VP8Encoder)(unsafe.Pointer(enc)).use_tokens_ != 0 { + (*VP8Encoder)(unsafe.Pointer(enc)).num_parts_ = 1 // doesn't work with multi-partition + } + } +} + +// Memory scaling with dimensions: +// memory (bytes) ~= 2.25 * w + 0.0625 * w * h +// +// Typical memory footprint (614x440 picture) +// encoder: 22111 +// info: 4368 +// preds: 17741 +// top samples: 1263 +// non-zero: 175 +// lf-stats: 0 +// total: 45658 +// Transient object sizes: +// VP8EncIterator: 3360 +// VP8ModeScore: 872 +// VP8SegmentInfo: 732 +// VP8EncProba: 18352 +// LFStats: 2048 +// Picture size (yuv): 419328 + +func InitVP8Encoder(tls *libc.TLS, config uintptr, picture uintptr) uintptr { /* webp_enc.c:144:18: */ + var enc uintptr + var use_filter int32 = (libc.Bool32(((*WebPConfig)(unsafe.Pointer(config)).filter_strength > 0) || ((*WebPConfig)(unsafe.Pointer(config)).autofilter > 0))) + var mb_w int32 = (((*WebPPicture)(unsafe.Pointer(picture)).width + 15) >> 4) + var mb_h int32 = (((*WebPPicture)(unsafe.Pointer(picture)).height + 15) >> 4) + var preds_w int32 = ((4 * mb_w) + 1) + var preds_h int32 = ((4 * mb_h) + 1) + var preds_size size_t = ((uint64(preds_w * preds_h)) * uint64(unsafe.Sizeof(uint8_t(0)))) + var top_stride int32 = (mb_w * 16) + var nz_size size_t = (((uint64(mb_w + 1)) * uint64(unsafe.Sizeof(uint32_t(0)))) + uint64(31)) + var info_size size_t = ((uint64(mb_w * mb_h)) * uint64(unsafe.Sizeof(VP8MBInfo{}))) + var samples_size size_t = (((uint64(2 * top_stride)) * uint64(unsafe.Sizeof(uint8_t(0)))) + // top-luma/u/v + uint64(31)) // align all + var lf_stats_size size_t + if (*WebPConfig)(unsafe.Pointer(config)).autofilter != 0 { + lf_stats_size = (uint64(unsafe.Sizeof(LFStats{})) + uint64(31)) + } else { + lf_stats_size = uint64(0) + } + var top_derr_size size_t + if ((*WebPConfig)(unsafe.Pointer(config)).quality <= float32(98)) || ((*WebPConfig)(unsafe.Pointer(config)).pass > 1) { + top_derr_size = (uint64(mb_w) * uint64(unsafe.Sizeof(DError{}))) + } else { + top_derr_size = uint64(0) + } + var mem uintptr + var size uint64_t = (((((((uint64_t(unsafe.Sizeof(VP8Encoder{})) + // main struct + uint64(31)) + // cache alignment + info_size) + // modes info + preds_size) + // prediction modes + samples_size) + // top/left samples + top_derr_size) + // top diffusion error + nz_size) + // coeff context bits + lf_stats_size) // autofilter stats + + mem = WebPSafeMalloc(tls, size, uint64(unsafe.Sizeof(uint8_t(0)))) + if mem == (uintptr(0)) { + WebPEncodingSetError(tls, picture, VP8_ENC_ERROR_OUT_OF_MEMORY) + return (uintptr(0)) + } + enc = mem + mem = (uintptr((uintptr_t((mem + uintptr(uint64(unsafe.Sizeof(VP8Encoder{}))))) + uint64(31)) & libc.Uint64FromInt32(libc.CplInt32(31)))) + libc.Xmemset(tls, enc, 0, uint64(unsafe.Sizeof(VP8Encoder{}))) + (*VP8Encoder)(unsafe.Pointer(enc)).num_parts_ = (int32(1) << (*WebPConfig)(unsafe.Pointer(config)).partitions) + (*VP8Encoder)(unsafe.Pointer(enc)).mb_w_ = mb_w + (*VP8Encoder)(unsafe.Pointer(enc)).mb_h_ = mb_h + (*VP8Encoder)(unsafe.Pointer(enc)).preds_w_ = preds_w + (*VP8Encoder)(unsafe.Pointer(enc)).mb_info_ = mem + mem += uintptr(info_size) + (*VP8Encoder)(unsafe.Pointer(enc)).preds_ = ((mem + uintptr(1)) + uintptr((*VP8Encoder)(unsafe.Pointer(enc)).preds_w_)) + mem += uintptr(preds_size) + (*VP8Encoder)(unsafe.Pointer(enc)).nz_ = (uintptr(1)*4 + (uintptr((uintptr_t((mem)) + uint64(31)) & libc.Uint64FromInt32(libc.CplInt32(31))))) + mem += uintptr(nz_size) + (*VP8Encoder)(unsafe.Pointer(enc)).lf_stats_ = func() uintptr { + if lf_stats_size != 0 { + return (uintptr((uintptr_t((mem)) + uint64(31)) & libc.Uint64FromInt32(libc.CplInt32(31)))) + } + return (uintptr(0)) + }() + mem += uintptr(lf_stats_size) + + // top samples (all 16-aligned) + mem = (uintptr((uintptr_t((mem)) + uint64(31)) & libc.Uint64FromInt32(libc.CplInt32(31)))) + (*VP8Encoder)(unsafe.Pointer(enc)).y_top_ = mem + (*VP8Encoder)(unsafe.Pointer(enc)).uv_top_ = ((*VP8Encoder)(unsafe.Pointer(enc)).y_top_ + uintptr(top_stride)) + mem += (uintptr(2 * top_stride)) + (*VP8Encoder)(unsafe.Pointer(enc)).top_derr_ = func() uintptr { + if top_derr_size != 0 { + return mem + } + return (uintptr(0)) + }() + mem += uintptr(top_derr_size) + + (*VP8Encoder)(unsafe.Pointer(enc)).config_ = config + (*VP8Encoder)(unsafe.Pointer(enc)).profile_ = func() int32 { + if use_filter != 0 { + return (func() int32 { + if (*WebPConfig)(unsafe.Pointer(config)).filter_type == 1 { + return 0 + } + return 1 + }()) + } + return 2 + }() + (*VP8Encoder)(unsafe.Pointer(enc)).pic_ = picture + (*VP8Encoder)(unsafe.Pointer(enc)).percent_ = 0 + + MapConfigToTools(tls, enc) + VP8EncDspInit(tls) + VP8DefaultProbas(tls, enc) + ResetSegmentHeader1(tls, enc) + ResetFilterHeader(tls, enc) + ResetBoundaryPredictions(tls, enc) + VP8EncDspCostInit(tls) + VP8EncInitAlpha(tls, enc) + + // lower quality means smaller output -> we modulate a little the page + // size based on quality. This is just a crude 1rst-order prediction. + { + var scale float32 = (1. + (((*WebPConfig)(unsafe.Pointer(config)).quality * 5.) / 100.)) // in [1,6] + VP8TBufferInit(tls, (enc + 496 /* &.tokens_ */), (libc.Int32FromFloat32((float32((mb_w * mb_h) * 4)) * scale))) + + } + return enc +} + +func DeleteVP8Encoder(tls *libc.TLS, enc uintptr) int32 { /* webp_enc.c:254:12: */ + var ok int32 = 1 + if enc != (uintptr(0)) { + ok = VP8EncDeleteAlpha(tls, enc) + VP8TBufferClear(tls, (enc + 496 /* &.tokens_ */)) + WebPSafeFree(tls, enc) + } + return ok +} + +//------------------------------------------------------------------------------ + +func GetPSNR2(tls *libc.TLS, err uint64_t, size uint64_t) float64 { /* webp_enc.c:267:15: */ + if (err > uint64(0)) && (size > uint64(0)) { + return (10. * libc.Xlog10(tls, (((float64(255.)*255.)*float64(size))/float64(err)))) + } + return 99. +} + +func FinalizePSNR(tls *libc.TLS, enc uintptr) { /* webp_enc.c:271:13: */ + var stats uintptr = (*WebPPicture)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).pic_)).stats + var size uint64_t = (*VP8Encoder)(unsafe.Pointer(enc)).sse_count_ + var sse uintptr = enc + 23512 /* &.sse_ */ + *(*float32)(unsafe.Pointer((stats + 4 /* &.PSNR */))) = float32(GetPSNR2(tls, *(*uint64_t)(unsafe.Pointer(sse)), size)) + *(*float32)(unsafe.Pointer((stats + 4 /* &.PSNR */) + 1*4)) = float32(GetPSNR2(tls, *(*uint64_t)(unsafe.Pointer(sse + 1*8)), (size / uint64(4)))) + *(*float32)(unsafe.Pointer((stats + 4 /* &.PSNR */) + 2*4)) = float32(GetPSNR2(tls, *(*uint64_t)(unsafe.Pointer(sse + 2*8)), (size / uint64(4)))) + *(*float32)(unsafe.Pointer((stats + 4 /* &.PSNR */) + 3*4)) = float32(GetPSNR2(tls, ((*(*uint64_t)(unsafe.Pointer(sse)) + *(*uint64_t)(unsafe.Pointer(sse + 1*8))) + *(*uint64_t)(unsafe.Pointer(sse + 2*8))), ((size * uint64(3)) / uint64(2)))) + *(*float32)(unsafe.Pointer((stats + 4 /* &.PSNR */) + 4*4)) = float32(GetPSNR2(tls, *(*uint64_t)(unsafe.Pointer(sse + 3*8)), size)) +} + +func StoreStats(tls *libc.TLS, enc uintptr) { /* webp_enc.c:283:13: */ + var stats uintptr = (*WebPPicture)(unsafe.Pointer((*VP8Encoder)(unsafe.Pointer(enc)).pic_)).stats + if stats != (uintptr(0)) { + var i int32 + var s int32 + for i = 0; i < NUM_MB_SEGMENTS; i++ { + *(*int32)(unsafe.Pointer((stats + 124 /* &.segment_level */) + uintptr(i)*4)) = (*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */) + uintptr(i)*744)).fstrength_ + *(*int32)(unsafe.Pointer((stats + 108 /* &.segment_quant */) + uintptr(i)*4)) = (*VP8SegmentInfo)(unsafe.Pointer((enc + 608 /* &.dqm_ */) + uintptr(i)*744)).quant_ + for s = 0; s <= 2; s++ { + *(*int32)(unsafe.Pointer(((stats + 44 /* &.residual_bytes */) + uintptr(s)*16) + uintptr(i)*4)) = *(*int32)(unsafe.Pointer(((enc + 23556 /* &.residual_bytes_ */) + uintptr(s)*16) + uintptr(i)*4)) + } + } + FinalizePSNR(tls, enc) + (*WebPAuxStats)(unsafe.Pointer(stats)).coded_size = (*VP8Encoder)(unsafe.Pointer(enc)).coded_size_ + for i = 0; i < 3; i++ { + *(*int32)(unsafe.Pointer((stats + 24 /* &.block_count */) + uintptr(i)*4)) = *(*int32)(unsafe.Pointer((enc + 23604 /* &.block_count_ */) + uintptr(i)*4)) + } + } +} + +func WebPEncodingSetError(tls *libc.TLS, pic uintptr, error WebPEncodingError) int32 { /* webp_enc.c:306:5: */ + + (*WebPPicture)(unsafe.Pointer((pic))).error_code = error + return 0 +} + +func WebPReportProgress(tls *libc.TLS, pic uintptr, percent int32, percent_store uintptr) int32 { /* webp_enc.c:314:5: */ + if (percent_store != (uintptr(0))) && (percent != *(*int32)(unsafe.Pointer(percent_store))) { + *(*int32)(unsafe.Pointer(percent_store)) = percent + if ((*WebPPicture)(unsafe.Pointer(pic)).progress_hook != 0) && !((*struct { + f func(*libc.TLS, int32, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPPicture)(unsafe.Pointer(pic)).progress_hook})).f(tls, percent, pic) != 0) { + // user abort requested + WebPEncodingSetError(tls, pic, VP8_ENC_ERROR_USER_ABORT) + return 0 + } + } + return 1 // ok +} + +//------------------------------------------------------------------------------ + +func WebPEncode(tls *libc.TLS, config uintptr, pic uintptr) int32 { /* webp_enc.c:328:5: */ + var ok int32 = 0 + if pic == (uintptr(0)) { + return 0 + } + + WebPEncodingSetError(tls, pic, VP8_ENC_OK) // all ok so far + if config == (uintptr(0)) { // bad params + return WebPEncodingSetError(tls, pic, VP8_ENC_ERROR_NULL_PARAMETER) + } + if !(WebPValidateConfig(tls, config) != 0) { + return WebPEncodingSetError(tls, pic, VP8_ENC_ERROR_INVALID_CONFIGURATION) + } + if ((*WebPPicture)(unsafe.Pointer(pic)).width <= 0) || ((*WebPPicture)(unsafe.Pointer(pic)).height <= 0) { + return WebPEncodingSetError(tls, pic, VP8_ENC_ERROR_BAD_DIMENSION) + } + if ((*WebPPicture)(unsafe.Pointer(pic)).width > 16383) || ((*WebPPicture)(unsafe.Pointer(pic)).height > 16383) { + return WebPEncodingSetError(tls, pic, VP8_ENC_ERROR_BAD_DIMENSION) + } + + if (*WebPPicture)(unsafe.Pointer(pic)).stats != (uintptr(0)) { + libc.Xmemset(tls, (*WebPPicture)(unsafe.Pointer(pic)).stats, 0, uint64(unsafe.Sizeof(WebPAuxStats{}))) + } + + if !((*WebPConfig)(unsafe.Pointer(config)).lossless != 0) { + var enc uintptr = (uintptr(0)) + + if ((((*WebPPicture)(unsafe.Pointer(pic)).use_argb != 0) || ((*WebPPicture)(unsafe.Pointer(pic)).y == (uintptr(0)))) || ((*WebPPicture)(unsafe.Pointer(pic)).u == (uintptr(0)))) || ((*WebPPicture)(unsafe.Pointer(pic)).v == (uintptr(0))) { + // Make sure we have YUVA samples. + if ((*WebPConfig)(unsafe.Pointer(config)).use_sharp_yuv != 0) || (((*WebPConfig)(unsafe.Pointer(config)).preprocessing & 4) != 0) { + if !(WebPPictureSharpARGBToYUVA(tls, pic) != 0) { + return 0 + } + } else { + var dithering float32 = 0. + if ((*WebPConfig)(unsafe.Pointer(config)).preprocessing & 2) != 0 { + var x float32 = ((*WebPConfig)(unsafe.Pointer(config)).quality / 100.) + var x2 float32 = (x * x) + // slowly decreasing from max dithering at low quality (q->0) + // to 0.5 dithering amplitude at high quality (q->100) + dithering = (1.0 + (((float32(0.5) - 1.0) * x2) * x2)) + } + if !(WebPPictureARGBToYUVADithered(tls, pic, WEBP_YUV420, dithering) != 0) { + return 0 + } + } + } + + if !((*WebPConfig)(unsafe.Pointer(config)).exact != 0) { + WebPCleanupTransparentArea(tls, pic) + } + + enc = InitVP8Encoder(tls, config, pic) + if enc == (uintptr(0)) { + return 0 + } // pic->error is already set. + // Note: each of the tasks below account for 20% in the progress report. + ok = VP8EncAnalyze(tls, enc) + + // Analysis is done, proceed to actual coding. + ok = (libc.Bool32((ok != 0) && (VP8EncStartAlpha(tls, enc) != 0))) // possibly done in parallel + if !((*VP8Encoder)(unsafe.Pointer(enc)).use_tokens_ != 0) { + ok = (libc.Bool32((ok != 0) && (VP8EncLoop(tls, enc) != 0))) + } else { + ok = (libc.Bool32((ok != 0) && (VP8EncTokenLoop(tls, enc) != 0))) + } + ok = (libc.Bool32((ok != 0) && (VP8EncFinishAlpha(tls, enc) != 0))) + + ok = (libc.Bool32((ok != 0) && (VP8EncWrite(tls, enc) != 0))) + StoreStats(tls, enc) + if !(ok != 0) { + VP8EncFreeBitWriters(tls, enc) + } + ok = ok & (DeleteVP8Encoder(tls, enc)) // must always be called, even if !ok + } else { + // Make sure we have ARGB samples. + if ((*WebPPicture)(unsafe.Pointer(pic)).argb == (uintptr(0))) && !(WebPPictureYUVAToARGB(tls, pic) != 0) { + return 0 + } + + if !((*WebPConfig)(unsafe.Pointer(config)).exact != 0) { + WebPReplaceTransparentPixels(tls, pic, uint32(0x000000)) + } + + ok = VP8LEncodeImage(tls, config, pic) // Sets pic->error in case of problem. + } + + return ok +} + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Misc. common utility functions +// +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) + +//------------------------------------------------------------------------------ +// VP8BitReader + +func VP8BitReaderSetBuffer(tls *libc.TLS, br uintptr, start uintptr, size size_t) { /* bit_reader_utils.c:24:6: */ + (*VP8BitReader)(unsafe.Pointer(br)).buf_ = start + (*VP8BitReader)(unsafe.Pointer(br)).buf_end_ = (start + uintptr(size)) + (*VP8BitReader)(unsafe.Pointer(br)).buf_max_ = func() uintptr { + if size >= size_t(unsafe.Sizeof(lbit_t(0))) { + return (((start + uintptr(size)) - uintptr(uint64(unsafe.Sizeof(lbit_t(0))))) + uintptr(1)) + } + return start + }() +} + +func VP8InitBitReader(tls *libc.TLS, br uintptr, start uintptr, size size_t) { /* bit_reader_utils.c:34:6: */ + + // limit ensured by format and upstream checks + (*VP8BitReader)(unsafe.Pointer(br)).range_ = (range_t(255 - 1)) + (*VP8BitReader)(unsafe.Pointer(br)).value_ = uint64(0) + (*VP8BitReader)(unsafe.Pointer(br)).bits_ = -8 // to load the very first 8bits + (*VP8BitReader)(unsafe.Pointer(br)).eof_ = 0 + VP8BitReaderSetBuffer(tls, br, start, size) + VP8LoadNewBytes(tls, br) +} + +func VP8RemapBitReader(tls *libc.TLS, br uintptr, offset ptrdiff_t) { /* bit_reader_utils.c:47:6: */ + if (*VP8BitReader)(unsafe.Pointer(br)).buf_ != (uintptr(0)) { + *(*uintptr)(unsafe.Pointer((br + 16 /* &.buf_ */))) += (uintptr(offset)) + *(*uintptr)(unsafe.Pointer((br + 24 /* &.buf_end_ */))) += (uintptr(offset)) + *(*uintptr)(unsafe.Pointer((br + 32 /* &.buf_max_ */))) += (uintptr(offset)) + } +} + +var kVP8Log2Range = [128]uint8_t{ + uint8_t(7), uint8_t(6), uint8_t(6), uint8_t(5), uint8_t(5), uint8_t(5), uint8_t(5), uint8_t(4), uint8_t(4), uint8_t(4), uint8_t(4), uint8_t(4), uint8_t(4), uint8_t(4), uint8_t(4), + uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), + uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), + uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), + uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), + uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), + uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), + uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), + uint8_t(0), +} /* bit_reader_utils.c:55:15 */ + +// range = ((range - 1) << kVP8Log2Range[range]) + 1 +var kVP8NewRange = [128]uint8_t{ + uint8_t(127), uint8_t(127), uint8_t(191), uint8_t(127), uint8_t(159), uint8_t(191), uint8_t(223), uint8_t(127), + uint8_t(143), uint8_t(159), uint8_t(175), uint8_t(191), uint8_t(207), uint8_t(223), uint8_t(239), uint8_t(127), + uint8_t(135), uint8_t(143), uint8_t(151), uint8_t(159), uint8_t(167), uint8_t(175), uint8_t(183), uint8_t(191), + uint8_t(199), uint8_t(207), uint8_t(215), uint8_t(223), uint8_t(231), uint8_t(239), uint8_t(247), uint8_t(127), + uint8_t(131), uint8_t(135), uint8_t(139), uint8_t(143), uint8_t(147), uint8_t(151), uint8_t(155), uint8_t(159), + uint8_t(163), uint8_t(167), uint8_t(171), uint8_t(175), uint8_t(179), uint8_t(183), uint8_t(187), uint8_t(191), + uint8_t(195), uint8_t(199), uint8_t(203), uint8_t(207), uint8_t(211), uint8_t(215), uint8_t(219), uint8_t(223), + uint8_t(227), uint8_t(231), uint8_t(235), uint8_t(239), uint8_t(243), uint8_t(247), uint8_t(251), uint8_t(127), + uint8_t(129), uint8_t(131), uint8_t(133), uint8_t(135), uint8_t(137), uint8_t(139), uint8_t(141), uint8_t(143), + uint8_t(145), uint8_t(147), uint8_t(149), uint8_t(151), uint8_t(153), uint8_t(155), uint8_t(157), uint8_t(159), + uint8_t(161), uint8_t(163), uint8_t(165), uint8_t(167), uint8_t(169), uint8_t(171), uint8_t(173), uint8_t(175), + uint8_t(177), uint8_t(179), uint8_t(181), uint8_t(183), uint8_t(185), uint8_t(187), uint8_t(189), uint8_t(191), + uint8_t(193), uint8_t(195), uint8_t(197), uint8_t(199), uint8_t(201), uint8_t(203), uint8_t(205), uint8_t(207), + uint8_t(209), uint8_t(211), uint8_t(213), uint8_t(215), uint8_t(217), uint8_t(219), uint8_t(221), uint8_t(223), + uint8_t(225), uint8_t(227), uint8_t(229), uint8_t(231), uint8_t(233), uint8_t(235), uint8_t(237), uint8_t(239), + uint8_t(241), uint8_t(243), uint8_t(245), uint8_t(247), uint8_t(249), uint8_t(251), uint8_t(253), uint8_t(127), +} /* bit_reader_utils.c:68:15 */ + +func VP8LoadFinalBytes(tls *libc.TLS, br uintptr) { /* bit_reader_utils.c:87:6: */ + + // Only read 8bits at a time + if (*VP8BitReader)(unsafe.Pointer(br)).buf_ < (*VP8BitReader)(unsafe.Pointer(br)).buf_end_ { + *(*int32)(unsafe.Pointer((br + 12 /* &.bits_ */))) += (8) + (*VP8BitReader)(unsafe.Pointer(br)).value_ = ((bit_t(*(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&(*VP8BitReader)(unsafe.Pointer(br)).buf_, 1))))) | ((*VP8BitReader)(unsafe.Pointer(br)).value_ << 8)) + } else if !((*VP8BitReader)(unsafe.Pointer(br)).eof_ != 0) { + libc.AssignShlPtrUint64((br /* &.value_ */), int(8)) + *(*int32)(unsafe.Pointer((br + 12 /* &.bits_ */))) += (8) + (*VP8BitReader)(unsafe.Pointer(br)).eof_ = 1 + } else { + (*VP8BitReader)(unsafe.Pointer(br)).bits_ = 0 // This is to avoid undefined behaviour with shifts. + } +} + +//------------------------------------------------------------------------------ +// Higher-level calls + +func VP8GetValue(tls *libc.TLS, br uintptr, bits int32) uint32_t { /* bit_reader_utils.c:105:10: */ + var v uint32_t = uint32_t(0) + for libc.PostDecInt32(&bits, 1) > 0 { + v = v | (uint32_t(VP8GetBit(tls, br, 0x80) << bits)) + } + return v +} + +func VP8GetSignedValue(tls *libc.TLS, br uintptr, bits int32) int32_t { /* bit_reader_utils.c:113:9: */ + var value int32 = int32(VP8GetValue(tls, br, bits)) + if VP8GetValue(tls, br, 1) != 0 { + return -value + } + return value +} + +//------------------------------------------------------------------------------ +// VP8LBitReader + +var kBitMask = [25]uint32_t{ + uint32_t(0), + uint32_t(0x000001), uint32_t(0x000003), uint32_t(0x000007), uint32_t(0x00000f), + uint32_t(0x00001f), uint32_t(0x00003f), uint32_t(0x00007f), uint32_t(0x0000ff), + uint32_t(0x0001ff), uint32_t(0x0003ff), uint32_t(0x0007ff), uint32_t(0x000fff), + uint32_t(0x001fff), uint32_t(0x003fff), uint32_t(0x007fff), uint32_t(0x00ffff), + uint32_t(0x01ffff), uint32_t(0x03ffff), uint32_t(0x07ffff), uint32_t(0x0fffff), + uint32_t(0x1fffff), uint32_t(0x3fffff), uint32_t(0x7fffff), uint32_t(0xffffff), +} /* bit_reader_utils.c:130:23 */ + +func VP8LInitBitReader(tls *libc.TLS, br uintptr, start uintptr, length size_t) { /* bit_reader_utils.c:140:6: */ + var i size_t + var value vp8l_val_t = uint64(0) + + // can't happen with a RIFF chunk. + + (*VP8LBitReader)(unsafe.Pointer(br)).len_ = length + (*VP8LBitReader)(unsafe.Pointer(br)).val_ = uint64(0) + (*VP8LBitReader)(unsafe.Pointer(br)).bit_pos_ = 0 + (*VP8LBitReader)(unsafe.Pointer(br)).eos_ = 0 + + if length > size_t(unsafe.Sizeof(vp8l_val_t(0))) { + length = size_t(unsafe.Sizeof(vp8l_val_t(0))) + } + for i = uint64(0); i < length; i++ { + value = value | (vp8l_val_t(*(*uint8_t)(unsafe.Pointer(start + uintptr(i)))) << (uint64(8) * i)) + } + (*VP8LBitReader)(unsafe.Pointer(br)).val_ = value + (*VP8LBitReader)(unsafe.Pointer(br)).pos_ = length + (*VP8LBitReader)(unsafe.Pointer(br)).buf_ = start +} + +func VP8LBitReaderSetBuffer(tls *libc.TLS, br uintptr, buf uintptr, len size_t) { /* bit_reader_utils.c:164:6: */ + + // can't happen with a RIFF chunk. + (*VP8LBitReader)(unsafe.Pointer(br)).buf_ = buf + (*VP8LBitReader)(unsafe.Pointer(br)).len_ = len + // pos_ > len_ should be considered a param error. + (*VP8LBitReader)(unsafe.Pointer(br)).eos_ = (libc.Bool32(((*VP8LBitReader)(unsafe.Pointer(br)).pos_ > (*VP8LBitReader)(unsafe.Pointer(br)).len_) || (VP8LIsEndOfStream(tls, br) != 0))) +} + +func VP8LSetEndOfStream(tls *libc.TLS, br uintptr) { /* bit_reader_utils.c:175:13: */ + (*VP8LBitReader)(unsafe.Pointer(br)).eos_ = 1 + (*VP8LBitReader)(unsafe.Pointer(br)).bit_pos_ = 0 // To avoid undefined behaviour with shifts. +} + +// If not at EOS, reload up to VP8L_LBITS byte-by-byte +func ShiftBytes(tls *libc.TLS, br uintptr) { /* bit_reader_utils.c:181:13: */ + for ((*VP8LBitReader)(unsafe.Pointer(br)).bit_pos_ >= 8) && ((*VP8LBitReader)(unsafe.Pointer(br)).pos_ < (*VP8LBitReader)(unsafe.Pointer(br)).len_) { + libc.AssignShrPtrUint64((br /* &.val_ */), int(8)) + *(*vp8l_val_t)(unsafe.Pointer((br /* &.val_ */))) |= ((vp8l_val_t(*(*uint8_t)(unsafe.Pointer((*VP8LBitReader)(unsafe.Pointer(br)).buf_ + uintptr((*VP8LBitReader)(unsafe.Pointer(br)).pos_))))) << (64 - 8)) + (*VP8LBitReader)(unsafe.Pointer(br)).pos_++ + *(*int32)(unsafe.Pointer((br + 32 /* &.bit_pos_ */))) -= (8) + } + if VP8LIsEndOfStream(tls, br) != 0 { + VP8LSetEndOfStream(tls, br) + } +} + +func VP8LDoFillBitWindow(tls *libc.TLS, br uintptr) { /* bit_reader_utils.c:193:6: */ + + if ((*VP8LBitReader)(unsafe.Pointer(br)).pos_ + size_t(unsafe.Sizeof(vp8l_val_t(0)))) < (*VP8LBitReader)(unsafe.Pointer(br)).len_ { + libc.AssignShrPtrUint64((br /* &.val_ */), int(32)) + *(*int32)(unsafe.Pointer((br + 32 /* &.bit_pos_ */))) -= (32) + *(*vp8l_val_t)(unsafe.Pointer((br /* &.val_ */))) |= ((vp8l_val_t(WebPMemToUint32(tls, ((*VP8LBitReader)(unsafe.Pointer(br)).buf_ + uintptr((*VP8LBitReader)(unsafe.Pointer(br)).pos_))))) << (64 - 32)) + *(*size_t)(unsafe.Pointer((br + 24 /* &.pos_ */))) += (uint64(4)) + return + } + ShiftBytes(tls, br) // Slow path. +} + +func VP8LReadBits(tls *libc.TLS, br uintptr, n_bits int32) uint32_t { /* bit_reader_utils.c:208:10: */ + + // Flag an error if end_of_stream or n_bits is more than allowed limit. + if !((*VP8LBitReader)(unsafe.Pointer(br)).eos_ != 0) && (n_bits <= 24) { + var val uint32_t = (VP8LPrefetchBits(tls, br) & kBitMask[n_bits]) + var new_bits int32 = ((*VP8LBitReader)(unsafe.Pointer(br)).bit_pos_ + n_bits) + (*VP8LBitReader)(unsafe.Pointer(br)).bit_pos_ = new_bits + ShiftBytes(tls, br) + return val + } else { + VP8LSetEndOfStream(tls, br) + return uint32_t(0) + } + return uint32_t(0) +} + +//------------------------------------------------------------------------------ +// Bit-tracing tool + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// VP8BitWriter + +func BitWriterResize(tls *libc.TLS, bw uintptr, extra_size size_t) int32 { /* bit_writer_utils.c:26:12: */ + var new_buf uintptr + var new_size size_t + var needed_size_64b uint64_t = ((*VP8BitWriter)(unsafe.Pointer(bw)).pos_ + extra_size) + var needed_size size_t = needed_size_64b + if needed_size_64b != needed_size { + (*VP8BitWriter)(unsafe.Pointer(bw)).error_ = 1 + return 0 + } + if needed_size <= (*VP8BitWriter)(unsafe.Pointer(bw)).max_pos_ { + return 1 + } + // If the following line wraps over 32bit, the test just after will catch it. + new_size = (uint64(2) * (*VP8BitWriter)(unsafe.Pointer(bw)).max_pos_) + if new_size < needed_size { + new_size = needed_size + } + if new_size < uint64(1024) { + new_size = uint64(1024) + } + new_buf = WebPSafeMalloc(tls, 1, new_size) + if new_buf == (uintptr(0)) { + (*VP8BitWriter)(unsafe.Pointer(bw)).error_ = 1 + return 0 + } + if (*VP8BitWriter)(unsafe.Pointer(bw)).pos_ > uint64(0) { + + libc.Xmemcpy(tls, new_buf, (*VP8BitWriter)(unsafe.Pointer(bw)).buf_, (*VP8BitWriter)(unsafe.Pointer(bw)).pos_) + } + WebPSafeFree(tls, (*VP8BitWriter)(unsafe.Pointer(bw)).buf_) + (*VP8BitWriter)(unsafe.Pointer(bw)).buf_ = new_buf + (*VP8BitWriter)(unsafe.Pointer(bw)).max_pos_ = new_size + return 1 +} + +func Flush(tls *libc.TLS, bw uintptr) { /* bit_writer_utils.c:55:13: */ + var s int32 = (8 + (*VP8BitWriter)(unsafe.Pointer(bw)).nb_bits_) + var bits int32_t = ((*VP8BitWriter)(unsafe.Pointer(bw)).value_ >> s) + + *(*int32_t)(unsafe.Pointer((bw + 4 /* &.value_ */))) -= (bits << s) + *(*int32)(unsafe.Pointer((bw + 12 /* &.nb_bits_ */))) -= (8) + if (bits & 0xff) != 0xff { + var pos size_t = (*VP8BitWriter)(unsafe.Pointer(bw)).pos_ + if !(BitWriterResize(tls, bw, (uint64((*VP8BitWriter)(unsafe.Pointer(bw)).run_+1))) != 0) { + return + } + if (bits & 0x100) != 0 { // overflow -> propagate carry over pending 0xff's + if pos > uint64(0) { + *(*uint8_t)(unsafe.Pointer((*VP8BitWriter)(unsafe.Pointer(bw)).buf_ + uintptr((pos - uint64(1)))))++ + } + } + if (*VP8BitWriter)(unsafe.Pointer(bw)).run_ > 0 { + var value int32 + if (bits & 0x100) != 0 { + value = 0x00 + } else { + value = 0xff + } + for ; (*VP8BitWriter)(unsafe.Pointer(bw)).run_ > 0; (*VP8BitWriter)(unsafe.Pointer(bw)).run_-- { + *(*uint8_t)(unsafe.Pointer((*VP8BitWriter)(unsafe.Pointer(bw)).buf_ + uintptr(libc.PostIncUint64(&pos, 1)))) = uint8_t(value) + } + } + *(*uint8_t)(unsafe.Pointer((*VP8BitWriter)(unsafe.Pointer(bw)).buf_ + uintptr(libc.PostIncUint64(&pos, 1)))) = (uint8_t(bits & 0xff)) + (*VP8BitWriter)(unsafe.Pointer(bw)).pos_ = pos + } else { + (*VP8BitWriter)(unsafe.Pointer(bw)).run_++ // delay writing of bytes 0xff, pending eventual carry. + } +} + +//------------------------------------------------------------------------------ +// renormalization + +var kNorm = [128]uint8_t{ // renorm_sizes[i] = 8 - log2(i) + uint8_t(7), uint8_t(6), uint8_t(6), uint8_t(5), uint8_t(5), uint8_t(5), uint8_t(5), uint8_t(4), uint8_t(4), uint8_t(4), uint8_t(4), uint8_t(4), uint8_t(4), uint8_t(4), uint8_t(4), + uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), uint8_t(3), + uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), + uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), uint8_t(2), + uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), + uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), + uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), + uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), uint8_t(1), + uint8_t(0), +} /* bit_writer_utils.c:83:22 */ + +// range = ((range + 1) << kVP8Log2Range[range]) - 1 +var kNewRange = [128]uint8_t{ + uint8_t(127), uint8_t(127), uint8_t(191), uint8_t(127), uint8_t(159), uint8_t(191), uint8_t(223), uint8_t(127), uint8_t(143), uint8_t(159), uint8_t(175), uint8_t(191), uint8_t(207), uint8_t(223), uint8_t(239), + uint8_t(127), uint8_t(135), uint8_t(143), uint8_t(151), uint8_t(159), uint8_t(167), uint8_t(175), uint8_t(183), uint8_t(191), uint8_t(199), uint8_t(207), uint8_t(215), uint8_t(223), uint8_t(231), uint8_t(239), + uint8_t(247), uint8_t(127), uint8_t(131), uint8_t(135), uint8_t(139), uint8_t(143), uint8_t(147), uint8_t(151), uint8_t(155), uint8_t(159), uint8_t(163), uint8_t(167), uint8_t(171), uint8_t(175), uint8_t(179), + uint8_t(183), uint8_t(187), uint8_t(191), uint8_t(195), uint8_t(199), uint8_t(203), uint8_t(207), uint8_t(211), uint8_t(215), uint8_t(219), uint8_t(223), uint8_t(227), uint8_t(231), uint8_t(235), uint8_t(239), + uint8_t(243), uint8_t(247), uint8_t(251), uint8_t(127), uint8_t(129), uint8_t(131), uint8_t(133), uint8_t(135), uint8_t(137), uint8_t(139), uint8_t(141), uint8_t(143), uint8_t(145), uint8_t(147), uint8_t(149), + uint8_t(151), uint8_t(153), uint8_t(155), uint8_t(157), uint8_t(159), uint8_t(161), uint8_t(163), uint8_t(165), uint8_t(167), uint8_t(169), uint8_t(171), uint8_t(173), uint8_t(175), uint8_t(177), uint8_t(179), + uint8_t(181), uint8_t(183), uint8_t(185), uint8_t(187), uint8_t(189), uint8_t(191), uint8_t(193), uint8_t(195), uint8_t(197), uint8_t(199), uint8_t(201), uint8_t(203), uint8_t(205), uint8_t(207), uint8_t(209), + uint8_t(211), uint8_t(213), uint8_t(215), uint8_t(217), uint8_t(219), uint8_t(221), uint8_t(223), uint8_t(225), uint8_t(227), uint8_t(229), uint8_t(231), uint8_t(233), uint8_t(235), uint8_t(237), uint8_t(239), + uint8_t(241), uint8_t(243), uint8_t(245), uint8_t(247), uint8_t(249), uint8_t(251), uint8_t(253), uint8_t(127), +} /* bit_writer_utils.c:96:22 */ + +func VP8PutBit(tls *libc.TLS, bw uintptr, bit int32, prob int32) int32 { /* bit_writer_utils.c:108:5: */ + var split int32 = (((*VP8BitWriter)(unsafe.Pointer(bw)).range_ * prob) >> 8) + if bit != 0 { + *(*int32_t)(unsafe.Pointer((bw + 4 /* &.value_ */))) += (split + 1) + *(*int32_t)(unsafe.Pointer((bw /* &.range_ */))) -= (split + 1) + } else { + (*VP8BitWriter)(unsafe.Pointer(bw)).range_ = split + } + if (*VP8BitWriter)(unsafe.Pointer(bw)).range_ < 127 { // emit 'shift' bits out and renormalize + var shift int32 = int32(kNorm[(*VP8BitWriter)(unsafe.Pointer(bw)).range_]) + (*VP8BitWriter)(unsafe.Pointer(bw)).range_ = int32_t(kNewRange[(*VP8BitWriter)(unsafe.Pointer(bw)).range_]) + libc.AssignShlPtrInt32((bw + 4 /* &.value_ */), int(shift)) + *(*int32)(unsafe.Pointer((bw + 12 /* &.nb_bits_ */))) += (shift) + if (*VP8BitWriter)(unsafe.Pointer(bw)).nb_bits_ > 0 { + Flush(tls, bw) + } + } + return bit +} + +func VP8PutBitUniform(tls *libc.TLS, bw uintptr, bit int32) int32 { /* bit_writer_utils.c:126:5: */ + var split int32 = ((*VP8BitWriter)(unsafe.Pointer(bw)).range_ >> 1) + if bit != 0 { + *(*int32_t)(unsafe.Pointer((bw + 4 /* &.value_ */))) += (split + 1) + *(*int32_t)(unsafe.Pointer((bw /* &.range_ */))) -= (split + 1) + } else { + (*VP8BitWriter)(unsafe.Pointer(bw)).range_ = split + } + if (*VP8BitWriter)(unsafe.Pointer(bw)).range_ < 127 { + (*VP8BitWriter)(unsafe.Pointer(bw)).range_ = int32_t(kNewRange[(*VP8BitWriter)(unsafe.Pointer(bw)).range_]) + libc.AssignShlPtrInt32((bw + 4 /* &.value_ */), int(1)) + *(*int32)(unsafe.Pointer((bw + 12 /* &.nb_bits_ */))) += (1) + if (*VP8BitWriter)(unsafe.Pointer(bw)).nb_bits_ > 0 { + Flush(tls, bw) + } + } + return bit +} + +func VP8PutBits(tls *libc.TLS, bw uintptr, value uint32_t, nb_bits int32) { /* bit_writer_utils.c:143:6: */ + var mask uint32_t + + for mask = (uint32(1) << (nb_bits - 1)); mask != 0; mask >>= 1 { + VP8PutBitUniform(tls, bw, (int32(value & mask))) + } +} + +func VP8PutSignedBits(tls *libc.TLS, bw uintptr, value int32, nb_bits int32) { /* bit_writer_utils.c:151:6: */ + if !(VP8PutBitUniform(tls, bw, (libc.Bool32(value != 0))) != 0) { + return + } + if value < 0 { + VP8PutBits(tls, bw, (uint32(((-value) << 1) | 1)), (nb_bits + 1)) + } else { + VP8PutBits(tls, bw, (uint32(value << 1)), (nb_bits + 1)) + } +} + +//------------------------------------------------------------------------------ + +func VP8BitWriterInit(tls *libc.TLS, bw uintptr, expected_size size_t) int32 { /* bit_writer_utils.c:162:5: */ + (*VP8BitWriter)(unsafe.Pointer(bw)).range_ = (255 - 1) + (*VP8BitWriter)(unsafe.Pointer(bw)).value_ = 0 + (*VP8BitWriter)(unsafe.Pointer(bw)).run_ = 0 + (*VP8BitWriter)(unsafe.Pointer(bw)).nb_bits_ = -8 + (*VP8BitWriter)(unsafe.Pointer(bw)).pos_ = uint64(0) + (*VP8BitWriter)(unsafe.Pointer(bw)).max_pos_ = uint64(0) + (*VP8BitWriter)(unsafe.Pointer(bw)).error_ = 0 + (*VP8BitWriter)(unsafe.Pointer(bw)).buf_ = (uintptr(0)) + if expected_size > uint64(0) { + return BitWriterResize(tls, bw, expected_size) + } + return 1 +} + +func VP8BitWriterFinish(tls *libc.TLS, bw uintptr) uintptr { /* bit_writer_utils.c:174:8: */ + VP8PutBits(tls, bw, uint32(0), (9 - (*VP8BitWriter)(unsafe.Pointer(bw)).nb_bits_)) + (*VP8BitWriter)(unsafe.Pointer(bw)).nb_bits_ = 0 // pad with zeroes + Flush(tls, bw) + return (*VP8BitWriter)(unsafe.Pointer(bw)).buf_ +} + +func VP8BitWriterAppend(tls *libc.TLS, bw uintptr, data uintptr, size size_t) int32 { /* bit_writer_utils.c:181:5: */ + + if (*VP8BitWriter)(unsafe.Pointer(bw)).nb_bits_ != -8 { + return 0 + } // Flush() must have been called + if !(BitWriterResize(tls, bw, size) != 0) { + return 0 + } + libc.Xmemcpy(tls, ((*VP8BitWriter)(unsafe.Pointer(bw)).buf_ + uintptr((*VP8BitWriter)(unsafe.Pointer(bw)).pos_)), data, size) + *(*size_t)(unsafe.Pointer((bw + 24 /* &.pos_ */))) += (size) + return 1 +} + +func VP8BitWriterWipeOut(tls *libc.TLS, bw uintptr) { /* bit_writer_utils.c:191:6: */ + if bw != (uintptr(0)) { + WebPSafeFree(tls, (*VP8BitWriter)(unsafe.Pointer(bw)).buf_) + libc.Xmemset(tls, bw, 0, uint64(unsafe.Sizeof(VP8BitWriter{}))) + } +} + +//------------------------------------------------------------------------------ +// VP8LBitWriter + +// This is the minimum amount of size the memory buffer is guaranteed to grow +// when extra space is needed. + +// Returns 1 on success. +func VP8LBitWriterResize(tls *libc.TLS, bw uintptr, extra_size size_t) int32 { /* bit_writer_utils.c:206:12: */ + var allocated_buf uintptr + var allocated_size size_t + var max_bytes size_t = (size_t((int64((*VP8LBitWriter)(unsafe.Pointer(bw)).end_) - int64((*VP8LBitWriter)(unsafe.Pointer(bw)).buf_)) / 1)) + var current_size size_t = (size_t((int64((*VP8LBitWriter)(unsafe.Pointer(bw)).cur_) - int64((*VP8LBitWriter)(unsafe.Pointer(bw)).buf_)) / 1)) + var size_required_64b uint64_t = (current_size + extra_size) + var size_required size_t = size_required_64b + if size_required != size_required_64b { + (*VP8LBitWriter)(unsafe.Pointer(bw)).error_ = 1 + return 0 + } + if (max_bytes > uint64(0)) && (size_required <= max_bytes) { + return 1 + } + allocated_size = ((uint64(3) * max_bytes) >> 1) + if allocated_size < size_required { + allocated_size = size_required + } + // make allocated size multiple of 1k + allocated_size = (((allocated_size >> 10) + uint64(1)) << 10) + allocated_buf = WebPSafeMalloc(tls, 1, allocated_size) + if allocated_buf == (uintptr(0)) { + (*VP8LBitWriter)(unsafe.Pointer(bw)).error_ = 1 + return 0 + } + if current_size > uint64(0) { + libc.Xmemcpy(tls, allocated_buf, (*VP8LBitWriter)(unsafe.Pointer(bw)).buf_, current_size) + } + WebPSafeFree(tls, (*VP8LBitWriter)(unsafe.Pointer(bw)).buf_) + (*VP8LBitWriter)(unsafe.Pointer(bw)).buf_ = allocated_buf + (*VP8LBitWriter)(unsafe.Pointer(bw)).cur_ = ((*VP8LBitWriter)(unsafe.Pointer(bw)).buf_ + uintptr(current_size)) + (*VP8LBitWriter)(unsafe.Pointer(bw)).end_ = ((*VP8LBitWriter)(unsafe.Pointer(bw)).buf_ + uintptr(allocated_size)) + return 1 +} + +func VP8LBitWriterInit(tls *libc.TLS, bw uintptr, expected_size size_t) int32 { /* bit_writer_utils.c:237:5: */ + libc.Xmemset(tls, bw, 0, uint64(unsafe.Sizeof(VP8LBitWriter{}))) + return VP8LBitWriterResize(tls, bw, expected_size) +} + +func VP8LBitWriterClone(tls *libc.TLS, src uintptr, dst uintptr) int32 { /* bit_writer_utils.c:242:5: */ + var current_size size_t = (size_t((int64((*VP8LBitWriter)(unsafe.Pointer(src)).cur_) - int64((*VP8LBitWriter)(unsafe.Pointer(src)).buf_)) / 1)) + + if !(VP8LBitWriterResize(tls, dst, current_size) != 0) { + return 0 + } + libc.Xmemcpy(tls, (*VP8LBitWriter)(unsafe.Pointer(dst)).buf_, (*VP8LBitWriter)(unsafe.Pointer(src)).buf_, current_size) + (*VP8LBitWriter)(unsafe.Pointer(dst)).bits_ = (*VP8LBitWriter)(unsafe.Pointer(src)).bits_ + (*VP8LBitWriter)(unsafe.Pointer(dst)).used_ = (*VP8LBitWriter)(unsafe.Pointer(src)).used_ + (*VP8LBitWriter)(unsafe.Pointer(dst)).error_ = (*VP8LBitWriter)(unsafe.Pointer(src)).error_ + (*VP8LBitWriter)(unsafe.Pointer(dst)).cur_ = ((*VP8LBitWriter)(unsafe.Pointer(dst)).buf_ + uintptr(current_size)) + return 1 +} + +func VP8LBitWriterWipeOut(tls *libc.TLS, bw uintptr) { /* bit_writer_utils.c:255:6: */ + if bw != (uintptr(0)) { + WebPSafeFree(tls, (*VP8LBitWriter)(unsafe.Pointer(bw)).buf_) + libc.Xmemset(tls, bw, 0, uint64(unsafe.Sizeof(VP8LBitWriter{}))) + } +} + +func VP8LBitWriterReset(tls *libc.TLS, bw_init uintptr, bw uintptr) { /* bit_writer_utils.c:262:6: */ + (*VP8LBitWriter)(unsafe.Pointer(bw)).bits_ = (*VP8LBitWriter)(unsafe.Pointer(bw_init)).bits_ + (*VP8LBitWriter)(unsafe.Pointer(bw)).used_ = (*VP8LBitWriter)(unsafe.Pointer(bw_init)).used_ + (*VP8LBitWriter)(unsafe.Pointer(bw)).cur_ = ((*VP8LBitWriter)(unsafe.Pointer(bw)).buf_ + uintptr(((int64((*VP8LBitWriter)(unsafe.Pointer(bw_init)).cur_) - int64((*VP8LBitWriter)(unsafe.Pointer(bw_init)).buf_)) / 1))) + + (*VP8LBitWriter)(unsafe.Pointer(bw)).error_ = (*VP8LBitWriter)(unsafe.Pointer(bw_init)).error_ +} + +func VP8LBitWriterSwap(tls *libc.TLS, src uintptr, dst uintptr) { /* bit_writer_utils.c:271:6: */ + var tmp = *(*VP8LBitWriter)(unsafe.Pointer(src)) + *(*VP8LBitWriter)(unsafe.Pointer(src)) = *(*VP8LBitWriter)(unsafe.Pointer(dst)) + *(*VP8LBitWriter)(unsafe.Pointer(dst)) = tmp +} + +func VP8LPutBitsFlushBits(tls *libc.TLS, bw uintptr) { /* bit_writer_utils.c:277:6: */ + // If needed, make some room by flushing some bits out. + if ((*VP8LBitWriter)(unsafe.Pointer(bw)).cur_ + uintptr(4)) > (*VP8LBitWriter)(unsafe.Pointer(bw)).end_ { + var extra_size uint64_t = (uint64_t((uint64((int64((*VP8LBitWriter)(unsafe.Pointer(bw)).end_) - int64((*VP8LBitWriter)(unsafe.Pointer(bw)).buf_)) / 1)) + (32768))) + if !(CheckSizeOverflow(tls, extra_size) != 0) || !(VP8LBitWriterResize(tls, bw, extra_size) != 0) { + (*VP8LBitWriter)(unsafe.Pointer(bw)).cur_ = (*VP8LBitWriter)(unsafe.Pointer(bw)).buf_ + (*VP8LBitWriter)(unsafe.Pointer(bw)).error_ = 1 + return + } + } + *(*vp8l_wtype_t)(unsafe.Pointer((*VP8LBitWriter)(unsafe.Pointer(bw)).cur_)) = (vp8l_wtype_t((*VP8LBitWriter)(unsafe.Pointer(bw)).bits_)) + *(*uintptr)(unsafe.Pointer((bw + 24 /* &.cur_ */))) += (uintptr(4)) + libc.AssignShrPtrUint64((bw /* &.bits_ */), int(32)) + *(*int32)(unsafe.Pointer((bw + 8 /* &.used_ */))) -= (32) +} + +func VP8LPutBitsInternal(tls *libc.TLS, bw uintptr, bits uint32_t, n_bits int32) { /* bit_writer_utils.c:294:6: */ + + // That's the max we can handle: + + if n_bits > 0 { + var lbits vp8l_atype_t = (*VP8LBitWriter)(unsafe.Pointer(bw)).bits_ + var used int32 = (*VP8LBitWriter)(unsafe.Pointer(bw)).used_ + // Special case of overflow handling for 32bit accumulator (2-steps flush). + // If needed, make some room by flushing some bits out. + for used >= 32 { + if ((*VP8LBitWriter)(unsafe.Pointer(bw)).cur_ + uintptr(4)) > (*VP8LBitWriter)(unsafe.Pointer(bw)).end_ { + var extra_size uint64_t = (uint64_t((uint64((int64((*VP8LBitWriter)(unsafe.Pointer(bw)).end_) - int64((*VP8LBitWriter)(unsafe.Pointer(bw)).buf_)) / 1)) + (32768))) + if !(CheckSizeOverflow(tls, extra_size) != 0) || !(VP8LBitWriterResize(tls, bw, extra_size) != 0) { + (*VP8LBitWriter)(unsafe.Pointer(bw)).cur_ = (*VP8LBitWriter)(unsafe.Pointer(bw)).buf_ + (*VP8LBitWriter)(unsafe.Pointer(bw)).error_ = 1 + return + } + } + *(*vp8l_wtype_t)(unsafe.Pointer((*VP8LBitWriter)(unsafe.Pointer(bw)).cur_)) = (vp8l_wtype_t(lbits)) + *(*uintptr)(unsafe.Pointer((bw + 24 /* &.cur_ */))) += (uintptr(4)) + lbits >>= 32 + used = used - (32) + } + (*VP8LBitWriter)(unsafe.Pointer(bw)).bits_ = (lbits | (vp8l_atype_t(bits) << used)) + (*VP8LBitWriter)(unsafe.Pointer(bw)).used_ = (used + n_bits) + } +} + +func VP8LBitWriterFinish(tls *libc.TLS, bw uintptr) uintptr { /* bit_writer_utils.c:334:8: */ + // flush leftover bits + if VP8LBitWriterResize(tls, bw, (uint64(((*VP8LBitWriter)(unsafe.Pointer(bw)).used_+7)>>3))) != 0 { + for (*VP8LBitWriter)(unsafe.Pointer(bw)).used_ > 0 { + *(*uint8_t)(unsafe.Pointer(libc.PostIncUintptr(&(*VP8LBitWriter)(unsafe.Pointer(bw)).cur_, 1))) = uint8_t((*VP8LBitWriter)(unsafe.Pointer(bw)).bits_) + libc.AssignShrPtrUint64((bw /* &.bits_ */), int(8)) + *(*int32)(unsafe.Pointer((bw + 8 /* &.used_ */))) -= (8) + } + (*VP8LBitWriter)(unsafe.Pointer(bw)).used_ = 0 + } + return (*VP8LBitWriter)(unsafe.Pointer(bw)).buf_ +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// VP8LColorCache. + +func VP8LColorCacheInit(tls *libc.TLS, color_cache uintptr, hash_bits int32) int32 { /* color_cache_utils.c:23:5: */ + var hash_size int32 = (int32(1) << hash_bits) + + (*VP8LColorCache)(unsafe.Pointer(color_cache)).colors_ = WebPSafeCalloc(tls, + uint64_t(hash_size), uint64(unsafe.Sizeof(uint32_t(0)))) + if (*VP8LColorCache)(unsafe.Pointer(color_cache)).colors_ == (uintptr(0)) { + return 0 + } + (*VP8LColorCache)(unsafe.Pointer(color_cache)).hash_shift_ = (32 - hash_bits) + (*VP8LColorCache)(unsafe.Pointer(color_cache)).hash_bits_ = hash_bits + return 1 +} + +func VP8LColorCacheClear(tls *libc.TLS, color_cache uintptr) { /* color_cache_utils.c:35:6: */ + if color_cache != (uintptr(0)) { + WebPSafeFree(tls, (*VP8LColorCache)(unsafe.Pointer(color_cache)).colors_) + (*VP8LColorCache)(unsafe.Pointer(color_cache)).colors_ = (uintptr(0)) + } +} + +func VP8LColorCacheCopy(tls *libc.TLS, src uintptr, dst uintptr) { /* color_cache_utils.c:42:6: */ + + libc.Xmemcpy(tls, (*VP8LColorCache)(unsafe.Pointer(dst)).colors_, (*VP8LColorCache)(unsafe.Pointer(src)).colors_, + ((size_t(uint64(1)) << (*VP8LColorCache)(unsafe.Pointer(dst)).hash_bits_) * size_t(unsafe.Sizeof(uint32_t(0))))) +} + +// ----------------------------------------------------------------------------- +// Quick estimate of a potentially interesting filter mode to try. + +func GradientPredictor(tls *libc.TLS, a uint8_t, b uint8_t, c uint8_t) int32 { /* filters_utils.c:24:24: */ + var g int32 = ((int32(a) + int32(b)) - int32(c)) + if (g & libc.CplInt32(0xff)) == 0 { + return g + } + if g < 0 { + return 0 + } + return 255 // clip to 8bit +} + +func WebPEstimateBestFilter(tls *libc.TLS, data uintptr, width int32, height int32, stride int32) WEBP_FILTER_TYPE { /* filters_utils.c:29:18: */ + bp := tls.Alloc(256) + defer tls.Free(256) + + var i int32 + var j int32 + // var bins [4][16]int32 at bp, 256 + + libc.Xmemset(tls, (bp) /* &bins[0] */, 0, uint64(unsafe.Sizeof([4][16]int32{}))) + + // We only sample every other pixels. That's enough. + for j = 2; j < (height - 1); j = j + (2) { + var p uintptr = (data + uintptr((j * stride))) + var mean int32 = int32(*(*uint8_t)(unsafe.Pointer(p))) + for i = 2; i < (width - 1); i = i + (2) { + var diff0 int32 = (libc.Xabs(tls, ((int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(i)))))-(mean))) >> 4) + var diff1 int32 = (libc.Xabs(tls, ((int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(i)))))-(int32(*(*uint8_t)(unsafe.Pointer(p + uintptr((i - 1)))))))) >> 4) + var diff2 int32 = (libc.Xabs(tls, ((int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(i)))))-(int32(*(*uint8_t)(unsafe.Pointer(p + uintptr((i - width)))))))) >> 4) + var grad_pred int32 = GradientPredictor(tls, *(*uint8_t)(unsafe.Pointer(p + uintptr((i - 1)))), *(*uint8_t)(unsafe.Pointer(p + uintptr((i - width)))), *(*uint8_t)(unsafe.Pointer(p + uintptr(((i - width) - 1))))) + var diff3 int32 = (libc.Xabs(tls, ((int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(i)))))-(grad_pred))) >> 4) + *(*int32)(unsafe.Pointer((bp) /* &bins[0] */ + uintptr(diff0)*4)) = 1 + *(*int32)(unsafe.Pointer(((bp) /* &bins[0] */ + 1*64) + uintptr(diff1)*4)) = 1 + *(*int32)(unsafe.Pointer(((bp) /* &bins[0] */ + 2*64) + uintptr(diff2)*4)) = 1 + *(*int32)(unsafe.Pointer(((bp) /* &bins[0] */ + 3*64) + uintptr(diff3)*4)) = 1 + mean = ((((3 * mean) + int32(*(*uint8_t)(unsafe.Pointer(p + uintptr(i))))) + 2) >> 2) + } + } + { + var filter int32 + var best_filter WEBP_FILTER_TYPE = WEBP_FILTER_NONE + var best_score int32 = 0x7fffffff + for filter = WEBP_FILTER_NONE; filter < WEBP_FILTER_LAST; filter++ { + var score int32 = 0 + for i = 0; i < 16; i++ { + if *(*int32)(unsafe.Pointer(((bp) /* &bins[0] */ + uintptr(filter)*64) + uintptr(i)*4)) > 0 { + score = score + (i) + } + } + if score < best_score { + best_score = score + best_filter = WEBP_FILTER_TYPE(filter) + } + } + return best_filter + + } + return WEBP_FILTER_TYPE(0) +} + +//------------------------------------------------------------------------------ + +// Alpha related constants. + +// Mux related constants. + +// Maximum chunk payload is such that adding the header and padding won't +// overflow a uint32_t. + +// ----------------------------------------------------------------------------- +// Util function to optimize the symbol map for RLE coding + +// Heuristics for selecting the stride ranges to collapse. +func ValuesShouldBeCollapsedToStrideAverage(tls *libc.TLS, a int32, b int32) int32 { /* huffman_encode_utils.c:25:12: */ + return (libc.Bool32(libc.Xabs(tls, (a-b)) < 4)) +} + +// Change the population counts in a way that the consequent +// Huffman tree compression, especially its RLE-part, give smaller output. +func OptimizeHuffmanForRle(tls *libc.TLS, length int32, good_for_rle uintptr, counts uintptr) { /* huffman_encode_utils.c:31:13: */ + // 1) Let's make the Huffman code more compatible with rle encoding. + var i int32 + for ; length >= 0; length-- { + if length == 0 { + return // All zeros. + } + if *(*uint32_t)(unsafe.Pointer(counts + uintptr((length-1))*4)) != uint32_t(0) { + // Now counts[0..length - 1] does not have trailing zeros. + break + } + } + // 2) Let's mark all population counts that already can be encoded + // with an rle code. + { + // Let's not spoil any of the existing good rle codes. + // Mark any seq of 0's that is longer as 5 as a good_for_rle. + // Mark any seq of non-0's that is longer as 7 as a good_for_rle. + var symbol uint32_t = *(*uint32_t)(unsafe.Pointer(counts)) + var stride int32 = 0 + for i = 0; i < (length + 1); i++ { + if (i == length) || (*(*uint32_t)(unsafe.Pointer(counts + uintptr(i)*4)) != symbol) { + if ((symbol == uint32_t(0)) && (stride >= 5)) || ((symbol != uint32_t(0)) && (stride >= 7)) { + var k int32 + for k = 0; k < stride; k++ { + *(*uint8_t)(unsafe.Pointer(good_for_rle + uintptr(((i - k) - 1)))) = uint8_t(1) + } + } + stride = 1 + if i != length { + symbol = *(*uint32_t)(unsafe.Pointer(counts + uintptr(i)*4)) + } + } else { + stride++ + } + } + + } + // 3) Let's replace those population counts that lead to more rle codes. + { + var stride uint32_t = uint32_t(0) + var limit uint32_t = *(*uint32_t)(unsafe.Pointer(counts)) + var sum uint32_t = uint32_t(0) + for i = 0; i < (length + 1); i++ { + if (((i == length) || (*(*uint8_t)(unsafe.Pointer(good_for_rle + uintptr(i))) != 0)) || ((i != 0) && (*(*uint8_t)(unsafe.Pointer(good_for_rle + uintptr((i - 1)))) != 0))) || !(ValuesShouldBeCollapsedToStrideAverage(tls, int32(*(*uint32_t)(unsafe.Pointer(counts + uintptr(i)*4))), int32(limit)) != 0) { + if (stride >= uint32_t(4)) || ((stride >= uint32_t(3)) && (sum == uint32_t(0))) { + var k uint32_t + // The stride must end, collapse what we have, if we have enough (4). + var count uint32_t = ((sum + (stride / uint32_t(2))) / stride) + if count < uint32_t(1) { + count = uint32_t(1) + } + if sum == uint32_t(0) { + // Don't make an all zeros stride to be upgraded to ones. + count = uint32_t(0) + } + for k = uint32_t(0); k < stride; k++ { + // We don't want to change value at counts[i], + // that is already belonging to the next stride. Thus - 1. + *(*uint32_t)(unsafe.Pointer(counts + uintptr(((uint32_t(i)-k)-uint32_t(1)))*4)) = count + } + } + stride = uint32_t(0) + sum = uint32_t(0) + if i < (length - 3) { + // All interesting strides have a count of at least 4, + // at least when non-zeros. + limit = (((((*(*uint32_t)(unsafe.Pointer(counts + uintptr(i)*4)) + *(*uint32_t)(unsafe.Pointer(counts + uintptr((i+1))*4))) + *(*uint32_t)(unsafe.Pointer(counts + uintptr((i+2))*4))) + *(*uint32_t)(unsafe.Pointer(counts + uintptr((i+3))*4))) + uint32_t(2)) / uint32_t(4)) + } else if i < length { + limit = *(*uint32_t)(unsafe.Pointer(counts + uintptr(i)*4)) + } else { + limit = uint32_t(0) + } + } + stride++ + if i != length { + sum = sum + (*(*uint32_t)(unsafe.Pointer(counts + uintptr(i)*4))) + if stride >= uint32_t(4) { + limit = ((sum + (stride / uint32_t(2))) / stride) + } + } + } + + } +} + +// A comparer function for two Huffman trees: sorts first by 'total count' +// (more comes first), and then by 'value' (more comes first). +func CompareHuffmanTrees(tls *libc.TLS, ptr1 uintptr, ptr2 uintptr) int32 { /* huffman_encode_utils.c:122:12: */ + var t1 uintptr = ptr1 + var t2 uintptr = ptr2 + if (*HuffmanTree)(unsafe.Pointer(t1)).total_count_ > (*HuffmanTree)(unsafe.Pointer(t2)).total_count_ { + return -1 + } else if (*HuffmanTree)(unsafe.Pointer(t1)).total_count_ < (*HuffmanTree)(unsafe.Pointer(t2)).total_count_ { + return 1 + } else { + + if (*HuffmanTree)(unsafe.Pointer(t1)).value_ < (*HuffmanTree)(unsafe.Pointer(t2)).value_ { + return -1 + } + return 1 + } + return int32(0) +} + +func SetBitDepths(tls *libc.TLS, tree uintptr, pool uintptr, bit_depths uintptr, level int32) { /* huffman_encode_utils.c:135:13: */ + if (*HuffmanTree)(unsafe.Pointer(tree)).pool_index_left_ >= 0 { + SetBitDepths(tls, (pool + uintptr((*HuffmanTree)(unsafe.Pointer(tree)).pool_index_left_)*16), pool, bit_depths, (level + 1)) + SetBitDepths(tls, (pool + uintptr((*HuffmanTree)(unsafe.Pointer(tree)).pool_index_right_)*16), pool, bit_depths, (level + 1)) + } else { + *(*uint8_t)(unsafe.Pointer(bit_depths + uintptr((*HuffmanTree)(unsafe.Pointer(tree)).value_))) = uint8_t(level) + } +} + +// Create an optimal Huffman tree. +// +// (data,length): population counts. +// tree_limit: maximum bit depth (inclusive) of the codes. +// bit_depths[]: how many bits are used for the symbol. +// +// Returns 0 when an error has occurred. +// +// The catch here is that the tree cannot be arbitrarily deep +// +// count_limit is the value that is to be faked as the minimum value +// and this minimum value is raised until the tree matches the +// maximum length requirement. +// +// This algorithm is not of excellent performance for very long data blocks, +// especially when population counts are longer than 2**tree_limit, but +// we are not planning to use this with extremely long blocks. +// +// See https://en.wikipedia.org/wiki/Huffman_coding +func GenerateOptimalTree(tls *libc.TLS, histogram uintptr, histogram_size int32, tree uintptr, tree_depth_limit int32, bit_depths uintptr) { /* huffman_encode_utils.c:165:13: */ + var count_min uint32_t + var tree_pool uintptr + var tree_size_orig int32 = 0 + var i int32 + + for i = 0; i < histogram_size; i++ { + if *(*uint32_t)(unsafe.Pointer(histogram + uintptr(i)*4)) != uint32_t(0) { + tree_size_orig++ + } + } + + if tree_size_orig == 0 { // pretty optimal already! + return + } + + tree_pool = (tree + uintptr(tree_size_orig)*16) + + // For block sizes with less than 64k symbols we never need to do a + // second iteration of this loop. + // If we actually start running inside this loop a lot, we would perhaps + // be better off with the Katajainen algorithm. + + for count_min = uint32_t(1); ; count_min = count_min * (uint32_t(2)) { + var tree_size int32 = tree_size_orig + // We need to pack the Huffman tree in tree_depth_limit bits. + // So, we try by faking histogram entries to be at least 'count_min'. + var idx int32 = 0 + var j int32 + for j = 0; j < histogram_size; j++ { + if *(*uint32_t)(unsafe.Pointer(histogram + uintptr(j)*4)) != uint32_t(0) { + var count uint32_t + if *(*uint32_t)(unsafe.Pointer(histogram + uintptr(j)*4)) < count_min { + count = count_min + } else { + count = *(*uint32_t)(unsafe.Pointer(histogram + uintptr(j)*4)) + } + (*HuffmanTree)(unsafe.Pointer(tree + uintptr(idx)*16)).total_count_ = count + (*HuffmanTree)(unsafe.Pointer(tree + uintptr(idx)*16)).value_ = j + (*HuffmanTree)(unsafe.Pointer(tree + uintptr(idx)*16)).pool_index_left_ = -1 + (*HuffmanTree)(unsafe.Pointer(tree + uintptr(idx)*16)).pool_index_right_ = -1 + idx++ + } + } + + // Build the Huffman tree. + libc.Xqsort(tls, tree, uint64(tree_size), uint64(unsafe.Sizeof(HuffmanTree{})), *(*uintptr)(unsafe.Pointer(&struct { + f func(*libc.TLS, uintptr, uintptr) int32 + }{CompareHuffmanTrees}))) + + if tree_size > 1 { // Normal case. + var tree_pool_size int32 = 0 + for tree_size > 1 { // Finish when we have only one root. + var count uint32_t + *(*HuffmanTree)(unsafe.Pointer(tree_pool + uintptr(libc.PostIncInt32(&tree_pool_size, 1))*16)) = *(*HuffmanTree)(unsafe.Pointer(tree + uintptr((tree_size-1))*16)) + *(*HuffmanTree)(unsafe.Pointer(tree_pool + uintptr(libc.PostIncInt32(&tree_pool_size, 1))*16)) = *(*HuffmanTree)(unsafe.Pointer(tree + uintptr((tree_size-2))*16)) + count = ((*HuffmanTree)(unsafe.Pointer(tree_pool+uintptr((tree_pool_size-1))*16)).total_count_ + (*HuffmanTree)(unsafe.Pointer(tree_pool+uintptr((tree_pool_size-2))*16)).total_count_) + tree_size = tree_size - (2) + { + // Search for the insertion point. + var k int32 + for k = 0; k < tree_size; k++ { + if (*HuffmanTree)(unsafe.Pointer(tree+uintptr(k)*16)).total_count_ <= count { + break + } + } + libc.Xmemmove(tls, (tree + uintptr((k+1))*16), (tree + uintptr(k)*16), ((uint64(tree_size - k)) * uint64(unsafe.Sizeof(HuffmanTree{})))) + (*HuffmanTree)(unsafe.Pointer(tree + uintptr(k)*16)).total_count_ = count + (*HuffmanTree)(unsafe.Pointer(tree + uintptr(k)*16)).value_ = -1 + + (*HuffmanTree)(unsafe.Pointer(tree + uintptr(k)*16)).pool_index_left_ = (tree_pool_size - 1) + (*HuffmanTree)(unsafe.Pointer(tree + uintptr(k)*16)).pool_index_right_ = (tree_pool_size - 2) + tree_size = (tree_size + 1) + + } + } + SetBitDepths(tls, (tree), tree_pool, bit_depths, 0) + } else if tree_size == 1 { // Trivial case: only one element. + *(*uint8_t)(unsafe.Pointer(bit_depths + uintptr((*HuffmanTree)(unsafe.Pointer(tree)).value_))) = uint8_t(1) + } + + { + // Test if this Huffman tree satisfies our 'tree_depth_limit' criteria. + var max_depth int32 = int32(*(*uint8_t)(unsafe.Pointer(bit_depths))) + for j = 1; j < histogram_size; j++ { + if max_depth < int32(*(*uint8_t)(unsafe.Pointer(bit_depths + uintptr(j)))) { + max_depth = int32(*(*uint8_t)(unsafe.Pointer(bit_depths + uintptr(j)))) + } + } + if max_depth <= tree_depth_limit { + break + } + + } + } +} + +// ----------------------------------------------------------------------------- +// Coding of the Huffman tree values + +func CodeRepeatedValues(tls *libc.TLS, repetitions int32, tokens uintptr, value int32, prev_value int32) uintptr { /* huffman_encode_utils.c:261:24: */ + + if value != prev_value { + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).code = uint8_t(value) + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).extra_bits = uint8_t(0) + tokens += 2 + repetitions-- + } + for repetitions >= 1 { + if repetitions < 3 { + var i int32 + for i = 0; i < repetitions; i++ { + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).code = uint8_t(value) + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).extra_bits = uint8_t(0) + tokens += 2 + } + break + } else if repetitions < 7 { + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).code = uint8_t(16) + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).extra_bits = (uint8_t(repetitions - 3)) + tokens += 2 + break + } else { + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).code = uint8_t(16) + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).extra_bits = uint8_t(3) + tokens += 2 + repetitions = repetitions - (6) + } + } + return tokens +} + +func CodeRepeatedZeros(tls *libc.TLS, repetitions int32, tokens uintptr) uintptr { /* huffman_encode_utils.c:295:24: */ + for repetitions >= 1 { + if repetitions < 3 { + var i int32 + for i = 0; i < repetitions; i++ { + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).code = uint8_t(0) // 0-value + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).extra_bits = uint8_t(0) + tokens += 2 + } + break + } else if repetitions < 11 { + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).code = uint8_t(17) + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).extra_bits = (uint8_t(repetitions - 3)) + tokens += 2 + break + } else if repetitions < 139 { + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).code = uint8_t(18) + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).extra_bits = (uint8_t(repetitions - 11)) + tokens += 2 + break + } else { + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).code = uint8_t(18) + (*HuffmanTreeToken)(unsafe.Pointer(tokens)).extra_bits = uint8_t(0x7f) // 138 repeated 0s + tokens += 2 + repetitions = repetitions - (138) + } + } + return tokens +} + +func VP8LCreateCompressedHuffmanTree(tls *libc.TLS, tree uintptr, tokens uintptr, max_tokens int32) int32 { /* huffman_encode_utils.c:326:5: */ + var starting_token uintptr = tokens + var ending_token uintptr = (tokens + uintptr(max_tokens)*2) + _ = ending_token + var depth_size int32 = (*HuffmanTreeCode)(unsafe.Pointer(tree)).num_symbols + var prev_value int32 = 8 // 8 is the initial value for rle. + var i int32 = 0 + + for i < depth_size { + var value int32 = int32(*(*uint8_t)(unsafe.Pointer((*HuffmanTreeCode)(unsafe.Pointer(tree)).code_lengths + uintptr(i)))) + var k int32 = (i + 1) + var runs int32 + for (k < depth_size) && (int32(*(*uint8_t)(unsafe.Pointer((*HuffmanTreeCode)(unsafe.Pointer(tree)).code_lengths + uintptr(k)))) == value) { + k++ + } + runs = (k - i) + if value == 0 { + tokens = CodeRepeatedZeros(tls, runs, tokens) + } else { + tokens = CodeRepeatedValues(tls, runs, tokens, value, prev_value) + prev_value = value + } + i = i + (runs) + + } + _ = ending_token // suppress 'unused variable' warning + return (int32((int64(tokens) - int64(starting_token)) / 2)) +} + +// ----------------------------------------------------------------------------- + +// Pre-reversed 4-bit values. +var kReversedBits = [16]uint8_t{ + uint8_t(0x0), uint8_t(0x8), uint8_t(0x4), uint8_t(0xc), uint8_t(0x2), uint8_t(0xa), uint8_t(0x6), uint8_t(0xe), + uint8_t(0x1), uint8_t(0x9), uint8_t(0x5), uint8_t(0xd), uint8_t(0x3), uint8_t(0xb), uint8_t(0x7), uint8_t(0xf), +} /* huffman_encode_utils.c:356:22 */ + +func ReverseBits(tls *libc.TLS, num_bits int32, bits uint32_t) uint32_t { /* huffman_encode_utils.c:361:17: */ + var retval uint32_t = uint32_t(0) + var i int32 = 0 + for i < num_bits { + i = i + (4) + retval = retval | (uint32_t(int32(kReversedBits[(bits&uint32_t(0xf))]) << ((15 + 1) - i))) + bits >>= 4 + } + retval >>= ((15 + 1) - num_bits) + return retval +} + +// Get the actual bit values for a tree of bit depths. +func ConvertBitDepthsToSymbols(tls *libc.TLS, tree uintptr) { /* huffman_encode_utils.c:374:13: */ + bp := tls.Alloc(128) + defer tls.Free(128) + + // 0 bit-depth means that the symbol does not exist. + var i int32 + var len int32 + // var next_code [16]uint32_t at bp+64, 64 + + *(*[16]int32)(unsafe.Pointer(bp /* depth_count */)) = [16]int32{0: 0} + + len = (*HuffmanTreeCode)(unsafe.Pointer(tree)).num_symbols + for i = 0; i < len; i++ { + var code_length int32 = int32(*(*uint8_t)(unsafe.Pointer((*HuffmanTreeCode)(unsafe.Pointer(tree)).code_lengths + uintptr(i)))) + + *(*int32)(unsafe.Pointer((bp) /* &depth_count[0] */ + uintptr(code_length)*4))++ + } + *(*int32)(unsafe.Pointer((bp) /* &depth_count[0] */)) = 0 // ignore unused symbol + *(*uint32_t)(unsafe.Pointer((bp + 64) /* &next_code[0] */)) = uint32_t(0) + { + var code uint32_t = uint32_t(0) + for i = 1; i <= 15; i++ { + code = ((code + uint32_t(*(*int32)(unsafe.Pointer((bp) /* &depth_count[0] */ + uintptr((i-1))*4)))) << 1) + *(*uint32_t)(unsafe.Pointer((bp + 64) /* &next_code[0] */ + uintptr(i)*4)) = code + } + + } + for i = 0; i < len; i++ { + var code_length int32 = int32(*(*uint8_t)(unsafe.Pointer((*HuffmanTreeCode)(unsafe.Pointer(tree)).code_lengths + uintptr(i)))) + *(*uint16_t)(unsafe.Pointer((*HuffmanTreeCode)(unsafe.Pointer(tree)).codes + uintptr(i)*2)) = uint16_t(ReverseBits(tls, code_length, libc.PostIncUint32(&*(*uint32_t)(unsafe.Pointer((bp + 64) /* &next_code[0] */ + uintptr(code_length)*4)), 1))) + } +} + +// ----------------------------------------------------------------------------- +// Main entry point + +func VP8LCreateHuffmanTree(tls *libc.TLS, histogram uintptr, tree_depth_limit int32, buf_rle uintptr, huff_tree uintptr, huff_code uintptr) { /* huffman_encode_utils.c:406:6: */ + var num_symbols int32 = (*HuffmanTreeCode)(unsafe.Pointer(huff_code)).num_symbols + libc.Xmemset(tls, buf_rle, 0, (uint64(num_symbols) * uint64(unsafe.Sizeof(uint8_t(0))))) + OptimizeHuffmanForRle(tls, num_symbols, buf_rle, histogram) + GenerateOptimalTree(tls, histogram, num_symbols, huff_tree, tree_depth_limit, + (*HuffmanTreeCode)(unsafe.Pointer(huff_code)).code_lengths) + // Create the actual bit codes for the bit lengths. + ConvertBitDepthsToSymbols(tls, huff_code) +} + +//------------------------------------------------------------------------------ + +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Internal header for constants related to WebP file format. +// +// Author: Urvang (urvang@google.com) + +// Huffman data read via DecodeImageStream is represented in two (red and green) +// bytes. + +func VP8LHtreeGroupsNew(tls *libc.TLS, num_htree_groups int32) uintptr { /* huffman_utils.c:25:11: */ + var htree_groups uintptr = WebPSafeMalloc(tls, uint64(num_htree_groups), uint64(unsafe.Sizeof(HTreeGroup{}))) + if htree_groups == (uintptr(0)) { + return (uintptr(0)) + } + + return htree_groups +} + +func VP8LHtreeGroupsFree(tls *libc.TLS, htree_groups uintptr) { /* huffman_utils.c:35:6: */ + if htree_groups != (uintptr(0)) { + WebPSafeFree(tls, htree_groups) + } +} + +// Returns reverse(reverse(key, len) + 1, len), where reverse(key, len) is the +// bit-wise reversal of the len least significant bits of key. +func GetNextKey(tls *libc.TLS, key uint32_t, len int32) uint32_t { /* huffman_utils.c:43:29: */ + var step uint32_t = (uint32_t(int32(1) << (len - 1))) + for (key & step) != 0 { + step >>= 1 + } + if step != 0 { + return ((key & (step - uint32_t(1))) + step) + } + return key +} + +// Stores code in table[0], table[step], table[2*step], ..., table[end]. +// Assumes that end is an integer multiple of step. +func ReplicateValue(tls *libc.TLS, table uintptr, step int32, end int32, code HuffmanCode) { /* huffman_utils.c:53:25: */ + + for ok := true; ok; ok = (end > 0) { + end = end - (step) + *(*HuffmanCode)(unsafe.Pointer(table + uintptr(end)*4)) = code + } +} + +// Returns the table width of the next 2nd level table. count is the histogram +// of bit lengths for the remaining symbols, len is the code length of the next +// processed symbol +func NextTableBitSize(tls *libc.TLS, count uintptr, len int32, root_bits int32) int32 { /* huffman_utils.c:66:24: */ + var left int32 = (int32(1) << (len - root_bits)) + for len < 15 { + left = left - (*(*int32)(unsafe.Pointer(count + uintptr(len)*4))) + if left <= 0 { + break + } + len++ + left <<= 1 + } + return (len - root_bits) +} + +// sorted[code_lengths_size] is a pre-allocated array for sorting symbols +// by code length. +func BuildHuffmanTable(tls *libc.TLS, root_table uintptr, root_bits int32, code_lengths uintptr, code_lengths_size int32, sorted uintptr) int32 { /* huffman_utils.c:80:12: */ + bp := tls.Alloc(128) + defer tls.Free(128) + + var table uintptr = root_table // next available space in table + var total_size int32 = (int32(1) << root_bits) // total size root table + 2nd level table + var len int32 // current code length + var symbol int32 // symbol index in original or sorted table + // number of codes of each length: + *(*[16]int32)(unsafe.Pointer(bp /* count */)) = [16]int32{0: 0} + // offsets in sorted table for each length: + // var offset [16]int32 at bp+64, 64 + + // Build histogram of code lengths. + for symbol = 0; symbol < code_lengths_size; symbol++ { + if *(*int32)(unsafe.Pointer(code_lengths + uintptr(symbol)*4)) > 15 { + return 0 + } + *(*int32)(unsafe.Pointer((bp) /* &count[0] */ + uintptr(*(*int32)(unsafe.Pointer(code_lengths + uintptr(symbol)*4)))*4))++ + } + + // Error, all code lengths are zeros. + if *(*int32)(unsafe.Pointer((bp) /* &count[0] */)) == code_lengths_size { + return 0 + } + + // Generate offsets into sorted symbol table by code length. + *(*int32)(unsafe.Pointer((bp + 64) /* &offset[0] */ + 1*4)) = 0 + for len = 1; len < 15; len++ { + if *(*int32)(unsafe.Pointer((bp) /* &count[0] */ + uintptr(len)*4)) > (int32(1) << len) { + return 0 + } + *(*int32)(unsafe.Pointer((bp + 64) /* &offset[0] */ + uintptr((len+1))*4)) = (*(*int32)(unsafe.Pointer((bp + 64) /* &offset[0] */ + uintptr(len)*4)) + *(*int32)(unsafe.Pointer((bp) /* &count[0] */ + uintptr(len)*4))) + } + + // Sort symbols by length, by symbol order within each length. + for symbol = 0; symbol < code_lengths_size; symbol++ { + var symbol_code_length int32 = *(*int32)(unsafe.Pointer(code_lengths + uintptr(symbol)*4)) + if *(*int32)(unsafe.Pointer(code_lengths + uintptr(symbol)*4)) > 0 { + if sorted != (uintptr(0)) { + *(*uint16_t)(unsafe.Pointer(sorted + uintptr(libc.PostIncInt32(&*(*int32)(unsafe.Pointer((bp + 64) /* &offset[0] */ + uintptr(symbol_code_length)*4)), 1))*2)) = uint16_t(symbol) + } else { + *(*int32)(unsafe.Pointer((bp + 64) /* &offset[0] */ + uintptr(symbol_code_length)*4))++ + } + } + } + + // Special case code with only one value. + if *(*int32)(unsafe.Pointer((bp + 64) /* &offset[0] */ + 15*4)) == 1 { + if sorted != (uintptr(0)) { + var code HuffmanCode + code.bits = uint8_t(0) + code.value = *(*uint16_t)(unsafe.Pointer(sorted)) + ReplicateValue(tls, table, 1, total_size, code) + } + return total_size + } + + { + var step int32 // step size to replicate values in current table + var low uint32_t = libc.Uint32FromInt32(-1) // low bits for current root entry + var mask uint32_t = (uint32_t(total_size - 1)) // mask for low bits + var key uint32_t = uint32_t(0) // reversed prefix code + var num_nodes int32 = 1 // number of Huffman tree nodes + var num_open int32 = 1 // number of open branches in current tree level + var table_bits int32 = root_bits // key length of current table + var table_size int32 = (int32(1) << table_bits) // size of current table + symbol = 0 + // Fill in root table. + len = 1 + step = 2 + __1: + if !(len <= root_bits) { + goto __3 + } + { + num_open <<= 1 + num_nodes = num_nodes + (num_open) + num_open = num_open - (*(*int32)(unsafe.Pointer((bp) /* &count[0] */ + uintptr(len)*4))) + if num_open < 0 { + return 0 + } + if root_table == (uintptr(0)) { + goto __2 + } + for ; *(*int32)(unsafe.Pointer((bp) /* &count[0] */ + uintptr(len)*4)) > 0; *(*int32)(unsafe.Pointer((bp) /* &count[0] */ + uintptr(len)*4))-- { + var code HuffmanCode + code.bits = uint8_t(len) + code.value = *(*uint16_t)(unsafe.Pointer(sorted + uintptr(libc.PostIncInt32(&symbol, 1))*2)) + ReplicateValue(tls, (table + uintptr(key)*4), step, table_size, code) + key = GetNextKey(tls, key, len) + } + + } + goto __2 + __2: + len++ + step <<= 1 + goto __1 + goto __3 + __3: + ; + + // Fill in 2nd level tables and add pointers to root table. + len = (root_bits + 1) + step = 2 + __4: + if !(len <= 15) { + goto __6 + } + { + num_open <<= 1 + num_nodes = num_nodes + (num_open) + num_open = num_open - (*(*int32)(unsafe.Pointer((bp) /* &count[0] */ + uintptr(len)*4))) + if num_open < 0 { + return 0 + } + if root_table == (uintptr(0)) { + goto __5 + } + for ; *(*int32)(unsafe.Pointer((bp) /* &count[0] */ + uintptr(len)*4)) > 0; *(*int32)(unsafe.Pointer((bp) /* &count[0] */ + uintptr(len)*4))-- { + var code HuffmanCode + if (key & mask) != low { + table += 4 * (uintptr(table_size)) + table_bits = NextTableBitSize(tls, (bp) /* &count[0] */, len, root_bits) + table_size = (int32(1) << table_bits) + total_size = total_size + (table_size) + low = (key & mask) + (*HuffmanCode)(unsafe.Pointer(root_table + uintptr(low)*4)).bits = (uint8_t(table_bits + root_bits)) + (*HuffmanCode)(unsafe.Pointer(root_table + uintptr(low)*4)).value = (uint16_t(((int64(table) - int64(root_table)) / 4) - int64(low))) + } + code.bits = (uint8_t(len - root_bits)) + code.value = *(*uint16_t)(unsafe.Pointer(sorted + uintptr(libc.PostIncInt32(&symbol, 1))*2)) + ReplicateValue(tls, (table + uintptr((key>>root_bits))*4), step, table_size, code) + key = GetNextKey(tls, key, len) + } + + } + goto __5 + __5: + len++ + step <<= 1 + goto __4 + goto __6 + __6: + ; + + // Check if tree is full. + if num_nodes != ((2 * *(*int32)(unsafe.Pointer((bp + 64) /* &offset[0] */ + 15*4))) - 1) { + return 0 + } + + } + + return total_size +} + +// Maximum code_lengths_size is 2328 (reached for 11-bit color_cache_bits). +// More commonly, the value is around ~280. +// Cut-off value for switching between heap and stack allocation. +func VP8LBuildHuffmanTable(tls *libc.TLS, root_table uintptr, root_bits int32, code_lengths uintptr, code_lengths_size int32) int32 { /* huffman_utils.c:214:5: */ + bp := tls.Alloc(1024) + defer tls.Free(1024) + + var total_size int32 + + if root_table == (uintptr(0)) { + total_size = BuildHuffmanTable(tls, (uintptr(0)), root_bits, + code_lengths, code_lengths_size, (uintptr(0))) + } else if code_lengths_size <= 512 { + // use local stack-allocated array. + // var sorted [512]uint16_t at bp, 1024 + + total_size = BuildHuffmanTable(tls, root_table, root_bits, + code_lengths, code_lengths_size, (bp) /* &sorted[0] */) + } else { // rare case. Use heap allocation. + var sorted uintptr = WebPSafeMalloc(tls, uint64(code_lengths_size), uint64(unsafe.Sizeof(uint16_t(0)))) + if sorted == (uintptr(0)) { + return 0 + } + total_size = BuildHuffmanTable(tls, root_table, root_bits, + code_lengths, code_lengths_size, sorted) + WebPSafeFree(tls, sorted) + } + return total_size +} + +//------------------------------------------------------------------------------ + +// #define USE_DITHERING // uncomment to enable ordered dithering (not vital) + +type SmoothParams = struct { + width_ int32 + height_ int32 + stride_ int32 + row_ int32 + src_ uintptr + dst_ uintptr + radius_ int32 + scale_ int32 + mem_ uintptr + start_ uintptr + cur_ uintptr + end_ uintptr + top_ uintptr + average_ uintptr + num_levels_ int32 + min_ int32 + max_ int32 + min_level_dist_ int32 + correction_ uintptr +} /* quant_levels_dec_utils.c:70:3 */ + +//------------------------------------------------------------------------------ + +func clip_8b3(tls *libc.TLS, v int32) uint8_t { /* quant_levels_dec_utils.c:75:28: */ + if !((v & (libc.Int32FromUint32(libc.Uint32(libc.CplUint32(libc.Uint32(0))) << (8 + 0)))) != 0) { + return (uint8_t(v >> 0)) + } + if v < 0 { + return uint8(0) + } + return uint8(255) +} + +// vertical accumulation +func VFilter(tls *libc.TLS, p uintptr) { /* quant_levels_dec_utils.c:81:13: */ + var src uintptr = (*SmoothParams)(unsafe.Pointer(p)).src_ + var w int32 = (*SmoothParams)(unsafe.Pointer(p)).width_ + var cur uintptr = (*SmoothParams)(unsafe.Pointer(p)).cur_ + var top uintptr = (*SmoothParams)(unsafe.Pointer(p)).top_ + var out uintptr = (*SmoothParams)(unsafe.Pointer(p)).end_ + var sum uint16_t = uint16_t(0) // all arithmetic is modulo 16bit + var x int32 + + for x = 0; x < w; x++ { + var new_value uint16_t + sum = uint16_t(int32(sum) + (int32(*(*uint8_t)(unsafe.Pointer(src + uintptr(x)))))) + new_value = (uint16_t(int32(*(*uint16_t)(unsafe.Pointer(top + uintptr(x)*2))) + int32(sum))) + *(*uint16_t)(unsafe.Pointer(out + uintptr(x)*2)) = (uint16_t(int32(new_value) - int32(*(*uint16_t)(unsafe.Pointer(cur + uintptr(x)*2))))) // vertical sum of 'r' pixels. + *(*uint16_t)(unsafe.Pointer(cur + uintptr(x)*2)) = new_value + } + // move input pointers one row down + (*SmoothParams)(unsafe.Pointer(p)).top_ = (*SmoothParams)(unsafe.Pointer(p)).cur_ + *(*uintptr)(unsafe.Pointer((p + 56 /* &.cur_ */))) += (uintptr(w)) * 2 + if (*SmoothParams)(unsafe.Pointer(p)).cur_ == (*SmoothParams)(unsafe.Pointer(p)).end_ { + (*SmoothParams)(unsafe.Pointer(p)).cur_ = (*SmoothParams)(unsafe.Pointer(p)).start_ + } // roll-over + // We replicate edges, as it's somewhat easier as a boundary condition. + // That's why we don't update the 'src' pointer on top/bottom area: + if ((*SmoothParams)(unsafe.Pointer(p)).row_ >= 0) && ((*SmoothParams)(unsafe.Pointer(p)).row_ < ((*SmoothParams)(unsafe.Pointer(p)).height_ - 1)) { + *(*uintptr)(unsafe.Pointer((p + 16 /* &.src_ */))) += (uintptr((*SmoothParams)(unsafe.Pointer(p)).stride_)) + } +} + +// horizontal accumulation. We use mirror replication of missing pixels, as it's +// a little easier to implement (surprisingly). +func HFilter(tls *libc.TLS, p uintptr) { /* quant_levels_dec_utils.c:110:13: */ + var in uintptr = (*SmoothParams)(unsafe.Pointer(p)).end_ + var out uintptr = (*SmoothParams)(unsafe.Pointer(p)).average_ + var scale uint32_t = uint32_t((*SmoothParams)(unsafe.Pointer(p)).scale_) + var w int32 = (*SmoothParams)(unsafe.Pointer(p)).width_ + var r int32 = (*SmoothParams)(unsafe.Pointer(p)).radius_ + var x int32 + for x = 0; x <= r; x++ { // left mirroring + var delta uint16_t = (uint16_t(int32(*(*uint16_t)(unsafe.Pointer(in + uintptr(((x+r)-1))*2))) + int32(*(*uint16_t)(unsafe.Pointer(in + uintptr((r-x))*2))))) + *(*uint16_t)(unsafe.Pointer(out + uintptr(x)*2)) = (uint16_t((uint32_t(delta) * scale) >> 16)) + } + for ; x < (w - r); x++ { // bulk middle run + var delta uint16_t = (uint16_t(int32(*(*uint16_t)(unsafe.Pointer(in + uintptr((x+r))*2))) - int32(*(*uint16_t)(unsafe.Pointer(in + uintptr(((x-r)-1))*2))))) + *(*uint16_t)(unsafe.Pointer(out + uintptr(x)*2)) = (uint16_t((uint32_t(delta) * scale) >> 16)) + } + for ; x < w; x++ { // right mirroring + var delta uint16_t = (uint16_t(((2 * int32(*(*uint16_t)(unsafe.Pointer(in + uintptr((w-1))*2)))) - int32(*(*uint16_t)(unsafe.Pointer(in + uintptr(((((2*w)-2)-r)-x))*2)))) - int32(*(*uint16_t)(unsafe.Pointer(in + uintptr(((x-r)-1))*2))))) + *(*uint16_t)(unsafe.Pointer(out + uintptr(x)*2)) = (uint16_t((uint32_t(delta) * scale) >> 16)) + } +} + +// emit one filtered output row +func ApplyFilter(tls *libc.TLS, p uintptr) { /* quant_levels_dec_utils.c:134:13: */ + var average uintptr = (*SmoothParams)(unsafe.Pointer(p)).average_ + var w int32 = (*SmoothParams)(unsafe.Pointer(p)).width_ + var correction uintptr = (*SmoothParams)(unsafe.Pointer(p)).correction_ + var dst uintptr = (*SmoothParams)(unsafe.Pointer(p)).dst_ + var x int32 + for x = 0; x < w; x++ { + var v int32 = int32(*(*uint8_t)(unsafe.Pointer(dst + uintptr(x)))) + if (v < (*SmoothParams)(unsafe.Pointer(p)).max_) && (v > (*SmoothParams)(unsafe.Pointer(p)).min_) { + var c int32 = ((v << 0) + int32(*(*int16_t)(unsafe.Pointer(correction + uintptr((int32(*(*uint16_t)(unsafe.Pointer(average + uintptr(x)*2)))-(v<<2)))*2)))) + *(*uint8_t)(unsafe.Pointer(dst + uintptr(x))) = clip_8b3(tls, c) + } + } + *(*uintptr)(unsafe.Pointer((p + 24 /* &.dst_ */))) += (uintptr((*SmoothParams)(unsafe.Pointer(p)).stride_)) // advance output pointer +} + +//------------------------------------------------------------------------------ +// Initialize correction table + +func InitCorrectionLUT(tls *libc.TLS, lut uintptr, min_dist int32) { /* quant_levels_dec_utils.c:160:13: */ + // The correction curve is: + // f(x) = x for x <= threshold2 + // f(x) = 0 for x >= threshold1 + // and a linear interpolation for range x=[threshold2, threshold1] + // (along with f(-x) = -f(x) symmetry). + // Note that: threshold2 = 3/4 * threshold1 + var threshold1 int32 = (min_dist << 2) + var threshold2 int32 = ((3 * threshold1) >> 2) + var max_threshold int32 = (threshold2 << 0) + var delta int32 = (threshold1 - threshold2) + var i int32 + for i = 1; i <= ((int32(1) << (8 + 2)) - 1); i++ { + var c int32 + if i <= threshold2 { + c = (i << 0) + } else { + if i < threshold1 { + c = ((max_threshold * (threshold1 - i)) / delta) + } else { + c = 0 + } + } + c >>= 2 + *(*int16_t)(unsafe.Pointer(lut + uintptr(+i)*2)) = +int16_t(c) + *(*int16_t)(unsafe.Pointer(lut + uintptr(-i)*2)) = int16_t(-c) + } + *(*int16_t)(unsafe.Pointer(lut)) = int16(0) +} + +func CountLevels(tls *libc.TLS, p uintptr) { /* quant_levels_dec_utils.c:183:13: */ + bp := tls.Alloc(256) + defer tls.Free(256) + + var i int32 + var j int32 + var last_level int32 + *(*[256]uint8_t)(unsafe.Pointer(bp /* used_levels */)) = [256]uint8_t{0: uint8_t(0)} + var data uintptr = (*SmoothParams)(unsafe.Pointer(p)).src_ + (*SmoothParams)(unsafe.Pointer(p)).min_ = 255 + (*SmoothParams)(unsafe.Pointer(p)).max_ = 0 + for j = 0; j < (*SmoothParams)(unsafe.Pointer(p)).height_; j++ { + for i = 0; i < (*SmoothParams)(unsafe.Pointer(p)).width_; i++ { + var v int32 = int32(*(*uint8_t)(unsafe.Pointer(data + uintptr(i)))) + if v < (*SmoothParams)(unsafe.Pointer(p)).min_ { + (*SmoothParams)(unsafe.Pointer(p)).min_ = v + } + if v > (*SmoothParams)(unsafe.Pointer(p)).max_ { + (*SmoothParams)(unsafe.Pointer(p)).max_ = v + } + *(*uint8_t)(unsafe.Pointer((bp) /* &used_levels[0] */ + uintptr(v))) = uint8_t(1) + } + data += uintptr((*SmoothParams)(unsafe.Pointer(p)).stride_) + } + // Compute the mininum distance between two non-zero levels. + (*SmoothParams)(unsafe.Pointer(p)).min_level_dist_ = ((*SmoothParams)(unsafe.Pointer(p)).max_ - (*SmoothParams)(unsafe.Pointer(p)).min_) + last_level = -1 + for i = 0; i < 256; i++ { + if *(*uint8_t)(unsafe.Pointer((bp) /* &used_levels[0] */ + uintptr(i))) != 0 { + (*SmoothParams)(unsafe.Pointer(p)).num_levels_++ + if last_level >= 0 { + var level_dist int32 = (i - last_level) + if level_dist < (*SmoothParams)(unsafe.Pointer(p)).min_level_dist_ { + (*SmoothParams)(unsafe.Pointer(p)).min_level_dist_ = level_dist + } + } + last_level = i + } + } +} + +// Initialize all params. +func InitParams(tls *libc.TLS, data uintptr, width int32, height int32, stride int32, radius int32, p uintptr) int32 { /* quant_levels_dec_utils.c:216:12: */ + var R int32 = ((2 * radius) + 1) // total size of the kernel + + var size_scratch_m size_t = ((uint64((R + 1) * width)) * uint64(unsafe.Sizeof(uint16_t(0)))) + var size_m size_t = (uint64(width) * uint64(unsafe.Sizeof(uint16_t(0)))) + var size_lut size_t = ((uint64(1 + (2 * ((int32(1) << (8 + 2)) - 1)))) * uint64(unsafe.Sizeof(int16_t(0)))) + var total_size size_t = ((size_scratch_m + size_m) + size_lut) + var mem uintptr = WebPSafeMalloc(tls, uint64(1), total_size) + + if mem == (uintptr(0)) { + return 0 + } + (*SmoothParams)(unsafe.Pointer(p)).mem_ = mem + + (*SmoothParams)(unsafe.Pointer(p)).start_ = mem + (*SmoothParams)(unsafe.Pointer(p)).cur_ = (*SmoothParams)(unsafe.Pointer(p)).start_ + (*SmoothParams)(unsafe.Pointer(p)).end_ = ((*SmoothParams)(unsafe.Pointer(p)).start_ + uintptr((R*width))*2) + (*SmoothParams)(unsafe.Pointer(p)).top_ = ((*SmoothParams)(unsafe.Pointer(p)).end_ - uintptr(width)*2) + libc.Xmemset(tls, (*SmoothParams)(unsafe.Pointer(p)).top_, 0, (uint64(width) * uint64(unsafe.Sizeof(uint16_t(0))))) + mem += uintptr(size_scratch_m) + + (*SmoothParams)(unsafe.Pointer(p)).average_ = mem + mem += uintptr(size_m) + + (*SmoothParams)(unsafe.Pointer(p)).width_ = width + (*SmoothParams)(unsafe.Pointer(p)).height_ = height + (*SmoothParams)(unsafe.Pointer(p)).stride_ = stride + (*SmoothParams)(unsafe.Pointer(p)).src_ = data + (*SmoothParams)(unsafe.Pointer(p)).dst_ = data + (*SmoothParams)(unsafe.Pointer(p)).radius_ = radius + (*SmoothParams)(unsafe.Pointer(p)).scale_ = ((int32(1) << (16 + 2)) / (R * R)) // normalization constant + (*SmoothParams)(unsafe.Pointer(p)).row_ = -radius + + // analyze the input distribution so we can best-fit the threshold + CountLevels(tls, p) + + // correction table + (*SmoothParams)(unsafe.Pointer(p)).correction_ = ((mem) + uintptr(((int32(1)<<(8+2))-1))*2) + InitCorrectionLUT(tls, (*SmoothParams)(unsafe.Pointer(p)).correction_, (*SmoothParams)(unsafe.Pointer(p)).min_level_dist_) + + return 1 +} + +func CleanupParams(tls *libc.TLS, p uintptr) { /* quant_levels_dec_utils.c:258:13: */ + WebPSafeFree(tls, (*SmoothParams)(unsafe.Pointer(p)).mem_) +} + +func WebPDequantizeLevels(tls *libc.TLS, data uintptr, width int32, height int32, stride int32, strength int32) int32 { /* quant_levels_dec_utils.c:262:5: */ + bp := tls.Alloc(112) + defer tls.Free(112) + + var radius int32 = ((4 * strength) / 100) + + if (strength < 0) || (strength > 100) { + return 0 + } + if ((data == (uintptr(0))) || (width <= 0)) || (height <= 0) { + return 0 + } // bad params + + // limit the filter size to not exceed the image dimensions + if ((2 * radius) + 1) > width { + radius = ((width - 1) >> 1) + } + if ((2 * radius) + 1) > height { + radius = ((height - 1) >> 1) + } + + if radius > 0 { + // var p SmoothParams at bp, 112 + + libc.Xmemset(tls, (bp) /* &p */, 0, uint64(unsafe.Sizeof(SmoothParams{}))) + if !(InitParams(tls, data, width, height, stride, radius, (bp) /* &p */) != 0) { + return 0 + } + if (*SmoothParams)(unsafe.Pointer(bp /* &p */)).num_levels_ > 2 { + for ; (*SmoothParams)(unsafe.Pointer(bp /* &p */)).row_ < (*SmoothParams)(unsafe.Pointer(bp /* &p */)).height_; (*SmoothParams)(unsafe.Pointer(bp /* &p */)).row_++ { + VFilter(tls, (bp) /* &p */) // accumulate average of input + // Need to wait few rows in order to prime the filter, + // before emitting some output. + if (*SmoothParams)(unsafe.Pointer(bp /* &p */)).row_ >= (*SmoothParams)(unsafe.Pointer(bp /* &p */)).radius_ { + HFilter(tls, (bp) /* &p */) + ApplyFilter(tls, (bp) /* &p */) + } + } + } + CleanupParams(tls, (bp) /* &p */) + } + return 1 +} + +// ----------------------------------------------------------------------------- +// Quantize levels. + +func QuantizeLevels(tls *libc.TLS, data uintptr, width int32, height int32, num_levels int32, sse uintptr) int32 { /* quant_levels_utils.c:27:5: */ + bp := tls.Alloc(8448) + defer tls.Free(8448) + + // var freq [256]int32 at bp, 1024 + + // var q_level [256]int32 at bp+3072, 1024 + + // var inv_q_level [256]float64 at bp+1024, 2048 + + var min_s int32 + var max_s int32 + var data_size size_t + var i int32 + var num_levels_in int32 + var iter int32 + var last_err float64 + var err float64 + var err_threshold float64 + var n size_t + var count float64 + var error float64 + // var q_sum [256]float64 at bp+4096, 2048 + + // var q_count [256]float64 at bp+6144, 2048 + + var s int32 + var slot int32 + var slot1 int32 + // double->int rounding operation can be costly, so we do it + // once for all before remapping. We also perform the data[] -> slot + // mapping, while at it (avoid one indirection in the final loop). + // var map1 [256]uint8_t at bp+8192, 256 + + var s1 int32 + var n1 size_t + *(*[256]int32)(unsafe.Pointer(bp /* freq */)) = [256]int32{0: 0} + *(*[256]int32)(unsafe.Pointer(bp + 3072 /* q_level */)) = [256]int32{0: 0} + *(*[256]float64)(unsafe.Pointer(bp + 1024 /* inv_q_level */)) = [256]float64{0: float64(0)} + min_s = 255 + max_s = 0 + data_size = (size_t(height * width)) + last_err = 1.e38 + err = 0. + err_threshold = (1e-4 * float64(data_size)) + + if !(data == (uintptr(0))) { + goto __1 + } + return 0 +__1: + ; + + if !((width <= 0) || (height <= 0)) { + goto __2 + } + return 0 +__2: + ; + + if !((num_levels < 2) || (num_levels > 256)) { + goto __3 + } + return 0 +__3: + ; + + num_levels_in = 0 + n = uint64(0) +__4: + if !(n < data_size) { + goto __6 + } + num_levels_in = num_levels_in + (libc.Bool32(*(*int32)(unsafe.Pointer((bp) /* &freq[0] */ + uintptr(*(*uint8_t)(unsafe.Pointer(data + uintptr(n))))*4)) == 0)) + if !(min_s > int32(*(*uint8_t)(unsafe.Pointer(data + uintptr(n))))) { + goto __7 + } + min_s = int32(*(*uint8_t)(unsafe.Pointer(data + uintptr(n)))) +__7: + ; + if !(max_s < int32(*(*uint8_t)(unsafe.Pointer(data + uintptr(n))))) { + goto __8 + } + max_s = int32(*(*uint8_t)(unsafe.Pointer(data + uintptr(n)))) +__8: + ; + *(*int32)(unsafe.Pointer((bp) /* &freq[0] */ + uintptr(*(*uint8_t)(unsafe.Pointer(data + uintptr(n))))*4))++ + goto __5 +__5: + n++ + goto __4 + goto __6 +__6: + ; + + if !(num_levels_in <= num_levels) { + goto __9 + } + goto End +__9: + ; // nothing to do! + + // Start with uniformly spread centroids. + i = 0 +__10: + if !(i < num_levels) { + goto __12 + } + *(*float64)(unsafe.Pointer((bp + 1024) /* &inv_q_level[0] */ + uintptr(i)*8)) = (float64(min_s) + (((float64(max_s - min_s)) * float64(i)) / (float64(num_levels - 1)))) + goto __11 +__11: + i++ + goto __10 + goto __12 +__12: + ; + + // Fixed values. Won't be changed. + *(*int32)(unsafe.Pointer((bp + 3072) /* &q_level[0] */ + uintptr(min_s)*4)) = 0 + *(*int32)(unsafe.Pointer((bp + 3072) /* &q_level[0] */ + uintptr(max_s)*4)) = (num_levels - 1) + + // k-Means iterations. + iter = 0 +__13: + if !(iter < 6) { + goto __15 + } + *(*[256]float64)(unsafe.Pointer(bp + 4096 /* q_sum */)) = [256]float64{0: float64(0)} + *(*[256]float64)(unsafe.Pointer(bp + 6144 /* q_count */)) = [256]float64{0: float64(0)} + slot = 0 + + // Assign classes to representatives. + s = min_s +__16: + if !(s <= max_s) { + goto __18 + } + // Keep track of the nearest neighbour 'slot' +__19: + if !((slot < (num_levels - 1)) && ((float64(2 * s)) > (*(*float64)(unsafe.Pointer((bp + 1024) /* &inv_q_level[0] */ + uintptr(slot)*8)) + *(*float64)(unsafe.Pointer((bp + 1024) /* &inv_q_level[0] */ + uintptr((slot+1))*8))))) { + goto __20 + } + slot++ + goto __19 +__20: + ; + if !(*(*int32)(unsafe.Pointer((bp) /* &freq[0] */ + uintptr(s)*4)) > 0) { + goto __21 + } + *(*float64)(unsafe.Pointer(((bp + 4096) /* &q_sum */ + uintptr(slot)*8))) += (float64(s * *(*int32)(unsafe.Pointer((bp) /* &freq[0] */ + uintptr(s)*4)))) + *(*float64)(unsafe.Pointer(((bp + 6144) /* &q_count */ + uintptr(slot)*8))) += (float64(*(*int32)(unsafe.Pointer((bp) /* &freq[0] */ + uintptr(s)*4)))) +__21: + ; + *(*int32)(unsafe.Pointer((bp + 3072) /* &q_level[0] */ + uintptr(s)*4)) = slot + goto __17 +__17: + s++ + goto __16 + goto __18 +__18: + ; + + // Assign new representatives to classes. + if !(num_levels > 2) { + goto __22 + } + slot = 1 +__23: + if !(slot < (num_levels - 1)) { + goto __25 + } + count = *(*float64)(unsafe.Pointer((bp + 6144) /* &q_count[0] */ + uintptr(slot)*8)) + if !(count > 0.) { + goto __26 + } + *(*float64)(unsafe.Pointer((bp + 1024) /* &inv_q_level[0] */ + uintptr(slot)*8)) = (*(*float64)(unsafe.Pointer((bp + 4096) /* &q_sum[0] */ + uintptr(slot)*8)) / count) +__26: + ; + goto __24 +__24: + slot++ + goto __23 + goto __25 +__25: + ; +__22: + ; + + // Compute convergence error. + err = 0. + s = min_s +__27: + if !(s <= max_s) { + goto __29 + } + error = (float64(s) - *(*float64)(unsafe.Pointer((bp + 1024) /* &inv_q_level[0] */ + uintptr(*(*int32)(unsafe.Pointer((bp + 3072) /* &q_level[0] */ + uintptr(s)*4)))*8))) + err = err + ((float64(*(*int32)(unsafe.Pointer((bp) /* &freq[0] */ + uintptr(s)*4))) * error) * error) + goto __28 +__28: + s++ + goto __27 + goto __29 +__29: + ; + + // Check for convergence: we stop as soon as the error is no + // longer improving. + if !((last_err - err) < err_threshold) { + goto __30 + } + goto __15 +__30: + ; + last_err = err + goto __14 +__14: + iter++ + goto __13 + goto __15 +__15: + ; + + // Remap the alpha plane to quantized values. + + s1 = min_s +__31: + if !(s1 <= max_s) { + goto __33 + } + slot1 = *(*int32)(unsafe.Pointer((bp + 3072) /* &q_level[0] */ + uintptr(s1)*4)) + *(*uint8_t)(unsafe.Pointer((bp + 8192) /* &map1[0] */ + uintptr(s1))) = (libc.Uint8FromFloat64(*(*float64)(unsafe.Pointer((bp + 1024) /* &inv_q_level[0] */ + uintptr(slot1)*8)) + .5)) + goto __32 +__32: + s1++ + goto __31 + goto __33 +__33: + ; + // Final pass. + n1 = uint64(0) +__34: + if !(n1 < data_size) { + goto __36 + } + *(*uint8_t)(unsafe.Pointer(data + uintptr(n1))) = *(*uint8_t)(unsafe.Pointer((bp + 8192) /* &map1[0] */ + uintptr(*(*uint8_t)(unsafe.Pointer(data + uintptr(n1)))))) + goto __35 +__35: + n1++ + goto __34 + goto __36 +__36: + ; + +End: + // Store sum of squared error if needed. + if !(sse != (uintptr(0))) { + goto __37 + } + *(*uint64_t)(unsafe.Pointer(sse)) = uint64_t(err) +__37: + ; + + return 1 +} + +//------------------------------------------------------------------------------ + +// 31b-range values +var kRandomTable = [55]uint32_t{ + uint32_t(0x0de15230), uint32_t(0x03b31886), uint32_t(0x775faccb), uint32_t(0x1c88626a), uint32_t(0x68385c55), uint32_t(0x14b3b828), + uint32_t(0x4a85fef8), uint32_t(0x49ddb84b), uint32_t(0x64fcf397), uint32_t(0x5c550289), uint32_t(0x4a290000), uint32_t(0x0d7ec1da), + uint32_t(0x5940b7ab), uint32_t(0x5492577d), uint32_t(0x4e19ca72), uint32_t(0x38d38c69), uint32_t(0x0c01ee65), uint32_t(0x32a1755f), + uint32_t(0x5437f652), uint32_t(0x5abb2c32), uint32_t(0x0faa57b1), uint32_t(0x73f533e7), uint32_t(0x685feeda), uint32_t(0x7563cce2), + uint32_t(0x6e990e83), uint32_t(0x4730a7ed), uint32_t(0x4fc0d9c6), uint32_t(0x496b153c), uint32_t(0x4f1403fa), uint32_t(0x541afb0c), + uint32_t(0x73990b32), uint32_t(0x26d7cb1c), uint32_t(0x6fcc3706), uint32_t(0x2cbb77d8), uint32_t(0x75762f2a), uint32_t(0x6425ccdd), + uint32_t(0x24b35461), uint32_t(0x0a7d8715), uint32_t(0x220414a8), uint32_t(0x141ebf67), uint32_t(0x56b41583), uint32_t(0x73e502e3), + uint32_t(0x44cab16f), uint32_t(0x28264d42), uint32_t(0x73baaefb), uint32_t(0x0a50ebed), uint32_t(0x1d6ab6fb), uint32_t(0x0d3ad40b), + uint32_t(0x35db3b68), uint32_t(0x2b081e83), uint32_t(0x77ce6b95), uint32_t(0x5181e5f0), uint32_t(0x78853bbc), uint32_t(0x009f9494), + uint32_t(0x27e5ed3c), +} /* random_utils.c:20:23 */ + +func VP8InitRandom(tls *libc.TLS, rg uintptr, dithering float32) { /* random_utils.c:33:6: */ + libc.Xmemcpy(tls, (rg + 8 /* &.tab_ */), uintptr(unsafe.Pointer(&kRandomTable)), uint64(unsafe.Sizeof([55]uint32_t{}))) + (*VP8Random)(unsafe.Pointer(rg)).index1_ = 0 + (*VP8Random)(unsafe.Pointer(rg)).index2_ = 31 + (*VP8Random)(unsafe.Pointer(rg)).amp_ = func() int32 { + if float64(dithering) < 0.0 { + return 0 + } + return func() int32 { + if float64(dithering) > 1.0 { + return (int32(1) << 8) + } + return int32((libc.Uint32FromFloat32((float32(int32(1) << 8)) * dithering))) + }() + }() +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +func WebPRescalerInit(tls *libc.TLS, rescaler uintptr, src_width int32, src_height int32, dst uintptr, dst_width int32, dst_height int32, dst_stride int32, num_channels int32, work uintptr) int32 { /* rescaler_utils.c:24:5: */ + var x_add int32 = src_width + var x_sub int32 = dst_width + var y_add int32 = src_height + var y_sub int32 = dst_height + var total_size uint64_t = (uint64_t(((2 * uint64(dst_width)) * uint64(num_channels)) * uint64(unsafe.Sizeof(rescaler_t(0))))) + if !(CheckSizeOverflow(tls, total_size) != 0) { + return 0 + } + + (*WebPRescaler)(unsafe.Pointer(rescaler)).x_expand = (libc.Bool32(src_width < dst_width)) + (*WebPRescaler)(unsafe.Pointer(rescaler)).y_expand = (libc.Bool32(src_height < dst_height)) + (*WebPRescaler)(unsafe.Pointer(rescaler)).src_width = src_width + (*WebPRescaler)(unsafe.Pointer(rescaler)).src_height = src_height + (*WebPRescaler)(unsafe.Pointer(rescaler)).dst_width = dst_width + (*WebPRescaler)(unsafe.Pointer(rescaler)).dst_height = dst_height + (*WebPRescaler)(unsafe.Pointer(rescaler)).src_y = 0 + (*WebPRescaler)(unsafe.Pointer(rescaler)).dst_y = 0 + (*WebPRescaler)(unsafe.Pointer(rescaler)).dst = dst + (*WebPRescaler)(unsafe.Pointer(rescaler)).dst_stride = dst_stride + (*WebPRescaler)(unsafe.Pointer(rescaler)).num_channels = num_channels + + // for 'x_expand', we use bilinear interpolation + (*WebPRescaler)(unsafe.Pointer(rescaler)).x_add = func() int32 { + if (*WebPRescaler)(unsafe.Pointer(rescaler)).x_expand != 0 { + return (x_sub - 1) + } + return x_add + }() + (*WebPRescaler)(unsafe.Pointer(rescaler)).x_sub = func() int32 { + if (*WebPRescaler)(unsafe.Pointer(rescaler)).x_expand != 0 { + return (x_add - 1) + } + return x_sub + }() + if !((*WebPRescaler)(unsafe.Pointer(rescaler)).x_expand != 0) { // fx_scale is not used otherwise + (*WebPRescaler)(unsafe.Pointer(rescaler)).fx_scale = (uint32_t((uint64_t((uint64(1))) << 32) / (uint64_t((*WebPRescaler)(unsafe.Pointer(rescaler)).x_sub)))) + } + // vertical scaling parameters + (*WebPRescaler)(unsafe.Pointer(rescaler)).y_add = func() int32 { + if (*WebPRescaler)(unsafe.Pointer(rescaler)).y_expand != 0 { + return (y_add - 1) + } + return y_add + }() + (*WebPRescaler)(unsafe.Pointer(rescaler)).y_sub = func() int32 { + if (*WebPRescaler)(unsafe.Pointer(rescaler)).y_expand != 0 { + return (y_sub - 1) + } + return y_sub + }() + (*WebPRescaler)(unsafe.Pointer(rescaler)).y_accum = func() int32 { + if (*WebPRescaler)(unsafe.Pointer(rescaler)).y_expand != 0 { + return (*WebPRescaler)(unsafe.Pointer(rescaler)).y_sub + } + return (*WebPRescaler)(unsafe.Pointer(rescaler)).y_add + }() + if !((*WebPRescaler)(unsafe.Pointer(rescaler)).y_expand != 0) { + // This is WEBP_RESCALER_FRAC(dst_height, x_add * y_add) without the cast. + // Its value is <= WEBP_RESCALER_ONE, because dst_height <= rescaler->y_add + // and rescaler->x_add >= 1; + var num uint64_t = (uint64_t(uint64(uint64_t(dst_height)) * (uint64(1) << 32))) + var den uint64_t = (uint64_t((*WebPRescaler)(unsafe.Pointer(rescaler)).x_add) * uint64_t((*WebPRescaler)(unsafe.Pointer(rescaler)).y_add)) + var ratio uint64_t = (num / den) + if ratio != uint64_t(uint32_t(ratio)) { + // When ratio == WEBP_RESCALER_ONE, we can't represent the ratio with the + // current fixed-point precision. This happens when src_height == + // rescaler->y_add (which == src_height), and rescaler->x_add == 1. + // => We special-case fxy_scale = 0, in WebPRescalerExportRow(). + (*WebPRescaler)(unsafe.Pointer(rescaler)).fxy_scale = uint32_t(0) + } else { + (*WebPRescaler)(unsafe.Pointer(rescaler)).fxy_scale = uint32_t(ratio) + } + (*WebPRescaler)(unsafe.Pointer(rescaler)).fy_scale = (uint32_t((uint64_t((uint64(1))) << 32) / (uint64_t((*WebPRescaler)(unsafe.Pointer(rescaler)).y_sub)))) + } else { + (*WebPRescaler)(unsafe.Pointer(rescaler)).fy_scale = (uint32_t((uint64_t((uint64(1))) << 32) / (uint64_t((*WebPRescaler)(unsafe.Pointer(rescaler)).x_add)))) + // rescaler->fxy_scale is unused here. + } + (*WebPRescaler)(unsafe.Pointer(rescaler)).irow = work + (*WebPRescaler)(unsafe.Pointer(rescaler)).frow = (work + uintptr((num_channels*dst_width))*4) + libc.Xmemset(tls, work, 0, total_size) + + WebPRescalerDspInit(tls) + return 1 +} + +func WebPRescalerGetScaledDimensions(tls *libc.TLS, src_width int32, src_height int32, scaled_width uintptr, scaled_height uintptr) int32 { /* rescaler_utils.c:85:5: */ + + { + var width int32 = *(*int32)(unsafe.Pointer(scaled_width)) + var height int32 = *(*int32)(unsafe.Pointer(scaled_height)) + var max_size int32 = (0x7fffffff / 2) + + // if width is unspecified, scale original proportionally to height ratio. + if (width == 0) && (src_height > 0) { + width = (int32((((uint64_t(src_width) * uint64_t(height)) + uint64_t(src_height)) - uint64(1)) / uint64_t(src_height))) + } + // if height is unspecified, scale original proportionally to width ratio. + if (height == 0) && (src_width > 0) { + height = (int32((((uint64_t(src_height) * uint64_t(width)) + uint64_t(src_width)) - uint64(1)) / uint64_t(src_width))) + } + // Check if the overall dimensions still make sense. + if (((width <= 0) || (height <= 0)) || (width > max_size)) || (height > max_size) { + return 0 + } + + *(*int32)(unsafe.Pointer(scaled_width)) = width + *(*int32)(unsafe.Pointer(scaled_height)) = height + return 1 + + } + return int32(0) +} + +//------------------------------------------------------------------------------ +// all-in-one calls + +func WebPRescaleNeededLines(tls *libc.TLS, rescaler uintptr, max_num_lines int32) int32 { /* rescaler_utils.c:119:5: */ + var num_lines int32 = ((((*WebPRescaler)(unsafe.Pointer(rescaler)).y_accum + (*WebPRescaler)(unsafe.Pointer(rescaler)).y_sub) - 1) / (*WebPRescaler)(unsafe.Pointer(rescaler)).y_sub) + if num_lines > max_num_lines { + return max_num_lines + } + return num_lines +} + +func WebPRescalerImport(tls *libc.TLS, rescaler uintptr, num_lines int32, src uintptr, src_stride int32) int32 { /* rescaler_utils.c:126:5: */ + var total_imported int32 = 0 + for (total_imported < num_lines) && !(WebPRescalerHasPendingOutput(tls, rescaler) != 0) { + if (*WebPRescaler)(unsafe.Pointer(rescaler)).y_expand != 0 { + var tmp uintptr = (*WebPRescaler)(unsafe.Pointer(rescaler)).irow + (*WebPRescaler)(unsafe.Pointer(rescaler)).irow = (*WebPRescaler)(unsafe.Pointer(rescaler)).frow + (*WebPRescaler)(unsafe.Pointer(rescaler)).frow = tmp + } + WebPRescalerImportRow(tls, rescaler, src) + if !((*WebPRescaler)(unsafe.Pointer(rescaler)).y_expand != 0) { // Accumulate the contribution of the new row. + var x int32 + for x = 0; x < ((*WebPRescaler)(unsafe.Pointer(rescaler)).num_channels * (*WebPRescaler)(unsafe.Pointer(rescaler)).dst_width); x++ { + *(*rescaler_t)(unsafe.Pointer(((*WebPRescaler)(unsafe.Pointer(rescaler)).irow + uintptr(x)*4))) += (*(*rescaler_t)(unsafe.Pointer((*WebPRescaler)(unsafe.Pointer(rescaler)).frow + uintptr(x)*4))) + } + } + (*WebPRescaler)(unsafe.Pointer(rescaler)).src_y++ + src += uintptr(src_stride) + total_imported++ + *(*int32)(unsafe.Pointer((rescaler + 24 /* &.y_accum */))) -= ((*WebPRescaler)(unsafe.Pointer(rescaler)).y_sub) + } + return total_imported +} + +func WebPRescalerExport(tls *libc.TLS, rescaler uintptr) int32 { /* rescaler_utils.c:151:5: */ + var total_exported int32 = 0 + for WebPRescalerHasPendingOutput(tls, rescaler) != 0 { + WebPRescalerExportRow(tls, rescaler) + total_exported++ + } + return total_exported +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +func Init(tls *libc.TLS, worker uintptr) { /* thread_utils.c:263:13: */ + libc.Xmemset(tls, worker, 0, uint64(unsafe.Sizeof(WebPWorker{}))) + (*WebPWorker)(unsafe.Pointer(worker)).status_ = NOT_OK +} + +func Sync(tls *libc.TLS, worker uintptr) int32 { /* thread_utils.c:268:12: */ + + return libc.BoolInt32(!((*WebPWorker)(unsafe.Pointer(worker)).had_error != 0)) +} + +func Reset(tls *libc.TLS, worker uintptr) int32 { /* thread_utils.c:276:12: */ + var ok int32 = 1 + (*WebPWorker)(unsafe.Pointer(worker)).had_error = 0 + if (*WebPWorker)(unsafe.Pointer(worker)).status_ < OK { + (*WebPWorker)(unsafe.Pointer(worker)).status_ = OK + } else if (*WebPWorker)(unsafe.Pointer(worker)).status_ > OK { + ok = Sync(tls, worker) + } + + return ok +} + +func Execute(tls *libc.TLS, worker uintptr) { /* thread_utils.c:316:13: */ + if (*WebPWorker)(unsafe.Pointer(worker)).hook != (uintptr(0)) { + *(*int32)(unsafe.Pointer((worker + 40 /* &.had_error */))) |= (libc.BoolInt32(!((*struct { + f func(*libc.TLS, uintptr, uintptr) int32 + })(unsafe.Pointer(&struct{ uintptr }{(*WebPWorker)(unsafe.Pointer(worker)).hook})).f(tls, (*WebPWorker)(unsafe.Pointer(worker)).data1, (*WebPWorker)(unsafe.Pointer(worker)).data2) != 0))) + } +} + +func Launch(tls *libc.TLS, worker uintptr) { /* thread_utils.c:322:13: */ + Execute(tls, worker) +} + +func End(tls *libc.TLS, worker uintptr) { /* thread_utils.c:330:13: */ + (*WebPWorker)(unsafe.Pointer(worker)).status_ = NOT_OK + +} + +//------------------------------------------------------------------------------ + +var g_worker_interface = WebPWorkerInterface{ + Init: 0, Reset: 0, Sync: 0, Launch: 0, Execute: 0, End: 0, +} /* thread_utils.c:350:28 */ + +func WebPSetWorkerInterface(tls *libc.TLS, winterface uintptr) int32 { /* thread_utils.c:354:5: */ + if ((((((winterface == (uintptr(0))) || ((*WebPWorkerInterface)(unsafe.Pointer(winterface)).Init == (uintptr(0)))) || ((*WebPWorkerInterface)(unsafe.Pointer(winterface)).Reset == (uintptr(0)))) || ((*WebPWorkerInterface)(unsafe.Pointer(winterface)).Sync == (uintptr(0)))) || ((*WebPWorkerInterface)(unsafe.Pointer(winterface)).Launch == (uintptr(0)))) || ((*WebPWorkerInterface)(unsafe.Pointer(winterface)).Execute == (uintptr(0)))) || ((*WebPWorkerInterface)(unsafe.Pointer(winterface)).End == (uintptr(0))) { + return 0 + } + g_worker_interface = *(*WebPWorkerInterface)(unsafe.Pointer(winterface)) + return 1 +} + +func WebPGetWorkerInterface(tls *libc.TLS) uintptr { /* thread_utils.c:365:26: */ + return uintptr(unsafe.Pointer(&g_worker_interface)) +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +// If PRINT_MEM_INFO is defined, extra info (like total memory used, number of +// alloc/free etc) is printed. For debugging/tuning purpose only (it's slow, +// and not multi-thread safe!). +// An interesting alternative is valgrind's 'massif' tool: +// https://valgrind.org/docs/manual/ms-manual.html +// Here is an example command line: +// valgrind --tool=massif --massif-out-file=massif.out --stacks=yes --alloc-fn=WebPSafeMalloc --alloc-fn=WebPSafeCalloc +// ms_print massif.out +// In addition: +// * if PRINT_MEM_TRAFFIC is defined, all the details of the malloc/free cycles +// are printed. +// * if MALLOC_FAIL_AT is defined, the global environment variable +// $MALLOC_FAIL_AT is used to simulate a memory error when calloc or malloc +// is called for the nth time. Example usage: +// export MALLOC_FAIL_AT=50 && ./examples/cwebp input.png +// * if MALLOC_LIMIT is defined, the global environment variable $MALLOC_LIMIT +// sets the maximum amount of memory (in bytes) made available to libwebp. +// This can be used to emulate environment with very limited memory. +// Example: export MALLOC_LIMIT=64000000 && ./examples/dwebp picture.webp + +// #define PRINT_MEM_INFO +// #define PRINT_MEM_TRAFFIC +// #define MALLOC_FAIL_AT +// #define MALLOC_LIMIT + +//------------------------------------------------------------------------------ +// Checked memory allocation + +// Returns 0 in case of overflow of nmemb * size. +func CheckSizeArgumentsOverflow(tls *libc.TLS, nmemb uint64_t, size size_t) int32 { /* utils.c:171:12: */ + var total_size uint64_t = (nmemb * size) + if nmemb == uint64(0) { + return 1 + } + if uint64(size) > ((uint64(1) << 34) / uint64(nmemb)) { + return 0 + } + if !(CheckSizeOverflow(tls, total_size) != 0) { + return 0 + } + + return 1 +} + +func WebPSafeMalloc(tls *libc.TLS, nmemb uint64_t, size size_t) uintptr { /* utils.c:194:5: */ + var ptr uintptr + for ok := true; ok; ok = (0 != 0) { + } + if !(CheckSizeArgumentsOverflow(tls, nmemb, size) != 0) { + return (uintptr(0)) + } + + ptr = libc.Xmalloc(tls, (nmemb * size)) + for ok1 := true; ok1; ok1 = (0 != 0) { + } + return ptr +} + +func WebPSafeCalloc(tls *libc.TLS, nmemb uint64_t, size size_t) uintptr { /* utils.c:204:5: */ + var ptr uintptr + for ok := true; ok; ok = (0 != 0) { + } + if !(CheckSizeArgumentsOverflow(tls, nmemb, size) != 0) { + return (uintptr(0)) + } + + ptr = libc.Xcalloc(tls, nmemb, size) + for ok1 := true; ok1; ok1 = (0 != 0) { + } + return ptr +} + +func WebPSafeFree(tls *libc.TLS, ptr uintptr) { /* utils.c:214:6: */ + if ptr != (uintptr(0)) { + for ok := true; ok; ok = (0 != 0) { + } + for ok1 := true; ok1; ok1 = (0 != 0) { + } + } + libc.Xfree(tls, ptr) +} + +// Public API functions. + +func WebPMalloc(tls *libc.TLS, size size_t) uintptr { /* utils.c:224:5: */ + return WebPSafeMalloc(tls, uint64(1), size) +} + +func WebPFree(tls *libc.TLS, ptr uintptr) { /* utils.c:228:6: */ + WebPSafeFree(tls, ptr) +} + +//------------------------------------------------------------------------------ + +func WebPCopyPlane(tls *libc.TLS, src uintptr, src_stride int32, dst uintptr, dst_stride int32, width int32, height int32) { /* utils.c:234:6: */ + + for libc.PostDecInt32(&height, 1) > 0 { + libc.Xmemcpy(tls, dst, src, uint64(width)) + src += uintptr(src_stride) + dst += uintptr(dst_stride) + } +} + +func WebPCopyPixels(tls *libc.TLS, src uintptr, dst uintptr) { /* utils.c:245:6: */ + + WebPCopyPlane(tls, (*WebPPicture)(unsafe.Pointer(src)).argb, (4 * (*WebPPicture)(unsafe.Pointer(src)).argb_stride), (*WebPPicture)(unsafe.Pointer(dst)).argb, + (4 * (*WebPPicture)(unsafe.Pointer(dst)).argb_stride), (4 * (*WebPPicture)(unsafe.Pointer(src)).width), (*WebPPicture)(unsafe.Pointer(src)).height) +} + +//------------------------------------------------------------------------------ + +func WebPGetColorPalette(tls *libc.TLS, pic uintptr, palette uintptr) int32 { /* utils.c:258:5: */ + bp := tls.Alloc(5120) + defer tls.Free(5120) + + var i int32 + var x int32 + var y int32 + var num_colors int32 = 0 + *(*[1024]uint8_t)(unsafe.Pointer(bp /* in_use */)) = [1024]uint8_t{0: uint8_t(0)} + // var colors [1024]uint32_t at bp+1024, 4096 + + var argb uintptr = (*WebPPicture)(unsafe.Pointer(pic)).argb + var width int32 = (*WebPPicture)(unsafe.Pointer(pic)).width + var height int32 = (*WebPPicture)(unsafe.Pointer(pic)).height + var last_pix uint32_t = ^*(*uint32_t)(unsafe.Pointer(argb)) // so we're sure that last_pix != argb[0] + + for y = 0; y < height; y++ { + for x = 0; x < width; x++ { + var key int32 + if *(*uint32_t)(unsafe.Pointer(argb + uintptr(x)*4)) == last_pix { + continue + } + last_pix = *(*uint32_t)(unsafe.Pointer(argb + uintptr(x)*4)) + key = VP8LHashPix(tls, last_pix, 22) + for 1 != 0 { + if !(int32(*(*uint8_t)(unsafe.Pointer((bp) /* &in_use[0] */ + uintptr(key)))) != 0) { + *(*uint32_t)(unsafe.Pointer((bp + 1024) /* &colors[0] */ + uintptr(key)*4)) = last_pix + *(*uint8_t)(unsafe.Pointer((bp) /* &in_use[0] */ + uintptr(key))) = uint8_t(1) + num_colors++ + if num_colors > 256 { + return (256 + 1) // Exact count not needed. + } + break + } else if *(*uint32_t)(unsafe.Pointer((bp + 1024) /* &colors[0] */ + uintptr(key)*4)) == last_pix { + break // The color is already there. + } else { + // Some other color sits here, so do linear conflict resolution. + key++ + key = key & ((256 * 4) - 1) // Key mask. + } + } + } + argb += 4 * (uintptr((*WebPPicture)(unsafe.Pointer(pic)).argb_stride)) + } + + if palette != (uintptr(0)) { // Fill the colors into palette. + num_colors = 0 + for i = 0; i < (256 * 4); i++ { + if *(*uint8_t)(unsafe.Pointer((bp) /* &in_use[0] */ + uintptr(i))) != 0 { + *(*uint32_t)(unsafe.Pointer(palette + uintptr(num_colors)*4)) = *(*uint32_t)(unsafe.Pointer((bp + 1024) /* &colors[0] */ + uintptr(i)*4)) + num_colors++ + } + } + } + return num_colors +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +func init() { + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&InitGammaTablesS_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&InitGammaTablesS_body_last_cpuinfo_used)) // picture_csp_enc.c:185:1: + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&InitGammaTables_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&InitGammaTables_body_last_cpuinfo_used)) // picture_csp_enc.c:93:1: + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&InitGetCoeffs_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&InitGetCoeffs_body_last_cpuinfo_used)) // vp8_dec.c:497:1: + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8DspInit_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&VP8DspInit_body_last_cpuinfo_used)) // dec.c:744:1: + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8EncDspCostInit_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&VP8EncDspCostInit_body_last_cpuinfo_used)) // cost.c:382:1: + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8EncDspInit_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&VP8EncDspInit_body_last_cpuinfo_used)) // enc.c:742:1: + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8FiltersInit_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&VP8FiltersInit_body_last_cpuinfo_used)) // filters.c:241:1: + *(*func(*libc.TLS, CPUFeature) int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8GetCPUInfo)) + 0)) = x86CPUInfo // cpu.c:176:28: + *(*func(*libc.TLS, CPUFeature) int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8GetCPUInfo)) + 0)) = x86CPUInfo // cpu.c:176:28: + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8LDspInit_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&VP8LDspInit_body_last_cpuinfo_used)) // lossless.c:616:1: + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8LEncDspInit_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&VP8LEncDspInit_body_last_cpuinfo_used)) // lossless_enc.c:801:1: + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8SSIMDspInit_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&VP8SSIMDspInit_body_last_cpuinfo_used)) // ssim.c:142:1: + *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8kabs0)) + 0)) = (uintptr(unsafe.Pointer(&abs0)) + 255) // dec_clip_tables.c:348:33: + *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8kabs0)) + 0)) = (uintptr(unsafe.Pointer(&abs0)) + 255) // dec_clip_tables.c:348:33: + *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8kclip1)) + 0)) = (uintptr(unsafe.Pointer(&clip1)) + 255) // dec_clip_tables.c:347:34: + *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8kclip1)) + 0)) = (uintptr(unsafe.Pointer(&clip1)) + 255) // dec_clip_tables.c:347:34: + *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8ksclip1)) + 0)) = (uintptr(unsafe.Pointer(&sclip1)) + 1020) // dec_clip_tables.c:345:34: + *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8ksclip1)) + 0)) = (uintptr(unsafe.Pointer(&sclip1)) + 1020) // dec_clip_tables.c:345:34: + *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8ksclip2)) + 0)) = (uintptr(unsafe.Pointer(&sclip2)) + 112) // dec_clip_tables.c:346:34: + *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&VP8ksclip2)) + 0)) = (uintptr(unsafe.Pointer(&sclip2)) + 112) // dec_clip_tables.c:346:34: + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&WebPInitAlphaProcessing_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&WebPInitAlphaProcessing_body_last_cpuinfo_used)) // alpha_processing.c:433:1: + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&WebPInitConvertARGBToYUV_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&WebPInitConvertARGBToYUV_body_last_cpuinfo_used)) // yuv.c:263:1: + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&WebPInitSamplers_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&WebPInitSamplers_body_last_cpuinfo_used)) // yuv.c:78:1: + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&WebPInitUpsamplers_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&WebPInitUpsamplers_body_last_cpuinfo_used)) // upsampling.c:263:1: + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&WebPInitYUV444Converters_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&WebPInitYUV444Converters_body_last_cpuinfo_used)) // upsampling.c:222:1: + *(*VP8CPUInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(&WebPRescalerDspInit_body_last_cpuinfo_used)) + 0)) = uintptr(unsafe.Pointer(&WebPRescalerDspInit_body_last_cpuinfo_used)) // rescaler.c:206:1: + *(*func(*libc.TLS, uintptr))(unsafe.Pointer(uintptr(unsafe.Pointer(&g_worker_interface)) + 0 /* .Init */)) = Init // thread_utils.c:351:3: + *(*func(*libc.TLS, uintptr) int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&g_worker_interface)) + 8 /* .Reset */)) = Reset // thread_utils.c:351:9: + *(*func(*libc.TLS, uintptr) int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&g_worker_interface)) + 16 /* .Sync */)) = Sync // thread_utils.c:351:16: + *(*func(*libc.TLS, uintptr))(unsafe.Pointer(uintptr(unsafe.Pointer(&g_worker_interface)) + 24 /* .Launch */)) = Launch // thread_utils.c:351:22: + *(*func(*libc.TLS, uintptr))(unsafe.Pointer(uintptr(unsafe.Pointer(&g_worker_interface)) + 32 /* .Execute */)) = Execute // thread_utils.c:351:30: + *(*func(*libc.TLS, uintptr))(unsafe.Pointer(uintptr(unsafe.Pointer(&g_worker_interface)) + 40 /* .End */)) = End // thread_utils.c:351:39: + *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&kCat3456)) + 0)) = uintptr(unsafe.Pointer(&kCat3)) // vp8_dec.c:401:44: + *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&kCat3456)) + 8)) = uintptr(unsafe.Pointer(&kCat4)) // vp8_dec.c:401:51: + *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&kCat3456)) + 16)) = uintptr(unsafe.Pointer(&kCat5)) // vp8_dec.c:401:58: + *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&kCat3456)) + 24)) = uintptr(unsafe.Pointer(&kCat6)) // vp8_dec.c:401:65: +} + +var ts1 = "Could not decode alpha data.\x00Frame setup failed\x00thread initialization failed.\x00no memory during frame initialization.\x00OK\x00no object\x00null VP8Io passed to VP8GetHeaders()\x00Truncated header.\x00Incorrect keyframe parameters.\x00Frame not displayable.\x00cannot parse picture header\x00Bad code word\x00bad partition length\x00cannot parse segment header\x00cannot parse filter header\x00cannot parse partitions\x00Not a key frame.\x00Premature end-of-partition0 encountered.\x00Premature end-of-file encountered.\x00Output aborted.\x00NULL VP8Io parameter in VP8Decode().\x00RIFF\x00WEBP\x00VP8X\x00VP8 \x00VP8L\x00ALPH\x00" +var ts = (*reflect.StringHeader)(unsafe.Pointer(&ts1)).Data diff --git a/main.go b/main.go @@ -0,0 +1,114 @@ +package main + +import ( + "encoding/binary" + "fmt" + "image" + "os" + "runtime" + "unsafe" + + _ "image/jpeg" + _ "image/png" + + "modernc.org/libc" +) + +func main() { + runtime.LockOSThread() + if err := run(os.Args[1:]); err != nil { + fmt.Printf("error: %v\n", err) + } +} + +func run(args []string) error { + if len(args) < 1 { + return fmt.Errorf("provide image to encode as webp, try megopher.png") + } + input := args[0] + srcf, err := os.Open(input) + if err != nil { + return fmt.Errorf("opening input file: %w", err) + } + defer srcf.Close() + img, _, err := image.Decode(srcf) + if err != nil { + return fmt.Errorf("decoding src image: %w", err) + } + rgbaImg, ok := img.(*image.NRGBA) + if !ok { + return fmt.Errorf("image is not NRGBA format: %T", img) + } + var ( + quality = float32(1.0) + lossless = int32(1) + // out buffer to contain webp data. + out *byte = nil + ) + size := Encode( + libc.NewTLS(), + uintptr(unsafe.Pointer(&rgbaImg.Pix[0])), + int32(img.Bounds().Dx()), + int32(img.Bounds().Dy()), + int32(rgbaImg.Stride), + // Function pointers are generated by taking a pointer to + // a struct who's first field is that function. + // That being said, this could be nil because we don't actually + // invoke it in our bsearch implementation. + *(*uintptr)(unsafe.Pointer( + &struct { + f func(tls *libc.TLS, picture uintptr, rgba uintptr, rgba_stride int32) int32 + }{ + WebPPictureImportRGBA, + }, + )), + quality, + lossless, + uintptr(unsafe.Pointer(&out)), + ) + if size == 0 { + return fmt.Errorf("encoding webp image: size %d", size) + } + if err := os.WriteFile("out.webp", libc.GoBytes(uintptr(unsafe.Pointer(out)), int(size)), 0644); err != nil { + return fmt.Errorf("writing out webp image: %w", err) + } + return nil +} + +// bsearch stub that ostensibly implements a binary search on unsafe data. +// +// NOTE(jfm): current implementation is actually just a linear search +// that ignores the predicate function for now. +// +// Input data is expected to be sorted low to high, and contain i32. +// +// key: raw pointer to object that serves as key +// base: raw pointer to first element in array +// elements: number of elements in array +// size: size of each element in bytes +// predicate: comparison function applied to each set of candidates [type predicate func(left, right uintptr) int32] +// +func bsearch(tls *libc.TLS, key, base uintptr, elements, size uint64, predicate uintptr) uintptr { + var ( + // This conversion from uintptr to unsafe.Pointer may actually be valid based + // on the codebase using uintptr exclusively, the memory is not GC'd like standard Go. + k int32 = *(*int32)(unsafe.Pointer(key)) + data = libc.GoBytes(base, int(elements*size)) + numbers []int32 = make([]int32, 0) + ) + for ii := uint64(0); ii < uint64(len(data)); ii += size { + numbers = append(numbers, int32(binary.LittleEndian.Uint32(data[ii:ii+size]))) + } + // Linear search for exact match. + for ii, n := range numbers { + ii := ii + if n == k { + // return the base pointer offset by the number of bytes + // at which the value exists. + return base + uintptr(ii*4) + } + } + // return the base memory offset if we didn't find a match. May not + // be correct semantically, but should avoid memory corruption. + return base +} diff --git a/megopher.png b/megopher.png Binary files differ. diff --git a/test.webp b/test.webp Binary files differ.