トーンカーブと濃度補正
画像処理の練習 -->トーンカーブ(濃度変換)
/**
* Copyright termat ( http://wonderfl.net/user/termat )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/vIKr
*/
/*
画像処理の練習 -->トーンカーブ(濃度変換)
*/
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
[SWF(framerate = "30", width = "500",height="500",backgroundColor="0xffffff")]
public class Practice32 extends Sprite{
private var image:ImagePanel;
public function Practice32() {
var xy:XYGraph = new XYGraph(180,180);
xy.x = 310;
xy.y = 200;
addChild(xy);
var lines:Lines = new Lines(180, 180);
lines.x = 310;
lines.y = 200;
addChild(lines);
stage.addEventListener(MouseEvent.MOUSE_DOWN, lines.onDown);
stage.addEventListener(MouseEvent.MOUSE_UP, lines.onUp);
stage.addEventListener(MouseEvent.MOUSE_MOVE, lines.onMove);
image = new ImagePanel(lines);
addChild(image);
image.x = 5;
image.y = 20;
stage.addEventListener(MouseEvent.MOUSE_UP, image.onMouseUp);
var hist:Histgram = new Histgram(180, 180);
image.hist = hist;
hist.x = 310;
hist.y = 10;
addChild(hist);
var _url:String = "http://assets.wonderfl.net/images/related_images/f/f0/f08c/f08c673a6768eaef2ce5226ebba5d0c0fcc80126";
image.load(_url);
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.display.MovieClip;
import flash.net.URLRequest;
import flash.system.LoaderContext;
class ImagePanel extends MovieClip {
private var backup:Vector.<uint>;
public var bmpdata:BitmapData;
private var loader:Loader;
private var bmp:Bitmap;
private var lines:Lines;
public var hist:Histgram = null;
public function ImagePanel(_lines:Lines):void {
lines = _lines;
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleted);
}
public function load(_url:String):void {
loader.load(new URLRequest(_url), new LoaderContext(true));
}
private function loadCompleted(e:Event):void {
backup = new Vector.<uint>();
bmpdata = new BitmapData(loader.width, loader.height);
bmpdata.draw(loader);
for (var i:int = 0; i < bmpdata.width; i++) {
for (var j:int = 0; j < bmpdata.height; j++) {
backup.push(bmpdata.getPixel(i,j));
}
}
bmp = new Bitmap(bmpdata);
addChild(bmp);
if (hist != null) {
hist.bmpdata = bmpdata;
hist.draw();
}
}
public function onMouseUp(e:MouseEvent):void {
if(!lines.isChanged)return;
var id:int = 0;
for (var i:int = 0; i < bmpdata.width; i++) {
for (var j:int = 0; j < bmpdata.height; j++) {
var color:uint = backup[id++];
var r:int = (color & 0xff0000) >> 16;
r = Math.min(Math.max(0,r * lines.getValue(r / 255.0)),255);
color = (r << 16) + (r << 8) + r;
bmpdata.setPixel(i, j, color);
}
}
if (hist != null) hist.draw();
lines.isChanged=false;
}
}
class Lines extends MovieClip {
private var xp:Vector.<Number>;
private var yp:Vector.<Number>;
private var selected:int = -1;
public var isChanged:Boolean=false;
public function Lines(w:Number,h:Number):void {
xp = new Vector.<Number>();
yp = new Vector.<Number>();
xp.push(0); yp.push(h);
xp.push(w); yp.push(0);
draw();
}
private function vector(x0:Number, y0:Number, x1:Number, y1:Number):Point {
var len:Number = Math.sqrt(Math.pow(x1 - x0, 2) + Math.pow(y1 - y0, 2));
return new Point((x1 - x0) / len, (y1 - y0) / len);
}
public function getValue(xv:Number):Number {
xv = Math.min(1.0, Math.max(0.0, xv));
var xx:Number = xp[xp.length - 1];
var px:int = xx * xv;
if (px == 0) return 0.0;
var id:int = getId(px);
var py:Number = (yp[id] - yp[id - 1]) / (xp[id] - xp[id - 1]);
py = py * (px - xp[id - 1]) + yp[id - 1];
return (yp[0]-py)/yp[0];
}
private function draw():void {
graphics.lineStyle(3, 0x222222);
graphics.moveTo(xp[0], yp[0]);
for (var i:int = 1; i < xp.length; i++) {
graphics.lineTo(xp[i], yp[i]);
}
graphics.lineStyle(1, 0xff0000);
for (i = 1; i < xp.length-1; i++) {
graphics.drawCircle(xp[i], yp[i], 5);
}
}
public function onUp(e:MouseEvent):void {
selected = -1;
}
public function onMove(e:MouseEvent):void {
if (selected < 1) return;
var px:Number = e.stageX - x;
var py:Number = e.stageY - y;
xp[selected] = Math.min(xp[selected + 1]-1, Math.max(xp[selected - 1]+1, px));
yp[selected] = Math.max(yp[yp.length - 1] - 1, Math.min(yp[0] + 1, py));
graphics.clear();
draw();
isChanged=true;
}
public function onDown(e:MouseEvent):void {
var px:Number = e.stageX - x;
var py:Number = e.stageY - y;
for (var i:int = 0; i < xp.length; i++) {
var len:Number = Math.sqrt(Math.pow(xp[i] - px, 2) + Math.pow(yp[i] - py, 2));
if (len < 10) {
selected = i;
return;
}
}
selected = getId(px);
if (selected < 1) return;
var yy:Number = (yp[selected] - yp[selected - 1]) / (xp[selected] - xp[selected - 1]);
yy = yy * (px - xp[selected - 1]) + yp[selected - 1];
if (Math.abs(yy - py) < 10) {
insetNode(selected, px, py);
}else {
selected = -1;
}
}
private function getId(px:Number):int {
for (var i:int = 1; i < xp.length; i++) {
if (xp[i - 1] < px && xp[i] >= px) {
return i;
}
}
return -1;
}
private function insetNode(id:int, xx:int, yy:int):void {
xp.splice(id, 0, xx);
yp.splice(id, 0, yy);
draw();
}
}
class XYGraph extends MovieClip {
public function XYGraph(w:Number,h:Number):void {
draw(w,h);
}
private function draw(w:Number,h:Number):void {
graphics.lineStyle(2, 0x000000);
graphics.drawRect(0, 0, w, h);
for (var i:int = 1; i < 5; i++) {
var x0:Number = i * 0.2 * h;
dashedLine(x0, 0, x0, h, 1, 5, 0xaaaaaa);
dashedLine(0, x0, w, x0, 1, 5, 0xaaaaaa);
}
}
private function dashedLine(x0:int, y0:int, x1:int, y1:int, w:Number, s:int, color:uint):void {
graphics.lineStyle(w, color);
var lx:Number = x1 - x0;
var ly:Number = y1 - y0;
var dist:Number = Math.sqrt(lx * lx + ly * ly);
var dx:Number = lx / dist;
var dy:Number = ly / dist;
var len:Number = 0;
var px:Number = x0;
var py:Number = y0;
var i:int = 0;
while (true) {
graphics.moveTo(px, py);
px += dx * s;
py += dy * s;
len = len + s;
if (len > dist) break;
if (i++ % 2 == 0) {
graphics.lineTo(px, py);
}
}
}
}
class Histgram extends MovieClip {
public var bmpdata:BitmapData=null;
private var hist:Vector.<int>;
private var _width:int;
private var _height:int;
public function Histgram(w:int,h:int):void {
_width = w;
_height = h;
hist = new Vector.<int>();
}
private function clear():void {
for (var i:int = 0; i < 256; i++) hist[i] = 0;
graphics.clear();
}
public function draw():void {
clear();
graphics.lineStyle(2, 0x000000);
graphics.drawRect(0, 0, _width, _height);
for (var i:int = 0; i < bmpdata.width; i++) {
for (var j:int = 0; j < bmpdata.height; j++) {
var r:int = (bmpdata.getPixel(i, j) & 0xff0000) >> 16;
hist[r]++;
}
}
var max:Number = 0;
for (i = 0; i < 256; i++) if(hist[i]>max)max=hist[i];
max = max * 1.5;
graphics.lineStyle(1, 0x888888);
for (i = 0; i < 256; i++) {
var col:Number = (i / 256.0) * (_width - 2);
var val:Number = (hist[i] / max) * (_height - 2);
graphics.moveTo(col, _height - 1);
graphics.lineTo(col,_height-1-val);
}
}
}