⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cplayer.java

📁 this is best wamp jkbkgnkldjkb jkfbjdksgkjl bjkgsbkjfdb gjdsblkj gbfkjsd
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
	ChibiPaint
    Copyright (c) 2006-2008 Marc Schefer

    This file is part of ChibiPaint.

    ChibiPaint is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    ChibiPaint is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ChibiPaint. If not, see <http://www.gnu.org/licenses/>.

 */

package chibipaint.engine;

import java.util.*;

import chibipaint.util.*;

public class CPLayer extends CPColorBmp {

	public int blendMode = LM_NORMAL, alpha = 100;
	public String name;
	public boolean visible = true;

	public final static int LM_NORMAL = 0;
	public final static int LM_MULTIPLY = 1;
	public final static int LM_ADD = 2;
	public final static int LM_SCREEN = 3;
	public final static int LM_LIGHTEN = 4;
	public final static int LM_DARKEN = 5;
	public final static int LM_SUBTRACT = 6;
	public final static int LM_DODGE = 7;
	public final static int LM_BURN = 8;
	public final static int LM_OVERLAY = 9;
	public final static int LM_HARDLIGHT = 10;
	public final static int LM_SOFTLIGHT = 11;
	public final static int LM_VIVIDLIGHT = 12;
	public final static int LM_LINEARLIGHT = 13;
	public final static int LM_PINLIGHT = 14;

	//
	// Look-Up tables for some of the blend modes
	//

	private static int softLightLUTSquare[];
	private static int softLightLUTSquareRoot[];

	public CPLayer(int width, int height) {
		super(width, height);

		name = new String("");
		clear(0xffffff);

		if (softLightLUTSquare == null) {
			makeLookUpTables();
		}
	}

	public void makeLookUpTables() {

		// V - V^2 table
		softLightLUTSquare = new int[256];
		for (int i = 0; i < 256; i++) {
			double v = i / 255.;
			softLightLUTSquare[i] = (int) ((v - v * v) * 255.);
		}

		// sqrt(V) - V table
		softLightLUTSquareRoot = new int[256];
		for (int i = 0; i < 256; i++) {
			double v = i / 255.;
			softLightLUTSquareRoot[i] = (int) ((Math.sqrt(v) - v) * 255.);
		}
	}

	public void clear() {
		clear(0);
	}

	public void clear(int color) {
		for (int i = 0; i < width * height; i++) {
			data[i] = color;
		}
	}

	public void clear(CPRect r, int color) {
		CPRect rect = new CPRect(0, 0, width, height);
		rect.clip(r);
		for (int j = rect.top; j < rect.bottom; j++) {
			for (int i = rect.left; i < rect.right; i++) {
				data[i + j * width] = color;
			}
		}
	}

	public int[] getData() {
		return data;
	}

	public int getAlpha() {
		return alpha;
	}

	public int getBlendMode() {
		return blendMode;
	}

	public void copyFrom(CPLayer l) {
		name = l.name;
		blendMode = l.blendMode;
		alpha = l.alpha;
		visible = l.visible;

		copyDataFrom(l);

	}

	// Layer blending functions
	//
	// The FullAlpha versions are the ones that work in all cases
	// others need the bottom layer to be 100% opaque but are faster

	public void fusionWith(CPLayer fusion, CPRect r) {
		if (alpha <= 0) {
			return;
		}

		switch (blendMode) {
		case LM_NORMAL:
			if (alpha >= 100) {
				fusionWithNormalNoAlpha(fusion, r);
			} else {
				fusionWithNormal(fusion, r);
			}
			break;

		case LM_MULTIPLY:
			fusionWithMultiply(fusion, r);
			break;

		case LM_ADD:
			fusionWithAdd(fusion, r);
			break;

		case LM_SCREEN:
			fusionWithScreenFullAlpha(fusion, r);
			break;

		case LM_LIGHTEN:
			fusionWithLightenFullAlpha(fusion, r);
			break;

		case LM_DARKEN:
			fusionWithDarkenFullAlpha(fusion, r);
			break;

		case LM_SUBTRACT:
			fusionWithSubtractFullAlpha(fusion, r);
			break;

		case LM_DODGE:
			fusionWithDodgeFullAlpha(fusion, r);
			break;

		case LM_BURN:
			fusionWithBurnFullAlpha(fusion, r);
			break;

		case LM_OVERLAY:
			fusionWithOverlayFullAlpha(fusion, r);
			break;

		case LM_HARDLIGHT:
			fusionWithHardLightFullAlpha(fusion, r);
			break;

		case LM_SOFTLIGHT:
			fusionWithSoftLightFullAlpha(fusion, r);
			break;

		case LM_VIVIDLIGHT:
			fusionWithVividLightFullAlpha(fusion, r);
			break;

		case LM_LINEARLIGHT:
			fusionWithLinearLightFullAlpha(fusion, r);
			break;

		case LM_PINLIGHT:
			fusionWithPinLightFullAlpha(fusion, r);
			break;
		}
	}

	public void fusionWithFullAlpha(CPLayer fusion, CPRect r) {
		if (alpha <= 0) {
			return;
		}

		switch (blendMode) {
		case LM_NORMAL:
			fusionWithNormalFullAlpha(fusion, r);
			break;

		case LM_MULTIPLY:
			fusionWithMultiplyFullAlpha(fusion, r);
			break;

		case LM_ADD:
			fusionWithAddFullAlpha(fusion, r);
			break;

		case LM_SCREEN:
			fusionWithScreenFullAlpha(fusion, r);
			break;

		case LM_LIGHTEN:
			fusionWithLightenFullAlpha(fusion, r);
			break;

		case LM_DARKEN:
			fusionWithDarkenFullAlpha(fusion, r);
			break;

		case LM_SUBTRACT:
			fusionWithSubtractFullAlpha(fusion, r);
			break;

		case LM_DODGE:
			fusionWithDodgeFullAlpha(fusion, r);
			break;

		case LM_BURN:
			fusionWithBurnFullAlpha(fusion, r);
			break;

		case LM_OVERLAY:
			fusionWithOverlayFullAlpha(fusion, r);
			break;

		case LM_HARDLIGHT:
			fusionWithHardLightFullAlpha(fusion, r);
			break;

		case LM_SOFTLIGHT:
			fusionWithSoftLightFullAlpha(fusion, r);
			break;

		case LM_VIVIDLIGHT:
			fusionWithVividLightFullAlpha(fusion, r);
			break;

		case LM_LINEARLIGHT:
			fusionWithLinearLightFullAlpha(fusion, r);
			break;

		case LM_PINLIGHT:
			fusionWithPinLightFullAlpha(fusion, r);
			break;
		}
	}

	public void fusionWithMultiply(CPLayer fusion, CPRect rc) {
		CPRect rect = new CPRect(0, 0, width, height);
		rect.clip(rc);

		for (int j = rect.top; j < rect.bottom; j++) {
			int off = rect.left + j * width;
			for (int i = rect.left; i < rect.right; i++, off++) {
				int color1 = data[off];
				int alpha = (color1 >>> 24) * this.alpha / 100;
				if (alpha == 0) {
					continue;
				} else {
					int color2 = fusion.data[off];
					color1 = color1 ^ 0xffffffff;
					fusion.data[off] = 0xff000000
							| ((color2 >>> 16 & 0xff) - (color1 >>> 16 & 0xff) * (color2 >>> 16 & 0xff) * alpha
									/ (255 * 255)) << 16
							| ((color2 >>> 8 & 0xff) - (color1 >>> 8 & 0xff) * (color2 >>> 8 & 0xff) * alpha
									/ (255 * 255)) << 8
							| ((color2 & 0xff) - (color1 & 0xff) * (color2 & 0xff) * alpha / (255 * 255));
				}
			}
		}
	}

	public void fusionWithNormal(CPLayer fusion, CPRect rc) {
		CPRect rect = new CPRect(0, 0, width, height);
		rect.clip(rc);

		for (int j = rect.top; j < rect.bottom; j++) {
			int off = rect.left + j * width;
			for (int i = rect.left; i < rect.right; i++, off++) {
				int color1 = data[off];
				int alpha = (color1 >>> 24) * this.alpha / 100;
				if (alpha == 0) {
					continue;
				} else if (alpha == 255) {
					fusion.data[off] = color1;
				} else {
					int color2 = fusion.data[off];

					int invAlpha = 255 - alpha;
					fusion.data[off] = 0xff000000
							| (((color1 >>> 16 & 0xff) * alpha + (color2 >>> 16 & 0xff) * invAlpha) / 255) << 16
							| (((color1 >>> 8 & 0xff) * alpha + (color2 >>> 8 & 0xff) * invAlpha) / 255) << 8
							| (((color1 & 0xff) * alpha + (color2 & 0xff) * invAlpha) / 255);
				}
			}
		}
	}

	public void fusionWithNormalNoAlpha(CPLayer fusion, CPRect rc) {
		CPRect rect = new CPRect(0, 0, width, height);
		rect.clip(rc);

		for (int j = rect.top; j < rect.bottom; j++) {
			int off = rect.left + j * width;
			for (int i = rect.left; i < rect.right; i++, off++) {
				int color1 = data[off];
				int alpha = color1 >>> 24;
				if (alpha == 0) {
					continue;
				} else if (alpha == 255) {
					fusion.data[off] = color1;
				} else {
					int color2 = fusion.data[off];

					int invAlpha = 255 - alpha;
					fusion.data[off] = 0xff000000
							| (((color1 >>> 16 & 0xff) * alpha + (color2 >>> 16 & 0xff) * invAlpha) / 255) << 16
							| (((color1 >>> 8 & 0xff) * alpha + (color2 >>> 8 & 0xff) * invAlpha) / 255) << 8
							| (((color1 & 0xff) * alpha + (color2 & 0xff) * invAlpha) / 255);
				}
			}
		}
	}

	public void fusionWithAdd(CPLayer fusion, CPRect rc) {
		CPRect rect = new CPRect(0, 0, width, height);
		rect.clip(rc);

		for (int j = rect.top; j < rect.bottom; j++) {
			int off = rect.left + j * width;
			for (int i = rect.left; i < rect.right; i++, off++) {
				int color1 = data[off];
				int alpha = (color1 >>> 24) * this.alpha / 100;
				if (alpha == 0) {
					continue;
				} else {
					int color2 = fusion.data[off];

					int r = Math.min(255, (color2 >>> 16 & 0xff) + alpha * (color1 >>> 16 & 0xff) / 255);
					int g = Math.min(255, (color2 >>> 8 & 0xff) + alpha * (color1 >>> 8 & 0xff) / 255);
					int b = Math.min(255, (color2 & 0xff) + alpha * (color1 & 0xff) / 255);

					fusion.data[off] = 0xff000000 | r << 16 | g << 8 | b;
				}
			}
		}
	}

	// Normal Alpha Mode
	// C = A*d + B*(1-d) and d = aa / (aa + ab - aa*ab)

	public void fusionWithNormalFullAlpha(CPLayer fusion, CPRect rc) {
		CPRect rect = new CPRect(0, 0, width, height);
		rect.clip(rc);

		for (int j = rect.top; j < rect.bottom; j++) {
			int off = rect.left + j * width;
			for (int i = rect.left; i < rect.right; i++, off++) {
				int color1 = data[off];
				int alpha1 = (color1 >>> 24) * alpha / 100;
				int color2 = fusion.data[off];
				int alpha2 = (color2 >>> 24) * fusion.alpha / 100;

				int newAlpha = alpha1 + alpha2 - alpha1 * alpha2 / 255;
				if (newAlpha > 0) {
					int realAlpha = alpha1 * 255 / newAlpha;
					int invAlpha = 255 - realAlpha;

					fusion.data[off] = newAlpha << 24
							| (((color1 >>> 16 & 0xff) * realAlpha + (color2 >>> 16 & 0xff) * invAlpha) / 255) << 16
							| (((color1 >>> 8 & 0xff) * realAlpha + (color2 >>> 8 & 0xff) * invAlpha) / 255) << 8
							| (((color1 & 0xff) * realAlpha + (color2 & 0xff) * invAlpha) / 255);
				}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -