[work 33] Floyd–Steinberg dithering
![[work 33] Floyd–Steinberg dithering](https://i0.wp.com/tsukuru.hayato-works.com/wp-content/uploads/2019/04/sketch0034.jpg?fit=1024%2C576&ssl=1)
Movie
Source code
about
- フロイド-スタインバーグ・ディザリングの手法を使ってグレースケール画像を2値画像に変換する
- 参考(https://en.wikipedia.org/wiki/Floyd–Steinberg_dithering)
file
- 上部にあるファイル名が表示されているボタンを押すと、表示されるファイルが切り替わります
- 別ウィンドウ表示したい時や行番号などが無いRawMode表示したい時は、コード内右上のボタンを押してください(ボタンはマウスオーバーすると表示されます)
#include "ofMain.h"
#include "ofApp.h"
//================================
int main( ){
// 4K:4096x2160
// 2K:2048x1080
// FullHD:1920x1080
// HD:1440x1080
// HD720p:1280x720
// DVD:720x480
// setup the GL context
ofSetupOpenGL(1280,720, OF_WINDOW);
// this kicks off the running of my app
// can be OF_WINDOW or OF_FULLSCREEN
// pass in width and height too:
ofRunApp( new ofApp());
}
#pragma once
#include "ofMain.h"
#include "Dithering.hpp"
class ofApp : public ofBaseApp{
public:
ofApp();
~ofApp();
void setup();
void update();
void draw();
void keyPressed(int key);
void keyReleased(int key);
void mouseMoved(int x, int y);
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseEntered(int x, int y);
void mouseExited(int x, int y);
void windowResized(int w, int h);
void dragEvent(ofDragInfo dragInfo);
void gotMessage(ofMessage msg);
private:
Dithering dithering;
ofTexture texture;
};
#include "ofApp.h"
ofApp::ofApp(){
}
ofApp::~ofApp(){
}
//--------------------------------------------------------------
void ofApp::setup(){
double fps = 30;
ofSetFrameRate(fps);
ofBackground(0);
ofSetBackgroundAuto(true);
// original image
ofPixels pix;
ofImage img;
img.load("IMG_3631.jpg");
img.setImageType(OF_IMAGE_GRAYSCALE);
pix = img.getPixels();
pix.resize(ofGetWidth(), ofGetHeight());
texture.allocate(pix);
dithering.setup();
}
//--------------------------------------------------------------
void ofApp::update(){
}
//--------------------------------------------------------------
void ofApp::draw(){
if (ofGetFrameNum() < 30 * 4) {
texture.draw(0, 0);
} else {
dithering.display();
}
}
#ifndef Dithering_hpp
#define Dithering_hpp
#include <stdio.h>
#include "ofMain.h"
class Dithering {
public:
Dithering();
~Dithering();
void setup();
void display();
private:
ofTexture texture;
};
#endif /* Dithering_hpp */
#include "Dithering.hpp"
Dithering::Dithering()
{
}
Dithering::~Dithering()
{
}
void Dithering::setup()
{
ofPixels pix;
ofImage img;
img.load("IMG_3631.jpg");
img.setImageType(OF_IMAGE_GRAYSCALE);
pix = img.getPixels();
pix.resize(ofGetWidth(), ofGetHeight());
for (int y = 0; y < ofGetHeight() - 1; y++) {
for (int x = 1; x < ofGetWidth() - 1; x++) {
int factor = 1;
ofColor oldCol = pix.getColor(x, y);
ofColor newCol;
newCol.r = factor * oldCol.r / 255 * (255 / factor);
newCol.g = factor * oldCol.g / 255 * (255 / factor);
newCol.b = factor * oldCol.b / 255 * (255 / factor);
ofColor quantumError = oldCol - newCol;
pix.setColor(x, y, newCol);
ofColor c;
ofColor tmp;
tmp.r = quantumError.r * 7 / 16;
tmp.g = quantumError.g * 7 / 16;
tmp.b = quantumError.b * 7 / 16;
c = pix.getColor(x+1, y) + tmp;
pix.setColor(x+1, y, c);
tmp.r = quantumError.r * 3 / 16;
tmp.g = quantumError.g * 3 / 16;
tmp.b = quantumError.b * 3 / 16;
c = pix.getColor(x-1, y+1) + tmp;
pix.setColor(x-1, y+1, c);
tmp.r = quantumError.r * 5 / 16;
tmp.g = quantumError.g * 5 / 16;
tmp.b = quantumError.b * 5 / 16;
c = pix.getColor(x, y+1) + tmp;
pix.setColor(x, y+1, c);
tmp.r = quantumError.r * 1 / 16;
tmp.g = quantumError.g * 1 / 16;
tmp.b = quantumError.b * 1 / 16;
c = pix.getColor(x+1, y+1) + tmp;
pix.setColor(x+1, y+1, c);
}
}
texture.allocate(pix);
}
void Dithering::display()
{
texture.draw(0, 0);
}
Link to the reference page
ソースコードで使用したAPIの中から要点になりそうなものをいくつか選んでリストアップしました。
Development environment
- openframeworks 0.10.1
- c++
- macOS
- Xcode