c't

c't-Projekte - Mailinglisten


[Voriger (Datum)] [Nächster (Datum)] [Voriger (Thread)] [Nächster (Thread)]
[Nach Datum][Nach Thread]

Re: AW: [ct-bot] Fotorealistisches LCDisplay

Absender: Stefan Geuken
Datum: Sa, 11.03.2006 14:27:57
In-reply-to: <BHEJINDCHHECOCOALILGEEMJCFAA.rl@xxxxxxxxxx>
References: <BHEJINDCHHECOCOALILGEEMJCFAA.rl@xxxxxxxxxx>


Hallo Ralf,

ja, Danke. Ich habe das jetzt eingebaut, das klappt!

Nochmal ein paar Anmerkungen:
- Ich habe in die Paint-Methode eine Zeitmessung eingebaut. Die neue Methode mit dem PNG scheint doppelt so schnell zu sein wie die alte. - Mit der neuen Methodik werden aber die oberen GUI-Elemente des ct-Panels nicht mehr immer korrekt gezeichnet. Die Buttons z.B. werden erst gezeichnet, wenn man mit der Maus drüber fährt. Weisst Du, wie das kommt? - Im Taskmamager ist der Prozessor bei laufenden Sim immer zu 100% ausgelastet. Das ist er allerdings auch völlig ohne LCDisplay. Ist das normal bzw. bei Dir auch so?

Die neue Klasse habe ich mal angehängt, das Bild geht ja leider nicht, aber ich erstelle einfach mal einen Patch und stelle in auf ctbot.de zur Verfügung...

Gruß
Stefan


Ralf Löhmer schrieb:
Hallo,
nochmal wg. Transparenz.
Vielleicht hilft der Anhang weiter.
rl

-----Ursprüngliche Nachricht-----
Von: ct-bot-entwickler-bounces@xxxxxxxxxxxxxxxxx
[mailto:ct-bot-entwickler-bounces@xxxxxxxxxxxxxxxxx]Im Auftrag von
Stefan Geuken
Gesendet: Donnerstag, 9. März 2006 22:33
An: ct-bot-entwickler@xxxxxxxxxxxxxxxxx
Betreff: [ct-bot] Fotorealistisches LCDisplay


Hallo,

ich experimentiere gerade mit meiner LCDisplay-Komponente
(http://www.ctbot.de/index.php?page=4&action=file&file_id=41). Ich habe
den ganzen Characterset jetzt in eine PNG-Datei gepackt (16x16 Zeichen,
bestehend aus schwarzen und weißen Pixeln) und ziehe mit Hilfe der
Klassen java.awt.image.PixelGrabber und java.awt.image.MemoryImageSource
den für jedes Zeichen richtigen Bereich aus der PNG-Datei raus. Das
klappt soweit auch.
Was ich nicht hingekomme ist, daß die weißen Pixel transparent
gezeichnet werden. Die bleiben weiß, obwohl ich im PNG die Farbe weiß
als transparent abgespeichert habe. Kann mir jemand einen Tipp geben,
wie man ein Bild mit transparenten Farben malen kann!?

Gruß
Stefan
_______________________________________________
ct-bot-entwickler Mailingliste
ct-bot-entwickler@xxxxxxxxxxxxxxxxx
http://www.heise.de/bin/newsletter/listinfo/ct-bot-entwickler

____________
Virus checked by G DATA AntiVirusKit
Version: AVK 16.5906 from 04.03.2006


__________ NOD32 1.1439 (20060311) Information __________

Diese E-Mail wurde vom NOD32 antivirus system geprüft
http://www.nod32.com

------------------------------------------------------------------------

14.12.4 Transparenz  Quelle: Java ist auch eine Insel, C. Ullenboom

Um eine bestimmte Farbe eines Bilds durchsichtig zu machen (also die Transparenz zu bestimmen), nutzen wir einen RGBImageFilter. Dabei implementieren wir einen Konstruktor, der die Farbe sichert, die transparent werden soll. Sie wird später in der Implementierung von filterRGB() verwendet. Die Methode, die ja für jeden Bildpunkt aufgerufen wird, liefert dann entweder die Farbe ohne Alpha-Kanal zurück (rgb|0xff000000) oder eben nur den Alpha-Kanal (rgb&0xffffff) für Transparenz. Eine interessante Erweiterung ist die Einführung einer Toleranzauswertung um einen »Zauberstab«, der ähnlich wie in Photoshop zu realisieren ist.

Listing 14.26   TransparentFilter.java


import java.awt.*;
import java.awt.image.*;

public class TransparentFilter extends RGBImageFilter
{
  public TransparentFilter( Color color )
  {
    this.color = color.getRGB();
  }

  public int filterRGB( int x, int y, int rgb )
  {
    if ( rgb != color )
      return rgb | 0xff000000;
    else
      return rgb & 0xffffff;    //transparent
  }

  private int color;
}
------------------------------------------------------------------------

_______________________________________________
ct-bot-entwickler Mailingliste
ct-bot-entwickler@xxxxxxxxxxxxxxxxx
http://www.heise.de/bin/newsletter/listinfo/ct-bot-entwickler

__________ NOD32 1.1439 (20060311) Information __________

Diese E-Mail wurde vom NOD32 antivirus system geprüft
http://www.nod32.com


package ctSim.View.LCDisplay;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageProducer;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import java.awt.image.RGBImageFilter;

import javax.swing.JPanel;

/**
 * Abstrakte LCDisplay-Komponente, die den Display-Text als einzelne Pixel
 * malt. Der Text besteht aus Zeilen und Spalten. Es werden nur die Zeichen
 * gezeichnet, die innerhalb der Dimension (Anzahl Zeilen/Spalten) des 
 * Displays liegen. Die Größe eines einzelnen Pixels bestimmt die Gesamtgröße
 * des Displays. Der gewählte Zeichensatz bestimmt das Aussehen der Zeichen.
 * 
 * @author Stefan Geuken (mail@xxxxxxxxxxxxxxxx)
 *
 */
public abstract class LCDisplay
  extends JPanel
{
  protected static final int CHARPIXELS_X = 5;
  protected static final int CHARPIXELS_Y = 8;  
  
  protected static final int GAPIXELS_X = 1;
  protected static final int GAPPIXELS_Y = 1;
  
  protected Color foregroundColor = Color.BLACK;
  protected Image charset;
  protected static final String DEFAULTIMAGE = "ctSim/View/LCDisplay/charsetA02.png";
  protected String[] text;
  
  protected int dotSize = 1;
  protected int rows = 0;
  protected int columns = 0;
  
  protected PixelGrabber grabber;
  protected int[] pix;
  
  /**
   * Erzeugt ein LCDisplay, prüft und initialisiert die lokalen Variablen.
   * 
   * @param dotSize
   *            Größe eines Pixels (>= 1)
   * @param rows
   *            Anzahl der Zeilen des Displays (>=0)
   * @param columns
   *            Anzahl der Zeichen einer einzelnen Displayzeile (>=0)
   * @param foregroundColor
   *            Farbe, in der die Zeichen gemalt werden. Wenn null, dann wird der Standardwert verwendet
   * @param charset
   *            Zeichensatz der zum Zeichnen der Zeichen verwendet wird. Wenn null, dann wird der Standardwert verwendet
   */
  public LCDisplay(int dotSize, int rows, int columns, Color foregroundColor, Image charset)
  {
    if (dotSize >= 1) {
      this.dotSize = dotSize;
    }
    
    if (rows >= 0) {
      this.rows = rows;
    }
    
    if (columns >= 0) {
      this.columns = columns;
    }
    
    text = new String[rows];
    
    if (foregroundColor != null) {
      this.foregroundColor = foregroundColor;
    }
    if (charset == null) {
      this.charset = this.getToolkit().getImage(ClassLoader.getSystemResource(DEFAULTIMAGE));
    }
    else {
      this.charset = charset;
    }
    
    pix = new int[(16*CHARPIXELS_X+15*1) * (16*CHARPIXELS_Y+15*1)];
    TransparentFilter filter = new TransparentFilter(Color.WHITE);
    ImageProducer producer = new FilteredImageSource(this.charset.getSource(), filter);
    Image filteredCharset = this.createImage(producer);
    grabber = new PixelGrabber(filteredCharset, 0, 0, 16*CHARPIXELS_X+15*1, 16*CHARPIXELS_Y+15*1, pix, 0, 16*CHARPIXELS_X+15*1);
    try {
      grabber.grabPixels();
    }
    catch( InterruptedException e ) {}
  }
  
  protected abstract int getXPosText();
  protected abstract int getYPosText();
  
  /**
   * Setzt den Text einer Displayzeile.
   * 
   * @param row
   *            Zeile des Displays (>= 0 und <= ANzhal der Zeilen)
   * @param text
   *            Text, der in der Zeile erscheinen soll. Wenn null, dann wird die Zeile gelöscht
   */
  public void setText(int row, String text)
  {
    if (row >= 0 && row <= this.rows) {
      this.text[row] = text;
    }
  }
  
  long gemesseneZeit = 0;
  int durchlaeufe = 0;
  
  /**
   * Zeichnet den gesamten Text des Displays in der gewählten Farbe.
   * 
   * @param g
   *            Graphics-Context, auf das gezeichnet wird
   */
  protected void drawText(Graphics g)
  {
//    long t1 = System.currentTimeMillis();
    
    g.setColor(foregroundColor);

    for (int y=0; y<this.rows; y++) {
      for (int x=0; x<this.columns; x++) {
        if (this.text[y] != null) {
          if (x < this.text[y].length()) {
            this.drawCharacter(g, x, y, text[y].charAt(x));
          }
        }
      }
    }
    
//    long t2 = System.currentTimeMillis();
//    
//    gemesseneZeit += (t2-t1);
//    durchlaeufe++;
//    if (durchlaeufe == 1000) {
//      System.out.println("Zeit: " + gemesseneZeit);
//      gemesseneZeit = 0;
//      durchlaeufe = 0;
//    }
  }
  
  /**
   * Zeichnet ein Zeichen auf das Display.
   * 
   * @param g
   *            Graphics-Context, auf das gezeichnet wird
   * @param xPos
   *            x-Position des Displays (Spalte), an der das Zeichen gezeichnet wird
   * @param yPos
   *            y-Position des Displays (Zeile), an der das Zeichen gezeichnet wird
   * @param c
   *            Das Zeichen, das gezeichnet wird
   */
  protected void drawCharacter(Graphics g, int xPos, int yPos, char c)
  {
    int imgX = (c / 16)*(CHARPIXELS_X+1);
    int imgY = (c % 16)*(CHARPIXELS_Y+1);
    
    Image newImg = this.createImage(new MemoryImageSource(CHARPIXELS_X, CHARPIXELS_Y, pix, imgX+imgY*(16*CHARPIXELS_X+15*1), 16*CHARPIXELS_X+15*1));
    
    g.drawImage(newImg, 
      this.getXPosText() + xPos*(CHARPIXELS_X+GAPIXELS_X)*this.dotSize, 
      this.getYPosText() + yPos*(CHARPIXELS_Y+GAPPIXELS_Y)*this.dotSize,
      this);
  }
  
  public class TransparentFilter 
    extends RGBImageFilter
  {
    private int color;
    
    public TransparentFilter( Color color )
    {
      this.color=color.getRGB();
    }
    
    public int filterRGB( int x, int y, int rgb )
    {
      if ( rgb != color )
        return rgb | 0xff000000;
      else
        return rgb & 0xffffff;    //transparent
    }
  }
}