2009-03-12 6 views
4

J'ai deux objets javax.swing.Icon différents et je veux créer une nouvelle icône qui est le composite de ces deux. Je veux que le composite soit un effet MULTIPLY, similaire à ce que vous obtiendriez dans n'importe quelle application de retouche d'image comme Photoshop lorsque vous choisissez cette option. Plus précisément, par chaque pixel, si vous avez la couleur Ca et Cb de l'image 1 et de l'image respectivementComment effectuer un effet composite MULTIPLY en utilisant Graphics2D

Ca = (Ra, Ga, Ba) Cb = (Rb, Gb, Bb)

i veulent sortie être

Cc = (Ra Rb, Ga Gb, Ba * Bb)

Je veux le faire à la volée (en temps réel), donc je dois le faire en utilisant uniquement des opérations Graphics2D . J'ai regardé AlphaComposite et ne vois pas que cela peut être fait. Quelqu'un a des idées?

+0

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

Répondre

0

É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(); 

} 
Questions connexes