diff --git a/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentCreationTask.java b/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentCreationTask.java
index d9e77d1d81ce81d134dbc4137b653af8a0dcc133..e9139be2518fbe34d37c90720e777ec3bf82e6be 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentCreationTask.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentCreationTask.java
@@ -1,6 +1,8 @@
 package org.briarproject.briar.android.attachment;
 
 import android.content.ContentResolver;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory.Options;
 import android.net.Uri;
 import android.support.annotation.Nullable;
 
@@ -12,11 +14,17 @@ import org.briarproject.briar.api.messaging.AttachmentHeader;
 import org.briarproject.briar.api.messaging.MessagingManager;
 import org.jsoup.UnsupportedMimeTypeException;
 
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Collection;
 import java.util.logging.Logger;
 
+import static android.graphics.Bitmap.CompressFormat.JPEG;
+import static android.graphics.BitmapFactory.decodeStream;
+import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 import static java.util.logging.Logger.getLogger;
 import static org.briarproject.bramble.util.IoUtils.tryToClose;
@@ -24,6 +32,7 @@ import static org.briarproject.bramble.util.LogUtils.logDuration;
 import static org.briarproject.bramble.util.LogUtils.logException;
 import static org.briarproject.bramble.util.LogUtils.now;
 import static org.briarproject.briar.api.messaging.MessagingConstants.IMAGE_MIME_TYPES;
+import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_IMAGE_SIZE;
 
 @NotNullByDefault
 class AttachmentCreationTask {
@@ -31,8 +40,11 @@ class AttachmentCreationTask {
 	private static Logger LOG =
 			getLogger(AttachmentCreationTask.class.getName());
 
+	private static final int MAX_ATTACHMENT_DIMENSION = 1000;
+
 	private final MessagingManager messagingManager;
 	private final ContentResolver contentResolver;
+	private final ImageSizeCalculator imageSizeCalculator;
 	private final GroupId groupId;
 	private final Collection<Uri> uris;
 	private final boolean needsSize;
@@ -43,24 +55,26 @@ class AttachmentCreationTask {
 
 	AttachmentCreationTask(MessagingManager messagingManager,
 			ContentResolver contentResolver,
-			AttachmentCreator attachmentCreator, GroupId groupId,
-			Collection<Uri> uris, boolean needsSize) {
+			AttachmentCreator attachmentCreator,
+			ImageSizeCalculator imageSizeCalculator,
+			GroupId groupId, Collection<Uri> uris, boolean needsSize) {
 		this.messagingManager = messagingManager;
 		this.contentResolver = contentResolver;
+		this.imageSizeCalculator = imageSizeCalculator;
 		this.groupId = groupId;
 		this.uris = uris;
 		this.needsSize = needsSize;
 		this.attachmentCreator = attachmentCreator;
 	}
 
-	public void cancel() {
+	void cancel() {
 		canceled = true;
 		attachmentCreator = null;
 	}
 
 	@IoExecutor
-	public void storeAttachments() {
-		for (Uri uri: uris) processUri(uri);
+	void storeAttachments() {
+		for (Uri uri : uris) processUri(uri);
 		AttachmentCreator attachmentCreator = this.attachmentCreator;
 		if (!canceled && attachmentCreator != null)
 			attachmentCreator.onAttachmentCreationFinished();
@@ -98,6 +112,8 @@ class AttachmentCreationTask {
 		}
 		InputStream is = contentResolver.openInputStream(uri);
 		if (is == null) throw new IOException();
+		is = compressImage(is, contentType);
+		contentType = "image/jpeg";
 		long timestamp = System.currentTimeMillis();
 		AttachmentHeader h = messagingManager
 				.addLocalAttachment(groupId, timestamp, contentType, is);
@@ -113,4 +129,48 @@ class AttachmentCreationTask {
 		return false;
 	}
 
+	private InputStream compressImage(InputStream is, String contentType)
+			throws IOException {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		try {
+			Bitmap bitmap = createBitmap(is, contentType);
+			for (int quality = 100; quality >= 0; quality -= 10) {
+				if (!bitmap.compress(JPEG, quality, out))
+					throw new IOException();
+				if (out.size() <= MAX_IMAGE_SIZE) {
+					if (LOG.isLoggable(INFO)) {
+						LOG.info("Compressed image to "
+								+ out.size() + " bytes, quality " + quality);
+					}
+					return new ByteArrayInputStream(out.toByteArray());
+				}
+				out.reset();
+			}
+			throw new IOException();
+		} finally {
+			tryToClose(is, LOG, WARNING);
+		}
+	}
+
+	private Bitmap createBitmap(InputStream is, String contentType)
+			throws IOException {
+		is = new BufferedInputStream(is);
+		Size size = imageSizeCalculator.getSize(is, contentType);
+		if (size.error) throw new IOException();
+		if (LOG.isLoggable(INFO))
+			LOG.info("Original image size: " + size.width + "x" + size.height);
+		int dimension = Math.max(size.width, size.height);
+		int scale = 1;
+		while (dimension > MAX_ATTACHMENT_DIMENSION) {
+			scale *= 2;
+			dimension /= 2;
+		}
+		if (LOG.isLoggable(INFO))
+			LOG.info("Scaling attachment by factor of " + scale);
+		Options options = new Options();
+		options.inSampleSize = scale;
+		Bitmap bitmap = decodeStream(is, null, options);
+		if (bitmap == null) throw new IOException();
+		return bitmap;
+	}
 }
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentCreatorImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentCreatorImpl.java
index bdf9d852dc787203da2a5612f1342be5afd7580d..e78be6805ff3a829cd12875b6989955fc36b3873 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentCreatorImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/attachment/AttachmentCreatorImpl.java
@@ -47,6 +47,7 @@ class AttachmentCreatorImpl implements AttachmentCreator {
 	private final Executor ioExecutor;
 	private final MessagingManager messagingManager;
 	private final AttachmentRetriever retriever;
+	private final ImageSizeCalculator imageSizeCalculator;
 
 	private final CopyOnWriteArrayList<Uri> uris = new CopyOnWriteArrayList<>();
 	private final CopyOnWriteArrayList<AttachmentItemResult> itemResults =
@@ -60,11 +61,13 @@ class AttachmentCreatorImpl implements AttachmentCreator {
 
 	@Inject
 	AttachmentCreatorImpl(Application app, @IoExecutor Executor ioExecutor,
-			MessagingManager messagingManager, AttachmentRetriever retriever) {
+			MessagingManager messagingManager, AttachmentRetriever retriever,
+			ImageSizeCalculator imageSizeCalculator) {
 		this.app = app;
 		this.ioExecutor = ioExecutor;
 		this.messagingManager = messagingManager;
 		this.retriever = retriever;
+		this.imageSizeCalculator = imageSizeCalculator;
 	}
 
 	@Override
@@ -78,7 +81,8 @@ class AttachmentCreatorImpl implements AttachmentCreator {
 			if (id == null) throw new IllegalStateException();
 			boolean needsSize = uris.size() == 1;
 			task = new AttachmentCreationTask(messagingManager,
-					app.getContentResolver(), this, id, uris, needsSize);
+					app.getContentResolver(), this, imageSizeCalculator, id,
+					uris, needsSize);
 			ioExecutor.execute(() -> task.storeAttachments());
 		});
 		MutableLiveData<AttachmentResult> result = new MutableLiveData<>();