@capgo/capacitor-file-compressor 8.0.33 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -18
- package/android/src/main/java/io/capgo/filecompressor/FileCompressorPlugin.java +115 -45
- package/dist/docs.json +21 -13
- package/dist/esm/definitions.d.ts +40 -20
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +5 -0
- package/dist/esm/web.js +50 -23
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +50 -23
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +50 -23
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/FileCompressorPlugin/FileCompressorPlugin.swift +202 -47
- package/ios/Tests/FileCompressorPluginTests/FileCompressorPluginTests.swift +4 -4
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Capacitor File Compressor Plugin interface for image compression.\n *\n * @since 7.0.0\n */\nexport interface FileCompressorPlugin {\n /**\n * Compresses an image file with specified dimensions and quality settings.\n *\n * This method compresses images to reduce file size while maintaining acceptable quality.\n * It supports resizing and format conversion (JPEG
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Capacitor File Compressor Plugin interface for image compression.\n *\n * @since 7.0.0\n */\nexport interface FileCompressorPlugin {\n /**\n * Compresses an image file with specified dimensions and quality settings.\n *\n * This method compresses images to reduce file size while maintaining acceptable quality.\n * It supports resizing and format conversion across common image formats.\n *\n * **Supported input formats (platform decoder dependent):**\n * JPEG, PNG, WebP, GIF, BMP, TIFF, HEIF/HEIC\n *\n * **Supported output formats:**\n * - **iOS:** `image/jpeg`, `image/png`, `image/heif`, `image/heic`, `image/webp` (iOS 14+)\n * - **Android:** `image/jpeg`, `image/png`, `image/webp`\n * - **Web:** `image/jpeg`, `image/png`, `image/webp`\n *\n * **Important Notes:**\n * - EXIF metadata is removed during compression on all platforms\n * - Aspect ratio is automatically maintained if only one dimension is provided\n * - When both width and height are provided, the image fits inside that box without upscaling\n * - Compressed files are saved to temporary directories on native platforms\n * - If the encoded output would be larger than the source file, quality is reduced automatically while keeping the requested output format\n *\n * @param options - Configuration options for image compression\n * @returns Promise that resolves with the compressed image path or blob\n * @throws Error if compression fails, invalid parameters, or unsupported format\n * @since 7.0.0\n * @example\n * ```typescript\n * // Web - Compress from file input\n * const fileInput = document.getElementById('file') as HTMLInputElement;\n * const file = fileInput.files[0];\n * const result = await FileCompressor.compressImage({\n * blob: file,\n * quality: 0.8,\n * width: 1200,\n * mimeType: 'image/jpeg'\n * });\n * const url = URL.createObjectURL(result.blob);\n * ```\n * @example\n * ```typescript\n * // iOS - Convert HEIF iPhone photo to JPEG\n * const result = await FileCompressor.compressImage({\n * path: heifFileUri,\n * quality: 0.7,\n * width: 1920,\n * height: 1080,\n * mimeType: 'image/jpeg'\n * });\n * console.log('Converted to JPEG:', result.path);\n * ```\n * @example\n * ```typescript\n * // Android - Convert PNG to WebP\n * const result = await FileCompressor.compressImage({\n * path: 'content://downloads/document/123',\n * quality: 0.6,\n * width: 800,\n * height: 600,\n * mimeType: 'image/webp'\n * });\n * console.log('Compressed to:', result.path);\n * ```\n * @example\n * ```typescript\n * // Maintain aspect ratio - only specify width\n * const result = await FileCompressor.compressImage({\n * path: imagePath,\n * quality: 0.75,\n * width: 1920,\n * mimeType: 'image/jpeg'\n * });\n * ```\n */\n compressImage(options: CompressImageOptions): Promise<CompressImageResult>;\n\n /**\n * Get the native Capacitor plugin version.\n *\n * Returns the version of the native plugin implementation.\n * Useful for debugging and ensuring compatibility.\n *\n * @returns Promise that resolves with the plugin version string\n * @throws Error if getting the version fails\n * @since 7.0.0\n * @example\n * ```typescript\n * const { version } = await FileCompressor.getPluginVersion();\n * console.log('Plugin version:', version); // \"7.0.0\"\n * ```\n */\n getPluginVersion(): Promise<{ version: string }>;\n}\n\n/**\n * Options for compressing an image.\n *\n * Configure the compression behavior including quality, dimensions, and output format.\n * Platform-specific options are available for path (native) and blob (web).\n *\n * @since 7.0.0\n */\nexport interface CompressImageOptions {\n /**\n * The file path of the image to compress.\n *\n * **Platform:** Android, iOS only (not supported on Web)\n *\n * Accepts various path formats:\n * - iOS: `file://` URLs or absolute paths\n * - Android: `content://` URIs, `file://` URLs, or absolute paths\n *\n * Common input formats include JPEG, PNG, WebP, GIF, BMP, TIFF, and HEIF/HEIC.\n *\n * @since 7.0.0\n * @example \"file:///var/mobile/Containers/Data/Application/photo.heic\" // iOS HEIF\n * @example \"content://com.android.providers.downloads.documents/document/msf%3A1000000485\" // Android\n * @example \"/storage/emulated/0/Download/photo.png\" // Android absolute path\n */\n path?: string;\n\n /**\n * The file blob of the image to compress.\n *\n * **Platform:** Web only (not supported on iOS/Android)\n *\n * Use this when compressing images from file inputs, fetch responses,\n * or any other Blob source in web applications.\n *\n * @since 7.0.0\n * @example\n * ```typescript\n * // From file input\n * const fileInput = document.getElementById('file') as HTMLInputElement;\n * const blob = fileInput.files[0];\n * ```\n * @example\n * ```typescript\n * // From fetch\n * const response = await fetch('https://example.com/image.jpg');\n * const blob = await response.blob();\n * ```\n */\n blob?: Blob;\n\n /**\n * The quality of the compressed image.\n *\n * **Range:** 0.0 to 1.0\n * - `0.0` = Maximum compression (lowest quality, smallest file)\n * - `1.0` = Minimum compression (highest quality, largest file)\n * - `0.6` = Default balanced compression\n *\n * **Platform:** All platforms\n *\n * Higher quality values result in larger files but better visual quality.\n * The actual compression ratio depends on the image content and format.\n * PNG output ignores quality because it is lossless.\n *\n * @since 7.0.0\n * @default 0.6\n * @example 0.8 // High quality\n * @example 0.5 // Medium quality, smaller file\n * @example 0.3 // Low quality, very small file\n */\n quality?: number;\n\n /**\n * The width of the compressed image in pixels.\n *\n * **Platform:** All platforms\n *\n * If only width is specified, height is calculated automatically\n * to maintain the original aspect ratio.\n *\n * If both width and height are specified, the image is scaled to fit inside\n * that box while preserving aspect ratio. Images are never upscaled.\n *\n * @since 7.0.0\n * @example 1920 // Full HD width\n * @example 1200 // Common web image width\n * @example 800 // Mobile-optimized width\n */\n width?: number;\n\n /**\n * The height of the compressed image in pixels.\n *\n * **Platform:** All platforms\n *\n * If only height is specified, width is calculated automatically\n * to maintain the original aspect ratio.\n *\n * If both width and height are specified, the image is scaled to fit inside\n * that box while preserving aspect ratio. Images are never upscaled.\n *\n * @since 7.0.0\n * @example 1080 // Full HD height\n * @example 800 // Common web image height\n * @example 600 // Mobile-optimized height\n */\n height?: number;\n\n /**\n * The MIME type of the compressed output image.\n *\n * **Platform Support:**\n * - **iOS:** `image/jpeg`, `image/png`, `image/heif`, `image/heic`, `image/webp` (iOS 14+)\n * - **Android:** `image/jpeg`, `image/png`, `image/webp`\n * - **Web:** `image/jpeg`, `image/png`, `image/webp`\n *\n * Use this option to convert the source image to another format while compressing.\n *\n * **Format Characteristics:**\n * - **JPEG:** Universal support, good for photos, no transparency\n * - **PNG:** Lossless, supports transparency\n * - **WebP:** Better compression, supports transparency\n * - **HEIF/HEIC:** Efficient photo format on iOS\n *\n * @since 7.0.0\n * @default \"image/jpeg\"\n * @example \"image/jpeg\" // JPEG format\n * @example \"image/png\" // PNG format\n * @example \"image/webp\" // WebP format\n * @example \"image/heif\" // HEIF format (iOS output)\n */\n mimeType?: string;\n}\n\n/**\n * The result of compressing an image.\n *\n * Contains either a file path (native platforms) or a Blob (web platform)\n * depending on where the compression was performed.\n *\n * @since 7.0.0\n */\nexport interface CompressImageResult {\n /**\n * The file path of the compressed image.\n *\n * **Platform:** Android, iOS only (undefined on Web)\n *\n * Points to a temporary file containing the compressed image.\n * On iOS, typically in `NSTemporaryDirectory()`.\n * On Android, typically in app cache directory.\n *\n * **Important:** These files may be cleaned up by the OS.\n * Copy to permanent storage if needed for long-term use.\n *\n * @since 7.0.0\n * @example \"/var/mobile/Containers/Data/tmp/compressed_abc123.jpg\" // iOS\n * @example \"/data/user/0/com.app/cache/compressed_xyz789.webp\" // Android\n */\n path?: string;\n\n /**\n * The blob of the compressed image.\n *\n * **Platform:** Web only (undefined on iOS/Android)\n *\n * A Blob object containing the compressed image data.\n * Can be used to:\n * - Create object URLs for preview: `URL.createObjectURL(blob)`\n * - Upload to server via FormData\n * - Save to IndexedDB or other storage\n * - Convert to base64 with FileReader\n *\n * @since 7.0.0\n * @example\n * ```typescript\n * // Create preview URL\n * const url = URL.createObjectURL(result.blob);\n * imageElement.src = url;\n * ```\n * @example\n * ```typescript\n * // Upload to server\n * const formData = new FormData();\n * formData.append('image', result.blob, 'compressed.jpg');\n * await fetch('/upload', { method: 'POST', body: formData });\n * ```\n */\n blob?: Blob;\n}\n"]}
|
package/dist/esm/web.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { WebPlugin } from '@capacitor/core';
|
|
2
2
|
import type { CompressImageOptions, CompressImageResult, FileCompressorPlugin } from './definitions';
|
|
3
3
|
export declare class FileCompressorWeb extends WebPlugin implements FileCompressorPlugin {
|
|
4
|
+
private readonly minimumQuality;
|
|
5
|
+
private readonly qualityStep;
|
|
4
6
|
compressImage(options: CompressImageOptions): Promise<CompressImageResult>;
|
|
5
7
|
getPluginVersion(): Promise<{
|
|
6
8
|
version: string;
|
|
7
9
|
}>;
|
|
10
|
+
private calculateDimensions;
|
|
11
|
+
private canvasToBlobWithinSize;
|
|
12
|
+
private canvasToBlob;
|
|
8
13
|
private createImageFromBlob;
|
|
9
14
|
}
|
package/dist/esm/web.js
CHANGED
|
@@ -1,29 +1,23 @@
|
|
|
1
1
|
import { WebPlugin } from '@capacitor/core';
|
|
2
|
+
const SUPPORTED_OUTPUT_MIME_TYPES = ['image/jpeg', 'image/png', 'image/webp'];
|
|
2
3
|
export class FileCompressorWeb extends WebPlugin {
|
|
4
|
+
constructor() {
|
|
5
|
+
super(...arguments);
|
|
6
|
+
this.minimumQuality = 0.1;
|
|
7
|
+
this.qualityStep = 0.05;
|
|
8
|
+
}
|
|
3
9
|
async compressImage(options) {
|
|
4
|
-
var _a, _b
|
|
10
|
+
var _a, _b;
|
|
5
11
|
if (!options.blob) {
|
|
6
12
|
throw new Error('blob is required on web platform');
|
|
7
13
|
}
|
|
8
14
|
const quality = (_a = options.quality) !== null && _a !== void 0 ? _a : 0.6;
|
|
9
|
-
const mimeType = (_b = options.mimeType) !== null && _b !== void 0 ? _b : 'image/jpeg';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
throw new Error('Only image/jpeg and image/webp are supported on web platform');
|
|
15
|
+
const mimeType = ((_b = options.mimeType) !== null && _b !== void 0 ? _b : 'image/jpeg').toLowerCase();
|
|
16
|
+
if (!SUPPORTED_OUTPUT_MIME_TYPES.includes(mimeType)) {
|
|
17
|
+
throw new Error(`Unsupported output mimeType: ${mimeType}. Supported: ${SUPPORTED_OUTPUT_MIME_TYPES.join(', ')}`);
|
|
13
18
|
}
|
|
14
|
-
// Create image element to load the blob
|
|
15
19
|
const img = await this.createImageFromBlob(options.blob);
|
|
16
|
-
|
|
17
|
-
let width = (_c = options.width) !== null && _c !== void 0 ? _c : img.width;
|
|
18
|
-
let height = (_d = options.height) !== null && _d !== void 0 ? _d : img.height;
|
|
19
|
-
// Maintain aspect ratio if only one dimension is provided
|
|
20
|
-
if (options.width && !options.height) {
|
|
21
|
-
height = (img.height / img.width) * width;
|
|
22
|
-
}
|
|
23
|
-
else if (options.height && !options.width) {
|
|
24
|
-
width = (img.width / img.height) * height;
|
|
25
|
-
}
|
|
26
|
-
// Create canvas and draw image
|
|
20
|
+
const { width, height } = this.calculateDimensions(img, options.width, options.height);
|
|
27
21
|
const canvas = document.createElement('canvas');
|
|
28
22
|
canvas.width = width;
|
|
29
23
|
canvas.height = height;
|
|
@@ -32,8 +26,45 @@ export class FileCompressorWeb extends WebPlugin {
|
|
|
32
26
|
throw new Error('Failed to get canvas context');
|
|
33
27
|
}
|
|
34
28
|
ctx.drawImage(img, 0, 0, width, height);
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
const blob = await this.canvasToBlobWithinSize(canvas, mimeType, quality, options.blob.size);
|
|
30
|
+
return { blob };
|
|
31
|
+
}
|
|
32
|
+
async getPluginVersion() {
|
|
33
|
+
return { version: '7.0.0' };
|
|
34
|
+
}
|
|
35
|
+
calculateDimensions(img, maxWidth, maxHeight) {
|
|
36
|
+
let width = img.width;
|
|
37
|
+
let height = img.height;
|
|
38
|
+
if (maxWidth != null && maxHeight != null) {
|
|
39
|
+
const ratio = Math.min(maxWidth / width, maxHeight / height, 1);
|
|
40
|
+
width = Math.round(width * ratio);
|
|
41
|
+
height = Math.round(height * ratio);
|
|
42
|
+
}
|
|
43
|
+
else if (maxWidth != null) {
|
|
44
|
+
const ratio = Math.min(maxWidth / width, 1);
|
|
45
|
+
width = Math.round(width * ratio);
|
|
46
|
+
height = Math.round(height * ratio);
|
|
47
|
+
}
|
|
48
|
+
else if (maxHeight != null) {
|
|
49
|
+
const ratio = Math.min(maxHeight / height, 1);
|
|
50
|
+
width = Math.round(width * ratio);
|
|
51
|
+
height = Math.round(height * ratio);
|
|
52
|
+
}
|
|
53
|
+
return { width, height };
|
|
54
|
+
}
|
|
55
|
+
async canvasToBlobWithinSize(canvas, mimeType, quality, maxBytes) {
|
|
56
|
+
let currentQuality = quality;
|
|
57
|
+
const supportsQuality = mimeType !== 'image/png';
|
|
58
|
+
while (true) {
|
|
59
|
+
const blob = await this.canvasToBlob(canvas, mimeType, currentQuality);
|
|
60
|
+
if (blob.size <= maxBytes || currentQuality <= this.minimumQuality || !supportsQuality) {
|
|
61
|
+
return blob;
|
|
62
|
+
}
|
|
63
|
+
currentQuality = Math.max(this.minimumQuality, currentQuality - this.qualityStep);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
canvasToBlob(canvas, mimeType, quality) {
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
37
68
|
canvas.toBlob((blob) => {
|
|
38
69
|
if (blob) {
|
|
39
70
|
resolve(blob);
|
|
@@ -43,10 +74,6 @@ export class FileCompressorWeb extends WebPlugin {
|
|
|
43
74
|
}
|
|
44
75
|
}, mimeType, quality);
|
|
45
76
|
});
|
|
46
|
-
return { blob };
|
|
47
|
-
}
|
|
48
|
-
async getPluginVersion() {
|
|
49
|
-
return { version: '7.0.0' };
|
|
50
77
|
}
|
|
51
78
|
createImageFromBlob(blob) {
|
|
52
79
|
return new Promise((resolve, reject) => {
|
package/dist/esm/web.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,MAAM,OAAO,iBAAkB,SAAQ,SAAS;
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"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","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type { CompressImageOptions, CompressImageResult, FileCompressorPlugin } from './definitions';\n\nconst SUPPORTED_OUTPUT_MIME_TYPES = ['image/jpeg', 'image/png', 'image/webp'] as const;\n\ntype SupportedOutputMimeType = (typeof SUPPORTED_OUTPUT_MIME_TYPES)[number];\n\nexport class FileCompressorWeb extends WebPlugin implements FileCompressorPlugin {\n private readonly minimumQuality = 0.1;\n private readonly qualityStep = 0.05;\n\n async compressImage(options: CompressImageOptions): Promise<CompressImageResult> {\n if (!options.blob) {\n throw new Error('blob is required on web platform');\n }\n\n const quality = options.quality ?? 0.6;\n const mimeType = (options.mimeType ?? 'image/jpeg').toLowerCase();\n\n if (!SUPPORTED_OUTPUT_MIME_TYPES.includes(mimeType as SupportedOutputMimeType)) {\n throw new Error(`Unsupported output mimeType: ${mimeType}. Supported: ${SUPPORTED_OUTPUT_MIME_TYPES.join(', ')}`);\n }\n\n const img = await this.createImageFromBlob(options.blob);\n const { width, height } = this.calculateDimensions(img, options.width, options.height);\n\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Failed to get canvas context');\n }\n\n ctx.drawImage(img, 0, 0, width, height);\n\n const blob = await this.canvasToBlobWithinSize(\n canvas,\n mimeType as SupportedOutputMimeType,\n quality,\n options.blob.size,\n );\n\n return { blob };\n }\n\n async getPluginVersion(): Promise<{ version: string }> {\n return { version: '7.0.0' };\n }\n\n private calculateDimensions(\n img: HTMLImageElement,\n maxWidth?: number,\n maxHeight?: number,\n ): { width: number; height: number } {\n let width = img.width;\n let height = img.height;\n\n if (maxWidth != null && maxHeight != null) {\n const ratio = Math.min(maxWidth / width, maxHeight / height, 1);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n } else if (maxWidth != null) {\n const ratio = Math.min(maxWidth / width, 1);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n } else if (maxHeight != null) {\n const ratio = Math.min(maxHeight / height, 1);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n }\n\n return { width, height };\n }\n\n private async canvasToBlobWithinSize(\n canvas: HTMLCanvasElement,\n mimeType: SupportedOutputMimeType,\n quality: number,\n maxBytes: number,\n ): Promise<Blob> {\n let currentQuality = quality;\n const supportsQuality = mimeType !== 'image/png';\n\n while (true) {\n const blob = await this.canvasToBlob(canvas, mimeType, currentQuality);\n if (blob.size <= maxBytes || currentQuality <= this.minimumQuality || !supportsQuality) {\n return blob;\n }\n\n currentQuality = Math.max(this.minimumQuality, currentQuality - this.qualityStep);\n }\n }\n\n private canvasToBlob(canvas: HTMLCanvasElement, mimeType: SupportedOutputMimeType, quality: number): Promise<Blob> {\n return new Promise((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new Error('Failed to create blob from canvas'));\n }\n },\n mimeType,\n quality,\n );\n });\n }\n\n private createImageFromBlob(blob: Blob): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n const url = URL.createObjectURL(blob);\n\n img.onload = () => {\n URL.revokeObjectURL(url);\n resolve(img);\n };\n\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error('Failed to load image from blob'));\n };\n\n img.src = url;\n });\n }\n}\n"]}
|
package/dist/plugin.cjs.js
CHANGED
|
@@ -6,31 +6,25 @@ const FileCompressor = core.registerPlugin('FileCompressor', {
|
|
|
6
6
|
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.FileCompressorWeb()),
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
+
const SUPPORTED_OUTPUT_MIME_TYPES = ['image/jpeg', 'image/png', 'image/webp'];
|
|
9
10
|
class FileCompressorWeb extends core.WebPlugin {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
13
|
+
this.minimumQuality = 0.1;
|
|
14
|
+
this.qualityStep = 0.05;
|
|
15
|
+
}
|
|
10
16
|
async compressImage(options) {
|
|
11
|
-
var _a, _b
|
|
17
|
+
var _a, _b;
|
|
12
18
|
if (!options.blob) {
|
|
13
19
|
throw new Error('blob is required on web platform');
|
|
14
20
|
}
|
|
15
21
|
const quality = (_a = options.quality) !== null && _a !== void 0 ? _a : 0.6;
|
|
16
|
-
const mimeType = (_b = options.mimeType) !== null && _b !== void 0 ? _b : 'image/jpeg';
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
throw new Error('Only image/jpeg and image/webp are supported on web platform');
|
|
22
|
+
const mimeType = ((_b = options.mimeType) !== null && _b !== void 0 ? _b : 'image/jpeg').toLowerCase();
|
|
23
|
+
if (!SUPPORTED_OUTPUT_MIME_TYPES.includes(mimeType)) {
|
|
24
|
+
throw new Error(`Unsupported output mimeType: ${mimeType}. Supported: ${SUPPORTED_OUTPUT_MIME_TYPES.join(', ')}`);
|
|
20
25
|
}
|
|
21
|
-
// Create image element to load the blob
|
|
22
26
|
const img = await this.createImageFromBlob(options.blob);
|
|
23
|
-
|
|
24
|
-
let width = (_c = options.width) !== null && _c !== void 0 ? _c : img.width;
|
|
25
|
-
let height = (_d = options.height) !== null && _d !== void 0 ? _d : img.height;
|
|
26
|
-
// Maintain aspect ratio if only one dimension is provided
|
|
27
|
-
if (options.width && !options.height) {
|
|
28
|
-
height = (img.height / img.width) * width;
|
|
29
|
-
}
|
|
30
|
-
else if (options.height && !options.width) {
|
|
31
|
-
width = (img.width / img.height) * height;
|
|
32
|
-
}
|
|
33
|
-
// Create canvas and draw image
|
|
27
|
+
const { width, height } = this.calculateDimensions(img, options.width, options.height);
|
|
34
28
|
const canvas = document.createElement('canvas');
|
|
35
29
|
canvas.width = width;
|
|
36
30
|
canvas.height = height;
|
|
@@ -39,8 +33,45 @@ class FileCompressorWeb extends core.WebPlugin {
|
|
|
39
33
|
throw new Error('Failed to get canvas context');
|
|
40
34
|
}
|
|
41
35
|
ctx.drawImage(img, 0, 0, width, height);
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
const blob = await this.canvasToBlobWithinSize(canvas, mimeType, quality, options.blob.size);
|
|
37
|
+
return { blob };
|
|
38
|
+
}
|
|
39
|
+
async getPluginVersion() {
|
|
40
|
+
return { version: '7.0.0' };
|
|
41
|
+
}
|
|
42
|
+
calculateDimensions(img, maxWidth, maxHeight) {
|
|
43
|
+
let width = img.width;
|
|
44
|
+
let height = img.height;
|
|
45
|
+
if (maxWidth != null && maxHeight != null) {
|
|
46
|
+
const ratio = Math.min(maxWidth / width, maxHeight / height, 1);
|
|
47
|
+
width = Math.round(width * ratio);
|
|
48
|
+
height = Math.round(height * ratio);
|
|
49
|
+
}
|
|
50
|
+
else if (maxWidth != null) {
|
|
51
|
+
const ratio = Math.min(maxWidth / width, 1);
|
|
52
|
+
width = Math.round(width * ratio);
|
|
53
|
+
height = Math.round(height * ratio);
|
|
54
|
+
}
|
|
55
|
+
else if (maxHeight != null) {
|
|
56
|
+
const ratio = Math.min(maxHeight / height, 1);
|
|
57
|
+
width = Math.round(width * ratio);
|
|
58
|
+
height = Math.round(height * ratio);
|
|
59
|
+
}
|
|
60
|
+
return { width, height };
|
|
61
|
+
}
|
|
62
|
+
async canvasToBlobWithinSize(canvas, mimeType, quality, maxBytes) {
|
|
63
|
+
let currentQuality = quality;
|
|
64
|
+
const supportsQuality = mimeType !== 'image/png';
|
|
65
|
+
while (true) {
|
|
66
|
+
const blob = await this.canvasToBlob(canvas, mimeType, currentQuality);
|
|
67
|
+
if (blob.size <= maxBytes || currentQuality <= this.minimumQuality || !supportsQuality) {
|
|
68
|
+
return blob;
|
|
69
|
+
}
|
|
70
|
+
currentQuality = Math.max(this.minimumQuality, currentQuality - this.qualityStep);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
canvasToBlob(canvas, mimeType, quality) {
|
|
74
|
+
return new Promise((resolve, reject) => {
|
|
44
75
|
canvas.toBlob((blob) => {
|
|
45
76
|
if (blob) {
|
|
46
77
|
resolve(blob);
|
|
@@ -50,10 +81,6 @@ class FileCompressorWeb extends core.WebPlugin {
|
|
|
50
81
|
}
|
|
51
82
|
}, mimeType, quality);
|
|
52
83
|
});
|
|
53
|
-
return { blob };
|
|
54
|
-
}
|
|
55
|
-
async getPluginVersion() {
|
|
56
|
-
return { version: '7.0.0' };
|
|
57
84
|
}
|
|
58
85
|
createImageFromBlob(blob) {
|
|
59
86
|
return new Promise((resolve, reject) => {
|
package/dist/plugin.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst FileCompressor = registerPlugin('FileCompressor', {\n web: () => import('./web').then((m) => new m.FileCompressorWeb()),\n});\nexport * from './definitions';\nexport { FileCompressor };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class FileCompressorWeb extends WebPlugin {\n async compressImage(options) {\n var _a, _b
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst FileCompressor = registerPlugin('FileCompressor', {\n web: () => import('./web').then((m) => new m.FileCompressorWeb()),\n});\nexport * from './definitions';\nexport { FileCompressor };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nconst SUPPORTED_OUTPUT_MIME_TYPES = ['image/jpeg', 'image/png', 'image/webp'];\nexport class FileCompressorWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.minimumQuality = 0.1;\n this.qualityStep = 0.05;\n }\n async compressImage(options) {\n var _a, _b;\n if (!options.blob) {\n throw new Error('blob is required on web platform');\n }\n const quality = (_a = options.quality) !== null && _a !== void 0 ? _a : 0.6;\n const mimeType = ((_b = options.mimeType) !== null && _b !== void 0 ? _b : 'image/jpeg').toLowerCase();\n if (!SUPPORTED_OUTPUT_MIME_TYPES.includes(mimeType)) {\n throw new Error(`Unsupported output mimeType: ${mimeType}. Supported: ${SUPPORTED_OUTPUT_MIME_TYPES.join(', ')}`);\n }\n const img = await this.createImageFromBlob(options.blob);\n const { width, height } = this.calculateDimensions(img, options.width, options.height);\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Failed to get canvas context');\n }\n ctx.drawImage(img, 0, 0, width, height);\n const blob = await this.canvasToBlobWithinSize(canvas, mimeType, quality, options.blob.size);\n return { blob };\n }\n async getPluginVersion() {\n return { version: '7.0.0' };\n }\n calculateDimensions(img, maxWidth, maxHeight) {\n let width = img.width;\n let height = img.height;\n if (maxWidth != null && maxHeight != null) {\n const ratio = Math.min(maxWidth / width, maxHeight / height, 1);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n }\n else if (maxWidth != null) {\n const ratio = Math.min(maxWidth / width, 1);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n }\n else if (maxHeight != null) {\n const ratio = Math.min(maxHeight / height, 1);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n }\n return { width, height };\n }\n async canvasToBlobWithinSize(canvas, mimeType, quality, maxBytes) {\n let currentQuality = quality;\n const supportsQuality = mimeType !== 'image/png';\n while (true) {\n const blob = await this.canvasToBlob(canvas, mimeType, currentQuality);\n if (blob.size <= maxBytes || currentQuality <= this.minimumQuality || !supportsQuality) {\n return blob;\n }\n currentQuality = Math.max(this.minimumQuality, currentQuality - this.qualityStep);\n }\n }\n canvasToBlob(canvas, mimeType, quality) {\n return new Promise((resolve, reject) => {\n canvas.toBlob((blob) => {\n if (blob) {\n resolve(blob);\n }\n else {\n reject(new Error('Failed to create blob from canvas'));\n }\n }, mimeType, quality);\n });\n }\n createImageFromBlob(blob) {\n return new Promise((resolve, reject) => {\n const img = new Image();\n const url = URL.createObjectURL(blob);\n img.onload = () => {\n URL.revokeObjectURL(url);\n resolve(img);\n };\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error('Failed to load image from blob'));\n };\n img.src = url;\n });\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
|
package/dist/plugin.js
CHANGED
|
@@ -5,31 +5,25 @@ var capacitorFileCompressor = (function (exports, core) {
|
|
|
5
5
|
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.FileCompressorWeb()),
|
|
6
6
|
});
|
|
7
7
|
|
|
8
|
+
const SUPPORTED_OUTPUT_MIME_TYPES = ['image/jpeg', 'image/png', 'image/webp'];
|
|
8
9
|
class FileCompressorWeb extends core.WebPlugin {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
this.minimumQuality = 0.1;
|
|
13
|
+
this.qualityStep = 0.05;
|
|
14
|
+
}
|
|
9
15
|
async compressImage(options) {
|
|
10
|
-
var _a, _b
|
|
16
|
+
var _a, _b;
|
|
11
17
|
if (!options.blob) {
|
|
12
18
|
throw new Error('blob is required on web platform');
|
|
13
19
|
}
|
|
14
20
|
const quality = (_a = options.quality) !== null && _a !== void 0 ? _a : 0.6;
|
|
15
|
-
const mimeType = (_b = options.mimeType) !== null && _b !== void 0 ? _b : 'image/jpeg';
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
throw new Error('Only image/jpeg and image/webp are supported on web platform');
|
|
21
|
+
const mimeType = ((_b = options.mimeType) !== null && _b !== void 0 ? _b : 'image/jpeg').toLowerCase();
|
|
22
|
+
if (!SUPPORTED_OUTPUT_MIME_TYPES.includes(mimeType)) {
|
|
23
|
+
throw new Error(`Unsupported output mimeType: ${mimeType}. Supported: ${SUPPORTED_OUTPUT_MIME_TYPES.join(', ')}`);
|
|
19
24
|
}
|
|
20
|
-
// Create image element to load the blob
|
|
21
25
|
const img = await this.createImageFromBlob(options.blob);
|
|
22
|
-
|
|
23
|
-
let width = (_c = options.width) !== null && _c !== void 0 ? _c : img.width;
|
|
24
|
-
let height = (_d = options.height) !== null && _d !== void 0 ? _d : img.height;
|
|
25
|
-
// Maintain aspect ratio if only one dimension is provided
|
|
26
|
-
if (options.width && !options.height) {
|
|
27
|
-
height = (img.height / img.width) * width;
|
|
28
|
-
}
|
|
29
|
-
else if (options.height && !options.width) {
|
|
30
|
-
width = (img.width / img.height) * height;
|
|
31
|
-
}
|
|
32
|
-
// Create canvas and draw image
|
|
26
|
+
const { width, height } = this.calculateDimensions(img, options.width, options.height);
|
|
33
27
|
const canvas = document.createElement('canvas');
|
|
34
28
|
canvas.width = width;
|
|
35
29
|
canvas.height = height;
|
|
@@ -38,8 +32,45 @@ var capacitorFileCompressor = (function (exports, core) {
|
|
|
38
32
|
throw new Error('Failed to get canvas context');
|
|
39
33
|
}
|
|
40
34
|
ctx.drawImage(img, 0, 0, width, height);
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
const blob = await this.canvasToBlobWithinSize(canvas, mimeType, quality, options.blob.size);
|
|
36
|
+
return { blob };
|
|
37
|
+
}
|
|
38
|
+
async getPluginVersion() {
|
|
39
|
+
return { version: '7.0.0' };
|
|
40
|
+
}
|
|
41
|
+
calculateDimensions(img, maxWidth, maxHeight) {
|
|
42
|
+
let width = img.width;
|
|
43
|
+
let height = img.height;
|
|
44
|
+
if (maxWidth != null && maxHeight != null) {
|
|
45
|
+
const ratio = Math.min(maxWidth / width, maxHeight / height, 1);
|
|
46
|
+
width = Math.round(width * ratio);
|
|
47
|
+
height = Math.round(height * ratio);
|
|
48
|
+
}
|
|
49
|
+
else if (maxWidth != null) {
|
|
50
|
+
const ratio = Math.min(maxWidth / width, 1);
|
|
51
|
+
width = Math.round(width * ratio);
|
|
52
|
+
height = Math.round(height * ratio);
|
|
53
|
+
}
|
|
54
|
+
else if (maxHeight != null) {
|
|
55
|
+
const ratio = Math.min(maxHeight / height, 1);
|
|
56
|
+
width = Math.round(width * ratio);
|
|
57
|
+
height = Math.round(height * ratio);
|
|
58
|
+
}
|
|
59
|
+
return { width, height };
|
|
60
|
+
}
|
|
61
|
+
async canvasToBlobWithinSize(canvas, mimeType, quality, maxBytes) {
|
|
62
|
+
let currentQuality = quality;
|
|
63
|
+
const supportsQuality = mimeType !== 'image/png';
|
|
64
|
+
while (true) {
|
|
65
|
+
const blob = await this.canvasToBlob(canvas, mimeType, currentQuality);
|
|
66
|
+
if (blob.size <= maxBytes || currentQuality <= this.minimumQuality || !supportsQuality) {
|
|
67
|
+
return blob;
|
|
68
|
+
}
|
|
69
|
+
currentQuality = Math.max(this.minimumQuality, currentQuality - this.qualityStep);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
canvasToBlob(canvas, mimeType, quality) {
|
|
73
|
+
return new Promise((resolve, reject) => {
|
|
43
74
|
canvas.toBlob((blob) => {
|
|
44
75
|
if (blob) {
|
|
45
76
|
resolve(blob);
|
|
@@ -49,10 +80,6 @@ var capacitorFileCompressor = (function (exports, core) {
|
|
|
49
80
|
}
|
|
50
81
|
}, mimeType, quality);
|
|
51
82
|
});
|
|
52
|
-
return { blob };
|
|
53
|
-
}
|
|
54
|
-
async getPluginVersion() {
|
|
55
|
-
return { version: '7.0.0' };
|
|
56
83
|
}
|
|
57
84
|
createImageFromBlob(blob) {
|
|
58
85
|
return new Promise((resolve, reject) => {
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst FileCompressor = registerPlugin('FileCompressor', {\n web: () => import('./web').then((m) => new m.FileCompressorWeb()),\n});\nexport * from './definitions';\nexport { FileCompressor };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class FileCompressorWeb extends WebPlugin {\n async compressImage(options) {\n var _a, _b
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst FileCompressor = registerPlugin('FileCompressor', {\n web: () => import('./web').then((m) => new m.FileCompressorWeb()),\n});\nexport * from './definitions';\nexport { FileCompressor };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nconst SUPPORTED_OUTPUT_MIME_TYPES = ['image/jpeg', 'image/png', 'image/webp'];\nexport class FileCompressorWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.minimumQuality = 0.1;\n this.qualityStep = 0.05;\n }\n async compressImage(options) {\n var _a, _b;\n if (!options.blob) {\n throw new Error('blob is required on web platform');\n }\n const quality = (_a = options.quality) !== null && _a !== void 0 ? _a : 0.6;\n const mimeType = ((_b = options.mimeType) !== null && _b !== void 0 ? _b : 'image/jpeg').toLowerCase();\n if (!SUPPORTED_OUTPUT_MIME_TYPES.includes(mimeType)) {\n throw new Error(`Unsupported output mimeType: ${mimeType}. Supported: ${SUPPORTED_OUTPUT_MIME_TYPES.join(', ')}`);\n }\n const img = await this.createImageFromBlob(options.blob);\n const { width, height } = this.calculateDimensions(img, options.width, options.height);\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Failed to get canvas context');\n }\n ctx.drawImage(img, 0, 0, width, height);\n const blob = await this.canvasToBlobWithinSize(canvas, mimeType, quality, options.blob.size);\n return { blob };\n }\n async getPluginVersion() {\n return { version: '7.0.0' };\n }\n calculateDimensions(img, maxWidth, maxHeight) {\n let width = img.width;\n let height = img.height;\n if (maxWidth != null && maxHeight != null) {\n const ratio = Math.min(maxWidth / width, maxHeight / height, 1);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n }\n else if (maxWidth != null) {\n const ratio = Math.min(maxWidth / width, 1);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n }\n else if (maxHeight != null) {\n const ratio = Math.min(maxHeight / height, 1);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n }\n return { width, height };\n }\n async canvasToBlobWithinSize(canvas, mimeType, quality, maxBytes) {\n let currentQuality = quality;\n const supportsQuality = mimeType !== 'image/png';\n while (true) {\n const blob = await this.canvasToBlob(canvas, mimeType, currentQuality);\n if (blob.size <= maxBytes || currentQuality <= this.minimumQuality || !supportsQuality) {\n return blob;\n }\n currentQuality = Math.max(this.minimumQuality, currentQuality - this.qualityStep);\n }\n }\n canvasToBlob(canvas, mimeType, quality) {\n return new Promise((resolve, reject) => {\n canvas.toBlob((blob) => {\n if (blob) {\n resolve(blob);\n }\n else {\n reject(new Error('Failed to create blob from canvas'));\n }\n }, mimeType, quality);\n });\n }\n createImageFromBlob(blob) {\n return new Promise((resolve, reject) => {\n const img = new Image();\n const url = URL.createObjectURL(blob);\n img.onload = () => {\n URL.revokeObjectURL(url);\n resolve(img);\n };\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error('Failed to load image from blob'));\n };\n img.src = url;\n });\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
|