Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

knowlton sketch #44

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions bin/data/scenes/yingKnowlton/exampleCode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

void draw() {

currentVideo = getVideo([[videoNum]]).draw();

for (int i = 0; i < [[iterations]]; i++) {

if (random() < [[mixRatio]]) {
targetImage = currentVideo;
} else {
targetImage = originalImage;
}

for (int i = 0; i < imageWidth; i++) {
for (int j = 0; j < imageHeight; j++) {

int randX = random(0, imageWidth);
int randY = random(0, imageHeight);

// randomly swap a pixel
sourceImageAfterSwap = sourceImage.swapPixels(i,j, randX, randY);

if (distanceToOriginal(sourceImageAfterSwap) <
distanceToOriginal(sourceImage)) {
sourceImage = sourceImageAfterSwap;
}
}
}


}
sourceImage.draw();
}
Binary file added bin/data/scenes/yingKnowlton/sfpc-final_640.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
15 changes: 15 additions & 0 deletions recoded.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
2AAF4613693D9695224E47EA /* annMolnarRectangles.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D790E5FFA07829E87D5854B1 /* annMolnarRectangles.cpp */; };
2CDF949125CD5802082364F3 /* mattKnowlton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A39AE0D2FA3A4C9F76FC4E61 /* mattKnowlton.cpp */; };
2DE293FAAF850C0ABF02DB62 /* exampleScene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 59429ADBB14FCD19148E74FB /* exampleScene.cpp */; };
2E55175E1FBC8D0300D6B8C9 /* yingKnowlton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E55175D1FBC8CFD00D6B8C9 /* yingKnowlton.cpp */; };
2E555A4FA8AD6EA2CA95AACF /* loloWhitney.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D6397CED8F069F8CCB13C01F /* loloWhitney.cpp */; };
2E6C274B1FBA494600D54DC9 /* zzSushiScene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E6C27491FBA48AC00D54DC9 /* zzSushiScene.cpp */; };
310ED8BB549B244C0DFB0FA1 /* mgsVeraMolnarLineStudy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA88C1467946DA7D2C11601B /* mgsVeraMolnarLineStudy.cpp */; };
Expand Down Expand Up @@ -246,6 +247,8 @@
2BAEA0543B2829CB46F35032 /* mgsRileyEllipsesAndSquares.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 30; name = mgsRileyEllipsesAndSquares.cpp; path = src/scenes/mgsRileyEllipsesAndSquares/mgsRileyEllipsesAndSquares.cpp; sourceTree = SOURCE_ROOT; };
2DB66B4D75A388D55904F54F /* fernandoWhitney2.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 30; name = fernandoWhitney2.h; path = src/scenes/fernandoWhitney2/fernandoWhitney2.h; sourceTree = SOURCE_ROOT; };
2E3CEE46463AC03FCB57EC56 /* loloVera.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 30; name = loloVera.h; path = src/scenes/loloVera/loloVera.h; sourceTree = SOURCE_ROOT; };
2E55175C1FBC8CFD00D6B8C9 /* yingKnowlton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = yingKnowlton.h; sourceTree = "<group>"; };
2E55175D1FBC8CFD00D6B8C9 /* yingKnowlton.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = yingKnowlton.cpp; sourceTree = "<group>"; };
2E6C27491FBA48AC00D54DC9 /* zzSushiScene.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = zzSushiScene.cpp; sourceTree = "<group>"; };
2E6C274A1FBA48AC00D54DC9 /* zzSushiScene.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = zzSushiScene.h; sourceTree = "<group>"; };
2F409986A645F575A744FC98 /* EstherKnowltonScene.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 30; name = EstherKnowltonScene.h; path = src/scenes/EstherKnowltonScene/EstherKnowltonScene.h; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -713,6 +716,16 @@
name = mgsCooperSymbols;
sourceTree = "<group>";
};
2E55175B1FBC8CFD00D6B8C9 /* yingKnowlton */ = {
isa = PBXGroup;
children = (
2E55175C1FBC8CFD00D6B8C9 /* yingKnowlton.h */,
2E55175D1FBC8CFD00D6B8C9 /* yingKnowlton.cpp */,
);
name = yingKnowlton;
path = scenes/yingKnowlton;
sourceTree = "<group>";
};
2E6C27481FBA48AC00D54DC9 /* zzSushiScene */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -788,6 +801,7 @@
36BF1C038F5AEC4D85473FE4 /* scenes */ = {
isa = PBXGroup;
children = (
2E55175B1FBC8CFD00D6B8C9 /* yingKnowlton */,
B0822B3B1FB786C900007B2D /* Guillermo_Whitney_catalogue_1 */,
B0822B311FB565DC00007B2D /* stacyButterflies */,
B0822B2D1FB5646A00007B2D /* diegoScene_01 */,
Expand Down Expand Up @@ -2226,6 +2240,7 @@
D391E4FB2414857BD467D9E8 /* gif_font.c in Sources */,
B0822AE51FB5491200007B2D /* ofxMidiMessage.cpp in Sources */,
149FF2205EB6D2EB34272D36 /* gif_hash.c in Sources */,
2E55175E1FBC8D0300D6B8C9 /* yingKnowlton.cpp in Sources */,
FFBFC666B626901721B1798A /* gifalloc.c in Sources */,
928A7D091FBB5BDE003A2403 /* zzEggScene.cpp in Sources */,
F3339D42B1A22AEF847B1F85 /* quantize.c in Sources */,
Expand Down
2 changes: 2 additions & 0 deletions src/sceneManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
#include "diegoScene_01.h"
#include "stacyButterflies.h"
#include "EstherMolnarScene.h"
#include "yingKnowlton.h"

// these are food related scenes

Expand Down Expand Up @@ -198,6 +199,7 @@ void sceneManager::setup(){
scenes.push_back(new annMolnarRectangles());
scenes.push_back(new weiWhitney());
scenes.push_back(new yumiNishida01());
scenes.push_back(new yingKnowlton());


#endif
Expand Down
195 changes: 195 additions & 0 deletions src/scenes/yingKnowlton/yingKnowlton.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@

#include "yingKnowlton.h"

void yingKnowlton::setup(){

originalImage.load("scenes/yingKnowlton/sfpc-final_640.png");
originalImage.setImageType(OF_IMAGE_COLOR);
sourceImage.load("scenes/yingKnowlton/sfpc-final_640.png");
sourceImage.setImageType(OF_IMAGE_COLOR);
targetScores = NULL;

ofBackground(0);

res = 4;

// note: pulled from @sfpc_nyc instagram feed
directory = ofDirectory("scenes/yingKnowlton/videos/");
directory.listDir();

playVideo(0);
center.set(dimensions.width/2, dimensions.height/2);
screenScale = dimensions.width/vidPlayer.getWidth();
screenScale *= 1.01; // MULTIPLY HERE TO MAKE EDGES BLEED PAST THE SCREEN

parameters.add(videoNum.set("videoNum", 0, 0, directory.size()));
parameters.add(iterations.set("iterations", 5000, 10, 10000));
parameters.add(mixRatio.set("mixRatio", 1, 0, 1));

setAuthor("Ying Quan Tan");
setOriginalArtist("Ken Knowlton");
loadCode("scenes/yingKnowlton/exampleCode.cpp");
}

void yingKnowlton::update(){
vidPlayer.update();
if (vidPlayer.isPlaying() && vidPlayer.getTotalNumFrames() - vidPlayer.getCurrentFrame() < 30) {
videoNum = ++videoNum % directory.size();
playVideo(videoNum);
}
if (current != videoNum) {
current = videoNum;
playVideo(videoNum);
}
}

void yingKnowlton::draw(){
ofPushMatrix();

int vidWidth = vidPlayer.getWidth() * screenScale;
int vidHeight = vidPlayer.getHeight() * screenScale;
// center the video
ofTranslate(center - ofPoint(vidWidth, vidHeight)/2);

// make sure video scales to screen.
ofScale(screenScale, screenScale);


if ((vidPlayer.isPlaying() && sourceImage.isAllocated())) {
unsigned char * vidPixels = vidPlayer.getPixels().getData();
unsigned char * originalPixels = originalImage.getPixels().getData();

ofImage &image = sourceImage;
int cols = image.getWidth() / res;
int rows = image.getHeight() / res;
int positions = cols * rows;
int bytesPerPixel = 3;

for (int it = 0; it < iterations; it++) {
unsigned char * targetPointer;
if (ofRandom(1.0) < mixRatio) {
targetPointer = vidPixels;
} else {
targetPointer = originalPixels;
}

int i = floor(ofRandom(cols)) * res;
int j = floor(ofRandom(rows)) * res;
float previousTargetScore = targetScore;
int index = (j * image.getWidth() + i) * bytesPerPixel;
int x = i / res;
int y = j / res;

int randX = floor(ofRandom(cols)) * res;
int randY = floor(ofRandom(rows)) * res;
int randIndex = (randY * image.getWidth() + randX) * bytesPerPixel;

unsigned char * from = getSubImage(image, i, j, res);
unsigned char * to = getSubImage(image, randX, randY, res);

// calculate costs
float fromScore = distance(from, targetPointer + index);
float toScore = distance(to, targetPointer + randIndex);

float afterSwapFromScore = distance(to, targetPointer + index);
float afterSwapToScore = distance(from, targetPointer + randIndex);

if (afterSwapFromScore + afterSwapToScore < fromScore + toScore) {
// perform swap
setSubImage(image, i, j, res, to);
setSubImage(image, randX, randY, res, from);
}
delete[] from;
delete[] to;
}

image.update();
image.draw(0, 0);
}
ofPopMatrix();
}

void yingKnowlton::playVideo(int index) {
vidPlayer.load(directory.getPath(index));
int cols = vidPlayer.getWidth() / res;
int rows = vidPlayer.getHeight() / res;
if (targetScores == NULL) {
targetScores = new unsigned char[cols * rows];
}
memset(targetScores,0,cols * rows);

vidPlayer.setVolume(0);
vidPlayer.play();

}

unsigned char * yingKnowlton::getSubImage(ofImage &image,
int _x,
int _y,
int maskSize) {
int bytesPerPixel = 3;
unsigned char * subImage = new unsigned char[maskSize * maskSize * bytesPerPixel];
unsigned char * data = image.getPixels().getData();

int c = 0;
for (int y = _y; y < _y + maskSize; y++) {
for (int x = _x; x < _x + maskSize; x++) {
int idx = y * image.getWidth()*bytesPerPixel + x*bytesPerPixel;
for (int i = 0; i < bytesPerPixel; i++) {
subImage[c + i] = data[idx + i];
}
c += bytesPerPixel;
}
}
return subImage;
}


void yingKnowlton::setSubImage(ofImage &image,
int _x,
int _y,
int maskSize,
unsigned char * subImage) {
int bytesPerPixel = 3;
unsigned char * data = image.getPixels().getData();
int c = 0;
for (int y = _y; y < _y + maskSize; y++) {
for (int x = _x; x < _x + maskSize; x++) {
int idx = (y * image.getWidth() + x) * bytesPerPixel;
for (int i = 0; i < bytesPerPixel; i++) {
data[idx + i] = subImage[c + i];
}
c += bytesPerPixel;
}
}
}

float yingKnowlton::distance(unsigned char * pixel1,
unsigned char * pixel2) {

float r1 = pixel1[0];
float g1 = pixel1[1];
float b1 = pixel1[2];

float r2 = pixel2[0];
float g2 = pixel2[1];
float b2 = pixel2[2];

float dist = abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2);
dist /= (255*3);
return dist;
}

float yingKnowlton::getTargetScore() {

float total = 0;
int cols = sourceImage.getWidth() / res;
int rows = sourceImage.getHeight() / res;
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
int score = targetScores[j * cols + i];
total += score;
}
}
return total;
}
45 changes: 45 additions & 0 deletions src/scenes/yingKnowlton/yingKnowlton.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

#include "ofMain.h"
#include "baseScene.h"

class yingKnowlton : public baseScene {

public:

void setup();
void update();
void draw();

int res;
ofVideoPlayer vidPlayer;
ofImage sourceImage;
ofImage originalImage;
ofImage targetImage;
ofPoint center;
float screenScale;
unsigned char * targetScores;
float targetScore;

unsigned char * getSubImage(ofImage &image,
int x,
int y,
int maskSize);
void setSubImage(ofImage &image,
int x,
int y,
int maskSize,
unsigned char * subImage);
float distance(unsigned char * pixel1,
unsigned char * pixel2);
float getTargetScore();

void playVideo(int index);


int current;
ofParameter < float > mixRatio;
ofParameter < int > videoNum;
ofParameter < int > iterations;
ofDirectory directory;
};