From mboxrd@z Thu Jan 1 00:00:00 1970 MIME-Version: 1.0 In-Reply-To: <14ec7b180903051921u10524f16naad654b297a67de3@mail.gmail.com> References: <14ec7b180903041807q58ae6a8fh31350709edd0c0c@mail.gmail.com> <14ec7b180903051921u10524f16naad654b297a67de3@mail.gmail.com> Date: Fri, 6 Mar 2009 12:48:31 -0800 Message-ID: Subject: Re: [9fans] Porter-Duff alpha blending From: Russ Cox To: Fans of the OS Plan 9 from Bell Labs <9fans@9fans.net> Content-Type: multipart/mixed; boundary=000e0cd146be5a2c980464796839 Topicbox-Message-UUID: b5059d34-ead4-11e9-9d60-3106f5b1d025 --000e0cd146be5a2c980464796839 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Thanks for tracking this down and pointing out where the error is. There are actually a handful of errors in that code. Assume a source value sv, source alpha sa, mask alpha ma, destination value dv, and destination alpha da. The values sv and dv are stored premultiplied by their corresponding alphas (the one true way). Given those values, the correct new values for the destination pixel in an S over D op are: dv =3D (sv*ma + dv*(255-sa*ma)) / 255 da =3D (sa*ma + da*(255-sa*ma)) / 255 Bug #1: The current draw.c does the division separately on the two halves: dv =3D (sv*ma)/255 + (dv*(255-sa*ma))/255 This can be off by one if the remainders from the two divisions sum to >=3D 255. Bug #2: The MUL0123 macro assumes four values are packed into a 32-bit int and runs them in simultaneous pairs as 32-bit operations (MUL02 and MUL13) operating on 16-bit halves of the word. Those two don't use the right rounding for the bitwise op implementation of /255. On a single value, the implementation is x / 255 =3D=3D (t =3D x+1, (t+(t>>8))>>8) (x+127) / 255 =3D=3D (t =3D x+128, (t+(t>>8))>>8) These calculations only need 16 bits so you can run two of them in the two halves of a 32-bit word. The second implements round-to-nearest and is what the draw code tries to do in this case. But it only adds 128 (0x80), so it only rounds the bottom half correctly. It needs to add 0x00800080, which would round both of them. This explains: src rFF gFF bFF =CE=B1FF mask kFF =CE=B1FF dst r00 g00 b00 =CE=B1FF dst after calc rFE gFE bFF =CE=B1FF Bug #3: MUL0123 is enabled whenever the src and dst both have 32-bit pixel width, but there is no check that the sub-channels are in the same order. You don't say what the image chans were in your test, but this: src rFF g00 b00 =CE=B1FF mask kFF =CE=B1FF dst r00 g00 b00 =CE=B1FF dst after calc rFE gFE b00 =CE=B100 would be explained by, say, src=3D=3DARGB and dst=3D=3DRGBA. The A and R values in src became the R and G chans in dst. (In fact, since the dst R and G are FE not FF, that's almost certainly the scenario, modulo the little-endian draw names.) This one is similarly explained: src rCC g00 b00 =CE=B1CC mask kFF =CE=B1FF dst r00 g00 b00 =CE=B1FF dst after calc rCB gCB b00 =CE=B133 The destination got scaled by 0x33/0xFF, leaving 00 00 00 33, and then the source, cc 00 00 cc, was added in the wrong place, using the incorrect rounding, to produce cb cb 00 33. I have corrected these bugs in the plan9port copy of src/libmemdraw/draw.c and finally get the right answer for Andrey's test (attached). I leave it as an exercise to the interested reader to port the changes to the other dozen copies of libmemdraw that are floating around, or to unify them all. Russ --000e0cd146be5a2c980464796839 Content-Type: image/png; name="andrey.png" Content-Disposition: attachment; filename="andrey.png" Content-Transfer-Encoding: base64 X-Attachment-Id: f_frzc8vrx0 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 --000e0cd146be5a2c980464796839--