@dynlabs/react-native-image-to-webp 0.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/LICENSE +20 -0
- package/README.md +247 -0
- package/ReactNativeImageToWebp.podspec +35 -0
- package/android/build.gradle +85 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/CMakeLists.txt +67 -0
- package/android/src/main/cpp/ImageToWebPJNI.cpp +73 -0
- package/android/src/main/java/com/dynlabs/reactnativeimagetowebp/ReactNativeImageToWebpModule.kt +258 -0
- package/android/src/main/java/com/dynlabs/reactnativeimagetowebp/ReactNativeImageToWebpPackage.kt +33 -0
- package/cpp/ImageToWebP.cpp +132 -0
- package/cpp/ImageToWebP.h +41 -0
- package/cpp/README.md +21 -0
- package/cpp/SETUP.md +71 -0
- package/ios/ReactNativeImageToWebp.h +5 -0
- package/ios/ReactNativeImageToWebp.mm +342 -0
- package/lib/module/NativeReactNativeImageToWebp.js +5 -0
- package/lib/module/NativeReactNativeImageToWebp.js.map +1 -0
- package/lib/module/index.js +78 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/presets.js +64 -0
- package/lib/module/presets.js.map +1 -0
- package/lib/module/validation.js +36 -0
- package/lib/module/validation.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeReactNativeImageToWebp.d.ts +24 -0
- package/lib/typescript/src/NativeReactNativeImageToWebp.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +35 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/presets.d.ts +3 -0
- package/lib/typescript/src/presets.d.ts.map +1 -0
- package/lib/typescript/src/validation.d.ts +9 -0
- package/lib/typescript/src/validation.d.ts.map +1 -0
- package/package.json +139 -0
- package/src/NativeReactNativeImageToWebp.ts +32 -0
- package/src/index.tsx +109 -0
- package/src/presets.ts +80 -0
- package/src/validation.ts +55 -0
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
#import "ReactNativeImageToWebp.h"
|
|
2
|
+
#import <React/RCTUtils.h>
|
|
3
|
+
#import <ImageIO/ImageIO.h>
|
|
4
|
+
#import <CoreGraphics/CoreGraphics.h>
|
|
5
|
+
#import <Accelerate/Accelerate.h>
|
|
6
|
+
#import <Foundation/Foundation.h>
|
|
7
|
+
#import "ImageToWebP.h"
|
|
8
|
+
|
|
9
|
+
// Error domain
|
|
10
|
+
static NSString *const kErrorDomain = @"ReactNativeImageToWebp";
|
|
11
|
+
|
|
12
|
+
// Error codes matching JS API
|
|
13
|
+
static NSString *const kErrorCodeInvalidInput = @"INVALID_INPUT";
|
|
14
|
+
static NSString *const kErrorCodeFileNotFound = @"FILE_NOT_FOUND";
|
|
15
|
+
static NSString *const kErrorCodeDecodeFailed = @"DECODE_FAILED";
|
|
16
|
+
static NSString *const kErrorCodeEncodeFailed = @"ENCODE_FAILED";
|
|
17
|
+
static NSString *const kErrorCodeIOError = @"IO_ERROR";
|
|
18
|
+
static NSString *const kErrorCodeUnsupportedFormat = @"UNSUPPORTED_FORMAT";
|
|
19
|
+
|
|
20
|
+
@interface ReactNativeImageToWebp ()
|
|
21
|
+
@end
|
|
22
|
+
|
|
23
|
+
@implementation ReactNativeImageToWebp
|
|
24
|
+
|
|
25
|
+
+ (NSString *)moduleName {
|
|
26
|
+
return @"ReactNativeImageToWebp";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Helper to get CGImageSource from file path
|
|
30
|
+
static CGImageSourceRef createImageSource(NSString *path, NSError **error) {
|
|
31
|
+
NSURL *url = [NSURL fileURLWithPath:path];
|
|
32
|
+
if (!url) {
|
|
33
|
+
if (error) {
|
|
34
|
+
*error = [NSError errorWithDomain:kErrorDomain
|
|
35
|
+
code:1
|
|
36
|
+
userInfo:@{NSLocalizedDescriptionKey: @"Invalid file path",
|
|
37
|
+
@"code": kErrorCodeInvalidInput}];
|
|
38
|
+
}
|
|
39
|
+
return NULL;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
CGImageSourceRef source = CGImageSourceCreateWithURL((__bridge CFURLRef)url, NULL);
|
|
43
|
+
if (!source) {
|
|
44
|
+
if (error) {
|
|
45
|
+
*error = [NSError errorWithDomain:kErrorDomain
|
|
46
|
+
code:1
|
|
47
|
+
userInfo:@{NSLocalizedDescriptionKey: @"File not found or cannot be read",
|
|
48
|
+
@"code": kErrorCodeFileNotFound}];
|
|
49
|
+
}
|
|
50
|
+
return NULL;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return source;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Get image properties including orientation
|
|
57
|
+
static NSDictionary *getImageProperties(CGImageSourceRef source) {
|
|
58
|
+
return (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(source, 0, NULL);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Apply EXIF orientation to get correctly oriented image
|
|
62
|
+
static CGImageRef createOrientedImage(CGImageRef image, NSDictionary *properties) {
|
|
63
|
+
NSNumber *orientationValue = properties[(__bridge NSString *)kCGImagePropertyOrientation];
|
|
64
|
+
if (!orientationValue) {
|
|
65
|
+
return CGImageRetain(image);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
int orientation = [orientationValue intValue];
|
|
69
|
+
if (orientation == 1) {
|
|
70
|
+
return CGImageRetain(image); // No rotation needed
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Calculate transform based on orientation
|
|
74
|
+
CGAffineTransform transform = CGAffineTransformIdentity;
|
|
75
|
+
CGFloat width = CGImageGetWidth(image);
|
|
76
|
+
CGFloat height = CGImageGetHeight(image);
|
|
77
|
+
|
|
78
|
+
switch (orientation) {
|
|
79
|
+
case 2: // Flip horizontal
|
|
80
|
+
transform = CGAffineTransformMakeScale(-1, 1);
|
|
81
|
+
transform = CGAffineTransformTranslate(transform, -width, 0);
|
|
82
|
+
break;
|
|
83
|
+
case 3: // Rotate 180
|
|
84
|
+
transform = CGAffineTransformMakeTranslation(width, height);
|
|
85
|
+
transform = CGAffineTransformRotate(transform, M_PI);
|
|
86
|
+
break;
|
|
87
|
+
case 4: // Flip vertical
|
|
88
|
+
transform = CGAffineTransformMakeScale(1, -1);
|
|
89
|
+
transform = CGAffineTransformTranslate(transform, 0, -height);
|
|
90
|
+
break;
|
|
91
|
+
case 5: // Rotate 90 CCW and flip
|
|
92
|
+
transform = CGAffineTransformMakeTranslation(height, 0);
|
|
93
|
+
transform = CGAffineTransformRotate(transform, M_PI_2);
|
|
94
|
+
transform = CGAffineTransformScale(transform, -1, 1);
|
|
95
|
+
break;
|
|
96
|
+
case 6: // Rotate 90 CW
|
|
97
|
+
transform = CGAffineTransformMakeTranslation(height, 0);
|
|
98
|
+
transform = CGAffineTransformRotate(transform, M_PI_2);
|
|
99
|
+
break;
|
|
100
|
+
case 7: // Rotate 90 CW and flip
|
|
101
|
+
transform = CGAffineTransformMakeTranslation(0, width);
|
|
102
|
+
transform = CGAffineTransformRotate(transform, -M_PI_2);
|
|
103
|
+
transform = CGAffineTransformScale(transform, -1, 1);
|
|
104
|
+
break;
|
|
105
|
+
case 8: // Rotate 90 CCW
|
|
106
|
+
transform = CGAffineTransformMakeTranslation(0, width);
|
|
107
|
+
transform = CGAffineTransformRotate(transform, -M_PI_2);
|
|
108
|
+
break;
|
|
109
|
+
default:
|
|
110
|
+
return CGImageRetain(image);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Create bitmap context and draw transformed image
|
|
114
|
+
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
115
|
+
CGContextRef context = CGBitmapContextCreate(NULL,
|
|
116
|
+
(orientation >= 5 && orientation <= 8) ? height : width,
|
|
117
|
+
(orientation >= 5 && orientation <= 8) ? width : height,
|
|
118
|
+
8, 0, colorSpace,
|
|
119
|
+
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
|
|
120
|
+
CGColorSpaceRelease(colorSpace);
|
|
121
|
+
|
|
122
|
+
if (!context) {
|
|
123
|
+
return CGImageRetain(image);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
CGContextConcatCTM(context, transform);
|
|
127
|
+
CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);
|
|
128
|
+
CGImageRef orientedImage = CGBitmapContextCreateImage(context);
|
|
129
|
+
CGContextRelease(context);
|
|
130
|
+
|
|
131
|
+
return orientedImage ?: CGImageRetain(image);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Resize image if maxLongEdge is specified
|
|
135
|
+
static CGImageRef resizeImageIfNeeded(CGImageRef image, NSNumber *maxLongEdge) {
|
|
136
|
+
if (!maxLongEdge || [maxLongEdge doubleValue] <= 0) {
|
|
137
|
+
return CGImageRetain(image);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
CGFloat width = CGImageGetWidth(image);
|
|
141
|
+
CGFloat height = CGImageGetHeight(image);
|
|
142
|
+
CGFloat maxEdge = [maxLongEdge doubleValue];
|
|
143
|
+
CGFloat currentMax = MAX(width, height);
|
|
144
|
+
|
|
145
|
+
if (currentMax <= maxEdge) {
|
|
146
|
+
return CGImageRetain(image);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
CGFloat scale = maxEdge / currentMax;
|
|
150
|
+
CGFloat newWidth = width * scale;
|
|
151
|
+
CGFloat newHeight = height * scale;
|
|
152
|
+
|
|
153
|
+
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
154
|
+
CGContextRef context = CGBitmapContextCreate(NULL,
|
|
155
|
+
(size_t)newWidth,
|
|
156
|
+
(size_t)newHeight,
|
|
157
|
+
8, 0, colorSpace,
|
|
158
|
+
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
|
|
159
|
+
CGColorSpaceRelease(colorSpace);
|
|
160
|
+
|
|
161
|
+
if (!context) {
|
|
162
|
+
return CGImageRetain(image);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
|
|
166
|
+
CGContextDrawImage(context, CGRectMake(0, 0, newWidth, newHeight), image);
|
|
167
|
+
CGImageRef resizedImage = CGBitmapContextCreateImage(context);
|
|
168
|
+
CGContextRelease(context);
|
|
169
|
+
|
|
170
|
+
return resizedImage ?: CGImageRetain(image);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Convert CGImage to RGBA buffer
|
|
174
|
+
static uint8_t *createRGBABuffer(CGImageRef image, uint32_t *outWidth, uint32_t *outHeight) {
|
|
175
|
+
size_t width = CGImageGetWidth(image);
|
|
176
|
+
size_t height = CGImageGetHeight(image);
|
|
177
|
+
size_t bytesPerPixel = 4;
|
|
178
|
+
size_t bytesPerRow = width * bytesPerPixel;
|
|
179
|
+
size_t bufferSize = bytesPerRow * height;
|
|
180
|
+
|
|
181
|
+
uint8_t *buffer = (uint8_t *)malloc(bufferSize);
|
|
182
|
+
if (!buffer) {
|
|
183
|
+
return NULL;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
187
|
+
CGContextRef context = CGBitmapContextCreate(buffer,
|
|
188
|
+
width,
|
|
189
|
+
height,
|
|
190
|
+
8,
|
|
191
|
+
bytesPerRow,
|
|
192
|
+
colorSpace,
|
|
193
|
+
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
|
|
194
|
+
CGColorSpaceRelease(colorSpace);
|
|
195
|
+
|
|
196
|
+
if (!context) {
|
|
197
|
+
free(buffer);
|
|
198
|
+
return NULL;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);
|
|
202
|
+
CGContextRelease(context);
|
|
203
|
+
|
|
204
|
+
*outWidth = (uint32_t)width;
|
|
205
|
+
*outHeight = (uint32_t)height;
|
|
206
|
+
return buffer;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Derive output path from input path if not provided
|
|
210
|
+
static NSString *deriveOutputPath(NSString *inputPath, NSString *outputPath) {
|
|
211
|
+
if (outputPath && outputPath.length > 0) {
|
|
212
|
+
return outputPath;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
NSString *directory = [inputPath stringByDeletingLastPathComponent];
|
|
216
|
+
NSString *filename = [[inputPath lastPathComponent] stringByDeletingPathExtension];
|
|
217
|
+
return [directory stringByAppendingPathComponent:[filename stringByAppendingPathExtension:@"webp"]];
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
- (void)convertImageToWebP:(NSDictionary *)options
|
|
221
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
222
|
+
rejecter:(RCTPromiseRejectBlock)reject {
|
|
223
|
+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
224
|
+
@autoreleasepool {
|
|
225
|
+
NSError *error = nil;
|
|
226
|
+
|
|
227
|
+
// Parse options
|
|
228
|
+
NSString *inputPath = options[@"inputPath"];
|
|
229
|
+
if (!inputPath || ![inputPath isKindOfClass:[NSString class]]) {
|
|
230
|
+
reject(kErrorCodeInvalidInput, @"inputPath is required", nil);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
NSString *outputPath = deriveOutputPath(inputPath, options[@"outputPath"]);
|
|
235
|
+
NSNumber *maxLongEdge = options[@"maxLongEdge"];
|
|
236
|
+
NSNumber *quality = options[@"quality"] ?: @80;
|
|
237
|
+
NSNumber *method = options[@"method"] ?: @3;
|
|
238
|
+
NSNumber *lossless = options[@"lossless"] ?: @NO;
|
|
239
|
+
NSNumber *stripMetadata = options[@"stripMetadata"];
|
|
240
|
+
if (!stripMetadata) {
|
|
241
|
+
stripMetadata = @YES;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Check if input file exists
|
|
245
|
+
if (![[NSFileManager defaultManager] fileExistsAtPath:inputPath]) {
|
|
246
|
+
reject(kErrorCodeFileNotFound, [NSString stringWithFormat:@"File not found: %@", inputPath], nil);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Create image source
|
|
251
|
+
CGImageSourceRef source = createImageSource(inputPath, &error);
|
|
252
|
+
if (!source) {
|
|
253
|
+
reject(error.userInfo[@"code"] ?: kErrorCodeDecodeFailed,
|
|
254
|
+
error.localizedDescription ?: @"Failed to create image source",
|
|
255
|
+
error);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Get image properties
|
|
260
|
+
NSDictionary *properties = getImageProperties(source);
|
|
261
|
+
if (!properties) {
|
|
262
|
+
CGImageSourceRelease(source);
|
|
263
|
+
reject(kErrorCodeDecodeFailed, @"Failed to read image properties", nil);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Create CGImage
|
|
268
|
+
CGImageRef image = CGImageSourceCreateImageAtIndex(source, 0, NULL);
|
|
269
|
+
CGImageSourceRelease(source);
|
|
270
|
+
if (!image) {
|
|
271
|
+
reject(kErrorCodeDecodeFailed, @"Failed to decode image", nil);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Apply orientation
|
|
276
|
+
CGImageRef orientedImage = createOrientedImage(image, properties);
|
|
277
|
+
CGImageRelease(image);
|
|
278
|
+
if (!orientedImage) {
|
|
279
|
+
reject(kErrorCodeDecodeFailed, @"Failed to apply orientation", nil);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Resize if needed
|
|
284
|
+
CGImageRef finalImage = resizeImageIfNeeded(orientedImage, maxLongEdge);
|
|
285
|
+
CGImageRelease(orientedImage);
|
|
286
|
+
if (!finalImage) {
|
|
287
|
+
reject(kErrorCodeDecodeFailed, @"Failed to resize image", nil);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Convert to RGBA buffer
|
|
292
|
+
uint32_t width, height;
|
|
293
|
+
uint8_t *rgbaData = createRGBABuffer(finalImage, &width, &height);
|
|
294
|
+
CGImageRelease(finalImage);
|
|
295
|
+
if (!rgbaData) {
|
|
296
|
+
reject(kErrorCodeDecodeFailed, @"Failed to create RGBA buffer", nil);
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Prepare WebP encoding options
|
|
301
|
+
WebPEncodeOptions encodeOptions;
|
|
302
|
+
encodeOptions.quality = [quality intValue];
|
|
303
|
+
encodeOptions.method = [method intValue];
|
|
304
|
+
encodeOptions.lossless = [lossless boolValue];
|
|
305
|
+
encodeOptions.stripMetadata = [stripMetadata boolValue];
|
|
306
|
+
encodeOptions.threadLevel = 1;
|
|
307
|
+
|
|
308
|
+
// Encode to WebP
|
|
309
|
+
std::string outputPathStr = [outputPath UTF8String];
|
|
310
|
+
WebPEncodeResult result = encodeWebP(rgbaData, width, height, encodeOptions, outputPathStr);
|
|
311
|
+
free(rgbaData);
|
|
312
|
+
|
|
313
|
+
if (!result.success) {
|
|
314
|
+
NSString *errorMsg = [NSString stringWithUTF8String:result.errorMessage.c_str()];
|
|
315
|
+
reject(kErrorCodeEncodeFailed, errorMsg, nil);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Get file size
|
|
320
|
+
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:outputPath error:&error];
|
|
321
|
+
NSNumber *fileSize = fileAttributes[NSFileSize];
|
|
322
|
+
if (!fileSize) {
|
|
323
|
+
fileSize = @0;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Return result
|
|
327
|
+
resolve(@{
|
|
328
|
+
@"outputPath": outputPath,
|
|
329
|
+
@"width": @(result.width ?: width),
|
|
330
|
+
@"height": @(result.height ?: height),
|
|
331
|
+
@"sizeBytes": fileSize,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
338
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params {
|
|
339
|
+
return std::make_shared<facebook::react::NativeReactNativeImageToWebpSpecJSI>(params);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
@end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"..\\..\\src","sources":["NativeReactNativeImageToWebp.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;AA+BpE,eAAeA,mBAAmB,CAACC,YAAY,CAAO,wBAAwB,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import NativeReactNativeImageToWebp from "./NativeReactNativeImageToWebp.js";
|
|
4
|
+
import { validateOptions } from "./validation.js";
|
|
5
|
+
import { applyPreset } from "./presets.js";
|
|
6
|
+
const ERROR_CODES = {
|
|
7
|
+
INVALID_INPUT: 'INVALID_INPUT',
|
|
8
|
+
FILE_NOT_FOUND: 'FILE_NOT_FOUND',
|
|
9
|
+
DECODE_FAILED: 'DECODE_FAILED',
|
|
10
|
+
ENCODE_FAILED: 'ENCODE_FAILED',
|
|
11
|
+
IO_ERROR: 'IO_ERROR',
|
|
12
|
+
UNSUPPORTED_FORMAT: 'UNSUPPORTED_FORMAT'
|
|
13
|
+
};
|
|
14
|
+
export class ImageToWebPError extends Error {
|
|
15
|
+
constructor(code, message) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = 'ImageToWebPError';
|
|
18
|
+
this.code = code;
|
|
19
|
+
Object.setPrototypeOf(this, ImageToWebPError.prototype);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Convert an image file to WebP format.
|
|
25
|
+
*
|
|
26
|
+
* @param options - Conversion options
|
|
27
|
+
* @returns Promise resolving to conversion result with output path and metadata
|
|
28
|
+
* @throws {ImageToWebPError} If conversion fails
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* const result = await convertImageToWebP({
|
|
33
|
+
* inputPath: '/path/to/image.jpg',
|
|
34
|
+
* preset: 'balanced',
|
|
35
|
+
* maxLongEdge: 2048,
|
|
36
|
+
* });
|
|
37
|
+
* console.log(`Output: ${result.outputPath}, Size: ${result.sizeBytes} bytes`);
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export async function convertImageToWebP(options) {
|
|
41
|
+
// Validate input
|
|
42
|
+
const validationError = validateOptions(options);
|
|
43
|
+
if (validationError) {
|
|
44
|
+
throw new ImageToWebPError(validationError.code, validationError.message);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Apply preset defaults
|
|
48
|
+
const finalOptions = applyPreset(options);
|
|
49
|
+
try {
|
|
50
|
+
return await NativeReactNativeImageToWebp.convertImageToWebP(finalOptions);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
// Map native errors to our error types
|
|
53
|
+
if (error instanceof Error) {
|
|
54
|
+
const message = error.message;
|
|
55
|
+
if (message.includes('FILE_NOT_FOUND')) {
|
|
56
|
+
throw new ImageToWebPError(ERROR_CODES.FILE_NOT_FOUND, `File not found: ${options.inputPath}`);
|
|
57
|
+
}
|
|
58
|
+
if (message.includes('DECODE_FAILED')) {
|
|
59
|
+
throw new ImageToWebPError(ERROR_CODES.DECODE_FAILED, `Failed to decode image: ${message}`);
|
|
60
|
+
}
|
|
61
|
+
if (message.includes('ENCODE_FAILED')) {
|
|
62
|
+
throw new ImageToWebPError(ERROR_CODES.ENCODE_FAILED, `Failed to encode WebP: ${message}`);
|
|
63
|
+
}
|
|
64
|
+
if (message.includes('IO_ERROR')) {
|
|
65
|
+
throw new ImageToWebPError(ERROR_CODES.IO_ERROR, `I/O error: ${message}`);
|
|
66
|
+
}
|
|
67
|
+
if (message.includes('UNSUPPORTED_FORMAT')) {
|
|
68
|
+
throw new ImageToWebPError(ERROR_CODES.UNSUPPORTED_FORMAT, `Unsupported image format: ${message}`);
|
|
69
|
+
}
|
|
70
|
+
if (message.includes('INVALID_INPUT')) {
|
|
71
|
+
throw new ImageToWebPError(ERROR_CODES.INVALID_INPUT, `Invalid input: ${message}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export { ERROR_CODES };
|
|
78
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["NativeReactNativeImageToWebp","validateOptions","applyPreset","ERROR_CODES","INVALID_INPUT","FILE_NOT_FOUND","DECODE_FAILED","ENCODE_FAILED","IO_ERROR","UNSUPPORTED_FORMAT","ImageToWebPError","Error","constructor","code","message","name","Object","setPrototypeOf","prototype","convertImageToWebP","options","validationError","finalOptions","error","includes","inputPath"],"sourceRoot":"..\\..\\src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,4BAA4B,MAI5B,mCAAgC;AACvC,SAASC,eAAe,QAAQ,iBAAc;AAC9C,SAASC,WAAW,QAAQ,cAAW;AAIvC,MAAMC,WAAW,GAAG;EAClBC,aAAa,EAAE,eAAe;EAC9BC,cAAc,EAAE,gBAAgB;EAChCC,aAAa,EAAE,eAAe;EAC9BC,aAAa,EAAE,eAAe;EAC9BC,QAAQ,EAAE,UAAU;EACpBC,kBAAkB,EAAE;AACtB,CAAU;AAIV,OAAO,MAAMC,gBAAgB,SAASC,KAAK,CAAC;EAG1CC,WAAWA,CAACC,IAAe,EAAEC,OAAe,EAAE;IAC5C,KAAK,CAACA,OAAO,CAAC;IACd,IAAI,CAACC,IAAI,GAAG,kBAAkB;IAC9B,IAAI,CAACF,IAAI,GAAGA,IAAI;IAChBG,MAAM,CAACC,cAAc,CAAC,IAAI,EAAEP,gBAAgB,CAACQ,SAAS,CAAC;EACzD;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,kBAAkBA,CACtCC,OAAuB,EACC;EACxB;EACA,MAAMC,eAAe,GAAGpB,eAAe,CAACmB,OAAO,CAAC;EAChD,IAAIC,eAAe,EAAE;IACnB,MAAM,IAAIX,gBAAgB,CAACW,eAAe,CAACR,IAAI,EAAEQ,eAAe,CAACP,OAAO,CAAC;EAC3E;;EAEA;EACA,MAAMQ,YAAY,GAAGpB,WAAW,CAACkB,OAAO,CAAC;EAEzC,IAAI;IACF,OAAO,MAAMpB,4BAA4B,CAACmB,kBAAkB,CAACG,YAAY,CAAC;EAC5E,CAAC,CAAC,OAAOC,KAAK,EAAE;IACd;IACA,IAAIA,KAAK,YAAYZ,KAAK,EAAE;MAC1B,MAAMG,OAAO,GAAGS,KAAK,CAACT,OAAO;MAC7B,IAAIA,OAAO,CAACU,QAAQ,CAAC,gBAAgB,CAAC,EAAE;QACtC,MAAM,IAAId,gBAAgB,CACxBP,WAAW,CAACE,cAAc,EAC1B,mBAAmBe,OAAO,CAACK,SAAS,EACtC,CAAC;MACH;MACA,IAAIX,OAAO,CAACU,QAAQ,CAAC,eAAe,CAAC,EAAE;QACrC,MAAM,IAAId,gBAAgB,CACxBP,WAAW,CAACG,aAAa,EACzB,2BAA2BQ,OAAO,EACpC,CAAC;MACH;MACA,IAAIA,OAAO,CAACU,QAAQ,CAAC,eAAe,CAAC,EAAE;QACrC,MAAM,IAAId,gBAAgB,CACxBP,WAAW,CAACI,aAAa,EACzB,0BAA0BO,OAAO,EACnC,CAAC;MACH;MACA,IAAIA,OAAO,CAACU,QAAQ,CAAC,UAAU,CAAC,EAAE;QAChC,MAAM,IAAId,gBAAgB,CACxBP,WAAW,CAACK,QAAQ,EACpB,cAAcM,OAAO,EACvB,CAAC;MACH;MACA,IAAIA,OAAO,CAACU,QAAQ,CAAC,oBAAoB,CAAC,EAAE;QAC1C,MAAM,IAAId,gBAAgB,CACxBP,WAAW,CAACM,kBAAkB,EAC9B,6BAA6BK,OAAO,EACtC,CAAC;MACH;MACA,IAAIA,OAAO,CAACU,QAAQ,CAAC,eAAe,CAAC,EAAE;QACrC,MAAM,IAAId,gBAAgB,CACxBP,WAAW,CAACC,aAAa,EACzB,kBAAkBU,OAAO,EAC3B,CAAC;MACH;IACF;IACA,MAAMS,KAAK;EACb;AACF;AAEA,SAASpB,WAAW","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const PRESETS = {
|
|
4
|
+
balanced: {
|
|
5
|
+
quality: 80,
|
|
6
|
+
method: 3,
|
|
7
|
+
lossless: false,
|
|
8
|
+
stripMetadata: true,
|
|
9
|
+
threadLevel: 1
|
|
10
|
+
},
|
|
11
|
+
small: {
|
|
12
|
+
quality: 74,
|
|
13
|
+
method: 5,
|
|
14
|
+
lossless: false,
|
|
15
|
+
stripMetadata: true,
|
|
16
|
+
threadLevel: 1
|
|
17
|
+
},
|
|
18
|
+
fast: {
|
|
19
|
+
quality: 78,
|
|
20
|
+
method: 1,
|
|
21
|
+
lossless: false,
|
|
22
|
+
stripMetadata: true,
|
|
23
|
+
threadLevel: 1
|
|
24
|
+
},
|
|
25
|
+
lossless: {
|
|
26
|
+
lossless: true,
|
|
27
|
+
method: 4,
|
|
28
|
+
stripMetadata: true
|
|
29
|
+
},
|
|
30
|
+
document: {
|
|
31
|
+
quality: 82,
|
|
32
|
+
method: 4,
|
|
33
|
+
lossless: false,
|
|
34
|
+
stripMetadata: true,
|
|
35
|
+
exact: true // Will be set conditionally if alpha present
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
export function applyPreset(options) {
|
|
39
|
+
const preset = options.preset || 'balanced';
|
|
40
|
+
const presetConfig = PRESETS[preset];
|
|
41
|
+
const result = {
|
|
42
|
+
...options
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Apply preset values only if not explicitly overridden
|
|
46
|
+
if (result.quality === undefined && presetConfig.quality !== undefined) {
|
|
47
|
+
result.quality = presetConfig.quality;
|
|
48
|
+
}
|
|
49
|
+
if (result.method === undefined && presetConfig.method !== undefined) {
|
|
50
|
+
result.method = presetConfig.method;
|
|
51
|
+
}
|
|
52
|
+
if (result.lossless === undefined && presetConfig.lossless !== undefined) {
|
|
53
|
+
result.lossless = presetConfig.lossless;
|
|
54
|
+
}
|
|
55
|
+
if (result.stripMetadata === undefined && presetConfig.stripMetadata !== undefined) {
|
|
56
|
+
result.stripMetadata = presetConfig.stripMetadata;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Note: threadLevel and exact are handled natively, not passed through JS API
|
|
60
|
+
// They are documented here for reference but applied in native code
|
|
61
|
+
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["PRESETS","balanced","quality","method","lossless","stripMetadata","threadLevel","small","fast","document","exact","applyPreset","options","preset","presetConfig","result","undefined"],"sourceRoot":"..\\..\\src","sources":["presets.ts"],"mappings":";;AAcA,MAAMA,OAA4C,GAAG;EACnDC,QAAQ,EAAE;IACRC,OAAO,EAAE,EAAE;IACXC,MAAM,EAAE,CAAC;IACTC,QAAQ,EAAE,KAAK;IACfC,aAAa,EAAE,IAAI;IACnBC,WAAW,EAAE;EACf,CAAC;EACDC,KAAK,EAAE;IACLL,OAAO,EAAE,EAAE;IACXC,MAAM,EAAE,CAAC;IACTC,QAAQ,EAAE,KAAK;IACfC,aAAa,EAAE,IAAI;IACnBC,WAAW,EAAE;EACf,CAAC;EACDE,IAAI,EAAE;IACJN,OAAO,EAAE,EAAE;IACXC,MAAM,EAAE,CAAC;IACTC,QAAQ,EAAE,KAAK;IACfC,aAAa,EAAE,IAAI;IACnBC,WAAW,EAAE;EACf,CAAC;EACDF,QAAQ,EAAE;IACRA,QAAQ,EAAE,IAAI;IACdD,MAAM,EAAE,CAAC;IACTE,aAAa,EAAE;EACjB,CAAC;EACDI,QAAQ,EAAE;IACRP,OAAO,EAAE,EAAE;IACXC,MAAM,EAAE,CAAC;IACTC,QAAQ,EAAE,KAAK;IACfC,aAAa,EAAE,IAAI;IACnBK,KAAK,EAAE,IAAI,CAAE;EACf;AACF,CAAC;AAED,OAAO,SAASC,WAAWA,CAACC,OAAuB,EAAkB;EACnE,MAAMC,MAAqB,GAAGD,OAAO,CAACC,MAAM,IAAI,UAAU;EAC1D,MAAMC,YAAY,GAAGd,OAAO,CAACa,MAAM,CAAC;EAEpC,MAAME,MAAsB,GAAG;IAC7B,GAAGH;EACL,CAAC;;EAED;EACA,IAAIG,MAAM,CAACb,OAAO,KAAKc,SAAS,IAAIF,YAAY,CAACZ,OAAO,KAAKc,SAAS,EAAE;IACtED,MAAM,CAACb,OAAO,GAAGY,YAAY,CAACZ,OAAO;EACvC;EACA,IAAIa,MAAM,CAACZ,MAAM,KAAKa,SAAS,IAAIF,YAAY,CAACX,MAAM,KAAKa,SAAS,EAAE;IACpED,MAAM,CAACZ,MAAM,GAAGW,YAAY,CAACX,MAAM;EACrC;EACA,IAAIY,MAAM,CAACX,QAAQ,KAAKY,SAAS,IAAIF,YAAY,CAACV,QAAQ,KAAKY,SAAS,EAAE;IACxED,MAAM,CAACX,QAAQ,GAAGU,YAAY,CAACV,QAAQ;EACzC;EACA,IACEW,MAAM,CAACV,aAAa,KAAKW,SAAS,IAClCF,YAAY,CAACT,aAAa,KAAKW,SAAS,EACxC;IACAD,MAAM,CAACV,aAAa,GAAGS,YAAY,CAACT,aAAa;EACnD;;EAEA;EACA;;EAEA,OAAOU,MAAM;AACf","ignoreList":[]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export function validateOptions(options) {
|
|
4
|
+
if (!options.inputPath || typeof options.inputPath !== 'string') {
|
|
5
|
+
return {
|
|
6
|
+
code: 'INVALID_INPUT',
|
|
7
|
+
message: 'inputPath is required and must be a string'
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
if (options.maxLongEdge !== undefined) {
|
|
11
|
+
if (typeof options.maxLongEdge !== 'number' || options.maxLongEdge <= 0) {
|
|
12
|
+
return {
|
|
13
|
+
code: 'INVALID_INPUT',
|
|
14
|
+
message: 'maxLongEdge must be a positive number'
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (options.quality !== undefined) {
|
|
19
|
+
if (typeof options.quality !== 'number' || options.quality < 0 || options.quality > 100) {
|
|
20
|
+
return {
|
|
21
|
+
code: 'INVALID_INPUT',
|
|
22
|
+
message: 'quality must be a number between 0 and 100'
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (options.method !== undefined) {
|
|
27
|
+
if (typeof options.method !== 'number' || options.method < 0 || options.method > 6) {
|
|
28
|
+
return {
|
|
29
|
+
code: 'INVALID_INPUT',
|
|
30
|
+
message: 'method must be a number between 0 and 6'
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["validateOptions","options","inputPath","code","message","maxLongEdge","undefined","quality","method"],"sourceRoot":"..\\..\\src","sources":["validation.ts"],"mappings":";;AAQA,OAAO,SAASA,eAAeA,CAC7BC,OAAuB,EACC;EACxB,IAAI,CAACA,OAAO,CAACC,SAAS,IAAI,OAAOD,OAAO,CAACC,SAAS,KAAK,QAAQ,EAAE;IAC/D,OAAO;MACLC,IAAI,EAAE,eAAe;MACrBC,OAAO,EAAE;IACX,CAAC;EACH;EAEA,IAAIH,OAAO,CAACI,WAAW,KAAKC,SAAS,EAAE;IACrC,IAAI,OAAOL,OAAO,CAACI,WAAW,KAAK,QAAQ,IAAIJ,OAAO,CAACI,WAAW,IAAI,CAAC,EAAE;MACvE,OAAO;QACLF,IAAI,EAAE,eAAe;QACrBC,OAAO,EAAE;MACX,CAAC;IACH;EACF;EAEA,IAAIH,OAAO,CAACM,OAAO,KAAKD,SAAS,EAAE;IACjC,IACE,OAAOL,OAAO,CAACM,OAAO,KAAK,QAAQ,IACnCN,OAAO,CAACM,OAAO,GAAG,CAAC,IACnBN,OAAO,CAACM,OAAO,GAAG,GAAG,EACrB;MACA,OAAO;QACLJ,IAAI,EAAE,eAAe;QACrBC,OAAO,EAAE;MACX,CAAC;IACH;EACF;EAEA,IAAIH,OAAO,CAACO,MAAM,KAAKF,SAAS,EAAE;IAChC,IACE,OAAOL,OAAO,CAACO,MAAM,KAAK,QAAQ,IAClCP,OAAO,CAACO,MAAM,GAAG,CAAC,IAClBP,OAAO,CAACO,MAAM,GAAG,CAAC,EAClB;MACA,OAAO;QACLL,IAAI,EAAE,eAAe;QACrBC,OAAO,EAAE;MACX,CAAC;IACH;EACF;EAEA,OAAO,IAAI;AACb","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type TurboModule } from 'react-native';
|
|
2
|
+
export type ConvertPreset = 'balanced' | 'small' | 'fast' | 'lossless' | 'document';
|
|
3
|
+
export interface ConvertOptions {
|
|
4
|
+
inputPath: string;
|
|
5
|
+
outputPath?: string;
|
|
6
|
+
preset?: ConvertPreset;
|
|
7
|
+
maxLongEdge?: number;
|
|
8
|
+
quality?: number;
|
|
9
|
+
method?: number;
|
|
10
|
+
lossless?: boolean;
|
|
11
|
+
stripMetadata?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface ConvertResult {
|
|
14
|
+
outputPath: string;
|
|
15
|
+
width: number;
|
|
16
|
+
height: number;
|
|
17
|
+
sizeBytes: number;
|
|
18
|
+
}
|
|
19
|
+
export interface Spec extends TurboModule {
|
|
20
|
+
convertImageToWebP(options: ConvertOptions): Promise<ConvertResult>;
|
|
21
|
+
}
|
|
22
|
+
declare const _default: Spec;
|
|
23
|
+
export default _default;
|
|
24
|
+
//# sourceMappingURL=NativeReactNativeImageToWebp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeReactNativeImageToWebp.d.ts","sourceRoot":"","sources":["../../../src/NativeReactNativeImageToWebp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAErE,MAAM,MAAM,aAAa,GACrB,UAAU,GACV,OAAO,GACP,MAAM,GACN,UAAU,GACV,UAAU,CAAC;AAEf,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CACrE;;AAED,wBAAgF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type ConvertOptions, type ConvertResult, type ConvertPreset } from './NativeReactNativeImageToWebp';
|
|
2
|
+
export type { ConvertOptions, ConvertResult, ConvertPreset };
|
|
3
|
+
declare const ERROR_CODES: {
|
|
4
|
+
readonly INVALID_INPUT: "INVALID_INPUT";
|
|
5
|
+
readonly FILE_NOT_FOUND: "FILE_NOT_FOUND";
|
|
6
|
+
readonly DECODE_FAILED: "DECODE_FAILED";
|
|
7
|
+
readonly ENCODE_FAILED: "ENCODE_FAILED";
|
|
8
|
+
readonly IO_ERROR: "IO_ERROR";
|
|
9
|
+
readonly UNSUPPORTED_FORMAT: "UNSUPPORTED_FORMAT";
|
|
10
|
+
};
|
|
11
|
+
export type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES];
|
|
12
|
+
export declare class ImageToWebPError extends Error {
|
|
13
|
+
code: ErrorCode;
|
|
14
|
+
constructor(code: ErrorCode, message: string);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Convert an image file to WebP format.
|
|
18
|
+
*
|
|
19
|
+
* @param options - Conversion options
|
|
20
|
+
* @returns Promise resolving to conversion result with output path and metadata
|
|
21
|
+
* @throws {ImageToWebPError} If conversion fails
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* const result = await convertImageToWebP({
|
|
26
|
+
* inputPath: '/path/to/image.jpg',
|
|
27
|
+
* preset: 'balanced',
|
|
28
|
+
* maxLongEdge: 2048,
|
|
29
|
+
* });
|
|
30
|
+
* console.log(`Output: ${result.outputPath}, Size: ${result.sizeBytes} bytes`);
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function convertImageToWebP(options: ConvertOptions): Promise<ConvertResult>;
|
|
34
|
+
export { ERROR_CODES };
|
|
35
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAqC,EACnC,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EACnB,MAAM,gCAAgC,CAAC;AAIxC,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC;AAE7D,QAAA,MAAM,WAAW;;;;;;;CAOP,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEvE,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,IAAI,EAAE,SAAS,CAAC;gBAEJ,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM;CAM7C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CAuDxB;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../../src/presets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EAEf,MAAM,gCAAgC,CAAC;AA+CxC,wBAAgB,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CA6BnE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ConvertOptions } from './NativeReactNativeImageToWebp';
|
|
2
|
+
import type { ErrorCode } from './index';
|
|
3
|
+
interface ValidationError {
|
|
4
|
+
code: ErrorCode;
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function validateOptions(options: ConvertOptions): ValidationError | null;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,UAAU,eAAe;IACvB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,cAAc,GACtB,eAAe,GAAG,IAAI,CA4CxB"}
|