ng2-file-upload icon indicating copy to clipboard operation
ng2-file-upload copied to clipboard

Exif orientation issue

Open smsoo opened this issue 8 years ago • 10 comments

Does ng2-file-upload have an option to apply exif orientation on the client side? When a photo is uploaded from the iPhone, it is always rotated 90 degrees. Not sure if there is a workaround for this issue. Any suggestions would be appreciated.

smsoo avatar Dec 14 '16 14:12 smsoo

I have the same issue when files are uploaded. Is this a bug?

Gillardo avatar May 26 '17 08:05 Gillardo

The same issue here

raeef-refai avatar Aug 20 '17 11:08 raeef-refai

Does anybody found the fix for this issue? I'm with the same problen.

Regards.

emersonlimap avatar May 07 '18 14:05 emersonlimap

I have managed to rotate the image using blueimp-load-image library:

  1. Instal the library by running npm i blueimp-load-image.
  2. Add the following script to your angular.json file:
{
  "projects": {
    "my-project": {
      "architect": {
        "build": {
          "options": {
            "scripts": ["./node_modules/blueimp-load-image/js/load-image.all.min.js"]

Or alternatively, you can include just necessary parts which should result in smaller bundle size:

"scripts": [
  "./node_modules/blueimp-load-image/js/load-image.js",
  "./node_modules/blueimp-load-image/js/load-image-scale.js",
  "./node_modules/blueimp-load-image/js/load-image-meta.js",
  "./node_modules/blueimp-load-image/js/load-image-orientation.js",
  "./node_modules/blueimp-load-image/js/load-image-exif.js"
]
  1. Define this function in some utils file:
declare let loadImage: any;

export function rotateImageBasedOnExifData(file: File): Promise<Blob> {
  return new Promise((resolve, reject) => {
    loadImage.parseMetaData(file, (data) => {
      const orientation = data.exif ? data.exif.get('Orientation') : 0;
      loadImage(
        file,
        (canvas) => canvas.toBlob((blob) => resolve(blob), 'image/jpeg'),
        { canvas: true, orientation }
      );
    });
  });
}

livthomas avatar Dec 17 '18 13:12 livthomas

Thanks @livthomas This worked perfectly!

aharris avatar Mar 13 '19 01:03 aharris

@livthomas can u add the 4th step, which is how to use this function, do you override thefileitem._file ? if yes, why would you convert this File to a Blob ?

mzane42 avatar Jun 03 '19 10:06 mzane42

@mzane42 Sure, I use it like this to show the image which is being uploaded:

export class MyComponent implements OnInit, OnDestroy {
  public imageUrl$ = new BehaviorSubject<string>('');
  private imageObjectUrl: string;

  private uploader: FileUploader;

  constructor(private domSanitizer: DomSanitizer) {}

  public ngOnInit() {
    this.uploader.onAfterAddingFile = (itemFile) => {
      itemFile.formData = { description: '' };
      rotateImageBasedOnExifData(itemFile._file).then((blob) => {
        this.imageObjectUrl = URL.createObjectURL(blob);
        const imageUrl = this.domSanitizer.bypassSecurityTrustUrl(this.imageObjectUrl);
        this.imageUrl$.next(imageUrl);
      });
    };
  }

  public ngOnDestroy() {
    freeImageObjectUrl(this.imageObjectUrl);
  }
}

And freeImageObjectUrl used in the code above is another of my util functions:

export function freeImageObjectUrl(imageObjectUrl: string) {
  if (!imageObjectUrl) {
    return;
  }

  try {
    URL.revokeObjectURL(imageObjectUrl);
  } catch (e) {
    console.error(e);
  }
}

HTMLCanvasElement has only toBlob method and no toFile. That's the reason why return value type is Blob.

livthomas avatar Jun 03 '19 11:06 livthomas

@livthomas Thanks for your fast reply, you're awesome man \o/

mzane42 avatar Jun 03 '19 11:06 mzane42

Thanks @livthomas I have this same problem. I have tried to implement the fix you propose, but something I am not doing well. After step 3, what do I have to do to finish implementing it?

amartinezg2001 avatar Dec 18 '19 12:12 amartinezg2001

@amartinezg2001 You just need to create an object URL, pass it to Angular DOM sanitizer and then use the result as an image source URL in your template. I explained that in my previous comment.

But it's been a year since I posted it here and new versions of both libraries were released in the meantime so there's a chance something has changed and it doesn't work anymore.

livthomas avatar Dec 18 '19 14:12 livthomas