From d2f60baef990221123f11e46dcde403ca5c13d52 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Thu, 11 Oct 2018 14:15:01 +0100 Subject: [PATCH] Handle vectors (#187) * Allow loading SVG. Fixes #138. I also made the resizer vector-aware, so you can resize the image larger & stay sharp. * Handling SVG without width/height set. * Simplifying maths * Doh, case sensitive --- src/codecs/resize/options.tsx | 4 ++- src/codecs/resize/resize.ts | 58 +++++++++++++++++++++++++------- src/components/App/index.tsx | 58 ++++++++++++++++++++++++++++---- src/components/Options/index.tsx | 12 +++---- src/lib/util.ts | 37 ++++++++++++++++---- 5 files changed, 137 insertions(+), 32 deletions(-) diff --git a/src/codecs/resize/options.tsx b/src/codecs/resize/options.tsx index 261326ff..8319bbb3 100644 --- a/src/codecs/resize/options.tsx +++ b/src/codecs/resize/options.tsx @@ -4,6 +4,7 @@ import { bind, inputFieldValueAsNumber } from '../../lib/util'; import { ResizeOptions } from './resize'; interface Props { + isVector: Boolean; options: ResizeOptions; aspect: number; onChange(newOptions: ResizeOptions): void; @@ -63,7 +64,7 @@ export default class ResizerOptions extends Component { this.form!.width.value = Math.round(height * this.props.aspect); } - render({ options, aspect }: Props, { maintainAspect }: State) { + render({ options, aspect, isVector }: Props, { maintainAspect }: State) { return (
this.form = el}> {preprocessorState.resize.enabled && @@ -223,7 +223,7 @@ export default class Options extends Component { increaseClass={style.increase} decreaseClass={style.decrease} file={imageFile} - compareTo={imageFile === sourceImageFile ? undefined : sourceImageFile} + compareTo={imageFile === source.file ? undefined : source.file} /> {(downloadUrl && imageFile) && ( diff --git a/src/lib/util.ts b/src/lib/util.ts index a1e7e8cc..b9cbb374 100644 --- a/src/lib/util.ts +++ b/src/lib/util.ts @@ -95,6 +95,10 @@ export function blobToArrayBuffer(blob: Blob): Promise { return new Response(blob).arrayBuffer(); } +export function blobToText(blob: Blob): Promise { + return new Response(blob).text(); +} + const magicNumberToMimeType = new Map([ [/^%PDF-/, 'application/pdf'], [/^GIF87a/, 'image/gif'], @@ -122,7 +126,7 @@ export async function sniffMimeType(blob: Blob): Promise { return ''; } -async function blobToImg(blob: Blob): Promise { +export async function blobToImg(blob: Blob): Promise { const url = URL.createObjectURL(blob); try { @@ -147,16 +151,37 @@ async function blobToImg(blob: Blob): Promise { } } -function drawableToImageData(drawable: ImageBitmap | HTMLImageElement): ImageData { +interface DrawableToImageDataOptions { + width?: number; + height?: number; + sx?: number; + sy?: number; + sw?: number; + sh?: number; +} + +export function drawableToImageData( + drawable: ImageBitmap | HTMLImageElement, + opts: DrawableToImageDataOptions = {}, +): ImageData { + const { + width = drawable.width, + height = drawable.height, + sx = 0, + sy = 0, + sw = drawable.width, + sh = drawable.height, + } = opts; + // Make canvas same size as image const canvas = document.createElement('canvas'); - canvas.width = drawable.width; - canvas.height = drawable.height; + canvas.width = width; + canvas.height = height; // Draw image onto canvas const ctx = canvas.getContext('2d'); if (!ctx) throw new Error('Could not create canvas context'); - ctx.drawImage(drawable, 0, 0); - return ctx.getImageData(0, 0, drawable.width, drawable.height); + ctx.drawImage(drawable, sx, sy, sw, sh, 0, 0, width, height); + return ctx.getImageData(0, 0, width, height); } export async function nativeDecode(blob: Blob): Promise {