Menu

Smooth Rendering for Java2DRenderer

user
Keith Chew
2007-01-06
2013-05-09
  • Keith Chew

    Keith Chew - 2007-01-06

    Hi

    I have just upgraded to Fobs 0.4, and tried the Java2DRenderer renderer. Previously, I was using Sun's LightWeightRenderer, which gave smooth rendering on repaints, resizes, etc.

    I have modified Java2DRenderer to achieve the same affect (by making it extend JPanel instead of creating a private JPanel variable). Below is the source, have fun!

    Regards
    Keith

    ===============
    public class Java2DRenderer extends JPanel implements VideoRenderer, FrameGrabbingControl  {
       
        private BufferStrategy strategy;

        public Java2DRenderer() {
        }
       
        private RGBFormat vf;
        private Image lastImage = null;
           
        void setValue(Object aValue,boolean isSelected) {
            System.out.println(aValue.getClass().getName());
        }

        public Format[] getSupportedInputFormats() {return new Format[] {new RGBFormat() };}

        public Format setInputFormat(Format format) {
            System.out.println("Fobs Java2DRenderer: setInputFormat");
            FobsConfiguration.videoFrameFormat=FobsConfiguration.RGBA;

            vf = (RGBFormat) format;
            int formatWidth = (int) vf.getSize().getWidth();
            int formatHeight = (int) vf.getSize().getHeight();
           
            this.setPreferredSize(new Dimension(formatWidth,formatHeight));
            return format;
        }

        public void start() {
            System.out.println("Fobs Java2DRenderer: start");
        }

        public void stop() {
            System.out.println("Fobs Java2DRenderer: stop");       
        }

        public int process(Buffer buffer) {
            Graphics2D g2d = (Graphics2D) this.getGraphics();
                       
            if(g2d != null) {
                if(lastImage == null) lastImage = bufferToImage(buffer);
                g2d.drawImage(lastImage, 0, 0, this.getWidth(),this.getHeight(), null);
            }
           
            return BUFFER_PROCESSED_OK;
        }

        protected void paintComponent(Graphics g) {
            g.drawImage(lastImage, 0, 0, this.getWidth(),this.getHeight(), null);
        }

        private BufferedImage bufferToImage(Buffer buffer) {
           RGBFormat format = (RGBFormat) buffer.getFormat();
           int rMask, gMask, bMask;
           Object data = buffer.getData();
           DirectColorModel dcm;

           rMask = format.getRedMask();
           gMask = format.getGreenMask();
           bMask = format.getBlueMask();
           int [] masks = new int[3];
           masks[0] = rMask;
           masks[1] = gMask;
           masks[2] = bMask;

           DataBuffer db = new DataBufferInt((int[])data,
                             format.getLineStride() *
                             format.getSize().height);

           SampleModel sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT,
                                     format.getLineStride(),
                                     format.getSize().height,
                                     masks);
           WritableRaster wr = Raster.createWritableRaster(sm, db, new Point(0, 0));

           dcm = new DirectColorModel(24, rMask, gMask, bMask);
           return new BufferedImage(dcm, wr, true, null);
       }

        public String getName() {
            return "Fobs Java2DRenderer";
        }

        public void open() throws ResourceUnavailableException {
           
        }

        public void close() {
           
           
        }

        public void reset() {
        }

        public Component getComponent() {
            return this;
        }

        public boolean setComponent(Component arg0) {
            return false;
        }

      // support for FrameGrabbingControl
      public Buffer grabFrame() {
        //BufferedImage bufimg = (BufferedImage)FobsConfiguration.properties.get("BufferedImage");
        Buffer buf = ImageToBuffer.createBuffer(lastImage,(float)0);
        return buf;
      }
      
      // No awt component is needed for FrameGrabbingControl
      public Component getControlComponent() {
        return null;
      }
      
      public Object[] getControls() {
        Object[] obj = { this };
        return obj;
      }
      
      public Object getControl(String arg) {
        Object rc = null;
        if(arg.equals("javax.media.control.FrameGrabbingControl")) rc = this;
        return rc;
      }
      // new code-end

       
    }
    ==================

     
    • Jose San Pedro

      Jose San Pedro - 2007-01-10

      Hi,

      the new code has been integrated, with minor modifications, and works like a charm!!! I'll commit changes to the CVS in the next few minutes.

      Thanks very much for your contribution!!!

      Cheers,

      Jose San Pedro

       
      • Keith Chew

        Keith Chew - 2007-01-11

        Hi Jose

        I have also made more modifications to it. It now works if I have a custom codec with the RGBFormat in byte[], the code expects it to be in int []. The key change is in the bufferToImage() method:

            private Image bufferToImage(Buffer buffer) {
               Object data = buffer.getData();
               BufferToImage bufferToImage = new BufferToImage((VideoFormat) buffer.getFormat());
               Image image = bufferToImage.createImage(buffer);
               return image;
            }

        Also in the process(Buffer buffer) method, it should always save the lastImage:
           
            public int process(Buffer buffer) {
              Graphics2D g2d = (Graphics2D) this.getGraphics();
              if(g2d != null) {
                g2d.drawImage(lastImage, 0, 0, this.getWidth(),this.getHeight(), null);
              }
              return BUFFER_PROCESSED_OK;
            }

        Regards
        Keith

         
        • Nobody/Anonymous

          Hi Keith, hi Jose,

          what if the format is a short[]? A cast from short[] to int[] failes.

          I can create a DataBufferShort, but the SinglePixelPackedSampleModel only supports unsigned short (or byte). Is there a fast way to convert the int[] to short[] or byte[]?

          If I use your suggestion from your last post, I get only a black output.

          Regards,
          Peter

           
          • Keith Chew

            Keith Chew - 2007-10-16

            Hi Peter

            If you see my previous post, I suggested using code that was independent of the type. Works for me, did not matter if it was byte[], short[], etc.

            Regards
            Keith

             
    • Keith Chew

      Keith Chew - 2007-10-16

      Hi Peter

      Sorry, I did not read your post properly.

      I am not sure why you are getting a black output with the new method suggested.

      Regards
      Keith

       
    • Nobody/Anonymous

      Hi Keith,

      I think you missed the line

      lastImage = bufferToImage(buffer);

      in your post from 2007-01-10 18:36.

      It should look like

      public int process(Buffer buffer) {

          Graphics2D g2d = (Graphics2D) this.getGraphics();
          if (g2d != null) {
                 
              lastImage = bufferToImage(buffer);
              g2d.drawImage(lastImage, 0, 0, this.getWidth(), this.getHeight(), null);
          }
           return BUFFER_PROCESSED_OK;
      }

      Did anyone tried this Renderer with RTP-DataSource?

      Regards,
      Peter

       
      • Keith Chew

        Keith Chew - 2007-10-20

        Hi Peter

        Ah, not sure how that got missed out, but it has always been in my code.

        Sorry about the mistake, however I did mention in the post that we should *always* save the lastImage.

        Regards
        Keith

         
    • Nobody/Anonymous

      Yes thats true, but this doesn't solve the problem with the black output.

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.