react-native-ensys-camera-x 1.0.7
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/CustomCamera.podspec +20 -0
- package/LICENSE +20 -0
- package/README.md +833 -0
- package/android/build.gradle +135 -0
- package/android/consumer-rules.pro +47 -0
- package/android/src/main/AndroidManifest.xml +72 -0
- package/android/src/main/java/android/print/PdfPrint.java +51 -0
- package/android/src/main/java/com/customcamera/AnimatedImageViewManager.kt +199 -0
- package/android/src/main/java/com/customcamera/AudioPlayerView.kt +322 -0
- package/android/src/main/java/com/customcamera/AudioRecorder.kt +506 -0
- package/android/src/main/java/com/customcamera/BarcodeScannerActivity.kt +361 -0
- package/android/src/main/java/com/customcamera/BlurBackgroundView.kt +199 -0
- package/android/src/main/java/com/customcamera/CacheCleanupManager.kt +386 -0
- package/android/src/main/java/com/customcamera/CameraAspectRatioMode.kt +77 -0
- package/android/src/main/java/com/customcamera/CameraAsset.kt +211 -0
- package/android/src/main/java/com/customcamera/CameraTheme.kt +479 -0
- package/android/src/main/java/com/customcamera/CompressionCacheStore.kt +504 -0
- package/android/src/main/java/com/customcamera/CompressionFileNameUtils.kt +7 -0
- package/android/src/main/java/com/customcamera/CompressionProfile.kt +195 -0
- package/android/src/main/java/com/customcamera/CustomCameraActivity.kt +7291 -0
- package/android/src/main/java/com/customcamera/CustomCameraFileProvider.kt +9 -0
- package/android/src/main/java/com/customcamera/CustomCameraModule.kt +2479 -0
- package/android/src/main/java/com/customcamera/CustomCameraPackage.kt +53 -0
- package/android/src/main/java/com/customcamera/DisplayUtils.kt +9 -0
- package/android/src/main/java/com/customcamera/DocumentPreviewView.kt +846 -0
- package/android/src/main/java/com/customcamera/DrawingView.kt +214 -0
- package/android/src/main/java/com/customcamera/EmojiPickerData.kt +228 -0
- package/android/src/main/java/com/customcamera/FilterStripAdapter.kt +158 -0
- package/android/src/main/java/com/customcamera/GifSupport.kt +215 -0
- package/android/src/main/java/com/customcamera/GlobalAudioPlayer.kt +320 -0
- package/android/src/main/java/com/customcamera/ImageExporter.kt +1394 -0
- package/android/src/main/java/com/customcamera/ImageFormatSupport.kt +163 -0
- package/android/src/main/java/com/customcamera/Localization.kt +206 -0
- package/android/src/main/java/com/customcamera/MediaAdapters.kt +758 -0
- package/android/src/main/java/com/customcamera/MediaCacheManager.kt +782 -0
- package/android/src/main/java/com/customcamera/MediaExportFormats.kt +201 -0
- package/android/src/main/java/com/customcamera/MediaFileIo.kt +310 -0
- package/android/src/main/java/com/customcamera/MediaMetadataStore.kt +494 -0
- package/android/src/main/java/com/customcamera/MediaPreviewEditor.kt +14865 -0
- package/android/src/main/java/com/customcamera/MediaPublisher.kt +423 -0
- package/android/src/main/java/com/customcamera/MediaStorageWorkflow.kt +722 -0
- package/android/src/main/java/com/customcamera/MediaStoreRepository.kt +378 -0
- package/android/src/main/java/com/customcamera/MediaThumbnailView.kt +286 -0
- package/android/src/main/java/com/customcamera/MediaUtils.kt +37 -0
- package/android/src/main/java/com/customcamera/NativeVideoViewManager.kt +845 -0
- package/android/src/main/java/com/customcamera/OfficeDocumentConverter.kt +2791 -0
- package/android/src/main/java/com/customcamera/PendingCaptureCrops.kt +88 -0
- package/android/src/main/java/com/customcamera/PowerPointPreview.kt +4077 -0
- package/android/src/main/java/com/customcamera/RecentPickerStore.kt +74 -0
- package/android/src/main/java/com/customcamera/SecureFileEraser.kt +411 -0
- package/android/src/main/java/com/customcamera/SecureKeyModule.kt +88 -0
- package/android/src/main/java/com/customcamera/SecureMediaDeleter.kt +493 -0
- package/android/src/main/java/com/customcamera/StickerPickerData.kt +107 -0
- package/android/src/main/java/com/customcamera/SvgDrawable.kt +175 -0
- package/android/src/main/java/com/customcamera/SvgIconViewManager.kt +77 -0
- package/android/src/main/java/com/customcamera/TextEntryController.kt +553 -0
- package/android/src/main/java/com/customcamera/ThumbnailLoader.kt +455 -0
- package/android/src/main/java/com/customcamera/UploadService.kt +909 -0
- package/android/src/main/java/com/customcamera/VideoEditUtils.kt +210 -0
- package/android/src/main/java/com/customcamera/VideoRotationTranscoder.kt +1992 -0
- package/android/src/main/java/com/customcamera/gif/AnimatedGifEncoder.kt +473 -0
- package/android/src/main/java/com/customcamera/gif/GifDecoder.kt +690 -0
- package/android/src/main/java/com/customcamera/gif/GifFramesDrawable.kt +160 -0
- package/android/src/main/java/com/customcamera/gif/GifHttp.kt +112 -0
- package/android/src/main/java/com/customcamera/gif/GifImageLoader.kt +186 -0
- package/android/src/main/java/com/customcamera/gif/GifModels.kt +74 -0
- package/android/src/main/java/com/customcamera/gif/GifProvider.kt +49 -0
- package/android/src/main/java/com/customcamera/gif/GifProviders.kt +27 -0
- package/android/src/main/java/com/customcamera/gif/GifRepository.kt +124 -0
- package/android/src/main/java/com/customcamera/gif/GifSafety.kt +33 -0
- package/android/src/main/java/com/customcamera/gif/GiphyGifProvider.kt +146 -0
- package/android/src/main/java/com/customcamera/gif/LZWEncoder.kt +258 -0
- package/android/src/main/java/com/customcamera/gif/NeuQuant.kt +435 -0
- package/android/src/main/java/com/customcamera/gif/TenorGifProvider.kt +147 -0
- package/android/src/main/res/drawable/bg_brush_selected.xml +5 -0
- package/android/src/main/res/drawable/bg_color_swatch.xml +5 -0
- package/android/src/main/res/drawable/bg_editor_toolbar.xml +6 -0
- package/android/src/main/res/drawable/bg_icon_circle.xml +5 -0
- package/android/src/main/res/drawable/bg_icon_circle_light.xml +5 -0
- package/android/src/main/res/drawable/bg_mode_tab_active.xml +6 -0
- package/android/src/main/res/drawable/bg_pill.xml +6 -0
- package/android/src/main/res/drawable/bg_recording_dot.xml +6 -0
- package/android/src/main/res/drawable/bg_selection_badge.xml +8 -0
- package/android/src/main/res/drawable/bg_send_button.xml +5 -0
- package/android/src/main/res/drawable/bg_shutter_inner.xml +5 -0
- package/android/src/main/res/drawable/bg_shutter_recording.xml +6 -0
- package/android/src/main/res/drawable/bg_shutter_ring.xml +8 -0
- package/android/src/main/res/drawable/bg_shutter_video_idle.xml +5 -0
- package/android/src/main/res/drawable/bg_thumbnail.xml +9 -0
- package/android/src/main/res/drawable/ic_aspect_ratio.xml +17 -0
- package/android/src/main/res/drawable/ic_audio.xml +10 -0
- package/android/src/main/res/drawable/ic_back.xml +10 -0
- package/android/src/main/res/drawable/ic_brush_medium.xml +12 -0
- package/android/src/main/res/drawable/ic_brush_thick.xml +12 -0
- package/android/src/main/res/drawable/ic_brush_thin.xml +12 -0
- package/android/src/main/res/drawable/ic_check.xml +17 -0
- package/android/src/main/res/drawable/ic_chevron_down.xml +10 -0
- package/android/src/main/res/drawable/ic_chevron_up.xml +13 -0
- package/android/src/main/res/drawable/ic_clear_drawing.xml +10 -0
- package/android/src/main/res/drawable/ic_close.xml +10 -0
- package/android/src/main/res/drawable/ic_cover.xml +9 -0
- package/android/src/main/res/drawable/ic_crop.xml +10 -0
- package/android/src/main/res/drawable/ic_delete.xml +9 -0
- package/android/src/main/res/drawable/ic_document.xml +10 -0
- package/android/src/main/res/drawable/ic_done.xml +10 -0
- package/android/src/main/res/drawable/ic_download.xml +10 -0
- package/android/src/main/res/drawable/ic_emoji.xml +10 -0
- package/android/src/main/res/drawable/ic_filter.xml +10 -0
- package/android/src/main/res/drawable/ic_flash_auto.xml +7 -0
- package/android/src/main/res/drawable/ic_flash_off.xml +23 -0
- package/android/src/main/res/drawable/ic_flash_on.xml +16 -0
- package/android/src/main/res/drawable/ic_flip.xml +15 -0
- package/android/src/main/res/drawable/ic_gallery.xml +10 -0
- package/android/src/main/res/drawable/ic_gif.xml +24 -0
- package/android/src/main/res/drawable/ic_lock.xml +19 -0
- package/android/src/main/res/drawable/ic_lock_open.xml +22 -0
- package/android/src/main/res/drawable/ic_marker.xml +10 -0
- package/android/src/main/res/drawable/ic_more_vert.xml +18 -0
- package/android/src/main/res/drawable/ic_overlay_close.xml +19 -0
- package/android/src/main/res/drawable/ic_overlay_resize.xml +18 -0
- package/android/src/main/res/drawable/ic_pause.xml +10 -0
- package/android/src/main/res/drawable/ic_photo_mode.xml +10 -0
- package/android/src/main/res/drawable/ic_play.xml +10 -0
- package/android/src/main/res/drawable/ic_redo.xml +10 -0
- package/android/src/main/res/drawable/ic_rotate.xml +9 -0
- package/android/src/main/res/drawable/ic_send.xml +10 -0
- package/android/src/main/res/drawable/ic_share.xml +10 -0
- package/android/src/main/res/drawable/ic_stat_upload.xml +10 -0
- package/android/src/main/res/drawable/ic_sticker.xml +24 -0
- package/android/src/main/res/drawable/ic_text.xml +10 -0
- package/android/src/main/res/drawable/ic_text_align_center.xml +11 -0
- package/android/src/main/res/drawable/ic_text_align_left.xml +11 -0
- package/android/src/main/res/drawable/ic_text_align_right.xml +11 -0
- package/android/src/main/res/drawable/ic_text_bg.xml +11 -0
- package/android/src/main/res/drawable/ic_trim.xml +23 -0
- package/android/src/main/res/drawable/ic_undo.xml +10 -0
- package/android/src/main/res/drawable/ic_video_mode.xml +10 -0
- package/android/src/main/res/drawable/ic_video_note.xml +13 -0
- package/android/src/main/res/drawable/ic_volume_off.xml +9 -0
- package/android/src/main/res/drawable/ic_volume_on.xml +9 -0
- package/android/src/main/res/drawable/sticker_heart.xml +9 -0
- package/android/src/main/res/drawable/sticker_smile.xml +9 -0
- package/android/src/main/res/drawable/sticker_star.xml +9 -0
- package/android/src/main/res/drawable/sticker_thumbsup.xml +9 -0
- package/android/src/main/res/values/colors.xml +34 -0
- package/android/src/main/res/values/ids.xml +15 -0
- package/android/src/main/res/values/strings.xml +15 -0
- package/android/src/main/res/values/styles.xml +20 -0
- package/android/src/main/res/xml/file_paths.xml +34 -0
- package/ios/CustomCamera.h +5 -0
- package/ios/CustomCamera.mm +214 -0
- package/lib/module/AudioPlayerContext.js +233 -0
- package/lib/module/AudioPlayerContext.js.map +1 -0
- package/lib/module/CameraPreview.js +304 -0
- package/lib/module/CameraPreview.js.map +1 -0
- package/lib/module/NativeAnimatedImageView.js +41 -0
- package/lib/module/NativeAnimatedImageView.js.map +1 -0
- package/lib/module/NativeAudioPlayerView.js +33 -0
- package/lib/module/NativeAudioPlayerView.js.map +1 -0
- package/lib/module/NativeBlurView.js +35 -0
- package/lib/module/NativeBlurView.js.map +1 -0
- package/lib/module/NativeCustomCamera.js +128 -0
- package/lib/module/NativeCustomCamera.js.map +1 -0
- package/lib/module/NativeCustomCamera.web.js +143 -0
- package/lib/module/NativeCustomCamera.web.js.map +1 -0
- package/lib/module/NativeCustomVideoView.js +5 -0
- package/lib/module/NativeCustomVideoView.js.map +1 -0
- package/lib/module/NativeDocumentPreviewView.js +156 -0
- package/lib/module/NativeDocumentPreviewView.js.map +1 -0
- package/lib/module/NativeMediaThumbnailView.js +110 -0
- package/lib/module/NativeMediaThumbnailView.js.map +1 -0
- package/lib/module/NativeSvgIcon.js +32 -0
- package/lib/module/NativeSvgIcon.js.map +1 -0
- package/lib/module/ResponsivePreviewContainer.js +171 -0
- package/lib/module/ResponsivePreviewContainer.js.map +1 -0
- package/lib/module/accessibility.js +61 -0
- package/lib/module/accessibility.js.map +1 -0
- package/lib/module/config.js +352 -0
- package/lib/module/config.js.map +1 -0
- package/lib/module/cpuOptimization.js +296 -0
- package/lib/module/cpuOptimization.js.map +1 -0
- package/lib/module/db/DatabaseManager.js +191 -0
- package/lib/module/db/DatabaseManager.js.map +1 -0
- package/lib/module/db/MediaMapper.js +284 -0
- package/lib/module/db/MediaMapper.js.map +1 -0
- package/lib/module/db/MediaRepository.js +242 -0
- package/lib/module/db/MediaRepository.js.map +1 -0
- package/lib/module/db/index.js +41 -0
- package/lib/module/db/index.js.map +1 -0
- package/lib/module/db/migrations.js +180 -0
- package/lib/module/db/migrations.js.map +1 -0
- package/lib/module/db/react-native-sqlcipher.d.js +2 -0
- package/lib/module/db/react-native-sqlcipher.d.js.map +1 -0
- package/lib/module/db/secureKey.js +87 -0
- package/lib/module/db/secureKey.js.map +1 -0
- package/lib/module/db/types.js +57 -0
- package/lib/module/db/types.js.map +1 -0
- package/lib/module/db/useMediaDatabase.js +123 -0
- package/lib/module/db/useMediaDatabase.js.map +1 -0
- package/lib/module/defaultIcons.js +2259 -0
- package/lib/module/defaultIcons.js.map +1 -0
- package/lib/module/deviceCapabilities.js +408 -0
- package/lib/module/deviceCapabilities.js.map +1 -0
- package/lib/module/errors.js +267 -0
- package/lib/module/errors.js.map +1 -0
- package/lib/module/iconConfig.js +796 -0
- package/lib/module/iconConfig.js.map +1 -0
- package/lib/module/icons.js +514 -0
- package/lib/module/icons.js.map +1 -0
- package/lib/module/index.js +251 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/jest-globals.d.js +2 -0
- package/lib/module/jest-globals.d.js.map +1 -0
- package/lib/module/library/MediaLibrary.js +107 -0
- package/lib/module/library/MediaLibrary.js.map +1 -0
- package/lib/module/library/MediaLibraryScreen.js +2597 -0
- package/lib/module/library/MediaLibraryScreen.js.map +1 -0
- package/lib/module/library/components/AudioPreview.js +74 -0
- package/lib/module/library/components/AudioPreview.js.map +1 -0
- package/lib/module/library/components/DocumentPreview.js +331 -0
- package/lib/module/library/components/DocumentPreview.js.map +1 -0
- package/lib/module/library/components/ExpandableFab.js +343 -0
- package/lib/module/library/components/ExpandableFab.js.map +1 -0
- package/lib/module/library/components/FileTiles.js +251 -0
- package/lib/module/library/components/FileTiles.js.map +1 -0
- package/lib/module/library/components/ImagePreview.js +70 -0
- package/lib/module/library/components/ImagePreview.js.map +1 -0
- package/lib/module/library/components/MediaMetadataHeader.js +175 -0
- package/lib/module/library/components/MediaMetadataHeader.js.map +1 -0
- package/lib/module/library/components/RecordAudioScreen.js +816 -0
- package/lib/module/library/components/RecordAudioScreen.js.map +1 -0
- package/lib/module/library/components/VideoPreview.js +453 -0
- package/lib/module/library/components/VideoPreview.js.map +1 -0
- package/lib/module/library/components/ViewerCounter.js +55 -0
- package/lib/module/library/components/ViewerCounter.js.map +1 -0
- package/lib/module/library/compressionEstimate.js +507 -0
- package/lib/module/library/compressionEstimate.js.map +1 -0
- package/lib/module/library/fileMetadata.js +196 -0
- package/lib/module/library/fileMetadata.js.map +1 -0
- package/lib/module/library/index.js +42 -0
- package/lib/module/library/index.js.map +1 -0
- package/lib/module/library/libraryIconRegistry.js +69 -0
- package/lib/module/library/libraryIconRegistry.js.map +1 -0
- package/lib/module/library/libraryIcons.js +858 -0
- package/lib/module/library/libraryIcons.js.map +1 -0
- package/lib/module/library/localizedFormat.js +181 -0
- package/lib/module/library/localizedFormat.js.map +1 -0
- package/lib/module/library/palette.js +225 -0
- package/lib/module/library/palette.js.map +1 -0
- package/lib/module/library/responsive.js +53 -0
- package/lib/module/library/responsive.js.map +1 -0
- package/lib/module/locales.js +416 -0
- package/lib/module/locales.js.map +1 -0
- package/lib/module/localization.js +1064 -0
- package/lib/module/localization.js.map +1 -0
- package/lib/module/logger.js +20 -0
- package/lib/module/logger.js.map +1 -0
- package/lib/module/lowMemoryCache.js +206 -0
- package/lib/module/lowMemoryCache.js.map +1 -0
- package/lib/module/mediaHistory.js +33 -0
- package/lib/module/mediaHistory.js.map +1 -0
- package/lib/module/mediaStorageService.js +402 -0
- package/lib/module/mediaStorageService.js.map +1 -0
- package/lib/module/memory.js +79 -0
- package/lib/module/memory.js.map +1 -0
- package/lib/module/nativeActions.js +307 -0
- package/lib/module/nativeActions.js.map +1 -0
- package/lib/module/nativeComponentSupport.js +61 -0
- package/lib/module/nativeComponentSupport.js.map +1 -0
- package/lib/module/networkPerformance.js +24 -0
- package/lib/module/networkPerformance.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/performance.js +104 -0
- package/lib/module/performance.js.map +1 -0
- package/lib/module/performanceMonitor.js +155 -0
- package/lib/module/performanceMonitor.js.map +1 -0
- package/lib/module/permissions.js +370 -0
- package/lib/module/permissions.js.map +1 -0
- package/lib/module/rendering.js +40 -0
- package/lib/module/rendering.js.map +1 -0
- package/lib/module/security.js +18 -0
- package/lib/module/security.js.map +1 -0
- package/lib/module/state.js +266 -0
- package/lib/module/state.js.map +1 -0
- package/lib/module/storage.js +400 -0
- package/lib/module/storage.js.map +1 -0
- package/lib/module/theme.js +390 -0
- package/lib/module/theme.js.map +1 -0
- package/lib/module/types.js +4 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils.js +115 -0
- package/lib/module/utils.js.map +1 -0
- package/lib/module/validation.js +288 -0
- package/lib/module/validation.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/AudioPlayerContext.d.ts +27 -0
- package/lib/typescript/src/AudioPlayerContext.d.ts.map +1 -0
- package/lib/typescript/src/CameraPreview.d.ts +13 -0
- package/lib/typescript/src/CameraPreview.d.ts.map +1 -0
- package/lib/typescript/src/NativeAnimatedImageView.d.ts +33 -0
- package/lib/typescript/src/NativeAnimatedImageView.d.ts.map +1 -0
- package/lib/typescript/src/NativeAudioPlayerView.d.ts +12 -0
- package/lib/typescript/src/NativeAudioPlayerView.d.ts.map +1 -0
- package/lib/typescript/src/NativeBlurView.d.ts +12 -0
- package/lib/typescript/src/NativeBlurView.d.ts.map +1 -0
- package/lib/typescript/src/NativeCustomCamera.d.ts +167 -0
- package/lib/typescript/src/NativeCustomCamera.d.ts.map +1 -0
- package/lib/typescript/src/NativeCustomCamera.web.d.ts +47 -0
- package/lib/typescript/src/NativeCustomCamera.web.d.ts.map +1 -0
- package/lib/typescript/src/NativeCustomVideoView.d.ts +30 -0
- package/lib/typescript/src/NativeCustomVideoView.d.ts.map +1 -0
- package/lib/typescript/src/NativeDocumentPreviewView.d.ts +48 -0
- package/lib/typescript/src/NativeDocumentPreviewView.d.ts.map +1 -0
- package/lib/typescript/src/NativeMediaThumbnailView.d.ts +54 -0
- package/lib/typescript/src/NativeMediaThumbnailView.d.ts.map +1 -0
- package/lib/typescript/src/NativeSvgIcon.d.ts +25 -0
- package/lib/typescript/src/NativeSvgIcon.d.ts.map +1 -0
- package/lib/typescript/src/ResponsivePreviewContainer.d.ts +92 -0
- package/lib/typescript/src/ResponsivePreviewContainer.d.ts.map +1 -0
- package/lib/typescript/src/accessibility.d.ts +20 -0
- package/lib/typescript/src/accessibility.d.ts.map +1 -0
- package/lib/typescript/src/config.d.ts +145 -0
- package/lib/typescript/src/config.d.ts.map +1 -0
- package/lib/typescript/src/cpuOptimization.d.ts +63 -0
- package/lib/typescript/src/cpuOptimization.d.ts.map +1 -0
- package/lib/typescript/src/db/DatabaseManager.d.ts +48 -0
- package/lib/typescript/src/db/DatabaseManager.d.ts.map +1 -0
- package/lib/typescript/src/db/MediaMapper.d.ts +77 -0
- package/lib/typescript/src/db/MediaMapper.d.ts.map +1 -0
- package/lib/typescript/src/db/MediaRepository.d.ts +66 -0
- package/lib/typescript/src/db/MediaRepository.d.ts.map +1 -0
- package/lib/typescript/src/db/index.d.ts +23 -0
- package/lib/typescript/src/db/index.d.ts.map +1 -0
- package/lib/typescript/src/db/migrations.d.ts +31 -0
- package/lib/typescript/src/db/migrations.d.ts.map +1 -0
- package/lib/typescript/src/db/secureKey.d.ts +10 -0
- package/lib/typescript/src/db/secureKey.d.ts.map +1 -0
- package/lib/typescript/src/db/types.d.ts +115 -0
- package/lib/typescript/src/db/types.d.ts.map +1 -0
- package/lib/typescript/src/db/useMediaDatabase.d.ts +41 -0
- package/lib/typescript/src/db/useMediaDatabase.d.ts.map +1 -0
- package/lib/typescript/src/defaultIcons.d.ts +139 -0
- package/lib/typescript/src/defaultIcons.d.ts.map +1 -0
- package/lib/typescript/src/deviceCapabilities.d.ts +92 -0
- package/lib/typescript/src/deviceCapabilities.d.ts.map +1 -0
- package/lib/typescript/src/errors.d.ts +95 -0
- package/lib/typescript/src/errors.d.ts.map +1 -0
- package/lib/typescript/src/iconConfig.d.ts +176 -0
- package/lib/typescript/src/iconConfig.d.ts.map +1 -0
- package/lib/typescript/src/icons.d.ts +217 -0
- package/lib/typescript/src/icons.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +104 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/library/MediaLibrary.d.ts +57 -0
- package/lib/typescript/src/library/MediaLibrary.d.ts.map +1 -0
- package/lib/typescript/src/library/MediaLibraryScreen.d.ts +51 -0
- package/lib/typescript/src/library/MediaLibraryScreen.d.ts.map +1 -0
- package/lib/typescript/src/library/components/AudioPreview.d.ts +6 -0
- package/lib/typescript/src/library/components/AudioPreview.d.ts.map +1 -0
- package/lib/typescript/src/library/components/DocumentPreview.d.ts +10 -0
- package/lib/typescript/src/library/components/DocumentPreview.d.ts.map +1 -0
- package/lib/typescript/src/library/components/ExpandableFab.d.ts +39 -0
- package/lib/typescript/src/library/components/ExpandableFab.d.ts.map +1 -0
- package/lib/typescript/src/library/components/FileTiles.d.ts +8 -0
- package/lib/typescript/src/library/components/FileTiles.d.ts.map +1 -0
- package/lib/typescript/src/library/components/ImagePreview.d.ts +5 -0
- package/lib/typescript/src/library/components/ImagePreview.d.ts.map +1 -0
- package/lib/typescript/src/library/components/MediaMetadataHeader.d.ts +16 -0
- package/lib/typescript/src/library/components/MediaMetadataHeader.d.ts.map +1 -0
- package/lib/typescript/src/library/components/RecordAudioScreen.d.ts +8 -0
- package/lib/typescript/src/library/components/RecordAudioScreen.d.ts.map +1 -0
- package/lib/typescript/src/library/components/VideoPreview.d.ts +20 -0
- package/lib/typescript/src/library/components/VideoPreview.d.ts.map +1 -0
- package/lib/typescript/src/library/components/ViewerCounter.d.ts +13 -0
- package/lib/typescript/src/library/components/ViewerCounter.d.ts.map +1 -0
- package/lib/typescript/src/library/compressionEstimate.d.ts +313 -0
- package/lib/typescript/src/library/compressionEstimate.d.ts.map +1 -0
- package/lib/typescript/src/library/fileMetadata.d.ts +33 -0
- package/lib/typescript/src/library/fileMetadata.d.ts.map +1 -0
- package/lib/typescript/src/library/index.d.ts +40 -0
- package/lib/typescript/src/library/index.d.ts.map +1 -0
- package/lib/typescript/src/library/libraryIconRegistry.d.ts +35 -0
- package/lib/typescript/src/library/libraryIconRegistry.d.ts.map +1 -0
- package/lib/typescript/src/library/libraryIcons.d.ts +85 -0
- package/lib/typescript/src/library/libraryIcons.d.ts.map +1 -0
- package/lib/typescript/src/library/localizedFormat.d.ts +49 -0
- package/lib/typescript/src/library/localizedFormat.d.ts.map +1 -0
- package/lib/typescript/src/library/palette.d.ts +104 -0
- package/lib/typescript/src/library/palette.d.ts.map +1 -0
- package/lib/typescript/src/library/responsive.d.ts +15 -0
- package/lib/typescript/src/library/responsive.d.ts.map +1 -0
- package/lib/typescript/src/locales.d.ts +103 -0
- package/lib/typescript/src/locales.d.ts.map +1 -0
- package/lib/typescript/src/localization.d.ts +1051 -0
- package/lib/typescript/src/localization.d.ts.map +1 -0
- package/lib/typescript/src/logger.d.ts +4 -0
- package/lib/typescript/src/logger.d.ts.map +1 -0
- package/lib/typescript/src/lowMemoryCache.d.ts +64 -0
- package/lib/typescript/src/lowMemoryCache.d.ts.map +1 -0
- package/lib/typescript/src/mediaHistory.d.ts +3 -0
- package/lib/typescript/src/mediaHistory.d.ts.map +1 -0
- package/lib/typescript/src/mediaStorageService.d.ts +155 -0
- package/lib/typescript/src/mediaStorageService.d.ts.map +1 -0
- package/lib/typescript/src/memory.d.ts +21 -0
- package/lib/typescript/src/memory.d.ts.map +1 -0
- package/lib/typescript/src/nativeActions.d.ts +174 -0
- package/lib/typescript/src/nativeActions.d.ts.map +1 -0
- package/lib/typescript/src/nativeComponentSupport.d.ts +30 -0
- package/lib/typescript/src/nativeComponentSupport.d.ts.map +1 -0
- package/lib/typescript/src/networkPerformance.d.ts +12 -0
- package/lib/typescript/src/networkPerformance.d.ts.map +1 -0
- package/lib/typescript/src/performance.d.ts +32 -0
- package/lib/typescript/src/performance.d.ts.map +1 -0
- package/lib/typescript/src/performanceMonitor.d.ts +45 -0
- package/lib/typescript/src/performanceMonitor.d.ts.map +1 -0
- package/lib/typescript/src/permissions.d.ts +132 -0
- package/lib/typescript/src/permissions.d.ts.map +1 -0
- package/lib/typescript/src/rendering.d.ts +9 -0
- package/lib/typescript/src/rendering.d.ts.map +1 -0
- package/lib/typescript/src/security.d.ts +6 -0
- package/lib/typescript/src/security.d.ts.map +1 -0
- package/lib/typescript/src/state.d.ts +102 -0
- package/lib/typescript/src/state.d.ts.map +1 -0
- package/lib/typescript/src/storage.d.ts +117 -0
- package/lib/typescript/src/storage.d.ts.map +1 -0
- package/lib/typescript/src/theme.d.ts +15 -0
- package/lib/typescript/src/theme.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +802 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/utils.d.ts +50 -0
- package/lib/typescript/src/utils.d.ts.map +1 -0
- package/lib/typescript/src/validation.d.ts +52 -0
- package/lib/typescript/src/validation.d.ts.map +1 -0
- package/package.json +204 -0
- package/react-native.config.js +17 -0
- package/src/AudioPlayerContext.tsx +220 -0
- package/src/CameraPreview.tsx +352 -0
- package/src/NativeAnimatedImageView.tsx +71 -0
- package/src/NativeAudioPlayerView.tsx +39 -0
- package/src/NativeBlurView.tsx +40 -0
- package/src/NativeCustomCamera.ts +305 -0
- package/src/NativeCustomCamera.web.ts +192 -0
- package/src/NativeCustomVideoView.ts +30 -0
- package/src/NativeDocumentPreviewView.tsx +196 -0
- package/src/NativeMediaThumbnailView.tsx +167 -0
- package/src/NativeSvgIcon.tsx +46 -0
- package/src/ResponsivePreviewContainer.tsx +227 -0
- package/src/accessibility.ts +80 -0
- package/src/config.ts +406 -0
- package/src/cpuOptimization.ts +365 -0
- package/src/db/DatabaseManager.ts +212 -0
- package/src/db/MediaMapper.ts +377 -0
- package/src/db/MediaRepository.ts +313 -0
- package/src/db/index.ts +73 -0
- package/src/db/migrations.ts +222 -0
- package/src/db/react-native-sqlcipher.d.ts +76 -0
- package/src/db/secureKey.ts +100 -0
- package/src/db/types.ts +123 -0
- package/src/db/useMediaDatabase.ts +191 -0
- package/src/defaultIcons.tsx +2390 -0
- package/src/deviceCapabilities.ts +438 -0
- package/src/errors.ts +350 -0
- package/src/iconConfig.tsx +962 -0
- package/src/icons.tsx +788 -0
- package/src/index.tsx +763 -0
- package/src/jest-globals.d.ts +9 -0
- package/src/library/MediaLibrary.tsx +141 -0
- package/src/library/MediaLibraryScreen.tsx +3003 -0
- package/src/library/components/AudioPreview.tsx +73 -0
- package/src/library/components/DocumentPreview.tsx +361 -0
- package/src/library/components/ExpandableFab.tsx +342 -0
- package/src/library/components/FileTiles.tsx +252 -0
- package/src/library/components/ImagePreview.tsx +72 -0
- package/src/library/components/MediaMetadataHeader.tsx +208 -0
- package/src/library/components/RecordAudioScreen.tsx +845 -0
- package/src/library/components/VideoPreview.tsx +478 -0
- package/src/library/components/ViewerCounter.tsx +71 -0
- package/src/library/compressionEstimate.ts +662 -0
- package/src/library/fileMetadata.ts +212 -0
- package/src/library/index.ts +66 -0
- package/src/library/libraryIconRegistry.tsx +86 -0
- package/src/library/libraryIcons.tsx +928 -0
- package/src/library/localizedFormat.ts +207 -0
- package/src/library/palette.ts +281 -0
- package/src/library/responsive.ts +49 -0
- package/src/locales.ts +381 -0
- package/src/localization.ts +1947 -0
- package/src/logger.ts +20 -0
- package/src/lowMemoryCache.ts +218 -0
- package/src/mediaHistory.ts +42 -0
- package/src/mediaStorageService.ts +546 -0
- package/src/memory.ts +102 -0
- package/src/nativeActions.ts +422 -0
- package/src/nativeComponentSupport.ts +60 -0
- package/src/networkPerformance.ts +30 -0
- package/src/performance.ts +137 -0
- package/src/performanceMonitor.ts +219 -0
- package/src/permissions.ts +403 -0
- package/src/rendering.ts +47 -0
- package/src/security.ts +19 -0
- package/src/state.ts +333 -0
- package/src/storage.ts +453 -0
- package/src/theme.tsx +467 -0
- package/src/types.ts +946 -0
- package/src/utils.ts +177 -0
- package/src/validation.ts +372 -0
|
@@ -0,0 +1,690 @@
|
|
|
1
|
+
package com.customcamera.gif
|
|
2
|
+
|
|
3
|
+
import android.graphics.Bitmap
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Dependency-free decoder for animated (and static) GIF87a / GIF89a images.
|
|
7
|
+
*
|
|
8
|
+
* This is a faithful Kotlin port of the canonical public-domain animated-GIF decoder in the
|
|
9
|
+
* Kevin Weiner / `com.bumptech.glide.gifdecoder` lineage, itself derived from the GIF89a
|
|
10
|
+
* specification. It parses an entire GIF held in memory and produces fully-composited
|
|
11
|
+
* ARGB_8888 [Bitmap] frames, honouring per-frame delays, transparency, interlacing and all four
|
|
12
|
+
* GIF disposal methods.
|
|
13
|
+
*
|
|
14
|
+
* Only [android.graphics.Bitmap] and the standard Kotlin/Java runtime are used, so there are no
|
|
15
|
+
* third-party dependencies. Target: minSdk 24. Malformed input yields a non-OK status / `null`
|
|
16
|
+
* rather than throwing.
|
|
17
|
+
*
|
|
18
|
+
* One-shot usage:
|
|
19
|
+
* ```
|
|
20
|
+
* val gif = GifDecoder.decodeAll(bytes, maxDimension = 1024) ?: return
|
|
21
|
+
* // gif.frames, gif.delaysMs, gif.loopCount, gif.width, gif.height
|
|
22
|
+
* ```
|
|
23
|
+
* Manual usage:
|
|
24
|
+
* ```
|
|
25
|
+
* val decoder = GifDecoder()
|
|
26
|
+
* if (decoder.read(bytes) == GifDecoder.STATUS_OK) {
|
|
27
|
+
* val first = decoder.getFrame(0)
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
class GifDecoder {
|
|
32
|
+
|
|
33
|
+
/** Logical screen width in pixels (valid after a successful [read]). */
|
|
34
|
+
var width: Int = 0
|
|
35
|
+
private set
|
|
36
|
+
|
|
37
|
+
/** Logical screen height in pixels (valid after a successful [read]). */
|
|
38
|
+
var height: Int = 0
|
|
39
|
+
private set
|
|
40
|
+
|
|
41
|
+
/** Number of frames successfully decoded from the current stream. */
|
|
42
|
+
var frameCount: Int = 0
|
|
43
|
+
private set
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Netscape/Animexts loop count. `0` means "loop forever" and is also the default when the
|
|
47
|
+
* extension is absent.
|
|
48
|
+
*/
|
|
49
|
+
var loopCount: Int = 0
|
|
50
|
+
private set
|
|
51
|
+
|
|
52
|
+
/** Current read status; one of [STATUS_OK], [STATUS_FORMAT_ERROR], [STATUS_OPEN_ERROR]. */
|
|
53
|
+
private var status: Int = STATUS_OK
|
|
54
|
+
|
|
55
|
+
// --- Raw input ------------------------------------------------------------
|
|
56
|
+
private var rawData: ByteArray = ByteArray(0)
|
|
57
|
+
private var rawPos: Int = 0
|
|
58
|
+
|
|
59
|
+
// --- Global (logical screen) descriptor -----------------------------------
|
|
60
|
+
private var gctFlag: Boolean = false
|
|
61
|
+
private var gctSize: Int = 0
|
|
62
|
+
private var gct: IntArray? = null
|
|
63
|
+
private var bgIndex: Int = 0
|
|
64
|
+
private var bgColor: Int = 0
|
|
65
|
+
|
|
66
|
+
// --- Current frame descriptor ---------------------------------------------
|
|
67
|
+
private var lctFlag: Boolean = false
|
|
68
|
+
private var interlace: Boolean = false
|
|
69
|
+
private var lctSize: Int = 0
|
|
70
|
+
private var lct: IntArray? = null
|
|
71
|
+
private var act: IntArray? = null
|
|
72
|
+
private var ix: Int = 0
|
|
73
|
+
private var iy: Int = 0
|
|
74
|
+
private var iw: Int = 0
|
|
75
|
+
private var ih: Int = 0
|
|
76
|
+
private var dispose: Int = 0
|
|
77
|
+
private var transparency: Boolean = false
|
|
78
|
+
private var transIndex: Int = 0
|
|
79
|
+
private var delay: Int = 0
|
|
80
|
+
|
|
81
|
+
// --- Previous frame tracking (for disposal) -------------------------------
|
|
82
|
+
private var lastDispose: Int = 0
|
|
83
|
+
private var lrx: Int = 0
|
|
84
|
+
private var lry: Int = 0
|
|
85
|
+
private var lrw: Int = 0
|
|
86
|
+
private var lrh: Int = 0
|
|
87
|
+
private var hasPreviousFrame: Boolean = false
|
|
88
|
+
|
|
89
|
+
// --- Composition buffers --------------------------------------------------
|
|
90
|
+
/** Persistent ARGB canvas reused across frames; each frame is composited here. */
|
|
91
|
+
private var mainScratch: IntArray = IntArray(0)
|
|
92
|
+
|
|
93
|
+
/** Snapshot of the last "leave in place" canvas, used to service DISPOSAL_PREVIOUS restores. */
|
|
94
|
+
private var previousImage: IntArray? = null
|
|
95
|
+
|
|
96
|
+
/** Decoded colour-table indices for the current frame. */
|
|
97
|
+
private var pixels: ByteArray? = null
|
|
98
|
+
|
|
99
|
+
// --- LZW working storage --------------------------------------------------
|
|
100
|
+
private var prefix: ShortArray? = null
|
|
101
|
+
private var suffix: ByteArray? = null
|
|
102
|
+
private var pixelStack: ByteArray? = null
|
|
103
|
+
private val block: ByteArray = ByteArray(256)
|
|
104
|
+
private var blockSize: Int = 0
|
|
105
|
+
|
|
106
|
+
// --- Decoded results ------------------------------------------------------
|
|
107
|
+
private val framesList: MutableList<Bitmap> = ArrayList()
|
|
108
|
+
private val delaysList: MutableList<Int> = ArrayList()
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Parses an entire GIF from an in-memory byte array.
|
|
112
|
+
*
|
|
113
|
+
* @param data the complete GIF file bytes, or `null`.
|
|
114
|
+
* @return [STATUS_OK] on success, [STATUS_OPEN_ERROR] if [data] is null, or [STATUS_FORMAT_ERROR]
|
|
115
|
+
* if the bytes are not a decodable GIF.
|
|
116
|
+
*/
|
|
117
|
+
fun read(data: ByteArray?): Int {
|
|
118
|
+
init()
|
|
119
|
+
if (data == null) {
|
|
120
|
+
status = STATUS_OPEN_ERROR
|
|
121
|
+
return status
|
|
122
|
+
}
|
|
123
|
+
rawData = data
|
|
124
|
+
rawPos = 0
|
|
125
|
+
try {
|
|
126
|
+
readHeader()
|
|
127
|
+
if (!err()) {
|
|
128
|
+
if (width <= 0 || height <= 0 ||
|
|
129
|
+
width.toLong() * height.toLong() > Int.MAX_VALUE.toLong()) {
|
|
130
|
+
status = STATUS_FORMAT_ERROR
|
|
131
|
+
} else {
|
|
132
|
+
mainScratch = IntArray(width * height)
|
|
133
|
+
readContents()
|
|
134
|
+
if (frameCount < 0) status = STATUS_FORMAT_ERROR
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
} catch (e: Exception) {
|
|
138
|
+
status = STATUS_FORMAT_ERROR
|
|
139
|
+
}
|
|
140
|
+
return status
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Returns the fully-composited ARGB_8888 bitmap for frame [n] (0-based), with all preceding
|
|
145
|
+
* frames' disposal methods already applied, or `null` if [n] is out of range.
|
|
146
|
+
*/
|
|
147
|
+
fun getFrame(n: Int): Bitmap? {
|
|
148
|
+
return if (n in 0 until frameCount && n < framesList.size) framesList[n] else null
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Returns the display delay for frame [n] in milliseconds. Frames that specify a zero/absent
|
|
153
|
+
* delay report [DEFAULT_FRAME_DELAY_MS] (100 ms).
|
|
154
|
+
*/
|
|
155
|
+
fun getDelay(n: Int): Int {
|
|
156
|
+
return if (n in 0 until frameCount && n < delaysList.size) delaysList[n] else DEFAULT_FRAME_DELAY_MS
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
// Parsing
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
162
|
+
|
|
163
|
+
private fun init() {
|
|
164
|
+
status = STATUS_OK
|
|
165
|
+
frameCount = 0
|
|
166
|
+
loopCount = 0
|
|
167
|
+
framesList.clear()
|
|
168
|
+
delaysList.clear()
|
|
169
|
+
gct = null
|
|
170
|
+
lct = null
|
|
171
|
+
act = null
|
|
172
|
+
previousImage = null
|
|
173
|
+
pixels = null
|
|
174
|
+
hasPreviousFrame = false
|
|
175
|
+
dispose = 0
|
|
176
|
+
lastDispose = 0
|
|
177
|
+
transparency = false
|
|
178
|
+
delay = 0
|
|
179
|
+
bgColor = 0
|
|
180
|
+
bgIndex = 0
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private fun err(): Boolean = status != STATUS_OK
|
|
184
|
+
|
|
185
|
+
/** Reads the 6-byte signature, then the logical screen descriptor + global colour table. */
|
|
186
|
+
private fun readHeader() {
|
|
187
|
+
val id = StringBuilder()
|
|
188
|
+
for (i in 0 until 6) {
|
|
189
|
+
id.append((readByte() and 0xff).toChar())
|
|
190
|
+
}
|
|
191
|
+
if (!id.toString().startsWith("GIF")) {
|
|
192
|
+
status = STATUS_FORMAT_ERROR
|
|
193
|
+
return
|
|
194
|
+
}
|
|
195
|
+
readLSD()
|
|
196
|
+
if (gctFlag && !err()) {
|
|
197
|
+
gct = readColorTable(gctSize)
|
|
198
|
+
val table = gct
|
|
199
|
+
bgColor = if (table != null && bgIndex < table.size) table[bgIndex] else 0
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** Logical Screen Descriptor: screen size, global colour table flags, background index. */
|
|
204
|
+
private fun readLSD() {
|
|
205
|
+
width = readShort()
|
|
206
|
+
height = readShort()
|
|
207
|
+
val packed = readByte()
|
|
208
|
+
gctFlag = (packed and 0x80) != 0
|
|
209
|
+
gctSize = 2 shl (packed and 7) // 2^(N+1)
|
|
210
|
+
bgIndex = readByte()
|
|
211
|
+
readByte() // pixel aspect ratio (unused)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** Reads a colour table of [ncolors] RGB triples into a 256-entry opaque-ARGB array. */
|
|
215
|
+
private fun readColorTable(ncolors: Int): IntArray? {
|
|
216
|
+
val nbytes = 3 * ncolors
|
|
217
|
+
if (ncolors <= 0 || rawPos + nbytes > rawData.size) {
|
|
218
|
+
status = STATUS_FORMAT_ERROR
|
|
219
|
+
return null
|
|
220
|
+
}
|
|
221
|
+
val tab = IntArray(256) // full size to avoid index bounds checks on lookup
|
|
222
|
+
var i = 0
|
|
223
|
+
var j = rawPos
|
|
224
|
+
while (i < ncolors) {
|
|
225
|
+
val r = rawData[j++].toInt() and 0xff
|
|
226
|
+
val g = rawData[j++].toInt() and 0xff
|
|
227
|
+
val b = rawData[j++].toInt() and 0xff
|
|
228
|
+
tab[i++] = 0xFF000000.toInt() or (r shl 16) or (g shl 8) or b
|
|
229
|
+
}
|
|
230
|
+
rawPos += nbytes
|
|
231
|
+
return tab
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** Main block loop: images, extensions and the trailer. */
|
|
235
|
+
private fun readContents() {
|
|
236
|
+
var done = false
|
|
237
|
+
while (!done && !err()) {
|
|
238
|
+
when (readByte()) {
|
|
239
|
+
0x2C -> readImage() // image separator
|
|
240
|
+
0x21 -> { // extension introducer
|
|
241
|
+
when (readByte()) {
|
|
242
|
+
0xF9 -> readGraphicControlExt()
|
|
243
|
+
0xFF -> { // application extension
|
|
244
|
+
readBlock()
|
|
245
|
+
val app = StringBuilder()
|
|
246
|
+
for (i in 0 until 11) {
|
|
247
|
+
app.append((block[i].toInt() and 0xff).toChar())
|
|
248
|
+
}
|
|
249
|
+
if (app.toString() == "NETSCAPE2.0") readNetscapeExt() else skip()
|
|
250
|
+
}
|
|
251
|
+
else -> skip() // comment / plain-text / unknown extension
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
0x3B -> done = true // trailer
|
|
255
|
+
0x00 -> { /* stray byte: tolerate and continue */ }
|
|
256
|
+
else -> status = STATUS_FORMAT_ERROR
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** Graphic Control Extension: disposal method, transparency flag/index and frame delay. */
|
|
262
|
+
private fun readGraphicControlExt() {
|
|
263
|
+
readByte() // block size (always 4)
|
|
264
|
+
val packed = readByte()
|
|
265
|
+
dispose = (packed and 0x1C) shr 2 // 0=unspecified 1=none 2=background 3=previous
|
|
266
|
+
transparency = (packed and 1) != 0
|
|
267
|
+
delay = readShort() * 10 // centiseconds -> milliseconds
|
|
268
|
+
transIndex = readByte()
|
|
269
|
+
readByte() // block terminator
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** Netscape 2.0 application extension: the animation loop count (0 = forever). */
|
|
273
|
+
private fun readNetscapeExt() {
|
|
274
|
+
do {
|
|
275
|
+
readBlock()
|
|
276
|
+
if (blockSize >= 3 && block[0].toInt() == 1) {
|
|
277
|
+
val b1 = block[1].toInt() and 0xff
|
|
278
|
+
val b2 = block[2].toInt() and 0xff
|
|
279
|
+
loopCount = (b2 shl 8) or b1
|
|
280
|
+
}
|
|
281
|
+
} while (blockSize > 0 && !err())
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/** Image Descriptor + optional local colour table + LZW pixel data for one frame. */
|
|
285
|
+
private fun readImage() {
|
|
286
|
+
ix = readShort()
|
|
287
|
+
iy = readShort()
|
|
288
|
+
iw = readShort()
|
|
289
|
+
ih = readShort()
|
|
290
|
+
|
|
291
|
+
val packed = readByte()
|
|
292
|
+
lctFlag = (packed and 0x80) != 0
|
|
293
|
+
interlace = (packed and 0x40) != 0
|
|
294
|
+
lctSize = 2 shl (packed and 7)
|
|
295
|
+
|
|
296
|
+
if (lctFlag) {
|
|
297
|
+
lct = readColorTable(lctSize)
|
|
298
|
+
act = lct
|
|
299
|
+
} else {
|
|
300
|
+
act = gct
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
var save = 0
|
|
304
|
+
val active = act
|
|
305
|
+
if (transparency && active != null && transIndex < active.size) {
|
|
306
|
+
save = active[transIndex]
|
|
307
|
+
active[transIndex] = 0 // render the transparent index as fully transparent
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (act == null) {
|
|
311
|
+
status = STATUS_FORMAT_ERROR
|
|
312
|
+
return
|
|
313
|
+
}
|
|
314
|
+
if (err()) return
|
|
315
|
+
|
|
316
|
+
decodeImageData()
|
|
317
|
+
skip()
|
|
318
|
+
if (err()) return
|
|
319
|
+
|
|
320
|
+
setPixels()
|
|
321
|
+
framesList.add(Bitmap.createBitmap(mainScratch, width, height, Bitmap.Config.ARGB_8888))
|
|
322
|
+
delaysList.add(if (delay > 0) delay else DEFAULT_FRAME_DELAY_MS)
|
|
323
|
+
frameCount++
|
|
324
|
+
|
|
325
|
+
val active2 = act
|
|
326
|
+
if (transparency && active2 != null && transIndex < active2.size) {
|
|
327
|
+
active2[transIndex] = save // restore the shared colour-table entry
|
|
328
|
+
}
|
|
329
|
+
resetFrame()
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/** Carries the just-drawn frame's disposal state forward as the "previous" state. */
|
|
333
|
+
private fun resetFrame() {
|
|
334
|
+
lastDispose = dispose
|
|
335
|
+
lrx = ix
|
|
336
|
+
lry = iy
|
|
337
|
+
lrw = iw
|
|
338
|
+
lrh = ih
|
|
339
|
+
hasPreviousFrame = true
|
|
340
|
+
dispose = 0
|
|
341
|
+
transparency = false
|
|
342
|
+
delay = 0
|
|
343
|
+
lct = null
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// ---------------------------------------------------------------------------
|
|
347
|
+
// Compositing
|
|
348
|
+
// ---------------------------------------------------------------------------
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Composites the freshly-decoded [pixels] onto [mainScratch]. First the *previous* frame's
|
|
352
|
+
* disposal method is applied to the persistent canvas, then this frame's sub-rectangle is
|
|
353
|
+
* blitted (de-interlacing and skipping transparent pixels). Finally the canvas is snapshotted
|
|
354
|
+
* when this frame "leaves in place", so a later DISPOSAL_PREVIOUS frame can restore it.
|
|
355
|
+
*/
|
|
356
|
+
private fun setPixels() {
|
|
357
|
+
val dest = mainScratch
|
|
358
|
+
val size = dest.size
|
|
359
|
+
|
|
360
|
+
// First frame starts from a clean, fully-transparent canvas.
|
|
361
|
+
if (!hasPreviousFrame) {
|
|
362
|
+
previousImage = null
|
|
363
|
+
java.util.Arrays.fill(dest, 0)
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// DISPOSAL_PREVIOUS with nothing saved to restore to -> clear.
|
|
367
|
+
if (hasPreviousFrame && lastDispose == DISPOSAL_PREVIOUS && previousImage == null) {
|
|
368
|
+
java.util.Arrays.fill(dest, 0)
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Apply the previous frame's disposal to the canvas before drawing this frame.
|
|
372
|
+
if (hasPreviousFrame && lastDispose > DISPOSAL_UNSPECIFIED) {
|
|
373
|
+
if (lastDispose == DISPOSAL_BACKGROUND) {
|
|
374
|
+
var c = 0
|
|
375
|
+
if (!transparency) {
|
|
376
|
+
c = bgColor
|
|
377
|
+
if (lct != null && bgIndex == transIndex) c = 0
|
|
378
|
+
}
|
|
379
|
+
val topLeft = lry * width + lrx
|
|
380
|
+
val bottomLeft = topLeft + lrh * width
|
|
381
|
+
var left = topLeft
|
|
382
|
+
while (left < bottomLeft) {
|
|
383
|
+
val right = left + lrw
|
|
384
|
+
var p = left
|
|
385
|
+
while (p < right) {
|
|
386
|
+
if (p in 0 until size) dest[p] = c
|
|
387
|
+
p++
|
|
388
|
+
}
|
|
389
|
+
left += width
|
|
390
|
+
}
|
|
391
|
+
} else if (lastDispose == DISPOSAL_PREVIOUS) {
|
|
392
|
+
val prev = previousImage
|
|
393
|
+
if (prev != null && prev.size == size) System.arraycopy(prev, 0, dest, 0, size)
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Blit this frame's sub-rectangle onto the canvas, de-interlacing as required.
|
|
398
|
+
val px = pixels ?: return
|
|
399
|
+
val actLocal = act ?: return
|
|
400
|
+
var pass = 1
|
|
401
|
+
var inc = 8
|
|
402
|
+
var iline = 0
|
|
403
|
+
var i = 0
|
|
404
|
+
while (i < ih) {
|
|
405
|
+
var line = i
|
|
406
|
+
if (interlace) {
|
|
407
|
+
if (iline >= ih) {
|
|
408
|
+
pass++
|
|
409
|
+
when (pass) {
|
|
410
|
+
2 -> iline = 4
|
|
411
|
+
3 -> { iline = 2; inc = 4 }
|
|
412
|
+
4 -> { iline = 1; inc = 2 }
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
line = iline
|
|
416
|
+
iline += inc
|
|
417
|
+
}
|
|
418
|
+
line += iy
|
|
419
|
+
if (line < height) {
|
|
420
|
+
val k = line * width
|
|
421
|
+
var dx = k + ix
|
|
422
|
+
var dlim = dx + iw
|
|
423
|
+
if (k + width < dlim) dlim = k + width // clamp to the logical screen edge
|
|
424
|
+
var sx = i * iw
|
|
425
|
+
while (dx < dlim) {
|
|
426
|
+
if (sx < px.size) {
|
|
427
|
+
val index = px[sx].toInt() and 0xff
|
|
428
|
+
if (index < actLocal.size) {
|
|
429
|
+
val c = actLocal[index]
|
|
430
|
+
if (c != 0 && dx >= 0 && dx < size) dest[dx] = c // c == 0 means transparent
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
sx++
|
|
434
|
+
dx++
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
i++
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Snapshot the canvas so a later DISPOSAL_PREVIOUS frame can restore this state.
|
|
441
|
+
if (dispose == DISPOSAL_UNSPECIFIED || dispose == DISPOSAL_NONE) {
|
|
442
|
+
var prev = previousImage
|
|
443
|
+
if (prev == null || prev.size != size) {
|
|
444
|
+
prev = IntArray(size)
|
|
445
|
+
previousImage = prev
|
|
446
|
+
}
|
|
447
|
+
System.arraycopy(dest, 0, prev, 0, size)
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// ---------------------------------------------------------------------------
|
|
452
|
+
// LZW decompression
|
|
453
|
+
// ---------------------------------------------------------------------------
|
|
454
|
+
|
|
455
|
+
/** Classic table-based LZW decode of the image data sub-blocks into [pixels]. */
|
|
456
|
+
private fun decodeImageData() {
|
|
457
|
+
val nullCode = -1
|
|
458
|
+
if (iw <= 0 || ih <= 0 || iw.toLong() * ih.toLong() > Int.MAX_VALUE.toLong()) {
|
|
459
|
+
status = STATUS_FORMAT_ERROR
|
|
460
|
+
return
|
|
461
|
+
}
|
|
462
|
+
val npix = iw * ih
|
|
463
|
+
|
|
464
|
+
var pxArr = pixels
|
|
465
|
+
if (pxArr == null || pxArr.size < npix) {
|
|
466
|
+
pxArr = ByteArray(npix)
|
|
467
|
+
pixels = pxArr
|
|
468
|
+
}
|
|
469
|
+
var pfx = prefix
|
|
470
|
+
if (pfx == null) { pfx = ShortArray(MAX_STACK_SIZE); prefix = pfx }
|
|
471
|
+
var sfx = suffix
|
|
472
|
+
if (sfx == null) { sfx = ByteArray(MAX_STACK_SIZE); suffix = sfx }
|
|
473
|
+
var pst = pixelStack
|
|
474
|
+
if (pst == null) { pst = ByteArray(MAX_STACK_SIZE + 1); pixelStack = pst }
|
|
475
|
+
|
|
476
|
+
val dataSize = readByte()
|
|
477
|
+
if (dataSize < 1 || dataSize > 8) { // guard the code-size shift against malformed input
|
|
478
|
+
status = STATUS_FORMAT_ERROR
|
|
479
|
+
return
|
|
480
|
+
}
|
|
481
|
+
val clear = 1 shl dataSize
|
|
482
|
+
val endOfInformation = clear + 1
|
|
483
|
+
var available = clear + 2
|
|
484
|
+
var oldCode = nullCode
|
|
485
|
+
var codeSize = dataSize + 1
|
|
486
|
+
var codeMask = (1 shl codeSize) - 1
|
|
487
|
+
|
|
488
|
+
var code = 0
|
|
489
|
+
while (code < clear) {
|
|
490
|
+
pfx[code] = 0
|
|
491
|
+
sfx[code] = code.toByte()
|
|
492
|
+
code++
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
var datum = 0
|
|
496
|
+
var bits = 0
|
|
497
|
+
var count = 0
|
|
498
|
+
var first = 0
|
|
499
|
+
var top = 0
|
|
500
|
+
var pi = 0
|
|
501
|
+
var bi = 0
|
|
502
|
+
var i = 0
|
|
503
|
+
|
|
504
|
+
while (i < npix) {
|
|
505
|
+
if (top == 0) {
|
|
506
|
+
if (bits < codeSize) {
|
|
507
|
+
if (count == 0) {
|
|
508
|
+
// Read the next data sub-block.
|
|
509
|
+
count = readBlock()
|
|
510
|
+
if (count <= 0) break
|
|
511
|
+
bi = 0
|
|
512
|
+
}
|
|
513
|
+
datum += (block[bi].toInt() and 0xff) shl bits
|
|
514
|
+
bits += 8
|
|
515
|
+
bi++
|
|
516
|
+
count--
|
|
517
|
+
continue
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Get the next code.
|
|
521
|
+
code = datum and codeMask
|
|
522
|
+
datum = datum shr codeSize
|
|
523
|
+
bits -= codeSize
|
|
524
|
+
|
|
525
|
+
// Interpret the code.
|
|
526
|
+
if (code > available || code == endOfInformation) break
|
|
527
|
+
if (code == clear) {
|
|
528
|
+
// Reset the decoder.
|
|
529
|
+
codeSize = dataSize + 1
|
|
530
|
+
codeMask = (1 shl codeSize) - 1
|
|
531
|
+
available = clear + 2
|
|
532
|
+
oldCode = nullCode
|
|
533
|
+
continue
|
|
534
|
+
}
|
|
535
|
+
if (oldCode == nullCode) {
|
|
536
|
+
pst[top++] = sfx[code]
|
|
537
|
+
oldCode = code
|
|
538
|
+
first = code
|
|
539
|
+
continue
|
|
540
|
+
}
|
|
541
|
+
val inCode = code
|
|
542
|
+
if (code == available) {
|
|
543
|
+
pst[top++] = first.toByte()
|
|
544
|
+
code = oldCode
|
|
545
|
+
}
|
|
546
|
+
while (code > clear) {
|
|
547
|
+
pst[top++] = sfx[code]
|
|
548
|
+
code = pfx[code].toInt()
|
|
549
|
+
}
|
|
550
|
+
first = sfx[code].toInt() and 0xff
|
|
551
|
+
|
|
552
|
+
// Add a new string to the table.
|
|
553
|
+
if (available >= MAX_STACK_SIZE) break
|
|
554
|
+
pst[top++] = first.toByte()
|
|
555
|
+
pfx[available] = oldCode.toShort()
|
|
556
|
+
sfx[available] = first.toByte()
|
|
557
|
+
available++
|
|
558
|
+
if ((available and codeMask) == 0 && available < MAX_STACK_SIZE) {
|
|
559
|
+
codeSize++
|
|
560
|
+
codeMask += available
|
|
561
|
+
}
|
|
562
|
+
oldCode = inCode
|
|
563
|
+
}
|
|
564
|
+
// Pop a pixel off the pixel stack into the output.
|
|
565
|
+
top--
|
|
566
|
+
pxArr[pi++] = pst[top]
|
|
567
|
+
i++
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// Zero any pixels a truncated stream failed to produce.
|
|
571
|
+
while (pi < npix) {
|
|
572
|
+
pxArr[pi++] = 0
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// ---------------------------------------------------------------------------
|
|
577
|
+
// Low-level byte / block reads
|
|
578
|
+
// ---------------------------------------------------------------------------
|
|
579
|
+
|
|
580
|
+
/** Reads one length-prefixed sub-block into [block]; returns the number of bytes read. */
|
|
581
|
+
private fun readBlock(): Int {
|
|
582
|
+
blockSize = readByte()
|
|
583
|
+
var n = 0
|
|
584
|
+
if (blockSize > 0) {
|
|
585
|
+
while (n < blockSize) {
|
|
586
|
+
val remaining = rawData.size - rawPos
|
|
587
|
+
if (remaining <= 0) break
|
|
588
|
+
val count = if (blockSize - n < remaining) blockSize - n else remaining
|
|
589
|
+
System.arraycopy(rawData, rawPos, block, n, count)
|
|
590
|
+
rawPos += count
|
|
591
|
+
n += count
|
|
592
|
+
}
|
|
593
|
+
if (n < blockSize) status = STATUS_FORMAT_ERROR
|
|
594
|
+
}
|
|
595
|
+
return n
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/** Consumes sub-blocks until the block terminator (a zero-length block). */
|
|
599
|
+
private fun skip() {
|
|
600
|
+
do {
|
|
601
|
+
readBlock()
|
|
602
|
+
} while (blockSize > 0 && !err())
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/** Reads a single unsigned byte, flagging a format error past end-of-data. */
|
|
606
|
+
private fun readByte(): Int {
|
|
607
|
+
if (rawPos >= rawData.size) {
|
|
608
|
+
status = STATUS_FORMAT_ERROR
|
|
609
|
+
return 0
|
|
610
|
+
}
|
|
611
|
+
return rawData[rawPos++].toInt() and 0xff
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/** Reads a little-endian unsigned 16-bit value. */
|
|
615
|
+
private fun readShort(): Int = readByte() or (readByte() shl 8)
|
|
616
|
+
|
|
617
|
+
companion object {
|
|
618
|
+
/** [read] status: success. */
|
|
619
|
+
const val STATUS_OK = 0
|
|
620
|
+
|
|
621
|
+
/** [read] status: the data could not be parsed as a GIF. */
|
|
622
|
+
const val STATUS_FORMAT_ERROR = 1
|
|
623
|
+
|
|
624
|
+
/** [read] status: no input was supplied. */
|
|
625
|
+
const val STATUS_OPEN_ERROR = 2
|
|
626
|
+
|
|
627
|
+
/** Maximum number of LZW codes (12-bit code space). */
|
|
628
|
+
private const val MAX_STACK_SIZE = 4096
|
|
629
|
+
|
|
630
|
+
/** Fallback per-frame delay when a GIF specifies a zero / absent delay. */
|
|
631
|
+
private const val DEFAULT_FRAME_DELAY_MS = 100
|
|
632
|
+
|
|
633
|
+
// GIF89a disposal methods.
|
|
634
|
+
private const val DISPOSAL_UNSPECIFIED = 0
|
|
635
|
+
private const val DISPOSAL_NONE = 1
|
|
636
|
+
private const val DISPOSAL_BACKGROUND = 2
|
|
637
|
+
private const val DISPOSAL_PREVIOUS = 3
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Convenience one-shot decode of every frame.
|
|
641
|
+
*
|
|
642
|
+
* @param data the complete GIF bytes.
|
|
643
|
+
* @param maxDimension when > 0, any composited frame whose larger side exceeds this value is
|
|
644
|
+
* proportionally down-scaled (and the full-size frame recycled) so its larger side equals
|
|
645
|
+
* [maxDimension].
|
|
646
|
+
* @return a [DecodedGif], or `null` on decode failure or if there are no frames.
|
|
647
|
+
*/
|
|
648
|
+
fun decodeAll(data: ByteArray, maxDimension: Int = 0): DecodedGif? {
|
|
649
|
+
return try {
|
|
650
|
+
val decoder = GifDecoder()
|
|
651
|
+
decoder.read(data)
|
|
652
|
+
if (decoder.frameCount <= 0) return null
|
|
653
|
+
val frames = ArrayList<Bitmap>(decoder.frameCount)
|
|
654
|
+
val delays = ArrayList<Int>(decoder.frameCount)
|
|
655
|
+
for (i in 0 until decoder.frameCount) {
|
|
656
|
+
var frame = decoder.getFrame(i) ?: continue
|
|
657
|
+
if (maxDimension > 0) {
|
|
658
|
+
val larger = if (frame.width > frame.height) frame.width else frame.height
|
|
659
|
+
if (larger > maxDimension) {
|
|
660
|
+
val scale = maxDimension.toFloat() / larger.toFloat()
|
|
661
|
+
val newW = Math.max(1, Math.round(frame.width * scale))
|
|
662
|
+
val newH = Math.max(1, Math.round(frame.height * scale))
|
|
663
|
+
val scaled = Bitmap.createScaledBitmap(frame, newW, newH, true)
|
|
664
|
+
if (scaled != frame) frame.recycle()
|
|
665
|
+
frame = scaled
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
frames.add(frame)
|
|
669
|
+
delays.add(decoder.getDelay(i))
|
|
670
|
+
}
|
|
671
|
+
if (frames.isEmpty()) null
|
|
672
|
+
else DecodedGif(frames, delays, decoder.loopCount, decoder.width, decoder.height)
|
|
673
|
+
} catch (e: Exception) {
|
|
674
|
+
null
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* Result of [decodeAll]: the composited [frames], their per-frame [delaysMs], the animation
|
|
681
|
+
* [loopCount] (0 = loop forever) and the logical [width] / [height] of the GIF.
|
|
682
|
+
*/
|
|
683
|
+
data class DecodedGif(
|
|
684
|
+
val frames: List<Bitmap>,
|
|
685
|
+
val delaysMs: List<Int>,
|
|
686
|
+
val loopCount: Int,
|
|
687
|
+
val width: Int,
|
|
688
|
+
val height: Int
|
|
689
|
+
)
|
|
690
|
+
}
|