mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-12 13:09:24 +01:00
Pebble: save screenshots as 1bit Windows 3.x BMP
TODO: - user feedback - support Pebble Time
This commit is contained in:
parent
d0178686d8
commit
a73d8b7f0a
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user