Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > de.comp.lang.iso-c++ > #2018

Selbstgestrickter Floyd-Steinberg-Filter sieht seltsam aus...

From Jörg "Yadgar" Bleimann <yazdegird@gmx.de>
Newsgroups de.comp.lang.iso-c++
Subject Selbstgestrickter Floyd-Steinberg-Filter sieht seltsam aus...
Date 2017-02-11 14:52 +0100
Organization albasani.net
Message-ID <o7n4v0$emd$1@news.albasani.net> (permalink)

Show all headers | View raw


Hi(gh)!

Hi(gh)!

Mittlerweile habe ich es tatsächlich geschafft, im Rahmen meines 
Kommandozeilen-Bildbearbeitungsprogramms "YIP" (Yadgar's Image Processor 
- ImageMagick für Arme...) so etwas wie Floyd-Steinberg-Rasterung zu 
programmieren, nach dem Artikel "Floyd-Steinberg" in der englischen 
Wikipedia... in Pseudocode wird der Algorithmus dort so dargestellt:

for each y from top to bottom
    for each x from left to right
       oldpixel  := pixel[x][y]
       newpixel  := find_closest_palette_color(oldpixel)
       pixel[x][y]  := newpixel
       quant_error  := oldpixel - newpixel
       pixel[x + 1][y    ] := pixel[x + 1][y    ] + quant_error * 7 / 16
       pixel[x - 1][y + 1] := pixel[x - 1][y + 1] + quant_error * 3 / 16
       pixel[x    ][y + 1] := pixel[x    ][y + 1] + quant_error * 5 / 16
       pixel[x + 1][y + 1] := pixel[x + 1][y + 1] + quant_error * 1 / 16

Bei mir in C++ sieht das so aus:

void floydsteinberg(vector<vector<pixel> > &img, vector<rgb> &pal)
{
   unsigned short h = img.size();
   unsigned short w = img[0].size();
   unsigned short r, c, i;
   unsigned short p = pal.size();
   rgb t0, t1, t2, t3, t4, closest=pal.at(0);
   rgb triple, dist;
   float newred, newgreen, newblue;

   for (r=0; r<h; r++)
   {
     for (c=0; c<w; c++)
     {
       img[r].at(c).get_all(triple);
       t0 = triple;
       t1 = {-1, -1, -1};
       t2 = {-1, -1, -1};
       t3 = {-1, -1, -1};
       t4 = {-1, -1, -1};
       if (c < w-1)
       {
           img[r].at(c+1).get_all(triple);
           t1 = triple;
       }
       if (c > 0 && r < h-1)
       {
         img[r+1].at(c-1).get_all(triple);
         t2 = triple;
       }
       if (r < h-1 )
       {
           img[r+1].at(c).get_all(triple);
         t3 = triple;
       }
       if (c < w-1 && r < h-1 )
       {
           img[r+1].at(c+1).get_all(triple);
         t4 = triple;
       }
       for (i=0; i<p; i++)
       {
           if (coldist(t0, pal.at(i)) < coldist(t0, closest))
             closest = pal.at(i);
       }
       img[r].at(c).set_all(closest.red, closest.green, closest.blue);
       dist.red = t0.red - closest.red;
       dist.green = t0.green - closest.green;
       dist.blue = t0.blue - closest.blue;
       if (t1.red > -1)
       {
           img[r].at(c+1).get_all(triple);
           newred = triple.red + dist.red*0.4375;
           newgreen = triple.green + dist.green*0.4375;
           newblue = triple.blue + dist.blue*0.4375;
         img[r].at(c+1).set_all(mround(newred), mround(newgreen), 
mround(newblue));
       }
       if (t2.red > -1)
       {
           img[r+1].at(c-1).get_all(triple);
           newred = triple.red + dist.red*0.1875;
           newgreen = triple.green + dist.green*0.1875;
           newblue = triple.blue + dist.blue*0.1875;
         img[r+1].at(c-1).set_all(mround(newred), mround(newgreen), 
mround(newblue));
       }
       if (t3.red > -1)
       {
           img[r+1].at(c).get_all(triple);
           newred = triple.red + dist.red*0.3125;
           newgreen = triple.green + dist.green*0.3125;
           newblue = triple.blue + dist.blue*0.3125;
         img[r+1].at(c).set_all(mround(newred), mround(newgreen), 
mround(newblue));
       }
       if (t4.red > -1)
       {
           img[r+1].at(c+1).get_all(triple);
           newred = triple.red + dist.red*0.0625;
           newgreen = triple.green + dist.green*0.0625;
           newblue = triple.blue + dist.blue*0.0625;
         img[r+1].at(c+1).set_all(mround(newred), mround(newgreen), 
mround(newblue));
       }

     }
   }


   cout << "Floyd-Steinberg-Rasterung wird berechnet!" << endl;
}

"pixel" ist eine selbst entwickelte Klasse, "rgb" ein struct-Objekt für 
Farbtripel.

Das Programm kompiliert problemlos (bis auf ein paar Warnungen wegen nur 
in C++11 verfügbarer Funktionen), es gibt auch keinen Laufzeitfehler... 
aber wenn ich mir die gerasterte Bilddatei (von RGB nach 
1-bit-Schwarzweiß) ansehe, frage ich mich, was da falsch gelaufen ist - 
wie Floyd-Steinberg-Schwarzweiß z. B. in GIMP sieht es nämlich nicht aus!

Hier das Original:
http://www.rock-o-data.de/fotos/Yadgar.png
... und das hier:
http://www.rock-o-data.de/fotos/Yadgar_monochrome.png
  ist die schwarzweiße gerasterte Version!

Bis bald im Khyberspace!

Yadgar

Back to de.comp.lang.iso-c++ | Previous | NextNext in thread | Find similar | Unroll thread


Thread

Selbstgestrickter Floyd-Steinberg-Filter sieht seltsam aus... Jörg "Yadgar" Bleimann <yazdegird@gmx.de> - 2017-02-11 14:52 +0100
  Re: Selbstgestrickter Floyd-Steinberg-Filter sieht seltsam aus... Stefan Reuther <stefan.news@arcor.de> - 2017-02-12 11:00 +0100
    Re: Selbstgestrickter Floyd-Steinberg-Filter sieht seltsam aus... Jörg "Yadgar" Bleimann <yazdegird@gmx.de> - 2017-02-12 21:43 +0100
    Re: Selbstgestrickter Floyd-Steinberg-Filter sieht seltsam aus... Jörg "Yadgar" Bleimann <yazdegird@gmx.de> - 2017-02-12 20:34 +0100
  Re: Selbstgestrickter Floyd-Steinberg-Filter sieht seltsam aus... Markus Schaaf <mschaaf@elaboris.de> - 2017-02-14 01:03 +0100
    Re: Selbstgestrickter Floyd-Steinberg-Filter sieht seltsam aus... Jörg "Yadgar" Bleimann <yazdegird@gmx.de> - 2017-02-14 11:36 +0100

csiph-web