![]() |
File LayerWriting PhotoJazz Files Since BitJazz is a shared library, your product cannot count on its existence on the user's machine. Before trying to write a PhotoJazz file, you should check whether PhotoJazz was successfully linked in. On the Power Macintosh, you can do this by testing the address of one of the interface functions: if (!&JzWriteBegin){ To write a PhotoJazz file, you ordinarily call three functions, JzWriteBegin to begin writing, JzWriteTile to write each tile, and JzWriteEnd to end reading. In addition, you can call JzWriteFlush to write out any changed parameters, and JzWritePrivateChunk to write out your own data. JzWriteBegin passes back a JzFile pointer which you pass back as the first argument to the other functions. JzStreamResult JzWriteBegin(JzStream *aStream, JzAllocator *aAllocator, JzYielder *aYielder, JzKey aProduct, JzFile **aJazzFile); All of these functions return a JzStreamResult to indicate either success (kJzStreamResultOkay) or some kind of error. If JzWriteTile, JzWriteFlush, or JzWritePrivateChunk returns an error, you must still call JzWriteEnd to allow PhotoJazz to clean up properly. Several of the result values always indicate errors in your use of the PhotoJazz interface. The result kJzStreamResultMissingArgument indicates that you passed in a NULL pointer for a required argument; kJzStreamResultIncompleteArgument means that you failed to assign a pointer to one of the members of a required argument; kJzStreamResultInconsistentArgument means that the value of an argument you specified is inconsistent with the current state. Three such errors are passed through from your JzStream mWrite callback function. Thus kJzStreamResultInvalidFileID means that the operating-system-specific file number you supplied is invalid; kJzStreamResultNotOpen means that you forgot to open the file before having PhotoJazz write to it, or closed the file before PhotoJazz was done writing to it; kJzStreamResultOutsideFile means that you positioned the stream before the beginning of the file. kJzStreamResultMissingArgument, //NULL address Several other result values sometimes indicate an error in your use of the PhotoJazz interface. The result kJzStreamResultInvalidSerialNumber may refer to either your product key or the user's key; kJzStreamResultUnwritable could mean either that you are trying to write to a file that you opened for read access, or (when passed through from your JzStream mWrite function) that the file itself is on a read-only or inaccessible volume; kJzStreamResultUnimplemented could mean either that you are specifying an invalid argument (typically enum) value, or that your PhotoJazz engine needs to be updated to a newer version. kJzStreamResultInvalidSerialNumber, //bad user key or product key To begin writing a PhotoJazz file, you create three C objects: a JzStream (aStream) to let PhotoJazz write data to the file, a JzAllocator (aAllocator) to allocate memory for PhotoJazz, and a JzYielder (aYielder) to let PhotoJazz yield time to other tasks. All three of these objects are required arguments. The stream must already be open and positioned at the beginning of the PhotoJazz file before calling JzWriteBegin. You must also pass in a JzKey (aProduct) for the product. For now, pass in the default key, kJzWatermarkProduct, which applies a watermark to all images you write. When your product has advanced to the stage where you need to test without watermarking, contact us for a commercial key for your product, which we supply free of charge under the terms of our developer license agreement. In its last argument, JzWriteBegin passes back an opaque JzFile pointer (aJazzFile) which you supply as the first argument in all subsequent JzWrite calls for this image. As its function result, JzWriteBegin returns a JzStreamResult. A result of kJzStreamResultOkay indicates success; Any other result indicates an error. If an error occurs during JzWriteBegin, JzWriteBegin cleans up and passes back a NULL pointer for the JzFile. JzStreamResult JzWriteBegin(JzStream *aStream, JzAllocator *aAllocator, JzYielder *aYielder, JzKey aProduct, JzFile **aJazzFile); In addition to allocating and initializing a JzFile structure, JzWriteBegin writes out the PhotoJazz identifier and the safety bits to the PhotoJazz file. The PhotoJazz file format is extensible, and supports private product-specific data classes. To write a private data chunk, call JzWritePrivateChunk. In addition to the JzFile pointer, JzWritePrivateChunk takes five arguments: the Owner number (aOwner), the chunk Class (aClass), the chunk-category Flags (aFlags), the chunk size (aSize) in bytes, and a pointer to the chunk itself (aData). JzStreamResult JzWritePrivateChunk(JzFile *me, unsigned long aOwner, unsigned long aClass, JzFlags aFlags, unsigned long aSize, void *aData); The Owner number you obtain from BitJazz Inc. If you need to store product-specific private data in the PhotoJazz files you create, contact us for an Owner number. On the other hand, if you feel that the Class of data you need to store is likely to fulfill a general need, let us consider adding it as a public Class. The Class number you define yourself. With your own unique Owner number, you can define as many different chunk Classes as you like, because the Class space is owner-specific. Therefore, if you have complicated data, you can take advantage of PhotoJazz's chunking machinery, rather than developing your own. Note that, in general, smaller Class numbers occupy less file space, so you would be advised to begin with serial number 0. The following chunk-category Flags are defined: typedef enum JzFlags { BitJazz Inc. may define other flags in the future. The kJzFlagsCritical flag, when set, indicates that the image data cannot be interpreted at all without understanding this chunk. Ancillary (non-critical) chunks may help render the image more accurately, or provide other information such as comments. If the kJzFlagsIndependent flag on a chunk is set, the validity of the chunk's contents are not affected by manipulating the other chunks in the file, and vice versa. A dependent chunk needs to be recomputed, marked as invalid, or discarded when the other chunks are altered. Setting the kJzFlagsPrivate flag indicates that the chunk is private. JzWritePrivateChunk sets this bit for you. A set kJzFlagsCompressed flag indicates that the contents of the chunk are compressed. In private chunks, the interpretation of this flag is up to you. If you do compress the data, it is advisable to prefix the compressed data with a byte identifying the compression method. In the future, BitJazz Inc. may provide general-purpose compression utilities for you to use in your private chunks. PhotoJazz does not hold onto the chunk data address you pass in; It writes the data straight out to the file. You can therefore free the chunk data immediately afterwards if you so desire. As its function result, JzWritePrivateChunk returns a JzStreamResult. A result of kJzStreamResultOkay indicates success; Any other result indicates an error. If an error occurs, you must still call JzWriteEnd to let PhotoJazz clean up properly. JzWritePrivateChunk first writes out any changed parameters, and then writes out your private chunk. Note that PhotoJazz takes care of computing and storing a CRC code for each of your private chunks. To write the next tile to a PhotoJazz file, you call JzWriteTile, passing it the JzFile pointer (aJazzFile) given you by JzWriteBegin; the width (aRowWidth) of the tile buffer in pixels (not in bytes!), and the address (aImage) of the tile buffer. JzStreamResult JzWriteTile(JzFile *aJazzFile, unsigned long aRowWidth, void *aImage); If you have access to all the channels of all the tiles in the image, then write the image directly out from your image buffer; otherwise, write each tile into an intermediate tile buffer. As its function result, JzWriteTile returns a JzStreamResult. A result of kJzStreamResultOkay indicates success; Any other result indicates an error. If an error occurs, you must still call JzWriteEnd to let PhotoJazz clean up properly. JzWrite first writes out all changed parameters to the PhotoJazz file, and then compresses and writes out the tile. PhotoJazz ordinarily writes the parameters out to the stream only when you call JzWriteTile or JzWriteEnd. If for some reason you need to force the changed parameters to be written out at some other time, you can call JzWriteFlush, passing it the JzFile pointer (aJazzFile) given you by JzWriteBegin. JzStreamResult JzWriteFlush(JzFile *aJazzFile); As its function result, JzWriteFlush returns a JzStreamResult. A result of kJzStreamResultOkay indicates success; Any other result indicates an error. If an error occurs, you must still call JzWriteEnd to let PhotoJazz clean up properly. After you have written all the tiles to a PhotoJazz image file, or if an error has occurred while processing and writing the tiles, you must call JzWriteEnd. JzWriteEnd only takes one argument, the JzFile pointer (aJazzFile) passed back by JzWriteBegin. JzStreamResult JzWriteEnd(JzFile *aJazzFile); JzWriteEnd first writes out any changed parameters, and then frees all the remaining buffers that PhotoJazz has allocated for the image. Once you have called JzWriteEnd, the JzFile pointer is no longer valid, so it is advisable to set it to zero for defensive programming. If the JzStream you passed in to JzWriteBegin needs to be closed, this is the time to do it. Examples Here is a code snippet of a JzWrite sequence that writes an entire PhotoJazz image out from an image buffer: struct JzFile *lJazzFile = 0;error: The variables lStream, lAllocator, lYielder, lMode, lImageWidth, lImageHeight, lPrimaryCount, lSpotColorCount, and lAlphaChannelCount are defined and initialized by you prior to this code snippet.
|