1import os, sys 2 3from Quartz import * 4import Quartz 5 6import objc 7 8def createDataProviderFromPathName (path): 9 # Create a CFURL for the supplied file system path. 10 url = CFURLCreateWithFileSystemPath(None, path, kCFURLPOSIXPathStyle, False) 11 if url is None: 12 print >>sys.stderr, "Couldn't create url!" 13 return None 14 15 # Create a Quartz data provider for the URL. 16 dataProvider = CGDataProviderCreateWithURL(url) 17 if dataProvider is None: 18 print >>sys.stderr, "Couldn't create data provider!" 19 return None 20 21 return dataProvider 22 23def createRGBRampDataProvider(): 24 width = 256 25 height = 256 26 imageDataSize = width*height*3 27 28 dataP = objc.allocateBuffer(imageDataSize) 29 30 # Build an image that is RGB 24 bits per sample. This is a ramp 31 # where the red component value increases in red from left to 32 # right and the green component increases from top to bottom. 33 # 34 idx=0 35 for g in xrange(height): 36 for r in xrange(width): 37 dataP[idx] = chr(r) 38 dataP[idx+1] = chr(g) 39 dataP[idx+2] = '\0' 40 idx += 3 41 42 # Once this data provider is created, the data associated 43 # with dataP MUST be available until Quartz calls the data 44 # releaser function 'rgbReleaseRampData'. 45 dataProvider = CGDataProviderCreateWithData( 46 None, dataP, imageDataSize, None) 47 return dataProvider 48 49class MyImageDataInfo (object): 50 fp = None 51 totalBytesRead = 0 52 skippedBytes = 0 53 numRewinds = 0 54 55def getBytesSequentialAccessDP(data, buffer, count): 56 buf = data.fp.read(count) 57 buffer[:len(buf)] = buf 58 data.totalBytesRead += len(buf) 59 return len(buf), buffer 60 61def skipBytesSequentialAccessDP(data, count): 62 try: 63 data.fp.seek(count, os.SEEK_CUR) 64 data.skippedBytes += count 65 66 except IOError, msg: 67 print >>sys.stderr, "Couldn't seek %d bytes because of %s"%(count, msg) 68 69 70def rewindSequentialAccessDP(data): 71 # Rewind the beginning of the data. 72 data.fp.seek(0, 0) 73 data.numRewinds += 1 74 75def releaseSequentialAccessDP(data): 76 if data is not None: 77 print >>sys.stderr, "read %d bytes, skipped %d bytes, rewind called %d times"%( 78 data.totalBytesRead, data.skippedBytes, 79 data.numRewinds) 80 data.fp.close() 81 82def createSequentialAccessDPForURL(url): 83 success, pathString = CFURLGetFileSystemRepresentation(url, True, None, 1024) 84 pathString = pathString.rstrip('\0') 85 if not success: 86 print >>sys.stderr, "Couldn't get the path name C string!" 87 return None 88 89 fp = open(pathString, "rb") 90 if fp is None: 91 print >>sys.stderr, "Couldn't open path to file %s!"%(pathString,) 92 return None 93 94 imageDataInfoP = MyImageDataInfo() 95 imageDataInfoP.fp = fp 96 97 provider = CGDataProviderCreate(imageDataInfoP, ( 98 getBytesSequentialAccessDP, 99 skipBytesSequentialAccessDP, 100 rewindSequentialAccessDP, 101 releaseSequentialAccessDP)) 102 if provider is None: 103 print >>sys.stderr, "Couldn't create data provider!" 104 # Release the info data and cleanup. 105 releaseSequentialAccessDP(imageDataInfoP) 106 return None 107 108 return provider 109 110 111def getBytesGrayRampDirectAccess(info, buffer, offset, count): 112 # This computes a linear gray ramp that is 256 samples wide and 113 # 1 sample high. The ith byte in the image is the sample 114 # value i. This produces a gray ramp that goes from 0 (black) to 115 # FF (white). 116 idx = 0 117 118 # This data provider provides 256 bytes total. If Quartz 119 # requests more data than is available, only return 120 # the available data. 121 if (offset + count) > 256: 122 count = 256 - offset 123 124 for i in range(offset, offset+count): 125 buffer[idx] = chr(i) 126 idx+=1 127 128 return count, buffer 129 130def createGrayRampDirectAccessDP(): 131 provider = CGDataProviderCreateDirectAccess(None, 256, ( 132 None, 133 None, 134 getBytesGrayRampDirectAccess, 135 None)) 136 if provider is None: 137 print >>sys.stderr, "Couldn't create data provider!" 138 return None 139 140 return provider 141 142# This only builds on Tiger and later. 143def myCGDataProviderCreateWithCFData(data): 144 # If the CFData object passed in is None, this code returns 145 # a None data provider. 146 if data is None: 147 return None 148 149 # Test to see if the Quartz version is available and if so, use it. 150 151 #XXX: force the replacment code to be used 152 #if hasattr(Quartz, 'CGDataProviderCreateWithCFData'): 153 # return CGDataProviderCreateWithCFData(data) 154 155 dataSize = CFDataGetLength(data) 156 provider = CGDataProviderCreateWithData(data, buffer(data), dataSize, None) 157 return provider 158 159def createDataConsumerFromPathName(path): 160 # Create a CFURL for the supplied file system path. 161 url = CFURLCreateWithFileSystemPath (None, path, kCFURLPOSIXPathStyle, False) 162 if url is None: 163 print >>sys.stderr, "Couldn't create url!" 164 return None 165 # Create a Quartz data provider for the URL. 166 dataConsumer = CGDataConsumerCreateWithURL(url) 167 if dataConsumer is None: 168 print >>sys.stderr, "Couldn't create data consumer!" 169 return None 170 171 return dataConsumer 172 173def myCFDataConsumerPutBytes(data, buffer, count): 174 # Append 'count' bytes from 'buffer' to the CFData 175 # object 'data'. 176 CFDataAppendBytes(data, buffer, count) 177 return count 178 179# This only builds on Tiger and later. 180def myCGDataConsumerCreateWithCFData(data): 181 # If the CFData object passed in is None, this code returns 182 # a None data consumer. 183 if data is None: 184 return None 185 186 # Test to see if the Quartz version is available. 187 188 # XXX: force the replacement code to be used: 189 #if hasattr(Quartz, 'CGDataConsumerCreateWithCFData'): 190 # return CGDataConsumerCreateWithCFData(data) 191 192 consumer = CGDataConsumerCreate(data, ( 193 myCFDataConsumerPutBytes, None)) 194 return consumer 195