Merge change 26915 into eclair
* changes: Fixed screenshot command line tool to deal with new RawImage
This commit is contained in:
@@ -127,17 +127,76 @@ public final class RawImage {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rotated version of the image
|
||||
* The image is rotated counter-clockwise.
|
||||
*/
|
||||
public RawImage getRotated() {
|
||||
RawImage rotated = new RawImage();
|
||||
rotated.version = this.version;
|
||||
rotated.bpp = this.bpp;
|
||||
rotated.size = this.size;
|
||||
rotated.red_offset = this.red_offset;
|
||||
rotated.red_length = this.red_length;
|
||||
rotated.blue_offset = this.blue_offset;
|
||||
rotated.blue_length = this.blue_length;
|
||||
rotated.green_offset = this.green_offset;
|
||||
rotated.green_length = this.green_length;
|
||||
rotated.alpha_offset = this.alpha_offset;
|
||||
rotated.alpha_length = this.alpha_length;
|
||||
|
||||
rotated.width = this.height;
|
||||
rotated.height = this.width;
|
||||
|
||||
int count = this.data.length;
|
||||
rotated.data = new byte[count];
|
||||
|
||||
int byteCount = this.bpp >> 3; // bpp is in bits, we want bytes to match our array
|
||||
final int w = this.width;
|
||||
final int h = this.height;
|
||||
for (int y = 0 ; y < h ; y++) {
|
||||
for (int x = 0 ; x < w ; x++) {
|
||||
System.arraycopy(
|
||||
this.data, (y * w + x) * byteCount,
|
||||
rotated.data, ((w-x-1) * h + y) * byteCount,
|
||||
byteCount);
|
||||
}
|
||||
}
|
||||
|
||||
return rotated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an ARGB integer value for the pixel at <var>index</var> in {@link #data}.
|
||||
*/
|
||||
public int getARGB(int index) {
|
||||
int value;
|
||||
if (bpp == 16) {
|
||||
value = data[index] & 0x00FF;
|
||||
value |= (data[index+1] << 8) & 0x0FF00;
|
||||
} else if (bpp == 32) {
|
||||
value = data[index] & 0x00FF;
|
||||
value |= (data[index+1] & 0x00FF) << 8;
|
||||
value |= (data[index+2] & 0x00FF) << 16;
|
||||
value |= (data[index+3] & 0x00FF) << 24;
|
||||
} else {
|
||||
throw new UnsupportedOperationException("RawImage.getARGB(int) only works in 16 and 32 bit mode.");
|
||||
}
|
||||
|
||||
int r = ((value >>> red_offset) & getMask(red_length)) << (8 - red_length);
|
||||
int g = ((value >>> green_offset) & getMask(green_length)) << (8 - green_length);
|
||||
int b = ((value >>> blue_offset) & getMask(blue_length)) << (8 - blue_length);
|
||||
int a = ((value >>> alpha_offset) & getMask(alpha_length)) << (8 - alpha_length);
|
||||
|
||||
return a << 24 | r << 16 | g << 8 | b;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a mask value based on a length and offset.
|
||||
* <p/>This value is compatible with org.eclipse.swt.graphics.PaletteData
|
||||
*/
|
||||
private int getMask(int length, int offset) {
|
||||
int res = 0;
|
||||
for (int i = 0 ; i < length ; i++) {
|
||||
res = (res << 1) + 1;
|
||||
}
|
||||
|
||||
res = res << offset;
|
||||
int res = getMask(length) << offset;
|
||||
|
||||
// if the bpp is 32 bits then we need to invert it because the buffer is in little endian
|
||||
if (bpp == 32) {
|
||||
@@ -146,4 +205,18 @@ public final class RawImage {
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mask value based on a length.
|
||||
* @param length
|
||||
* @return
|
||||
*/
|
||||
private int getMask(int length) {
|
||||
int res = 0;
|
||||
for (int i = 0 ; i < length ; i++) {
|
||||
res = (res << 1) + 1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ public class ScreenShotDialog extends Dialog {
|
||||
private Label mImageLabel;
|
||||
private Button mSave;
|
||||
private IDevice mDevice;
|
||||
private RawImage mRawImage;
|
||||
|
||||
|
||||
/**
|
||||
@@ -95,7 +96,9 @@ public class ScreenShotDialog extends Dialog {
|
||||
private void createContents(final Shell shell) {
|
||||
GridData data;
|
||||
|
||||
shell.setLayout(new GridLayout(3, true));
|
||||
final int colCount = 4;
|
||||
|
||||
shell.setLayout(new GridLayout(colCount, true));
|
||||
|
||||
// "refresh" button
|
||||
Button refresh = new Button(shell, SWT.PUSH);
|
||||
@@ -110,6 +113,22 @@ public class ScreenShotDialog extends Dialog {
|
||||
}
|
||||
});
|
||||
|
||||
// "rotate" button
|
||||
Button rotate = new Button(shell, SWT.PUSH);
|
||||
rotate.setText("Rotate");
|
||||
data = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
|
||||
data.widthHint = 80;
|
||||
rotate.setLayoutData(data);
|
||||
rotate.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
if (mRawImage != null) {
|
||||
mRawImage = mRawImage.getRotated();
|
||||
updateImageDisplay(shell);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// "save" button
|
||||
mSave = new Button(shell, SWT.PUSH);
|
||||
mSave.setText("Save");
|
||||
@@ -156,22 +175,43 @@ public class ScreenShotDialog extends Dialog {
|
||||
shell.setDefaultButton(done);
|
||||
}
|
||||
|
||||
/*
|
||||
* Capture a new image from the device.
|
||||
/**
|
||||
* Captures a new image from the device, and display it.
|
||||
*/
|
||||
private void updateDeviceImage(Shell shell) {
|
||||
mBusyLabel.setText("Capturing..."); // no effect
|
||||
|
||||
shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
|
||||
|
||||
Image image = getDeviceImage();
|
||||
if (image == null) {
|
||||
mRawImage = getDeviceImage();
|
||||
|
||||
updateImageDisplay(shell);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the display with {@link #mRawImage}.
|
||||
* @param shell
|
||||
*/
|
||||
private void updateImageDisplay(Shell shell) {
|
||||
Image image;
|
||||
if (mRawImage == null) {
|
||||
Display display = shell.getDisplay();
|
||||
image = ImageHelper.createPlaceHolderArt(
|
||||
display, 320, 240, display.getSystemColor(SWT.COLOR_BLUE));
|
||||
|
||||
mSave.setEnabled(false);
|
||||
mBusyLabel.setText("Screen not available");
|
||||
} else {
|
||||
// convert raw data to an Image.
|
||||
PaletteData palette = new PaletteData(
|
||||
mRawImage.getRedMask(),
|
||||
mRawImage.getGreenMask(),
|
||||
mRawImage.getBlueMask());
|
||||
|
||||
ImageData imageData = new ImageData(mRawImage.width, mRawImage.height,
|
||||
mRawImage.bpp, palette, 1, mRawImage.data);
|
||||
image = new Image(getParent().getDisplay(), imageData);
|
||||
|
||||
mSave.setEnabled(true);
|
||||
mBusyLabel.setText("Captured image:");
|
||||
}
|
||||
@@ -184,40 +224,19 @@ public class ScreenShotDialog extends Dialog {
|
||||
shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_ARROW));
|
||||
}
|
||||
|
||||
/*
|
||||
* Grab an image from an ADB-connected device.
|
||||
/**
|
||||
* Grabs an image from an ADB-connected device and returns it as a {@link RawImage}.
|
||||
*/
|
||||
private Image getDeviceImage() {
|
||||
RawImage rawImage;
|
||||
|
||||
private RawImage getDeviceImage() {
|
||||
try {
|
||||
rawImage = mDevice.getScreenshot();
|
||||
return mDevice.getScreenshot();
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
Log.w("ddms", "Unable to get frame buffer: " + ioe.getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
// device/adb not available?
|
||||
if (rawImage == null)
|
||||
return null;
|
||||
|
||||
// convert raw data to an Image.
|
||||
PaletteData palette = new PaletteData(
|
||||
rawImage.getRedMask(),
|
||||
rawImage.getGreenMask(),
|
||||
rawImage.getBlueMask());
|
||||
ImageData imageData = new ImageData(rawImage.width, rawImage.height,
|
||||
rawImage.bpp, palette, 1, rawImage.data);
|
||||
|
||||
if (imageData != null) {
|
||||
return new Image(getParent().getDisplay(), imageData);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prompt the user to save the image to disk.
|
||||
*/
|
||||
|
||||
@@ -208,55 +208,23 @@ public class Screenshot {
|
||||
if (rawImage == null)
|
||||
return;
|
||||
|
||||
assert rawImage.bpp == 16;
|
||||
|
||||
BufferedImage image;
|
||||
|
||||
if (landscape) {
|
||||
rawImage = rawImage.getRotated();
|
||||
}
|
||||
|
||||
// convert raw data to an Image
|
||||
image = new BufferedImage(rawImage.height, rawImage.width,
|
||||
BufferedImage image = new BufferedImage(rawImage.width, rawImage.height,
|
||||
BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
byte[] buffer = rawImage.data;
|
||||
int index = 0;
|
||||
int IndexInc = rawImage.bpp >> 3;
|
||||
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 >> 0) & 0x01F) << 3;
|
||||
|
||||
value = 0xFF << 24 | r << 16 | g << 8 | b;
|
||||
|
||||
image.setRGB(y, rawImage.width - x - 1, value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// convert raw data to an Image
|
||||
image = new BufferedImage(rawImage.width, rawImage.height,
|
||||
BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
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 >> 0) & 0x01F) << 3;
|
||||
|
||||
value = 0xFF << 24 | r << 16 | g << 8 | b;
|
||||
|
||||
int value = rawImage.getARGB(index);
|
||||
index += IndexInc;
|
||||
image.setRGB(x, y, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ImageIO.write(image, "png", new File(filepath))) {
|
||||
throw new IOException("Failed to find png writer");
|
||||
|
||||
Reference in New Issue
Block a user