├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── app └── uti_exporter.app │ └── Contents │ ├── Info.plist │ ├── MacOS │ └── Application Stub │ ├── Resources │ └── English.lproj │ │ └── ApplicationStub.nib │ └── document.wflow ├── common ├── bpg_decode.h ├── bpg_decode.m ├── netpbm_decode.h ├── netpbm_decode.m ├── tools.h ├── tools.m ├── webp_decode.h └── webp_decode.m ├── deps ├── libbpg │ ├── libbpg.a │ └── libbpg.h └── libwebp │ ├── decode.h │ ├── demux.h │ ├── encode.h │ ├── format_constants.h │ ├── libwebp.a │ ├── mux.h │ ├── mux_types.h │ └── types.h ├── images-samples.txz ├── mdimporter ├── rsrc │ └── Info.plist └── src │ ├── GetMetadataForFile.m │ └── main.c ├── qlImageSize.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings │ └── xcuserdata │ │ └── nyxouf.xcuserdatad │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ ├── benjamin.xcuserdatad │ └── xcschemes │ │ ├── mdImageSize.xcscheme │ │ ├── qlImageSize.xcscheme │ │ └── xcschememanagement.plist │ └── nyxouf.xcuserdatad │ ├── xcdebugger │ └── Breakpoints.xcbkptlist │ └── xcschemes │ ├── mdImageSize.xcscheme │ ├── qlImageSize.xcscheme │ └── xcschememanagement.plist └── qlgenerator ├── rsrc └── Info.plist └── src ├── GeneratePreviewForURL.m ├── GenerateThumbnailForURL.m └── main.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # Pods/ 38 | 39 | # Carthage 40 | # 41 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 42 | # Carthage/Checkouts 43 | 44 | Carthage/Build 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 52 | 53 | fastlane/report.xml 54 | fastlane/Preview.html 55 | fastlane/screenshots 56 | fastlane/test_output 57 | 58 | # Code Injection 59 | # 60 | # After new code Injection tools there's a generated folder /iOSInjectionProject 61 | # https://github.com/johnno1962/injectionforxcode 62 | 63 | iOSInjectionProject/ 64 | 65 | mdimporter/.DS_Store 66 | 67 | qlgenerator/.DS_Store 68 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | script: 3 | - xcodebuild -project qlImageSize.xcodeproj -target qlImageSize -target mdImageSize 4 | - mv build/Release/qlImageSize.qlgenerator . 5 | - mv build/Release/mdImageSize.mdimporter . 6 | - zip -r qlImageSize.qlgenerator.zip qlImageSize.qlgenerator 7 | - zip -r mdImageSize.mdimporter.zip mdImageSize.mdimporter 8 | deploy: 9 | provider: releases 10 | api_key: 11 | secure: "M2Y26YDsPqMt5MERoMHIVojR/lwp6dnvnKbqg37nT+74InQ/SNpxDbYg0weOdPm/ostV4a7YYGoTwlE5VrA3VOIPwVWUC5jcGB3H7VwENO1brBXUEM2DI6X/2Kr0bRzcL6Qnoqw8i8hD892bbsVyqE1teEpaTOuGUXXRE3lnB4EdfLVb4Jbl1k96rQGpUPpXr2d2OpusFeK0no2ysjdW50dR39yrwEqca9uKhRk3FwacbYahnujGnzWW/sMvnoh75n32ZWFdgiGTRoetJ2zHdh158wAWrWgLkBlr0WnqQDkQBoVeZ1K+iZtoXkpcuqdGa8mGABl1pEQTsVMlyriG6bZ67BLvJIzMZhwD2jgKoWpQSRiu42UnmKR9zBG5zUfpmOvVw79QKl5DBRt6hwQI+mKvDwHv68Q9pC3/eMKKCbmxU0tsXOyR3mDQzB1Nr2b4KJVyj/vRe1YhTORzTXIxL/cJz3mUdG3WYHFdBmFNLIutsnl4Xm/qDS0nxL0H6HcYGNddHkcMGfkIJYo5gZozyo6GeF9hu0EEUZ4DvG6gGl0KeW1DGA9ASDyrcHvmkiuiM8xtmMND9NCbH1kLWvgrqJpTUG48w1UWC+M4YL/MLK1NNdogSNiPs+07aHF8m9mPLYwGf4Aag9971D1oWaiiYvoQGLZDnUepD3791i/ow0E=" 12 | file: 13 | - qlImageSize.qlgenerator.zip 14 | - mdImageSize.mdimporter.zip 15 | skip_cleanup: true 16 | on: 17 | tags: true 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Nyx0uf 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This project is not maintained anymore, it has been killed by macOS 10.15, see issues for details. 2 | 3 | ![License: BSD](https://img.shields.io/badge/license-BSD-blue.svg?style=flat) [![Build Status](https://travis-ci.com/Nyx0uf/qlImageSize.svg?branch=master)](https://travis-ci.com/Nyx0uf/qlImageSize) 4 | 5 | This project is composed of both a **QuickLook** plugin and a **Spotlight** plugin. Both are independant and can be built separately. 6 | They require at least *macOS High Sierra (10.13)*. 7 | 8 | # qlImageSize 9 | 10 | This is the **QuickLook** plugin, it displays the dimensions, DPI and file size of an image in the title bar. 11 | 12 | ![https://static.whine.fr/images/2014/qlimagesize4.jpg](https://static.whine.fr/images/2019/qlimagesize1.jpg) 13 | 14 | This plugin can also preview and generate *Finder* thumbnails for natively unsupported images formats [bpg](http://bellard.org/bpg/ "bpg") and [WebP](https://developers.google.com/speed/webp/ "WebP"). 15 | 16 | ![https://static.whine.fr/images/2014/qlimagesize3.jpg](https://static.whine.fr/images/2014/qlimagesize3.jpg) 17 | 18 | ![https://static.whine.fr/images/2014/qlimagesize2.jpg](https://static.whine.fr/images/2014/qlimagesize2.jpg) 19 | 20 | 21 | # mdImageSize 22 | 23 | This is the **Spotlight** plugin, it displays informations of unsupported images (**WebP**, **bpg**) in the Finder's inspector window. 24 | 25 | ![https://static.whine.fr/images/2014/mdimagesize1.jpg](https://static.whine.fr/images/2014/mdimagesize1.jpg) 26 | 27 | 28 | # Install 29 | 30 | 3 choices : 31 | 32 | 1. Using [Homebrew Cask](https://brew.sh/): 33 | ``` 34 | brew install --cask qlimagesize mdimagesizemdimporter 35 | ``` 36 | 2. Download the latest build from https://github.com/Nyx0uf/qlImageSize/releases/latest and save it to your `~/Library/QuickLook` and/or `~/Library/Spotlight` folder. 37 | 3. Build from sources using Xcode. (just have to hit the build button). 38 | 39 | 40 | # Uninstall 41 | 42 | 2 choices : 43 | 44 | 1. Using [Homebrew Cask](https://brew.sh/): 45 | ``` 46 | brew uninstall --cask qlimagesize mdimagesizemdimporter 47 | ``` 48 | 2. Manually : 49 | - Launch *Terminal.app* in `/Applications/Utilities` 50 | - Copy and paste the following line: 51 | ``` 52 | rm -rf ~/Library/QuickLook/qlImageSize.qlgenerator ~/Library/Spotlight/mdImageSize.mdimporter 53 | ``` 54 | - Press Enter. 55 | 56 | 57 | # Limitations 58 | 59 | If you are a **Pixelmator** user, its own QuickLook plugin might get in the way when previewing **WebP** files. To fix this you need to edit the file `/Applications/Pixelmator.app/Contents/Library/QuickLook/PixelmatorLook.qlgenerator/Contents/Info.plist` and remove the dict entry that handles **webp**. 60 | 61 | After editing the `Info.plist`, QuickLook for the Pixelmator file format (such as `.pxm`) might not work due to Code Signing. You can unsign Pixelmator's QuickLook binary using the tool [unsign](https://github.com/steakknife/unsign). After downloading and building it, just run : 62 | 63 | unsign /Applications/Pixelmator.app/Contents/Library/QuickLook/PixelmatorLook.qlgenerator/Contents/MacOS/PixelmatorLook`. 64 | 65 | It will create another binary with the extension **unsigned**, rename the orignal binary for backup then remove the extension for the unsigned binary, ex : 66 | 67 | mv /Applications/Pixelmator.app/Contents/Library/QuickLook/PixelmatorLook.qlgenerator/Contents/MacOS/PixelmatorLook /Applications/Pixelmator.app/Contents/Library/QuickLook/PixelmatorLook.qlgenerator/Contents/MacOS/PixelmatorLook.bak 68 | mv /Applications/Pixelmator.app/Contents/Library/QuickLook/PixelmatorLook.qlgenerator/Contents/MacOS/PixelmatorLook.unsigned /Applications/Pixelmator.app/Contents/Library/QuickLook/PixelmatorLook.qlgenerator/Contents/MacOS/PixelmatorLook 69 | 70 | 71 | # Upgrading dependencies 72 | 73 | ### libwbep 74 | 75 | Grab the [latest version](https://github.com/webmproject/libwebp/releases). Decompress the archive and simply run : 76 | 77 | ./autogen.sh 78 | CFLAGS="-mmacosx-version-min=10.13" ./configure --disable-shared 79 | make 80 | 81 | The resulting library can be found in *src/.libs/libwebp.a*. 82 | 83 | ### libbpg 84 | 85 | Grab the [latest version](https://bellard.org/bpg/). Decompress the archive and edit the `Makefile` with the following changes : 86 | 87 | - Uncomment the line which reads `CONFIG_APPLE=y` 88 | - Comment both lines `USE_X265=y` and `USE_BPGVIEW=y` 89 | 90 | And replace the following 91 | 92 | ifdef CONFIG_APPLE 93 | LDFLAGS+=-Wl,-dead_strip 94 | 95 | with 96 | 97 | ifdef CONFIG_APPLE 98 | LDFLAGS+=-Wl,-dead_strip 99 | CFLAGS+=-mmacosx-version-min=10.13 100 | 101 | Then simply run `make`. The resulting library will be in the project directory. 102 | 103 | # License 104 | 105 | This project is released under the *MIT license*, see **LICENSE**. 106 | -------------------------------------------------------------------------------- /app/uti_exporter.app/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AMIsApplet 6 | 7 | AMStayOpen 8 | 9 | BuildMachineOSBuild 10 | 13A563a 11 | CFBundleDevelopmentRegion 12 | English 13 | CFBundleDocumentTypes 14 | 15 | 16 | CFBundleTypeExtensions 17 | 18 | * 19 | 20 | CFBundleTypeName 21 | Automator workflow file 22 | CFBundleTypeOSTypes 23 | 24 | **** 25 | 26 | CFBundleTypeRole 27 | Viewer 28 | 29 | 30 | CFBundleExecutable 31 | Application Stub 32 | CFBundleIconFile 33 | AutomatorApplet 34 | CFBundleIdentifier 35 | com.apple.automator.uti_exporter 36 | CFBundleInfoDictionaryVersion 37 | 6.0 38 | CFBundleName 39 | uti_exporter 40 | CFBundlePackageType 41 | APPL 42 | CFBundleShortVersionString 43 | 1.2 44 | CFBundleSignature 45 | ???? 46 | CFBundleURLTypes 47 | 48 | CFBundleVersion 49 | 381 50 | DTCompiler 51 | com.apple.compilers.llvm.clang.1_0 52 | DTPlatformBuild 53 | 5A11344p 54 | DTPlatformVersion 55 | GM 56 | DTSDKBuild 57 | 13A563a 58 | DTSDKName 59 | 60 | DTXcode 61 | 0500 62 | DTXcodeBuild 63 | 5A11344p 64 | LSMinimumSystemVersion 65 | 10.5 66 | LSMinimumSystemVersionByArchitecture 67 | 68 | x86_64 69 | 10.6 70 | 71 | LSUIElement 72 | 73 | NSAppleScriptEnabled 74 | YES 75 | NSMainNibFile 76 | ApplicationStub 77 | NSPrincipalClass 78 | NSApplication 79 | NSServices 80 | 81 | UTExportedTypeDeclarations 82 | 83 | 84 | UTTypeConformsTo 85 | 86 | public.image 87 | 88 | UTTypeDescription 89 | Netpbm bi-level image format 90 | UTTypeIdentifier 91 | fr.whine.pbm 92 | UTTypeReferenceURL 93 | http://netpbm.sourceforge.net/doc/pbm.html 94 | UTTypeTagSpecification 95 | 96 | public.filename-extension 97 | 98 | pbm 99 | PBM 100 | 101 | 102 | 103 | 104 | UTTypeConformsTo 105 | 106 | public.image 107 | 108 | UTTypeDescription 109 | Netpbm grayscale image format 110 | UTTypeIdentifier 111 | fr.whine.pgm 112 | UTTypeReferenceURL 113 | http://netpbm.sourceforge.net/doc/pgm.html 114 | UTTypeTagSpecification 115 | 116 | public.filename-extension 117 | 118 | pgm 119 | PGM 120 | 121 | 122 | 123 | 124 | UTTypeConformsTo 125 | 126 | public.image 127 | 128 | UTTypeDescription 129 | Netpbm color image format 130 | UTTypeIdentifier 131 | fr.whine.ppm 132 | UTTypeReferenceURL 133 | http://netpbm.sourceforge.net/doc/ppm.html 134 | UTTypeTagSpecification 135 | 136 | public.filename-extension 137 | 138 | ppm 139 | PPM 140 | 141 | 142 | 143 | 144 | UTTypeConformsTo 145 | 146 | public.image 147 | 148 | UTTypeDescription 149 | BPG 150 | UTTypeIdentifier 151 | fr.whine.bpg 152 | UTTypeReferenceURL 153 | http://bellard.org/bpg/ 154 | UTTypeTagSpecification 155 | 156 | public.filename-extension 157 | 158 | bpg 159 | BPG 160 | 161 | 162 | 163 | 164 | UTTypeConformsTo 165 | 166 | public.image 167 | 168 | UTTypeDescription 169 | WebP 170 | UTTypeIdentifier 171 | fr.whine.webp 172 | UTTypeReferenceURL 173 | https://developers.google.com/speed/webp/docs/riff_container 174 | UTTypeTagSpecification 175 | 176 | public.filename-extension 177 | 178 | webp 179 | WEBP 180 | 181 | 182 | 183 | 184 | UTImportedTypeDeclarations 185 | 186 | 187 | UTTypeConformsTo 188 | 189 | public.image 190 | 191 | UTTypeDescription 192 | Netpbm bi-level image format 193 | UTTypeIdentifier 194 | fr.whine.pbm 195 | UTTypeReferenceURL 196 | http://netpbm.sourceforge.net/doc/pbm.html 197 | UTTypeTagSpecification 198 | 199 | public.filename-extension 200 | 201 | pbm 202 | PBM 203 | 204 | 205 | 206 | 207 | UTTypeConformsTo 208 | 209 | public.image 210 | 211 | UTTypeDescription 212 | Netpbm grayscale image format 213 | UTTypeIdentifier 214 | fr.whine.pgm 215 | UTTypeReferenceURL 216 | http://netpbm.sourceforge.net/doc/pgm.html 217 | UTTypeTagSpecification 218 | 219 | public.filename-extension 220 | 221 | pgm 222 | PGM 223 | 224 | 225 | 226 | 227 | UTTypeConformsTo 228 | 229 | public.image 230 | 231 | UTTypeDescription 232 | Netpbm color image format 233 | UTTypeIdentifier 234 | fr.whine.ppm 235 | UTTypeReferenceURL 236 | http://netpbm.sourceforge.net/doc/ppm.html 237 | UTTypeTagSpecification 238 | 239 | public.filename-extension 240 | 241 | ppm 242 | PPM 243 | 244 | 245 | 246 | 247 | UTTypeConformsTo 248 | 249 | public.image 250 | 251 | UTTypeDescription 252 | BPG 253 | UTTypeIdentifier 254 | fr.whine.bpg 255 | UTTypeReferenceURL 256 | http://bellard.org/bpg/ 257 | UTTypeTagSpecification 258 | 259 | public.filename-extension 260 | 261 | bpg 262 | BPG 263 | 264 | 265 | 266 | 267 | UTTypeConformsTo 268 | 269 | public.image 270 | 271 | UTTypeDescription 272 | WebP 273 | UTTypeIdentifier 274 | fr.whine.webp 275 | UTTypeReferenceURL 276 | https://developers.google.com/speed/webp/docs/riff_container 277 | UTTypeTagSpecification 278 | 279 | public.filename-extension 280 | 281 | webp 282 | WEBP 283 | 284 | 285 | 286 | 287 | 288 | 289 | -------------------------------------------------------------------------------- /app/uti_exporter.app/Contents/MacOS/Application Stub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nyx0uf/qlImageSize/41082059f6b0d57609a60aa27b7127552e17708f/app/uti_exporter.app/Contents/MacOS/Application Stub -------------------------------------------------------------------------------- /app/uti_exporter.app/Contents/Resources/English.lproj/ApplicationStub.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nyx0uf/qlImageSize/41082059f6b0d57609a60aa27b7127552e17708f/app/uti_exporter.app/Contents/Resources/English.lproj/ApplicationStub.nib -------------------------------------------------------------------------------- /app/uti_exporter.app/Contents/document.wflow: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AMApplicationBuild 6 | 381 7 | AMApplicationVersion 8 | 2.4 9 | AMDocumentVersion 10 | 2 11 | actions 12 | 13 | connectors 14 | 15 | workflowMetaData 16 | 17 | workflowTypeIdentifier 18 | com.apple.Automator.application 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /common/bpg_decode.h: -------------------------------------------------------------------------------- 1 | // 2 | // bpg_decode.h 3 | // qlImageSize 4 | // 5 | // Created by @Nyx0uf on 30/12/14. 6 | // Copyright (c) 2014 Nyx0uf. All rights reserved. 7 | // 8 | 9 | 10 | #import "tools.h" 11 | 12 | 13 | #ifdef NYX_QL_SUPPORT_BPG_DECODE 14 | CF_RETURNS_RETAINED CGImageRef decode_bpg_at_path(CFStringRef filepath, image_infos* infos); 15 | #endif 16 | 17 | #ifdef NYX_MD_SUPPORT_BPG_DECODE 18 | bool get_bpg_informations_for_filepath(CFStringRef filepath, image_infos* infos); 19 | #endif 20 | -------------------------------------------------------------------------------- /common/bpg_decode.m: -------------------------------------------------------------------------------- 1 | // 2 | // bpg_decode.m 3 | // qlImageSize 4 | // 5 | // Created by @Nyx0uf on 30/12/14. 6 | // Copyright (c) 2014 Nyx0uf. All rights reserved. 7 | // 8 | 9 | 10 | #import "bpg_decode.h" 11 | #import "libbpg.h" 12 | 13 | 14 | #ifdef NYX_QL_SUPPORT_BPG_DECODE 15 | CF_RETURNS_RETAINED CGImageRef decode_bpg_at_path(CFStringRef filepath, image_infos* infos) 16 | { 17 | // Read file 18 | uint8_t* buffer = NULL; 19 | const size_t file_size = read_file(filepath, &buffer); 20 | if (0 == file_size) 21 | { 22 | free(buffer); 23 | return NULL; 24 | } 25 | 26 | // Decode image 27 | BPGDecoderContext* bpg_ctx = bpg_decoder_open(); 28 | int ret = bpg_decoder_decode(bpg_ctx, buffer, (int)file_size); 29 | free(buffer); 30 | if (ret < 0) 31 | { 32 | bpg_decoder_close(bpg_ctx); 33 | return NULL; 34 | } 35 | 36 | // Get image infos 37 | BPGImageInfo img_info_s, *img_info = &img_info_s; 38 | bpg_decoder_get_info(bpg_ctx, img_info); 39 | const size_t w = (size_t)img_info->width; 40 | const size_t h = (size_t)img_info->height; 41 | 42 | // Choose output colorspace (RGB / RGBA) 43 | const size_t num_c = img_info->has_alpha ? 4 : 3; 44 | const size_t stride = num_c * w; 45 | const size_t img_size = stride * h; 46 | uint8_t* rgb_buffer = (uint8_t*)malloc(img_size); 47 | size_t idx = 0; 48 | bpg_decoder_start(bpg_ctx, img_info->has_alpha ? BPG_OUTPUT_FORMAT_RGBA32 : BPG_OUTPUT_FORMAT_RGB24); 49 | for (size_t y = 0; y < h; y++) 50 | { 51 | bpg_decoder_get_line(bpg_ctx, rgb_buffer + idx); 52 | idx += stride; 53 | } 54 | bpg_decoder_close(bpg_ctx); 55 | 56 | if (infos != NULL) 57 | { 58 | infos->width = w; 59 | infos->height = h; 60 | infos->filesize = file_size; 61 | } 62 | 63 | // Create CGImage 64 | CGDataProviderRef data_provider = CGDataProviderCreateWithData(NULL, rgb_buffer, img_size, NULL); 65 | if (data_provider == NULL) 66 | { 67 | free(rgb_buffer); 68 | return NULL; 69 | } 70 | CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); 71 | CGImageRef img_ref = CGImageCreate(w, h, 8, 8 * num_c, stride, color_space, kCGBitmapByteOrderDefault | ((img_info->has_alpha) ? kCGImageAlphaPremultipliedLast : kCGImageAlphaNone), data_provider, NULL, true, kCGRenderingIntentDefault); 72 | CGColorSpaceRelease(color_space); 73 | CGDataProviderRelease(data_provider); 74 | free(rgb_buffer); 75 | return img_ref; 76 | } 77 | #endif /* NYX_QL_SUPPORT_BPG_DECODE */ 78 | 79 | #ifdef NYX_MD_SUPPORT_BPG_DECODE 80 | bool get_bpg_informations_for_filepath(CFStringRef filepath, image_infos* infos) 81 | { 82 | // Read file 83 | uint8_t* buffer = NULL; 84 | const size_t size = read_file(filepath, &buffer); 85 | if (0 == size) 86 | { 87 | free(buffer); 88 | return false; 89 | } 90 | 91 | // Decode image 92 | BPGDecoderContext* bpg_ctx = bpg_decoder_open(); 93 | int ret = bpg_decoder_decode(bpg_ctx, buffer, (int)size); 94 | free(buffer); 95 | if (ret < 0) 96 | { 97 | bpg_decoder_close(bpg_ctx); 98 | return false; 99 | } 100 | 101 | // Get image infos 102 | BPGImageInfo img_info_s, *img_info = &img_info_s; 103 | bpg_decoder_get_info(bpg_ctx, img_info); 104 | infos->width = (size_t)img_info->width; 105 | infos->height = (size_t)img_info->height; 106 | infos->has_alpha = (uint8_t)img_info->has_alpha; 107 | infos->bit_depth = (uint8_t)img_info->bit_depth; 108 | colorspace_t cs = colorspace_unknown; 109 | const BPGColorSpaceEnum color_space = (BPGColorSpaceEnum)img_info->color_space; 110 | switch (color_space) 111 | { 112 | case BPG_CS_RGB: 113 | cs = colorspace_rgb; 114 | break; 115 | case BPG_CS_YCbCr: 116 | cs = colorspace_ycbcr; 117 | break; 118 | case BPG_CS_YCgCo: 119 | cs = colorspace_ycgco; 120 | break; 121 | case BPG_CS_YCbCr_BT709: 122 | cs = colorspace_bt709; 123 | break; 124 | case BPG_CS_YCbCr_BT2020: 125 | cs = colorspace_bt2020; 126 | break; 127 | default: 128 | cs = colorspace_unknown; 129 | } 130 | infos->colorspace = cs; 131 | bpg_decoder_close(bpg_ctx); 132 | 133 | return true; 134 | } 135 | #endif /* NYX_MD_SUPPORT_BPG_DECODE */ 136 | -------------------------------------------------------------------------------- /common/netpbm_decode.h: -------------------------------------------------------------------------------- 1 | // 2 | // netpbm_decode.h 3 | // qlImageSize 4 | // 5 | // Created by @Nyx0uf on 30/12/14. 6 | // Copyright (c) 2014 Nyx0uf. All rights reserved. 7 | // 8 | 9 | 10 | #import "tools.h" 11 | 12 | 13 | #ifdef NYX_QL_SUPPORT_NETPBM_DECODE 14 | CF_RETURNS_RETAINED CGImageRef decode_netpbm_at_path(CFStringRef filepath, image_infos* infos); 15 | #endif 16 | 17 | #ifdef NYX_MD_SUPPORT_NETPBM_DECODE 18 | bool get_netpbm_informations_for_filepath(CFStringRef filepath, image_infos* infos); 19 | #endif 20 | -------------------------------------------------------------------------------- /common/netpbm_decode.m: -------------------------------------------------------------------------------- 1 | // 2 | // netpbm_decode.m 3 | // qlImageSize 4 | // 5 | // Created by @Nyx0uf on 30/12/14. 6 | // Copyright (c) 2014 Nyx0uf. All rights reserved. 7 | // 8 | 9 | 10 | #import "netpbm_decode.h" 11 | 12 | #ifdef NYX_MD_SUPPORT_NETPBM_DECODE 13 | bool get_netpbm_informations_for_filepath(CFStringRef filepath, image_infos* infos) 14 | { 15 | // Read file 16 | uint8_t* buffer = NULL; 17 | const size_t size = read_file(filepath, &buffer); 18 | if (size <= 2) 19 | { 20 | free(buffer); 21 | return false; 22 | } 23 | 24 | // Check if Portable Pixmap 25 | // Luckily '0'-'9' are always sequential in C, so the code below should work 26 | if ((char)buffer[0] != 'P' && ((char)buffer[1] < '1' || (char)buffer[1] > '6')) 27 | { 28 | free(buffer); 29 | return false; 30 | } 31 | 32 | // Get width and height 33 | size_t index = 3, i = 0; 34 | char ctmp[8] = {0x00}; 35 | char c; 36 | // The dimension we're finished reading; 0 if width, 1 if height, 2 if done 37 | int status = 0; 38 | while (status < 2 && index < size) 39 | { 40 | c = (char)buffer[index++]; 41 | 42 | // Ignore whitespace 43 | if (isblank(c)) continue; 44 | 45 | // Ignore comments, which are from a '#' to the end of the line 46 | if (c == '#') 47 | { 48 | while (buffer[index++] != '\n'); 49 | continue; 50 | } 51 | 52 | // Read width/height 53 | if (isnumber(c)) 54 | { 55 | index--; // Push back number 56 | while (isnumber(c = (char)buffer[index++])) 57 | { 58 | ctmp[i++] = c; 59 | } 60 | switch (status) 61 | { 62 | case 0: // width 63 | infos->width = (size_t)atol(ctmp); 64 | case 1: // height 65 | infos->height = (size_t)atol(ctmp); 66 | } 67 | 68 | // Clean up 69 | status++; 70 | i = 0; 71 | memset(ctmp, 0x00, 8); 72 | } 73 | } 74 | 75 | infos->has_alpha = 0; 76 | infos->bit_depth = 8; 77 | infos->colorspace = colorspace_rgb; 78 | 79 | free(buffer); 80 | 81 | return true; 82 | } 83 | #endif /* NYX_MD_SUPPORT_NETPBM_DECODE */ 84 | 85 | #ifdef NYX_QL_SUPPORT_NETPBM_DECODE 86 | 87 | #import 88 | 89 | typedef struct _nyx_rgb_pixel_struct { 90 | uint8_t r; 91 | uint8_t g; 92 | uint8_t b; 93 | } rgb_pixel; 94 | 95 | /* Private functions declarations */ 96 | static void* _decode_pbm(const uint8_t* bytes, const size_t size, size_t* width, size_t* height); 97 | static void* _decode_pgm(const uint8_t* bytes, const size_t size, size_t* width, size_t* height); 98 | static void* _decode_ppm(const uint8_t* bytes, const size_t size, size_t* width, size_t* height); 99 | 100 | CF_RETURNS_RETAINED CGImageRef decode_netpbm_at_path(CFStringRef filepath, image_infos* infos) 101 | { 102 | // Read file 103 | uint8_t* buffer = NULL; 104 | const size_t file_size = read_file(filepath, &buffer); 105 | if (0 == file_size) 106 | { 107 | free(buffer); 108 | return NULL; 109 | } 110 | 111 | // Identify type (handle binary only) 112 | if ((char)buffer[0] != 'P') 113 | { 114 | free(buffer); 115 | return NULL; 116 | } 117 | 118 | // Only handle binary version for now 119 | uint8_t* rgb_buffer = NULL; 120 | size_t width = 0, height = 0; 121 | const char idd = (char)buffer[1]; 122 | if (idd == '4'/* || idd == '1'*/) // pbm 123 | rgb_buffer = _decode_pbm(buffer, file_size, &width, &height); 124 | else if (idd == '5'/* || idd == '2'*/) // pgm 125 | rgb_buffer = _decode_pgm(buffer, file_size, &width, &height); 126 | else if (idd == '6'/* || idd == '3'*/) // ppm 127 | rgb_buffer = _decode_ppm(buffer, file_size, &width, &height); 128 | else 129 | { 130 | free(buffer); 131 | return NULL; 132 | } 133 | free(buffer); 134 | 135 | if (infos != NULL) 136 | { 137 | infos->width = width; 138 | infos->height = height; 139 | infos->filesize = file_size; 140 | } 141 | 142 | // Create CGImage 143 | CGDataProviderRef data_provider = CGDataProviderCreateWithData(NULL, rgb_buffer, width * height * 3, NULL); 144 | CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); 145 | CGImageRef img_ref = CGImageCreate(width, height, 8, 24, 3 * width, color_space, kCGBitmapByteOrderDefault | kCGImageAlphaNone, data_provider, NULL, true, kCGRenderingIntentDefault); 146 | CGColorSpaceRelease(color_space); 147 | CGDataProviderRelease(data_provider); 148 | free(rgb_buffer); 149 | return img_ref; 150 | } 151 | 152 | #pragma mark - Private 153 | static void* _decode_pbm(const uint8_t* bytes, const size_t size, size_t* width, size_t* height) 154 | { 155 | // TODO: FIX cause it's bugged :> 156 | // format, where • is a separator (space, tab, newline) 157 | // P4•WIDTH•HEIGHT 158 | 159 | // Get width 160 | size_t index = 3, i = 0; 161 | char ctmp[8] = {0x00}; 162 | char c = 0x00; 163 | while ((c = (char)bytes[index++]) && (!isspace(c))) 164 | ctmp[i++] = c; 165 | *width = (size_t)atol(ctmp); 166 | 167 | // Get height 168 | i = 0; 169 | memset(ctmp, 0x00, 8); 170 | while ((c = (char)bytes[index++]) && (!isspace(c))) 171 | ctmp[i++] = c; 172 | *height = (size_t)atol(ctmp); 173 | 174 | // 1 byte = 8 px 175 | //rgb_pixel* rgb_buffer = (rgb_pixel*)malloc(((size - index + 1) * 8) * 3); 176 | rgb_pixel* rgb_buffer = (rgb_pixel*)malloc((*width) * (*height) * 3); 177 | i = 0; 178 | while (index < size) 179 | { 180 | uint8_t b = bytes[index++]; 181 | for (int a = 8; a >= 1; a--) 182 | { 183 | uint8_t tmp = ((b >> a) & 0x01); 184 | tmp = (0 == tmp) ? 255 : 0; 185 | rgb_buffer[i++] = (rgb_pixel){tmp, tmp, tmp}; 186 | } 187 | } 188 | 189 | return rgb_buffer; 190 | } 191 | 192 | static void* _decode_pgm(const uint8_t* bytes, const size_t size, size_t* width, size_t* height) 193 | { 194 | // format, where • is a separator (space, tab, newline) 195 | // P5•WIDTH•HEIGHT•MAX_GRAY_VAL 196 | 197 | // Get width 198 | size_t index = 3, i = 0; 199 | char ctmp[8] = {0x00}; 200 | char c = 0x00; 201 | while ((c = (char)bytes[index++]) && (!isspace(c))) 202 | ctmp[i++] = c; 203 | *width = (size_t)atol(ctmp); 204 | 205 | // Get height 206 | i = 0; 207 | memset(ctmp, 0x00, 8); 208 | while ((c = (char)bytes[index++]) && (!isspace(c))) 209 | ctmp[i++] = c; 210 | *height = (size_t)atol(ctmp); 211 | 212 | // Get max gray value (max is 65535), but we only handle 8-bit so over 255 is a no-no 213 | i = 0; 214 | memset(ctmp, 0x00, 8); 215 | while ((c = (char)bytes[index++]) && (!isspace(c))) 216 | ctmp[i++] = c; 217 | const size_t max_val = (size_t)atol(ctmp); 218 | if (max_val > 255) 219 | return NULL; // 16-bit, ignore. 220 | 221 | // Convert to RGB 222 | const size_t actual_size = (size - index + 1); 223 | rgb_pixel* rgb_buffer = (rgb_pixel*)malloc(sizeof(rgb_pixel) * actual_size); 224 | const float ratio = (float)max_val / 255.0f; 225 | i = 0; 226 | if ((int)ratio == 1) 227 | { 228 | while (index < size) 229 | { 230 | const uint8_t b = bytes[index++]; 231 | rgb_buffer[i++] = (rgb_pixel){b, b, b}; 232 | } 233 | } 234 | else 235 | { 236 | while (index < size) 237 | { 238 | const uint8_t b = (uint8_t)((float)bytes[index++] / ratio); 239 | rgb_buffer[i++] = (rgb_pixel){b, b, b}; 240 | } 241 | } 242 | 243 | return rgb_buffer; 244 | } 245 | 246 | static void* _decode_ppm(const uint8_t* bytes, const size_t size, size_t* width, size_t* height) 247 | { 248 | // format, where • is a separator (space, tab, newline) 249 | // P6•WIDTH•HEIGHT•MAX_VAL 250 | 251 | // Get width 252 | size_t index = 3, i = 0; 253 | char ctmp[8] = {0x00}; 254 | char c = 0x00; 255 | while ((c = (char)bytes[index++]) && (!isspace(c))) 256 | ctmp[i++] = c; 257 | *width = (size_t)atol(ctmp); 258 | 259 | // Get height 260 | i = 0; 261 | memset(ctmp, 0x00, 8); 262 | while ((c = (char)bytes[index++]) && (!isspace(c))) 263 | ctmp[i++] = c; 264 | *height = (size_t)atol(ctmp); 265 | 266 | // Get max component value (max is 65535), but we only handle 8-bit so over 255 is a no-no 267 | i = 0; 268 | memset(ctmp, 0x00, 8); 269 | while ((c = (char)bytes[index++]) && (!isspace(c))) 270 | ctmp[i++] = c; 271 | const size_t max_val = (size_t)atol(ctmp); 272 | if (max_val > 255) 273 | return NULL; // 16-bit, ignore. 274 | 275 | void* buffer = NULL; 276 | const size_t actual_size = (size - index + 1); 277 | const float ratio = (float)max_val / 255.0f; 278 | if ((int)ratio == 1) 279 | { 280 | // Got the same ratio, just have to make a copy 281 | buffer = (uint8_t*)malloc(sizeof(uint8_t) * actual_size); 282 | memcpy(buffer, &(bytes[index]), actual_size); 283 | } 284 | else 285 | { 286 | // Moronic case, whoever does this deserve to die 287 | float* data_as_float = (float*)malloc(sizeof(float) * actual_size); 288 | buffer = (uint8_t*)malloc(sizeof(uint8_t) * actual_size); 289 | vDSP_vfltu8(&(bytes[index]), 1, data_as_float, 1, actual_size); 290 | vDSP_vsdiv(data_as_float, 1, &ratio, data_as_float, 1, actual_size); 291 | vDSP_vfixu8(data_as_float, 1, buffer, 1, actual_size); 292 | free(data_as_float); 293 | } 294 | 295 | return buffer; 296 | } 297 | 298 | #endif /* NYX_QL_SUPPORT_NETPBM_DECODE */ 299 | -------------------------------------------------------------------------------- /common/tools.h: -------------------------------------------------------------------------------- 1 | // 2 | // tools.h 3 | // qlImageSize 4 | // 5 | // Created by @Nyx0uf on 02/02/12. 6 | // Copyright (c) 2012 Nyx0uf. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | 12 | #define NYX_QL_SUPPORT_BPG_DECODE 13 | #define NYX_MD_SUPPORT_BPG_DECODE 14 | #define NYX_QL_SUPPORT_WEBP_DECODE 15 | #define NYX_MD_SUPPORT_WEBP_DECODE 16 | //#define NYX_QL_SUPPORT_NETPBM_DECODE 17 | #define NYX_MD_SUPPORT_NETPBM_DECODE 18 | 19 | #define SAFE_CFRelease(ptr) do { if (ptr != NULL){ CFRelease(ptr); ptr = NULL;}} while(0) 20 | 21 | 22 | typedef enum _nyx_colorspace_t { 23 | colorspace_unknown = 0, 24 | colorspace_rgb = 1, 25 | colorspace_ycbcr, 26 | colorspace_ycgco, 27 | colorspace_bt709, 28 | colorspace_bt2020, 29 | } colorspace_t; 30 | 31 | 32 | typedef struct _nyx_image_infos_struct { 33 | size_t width; 34 | size_t height; 35 | uint8_t has_alpha; 36 | uint8_t bit_depth; 37 | size_t filesize; 38 | colorspace_t colorspace; 39 | size_t dpi; 40 | } image_infos; 41 | 42 | 43 | void properties_for_file(CFURLRef url, size_t* width, size_t* height, size_t* dpi, size_t* file_size); 44 | 45 | size_t read_file(CFStringRef filepath, uint8_t** buffer); 46 | 47 | const char* colorspace_string(const colorspace_t cs); 48 | -------------------------------------------------------------------------------- /common/tools.m: -------------------------------------------------------------------------------- 1 | // 2 | // tools.m 3 | // qlImageSize 4 | // 5 | // Created by @Nyx0uf on 02/02/12. 6 | // Copyright (c) 2012 Nyx0uf. All rights reserved. 7 | // 8 | 9 | 10 | #import "tools.h" 11 | #import 12 | #import 13 | #import 14 | 15 | 16 | static size_t _get_file_size(CFURLRef url); 17 | 18 | 19 | #pragma mark - Public 20 | void properties_for_file(CFURLRef url, size_t* width, size_t* height, size_t* dpi, size_t* file_size) 21 | { 22 | // Create the image source 23 | *width = 0, *height = 0, *dpi = 0, *file_size = 0; 24 | CGImageSourceRef img_src = CGImageSourceCreateWithURL(url, NULL); 25 | if (NULL == img_src) 26 | return; 27 | 28 | // Copy images properties 29 | CFDictionaryRef img_properties = CGImageSourceCopyPropertiesAtIndex(img_src, 0, NULL); 30 | if (NULL == img_properties) 31 | { 32 | CFRelease(img_src); 33 | return; 34 | } 35 | 36 | // Get image width 37 | CFNumberRef w = CFDictionaryGetValue(img_properties, kCGImagePropertyPixelWidth); 38 | CFNumberGetValue(w, kCFNumberSInt64Type, width); 39 | // Get image height 40 | CFNumberRef h = CFDictionaryGetValue(img_properties, kCGImagePropertyPixelHeight); 41 | CFNumberGetValue(h, kCFNumberSInt64Type, height); 42 | // Get DPI 43 | CFNumberRef d = CFDictionaryGetValue(img_properties, kCGImagePropertyDPIWidth); 44 | if (d != NULL) 45 | CFNumberGetValue(d, kCFNumberSInt64Type, dpi); 46 | CFRelease(img_properties); 47 | CFRelease(img_src); 48 | 49 | // Get the filesize, because it's not always present in the image properties dictionary :/ 50 | *file_size = _get_file_size(url); 51 | } 52 | 53 | size_t read_file(CFStringRef filepath, uint8_t** buffer) 54 | { 55 | // Open the file, get its size and read it 56 | FILE* f = fopen([(__bridge NSString*)filepath UTF8String], "rb"); 57 | if (NULL == f) 58 | return 0; 59 | 60 | fseek(f, 0, SEEK_END); 61 | const size_t file_size = (size_t)ftell(f); 62 | fseek(f, 0, SEEK_SET); 63 | 64 | *buffer = (uint8_t*)malloc(file_size); 65 | if (NULL == (*buffer)) 66 | { 67 | fclose(f); 68 | return 0; 69 | } 70 | const size_t read_size = fread(*buffer, 1, file_size, f); 71 | fclose(f); 72 | if (read_size != file_size) 73 | { 74 | free(*buffer), *buffer = NULL; 75 | return 0; 76 | } 77 | 78 | return file_size; 79 | } 80 | 81 | const char* colorspace_string(const colorspace_t cs) 82 | { 83 | switch (cs) 84 | { 85 | case colorspace_unknown: 86 | return "Unknown"; 87 | case colorspace_rgb: 88 | return "RGB"; 89 | case colorspace_ycbcr: 90 | return "Y'CbCr"; 91 | case colorspace_ycgco: 92 | return "Y'CgCo"; 93 | case colorspace_bt709: 94 | return "BT.709"; 95 | case colorspace_bt2020: 96 | return "BT.2020"; 97 | default: 98 | return "Unknown"; 99 | } 100 | } 101 | 102 | #pragma mark - Private 103 | static size_t _get_file_size(CFURLRef url) 104 | { 105 | UInt8 buf[4096] = {0x00}; 106 | CFURLGetFileSystemRepresentation(url, true, buf, 4096); 107 | struct stat st; 108 | stat((const char*)buf, &st); 109 | return (size_t)st.st_size; 110 | } 111 | -------------------------------------------------------------------------------- /common/webp_decode.h: -------------------------------------------------------------------------------- 1 | // 2 | // webp_decode.h 3 | // qlImageSize 4 | // 5 | // Created by @Nyx0uf on 30/12/14. 6 | // Copyright (c) 2014 Nyx0uf. All rights reserved. 7 | // 8 | 9 | 10 | #import "tools.h" 11 | 12 | 13 | #ifdef NYX_QL_SUPPORT_WEBP_DECODE 14 | CF_RETURNS_RETAINED CGImageRef decode_webp_at_path(CFStringRef filepath, image_infos* infos); 15 | #endif 16 | 17 | #ifdef NYX_MD_SUPPORT_WEBP_DECODE 18 | bool get_webp_informations_for_filepath(CFStringRef filepath, image_infos* infos); 19 | #endif 20 | -------------------------------------------------------------------------------- /common/webp_decode.m: -------------------------------------------------------------------------------- 1 | // 2 | // webp_decode.m 3 | // qlImageSize 4 | // 5 | // Created by @Nyx0uf on 30/12/14. 6 | // Copyright (c) 2014 Nyx0uf. All rights reserved. 7 | // 8 | 9 | 10 | #import "webp_decode.h" 11 | #import "decode.h" 12 | 13 | 14 | #ifdef NYX_QL_SUPPORT_WEBP_DECODE 15 | CF_RETURNS_RETAINED CGImageRef decode_webp_at_path(CFStringRef filepath, image_infos* infos) 16 | { 17 | // Init WebP decoder 18 | WebPDecoderConfig webp_cfg; 19 | if (!WebPInitDecoderConfig(&webp_cfg)) 20 | return NULL; 21 | 22 | // Read file 23 | uint8_t* buffer = NULL; 24 | const size_t file_size = read_file(filepath, &buffer); 25 | if (0 == file_size) 26 | { 27 | free(buffer); 28 | return NULL; 29 | } 30 | 31 | // Get image infos 32 | if (WebPGetFeatures(buffer, file_size, &webp_cfg.input) != VP8_STATUS_OK) 33 | { 34 | free(buffer); 35 | return NULL; 36 | } 37 | 38 | // Decode image, always RGBA 39 | webp_cfg.output.colorspace = webp_cfg.input.has_alpha ? MODE_rgbA : MODE_RGB; 40 | webp_cfg.options.use_threads = 1; 41 | WebPIDecoder* const idec = WebPIDecode(buffer, file_size, &webp_cfg); 42 | if (idec == NULL) 43 | { 44 | free(buffer); 45 | return NULL; 46 | } 47 | else 48 | { 49 | VP8StatusCode status = VP8_STATUS_OK; 50 | size_t done_size = 0; 51 | const size_t incr = 25165824; // 24MB, arbitrary chosen 52 | while (done_size < file_size) 53 | { 54 | size_t next_size = done_size + incr; 55 | if (next_size > file_size) 56 | next_size = file_size; 57 | status = WebPIUpdate(idec, buffer, next_size); 58 | if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) 59 | break; 60 | done_size = next_size; 61 | } 62 | WebPIDelete(idec); 63 | } 64 | free(buffer); 65 | 66 | const size_t width = (size_t)webp_cfg.input.width; 67 | const size_t height = (size_t)webp_cfg.input.height; 68 | if (infos != NULL) 69 | { 70 | infos->width = width; 71 | infos->height = height; 72 | infos->filesize = (size_t)file_size; 73 | } 74 | 75 | // Create CGImage 76 | CGDataProviderRef data_provider = CGDataProviderCreateWithData(NULL, webp_cfg.output.u.RGBA.rgba, webp_cfg.output.u.RGBA.size, NULL); 77 | if (data_provider == NULL) 78 | return NULL; 79 | CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); 80 | CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Big | (webp_cfg.input.has_alpha ? kCGImageAlphaPremultipliedLast : kCGImageAlphaNone); 81 | const size_t components = webp_cfg.input.has_alpha ? 4 : 3; 82 | CGImageRef img_ref = CGImageCreate(width, height, 8, components * 8, components * width, color_space, bitmapInfo, data_provider, NULL, false, kCGRenderingIntentDefault); 83 | 84 | CGColorSpaceRelease(color_space); 85 | CGDataProviderRelease(data_provider); 86 | 87 | return img_ref; 88 | } 89 | #endif /* NYX_QL_SUPPORT_WEBP_DECODE */ 90 | 91 | #ifdef NYX_MD_SUPPORT_WEBP_DECODE 92 | bool get_webp_informations_for_filepath(CFStringRef filepath, image_infos* infos) 93 | { 94 | WebPDecoderConfig webp_cfg; 95 | if (!WebPInitDecoderConfig(&webp_cfg)) 96 | return false; 97 | 98 | // Read file 99 | uint8_t* buffer = NULL; 100 | const size_t size = read_file(filepath, &buffer); 101 | if (0 == size) 102 | { 103 | free(buffer); 104 | return false; 105 | } 106 | 107 | // Get file informations 108 | if (WebPGetFeatures(buffer, size, &webp_cfg.input) != VP8_STATUS_OK) 109 | { 110 | free(buffer); 111 | return false; 112 | } 113 | free(buffer); 114 | 115 | infos->width = (size_t)webp_cfg.input.width; 116 | infos->height = (size_t)webp_cfg.input.height; 117 | infos->has_alpha = (uint8_t)webp_cfg.input.has_alpha; 118 | infos->bit_depth = 8; 119 | infos->colorspace = (webp_cfg.input.format == 2) ? colorspace_rgb : colorspace_ycbcr; // lossy WebP, always YUV 4:2:0 | lossless WebP, always ARGB 120 | 121 | return true; 122 | } 123 | #endif /* NYX_MD_SUPPORT_WEBP_DECODE */ 124 | -------------------------------------------------------------------------------- /deps/libbpg/libbpg.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nyx0uf/qlImageSize/41082059f6b0d57609a60aa27b7127552e17708f/deps/libbpg/libbpg.a -------------------------------------------------------------------------------- /deps/libbpg/libbpg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BPG decoder 3 | * 4 | * Copyright (c) 2014 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef _LIBBPG_H 25 | #define _LIBBPG_H 26 | 27 | #include 28 | 29 | typedef struct BPGDecoderContext BPGDecoderContext; 30 | 31 | typedef enum { 32 | BPG_FORMAT_GRAY, 33 | BPG_FORMAT_420, /* chroma at offset (0.5, 0.5) (JPEG) */ 34 | BPG_FORMAT_422, /* chroma at offset (0.5, 0) (JPEG) */ 35 | BPG_FORMAT_444, 36 | BPG_FORMAT_420_VIDEO, /* chroma at offset (0, 0.5) (MPEG2) */ 37 | BPG_FORMAT_422_VIDEO, /* chroma at offset (0, 0) (MPEG2) */ 38 | } BPGImageFormatEnum; 39 | 40 | typedef enum { 41 | BPG_CS_YCbCr, 42 | BPG_CS_RGB, 43 | BPG_CS_YCgCo, 44 | BPG_CS_YCbCr_BT709, 45 | BPG_CS_YCbCr_BT2020, 46 | 47 | BPG_CS_COUNT, 48 | } BPGColorSpaceEnum; 49 | 50 | typedef struct { 51 | uint32_t width; 52 | uint32_t height; 53 | uint8_t format; /* see BPGImageFormatEnum */ 54 | uint8_t has_alpha; /* TRUE if an alpha plane is present */ 55 | uint8_t color_space; /* see BPGColorSpaceEnum */ 56 | uint8_t bit_depth; 57 | uint8_t premultiplied_alpha; /* TRUE if the color is alpha premultiplied */ 58 | uint8_t has_w_plane; /* TRUE if a W plane is present (for CMYK encoding) */ 59 | uint8_t limited_range; /* TRUE if limited range for the color */ 60 | uint8_t has_animation; /* TRUE if the image contains animations */ 61 | uint16_t loop_count; /* animations: number of loop, 0 = infinity */ 62 | } BPGImageInfo; 63 | 64 | typedef enum { 65 | BPG_EXTENSION_TAG_EXIF = 1, 66 | BPG_EXTENSION_TAG_ICCP = 2, 67 | BPG_EXTENSION_TAG_XMP = 3, 68 | BPG_EXTENSION_TAG_THUMBNAIL = 4, 69 | BPG_EXTENSION_TAG_ANIM_CONTROL = 5, 70 | } BPGExtensionTagEnum; 71 | 72 | typedef struct BPGExtensionData { 73 | BPGExtensionTagEnum tag; 74 | uint32_t buf_len; 75 | uint8_t *buf; 76 | struct BPGExtensionData *next; 77 | } BPGExtensionData; 78 | 79 | typedef enum { 80 | BPG_OUTPUT_FORMAT_RGB24, 81 | BPG_OUTPUT_FORMAT_RGBA32, /* not premultiplied alpha */ 82 | BPG_OUTPUT_FORMAT_RGB48, 83 | BPG_OUTPUT_FORMAT_RGBA64, /* not premultiplied alpha */ 84 | BPG_OUTPUT_FORMAT_CMYK32, 85 | BPG_OUTPUT_FORMAT_CMYK64, 86 | } BPGDecoderOutputFormat; 87 | 88 | #define BPG_DECODER_INFO_BUF_SIZE 16 89 | 90 | BPGDecoderContext *bpg_decoder_open(void); 91 | 92 | /* If enable is true, extension data are kept during the image 93 | decoding and can be accessed after bpg_decoder_decode() with 94 | bpg_decoder_get_extension(). By default, the extension data are 95 | discarded. */ 96 | void bpg_decoder_keep_extension_data(BPGDecoderContext *s, int enable); 97 | 98 | /* return 0 if 0K, < 0 if error */ 99 | int bpg_decoder_decode(BPGDecoderContext *s, const uint8_t *buf, int buf_len); 100 | 101 | /* Return the first element of the extension data list */ 102 | BPGExtensionData *bpg_decoder_get_extension_data(BPGDecoderContext *s); 103 | 104 | /* return 0 if 0K, < 0 if error */ 105 | int bpg_decoder_get_info(BPGDecoderContext *s, BPGImageInfo *p); 106 | 107 | /* return 0 if 0K, < 0 if error */ 108 | int bpg_decoder_start(BPGDecoderContext *s, BPGDecoderOutputFormat out_fmt); 109 | 110 | /* return the frame delay for animations as a fraction (*pnum) / (*pden) 111 | in seconds. In case there is no animation, 0 / 1 is returned. */ 112 | void bpg_decoder_get_frame_duration(BPGDecoderContext *s, int *pnum, int *pden); 113 | 114 | /* return 0 if 0K, < 0 if error */ 115 | int bpg_decoder_get_line(BPGDecoderContext *s, void *buf); 116 | 117 | void bpg_decoder_close(BPGDecoderContext *s); 118 | 119 | /* only useful for low level access to the image data */ 120 | uint8_t *bpg_decoder_get_data(BPGDecoderContext *s, int *pline_size, int plane); 121 | 122 | /* Get information from the start of the image data in 'buf' (at least 123 | min(BPG_DECODER_INFO_BUF_SIZE, file_size) bytes must be given). 124 | 125 | If pfirst_md != NULL, the extension data are also parsed and the 126 | first element of the list is returned in *pfirst_md. The list must 127 | be freed with bpg_decoder_free_extension_data(). 128 | 129 | BPGImageInfo.loop_count is only set if extension data are parsed. 130 | 131 | Return 0 if OK, < 0 if unrecognized data. */ 132 | int bpg_decoder_get_info_from_buf(BPGImageInfo *p, 133 | BPGExtensionData **pfirst_md, 134 | const uint8_t *buf, int buf_len); 135 | /* Free the extension data returned by bpg_decoder_get_info_from_buf() */ 136 | void bpg_decoder_free_extension_data(BPGExtensionData *first_md); 137 | 138 | #endif /* _LIBBPG_H */ 139 | -------------------------------------------------------------------------------- /deps/libwebp/decode.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Main decoding functions for WebP images. 11 | // 12 | // Author: Skal (pascal.massimino@gmail.com) 13 | 14 | #ifndef WEBP_WEBP_DECODE_H_ 15 | #define WEBP_WEBP_DECODE_H_ 16 | 17 | #include "./types.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #define WEBP_DECODER_ABI_VERSION 0x0208 // MAJOR(8b) + MINOR(8b) 24 | 25 | // Note: forward declaring enumerations is not allowed in (strict) C and C++, 26 | // the types are left here for reference. 27 | // typedef enum VP8StatusCode VP8StatusCode; 28 | // typedef enum WEBP_CSP_MODE WEBP_CSP_MODE; 29 | typedef struct WebPRGBABuffer WebPRGBABuffer; 30 | typedef struct WebPYUVABuffer WebPYUVABuffer; 31 | typedef struct WebPDecBuffer WebPDecBuffer; 32 | typedef struct WebPIDecoder WebPIDecoder; 33 | typedef struct WebPBitstreamFeatures WebPBitstreamFeatures; 34 | typedef struct WebPDecoderOptions WebPDecoderOptions; 35 | typedef struct WebPDecoderConfig WebPDecoderConfig; 36 | 37 | // Return the decoder's version number, packed in hexadecimal using 8bits for 38 | // each of major/minor/revision. E.g: v2.5.7 is 0x020507. 39 | WEBP_EXTERN int WebPGetDecoderVersion(void); 40 | 41 | // Retrieve basic header information: width, height. 42 | // This function will also validate the header, returning true on success, 43 | // false otherwise. '*width' and '*height' are only valid on successful return. 44 | // Pointers 'width' and 'height' can be passed NULL if deemed irrelevant. 45 | WEBP_EXTERN int WebPGetInfo(const uint8_t* data, size_t data_size, 46 | int* width, int* height); 47 | 48 | // Decodes WebP images pointed to by 'data' and returns RGBA samples, along 49 | // with the dimensions in *width and *height. The ordering of samples in 50 | // memory is R, G, B, A, R, G, B, A... in scan order (endian-independent). 51 | // The returned pointer should be deleted calling WebPFree(). 52 | // Returns NULL in case of error. 53 | WEBP_EXTERN uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, 54 | int* width, int* height); 55 | 56 | // Same as WebPDecodeRGBA, but returning A, R, G, B, A, R, G, B... ordered data. 57 | WEBP_EXTERN uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size, 58 | int* width, int* height); 59 | 60 | // Same as WebPDecodeRGBA, but returning B, G, R, A, B, G, R, A... ordered data. 61 | WEBP_EXTERN uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, 62 | int* width, int* height); 63 | 64 | // Same as WebPDecodeRGBA, but returning R, G, B, R, G, B... ordered data. 65 | // If the bitstream contains transparency, it is ignored. 66 | WEBP_EXTERN uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, 67 | int* width, int* height); 68 | 69 | // Same as WebPDecodeRGB, but returning B, G, R, B, G, R... ordered data. 70 | WEBP_EXTERN uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, 71 | int* width, int* height); 72 | 73 | 74 | // Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer 75 | // returned is the Y samples buffer. Upon return, *u and *v will point to 76 | // the U and V chroma data. These U and V buffers need NOT be passed to 77 | // WebPFree(), unlike the returned Y luma one. The dimension of the U and V 78 | // planes are both (*width + 1) / 2 and (*height + 1)/ 2. 79 | // Upon return, the Y buffer has a stride returned as '*stride', while U and V 80 | // have a common stride returned as '*uv_stride'. 81 | // Return NULL in case of error. 82 | // (*) Also named Y'CbCr. See: http://en.wikipedia.org/wiki/YCbCr 83 | WEBP_EXTERN uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, 84 | int* width, int* height, 85 | uint8_t** u, uint8_t** v, 86 | int* stride, int* uv_stride); 87 | 88 | // Releases memory returned by the WebPDecode*() functions above. 89 | WEBP_EXTERN void WebPFree(void* ptr); 90 | 91 | // These five functions are variants of the above ones, that decode the image 92 | // directly into a pre-allocated buffer 'output_buffer'. The maximum storage 93 | // available in this buffer is indicated by 'output_buffer_size'. If this 94 | // storage is not sufficient (or an error occurred), NULL is returned. 95 | // Otherwise, output_buffer is returned, for convenience. 96 | // The parameter 'output_stride' specifies the distance (in bytes) 97 | // between scanlines. Hence, output_buffer_size is expected to be at least 98 | // output_stride x picture-height. 99 | WEBP_EXTERN uint8_t* WebPDecodeRGBAInto( 100 | const uint8_t* data, size_t data_size, 101 | uint8_t* output_buffer, size_t output_buffer_size, int output_stride); 102 | WEBP_EXTERN uint8_t* WebPDecodeARGBInto( 103 | const uint8_t* data, size_t data_size, 104 | uint8_t* output_buffer, size_t output_buffer_size, int output_stride); 105 | WEBP_EXTERN uint8_t* WebPDecodeBGRAInto( 106 | const uint8_t* data, size_t data_size, 107 | uint8_t* output_buffer, size_t output_buffer_size, int output_stride); 108 | 109 | // RGB and BGR variants. Here too the transparency information, if present, 110 | // will be dropped and ignored. 111 | WEBP_EXTERN uint8_t* WebPDecodeRGBInto( 112 | const uint8_t* data, size_t data_size, 113 | uint8_t* output_buffer, size_t output_buffer_size, int output_stride); 114 | WEBP_EXTERN uint8_t* WebPDecodeBGRInto( 115 | const uint8_t* data, size_t data_size, 116 | uint8_t* output_buffer, size_t output_buffer_size, int output_stride); 117 | 118 | // WebPDecodeYUVInto() is a variant of WebPDecodeYUV() that operates directly 119 | // into pre-allocated luma/chroma plane buffers. This function requires the 120 | // strides to be passed: one for the luma plane and one for each of the 121 | // chroma ones. The size of each plane buffer is passed as 'luma_size', 122 | // 'u_size' and 'v_size' respectively. 123 | // Pointer to the luma plane ('*luma') is returned or NULL if an error occurred 124 | // during decoding (or because some buffers were found to be too small). 125 | WEBP_EXTERN uint8_t* WebPDecodeYUVInto( 126 | const uint8_t* data, size_t data_size, 127 | uint8_t* luma, size_t luma_size, int luma_stride, 128 | uint8_t* u, size_t u_size, int u_stride, 129 | uint8_t* v, size_t v_size, int v_stride); 130 | 131 | //------------------------------------------------------------------------------ 132 | // Output colorspaces and buffer 133 | 134 | // Colorspaces 135 | // Note: the naming describes the byte-ordering of packed samples in memory. 136 | // For instance, MODE_BGRA relates to samples ordered as B,G,R,A,B,G,R,A,... 137 | // Non-capital names (e.g.:MODE_Argb) relates to pre-multiplied RGB channels. 138 | // RGBA-4444 and RGB-565 colorspaces are represented by following byte-order: 139 | // RGBA-4444: [r3 r2 r1 r0 g3 g2 g1 g0], [b3 b2 b1 b0 a3 a2 a1 a0], ... 140 | // RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ... 141 | // In the case WEBP_SWAP_16BITS_CSP is defined, the bytes are swapped for 142 | // these two modes: 143 | // RGBA-4444: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], ... 144 | // RGB-565: [g2 g1 g0 b4 b3 b2 b1 b0], [r4 r3 r2 r1 r0 g5 g4 g3], ... 145 | 146 | typedef enum WEBP_CSP_MODE { 147 | MODE_RGB = 0, MODE_RGBA = 1, 148 | MODE_BGR = 2, MODE_BGRA = 3, 149 | MODE_ARGB = 4, MODE_RGBA_4444 = 5, 150 | MODE_RGB_565 = 6, 151 | // RGB-premultiplied transparent modes (alpha value is preserved) 152 | MODE_rgbA = 7, 153 | MODE_bgrA = 8, 154 | MODE_Argb = 9, 155 | MODE_rgbA_4444 = 10, 156 | // YUV modes must come after RGB ones. 157 | MODE_YUV = 11, MODE_YUVA = 12, // yuv 4:2:0 158 | MODE_LAST = 13 159 | } WEBP_CSP_MODE; 160 | 161 | // Some useful macros: 162 | static WEBP_INLINE int WebPIsPremultipliedMode(WEBP_CSP_MODE mode) { 163 | return (mode == MODE_rgbA || mode == MODE_bgrA || mode == MODE_Argb || 164 | mode == MODE_rgbA_4444); 165 | } 166 | 167 | static WEBP_INLINE int WebPIsAlphaMode(WEBP_CSP_MODE mode) { 168 | return (mode == MODE_RGBA || mode == MODE_BGRA || mode == MODE_ARGB || 169 | mode == MODE_RGBA_4444 || mode == MODE_YUVA || 170 | WebPIsPremultipliedMode(mode)); 171 | } 172 | 173 | static WEBP_INLINE int WebPIsRGBMode(WEBP_CSP_MODE mode) { 174 | return (mode < MODE_YUV); 175 | } 176 | 177 | //------------------------------------------------------------------------------ 178 | // WebPDecBuffer: Generic structure for describing the output sample buffer. 179 | 180 | struct WebPRGBABuffer { // view as RGBA 181 | uint8_t* rgba; // pointer to RGBA samples 182 | int stride; // stride in bytes from one scanline to the next. 183 | size_t size; // total size of the *rgba buffer. 184 | }; 185 | 186 | struct WebPYUVABuffer { // view as YUVA 187 | uint8_t* y, *u, *v, *a; // pointer to luma, chroma U/V, alpha samples 188 | int y_stride; // luma stride 189 | int u_stride, v_stride; // chroma strides 190 | int a_stride; // alpha stride 191 | size_t y_size; // luma plane size 192 | size_t u_size, v_size; // chroma planes size 193 | size_t a_size; // alpha-plane size 194 | }; 195 | 196 | // Output buffer 197 | struct WebPDecBuffer { 198 | WEBP_CSP_MODE colorspace; // Colorspace. 199 | int width, height; // Dimensions. 200 | int is_external_memory; // If non-zero, 'internal_memory' pointer is not 201 | // used. If value is '2' or more, the external 202 | // memory is considered 'slow' and multiple 203 | // read/write will be avoided. 204 | union { 205 | WebPRGBABuffer RGBA; 206 | WebPYUVABuffer YUVA; 207 | } u; // Nameless union of buffer parameters. 208 | uint32_t pad[4]; // padding for later use 209 | 210 | uint8_t* private_memory; // Internally allocated memory (only when 211 | // is_external_memory is 0). Should not be used 212 | // externally, but accessed via the buffer union. 213 | }; 214 | 215 | // Internal, version-checked, entry point 216 | WEBP_EXTERN int WebPInitDecBufferInternal(WebPDecBuffer*, int); 217 | 218 | // Initialize the structure as empty. Must be called before any other use. 219 | // Returns false in case of version mismatch 220 | static WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) { 221 | return WebPInitDecBufferInternal(buffer, WEBP_DECODER_ABI_VERSION); 222 | } 223 | 224 | // Free any memory associated with the buffer. Must always be called last. 225 | // Note: doesn't free the 'buffer' structure itself. 226 | WEBP_EXTERN void WebPFreeDecBuffer(WebPDecBuffer* buffer); 227 | 228 | //------------------------------------------------------------------------------ 229 | // Enumeration of the status codes 230 | 231 | typedef enum VP8StatusCode { 232 | VP8_STATUS_OK = 0, 233 | VP8_STATUS_OUT_OF_MEMORY, 234 | VP8_STATUS_INVALID_PARAM, 235 | VP8_STATUS_BITSTREAM_ERROR, 236 | VP8_STATUS_UNSUPPORTED_FEATURE, 237 | VP8_STATUS_SUSPENDED, 238 | VP8_STATUS_USER_ABORT, 239 | VP8_STATUS_NOT_ENOUGH_DATA 240 | } VP8StatusCode; 241 | 242 | //------------------------------------------------------------------------------ 243 | // Incremental decoding 244 | // 245 | // This API allows streamlined decoding of partial data. 246 | // Picture can be incrementally decoded as data become available thanks to the 247 | // WebPIDecoder object. This object can be left in a SUSPENDED state if the 248 | // picture is only partially decoded, pending additional input. 249 | // Code example: 250 | // 251 | // WebPInitDecBuffer(&output_buffer); 252 | // output_buffer.colorspace = mode; 253 | // ... 254 | // WebPIDecoder* idec = WebPINewDecoder(&output_buffer); 255 | // while (additional_data_is_available) { 256 | // // ... (get additional data in some new_data[] buffer) 257 | // status = WebPIAppend(idec, new_data, new_data_size); 258 | // if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) { 259 | // break; // an error occurred. 260 | // } 261 | // 262 | // // The above call decodes the current available buffer. 263 | // // Part of the image can now be refreshed by calling 264 | // // WebPIDecGetRGB()/WebPIDecGetYUVA() etc. 265 | // } 266 | // WebPIDelete(idec); 267 | 268 | // Creates a new incremental decoder with the supplied buffer parameter. 269 | // This output_buffer can be passed NULL, in which case a default output buffer 270 | // is used (with MODE_RGB). Otherwise, an internal reference to 'output_buffer' 271 | // is kept, which means that the lifespan of 'output_buffer' must be larger than 272 | // that of the returned WebPIDecoder object. 273 | // The supplied 'output_buffer' content MUST NOT be changed between calls to 274 | // WebPIAppend() or WebPIUpdate() unless 'output_buffer.is_external_memory' is 275 | // not set to 0. In such a case, it is allowed to modify the pointers, size and 276 | // stride of output_buffer.u.RGBA or output_buffer.u.YUVA, provided they remain 277 | // within valid bounds. 278 | // All other fields of WebPDecBuffer MUST remain constant between calls. 279 | // Returns NULL if the allocation failed. 280 | WEBP_EXTERN WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer); 281 | 282 | // This function allocates and initializes an incremental-decoder object, which 283 | // will output the RGB/A samples specified by 'csp' into a preallocated 284 | // buffer 'output_buffer'. The size of this buffer is at least 285 | // 'output_buffer_size' and the stride (distance in bytes between two scanlines) 286 | // is specified by 'output_stride'. 287 | // Additionally, output_buffer can be passed NULL in which case the output 288 | // buffer will be allocated automatically when the decoding starts. The 289 | // colorspace 'csp' is taken into account for allocating this buffer. All other 290 | // parameters are ignored. 291 | // Returns NULL if the allocation failed, or if some parameters are invalid. 292 | WEBP_EXTERN WebPIDecoder* WebPINewRGB( 293 | WEBP_CSP_MODE csp, 294 | uint8_t* output_buffer, size_t output_buffer_size, int output_stride); 295 | 296 | // This function allocates and initializes an incremental-decoder object, which 297 | // will output the raw luma/chroma samples into a preallocated planes if 298 | // supplied. The luma plane is specified by its pointer 'luma', its size 299 | // 'luma_size' and its stride 'luma_stride'. Similarly, the chroma-u plane 300 | // is specified by the 'u', 'u_size' and 'u_stride' parameters, and the chroma-v 301 | // plane by 'v' and 'v_size'. And same for the alpha-plane. The 'a' pointer 302 | // can be pass NULL in case one is not interested in the transparency plane. 303 | // Conversely, 'luma' can be passed NULL if no preallocated planes are supplied. 304 | // In this case, the output buffer will be automatically allocated (using 305 | // MODE_YUVA) when decoding starts. All parameters are then ignored. 306 | // Returns NULL if the allocation failed or if a parameter is invalid. 307 | WEBP_EXTERN WebPIDecoder* WebPINewYUVA( 308 | uint8_t* luma, size_t luma_size, int luma_stride, 309 | uint8_t* u, size_t u_size, int u_stride, 310 | uint8_t* v, size_t v_size, int v_stride, 311 | uint8_t* a, size_t a_size, int a_stride); 312 | 313 | // Deprecated version of the above, without the alpha plane. 314 | // Kept for backward compatibility. 315 | WEBP_EXTERN WebPIDecoder* WebPINewYUV( 316 | uint8_t* luma, size_t luma_size, int luma_stride, 317 | uint8_t* u, size_t u_size, int u_stride, 318 | uint8_t* v, size_t v_size, int v_stride); 319 | 320 | // Deletes the WebPIDecoder object and associated memory. Must always be called 321 | // if WebPINewDecoder, WebPINewRGB or WebPINewYUV succeeded. 322 | WEBP_EXTERN void WebPIDelete(WebPIDecoder* idec); 323 | 324 | // Copies and decodes the next available data. Returns VP8_STATUS_OK when 325 | // the image is successfully decoded. Returns VP8_STATUS_SUSPENDED when more 326 | // data is expected. Returns error in other cases. 327 | WEBP_EXTERN VP8StatusCode WebPIAppend( 328 | WebPIDecoder* idec, const uint8_t* data, size_t data_size); 329 | 330 | // A variant of the above function to be used when data buffer contains 331 | // partial data from the beginning. In this case data buffer is not copied 332 | // to the internal memory. 333 | // Note that the value of the 'data' pointer can change between calls to 334 | // WebPIUpdate, for instance when the data buffer is resized to fit larger data. 335 | WEBP_EXTERN VP8StatusCode WebPIUpdate( 336 | WebPIDecoder* idec, const uint8_t* data, size_t data_size); 337 | 338 | // Returns the RGB/A image decoded so far. Returns NULL if output params 339 | // are not initialized yet. The RGB/A output type corresponds to the colorspace 340 | // specified during call to WebPINewDecoder() or WebPINewRGB(). 341 | // *last_y is the index of last decoded row in raster scan order. Some pointers 342 | // (*last_y, *width etc.) can be NULL if corresponding information is not 343 | // needed. The values in these pointers are only valid on successful (non-NULL) 344 | // return. 345 | WEBP_EXTERN uint8_t* WebPIDecGetRGB( 346 | const WebPIDecoder* idec, int* last_y, 347 | int* width, int* height, int* stride); 348 | 349 | // Same as above function to get a YUVA image. Returns pointer to the luma 350 | // plane or NULL in case of error. If there is no alpha information 351 | // the alpha pointer '*a' will be returned NULL. 352 | WEBP_EXTERN uint8_t* WebPIDecGetYUVA( 353 | const WebPIDecoder* idec, int* last_y, 354 | uint8_t** u, uint8_t** v, uint8_t** a, 355 | int* width, int* height, int* stride, int* uv_stride, int* a_stride); 356 | 357 | // Deprecated alpha-less version of WebPIDecGetYUVA(): it will ignore the 358 | // alpha information (if present). Kept for backward compatibility. 359 | static WEBP_INLINE uint8_t* WebPIDecGetYUV( 360 | const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v, 361 | int* width, int* height, int* stride, int* uv_stride) { 362 | return WebPIDecGetYUVA(idec, last_y, u, v, NULL, width, height, 363 | stride, uv_stride, NULL); 364 | } 365 | 366 | // Generic call to retrieve information about the displayable area. 367 | // If non NULL, the left/right/width/height pointers are filled with the visible 368 | // rectangular area so far. 369 | // Returns NULL in case the incremental decoder object is in an invalid state. 370 | // Otherwise returns the pointer to the internal representation. This structure 371 | // is read-only, tied to WebPIDecoder's lifespan and should not be modified. 372 | WEBP_EXTERN const WebPDecBuffer* WebPIDecodedArea( 373 | const WebPIDecoder* idec, int* left, int* top, int* width, int* height); 374 | 375 | //------------------------------------------------------------------------------ 376 | // Advanced decoding parametrization 377 | // 378 | // Code sample for using the advanced decoding API 379 | /* 380 | // A) Init a configuration object 381 | WebPDecoderConfig config; 382 | CHECK(WebPInitDecoderConfig(&config)); 383 | 384 | // B) optional: retrieve the bitstream's features. 385 | CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK); 386 | 387 | // C) Adjust 'config', if needed 388 | config.no_fancy_upsampling = 1; 389 | config.output.colorspace = MODE_BGRA; 390 | // etc. 391 | 392 | // Note that you can also make config.output point to an externally 393 | // supplied memory buffer, provided it's big enough to store the decoded 394 | // picture. Otherwise, config.output will just be used to allocate memory 395 | // and store the decoded picture. 396 | 397 | // D) Decode! 398 | CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK); 399 | 400 | // E) Decoded image is now in config.output (and config.output.u.RGBA) 401 | 402 | // F) Reclaim memory allocated in config's object. It's safe to call 403 | // this function even if the memory is external and wasn't allocated 404 | // by WebPDecode(). 405 | WebPFreeDecBuffer(&config.output); 406 | */ 407 | 408 | // Features gathered from the bitstream 409 | struct WebPBitstreamFeatures { 410 | int width; // Width in pixels, as read from the bitstream. 411 | int height; // Height in pixels, as read from the bitstream. 412 | int has_alpha; // True if the bitstream contains an alpha channel. 413 | int has_animation; // True if the bitstream is an animation. 414 | int format; // 0 = undefined (/mixed), 1 = lossy, 2 = lossless 415 | 416 | uint32_t pad[5]; // padding for later use 417 | }; 418 | 419 | // Internal, version-checked, entry point 420 | WEBP_EXTERN VP8StatusCode WebPGetFeaturesInternal( 421 | const uint8_t*, size_t, WebPBitstreamFeatures*, int); 422 | 423 | // Retrieve features from the bitstream. The *features structure is filled 424 | // with information gathered from the bitstream. 425 | // Returns VP8_STATUS_OK when the features are successfully retrieved. Returns 426 | // VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the 427 | // features from headers. Returns error in other cases. 428 | static WEBP_INLINE VP8StatusCode WebPGetFeatures( 429 | const uint8_t* data, size_t data_size, 430 | WebPBitstreamFeatures* features) { 431 | return WebPGetFeaturesInternal(data, data_size, features, 432 | WEBP_DECODER_ABI_VERSION); 433 | } 434 | 435 | // Decoding options 436 | struct WebPDecoderOptions { 437 | int bypass_filtering; // if true, skip the in-loop filtering 438 | int no_fancy_upsampling; // if true, use faster pointwise upsampler 439 | int use_cropping; // if true, cropping is applied _first_ 440 | int crop_left, crop_top; // top-left position for cropping. 441 | // Will be snapped to even values. 442 | int crop_width, crop_height; // dimension of the cropping area 443 | int use_scaling; // if true, scaling is applied _afterward_ 444 | int scaled_width, scaled_height; // final resolution 445 | int use_threads; // if true, use multi-threaded decoding 446 | int dithering_strength; // dithering strength (0=Off, 100=full) 447 | int flip; // flip output vertically 448 | int alpha_dithering_strength; // alpha dithering strength in [0..100] 449 | 450 | uint32_t pad[5]; // padding for later use 451 | }; 452 | 453 | // Main object storing the configuration for advanced decoding. 454 | struct WebPDecoderConfig { 455 | WebPBitstreamFeatures input; // Immutable bitstream features (optional) 456 | WebPDecBuffer output; // Output buffer (can point to external mem) 457 | WebPDecoderOptions options; // Decoding options 458 | }; 459 | 460 | // Internal, version-checked, entry point 461 | WEBP_EXTERN int WebPInitDecoderConfigInternal(WebPDecoderConfig*, int); 462 | 463 | // Initialize the configuration as empty. This function must always be 464 | // called first, unless WebPGetFeatures() is to be called. 465 | // Returns false in case of mismatched version. 466 | static WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) { 467 | return WebPInitDecoderConfigInternal(config, WEBP_DECODER_ABI_VERSION); 468 | } 469 | 470 | // Instantiate a new incremental decoder object with the requested 471 | // configuration. The bitstream can be passed using 'data' and 'data_size' 472 | // parameter, in which case the features will be parsed and stored into 473 | // config->input. Otherwise, 'data' can be NULL and no parsing will occur. 474 | // Note that 'config' can be NULL too, in which case a default configuration 475 | // is used. If 'config' is not NULL, it must outlive the WebPIDecoder object 476 | // as some references to its fields will be used. No internal copy of 'config' 477 | // is made. 478 | // The return WebPIDecoder object must always be deleted calling WebPIDelete(). 479 | // Returns NULL in case of error (and config->status will then reflect 480 | // the error condition, if available). 481 | WEBP_EXTERN WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, 482 | WebPDecoderConfig* config); 483 | 484 | // Non-incremental version. This version decodes the full data at once, taking 485 | // 'config' into account. Returns decoding status (which should be VP8_STATUS_OK 486 | // if the decoding was successful). Note that 'config' cannot be NULL. 487 | WEBP_EXTERN VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, 488 | WebPDecoderConfig* config); 489 | 490 | #ifdef __cplusplus 491 | } // extern "C" 492 | #endif 493 | 494 | #endif // WEBP_WEBP_DECODE_H_ 495 | -------------------------------------------------------------------------------- /deps/libwebp/demux.h: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Demux API. 11 | // Enables extraction of image and extended format data from WebP files. 12 | 13 | // Code Example: Demuxing WebP data to extract all the frames, ICC profile 14 | // and EXIF/XMP metadata. 15 | /* 16 | WebPDemuxer* demux = WebPDemux(&webp_data); 17 | 18 | uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH); 19 | uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT); 20 | // ... (Get information about the features present in the WebP file). 21 | uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS); 22 | 23 | // ... (Iterate over all frames). 24 | WebPIterator iter; 25 | if (WebPDemuxGetFrame(demux, 1, &iter)) { 26 | do { 27 | // ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(), 28 | // ... and get other frame properties like width, height, offsets etc. 29 | // ... see 'struct WebPIterator' below for more info). 30 | } while (WebPDemuxNextFrame(&iter)); 31 | WebPDemuxReleaseIterator(&iter); 32 | } 33 | 34 | // ... (Extract metadata). 35 | WebPChunkIterator chunk_iter; 36 | if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter); 37 | // ... (Consume the ICC profile in 'chunk_iter.chunk'). 38 | WebPDemuxReleaseChunkIterator(&chunk_iter); 39 | if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter); 40 | // ... (Consume the EXIF metadata in 'chunk_iter.chunk'). 41 | WebPDemuxReleaseChunkIterator(&chunk_iter); 42 | if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter); 43 | // ... (Consume the XMP metadata in 'chunk_iter.chunk'). 44 | WebPDemuxReleaseChunkIterator(&chunk_iter); 45 | WebPDemuxDelete(demux); 46 | */ 47 | 48 | #ifndef WEBP_WEBP_DEMUX_H_ 49 | #define WEBP_WEBP_DEMUX_H_ 50 | 51 | #include "./decode.h" // for WEBP_CSP_MODE 52 | #include "./mux_types.h" 53 | 54 | #ifdef __cplusplus 55 | extern "C" { 56 | #endif 57 | 58 | #define WEBP_DEMUX_ABI_VERSION 0x0107 // MAJOR(8b) + MINOR(8b) 59 | 60 | // Note: forward declaring enumerations is not allowed in (strict) C and C++, 61 | // the types are left here for reference. 62 | // typedef enum WebPDemuxState WebPDemuxState; 63 | // typedef enum WebPFormatFeature WebPFormatFeature; 64 | typedef struct WebPDemuxer WebPDemuxer; 65 | typedef struct WebPIterator WebPIterator; 66 | typedef struct WebPChunkIterator WebPChunkIterator; 67 | typedef struct WebPAnimInfo WebPAnimInfo; 68 | typedef struct WebPAnimDecoderOptions WebPAnimDecoderOptions; 69 | 70 | //------------------------------------------------------------------------------ 71 | 72 | // Returns the version number of the demux library, packed in hexadecimal using 73 | // 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. 74 | WEBP_EXTERN int WebPGetDemuxVersion(void); 75 | 76 | //------------------------------------------------------------------------------ 77 | // Life of a Demux object 78 | 79 | typedef enum WebPDemuxState { 80 | WEBP_DEMUX_PARSE_ERROR = -1, // An error occurred while parsing. 81 | WEBP_DEMUX_PARSING_HEADER = 0, // Not enough data to parse full header. 82 | WEBP_DEMUX_PARSED_HEADER = 1, // Header parsing complete, 83 | // data may be available. 84 | WEBP_DEMUX_DONE = 2 // Entire file has been parsed. 85 | } WebPDemuxState; 86 | 87 | // Internal, version-checked, entry point 88 | WEBP_EXTERN WebPDemuxer* WebPDemuxInternal( 89 | const WebPData*, int, WebPDemuxState*, int); 90 | 91 | // Parses the full WebP file given by 'data'. For single images the WebP file 92 | // header alone or the file header and the chunk header may be absent. 93 | // Returns a WebPDemuxer object on successful parse, NULL otherwise. 94 | static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { 95 | return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION); 96 | } 97 | 98 | // Parses the possibly incomplete WebP file given by 'data'. 99 | // If 'state' is non-NULL it will be set to indicate the status of the demuxer. 100 | // Returns NULL in case of error or if there isn't enough data to start parsing; 101 | // and a WebPDemuxer object on successful parse. 102 | // Note that WebPDemuxer keeps internal pointers to 'data' memory segment. 103 | // If this data is volatile, the demuxer object should be deleted (by calling 104 | // WebPDemuxDelete()) and WebPDemuxPartial() called again on the new data. 105 | // This is usually an inexpensive operation. 106 | static WEBP_INLINE WebPDemuxer* WebPDemuxPartial( 107 | const WebPData* data, WebPDemuxState* state) { 108 | return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION); 109 | } 110 | 111 | // Frees memory associated with 'dmux'. 112 | WEBP_EXTERN void WebPDemuxDelete(WebPDemuxer* dmux); 113 | 114 | //------------------------------------------------------------------------------ 115 | // Data/information extraction. 116 | 117 | typedef enum WebPFormatFeature { 118 | WEBP_FF_FORMAT_FLAGS, // bit-wise combination of WebPFeatureFlags 119 | // corresponding to the 'VP8X' chunk (if present). 120 | WEBP_FF_CANVAS_WIDTH, 121 | WEBP_FF_CANVAS_HEIGHT, 122 | WEBP_FF_LOOP_COUNT, // only relevant for animated file 123 | WEBP_FF_BACKGROUND_COLOR, // idem. 124 | WEBP_FF_FRAME_COUNT // Number of frames present in the demux object. 125 | // In case of a partial demux, this is the number 126 | // of frames seen so far, with the last frame 127 | // possibly being partial. 128 | } WebPFormatFeature; 129 | 130 | // Get the 'feature' value from the 'dmux'. 131 | // NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial() 132 | // returned a state > WEBP_DEMUX_PARSING_HEADER. 133 | // If 'feature' is WEBP_FF_FORMAT_FLAGS, the returned value is a bit-wise 134 | // combination of WebPFeatureFlags values. 135 | // If 'feature' is WEBP_FF_LOOP_COUNT, WEBP_FF_BACKGROUND_COLOR, the returned 136 | // value is only meaningful if the bitstream is animated. 137 | WEBP_EXTERN uint32_t WebPDemuxGetI( 138 | const WebPDemuxer* dmux, WebPFormatFeature feature); 139 | 140 | //------------------------------------------------------------------------------ 141 | // Frame iteration. 142 | 143 | struct WebPIterator { 144 | int frame_num; 145 | int num_frames; // equivalent to WEBP_FF_FRAME_COUNT. 146 | int x_offset, y_offset; // offset relative to the canvas. 147 | int width, height; // dimensions of this frame. 148 | int duration; // display duration in milliseconds. 149 | WebPMuxAnimDispose dispose_method; // dispose method for the frame. 150 | int complete; // true if 'fragment' contains a full frame. partial images 151 | // may still be decoded with the WebP incremental decoder. 152 | WebPData fragment; // The frame given by 'frame_num'. Note for historical 153 | // reasons this is called a fragment. 154 | int has_alpha; // True if the frame contains transparency. 155 | WebPMuxAnimBlend blend_method; // Blend operation for the frame. 156 | 157 | uint32_t pad[2]; // padding for later use. 158 | void* private_; // for internal use only. 159 | }; 160 | 161 | // Retrieves frame 'frame_number' from 'dmux'. 162 | // 'iter->fragment' points to the frame on return from this function. 163 | // Setting 'frame_number' equal to 0 will return the last frame of the image. 164 | // Returns false if 'dmux' is NULL or frame 'frame_number' is not present. 165 | // Call WebPDemuxReleaseIterator() when use of the iterator is complete. 166 | // NOTE: 'dmux' must persist for the lifetime of 'iter'. 167 | WEBP_EXTERN int WebPDemuxGetFrame( 168 | const WebPDemuxer* dmux, int frame_number, WebPIterator* iter); 169 | 170 | // Sets 'iter->fragment' to point to the next ('iter->frame_num' + 1) or 171 | // previous ('iter->frame_num' - 1) frame. These functions do not loop. 172 | // Returns true on success, false otherwise. 173 | WEBP_EXTERN int WebPDemuxNextFrame(WebPIterator* iter); 174 | WEBP_EXTERN int WebPDemuxPrevFrame(WebPIterator* iter); 175 | 176 | // Releases any memory associated with 'iter'. 177 | // Must be called before any subsequent calls to WebPDemuxGetChunk() on the same 178 | // iter. Also, must be called before destroying the associated WebPDemuxer with 179 | // WebPDemuxDelete(). 180 | WEBP_EXTERN void WebPDemuxReleaseIterator(WebPIterator* iter); 181 | 182 | //------------------------------------------------------------------------------ 183 | // Chunk iteration. 184 | 185 | struct WebPChunkIterator { 186 | // The current and total number of chunks with the fourcc given to 187 | // WebPDemuxGetChunk(). 188 | int chunk_num; 189 | int num_chunks; 190 | WebPData chunk; // The payload of the chunk. 191 | 192 | uint32_t pad[6]; // padding for later use 193 | void* private_; 194 | }; 195 | 196 | // Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from 197 | // 'dmux'. 198 | // 'fourcc' is a character array containing the fourcc of the chunk to return, 199 | // e.g., "ICCP", "XMP ", "EXIF", etc. 200 | // Setting 'chunk_number' equal to 0 will return the last chunk in a set. 201 | // Returns true if the chunk is found, false otherwise. Image related chunk 202 | // payloads are accessed through WebPDemuxGetFrame() and related functions. 203 | // Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete. 204 | // NOTE: 'dmux' must persist for the lifetime of the iterator. 205 | WEBP_EXTERN int WebPDemuxGetChunk(const WebPDemuxer* dmux, 206 | const char fourcc[4], int chunk_number, 207 | WebPChunkIterator* iter); 208 | 209 | // Sets 'iter->chunk' to point to the next ('iter->chunk_num' + 1) or previous 210 | // ('iter->chunk_num' - 1) chunk. These functions do not loop. 211 | // Returns true on success, false otherwise. 212 | WEBP_EXTERN int WebPDemuxNextChunk(WebPChunkIterator* iter); 213 | WEBP_EXTERN int WebPDemuxPrevChunk(WebPChunkIterator* iter); 214 | 215 | // Releases any memory associated with 'iter'. 216 | // Must be called before destroying the associated WebPDemuxer with 217 | // WebPDemuxDelete(). 218 | WEBP_EXTERN void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter); 219 | 220 | //------------------------------------------------------------------------------ 221 | // WebPAnimDecoder API 222 | // 223 | // This API allows decoding (possibly) animated WebP images. 224 | // 225 | // Code Example: 226 | /* 227 | WebPAnimDecoderOptions dec_options; 228 | WebPAnimDecoderOptionsInit(&dec_options); 229 | // Tune 'dec_options' as needed. 230 | WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options); 231 | WebPAnimInfo anim_info; 232 | WebPAnimDecoderGetInfo(dec, &anim_info); 233 | for (uint32_t i = 0; i < anim_info.loop_count; ++i) { 234 | while (WebPAnimDecoderHasMoreFrames(dec)) { 235 | uint8_t* buf; 236 | int timestamp; 237 | WebPAnimDecoderGetNext(dec, &buf, ×tamp); 238 | // ... (Render 'buf' based on 'timestamp'). 239 | // ... (Do NOT free 'buf', as it is owned by 'dec'). 240 | } 241 | WebPAnimDecoderReset(dec); 242 | } 243 | const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec); 244 | // ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data). 245 | WebPAnimDecoderDelete(dec); 246 | */ 247 | 248 | typedef struct WebPAnimDecoder WebPAnimDecoder; // Main opaque object. 249 | 250 | // Global options. 251 | struct WebPAnimDecoderOptions { 252 | // Output colorspace. Only the following modes are supported: 253 | // MODE_RGBA, MODE_BGRA, MODE_rgbA and MODE_bgrA. 254 | WEBP_CSP_MODE color_mode; 255 | int use_threads; // If true, use multi-threaded decoding. 256 | uint32_t padding[7]; // Padding for later use. 257 | }; 258 | 259 | // Internal, version-checked, entry point. 260 | WEBP_EXTERN int WebPAnimDecoderOptionsInitInternal( 261 | WebPAnimDecoderOptions*, int); 262 | 263 | // Should always be called, to initialize a fresh WebPAnimDecoderOptions 264 | // structure before modification. Returns false in case of version mismatch. 265 | // WebPAnimDecoderOptionsInit() must have succeeded before using the 266 | // 'dec_options' object. 267 | static WEBP_INLINE int WebPAnimDecoderOptionsInit( 268 | WebPAnimDecoderOptions* dec_options) { 269 | return WebPAnimDecoderOptionsInitInternal(dec_options, 270 | WEBP_DEMUX_ABI_VERSION); 271 | } 272 | 273 | // Internal, version-checked, entry point. 274 | WEBP_EXTERN WebPAnimDecoder* WebPAnimDecoderNewInternal( 275 | const WebPData*, const WebPAnimDecoderOptions*, int); 276 | 277 | // Creates and initializes a WebPAnimDecoder object. 278 | // Parameters: 279 | // webp_data - (in) WebP bitstream. This should remain unchanged during the 280 | // lifetime of the output WebPAnimDecoder object. 281 | // dec_options - (in) decoding options. Can be passed NULL to choose 282 | // reasonable defaults (in particular, color mode MODE_RGBA 283 | // will be picked). 284 | // Returns: 285 | // A pointer to the newly created WebPAnimDecoder object, or NULL in case of 286 | // parsing error, invalid option or memory error. 287 | static WEBP_INLINE WebPAnimDecoder* WebPAnimDecoderNew( 288 | const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options) { 289 | return WebPAnimDecoderNewInternal(webp_data, dec_options, 290 | WEBP_DEMUX_ABI_VERSION); 291 | } 292 | 293 | // Global information about the animation.. 294 | struct WebPAnimInfo { 295 | uint32_t canvas_width; 296 | uint32_t canvas_height; 297 | uint32_t loop_count; 298 | uint32_t bgcolor; 299 | uint32_t frame_count; 300 | uint32_t pad[4]; // padding for later use 301 | }; 302 | 303 | // Get global information about the animation. 304 | // Parameters: 305 | // dec - (in) decoder instance to get information from. 306 | // info - (out) global information fetched from the animation. 307 | // Returns: 308 | // True on success. 309 | WEBP_EXTERN int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, 310 | WebPAnimInfo* info); 311 | 312 | // Fetch the next frame from 'dec' based on options supplied to 313 | // WebPAnimDecoderNew(). This will be a fully reconstructed canvas of size 314 | // 'canvas_width * 4 * canvas_height', and not just the frame sub-rectangle. The 315 | // returned buffer 'buf' is valid only until the next call to 316 | // WebPAnimDecoderGetNext(), WebPAnimDecoderReset() or WebPAnimDecoderDelete(). 317 | // Parameters: 318 | // dec - (in/out) decoder instance from which the next frame is to be fetched. 319 | // buf - (out) decoded frame. 320 | // timestamp - (out) timestamp of the frame in milliseconds. 321 | // Returns: 322 | // False if any of the arguments are NULL, or if there is a parsing or 323 | // decoding error, or if there are no more frames. Otherwise, returns true. 324 | WEBP_EXTERN int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, 325 | uint8_t** buf, int* timestamp); 326 | 327 | // Check if there are more frames left to decode. 328 | // Parameters: 329 | // dec - (in) decoder instance to be checked. 330 | // Returns: 331 | // True if 'dec' is not NULL and some frames are yet to be decoded. 332 | // Otherwise, returns false. 333 | WEBP_EXTERN int WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec); 334 | 335 | // Resets the WebPAnimDecoder object, so that next call to 336 | // WebPAnimDecoderGetNext() will restart decoding from 1st frame. This would be 337 | // helpful when all frames need to be decoded multiple times (e.g. 338 | // info.loop_count times) without destroying and recreating the 'dec' object. 339 | // Parameters: 340 | // dec - (in/out) decoder instance to be reset 341 | WEBP_EXTERN void WebPAnimDecoderReset(WebPAnimDecoder* dec); 342 | 343 | // Grab the internal demuxer object. 344 | // Getting the demuxer object can be useful if one wants to use operations only 345 | // available through demuxer; e.g. to get XMP/EXIF/ICC metadata. The returned 346 | // demuxer object is owned by 'dec' and is valid only until the next call to 347 | // WebPAnimDecoderDelete(). 348 | // 349 | // Parameters: 350 | // dec - (in) decoder instance from which the demuxer object is to be fetched. 351 | WEBP_EXTERN const WebPDemuxer* WebPAnimDecoderGetDemuxer( 352 | const WebPAnimDecoder* dec); 353 | 354 | // Deletes the WebPAnimDecoder object. 355 | // Parameters: 356 | // dec - (in/out) decoder instance to be deleted 357 | WEBP_EXTERN void WebPAnimDecoderDelete(WebPAnimDecoder* dec); 358 | 359 | #ifdef __cplusplus 360 | } // extern "C" 361 | #endif 362 | 363 | #endif // WEBP_WEBP_DEMUX_H_ 364 | -------------------------------------------------------------------------------- /deps/libwebp/encode.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // WebP encoder: main interface 11 | // 12 | // Author: Skal (pascal.massimino@gmail.com) 13 | 14 | #ifndef WEBP_WEBP_ENCODE_H_ 15 | #define WEBP_WEBP_ENCODE_H_ 16 | 17 | #include "./types.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #define WEBP_ENCODER_ABI_VERSION 0x020e // MAJOR(8b) + MINOR(8b) 24 | 25 | // Note: forward declaring enumerations is not allowed in (strict) C and C++, 26 | // the types are left here for reference. 27 | // typedef enum WebPImageHint WebPImageHint; 28 | // typedef enum WebPEncCSP WebPEncCSP; 29 | // typedef enum WebPPreset WebPPreset; 30 | // typedef enum WebPEncodingError WebPEncodingError; 31 | typedef struct WebPConfig WebPConfig; 32 | typedef struct WebPPicture WebPPicture; // main structure for I/O 33 | typedef struct WebPAuxStats WebPAuxStats; 34 | typedef struct WebPMemoryWriter WebPMemoryWriter; 35 | 36 | // Return the encoder's version number, packed in hexadecimal using 8bits for 37 | // each of major/minor/revision. E.g: v2.5.7 is 0x020507. 38 | WEBP_EXTERN int WebPGetEncoderVersion(void); 39 | 40 | //------------------------------------------------------------------------------ 41 | // One-stop-shop call! No questions asked: 42 | 43 | // Returns the size of the compressed data (pointed to by *output), or 0 if 44 | // an error occurred. The compressed data must be released by the caller 45 | // using the call 'WebPFree(*output)'. 46 | // These functions compress using the lossy format, and the quality_factor 47 | // can go from 0 (smaller output, lower quality) to 100 (best quality, 48 | // larger output). 49 | WEBP_EXTERN size_t WebPEncodeRGB(const uint8_t* rgb, 50 | int width, int height, int stride, 51 | float quality_factor, uint8_t** output); 52 | WEBP_EXTERN size_t WebPEncodeBGR(const uint8_t* bgr, 53 | int width, int height, int stride, 54 | float quality_factor, uint8_t** output); 55 | WEBP_EXTERN size_t WebPEncodeRGBA(const uint8_t* rgba, 56 | int width, int height, int stride, 57 | float quality_factor, uint8_t** output); 58 | WEBP_EXTERN size_t WebPEncodeBGRA(const uint8_t* bgra, 59 | int width, int height, int stride, 60 | float quality_factor, uint8_t** output); 61 | 62 | // These functions are the equivalent of the above, but compressing in a 63 | // lossless manner. Files are usually larger than lossy format, but will 64 | // not suffer any compression loss. 65 | WEBP_EXTERN size_t WebPEncodeLosslessRGB(const uint8_t* rgb, 66 | int width, int height, int stride, 67 | uint8_t** output); 68 | WEBP_EXTERN size_t WebPEncodeLosslessBGR(const uint8_t* bgr, 69 | int width, int height, int stride, 70 | uint8_t** output); 71 | WEBP_EXTERN size_t WebPEncodeLosslessRGBA(const uint8_t* rgba, 72 | int width, int height, int stride, 73 | uint8_t** output); 74 | WEBP_EXTERN size_t WebPEncodeLosslessBGRA(const uint8_t* bgra, 75 | int width, int height, int stride, 76 | uint8_t** output); 77 | 78 | // Releases memory returned by the WebPEncode*() functions above. 79 | WEBP_EXTERN void WebPFree(void* ptr); 80 | 81 | //------------------------------------------------------------------------------ 82 | // Coding parameters 83 | 84 | // Image characteristics hint for the underlying encoder. 85 | typedef enum WebPImageHint { 86 | WEBP_HINT_DEFAULT = 0, // default preset. 87 | WEBP_HINT_PICTURE, // digital picture, like portrait, inner shot 88 | WEBP_HINT_PHOTO, // outdoor photograph, with natural lighting 89 | WEBP_HINT_GRAPH, // Discrete tone image (graph, map-tile etc). 90 | WEBP_HINT_LAST 91 | } WebPImageHint; 92 | 93 | // Compression parameters. 94 | struct WebPConfig { 95 | int lossless; // Lossless encoding (0=lossy(default), 1=lossless). 96 | float quality; // between 0 and 100. For lossy, 0 gives the smallest 97 | // size and 100 the largest. For lossless, this 98 | // parameter is the amount of effort put into the 99 | // compression: 0 is the fastest but gives larger 100 | // files compared to the slowest, but best, 100. 101 | int method; // quality/speed trade-off (0=fast, 6=slower-better) 102 | 103 | WebPImageHint image_hint; // Hint for image type (lossless only for now). 104 | 105 | int target_size; // if non-zero, set the desired target size in bytes. 106 | // Takes precedence over the 'compression' parameter. 107 | float target_PSNR; // if non-zero, specifies the minimal distortion to 108 | // try to achieve. Takes precedence over target_size. 109 | int segments; // maximum number of segments to use, in [1..4] 110 | int sns_strength; // Spatial Noise Shaping. 0=off, 100=maximum. 111 | int filter_strength; // range: [0 = off .. 100 = strongest] 112 | int filter_sharpness; // range: [0 = off .. 7 = least sharp] 113 | int filter_type; // filtering type: 0 = simple, 1 = strong (only used 114 | // if filter_strength > 0 or autofilter > 0) 115 | int autofilter; // Auto adjust filter's strength [0 = off, 1 = on] 116 | int alpha_compression; // Algorithm for encoding the alpha plane (0 = none, 117 | // 1 = compressed with WebP lossless). Default is 1. 118 | int alpha_filtering; // Predictive filtering method for alpha plane. 119 | // 0: none, 1: fast, 2: best. Default if 1. 120 | int alpha_quality; // Between 0 (smallest size) and 100 (lossless). 121 | // Default is 100. 122 | int pass; // number of entropy-analysis passes (in [1..10]). 123 | 124 | int show_compressed; // if true, export the compressed picture back. 125 | // In-loop filtering is not applied. 126 | int preprocessing; // preprocessing filter: 127 | // 0=none, 1=segment-smooth, 2=pseudo-random dithering 128 | int partitions; // log2(number of token partitions) in [0..3]. Default 129 | // is set to 0 for easier progressive decoding. 130 | int partition_limit; // quality degradation allowed to fit the 512k limit 131 | // on prediction modes coding (0: no degradation, 132 | // 100: maximum possible degradation). 133 | int emulate_jpeg_size; // If true, compression parameters will be remapped 134 | // to better match the expected output size from 135 | // JPEG compression. Generally, the output size will 136 | // be similar but the degradation will be lower. 137 | int thread_level; // If non-zero, try and use multi-threaded encoding. 138 | int low_memory; // If set, reduce memory usage (but increase CPU use). 139 | 140 | int near_lossless; // Near lossless encoding [0 = max loss .. 100 = off 141 | // (default)]. 142 | int exact; // if non-zero, preserve the exact RGB values under 143 | // transparent area. Otherwise, discard this invisible 144 | // RGB information for better compression. The default 145 | // value is 0. 146 | 147 | int use_delta_palette; // reserved for future lossless feature 148 | int use_sharp_yuv; // if needed, use sharp (and slow) RGB->YUV conversion 149 | 150 | uint32_t pad[2]; // padding for later use 151 | }; 152 | 153 | // Enumerate some predefined settings for WebPConfig, depending on the type 154 | // of source picture. These presets are used when calling WebPConfigPreset(). 155 | typedef enum WebPPreset { 156 | WEBP_PRESET_DEFAULT = 0, // default preset. 157 | WEBP_PRESET_PICTURE, // digital picture, like portrait, inner shot 158 | WEBP_PRESET_PHOTO, // outdoor photograph, with natural lighting 159 | WEBP_PRESET_DRAWING, // hand or line drawing, with high-contrast details 160 | WEBP_PRESET_ICON, // small-sized colorful images 161 | WEBP_PRESET_TEXT // text-like 162 | } WebPPreset; 163 | 164 | // Internal, version-checked, entry point 165 | WEBP_EXTERN int WebPConfigInitInternal(WebPConfig*, WebPPreset, float, int); 166 | 167 | // Should always be called, to initialize a fresh WebPConfig structure before 168 | // modification. Returns false in case of version mismatch. WebPConfigInit() 169 | // must have succeeded before using the 'config' object. 170 | // Note that the default values are lossless=0 and quality=75. 171 | static WEBP_INLINE int WebPConfigInit(WebPConfig* config) { 172 | return WebPConfigInitInternal(config, WEBP_PRESET_DEFAULT, 75.f, 173 | WEBP_ENCODER_ABI_VERSION); 174 | } 175 | 176 | // This function will initialize the configuration according to a predefined 177 | // set of parameters (referred to by 'preset') and a given quality factor. 178 | // This function can be called as a replacement to WebPConfigInit(). Will 179 | // return false in case of error. 180 | static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, 181 | WebPPreset preset, float quality) { 182 | return WebPConfigInitInternal(config, preset, quality, 183 | WEBP_ENCODER_ABI_VERSION); 184 | } 185 | 186 | // Activate the lossless compression mode with the desired efficiency level 187 | // between 0 (fastest, lowest compression) and 9 (slower, best compression). 188 | // A good default level is '6', providing a fair tradeoff between compression 189 | // speed and final compressed size. 190 | // This function will overwrite several fields from config: 'method', 'quality' 191 | // and 'lossless'. Returns false in case of parameter error. 192 | WEBP_EXTERN int WebPConfigLosslessPreset(WebPConfig* config, int level); 193 | 194 | // Returns true if 'config' is non-NULL and all configuration parameters are 195 | // within their valid ranges. 196 | WEBP_EXTERN int WebPValidateConfig(const WebPConfig* config); 197 | 198 | //------------------------------------------------------------------------------ 199 | // Input / Output 200 | // Structure for storing auxiliary statistics. 201 | 202 | struct WebPAuxStats { 203 | int coded_size; // final size 204 | 205 | float PSNR[5]; // peak-signal-to-noise ratio for Y/U/V/All/Alpha 206 | int block_count[3]; // number of intra4/intra16/skipped macroblocks 207 | int header_bytes[2]; // approximate number of bytes spent for header 208 | // and mode-partition #0 209 | int residual_bytes[3][4]; // approximate number of bytes spent for 210 | // DC/AC/uv coefficients for each (0..3) segments. 211 | int segment_size[4]; // number of macroblocks in each segments 212 | int segment_quant[4]; // quantizer values for each segments 213 | int segment_level[4]; // filtering strength for each segments [0..63] 214 | 215 | int alpha_data_size; // size of the transparency data 216 | int layer_data_size; // size of the enhancement layer data 217 | 218 | // lossless encoder statistics 219 | uint32_t lossless_features; // bit0:predictor bit1:cross-color transform 220 | // bit2:subtract-green bit3:color indexing 221 | int histogram_bits; // number of precision bits of histogram 222 | int transform_bits; // precision bits for transform 223 | int cache_bits; // number of bits for color cache lookup 224 | int palette_size; // number of color in palette, if used 225 | int lossless_size; // final lossless size 226 | int lossless_hdr_size; // lossless header (transform, huffman etc) size 227 | int lossless_data_size; // lossless image data size 228 | 229 | uint32_t pad[2]; // padding for later use 230 | }; 231 | 232 | // Signature for output function. Should return true if writing was successful. 233 | // data/data_size is the segment of data to write, and 'picture' is for 234 | // reference (and so one can make use of picture->custom_ptr). 235 | typedef int (*WebPWriterFunction)(const uint8_t* data, size_t data_size, 236 | const WebPPicture* picture); 237 | 238 | // WebPMemoryWrite: a special WebPWriterFunction that writes to memory using 239 | // the following WebPMemoryWriter object (to be set as a custom_ptr). 240 | struct WebPMemoryWriter { 241 | uint8_t* mem; // final buffer (of size 'max_size', larger than 'size'). 242 | size_t size; // final size 243 | size_t max_size; // total capacity 244 | uint32_t pad[1]; // padding for later use 245 | }; 246 | 247 | // The following must be called first before any use. 248 | WEBP_EXTERN void WebPMemoryWriterInit(WebPMemoryWriter* writer); 249 | 250 | // The following must be called to deallocate writer->mem memory. The 'writer' 251 | // object itself is not deallocated. 252 | WEBP_EXTERN void WebPMemoryWriterClear(WebPMemoryWriter* writer); 253 | // The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon 254 | // completion, writer.mem and writer.size will hold the coded data. 255 | // writer.mem must be freed by calling WebPMemoryWriterClear. 256 | WEBP_EXTERN int WebPMemoryWrite(const uint8_t* data, size_t data_size, 257 | const WebPPicture* picture); 258 | 259 | // Progress hook, called from time to time to report progress. It can return 260 | // false to request an abort of the encoding process, or true otherwise if 261 | // everything is OK. 262 | typedef int (*WebPProgressHook)(int percent, const WebPPicture* picture); 263 | 264 | // Color spaces. 265 | typedef enum WebPEncCSP { 266 | // chroma sampling 267 | WEBP_YUV420 = 0, // 4:2:0 268 | WEBP_YUV420A = 4, // alpha channel variant 269 | WEBP_CSP_UV_MASK = 3, // bit-mask to get the UV sampling factors 270 | WEBP_CSP_ALPHA_BIT = 4 // bit that is set if alpha is present 271 | } WebPEncCSP; 272 | 273 | // Encoding error conditions. 274 | typedef enum WebPEncodingError { 275 | VP8_ENC_OK = 0, 276 | VP8_ENC_ERROR_OUT_OF_MEMORY, // memory error allocating objects 277 | VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY, // memory error while flushing bits 278 | VP8_ENC_ERROR_NULL_PARAMETER, // a pointer parameter is NULL 279 | VP8_ENC_ERROR_INVALID_CONFIGURATION, // configuration is invalid 280 | VP8_ENC_ERROR_BAD_DIMENSION, // picture has invalid width/height 281 | VP8_ENC_ERROR_PARTITION0_OVERFLOW, // partition is bigger than 512k 282 | VP8_ENC_ERROR_PARTITION_OVERFLOW, // partition is bigger than 16M 283 | VP8_ENC_ERROR_BAD_WRITE, // error while flushing bytes 284 | VP8_ENC_ERROR_FILE_TOO_BIG, // file is bigger than 4G 285 | VP8_ENC_ERROR_USER_ABORT, // abort request by user 286 | VP8_ENC_ERROR_LAST // list terminator. always last. 287 | } WebPEncodingError; 288 | 289 | // maximum width/height allowed (inclusive), in pixels 290 | #define WEBP_MAX_DIMENSION 16383 291 | 292 | // Main exchange structure (input samples, output bytes, statistics) 293 | struct WebPPicture { 294 | // INPUT 295 | ////////////// 296 | // Main flag for encoder selecting between ARGB or YUV input. 297 | // It is recommended to use ARGB input (*argb, argb_stride) for lossless 298 | // compression, and YUV input (*y, *u, *v, etc.) for lossy compression 299 | // since these are the respective native colorspace for these formats. 300 | int use_argb; 301 | 302 | // YUV input (mostly used for input to lossy compression) 303 | WebPEncCSP colorspace; // colorspace: should be YUV420 for now (=Y'CbCr). 304 | int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION) 305 | uint8_t *y, *u, *v; // pointers to luma/chroma planes. 306 | int y_stride, uv_stride; // luma/chroma strides. 307 | uint8_t* a; // pointer to the alpha plane 308 | int a_stride; // stride of the alpha plane 309 | uint32_t pad1[2]; // padding for later use 310 | 311 | // ARGB input (mostly used for input to lossless compression) 312 | uint32_t* argb; // Pointer to argb (32 bit) plane. 313 | int argb_stride; // This is stride in pixels units, not bytes. 314 | uint32_t pad2[3]; // padding for later use 315 | 316 | // OUTPUT 317 | /////////////// 318 | // Byte-emission hook, to store compressed bytes as they are ready. 319 | WebPWriterFunction writer; // can be NULL 320 | void* custom_ptr; // can be used by the writer. 321 | 322 | // map for extra information (only for lossy compression mode) 323 | int extra_info_type; // 1: intra type, 2: segment, 3: quant 324 | // 4: intra-16 prediction mode, 325 | // 5: chroma prediction mode, 326 | // 6: bit cost, 7: distortion 327 | uint8_t* extra_info; // if not NULL, points to an array of size 328 | // ((width + 15) / 16) * ((height + 15) / 16) that 329 | // will be filled with a macroblock map, depending 330 | // on extra_info_type. 331 | 332 | // STATS AND REPORTS 333 | /////////////////////////// 334 | // Pointer to side statistics (updated only if not NULL) 335 | WebPAuxStats* stats; 336 | 337 | // Error code for the latest error encountered during encoding 338 | WebPEncodingError error_code; 339 | 340 | // If not NULL, report progress during encoding. 341 | WebPProgressHook progress_hook; 342 | 343 | void* user_data; // this field is free to be set to any value and 344 | // used during callbacks (like progress-report e.g.). 345 | 346 | uint32_t pad3[3]; // padding for later use 347 | 348 | // Unused for now 349 | uint8_t *pad4, *pad5; 350 | uint32_t pad6[8]; // padding for later use 351 | 352 | // PRIVATE FIELDS 353 | //////////////////// 354 | void* memory_; // row chunk of memory for yuva planes 355 | void* memory_argb_; // and for argb too. 356 | void* pad7[2]; // padding for later use 357 | }; 358 | 359 | // Internal, version-checked, entry point 360 | WEBP_EXTERN int WebPPictureInitInternal(WebPPicture*, int); 361 | 362 | // Should always be called, to initialize the structure. Returns false in case 363 | // of version mismatch. WebPPictureInit() must have succeeded before using the 364 | // 'picture' object. 365 | // Note that, by default, use_argb is false and colorspace is WEBP_YUV420. 366 | static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) { 367 | return WebPPictureInitInternal(picture, WEBP_ENCODER_ABI_VERSION); 368 | } 369 | 370 | //------------------------------------------------------------------------------ 371 | // WebPPicture utils 372 | 373 | // Convenience allocation / deallocation based on picture->width/height: 374 | // Allocate y/u/v buffers as per colorspace/width/height specification. 375 | // Note! This function will free the previous buffer if needed. 376 | // Returns false in case of memory error. 377 | WEBP_EXTERN int WebPPictureAlloc(WebPPicture* picture); 378 | 379 | // Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*(). 380 | // Note that this function does _not_ free the memory used by the 'picture' 381 | // object itself. 382 | // Besides memory (which is reclaimed) all other fields of 'picture' are 383 | // preserved. 384 | WEBP_EXTERN void WebPPictureFree(WebPPicture* picture); 385 | 386 | // Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return, *dst 387 | // will fully own the copied pixels (this is not a view). The 'dst' picture need 388 | // not be initialized as its content is overwritten. 389 | // Returns false in case of memory allocation error. 390 | WEBP_EXTERN int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst); 391 | 392 | // Compute the single distortion for packed planes of samples. 393 | // 'src' will be compared to 'ref', and the raw distortion stored into 394 | // '*distortion'. The refined metric (log(MSE), log(1 - ssim),...' will be 395 | // stored in '*result'. 396 | // 'x_step' is the horizontal stride (in bytes) between samples. 397 | // 'src/ref_stride' is the byte distance between rows. 398 | // Returns false in case of error (bad parameter, memory allocation error, ...). 399 | WEBP_EXTERN int WebPPlaneDistortion(const uint8_t* src, size_t src_stride, 400 | const uint8_t* ref, size_t ref_stride, 401 | int width, int height, 402 | size_t x_step, 403 | int type, // 0 = PSNR, 1 = SSIM, 2 = LSIM 404 | float* distortion, float* result); 405 | 406 | // Compute PSNR, SSIM or LSIM distortion metric between two pictures. Results 407 | // are in dB, stored in result[] in the B/G/R/A/All order. The distortion is 408 | // always performed using ARGB samples. Hence if the input is YUV(A), the 409 | // picture will be internally converted to ARGB (just for the measurement). 410 | // Warning: this function is rather CPU-intensive. 411 | WEBP_EXTERN int WebPPictureDistortion( 412 | const WebPPicture* src, const WebPPicture* ref, 413 | int metric_type, // 0 = PSNR, 1 = SSIM, 2 = LSIM 414 | float result[5]); 415 | 416 | // self-crops a picture to the rectangle defined by top/left/width/height. 417 | // Returns false in case of memory allocation error, or if the rectangle is 418 | // outside of the source picture. 419 | // The rectangle for the view is defined by the top-left corner pixel 420 | // coordinates (left, top) as well as its width and height. This rectangle 421 | // must be fully be comprised inside the 'src' source picture. If the source 422 | // picture uses the YUV420 colorspace, the top and left coordinates will be 423 | // snapped to even values. 424 | WEBP_EXTERN int WebPPictureCrop(WebPPicture* picture, 425 | int left, int top, int width, int height); 426 | 427 | // Extracts a view from 'src' picture into 'dst'. The rectangle for the view 428 | // is defined by the top-left corner pixel coordinates (left, top) as well 429 | // as its width and height. This rectangle must be fully be comprised inside 430 | // the 'src' source picture. If the source picture uses the YUV420 colorspace, 431 | // the top and left coordinates will be snapped to even values. 432 | // Picture 'src' must out-live 'dst' picture. Self-extraction of view is allowed 433 | // ('src' equal to 'dst') as a mean of fast-cropping (but note that doing so, 434 | // the original dimension will be lost). Picture 'dst' need not be initialized 435 | // with WebPPictureInit() if it is different from 'src', since its content will 436 | // be overwritten. 437 | // Returns false in case of memory allocation error or invalid parameters. 438 | WEBP_EXTERN int WebPPictureView(const WebPPicture* src, 439 | int left, int top, int width, int height, 440 | WebPPicture* dst); 441 | 442 | // Returns true if the 'picture' is actually a view and therefore does 443 | // not own the memory for pixels. 444 | WEBP_EXTERN int WebPPictureIsView(const WebPPicture* picture); 445 | 446 | // Rescale a picture to new dimension width x height. 447 | // If either 'width' or 'height' (but not both) is 0 the corresponding 448 | // dimension will be calculated preserving the aspect ratio. 449 | // No gamma correction is applied. 450 | // Returns false in case of error (invalid parameter or insufficient memory). 451 | WEBP_EXTERN int WebPPictureRescale(WebPPicture* pic, int width, int height); 452 | 453 | // Colorspace conversion function to import RGB samples. 454 | // Previous buffer will be free'd, if any. 455 | // *rgb buffer should have a size of at least height * rgb_stride. 456 | // Returns false in case of memory error. 457 | WEBP_EXTERN int WebPPictureImportRGB( 458 | WebPPicture* picture, const uint8_t* rgb, int rgb_stride); 459 | // Same, but for RGBA buffer. 460 | WEBP_EXTERN int WebPPictureImportRGBA( 461 | WebPPicture* picture, const uint8_t* rgba, int rgba_stride); 462 | // Same, but for RGBA buffer. Imports the RGB direct from the 32-bit format 463 | // input buffer ignoring the alpha channel. Avoids needing to copy the data 464 | // to a temporary 24-bit RGB buffer to import the RGB only. 465 | WEBP_EXTERN int WebPPictureImportRGBX( 466 | WebPPicture* picture, const uint8_t* rgbx, int rgbx_stride); 467 | 468 | // Variants of the above, but taking BGR(A|X) input. 469 | WEBP_EXTERN int WebPPictureImportBGR( 470 | WebPPicture* picture, const uint8_t* bgr, int bgr_stride); 471 | WEBP_EXTERN int WebPPictureImportBGRA( 472 | WebPPicture* picture, const uint8_t* bgra, int bgra_stride); 473 | WEBP_EXTERN int WebPPictureImportBGRX( 474 | WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride); 475 | 476 | // Converts picture->argb data to the YUV420A format. The 'colorspace' 477 | // parameter is deprecated and should be equal to WEBP_YUV420. 478 | // Upon return, picture->use_argb is set to false. The presence of real 479 | // non-opaque transparent values is detected, and 'colorspace' will be 480 | // adjusted accordingly. Note that this method is lossy. 481 | // Returns false in case of error. 482 | WEBP_EXTERN int WebPPictureARGBToYUVA(WebPPicture* picture, 483 | WebPEncCSP /*colorspace = WEBP_YUV420*/); 484 | 485 | // Same as WebPPictureARGBToYUVA(), but the conversion is done using 486 | // pseudo-random dithering with a strength 'dithering' between 487 | // 0.0 (no dithering) and 1.0 (maximum dithering). This is useful 488 | // for photographic picture. 489 | WEBP_EXTERN int WebPPictureARGBToYUVADithered( 490 | WebPPicture* picture, WebPEncCSP colorspace, float dithering); 491 | 492 | // Performs 'sharp' RGBA->YUVA420 downsampling and colorspace conversion. 493 | // Downsampling is handled with extra care in case of color clipping. This 494 | // method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better 495 | // and sharper YUV representation. 496 | // Returns false in case of error. 497 | WEBP_EXTERN int WebPPictureSharpARGBToYUVA(WebPPicture* picture); 498 | // kept for backward compatibility: 499 | WEBP_EXTERN int WebPPictureSmartARGBToYUVA(WebPPicture* picture); 500 | 501 | // Converts picture->yuv to picture->argb and sets picture->use_argb to true. 502 | // The input format must be YUV_420 or YUV_420A. The conversion from YUV420 to 503 | // ARGB incurs a small loss too. 504 | // Note that the use of this colorspace is discouraged if one has access to the 505 | // raw ARGB samples, since using YUV420 is comparatively lossy. 506 | // Returns false in case of error. 507 | WEBP_EXTERN int WebPPictureYUVAToARGB(WebPPicture* picture); 508 | 509 | // Helper function: given a width x height plane of RGBA or YUV(A) samples 510 | // clean-up or smoothen the YUV or RGB samples under fully transparent area, 511 | // to help compressibility (no guarantee, though). 512 | WEBP_EXTERN void WebPCleanupTransparentArea(WebPPicture* picture); 513 | 514 | // Scan the picture 'picture' for the presence of non fully opaque alpha values. 515 | // Returns true in such case. Otherwise returns false (indicating that the 516 | // alpha plane can be ignored altogether e.g.). 517 | WEBP_EXTERN int WebPPictureHasTransparency(const WebPPicture* picture); 518 | 519 | // Remove the transparency information (if present) by blending the color with 520 | // the background color 'background_rgb' (specified as 24bit RGB triplet). 521 | // After this call, all alpha values are reset to 0xff. 522 | WEBP_EXTERN void WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb); 523 | 524 | //------------------------------------------------------------------------------ 525 | // Main call 526 | 527 | // Main encoding call, after config and picture have been initialized. 528 | // 'picture' must be less than 16384x16384 in dimension (cf WEBP_MAX_DIMENSION), 529 | // and the 'config' object must be a valid one. 530 | // Returns false in case of error, true otherwise. 531 | // In case of error, picture->error_code is updated accordingly. 532 | // 'picture' can hold the source samples in both YUV(A) or ARGB input, depending 533 | // on the value of 'picture->use_argb'. It is highly recommended to use 534 | // the former for lossy encoding, and the latter for lossless encoding 535 | // (when config.lossless is true). Automatic conversion from one format to 536 | // another is provided but they both incur some loss. 537 | WEBP_EXTERN int WebPEncode(const WebPConfig* config, WebPPicture* picture); 538 | 539 | //------------------------------------------------------------------------------ 540 | 541 | #ifdef __cplusplus 542 | } // extern "C" 543 | #endif 544 | 545 | #endif // WEBP_WEBP_ENCODE_H_ 546 | -------------------------------------------------------------------------------- /deps/libwebp/format_constants.h: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Internal header for constants related to WebP file format. 11 | // 12 | // Author: Urvang (urvang@google.com) 13 | 14 | #ifndef WEBP_WEBP_FORMAT_CONSTANTS_H_ 15 | #define WEBP_WEBP_FORMAT_CONSTANTS_H_ 16 | 17 | // Create fourcc of the chunk from the chunk tag characters. 18 | #define MKFOURCC(a, b, c, d) ((a) | (b) << 8 | (c) << 16 | (uint32_t)(d) << 24) 19 | 20 | // VP8 related constants. 21 | #define VP8_SIGNATURE 0x9d012a // Signature in VP8 data. 22 | #define VP8_MAX_PARTITION0_SIZE (1 << 19) // max size of mode partition 23 | #define VP8_MAX_PARTITION_SIZE (1 << 24) // max size for token partition 24 | #define VP8_FRAME_HEADER_SIZE 10 // Size of the frame header within VP8 data. 25 | 26 | // VP8L related constants. 27 | #define VP8L_SIGNATURE_SIZE 1 // VP8L signature size. 28 | #define VP8L_MAGIC_BYTE 0x2f // VP8L signature byte. 29 | #define VP8L_IMAGE_SIZE_BITS 14 // Number of bits used to store 30 | // width and height. 31 | #define VP8L_VERSION_BITS 3 // 3 bits reserved for version. 32 | #define VP8L_VERSION 0 // version 0 33 | #define VP8L_FRAME_HEADER_SIZE 5 // Size of the VP8L frame header. 34 | 35 | #define MAX_PALETTE_SIZE 256 36 | #define MAX_CACHE_BITS 11 37 | #define HUFFMAN_CODES_PER_META_CODE 5 38 | #define ARGB_BLACK 0xff000000 39 | 40 | #define DEFAULT_CODE_LENGTH 8 41 | #define MAX_ALLOWED_CODE_LENGTH 15 42 | 43 | #define NUM_LITERAL_CODES 256 44 | #define NUM_LENGTH_CODES 24 45 | #define NUM_DISTANCE_CODES 40 46 | #define CODE_LENGTH_CODES 19 47 | 48 | #define MIN_HUFFMAN_BITS 2 // min number of Huffman bits 49 | #define MAX_HUFFMAN_BITS 9 // max number of Huffman bits 50 | 51 | #define TRANSFORM_PRESENT 1 // The bit to be written when next data 52 | // to be read is a transform. 53 | #define NUM_TRANSFORMS 4 // Maximum number of allowed transform 54 | // in a bitstream. 55 | typedef enum { 56 | PREDICTOR_TRANSFORM = 0, 57 | CROSS_COLOR_TRANSFORM = 1, 58 | SUBTRACT_GREEN = 2, 59 | COLOR_INDEXING_TRANSFORM = 3 60 | } VP8LImageTransformType; 61 | 62 | // Alpha related constants. 63 | #define ALPHA_HEADER_LEN 1 64 | #define ALPHA_NO_COMPRESSION 0 65 | #define ALPHA_LOSSLESS_COMPRESSION 1 66 | #define ALPHA_PREPROCESSED_LEVELS 1 67 | 68 | // Mux related constants. 69 | #define TAG_SIZE 4 // Size of a chunk tag (e.g. "VP8L"). 70 | #define CHUNK_SIZE_BYTES 4 // Size needed to store chunk's size. 71 | #define CHUNK_HEADER_SIZE 8 // Size of a chunk header. 72 | #define RIFF_HEADER_SIZE 12 // Size of the RIFF header ("RIFFnnnnWEBP"). 73 | #define ANMF_CHUNK_SIZE 16 // Size of an ANMF chunk. 74 | #define ANIM_CHUNK_SIZE 6 // Size of an ANIM chunk. 75 | #define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk. 76 | 77 | #define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height. 78 | #define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height. 79 | #define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count 80 | #define MAX_DURATION (1 << 24) // maximum duration 81 | #define MAX_POSITION_OFFSET (1 << 24) // maximum frame x/y offset 82 | 83 | // Maximum chunk payload is such that adding the header and padding won't 84 | // overflow a uint32_t. 85 | #define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1) 86 | 87 | #endif // WEBP_WEBP_FORMAT_CONSTANTS_H_ 88 | -------------------------------------------------------------------------------- /deps/libwebp/libwebp.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nyx0uf/qlImageSize/41082059f6b0d57609a60aa27b7127552e17708f/deps/libwebp/libwebp.a -------------------------------------------------------------------------------- /deps/libwebp/mux.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // RIFF container manipulation and encoding for WebP images. 11 | // 12 | // Authors: Urvang (urvang@google.com) 13 | // Vikas (vikasa@google.com) 14 | 15 | #ifndef WEBP_WEBP_MUX_H_ 16 | #define WEBP_WEBP_MUX_H_ 17 | 18 | #include "./mux_types.h" 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #define WEBP_MUX_ABI_VERSION 0x0108 // MAJOR(8b) + MINOR(8b) 25 | 26 | //------------------------------------------------------------------------------ 27 | // Mux API 28 | // 29 | // This API allows manipulation of WebP container images containing features 30 | // like color profile, metadata, animation. 31 | // 32 | // Code Example#1: Create a WebPMux object with image data, color profile and 33 | // XMP metadata. 34 | /* 35 | int copy_data = 0; 36 | WebPMux* mux = WebPMuxNew(); 37 | // ... (Prepare image data). 38 | WebPMuxSetImage(mux, &image, copy_data); 39 | // ... (Prepare ICCP color profile data). 40 | WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data); 41 | // ... (Prepare XMP metadata). 42 | WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data); 43 | // Get data from mux in WebP RIFF format. 44 | WebPMuxAssemble(mux, &output_data); 45 | WebPMuxDelete(mux); 46 | // ... (Consume output_data; e.g. write output_data.bytes to file). 47 | WebPDataClear(&output_data); 48 | */ 49 | 50 | // Code Example#2: Get image and color profile data from a WebP file. 51 | /* 52 | int copy_data = 0; 53 | // ... (Read data from file). 54 | WebPMux* mux = WebPMuxCreate(&data, copy_data); 55 | WebPMuxGetFrame(mux, 1, &image); 56 | // ... (Consume image; e.g. call WebPDecode() to decode the data). 57 | WebPMuxGetChunk(mux, "ICCP", &icc_profile); 58 | // ... (Consume icc_data). 59 | WebPMuxDelete(mux); 60 | free(data); 61 | */ 62 | 63 | // Note: forward declaring enumerations is not allowed in (strict) C and C++, 64 | // the types are left here for reference. 65 | // typedef enum WebPMuxError WebPMuxError; 66 | // typedef enum WebPChunkId WebPChunkId; 67 | typedef struct WebPMux WebPMux; // main opaque object. 68 | typedef struct WebPMuxFrameInfo WebPMuxFrameInfo; 69 | typedef struct WebPMuxAnimParams WebPMuxAnimParams; 70 | typedef struct WebPAnimEncoderOptions WebPAnimEncoderOptions; 71 | 72 | // Error codes 73 | typedef enum WebPMuxError { 74 | WEBP_MUX_OK = 1, 75 | WEBP_MUX_NOT_FOUND = 0, 76 | WEBP_MUX_INVALID_ARGUMENT = -1, 77 | WEBP_MUX_BAD_DATA = -2, 78 | WEBP_MUX_MEMORY_ERROR = -3, 79 | WEBP_MUX_NOT_ENOUGH_DATA = -4 80 | } WebPMuxError; 81 | 82 | // IDs for different types of chunks. 83 | typedef enum WebPChunkId { 84 | WEBP_CHUNK_VP8X, // VP8X 85 | WEBP_CHUNK_ICCP, // ICCP 86 | WEBP_CHUNK_ANIM, // ANIM 87 | WEBP_CHUNK_ANMF, // ANMF 88 | WEBP_CHUNK_DEPRECATED, // (deprecated from FRGM) 89 | WEBP_CHUNK_ALPHA, // ALPH 90 | WEBP_CHUNK_IMAGE, // VP8/VP8L 91 | WEBP_CHUNK_EXIF, // EXIF 92 | WEBP_CHUNK_XMP, // XMP 93 | WEBP_CHUNK_UNKNOWN, // Other chunks. 94 | WEBP_CHUNK_NIL 95 | } WebPChunkId; 96 | 97 | //------------------------------------------------------------------------------ 98 | 99 | // Returns the version number of the mux library, packed in hexadecimal using 100 | // 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. 101 | WEBP_EXTERN int WebPGetMuxVersion(void); 102 | 103 | //------------------------------------------------------------------------------ 104 | // Life of a Mux object 105 | 106 | // Internal, version-checked, entry point 107 | WEBP_EXTERN WebPMux* WebPNewInternal(int); 108 | 109 | // Creates an empty mux object. 110 | // Returns: 111 | // A pointer to the newly created empty mux object. 112 | // Or NULL in case of memory error. 113 | static WEBP_INLINE WebPMux* WebPMuxNew(void) { 114 | return WebPNewInternal(WEBP_MUX_ABI_VERSION); 115 | } 116 | 117 | // Deletes the mux object. 118 | // Parameters: 119 | // mux - (in/out) object to be deleted 120 | WEBP_EXTERN void WebPMuxDelete(WebPMux* mux); 121 | 122 | //------------------------------------------------------------------------------ 123 | // Mux creation. 124 | 125 | // Internal, version-checked, entry point 126 | WEBP_EXTERN WebPMux* WebPMuxCreateInternal(const WebPData*, int, int); 127 | 128 | // Creates a mux object from raw data given in WebP RIFF format. 129 | // Parameters: 130 | // bitstream - (in) the bitstream data in WebP RIFF format 131 | // copy_data - (in) value 1 indicates given data WILL be copied to the mux 132 | // object and value 0 indicates data will NOT be copied. 133 | // Returns: 134 | // A pointer to the mux object created from given data - on success. 135 | // NULL - In case of invalid data or memory error. 136 | static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream, 137 | int copy_data) { 138 | return WebPMuxCreateInternal(bitstream, copy_data, WEBP_MUX_ABI_VERSION); 139 | } 140 | 141 | //------------------------------------------------------------------------------ 142 | // Non-image chunks. 143 | 144 | // Note: Only non-image related chunks should be managed through chunk APIs. 145 | // (Image related chunks are: "ANMF", "VP8 ", "VP8L" and "ALPH"). 146 | // To add, get and delete images, use WebPMuxSetImage(), WebPMuxPushFrame(), 147 | // WebPMuxGetFrame() and WebPMuxDeleteFrame(). 148 | 149 | // Adds a chunk with id 'fourcc' and data 'chunk_data' in the mux object. 150 | // Any existing chunk(s) with the same id will be removed. 151 | // Parameters: 152 | // mux - (in/out) object to which the chunk is to be added 153 | // fourcc - (in) a character array containing the fourcc of the given chunk; 154 | // e.g., "ICCP", "XMP ", "EXIF" etc. 155 | // chunk_data - (in) the chunk data to be added 156 | // copy_data - (in) value 1 indicates given data WILL be copied to the mux 157 | // object and value 0 indicates data will NOT be copied. 158 | // Returns: 159 | // WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL 160 | // or if fourcc corresponds to an image chunk. 161 | // WEBP_MUX_MEMORY_ERROR - on memory allocation error. 162 | // WEBP_MUX_OK - on success. 163 | WEBP_EXTERN WebPMuxError WebPMuxSetChunk( 164 | WebPMux* mux, const char fourcc[4], const WebPData* chunk_data, 165 | int copy_data); 166 | 167 | // Gets a reference to the data of the chunk with id 'fourcc' in the mux object. 168 | // The caller should NOT free the returned data. 169 | // Parameters: 170 | // mux - (in) object from which the chunk data is to be fetched 171 | // fourcc - (in) a character array containing the fourcc of the chunk; 172 | // e.g., "ICCP", "XMP ", "EXIF" etc. 173 | // chunk_data - (out) returned chunk data 174 | // Returns: 175 | // WEBP_MUX_INVALID_ARGUMENT - if mux, fourcc or chunk_data is NULL 176 | // or if fourcc corresponds to an image chunk. 177 | // WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given id. 178 | // WEBP_MUX_OK - on success. 179 | WEBP_EXTERN WebPMuxError WebPMuxGetChunk( 180 | const WebPMux* mux, const char fourcc[4], WebPData* chunk_data); 181 | 182 | // Deletes the chunk with the given 'fourcc' from the mux object. 183 | // Parameters: 184 | // mux - (in/out) object from which the chunk is to be deleted 185 | // fourcc - (in) a character array containing the fourcc of the chunk; 186 | // e.g., "ICCP", "XMP ", "EXIF" etc. 187 | // Returns: 188 | // WEBP_MUX_INVALID_ARGUMENT - if mux or fourcc is NULL 189 | // or if fourcc corresponds to an image chunk. 190 | // WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given fourcc. 191 | // WEBP_MUX_OK - on success. 192 | WEBP_EXTERN WebPMuxError WebPMuxDeleteChunk( 193 | WebPMux* mux, const char fourcc[4]); 194 | 195 | //------------------------------------------------------------------------------ 196 | // Images. 197 | 198 | // Encapsulates data about a single frame. 199 | struct WebPMuxFrameInfo { 200 | WebPData bitstream; // image data: can be a raw VP8/VP8L bitstream 201 | // or a single-image WebP file. 202 | int x_offset; // x-offset of the frame. 203 | int y_offset; // y-offset of the frame. 204 | int duration; // duration of the frame (in milliseconds). 205 | 206 | WebPChunkId id; // frame type: should be one of WEBP_CHUNK_ANMF 207 | // or WEBP_CHUNK_IMAGE 208 | WebPMuxAnimDispose dispose_method; // Disposal method for the frame. 209 | WebPMuxAnimBlend blend_method; // Blend operation for the frame. 210 | uint32_t pad[1]; // padding for later use 211 | }; 212 | 213 | // Sets the (non-animated) image in the mux object. 214 | // Note: Any existing images (including frames) will be removed. 215 | // Parameters: 216 | // mux - (in/out) object in which the image is to be set 217 | // bitstream - (in) can be a raw VP8/VP8L bitstream or a single-image 218 | // WebP file (non-animated) 219 | // copy_data - (in) value 1 indicates given data WILL be copied to the mux 220 | // object and value 0 indicates data will NOT be copied. 221 | // Returns: 222 | // WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL. 223 | // WEBP_MUX_MEMORY_ERROR - on memory allocation error. 224 | // WEBP_MUX_OK - on success. 225 | WEBP_EXTERN WebPMuxError WebPMuxSetImage( 226 | WebPMux* mux, const WebPData* bitstream, int copy_data); 227 | 228 | // Adds a frame at the end of the mux object. 229 | // Notes: (1) frame.id should be WEBP_CHUNK_ANMF 230 | // (2) For setting a non-animated image, use WebPMuxSetImage() instead. 231 | // (3) Type of frame being pushed must be same as the frames in mux. 232 | // (4) As WebP only supports even offsets, any odd offset will be snapped 233 | // to an even location using: offset &= ~1 234 | // Parameters: 235 | // mux - (in/out) object to which the frame is to be added 236 | // frame - (in) frame data. 237 | // copy_data - (in) value 1 indicates given data WILL be copied to the mux 238 | // object and value 0 indicates data will NOT be copied. 239 | // Returns: 240 | // WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL 241 | // or if content of 'frame' is invalid. 242 | // WEBP_MUX_MEMORY_ERROR - on memory allocation error. 243 | // WEBP_MUX_OK - on success. 244 | WEBP_EXTERN WebPMuxError WebPMuxPushFrame( 245 | WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data); 246 | 247 | // Gets the nth frame from the mux object. 248 | // The content of 'frame->bitstream' is allocated using malloc(), and NOT 249 | // owned by the 'mux' object. It MUST be deallocated by the caller by calling 250 | // WebPDataClear(). 251 | // nth=0 has a special meaning - last position. 252 | // Parameters: 253 | // mux - (in) object from which the info is to be fetched 254 | // nth - (in) index of the frame in the mux object 255 | // frame - (out) data of the returned frame 256 | // Returns: 257 | // WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL. 258 | // WEBP_MUX_NOT_FOUND - if there are less than nth frames in the mux object. 259 | // WEBP_MUX_BAD_DATA - if nth frame chunk in mux is invalid. 260 | // WEBP_MUX_MEMORY_ERROR - on memory allocation error. 261 | // WEBP_MUX_OK - on success. 262 | WEBP_EXTERN WebPMuxError WebPMuxGetFrame( 263 | const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame); 264 | 265 | // Deletes a frame from the mux object. 266 | // nth=0 has a special meaning - last position. 267 | // Parameters: 268 | // mux - (in/out) object from which a frame is to be deleted 269 | // nth - (in) The position from which the frame is to be deleted 270 | // Returns: 271 | // WEBP_MUX_INVALID_ARGUMENT - if mux is NULL. 272 | // WEBP_MUX_NOT_FOUND - If there are less than nth frames in the mux object 273 | // before deletion. 274 | // WEBP_MUX_OK - on success. 275 | WEBP_EXTERN WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth); 276 | 277 | //------------------------------------------------------------------------------ 278 | // Animation. 279 | 280 | // Animation parameters. 281 | struct WebPMuxAnimParams { 282 | uint32_t bgcolor; // Background color of the canvas stored (in MSB order) as: 283 | // Bits 00 to 07: Alpha. 284 | // Bits 08 to 15: Red. 285 | // Bits 16 to 23: Green. 286 | // Bits 24 to 31: Blue. 287 | int loop_count; // Number of times to repeat the animation [0 = infinite]. 288 | }; 289 | 290 | // Sets the animation parameters in the mux object. Any existing ANIM chunks 291 | // will be removed. 292 | // Parameters: 293 | // mux - (in/out) object in which ANIM chunk is to be set/added 294 | // params - (in) animation parameters. 295 | // Returns: 296 | // WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL. 297 | // WEBP_MUX_MEMORY_ERROR - on memory allocation error. 298 | // WEBP_MUX_OK - on success. 299 | WEBP_EXTERN WebPMuxError WebPMuxSetAnimationParams( 300 | WebPMux* mux, const WebPMuxAnimParams* params); 301 | 302 | // Gets the animation parameters from the mux object. 303 | // Parameters: 304 | // mux - (in) object from which the animation parameters to be fetched 305 | // params - (out) animation parameters extracted from the ANIM chunk 306 | // Returns: 307 | // WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL. 308 | // WEBP_MUX_NOT_FOUND - if ANIM chunk is not present in mux object. 309 | // WEBP_MUX_OK - on success. 310 | WEBP_EXTERN WebPMuxError WebPMuxGetAnimationParams( 311 | const WebPMux* mux, WebPMuxAnimParams* params); 312 | 313 | //------------------------------------------------------------------------------ 314 | // Misc Utilities. 315 | 316 | // Sets the canvas size for the mux object. The width and height can be 317 | // specified explicitly or left as zero (0, 0). 318 | // * When width and height are specified explicitly, then this frame bound is 319 | // enforced during subsequent calls to WebPMuxAssemble() and an error is 320 | // reported if any animated frame does not completely fit within the canvas. 321 | // * When unspecified (0, 0), the constructed canvas will get the frame bounds 322 | // from the bounding-box over all frames after calling WebPMuxAssemble(). 323 | // Parameters: 324 | // mux - (in) object to which the canvas size is to be set 325 | // width - (in) canvas width 326 | // height - (in) canvas height 327 | // Returns: 328 | // WEBP_MUX_INVALID_ARGUMENT - if mux is NULL; or 329 | // width or height are invalid or out of bounds 330 | // WEBP_MUX_OK - on success. 331 | WEBP_EXTERN WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux, 332 | int width, int height); 333 | 334 | // Gets the canvas size from the mux object. 335 | // Note: This method assumes that the VP8X chunk, if present, is up-to-date. 336 | // That is, the mux object hasn't been modified since the last call to 337 | // WebPMuxAssemble() or WebPMuxCreate(). 338 | // Parameters: 339 | // mux - (in) object from which the canvas size is to be fetched 340 | // width - (out) canvas width 341 | // height - (out) canvas height 342 | // Returns: 343 | // WEBP_MUX_INVALID_ARGUMENT - if mux, width or height is NULL. 344 | // WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid. 345 | // WEBP_MUX_OK - on success. 346 | WEBP_EXTERN WebPMuxError WebPMuxGetCanvasSize(const WebPMux* mux, 347 | int* width, int* height); 348 | 349 | // Gets the feature flags from the mux object. 350 | // Note: This method assumes that the VP8X chunk, if present, is up-to-date. 351 | // That is, the mux object hasn't been modified since the last call to 352 | // WebPMuxAssemble() or WebPMuxCreate(). 353 | // Parameters: 354 | // mux - (in) object from which the features are to be fetched 355 | // flags - (out) the flags specifying which features are present in the 356 | // mux object. This will be an OR of various flag values. 357 | // Enum 'WebPFeatureFlags' can be used to test individual flag values. 358 | // Returns: 359 | // WEBP_MUX_INVALID_ARGUMENT - if mux or flags is NULL. 360 | // WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid. 361 | // WEBP_MUX_OK - on success. 362 | WEBP_EXTERN WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, 363 | uint32_t* flags); 364 | 365 | // Gets number of chunks with the given 'id' in the mux object. 366 | // Parameters: 367 | // mux - (in) object from which the info is to be fetched 368 | // id - (in) chunk id specifying the type of chunk 369 | // num_elements - (out) number of chunks with the given chunk id 370 | // Returns: 371 | // WEBP_MUX_INVALID_ARGUMENT - if mux, or num_elements is NULL. 372 | // WEBP_MUX_OK - on success. 373 | WEBP_EXTERN WebPMuxError WebPMuxNumChunks(const WebPMux* mux, 374 | WebPChunkId id, int* num_elements); 375 | 376 | // Assembles all chunks in WebP RIFF format and returns in 'assembled_data'. 377 | // This function also validates the mux object. 378 | // Note: The content of 'assembled_data' will be ignored and overwritten. 379 | // Also, the content of 'assembled_data' is allocated using malloc(), and NOT 380 | // owned by the 'mux' object. It MUST be deallocated by the caller by calling 381 | // WebPDataClear(). It's always safe to call WebPDataClear() upon return, 382 | // even in case of error. 383 | // Parameters: 384 | // mux - (in/out) object whose chunks are to be assembled 385 | // assembled_data - (out) assembled WebP data 386 | // Returns: 387 | // WEBP_MUX_BAD_DATA - if mux object is invalid. 388 | // WEBP_MUX_INVALID_ARGUMENT - if mux or assembled_data is NULL. 389 | // WEBP_MUX_MEMORY_ERROR - on memory allocation error. 390 | // WEBP_MUX_OK - on success. 391 | WEBP_EXTERN WebPMuxError WebPMuxAssemble(WebPMux* mux, 392 | WebPData* assembled_data); 393 | 394 | //------------------------------------------------------------------------------ 395 | // WebPAnimEncoder API 396 | // 397 | // This API allows encoding (possibly) animated WebP images. 398 | // 399 | // Code Example: 400 | /* 401 | WebPAnimEncoderOptions enc_options; 402 | WebPAnimEncoderOptionsInit(&enc_options); 403 | // Tune 'enc_options' as needed. 404 | WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options); 405 | while() { 406 | WebPConfig config; 407 | WebPConfigInit(&config); 408 | // Tune 'config' as needed. 409 | WebPAnimEncoderAdd(enc, frame, timestamp_ms, &config); 410 | } 411 | WebPAnimEncoderAdd(enc, NULL, timestamp_ms, NULL); 412 | WebPAnimEncoderAssemble(enc, webp_data); 413 | WebPAnimEncoderDelete(enc); 414 | // Write the 'webp_data' to a file, or re-mux it further. 415 | */ 416 | 417 | typedef struct WebPAnimEncoder WebPAnimEncoder; // Main opaque object. 418 | 419 | // Forward declarations. Defined in encode.h. 420 | struct WebPPicture; 421 | struct WebPConfig; 422 | 423 | // Global options. 424 | struct WebPAnimEncoderOptions { 425 | WebPMuxAnimParams anim_params; // Animation parameters. 426 | int minimize_size; // If true, minimize the output size (slow). Implicitly 427 | // disables key-frame insertion. 428 | int kmin; 429 | int kmax; // Minimum and maximum distance between consecutive key 430 | // frames in the output. The library may insert some key 431 | // frames as needed to satisfy this criteria. 432 | // Note that these conditions should hold: kmax > kmin 433 | // and kmin >= kmax / 2 + 1. Also, if kmax <= 0, then 434 | // key-frame insertion is disabled; and if kmax == 1, 435 | // then all frames will be key-frames (kmin value does 436 | // not matter for these special cases). 437 | int allow_mixed; // If true, use mixed compression mode; may choose 438 | // either lossy and lossless for each frame. 439 | int verbose; // If true, print info and warning messages to stderr. 440 | 441 | uint32_t padding[4]; // Padding for later use. 442 | }; 443 | 444 | // Internal, version-checked, entry point. 445 | WEBP_EXTERN int WebPAnimEncoderOptionsInitInternal( 446 | WebPAnimEncoderOptions*, int); 447 | 448 | // Should always be called, to initialize a fresh WebPAnimEncoderOptions 449 | // structure before modification. Returns false in case of version mismatch. 450 | // WebPAnimEncoderOptionsInit() must have succeeded before using the 451 | // 'enc_options' object. 452 | static WEBP_INLINE int WebPAnimEncoderOptionsInit( 453 | WebPAnimEncoderOptions* enc_options) { 454 | return WebPAnimEncoderOptionsInitInternal(enc_options, WEBP_MUX_ABI_VERSION); 455 | } 456 | 457 | // Internal, version-checked, entry point. 458 | WEBP_EXTERN WebPAnimEncoder* WebPAnimEncoderNewInternal( 459 | int, int, const WebPAnimEncoderOptions*, int); 460 | 461 | // Creates and initializes a WebPAnimEncoder object. 462 | // Parameters: 463 | // width/height - (in) canvas width and height of the animation. 464 | // enc_options - (in) encoding options; can be passed NULL to pick 465 | // reasonable defaults. 466 | // Returns: 467 | // A pointer to the newly created WebPAnimEncoder object. 468 | // Or NULL in case of memory error. 469 | static WEBP_INLINE WebPAnimEncoder* WebPAnimEncoderNew( 470 | int width, int height, const WebPAnimEncoderOptions* enc_options) { 471 | return WebPAnimEncoderNewInternal(width, height, enc_options, 472 | WEBP_MUX_ABI_VERSION); 473 | } 474 | 475 | // Optimize the given frame for WebP, encode it and add it to the 476 | // WebPAnimEncoder object. 477 | // The last call to 'WebPAnimEncoderAdd' should be with frame = NULL, which 478 | // indicates that no more frames are to be added. This call is also used to 479 | // determine the duration of the last frame. 480 | // Parameters: 481 | // enc - (in/out) object to which the frame is to be added. 482 | // frame - (in/out) frame data in ARGB or YUV(A) format. If it is in YUV(A) 483 | // format, it will be converted to ARGB, which incurs a small loss. 484 | // timestamp_ms - (in) timestamp of this frame in milliseconds. 485 | // Duration of a frame would be calculated as 486 | // "timestamp of next frame - timestamp of this frame". 487 | // Hence, timestamps should be in non-decreasing order. 488 | // config - (in) encoding options; can be passed NULL to pick 489 | // reasonable defaults. 490 | // Returns: 491 | // On error, returns false and frame->error_code is set appropriately. 492 | // Otherwise, returns true. 493 | WEBP_EXTERN int WebPAnimEncoderAdd( 494 | WebPAnimEncoder* enc, struct WebPPicture* frame, int timestamp_ms, 495 | const struct WebPConfig* config); 496 | 497 | // Assemble all frames added so far into a WebP bitstream. 498 | // This call should be preceded by a call to 'WebPAnimEncoderAdd' with 499 | // frame = NULL; if not, the duration of the last frame will be internally 500 | // estimated. 501 | // Parameters: 502 | // enc - (in/out) object from which the frames are to be assembled. 503 | // webp_data - (out) generated WebP bitstream. 504 | // Returns: 505 | // True on success. 506 | WEBP_EXTERN int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, 507 | WebPData* webp_data); 508 | 509 | // Get error string corresponding to the most recent call using 'enc'. The 510 | // returned string is owned by 'enc' and is valid only until the next call to 511 | // WebPAnimEncoderAdd() or WebPAnimEncoderAssemble() or WebPAnimEncoderDelete(). 512 | // Parameters: 513 | // enc - (in/out) object from which the error string is to be fetched. 514 | // Returns: 515 | // NULL if 'enc' is NULL. Otherwise, returns the error string if the last call 516 | // to 'enc' had an error, or an empty string if the last call was a success. 517 | WEBP_EXTERN const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc); 518 | 519 | // Deletes the WebPAnimEncoder object. 520 | // Parameters: 521 | // enc - (in/out) object to be deleted 522 | WEBP_EXTERN void WebPAnimEncoderDelete(WebPAnimEncoder* enc); 523 | 524 | //------------------------------------------------------------------------------ 525 | 526 | #ifdef __cplusplus 527 | } // extern "C" 528 | #endif 529 | 530 | #endif // WEBP_WEBP_MUX_H_ 531 | -------------------------------------------------------------------------------- /deps/libwebp/mux_types.h: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Data-types common to the mux and demux libraries. 11 | // 12 | // Author: Urvang (urvang@google.com) 13 | 14 | #ifndef WEBP_WEBP_MUX_TYPES_H_ 15 | #define WEBP_WEBP_MUX_TYPES_H_ 16 | 17 | #include // free() 18 | #include // memset() 19 | #include "./types.h" 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | // Note: forward declaring enumerations is not allowed in (strict) C and C++, 26 | // the types are left here for reference. 27 | // typedef enum WebPFeatureFlags WebPFeatureFlags; 28 | // typedef enum WebPMuxAnimDispose WebPMuxAnimDispose; 29 | // typedef enum WebPMuxAnimBlend WebPMuxAnimBlend; 30 | typedef struct WebPData WebPData; 31 | 32 | // VP8X Feature Flags. 33 | typedef enum WebPFeatureFlags { 34 | ANIMATION_FLAG = 0x00000002, 35 | XMP_FLAG = 0x00000004, 36 | EXIF_FLAG = 0x00000008, 37 | ALPHA_FLAG = 0x00000010, 38 | ICCP_FLAG = 0x00000020, 39 | 40 | ALL_VALID_FLAGS = 0x0000003e 41 | } WebPFeatureFlags; 42 | 43 | // Dispose method (animation only). Indicates how the area used by the current 44 | // frame is to be treated before rendering the next frame on the canvas. 45 | typedef enum WebPMuxAnimDispose { 46 | WEBP_MUX_DISPOSE_NONE, // Do not dispose. 47 | WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color. 48 | } WebPMuxAnimDispose; 49 | 50 | // Blend operation (animation only). Indicates how transparent pixels of the 51 | // current frame are blended with those of the previous canvas. 52 | typedef enum WebPMuxAnimBlend { 53 | WEBP_MUX_BLEND, // Blend. 54 | WEBP_MUX_NO_BLEND // Do not blend. 55 | } WebPMuxAnimBlend; 56 | 57 | // Data type used to describe 'raw' data, e.g., chunk data 58 | // (ICC profile, metadata) and WebP compressed image data. 59 | struct WebPData { 60 | const uint8_t* bytes; 61 | size_t size; 62 | }; 63 | 64 | // Initializes the contents of the 'webp_data' object with default values. 65 | static WEBP_INLINE void WebPDataInit(WebPData* webp_data) { 66 | if (webp_data != NULL) { 67 | memset(webp_data, 0, sizeof(*webp_data)); 68 | } 69 | } 70 | 71 | // Clears the contents of the 'webp_data' object by calling free(). Does not 72 | // deallocate the object itself. 73 | static WEBP_INLINE void WebPDataClear(WebPData* webp_data) { 74 | if (webp_data != NULL) { 75 | free((void*)webp_data->bytes); 76 | WebPDataInit(webp_data); 77 | } 78 | } 79 | 80 | // Allocates necessary storage for 'dst' and copies the contents of 'src'. 81 | // Returns true on success. 82 | static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) { 83 | if (src == NULL || dst == NULL) return 0; 84 | WebPDataInit(dst); 85 | if (src->bytes != NULL && src->size != 0) { 86 | dst->bytes = (uint8_t*)malloc(src->size); 87 | if (dst->bytes == NULL) return 0; 88 | memcpy((void*)dst->bytes, src->bytes, src->size); 89 | dst->size = src->size; 90 | } 91 | return 1; 92 | } 93 | 94 | #ifdef __cplusplus 95 | } // extern "C" 96 | #endif 97 | 98 | #endif // WEBP_WEBP_MUX_TYPES_H_ 99 | -------------------------------------------------------------------------------- /deps/libwebp/types.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Common types 11 | // 12 | // Author: Skal (pascal.massimino@gmail.com) 13 | 14 | #ifndef WEBP_WEBP_TYPES_H_ 15 | #define WEBP_WEBP_TYPES_H_ 16 | 17 | #include // for size_t 18 | 19 | #ifndef _MSC_VER 20 | #include 21 | #if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \ 22 | (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) 23 | #define WEBP_INLINE inline 24 | #else 25 | #define WEBP_INLINE 26 | #endif 27 | #else 28 | typedef signed char int8_t; 29 | typedef unsigned char uint8_t; 30 | typedef signed short int16_t; 31 | typedef unsigned short uint16_t; 32 | typedef signed int int32_t; 33 | typedef unsigned int uint32_t; 34 | typedef unsigned long long int uint64_t; 35 | typedef long long int int64_t; 36 | #define WEBP_INLINE __forceinline 37 | #endif /* _MSC_VER */ 38 | 39 | #ifndef WEBP_EXTERN 40 | // This explicitly marks library functions and allows for changing the 41 | // signature for e.g., Windows DLL builds. 42 | # if defined(__GNUC__) && __GNUC__ >= 4 43 | # define WEBP_EXTERN extern __attribute__ ((visibility ("default"))) 44 | # else 45 | # define WEBP_EXTERN extern 46 | # endif /* __GNUC__ >= 4 */ 47 | #endif /* WEBP_EXTERN */ 48 | 49 | // Macro to check ABI compatibility (same major revision number) 50 | #define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8)) 51 | 52 | #endif // WEBP_WEBP_TYPES_H_ 53 | -------------------------------------------------------------------------------- /images-samples.txz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nyx0uf/qlImageSize/41082059f6b0d57609a60aa27b7127552e17708f/images-samples.txz -------------------------------------------------------------------------------- /mdimporter/rsrc/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDocumentTypes 8 | 9 | 10 | CFBundleTypeRole 11 | MDImporter 12 | LSItemContentTypes 13 | 14 | public.image 15 | public.webp 16 | com.google.webp 17 | fr.whine.bpg 18 | fr.whine.ppm 19 | fr.whine.pbm 20 | fr.whine.pgm 21 | 22 | 23 | 24 | CFBundleExecutable 25 | $(EXECUTABLE_NAME) 26 | CFBundleIdentifier 27 | $(PRODUCT_BUNDLE_IDENTIFIER) 28 | CFBundleInfoDictionaryVersion 29 | 6.0 30 | CFBundleName 31 | $(PRODUCT_NAME) 32 | CFBundleShortVersionString 33 | 1 34 | CFBundleSignature 35 | NYXM 36 | CFBundleVersion 37 | 2.6 38 | CFPlugInDynamicRegisterFunction 39 | 40 | CFPlugInDynamicRegistration 41 | NO 42 | CFPlugInFactories 43 | 44 | F0D38E63-504A-49AF-936B-2468C8D82C96 45 | MetadataImporterPluginFactory 46 | 47 | CFPlugInTypes 48 | 49 | 8B08C4BF-415B-11D8-B3F9-0003936726FC 50 | 51 | F0D38E63-504A-49AF-936B-2468C8D82C96 52 | 53 | 54 | CFPlugInUnloadFunction 55 | 56 | LSMinimumSystemVersion 57 | $(MACOSX_DEPLOYMENT_TARGET) 58 | NSHumanReadableCopyright 59 | Copyright © 2019 Nyx0uf. All rights reserved. 60 | 61 | 62 | -------------------------------------------------------------------------------- /mdimporter/src/GetMetadataForFile.m: -------------------------------------------------------------------------------- 1 | // 2 | // GetMetadataForFile.m 3 | // qlImageSize 4 | // 5 | // Created by @Nyx0uf on 20/12/14. 6 | // Copyright (c) 2014 Nyx0uf. All rights reserved. 7 | // 8 | 9 | 10 | #import "tools.h" 11 | 12 | #ifdef NYX_MD_SUPPORT_BPG_DECODE 13 | #import "bpg_decode.h" 14 | #endif 15 | 16 | #ifdef NYX_MD_SUPPORT_WEBP_DECODE 17 | #import "webp_decode.h" 18 | #endif 19 | 20 | #ifdef NYX_MD_SUPPORT_NETPBM_DECODE 21 | #import "netpbm_decode.h" 22 | #endif 23 | 24 | 25 | Boolean GetMetadataForFile(void* thisInterface, CFMutableDictionaryRef attributes, CFStringRef contentTypeUTI, CFStringRef pathToFile); 26 | bool GetImageInfos(CFStringRef pathToFile, NSMutableDictionary* attrs, bool (*infos_fn_ptr)(CFStringRef, image_infos*)); 27 | 28 | 29 | Boolean GetMetadataForFile(__unused void* thisInterface, CFMutableDictionaryRef attributes, __unused CFStringRef contentTypeUTI, CFStringRef pathToFile) 30 | { 31 | @autoreleasepool 32 | { 33 | NSString* extension = [[(__bridge NSString*)pathToFile pathExtension] lowercaseString]; 34 | 35 | #ifdef NYX_MD_SUPPORT_BPG_DECODE 36 | if ([extension isEqualToString:@"bpg"]) 37 | { 38 | return GetImageInfos(pathToFile, (__bridge NSMutableDictionary*)attributes, &get_bpg_informations_for_filepath); 39 | } 40 | #endif 41 | #ifdef NYX_MD_SUPPORT_WEBP_DECODE 42 | if ([extension isEqualToString:@"webp"]) 43 | { 44 | return GetImageInfos(pathToFile, (__bridge NSMutableDictionary*)attributes, &get_webp_informations_for_filepath); 45 | } 46 | #endif 47 | #ifdef NYX_MD_SUPPORT_NETPBM_DECODE 48 | if ([extension isEqualToString:@"ppm"] || [extension isEqualToString:@"pgm"] || [extension isEqualToString:@"pbm"]) 49 | { 50 | return GetImageInfos(pathToFile, (__bridge NSMutableDictionary*)attributes, &get_netpbm_informations_for_filepath); 51 | } 52 | #endif 53 | } 54 | 55 | return TRUE; 56 | } 57 | 58 | bool GetImageInfos(CFStringRef pathToFile, NSMutableDictionary* attrs, bool (*infos_fn_ptr)(CFStringRef, image_infos*)) 59 | { 60 | image_infos infos; 61 | memset(&infos, 0, sizeof(image_infos)); 62 | bool ret = infos_fn_ptr(pathToFile, &infos); 63 | 64 | if (!ret) 65 | return FALSE; 66 | 67 | attrs[(NSString*)kMDItemPixelWidth] = @(infos.width); 68 | attrs[(NSString*)kMDItemPixelHeight] = @(infos.height); 69 | attrs[(NSString*)kMDItemPixelCount] = @(infos.height * infos.width); 70 | attrs[(NSString*)kMDItemHasAlphaChannel] = (!infos.has_alpha) ? @NO : @YES; 71 | attrs[(NSString*)kMDItemBitsPerSample] = @(infos.bit_depth); 72 | attrs[(NSString*)kMDItemColorSpace] = @(colorspace_string(infos.colorspace)); 73 | 74 | return TRUE; 75 | } 76 | -------------------------------------------------------------------------------- /mdimporter/src/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // qlImageSize 4 | // 5 | // Created by @Nyx0uf on 20/12/14. 6 | // Copyright (c) 2014 Nyx0uf. All rights reserved. 7 | // 8 | 9 | 10 | //============================================================================== 11 | // 12 | // DO NO MODIFY THE CONTENT OF THIS FILE 13 | // 14 | // This file contains the generic CFPlug-in code necessary for your importer 15 | // To complete your importer implement the function in GetMetadataForFile.c 16 | // 17 | //============================================================================== 18 | 19 | 20 | #import 21 | #import 22 | #import 23 | 24 | // ----------------------------------------------------------------------------- 25 | // constants 26 | // ----------------------------------------------------------------------------- 27 | 28 | 29 | #define PLUGIN_ID "F0D38E63-504A-49AF-936B-2468C8D82C96" 30 | 31 | // 32 | // Below is the generic glue code for all plug-ins. 33 | // 34 | // You should not have to modify this code aside from changing 35 | // names if you decide to change the names defined in the Info.plist 36 | // 37 | 38 | 39 | // ----------------------------------------------------------------------------- 40 | // typedefs 41 | // ----------------------------------------------------------------------------- 42 | 43 | // The import function to be implemented in GetMetadataForFile.c 44 | Boolean GetMetadataForFile(void* thisInterface, CFMutableDictionaryRef attributes, CFStringRef contentTypeUTI, CFStringRef pathToFile); 45 | 46 | // The layout for an instance of MetaDataImporterPlugIn 47 | typedef struct __MetadataImporterPluginType 48 | { 49 | MDImporterInterfaceStruct* conduitInterface; 50 | CFUUIDRef factoryID; 51 | UInt32 refCount; 52 | } MetadataImporterPluginType; 53 | 54 | // ----------------------------------------------------------------------------- 55 | // prototypes 56 | // ----------------------------------------------------------------------------- 57 | // Forward declaration for the IUnknown implementation. 58 | // 59 | 60 | MetadataImporterPluginType* AllocMetadataImporterPluginType(CFUUIDRef inFactoryID); 61 | void DeallocMetadataImporterPluginType(MetadataImporterPluginType* thisInstance); 62 | HRESULT MetadataImporterQueryInterface(void* thisInstance, REFIID iid, LPVOID* ppv); 63 | void* MetadataImporterPluginFactory(CFAllocatorRef allocator, CFUUIDRef typeID); 64 | ULONG MetadataImporterPluginAddRef(void* thisInstance); 65 | ULONG MetadataImporterPluginRelease(void* thisInstance); 66 | // ----------------------------------------------------------------------------- 67 | // testInterfaceFtbl definition 68 | // ----------------------------------------------------------------------------- 69 | // The TestInterface function table. 70 | // 71 | 72 | static MDImporterInterfaceStruct testInterfaceFtbl = { 73 | NULL, 74 | MetadataImporterQueryInterface, 75 | MetadataImporterPluginAddRef, 76 | MetadataImporterPluginRelease, 77 | GetMetadataForFile 78 | }; 79 | 80 | 81 | // ----------------------------------------------------------------------------- 82 | // AllocMetadataImporterPluginType 83 | // ----------------------------------------------------------------------------- 84 | // Utility function that allocates a new instance. 85 | // You can do some initial setup for the importer here if you wish 86 | // like allocating globals etc... 87 | // 88 | MetadataImporterPluginType* AllocMetadataImporterPluginType(CFUUIDRef inFactoryID) 89 | { 90 | MetadataImporterPluginType* theNewInstance; 91 | 92 | theNewInstance = (MetadataImporterPluginType*)malloc(sizeof(MetadataImporterPluginType)); 93 | memset(theNewInstance, 0, sizeof(MetadataImporterPluginType)); 94 | 95 | /* Point to the function table */ 96 | theNewInstance->conduitInterface = &testInterfaceFtbl; 97 | 98 | /* Retain and keep an open instance refcount for each factory. */ 99 | theNewInstance->factoryID = CFRetain(inFactoryID); 100 | CFPlugInAddInstanceForFactory(inFactoryID); 101 | 102 | /* This function returns the IUnknown interface so set the refCount to one. */ 103 | theNewInstance->refCount = 1; 104 | return theNewInstance; 105 | } 106 | 107 | // ----------------------------------------------------------------------------- 108 | // DeallocmdImageSizeMDImporterPluginType 109 | // ----------------------------------------------------------------------------- 110 | // Utility function that deallocates the instance when 111 | // the refCount goes to zero. 112 | // In the current implementation importer interfaces are never deallocated 113 | // but implement this as this might change in the future 114 | // 115 | void DeallocMetadataImporterPluginType(MetadataImporterPluginType* thisInstance) 116 | { 117 | CFUUIDRef theFactoryID; 118 | 119 | theFactoryID = thisInstance->factoryID; 120 | free(thisInstance); 121 | if (theFactoryID) 122 | { 123 | CFPlugInRemoveInstanceForFactory(theFactoryID); 124 | CFRelease(theFactoryID); 125 | } 126 | } 127 | 128 | // ----------------------------------------------------------------------------- 129 | // MetadataImporterQueryInterface 130 | // ----------------------------------------------------------------------------- 131 | // Implementation of the IUnknown QueryInterface function. 132 | // 133 | HRESULT MetadataImporterQueryInterface(void* thisInstance, REFIID iid, LPVOID* ppv) 134 | { 135 | CFUUIDRef interfaceID; 136 | 137 | interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid); 138 | 139 | if (CFEqual(interfaceID, kMDImporterInterfaceID)) 140 | { 141 | /* If the Right interface was requested, bump the ref count, 142 | * set the ppv parameter equal to the instance, and 143 | * return good status. 144 | */ 145 | ((MetadataImporterPluginType*)thisInstance)->conduitInterface->AddRef(thisInstance); 146 | *ppv = thisInstance; 147 | CFRelease(interfaceID); 148 | return S_OK; 149 | } 150 | else 151 | { 152 | if (CFEqual(interfaceID,IUnknownUUID)) 153 | { 154 | /* If the IUnknown interface was requested, same as above. */ 155 | ((MetadataImporterPluginType*)thisInstance)->conduitInterface->AddRef(thisInstance); 156 | *ppv = thisInstance; 157 | CFRelease(interfaceID); 158 | return S_OK; 159 | } 160 | else 161 | { 162 | /* Requested interface unknown, bail with error. */ 163 | *ppv = NULL; 164 | CFRelease(interfaceID); 165 | return E_NOINTERFACE; 166 | } 167 | } 168 | } 169 | 170 | // ----------------------------------------------------------------------------- 171 | // MetadataImporterPluginAddRef 172 | // ----------------------------------------------------------------------------- 173 | // Implementation of reference counting for this type. Whenever an interface 174 | // is requested, bump the refCount for the instance. NOTE: returning the 175 | // refcount is a convention but is not required so don't rely on it. 176 | // 177 | ULONG MetadataImporterPluginAddRef(void* thisInstance) 178 | { 179 | ((MetadataImporterPluginType*)thisInstance)->refCount += 1; 180 | return ((MetadataImporterPluginType*)thisInstance)->refCount; 181 | } 182 | 183 | // ----------------------------------------------------------------------------- 184 | // SampleCMPluginRelease 185 | // ----------------------------------------------------------------------------- 186 | // When an interface is released, decrement the refCount. 187 | // If the refCount goes to zero, deallocate the instance. 188 | // 189 | ULONG MetadataImporterPluginRelease(void* thisInstance) 190 | { 191 | ((MetadataImporterPluginType*)thisInstance)->refCount -= 1; 192 | if (((MetadataImporterPluginType*)thisInstance)->refCount == 0) 193 | { 194 | DeallocMetadataImporterPluginType((MetadataImporterPluginType*)thisInstance); 195 | return 0; 196 | } 197 | else 198 | return ((MetadataImporterPluginType*)thisInstance)->refCount; 199 | } 200 | 201 | // ----------------------------------------------------------------------------- 202 | // mdImageSizeMDImporterPluginFactory 203 | // ----------------------------------------------------------------------------- 204 | // Implementation of the factory function for this type. 205 | // 206 | void* MetadataImporterPluginFactory(__unused CFAllocatorRef allocator, CFUUIDRef typeID) 207 | { 208 | MetadataImporterPluginType* result; 209 | CFUUIDRef uuid; 210 | 211 | /* If correct type is being requested, allocate an 212 | * instance of TestType and return the IUnknown interface. 213 | */ 214 | if (CFEqual(typeID, kMDImporterTypeID)) 215 | { 216 | uuid = CFUUIDCreateFromString(kCFAllocatorDefault, CFSTR(PLUGIN_ID)); 217 | result = AllocMetadataImporterPluginType(uuid); 218 | CFRelease(uuid); 219 | return result; 220 | } 221 | /* If the requested type is incorrect, return NULL. */ 222 | return NULL; 223 | } 224 | -------------------------------------------------------------------------------- /qlImageSize.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /qlImageSize.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /qlImageSize.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /qlImageSize.xcodeproj/project.xcworkspace/xcuserdata/nyxouf.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /qlImageSize.xcodeproj/xcuserdata/benjamin.xcuserdatad/xcschemes/mdImageSize.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /qlImageSize.xcodeproj/xcuserdata/benjamin.xcuserdatad/xcschemes/qlImageSize.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /qlImageSize.xcodeproj/xcuserdata/benjamin.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | mdImageSize.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | qlImageSize.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 1E7F115A1A459FE800EA2767 21 | 22 | primary 23 | 24 | 25 | 1EFA993D14D9288600A09F03 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /qlImageSize.xcodeproj/xcuserdata/nyxouf.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /qlImageSize.xcodeproj/xcuserdata/nyxouf.xcuserdatad/xcschemes/mdImageSize.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 67 | 68 | 69 | 70 | 72 | 73 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /qlImageSize.xcodeproj/xcuserdata/nyxouf.xcuserdatad/xcschemes/qlImageSize.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 63 | 64 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /qlImageSize.xcodeproj/xcuserdata/nyxouf.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | mdImageSize.xcscheme 8 | 9 | orderHint 10 | 2 11 | 12 | qlImageSize.xcscheme 13 | 14 | orderHint 15 | 1 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 1E7F115A1A459FE800EA2767 21 | 22 | primary 23 | 24 | 25 | 1EFA993D14D9288600A09F03 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /qlgenerator/rsrc/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDocumentTypes 8 | 9 | 10 | CFBundleTypeRole 11 | QLGenerator 12 | LSItemContentTypes 13 | 14 | public.image 15 | public.webp 16 | com.google.webp 17 | fr.whine.bpg 18 | fr.whine.ppm 19 | fr.whine.pbm 20 | fr.whine.pgm 21 | 22 | 23 | 24 | CFBundleExecutable 25 | ${EXECUTABLE_NAME} 26 | CFBundleIconFile 27 | 28 | CFBundleIdentifier 29 | $(PRODUCT_BUNDLE_IDENTIFIER) 30 | CFBundleInfoDictionaryVersion 31 | 6.0 32 | CFBundleName 33 | ${PRODUCT_NAME} 34 | CFBundleShortVersionString 35 | 1 36 | CFBundleVersion 37 | 2.6 38 | CFPlugInDynamicRegisterFunction 39 | 40 | CFPlugInDynamicRegistration 41 | NO 42 | CFPlugInFactories 43 | 44 | B39D1988-F7D1-4420-B89F-4627490F6326 45 | QuickLookGeneratorPluginFactory 46 | 47 | CFPlugInTypes 48 | 49 | 5E2D9680-5022-40FA-B806-43349622E5B9 50 | 51 | B39D1988-F7D1-4420-B89F-4627490F6326 52 | 53 | 54 | CFPlugInUnloadFunction 55 | 56 | NSHumanReadableCopyright 57 | Copyright © 2019 Nyx0uf. All rights reserved. 58 | QLNeedsToBeRunInMainThread 59 | 60 | QLPreviewHeight 61 | 600 62 | QLPreviewWidth 63 | 800 64 | QLSupportsConcurrentRequests 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /qlgenerator/src/GeneratePreviewForURL.m: -------------------------------------------------------------------------------- 1 | // 2 | // GeneratePreviewForURL.c 3 | // qlImageSize 4 | // 5 | // Created by @Nyx0uf on 31/01/12. 6 | // Copyright (c) 2012 Nyx0uf. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | #import "tools.h" 12 | 13 | #ifdef NYX_QL_SUPPORT_BPG_DECODE 14 | #import "bpg_decode.h" 15 | #endif 16 | 17 | #ifdef NYX_QL_SUPPORT_WEBP_DECODE 18 | #import "webp_decode.h" 19 | #endif 20 | 21 | #ifdef NYX_QL_SUPPORT_NETPBM_DECODE 22 | #import "netpbm_decode.h" 23 | #endif 24 | 25 | // To enable logging --> defaults write -g QLEnableLogging NO 26 | OSStatus GeneratePreviewForURL(void* thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options); 27 | void CancelPreviewGeneration(void* thisInterface, QLPreviewRequestRef preview); 28 | void HandleFileForPreview(CFURLRef url, CGImageRef (*decode_fn_ptr)(CFStringRef, image_infos*), QLPreviewRequestRef preview, CFStringRef contentTypeUTI); 29 | CF_RETURNS_RETAINED static CFDictionaryRef _create_properties(CFURLRef url, const size_t size, const size_t width, const size_t height, const size_t dpi, const bool b); 30 | 31 | 32 | OSStatus GeneratePreviewForURL(__unused void* thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, __unused CFDictionaryRef options) 33 | { 34 | @autoreleasepool 35 | { 36 | // Non-standard images (not supported by the OS by default) 37 | // Check by extension because it's highly unprobable that an UTI for these formats is declared 38 | NSString* extension = [[(__bridge NSURL*)url pathExtension] lowercaseString]; 39 | 40 | #ifdef NYX_QL_SUPPORT_BPG_DECODE 41 | if ([extension isEqualToString:@"bpg"]) 42 | { 43 | HandleFileForPreview(url, &decode_bpg_at_path, preview, contentTypeUTI); 44 | return kQLReturnNoError; 45 | } 46 | #endif 47 | #ifdef NYX_QL_SUPPORT_WEBP_DECODE 48 | if ([extension isEqualToString:@"webp"]) 49 | { 50 | HandleFileForPreview(url, &decode_webp_at_path, preview, contentTypeUTI); 51 | return kQLReturnNoError; 52 | } 53 | #endif 54 | #ifdef NYX_QL_SUPPORT_NETPBM_DECODE 55 | if ([extension isEqualToString:@"ppm"] || [extension isEqualToString:@"pgm"] || [extension isEqualToString:@"pbm"]) 56 | { 57 | HandleFileForPreview(url, &decode_netpbm_at_path, preview, contentTypeUTI); 58 | return kQLReturnNoError; 59 | } 60 | #endif 61 | // Standard images (supported by the OS by default) 62 | size_t width = 0, height = 0, dpi = 0, file_size = 0; 63 | properties_for_file(url, &width, &height, &dpi, &file_size); 64 | 65 | // Request preview with updated titlebar 66 | CFDictionaryRef properties = _create_properties(url, file_size, width, height, dpi, false); 67 | QLPreviewRequestSetURLRepresentation(preview, url, contentTypeUTI, properties); 68 | 69 | SAFE_CFRelease(properties); 70 | } 71 | return kQLReturnNoError; 72 | } 73 | 74 | void HandleFileForPreview(CFURLRef url, CGImageRef (*decode_fn_ptr)(CFStringRef, image_infos*), QLPreviewRequestRef preview, CFStringRef contentTypeUTI) 75 | { 76 | // 1. decode the image 77 | if (!QLPreviewRequestIsCancelled(preview)) 78 | { 79 | image_infos infos; 80 | memset(&infos, 0, sizeof(image_infos)); 81 | CFStringRef filepath = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); 82 | CGImageRef img_ref = decode_fn_ptr(filepath, &infos); 83 | SAFE_CFRelease(filepath); 84 | 85 | // 2. render it 86 | CFDictionaryRef properties = _create_properties(url, infos.filesize, infos.width, infos.height, infos.dpi, true); 87 | if (img_ref != NULL) 88 | { 89 | // Have to draw the image ourselves 90 | CGContextRef ctx = QLPreviewRequestCreateContext(preview, (CGSize){.width = infos.width, .height = infos.height}, YES, properties); 91 | CGContextDrawImage(ctx, (CGRect){.origin = CGPointZero, .size.width = infos.width, .size.height = infos.height}, img_ref); 92 | QLPreviewRequestFlushContext(preview, ctx); 93 | CGContextRelease(ctx); 94 | CGImageRelease(img_ref); 95 | } 96 | else 97 | QLPreviewRequestSetURLRepresentation(preview, url, contentTypeUTI, properties); 98 | SAFE_CFRelease(properties); 99 | } 100 | } 101 | 102 | void CancelPreviewGeneration(__unused void* thisInterface, __unused QLPreviewRequestRef preview) 103 | { 104 | } 105 | 106 | CF_RETURNS_RETAINED static CFDictionaryRef _create_properties(CFURLRef url, const size_t size, const size_t width, const size_t height, const size_t dpi, const bool b) 107 | { 108 | // Format file size 109 | NSString* fmt = nil; 110 | if (size > 1048576) // More than 1Mb 111 | fmt = [[NSString alloc] initWithFormat:@"%.1fMb", (float)((float)size / 1048576.0f)]; 112 | else if ((size < 1048576) && (size > 1024)) // 1Kb - 1Mb 113 | fmt = [[NSString alloc] initWithFormat:@"%.2fKb", (float)((float)size / 1024.0f)]; 114 | else // Less than 1Kb 115 | fmt = [[NSString alloc] initWithFormat:@"%zub", size]; 116 | 117 | // Get filename 118 | CFStringRef filename = CFURLCopyLastPathComponent(url); 119 | 120 | // Create props 121 | CFDictionaryRef properties = NULL; 122 | if (b) 123 | { 124 | CFTypeRef keys[3] = {kQLPreviewPropertyDisplayNameKey, kQLPreviewPropertyWidthKey, kQLPreviewPropertyHeightKey}; 125 | // WIDTH×HEIGHTpx • 25.01Kb • filename 126 | CFStringRef title = dpi > 0 ? CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d×%dpx (%ddpi) • %@ • %@"), (int)width, (int)height, (int)dpi, fmt, filename) : CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d×%dpx • %@ • %@"), (int)width, (int)height, fmt, filename); 127 | CFTypeRef values[3] = {title, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &width), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &height)}; 128 | properties = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 129 | SAFE_CFRelease(values[0]); 130 | SAFE_CFRelease(values[1]); 131 | SAFE_CFRelease(values[2]); 132 | } 133 | else 134 | { 135 | CFTypeRef keys[1] = {kQLPreviewPropertyDisplayNameKey}; 136 | // WIDTH×HEIGHTpx • 25.01Kb • filename 137 | CFStringRef title = dpi > 0 ? CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d×%dpx (%ddpi) • %@ • %@"), (int)width, (int)height, (int)dpi, fmt, filename) : CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d×%dpx • %@ • %@"), (int)width, (int)height, fmt, filename); 138 | CFTypeRef values[1] = {title}; 139 | properties = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 140 | SAFE_CFRelease(values[0]); 141 | } 142 | 143 | SAFE_CFRelease(filename); 144 | 145 | return properties; 146 | } 147 | -------------------------------------------------------------------------------- /qlgenerator/src/GenerateThumbnailForURL.m: -------------------------------------------------------------------------------- 1 | // 2 | // GenerateThumbnailForURL.c 3 | // qlImageSize 4 | // 5 | // Created by @Nyx0uf on 31/01/12. 6 | // Copyright (c) 2012 Nyx0uf. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | #import "tools.h" 12 | 13 | #ifdef NYX_QL_SUPPORT_BPG_DECODE 14 | #import "bpg_decode.h" 15 | #endif 16 | 17 | #ifdef NYX_QL_SUPPORT_WEBP_DECODE 18 | #import "webp_decode.h" 19 | #endif 20 | 21 | #ifdef NYX_QL_SUPPORT_NETPBM_DECODE 22 | #import "netpbm_decode.h" 23 | #endif 24 | 25 | 26 | OSStatus GenerateThumbnailForURL(void* thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize); 27 | void CancelThumbnailGeneration(void* thisInterface, QLThumbnailRequestRef thumbnail); 28 | void HandleFileForThumbnail(CFURLRef url, CGImageRef (*decode_fn_ptr)(CFStringRef, image_infos*), QLThumbnailRequestRef thumbnail); 29 | 30 | 31 | OSStatus GenerateThumbnailForURL(__unused void* thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, __unused CFStringRef contentTypeUTI, __unused CFDictionaryRef options, __unused CGSize maxSize) 32 | { 33 | @autoreleasepool 34 | { 35 | // Check by extension because it's highly unprobable that an UTI for these formats is declared 36 | // the simplest way to declare one is creating a dummy automator app and adding imported/exported UTI conforming to public.image 37 | NSString* extension = [[(__bridge NSURL*)url pathExtension] lowercaseString]; 38 | CFDictionaryRef properties = NULL; 39 | 40 | #ifdef NYX_QL_SUPPORT_BPG_DECODE 41 | if ([extension isEqualToString:@"bpg"]) 42 | { 43 | HandleFileForThumbnail(url, &decode_bpg_at_path, thumbnail); 44 | return kQLReturnNoError; 45 | } 46 | #endif 47 | #ifdef NYX_QL_SUPPORT_WEBP_DECODE 48 | if ([extension isEqualToString:@"webp"]) 49 | { 50 | HandleFileForThumbnail(url, &decode_webp_at_path, thumbnail); 51 | return kQLReturnNoError; 52 | } 53 | #endif 54 | #ifdef NYX_QL_SUPPORT_NETPBM_DECODE 55 | if ([extension isEqualToString:@"ppm"] || [extension isEqualToString:@"pgm"] || [extension isEqualToString:@"pbm"]) 56 | { 57 | HandleFileForThumbnail(url, &decode_netpbm_at_path, thumbnail); 58 | return kQLReturnNoError; 59 | } 60 | #endif 61 | QLThumbnailRequestSetImageAtURL(thumbnail, url, properties); 62 | } 63 | return kQLReturnNoError; 64 | } 65 | 66 | void HandleFileForThumbnail(CFURLRef url, CGImageRef (*decode_fn_ptr)(CFStringRef, image_infos*), QLThumbnailRequestRef thumbnail) 67 | { 68 | CFDictionaryRef properties = NULL; 69 | if (!QLThumbnailRequestIsCancelled(thumbnail)) 70 | { 71 | // 1. decode the image 72 | CFStringRef filepath = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); 73 | CGImageRef img_ref = decode_fn_ptr(filepath, NULL); 74 | SAFE_CFRelease(filepath); 75 | 76 | // 2. render it 77 | if (img_ref != NULL) 78 | { 79 | QLThumbnailRequestSetImage(thumbnail, img_ref, properties); 80 | CGImageRelease(img_ref); 81 | } 82 | else 83 | QLThumbnailRequestSetImageAtURL(thumbnail, url, properties); 84 | } 85 | else 86 | QLThumbnailRequestSetImageAtURL(thumbnail, url, properties); 87 | } 88 | 89 | void CancelThumbnailGeneration(__unused void* thisInterface, __unused QLThumbnailRequestRef thumbnail) 90 | { 91 | } 92 | -------------------------------------------------------------------------------- /qlgenerator/src/main.m: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // DO NO MODIFY THE CONTENT OF THIS FILE 4 | // 5 | // This file contains the generic CFPlug-in code necessary for your generator 6 | // To complete your generator implement the function in GenerateThumbnailForURL/GeneratePreviewForURL.c 7 | // 8 | //============================================================================== 9 | 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // ----------------------------------------------------------------------------- 16 | // constants 17 | // ----------------------------------------------------------------------------- 18 | 19 | // Don't modify this line 20 | #define PLUGIN_ID "B39D1988-F7D1-4420-B89F-4627490F6326" 21 | 22 | // 23 | // Below is the generic glue code for all plug-ins. 24 | // 25 | // You should not have to modify this code aside from changing 26 | // names if you decide to change the names defined in the Info.plist 27 | // 28 | 29 | 30 | // ----------------------------------------------------------------------------- 31 | // typedefs 32 | // ----------------------------------------------------------------------------- 33 | 34 | // The thumbnail generation function to be implemented in GenerateThumbnailForURL.c 35 | OSStatus GenerateThumbnailForURL(void* thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize); 36 | void CancelThumbnailGeneration(void* thisInterface, QLThumbnailRequestRef thumbnail); 37 | 38 | // The preview generation function to be implemented in GeneratePreviewForURL.c 39 | OSStatus GeneratePreviewForURL(void* thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options); 40 | void CancelPreviewGeneration(void* thisInterface, QLPreviewRequestRef preview); 41 | 42 | // The layout for an instance of QuickLookGeneratorPlugIn 43 | typedef struct __QuickLookGeneratorPluginType 44 | { 45 | void* conduitInterface; 46 | CFUUIDRef factoryID; 47 | UInt32 refCount; 48 | } QuickLookGeneratorPluginType; 49 | 50 | // ----------------------------------------------------------------------------- 51 | // prototypes 52 | // ----------------------------------------------------------------------------- 53 | // Forward declaration for the IUnknown implementation. 54 | // 55 | 56 | QuickLookGeneratorPluginType* AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID); 57 | void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType* thisInstance); 58 | HRESULT QuickLookGeneratorQueryInterface(void* thisInstance, REFIID iid, LPVOID* ppv); 59 | void* QuickLookGeneratorPluginFactory(CFAllocatorRef allocator, CFUUIDRef typeID); 60 | ULONG QuickLookGeneratorPluginAddRef(void* thisInstance); 61 | ULONG QuickLookGeneratorPluginRelease(void* thisInstance); 62 | 63 | // ----------------------------------------------------------------------------- 64 | // myInterfaceFtbl definition 65 | // ----------------------------------------------------------------------------- 66 | // The QLGeneratorInterfaceStruct function table. 67 | // 68 | static QLGeneratorInterfaceStruct myInterfaceFtbl = { 69 | NULL, 70 | QuickLookGeneratorQueryInterface, 71 | QuickLookGeneratorPluginAddRef, 72 | QuickLookGeneratorPluginRelease, 73 | NULL, 74 | NULL, 75 | NULL, 76 | NULL 77 | }; 78 | 79 | 80 | // ----------------------------------------------------------------------------- 81 | // AllocQuickLookGeneratorPluginType 82 | // ----------------------------------------------------------------------------- 83 | // Utility function that allocates a new instance. 84 | // You can do some initial setup for the generator here if you wish 85 | // like allocating globals etc... 86 | // 87 | QuickLookGeneratorPluginType* AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID) 88 | { 89 | QuickLookGeneratorPluginType* theNewInstance; 90 | 91 | theNewInstance = (QuickLookGeneratorPluginType*)malloc(sizeof(QuickLookGeneratorPluginType)); 92 | memset(theNewInstance, 0, sizeof(QuickLookGeneratorPluginType)); 93 | 94 | /* Point to the function table Malloc enough to store the stuff and copy the filler from myInterfaceFtbl over */ 95 | theNewInstance->conduitInterface = malloc(sizeof(QLGeneratorInterfaceStruct)); 96 | memcpy(theNewInstance->conduitInterface, &myInterfaceFtbl, sizeof(QLGeneratorInterfaceStruct)); 97 | 98 | /* Retain and keep an open instance refcount for each factory. */ 99 | theNewInstance->factoryID = CFRetain(inFactoryID); 100 | CFPlugInAddInstanceForFactory(inFactoryID); 101 | 102 | /* This function returns the IUnknown interface so set the refCount to one. */ 103 | theNewInstance->refCount = 1; 104 | return theNewInstance; 105 | } 106 | 107 | // ----------------------------------------------------------------------------- 108 | // DeallocQuickLookGeneratorPluginType 109 | // ----------------------------------------------------------------------------- 110 | // Utility function that deallocates the instance when 111 | // the refCount goes to zero. 112 | // In the current implementation generator interfaces are never deallocated 113 | // but implement this as this might change in the future 114 | // 115 | void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType* thisInstance) 116 | { 117 | CFUUIDRef theFactoryID; 118 | 119 | theFactoryID = thisInstance->factoryID; 120 | /* Free the conduitInterface table up */ 121 | free(thisInstance->conduitInterface); 122 | 123 | /* Free the instance structure */ 124 | free(thisInstance); 125 | if (theFactoryID) 126 | { 127 | CFPlugInRemoveInstanceForFactory(theFactoryID); 128 | CFRelease(theFactoryID); 129 | } 130 | } 131 | 132 | // ----------------------------------------------------------------------------- 133 | // QuickLookGeneratorQueryInterface 134 | // ----------------------------------------------------------------------------- 135 | // Implementation of the IUnknown QueryInterface function. 136 | // 137 | HRESULT QuickLookGeneratorQueryInterface(void* thisInstance, REFIID iid, LPVOID* ppv) 138 | { 139 | CFUUIDRef interfaceID; 140 | 141 | interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault,iid); 142 | 143 | if (CFEqual(interfaceID, kQLGeneratorCallbacksInterfaceID)) 144 | { 145 | /* If the Right interface was requested, bump the ref count, 146 | * set the ppv parameter equal to the instance, and 147 | * return good status. 148 | */ 149 | ((QLGeneratorInterfaceStruct*)((QuickLookGeneratorPluginType*)thisInstance)->conduitInterface)->GenerateThumbnailForURL = GenerateThumbnailForURL; 150 | ((QLGeneratorInterfaceStruct*)((QuickLookGeneratorPluginType*)thisInstance)->conduitInterface)->CancelThumbnailGeneration = CancelThumbnailGeneration; 151 | ((QLGeneratorInterfaceStruct*)((QuickLookGeneratorPluginType*)thisInstance)->conduitInterface)->GeneratePreviewForURL = GeneratePreviewForURL; 152 | ((QLGeneratorInterfaceStruct*)((QuickLookGeneratorPluginType*)thisInstance)->conduitInterface)->CancelPreviewGeneration = CancelPreviewGeneration; 153 | ((QLGeneratorInterfaceStruct*)((QuickLookGeneratorPluginType*)thisInstance)->conduitInterface)->AddRef(thisInstance); 154 | *ppv = thisInstance; 155 | CFRelease(interfaceID); 156 | return S_OK; 157 | } 158 | else 159 | { 160 | /* Requested interface unknown, bail with error. */ 161 | *ppv = NULL; 162 | CFRelease(interfaceID); 163 | return E_NOINTERFACE; 164 | } 165 | } 166 | 167 | // ----------------------------------------------------------------------------- 168 | // QuickLookGeneratorPluginAddRef 169 | // ----------------------------------------------------------------------------- 170 | // Implementation of reference counting for this type. Whenever an interface 171 | // is requested, bump the refCount for the instance. NOTE: returning the 172 | // refcount is a convention but is not required so don't rely on it. 173 | // 174 | ULONG QuickLookGeneratorPluginAddRef(void* thisInstance) 175 | { 176 | ((QuickLookGeneratorPluginType*)thisInstance)->refCount += 1; 177 | return ((QuickLookGeneratorPluginType*)thisInstance)->refCount; 178 | } 179 | 180 | // ----------------------------------------------------------------------------- 181 | // QuickLookGeneratorPluginRelease 182 | // ----------------------------------------------------------------------------- 183 | // When an interface is released, decrement the refCount. 184 | // If the refCount goes to zero, deallocate the instance. 185 | // 186 | ULONG QuickLookGeneratorPluginRelease(void* thisInstance) 187 | { 188 | ((QuickLookGeneratorPluginType*)thisInstance)->refCount -= 1; 189 | if (((QuickLookGeneratorPluginType*)thisInstance)->refCount == 0) 190 | { 191 | DeallocQuickLookGeneratorPluginType((QuickLookGeneratorPluginType*)thisInstance); 192 | return 0; 193 | } 194 | else 195 | { 196 | return ((QuickLookGeneratorPluginType*)thisInstance)->refCount; 197 | } 198 | } 199 | 200 | // ----------------------------------------------------------------------------- 201 | // QuickLookGeneratorPluginFactory 202 | // ----------------------------------------------------------------------------- 203 | void* QuickLookGeneratorPluginFactory(CFAllocatorRef __unused allocator, CFUUIDRef typeID) 204 | { 205 | QuickLookGeneratorPluginType* result; 206 | CFUUIDRef uuid; 207 | 208 | /* If correct type is being requested, allocate an 209 | * instance of kQLGeneratorTypeID and return the IUnknown interface. 210 | */ 211 | if (CFEqual(typeID, kQLGeneratorTypeID)) 212 | { 213 | uuid = CFUUIDCreateFromString(kCFAllocatorDefault, CFSTR(PLUGIN_ID)); 214 | result = AllocQuickLookGeneratorPluginType(uuid); 215 | CFRelease(uuid); 216 | return result; 217 | } 218 | /* If the requested type is incorrect, return NULL. */ 219 | return NULL; 220 | } 221 | --------------------------------------------------------------------------------