Package net.sf.fmj.media.renderer.video

Source Code of net.sf.fmj.media.renderer.video.SimpleAWTRenderer

package net.sf.fmj.media.renderer.video;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.logging.Logger;

import javax.media.Buffer;
import javax.media.Format;
import javax.media.format.RGBFormat;
import javax.media.format.VideoFormat;
import javax.media.renderer.VideoRenderer;

import net.sf.fmj.media.AbstractVideoRenderer;
import net.sf.fmj.media.util.BufferToImage;
import net.sf.fmj.utility.FPSCounter;
import net.sf.fmj.utility.LoggerSingleton;

/**
*
* The simplest possible AWT Renderer.
* @author Ken Larson
*
*/
public class SimpleAWTRenderer extends AbstractVideoRenderer implements VideoRenderer
{
  private static final Logger logger = LoggerSingleton.logger;
 
  private final Format[] supportedInputFormats = new Format[] {
    //RGB, 32-bit, Masks=16711680:65280:255, LineStride=-1, class [I
    new RGBFormat(null, -1, Format.intArray, -1.0f, 32, 0xff0000, 0xff00, 0xff, 1, -1, 0, -1),
   
    //RGB, 32-bit, Masks=255:65280:16711680, LineStride=-1, class [I
    new RGBFormat(null, -1, Format.intArray, -1.0f, 32, 0xff, 0xff00, 0xff0000, 1, -1, 0, -1),

    new RGBFormat(null, -1, Format.byteArray, -1.0f, 32, 1, 2, 3),

    new RGBFormat(null, -1, Format.byteArray, -1.0f, 32, 3, 2, 1),

    new RGBFormat(null, -1, Format.byteArray, -1.0f, 24, 1, 2, 3),

    new RGBFormat(null, -1, Format.byteArray, -1.0f, 24, 3, 2, 1),

    // rgb565, rgb555, bgr565, bgr555
    new RGBFormat(null, -1, Format.shortArray, -1.0f, 16, -1, -1, -1, 1, -1, 0, -1),

    // rgb8,bgr8
    new RGBFormat(null, -1, Format.byteArray, -1.0f, 8, -1, -1, -1, 1, -1, 0, -1),

  };
 
 
  //@Override
  @Override
  public String getName()
  {
    return "Simple AWT Renderer";
  }


  //@Override
  @Override
  public Format[] getSupportedInputFormats()
  {
    return supportedInputFormats;
  }

  private AwtVideoComponent component = new AwtVideoComponent();
  @Override
  public Component getComponent()
  {  return component;
  }
 
  private Object[] controls = new Object[] {this};
  @Override
  public Object[] getControls()
  {  return controls;
  }

 
  private BufferToImage bufferToImage;
 
  //@Override
  @Override
  public Format setInputFormat(Format format)
  {
//    logger.fine("FORMAT: " + MediaCGUtils.formatToStr(format));
    // TODO: check VideoFormat and compatibility
    bufferToImage = new BufferToImage((VideoFormat) format);
    return super.setInputFormat(format);
  }

  private final FPSCounter fpsCounter = new FPSCounter();

  @Override
  public int doProcess(Buffer buffer)
  {
    if (buffer.isEOM())
    {  logger.warning(this.getClass().getSimpleName() + "passed buffer with EOM flag")// normally not supposed to happen, is it?
      return BUFFER_PROCESSED_OK;
    }
//    if (buffer.isDiscard())
//      return BUFFER_PROCESSED_OK;  // TODO: where do we check for this?
   
    if (buffer.getData() == null)
    {  return BUFFER_PROCESSED_FAILED;    // TODO: check for EOM?
    }
   
   
    java.awt.Image image = bufferToImage.createImage(buffer);
    component.setImage(image);
   
//    fpsCounter.nextFrame();
//    if (fpsCounter.getNumFrames() >= 50)
//    {  System.out.println(fpsCounter);
//      fpsCounter.reset();
//    }
    return BUFFER_PROCESSED_OK;
  }

  /**
   * Component used for rendering video images.
   */
  private class AwtVideoComponent extends Component {
    private Image image;
   
    public void setImage(Image image) {
      this.image = image;
      repaint();
     
    }
   
    @Override
    public Dimension getPreferredSize() {
      if (inputFormat == null) {
        return super.getPreferredSize();
      }
      VideoFormat videoFormat = (VideoFormat) inputFormat;
      return videoFormat.getSize();
    }

    private Rectangle getVideoRect(final boolean scale)
    {
      final int x, y;
      final int w, h;
      final Dimension preferredSize = getPreferredSize();
      final Dimension size = getSize();
     
      if (!scale)
      {
        if (preferredSize.width <= size.width)
        {  x = (size.width - preferredSize.width) / 2;
          w = preferredSize.width;
        }
        else
        x = 0;
          w = preferredSize.width;
        }
       
        if (preferredSize.height <= size.height)
        {  y = (size.height - preferredSize.height) / 2;
          h = preferredSize.height;
        }
        else
        y = 0;
          h = preferredSize.height;
        }
      }
      else
      {
        if (scaleKeepAspectRatio)
        {
          if ((float)size.width  / preferredSize.width < (float)size.height / preferredSize.height) {
            w = size.width;
            h = size.width * preferredSize.height  / preferredSize.width;
            x = 0;
            y = (size.height-h)/2;
          }
          else {
            w = size.height * preferredSize.width / preferredSize.height;
            h = size.height;         
            x = (size.width-w)/2;
            y = 0;
          }
        }
        else
        {
          x = 0;
          y = 0;
          w = size.width;
          h = size.height;
        }
      }
      return new Rectangle(x, y, w, h);
    }
   
    // jmf scales without keeping the aspect ratio, TODO: make scale and scaleKeepAspectRatio accessible by application
    private boolean scaleKeepAspectRatio = false;
    private boolean scale = true;
    private BufferedImage biCompatible;
    @Override
    public void paint(Graphics g) {
      if (image != null) {
        Rectangle rect = getVideoRect(scale);

//        long start = System.currentTimeMillis();
       
        try
        {
          if (biCompatible == null// try drawing directly, unless we already know that won't work (biCompatible is set)
          g.drawImage(image, rect.x, rect.y, rect.width, rect.height, null);
            return;
          }
        }
        catch (java.awt.image.ImagingOpException e)
        {
          // some images do not seem to be able to be scaled directly.
          // this appears to only happen when the image has a ComponentColorModel.
          // the graphics destination appears to use a DirectColorModel, and for scaling,
          // they are incompatible.  Civil uses ComponentColorModel in many cases, so
          // this is generally when we have this problem.
         
          // fall through and convert manually.
         
          // no idea why AWT/Java2d doesn't just do this for us behind the scenes.
        }
       
        getCompatibleBufferedImage();
        biCompatible.getGraphics().drawImage(image, 0, 0, image.getWidth(null), image.getHeight(null), null);
         
        g.drawImage(biCompatible, rect.x, rect.y, rect.width, rect.height, null);

      }
//      else {
//        Dimension size = getSize();
//        g.setColor(getBackground());
//        g.fillRect(0, 0, size.width, size.height);
//      }
    }
   
    private BufferedImage getCompatibleBufferedImage()
    {
      if (biCompatible == null || biCompatible.getWidth() != image.getWidth(null) || biCompatible.getHeight() != image.getHeight(null))
        biCompatible = this.getGraphicsConfiguration().createCompatibleImage(image.getWidth(null), image.getHeight(null));
      return biCompatible;
    }
   
    @Override
    public void update(Graphics g) {
      paint(g);
    }
  }



}
TOP

Related Classes of net.sf.fmj.media.renderer.video.SimpleAWTRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.