mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-14 09:39:15 +00:00
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
This commit is contained in:
@@ -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<Props, State> {
|
||||
this.form!.width.value = Math.round(height * this.props.aspect);
|
||||
}
|
||||
|
||||
render({ options, aspect }: Props, { maintainAspect }: State) {
|
||||
render({ options, aspect, isVector }: Props, { maintainAspect }: State) {
|
||||
return (
|
||||
<form ref={el => this.form = el}>
|
||||
<label>
|
||||
@@ -73,6 +74,7 @@ export default class ResizerOptions extends Component<Props, State> {
|
||||
value={options.method}
|
||||
onChange={this.onChange}
|
||||
>
|
||||
{isVector && <option value="vector">Vector</option>}
|
||||
<option value="browser-pixelated">Browser pixelated</option>
|
||||
<option value="browser-low">Browser low quality</option>
|
||||
<option value="browser-medium">Browser medium quality</option>
|
||||
|
||||
@@ -1,21 +1,28 @@
|
||||
import { nativeResize, NativeResizeMethod } from '../../lib/util';
|
||||
import { nativeResize, NativeResizeMethod, drawableToImageData } from '../../lib/util';
|
||||
|
||||
export function resize(data: ImageData, opts: ResizeOptions): ImageData {
|
||||
function getCoverOffsets(sw: number, sh: number, dw: number, dh: number) {
|
||||
const currentAspect = sw / sh;
|
||||
const endAspect = dw / dh;
|
||||
|
||||
if (endAspect > currentAspect) {
|
||||
const newSh = sw / endAspect;
|
||||
const newSy = (sh - newSh) / 2;
|
||||
return { sw, sh: newSh, sx: 0, sy: newSy };
|
||||
}
|
||||
|
||||
const newSw = sh * endAspect;
|
||||
const newSx = (sw - newSw) / 2;
|
||||
return { sh, sw: newSw, sx: newSx, sy: 0 };
|
||||
}
|
||||
|
||||
export function resize(data: ImageData, opts: BitmapResizeOptions): ImageData {
|
||||
let sx = 0;
|
||||
let sy = 0;
|
||||
let sw = data.width;
|
||||
let sh = data.height;
|
||||
|
||||
if (opts.fitMethod === 'cover') {
|
||||
const currentAspect = data.width / data.height;
|
||||
const endAspect = opts.width / opts.height;
|
||||
if (endAspect > currentAspect) {
|
||||
sh = opts.height / (opts.width / data.width);
|
||||
sy = (data.height - sh) / 2;
|
||||
} else {
|
||||
sw = opts.width / (opts.height / data.height);
|
||||
sx = (data.width - sw) / 2;
|
||||
}
|
||||
({ sx, sy, sw, sh } = getCoverOffsets(sw, sh, opts.width, opts.height));
|
||||
}
|
||||
|
||||
return nativeResize(
|
||||
@@ -24,18 +31,45 @@ export function resize(data: ImageData, opts: ResizeOptions): ImageData {
|
||||
);
|
||||
}
|
||||
|
||||
export function vectorResize(data: HTMLImageElement, opts: VectorResizeOptions): ImageData {
|
||||
let sx = 0;
|
||||
let sy = 0;
|
||||
let sw = data.width;
|
||||
let sh = data.height;
|
||||
|
||||
if (opts.fitMethod === 'cover') {
|
||||
({ sx, sy, sw, sh } = getCoverOffsets(sw, sh, opts.width, opts.height));
|
||||
}
|
||||
|
||||
return drawableToImageData(data, {
|
||||
sx, sy, sw, sh,
|
||||
width: opts.width, height: opts.height,
|
||||
});
|
||||
}
|
||||
|
||||
type BitmapResizeMethods = 'browser-pixelated' | 'browser-low' | 'browser-medium' | 'browser-high';
|
||||
|
||||
export interface ResizeOptions {
|
||||
width: number;
|
||||
height: number;
|
||||
method: 'browser-pixelated' | 'browser-low' | 'browser-medium' | 'browser-high';
|
||||
method: 'vector' | BitmapResizeMethods;
|
||||
fitMethod: 'stretch' | 'cover';
|
||||
}
|
||||
|
||||
export interface BitmapResizeOptions extends ResizeOptions {
|
||||
method: BitmapResizeMethods;
|
||||
}
|
||||
|
||||
export interface VectorResizeOptions extends ResizeOptions {
|
||||
method: 'vector';
|
||||
}
|
||||
|
||||
export const defaultOptions: ResizeOptions = {
|
||||
// Width and height will always default to the image size.
|
||||
// This is set elsewhere.
|
||||
width: 1,
|
||||
height: 1,
|
||||
// This will be set to 'vector' if the input is SVG.
|
||||
method: 'browser-high',
|
||||
fitMethod: 'stretch',
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user