├── ql-iff.zip ├── screenshot.png ├── ql-iff ├── en.lproj │ └── InfoPlist.strings ├── ql-iff-Prefix.pch ├── GenerateThumbnailForURL.c ├── GeneratePreviewForURL.c ├── ql-iff-Info.plist └── main.c ├── readme.txt ├── README.md ├── iff.h ├── ql-iff.xcodeproj └── project.pbxproj └── iff.c /ql-iff.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dalton-tulou/ql-iff/HEAD/ql-iff.zip -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dalton-tulou/ql-iff/HEAD/screenshot.png -------------------------------------------------------------------------------- /ql-iff/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /ql-iff/ql-iff-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'ql-iff' target in the 'ql-iff' project 3 | // 4 | 5 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | OS X Quick Look plugin for IFF ILBM images 2 | Version 1.0 Beta (March 22, 2013) 3 | 4 | 5 | Supported IFF-features: 6 | 7 | * ILBM and PBM 8 | * 1-8 bitplanes 9 | * Extra halfbrite 10 | * Hold and modify 11 | * Transparency 12 | 13 | 14 | Install: 15 | 16 | * For one user, copy iff.qlgenerator to ~/Library/QuickLook/ 17 | * For all users, copy iff.qlgenerator to /Library/QuickLook/ 18 | 19 | 20 | Download latest version from http://www.modermodemet.se/ 21 | 22 | Source code available at https://github.com/dalton-tulou/ql-iff 23 | 24 | 25 | Coded by David Revelj 26 | 27 | Please send bug reports and non-working IFF files to dalton@tulou.org 28 | 29 | 30 | 31 | 32 | Be cool, stay in school! 33 | 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ql-iff 2 | ====== 3 | 4 | OS X Quick Look plugin for IFF ILBM images 5 | Version 1.0 Beta (March 22, 2013) 6 | 7 | ![screenshot](screenshot.png) 8 | 9 | Supported IFF-features: 10 | 11 | * ILBM and PBM 12 | * 1-8 bitplanes 13 | * Extra halfbrite 14 | * Hold and modify 15 | * Transparency 16 | 17 | Install: 18 | 19 | * For one user, copy iff.qlgenerator to ~/Library/QuickLook/ 20 | * For all users, copy iff.qlgenerator to /Library/QuickLook/ 21 | 22 | Download latest version from [https://github.com/dalton-tulou/ql-iff/releases/download/v1.0-beta/ql-iff.zip](https://github.com/dalton-tulou/ql-iff/releases/download/v1.0-beta/ql-iff.zip) 23 | 24 | Source code available at https://github.com/dalton-tulou/ql-iff 25 | 26 | Coded by David Revelj 27 | 28 | Be cool, stay in school! 29 | -------------------------------------------------------------------------------- /ql-iff/GenerateThumbnailForURL.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "iff.h" 5 | 6 | OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize); 7 | void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail); 8 | 9 | /* ----------------------------------------------------------------------------- 10 | Generate a thumbnail for file 11 | 12 | This function's job is to create thumbnail for designated file as fast as possible 13 | ----------------------------------------------------------------------------- */ 14 | 15 | OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize) 16 | { 17 | CGImageRef image = iff_createImage(url, true); 18 | 19 | if (image) 20 | { 21 | QLThumbnailRequestSetImage(thumbnail, image, NULL); 22 | } 23 | 24 | return noErr; 25 | } 26 | 27 | void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail) 28 | { 29 | // Implement only if supported 30 | } 31 | -------------------------------------------------------------------------------- /iff.h: -------------------------------------------------------------------------------- 1 | /* 2 | * iff.h 3 | * ql_plugin_test_2 4 | * 5 | * Created by David R on 13-03-09. 6 | * Copyright 2013 __MyCompanyName__. All rights reserved. 7 | * 8 | */ 9 | 10 | #include 11 | 12 | typedef struct 13 | { 14 | uint32_t id; 15 | uint32_t size; 16 | } 17 | header_t; 18 | 19 | typedef struct 20 | { 21 | header_t header; 22 | uint32_t type; 23 | } 24 | form_t; 25 | 26 | typedef struct 27 | { 28 | header_t header; 29 | uint16_t w,h; /* raster width & height in pixels */ 30 | int16_t x,y; /* pixel position for this image */ 31 | uint8_t nPlanes; /* # source bitplanes */ 32 | uint8_t masking; 33 | uint8_t compression; 34 | uint8_t pad1; /* unused; for consistency, put 0 here */ 35 | uint16_t transparentColor; /* transparent "color number" (sort of) */ 36 | uint8_t xAspect, yAspect; /* pixel aspect, a ratio width : height */ 37 | int16_t pageWidth, pageHeight; /* source "page" size in pixels */ 38 | } 39 | bmhd_t; 40 | 41 | typedef struct 42 | { 43 | header_t header; 44 | uint8_t data; 45 | } 46 | cmap_t; 47 | 48 | typedef struct 49 | { 50 | header_t header; 51 | uint8_t data; 52 | } 53 | body_t; 54 | 55 | typedef struct 56 | { 57 | header_t header; 58 | uint32_t viewMode; 59 | } 60 | camg_t; 61 | 62 | typedef struct 63 | { 64 | form_t *form; 65 | bmhd_t *bmhd; 66 | camg_t *camg; 67 | cmap_t *cmap; 68 | body_t *body; 69 | } 70 | chunkMap_t; 71 | 72 | CGImageRef iff_createImage(CFURLRef url, bool withAlpha); 73 | 74 | -------------------------------------------------------------------------------- /ql-iff/GeneratePreviewForURL.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "iff.h" 5 | 6 | OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options); 7 | void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview); 8 | 9 | /* ----------------------------------------------------------------------------- 10 | Generate a preview for file 11 | 12 | This function's job is to create preview for designated file 13 | ----------------------------------------------------------------------------- */ 14 | 15 | OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options) 16 | { 17 | CGImageRef image = iff_createImage(url, false); 18 | 19 | if (!image) 20 | { 21 | return noErr; 22 | } 23 | 24 | size_t width = CGImageGetWidth(image); 25 | size_t height = CGImageGetHeight(image); 26 | 27 | CGContextRef context = QLPreviewRequestCreateContext(preview, CGSizeMake(width, height), false, NULL); 28 | 29 | if (!context) 30 | { 31 | return noErr; 32 | } 33 | 34 | // CGColorRef color = CGColorCreateGenericRGB(0.0, 1.0, 0.0, 1.0); 35 | // CGContextSetFillColorWithColor(context, color); 36 | // CGContextFillRect(context, CGRectMake(0, 0, width, height)); 37 | 38 | CGContextDrawImage(context, CGRectMake(0, 0, width, height), image); 39 | 40 | CGImageRelease(image); 41 | 42 | QLPreviewRequestFlushContext(preview, context); 43 | CFRelease(context); 44 | 45 | return noErr; 46 | } 47 | 48 | void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview) 49 | { 50 | // Implement only if supported 51 | } 52 | -------------------------------------------------------------------------------- /ql-iff/ql-iff-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDocumentTypes 8 | 9 | 10 | CFBundleTypeRole 11 | QLGenerator 12 | LSItemContentTypes 13 | 14 | com.ea.iff-ilbm 15 | 16 | 17 | 18 | CFBundleExecutable 19 | ${EXECUTABLE_NAME} 20 | CFBundleIconFile 21 | 22 | CFBundleIdentifier 23 | tlu.${PRODUCT_NAME:rfc1034identifier} 24 | CFBundleInfoDictionaryVersion 25 | 6.0 26 | CFBundleName 27 | ${PRODUCT_NAME} 28 | CFBundleShortVersionString 29 | 30 | CFBundleVersion 31 | 1.0 Beta 32 | CFPlugInDynamicRegisterFunction 33 | 34 | CFPlugInDynamicRegistration 35 | NO 36 | CFPlugInFactories 37 | 38 | B3A65A51-E272-4667-A260-C59FC5D5DBBB 39 | QuickLookGeneratorPluginFactory 40 | 41 | CFPlugInTypes 42 | 43 | 5E2D9680-5022-40FA-B806-43349622E5B9 44 | 45 | B3A65A51-E272-4667-A260-C59FC5D5DBBB 46 | 47 | 48 | CFPlugInUnloadFunction 49 | 50 | NSHumanReadableCopyright 51 | Copyright © 2013 Tulou. All rights reserved. 52 | QLNeedsToBeRunInMainThread 53 | 54 | QLPreviewHeight 55 | 512 56 | QLPreviewWidth 57 | 640 58 | QLSupportsConcurrentRequests 59 | 60 | UTImportedTypeDeclarations 61 | 62 | 63 | UTTypeConformsTo 64 | 65 | public.image 66 | 67 | UTTypeIdentifier 68 | com.ea.iff-ilbm 69 | UTTypeTagSpecification 70 | 71 | public.mime-type 72 | 73 | application/x-iff 74 | image/ilbm 75 | image/x-ilbm 76 | 77 | public.filename-extension 78 | 79 | iff 80 | ilbm 81 | lbm 82 | 83 | 84 | UTTypeDescription 85 | IFF ILBM 86 | 87 | 88 | QLThumbnailMinimumSize 89 | 17 90 | 91 | 92 | -------------------------------------------------------------------------------- /ql-iff/main.c: -------------------------------------------------------------------------------- 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 | 12 | 13 | 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | // ----------------------------------------------------------------------------- 21 | // constants 22 | // ----------------------------------------------------------------------------- 23 | 24 | // Don't modify this line 25 | #define PLUGIN_ID "B3A65A51-E272-4667-A260-C59FC5D5DBBB" 26 | 27 | // 28 | // Below is the generic glue code for all plug-ins. 29 | // 30 | // You should not have to modify this code aside from changing 31 | // names if you decide to change the names defined in the Info.plist 32 | // 33 | 34 | 35 | // ----------------------------------------------------------------------------- 36 | // typedefs 37 | // ----------------------------------------------------------------------------- 38 | 39 | // The thumbnail generation function to be implemented in GenerateThumbnailForURL.c 40 | OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize); 41 | void CancelThumbnailGeneration(void* thisInterface, QLThumbnailRequestRef thumbnail); 42 | 43 | // The preview generation function to be implemented in GeneratePreviewForURL.c 44 | OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options); 45 | void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview); 46 | 47 | // The layout for an instance of QuickLookGeneratorPlugIn 48 | typedef struct __QuickLookGeneratorPluginType 49 | { 50 | void *conduitInterface; 51 | CFUUIDRef factoryID; 52 | UInt32 refCount; 53 | } QuickLookGeneratorPluginType; 54 | 55 | // ----------------------------------------------------------------------------- 56 | // prototypes 57 | // ----------------------------------------------------------------------------- 58 | // Forward declaration for the IUnknown implementation. 59 | // 60 | 61 | QuickLookGeneratorPluginType *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID); 62 | void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance); 63 | HRESULT QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv); 64 | void *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID); 65 | ULONG QuickLookGeneratorPluginAddRef(void *thisInstance); 66 | ULONG QuickLookGeneratorPluginRelease(void *thisInstance); 67 | 68 | // ----------------------------------------------------------------------------- 69 | // myInterfaceFtbl definition 70 | // ----------------------------------------------------------------------------- 71 | // The QLGeneratorInterfaceStruct function table. 72 | // 73 | static QLGeneratorInterfaceStruct myInterfaceFtbl = { 74 | NULL, 75 | QuickLookGeneratorQueryInterface, 76 | QuickLookGeneratorPluginAddRef, 77 | QuickLookGeneratorPluginRelease, 78 | NULL, 79 | NULL, 80 | NULL, 81 | NULL 82 | }; 83 | 84 | 85 | // ----------------------------------------------------------------------------- 86 | // AllocQuickLookGeneratorPluginType 87 | // ----------------------------------------------------------------------------- 88 | // Utility function that allocates a new instance. 89 | // You can do some initial setup for the generator here if you wish 90 | // like allocating globals etc... 91 | // 92 | QuickLookGeneratorPluginType *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID) 93 | { 94 | QuickLookGeneratorPluginType *theNewInstance; 95 | 96 | theNewInstance = (QuickLookGeneratorPluginType *)malloc(sizeof(QuickLookGeneratorPluginType)); 97 | memset(theNewInstance,0,sizeof(QuickLookGeneratorPluginType)); 98 | 99 | /* Point to the function table Malloc enough to store the stuff and copy the filler from myInterfaceFtbl over */ 100 | theNewInstance->conduitInterface = malloc(sizeof(QLGeneratorInterfaceStruct)); 101 | memcpy(theNewInstance->conduitInterface,&myInterfaceFtbl,sizeof(QLGeneratorInterfaceStruct)); 102 | 103 | /* Retain and keep an open instance refcount for each factory. */ 104 | theNewInstance->factoryID = CFRetain(inFactoryID); 105 | CFPlugInAddInstanceForFactory(inFactoryID); 106 | 107 | /* This function returns the IUnknown interface so set the refCount to one. */ 108 | theNewInstance->refCount = 1; 109 | return theNewInstance; 110 | } 111 | 112 | // ----------------------------------------------------------------------------- 113 | // DeallocQuickLookGeneratorPluginType 114 | // ----------------------------------------------------------------------------- 115 | // Utility function that deallocates the instance when 116 | // the refCount goes to zero. 117 | // In the current implementation generator interfaces are never deallocated 118 | // but implement this as this might change in the future 119 | // 120 | void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance) 121 | { 122 | CFUUIDRef theFactoryID; 123 | 124 | theFactoryID = thisInstance->factoryID; 125 | /* Free the conduitInterface table up */ 126 | free(thisInstance->conduitInterface); 127 | 128 | /* Free the instance structure */ 129 | free(thisInstance); 130 | if (theFactoryID){ 131 | CFPlugInRemoveInstanceForFactory(theFactoryID); 132 | CFRelease(theFactoryID); 133 | } 134 | } 135 | 136 | // ----------------------------------------------------------------------------- 137 | // QuickLookGeneratorQueryInterface 138 | // ----------------------------------------------------------------------------- 139 | // Implementation of the IUnknown QueryInterface function. 140 | // 141 | HRESULT QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv) 142 | { 143 | CFUUIDRef interfaceID; 144 | 145 | interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault,iid); 146 | 147 | if (CFEqual(interfaceID,kQLGeneratorCallbacksInterfaceID)){ 148 | /* If the Right interface was requested, bump the ref count, 149 | * set the ppv parameter equal to the instance, and 150 | * return good status. 151 | */ 152 | ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GenerateThumbnailForURL = GenerateThumbnailForURL; 153 | ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelThumbnailGeneration = CancelThumbnailGeneration; 154 | ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GeneratePreviewForURL = GeneratePreviewForURL; 155 | ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelPreviewGeneration = CancelPreviewGeneration; 156 | ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType*)thisInstance)->conduitInterface)->AddRef(thisInstance); 157 | *ppv = thisInstance; 158 | CFRelease(interfaceID); 159 | return S_OK; 160 | }else{ 161 | /* Requested interface unknown, bail with error. */ 162 | *ppv = NULL; 163 | CFRelease(interfaceID); 164 | return E_NOINTERFACE; 165 | } 166 | } 167 | 168 | // ----------------------------------------------------------------------------- 169 | // QuickLookGeneratorPluginAddRef 170 | // ----------------------------------------------------------------------------- 171 | // Implementation of reference counting for this type. Whenever an interface 172 | // is requested, bump the refCount for the instance. NOTE: returning the 173 | // refcount is a convention but is not required so don't rely on it. 174 | // 175 | ULONG QuickLookGeneratorPluginAddRef(void *thisInstance) 176 | { 177 | ((QuickLookGeneratorPluginType *)thisInstance )->refCount += 1; 178 | return ((QuickLookGeneratorPluginType*) thisInstance)->refCount; 179 | } 180 | 181 | // ----------------------------------------------------------------------------- 182 | // QuickLookGeneratorPluginRelease 183 | // ----------------------------------------------------------------------------- 184 | // When an interface is released, decrement the refCount. 185 | // If the refCount goes to zero, deallocate the instance. 186 | // 187 | ULONG QuickLookGeneratorPluginRelease(void *thisInstance) 188 | { 189 | ((QuickLookGeneratorPluginType*)thisInstance)->refCount -= 1; 190 | if (((QuickLookGeneratorPluginType*)thisInstance)->refCount == 0){ 191 | DeallocQuickLookGeneratorPluginType((QuickLookGeneratorPluginType*)thisInstance ); 192 | return 0; 193 | }else{ 194 | return ((QuickLookGeneratorPluginType*) thisInstance )->refCount; 195 | } 196 | } 197 | 198 | // ----------------------------------------------------------------------------- 199 | // QuickLookGeneratorPluginFactory 200 | // ----------------------------------------------------------------------------- 201 | void *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID) 202 | { 203 | QuickLookGeneratorPluginType *result; 204 | CFUUIDRef uuid; 205 | 206 | /* If correct type is being requested, allocate an 207 | * instance of kQLGeneratorTypeID and return the IUnknown interface. 208 | */ 209 | if (CFEqual(typeID,kQLGeneratorTypeID)){ 210 | uuid = CFUUIDCreateFromString(kCFAllocatorDefault,CFSTR(PLUGIN_ID)); 211 | result = AllocQuickLookGeneratorPluginType(uuid); 212 | CFRelease(uuid); 213 | return result; 214 | } 215 | /* If the requested type is incorrect, return NULL. */ 216 | return NULL; 217 | } 218 | 219 | -------------------------------------------------------------------------------- /ql-iff.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 635477E116F127580032D294 /* iff.qlgenerator in CopyFiles */ = {isa = PBXBuildFile; fileRef = 639C91D416F0E8D0008C3BF1 /* iff.qlgenerator */; }; 11 | 637175B516FD06AD0016726E /* readme.txt in Resources */ = {isa = PBXBuildFile; fileRef = 637175B416FD06AD0016726E /* readme.txt */; }; 12 | 639C91D816F0E8D0008C3BF1 /* QuickLook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 639C91D716F0E8D0008C3BF1 /* QuickLook.framework */; }; 13 | 639C91DA16F0E8D0008C3BF1 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 639C91D916F0E8D0008C3BF1 /* ApplicationServices.framework */; }; 14 | 639C91DC16F0E8D0008C3BF1 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 639C91DB16F0E8D0008C3BF1 /* CoreServices.framework */; }; 15 | 639C91DE16F0E8D0008C3BF1 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 639C91DD16F0E8D0008C3BF1 /* CoreFoundation.framework */; }; 16 | 639C91E416F0E8D0008C3BF1 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 639C91E216F0E8D0008C3BF1 /* InfoPlist.strings */; }; 17 | 639C91E616F0E8D0008C3BF1 /* GenerateThumbnailForURL.c in Sources */ = {isa = PBXBuildFile; fileRef = 639C91E516F0E8D0008C3BF1 /* GenerateThumbnailForURL.c */; }; 18 | 639C91E816F0E8D0008C3BF1 /* GeneratePreviewForURL.c in Sources */ = {isa = PBXBuildFile; fileRef = 639C91E716F0E8D0008C3BF1 /* GeneratePreviewForURL.c */; }; 19 | 639C91EA16F0E8D0008C3BF1 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 639C91E916F0E8D0008C3BF1 /* main.c */; }; 20 | 63BF78D516F115A4008D1D69 /* iff.c in Sources */ = {isa = PBXBuildFile; fileRef = 63BF78D316F115A4008D1D69 /* iff.c */; }; 21 | 63BF78D616F115A4008D1D69 /* iff.h in Headers */ = {isa = PBXBuildFile; fileRef = 63BF78D416F115A4008D1D69 /* iff.h */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXCopyFilesBuildPhase section */ 25 | 635477DF16F127490032D294 /* CopyFiles */ = { 26 | isa = PBXCopyFilesBuildPhase; 27 | buildActionMask = 2147483647; 28 | dstPath = "~/Library/QuickLook/"; 29 | dstSubfolderSpec = 0; 30 | files = ( 31 | 635477E116F127580032D294 /* iff.qlgenerator in CopyFiles */, 32 | ); 33 | runOnlyForDeploymentPostprocessing = 0; 34 | }; 35 | /* End PBXCopyFilesBuildPhase section */ 36 | 37 | /* Begin PBXFileReference section */ 38 | 637175B416FD06AD0016726E /* readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = readme.txt; sourceTree = SOURCE_ROOT; }; 39 | 639C91D416F0E8D0008C3BF1 /* iff.qlgenerator */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = iff.qlgenerator; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | 639C91D716F0E8D0008C3BF1 /* QuickLook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLook.framework; path = System/Library/Frameworks/QuickLook.framework; sourceTree = SDKROOT; }; 41 | 639C91D916F0E8D0008C3BF1 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = System/Library/Frameworks/ApplicationServices.framework; sourceTree = SDKROOT; }; 42 | 639C91DB16F0E8D0008C3BF1 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; 43 | 639C91DD16F0E8D0008C3BF1 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; 44 | 639C91E116F0E8D0008C3BF1 /* ql-iff-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ql-iff-Info.plist"; sourceTree = ""; }; 45 | 639C91E316F0E8D0008C3BF1 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 46 | 639C91E516F0E8D0008C3BF1 /* GenerateThumbnailForURL.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = GenerateThumbnailForURL.c; sourceTree = ""; }; 47 | 639C91E716F0E8D0008C3BF1 /* GeneratePreviewForURL.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = GeneratePreviewForURL.c; sourceTree = ""; }; 48 | 639C91E916F0E8D0008C3BF1 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; 49 | 639C91EB16F0E8D0008C3BF1 /* ql-iff-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ql-iff-Prefix.pch"; sourceTree = ""; }; 50 | 63BF78D316F115A4008D1D69 /* iff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = iff.c; path = ../iff.c; sourceTree = ""; }; 51 | 63BF78D416F115A4008D1D69 /* iff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = iff.h; path = ../iff.h; sourceTree = ""; }; 52 | /* End PBXFileReference section */ 53 | 54 | /* Begin PBXFrameworksBuildPhase section */ 55 | 639C91CF16F0E8D0008C3BF1 /* Frameworks */ = { 56 | isa = PBXFrameworksBuildPhase; 57 | buildActionMask = 2147483647; 58 | files = ( 59 | 639C91D816F0E8D0008C3BF1 /* QuickLook.framework in Frameworks */, 60 | 639C91DA16F0E8D0008C3BF1 /* ApplicationServices.framework in Frameworks */, 61 | 639C91DC16F0E8D0008C3BF1 /* CoreServices.framework in Frameworks */, 62 | 639C91DE16F0E8D0008C3BF1 /* CoreFoundation.framework in Frameworks */, 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | 639C91C716F0E8D0008C3BF1 = { 70 | isa = PBXGroup; 71 | children = ( 72 | 639C91DF16F0E8D0008C3BF1 /* ql-iff */, 73 | 639C91D616F0E8D0008C3BF1 /* Frameworks */, 74 | 639C91D516F0E8D0008C3BF1 /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 639C91D516F0E8D0008C3BF1 /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 639C91D416F0E8D0008C3BF1 /* iff.qlgenerator */, 82 | ); 83 | name = Products; 84 | sourceTree = ""; 85 | }; 86 | 639C91D616F0E8D0008C3BF1 /* Frameworks */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 639C91D716F0E8D0008C3BF1 /* QuickLook.framework */, 90 | 639C91D916F0E8D0008C3BF1 /* ApplicationServices.framework */, 91 | 639C91DB16F0E8D0008C3BF1 /* CoreServices.framework */, 92 | 639C91DD16F0E8D0008C3BF1 /* CoreFoundation.framework */, 93 | ); 94 | name = Frameworks; 95 | sourceTree = ""; 96 | }; 97 | 639C91DF16F0E8D0008C3BF1 /* ql-iff */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 63BF78D316F115A4008D1D69 /* iff.c */, 101 | 63BF78D416F115A4008D1D69 /* iff.h */, 102 | 639C91E516F0E8D0008C3BF1 /* GenerateThumbnailForURL.c */, 103 | 639C91E716F0E8D0008C3BF1 /* GeneratePreviewForURL.c */, 104 | 639C91E916F0E8D0008C3BF1 /* main.c */, 105 | 639C91E016F0E8D0008C3BF1 /* Supporting Files */, 106 | 637175B416FD06AD0016726E /* readme.txt */, 107 | ); 108 | path = "ql-iff"; 109 | sourceTree = ""; 110 | }; 111 | 639C91E016F0E8D0008C3BF1 /* Supporting Files */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 639C91E116F0E8D0008C3BF1 /* ql-iff-Info.plist */, 115 | 639C91E216F0E8D0008C3BF1 /* InfoPlist.strings */, 116 | 639C91EB16F0E8D0008C3BF1 /* ql-iff-Prefix.pch */, 117 | ); 118 | name = "Supporting Files"; 119 | sourceTree = ""; 120 | }; 121 | /* End PBXGroup section */ 122 | 123 | /* Begin PBXHeadersBuildPhase section */ 124 | 639C91D016F0E8D0008C3BF1 /* Headers */ = { 125 | isa = PBXHeadersBuildPhase; 126 | buildActionMask = 2147483647; 127 | files = ( 128 | 63BF78D616F115A4008D1D69 /* iff.h in Headers */, 129 | ); 130 | runOnlyForDeploymentPostprocessing = 0; 131 | }; 132 | /* End PBXHeadersBuildPhase section */ 133 | 134 | /* Begin PBXNativeTarget section */ 135 | 639C91D316F0E8D0008C3BF1 /* ql-iff */ = { 136 | isa = PBXNativeTarget; 137 | buildConfigurationList = 639C91EE16F0E8D0008C3BF1 /* Build configuration list for PBXNativeTarget "ql-iff" */; 138 | buildPhases = ( 139 | 639C91CE16F0E8D0008C3BF1 /* Sources */, 140 | 639C91CF16F0E8D0008C3BF1 /* Frameworks */, 141 | 639C91D016F0E8D0008C3BF1 /* Headers */, 142 | 639C91D116F0E8D0008C3BF1 /* Resources */, 143 | 639C91D216F0E8D0008C3BF1 /* Rez */, 144 | 635477DF16F127490032D294 /* CopyFiles */, 145 | ); 146 | buildRules = ( 147 | ); 148 | dependencies = ( 149 | ); 150 | name = "ql-iff"; 151 | productName = "ql-iff"; 152 | productReference = 639C91D416F0E8D0008C3BF1 /* iff.qlgenerator */; 153 | productType = "com.apple.product-type.bundle"; 154 | }; 155 | /* End PBXNativeTarget section */ 156 | 157 | /* Begin PBXProject section */ 158 | 639C91C916F0E8D0008C3BF1 /* Project object */ = { 159 | isa = PBXProject; 160 | attributes = { 161 | LastUpgradeCheck = 0440; 162 | ORGANIZATIONNAME = Tulou; 163 | }; 164 | buildConfigurationList = 639C91CC16F0E8D0008C3BF1 /* Build configuration list for PBXProject "ql-iff" */; 165 | compatibilityVersion = "Xcode 3.2"; 166 | developmentRegion = English; 167 | hasScannedForEncodings = 0; 168 | knownRegions = ( 169 | en, 170 | ); 171 | mainGroup = 639C91C716F0E8D0008C3BF1; 172 | productRefGroup = 639C91D516F0E8D0008C3BF1 /* Products */; 173 | projectDirPath = ""; 174 | projectRoot = ""; 175 | targets = ( 176 | 639C91D316F0E8D0008C3BF1 /* ql-iff */, 177 | ); 178 | }; 179 | /* End PBXProject section */ 180 | 181 | /* Begin PBXResourcesBuildPhase section */ 182 | 639C91D116F0E8D0008C3BF1 /* Resources */ = { 183 | isa = PBXResourcesBuildPhase; 184 | buildActionMask = 2147483647; 185 | files = ( 186 | 639C91E416F0E8D0008C3BF1 /* InfoPlist.strings in Resources */, 187 | 637175B516FD06AD0016726E /* readme.txt in Resources */, 188 | ); 189 | runOnlyForDeploymentPostprocessing = 0; 190 | }; 191 | /* End PBXResourcesBuildPhase section */ 192 | 193 | /* Begin PBXRezBuildPhase section */ 194 | 639C91D216F0E8D0008C3BF1 /* Rez */ = { 195 | isa = PBXRezBuildPhase; 196 | buildActionMask = 2147483647; 197 | files = ( 198 | ); 199 | runOnlyForDeploymentPostprocessing = 0; 200 | }; 201 | /* End PBXRezBuildPhase section */ 202 | 203 | /* Begin PBXSourcesBuildPhase section */ 204 | 639C91CE16F0E8D0008C3BF1 /* Sources */ = { 205 | isa = PBXSourcesBuildPhase; 206 | buildActionMask = 2147483647; 207 | files = ( 208 | 639C91E616F0E8D0008C3BF1 /* GenerateThumbnailForURL.c in Sources */, 209 | 639C91E816F0E8D0008C3BF1 /* GeneratePreviewForURL.c in Sources */, 210 | 639C91EA16F0E8D0008C3BF1 /* main.c in Sources */, 211 | 63BF78D516F115A4008D1D69 /* iff.c in Sources */, 212 | ); 213 | runOnlyForDeploymentPostprocessing = 0; 214 | }; 215 | /* End PBXSourcesBuildPhase section */ 216 | 217 | /* Begin PBXVariantGroup section */ 218 | 639C91E216F0E8D0008C3BF1 /* InfoPlist.strings */ = { 219 | isa = PBXVariantGroup; 220 | children = ( 221 | 639C91E316F0E8D0008C3BF1 /* en */, 222 | ); 223 | name = InfoPlist.strings; 224 | sourceTree = ""; 225 | }; 226 | /* End PBXVariantGroup section */ 227 | 228 | /* Begin XCBuildConfiguration section */ 229 | 639C91EC16F0E8D0008C3BF1 /* Debug */ = { 230 | isa = XCBuildConfiguration; 231 | buildSettings = { 232 | ALWAYS_SEARCH_USER_PATHS = NO; 233 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 234 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 235 | CLANG_ENABLE_OBJC_ARC = YES; 236 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 237 | COPY_PHASE_STRIP = NO; 238 | GCC_C_LANGUAGE_STANDARD = gnu99; 239 | GCC_DYNAMIC_NO_PIC = NO; 240 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 241 | GCC_OPTIMIZATION_LEVEL = 0; 242 | GCC_PREPROCESSOR_DEFINITIONS = ( 243 | "DEBUG=1", 244 | "$(inherited)", 245 | ); 246 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 247 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 248 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 249 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 250 | GCC_WARN_UNUSED_VARIABLE = YES; 251 | MACOSX_DEPLOYMENT_TARGET = 10.7; 252 | ONLY_ACTIVE_ARCH = YES; 253 | SDKROOT = macosx; 254 | }; 255 | name = Debug; 256 | }; 257 | 639C91ED16F0E8D0008C3BF1 /* Release */ = { 258 | isa = XCBuildConfiguration; 259 | buildSettings = { 260 | ALWAYS_SEARCH_USER_PATHS = NO; 261 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 262 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 263 | CLANG_ENABLE_OBJC_ARC = YES; 264 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 265 | COPY_PHASE_STRIP = YES; 266 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 267 | GCC_C_LANGUAGE_STANDARD = gnu99; 268 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 271 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 272 | GCC_WARN_UNUSED_VARIABLE = YES; 273 | MACOSX_DEPLOYMENT_TARGET = 10.7; 274 | SDKROOT = macosx; 275 | }; 276 | name = Release; 277 | }; 278 | 639C91EF16F0E8D0008C3BF1 /* Debug */ = { 279 | isa = XCBuildConfiguration; 280 | buildSettings = { 281 | COMBINE_HIDPI_IMAGES = YES; 282 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 283 | GCC_PREFIX_HEADER = "ql-iff/ql-iff-Prefix.pch"; 284 | INFOPLIST_FILE = "ql-iff/ql-iff-Info.plist"; 285 | INSTALL_PATH = /Library/QuickLook; 286 | PRODUCT_NAME = iff; 287 | WRAPPER_EXTENSION = qlgenerator; 288 | }; 289 | name = Debug; 290 | }; 291 | 639C91F016F0E8D0008C3BF1 /* Release */ = { 292 | isa = XCBuildConfiguration; 293 | buildSettings = { 294 | COMBINE_HIDPI_IMAGES = YES; 295 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 296 | GCC_PREFIX_HEADER = "ql-iff/ql-iff-Prefix.pch"; 297 | INFOPLIST_FILE = "ql-iff/ql-iff-Info.plist"; 298 | INSTALL_PATH = /Library/QuickLook; 299 | PRODUCT_NAME = iff; 300 | WRAPPER_EXTENSION = qlgenerator; 301 | }; 302 | name = Release; 303 | }; 304 | /* End XCBuildConfiguration section */ 305 | 306 | /* Begin XCConfigurationList section */ 307 | 639C91CC16F0E8D0008C3BF1 /* Build configuration list for PBXProject "ql-iff" */ = { 308 | isa = XCConfigurationList; 309 | buildConfigurations = ( 310 | 639C91EC16F0E8D0008C3BF1 /* Debug */, 311 | 639C91ED16F0E8D0008C3BF1 /* Release */, 312 | ); 313 | defaultConfigurationIsVisible = 0; 314 | defaultConfigurationName = Release; 315 | }; 316 | 639C91EE16F0E8D0008C3BF1 /* Build configuration list for PBXNativeTarget "ql-iff" */ = { 317 | isa = XCConfigurationList; 318 | buildConfigurations = ( 319 | 639C91EF16F0E8D0008C3BF1 /* Debug */, 320 | 639C91F016F0E8D0008C3BF1 /* Release */, 321 | ); 322 | defaultConfigurationIsVisible = 0; 323 | defaultConfigurationName = Release; 324 | }; 325 | /* End XCConfigurationList section */ 326 | }; 327 | rootObject = 639C91C916F0E8D0008C3BF1 /* Project object */; 328 | } 329 | -------------------------------------------------------------------------------- /iff.c: -------------------------------------------------------------------------------- 1 | /* 2 | * iff.c 3 | * ql_plugin_test_2 4 | * 5 | * Created by David R on 13-03-09. 6 | * Copyright 2013 __MyCompanyName__. All rights reserved. 7 | * 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include "iff.h" 17 | 18 | uint32_t form_getType(form_t *form) 19 | { 20 | return CFSwapInt32(form->type); 21 | } 22 | 23 | header_t *form_getFirstChunk(form_t *form) 24 | { 25 | return (header_t *)((UInt8 *)form+sizeof(*form)); 26 | } 27 | 28 | uint32_t header_getID(header_t *h) 29 | { 30 | return CFSwapInt32(h->id); 31 | } 32 | 33 | int header_getSize(header_t *h) 34 | { 35 | return CFSwapInt32(h->size); 36 | } 37 | 38 | void *header_getData(header_t *h) 39 | { 40 | return (UInt8 *)h+sizeof(*h); 41 | } 42 | 43 | header_t *header_getNext(header_t *h) 44 | { 45 | return header_getData(h) + ((header_getSize(h)+1) & -2); 46 | } 47 | 48 | int bmhd_getWidth(bmhd_t *bmhd) 49 | { 50 | return CFSwapInt16(bmhd->w); 51 | } 52 | 53 | int bmhd_getHeight(bmhd_t *bmhd) 54 | { 55 | return CFSwapInt16(bmhd->h); 56 | } 57 | 58 | int bmhd_getDepth(bmhd_t *bmhd) 59 | { 60 | return bmhd->nPlanes; 61 | } 62 | 63 | int bmhd_getCompression(bmhd_t *bmhd) 64 | { 65 | return bmhd->compression; 66 | } 67 | 68 | static int bmhd_getMasking(bmhd_t *bmhd) 69 | { 70 | return bmhd->masking; 71 | } 72 | 73 | static int bmhd_getTransparentColor(bmhd_t *bmhd) 74 | { 75 | return CFSwapInt16(bmhd->transparentColor); 76 | } 77 | 78 | int camg_getEHB(camg_t *camg) 79 | { 80 | return !!(CFSwapInt32(camg->viewMode) & 0x0080); 81 | } 82 | 83 | int camg_getHAM(camg_t *camg) 84 | { 85 | return !!(CFSwapInt32(camg->viewMode) & 0x0800); 86 | } 87 | 88 | int camg_getLace(camg_t *camg) 89 | { 90 | return !!(CFSwapInt32(camg->viewMode) & 0x0004); 91 | } 92 | 93 | int camg_getHires(camg_t *camg) 94 | { 95 | return !!(CFSwapInt32(camg->viewMode) & 0x8000); 96 | } 97 | 98 | int camg_getSuper(camg_t *camg) 99 | { 100 | return (CFSwapInt32(camg->viewMode) & 0x8020) == 0x8020; 101 | } 102 | 103 | int camg_getSDbl(camg_t *camg) 104 | { 105 | return !!(CFSwapInt32(camg->viewMode) & 0x0008); 106 | } 107 | 108 | int iff_mapChunks(const UInt8 *bytePtr, long length, chunkMap_t *ckmap) 109 | { 110 | memset(ckmap, 0, sizeof(*ckmap)); 111 | 112 | form_t *form = (form_t *)bytePtr; 113 | 114 | if (header_getID(&form->header) != 'FORM') 115 | { 116 | return 1; 117 | } 118 | 119 | if (header_getSize(&form->header) + sizeof(form->header) > length) 120 | { 121 | return 1; 122 | } 123 | 124 | if (form_getType(form) != 'ILBM' && form_getType(form) != 'PBM ') 125 | { 126 | return 1; 127 | } 128 | 129 | ckmap->form = form; 130 | 131 | header_t *header = form_getFirstChunk(form); 132 | 133 | while (header < header_getNext(&form->header)) 134 | { 135 | switch (header_getID(header)) 136 | { 137 | case 'BMHD': 138 | ckmap->bmhd = (bmhd_t *)header; 139 | break; 140 | 141 | case 'CMAP': 142 | ckmap->cmap = (cmap_t *)header; 143 | break; 144 | 145 | case 'BODY': 146 | ckmap->body = (body_t *)header; 147 | break; 148 | 149 | case 'CAMG': 150 | ckmap->camg = (camg_t *)header; 151 | break; 152 | } 153 | 154 | header = header_getNext(header); 155 | } 156 | 157 | return 0; 158 | } 159 | 160 | int cmap_unpack(chunkMap_t *ckmap, UInt32 *dest) 161 | { 162 | cmap_t *cmap = ckmap->cmap; 163 | 164 | if (!cmap) 165 | { 166 | return -1; 167 | } 168 | 169 | int numColors = header_getSize(&cmap->header) / 3; 170 | UInt8 *src = header_getData(&cmap->header); 171 | 172 | UInt8 (*palette)[4] = (void *)dest; 173 | 174 | for (int i=0; icamg && camg_getEHB(ckmap->camg) 183 | && ckmap->bmhd && bmhd_getDepth(ckmap->bmhd) == 6 184 | && numColors <= 32) 185 | { 186 | for (int i=0; i= 0) 207 | { 208 | while (x-- >= 0) 209 | { 210 | *dest++ = *src++; 211 | } 212 | } 213 | else if (x != -128) // rle 214 | { 215 | int y = *src++; 216 | 217 | while (x++ <= 0) 218 | { 219 | *dest++ = y; 220 | } 221 | } 222 | } 223 | assert(dest == rowEnd); 224 | 225 | return src; 226 | } 227 | 228 | int body_unpack(chunkMap_t *ckmap, UInt8 *chunky) 229 | { 230 | bmhd_t *bmhd = ckmap->bmhd; 231 | body_t *body = ckmap->body; 232 | 233 | if (!bmhd || !body) 234 | { 235 | return -1; 236 | } 237 | 238 | int comp = bmhd_getCompression(bmhd); 239 | 240 | if (comp != 0 && comp != 1) 241 | { 242 | return -1; 243 | } 244 | 245 | int height = bmhd_getHeight(bmhd); 246 | int width = bmhd_getWidth(bmhd); 247 | int depth = bmhd_getDepth(bmhd); 248 | 249 | UInt32 type = form_getType(ckmap->form); 250 | 251 | int cols = ((width+15) & -16) >> 3; 252 | 253 | UInt8 *planar = malloc(height*cols*8); 254 | 255 | if (type == 'ILBM') 256 | { 257 | UInt8 *dest = planar; 258 | 259 | SInt8 *src = header_getData(&body->header); 260 | 261 | for (int y=0; y=0; z--) 287 | { 288 | int pos = (y*depth+z)*cols + (x>>3); 289 | int bit = 7-(x & 7); 290 | 291 | c += c + ((planar[pos] >> bit) & 1); 292 | } 293 | 294 | chunky[y*width+x] = c; 295 | } 296 | } 297 | } 298 | else if (type == 'PBM ') 299 | { 300 | UInt8 *dest = chunky; 301 | SInt8 *src = header_getData(&body->header); 302 | 303 | if (comp) 304 | { 305 | src = byterun_unpack(src, dest, height*width); 306 | } 307 | else 308 | { 309 | memcpy(dest, src, height*width); 310 | } 311 | } 312 | 313 | free(planar); 314 | 315 | return 0; 316 | } 317 | 318 | int camg_getPixelAspect(camg_t *camg) 319 | { 320 | int aspect = 0; 321 | 322 | if (camg) 323 | { 324 | aspect += camg_getHires(camg); 325 | aspect += camg_getSuper(camg); 326 | aspect += camg_getSDbl(camg); 327 | aspect -= camg_getLace(camg); 328 | } 329 | 330 | return aspect; 331 | } 332 | 333 | CGSize ilbm_getFinalSize(chunkMap_t *ckmap) 334 | { 335 | int w=0, h=0; 336 | 337 | if (ckmap->bmhd && ckmap->body && ckmap->cmap) 338 | { 339 | w = bmhd_getWidth(ckmap->bmhd); 340 | h = bmhd_getHeight(ckmap->bmhd); 341 | 342 | int aspect = camg_getPixelAspect(ckmap->camg); 343 | 344 | if (aspect < 0) 345 | { 346 | w <<= -aspect; 347 | } 348 | else if (aspect > 0) 349 | { 350 | h <<= aspect; 351 | } 352 | } 353 | else if (ckmap->cmap) 354 | { 355 | w = 256; 356 | h = 256; 357 | } 358 | 359 | return CGSizeMake(w, h); 360 | } 361 | 362 | 363 | int ilbm_decode(chunkMap_t *ckmap, UInt32 *picture) 364 | { 365 | if (ckmap->bmhd && ckmap->body && ckmap->cmap) 366 | { 367 | int width = bmhd_getWidth(ckmap->bmhd); 368 | int height = bmhd_getHeight(ckmap->bmhd); 369 | int depth = bmhd_getDepth(ckmap->bmhd); 370 | 371 | UInt8 *chunky = malloc(width*height*8); 372 | 373 | if (!chunky) 374 | { 375 | return -1; 376 | } 377 | 378 | if (body_unpack(ckmap, chunky) < 0) 379 | { 380 | free(chunky); 381 | return -1; 382 | } 383 | 384 | UInt32 *palette = malloc(256*4); 385 | 386 | if (!palette) 387 | { 388 | free(chunky); 389 | return -1; 390 | } 391 | 392 | if (cmap_unpack(ckmap, palette) < 0) 393 | { 394 | free(chunky); 395 | free(palette); 396 | return -1; 397 | } 398 | 399 | if (ckmap->camg && camg_getHAM(ckmap->camg) && depth >= 5) 400 | { 401 | // HAM 402 | 403 | int r=0, g=0, b=0; 404 | 405 | for (int i=0; i> (depth-2); 408 | int lo = chunky[i] & (255 >> (10-depth)); 409 | 410 | switch (hi & 3) 411 | { 412 | case 0: 413 | r = (palette[lo] >> 8) & 255; 414 | g = (palette[lo] >> 16) & 255; 415 | b = (palette[lo] >> 24) & 255; 416 | break; 417 | 418 | case 2: 419 | r = lo << (10-depth); 420 | break; 421 | 422 | case 3: 423 | g = lo << (10-depth); 424 | break; 425 | 426 | case 1: 427 | b = lo << (10-depth); 428 | break; 429 | } 430 | 431 | picture[i] = (b<<24)+(g<<16)+(r<<8)+255; 432 | } 433 | } 434 | else 435 | { 436 | // normal indexed colors 437 | 438 | int tc = bmhd_getMasking(ckmap->bmhd) == 2 ? bmhd_getTransparentColor(ckmap->bmhd) : -1; 439 | 440 | for (int i=0; icamg); 459 | 460 | if (aspect < 0) 461 | { 462 | aspect = -aspect; 463 | 464 | for (int y=height-1; y>=0; y--) 465 | { 466 | for (int x=width-1; x>=0; x--) 467 | { 468 | for (int z=0; z<(1< 0) 477 | { 478 | for (int x=width-1; x>=0; x--) 479 | { 480 | for (int y=height-1; y>=0; y--) 481 | { 482 | for (int z=0; z<(1<cmap) 494 | { 495 | int width = 256; 496 | int height = 256; 497 | 498 | UInt32 *palette = malloc(256*4); 499 | 500 | if (!palette) 501 | { 502 | return -1; 503 | } 504 | 505 | int numColors = cmap_unpack(ckmap, palette); 506 | 507 | if (numColors <= 0 || numColors > 256) 508 | { 509 | free(palette); 510 | return -1; 511 | } 512 | 513 | int n = 8*sizeof(numColors)-1-__builtin_clz(numColors); // n = log2(numColors) 514 | 515 | int rows = 1<<(n/2); 516 | int cols = 1<<(n-n/2); 517 | 518 | for (int y=0; ybmhd) == 2 ? bmhd_getTransparentColor(ckmap->bmhd) : 0; 538 | return CGColorCreateGenericRGB(palette[i][1]/255.0, palette[i][2]/255.0, palette[i][3]/255.0, 1.0); 539 | } 540 | 541 | 542 | CGImageRef iff_createImage(CFURLRef url, bool withAlpha) 543 | { 544 | CFDataRef data; 545 | 546 | int errorCode; 547 | 548 | Boolean success = CFURLCreateDataAndPropertiesFromResource(NULL, url, &data, NULL, NULL, &errorCode); 549 | 550 | if (!success) return NULL; 551 | 552 | CFIndex length = CFDataGetLength(data); 553 | const UInt8 *bytePtr = CFDataGetBytePtr(data); 554 | 555 | chunkMap_t ckmap; 556 | 557 | errorCode = iff_mapChunks(bytePtr, length, &ckmap); 558 | 559 | if (errorCode) return NULL; 560 | 561 | CGSize size = ilbm_getFinalSize(&ckmap); 562 | 563 | UInt32 *picture = malloc(4*size.width*size.height); 564 | 565 | errorCode = ilbm_decode(&ckmap, picture); 566 | 567 | if (errorCode) return NULL; 568 | 569 | CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 570 | 571 | if (!colorSpace) return NULL; 572 | 573 | CGContextRef context = CGBitmapContextCreate(picture, size.width, size.height, 8, 4*size.width, colorSpace, withAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst); 574 | 575 | if (!context) return NULL; 576 | 577 | CGColorSpaceRelease(colorSpace); 578 | 579 | CGColorRef color = CGColorCreateGenericRGB(1.0, 0.0, 1.0, 1.0); 580 | CGContextSetFillColorWithColor(context, color); 581 | 582 | CGImageRef image = CGBitmapContextCreateImage(context); 583 | 584 | CFRelease(context); 585 | free(picture); 586 | 587 | return image; 588 | } --------------------------------------------------------------------------------