Export composite to image independent of the screen resolution

孤街醉人 提交于 2019-12-13 20:13:57

问题


Is there a way in SWT to export a composite to an image which always has the same size/resolution? The problem is that we have a Dashboard which looks always different when opening on screens with different display size/resolution. The question is now can I export the Dashboard to an image wich has a fixed size and always looks the same no matter on which screen size/resolution it has been created?

For the time being we do it like that but as said it depends on the display it has been created on:

Image image = new Image(Display.getCurrent(), this.content.getBounds().width, this.content.getBounds().height);
ImageLoader loader = new ImageLoader();
FileOutputStream fileOutputStream = new FileOutputStream(file);

GC gc = new GC(image);
this.content.print(gc);

gc.dispose();

loader.data = new ImageData[] { image.getImageData() };
loader.save(fileOutputStream, imageFormat);
fileOutputStream.close();

Is there for example some way to create a virtual screen with a certain resolution, which isn't actually displayed and only used for exporting the Dashboard? Any help or pointers would be appreciated.


回答1:


In one of my applications I was creating graphs and charts in SWT. The user was able to export these to an image of a size and format that they specified. My solution was to take the GC of the chart composite and redraw it to a new composite off screen, then export the newly drawn composite.

Here's my class which accomplished this:

import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.widgets.Composite;

/**
 * The class used for writing an {@link Composite} to an image file
 * 
 * @author David L. Moffett
 * 
 */
public class CompositeImageWriter
{
  /**
   * Redraws the composite to the desired size off-screen and then writes that
   * composite as an image to the desired location and in the desired format
   * 
   * @param absolutePath
   *          the absolute path to the desired output file
   * @param compositeToDraw
   *          the composite to be written to file as an image
   * @param width
   *          the desired width in pixels that the composite should be redrawn
   *          to
   * @param height
   *          the desired height in pixels that the composite should be redrawn
   *          to
   * @param imageType
   *          an int representing the type of image that should be written
   */
  public static void drawComposite(String absolutePath, Composite compositeToDraw, int width,
      int height, int imageType)
  {
    Image image = new Image(compositeToDraw.getDisplay(), width, height);
    GC gc = new GC(image);
    int originalWidth = compositeToDraw.getBounds().width;
    int originalHeight = compositeToDraw.getBounds().height;
    compositeToDraw.setSize(width, height);
    compositeToDraw.print(gc);
    compositeToDraw.setSize(originalWidth, originalHeight);

    ImageLoader loader = new ImageLoader();
    loader.data = new ImageData[] { image.getImageData() };
    loader.save(absolutePath, imageType);

    image.dispose();
    gc.dispose();
  }
}

For your case of wanting to always export at a specific size, just replace the width and height arguments with appropriate constants.

Edit 1

I should add that the int imageType argument is the corresponding SWT modifier (for example: SWT.IMAGE_PNG, SWT.IMAGE_JPEG, SWT.IMAGE_BMP, etc...).

Edit 2

I updated the static reference to dynamically get the display from the compositeToDraw. Further, here's an example I put together which uses the CompositeImageWriter which you may be able to use to debug your issue:

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;

public class CompositeToWrite extends Composite
{
  private int   width, height;

  private Label l;

  public CompositeToWrite(Composite parent, int style)
  {
    super(parent, style);
    this.setLayout(new GridLayout(1, true));
    this.addListener(SWT.Resize, new Listener()
    {

      @Override
      public void handleEvent(Event event)
      {
        updateText();
      }
    });

    Button b = new Button(this, SWT.NONE);
    b.setText("Export as image (500, 500)");
    b.addListener(SWT.Selection, new Listener()
    {

      @Override
      public void handleEvent(Event event)
      {
        CompositeImageWriter.drawComposite("./img/output.png", CompositeToWrite.this, 500, 500,
            SWT.IMAGE_PNG);
      }
    });

    l = new Label(this, SWT.CENTER);
    GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
    gd.verticalAlignment = SWT.CENTER;
    l.setLayoutData(gd);
    updateText();
  }

  protected void updateText()
  {
    width = this.getBounds().width;
    height = this.getBounds().height;

    l.setText("My label is centered in composite (" + width + ", " + height + ")");
  }

}

In the case of this example I create a simple composite that once added to a shell will look something like this:

When I click the button it resizes the composite to 500 x 500 and writes the resized composite to a file. The result is this picture:

I should note that I did notice the composite flicker when the button is clicked, so this may not be happening completely in the background or "off screen" as I initially suggested.



来源:https://stackoverflow.com/questions/32355656/export-composite-to-image-independent-of-the-screen-resolution

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!