JS Client-Side Exif Orientation: Rotate and Mirror JPEG Images
The github project JavaScript-Load-Image provides a complete solution to the EXIF orientation problem, correctly rotating/mirroring images for all 8 exif orientations. See the online demo of javascript exif orientation
The image is drawn onto an HTML5 canvas. Its correct rendering is implemented in js/load-image-orientation.js through canvas operations.
Hope this saves somebody else some time, and teaches the search engines about this open source gem :)
Images being displayed in wrong orientation
I'm guessing the OP is having problems due to EXIF data. If the original images contain EXIF data indicating that they should be rotated, special measures must be taken to get that data interpreted by a web browser when displaying a page. It is discussed here:
Is there a way to tell browsers to honor the jpeg exif orientation?
If the the solutions provided for exif orientation are not acceptable, the OP will have to preprocess the images to rotate them to proper orientation and save them that way on the serverside. Then the correctly rotated images can be delivered on web page.
Photos show up in landscape orientation on a webpage, vertically elsewhere. Why?
Your image has embedded exif orientation data which is presumably being ignored when rendering the page. See this answer for a bit more detail.
Basically, the camera you took the image with stored it in landscape, but stored some metadata with it saying that the image needs to be rotated 270°. The browser is apparently ignoring this tag when rendering it in the webpage, but not when you access the image directly.
Image Upload Not Retrieving Orientation exif data
Solution
I realised that every time it got to the point where it tried to read the exif data using exif_read_data()
the data was already gone.
I resulted to retrieving the exif data within the JavaScript instead using a library called exif.js. Further explanation found here.
What's wrong with the image?
Below is Thilo's answer:
There is a EXIF attribute "Orientation" in the file, set to "3 (rotated 180 degrees)".
Same problem in a .NET image processor: Problem reading JPEG Metadata (Orientation)
Browser support for EXIF orientation is complicated:https://code.google.com/p/chromium/issues/detail?id=56845
And I also found a post about the EXIF "Orientation": Exif Orientation Tag
Thanks Thilo!
Am I serving my images incorrect, they are all shown rotated 90 degrees
Orientation was setted in Exif. Picture wasn't rotated phisicaly.
Image-viewer can to work with it but the browser in tag doesn't rotate it.
Your can rotate pictures on server by imagemagick --auto-orient http://imagemagick.org/Usage/photos/#orient
You can also rotate it "on fly". Just get Exif info by exif_read_data() and rotate it if it has 3(180degree), 6(90CW), or 8(-90CCW) in 'Orientation'
// dump the picture and stop the script
$source = imagecreatefromjpeg($filename);
$exif = exif_read_data($filename);
if (isset($exif['Orientation'])) {
switch($exif['Orientation']) {
case 3: // 180 degree
$rotate=imagerotate($source,180,0);
break;
case 6: // 90 CW
$rotate=imagerotate($source,-90,0);
break;
case 8: // 90 CCW
$rotate=imagerotate($source,90,0);
break;
default:
$rotate=imagerotate($source,0,0);
break;
}
imagejpeg($rotate);
imagedestroy($source);
imagedestroy($rotate);
} else {
imagejpeg($source);
imagedestroy($source);
}
But of course better to prepare all pictures once.
How to rotate JPEG images based on the orientation metadata?
If you want to rotate your images, I would suggest to use the metadata extractor library http://code.google.com/p/metadata-extractor/. You can get the image information with the following code:
// Inner class containing image information
public static class ImageInformation {
public final int orientation;
public final int width;
public final int height;
public ImageInformation(int orientation, int width, int height) {
this.orientation = orientation;
this.width = width;
this.height = height;
}
public String toString() {
return String.format("%dx%d,%d", this.width, this.height, this.orientation);
}
}
public static ImageInformation readImageInformation(File imageFile) throws IOException, MetadataException, ImageProcessingException {
Metadata metadata = ImageMetadataReader.readMetadata(imageFile);
Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
JpegDirectory jpegDirectory = metadata.getFirstDirectoryOfType(JpegDirectory.class);
int orientation = 1;
try {
orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
} catch (MetadataException me) {
logger.warn("Could not get orientation");
}
int width = jpegDirectory.getImageWidth();
int height = jpegDirectory.getImageHeight();
return new ImageInformation(orientation, width, height);
}
Then given the orientation you retrieve, you can rotate and/or flip the image to the right orientation. The Affine transform for the EXIF orientation is given by the following method:
// Look at http://chunter.tistory.com/143 for information
public static AffineTransform getExifTransformation(ImageInformation info) {
AffineTransform t = new AffineTransform();
switch (info.orientation) {
case 1:
break;
case 2: // Flip X
t.scale(-1.0, 1.0);
t.translate(-info.width, 0);
break;
case 3: // PI rotation
t.translate(info.width, info.height);
t.rotate(Math.PI);
break;
case 4: // Flip Y
t.scale(1.0, -1.0);
t.translate(0, -info.height);
break;
case 5: // - PI/2 and Flip X
t.rotate(-Math.PI / 2);
t.scale(-1.0, 1.0);
break;
case 6: // -PI/2 and -width
t.translate(info.height, 0);
t.rotate(Math.PI / 2);
break;
case 7: // PI/2 and Flip
t.scale(-1.0, 1.0);
t.translate(-info.height, 0);
t.translate(0, info.width);
t.rotate( 3 * Math.PI / 2);
break;
case 8: // PI / 2
t.translate(0, info.width);
t.rotate( 3 * Math.PI / 2);
break;
}
return t;
}
The rotation of the image would be done by the following method:
public static BufferedImage transformImage(BufferedImage image, AffineTransform transform) throws Exception {
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BICUBIC);
BufferedImage destinationImage = op.createCompatibleDestImage(image, (image.getType() == BufferedImage.TYPE_BYTE_GRAY) ? image.getColorModel() : null );
Graphics2D g = destinationImage.createGraphics();
g.setBackground(Color.WHITE);
g.clearRect(0, 0, destinationImage.getWidth(), destinationImage.getHeight());
destinationImage = op.filter(image, destinationImage);
return destinationImage;
}
In a server environment, don't forget to run with -Djava.awt.headless=true
Related Topics
Can Outlook 2010 Use a Web Font in an HTML Email
Putting an Image Background Onto a CSS Triangle
Make an Image Width 100% of Parent Div, But Not Bigger Than Its Own Width
How to Create a Frosted Glass Effect Using CSS
How to Force Inline Divs to Stay on Same Line
How to Get the Browser's Default Font Family in CSS
Why Does 'Transform' Break 'Position: Fixed'
What Is Aria-Label and How to Use It
How to Apply a CSS Gradient Over a Text, from a Transparent to an Opaque Colour
Add External CSS File to Blogger Template
How to Use Webp Images and Support Safari
Offline iOS Web App: Loads My Manifest, But Doesn't Work Offline
Why Isn't Position:Sticky with Left:0 Working Inside a Scrollable Container
Twitter Bootstrap: Align Nav-Tabs to Bottom of Div
Equivalent to Float in Outlook