1// 2// PXBitmapExporter.m 3// Pixen-XCode 4// 5// Created by Andy Matuschak on Wed Jun 09 2004. 6// Copyright (c) 2004 Open Sword Group. All rights reserved. 7// 8 9#import "PXBitmapExporter.h" 10#import <QuickTime/QuickTime.h> 11// PXBitmapExporter.m 12// Pixen-XCode 13// 14// Created by Andy Matuschak on Wed Jun 09 2004. 15// Copyright (c) 2004 Open Sword Group. All rights reserved. 16// 17 18#import "PXBitmapExporter.h" 19#import <QuickTime/QuickTime.h> 20 21// BMPDataForImage by Florrent Pillet 22// myCreateHandleDataRef by Apple 23 24@implementation PXBitmapExporter 25 26Handle myCreateHandleDataRef(Handle dataHandle, Str255 fileName, OSType fileType, StringPtr mimeTypeString, Ptr initDataPtr, Size initDataByteCount) 27{ 28 OSErr err; 29 Handle dataRef = nil; 30 Str31 tempName; 31 long atoms[3]; 32 StringPtr name; 33 34 // First create a data reference handle for our data 35 err = PtrToHand( &dataHandle, &dataRef, sizeof(Handle)); 36 37 if (err) goto bail; 38 39 // If this is QuickTime 3 or later, we can add 40 // the filename to the data ref to help importer 41 // finding process. Find uses the extension. 42 43 name = fileName; 44 if (name == nil) 45 { 46 tempName[0] = 0; 47 name = tempName; 48 } 49 50 // Only add the file name if we are also adding a 51 // file type, MIME type or initialization data 52 53 if ((fileType) || (mimeTypeString) || (initDataPtr)) 54 { 55 err = PtrAndHand(name, dataRef, name[0]+1); 56 if (err) goto bail; 57 } 58 59 // If this is QuickTime 4, the handle data handler 60 // can also be told the filetype and/or 61 // MIME type by adding data ref extensions. These 62 // help the importer finding process. 63 // NOTE: If you add either of these, you MUST add 64 // a filename first -- even if it is an empty Pascal 65 // string. Under QuickTime 3, any data ref extensions 66 // will be ignored. 67 68 // to add file type, you add a classic atom followed 69 // by the Mac OS filetype for the kind of file 70 if (fileType) 71 { 72 atoms[0] = EndianU32_NtoB(sizeof(long) * 3); 73 atoms[1] = EndianU32_NtoB(kDataRefExtensionMacOSFileType); 74 atoms[2] = EndianU32_NtoB(fileType); 75 err = PtrAndHand(atoms, dataRef, sizeof(long) * 3); 76 if (err) goto bail; 77 } 78 79 // to add MIME type information, add a classic atom followed by 80 // a Pascal string holding the MIME type 81 82 if (mimeTypeString) 83 { 84 atoms[0] = EndianU32_NtoB(sizeof(long) * 2 + mimeTypeString[0]+1); 85 atoms[1] = EndianU32_NtoB(kDataRefExtensionMIMEType); 86 err = PtrAndHand(atoms, dataRef, sizeof(long) * 2); 87 if (err) goto bail; 88 err = PtrAndHand(mimeTypeString, dataRef, mimeTypeString[0]+1); 89 if (err) goto bail; 90 } 91 92 // add any initialization data, but only if a dataHandle was 93 // not already specified (any initialization data is ignored 94 // in this case) 95 if((dataHandle == nil) && (initDataPtr)) 96 { 97 atoms[0] = EndianU32_NtoB(sizeof(long) * 2 + initDataByteCount); 98 atoms[1] = EndianU32_NtoB(kDataRefExtensionInitializationData); 99 err = PtrAndHand(atoms, dataRef, sizeof(long) * 2); 100 if (err) goto bail; 101 err = PtrAndHand(initDataPtr, dataRef, initDataByteCount); 102 if (err) goto bail; 103 } 104 return dataRef; 105 106bail: 107 if (dataRef) 108 { 109 // make sure and dispose the data reference handle 110 // once we are done with it 111 DisposeHandle(dataRef); 112 } 113 114 return nil; 115} 116 117+ dataForImage:image type:(int)type 118{ 119 NSRect r = NSMakeRect(0,0,[image size].width,[image size].height); 120 id whiteImage = [[NSImage alloc] initWithSize:[image size]]; 121 [whiteImage lockFocus]; 122 [[NSColor whiteColor] set]; 123 NSRectFill(r); 124 [image compositeToPoint:NSMakePoint(0,0) operation:NSCompositeSourceAtop]; 125 NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:r]; 126 [whiteImage unlockFocus]; 127 [whiteImage release]; 128 NSData *bmpData = [rep representationUsingType:NSBMPFileType properties:nil]; 129 130 if (bmpData == nil) 131 { 132 NSData *pngData = [rep representationUsingType:NSPNGFileType properties:nil]; 133 if ([pngData length] == 0) 134 { 135 NSLog(@"Can't export bitmap data to BMP"); 136 [rep release]; 137 return nil; 138 } 139 140 // create a data reference handle for quicktime (see TN 1195 for myCreateHandleDataRef source) 141 Handle pngDataH = NULL; 142 PtrToHand([pngData bytes], &pngDataH, [pngData length]); 143 Handle dataRef = myCreateHandleDataRef(pngDataH, "\pdummy.png", kQTFileTypePNG, nil, nil, 0); 144 145 // create a Graphics Importer component that will read from the PNG data 146 ComponentInstance importComponent=0, exportComponent=0; 147 OSErr err = GetGraphicsImporterForDataRef(dataRef, HandleDataHandlerSubType, &importComponent); 148 DisposeHandle(dataRef); 149 if (err == noErr) 150 { 151 // create a Graphics Exporter component that will write BMP data 152 err = OpenADefaultComponent(GraphicsExporterComponentType, type, &exportComponent); 153 if (err == noErr) 154 { 155 // set export parameters 156 Handle bmpDataH = NewHandle(0); 157 GraphicsExportSetInputGraphicsImporter(exportComponent, importComponent); 158 GraphicsExportSetOutputHandle(exportComponent, bmpDataH); 159 160 // export data to BMP into handle 161 unsigned long actualSizeWritten = 0; 162 err = GraphicsExportDoExport(exportComponent, &actualSizeWritten); 163 if (err == noErr) 164 { 165 // export done: create the NSData that will be returned 166 HLock(bmpDataH); 167 bmpData = [NSData dataWithBytes:*bmpDataH length:GetHandleSize(bmpDataH)]; 168 HUnlock(bmpDataH); 169 } 170 DisposeHandle(bmpDataH); 171 CloseComponent(exportComponent); 172 } 173 CloseComponent(importComponent); 174 } 175 DisposeHandle(pngDataH); 176 } 177 [rep release]; 178 return bmpData; 179 180} 181 182+ PICTDataForImage:image 183{ 184 return [self dataForImage:image type:kQTFileTypePicture]; 185} 186 187+ BMPDataForImage:image 188{ 189 return [self dataForImage:image type:kQTFileTypeBMP]; 190} 191/* 192@end 193 194 195// BMPDataForImage by Florrent Pillet 196// myCreateHandleDataRef by Apple 197 198@implementation PXBitmapExporter 199 200Handle myCreateHandleDataRef(Handle dataHandle, Str255 fileName, OSType fileType, StringPtr mimeTypeString, Ptr initDataPtr, Size initDataByteCount) 201{ 202 OSErr err; 203 Handle dataRef = nil; 204 Str31 tempName; 205 long atoms[3]; 206 StringPtr name; 207 208 // First create a data reference handle for our data 209 err = PtrToHand( &dataHandle, &dataRef, sizeof(Handle)); 210 211 if (err) goto bail; 212 213 // If this is QuickTime 3 or later, we can add 214 // the filename to the data ref to help importer 215 // finding process. Find uses the extension. 216 217 name = fileName; 218 if (name == nil) 219 { 220 tempName[0] = 0; 221 name = tempName; 222 } 223 224 // Only add the file name if we are also adding a 225 // file type, MIME type or initialization data 226 227 if ((fileType) || (mimeTypeString) || (initDataPtr)) 228 { 229 err = PtrAndHand(name, dataRef, name[0]+1); 230 if (err) goto bail; 231 } 232 233 // If this is QuickTime 4, the handle data handler 234 // can also be told the filetype and/or 235 // MIME type by adding data ref extensions. These 236 // help the importer finding process. 237 // NOTE: If you add either of these, you MUST add 238 // a filename first -- even if it is an empty Pascal 239 // string. Under QuickTime 3, any data ref extensions 240 // will be ignored. 241 242 // to add file type, you add a classic atom followed 243 // by the Mac OS filetype for the kind of file 244 if (fileType) 245 { 246 atoms[0] = EndianU32_NtoB(sizeof(long) * 3); 247 atoms[1] = EndianU32_NtoB(kDataRefExtensionMacOSFileType); 248 atoms[2] = EndianU32_NtoB(fileType); 249 err = PtrAndHand(atoms, dataRef, sizeof(long) * 3); 250 if (err) goto bail; 251 } 252 253 // to add MIME type information, add a classic atom followed by 254 // a Pascal string holding the MIME type 255 256 if (mimeTypeString) 257 { 258 atoms[0] = EndianU32_NtoB(sizeof(long) * 2 + mimeTypeString[0]+1); 259 atoms[1] = EndianU32_NtoB(kDataRefExtensionMIMEType); 260 err = PtrAndHand(atoms, dataRef, sizeof(long) * 2); 261 if (err) goto bail; 262 err = PtrAndHand(mimeTypeString, dataRef, mimeTypeString[0]+1); 263 if (err) goto bail; 264 } 265 266 // add any initialization data, but only if a dataHandle was 267 // not already specified (any initialization data is ignored 268 // in this case) 269 if((dataHandle == nil) && (initDataPtr)) 270 { 271 atoms[0] = EndianU32_NtoB(sizeof(long) * 2 + initDataByteCount); 272 atoms[1] = EndianU32_NtoB(kDataRefExtensionInitializationData); 273 err = PtrAndHand(atoms, dataRef, sizeof(long) * 2); 274 if (err) goto bail; 275 err = PtrAndHand(initDataPtr, dataRef, initDataByteCount); 276 if (err) goto bail; 277 } 278 return dataRef; 279 280bail: 281 if (dataRef) 282 { 283 // make sure and dispose the data reference handle 284 // once we are done with it 285 DisposeHandle(dataRef); 286 } 287 288 return nil; 289} 290 291+ dataForImage:image type:(int)type 292{ 293 NSRect r = NSMakeRect(0,0,[image size].width,[image size].height); 294 id whiteImage = [[NSImage alloc] initWithSize:[image size]]; 295 [whiteImage lockFocus]; 296 [[NSColor whiteColor] set]; 297 NSRectFill(r); 298 [image compositeToPoint:NSMakePoint(0,0) operation:NSCompositeSourceAtop]; 299 NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:r]; 300 [whiteImage unlockFocus]; 301 [whiteImage release]; 302 NSData *bmpData = [rep representationUsingType:NSBMPFileType properties:nil]; 303 304 if (bmpData == nil) 305 { 306 NSData *pngData = [rep representationUsingType:NSPNGFileType properties:nil]; 307 if ([pngData length] == 0) 308 { 309 NSLog(@"Can't export bitmap data to BMP"); 310 [rep release]; 311 return nil; 312 } 313 314 // create a data reference handle for quicktime (see TN 1195 for myCreateHandleDataRef source) 315 Handle pngDataH = NULL; 316 PtrToHand([pngData bytes], &pngDataH, [pngData length]); 317 Handle dataRef = myCreateHandleDataRef(pngDataH, "\pdummy.png", kQTFileTypePNG, nil, nil, 0); 318 319 // create a Graphics Importer component that will read from the PNG data 320 ComponentInstance importComponent=0, exportComponent=0; 321 OSErr err = GetGraphicsImporterForDataRef(dataRef, HandleDataHandlerSubType, &importComponent); 322 DisposeHandle(dataRef); 323 if (err == noErr) 324 { 325 // create a Graphics Exporter component that will write BMP data 326 err = OpenADefaultComponent(GraphicsExporterComponentType, type, &exportComponent); 327 if (err == noErr) 328 { 329 // set export parameters 330 Handle bmpDataH = NewHandle(0); 331 GraphicsExportSetInputGraphicsImporter(exportComponent, importComponent); 332 GraphicsExportSetOutputHandle(exportComponent, bmpDataH); 333 334 // export data to BMP into handle 335 unsigned long actualSizeWritten = 0; 336 err = GraphicsExportDoExport(exportComponent, &actualSizeWritten); 337 if (err == noErr) 338 { 339 // export done: create the NSData that will be returned 340 HLock(bmpDataH); 341 bmpData = [NSData dataWithBytes:*bmpDataH length:GetHandleSize(bmpDataH)]; 342 HUnlock(bmpDataH); 343 } 344 DisposeHandle(bmpDataH); 345 CloseComponent(exportComponent); 346 } 347 CloseComponent(importComponent); 348 } 349 DisposeHandle(pngDataH); 350 } 351 [rep release]; 352 return bmpData; 353 354} 355 356+ PICTDataForImage:image 357{ 358 return [self dataForImage:image type:kQTFileTypePicture]; 359} 360 361+ BMPDataForImage:image 362{ 363 return [self dataForImage:image type:kQTFileTypeBMP]; 364} 365*/ 366 367@end