[work 35] Mosaic – Wavy Line –

[work 35] Mosaic – Wavy Line –

Movie

Source code

about

  • 振幅・周波数の違う波線でモザイク画を描く
  • 指定した階調のモザイク画を生成し、モザイクのマス目を波線で置き換える

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);
    ofSetupOpenGL(1024,1024, 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 "WavyLine.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:
    unique_ptr<WavyLine> mosaic;
};
#include "ofApp.h"


ofApp::ofApp(){
    
}

ofApp::~ofApp(){
    
}

//--------------------------------------------------------------
void ofApp::setup(){
    double fps = 30;
    
    
    ofSetFrameRate(fps);
    ofBackground(255);
    ofSetBackgroundAuto(false);
    ofSetVerticalSync(true);
    
    ofImage img;
    img.load("Lenna.bmp");
//    img.setImageType(OF_IMAGE_GRAYSCALE);
    
    mosaic = make_unique<WavyLine>(img, 20, 8);
    mosaic->setup();
}

//--------------------------------------------------------------
void ofApp::update(){
    mosaic->update();
}

//--------------------------------------------------------------
void ofApp::draw(){
    mosaic->display();
}
#ifndef Mosaic_hpp
#define Mosaic_hpp

#include <stdio.h>
#include "ofMain.h"

class Mosaic {
public:
    Mosaic(ofImage &img, float c, int f);
    ~Mosaic();
    void setup();
    virtual void update();
    virtual void display();
    
protected:
    int factor;
    float cellSize;
    int cols, rows;
    std::vector<ofColor> colors;
    std::vector<int> toneIdxes;
    
private:
    ofImage orgImg;
    ofPixels pixs;
};
#endif /* Mosaic_hpp */
#include "Mosaic.hpp"


Mosaic::Mosaic(ofImage &img, float c, int f)
{
    std::cout << "Mosaic:Start" << std::endl;
    orgImg = img;
    cellSize = c;
    factor = f - 1;
}


Mosaic::~Mosaic()
{
    std::cout << "Mosaic:End" << std::endl;
}


void Mosaic::setup()
{
    std::cout << "Mosaic:setup" << std::endl;
    pixs = orgImg.getPixels();
    pixs.resize(ofGetWidth(), ofGetHeight());
    
    cols = (int)(ofGetWidth() / cellSize);
    rows = (int)(ofGetHeight() / cellSize);
    
    for (int row = 0; row < rows; row++) {
        for (int col = 0; col < cols; col++) {
            int sum_r = 0;
            int sum_g = 0;
            int sum_b = 0;
            for (int j = 0; j < cellSize; j++) {
                for (int i = 0; i < cellSize; i++) {
                    ofColor c;
                    int x = col * cellSize + i;
                    int y = row * cellSize + j;
                    c = pixs.getColor(x, y);
                    sum_r += c.r;
                    sum_g += c.g;
                    sum_b += c.b;
                }
            }
            
            int ave_r = sum_r / (cellSize * cellSize);
            int ave_g = sum_g / (cellSize * cellSize);
            int ave_b = sum_b / (cellSize * cellSize);
            
            int tone_r = factor * ave_r / 255 * (255 / factor);
            int tone_g = factor * ave_g / 255 * (255 / factor);
            int tone_b = factor * ave_b / 255 * (255 / factor);
            ofColor tone = ofColor(tone_r, tone_g, tone_b);
            colors.push_back(tone);
            
            int index = factor * (int)tone.getBrightness() / 255;
            toneIdxes.push_back(index);
        }
    }
}


void Mosaic::update()
{
    std::cout << "Mosaic:update" << std::endl;
}


void Mosaic::display()
{
    std::cout << "Mosaic:display" << std::endl;
    
    for (int row = 0; row < rows; row++) {
        for (int col = 0; col < cols; col++) {
            int idx = cols * row + col;
            ofVec2f corner = ofVec2f(col * cellSize, row * cellSize);
            ofPushMatrix();
            ofSetRectMode(OF_RECTMODE_CORNER);
            ofTranslate(corner);
            ofFill();
            ofSetColor(colors[idx]);
            ofDrawRectangle(0, 0, cellSize, cellSize);
            ofPopMatrix();
        }
    }
}
#ifndef WavyLine_hpp
#define WavyLine_hpp

#include <stdio.h>
#include "ofMain.h"
#include "Mosaic.hpp"


struct WaveSet {
    float freq;
    float amp;
    
    WaveSet(float f, float a) {
        freq = f;
        amp = a;
    }
};


class WavyLine : public Mosaic {
public:
    WavyLine(ofImage &img, float c, int f);
    ~WavyLine();
    void setup();
    void update();
    void display();
    
private:
    bool drawFinish;
    int indexX, indexY;
    float theta;
    int x;
    std::vector<ofVec2f> wave;
    std::vector<WaveSet> tonePattern;
    ofVec2f terminatePoint;
};
#endif /* WavyLine_hpp */
#include "WavyLine.hpp"



WavyLine::WavyLine(ofImage &img, float c, int f) : Mosaic(img, c, f)
{
    std::cout << "WavyMosaic:Start" << std::endl;
    drawFinish = false;
    theta = 0;
    x = 0;
    indexX = 0;
    indexY = 0;
}


WavyLine::~WavyLine()
{
    std::cout << "WavyMosaic:End" << std::endl;}


void WavyLine::setup()
{
    std::cout << "WavyMosaic:setup" << std::endl;
    
    Mosaic::setup();
    
    float amp = ((cellSize / 2) * 0.8);
    tonePattern.push_back(WaveSet(5, amp));
    tonePattern.push_back(WaveSet(4, amp));
    tonePattern.push_back(WaveSet(3, amp));
    tonePattern.push_back(WaveSet(2, amp));
    tonePattern.push_back(WaveSet(1, amp));
    tonePattern.push_back(WaveSet(2, amp / 2));
    tonePattern.push_back(WaveSet(1, amp / 2));
    tonePattern.push_back(WaveSet(1, 0));
}


void WavyLine::update()
{
    std::cout << "WavyMosaic:update" << std::endl;
    
    if (theta > TWO_PI) {
        theta = 0;
        terminatePoint = wave.back();
        wave.clear();
        wave.push_back(terminatePoint);
        
        indexX++;
        if (!(indexX < cols)) {
            indexX = 0;
            x = 0;
            wave.clear();
            
            indexY++;
            if (!(indexY < rows)) {
                drawFinish = true;
            }
        }
    }
    
    if (!drawFinish) {
        int index = cols * indexY + indexX;
        int waveIdx = toneIdxes.at(index);
        
        ofVec2f point;
        float t = tonePattern[waveIdx].freq * theta;
        point.x = x++;
        point.y = std::sin(t) * tonePattern[waveIdx].amp;
        wave.push_back(point);
        theta += TWO_PI / cellSize;
    }
}


void WavyLine::display()
{
    std::cout << "WavyMosaic:display" << std::endl;
    
    if (!drawFinish) {
        int index = cols * indexY + indexX;
        ofPushMatrix();
        ofTranslate(0, cellSize * indexY + cellSize / 2);
        ofNoFill();
        ofBeginShape();
        for (ofVec2f &w : wave) {
            ofSetColor(colors.at(index));
            ofVertex(w);
        }
        ofEndShape();
        ofPopMatrix();
    }
}

Link to the reference page

ソースコードで使用したAPIの中から要点になりそうなものをいくつか選んでリストアップしました。

categoryAPI/Lib
c++std::sin
c++std::vector

Development environment

  • openframeworks 0.10.1
  • c++
  • macOS
  • Xcode