Dropzone: horizontally images

Created on 27 Feb 2013  路  36Comments  路  Source: dropzone/dropzone

when I upload a vertical image taken from my ipod this is shown horizontally, only about such images, nose happens if taken with an iphone or an ipad

Most helpful comment

Here is my approach (without modifying Dropzone.js).

1) Include necessary dependencies:

<script src="/js/exif.js"></script>
<script src="/js/load-image.all.min.js"></script>

2) Disable thumbnail option:

createImageThumbnails: false

3) Code for 'addedfile' event handler:

this.on("addedfile", function(file) {
    window.loadImage.parseMetaData(file, function (data) {

        // use embedded thumbnail if exists.
        if (data.exif) {
            var thumbnail = data.exif.get('Thumbnail');
            var orientation = data.exif.get('Orientation');

            if (thumbnail && orientation) {
                window.loadImage(thumbnail, function (img) {
                    self.emit('thumbnail', file, img.toDataURL());
                }, { orientation: orientation });
                return;
            }
        }

        // use default implementation for PNG, etc.
        self.createThumbnail(file);
    });
}

All 36 comments

Interesting. I guess that's because the image is actually horizontal, but the iPod turns it correctly, depending on the EXIF information. I'll look into that some time. I'd have to read out the EXIF information and rotate it correctly... Seems a bit much, especially since I've never encountered the problem

Sorry works fine!! this is a great js but need more functionality, I hope that with the cooperation of all is a great library

What functionality are you talking about? I provided lots of events you can register to to extend functionality. I like to keep the library as simple as possible.

For example control the extension of a file to show thumbnail or not (or maybe the usar can't drag the file), return a response after upload with json for example

You can implement all of that by listening to the events. If you think you're unable to do something feel free to reopen this issue.

Just so you know, this is still a problem, especially with pictures from mobile phones. I've overcome it by using custom thumbnail generation code as provided by the excellent blueimp Load Image javascript library: https://github.com/blueimp/JavaScript-Load-Image

specterstudios do you have a working example? I am sitting with this very same problem right now... so a gist would be nice :-)

@specterstudios , @carstengehling I'm having the same problem too. However, I guess blueimp solution just checks the exif and shows the picture according to that info. The original file is still not vertical.

Isn't there a solution that uploads the picture accordingly? :) Would be really really nice. I know @enyo does not want script to get fat but may be a kind of additional script to work with?

Anyway, if I can't find any other way, I will handle it on my server side. Thanks for the amazing work!

I just did excactly that. I let my server side upload respond with json-data containing a url for a server-side rotated thumbnail, and then uses that as the preview image src instead.

1 - include https://raw.githubusercontent.com/jseidelin/exif-js/master/exif.js

2 - edit dropzone.js

  • Find & Add after img.onload = function() {
    var orientation = 0; EXIF.getData(img, function() { switch(parseInt(EXIF.getTag(this, "Orientation"))){ case 3: orientation = 180; break; case 6: orientation = -90; break; case 8: orientation = 90; break; } });
  • Replace > drawImageIOSFix(ctx to drawImageIOSFix(orientation, ctx
  • Find & Add after vertSquashRatio = detectVerticalSquash(img);
 `dh = dh / vertSquashRatio;

ctx.translate( dx+dw/2, dy+dh/2 );
ctx.rotate(o*Math.PI/180);
dx = -dw/2;
dy = -dh/2;`

@viroxic hey man, great to see you have solution over there.

But can you please attach your dropzone.js file here? Cause I've tried and seems like not working.

And also include exif.js means include in my HTML file right? or within the dropzone.js file?

@viroxic just to clarify... This still just changes the visual orientation on the preview right? One still need to fix the orientation on the server side, once upload has completed.

  1. @carstengehling you are right.
  2. @mypickles, you'll need to make a server side rotation of the image as well if the EXIF of the uploaded image got an "orientation" value different than zero.

with PHP it's like :

<?php //Mimetype validation and all ... $exif = exif_read_data($img); $rotate = null; switch($exif['Orientation']){ case 3: $rotate = 180; break; case 6: $rotate = -90; break; case 8: $rotate = 90; break; } if($rotate){ rotateImage($img)->withAngle($rotate); } ?>

Files :

Dropzone : http://khayati.net/dropzone.js

EXIF : http://khayati.net/exif.js

Things to check in the code :

  • Dropzone.prototype.createThumbnail ....
  • drawImageIOSFix = function ....

Finally, if you have any issue, please send me the dropzone you have and I'll edit it for you with comments.
And as carstengehling remembered us, for sure a server side processing should be implemented for a better solution.

@jachine solution did not work for me (it was turning the image upside down), what I ended up doing was copy the transformCoordinates function from this url https://github.com/blueimp/JavaScript-Load-Image/blob/master/js/load-image-orientation.js directly into the drawImageIOSFix function (with some adaptations) without any other modifications to other parts of the code

@alfaro28 don't be too dependent on the javascript solution, since it won't affect the server-side anyway. Instead I suggest, that you do like I did:

Make sure that your server-side upload script returns a json-object with the following attributes:

{
  id: <internal server-side id>,
  thumbnailUrl: <url to a version of the uploaded image that has been rotated server-side>
}

for example:

{
  id: 512,
  thumbnailUrl: "/system/myimages/512-thumbnailed.png"
}

Then apply this to your Dropzone init code:

var myDropzone = new Dropzone(".dropzone", {
  ..other init attributes...
  success: function(file, data) {
    file.id = data.id
    file.previewElement.setAttribute('data-id', data.id);
    this.emit("thumbnail", file, data.thumbnailUrl);
  }
};

This will insert your server-side processed image at the correct place in the Dropzone overview

@carstengehling that's actually a very good idea, I was already modifying the image server side but my client complained about the preview.

I have this same problem and have been trying to read down this forum but am a bit lost since everyone gave their two cents. Can someone lay out a solution so I can follow and try and duplicate the solution? Thanks all!

@jeynon the gist is that you should do the rotation serverside after upload. However you do this depends on your server framework (Rails, PHP, aspx,...) Then your server framework should respond with the json, that I described above.

Thanks @carstengehling ! I actually dug a bit deeper and found another Git ticket that had the answer. https://github.com/enyo/dropzone/issues/615

But that only displays the image correctly on the upload page. You might still need to exif rotate the ima on the server, since not all browsers use exif when displaying the images later on.

I am using exif_read_data() on the php side to get the info and rotate.

Perfect then :-)

patch works but need to replace

ctx.rotate(o*Math.PI/180);

to

ctx.rotate(orientation*Math.PI/180);

I have fixed rotating to the right direction and added handling flipped orientation values. Attached patch file for current version.

This is a backend solution. We dont allow tiff image uploads, so I didnt include the image type check.

$uploadedFile->tempName is the file path eg: "/var/www/site/upload/images/someImage.jpg"

if(exif_imagetype($uploadedFile->tempName) == 2)//2 IMAGETYPE_JPEG
{
    $exif = exif_read_data($uploadedFile->tempName);
    if(!empty($exif['Orientation']))
    {
        $image = imagecreatefromjpeg($uploadedFile->tempName);

        switch($exif['Orientation']) 
                {
        case 8:
            $image = imagerotate($image,90,0);
            break;
        case 3:
            $image = imagerotate($image,180,0);
            break;
        case 6:
            $image = imagerotate($image,-90,0);
            break;
        }
            imagejpeg($image, $uploadedFile->tempName);
    }
}

For people struggling with image orientation, I was able to achieve so by doing the following:

1) Adding blueimp-load-image. For it to get the orientation right it requires the whole bundle (load-image.all.min.js).

2) Adding the following to the thumbnail event:

// Try to access the image's EXIF data to fix the orientation on the client.
this.on('thumbnail', (file) => {
  // loadImage comes from blueimp-load-image
  window.loadImage.parseMetaData(file, (data) => {
    if (data.exif) {
      // In case the EXIF is readable, we display a canvas element
      // with the rotated image and hide the default thumbnail.
      window.loadImage(file, (img) => {
        filepicker.classList.remove('js-dropzone--show-thumbmail');
        document.querySelector('.dz-image').appendChild(img);
      }, {
        orientation: data.exif.get('Orientation'),
      });
    } else {
      // In case the EXIF data is unavailable, we just show the default thumbnail.
      filepicker.classList.add('js-dropzone--show-thumbmail');
    }
  });
}

Here is my approach (without modifying Dropzone.js).

1) Include necessary dependencies:

<script src="/js/exif.js"></script>
<script src="/js/load-image.all.min.js"></script>

2) Disable thumbnail option:

createImageThumbnails: false

3) Code for 'addedfile' event handler:

this.on("addedfile", function(file) {
    window.loadImage.parseMetaData(file, function (data) {

        // use embedded thumbnail if exists.
        if (data.exif) {
            var thumbnail = data.exif.get('Thumbnail');
            var orientation = data.exif.get('Orientation');

            if (thumbnail && orientation) {
                window.loadImage(thumbnail, function (img) {
                    self.emit('thumbnail', file, img.toDataURL());
                }, { orientation: orientation });
                return;
            }
        }

        // use default implementation for PNG, etc.
        self.createThumbnail(file);
    });
}

Kevin, thanks a lot for your great contribution @haoxi911 I tried with all solutions listed here but without good results, until I try with your suggestion and it run well for me.

Just a little change to clarify:

myDropzone.on('addedfile', function(file) {
    var self = this;
    window.loadImage.parseMetaData(file, function (data) {
        // use embedded thumbnail if exists.
        if (data.exif) {
            var thumbnail = data.exif.get('Thumbnail');
            var orientation = data.exif.get('Orientation');
            if (thumbnail && orientation) {
                window.loadImage(thumbnail, function (img) {
                    self.emit('thumbnail', file, img.toDataURL());
                }, { orientation: orientation });
                return;
            }
        }
        // use default implementation for PNG, etc.
        self.createThumbnail(file);
    });
});

I added the myDropzone object and I instanced it with self variable.

Hi @seytone thanks for the solution, it works well for Android. But did you tested it with iOS? To upload photo directly from camera? I've tested it and when takes portrait photo it keeps photo turned 90掳 clockwise :-(

Hi! I have a similar problem. I am trying to block upload (on the client-side) if an image is in portrait mode. I can't figure out at what step I have to include the control. If someone has already done this, I am interested. Thanks!

At least for orientation 6 dropzone rotates thumbnail incorrectly - the result appears shifted to the right. I changed the rotate/translate combination to ctx.transform(0, 1, -1, 0, canvas.width , 0); It fixed the problem.
The solution is taken from https://stackoverflow.com/questions/20600800/js-client-side-exif-orientation-rotate-and-mirror-jpeg-images

Apparently, you just need to include exif-js.
(window.EXIF needs to be defined).
If so, dropzone will use that to properly rotate the thumbnails it generates.

@syastrov Yeah it seems there is already part of code in dropzone source that uses EXIF and all the rotation operations.
Its just that i still dont understand does this orientation problem occurs on some specific devices or all of them depending on how you take the photo with device?

Hi, is there a way to rotate the thumbnail manually? like adding a button that rotates the image 90 degrees every time you click on it?

  • install exif npm package
  • install blueimp-load-image npm package
  • add 'createThumbnail' as callback for the file added event

createThumbnail: function(file){ var scaledImage = loadImage.scale( file, { maxWidth: 150, imageOrientation: true } ); $('[data-dz-thumbnail]').last().attr("src", scaledImage.dataURL); },

What we do is: create thumbnail with correct orientation and replace the faulty thumbnail generated by dropzone

out of all the above post, I can't figure out what to do or where to add/change the code to "prevent image rotation when saving the image file to the server".

Can someone provide the details?
Thanks for your time!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dhardtke picture dhardtke  路  15Comments

rogamoore picture rogamoore  路  19Comments

lox picture lox  路  63Comments

bschmitt picture bschmitt  路  33Comments

leighsmith picture leighsmith  路  18Comments