react-native-compressor 1.19.2 → 1.19.4

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.
@@ -44,7 +44,7 @@ class ImageCompressor {
44
44
  }
45
45
 
46
46
 
47
- static func manualResize(_ image: UIImage, maxWidth: Int, maxHeight: Int) -> UIImage {
47
+ static func manualResize(_ image: UIImage, maxWidth: Int, maxHeight: Int) throws -> UIImage {
48
48
  let targetSize = findTargetSize(image, maxWidth: maxWidth, maxHeight: maxHeight)
49
49
 
50
50
  if let cgImage = image.cgImage {
@@ -82,6 +82,10 @@ class ImageCompressor {
82
82
  free(&targetData)
83
83
  let exception = NSException(name: NSExceptionName(rawValue: "drawing_error"), reason: "Problem while rendering your image", userInfo: nil)
84
84
  exception.raise()
85
+ // Throw instead of raising an NSException (process abort no JS
86
+ // catch survives) — the caller rejects the promise.
87
+ throw NSError(domain: "drawing_error", code: 1,
88
+ userInfo: [NSLocalizedDescriptionKey: "Problem while rendering your image"])
85
89
  }
86
90
 
87
91
  let targetContext = CGContext(data: &targetData,
@@ -164,7 +168,7 @@ class ImageCompressor {
164
168
  return destinationData as Data
165
169
  }
166
170
 
167
- static func writeImage(_ image: UIImage, output: Int, quality: Float, outputExtension: String, isBase64: Bool, disablePngTransparency: Bool, isEnableAutoCompress: Bool, actualImagePath: String?)-> String {
171
+ static func writeImage(_ image: UIImage, output: Int, quality: Float, outputExtension: String, isBase64: Bool, disablePngTransparency: Bool, isEnableAutoCompress: Bool, actualImagePath: String?) throws -> String {
168
172
  var data: Data
169
173
  var exception: NSException?
170
174
  let normalizedQuality = CGFloat(min(max(quality, 0), 1))
@@ -212,14 +216,19 @@ class ImageCompressor {
212
216
  } catch {
213
217
  exception = NSException(name: NSExceptionName(rawValue: "file_error"), reason: "Error writing file", userInfo: nil)
214
218
  exception?.raise()
219
+ // Throw instead of raising an NSException: a raise inside a
220
+ // TurboModule invocation aborts the whole app and no JS catch
221
+ // can intercept it — the caller rejects the promise instead.
222
+ throw NSError(domain: "file_error", code: 1,
223
+ userInfo: [NSLocalizedDescriptionKey: "Error writing file: \(error.localizedDescription)"])
215
224
  }
216
225
  }
217
226
  return ""
218
227
  }
219
228
 
220
229
 
221
- static func manualCompress(_ image: UIImage, output: Int, quality: Float, outputExtension: String, isBase64: Bool, disablePngTransparency: Bool, actualImagePath: String?) -> String {
222
- return writeImage(image, output: output, quality: quality, outputExtension: outputExtension, isBase64: isBase64, disablePngTransparency: disablePngTransparency, isEnableAutoCompress: false, actualImagePath: actualImagePath)
230
+ static func manualCompress(_ image: UIImage, output: Int, quality: Float, outputExtension: String, isBase64: Bool, disablePngTransparency: Bool, actualImagePath: String?) throws -> String {
231
+ return try writeImage(image, output: output, quality: quality, outputExtension: outputExtension, isBase64: isBase64, disablePngTransparency: disablePngTransparency, isEnableAutoCompress: false, actualImagePath: actualImagePath)
223
232
  }
224
233
 
225
234
 
@@ -288,7 +297,7 @@ class ImageCompressor {
288
297
  }
289
298
 
290
299
 
291
- static func manualCompressHandler(imagePath: String?, base64: String?, options: ImageCompressorOptions) -> String {
300
+ static func manualCompressHandler(imagePath: String?, base64: String?, options: ImageCompressorOptions) throws -> String {
292
301
  var exception: NSException?
293
302
  var image: UIImage?
294
303
 
@@ -306,22 +315,28 @@ class ImageCompressor {
306
315
  if let _image = image {
307
316
  image = ImageCompressor.scaleAndRotateImage(_image)
308
317
  let outputExtension = ImageCompressorOptions.getOutputInString(options.output)
309
- let resizedImage = ImageCompressor.manualResize(image!, maxWidth: options.maxWidth, maxHeight: options.maxHeight)
318
+ let resizedImage = try ImageCompressor.manualResize(image!, maxWidth: options.maxWidth, maxHeight: options.maxHeight)
310
319
  let isBase64 = options.returnableOutputType == .rbase64
311
- return ImageCompressor.manualCompress(resizedImage, output: options.output.rawValue, quality: options.quality, outputExtension: outputExtension, isBase64: isBase64,disablePngTransparency: options.disablePngTransparency, actualImagePath: imagePath)
320
+ return try ImageCompressor.manualCompress(resizedImage, output: options.output.rawValue, quality: options.quality, outputExtension: outputExtension, isBase64: isBase64,disablePngTransparency: options.disablePngTransparency, actualImagePath: imagePath)
312
321
  } else {
313
322
  exception = NSException(name: NSExceptionName(rawValue: "unsupported_value"), reason: "Unsupported value type.", userInfo: nil)
314
323
  exception?.raise()
324
+ // Throw instead of raising an NSException (process abort no JS
325
+ // catch survives — e.g. a stored file path invalidated by an iOS
326
+ // container relocation boot-looped an app at startup). The caller
327
+ // rejects the promise with the same name/message.
328
+ throw NSError(domain: "unsupported_value", code: 1,
329
+ userInfo: [NSLocalizedDescriptionKey: "Unsupported value type."])
315
330
  }
316
331
 
317
332
  return ""
318
333
  }
319
334
 
320
335
 
321
- static func autoCompressHandler(imagePath: String?, base64: String?, options: ImageCompressorOptions) -> String {
336
+ static func autoCompressHandler(imagePath: String?, base64: String?, options: ImageCompressorOptions) throws -> String {
322
337
  var exception: NSException?
323
338
  var image: UIImage?
324
-
339
+
325
340
  switch options.input {
326
341
  case .base64:
327
342
  if let _base64 = base64 {
@@ -332,11 +347,11 @@ class ImageCompressor {
332
347
  image = ImageCompressor.loadImage(_imagePath)
333
348
  }
334
349
  }
335
-
350
+
336
351
  if var image = image {
337
352
  image = ImageCompressor.scaleAndRotateImage(image)
338
353
  let outputExtension = ImageCompressorOptions.getOutputInString(options.output)
339
-
354
+
340
355
  var actualHeight = image.size.height
341
356
  var actualWidth = image.size.width
342
357
  let maxHeight: CGFloat = CGFloat(options.maxHeight)
@@ -344,7 +359,7 @@ class ImageCompressor {
344
359
  var imgRatio = actualWidth / actualHeight
345
360
  let maxRatio = maxWidth / maxHeight
346
361
  let compressionQuality: CGFloat = CGFloat(options.quality)
347
-
362
+
348
363
  if actualHeight > maxHeight || actualWidth > maxWidth {
349
364
  if imgRatio < maxRatio {
350
365
  imgRatio = maxHeight / actualHeight
@@ -359,20 +374,26 @@ class ImageCompressor {
359
374
  actualWidth = maxWidth
360
375
  }
361
376
  }
362
-
377
+
363
378
  let rect = CGRect(x: 0.0, y: 0.0, width: actualWidth, height: actualHeight)
364
379
  UIGraphicsBeginImageContext(rect.size)
365
380
  image.draw(in: rect)
366
381
  let isBase64 = options.returnableOutputType == .rbase64
367
-
382
+
368
383
  if let img = UIGraphicsGetImageFromCurrentImageContext() {
369
- return writeImage(img, output: options.output.rawValue, quality: Float(compressionQuality), outputExtension: outputExtension, isBase64: isBase64, disablePngTransparency: options.disablePngTransparency, isEnableAutoCompress: true, actualImagePath: imagePath)
384
+ return try writeImage(img, output: options.output.rawValue, quality: Float(compressionQuality), outputExtension: outputExtension, isBase64: isBase64, disablePngTransparency: options.disablePngTransparency, isEnableAutoCompress: true, actualImagePath: imagePath)
370
385
  }
371
386
  } else {
372
387
  exception = NSException(name: NSExceptionName(rawValue: "unsupported_value"), reason: "Unsupported value type.", userInfo: nil)
373
388
  exception?.raise()
389
+ // Throw instead of raising an NSException (process abort no JS
390
+ // catch survives — e.g. a stored file path invalidated by an iOS
391
+ // container relocation boot-looped an app at startup). The caller
392
+ // rejects the promise with the same name/message.
393
+ throw NSError(domain: "unsupported_value", code: 1,
394
+ userInfo: [NSLocalizedDescriptionKey: "Unsupported value type."])
374
395
  }
375
-
396
+
376
397
  return ""
377
398
  }
378
399
 
@@ -13,22 +13,32 @@ class ImageMain {
13
13
 
14
14
  if options.input != InputType.base64 {
15
15
  ImageCompressor.getAbsoluteImagePath(value, options: options) { absoluteImagePath in
16
+ // The escaping completion runs outside the outer do/catch,
17
+ // so failures here need their own catch to reject.
18
+ do {
19
+ if options.autoCompress {
20
+ let result = try ImageCompressor.autoCompressHandler(imagePath: absoluteImagePath, base64: nil, options: options)
21
+ resolve(result)
22
+ } else {
23
+ let result = try ImageCompressor.manualCompressHandler(imagePath: absoluteImagePath, base64: nil, options: options)
24
+ resolve(result)
25
+ }
26
+ } catch {
27
+ reject((error as NSError).domain, error.localizedDescription, error)
28
+ }
29
+ MediaCache.removeCompletedImagePath(absoluteImagePath)
30
+ }
31
+ } else {
32
+ do {
16
33
  if options.autoCompress {
17
- let result = ImageCompressor.autoCompressHandler(imagePath: absoluteImagePath, base64: nil, options: options)
34
+ let result = try ImageCompressor.autoCompressHandler(imagePath: nil, base64: value, options: options)
18
35
  resolve(result)
19
36
  } else {
20
- let result = ImageCompressor.manualCompressHandler(imagePath: absoluteImagePath, base64: nil, options: options)
37
+ let result = try ImageCompressor.manualCompressHandler(imagePath: nil, base64: value, options: options)
21
38
  resolve(result)
22
39
  }
23
- MediaCache.removeCompletedImagePath(absoluteImagePath)
24
- }
25
- } else {
26
- if options.autoCompress {
27
- let result = ImageCompressor.autoCompressHandler(imagePath: nil, base64: value, options: options)
28
- resolve(result)
29
- } else {
30
- let result = ImageCompressor.manualCompressHandler(imagePath: nil, base64: value, options: options)
31
- resolve(result)
40
+ } catch {
41
+ reject((error as NSError).domain, error.localizedDescription, error)
32
42
  }
33
43
  }
34
44
  } catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-compressor",
3
- "version": "1.19.2",
3
+ "version": "1.19.4",
4
4
  "description": "Compress Image, Video, and Audio same like Whatsapp & Auto/Manual Compression | Background Upload | Download File | Create Video Thumbnail",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -1,112 +0,0 @@
1
- package com.reactnativecompressor.Audio
2
-
3
- import android.annotation.SuppressLint
4
- import android.media.MediaCodec
5
- import android.media.MediaExtractor
6
- import android.media.MediaFormat
7
- import android.media.MediaMetadataRetriever
8
- import android.media.MediaMuxer
9
- import android.util.Log
10
- import java.io.IOException
11
- import java.nio.ByteBuffer
12
-
13
-
14
- class AudioExtractor {
15
- /**
16
- * @param srcPath the path of source video file.
17
- * @param dstPath the path of destination video file.
18
- * @param startMs starting time in milliseconds for trimming. Set to
19
- * negative if starting from beginning.
20
- * @param endMs end time for trimming in milliseconds. Set to negative if
21
- * no trimming at the end.
22
- * @param useAudio true if keep the audio track from the source.
23
- * @param useVideo true if keep the video track from the source.
24
- * @throws IOException
25
- */
26
- @SuppressLint("NewApi", "WrongConstant")
27
- @Throws(IOException::class)
28
- fun genVideoUsingMuxer(srcPath: String?, dstPath: String?, startMs: Int, endMs: Int, useAudio: Boolean, useVideo: Boolean) {
29
- // Set up MediaExtractor to read from the source.
30
- val extractor = MediaExtractor()
31
- extractor.setDataSource(srcPath!!)
32
- val trackCount = extractor.trackCount
33
- // Set up MediaMuxer for the destination.
34
- val muxer: MediaMuxer
35
- muxer = MediaMuxer(dstPath!!, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
36
- // Set up the tracks and retrieve the max buffer size for selected
37
- // tracks.
38
- val indexMap = HashMap<Int, Int>(trackCount)
39
- var bufferSize = -1
40
- for (i in 0 until trackCount) {
41
- val format = extractor.getTrackFormat(i)
42
- val mime = format.getString(MediaFormat.KEY_MIME)
43
- var selectCurrentTrack = false
44
- if (mime!!.startsWith("audio/") && useAudio) {
45
- selectCurrentTrack = true
46
- } else if (mime.startsWith("video/") && useVideo) {
47
- selectCurrentTrack = true
48
- }
49
- if (selectCurrentTrack) {
50
- extractor.selectTrack(i)
51
- val dstIndex = muxer.addTrack(format)
52
- indexMap[i] = dstIndex
53
- if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
54
- val newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE)
55
- bufferSize = if (newSize > bufferSize) newSize else bufferSize
56
- }
57
- }
58
- }
59
- if (bufferSize < 0) {
60
- bufferSize = DEFAULT_BUFFER_SIZE
61
- }
62
- // Set up the orientation and starting time for extractor.
63
- val retrieverSrc = MediaMetadataRetriever()
64
- retrieverSrc.setDataSource(srcPath)
65
- val degreesString = retrieverSrc.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)
66
- if (degreesString != null) {
67
- val degrees = degreesString.toInt()
68
- if (degrees >= 0) {
69
- muxer.setOrientationHint(degrees)
70
- }
71
- }
72
- if (startMs > 0) {
73
- extractor.seekTo((startMs * 1000).toLong(), MediaExtractor.SEEK_TO_CLOSEST_SYNC)
74
- }
75
- // Copy the samples from MediaExtractor to MediaMuxer. We will loop
76
- // for copying each sample and stop when we get to the end of the source
77
- // file or exceed the end time of the trimming.
78
- val offset = 0
79
- var trackIndex = -1
80
- val dstBuf = ByteBuffer.allocate(bufferSize)
81
- val bufferInfo = MediaCodec.BufferInfo()
82
- muxer.start()
83
- while (true) {
84
- bufferInfo.offset = offset
85
- bufferInfo.size = extractor.readSampleData(dstBuf, offset)
86
- if (bufferInfo.size < 0) {
87
- Log.d(TAG, "Saw input EOS.")
88
- bufferInfo.size = 0
89
- break
90
- } else {
91
- bufferInfo.presentationTimeUs = extractor.sampleTime
92
- if (endMs > 0 && bufferInfo.presentationTimeUs > endMs * 1000) {
93
- Log.d(TAG, "The current sample is over the trim end time.")
94
- break
95
- } else {
96
- bufferInfo.flags = extractor.sampleFlags
97
- trackIndex = extractor.sampleTrackIndex
98
- muxer.writeSampleData(indexMap[trackIndex]!!, dstBuf, bufferInfo)
99
- extractor.advance()
100
- }
101
- }
102
- }
103
- muxer.stop()
104
- muxer.release()
105
- return
106
- }
107
-
108
- companion object {
109
- private const val DEFAULT_BUFFER_SIZE = 1 * 1024 * 1024
110
- private const val TAG = "AudioExtractorDecoder"
111
- }
112
- }