/* * Copyright (C) 2009-2013 adakoda * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.adakoda.android.asm; import java.awt.Color; import java.awt.Graphics; import java.awt.Image; import java.awt.Insets; import java.awt.Point; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.prefs.Preferences; import javax.imageio.ImageIO; import javax.swing.AbstractAction; import javax.swing.ButtonGroup; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JRadioButtonMenuItem; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import javax.swing.filechooser.FileFilter; import com.android.chimpchat.adb.AdbChimpDevice; import com.android.ddmlib.AdbCommandRejectedException; import com.android.ddmlib.IDevice; import com.android.ddmlib.RawImage; import com.android.ddmlib.TimeoutException; @SuppressWarnings("serial") public class MainFrame extends JFrame { private static final int DEFAULT_WIDTH = 320; private static final int DEFAULT_HEIGHT = 480; private static final String EXT_PNG = "png"; private static final int FB_TYPE_XBGR = 0; private static final int FB_TYPE_RGBX = 1; private static final int FB_TYPE_XRGB = 2; private static int[][] FB_OFFSET_LIST = { {0, 1, 2, 3}, // XBGR : Normal {3, 2, 1, 0}, // RGBX : Xperia Arc {2, 1, 0, 3} // XRGB : FireFox OS(B2G) }; private MainPanel mPanel; private JPopupMenu mPopupMenu; private Preferences mPrefs; private int mRawImageWidth = DEFAULT_WIDTH; private int mRawImageHeight = DEFAULT_HEIGHT; private boolean mPortrait = true; private double mZoom = 1.0; private int mFbType = FB_TYPE_XBGR; private ADB mADB; private IDevice[] mDevices; private IDevice mDevice; private AdbChimpDevice mChimpDevice; private MonitorThread mMonitorThread; private String mBuildDevice = ""; public MainFrame(String[] args) { initialize(args); } public void startMonitor() { mMonitorThread = new MonitorThread(); mMonitorThread.start(); } public void stopMonitor() { mMonitorThread = null; } public void selectDevice() { stopMonitor(); mDevices = mADB.getDevices(); if (mDevices != null) { ArrayList<String> list = new ArrayList<String>(); for (int i = 0; i < mDevices.length; i++) { list.add(mDevices[i].toString()); } SelectDeviceDialog dialog = new SelectDeviceDialog(this, true, list); dialog.setLocationRelativeTo(this); dialog.setVisible(true); if (dialog.isOK()) { int selectedIndex = dialog.getSelectedIndex(); if (selectedIndex >= 0) { mDevice = mDevices[selectedIndex]; setImage(null); } } } mChimpDevice = new AdbChimpDevice(mDevice); mBuildDevice = mChimpDevice.getProperty("build.device"); startMonitor(); } public void setOrientation(boolean portrait) { if (mPortrait != portrait) { mPortrait = portrait; savePrefs(); updateSize(); } } public void setZoom(double zoom) { if (mZoom != zoom) { mZoom = zoom; savePrefs(); updateSize(); } } public void setFrameBuffer(int fbType) { if (mFbType != fbType) { mFbType = fbType; savePrefs(); } } public void saveImage() { FBImage inImage = mPanel.getFBImage(); if (inImage != null) { BufferedImage outImage = new BufferedImage((int) (inImage .getWidth() * mZoom), (int) (inImage.getHeight() * mZoom), inImage.getType()); if (outImage != null) { AffineTransformOp op = new AffineTransformOp(AffineTransform .getScaleInstance(mZoom, mZoom), AffineTransformOp.TYPE_BILINEAR); op.filter(inImage, outImage); JFileChooser fileChooser = new JFileChooser(); fileChooser.setFileFilter(new FileFilter() { @Override public String getDescription() { return "*." + EXT_PNG; } @Override public boolean accept(File f) { String ext = f.getName().toLowerCase(); return (ext.endsWith("." + EXT_PNG)); } }); if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) { try { File file = fileChooser.getSelectedFile(); String path = file.getAbsolutePath(); if (!path.endsWith("." + EXT_PNG)) { file = new File(path + "." + EXT_PNG); } ImageIO.write(outImage, EXT_PNG, file); } catch (Exception ex) { JOptionPane.showMessageDialog(this, "Failed to save a image.", "Save Image", JOptionPane.ERROR_MESSAGE); } } } } } public void about() { AboutDialog dialog = new AboutDialog(this, true); dialog.setLocationRelativeTo(this); dialog.setVisible(true); } public void updateSize() { int width; int height; if (mPortrait) { width = mRawImageWidth; height = mRawImageHeight; } else { width = mRawImageHeight; height = mRawImageWidth; } Insets insets = getInsets(); int newWidth = (int) (width * mZoom) + insets.left + insets.right; int newHeight = (int) (height * mZoom) + insets.top + insets.bottom; // Known bug // If new window size is over physical window size, cannot update window // size... // FIXME if ((getWidth() != newWidth) || (getHeight() != newHeight)) { setSize(newWidth, newHeight); } } public void setImage(FBImage fbImage) { if (fbImage != null) { mRawImageWidth = fbImage.getRawWidth(); mRawImageHeight = fbImage.getRawHeight(); } mPanel.setFBImage(fbImage); updateSize(); } private void initialize(String[] args) { mADB = new ADB(); if (!mADB.initialize(args)) { JOptionPane.showMessageDialog(this, "Could not find adb, please install Android SDK and set path to adb.", "Error", JOptionPane.ERROR_MESSAGE); } parseArgs(args); initializePrefs(); initializeFrame(); initializePanel(); initializeMenu(); initializeActionMap(); addMouseListener(mMouseListener); addWindowListener(mWindowListener); addMouseMotionListener(mMouseMotionListener); addKeyListener(mKeyListener); pack(); setImage(null); } private void parseArgs(String[] args) { if (args != null) { for (int i = 0; i < args.length; i++) { String arg = args[i]; if (arg.equals("-f0")) { mFbType = FB_TYPE_XBGR; } else if (arg.equals("-f1")) { mFbType = FB_TYPE_RGBX; } else if (arg.equals("-f2")) { mFbType = FB_TYPE_XRGB; } } } } private void savePrefs() { if (mPrefs != null) { mPrefs.putInt("PrefVer", 1); mPrefs.putBoolean("Portrait", mPortrait); mPrefs.putDouble("Zoom", mZoom); mPrefs.putInt("FbType", mFbType); } } private void initializePrefs() { mPrefs = Preferences.userNodeForPackage(this.getClass()); if (mPrefs != null) { int prefVer = mPrefs.getInt("PrefVer", 1); if (prefVer == 1) { mPortrait = mPrefs.getBoolean("Portrait", true); mZoom = mPrefs.getDouble("Zoom", 1.0); mFbType = mPrefs.getInt("FbType", FB_TYPE_XBGR); } } } private void initializeFrame() { setTitle("Android Screen Monitor"); setIconImage(Toolkit.getDefaultToolkit().getImage( getClass().getResource("icon.png"))); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setResizable(false); } private void initializePanel() { mPanel = new MainPanel(); add(mPanel); } private void initializeMenu() { mPopupMenu = new JPopupMenu(); initializeSelectDeviceMenu(); mPopupMenu.addSeparator(); initializeOrientationMenu(); initializeZoomMenu(); initializeFrameBufferMenu(); mPopupMenu.addSeparator(); initializeSaveImageMenu(); mPopupMenu.addSeparator(); initializeAbout(); mPopupMenu.addPopupMenuListener(new PopupMenuListener() { public void popupMenuWillBecomeVisible(PopupMenuEvent e) { } public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { } public void popupMenuCanceled(PopupMenuEvent e) { } }); } private void initializeSelectDeviceMenu() { JMenuItem menuItemSelectDevice = new JMenuItem("Select Device..."); menuItemSelectDevice.setMnemonic(KeyEvent.VK_D); menuItemSelectDevice.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { selectDevice(); } }); mPopupMenu.add(menuItemSelectDevice); } private void initializeOrientationMenu() { JMenu menuOrientation = new JMenu("Orientation"); menuOrientation.setMnemonic(KeyEvent.VK_O); mPopupMenu.add(menuOrientation); ButtonGroup buttonGroup = new ButtonGroup(); // Portrait JRadioButtonMenuItem radioButtonMenuItemPortrait = new JRadioButtonMenuItem( "Portrait"); radioButtonMenuItemPortrait.setMnemonic(KeyEvent.VK_P); radioButtonMenuItemPortrait.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setOrientation(true); } }); if (mPortrait) { radioButtonMenuItemPortrait.setSelected(true); } buttonGroup.add(radioButtonMenuItemPortrait); menuOrientation.add(radioButtonMenuItemPortrait); // Landscape JRadioButtonMenuItem radioButtonMenuItemLandscape = new JRadioButtonMenuItem( "Landscape"); radioButtonMenuItemLandscape.setMnemonic(KeyEvent.VK_L); radioButtonMenuItemLandscape.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setOrientation(false); } }); if (!mPortrait) { radioButtonMenuItemLandscape.setSelected(true); } buttonGroup.add(radioButtonMenuItemLandscape); menuOrientation.add(radioButtonMenuItemLandscape); } private void initializeZoomMenu() { JMenu menuZoom = new JMenu("Zoom"); menuZoom.setMnemonic(KeyEvent.VK_Z); mPopupMenu.add(menuZoom); ButtonGroup buttonGroup = new ButtonGroup(); addRadioButtonMenuItemZoom(menuZoom, buttonGroup, 0.1, "10%", -1, mZoom); addRadioButtonMenuItemZoom(menuZoom, buttonGroup, 0.25, "25%", -1, mZoom); addRadioButtonMenuItemZoom(menuZoom, buttonGroup, 0.5, "50%", KeyEvent.VK_5, mZoom); addRadioButtonMenuItemZoom(menuZoom, buttonGroup, 0.75, "75%", KeyEvent.VK_7, mZoom); addRadioButtonMenuItemZoom(menuZoom, buttonGroup, 1.0, "100%", KeyEvent.VK_1, mZoom); addRadioButtonMenuItemZoom(menuZoom, buttonGroup, 1.5, "150%", KeyEvent.VK_0, mZoom); addRadioButtonMenuItemZoom(menuZoom, buttonGroup, 2.0, "200%", KeyEvent.VK_2, mZoom); } private void addRadioButtonMenuItemZoom( JMenu menuZoom, ButtonGroup buttonGroup, final double zoom, String caption, int nemonic, double currentZoom) { JRadioButtonMenuItem radioButtonMenuItemZoom = new JRadioButtonMenuItem(caption); if (nemonic != -1) { radioButtonMenuItemZoom.setMnemonic(nemonic); } radioButtonMenuItemZoom.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setZoom(zoom); } }); if (currentZoom == zoom) { radioButtonMenuItemZoom.setSelected(true); } buttonGroup.add(radioButtonMenuItemZoom); menuZoom.add(radioButtonMenuItemZoom); } private void initializeFrameBufferMenu() { JMenu menuZoom = new JMenu("FrameBuffer"); menuZoom.setMnemonic(KeyEvent.VK_F); mPopupMenu.add(menuZoom); ButtonGroup buttonGroup = new ButtonGroup(); // XBGR JRadioButtonMenuItem radioButtonMenuItemFbXBGR = new JRadioButtonMenuItem( "XBGR"); radioButtonMenuItemFbXBGR.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setFrameBuffer(FB_TYPE_XBGR); } }); if (mFbType == FB_TYPE_XBGR) { radioButtonMenuItemFbXBGR.setSelected(true); } buttonGroup.add(radioButtonMenuItemFbXBGR); menuZoom.add(radioButtonMenuItemFbXBGR); // RGBX JRadioButtonMenuItem radioButtonMenuItemFbRGBX = new JRadioButtonMenuItem( "RGBX"); radioButtonMenuItemFbRGBX.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setFrameBuffer(FB_TYPE_RGBX); } }); if (mFbType == FB_TYPE_RGBX) { radioButtonMenuItemFbRGBX.setSelected(true); } buttonGroup.add(radioButtonMenuItemFbRGBX); menuZoom.add(radioButtonMenuItemFbRGBX); // XRGB JRadioButtonMenuItem radioButtonMenuItemFbXRGB = new JRadioButtonMenuItem( "XRGB"); radioButtonMenuItemFbXRGB.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setFrameBuffer(FB_TYPE_XRGB); } }); if (mFbType == FB_TYPE_XRGB) { radioButtonMenuItemFbXRGB.setSelected(true); } buttonGroup.add(radioButtonMenuItemFbXRGB); menuZoom.add(radioButtonMenuItemFbXRGB); } private void initializeSaveImageMenu() { JMenuItem menuItemSaveImage = new JMenuItem("Save Image..."); menuItemSaveImage.setMnemonic(KeyEvent.VK_S); menuItemSaveImage.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { saveImage(); } }); mPopupMenu.add(menuItemSaveImage); } private void initializeActionMap() { AbstractAction actionSelectDevice = new AbstractAction() { public void actionPerformed(ActionEvent e) { selectDevice(); } }; AbstractAction actionPortrait = new AbstractAction() { public void actionPerformed(ActionEvent e) { setOrientation(true); } }; AbstractAction actionLandscape = new AbstractAction() { public void actionPerformed(ActionEvent e) { setOrientation(false); } }; AbstractAction actionZoom50 = new AbstractAction() { public void actionPerformed(ActionEvent e) { setZoom(0.5); } }; AbstractAction actionZoom75 = new AbstractAction() { public void actionPerformed(ActionEvent e) { setZoom(0.75); } }; AbstractAction actionZoom100 = new AbstractAction() { public void actionPerformed(ActionEvent e) { setZoom(1.0); } }; AbstractAction actionZoom150 = new AbstractAction() { public void actionPerformed(ActionEvent e) { setZoom(1.5); } }; AbstractAction actionZoom200 = new AbstractAction() { public void actionPerformed(ActionEvent e) { setZoom(2.0); } }; AbstractAction actionSaveImage = new AbstractAction() { public void actionPerformed(ActionEvent e) { saveImage(); } }; AbstractAction actionAbout = new AbstractAction() { public void actionPerformed(ActionEvent e) { about(); } }; JComponent targetComponent = getRootPane(); InputMap inputMap = targetComponent.getInputMap(); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_DOWN_MASK), "Select Device"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_DOWN_MASK), "Portrait"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_L, InputEvent.CTRL_DOWN_MASK), "Landscape"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_5, InputEvent.CTRL_DOWN_MASK), "50%"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_7, InputEvent.CTRL_DOWN_MASK), "75%"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_1, InputEvent.CTRL_DOWN_MASK), "100%"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_0, InputEvent.CTRL_DOWN_MASK), "150%"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_2, InputEvent.CTRL_DOWN_MASK), "200%"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK), "Save Image"); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_DOWN_MASK), "About ASM"); targetComponent.setInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, inputMap); targetComponent.getActionMap().put("Select Device", actionSelectDevice); targetComponent.getActionMap().put("Portrait", actionPortrait); targetComponent.getActionMap().put("Landscape", actionLandscape); targetComponent.getActionMap().put("Select Device", actionSelectDevice); targetComponent.getActionMap().put("50%", actionZoom50); targetComponent.getActionMap().put("75%", actionZoom75); targetComponent.getActionMap().put("100%", actionZoom100); targetComponent.getActionMap().put("150%", actionZoom150); targetComponent.getActionMap().put("200%", actionZoom200); targetComponent.getActionMap().put("Save Image", actionSaveImage); targetComponent.getActionMap().put("About ASM", actionAbout); } private void initializeAbout() { JMenuItem menuItemAbout = new JMenuItem("About ASM"); menuItemAbout.setMnemonic(KeyEvent.VK_A); menuItemAbout.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { about(); } }); mPopupMenu.add(menuItemAbout); } private Point getRealPoint(Point p) { int x = p.x; int y = p.y; Insets insets = getInsets(); int realX = (int) ((x - insets.left) / mZoom); int realY = (int) ((y - insets.top) / mZoom); return new Point(realX, realY); } private boolean isGlass() { return mBuildDevice.startsWith("glass-"); } private MouseListener mMouseListener = new MouseListener() { public void mouseReleased(MouseEvent e) { try { if (isGlass()) { // TODO } else { Point p = new Point(e.getX(), e.getY()); Point real = getRealPoint(p); mChimpDevice.getManager().touchUp(real.x, real.y); } } catch (IOException ex) { ex.printStackTrace(); } } public void mousePressed(MouseEvent e) { try { if (isGlass()) { mChimpDevice.getManager().press("KEYCODE_DPAD_CENTER"); } else { Point p = new Point(e.getX(), e.getY()); Point real = getRealPoint(p); mChimpDevice.getManager().touchDown(real.x, real.y); } } catch (IOException ex) { ex.printStackTrace(); } } public void mouseExited(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseClicked(MouseEvent e) { if (SwingUtilities.isRightMouseButton(e)) { mPopupMenu.show(e.getComponent(), e.getX(), e.getY()); } } }; private WindowListener mWindowListener = new WindowListener() { public void windowOpened(WindowEvent arg0) { } public void windowIconified(WindowEvent arg0) { } public void windowDeiconified(WindowEvent arg0) { } public void windowDeactivated(WindowEvent arg0) { } public void windowClosing(WindowEvent arg0) { if (mChimpDevice != null) { mChimpDevice.dispose(); } if (mADB != null) { mADB.terminate(); } } public void windowClosed(WindowEvent arg0) { } public void windowActivated(WindowEvent arg0) { } }; private MouseMotionListener mMouseMotionListener = new MouseMotionListener() { @Override public void mouseMoved(MouseEvent e) { } @Override public void mouseDragged(MouseEvent e) { try { Point p = new Point(e.getX(), e.getY()); Point real = getRealPoint(p); mChimpDevice.getManager().touchMove(real.x, real.y); } catch (IOException ex) { ex.printStackTrace(); } } }; private KeyListener mKeyListener = new KeyListener() { @Override public void keyTyped(KeyEvent keyEvent) { } @Override public void keyReleased(KeyEvent keyEvent) { } @Override public void keyPressed(KeyEvent keyEvent) { int code = keyEvent.getKeyCode(); char c = keyEvent.getKeyChar(); System.out.println(c + ":" + code + ":" + (int) c); try { switch (code) { case KeyEvent.VK_BACK_SPACE: case KeyEvent.VK_DELETE: mChimpDevice.getManager().press("KEYCODE_DEL"); break; case KeyEvent.VK_SPACE: if (isGlass()) { mChimpDevice.getManager().press("KEYCODE_DPAD_CENTER"); } else { mChimpDevice.getManager().press("KEYCODE_SPACE"); } break; case KeyEvent.VK_ESCAPE: mChimpDevice.getManager().press("KEYCODE_HOME"); break; case KeyEvent.VK_LEFT: mChimpDevice.getManager().press("KEYCODE_DPAD_LEFT"); break; case KeyEvent.VK_RIGHT: mChimpDevice.getManager().press("KEYCODE_DPAD_RIGHT"); break; case KeyEvent.VK_UP: mChimpDevice.getManager().press("KEYCODE_DPAD_UP"); break; case KeyEvent.VK_DOWN: mChimpDevice.getManager().press("KEYCODE_DPAD_DOWN"); break; default: mChimpDevice.getManager().type(c); break; } } catch (IOException e) { e.printStackTrace(); } } }; public class MainPanel extends JPanel { private FBImage mFBImage; public MainPanel() { setBackground(Color.BLACK); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (mFBImage != null) { int srcWidth; int srcHeight; int dstWidth; int dstHeight; if (mPortrait) { srcWidth = mRawImageWidth; srcHeight = mRawImageHeight; } else { srcWidth = mRawImageHeight; srcHeight = mRawImageWidth; } dstWidth = (int) (srcWidth * mZoom); dstHeight = (int) (srcHeight * mZoom); if (mZoom == 1.0) { g.drawImage(mFBImage, 0, 0, dstWidth, dstHeight, 0, 0, srcWidth, srcHeight, null); } else { Image image = mFBImage.getScaledInstance(dstWidth, dstHeight, Image.SCALE_SMOOTH); if (image != null) { g.drawImage(image, 0, 0, dstWidth, dstHeight, 0, 0, dstWidth, dstHeight, null); } } } } public void setFBImage(FBImage fbImage) { mFBImage = fbImage; repaint(); } public FBImage getFBImage() { return mFBImage; } } public class MonitorThread extends Thread { @Override public void run() { Thread thread = Thread.currentThread(); if (mDevice != null) { try { while (mMonitorThread == thread) { final FBImage fbImage = getDeviceImage(); SwingUtilities.invokeLater(new Runnable() { public void run() { setImage(fbImage); } }); } } catch (IOException e) { } } } private FBImage getDeviceImage() throws IOException { boolean success = true; boolean debug = false; FBImage fbImage = null; RawImage tmpRawImage = null; RawImage rawImage = null; if (success) { try { tmpRawImage = mDevice.getScreenshot(); if (tmpRawImage == null) { success = false; } else { if (debug == false) { rawImage = tmpRawImage; } else { rawImage = new RawImage(); rawImage.version = 1; rawImage.bpp = 32; rawImage.size = tmpRawImage.width * tmpRawImage.height * 4; rawImage.width = tmpRawImage.width; rawImage.height = tmpRawImage.height; rawImage.red_offset = 0; rawImage.red_length = 8; rawImage.blue_offset = 16; rawImage.blue_length = 8; rawImage.green_offset = 8; rawImage.green_length = 8; rawImage.alpha_offset = 0; rawImage.alpha_length = 0; rawImage.data = new byte[rawImage.size]; int index = 0; int dst = 0; for (int y = 0; y < rawImage.height; y++) { for (int x = 0; x < rawImage.width; x++) { int value = tmpRawImage.data[index++] & 0x00FF; value |= (tmpRawImage.data[index++] << 8) & 0xFF00; int r = ((value >> 11) & 0x01F) << 3; int g = ((value >> 5) & 0x03F) << 2; int b = ((value >> 0) & 0x01F) << 3; // little endian rawImage.data[dst++] = (byte) r; rawImage.data[dst++] = (byte) g; rawImage.data[dst++] = (byte) b; rawImage.data[dst++] = (byte) 0xFF; // // big endian // rawImage.data[dst++] = (byte) 0xFF; // rawImage.data[dst++] = (byte) b; // rawImage.data[dst++] = (byte) g; // rawImage.data[dst++] = (byte) r; } } } } } catch (IOException ioe) { } catch (TimeoutException e) { e.printStackTrace(); } catch (AdbCommandRejectedException e) { e.printStackTrace(); } finally { if ((rawImage == null) || ((rawImage.bpp != 16) && (rawImage.bpp != 32))) { success = false; } } } if (success) { final int imageWidth; final int imageHeight; if (mPortrait) { imageWidth = rawImage.width; imageHeight = rawImage.height; } else { imageWidth = rawImage.height; imageHeight = rawImage.width; } fbImage = new FBImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB, // BufferedImage.TYPE_INT_ARGB rawImage.width, rawImage.height); final byte[] buffer = rawImage.data; final int redOffset = rawImage.red_offset; final int greenOffset = rawImage.green_offset; final int blueOffset = rawImage.blue_offset; final int alphaOffset = rawImage.alpha_offset; final int redMask = getMask(rawImage.red_length); final int greenMask = getMask(rawImage.green_length); final int blueMask = getMask(rawImage.blue_length); final int alphaMask = getMask(rawImage.alpha_length); final int redShift = (8 - rawImage.red_length); final int greenShift = (8 - rawImage.green_length); final int blueShift = (8 - rawImage.blue_length); final int alphaShift = (8 - rawImage.alpha_length); int index = 0; final int offset0; final int offset1; final int offset2; final int offset3; if (rawImage.bpp == 16) { offset0 = 0; offset1 = 1; if (mPortrait) { int[] lineBuf = new int[rawImage.width]; for (int y = 0; y < rawImage.height; y++) { for (int x = 0; x < rawImage.width; x++, index += 2) { int value = buffer[index + offset0] & 0x00FF; value |= (buffer[index + offset1] << 8) & 0xFF00; int r = ((value >>> redOffset) & redMask) << redShift; int g = ((value >>> greenOffset) & greenMask) << greenShift; int b = ((value >>> blueOffset) & blueMask) << blueShift; lineBuf[x] = 255 << 24 | r << 16 | g << 8 | b; } fbImage.setRGB(0, y, rawImage.width, 1, lineBuf, 0, rawImage.width); } } else { for (int y = 0; y < rawImage.height; y++) { for (int x = 0; x < rawImage.width; x++) { int value = buffer[index + offset0] & 0x00FF; value |= (buffer[index + offset1] << 8) & 0xFF00; int r = ((value >>> redOffset) & redMask) << redShift; int g = ((value >>> greenOffset) & greenMask) << greenShift; int b = ((value >>> blueOffset) & blueMask) << blueShift; value = 255 << 24 | r << 16 | g << 8 | b; index += 2; fbImage .setRGB(y, rawImage.width - x - 1, value); } } } } else if (rawImage.bpp == 32) { offset0 = FB_OFFSET_LIST[mFbType][0]; offset1 = FB_OFFSET_LIST[mFbType][1]; offset2 = FB_OFFSET_LIST[mFbType][2]; offset3 = FB_OFFSET_LIST[mFbType][3]; if (mPortrait) { int[] lineBuf = new int[rawImage.width]; for (int y = 0; y < rawImage.height; y++) { for (int x = 0; x < rawImage.width; x++, index += 4) { int value = buffer[index + offset0] & 0x00FF; value |= (buffer[index + offset1] & 0x00FF) << 8; value |= (buffer[index + offset2] & 0x00FF) << 16; value |= (buffer[index + offset3] & 0x00FF) << 24; final int r = ((value >>> redOffset) & redMask) << redShift; final int g = ((value >>> greenOffset) & greenMask) << greenShift; final int b = ((value >>> blueOffset) & blueMask) << blueShift; final int a; if (rawImage.alpha_length == 0) { a = 0xFF; } else { a = ((value >>> alphaOffset) & alphaMask) << alphaShift; } lineBuf[x] = a << 24 | r << 16 | g << 8 | b; } fbImage.setRGB(0, y, rawImage.width, 1, lineBuf, 0, rawImage.width); } } else { for (int y = 0; y < rawImage.height; y++) { for (int x = 0; x < rawImage.width; x++) { int value; value = buffer[index + offset0] & 0x00FF; value |= (buffer[index + offset1] & 0x00FF) << 8; value |= (buffer[index + offset2] & 0x00FF) << 16; value |= (buffer[index + offset3] & 0x00FF) << 24; final int r = ((value >>> redOffset) & redMask) << redShift; final int g = ((value >>> greenOffset) & greenMask) << greenShift; final int b = ((value >>> blueOffset) & blueMask) << blueShift; final int a; if (rawImage.alpha_length == 0) { a = 0xFF; } else { a = ((value >>> alphaOffset) & alphaMask) << alphaShift; } value = a << 24 | r << 16 | g << 8 | b; index += 4; fbImage .setRGB(y, rawImage.width - x - 1, value); } } } } } return fbImage; } public int getMask(int length) { int res = 0; for (int i = 0 ; i < length ; i++) { res = (res << 1) + 1; } return res; } } }