将合成导出为独立于屏幕分辨率的图像

Export composite to image independent of the screen resolution

在 SWT 中有没有办法将合成导出到始终具有相同 size/resolution 的图像?问题是我们有一个仪表板,当在具有不同显示 size/resolution 的屏幕上打开时,它看起来总是不同的。现在的问题是,我能否将 Dashboard 导出为具有固定大小且无论在哪个屏幕上创建都始终看起来相同的图像?size/resolution?

目前我们是这样做的,但如前所述,这取决于创建它的显示器:

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

例如,是否有某种方法可以创建具有特定分辨率的虚拟屏幕,该屏幕实际上并未显示,仅用于导出仪表板? 任何帮助或指点将不胜感激。

在我的一个应用程序中,我使用 SWT 创建图形和图表。用户能够将这些导出为他们指定的大小和格式的图像。我的解决方案是获取图表合成的 GC 并将其重新绘制到屏幕外的新合成,然后导出新绘制的合成。

这是我的 class 完成的:

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

对于您想要始终以特定尺寸导出的情况,只需将宽度和高度参数替换为适当的常量即可。

编辑 1

我应该补充一点,int imageType 参数是相应的 SWT 修饰符(例如:SWT.IMAGE_PNGSWT.IMAGE_JPEGSWT.IMAGE_BMP 等...)。

编辑 2

我更新了静态引用以从 compositeToDraw 动态获取显示。此外,这是我放在一起的一个示例,它使用 CompositeImageWriter,您可以使用它来调试问题:

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 + ")");
  }

}

在这个例子中,我创建了一个简单的组合,一旦添加到 shell 中,它看起来像这样:

当我单击该按钮时,它会将合成图像的大小调整为 500 x 500,并将调整后的合成图像写入文件。结果是这张图:

我应该注意到,我确实注意到单击按钮时复合闪烁,因此这可能不会完全在后台发生,或者 "off screen" 正如我最初建议的那样。