ETERNITY DESIGN BLOG

ブレンドモードとPixel Bender

WCAN mini ActionScript Vol.12での発表したものです。

PhotoshopにあってFlashにないブレンドモード(Photoshopでは描画モード)の中で、自分がよく使うソフトライトをAS(とPixel Bender)で実装しましたというお話をさせていただきました。

まずは、紹介させていただいた本。

参加者から頂いたアンケートでPsとFlの色の扱いの違いを確認しろいわれて気づいたことがありました。

発表中に双方での結果を比較して「微妙に違う」とかありましたが、よく考えたら、Psのほうで「色の校正」にチェック入れるの忘れてました。(頂いたアンケートの指摘がこれかどうかは知りません)
Mac環境ではWebと同じ色表示にするのには必須ですよね。Flash以外でも。
よく忘れるんです。これ。
まー、でも、実際、「色の校正」にチェック入れても微妙に色違うんです。
目で比較してもわからないぐらい微妙で、ピクセルごとに調べないとわからないレベルではあります。
PsとFlで共通にあるオーバーレイで比較しても微妙に色違うので、目を瞑る方向で。

流れとしては、ASonlyで実装したものをお見せして、ちょいモーションさせるには遅いですよね。
ですからPixel Benderでやってみました。→ おお、動く!

という感じでやりたかったのに、ASonlyバージョンが動かず。
仕様を変えようかなとちょい弄ったところでやめて、そのままにしてたの忘れてた。

最下部より修正したASファイルやPixel Bender関連ファイルをダウンロードできます。
一応ASonly版は、ソフトライト以外に、覆い焼き、焼き込み、色相とあります。
色相は、Psとまったく違う結果になるので、何か間違えてるかもだけど、面白いのでそのままに。

紹介した本にはブレンドモードだけでなく、Pixel Benderの章もあるので、この先読み進んで何か修正できそうならするかも。

//AS3///////////////////////////////////////////////////////////////////////////
// 
// Photoshop SoftLightクラス
// 
////////////////////////////////////////////////////////////////////////////////

package net.eternitydesign.Graphics {
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.geom.Rectangle;
	import sketchbook.colors.ColorUtil;

	public class ExtendBlendMode {

		public function ExtendBlendMode() {
			
		}

		//---------------------------------------
		// 指定されたBitmapDataを元にSoftLight処理されたBitmapを返す
		//---------------------------------------
		public function getImage(m:String, topBitmap:BitmapData, bottomBitmap:BitmapData, rect:Rectangle = null):BitmapData {
			var tempColorTop:uint;
			var tempColorBottom:uint;
			var red:uint;
			var green:uint;
			var blue:uint;
			var resultColor:uint;

			var resultBitmapData = new BitmapData(bottomBitmap.width, bottomBitmap.height, true, 0xff000000);

			for(var i:Number = 0; i < topBitmap.width; i++) {
				for(var j:Number = 0; j > 16), (tempColorBottom >> 16));
							green = this[m]((tempColorTop >> 8 & 0xff), (tempColorBottom >> 8 & 0xff));
							blue = this[m]((tempColorTop & 0xff), (tempColorBottom & 0xff));
							resultColor = (red << 16) | (green <> 16), (tempColorBottom >> 16));
						green = this[m]((tempColorTop >> 8 & 0xff), (tempColorBottom >> 8 & 0xff));
						blue = this[m]((tempColorTop & 0xff), (tempColorBottom & 0xff));
						resultColor = (red << 16) | (green << 8) | (blue);
					}

					resultBitmapData.setPixel(i, j, resultColor);
				}
			}
			return resultBitmapData;
		}

		//---------------------------------------
		// ソフトライトモード
		//---------------------------------------
		public function softLight(topPixel:uint, bottomPixel:uint):uint {
			var color:uint;
			if(topPixel < 128) {
				//Pn = ( Pa / 255 ) ^ ( ( 255 - Pb ) / 128 ) * 255
				color = Math.pow((bottomPixel / 255), ((255 - topPixel) / 128)) * 255;
			}
			else {
				//( Pa / 255 ) ^ ( 128 / Pb ) * 255
				color = Math.pow((bottomPixel / 255), (128 / topPixel)) * 255;
			}

			return color;
		}

		//---------------------------------------
		// 覆い焼き
		//---------------------------------------
		public function dodge(topPixel:uint, bottomPixel:uint):uint {
			var color:uint;
			if(topPixel == 255) {
				color = 255;
			}
			else {
				// Pn = Pa * 255 / ( 255 - Pb )
				color = Math.min(255, bottomPixel * 255 / (255 - topPixel));
			}

			return color;
		}

		//---------------------------------------
		// 焼き込み
		//---------------------------------------
		public function burn(topPixel:uint, bottomPixel:uint):uint {
			var color:uint = 0;
			
			if(topPixel != 0) {
				//Pn = 255 - (( 255 - Pa ) * 255 / Pb ))
				color = Math.max(0, 255 - ((255 - bottomPixel) * 255 / topPixel));
			}

			return color;
		}

		//---------------------------------------
		// 色相
		//---------------------------------------
		public function hue(topBitmap:BitmapData, bottomBitmap:BitmapData, rect:Rectangle = null):BitmapData {
			var tempColorTop:uint;
			var tempColorBottom:uint;
			var topHue:int;
			var bottomHLS:Object;
			var bottomRGB:Object;
			var resultColor:uint;

			var resultBitmapData = new BitmapData(bottomBitmap.width, bottomBitmap.height, true, 0xff000000);

			for(var i:Number = 0; i < topBitmap.width; i++) {
				for(var j:Number = 0; j > 16), (tempColorTop >> 8 & 0xff), (tempColorTop & 0xff)).h;
							bottomHLS = ColorUtil.RGB2HLS((tempColorBottom >> 16), (tempColorBottom >> 8 & 0xff), (tempColorBottom & 0xff));
							bottomRGB = ColorUtil.HLS2RGB(topHue, bottomHLS.l, bottomHLS.s);
							resultColor = (bottomRGB.r << 16) | (bottomRGB.g <> 16), (tempColorTop >> 8 & 0xff), (tempColorTop & 0xff)).h;
						bottomHLS = ColorUtil.RGB2HLS((tempColorBottom >> 16), (tempColorBottom >> 8 & 0xff), (tempColorBottom & 0xff));
						bottomRGB = ColorUtil.HLS2RGB(topHue, bottomHLS.l, bottomHLS.s);
						resultColor = (bottomRGB.r << 16) | (bottomRGB.g << 8) | (bottomRGB.b);
					}

					resultBitmapData.setPixel(i, j, resultColor);
				}
			}
			return resultBitmapData;
		}
	}
	
}

{title}のダウンロード

以下のサイトを参考にさせていただきました。
http://ofo.jp/osakana/cgtips/blendmode.phtml
http://www21.atwiki.jp/submarine/pages/56.html

ABOUT ME

名古屋を中心に、フリーランスでホームページ制作してます。 デザイン・サイト制作・WordPress案件・Flash制作、JavaScript(jQuery)と幅広く対応可能です。 案件のご依頼・ご相談はCONTACTよりご連絡ください。

CATEGORIES

ARCHIVES

TAGS