Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Compress images in Angular recursively using rxJS
import { Component } from '@angular/core';
import { map, expand } from 'rxjs/operators';
import { EMPTY } from 'rxjs';
import { CompressorService } from './compressor.service';
@Component({
selector: 'app-root',
template: '<input type="file" (change)="process($event)" multiple/>',
styles: ['']
})
export class AppComponent {
constructor(private compressor: CompressorService) {}
data: FileList;
compressedImages = [];
recursiveCompress = (image: File, index, array) => {
return this.compressor.compress(image).pipe (
map(response => {
//Code block after completing each compression
console.log('compressed ' + index + image.name);
this.compressedImages.push(response);
return {
data: response,
index: index + 1,
array: array,
};
}),
);
}
//process files for upload
public process (event) {
this.data = event.target.files;
console.log('input: ' + this.data);
const compress = this.recursiveCompress( this.data[0], 0, this.data ).pipe(
expand(res => {
return res.index > res.array.length - 1
? EMPTY
: this.recursiveCompress( this.data[res.index], res.index, this.data );
}),
);
compress.subscribe(res => {
if (res.index > res.array.length - 1) {
//Code block after completing all compression
console.log('Compression successful ' + this.compressedImages);
}
});
}
}
import { Injectable } from '@angular/core';
import { Observable} from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class CompressorService {
constructor() { }
compress(file: File): Observable<any> {
const width = 600; // For scaling relative to width
const reader = new FileReader();
reader.readAsDataURL(file);
return Observable.create(observer => {
reader.onload = ev => {
const img = new Image();
img.src = (ev.target as any).result;
(img.onload = () => {
const elem = document.createElement('canvas'); // Use Angular's Renderer2 method
const scaleFactor = width / img.width;
elem.width = width;
elem.height = img.height * scaleFactor;
const ctx = <CanvasRenderingContext2D>elem.getContext('2d');
ctx.drawImage(img, 0, 0, width, img.height * scaleFactor);
ctx.canvas.toBlob(
blob => {
observer.next(
new File([blob], file.name, {
type: 'image/jpeg',
lastModified: Date.now(),
}),
);
},
'image/jpeg',
1,
);
}),
(reader.onerror = error => observer.error(error));
};
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.