diff --git a/src/codecs/browser-bmp/encoder.ts b/src/codecs/browser-bmp/encoder.ts new file mode 100644 index 000000000..4b033f2b0 --- /dev/null +++ b/src/codecs/browser-bmp/encoder.ts @@ -0,0 +1,16 @@ +import { canvasEncode } from '../../lib/util'; +import { canvasEncodeTest } from '../generic/util'; + +export interface EncodeOptions { } +export interface EncoderState { type: typeof type; options: EncodeOptions; } + +export const type = 'browser-bmp'; +export const label = 'Browser BMP'; +export const mimeType = 'image/bmp'; +export const extension = 'bmp'; +export const defaultOptions: EncodeOptions = {}; +export const featureTest = () => canvasEncodeTest(mimeType); + +export function encode(data: ImageData, options: EncodeOptions) { + return canvasEncode(data, mimeType); +} diff --git a/src/codecs/browser-gif/encoder.ts b/src/codecs/browser-gif/encoder.ts new file mode 100644 index 000000000..fea81fa3c --- /dev/null +++ b/src/codecs/browser-gif/encoder.ts @@ -0,0 +1,16 @@ +import { canvasEncode } from '../../lib/util'; +import { canvasEncodeTest } from '../generic/util'; + +export interface EncodeOptions {} +export interface EncoderState { type: typeof type; options: EncodeOptions; } + +export const type = 'browser-gif'; +export const label = 'Browser GIF'; +export const mimeType = 'image/gif'; +export const extension = 'gif'; +export const defaultOptions: EncodeOptions = {}; +export const featureTest = () => canvasEncodeTest(mimeType); + +export function encode(data: ImageData, options: EncodeOptions) { + return canvasEncode(data, mimeType); +} diff --git a/src/codecs/browser-jp2/encoder.ts b/src/codecs/browser-jp2/encoder.ts new file mode 100644 index 000000000..af9a3a921 --- /dev/null +++ b/src/codecs/browser-jp2/encoder.ts @@ -0,0 +1,16 @@ +import { canvasEncode } from '../../lib/util'; +import { canvasEncodeTest } from '../generic/util'; + +export interface EncodeOptions { } +export interface EncoderState { type: typeof type; options: EncodeOptions; } + +export const type = 'browser-jp2'; +export const label = 'Browser JPEG 2000'; +export const mimeType = 'image/jp2'; +export const extension = 'jp2'; +export const defaultOptions: EncodeOptions = {}; +export const featureTest = () => canvasEncodeTest(mimeType); + +export function encode(data: ImageData, options: EncodeOptions) { + return canvasEncode(data, mimeType); +} diff --git a/src/codecs/browser-pdf/encoder.ts b/src/codecs/browser-pdf/encoder.ts new file mode 100644 index 000000000..a3c961939 --- /dev/null +++ b/src/codecs/browser-pdf/encoder.ts @@ -0,0 +1,16 @@ +import { canvasEncode } from '../../lib/util'; +import { canvasEncodeTest } from '../generic/util'; + +export interface EncodeOptions { } +export interface EncoderState { type: typeof type; options: EncodeOptions; } + +export const type = 'browser-pdf'; +export const label = 'Browser PDF'; +export const mimeType = 'application/pdf'; +export const extension = 'pdf'; +export const defaultOptions: EncodeOptions = {}; +export const featureTest = () => canvasEncodeTest(mimeType); + +export function encode(data: ImageData, options: EncodeOptions) { + return canvasEncode(data, mimeType); +} diff --git a/src/codecs/browser-tiff/encoder.ts b/src/codecs/browser-tiff/encoder.ts new file mode 100644 index 000000000..6b4033904 --- /dev/null +++ b/src/codecs/browser-tiff/encoder.ts @@ -0,0 +1,16 @@ +import { canvasEncode } from '../../lib/util'; +import { canvasEncodeTest } from '../generic/util'; + +export interface EncodeOptions { } +export interface EncoderState { type: typeof type; options: EncodeOptions; } + +export const type = 'browser-tiff'; +export const label = 'Browser TIFF'; +export const mimeType = 'image/tiff'; +export const extension = 'tiff'; +export const defaultOptions: EncodeOptions = {}; +export const featureTest = () => canvasEncodeTest(mimeType); + +export function encode(data: ImageData, options: EncodeOptions) { + return canvasEncode(data, mimeType); +} diff --git a/src/codecs/browser-webp/encoder.ts b/src/codecs/browser-webp/encoder.ts index aae422259..55e13bb84 100644 --- a/src/codecs/browser-webp/encoder.ts +++ b/src/codecs/browser-webp/encoder.ts @@ -1,4 +1,5 @@ import { canvasEncode } from '../../lib/util'; +import { canvasEncodeTest } from '../generic/util'; export interface EncodeOptions { quality: number; } export interface EncoderState { type: typeof type; options: EncodeOptions; } @@ -8,15 +9,7 @@ export const label = 'Browser WebP'; export const mimeType = 'image/webp'; export const extension = 'webp'; export const defaultOptions: EncodeOptions = { quality: 0.5 }; - -export async function featureTest() { - const data = new ImageData(1, 1); - const blob = await encode(data, defaultOptions); - // According to the spec, the blob should be null if the format isn't supported… - if (!blob) return false; - // …but Safari falls back to PNG, so we need to check the mime type. - return blob.type === mimeType; -} +export const featureTest = () => canvasEncodeTest(mimeType); export function encode(data: ImageData, { quality }: EncodeOptions) { return canvasEncode(data, mimeType, quality); diff --git a/src/codecs/encoders.ts b/src/codecs/encoders.ts index 51a7e5a9d..0b121816c 100644 --- a/src/codecs/encoders.ts +++ b/src/codecs/encoders.ts @@ -3,6 +3,11 @@ import * as identity from './identity/encoder'; import * as browserPNG from './browser-png/encoder'; import * as browserJPEG from './browser-jpeg/encoder'; import * as browserWebP from './browser-webp/encoder'; +import * as browserGIF from './browser-gif/encoder'; +import * as browserTIFF from './browser-tiff/encoder'; +import * as browserJP2 from './browser-jp2/encoder'; +import * as browserBMP from './browser-bmp/encoder'; +import * as browserPDF from './browser-pdf/encoder'; export interface EncoderSupportMap { [key: string]: boolean; @@ -10,10 +15,14 @@ export interface EncoderSupportMap { export type EncoderState = identity.EncoderState | mozJPEG.EncoderState | browserPNG.EncoderState | - browserJPEG.EncoderState | browserWebP.EncoderState; + browserJPEG.EncoderState | browserWebP.EncoderState | browserGIF.EncoderState | + browserTIFF.EncoderState | browserJP2.EncoderState | browserBMP.EncoderState | + browserPDF.EncoderState; export type EncoderOptions = identity.EncodeOptions | mozJPEG.EncodeOptions | browserPNG.EncodeOptions | - browserJPEG.EncodeOptions | browserWebP.EncodeOptions; + browserJPEG.EncodeOptions | browserWebP.EncodeOptions | browserGIF.EncodeOptions | + browserTIFF.EncodeOptions | browserJP2.EncodeOptions | browserBMP.EncodeOptions | + browserPDF.EncodeOptions; export type EncoderType = keyof typeof encoderMap; export const encoderMap = { @@ -22,6 +31,13 @@ export const encoderMap = { [browserPNG.type]: browserPNG, [browserJPEG.type]: browserJPEG, [browserWebP.type]: browserWebP, + // Safari & Firefox only: + [browserBMP.type]: browserBMP, + // Safari only: + [browserGIF.type]: browserGIF, + [browserTIFF.type]: browserTIFF, + [browserJP2.type]: browserJP2, + [browserPDF.type]: browserPDF, }; export const encoders = Array.from(Object.values(encoderMap)); diff --git a/src/codecs/generic/util.ts b/src/codecs/generic/util.ts new file mode 100644 index 000000000..5b704693b --- /dev/null +++ b/src/codecs/generic/util.ts @@ -0,0 +1,13 @@ +import { canvasEncode } from '../../lib/util'; + +export async function canvasEncodeTest(mimeType: string) { + try { + const blob = await canvasEncode(new ImageData(1, 1), mimeType); + // According to the spec, the blob should be null if the format isn't supported… + if (!blob) return false; + // …but Safari & Firefox fall back to PNG, so we need to check the mime type. + return blob.type === mimeType; + } catch (err) { + return false; + } +} diff --git a/src/components/app/index.tsx b/src/components/app/index.tsx index 058a60df2..46b5c8f7f 100644 --- a/src/components/app/index.tsx +++ b/src/components/app/index.tsx @@ -13,6 +13,11 @@ import * as identity from '../../codecs/identity/encoder'; import * as browserPNG from '../../codecs/browser-png/encoder'; import * as browserJPEG from '../../codecs/browser-jpeg/encoder'; import * as browserWebP from '../../codecs/browser-webp/encoder'; +import * as browserGIF from '../../codecs/browser-gif/encoder'; +import * as browserTIFF from '../../codecs/browser-tiff/encoder'; +import * as browserJP2 from '../../codecs/browser-jp2/encoder'; +import * as browserBMP from '../../codecs/browser-bmp/encoder'; +import * as browserPDF from '../../codecs/browser-pdf/encoder'; import { EncoderState, EncoderType, @@ -62,6 +67,11 @@ async function compressImage( case browserPNG.type: return browserPNG.encode(source.data, encodeData.options); case browserJPEG.type: return browserJPEG.encode(source.data, encodeData.options); case browserWebP.type: return browserWebP.encode(source.data, encodeData.options); + case browserGIF.type: return browserGIF.encode(source.data, encodeData.options); + case browserTIFF.type: return browserTIFF.encode(source.data, encodeData.options); + case browserJP2.type: return browserJP2.encode(source.data, encodeData.options); + case browserBMP.type: return browserBMP.encode(source.data, encodeData.options); + case browserPDF.type: return browserPDF.encode(source.data, encodeData.options); default: throw Error(`Unexpected encoder ${JSON.stringify(encodeData)}`); } })(); diff --git a/src/components/options/index.tsx b/src/components/options/index.tsx index ef59272e6..0db239703 100644 --- a/src/components/options/index.tsx +++ b/src/components/options/index.tsx @@ -10,6 +10,11 @@ import * as identity from '../../codecs/identity/encoder'; import * as browserPNG from '../../codecs/browser-png/encoder'; import * as browserJPEG from '../../codecs/browser-jpeg/encoder'; import * as browserWebP from '../../codecs/browser-webp/encoder'; +import * as browserGIF from '../../codecs/browser-gif/encoder'; +import * as browserTIFF from '../../codecs/browser-tiff/encoder'; +import * as browserJP2 from '../../codecs/browser-jp2/encoder'; +import * as browserBMP from '../../codecs/browser-bmp/encoder'; +import * as browserPDF from '../../codecs/browser-pdf/encoder'; import { EncoderState, EncoderType, @@ -25,6 +30,12 @@ const encoderOptionsComponentMap = { [browserPNG.type]: undefined, [browserJPEG.type]: BrowserJPEGEncoderOptions, [browserWebP.type]: BrowserWebPEncoderOptions, + [browserBMP.type]: undefined, + // Only Safari supports the rest, and it doesn't support quality settings. + [browserGIF.type]: undefined, + [browserTIFF.type]: undefined, + [browserJP2.type]: undefined, + [browserPDF.type]: undefined, }; interface Props {