processingでテクニカラー時代映画風の画像フィルターを作る

U-Nextに加入したので、MGMのテクニカラーのミュージカル映画とかを改めて観ていたらどれも夢みたいな色彩で素晴らしく、一体テクニカラーってどういう理屈で色を付けているのかな?と疑問におもった。

上の動画によると、映像を撮るときにRGB要素別に分解したネガを反転させ、それぞれの補色で染め、それをまた合体させる。。という原理のもよう。

要は元の絵からRGB分解したものを再度合体させているだけなので、デジタルでやると同じ手法をとってもオリジナルの色味がそのまま再現されてしまうだけ。

たぶん、アナログだとフィルム染めるときに色むらがあったり、合成するときのずれだったり、染料のシアンやマゼンダの色味とかが作用して独特のかんじになっているんだとおもう。

そりあえず彩度の高さとコントラストの強さ、あと滲んだムラのある感じを真似したらそれっぽくなるのかなとおもったので、画像の色情報を取って、ブレンドモードをハードライトにしてそのまま点描してみた。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
PImage img;
void setup() {
size(500, 1000); //画像のサイズ
img = loadImage("img/input.jpg"); //画像読み込み
}
void draw() {
noLoop();
//ピクセル読み込み用
loadPixels();
img.loadPixels();
//点描設定
noStroke();
blendMode(HARD_LIGHT);
float alpha = 40;
float pointSize = 4;
//画像サイズ分ループ
for ( int y = 0; y < height; y++ ) {
for ( int x = 0; x < width; x++ ) {
      //ピクセルごとの色情報の取得
int loc = x + y * width;
float r = red( img.pixels[loc] );
float g = green( img.pixels[loc] );
float b = blue( img.pixels[loc] );
    //取得した色で円を描画
fill( r, g, b, alpha );
ellipse( x, y, pointSize, pointSize );
}
}
}
PImage img; void setup() { size(500, 1000); //画像のサイズ img = loadImage("img/input.jpg"); //画像読み込み } void draw() { noLoop(); //ピクセル読み込み用 loadPixels(); img.loadPixels(); //点描設定 noStroke(); blendMode(HARD_LIGHT); float alpha = 40; float pointSize = 4; //画像サイズ分ループ for ( int y = 0; y < height; y++ ) { for ( int x = 0; x < width; x++ ) {       //ピクセルごとの色情報の取得 int loc = x + y * width; float r = red( img.pixels[loc] ); float g = green( img.pixels[loc] ); float b = blue( img.pixels[loc] );     //取得した色で円を描画 fill( r, g, b, alpha ); ellipse( x, y, pointSize, pointSize ); } } }
PImage img;

void setup() {
  size(500, 1000); //画像のサイズ
  img = loadImage("img/input.jpg"); //画像読み込み
}

void draw() {
    noLoop();
    //ピクセル読み込み用
    loadPixels();
    img.loadPixels();
    //点描設定
    noStroke();
    blendMode(HARD_LIGHT); 
    float alpha = 40;
    float pointSize = 4;
    //画像サイズ分ループ
    for ( int y = 0; y < height; y++ ) {
        for ( int x = 0; x < width; x++ ) {
       //ピクセルごとの色情報の取得
            int loc = x + y * width;           
            float r = red( img.pixels[loc] );
            float g = green( img.pixels[loc] );
            float b = blue( img.pixels[loc] );
         //取得した色で円を描画
            fill( r, g, b, alpha );
            ellipse( x, y, pointSize, pointSize );
         }
     }    
 }
左がオリジナル、右が加工後

結構これだけでもそれっぽい感じの色味になった。

さらに、描画する円のサイズを細かくしたり、描画位置(ellipseの(x,y)部分)にランダムな値を加えたりしてフィルムグレインっぽさを追加すると昔っぽさがでる。

円描画にランダム要素を追加

ついでに、シアン、マゼンダ、イエローをブレンドモード=MULTIPYEで描画したあと、ハードライトでハイライトを追加するという加工も試してみた。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
PImage img;
void setup() {
size(500, 1000);
img = loadImage("img/input.jpg");
}
void draw() {
noLoop();
loadPixels();
img.loadPixels();
noStroke();
float alpha = 50;
float pointSize = 8;
for ( int y = 0; y < height; y++ ) {
for ( int x = 0; x < width; x++ ) {
int loc = x + y * width;
float r = red( img.pixels[loc] );
float g = green( img.pixels[loc] );
float b = blue( img.pixels[loc] );
float n = random(50); //ランダム値を作成
//MULTIPLYモードでシアン、イエロー、マゼンダを描画
//ランダム値を足して色むらを表現
//描画位置をずらして版ずれ?っぽさを出す
blendMode( MULTIPLY );
fill( r+n, 225, 225, alpha );
ellipse( x, y, pointSize, pointSize );
fill( 225, g+n, 225, alpha );
ellipse( x+2, y, pointSize, pointSize );
fill( 225, 225, b+n, alpha );
ellipse( x, y+1, pointSize, pointSize );
//HARD LIGHTモードでグレースケールを付加してハイライトを付ける
blendMode( HARD_LIGHT );
fill( ( r+g+b )/3+100, 15 ); //白っぽくするため100足してる
ellipse( x, y, pointSize, pointSize );
}
}
}
PImage img; void setup() { size(500, 1000); img = loadImage("img/input.jpg"); } void draw() { noLoop(); loadPixels(); img.loadPixels(); noStroke(); float alpha = 50; float pointSize = 8; for ( int y = 0; y < height; y++ ) { for ( int x = 0; x < width; x++ ) { int loc = x + y * width; float r = red( img.pixels[loc] ); float g = green( img.pixels[loc] ); float b = blue( img.pixels[loc] ); float n = random(50); //ランダム値を作成 //MULTIPLYモードでシアン、イエロー、マゼンダを描画 //ランダム値を足して色むらを表現 //描画位置をずらして版ずれ?っぽさを出す blendMode( MULTIPLY ); fill( r+n, 225, 225, alpha ); ellipse( x, y, pointSize, pointSize ); fill( 225, g+n, 225, alpha ); ellipse( x+2, y, pointSize, pointSize ); fill( 225, 225, b+n, alpha ); ellipse( x, y+1, pointSize, pointSize ); //HARD LIGHTモードでグレースケールを付加してハイライトを付ける blendMode( HARD_LIGHT ); fill( ( r+g+b )/3+100, 15 ); //白っぽくするため100足してる ellipse( x, y, pointSize, pointSize ); } } }
PImage img;

void setup() {
    size(500, 1000);
    img = loadImage("img/input.jpg");
}

void draw() {
    noLoop();
    loadPixels(); 
    img.loadPixels();
    noStroke();
    float alpha = 50;
    float pointSize = 8;
    
    for ( int y = 0; y < height; y++ ) {
        for ( int x = 0; x < width; x++ ) {
            int loc = x + y * width;
            float r = red( img.pixels[loc] );
            float g = green( img.pixels[loc] );
            float b = blue( img.pixels[loc] );
            float n = random(50); //ランダム値を作成
            //MULTIPLYモードでシアン、イエロー、マゼンダを描画
            //ランダム値を足して色むらを表現
            //描画位置をずらして版ずれ?っぽさを出す
            blendMode( MULTIPLY ); 
            fill( r+n, 225, 225, alpha );
            ellipse( x, y, pointSize, pointSize );
            fill( 225, g+n, 225, alpha );
            ellipse( x+2, y, pointSize, pointSize );
            fill( 225, 225, b+n, alpha );
            ellipse( x, y+1, pointSize, pointSize );            
            //HARD LIGHTモードでグレースケールを付加してハイライトを付ける
            blendMode( HARD_LIGHT ); 
            fill( ( r+g+b )/3+100, 15 ); //白っぽくするため100足してる
            ellipse( x, y, pointSize, pointSize );          
         }
     }
 }
 
乗算+ハードライト

これはこれで彩度の低さがレトロっぽくてロマンチックな気がするし、ぼやけ方が写ルンですっぽくもありエモ。

因みに使った写真はおととしタイに行ったときに撮ったもの。また行きたいなあ。。