diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/AbstractDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/AbstractDeviceSupport.java index 73578f1fa..8387ee3ed 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/AbstractDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/AbstractDeviceSupport.java @@ -8,6 +8,9 @@ import android.support.v4.content.LocalBroadcastManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.text.SimpleDateFormat; +import java.util.Date; + import nodomain.freeyourgadget.gadgetbridge.activities.SleepChartActivity; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppInfo; @@ -141,6 +144,8 @@ public abstract class AbstractDeviceSupport implements DeviceSupport { } private void handleGBDeviceEvent(GBDeviceEventScreenshot screenshot) { - GB.writeScreenshot(screenshot, null); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd-hhmmss"); + + GB.writeScreenshot(screenshot, "screenshot_" + dateFormat.format(new Date()) + ".bmp"); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GB.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GB.java index c133a71c6..1e2821bed 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GB.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GB.java @@ -13,6 +13,13 @@ import android.support.v4.app.NotificationCompat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventScreenshot; import nodomain.freeyourgadget.gadgetbridge.externalevents.K9Receiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.MusicPlaybackReceiver; @@ -105,7 +112,59 @@ public class GB { } public static void writeScreenshot(GBDeviceEventScreenshot screenshot, String filename) { - LOG.info("got screenshot: " + screenshot.width + "x" + screenshot.height + "x" + screenshot.bpp + "bpp"); - // TODO encode bmp or something trivial + + LOG.info("Will write screenshot: " + screenshot.width + "x" + screenshot.height + "x" + screenshot.bpp + "bpp"); + final int FILE_HEADER_SIZE = 14; + final int INFO_HEADER_SIZE = 40; + + File dir = GBApplication.getContext().getExternalFilesDir(null); + if (dir != null) { + if (!dir.exists()) { + dir.mkdirs(); + } + } + FileOutputStream fos; + try { + fos = new FileOutputStream(dir + "/" + filename); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return; + } + + ByteBuffer headerbuf = ByteBuffer.allocate(FILE_HEADER_SIZE + INFO_HEADER_SIZE + screenshot.clut.length); + headerbuf.order(ByteOrder.LITTLE_ENDIAN); + + // file header + headerbuf.put((byte) 'B'); + headerbuf.put((byte) 'M'); + headerbuf.putInt(0); // size in bytes (unconpressed = 0) + headerbuf.putInt(0); // reserved + headerbuf.putInt(FILE_HEADER_SIZE + INFO_HEADER_SIZE + screenshot.clut.length); + + // info header + headerbuf.putInt(INFO_HEADER_SIZE); + headerbuf.putInt(screenshot.width); + headerbuf.putInt(-screenshot.height); + headerbuf.putShort((short) 1); // planes + headerbuf.putShort((short) 1); // bit count + headerbuf.putInt(0); // compression + headerbuf.putInt(0); // length of pixeldata in byte (uncompressed=0) + headerbuf.putInt(0); // pixels per meter (x) + headerbuf.putInt(0); // pixels per meter (y) + headerbuf.putInt(2); // number of colors in CLUT + headerbuf.putInt(2); // numbers of used colors + headerbuf.put(screenshot.clut); + try { + fos.write(headerbuf.array()); + int rowbytes = screenshot.width / 8; + byte[] pad = new byte[rowbytes % 4]; + for (int i = 0; i < screenshot.height; i++) { + fos.write(screenshot.data, rowbytes * i, rowbytes); + fos.write(pad); + } + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleProtocol.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleProtocol.java index dc06038f6..af4987044 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleProtocol.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleProtocol.java @@ -723,6 +723,15 @@ public class PebbleProtocol extends GBDeviceProtocol { return buf.array(); } + private static byte reverseBits(byte in) { + byte out = 0; + for (int i = 0; i < 8; i++) { + byte bit = (byte) (in & 1); + out = (byte) ((out << 1) | bit); + in = (byte) (in >> 1); + } + return out; + } private GBDeviceEvent decodeResponseScreenshot(ByteBuffer buf, int length) { if (mDevEventScreenshot == null) { @@ -735,6 +744,10 @@ public class PebbleProtocol extends GBDeviceProtocol { mDevEventScreenshot.width = buf.getInt(); mDevEventScreenshot.height = buf.getInt(); mDevEventScreenshot.bpp = 1; + mDevEventScreenshot.clut = new byte[]{ + 0x00, 0x00, 0x00, 0x00, (byte) 0xff, + (byte) 0xff, (byte) 0xff, 0x00 + }; mScreenshotRemaining = (mDevEventScreenshot.width * mDevEventScreenshot.height) / 8; if (mScreenshotRemaining > 50000) { @@ -748,7 +761,11 @@ public class PebbleProtocol extends GBDeviceProtocol { return null; } - buf.get(mDevEventScreenshot.data, mDevEventScreenshot.data.length - mScreenshotRemaining, length); + for (int i = 0; i < length; i++) { + byte corrected = reverseBits(buf.get()); + mDevEventScreenshot.data[mDevEventScreenshot.data.length - mScreenshotRemaining + i] = corrected; + } + mScreenshotRemaining -= length; LOG.info("Screenshot remaining bytes " + mScreenshotRemaining); if (mScreenshotRemaining == 0) {