{"id":6,"date":"2008-04-04T09:44:00","date_gmt":"2008-04-04T14:44:00","guid":{"rendered":"http:\/\/coherentpdf.com\/blog\/?p=6"},"modified":"2008-06-30T04:34:30","modified_gmt":"2008-06-30T09:34:30","slug":"storing-colours-in-31-bits-part-one","status":"publish","type":"post","link":"https:\/\/coherentpdf.com\/blog\/?p=6","title":{"rendered":"Storing Colours in 31 bits (Part One)"},"content":{"rendered":"<p>For rendering vector graphics scenes, colours are usually stored with what we call &#8220;premultiplied&#8221; or &#8220;associated&#8221; alpha. For instance, opaque dark red is stored as:<\/p>\n<div><\/div>\n<div>0.5, 0, 0, 0.5 (R * A, G * A, B * A, A)<\/div>\n<div><\/div>\n<div>instead of<\/div>\n<div><\/div>\n<div>0.5, 0, 0, 1 (R, G, B, A).<\/div>\n<div><\/div>\n<div>This originally had to do with making compositing algorithms fast (fewer multiplications), but it has other advantages &#8211; for instance there is only a single value for the clear colour (0, 0, 0, 0) instead of many (x, y, z, 0).<\/div>\n<div><\/div>\n<div>We usually use 8 bits for each component, packing them into a 32 bit word.<\/div>\n<div><\/div>\n<div>Now, 32 bits can store 2^32 colours. In fact, in the premultiplied scheme, many bit patterns are unused (when R, G or B is > A). It turns out there are only slightly more than 2^30 unique premultiplied colours. In other words, with a suitable mapping, we should be able to store them in OCaml&#8217;s 31 bit integers. This is important so we can store them in native arrays unboxed, for example.<\/div>\n<div><\/div>\n<div>Such a mapping (togther with a discussion of all this) is in Jim Blinn&#8217;s book &#8220;Dirty Pixels&#8221;, Chapter 20. Unfortunately, it&#8217;s too slow for practical use. Can you think of a fast one?<\/div>\n<div><\/div>\n<div>Meanwhile, here&#8217;s some code from our <a href=\"http:\/\/www.coherentgraphics.co.uk\/\">renderer<\/a> which uses a lossy approach: throwing away the least significant red bit (The question of which colour to lose the bit is not clear: theoretically the eyes are less sensitive to changes in blue, but my tests didn&#8217;t seem to bear that out).<\/div>\n<div><\/div>\n<div>To build one of these colours (assertions left out for this post)<\/div>\n<div><\/div>\n<div>\n<div><span class=\"Apple-style-span\"  style=\"font-family:'courier new';\"><span class=\"Apple-style-span\"  style=\"font-size:small;\">let colour_of_rgba r g b a =<\/span><\/span><\/div>\n<div><span class=\"Apple-style-span\"  style=\"font-family:'courier new';\"><span class=\"Apple-style-span\"  style=\"font-size:small;\">\u00a0\u00a0(a lsl 23) lor (b lsl 15) lor (g lsl 7) lor (r lsr 1)<\/span><\/span><\/div>\n<div><\/div>\n<div>Extraction of blue, green and alpha components is easy, but where we&#8217;ve dropped the LSB, we need to reconstruct carefully, at least making sure 254 reconstructs to 255 &#8211; otherwise we couldn&#8217;t represent full red. We must also make sure the invariant that a component can never be more than the alpha is obeyed.<\/div>\n<div><\/div>\n<\/div>\n<div>\n<div><span class=\"Apple-style-span\"  style=\"font-family:'courier new';\"><span class=\"Apple-style-span\"  style=\"font-size:small;\">let rec red_of_colour c =<\/span><\/span><\/div>\n<div><span class=\"Apple-style-span\"  style=\"font-family:'courier new';\"><span class=\"Apple-style-span\"  style=\"font-size:small;\">\u00a0\u00a0let red =<\/span><\/span><\/div>\n<div><span class=\"Apple-style-span\"  style=\"font-family:'courier new';\"><span class=\"Apple-style-span\"  style=\"font-size:small;\">\u00a0\u00a0 \u00a0match (c land 127) lsl 1 with<\/span><\/span><\/div>\n<div><span class=\"Apple-style-span\"  style=\"font-family:'courier new';\"><span class=\"Apple-style-span\"  style=\"font-size:small;\">\u00a0\u00a0 \u00a0| 254 -> 255<\/span><\/span><\/div>\n<div><span class=\"Apple-style-span\"  style=\"font-family:'courier new';\"><span class=\"Apple-style-span\"  style=\"font-size:small;\">\u00a0\u00a0 \u00a0| r -> r<\/span><\/span><\/div>\n<div><span class=\"Apple-style-span\"  style=\"font-family:'courier new';\"><span class=\"Apple-style-span\"  style=\"font-size:small;\">\u00a0\u00a0and alpha = c lsr 23 in<\/span><\/span><\/div>\n<div><span class=\"Apple-style-span\"  style=\"font-family:'courier new';\"><span class=\"Apple-style-span\"  style=\"font-size:small;\">\u00a0\u00a0 \u00a0if red > alpha then alpha else red<\/span><\/span><\/div>\n<div><\/div>\n<div>In Part Two, I&#8217;ll release the Colour module, which provides for all this, and implements the standard Porter\/Duff compositing arithmetic efficiently.<\/div>\n<div><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>For rendering vector graphics scenes, colours are usually stored with what we call &#8220;premultiplied&#8221; or &#8220;associated&#8221; alpha. For instance, opaque dark red is stored as: 0.5, 0, 0, 0.5 (R * A, G * A, B * A, A) instead &hellip; <a href=\"https:\/\/coherentpdf.com\/blog\/?p=6\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[10,5],"class_list":["post-6","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-graphics","tag-ocaml"],"_links":{"self":[{"href":"https:\/\/coherentpdf.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/coherentpdf.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/coherentpdf.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/coherentpdf.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/coherentpdf.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6"}],"version-history":[{"count":0,"href":"https:\/\/coherentpdf.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6\/revisions"}],"wp:attachment":[{"href":"https:\/\/coherentpdf.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/coherentpdf.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/coherentpdf.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}