Étant donné que la plupart des réponses à cette question indiquent un grand nombre de ressources hors site, j'ai pensé que je fournirais une implémentation complète ici. C'est essentiellement la même que les grandes bibliothèques de modes de fusion que vous avez pu voir, mais j'ai enlevé l'abstraction dans le seul but de mettre en œuvre le mode de fusion spécifique.
Quelques notes sur le code ci-dessous:
simplement utiliser g.setComposite(MultiplyComposite.Multiply)
La classe MultiplyComposite
implémente Composite
et CompositeContext
puisque pour mes besoins il n'y a rien d'autre entre les deux. Si vous avez un mode de fusion où les paramètres peuvent être ajustés ou le mélange s'applique différemment, vous devrez implémenter les deux classes séparément.
Ce code fonctionne uniquement sur les tampons "entiers" de 32 bits. Vous devez modifier ceci pour travailler avec la couleur 16 bits (décalage et masquage pour 5/6 bits au lieu de 8)
Ce code fonctionne avec le dernier octet comme canal alpha. Vous devrez modifier le code pour travailler avec des données sans canal alpha (24 bits).
Le décalage vers la droite de 8 dans la méthode mixPixel
est un moyen rapide de diviser par 256. ex. (a * b) >> 8
au lieu de (a * b)/256
Les pixels sont traités une ligne à la fois, de gauche à droite. Si vous avez plus de mémoire, vous pouvez le modifier pour traiter le tampon entier en une fois.
public class MultiplyComposite implements Composite, CompositeContext {
protected void checkRaster(Raster r) {
if (r.getSampleModel().getDataType() != DataBuffer.TYPE_INT) {
throw new IllegalStateException("Expected integer sample type");
}
}
@Override
public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
checkRaster(src);
checkRaster(dstIn);
checkRaster(dstOut);
int width = Math.min(src.getWidth(), dstIn.getWidth());
int height = Math.min(src.getHeight(), dstIn.getHeight());
int x, y;
int[] srcPixels = new int[width];
int[] dstPixels = new int[width];
for (y=0; y < height; y++) {
src.getDataElements(0, y, width, 1, srcPixels);
dstIn.getDataElements(0, y, width, 1, dstPixels);
for (x=0; x < width; x++) {
dstPixels[x] = mixPixel(srcPixels[x], dstPixels[x]);
}
dstOut.setDataElements(0, y, width, 1, dstPixels);
}
}
private static int mixPixel(int x, int y) {
int xb = (x) & 0xFF;
int yb = (y) & 0xFF;
int b = (xb * yb)/255;
int xg = (x >> 8) & 0xFF;
int yg = (y >> 8) & 0xFF;
int g = (xg * yg)/255;
int xr = (x >> 16) & 0xFF;
int yr = (y >> 16) & 0xFF;
int r = (xr * yr)/255;
int xa = (x >> 24) & 0xFF;
int ya = (y >> 24) & 0xFF;
int a = Math.min(255, xa + ya);
return (b) | (g << 8) | (r << 16) | (a << 24);
}
@Override
public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints) {
return this;
}
@Override
public void dispose() {
}
public static final MultiplyComposite Multiply = new MultiplyComposite();
}
Avez-vous déjà regardé le contenu de java.awt.image? Y a-t-il une raison pour laquelle BufferedImageFilter et BufferedImageOp ne sont pas appropriés? – DJClayworth