mirror of
https://github.com/OMGeeky/ATCS.git
synced 2025-12-26 23:57:25 +01:00
Implemented all colorfilters in TMXMapEditor, thanks to the new
MatrixComposite that really emulates the ColorMatrixColorFilter of Android ! Hi-fidelity filter emulation !
This commit is contained in:
@@ -44,7 +44,10 @@ public class TMXMap extends GameDataElement {
|
||||
black60,
|
||||
black80,
|
||||
invert,
|
||||
bw
|
||||
bw,
|
||||
redtint,
|
||||
greentint,
|
||||
bluetint
|
||||
}
|
||||
|
||||
public File tmxFile = null;
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.gpl.rpg.atcontentstudio.ui.map;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
@@ -10,7 +11,6 @@ import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyAdapter;
|
||||
@@ -19,13 +19,7 @@ import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseMotionAdapter;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
import java.awt.image.BandCombineOp;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ByteLookupTable;
|
||||
import java.awt.image.ColorConvertOp;
|
||||
import java.awt.image.LookupOp;
|
||||
import java.awt.image.LookupTable;
|
||||
import java.awt.image.ShortLookupTable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -108,6 +102,7 @@ import com.gpl.rpg.atcontentstudio.ui.Editor;
|
||||
import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener;
|
||||
import com.gpl.rpg.atcontentstudio.ui.IntegerBasedCheckBox;
|
||||
import com.gpl.rpg.atcontentstudio.ui.ScrollablePanel;
|
||||
import com.gpl.rpg.atcontentstudio.ui.tools.MatrixComposite;
|
||||
import com.jidesoft.swing.JideBoxLayout;
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
|
||||
@@ -1473,37 +1468,101 @@ public class TMXMapEditor extends Editor {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (map.colorFilter != null) {
|
||||
Composite oldComp = g2d.getComposite();
|
||||
MatrixComposite newComp = null;
|
||||
float f=0.0f;
|
||||
switch(map.colorFilter) {
|
||||
case black20:
|
||||
g2d.setPaint(new Color(0f, 0f, 0f, 0.2f));
|
||||
g2d.fill(clip);
|
||||
f=0.8f;
|
||||
newComp = new MatrixComposite(new float[]{
|
||||
f, 0.00f, 0.00f, 0.0f, 0.0f,
|
||||
0.00f, f, 0.00f, 0.0f, 0.0f,
|
||||
0.00f, 0.00f, f, 0.0f, 0.0f,
|
||||
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
|
||||
});
|
||||
break;
|
||||
case black40:
|
||||
g2d.setPaint(new Color(0f, 0f, 0f, 0.4f));
|
||||
g2d.fill(clip);
|
||||
f=0.6f;
|
||||
newComp = new MatrixComposite(new float[]{
|
||||
f, 0.00f, 0.00f, 0.0f, 0.0f,
|
||||
0.00f, f, 0.00f, 0.0f, 0.0f,
|
||||
0.00f, 0.00f, f, 0.0f, 0.0f,
|
||||
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
|
||||
});
|
||||
break;
|
||||
case black60:
|
||||
g2d.setPaint(new Color(0f, 0f, 0f, 0.6f));
|
||||
g2d.fill(clip);
|
||||
f=0.4f;
|
||||
newComp = new MatrixComposite(new float[]{
|
||||
f, 0.00f, 0.00f, 0.0f, 0.0f,
|
||||
0.00f, f, 0.00f, 0.0f, 0.0f,
|
||||
0.00f, 0.00f, f, 0.0f, 0.0f,
|
||||
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
|
||||
});
|
||||
break;
|
||||
case black80:
|
||||
g2d.setPaint(new Color(0f, 0f, 0f, 0.8f));
|
||||
g2d.fill(clip);
|
||||
f=0.2f;
|
||||
newComp = new MatrixComposite(new float[]{
|
||||
f, 0.00f, 0.00f, 0.0f, 0.0f,
|
||||
0.00f, f, 0.00f, 0.0f, 0.0f,
|
||||
0.00f, 0.00f, f, 0.0f, 0.0f,
|
||||
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
|
||||
});
|
||||
break;
|
||||
case bw:
|
||||
newComp = new MatrixComposite(new float[]{
|
||||
0.33f, 0.59f, 0.11f, 0.0f, 0.0f,
|
||||
0.33f, 0.59f, 0.11f, 0.0f, 0.0f,
|
||||
0.33f, 0.59f, 0.11f, 0.0f, 0.0f,
|
||||
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
|
||||
});
|
||||
break;
|
||||
case invert:
|
||||
newComp = new MatrixComposite(new float[]{
|
||||
-1.00f, 0.00f, 0.00f, 0.0f, 255.0f,
|
||||
0.00f, -1.00f, 0.00f, 0.0f, 255.0f,
|
||||
0.00f, 0.00f, -1.00f, 0.0f, 255.0f,
|
||||
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
|
||||
});
|
||||
break;
|
||||
case redtint:
|
||||
newComp = new MatrixComposite(new float[]{
|
||||
1.20f, 0.20f, 0.20f, 0.0f, 25.0f,
|
||||
0.00f, 0.80f, 0.00f, 0.0f, 0.0f,
|
||||
0.00f, 0.00f, 0.80f, 0.0f, 0.0f,
|
||||
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
|
||||
});
|
||||
break;
|
||||
case greentint:
|
||||
newComp = new MatrixComposite(new float[]{
|
||||
0.85f, 0.00f, 0.00f, 0.0f, 0.0f,
|
||||
0.15f, 1.15f, 0.15f, 0.0f, 15.0f,
|
||||
0.00f, 0.00f, 0.85f, 0.0f, 0.0f,
|
||||
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
|
||||
});
|
||||
break;
|
||||
case bluetint:
|
||||
newComp = new MatrixComposite(new float[]{
|
||||
0.70f, 0.00f, 0.00f, 0.0f, 0.0f,
|
||||
0.00f, 0.70f, 0.00f, 0.0f, 0.0f,
|
||||
0.30f, 0.30f, 1.30f, 0.0f, 40.0f,
|
||||
0.00f, 0.00f, 0.00f, 1.0f, 0.0f
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
if (newComp != null) {
|
||||
g2d.setComposite(newComp);
|
||||
g2d.setPaint(new Color(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
g2d.fill(clip);
|
||||
g2d.setComposite(oldComp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Draw each object map layer
|
||||
// Draw each map object layer
|
||||
boolean paintSelected = false;
|
||||
for (tiled.core.MapLayer layer : ((TMXMap)target).tmxMap) {
|
||||
if (layer instanceof tiled.core.ObjectGroup && layer.isVisible()) {
|
||||
|
||||
124
src/com/gpl/rpg/atcontentstudio/ui/tools/MatrixComposite.java
Normal file
124
src/com/gpl/rpg/atcontentstudio/ui/tools/MatrixComposite.java
Normal file
@@ -0,0 +1,124 @@
|
||||
package com.gpl.rpg.atcontentstudio.ui.tools;
|
||||
|
||||
import java.awt.Composite;
|
||||
import java.awt.CompositeContext;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
|
||||
/**
|
||||
* This Composite emulates the behaviour of Android's ColorMatrixColorFilter,
|
||||
* except that you have to use this one a posteriori instead of a filtering paint.
|
||||
*
|
||||
* It applies a ColorMatrix to the destination pixels, regardless of potential "source" pixels.
|
||||
* Once created and activated through Graphics2D.setComposite(), just paint anything over the pixels you want "filtered".
|
||||
*
|
||||
* Works on a per-pixel basis, no sampling of surrounding pixels, or anything.
|
||||
*
|
||||
* @author pochat
|
||||
*
|
||||
*/
|
||||
public class MatrixComposite implements Composite {
|
||||
|
||||
|
||||
final float[] matrix = new float[20];
|
||||
|
||||
|
||||
/**
|
||||
* Dismisses the source pixels. Just paint it black, or white, it only affects the dest RGB with the following formulae.
|
||||
*
|
||||
* R' = a*R + b*G + c*B + d*A + e;
|
||||
* G' = f*R + g*G + h*B + i*A + j;
|
||||
* B' = k*R + l*G + m*B + n*A + o;
|
||||
* A' = p*R + q*G + r*B + s*A + t;
|
||||
*
|
||||
* @param matrix a flat float[20] array, giving the a..t values;
|
||||
*/
|
||||
public MatrixComposite(float[] matrix) {
|
||||
if (matrix.length != this.matrix.length) {
|
||||
throw new Error("MatrixComposite matrix must be of length "+this.matrix.length);
|
||||
}
|
||||
System.arraycopy(matrix, 0, this.matrix, 0, this.matrix.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeContext createContext(ColorModel srcColorModel,
|
||||
ColorModel dstColorModel, RenderingHints hints) {
|
||||
return new MatrixCompositeContext(this);
|
||||
}
|
||||
|
||||
class MatrixCompositeContext implements CompositeContext {
|
||||
|
||||
MatrixComposite composite;
|
||||
|
||||
public MatrixCompositeContext(MatrixComposite composite) {
|
||||
this.composite = composite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
|
||||
if (src.getSampleModel().getDataType() != DataBuffer.TYPE_INT ||
|
||||
dstIn.getSampleModel().getDataType() != DataBuffer.TYPE_INT ||
|
||||
dstOut.getSampleModel().getDataType() != DataBuffer.TYPE_INT) {
|
||||
throw new IllegalStateException(
|
||||
"Source and destination must store pixels as INT.");
|
||||
}
|
||||
|
||||
int width = Math.min(src.getWidth(), dstIn.getWidth());
|
||||
int height = Math.min(src.getHeight(), dstIn.getHeight());
|
||||
|
||||
float alpha = 1.0f;
|
||||
|
||||
int[] srcPixel = new int[4];
|
||||
int[] dstPixel = new int[4];
|
||||
int[] srcPixels = new int[width];
|
||||
int[] dstPixels = new int[width];
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
src.getDataElements(0, y, width, 1, srcPixels);
|
||||
dstIn.getDataElements(0, y, width, 1, dstPixels);
|
||||
for (int x = 0; x < width; x++) {
|
||||
// pixels are stored as INT_ARGB
|
||||
// our arrays are [R, G, B, A]
|
||||
int pixel = srcPixels[x];
|
||||
srcPixel[0] = (pixel >> 16) & 0xFF;
|
||||
srcPixel[1] = (pixel >> 8) & 0xFF;
|
||||
srcPixel[2] = (pixel ) & 0xFF;
|
||||
srcPixel[3] = (pixel >> 24) & 0xFF;
|
||||
|
||||
pixel = dstPixels[x];
|
||||
dstPixel[0] = (pixel >> 16) & 0xFF;
|
||||
dstPixel[1] = (pixel >> 8) & 0xFF;
|
||||
dstPixel[2] = (pixel ) & 0xFF;
|
||||
dstPixel[3] = (pixel >> 24) & 0xFF;
|
||||
|
||||
int[] result = applyMatrix(matrix, dstPixel);
|
||||
|
||||
// mixes the result with the opacity
|
||||
dstPixels[x] = ((int) (dstPixel[3] + (result[3] - dstPixel[3]) * alpha) & 0xFF) << 24 |
|
||||
((int) (dstPixel[0] + (result[0] - dstPixel[0]) * alpha) & 0xFF) << 16 |
|
||||
((int) (dstPixel[1] + (result[1] - dstPixel[1]) * alpha) & 0xFF) << 8 |
|
||||
(int) (dstPixel[2] + (result[2] - dstPixel[2]) * alpha) & 0xFF;
|
||||
}
|
||||
dstOut.setDataElements(0, y, width, 1, dstPixels);
|
||||
}
|
||||
}
|
||||
|
||||
private int[] applyMatrix(float[] matrix, int[] dstPixel) {
|
||||
int[] result = new int[4];
|
||||
result[0] = Math.max(0, Math.min(255, (int) (matrix[ 0] * dstPixel[0] + matrix[ 1] * dstPixel[1] + matrix[ 2] * dstPixel[2] + matrix[ 3] * dstPixel[3] + matrix[ 4]) ));
|
||||
result[1] = Math.max(0, Math.min(255, (int) (matrix[ 5] * dstPixel[0] + matrix[ 6] * dstPixel[1] + matrix[ 7] * dstPixel[2] + matrix[ 8] * dstPixel[3] + matrix[ 9]) ));
|
||||
result[2] = Math.max(0, Math.min(255, (int) (matrix[10] * dstPixel[0] + matrix[11] * dstPixel[1] + matrix[12] * dstPixel[2] + matrix[13] * dstPixel[3] + matrix[14]) ));
|
||||
result[3] = Math.max(0, Math.min(255, (int) (matrix[15] * dstPixel[0] + matrix[16] * dstPixel[1] + matrix[17] * dstPixel[2] + matrix[18] * dstPixel[3] + matrix[19]) ));
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user