blob: bae1270cc3b26d64e23dcac80968b22fc74511bb [file] [log] [blame]
package com.android.hierarchyviewer.ui;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.RawImage;
import com.android.hierarchyviewer.scene.ViewNode;
import com.android.hierarchyviewer.ui.util.IconLoader;
import com.android.hierarchyviewer.ui.util.PngFileFilter;
import com.android.hierarchyviewer.util.WorkerThread;
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
class ScreenViewer extends JPanel implements ActionListener {
private final Workspace workspace;
private final IDevice device;
private GetScreenshotTask task;
private BufferedImage image;
private int[] scanline;
private volatile boolean isLoading;
private BufferedImage overlay;
private AlphaComposite overlayAlpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
private ScreenViewer.LoupeStatus status;
private ScreenViewer.LoupeViewer loupe;
private ScreenViewer.Crosshair crosshair;
private int zoom = 8;
private int y = 0;
private Timer timer;
private ViewNode node;
private JSlider zoomSlider;
ScreenViewer(Workspace workspace, IDevice device, int spacing) {
setLayout(new GridBagLayout());
setOpaque(false);
this.workspace = workspace;
this.device = device;
timer = new Timer(5000, this);
timer.setInitialDelay(0);
timer.setRepeats(true);
JPanel panel = buildViewerAndControls();
add(panel, new GridBagConstraints(0, 0, 1, 1, 0.3f, 1.0f,
GridBagConstraints.FIRST_LINE_START, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 0), 0, 0));
JPanel loupePanel = buildLoupePanel(spacing);
add(loupePanel, new GridBagConstraints(1, 0, 1, 1, 0.7f, 1.0f,
GridBagConstraints.FIRST_LINE_START, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 0), 0, 0));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
timer.start();
}
});
}
private JPanel buildLoupePanel(int spacing) {
loupe = new LoupeViewer();
loupe.addMouseWheelListener(new WheelZoomListener());
CrosshairPanel crosshairPanel = new CrosshairPanel(loupe);
JPanel loupePanel = new JPanel(new BorderLayout());
loupePanel.add(crosshairPanel);
status = new LoupeStatus();
loupePanel.add(status, BorderLayout.SOUTH);
loupePanel.setBorder(BorderFactory.createEmptyBorder(0, spacing, 0, 0));
return loupePanel;
}
private class WheelZoomListener implements MouseWheelListener {
public void mouseWheelMoved(MouseWheelEvent e) {
if (zoomSlider != null) {
int val = zoomSlider.getValue();
val -= e.getWheelRotation() * 2;
zoomSlider.setValue(val);
}
}
}
private JPanel buildViewerAndControls() {
JPanel panel = new JPanel(new GridBagLayout());
crosshair = new Crosshair(new ScreenshotViewer());
crosshair.addMouseWheelListener(new WheelZoomListener());
JScrollPane scroller = new JScrollPane(crosshair);
scroller.setPreferredSize(new Dimension(320, 480));
scroller.setBorder(null);
panel.add(scroller,
new GridBagConstraints(0, y++, 2, 1, 1.0f, 1.0f,
GridBagConstraints.FIRST_LINE_START, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 0), 0, 0));
buildSlider(panel, "Overlay:", "0%", "100%", 0, 100, 30, 1).addChangeListener(
new ChangeListener() {
public void stateChanged(ChangeEvent event) {
float opacity = ((JSlider) event.getSource()).getValue() / 100.0f;
overlayAlpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity);
repaint();
}
});
buildOverlayExtraControls(panel);
buildSlider(panel, "Refresh Rate:", "1s", "40s", 1, 40, 5, 1).addChangeListener(
new ChangeListener() {
public void stateChanged(ChangeEvent event) {
int rate = ((JSlider) event.getSource()).getValue() * 1000;
timer.setDelay(rate);
timer.setInitialDelay(0);
timer.restart();
}
});
zoomSlider = buildSlider(panel, "Zoom:", "2x", "24x", 2, 24, 8, 2);
zoomSlider.addChangeListener(
new ChangeListener() {
public void stateChanged(ChangeEvent event) {
zoom = ((JSlider) event.getSource()).getValue();
loupe.clearGrid = true;
loupe.moveToPoint(crosshair.crosshair.x, crosshair.crosshair.y);
repaint();
}
});
panel.add(Box.createVerticalGlue(),
new GridBagConstraints(0, y++, 2, 1, 1.0f, 1.0f,
GridBagConstraints.FIRST_LINE_START, GridBagConstraints.NONE,
new Insets(0, 0, 0, 0), 0, 0));
return panel;
}
private void buildOverlayExtraControls(JPanel panel) {
JPanel extras = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
JButton loadOverlay = new JButton("Load...");
loadOverlay.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
SwingWorker<?, ?> worker = openOverlay();
if (worker != null) {
worker.execute();
}
}
});
extras.add(loadOverlay);
JCheckBox showInLoupe = new JCheckBox("Show in Loupe");
showInLoupe.setSelected(false);
showInLoupe.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
loupe.showOverlay = ((JCheckBox) event.getSource()).isSelected();
loupe.repaint();
}
});
extras.add(showInLoupe);
panel.add(extras, new GridBagConstraints(1, y++, 1, 1, 1.0f, 0.0f,
GridBagConstraints.LINE_START, GridBagConstraints.NONE,
new Insets(0, 0, 0, 0), 0, 0));
}
public SwingWorker<?, ?> openOverlay() {
JFileChooser chooser = new JFileChooser();
chooser.setFileFilter(new PngFileFilter());
int choice = chooser.showOpenDialog(this);
if (choice == JFileChooser.APPROVE_OPTION) {
return new OpenOverlayTask(chooser.getSelectedFile());
} else {
return null;
}
}
private JSlider buildSlider(JPanel panel, String title, String minName, String maxName,
int min, int max, int value, int tick) {
panel.add(new JLabel(title), new GridBagConstraints(0, y, 1, 1, 1.0f, 0.0f,
GridBagConstraints.LINE_END, GridBagConstraints.NONE,
new Insets(0, 0, 0, 6), 0, 0));
JPanel sliderPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
sliderPanel.add(new JLabel(minName));
JSlider slider = new JSlider(min, max, value);
slider.setMinorTickSpacing(tick);
slider.setMajorTickSpacing(tick);
slider.setSnapToTicks(true);
sliderPanel.add(slider);
sliderPanel.add(new JLabel(maxName));
panel.add(sliderPanel, new GridBagConstraints(1, y++, 1, 1, 1.0f, 0.0f,
GridBagConstraints.FIRST_LINE_START, GridBagConstraints.NONE,
new Insets(0, 0, 0, 0), 0, 0));
return slider;
}
void stop() {
timer.stop();
}
void start() {
timer.start();
}
void select(ViewNode node) {
this.node = node;
repaint();
}
class LoupeViewer extends JComponent {
private final Color lineColor = new Color(1.0f, 1.0f, 1.0f, 0.3f);
private int width;
private int height;
private BufferedImage grid;
private int left;
private int top;
public boolean clearGrid;
private final Rectangle clip = new Rectangle();
private boolean showOverlay = false;
LoupeViewer() {
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent event) {
moveToPoint(event);
}
});
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent event) {
moveToPoint(event);
}
});
}
@Override
protected void paintComponent(Graphics g) {
if (isLoading) {
return;
}
g.translate(-left, -top);
if (image != null) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
g2.scale(zoom, zoom);
g2.drawImage(image, 0, 0, null);
if (overlay != null && showOverlay) {
g2.setComposite(overlayAlpha);
g2.drawImage(overlay, 0, image.getHeight() - overlay.getHeight(), null);
}
g2.dispose();
}
int width = getWidth();
int height = getHeight();
Graphics2D g2 = null;
if (width != this.width || height != this.height) {
this.width = width;
this.height = height;
grid = new BufferedImage(width + zoom + 1, height + zoom + 1,
BufferedImage.TYPE_INT_ARGB);
clearGrid = true;
g2 = grid.createGraphics();
} else if (clearGrid) {
g2 = grid.createGraphics();
g2.setComposite(AlphaComposite.Clear);
g2.fillRect(0, 0, grid.getWidth(), grid.getHeight());
g2.setComposite(AlphaComposite.SrcOver);
}
if (clearGrid) {
clearGrid = false;
g2.setColor(lineColor);
width += zoom;
height += zoom;
for (int x = zoom; x <= width; x += zoom) {
g2.drawLine(x, 0, x, height);
}
for (int y = 0; y <= height; y += zoom) {
g2.drawLine(0, y, width, y);
}
g2.dispose();
}
if (image != null) {
g.getClipBounds(clip);
g.clipRect(0, 0, image.getWidth() * zoom + 1, image.getHeight() * zoom + 1);
g.drawImage(grid, clip.x - clip.x % zoom, clip.y - clip.y % zoom, null);
}
g.translate(left, top);
}
void moveToPoint(MouseEvent event) {
int x = Math.max(0, Math.min((event.getX() + left) / zoom, image.getWidth() - 1));
int y = Math.max(0, Math.min((event.getY() + top) / zoom, image.getHeight() - 1));
moveToPoint(x, y);
crosshair.moveToPoint(x, y);
}
void moveToPoint(int x, int y) {
left = x * zoom - width / 2 + zoom / 2;
top = y * zoom - height / 2 + zoom / 2;
repaint();
}
}
class LoupeStatus extends JPanel {
private JLabel xLabel;
private JLabel yLabel;
private JLabel rLabel;
private JLabel gLabel;
private JLabel bLabel;
private JLabel hLabel;
private ScreenViewer.LoupeStatus.ColoredSquare square;
private Color color;
LoupeStatus() {
setOpaque(true);
setLayout(new GridBagLayout());
setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
square = new ColoredSquare();
add(square, new GridBagConstraints(0, 0, 1, 2, 0.0f, 0.0f,
GridBagConstraints.LINE_START, GridBagConstraints.NONE,
new Insets(0, 0, 0, 12), 0, 0 ));
JLabel label;
add(label = new JLabel("#ffffff"), new GridBagConstraints(0, 2, 1, 1, 0.0f, 0.0f,
GridBagConstraints.LINE_START, GridBagConstraints.NONE,
new Insets(0, 0, 0, 12), 0, 0 ));
label.setForeground(Color.WHITE);
hLabel = label;
add(label = new JLabel("R:"), new GridBagConstraints(1, 0, 1, 1, 0.0f, 0.0f,
GridBagConstraints.LINE_START, GridBagConstraints.NONE,
new Insets(0, 6, 0, 6), 0, 0 ));
label.setForeground(Color.WHITE);
add(label = new JLabel("255"), new GridBagConstraints(2, 0, 1, 1, 0.0f, 0.0f,
GridBagConstraints.LINE_START, GridBagConstraints.NONE,
new Insets(0, 0, 0, 12), 0, 0 ));
label.setForeground(Color.WHITE);
rLabel = label;
add(label = new JLabel("G:"), new GridBagConstraints(1, 1, 1, 1, 0.0f, 0.0f,
GridBagConstraints.LINE_START, GridBagConstraints.NONE,
new Insets(0, 6, 0, 6), 0, 0 ));
label.setForeground(Color.WHITE);
add(label = new JLabel("255"), new GridBagConstraints(2, 1, 1, 1, 0.0f, 0.0f,
GridBagConstraints.LINE_START, GridBagConstraints.NONE,
new Insets(0, 0, 0, 12), 0, 0 ));
label.setForeground(Color.WHITE);
gLabel = label;
add(label = new JLabel("B:"), new GridBagConstraints(1, 2, 1, 1, 0.0f, 0.0f,
GridBagConstraints.LINE_START, GridBagConstraints.NONE,
new Insets(0, 6, 0, 6), 0, 0 ));
label.setForeground(Color.WHITE);
add(label = new JLabel("255"), new GridBagConstraints(2, 2, 1, 1, 0.0f, 0.0f,
GridBagConstraints.LINE_START, GridBagConstraints.NONE,
new Insets(0, 0, 0, 12), 0, 0 ));
label.setForeground(Color.WHITE);
bLabel = label;
add(label = new JLabel("X:"), new GridBagConstraints(3, 0, 1, 1, 0.0f, 0.0f,
GridBagConstraints.LINE_START, GridBagConstraints.NONE,
new Insets(0, 6, 0, 6), 0, 0 ));
label.setForeground(Color.WHITE);
add(label = new JLabel("0 px"), new GridBagConstraints(4, 0, 1, 1, 0.0f, 0.0f,
GridBagConstraints.LINE_START, GridBagConstraints.NONE,
new Insets(0, 0, 0, 12), 0, 0 ));
label.setForeground(Color.WHITE);
xLabel = label;
add(label = new JLabel("Y:"), new GridBagConstraints(3, 1, 1, 1, 0.0f, 0.0f,
GridBagConstraints.LINE_START, GridBagConstraints.NONE,
new Insets(0, 6, 0, 6), 0, 0 ));
label.setForeground(Color.WHITE);
add(label = new JLabel("0 px"), new GridBagConstraints(4, 1, 1, 1, 0.0f, 0.0f,
GridBagConstraints.LINE_START, GridBagConstraints.NONE,
new Insets(0, 0, 0, 12), 0, 0 ));
label.setForeground(Color.WHITE);
yLabel = label;
add(Box.createHorizontalGlue(), new GridBagConstraints(5, 0, 1, 1, 1.0f, 0.0f,
GridBagConstraints.LINE_START, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 0), 0, 0 ));
}
@Override
protected void paintComponent(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
}
void showPixel(int x, int y) {
xLabel.setText(x + " px");
yLabel.setText(y + " px");
int pixel = image.getRGB(x, y);
color = new Color(pixel);
hLabel.setText("#" + Integer.toHexString(pixel));
rLabel.setText(String.valueOf((pixel >> 16) & 0xff));
gLabel.setText(String.valueOf((pixel >> 8) & 0xff));
bLabel.setText(String.valueOf((pixel ) & 0xff));
square.repaint();
}
private class ColoredSquare extends JComponent {
@Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
d.width = 60;
d.height = 30;
return d;
}
@Override
protected void paintComponent(Graphics g) {
g.setColor(color);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.WHITE);
g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
}
}
}
class Crosshair extends JPanel {
// magenta = 0xff5efe
private final Color crosshairColor = new Color(0x00ffff);
Point crosshair = new Point();
private int width;
private int height;
private final ScreenshotViewer screenshotViewer;
Crosshair(ScreenshotViewer screenshotViewer) {
this.screenshotViewer = screenshotViewer;
setOpaque(true);
setLayout(new BorderLayout());
add(screenshotViewer);
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent event) {
moveToPoint(event);
}
});
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent event) {
moveToPoint(event);
}
});
}
void moveToPoint(int x, int y) {
crosshair.x = x;
crosshair.y = y;
status.showPixel(crosshair.x, crosshair.y);
repaint();
}
private void moveToPoint(MouseEvent event) {
crosshair.x = Math.max(0, Math.min(image.getWidth() - 1, event.getX()));
crosshair.y = Math.max(0, Math.min(image.getHeight() - 1, event.getY()));
loupe.moveToPoint(crosshair.x, crosshair.y);
status.showPixel(crosshair.x, crosshair.y);
repaint();
}
@Override
public Dimension getPreferredSize() {
return screenshotViewer.getPreferredSize();
}
@Override
public Dimension getMaximumSize() {
return screenshotViewer.getPreferredSize();
}
@Override
public void paint(Graphics g) {
super.paint(g);
if (crosshair == null || width != getWidth() || height != getHeight()) {
width = getWidth();
height = getHeight();
crosshair = new Point(width / 2, height / 2);
}
g.setColor(crosshairColor);
g.drawLine(crosshair.x, 0, crosshair.x, height);
g.drawLine(0, crosshair.y, width, crosshair.y);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
}
}
class ScreenshotViewer extends JComponent {
private final Color boundsColor = new Color(0xff5efe);
ScreenshotViewer() {
setOpaque(true);
}
@Override
protected void paintComponent(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
if (isLoading) {
return;
}
if (image != null) {
g.drawImage(image, 0, 0, null);
if (overlay != null) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setComposite(overlayAlpha);
g2.drawImage(overlay, 0, image.getHeight() - overlay.getHeight(), null);
}
}
if (node != null) {
Graphics s = g.create();
s.setColor(boundsColor);
ViewNode p = node.parent;
while (p != null) {
s.translate(p.left - p.scrollX, p.top - p.scrollY);
p = p.parent;
}
s.drawRect(node.left, node.top, node.width - 1, node.height - 1);
s.translate(node.left, node.top);
s.setXORMode(Color.WHITE);
if ((node.paddingBottom | node.paddingLeft |
node.paddingTop | node.paddingRight) != 0) {
s.setColor(Color.BLACK);
s.drawRect(node.paddingLeft, node.paddingTop,
node.width - node.paddingRight - node.paddingLeft - 1,
node.height - node.paddingBottom - node.paddingTop - 1);
}
if (node.hasMargins && (node.marginLeft | node.marginBottom |
node.marginRight | node.marginRight) != 0) {
s.setColor(Color.BLACK);
s.drawRect(-node.marginLeft, -node.marginTop,
node.marginLeft + node.width + node.marginRight - 1,
node.marginTop + node.height + node.marginBottom - 1);
}
s.dispose();
}
}
@Override
public Dimension getPreferredSize() {
if (image == null) {
return new Dimension(320, 480);
}
return new Dimension(image.getWidth(), image.getHeight());
}
}
private class CrosshairPanel extends JPanel {
private final Color crosshairColor = new Color(0xff5efe);
private final Insets insets = new Insets(0, 0, 0, 0);
CrosshairPanel(LoupeViewer loupe) {
setLayout(new BorderLayout());
add(loupe);
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(crosshairColor);
int width = getWidth();
int height = getHeight();
getInsets(insets);
int x = (width - insets.left - insets.right) / 2;
int y = (height - insets.top - insets.bottom) / 2;
g.drawLine(insets.left + x, insets.top, insets.left + x, height - insets.bottom);
g.drawLine(insets.left, insets.top + y, width - insets.right, insets.top + y);
}
@Override
protected void paintComponent(Graphics g) {
g.setColor(Color.BLACK);
Insets insets = getInsets();
g.fillRect(insets.left, insets.top, getWidth() - insets.left - insets.right,
getHeight() - insets.top - insets.bottom);
}
}
public void actionPerformed(ActionEvent event) {
if (task != null && !task.isDone()) {
return;
}
task = new GetScreenshotTask();
task.execute();
}
private class GetScreenshotTask extends SwingWorker<Boolean, Void> {
private GetScreenshotTask() {
workspace.beginTask();
}
@Override
@WorkerThread
protected Boolean doInBackground() throws Exception {
RawImage rawImage;
try {
rawImage = device.getScreenshot();
} catch (IOException ioe) {
return false;
}
boolean resize = false;
isLoading = true;
try {
if (rawImage != null) {
if (image == null || rawImage.width != image.getWidth() ||
rawImage.height != image.getHeight()) {
image = new BufferedImage(rawImage.width, rawImage.height,
BufferedImage.TYPE_INT_ARGB);
scanline = new int[rawImage.width];
resize = true;
}
switch (rawImage.bpp) {
case 16:
rawImage16toARGB(rawImage);
break;
case 32:
rawImage32toARGB(rawImage);
break;
}
}
} finally {
isLoading = false;
}
return resize;
}
private int getMask(int length) {
int res = 0;
for (int i = 0 ; i < length ; i++) {
res = (res << 1) + 1;
}
return res;
}
private void rawImage32toARGB(RawImage rawImage) {
byte[] buffer = rawImage.data;
int index = 0;
final int redOffset = rawImage.red_offset;
final int redLength = rawImage.red_length;
final int redMask = getMask(redLength);
final int greenOffset = rawImage.green_offset;
final int greenLength = rawImage.green_length;
final int greenMask = getMask(greenLength);
final int blueOffset = rawImage.blue_offset;
final int blueLength = rawImage.blue_length;
final int blueMask = getMask(blueLength);
final int alphaLength = rawImage.alpha_length;
final int alphaOffset = rawImage.alpha_offset;
final int alphaMask = getMask(alphaLength);
for (int y = 0 ; y < rawImage.height ; y++) {
for (int x = 0 ; x < rawImage.width ; x++) {
int value = buffer[index++] & 0x00FF;
value |= (buffer[index++] & 0x00FF) << 8;
value |= (buffer[index++] & 0x00FF) << 16;
value |= (buffer[index++] & 0x00FF) << 24;
int r = ((value >>> redOffset) & redMask) << (8 - redLength);
int g = ((value >>> greenOffset) & greenMask) << (8 - greenLength);
int b = ((value >>> blueOffset) & blueMask) << (8 - blueLength);
int a = 0xFF;
if (alphaLength != 0) {
a = ((value >>> alphaOffset) & alphaMask) << (8 - alphaLength);
}
scanline[x] = a << 24 | r << 16 | g << 8 | b;
}
image.setRGB(0, y, rawImage.width, 1, scanline,
0, rawImage.width);
}
}
private void rawImage16toARGB(RawImage rawImage) {
byte[] buffer = rawImage.data;
int index = 0;
for (int y = 0 ; y < rawImage.height ; y++) {
for (int x = 0 ; x < rawImage.width ; x++) {
int value = buffer[index++] & 0x00FF;
value |= (buffer[index++] << 8) & 0x0FF00;
int r = ((value >> 11) & 0x01F) << 3;
int g = ((value >> 5) & 0x03F) << 2;
int b = ((value ) & 0x01F) << 3;
scanline[x] = 0xFF << 24 | r << 16 | g << 8 | b;
}
image.setRGB(0, y, rawImage.width, 1, scanline,
0, rawImage.width);
}
}
@Override
protected void done() {
workspace.endTask();
try {
if (get()) {
validate();
crosshair.crosshair = new Point(image.getWidth() / 2,
image.getHeight() / 2);
status.showPixel(image.getWidth() / 2, image.getHeight() / 2);
loupe.moveToPoint(image.getWidth() / 2, image.getHeight() / 2);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
repaint();
}
}
private class OpenOverlayTask extends SwingWorker<BufferedImage, Void> {
private File file;
private OpenOverlayTask(File file) {
this.file = file;
workspace.beginTask();
}
@Override
@WorkerThread
protected BufferedImage doInBackground() {
try {
return IconLoader.toCompatibleImage(ImageIO.read(file));
} catch (IOException ex) {
ex.printStackTrace();
}
return null;
}
@Override
protected void done() {
try {
overlay = get();
repaint();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
workspace.endTask();
}
}
}
}