/*============================================================================== Project: POV Version: 3 File: sysMacPict.c Description: This module contains the code to read/write Mac PICT files. (System-dependent image_map file format read/write routines - for Macintosh PICT) ------------------------------------------------------------------------------ Authors: Eduard [esp] Schwan and Thorsten Froehlich ------------------------------------------------------------------------------ from Persistence of Vision(tm) Ray Tracer Copyright 1996,1998 Persistence of Vision Team ------------------------------------------------------------------------------ NOTICE: This source code file is provided so that users may experiment with enhancements to POV-Ray and to port the software to platforms other than those supported by the POV-Ray Team. There are strict rules under which you are permitted to use this file. The rules are in the file named POVLEGAL.DOC which should be distributed with this file. If POVLEGAL.DOC is not available or for more info please contact the POV-Ray Team Coordinator by leaving a message in CompuServe's Graphics Developer's Forum. The latest version of POV-Ray may be found there as well. This program is based on the popular DKB raytracer version 2.12. DKBTrace was originally written by David K. Buck. DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. ------------------------------------------------------------------------------ More Info: This Macintosh version of POV-Ray was updated and compiled by Eduard Schwan and now builds under Metrowerks CodeWarrior CW Pro 3+ for 68k and PPC. It used to, and may still build under Apple MPW 3.3.x, and Symantec C 8. The Macintosh code was based (loosely) on the original DKB 0.5 port by Thomas Okken and David Lichtman, with some help from Glenn Sugden. Jim Nitchals was instrumental in getting 1.0 out, Jim and Eduard jointly pulled off 2.x with help from Dave Harr for initial Balloon help and the custom palette code, and 3.0 was done by Eduard Schwan. 3.1 was done jointly by Eduard Schwan and Thorsten Froehlich. For bug reports regarding the Macintosh version, you may contact the POV-Ray MacOS team at the following e-mail address. Please send in bugs by filling out the bug report form, in the Documentation folder with POV-Ray: POV-Ray MacOS Team CompuServe: 104706,3276 Internet: povraymac@compuserve.com WWW: http://ourworld.compuserve.com/homepages/povraymac/ ------------------------------------------------------------------------------ Change History: 960123 [esp] Created. 970819 [trf] Basic PICT support implemented for POV-Ray (using handle->buffer as GWorld pointer and custom "Mac_SpecialMakeFSSpec" function to bypass POV-Ray file search mechanism because we may need to access the file's resource fork to read PICTs) NOTE: "void Read_MacPICT_Image(void *Image,char *name)" is declared this way because the MrC compiler will not read the include file "Frame.h" and the right declaration for the "IMAGE" structure before the functions declaration and with the current compiler setting this will result in an error because the structure "IMAGE" is not defined! 971026 [trf] PICT line read/write support implemented, but parts of files will not be read/written as expected. 971029 [esp] Added more error checking, hooked into POV-Ray alpha release, swapped order of file search and data/resource fork open. 971114 [trf] handle->buffer is a pointer to the structure DoubleGWorld now. Added parts of alpha-channel support. Removed unused PICT writing code. 971125 [trf] Finished alpha-channel support. Cleaned up everything and restructured the functions. 971126 [esp] Reworked alpha channel support. 980103 [trf] Added full output support. Now parts of images can be read, too. IMPORTANT: For now it will only work with ONE file open for reading and ONE file open for writing (so be care- ful if histogram support will be added => there will a few changes/checks be required). They are not in now simply because I cannot verify them until a second open file is needed. And I hope this code will move to C++ before this. 980430 [esp] Changed verbose printfs to debug level ==============================================================================*/ #undef POV_COMMENTS // turn on for internal comment stamping #include "sysMacPict.h" #include #include #include #include #include #include "frame.h" #include "povproto.h" #include "povray.h" #include "optout.h" #include "PovMacInit.h" // gHasImageCompressionMgr #include "AppPrefs.h" // gAppPrefs_h #include "FilePrefs.h" // gPrefs2Use_h #include "TextEditor.h" // gSrcWind_VRefNum #include "ImageUtils.h" extern Boolean gMapPictToMovie; extern Boolean gHasQuickTime; extern long gQTVersion; FSSpec gMovieFile = { 0,0,"\p" }; #define PICTF_HEADER_SIZE 512 // old MacDraw PICTF header size in bytes typedef struct { short picSize; // low word of size Rect picFrame; // picture bounds } PictFHeader, *PictFHeaderPtr; typedef struct MovieFile_Struct MOVIE_FILE; typedef struct PictureFile_Struct PICTURE_FILE; typedef struct PictFileHeader_Struct PICT_FILE_HEADER,*PICT_FILE_HEADER_PTR; struct MovieFile_Struct { int fWidth; int fHeight; int fMode; GWorldPtr fTargetGWorld; }; struct PictureFile_Struct { int fWidth; int fHeight; int fMode; int fLastLine; GWorldPtr fTargetGWorld; FSSpec fFile; }; struct PictFileHeader_Struct { // low word of size short picSize; // picture bounds Rect picFrame; }; //PICT // PICT FUNCTION // PICT Fileを圧縮する static OSErr image_compress_pict_file(ComponentInstance,FSSpec *); static int Open_MacPICT_File(FILE_HANDLE *,char *,int *,int *,int,int); static void Write_MacPICT_Line(FILE_HANDLE *,COLOUR *,int); static int Read_MacPICT_Line(FILE_HANDLE *,COLOUR *,int *); static void Close_MacPICT_File(FILE_HANDLE *handle); static OSErr image_movie_create(MOVIE_FILE *mhandle,char *name, int *width, int *height, int mode); static void image_movie_write_line(MOVIE_FILE *mhandle,COLOUR *line_data,int line_number); static void image_movie_delete(MOVIE_FILE *mhandle); OSErr image_picture_create(PICTURE_FILE *mhandle,char *name, int *width, int *height, int mode); static void image_picture_write_line(PICTURE_FILE *mhandle,COLOUR *line_data, int line_number); static int image_picture_read_line(PICTURE_FILE *mhandle,COLOUR *line_data, int *line_number); static void image_picture_read_image(PICTURE_FILE *mhandle,IMAGE *imageptr); static void image_picture_delete(PICTURE_FILE *mhandle); static OSErr image_picture_gworld_from_file(PICTURE_FILE *mhandle); static OSErr image_picture_gworld_from_image(PICTURE_FILE *mhandle); static OSErr image_picture_gworld_create(PICTURE_FILE *mhandle,int w, int h, int d); static void image_picture_gworld_clear(PICTURE_FILE *mhandle); static OSErr image_picture_new(PICTURE_FILE *mhandle); static OSErr image_picture_paint(PICTURE_FILE *mhandle,PicHandle pict); static PicHandle image_picture_handle_from_file(PICTURE_FILE *mhandle); // Mac File形式に変換 static OSErr image_picture_make_file(char *name_cstring, FSSpec *fs); static void image_picture_alpha_channel(GWorldPtr); static pascal void MyPutPicProc(char *dataPtr, short byteCount); static OSErr Mac_SpecialMakeFSSpec(ConstStr255Param name,FSSpec *fs); static OSErr Mac_PaintPictToGWorld(PicHandle pict,GWorldPtr gw_rgb,int w,int h); static OSErr Mac_ReadPictImageFromFile(FSSpec *f,PicHandle *pict); static void Mac_ActivateAlphaChannel(GWorldPtr gw); int Open_MacMovie_File(FILE_HANDLE *handle,char *name,int *width,int *height,int buffer_size,int mode); void Write_MacMovie_Line(FILE_HANDLE *handle,COLOUR *line_data,int line_number); void Close_MacMovie_File(FILE_HANDLE *handle); static int gMacPICTLineNumber; static int gMacValidLineCount; // These are the globals that are "weak", see the 980103 note. [trf] static CQDProcsPtr gMacOldQDProcsPtr; static CQDProcs gMacNewQDProcs; static QDPutPicUPP gMacDrawProcUPP; static CGrafPort gMacGrafPort; static PicHandle gMacPicHandle; static FILE *gMacImagePictFile; static long gMacPicSize; // End of the "weak" globals. // --------------------------------------------------------------------- // Creates a PICT file handle for POV-Ray. FILE_HANDLE *Get_MacPICT_File_Handle() { FILE_HANDLE *handle; handle = (FILE_HANDLE *) POV_MALLOC(sizeof(FILE_HANDLE), "Mac PICT file handle") ; if (handle) { handle->Open_File_p = Open_MacPICT_File; handle->Write_Line_p = Write_MacPICT_Line; handle->Read_Line_p = Read_MacPICT_Line; handle->Read_Image_p = Read_MacPICT_Image; handle->Close_File_p = Close_MacPICT_File; handle->file = NULL; handle->buffer = NULL; handle->buffer_size = 0; } return (handle); } // --------------------------------------------------------------------- static pascal void MyPutPicProc(char *dataPtr, short byteCount) { size_t myByteCount; myByteCount = byteCount; gMacPicSize += byteCount; if(gMacImagePictFile) { if(fwrite( dataPtr, 1, myByteCount, gMacImagePictFile) != myByteCount) { fclose(gMacImagePictFile); gMacImagePictFile = NULL; SysBeep(3); } } // we have to keep the picture handle header updated for Quickdraw! if(gMacPicHandle) (**gMacPicHandle).picSize = gMacPicSize; } // MyPutPicProc // --------------------------------------------------------------------- // The same as FSMakeFSSpec, but it searches the library paths passed to // POV-Ray to find the file. It will only find files of type 'PICT'. // // [esp] Switched order of search, now checks scene folder first. static OSErr Mac_SpecialMakeFSSpec(ConstStr255Param name,FSSpec *fs) { FInfo finfo; OSErr err,olderr; Boolean b; // First look in the same folder as the scene file err = FSMakeFSSpec(gSrcWind_FSSpec.vRefNum, gSrcWind_FSSpec.parID, name, fs); if(err == 0) err = FSpGetFInfo(fs, &finfo); if(err == 0) { if(finfo.fdType == 'PICT') return 0; // found else err = 1; // not found, but valid } olderr = err; // if not there, then look in include folder. // Note: this does not look in *all* POV-Ray library paths ResolveAlias(NULL, (AliasHandle)((**gAppPrefs_h).libPath[0]), fs, &b); err = FSMakeFSSpec(fs->vRefNum, fs->parID, name, fs); if(err == 0) err = FSpGetFInfo(fs, &finfo); if(err == 0) { if(finfo.fdType == 'PICT') return 0; // found else err = 1; // not found, but valid } // if not there, then look in include folder. // Note: this does not look in *all* POV-Ray library paths ResolveAlias(NULL, (AliasHandle)((**gAppPrefs_h).libPath[1]), fs, &b); err = FSMakeFSSpec(fs->vRefNum, fs->parID, name, fs); if(err == 0) err = FSpGetFInfo(fs, &finfo); if(err == 0) { if(finfo.fdType == 'PICT') return 0; // found else err = 1; // not found, but valid } else if(olderr == 1) { err = FSMakeFSSpec(gSrcWind_FSSpec.vRefNum, gSrcWind_FSSpec.parID, name, fs); if(err == 0) err = 1; } return err; } // --------------------------------------------------------------------- // Paints the PICT to an R/G/B/Alpha GWorld static OSErr Mac_PaintPictToGWorld(PicHandle pict,GWorldPtr gw_rgb,int w,int h) { PixMapHandle offPixMapH; Rect r; Boolean imageHasAlpha = false; OSErr err = 0; CGrafPtr oldPort; GDHandle oldGDev; if((pict == NULL) || (gw_rgb == NULL)) return -1; if(w > 2047) { Error("PICT is to big, maximal width of PICTs to read is 2047 pixels!"); return -1; } if ((**gPrefs2Use_h).progress >= eProgDebug) printf("PICT size is %d * %d pixel.\n",w,h); SetRect(&r,0,0,w,h); offPixMapH = GetGWorldPixMap(gw_rgb); if(NULL == offPixMapH) return -1; if(!LockPixels(offPixMapH)) return -1; GetGWorld(&oldPort,&oldGDev); SetGWorld(gw_rgb,NULL); ForeColor(blackColor); BackColor(whiteColor); // copy the image into the offscreen EraseRect(&r); DrawPicture(pict, &r); UnlockPixels(offPixMapH); SetGWorld(oldPort,oldGDev); return err; } // --------------------------------------------------------------------- // The usual MacOS PICT reading code. // // [esp] Switched order of open, first tries data fork, then resource fork. This way // we ignore any thumbnails attached as resources & find data fork first. static OSErr Mac_ReadPictImageFromFile(FSSpec *f,PicHandle *pict) { const long kPictHeaderSize = 512; Boolean tryRsrcFork; long pictFileLen,headerFileLen; short applref,fref; PicHandle hPic; char povheader[61]; if((f == NULL) || (pict == NULL)) return -1; *pict = NULL; gMacValidLineCount = -1; // Try to open data fork tryRsrcFork = true; /* assume true until disproved */ if(FSpOpenDF(f,fsRdPerm,&fref) == 0) { (void)GetEOF(fref,&pictFileLen); pictFileLen -= kPictHeaderSize; if (pictFileLen > 0) { (void)SetFPos(fref,fsFromStart,0); headerFileLen = 60; (void)FSRead(fref,&headerFileLen,(Ptr)&povheader[0]); povheader[60] = 0; if(strncmp("POV-Ray",povheader,7) == 0) { sscanf(&povheader[54],"%6d",&gMacValidLineCount); opts.First_Line = gMacValidLineCount; } (void)SetFPos(fref,fsFromStart,kPictHeaderSize); hPic = (PicHandle)NewHandleClear(pictFileLen); if (hPic != NULL) { HLock((Handle)hPic); (void)FSRead(fref,&pictFileLen,(Ptr)*hPic); HUnlock((Handle)hPic); if ((**gPrefs2Use_h).progress >= eProgDebug) puts("Reading PICT from data fork."); tryRsrcFork = false; /* successful! */ } } (void)FSClose(fref); } // Try to open as a PICT resource, data fork failed if (tryRsrcFork == true) { applref = CurResFile(); fref = FSpOpenResFile(f,fsRdPerm); if ((ResError() == 0) && (fref != -1)) { UseResFile(fref); if(CountResources('PICT') > 0) { hPic = (PicHandle)Get1IndResource('PICT',1); if(hPic != NULL) { DetachResource((Handle)hPic); if ((**gPrefs2Use_h).progress >= eProgDebug) puts("Reading PICT from resource fork."); } } (void)FSClose(fref); UseResFile(applref); } } if(hPic == NULL) return -2; *pict = hPic; return 0; } // Here's a really skanky thing to do to allow an alpha channel in offscreens static void Mac_ActivateAlphaChannel(GWorldPtr gw) { CGrafPtr oldPort; GDHandle oldGDev; PixMapHandle aPixMapH; GetGWorld(&oldPort,&oldGDev); SetGWorld(gw,NULL); aPixMapH = GetGWorldPixMap(gw); (**aPixMapH).cmpCount = 4; // from RGB to RGBA! PortChanged(qd.thePort); // tell QD to notice the cmpCount change SetGWorld(oldPort,oldGDev); } int Open_MacMovie_File(FILE_HANDLE *handle,char *name,int *width,int *height,int buffer_size,int mode) { PixMapHandle offPix; CGrafPtr oldPort; GDHandle oldGDev; Rect r; Movie movie; short fref; short resID = 128; Track dstTrack; Media dstMedia; OSErr err = 0,err2 = 0; int pixelSize; if(mode != WRITE_MODE) // movies are only written for now { Error("QuickTime Movies can only be written."); return 0; } // create movie once the first time, because we want animations to be saved to ONE movie, not each frame to one movie if(gMovieFile.name[0] == 0) { // Create an output movie file name from the scene name, in the same folder as the scene file gMovieFile = gSrcWind_FSSpec; BlockMoveData(opts.Scene_Name, gMovieFile.name, 1+strlen(opts.Scene_Name)); // change the output file name by adding a ".mov" on the end if(strlen((char*)gMovieFile.name)+4 > 31) gMovieFile.name[31-4] = 0; strcat((char*)gMovieFile.name,".mov"); // restore it to Pascal string C2PStr((char*)gMovieFile.name); // create the movie file err = CreateMovieFile(&gMovieFile,'TVOD',0,createMovieFileDeleteCurFile,&fref,&movie); if(err != noErr) { Error("Cannot open QuickTime Movie file. (Error: %d)", (int)err); return 0; } dstTrack = NewMovieTrack(movie,(long)(*width) << 16,(long)(*height) << 16,0); if(GetMoviesError() == 0) dstMedia = NewTrackMedia(dstTrack,VIDEO_TYPE,600,NULL,0); if(GetMoviesError() != 0) return GetMoviesError(); err = AddMovieResource(movie,fref,&resID,"\pPOV-Ray Animation"); if(err != noErr) Error("Cannot add QuickTime Movie resource. (Error: %d)", (int)err); err2 = CloseMovieFile(fref); if(err2 != noErr) Error("Cannot close QuickTime Movie file."); DisposeMovie(movie); if((err != noErr) || (err2 != noErr)) { gMovieFile.name[0] = 0; return 0; } } handle->buffer = NULL; handle->mode = mode; handle->filename = name; handle->width = *width; handle->height = *height; SetRect(&r,0,0,(int)(handle->width),(int)(handle->height)); GetGWorld(&oldPort,&oldGDev); if(opts.OutputQuality == 8) // 8 bits per color pixelSize = 32; else // 5 bits per color (and the rest for now) pixelSize = 16; err = NewGWorld((GWorldPtr *)&(handle->buffer),pixelSize,&r,NULL,NULL,0); if((err == 0) && (opts.Options & OUTPUT_ALPHA) && (pixelSize == 32)) // alpha-channels need 32 bits per pixel Mac_ActivateAlphaChannel((GWorldPtr)(handle->buffer)); if(err == 0) { offPix = GetGWorldPixMap((GWorldPtr)(handle->buffer)); if(offPix != NULL) { if(LockPixels(offPix)) { SetGWorld((GWorldPtr)(handle->buffer),NULL); ForeColor(blackColor); BackColor(whiteColor); EraseRect(&r); } UnlockPixels(offPix); } SetGWorld(oldPort,oldGDev); return 1; } return 0; // Something failed. } void Write_MacMovie_Line(FILE_HANDLE *handle,COLOUR *line_data,int line_number) { int i; unsigned char *pixPtr; unsigned short *bigPixPtr; unsigned short buf,component; PixMapHandle offPixMapH; offPixMapH = GetGWorldPixMap((GWorldPtr)(handle->buffer)); if(NULL == offPixMapH) Error("Cannot write QuickTime Movie (No GWorld)."); LockPixels(offPixMapH); pixPtr = (unsigned char *)GetPixBaseAddr(offPixMapH); pixPtr += line_number*(((**offPixMapH).rowBytes)&0x3fff); if((**offPixMapH).pixelSize == 32) { for(i = 0;i < handle->width; i++) { (*pixPtr++) = (unsigned char)(255.0 - (line_data[i][TRANSM] * 255.0)); // always written, but only saved if alpha-channel output is on (*pixPtr++) = (unsigned char)(line_data[i][RED] * 255.0); (*pixPtr++) = (unsigned char)(line_data[i][GREEN] * 255.0); (*pixPtr++) = (unsigned char)(line_data[i][BLUE] * 255.0); } } else if((**offPixMapH).pixelSize == 16) { bigPixPtr = (unsigned short *)pixPtr; for(i = 0;i < handle->width; i++) { buf = 0; component = ((unsigned char)(line_data[i][RED] * 31.0)) << 10; buf |= component; component = ((unsigned char)(line_data[i][GREEN] * 31.0)) << 5; buf |= component; component = ((unsigned char)(line_data[i][BLUE] * 31.0)); buf |= component; (*bigPixPtr++) = buf; } } UnlockPixels(offPixMapH); } void Close_MacMovie_File(FILE_HANDLE *handle) { Track dstTrack; Media dstMedia; OSType mediaType; OSErr err = 0; Handle compressedData = NULL; ImageDescriptionHandle imageDescH = NULL; TimeValue sampleDuration; short movieResRefNum; short actualResId; Movie movie; Rect r; Boolean editing = false; Boolean haveMovie = false; Fixed fval; TimeValue tval; if(gMovieFile.name[0] == 0) // there is no file open so we have to return return; if(handle->buffer == NULL) // if there is no image data we return return; err = OpenMovieFile(&gMovieFile,&movieResRefNum,fsWrPerm); if(err != noErr) Error("Cannot open QuickTime Movie file. (Error: %d)", (int)err); else { actualResId = 0; err = NewMovieFromFile(&movie,movieResRefNum,&actualResId,(StringPtr)0,newMovieActive,(Boolean *)0); if(err == noErr) haveMovie = true; } if((GetMoviesError() == noErr) && (err == noErr)) dstTrack = GetMovieIndTrack(movie,1); if((GetMoviesError() == noErr) && (err == noErr)) dstMedia = GetTrackMedia(dstTrack); if((GetMoviesError() == noErr) && (err == noErr)) GetMediaHandlerDescription(dstMedia,&mediaType,NULL,NULL); if(mediaType != VideoMediaType) { Error("Cannot find video track in movie."); err = paramErr; } if((GetMoviesError() == noErr) && (err == noErr)) { BeginMediaEdits(dstMedia); editing = true; } if((GetMoviesError() == noErr) && (err == noErr)) { LockPixels(GetGWorldPixMap((GWorldPtr)(handle->buffer))); SetRect(&r,0,0,(int)(handle->width),(int)(handle->height)); err = SCCompressImage(gtheSCComponent,GetGWorldPixMap((GWorldPtr)(handle->buffer)),&r,&imageDescH,&compressedData); } if((GetMoviesError() == noErr) && (err == noErr)) { fval = (GetMediaTimeScale(dstMedia) & 0x0000ffff) << 16; fval = FixDiv(fval,(**gPrefs2Use_h).sc_TemporalDialogParams.frameRate); tval = fval >> 16; err = AddMediaSample(dstMedia,compressedData,0,(**imageDescH).dataSize,tval,(SampleDescriptionHandle)imageDescH,1,0,&sampleDuration); } if((GetMoviesError() == noErr) && (err == noErr)) err = InsertMediaIntoTrack(dstTrack,GetTrackDuration(dstTrack),sampleDuration,tval,0x00010000); if(editing == true) EndMediaEdits(dstMedia); if((GetMoviesError() == noErr) && (err == noErr)) err = UpdateMovieResource(movie,movieResRefNum,actualResId,NULL); if((GetMoviesError() == noErr) && (err == noErr)) err = CloseMovieFile(movieResRefNum); if(haveMovie == true) DisposeMovie(movie); if(compressedData != NULL) DisposeHandle(compressedData); if(imageDescH != NULL) DisposeHandle((Handle)imageDescH); DisposeGWorld((GWorldPtr)(handle->buffer)); handle->file = NULL; handle->buffer = NULL; return; } // Opens a PICT file for read, write, or append. static int Open_MacPICT_File(FILE_HANDLE *handle,char *name,int *width,int *height,int buffersize,int mode) { char *nameptr; OSErr anError = noErr; if(gHasQuickTime == false) gMapPictToMovie = false; if(name == NULL) return 0; //string.h nameptr = strrchr(name, ':'); if(nameptr == NULL) nameptr = name; if((gMapPictToMovie == true) && (mode == WRITE_MODE)) { handle->flag = 2; handle->buffer = (char *)POV_MALLOC(sizeof(MOVIE_FILE),"movie"); anError = image_movie_create((MOVIE_FILE *)handle->buffer,name,width,height,mode); } else { handle->flag = 1; handle->buffer = (char *)POV_MALLOC(sizeof(PICTURE_FILE),"pict"); anError = image_picture_create((PICTURE_FILE *)handle->buffer,name,width,height,mode); } if(anError != noErr) return 0; else return 1; } // Writes a single image line. static void Write_MacPICT_Line(FILE_HANDLE *handle,COLOUR *line_data,int line_number) { if(handle->buffer == NULL) { puts("warning: got invalid mac file handle."); return; } if(handle->flag == 2) image_movie_write_line((MOVIE_FILE *)handle->buffer,line_data,line_number); else image_picture_write_line((PICTURE_FILE *)handle->buffer,line_data,line_number); } // Reads a single image line to resuming partial renders. static int Read_MacPICT_Line(FILE_HANDLE *handle,COLOUR *line_data,int *line_number) { if(handle->flag == 2) return 0; else return image_picture_read_line((PICTURE_FILE *)handle->buffer,line_data,line_number); } // Closes a PICT file. static void Close_MacPICT_File(FILE_HANDLE *handle) { if(handle->buffer == NULL) return; if(handle->flag == 2) { image_movie_delete((MOVIE_FILE *)handle->buffer); POV_FREE(handle->buffer); handle->buffer = NULL; } else { image_picture_delete((PICTURE_FILE *)handle->buffer); POV_FREE(handle->buffer); handle->buffer = NULL; } } void Read_MacPICT_Image(IMAGE *imageptr,char *filename) { OSErr anError = noErr; int width; int height; PICTURE_FILE *mhandle = NULL; mhandle = (PICTURE_FILE *)POV_MALLOC(sizeof(PICTURE_FILE),"pict"); anError = image_picture_create(mhandle,filename,&width,&height,READ_MODE); if(anError) Error("can not read pict."); else { image_picture_read_image(mhandle,imageptr); POV_FREE(mhandle); } } static void image_picture_alpha_channel(GWorldPtr gw) { CGrafPtr keepGPtr; GDHandle keepGDh; PixMapHandle keepPixMapH; //QDOffscreen.h GetGWorld(&keepGPtr,&keepGDh); //QDOffscreen.h SetGWorld(gw,NULL); //QDOffscreen.h keepPixMapH = GetGWorldPixMap(gw); (**keepPixMapH).cmpCount = 4; //QDOffscreen.h PortChanged(qd.thePort); //QDOffscreen.h SetGWorld(keepGPtr,keepGDh); } static OSErr image_movie_create(MOVIE_FILE *mhandle,char *name, int *width, int *height, int mode) { PixMapHandle keepPixMapH; CGrafPtr keepGPtr; GDHandle keepGDh; OSErr anError = 0; OSErr anError2 = 0; Rect r; Movie keepMovie; short fref; short resID = 128; Track keepTrack; Media keepMedia; int pixelSize; if(mode != WRITE_MODE) { Error("QuickTime Movies can only be written."); return paramErr; } if(gMovieFile.name[0] == 0) { gMovieFile = gSrcWind_FSSpec; //MacMemory.h //string.h BlockMoveData(opts.Scene_Name, gMovieFile.name, 1 + strlen(opts.Scene_Name)); //string.h if(strlen((char *)(gMovieFile.name)) + 4 > 63) gMovieFile.name[63-4] = 0; //string.h strcat((char *)(gMovieFile.name), ".mov"); //TextUtils.h c2pstr((char *)(gMovieFile.name)); //Movies.h anError = CreateMovieFile(&gMovieFile, 'TVOD', 0, createMovieFileDeleteCurFile, &fref, &keepMovie); if(anError != noErr) { Error("can not open QuickTime Movie file. (Error: %d)", (int)anError); return anError; } //Movies.h keepTrack = NewMovieTrack(keepMovie,(long)(*width) << 16,(long)(*height) << 16,0); if(GetMoviesError() == noErr) { //Movies.h keepMedia = NewTrackMedia(keepTrack, VIDEO_TYPE, 600, NULL, 0); } //Movies.h if(GetMoviesError() != noErr) return GetMoviesError(); //Movies.h anError = AddMovieResource(keepMovie, fref, &resID, "\pPOV-Ray Animation"); if(anError != noErr) Error("can not add QuickTime Movie resource. (Error: %d)", (int)anError); //Movies.h anError2 = CloseMovieFile(fref); if(anError2 != noErr) Error("can not close QuickTime Movie file."); //Movies.h DisposeMovie(keepMovie); if((anError != noErr) || (anError2 != noErr)) { gMovieFile.name[0] = 0; return anError; } } mhandle->fMode = mode; mhandle->fWidth = *width; mhandle->fHeight = *height; //Quickdraw.h SetRect(&r, 0, 0, mhandle->fWidth, mhandle->fHeight); //QDOffscreen.h GetGWorld(&keepGPtr, &keepGDh); if(opts.OutputQuality == 8) pixelSize = 32; else pixelSize = 16; //QDOffscreen.h anError = NewGWorld(&mhandle->fTargetGWorld, pixelSize, &r, NULL, NULL, 0); if((anError == noErr) && (opts.Options & OUTPUT_ALPHA) && (pixelSize == 32)) // alpha-channels need 32 bits per pixel image_picture_alpha_channel(mhandle->fTargetGWorld); if(anError == noErr) { //QDOffscreen.h keepPixMapH = GetGWorldPixMap(mhandle->fTargetGWorld); if(keepPixMapH != NULL) { //QDOffscreen.h if(LockPixels(keepPixMapH)) { //QDOffscreen.h SetGWorld(mhandle->fTargetGWorld,NULL); //Quickdraw.h ForeColor(blackColor); //Quickdraw.h BackColor(whiteColor); //Quickdraw.h EraseRect(&r); } //QDOffscreen.h UnlockPixels(keepPixMapH); } //QDOffscreen.h SetGWorld(keepGPtr,keepGDh); anError = noErr; } return anError; // Something failed. } OSErr image_picture_create(PICTURE_FILE *mhandle,char *name, int *width, int *height, int mode) { OSErr anError = noErr; int pixelSize; mhandle->fMode = mode; mhandle->fTargetGWorld = NULL; mhandle->fLastLine = 0; if(opts.OutputQuality == 8) pixelSize = 32; else pixelSize = 16; switch(mhandle->fMode) { case READ_MODE: case APPEND_MODE: anError = image_picture_make_file(name, &mhandle->fFile); if(anError == noErr) anError = image_picture_gworld_from_file(mhandle); else if(anError == 1) anError = image_picture_gworld_from_image(mhandle); if(anError == noErr) { *width = mhandle->fWidth; *height = mhandle->fHeight; if((mhandle->fLastLine == 0) || (mhandle->fLastLine > mhandle->fHeight)) mhandle->fLastLine = mhandle->fHeight; } break; case WRITE_MODE: mhandle->fWidth = *width; mhandle->fHeight = *height; //string.h mhandle->fFile.name[0] = strlen(name); if(mhandle->fFile.name[0] > 63) mhandle->fFile.name[0] = 63; //MacMemory.h BlockMoveData(name, &mhandle->fFile.name[1], mhandle->fFile.name[0]); mhandle->fFile.vRefNum = gSrcWind_FSSpec.vRefNum; mhandle->fFile.parID = gSrcWind_FSSpec.parID; if(anError == noErr) anError = image_picture_gworld_create(mhandle,*width, *height, pixelSize); if(anError == noErr) anError = image_picture_new(mhandle); break; } if(anError != noErr) return 1; else return 0; } static void image_picture_write_line(PICTURE_FILE *mhandle,COLOUR *line_data, int line_number) { int i; unsigned char *pixPtr; unsigned short *bigPixPtr; unsigned short buf; unsigned short component; PixMapHandle keepPixMapH; //QDOffscreen.h keepPixMapH = GetGWorldPixMap(mhandle->fTargetGWorld); if(NULL == keepPixMapH) Error("can not write Mac Picture (No GWorld PixMap)."); //QDOffscreen.h if(LockPixels(keepPixMapH) == false) Error("can not lock Mac Picture GWorld PixMap."); //QDOffscreen.h pixPtr = (unsigned char *)GetPixBaseAddr(keepPixMapH); pixPtr += line_number * (((**keepPixMapH).rowBytes) & 0x3fff); // + Y scanline offset down if((**keepPixMapH).pixelSize == 32) { for(i = 0;i < mhandle->fWidth; i++) { (*pixPtr++) = (unsigned char)(255.0 - (line_data[i][TRANSM] * 255.0)); // always written, but only saved if alpha-channel output is on (*pixPtr++) = (unsigned char)(line_data[i][RED] * 255.0); (*pixPtr++) = (unsigned char)(line_data[i][GREEN] * 255.0); (*pixPtr++) = (unsigned char)(line_data[i][BLUE] * 255.0); } } else if((**keepPixMapH).pixelSize == 16) { bigPixPtr = (unsigned short *)pixPtr; for(i = 0;i < mhandle->fWidth; i++) { buf = 0; component = ((unsigned short)(line_data[i][RED] * 31.0)) << 10; buf |= component; component = ((unsigned short)(line_data[i][GREEN] * 31.0)) << 5; buf |= component; component = ((unsigned short)(line_data[i][BLUE] * 31.0)); buf |= component; (*bigPixPtr++) = buf; } } //QDOffscreen.h UnlockPixels(keepPixMapH); mhandle->fLastLine++; } static void image_movie_write_line(MOVIE_FILE *mhandle,COLOUR *line_data,int line_number) { int i; unsigned char *pixPtr; unsigned short *bigPixPtr; unsigned short buf; unsigned short component; PixMapHandle keepPixMapH; //QDOffscreen.h keepPixMapH = GetGWorldPixMap(mhandle->fTargetGWorld); if(NULL == keepPixMapH) Error("can not write QuickTime Movie (No GWorld)."); //QDOffscreen.h LockPixels(keepPixMapH); //QDOffscreen.h pixPtr = (unsigned char *)GetPixBaseAddr(keepPixMapH); pixPtr += line_number * (((**keepPixMapH).rowBytes) & 0x3fff); if((**keepPixMapH).pixelSize == 32) { for(i = 0;i < mhandle->fWidth; i++) { (*pixPtr++) = (unsigned char)(255.0 - (line_data[i][TRANSM] * 255.0)); // always written, but only saved if alpha-channel output is on (*pixPtr++) = (unsigned char)(line_data[i][RED] * 255.0); (*pixPtr++) = (unsigned char)(line_data[i][GREEN] * 255.0); (*pixPtr++) = (unsigned char)(line_data[i][BLUE] * 255.0); } } else if((**keepPixMapH).pixelSize == 16) { bigPixPtr = (unsigned short *)pixPtr; for(i = 0;i < mhandle->fWidth; i++) { buf = 0; component = ((unsigned char)(line_data[i][RED] * 31.0)) << 10; buf |= component; component = ((unsigned char)(line_data[i][GREEN] * 31.0)) << 5; buf |= component; component = ((unsigned char)(line_data[i][BLUE] * 31.0)); buf |= component; (*bigPixPtr++) = buf; } } //QDOffscreen.h UnlockPixels(keepPixMapH); } static int image_picture_read_line(PICTURE_FILE *mhandle,COLOUR *line_data, int *line_number) { int x; unsigned char *pixPtr; PixMapHandle keepPixMapH; if(mhandle->fLastLine >= 0) { if(*line_number >= mhandle->fLastLine) { (*line_number)--; return 0; } } if(*line_number >= mhandle->fHeight) { (*line_number)--; return 0; } (*line_number)++; if ((**gPrefs2Use_h).progress >= eProgDebug) printf("reading line: %d\n", (1 + *line_number)); //QDOffscreen.h keepPixMapH = GetGWorldPixMap(mhandle->fTargetGWorld); if(NULL == keepPixMapH) Error("can not read Mac Picture (No PixMap)."); //QDOffscreen.h LockPixels(keepPixMapH); if(NULL == keepPixMapH) Error("can not lock Mac Picture GWorld PixMap."); //QDOffscreen.h pixPtr = (unsigned char *)GetPixBaseAddr(keepPixMapH); // start at base address pixPtr += *line_number * (((**keepPixMapH).rowBytes) & 0x3fff);// + Y scanline offset down for(x = 0; x < mhandle->fWidth; x++) { if((**keepPixMapH).cmpCount == 4) line_data[x][TRANSM] = (255.0 - (*pixPtr++)) / 255.0; else { pixPtr++; line_data[x][TRANSM] = 0.0; } line_data[x][RED] = ((*pixPtr++)) / 255.0; line_data[x][GREEN] = ((*pixPtr++)) / 255.0; line_data[x][BLUE] = ((*pixPtr++)) / 255.0; line_data[x][FILTER] = 0.0; } //QDOffscreen.h UnlockPixels(keepPixMapH); return 1; } static void image_picture_read_image(PICTURE_FILE *mhandle,IMAGE *imageptr) { int x; int y; unsigned char *pixPtr; PixMapHandle keepPixMapH; imageptr->iwidth = mhandle->fWidth; imageptr->iheight = mhandle->fHeight; imageptr->width = (float)mhandle->fWidth; imageptr->height = (float)mhandle->fHeight; imageptr->Colour_Map_Size = 0; imageptr->Colour_Map = NULL; imageptr->data.rgb_lines = (IMAGE_LINE *)POV_MALLOC(mhandle->fHeight * sizeof(IMAGE_LINE), "pict"); if(imageptr->data.rgb_lines != NULL) { //QDOffscreen.h keepPixMapH = GetGWorldPixMap(mhandle->fTargetGWorld); if(NULL == keepPixMapH) Error("can not read Mac Picture (No GWorld)."); //QDOffscreen.h if(LockPixels(keepPixMapH) == false) Error("can not lock Mac Picture GWorld PixMap."); for(y = 0;y < mhandle->fHeight;y++) { //QDOffscreen.h pixPtr = (unsigned char *)GetPixBaseAddr(keepPixMapH); // start at base address pixPtr += y * (((**keepPixMapH).rowBytes) & 0x3fff); // + Y scanline offset down imageptr->data.rgb_lines[y].red = (unsigned char *)POV_MALLOC(mhandle->fWidth, "red"); imageptr->data.rgb_lines[y].green = (unsigned char *)POV_MALLOC(mhandle->fWidth, "green"); imageptr->data.rgb_lines[y].blue = (unsigned char *)POV_MALLOC(mhandle->fWidth, "blue"); imageptr->data.rgb_lines[y].transm = (unsigned char *)POV_MALLOC(mhandle->fWidth, "transparency"); for(x = 0;x < mhandle->fWidth; x++) { if((**keepPixMapH).cmpCount == 4) imageptr->data.rgb_lines[y].transm[x] = 255 - (*pixPtr++); else { pixPtr++; imageptr->data.rgb_lines[y].transm[x] = 0.0; } imageptr->data.rgb_lines[y].red[x] = (*pixPtr++); imageptr->data.rgb_lines[y].green[x] = (*pixPtr++); imageptr->data.rgb_lines[y].blue[x] = (*pixPtr++); } } //QDOffscreen.h UnlockPixels(keepPixMapH); } else Error("can not read Mac Picture (Out of memory!)."); } static void image_movie_delete(MOVIE_FILE *mhandle) { Track keepTrack; Media keepMedia; OSType mediaType; OSErr anError = 0; Handle compressedData = NULL; ImageDescriptionHandle imageDescH = NULL; short movieResRefNum; short actualResId; Movie keepMovie; Rect r; Boolean editing = false; Boolean haveMovie = false; Fixed fval; TimeValue tval; TimeValue sampleDuration; if(gMovieFile.name[0] == 0) return; //Movies.h anError = OpenMovieFile(&gMovieFile,&movieResRefNum,fsWrPerm); if(anError != noErr) Error("can not open QuickTime Movie file. (Error: %d)", (int)anError); else { actualResId = 0; //Movies.h anError = NewMovieFromFile(&keepMovie,movieResRefNum,&actualResId,(StringPtr)0,newMovieActive,(Boolean *)0); if(anError == noErr) haveMovie = true; } //Movies.h if((GetMoviesError() == noErr) && (anError == noErr)) keepTrack = GetMovieIndTrack(keepMovie,1); //Movies.h if((GetMoviesError() == noErr) && (anError == noErr)) keepMedia = GetTrackMedia(keepTrack); //Movies.h if((GetMoviesError() == noErr) && (anError == noErr)) GetMediaHandlerDescription(keepMedia,&mediaType,NULL,NULL); if(mediaType != VideoMediaType) { Error("can not find video track in movie."); anError = paramErr; } //Movies.h if((GetMoviesError() == noErr) && (anError == noErr)) { //Movies.h BeginMediaEdits(keepMedia); editing = true; } //Movies.h if((GetMoviesError() == noErr) && (anError == noErr)) { //QDOffscreen.h LockPixels(GetGWorldPixMap(mhandle->fTargetGWorld)); //Quickdraw.h SetRect(&r, 0, 0, mhandle->fWidth, mhandle->fHeight); //QuickTimeComponents.h //QDOffscreen.h anError = SCCompressImage(gtheSCComponent, GetGWorldPixMap(mhandle->fTargetGWorld), &r, &imageDescH, &compressedData); } //Movies.h if((GetMoviesError() == noErr) && (anError == noErr)) { //Movies.h fval = (GetMediaTimeScale(keepMedia) & 0x0000ffff) << 16; //FixMath.h fval = FixDiv(fval,(**gPrefs2Use_h).sc_TemporalDialogParams.frameRate); tval = fval >> 16; //Movies.h anError = AddMediaSample(keepMedia,compressedData,0,(**imageDescH).dataSize,tval,(SampleDescriptionHandle)imageDescH,1,0,&sampleDuration); } //Movies.h if((GetMoviesError() == noErr) && (anError == noErr)) anError = InsertMediaIntoTrack(keepTrack,GetTrackDuration(keepTrack),sampleDuration,tval,0x00010000); //Movies.h if(editing == true) EndMediaEdits(keepMedia); //Movies.h if((GetMoviesError() == noErr) && (anError == noErr)) anError = UpdateMovieResource(keepMovie,movieResRefNum,actualResId,NULL); //Movies.h if((GetMoviesError() == noErr) && (anError == noErr)) anError = CloseMovieFile(movieResRefNum); //Movies.h if(haveMovie == true) DisposeMovie(keepMovie); //MacMemory.h if(compressedData != NULL) DisposeHandle(compressedData); //MacMemory.h if(imageDescH != NULL) DisposeHandle((Handle)imageDescH); //QDOffscreen.h DisposeGWorld(mhandle->fTargetGWorld); return; } static void image_picture_delete(PICTURE_FILE *mhandle) { long dataSize; int pixelSize; SInt16 fref; OSErr anError = noErr; PicHandle keepPicH = NULL; CGrafPtr keepGPtr; GDHandle keepGDh; PixMapHandle keepPixMapH; Rect r; char headerString[PICTF_HEADER_SIZE] = "POV-Ray!"; PICT_FILE_HEADER myPictFHeader; if(opts.OutputQuality == 8) pixelSize = 32; else pixelSize = 16; switch(mhandle->fMode) { case WRITE_MODE: case APPEND_MODE: //QDOffscreen.h GetGWorld(&keepGPtr, &keepGDh); //QDOffscreen.h SetGWorld(mhandle->fTargetGWorld, NULL); //Quickdraw.h keepPicH = OpenPicture(&r); //Quickdraw.h anError = QDError(); if(keepPicH == NULL) anError = mFulErr; else if(anError == noErr) { //Quickdraw.h SetRect(&r, 0, 0, mhandle->fWidth, mhandle->fHeight); //Quickdraw.h ClipRect(&r); //Quickdraw.h ForeColor(blackColor); //Quickdraw.h BackColor(whiteColor); //QDOffscreen.h keepPixMapH = GetGWorldPixMap(mhandle->fTargetGWorld); //QDOffscreen.h if(LockPixels(keepPixMapH) == false) Error("can not lock Mac Picture GWorld PixMap."); //Quickdraw.h CopyBits((BitMap *)(*keepPixMapH), (BitMap *)(*keepPixMapH), &r, &r, srcCopy | ditherCopy, NULL); anError = QDError(); //QDOffscreen.h UnlockPixels(keepPixMapH); //Quickdraw.h ClosePicture(); //MacMemory.h HLock((Handle)keepPicH); //Files.h if(anError == noErr) anError = FSpOpenDF(&mhandle->fFile, fsWrPerm, &fref); if(anError == noErr) { //MacMemory.h BlockMoveData(&mhandle->fLastLine, &headerString[9], sizeof(mhandle->fLastLine)); dataSize = PICTF_HEADER_SIZE; //Files.h anError = FSWrite(fref, &dataSize, &headerString[0]); //MacMemory.h dataSize = GetHandleSize((Handle)keepPicH); //Files.h anError = FSWrite(fref, &dataSize, (Ptr)(*keepPicH)); myPictFHeader.picSize = (short)(dataSize & 0x7fff); //Quickdraw.h SetRect(&myPictFHeader.picFrame, 0, 0, mhandle->fWidth, mhandle->fHeight); //Files.h (void)SetFPos(fref, fsFromStart, PICTF_HEADER_SIZE); dataSize = sizeof(PICT_FILE_HEADER); //Files.h anError = FSWrite(fref, &dataSize, (Ptr)(&myPictFHeader)); //Files.h (void)FSClose(fref); } //MacMemory.h HUnlock((Handle)keepPicH); //Quickdraw.h KillPicture(keepPicH); if ((anError == noErr) && (gHasImageCompressionMgr == true) && ((**gPrefs2Use_h).doCompression)) { (void)image_compress_pict_file(gtheSCComponent, &mhandle->fFile); } if ((anError == noErr) && (gHasImageCompressionMgr == true) && (APGetDataAccessor(kAPData_AddCustomIcons,NULL) != 0)) { anError = AppendFinderIcons2PictF(&mhandle->fFile, &r, eAFI_ShrinkWholeImage); } } //QDOffscreen.h SetGWorld(keepGPtr,keepGDh); break; } //QDOffscreen.h if(mhandle->fTargetGWorld != NULL) DisposeGWorld(mhandle->fTargetGWorld); if(anError != noErr) Error("can not write Mac Picture file (MacOS returned error %d).", (int)anError); } static OSErr image_picture_make_file(char *name_cstring, FSSpec *fs) { FInfo keepFileInfo; OSErr anError; OSErr anError2; Boolean b; Str255 name; //MacMemory.h //string.h BlockMoveData(name_cstring,&name[1],strlen(name_cstring)); //string.h name[0] = strlen(name_cstring); //Files.h anError = FSMakeFSSpec(gSrcWind_FSSpec.vRefNum, gSrcWind_FSSpec.parID, name, fs); //Files.h if(anError == noErr) anError = FSpGetFInfo(fs, &keepFileInfo); if(anError == noErr) { if(keepFileInfo.fdType == 'PICT') return noErr; // found else anError = 1; // not found, but valid } anError2 = anError; //Aliases.h ResolveAlias(NULL, (AliasHandle)((**gAppPrefs_h).libPath[0]), fs, &b); //Files.h anError = FSMakeFSSpec(fs->vRefNum, fs->parID, name, fs); //Files.h if(anError == noErr) anError = FSpGetFInfo(fs, &keepFileInfo); if(anError == noErr) { if(keepFileInfo.fdType == 'PICT') return noErr; // found else anError = 1; // not found, but valid } //Aliases.h ResolveAlias(NULL, (AliasHandle)((**gAppPrefs_h).libPath[1]), fs, &b); //Files.h anError = FSMakeFSSpec(fs->vRefNum, fs->parID, name, fs); //Files.h if(anError == noErr) anError = FSpGetFInfo(fs, &keepFileInfo); if(anError == noErr) { if(keepFileInfo.fdType == 'PICT') return noErr; // found else anError = 1; // not found, but valid } else if(anError2 == 1) { //Files.h anError = FSMakeFSSpec(gSrcWind_FSSpec.vRefNum, gSrcWind_FSSpec.parID, name, fs); if(anError == noErr) anError = 1; } return anError; } static OSErr image_picture_gworld_from_file(PICTURE_FILE *mhandle) { PicHandle keepPicH = NULL; OSErr anError = noErr; Rect r = { 0, 0, 0, 0 }; keepPicH = image_picture_handle_from_file(mhandle); if(keepPicH == NULL) anError = mFulErr; if(anError == noErr) { r = (**keepPicH).picFrame; r.right -= r.left; r.bottom -= r.top; r.left = 0; r.top = 0; mhandle->fWidth = r.right; mhandle->fHeight = r.bottom; anError = image_picture_gworld_create(mhandle,mhandle->fWidth, mhandle->fHeight, 32); } if(anError == noErr) anError = image_picture_paint(mhandle,keepPicH); //Quickdraw.h if(keepPicH != NULL) KillPicture(keepPicH); return anError; } static OSErr image_picture_gworld_from_image(PICTURE_FILE *mhandle) { OSErr anError = paramErr; Rect r; GraphicsImportComponent gi; if(gHasQuickTime == true) { //ImageCompression.h anError = GetGraphicsImporterForFile(&mhandle->fFile, &gi); //ImageCompression.h if(anError == noErr) anError = GraphicsImportGetNaturalBounds(gi, &r); if(anError == noErr) { r.right -= r.left; r.bottom -= r.top; r.left = 0; r.top = 0; mhandle->fWidth = r.right; mhandle->fHeight = r.bottom; //ImageCompression.h anError = GraphicsImportSetBoundsRect(gi, &r); } if(anError == noErr) anError = image_picture_gworld_create(mhandle,mhandle->fWidth, mhandle->fHeight, 32); //ImageCompression.h //QDOffscreen.h if(anError == noErr) anError = GraphicsImportSetGWorld(gi, mhandle->fTargetGWorld, GetGWorldDevice(mhandle->fTargetGWorld)); //ImageCompression.h if(anError == noErr) anError = GraphicsImportDraw(gi); //Components.h CloseComponent(gi); } return anError; } static OSErr image_picture_gworld_create(PICTURE_FILE *mhandle,int w, int h, int d) { OSErr anError; Rect r; //Quickdraw.h SetRect(&r, 0, 0, w, h); //QDOffscreen.h anError = NewGWorld(&mhandle->fTargetGWorld, d, &r, NULL, NULL, 0); if((mhandle->fTargetGWorld == NULL) && (anError == noErr)) anError = mFulErr; if(anError == noErr) image_picture_gworld_clear(mhandle); return anError; } static OSErr image_picture_new(PICTURE_FILE *mhandle) { OSErr anError = noErr; OSType *keepType; keepType = FilePrefs_GetFCPtr(*gPrefs2Use_h, eOutfSystem); //Files.h anError = FSpCreate(&mhandle->fFile, *keepType, 'PICT', smSystemScript); if(anError == dupFNErr) anError = noErr; return anError; } static void image_picture_gworld_clear(PICTURE_FILE *mhandle) { int i; int l; unsigned char *pixPtr; unsigned short *bigPixPtr; unsigned short buf; PixMapHandle keepPixMapH; //QDOffscreen.h keepPixMapH = GetGWorldPixMap(mhandle->fTargetGWorld); if(NULL == keepPixMapH) Error("can not write Mac Picture (No GWorld PixMap)."); //QDOffscreen.h if(LockPixels(keepPixMapH) == false) Error("can not lock Mac Picture GWorld PixMap."); for(l = 0;l < mhandle->fHeight; l++) { //QDOffscreen.h pixPtr = (unsigned char *)GetPixBaseAddr(keepPixMapH); pixPtr += l * (((**keepPixMapH).rowBytes) & 0x3fff); // + Y scanline offset down if((**keepPixMapH).pixelSize == 32) { for(i = 0;i < mhandle->fWidth; i++) { (*pixPtr++) = (unsigned char)0; (*pixPtr++) = (unsigned char)0; (*pixPtr++) = (unsigned char)0; (*pixPtr++) = (unsigned char)0; } } else if((**keepPixMapH).pixelSize == 16) { bigPixPtr = (unsigned short *)pixPtr; for(i = 0;i < mhandle->fWidth; i++) { buf = 0; (*bigPixPtr++) = buf; } } } //QDOffscreen.h UnlockPixels(keepPixMapH); } // Paints the PICT to an R/G/B/Alpha GWorld static OSErr image_picture_paint(PICTURE_FILE *mhandle,PicHandle pict) { PixMapHandle keepPixMapH; Rect r; Boolean imageHasAlpha = false; OSErr anError = 0; CGrafPtr keepGPtr; GDHandle keepGDh; if((pict == NULL) || (mhandle->fTargetGWorld == NULL)) return paramErr; if(mhandle->fWidth > 2047) { Error("pict is too big, maximal width of picture to read is 2047 pixels!"); return mFulErr; } if((**gPrefs2Use_h).progress >= eProgDebug) printf("picture size is %d * %d pixel.\n", mhandle->fWidth, mhandle->fHeight); //Quickdraw.h SetRect(&r, 0, 0, mhandle->fWidth, mhandle->fHeight); //QDOffscreen.h keepPixMapH = GetGWorldPixMap(mhandle->fTargetGWorld); if(NULL == keepPixMapH) return -1; //QDOffscreen.h if(!LockPixels(keepPixMapH)) return -1; //QDOffscreen.h GetGWorld(&keepGPtr, &keepGDh); //QDOffscreen.h SetGWorld(mhandle->fTargetGWorld, NULL); //Quickdraw.h ForeColor(blackColor); //Quickdraw.h BackColor(whiteColor); //Quickdraw.h EraseRect(&r); //Quickdraw.h DrawPicture(pict, &r); //QDOffscreen.h UnlockPixels(keepPixMapH); //QDOffscreen.h SetGWorld(keepGPtr, keepGDh); return anError; } // Mac Picture reading code static PicHandle image_picture_handle_from_file(PICTURE_FILE *mhandle) { const long kPictHeaderSize = PICTF_HEADER_SIZE; Boolean tryRsrcFork; long pictFileLen; long headerFileLen; short applref; short fref; PicHandle keepPicH; char headerString[PICTF_HEADER_SIZE]; tryRsrcFork = true; //Files.h if(FSpOpenDF(&mhandle->fFile, fsRdPerm, &fref) == 0) { //Files.h (void)GetEOF(fref, &pictFileLen); pictFileLen -= kPictHeaderSize; if(pictFileLen > 0) { //Files.h (void)SetFPos(fref, fsFromStart, 0); headerFileLen = PICTF_HEADER_SIZE; //Files.h (void)FSRead(fref, &headerFileLen, (Ptr)(&headerString[0])); headerString[8] = 0; //string.h //MacMemory.h if(strcmp(headerString, "POV-Ray!") == 0) BlockMoveData(&headerString[9], &mhandle->fLastLine, sizeof(mhandle->fLastLine)); //Files.h (void)SetFPos(fref, fsFromStart, PICTF_HEADER_SIZE); //MacMemory.h keepPicH = (PicHandle)NewHandleClear(pictFileLen); if (keepPicH != NULL) { //MacMemory.h HLock((Handle)keepPicH); //Files.h (void)FSRead(fref, &pictFileLen, (Ptr)(*keepPicH)); //MacMemory.h HUnlock((Handle)keepPicH); if((**gPrefs2Use_h).progress >= eProgDebug) puts("Reading PICT from data fork."); tryRsrcFork = false; } } //Files.h (void)FSClose(fref); } if(tryRsrcFork == true) { //Resources.h applref = CurResFile(); //Resources.h fref = FSpOpenResFile(&mhandle->fFile, fsRdPerm); //Resources.h if((ResError() == 0) && (fref != -1)) { //Resources.h UseResFile(fref); //Resources.h if(CountResources('PICT') > 0) { //Resources.h keepPicH = (PicHandle)Get1IndResource('PICT', 1); if(keepPicH != NULL) { //Resources.h DetachResource((Handle)keepPicH); if((**gPrefs2Use_h).progress >= eProgDebug) puts("Reading PICT from resource fork."); } } //Files.h (void)FSClose(fref); //Resources.h UseResFile(applref); } } return keepPicH; } static OSErr image_compress_pict_file(ComponentInstance ci,FSSpec *theImageFile) { OSErr anError; short theFileRefNum; //Files.h anError = FSpOpenDF(theImageFile,fsRdWrPerm,&theFileRefNum); if(!anError) { //QuickTimeComponents.h anError = SCCompressPictureFile(ci,theFileRefNum,theFileRefNum); //Files.h FSClose(theFileRefNum); } return(anError); }