packages feed

JuicyPixels 3.2.3.2 → 3.2.4

raw patch · 5 files changed

+358/−5 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Codec.Picture: imageIPixels :: (Pixel pxa, Pixel pxb) => Traversal (Image pxa) (Image pxb) (Int, Int, pxa) pxb
+ Codec.Picture: imagePixels :: (Pixel pxa, Pixel pxb) => Traversal (Image pxa) (Image pxb) pxa pxb
+ Codec.Picture: type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s -> f t
+ Codec.Picture.Types: imageIPixels :: (Pixel pxa, Pixel pxb) => Traversal (Image pxa) (Image pxb) (Int, Int, pxa) pxb
+ Codec.Picture.Types: imagePixels :: (Pixel pxa, Pixel pxb) => Traversal (Image pxa) (Image pxb) pxa pxb
+ Codec.Picture.Types: type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s -> f t

Files

JuicyPixels.cabal view
@@ -1,5 +1,5 @@ Name:                JuicyPixels-Version:             3.2.3.2+Version:             3.2.4 Synopsis:            Picture loading/serialization (in png, jpeg, bitmap, gif, tga, tiff and radiance) Description:     <<data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMAAAADABAMAAACg8nE0AAAAElBMVEUAAABJqDSTWEL/qyb///8AAABH/1GTAAAAAXRSTlMAQObYZgAAAN5JREFUeF7s1sEJgFAQxFBbsAV72v5bEVYWPwT/XDxmCsi7zvHXavYREBDI3XP2GgICqBBYuwIC+/rVayPUAyAg0HvIXBcQoDFDGnUBgWQQ2Bx3AYFaRoBpAQHWb3bt2ARgGAiCYFFuwf3X5HA/McgGJWI2FdykCv4aBYzmKwDwvl6NVmUAAK2vlwEALK7fo88GANB6HQsAAAAAAAAA7P94AQCzswEAAAAAAAAAAAAAAAAAAICzh4UAO4zWAYBfRutHA4Bn5C69JhowAMGoBaMWDG0wCkbBKBgFo2AUAACPmegUST/IJAAAAABJRU5ErkJggg==>>@@ -18,8 +18,8 @@ -- Constraint on the version of Cabal needed to build this package. Cabal-version:       >= 1.10 -extra-source-files: changelog, docimages/*.png-extra-doc-files: docimages/*.png+extra-source-files: changelog, docimages/*.png, docimages/*.svg+extra-doc-files: docimages/*.png, docimages/*.svg  Source-Repository head     Type:      git@@ -28,7 +28,7 @@ Source-Repository this     Type:      git     Location:  git://github.com/Twinside/Juicy.Pixels.git-    Tag:       v3.2.3.2+    Tag:       v3.2.4  Flag Mmap     Description: Enable the file loading via mmap (memory map)
changelog view
@@ -1,5 +1,8 @@ -*-change-log-*- +v3.2.4 April 2015+ * Adding: Traversals compatible with the lens library.+ v3.2.3.2 April 2015  * Bumping: zlib max bound 
+ docimages/pixelgraph.svg view
@@ -0,0 +1,264 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">+<!-- Generated by graphviz version 2.22.2 (20090313.1817)+ -->+<!-- Title: pixelGraphic Pages: 1 -->+<svg width="620pt" height="464pt"+ viewBox="0.00 0.00 620.00 464.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">+<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 460)">+<title>pixelGraphic</title>+<polygon fill="white" stroke="white" points="-4,5 -4,-460 617,-460 617,5 -4,5"/>+<!-- PixelRGB8 -->+<g id="node1" class="node"><title>PixelRGB8</title>+<ellipse fill="none" stroke="black" cx="246" cy="-438" rx="31.7878" ry="18"/>+<text text-anchor="middle" x="246" y="-436.3" font-family="sans-serif" font-size="8.00">PixelRGB8</text>+</g>+<!-- PixelRGBA8 -->+<g id="node6" class="node"><title>PixelRGBA8</title>+<ellipse fill="none" stroke="black" cx="441" cy="-354" rx="34.8223" ry="18"/>+<text text-anchor="middle" x="441" y="-352.3" font-family="sans-serif" font-size="8.00">PixelRGBA8</text>+</g>+<!-- PixelRGB8&#45;&gt;PixelRGBA8 -->+<g id="edge4" class="edge"><title>PixelRGB8&#45;&gt;PixelRGBA8</title>+<path fill="none" stroke="black" d="M274.25,-429.506C295.421,-422.833 324.934,-412.874 350,-402 351.523,-401.339 381.994,-385.244 407.261,-371.871"/>+<polygon fill="black" stroke="black" points="409.071,-374.874 416.272,-367.102 405.796,-368.687 409.071,-374.874"/>+<text text-anchor="middle" x="393" y="-394.3" font-family="sans-serif" font-size="8.00">promotePixel</text>+</g>+<!-- PixelRGBF -->+<g id="node8" class="node"><title>PixelRGBF</title>+<ellipse fill="none" stroke="black" cx="33" cy="-102" rx="31.7878" ry="18"/>+<text text-anchor="middle" x="33" y="-100.3" font-family="sans-serif" font-size="8.00">PixelRGBF</text>+</g>+<!-- PixelRGB8&#45;&gt;PixelRGBF -->+<g id="edge6" class="edge"><title>PixelRGB8&#45;&gt;PixelRGBF</title>+<path fill="none" stroke="black" d="M214.594,-434.005C148.276,-424.689 0,-398.847 0,-354 0,-354 0,-354 0,-186 0,-165.437 8.67323,-143.88 17.1268,-127.753"/>+<polygon fill="black" stroke="black" points="20.228,-129.378 22.0115,-118.934 14.1045,-125.986 20.228,-129.378"/>+<text text-anchor="middle" x="23" y="-268.3" font-family="sans-serif" font-size="8.00">promotePixel</text>+</g>+<!-- Pixel8 -->+<g id="node20" class="node"><title>Pixel8</title>+<ellipse fill="none" stroke="black" cx="308" cy="-270" rx="27" ry="18"/>+<text text-anchor="middle" x="308" y="-268.3" font-family="sans-serif" font-size="8.00">Pixel8</text>+</g>+<!-- PixelRGB8&#45;&gt;Pixel8 -->+<g id="edge60" class="edge"><title>PixelRGB8&#45;&gt;Pixel8</title>+<path fill="none" stroke="black" d="M214.516,-433.811C149.341,-423.852 9.37863,-395.049 55,-336 81.2893,-301.973 207.23,-282.163 270.929,-274.163"/>+<polygon fill="black" stroke="black" points="271.46,-277.624 280.961,-272.936 270.61,-270.676 271.46,-277.624"/>+<text text-anchor="middle" x="80" y="-352.3" font-family="sans-serif" font-size="8.00">computeLuma</text>+</g>+<!-- PixelCMYK8 -->+<g id="node28" class="node"><title>PixelCMYK8</title>+<ellipse fill="none" stroke="black" cx="253" cy="-354" rx="34.8223" ry="18"/>+<text text-anchor="middle" x="253" y="-352.3" font-family="sans-serif" font-size="8.00">PixelCMYK8</text>+</g>+<!-- PixelRGB8&#45;&gt;PixelCMYK8 -->+<g id="edge40" class="edge"><title>PixelRGB8&#45;&gt;PixelCMYK8</title>+<path fill="none" stroke="black" d="M224.748,-423.894C213.935,-414.831 204.182,-402.459 210,-390 212.758,-384.095 217.013,-378.817 221.794,-374.241"/>+<polygon fill="black" stroke="black" points="224.225,-376.77 229.601,-367.64 219.705,-371.424 224.225,-376.77"/>+<text text-anchor="middle" x="232" y="-394.3" font-family="sans-serif" font-size="8.00">convertPixel</text>+</g>+<!-- PixelYCbCr8 -->+<g id="node30" class="node"><title>PixelYCbCr8</title>+<ellipse fill="none" stroke="black" cx="150" cy="-354" rx="35.9084" ry="18"/>+<text text-anchor="middle" x="150" y="-352.3" font-family="sans-serif" font-size="8.00">PixelYCbCr8</text>+</g>+<!-- PixelRGB8&#45;&gt;PixelYCbCr8 -->+<g id="edge42" class="edge"><title>PixelRGB8&#45;&gt;PixelYCbCr8</title>+<path fill="none" stroke="black" d="M214.399,-434.415C177.053,-429.451 118.29,-419.109 105,-402 97.106,-391.837 104.874,-381.324 116.049,-372.736"/>+<polygon fill="black" stroke="black" points="118.35,-375.401 124.612,-366.856 114.387,-369.631 118.35,-375.401"/>+<text text-anchor="middle" x="127" y="-394.3" font-family="sans-serif" font-size="8.00">convertPixel</text>+</g>+<!-- PixelRGB16 -->+<g id="node2" class="node"><title>PixelRGB16</title>+<ellipse fill="none" stroke="black" cx="429" cy="-102" rx="34.1425" ry="18"/>+<text text-anchor="middle" x="429" y="-100.3" font-family="sans-serif" font-size="8.00">PixelRGB16</text>+</g>+<!-- PixelRGBA16 -->+<g id="node4" class="node"><title>PixelRGBA16</title>+<ellipse fill="none" stroke="black" cx="343" cy="-18" rx="37.1721" ry="18"/>+<text text-anchor="middle" x="343" y="-16.3" font-family="sans-serif" font-size="8.00">PixelRGBA16</text>+</g>+<!-- PixelRGB16&#45;&gt;PixelRGBA16 -->+<g id="edge2" class="edge"><title>PixelRGB16&#45;&gt;PixelRGBA16</title>+<path fill="none" stroke="black" d="M400.098,-92.2134C386.67,-86.4097 371.409,-77.8363 361,-66 355.909,-60.2106 352.202,-52.8433 349.526,-45.6287"/>+<polygon fill="black" stroke="black" points="352.846,-44.5187 346.482,-36.0479 346.174,-46.6383 352.846,-44.5187"/>+<text text-anchor="middle" x="384" y="-58.3" font-family="sans-serif" font-size="8.00">promotePixel</text>+</g>+<!-- Pixel16 -->+<g id="node16" class="node"><title>Pixel16</title>+<ellipse fill="none" stroke="black" cx="296" cy="-186" rx="27" ry="18"/>+<text text-anchor="middle" x="296" y="-184.3" font-family="sans-serif" font-size="8.00">Pixel16</text>+</g>+<!-- PixelRGB16&#45;&gt;Pixel16 -->+<g id="edge58" class="edge"><title>PixelRGB16&#45;&gt;Pixel16</title>+<path fill="none" stroke="black" d="M424.573,-120.149C421.265,-130.199 415.765,-142.199 407,-150 386.436,-168.304 356.427,-177.32 332.795,-181.75"/>+<polygon fill="black" stroke="black" points="332.056,-178.325 322.773,-183.431 333.214,-185.228 332.056,-178.325"/>+<text text-anchor="middle" x="441" y="-142.3" font-family="sans-serif" font-size="8.00">computeLuma</text>+</g>+<!-- PixelCMYK16 -->+<g id="node26" class="node"><title>PixelCMYK16</title>+<ellipse fill="none" stroke="black" cx="553" cy="-18" rx="37.1721" ry="18"/>+<text text-anchor="middle" x="553" y="-16.3" font-family="sans-serif" font-size="8.00">PixelCMYK16</text>+</g>+<!-- PixelRGB16&#45;&gt;PixelCMYK16 -->+<g id="edge38" class="edge"><title>PixelRGB16&#45;&gt;PixelCMYK16</title>+<path fill="none" stroke="black" d="M451.832,-88.3606C462.615,-81.7841 475.593,-73.6731 487,-66 499.46,-57.6189 512.915,-47.9503 524.406,-39.4968"/>+<polygon fill="black" stroke="black" points="526.807,-42.074 532.761,-33.3106 522.641,-36.4482 526.807,-42.074"/>+<text text-anchor="middle" x="525" y="-58.3" font-family="sans-serif" font-size="8.00">convertPixel</text>+</g>+<!-- PixelRGBA16&#45;&gt;PixelRGB16 -->+<g id="edge44" class="edge"><title>PixelRGBA16&#45;&gt;PixelRGB16</title>+<path fill="none" stroke="black" d="M371.789,-29.3863C383.871,-35.2918 397.329,-43.4955 407,-54 412.378,-59.8422 416.636,-67.2266 419.915,-74.4406"/>+<polygon fill="black" stroke="black" points="416.794,-76.0584 423.794,-84.0115 423.282,-73.4291 416.794,-76.0584"/>+<text text-anchor="middle" x="449" y="-58.3" font-family="sans-serif" font-size="8.00">dropTransparency</text>+</g>+<!-- PixelRGBA8&#45;&gt;PixelRGB8 -->+<g id="edge46" class="edge"><title>PixelRGBA8&#45;&gt;PixelRGB8</title>+<path fill="none" stroke="black" d="M437.029,-372.038C433.845,-382.309 428.318,-394.571 419,-402 399.083,-417.88 332.208,-428.306 287.678,-433.672"/>+<polygon fill="black" stroke="black" points="287.239,-430.2 277.712,-434.834 288.05,-437.153 287.239,-430.2"/>+<text text-anchor="middle" x="463" y="-394.3" font-family="sans-serif" font-size="8.00">dropTransparency</text>+</g>+<!-- PixelRGBA8&#45;&gt;Pixel8 -->+<g id="edge52" class="edge"><title>PixelRGBA8&#45;&gt;Pixel8</title>+<path fill="none" stroke="black" d="M413.829,-342.599C399.476,-336.131 381.815,-327.451 367,-318 354.878,-310.267 342.394,-300.428 332.048,-291.673"/>+<polygon fill="black" stroke="black" points="334.114,-288.833 324.258,-284.946 329.539,-294.131 334.114,-288.833"/>+<text text-anchor="middle" x="392" y="-310.3" font-family="sans-serif" font-size="8.00">computeLuma</text>+</g>+<!-- PixelF -->+<g id="node14" class="node"><title>PixelF</title>+<ellipse fill="none" stroke="black" cx="106" cy="-186" rx="27" ry="18"/>+<text text-anchor="middle" x="106" y="-184.3" font-family="sans-serif" font-size="8.00">PixelF</text>+</g>+<!-- PixelRGBF&#45;&gt;PixelF -->+<g id="edge56" class="edge"><title>PixelRGBF&#45;&gt;PixelF</title>+<path fill="none" stroke="black" d="M27.0137,-120.147C24.9943,-129.716 24.4635,-141.251 30,-150 38.9021,-164.067 54.9514,-172.745 70.015,-178.044"/>+<polygon fill="black" stroke="black" points="69.0981,-181.424 79.6867,-181.06 71.1825,-174.741 69.0981,-181.424"/>+<text text-anchor="middle" x="55" y="-142.3" font-family="sans-serif" font-size="8.00">computeLuma</text>+</g>+<!-- PixelYA16 -->+<g id="node9" class="node"><title>PixelYA16</title>+<ellipse fill="none" stroke="black" cx="259" cy="-102" rx="31.7878" ry="18"/>+<text text-anchor="middle" x="259" y="-100.3" font-family="sans-serif" font-size="8.00">PixelYA16</text>+</g>+<!-- PixelYA16&#45;&gt;PixelRGBA16 -->+<g id="edge8" class="edge"><title>PixelYA16&#45;&gt;PixelRGBA16</title>+<path fill="none" stroke="black" d="M258.152,-83.5434C258.613,-73.883 260.687,-62.36 267,-54 275.273,-43.0444 287.722,-35.28 300.163,-29.8405"/>+<polygon fill="black" stroke="black" points="301.586,-33.0421 309.607,-26.1198 299.02,-26.5294 301.586,-33.0421"/>+<text text-anchor="middle" x="290" y="-58.3" font-family="sans-serif" font-size="8.00">promotePixel</text>+</g>+<!-- PixelYA16&#45;&gt;Pixel16 -->+<g id="edge48" class="edge"><title>PixelYA16&#45;&gt;Pixel16</title>+<path fill="none" stroke="black" d="M229.98,-109.854C206.015,-117.845 177.897,-131.656 191,-150 199.293,-161.611 233.125,-171.835 260.175,-178.391"/>+<polygon fill="black" stroke="black" points="259.609,-181.853 270.143,-180.72 261.201,-175.037 259.609,-181.853"/>+<text text-anchor="middle" x="225" y="-142.3" font-family="sans-serif" font-size="8.00">dropTransparency</text>+</g>+<!-- PixelYA8 -->+<g id="node11" class="node"><title>PixelYA8</title>+<ellipse fill="none" stroke="black" cx="439" cy="-186" rx="28.8445" ry="18"/>+<text text-anchor="middle" x="439" y="-184.3" font-family="sans-serif" font-size="8.00">PixelYA8</text>+</g>+<!-- PixelYA8&#45;&gt;PixelRGB8 -->+<g id="edge12" class="edge"><title>PixelYA8&#45;&gt;PixelRGB8</title>+<path fill="none" stroke="black" d="M464.762,-194.278C489.627,-203.81 525.815,-222.121 542,-252 574.918,-312.769 554.613,-358.387 501,-402 484.752,-415.217 355.671,-428.373 287.639,-434.476"/>+<polygon fill="black" stroke="black" points="287.321,-430.99 277.669,-435.359 287.938,-437.963 287.321,-430.99"/>+<text text-anchor="middle" x="580" y="-310.3" font-family="sans-serif" font-size="8.00">promotePixel</text>+</g>+<!-- PixelYA8&#45;&gt;PixelRGBA8 -->+<g id="edge10" class="edge"><title>PixelYA8&#45;&gt;PixelRGBA8</title>+<path fill="none" stroke="black" d="M460.035,-198.84C467.824,-204.817 475.781,-212.68 480,-222 497.598,-260.871 496.093,-278.904 479,-318 476.725,-323.204 473.295,-328.013 469.411,-332.309"/>+<polygon fill="black" stroke="black" points="466.792,-329.975 462.079,-339.464 471.681,-334.985 466.792,-329.975"/>+<text text-anchor="middle" x="515" y="-268.3" font-family="sans-serif" font-size="8.00">promotePixel</text>+</g>+<!-- PixelYA8&#45;&gt;Pixel8 -->+<g id="edge50" class="edge"><title>PixelYA8&#45;&gt;Pixel8</title>+<path fill="none" stroke="black" d="M412.102,-193.018C393.267,-198.789 368.145,-208.269 349,-222 340.05,-228.419 331.808,-237.196 325.098,-245.49"/>+<polygon fill="black" stroke="black" points="322.247,-243.456 318.929,-253.518 327.797,-247.721 322.247,-243.456"/>+<text text-anchor="middle" x="383" y="-226.3" font-family="sans-serif" font-size="8.00">dropTransparency</text>+</g>+<!-- PixelYA8&#45;&gt;Pixel8 -->+<g id="edge62" class="edge"><title>PixelYA8&#45;&gt;Pixel8</title>+<path fill="none" stroke="black" d="M434.558,-204.131C431.244,-214.175 425.744,-226.175 417,-234 397.039,-251.864 367.99,-260.893 344.899,-265.441"/>+<polygon fill="black" stroke="black" points="344.002,-262.045 334.763,-267.23 345.219,-268.938 344.002,-262.045"/>+<text text-anchor="middle" x="451" y="-226.3" font-family="sans-serif" font-size="8.00">computeLuma</text>+</g>+<!-- PixelF&#45;&gt;PixelRGBF -->+<g id="edge14" class="edge"><title>PixelF&#45;&gt;PixelRGBF</title>+<path fill="none" stroke="black" d="M100.45,-168.312C96.8232,-158.653 91.3784,-146.886 84,-138 78.5966,-131.492 71.7476,-125.606 64.8367,-120.568"/>+<polygon fill="black" stroke="black" points="66.3898,-117.392 56.1539,-114.657 62.4504,-123.178 66.3898,-117.392"/>+<text text-anchor="middle" x="115" y="-142.3" font-family="sans-serif" font-size="8.00">promotePixel</text>+</g>+<!-- Pixel16&#45;&gt;PixelRGB16 -->+<g id="edge18" class="edge"><title>Pixel16&#45;&gt;PixelRGB16</title>+<path fill="none" stroke="black" d="M313.43,-172.019C326.239,-162.023 344.257,-148.532 361,-138 371.689,-131.277 383.756,-124.61 394.725,-118.875"/>+<polygon fill="black" stroke="black" points="396.336,-121.982 403.628,-114.295 393.134,-115.757 396.336,-121.982"/>+<text text-anchor="middle" x="384" y="-142.3" font-family="sans-serif" font-size="8.00">promotePixel</text>+</g>+<!-- Pixel16&#45;&gt;PixelRGBA16 -->+<g id="edge16" class="edge"><title>Pixel16&#45;&gt;PixelRGBA16</title>+<path fill="none" stroke="black" d="M305.084,-168.741C307.903,-162.903 310.835,-156.272 313,-150 325.048,-115.091 333.609,-73.3023 338.424,-46.2333"/>+<polygon fill="black" stroke="black" points="341.89,-46.732 340.143,-36.2822 334.992,-45.5405 341.89,-46.732"/>+<text text-anchor="middle" x="353" y="-100.3" font-family="sans-serif" font-size="8.00">promotePixel</text>+</g>+<!-- Pixel16&#45;&gt;PixelYA16 -->+<g id="edge20" class="edge"><title>Pixel16&#45;&gt;PixelYA16</title>+<path fill="none" stroke="black" d="M280.78,-170.7C275.635,-164.701 270.35,-157.469 267,-150 264.277,-143.93 262.473,-137.052 261.279,-130.438"/>+<polygon fill="black" stroke="black" points="264.727,-129.827 259.862,-120.415 257.796,-130.807 264.727,-129.827"/>+<text text-anchor="middle" x="290" y="-142.3" font-family="sans-serif" font-size="8.00">promotePixel</text>+</g>+<!-- Pixel8&#45;&gt;PixelRGB8 -->+<g id="edge24" class="edge"><title>Pixel8&#45;&gt;PixelRGB8</title>+<path fill="none" stroke="black" d="M312.919,-288.095C319.136,-314.953 326.712,-366.057 306,-402 300.622,-411.332 291.773,-418.518 282.501,-423.926"/>+<polygon fill="black" stroke="black" points="280.83,-420.85 273.581,-428.577 284.067,-427.057 280.83,-420.85"/>+<text text-anchor="middle" x="342" y="-352.3" font-family="sans-serif" font-size="8.00">promotePixel</text>+</g>+<!-- Pixel8&#45;&gt;PixelRGBA8 -->+<g id="edge22" class="edge"><title>Pixel8&#45;&gt;PixelRGBA8</title>+<path fill="none" stroke="black" d="M334.939,-272.185C360.073,-275.561 397.177,-284.15 421,-306 426.855,-311.37 431.048,-318.72 434.03,-326.054"/>+<polygon fill="black" stroke="black" points="430.836,-327.531 437.387,-335.858 437.458,-325.263 430.836,-327.531"/>+<text text-anchor="middle" x="452" y="-310.3" font-family="sans-serif" font-size="8.00">promotePixel</text>+</g>+<!-- Pixel8&#45;&gt;PixelYA8 -->+<g id="edge26" class="edge"><title>Pixel8&#45;&gt;PixelYA8</title>+<path fill="none" stroke="black" d="M290.77,-255.865C280.734,-245.919 271.57,-232.553 280,-222 287.559,-212.538 356.092,-199.635 400.682,-192.122"/>+<polygon fill="black" stroke="black" points="401.335,-195.562 410.626,-190.469 400.187,-188.657 401.335,-195.562"/>+<text text-anchor="middle" x="303" y="-226.3" font-family="sans-serif" font-size="8.00">promotePixel</text>+</g>+<!-- Pixel8&#45;&gt;PixelF -->+<g id="edge28" class="edge"><title>Pixel8&#45;&gt;PixelF</title>+<path fill="none" stroke="black" d="M281.145,-267.812C249.741,-264.331 196.969,-255.554 157,-234 145.577,-227.84 134.814,-218.473 126.146,-209.643"/>+<polygon fill="black" stroke="black" points="128.492,-207.028 119.104,-202.117 123.381,-211.81 128.492,-207.028"/>+<text text-anchor="middle" x="180" y="-226.3" font-family="sans-serif" font-size="8.00">promotePixel</text>+</g>+<!-- Pixel8&#45;&gt;Pixel16 -->+<g id="edge30" class="edge"><title>Pixel8&#45;&gt;Pixel16</title>+<path fill="none" stroke="black" d="M282.206,-263.957C256.398,-257.327 219.359,-246.018 211,-234 196.025,-212.469 230.216,-199.429 259.604,-192.482"/>+<polygon fill="black" stroke="black" points="260.687,-195.828 269.71,-190.275 259.193,-188.989 260.687,-195.828"/>+<text text-anchor="middle" x="234" y="-226.3" font-family="sans-serif" font-size="8.00">promotePixel</text>+</g>+<!-- PixelCMYK16&#45;&gt;PixelRGB16 -->+<g id="edge32" class="edge"><title>PixelCMYK16&#45;&gt;PixelRGB16</title>+<path fill="none" stroke="black" d="M564.03,-35.4654C568.707,-45.2873 571.707,-57.2873 565,-66 553.678,-80.7091 507.858,-90.6423 472.496,-96.2857"/>+<polygon fill="black" stroke="black" points="471.73,-92.862 462.373,-97.8319 472.787,-99.7817 471.73,-92.862"/>+<text text-anchor="middle" x="590" y="-58.3" font-family="sans-serif" font-size="8.00">convertPixel</text>+</g>+<!-- PixelCMYK8&#45;&gt;PixelRGB8 -->+<g id="edge34" class="edge"><title>PixelCMYK8&#45;&gt;PixelRGB8</title>+<path fill="none" stroke="black" d="M257.173,-372.299C258.645,-381.28 259.584,-392.241 258,-402 257.535,-404.865 256.875,-407.811 256.1,-410.724"/>+<polygon fill="black" stroke="black" points="252.737,-409.753 253.143,-420.34 259.427,-411.811 252.737,-409.753"/>+<text text-anchor="middle" x="280" y="-394.3" font-family="sans-serif" font-size="8.00">convertPixel</text>+</g>+<!-- PixelYCbCr8&#45;&gt;PixelRGB8 -->+<g id="edge36" class="edge"><title>PixelYCbCr8&#45;&gt;PixelRGB8</title>+<path fill="none" stroke="black" d="M149.836,-372.162C150.645,-381.97 153.174,-393.727 160,-402 171.431,-415.854 189.112,-424.462 205.475,-429.768"/>+<polygon fill="black" stroke="black" points="204.847,-433.23 215.426,-432.663 206.802,-426.509 204.847,-433.23"/>+<text text-anchor="middle" x="182" y="-394.3" font-family="sans-serif" font-size="8.00">convertPixel</text>+</g>+<!-- PixelYCbCr8&#45;&gt;Pixel8 -->+<g id="edge54" class="edge"><title>PixelYCbCr8&#45;&gt;Pixel8</title>+<path fill="none" stroke="black" d="M174.688,-340.875C202.411,-326.136 247.432,-302.201 277.376,-286.281"/>+<polygon fill="black" stroke="black" points="279.34,-289.201 286.527,-281.416 276.054,-283.02 279.34,-289.201"/>+<text text-anchor="middle" x="263" y="-310.3" font-family="sans-serif" font-size="8.00">computeLuma</text>+</g>+</g>+</svg>
src/Codec/Picture.hs view
@@ -20,6 +20,11 @@                      , generateFoldImage
                      , withImage
 
+                     -- * Lens compatibility
+                     , Traversal
+                     , imagePixels
+                     , imageIPixels
+
                      -- * Generic image writing
                      , saveBmpImage
                      , saveJpgImage
src/Codec/Picture/Types.hs view
@@ -25,6 +25,11 @@                           , thawImage
                           , unsafeThawImage
 
+                            -- ** Image Lenses
+                          , Traversal
+                          , imagePixels
+                          , imageIPixels
+
                             -- ** Pixel types
                           , Pixel8
                           , Pixel16
@@ -95,12 +100,13 @@ 
 #if !MIN_VERSION_base(4,8,0)
 import Data.Monoid( Monoid, mempty )
+import Control.Applicative( Applicative, pure, (<*>), (<$>) )
 #endif
 
 import Data.Monoid( (<>) )
 import Control.Monad( foldM, liftM, ap )
 import Control.DeepSeq( NFData( .. ) )
-import Control.Monad.ST( runST )
+import Control.Monad.ST( ST, runST )
 import Control.Monad.Primitive ( PrimMonad, PrimState )
 import Foreign.ForeignPtr( castForeignPtr )
 import Foreign.Storable ( Storable )
@@ -912,6 +918,81 @@             -- safe because newArray can't be referenced as a mutable array
             -- outside of this where block
             V.unsafeFreeze newArr
+
+
+-- | Helpers to embed a rankNTypes inside an Applicative
+newtype GenST a = GenST { genAction :: forall s. ST s (M.STVector s a) }
+
+-- | Traversal type matching the definition in the Lens package.
+type Traversal s t a b =
+    forall f. Applicative f => (a -> f b) -> s -> f t 
+
+writePx :: Pixel px
+        => Int -> GenST (PixelBaseComponent px) -> px -> GenST (PixelBaseComponent px)
+{-# INLINE writePx #-}
+writePx idx act px = GenST $ do
+   vec <- genAction act
+   unsafeWritePixel vec idx px
+   return vec
+
+freezeGenST :: Pixel px
+            => Int -> Int -> GenST (PixelBaseComponent px) -> Image px
+freezeGenST w h act =
+  Image w h (runST (genAction act >>= V.unsafeFreeze))
+
+-- | Traversal in "raster" order, from left to right the top to bottom.
+-- This traversal is matching pixelMap in spirit.
+--
+-- Since 3.2.4
+imagePixels :: forall pxa pxb. (Pixel pxa, Pixel pxb)
+            => Traversal (Image pxa) (Image pxb) pxa pxb
+{-# INLINE imagePixels #-}
+imagePixels f Image { imageWidth = w, imageHeight = h, imageData = vec } =
+  freezeGenST w h <$> pixels
+  where
+    sourceComponentCount = componentCount (undefined :: pxa)
+    destComponentCount = componentCount (undefined :: pxb)
+
+    maxi = w * h * sourceComponentCount
+    pixels =
+      go (pure $ GenST $ M.new (w * h * destComponentCount)) 0 0
+
+    go act readIdx _ | readIdx >= maxi = act
+    go act readIdx writeIdx =
+      go newAct (readIdx + sourceComponentCount) (writeIdx + destComponentCount)
+      where
+        px = f (unsafePixelAt vec readIdx)
+        newAct = writePx writeIdx <$> act <*> px
+
+-- | Traversal providing the pixel position with it's value.
+-- The traversal in raster order, from lef to right, then top
+-- to bottom. The traversal match pixelMapXY in spirit.
+--
+-- Since 3.2.4
+imageIPixels :: forall pxa pxb. (Pixel pxa, Pixel pxb)
+             => Traversal (Image pxa) (Image pxb) (Int, Int, pxa) pxb
+{-# INLINE imageIPixels #-}
+imageIPixels f Image { imageWidth = w, imageHeight = h, imageData = vec } =
+  freezeGenST w h <$> pixels
+  where
+    sourceComponentCount = componentCount (undefined :: pxa)
+    destComponentCount = componentCount (undefined :: pxb)
+
+    pixels =
+      lineMapper (pure $ GenST $ M.new (w * h * destComponentCount)) 0 0 0
+
+    lineMapper act _ _ y | y >= h = act
+    lineMapper act readIdxLine writeIdxLine y =
+        go act readIdxLine writeIdxLine 0
+      where
+        go cact readIdx writeIdx x
+          | x >= w = lineMapper cact readIdx writeIdx $ y + 1
+          | otherwise = do
+             let px = f (x, y, unsafePixelAt vec readIdx)
+             go (writePx writeIdx <$> cact <*> px)
+                (readIdx + sourceComponentCount)
+                (writeIdx + destComponentCount)
+                (x + 1)
 
 -- | Just like `pixelMap` only the function takes the pixel coordinates as
 --   additional parameters.