{"id":287,"date":"2017-03-28T13:32:33","date_gmt":"2017-03-28T13:32:33","guid":{"rendered":"http:\/\/ifdesignelseart.com\/?p=287"},"modified":"2017-03-28T15:42:47","modified_gmt":"2017-03-28T15:42:47","slug":"implementation-de-lalgorithme-de-diffusion-floyd-steinberg","status":"publish","type":"post","link":"https:\/\/ifdesignelseart.com\/?p=287","title":{"rendered":"Impl\u00e9mentation de l&rsquo;algorithme de diffusion Floyd-Steinberg"},"content":{"rendered":"<p>L&rsquo;algorithme de diffusion Floyd-Steinberg, invent\u00e9 en 1976, permet de tramer une image de mani\u00e8re intelligente. On peut lire son fonctionnement en d\u00e9tails <a href=\"https:\/\/fr.wikipedia.org\/wiki\/Algorithme_de_Floyd-Steinberg\" target=\"_blank\">sur Wikip\u00e9dia<\/a>.<br \/>\nL&rsquo;image qui suit nous permet de comparer un d\u00e9tail d&rsquo;image transform\u00e9e en image 1bit (noir ou blanc) avec cet algorithme (gauche) et sans (droite).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-293 size-full\" src=\"http:\/\/ifdesignelseart.com\/wp-content\/uploads\/2017\/03\/floyd_steinberg2.png\" alt=\"\" width=\"600\" height=\"300\" srcset=\"https:\/\/ifdesignelseart.com\/wp-content\/uploads\/2017\/03\/floyd_steinberg2.png 600w, https:\/\/ifdesignelseart.com\/wp-content\/uploads\/2017\/03\/floyd_steinberg2-300x150.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>Le programme qui suit est une impl\u00e9mentation de cet algorithme pour Processing. Il n&rsquo;est pas forc\u00e9ment rapide mais il fonctionne bien, en niveaux de gris. Lorsque la variable colorsNumber est 2, il n&rsquo;y a que deux couleurs qui seront employ\u00e9es : le blanc et le noir.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-288 size-full alignnone\" src=\"http:\/\/ifdesignelseart.com\/wp-content\/uploads\/2017\/03\/montagne.jpg\" alt=\"\" width=\"600\" height=\"600\" srcset=\"https:\/\/ifdesignelseart.com\/wp-content\/uploads\/2017\/03\/montagne.jpg 600w, https:\/\/ifdesignelseart.com\/wp-content\/uploads\/2017\/03\/montagne-150x150.jpg 150w, https:\/\/ifdesignelseart.com\/wp-content\/uploads\/2017\/03\/montagne-300x300.jpg 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><br \/>\nEn entrant l&rsquo;image en couleurs ci-dessus (\u00ab\u00a0montagne.png\u00a0\u00bb), on obtient l&rsquo;image en noir et blanc qui suit et qui sera enregistr\u00e9e sous le nom \u00ab\u00a0floyd_steinberg.png\u00a0\u00bb.<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"wp-image-289 size-full alignnone\" src=\"http:\/\/ifdesignelseart.com\/wp-content\/uploads\/2017\/03\/floyd_steinberg.png\" alt=\"\" width=\"600\" height=\"600\" srcset=\"https:\/\/ifdesignelseart.com\/wp-content\/uploads\/2017\/03\/floyd_steinberg.png 600w, https:\/\/ifdesignelseart.com\/wp-content\/uploads\/2017\/03\/floyd_steinberg-150x150.png 150w, https:\/\/ifdesignelseart.com\/wp-content\/uploads\/2017\/03\/floyd_steinberg-300x300.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<pre class=\"brush:java\">float palette[];\r\nfloat mu1 = 7.0\/16, mu2 = 3.0\/16, mu3=5.0\/16, mu4=1.0\/16;\r\n\r\n\r\nvoid setup() {\r\n  size(600, 480);\r\n  background(255);\r\n  int colorsNumber = 2; \/\/ ici on d\u00e9cide le nombre de couleurs de la palette\r\n  palette=getPalette(0,255,colorsNumber);  \r\n}\r\n\r\nvoid draw() {\r\n  \/\/ l'image \u00e0 charger s'appelle \"montagne.jpg\" et doit \r\n  \/\/ se trouver dans le dossier \"data\"\r\n  PGraphics g= floydSteinberg(loadImage(\"montagne.jpg\")); \r\n  image(g,0,0);\r\n  g.save(\"floyd_steinberg.png\");\r\n  noLoop();\r\n}\r\n\r\nPGraphics floydSteinberg(PImage img) { \r\n  PGraphics g = createGraphics(img.width, img.height);\r\n  g.beginDraw();\r\n  g.background(0);\r\n  float[][] pixelz;\r\n  pixelz = new float[img.width][img.height];\r\n  for (int y=0; y&lt;img.height; y++) {\r\n    for (int x=0; x&lt;img.width; x++) {\r\n      pixelz[x][y]= brightness(img.get(x, y));\r\n    }\r\n  }\r\n  for (int y=0; y&lt;img.height; y++) {\r\n    for (int x=0; x&lt;img.width; x++) {\r\n      float ancien=pixelz[x][y];  \r\n      float[] nouveau = couleur_la_plus_proche(ancien);\r\n\r\n      pixelz[x][y] = nouveau[0];\r\n      float error= nouveau[1];\r\n      boolean xMax=(x==img.width-1);\r\n      boolean xMin=(x==0);\r\n      boolean yMax=(y==img.height-1);\r\n      if (!xMax) pixelz[x+1][y] += mu1* error;\r\n      if (!xMin &amp;&amp; !yMax) pixelz[x-1][y+1] += mu2* error;\r\n      if (!yMax)pixelz[x][y+1] += mu3* error;\r\n      if (!xMax &amp;&amp; !yMax)pixelz[x+1][y+1] += mu4* error;\r\n    }\r\n  }\r\n  for (int y=0; y&lt;img.height; y++) {\r\n    for (int x=0; x&lt;img.width; x++) {\r\n      float b=pixelz[x][y];\r\n      g.stroke(b);\r\n      g.point(x, y);\r\n    }\r\n  }\r\n  g.endDraw();\r\n  return g;\r\n}\r\n\r\nfloat[] couleur_la_plus_proche(float b) {\r\n  float[] paire = {0, 0};\r\n  float min=256; \r\n  for (int i=0; i&lt;palette.length; i++) {\r\n    float c=palette[i];\r\n    float dis = abs(b-c);\r\n    if (dis&lt;min) {\r\n      min=dis;\r\n      paire[0]=c;\r\n    }\r\n  } \r\n  paire[1]=b-paire[0];\r\n  return paire;\r\n}\r\n\r\nfloat[] getPalette(float depart, float fin, int n){\r\n  if(n&lt;2)n=2;\r\n  float[] toreturn = new float[0];\r\n  float diff = (fin-depart)\/(n-1);\r\n  for(int a=0;a&lt;n;a++){\r\n    toreturn = (float[]) append (toreturn, a*diff);\r\n  } \r\n  return toreturn;\r\n}\r\n<\/pre>\n<p>La valeur de chaque pixel (ligne par ligne depuis le haut jusqu&rsquo;en bas et de gauche \u00e0 droite \u00e0 l&rsquo;int\u00e9rieur de chaque ligne) est lue et compar\u00e9 \u00e0 sa valeur index\u00e9e la plus proche. Si la valeur du pixel est 120 et que la valeur la plus proche dans ma palette est 128, la marge (dite \u00ab\u00a0erreur\u00a0\u00bb) sera de -8. Nous allons alors ajouter :<br \/>\n7\/16e de -8 \u00e0 la valeur du pixel (x+1, y)<br \/>\n3\/16e de -8 au pixel (x-1, y+1)<br \/>\n5\/16e de -8 \u00e0 (x,y+1)<br \/>\n1\/16e de -8 \u00e0 (x+1,y+1)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>L&rsquo;algorithme de diffusion Floyd-Steinberg, invent\u00e9 en 1976, permet de tramer une image de mani\u00e8re intelligente. On peut lire son fonctionnement en d\u00e9tails sur Wikip\u00e9dia. L&rsquo;image qui suit nous permet de comparer un d\u00e9tail d&rsquo;image transform\u00e9e en image 1bit (noir ou blanc) avec cet algorithme (gauche) et sans (droite). Le programme qui suit est une impl\u00e9mentation [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-287","post","type-post","status-publish","format-standard","hentry","category-non-classe"],"_links":{"self":[{"href":"https:\/\/ifdesignelseart.com\/index.php?rest_route=\/wp\/v2\/posts\/287","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ifdesignelseart.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ifdesignelseart.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ifdesignelseart.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/ifdesignelseart.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=287"}],"version-history":[{"count":8,"href":"https:\/\/ifdesignelseart.com\/index.php?rest_route=\/wp\/v2\/posts\/287\/revisions"}],"predecessor-version":[{"id":298,"href":"https:\/\/ifdesignelseart.com\/index.php?rest_route=\/wp\/v2\/posts\/287\/revisions\/298"}],"wp:attachment":[{"href":"https:\/\/ifdesignelseart.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=287"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ifdesignelseart.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=287"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ifdesignelseart.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=287"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}