diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/RawImage.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/RawImage.java index e3d4e095f..6132bd0fe 100644 --- a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/RawImage.java +++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/RawImage.java @@ -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 index 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. *
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; + } } diff --git a/tools/ddms/libs/ddmuilib/src/com/android/ddmuilib/ScreenShotDialog.java b/tools/ddms/libs/ddmuilib/src/com/android/ddmuilib/ScreenShotDialog.java index 0319642cc..88f1ad1ee 100644 --- a/tools/ddms/libs/ddmuilib/src/com/android/ddmuilib/ScreenShotDialog.java +++ b/tools/ddms/libs/ddmuilib/src/com/android/ddmuilib/ScreenShotDialog.java @@ -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. */ diff --git a/tools/screenshot/src/com/android/screenshot/Screenshot.java b/tools/screenshot/src/com/android/screenshot/Screenshot.java index 06e1f6b44..a3fe5209f 100644 --- a/tools/screenshot/src/com/android/screenshot/Screenshot.java +++ b/tools/screenshot/src/com/android/screenshot/Screenshot.java @@ -208,53 +208,21 @@ public class Screenshot { if (rawImage == null) return; - assert rawImage.bpp == 16; - - BufferedImage image; - if (landscape) { - // convert raw data to an Image - image = new BufferedImage(rawImage.height, rawImage.width, - BufferedImage.TYPE_INT_ARGB); + rawImage = rawImage.getRotated(); + } - byte[] buffer = rawImage.data; - int index = 0; - for (int y = 0 ; y < rawImage.height ; y++) { - for (int x = 0 ; x < rawImage.width ; x++) { + // convert raw data to an Image + BufferedImage image = new BufferedImage(rawImage.width, rawImage.height, + BufferedImage.TYPE_INT_ARGB); - 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; - - image.setRGB(x, y, value); - } + 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 = rawImage.getARGB(index); + index += IndexInc; + image.setRGB(x, y, value); } }