Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support EXIF orientation for network JPG/TIFF #692

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion picasso/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@
<artifactId>okhttp-urlconnection</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.apache.sanselan</groupId>
<artifactId>sanselan</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.NetworkInfo;
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.Sanselan;
import org.apache.sanselan.common.IImageMetadata;
import org.apache.sanselan.formats.jpeg.JpegImageMetadata;
import org.apache.sanselan.formats.tiff.TiffField;
import org.apache.sanselan.formats.tiff.TiffImageMetadata;
import org.apache.sanselan.formats.tiff.constants.TiffTagConstants;

import java.io.IOException;
import java.io.InputStream;

Expand All @@ -32,12 +40,19 @@ class NetworkRequestHandler extends RequestHandler {
private static final String SCHEME_HTTP = "http";
private static final String SCHEME_HTTPS = "https";

// These constants are not defined in Sanselan
static final int ORIENTATION_VALUE_ROTATE_180 = 3;
static final int ORIENTATION_VALUE_ROTATE_90_CW = 6;
static final int ORIENTATION_VALUE_ROTATE_270_CW = 8;

private final Downloader downloader;
private final Stats stats;
private final boolean hasImaging;

public NetworkRequestHandler(Downloader downloader, Stats stats) {
this.downloader = downloader;
this.stats = stats;
this.hasImaging = isImagingOnClasspath();
}

@Override public boolean canHandleRequest(Request data) {
Expand Down Expand Up @@ -72,7 +87,11 @@ public NetworkRequestHandler(Downloader downloader, Stats stats) {
stats.dispatchDownloadFinished(response.getContentLength());
}
try {
return new Result(decodeStream(is, data), loadedFrom);
MarkableInputStream markStream = new MarkableInputStream(is);
long mark = markStream.savePosition(MARKER);
int orientation = getOrientation(markStream);
markStream.reset(mark);
return new Result(decodeStream(markStream, data), loadedFrom, orientation);
} finally {
Utils.closeQuietly(is);
}
Expand All @@ -90,17 +109,14 @@ public NetworkRequestHandler(Downloader downloader, Stats stats) {
return true;
}

private Bitmap decodeStream(InputStream stream, Request data) throws IOException {
MarkableInputStream markStream = new MarkableInputStream(stream);
stream = markStream;

long mark = markStream.savePosition(MARKER);
private Bitmap decodeStream(MarkableInputStream stream, Request data) throws IOException {
long mark = stream.savePosition(MARKER);

final BitmapFactory.Options options = createBitmapOptions(data);
final boolean calculateSize = requiresInSampleSize(options);

boolean isWebPFile = Utils.isWebPFile(stream);
markStream.reset(mark);
stream.reset(mark);
// When decode WebP network stream, BitmapFactory throw JNI Exception and make app crash.
// Decode byte array instead
if (isWebPFile) {
Expand All @@ -114,8 +130,7 @@ private Bitmap decodeStream(InputStream stream, Request data) throws IOException
if (calculateSize) {
BitmapFactory.decodeStream(stream, null, options);
calculateInSampleSize(data.targetWidth, data.targetHeight, options, data);

markStream.reset(mark);
stream.reset(mark);
}
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);
if (bitmap == null) {
Expand All @@ -125,4 +140,49 @@ private Bitmap decodeStream(InputStream stream, Request data) throws IOException
return bitmap;
}
}

private int getOrientation(InputStream is) {
if (!hasImaging) {
return 0;
}

try {
IImageMetadata metadata = Sanselan.getMetadata(is, null);
TiffImageMetadata tiffMetaData;
if (metadata instanceof JpegImageMetadata) {
JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
tiffMetaData = jpegMetadata.getExif();
} else if (metadata instanceof TiffImageMetadata) {
tiffMetaData = (TiffImageMetadata) metadata;
} else {
return 0;
}
TiffField orientationField = tiffMetaData.findField(TiffTagConstants.TIFF_TAG_ORIENTATION);
if (orientationField != null) {
int orientationValue = orientationField.getIntValue();
switch (orientationValue) {
case ORIENTATION_VALUE_ROTATE_180:
return 180;
case ORIENTATION_VALUE_ROTATE_90_CW:
return 90;
case ORIENTATION_VALUE_ROTATE_270_CW:
return 270;
default:
return 0;
}
}
} catch (IOException ignored) {
} catch (ImageReadException ignored) {
}
return 0;
}

private Boolean isImagingOnClasspath() {
try {
Class.forName("org.apache.sanselan.Sanselan");
return true;
} catch (ClassNotFoundException ignored) {
return false;
}
}
}
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@
<version>1.6.0</version>
</dependency>

<dependency>
<groupId>org.apache.sanselan</groupId>
<artifactId>sanselan</artifactId>
<version>0.97-incubator</version>
</dependency>

<dependency>
<groupId>com.intellij</groupId>
<artifactId>annotations</artifactId>
Expand Down