192fd3c4332038bf4e38be945a2e9fcd8179132d
[blender-staging.git] / source / blender / quicktime / apple / quicktime_import.c
1 /*
2  * $Id$
3  *
4  * quicktime_import.c
5  *
6  * Code to use Quicktime to load images/movies as texture.
7  *
8  * ***** BEGIN GPL LICENSE BLOCK *****
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  *
23  *
24  * The Original Code is written by Rob Haarsma (phase)
25  *
26  * Contributor(s): Stefan Gartner (sgefant)
27  *
28  * ***** END GPL LICENSE BLOCK *****
29  */
30
31 /** \file blender/quicktime/apple/quicktime_import.c
32  *  \ingroup quicktime
33  */
34
35 #ifdef WITH_QUICKTIME
36
37 #if defined(_WIN32) || defined(__APPLE__)
38 #ifndef USE_QTKIT
39
40 #include "MEM_guardedalloc.h"
41 #include "IMB_anim.h"
42 #include "BLO_sys_types.h"
43 #include "BKE_global.h"
44 #include "BLI_dynstr.h"
45
46 #ifdef __APPLE__
47 #include <QuickTime/Movies.h>
48 #include <QuickTime/QuickTimeComponents.h>
49 #endif
50
51 #ifdef _WIN32
52 #include <Movies.h>
53 #include <QTML.h>
54 #include <TextUtils.h>
55 #include <QuickTimeComponents.h>
56 #include <QTLoadLibraryUtils.h>
57 #endif /* _WIN32 */
58
59
60 #include "quicktime_import.h"
61 #include "quicktime_export.h"
62
63 #define RECT_WIDTH(r)   (r.right-r.left)
64 #define RECT_HEIGHT(r)  (r.bottom-r.top)
65
66 #define QTIME_DEBUG 0
67
68 typedef struct _QuicktimeMovie {
69
70         GWorldPtr       offscreenGWorld;
71         PixMapHandle    offscreenPixMap;
72         Movie           movie;
73         Rect            movieBounds;
74         short           movieRefNum;
75         short           movieResId;
76         int                     movWidth, movHeight;
77
78         
79         int                     framecount;
80         
81         
82         ImBuf           *ibuf;
83         
84
85         TimeValue       *frameIndex;
86         Media           theMedia;
87         Track           theTrack;
88         long            trackIndex;
89         short           depth;
90         
91         int                     have_gw;        //ugly
92 } QuicktimeMovie;
93
94
95
96 void quicktime_init(void)
97 {
98         OSErr nerr;
99 #ifdef _WIN32
100         QTLoadLibrary("QTCF.dll");
101         nerr = InitializeQTML(0);
102         if (nerr != noErr) {
103                 G.have_quicktime = FALSE;
104                 printf("Error initializing quicktime\n");
105         }
106         else
107                 G.have_quicktime = TRUE;
108 #endif /* _WIN32 */
109
110         /* Initialize QuickTime */
111 #if defined(_WIN32) || defined (__APPLE__)
112         nerr = EnterMovies();
113         if (nerr != noErr)
114                 G.have_quicktime = FALSE;
115         else
116 #endif /* _WIN32 || __APPLE__ */
117 #ifdef __linux__
118         /* inititalize quicktime codec registry */
119                 lqt_registry_init();
120 #endif
121         G.have_quicktime = TRUE;
122 }
123
124
125 void quicktime_exit(void)
126 {
127 #if defined(_WIN32) || defined(__APPLE__)
128 #ifdef WITH_QUICKTIME
129         if(G.have_quicktime) {
130                 free_qtcomponentdata();
131                 ExitMovies();
132 #ifdef _WIN32
133                 TerminateQTML();
134 #endif /* _WIN32 */
135         }
136 #endif /* WITH_QUICKTIME */
137 #endif /* _WIN32 || __APPLE__ */
138 }
139
140
141 #ifdef _WIN32
142 char *get_valid_qtname(char *name)
143 {
144         TCHAR Buffer[MAX_PATH];
145         DWORD dwRet;
146         char *qtname;
147         DynStr *ds= BLI_dynstr_new();
148
149         dwRet = GetCurrentDirectory(MAX_PATH, Buffer);
150
151         if(name[1] != ':') {
152                 char drive[2];
153
154                 if(name[0] == '/' || name[0] == '\\') {
155                         drive[0] = Buffer[0];
156                         drive[1] = '\0';
157
158                         BLI_dynstr_append(ds, drive);
159                         BLI_dynstr_append(ds, ":");
160                         BLI_dynstr_append(ds, name);
161                 } else {
162                         BLI_dynstr_append(ds, Buffer);
163                         BLI_dynstr_append(ds, "/");
164                         BLI_dynstr_append(ds, name);
165                 }
166         } else {
167                 BLI_dynstr_append(ds, name);
168         }
169
170         qtname= BLI_dynstr_get_cstring(ds);
171         BLI_dynstr_free(ds);
172
173         return qtname;
174 }
175 #endif /* _WIN32 */
176
177
178 int anim_is_quicktime (const char *name)
179 {
180         FSSpec  theFSSpec;
181         char    theFullPath[255];
182
183         Boolean                                         isMovieFile = false;
184         AliasHandle                                     myAlias = NULL;
185         Component                                       myImporter = NULL;
186 #ifdef __APPLE__
187         FInfo                                           myFinderInfo;
188         FSRef                                           myRef;
189 #else
190         char *qtname;
191         Str255  dst;
192 #endif
193         OSErr                                           err = noErr;
194                         
195         // dont let quicktime movie import handle these
196         if( BLI_testextensie(name, ".swf") ||
197                 BLI_testextensie(name, ".txt") ||
198                 BLI_testextensie(name, ".mpg") ||
199                 BLI_testextensie(name, ".avi") ||       // wouldnt be appropriate ;)
200                 BLI_testextensie(name, ".tga") ||
201                 BLI_testextensie(name, ".png") ||
202                 BLI_testextensie(name, ".bmp") ||
203                 BLI_testextensie(name, ".jpg") ||
204                 BLI_testextensie(name, ".wav") ||
205                 BLI_testextensie(name, ".zip") ||
206                 BLI_testextensie(name, ".mp3")) return 0;
207
208         if(QTIME_DEBUG) printf("qt: checking as movie: %s\n", name);
209
210 #ifdef __APPLE__
211         sprintf(theFullPath, "%s", name);
212
213         err = FSPathMakeRef(theFullPath, &myRef, 0);
214         err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &theFSSpec, NULL);
215 #else
216         qtname = get_valid_qtname(name);
217         sprintf(theFullPath, "%s", qtname);
218         MEM_freeN(qtname);
219
220         CopyCStringToPascal(theFullPath, dst);
221         err = FSMakeFSSpec(0, 0L, dst, &theFSSpec);
222 #endif
223
224 #ifdef __APPLE__
225         // see whether the file type is MovieFileType; to do this, get the Finder information
226         err = FSpGetFInfo(&theFSSpec, &myFinderInfo);
227         if (err == noErr) {
228                 if (myFinderInfo.fdType == kQTFileTypeMovie) {
229                         return(true);
230                 }
231         }
232 #endif
233
234 /* on mac os x this results in using quicktime for other formats as well
235  * not sure whether this is intended
236  */
237         // if it isn't a movie file, see whether the file can be imported as a movie
238         err = QTNewAlias(&theFSSpec, &myAlias, true);
239         if (err == noErr) {
240                 if (myAlias != NULL) {
241                         err = GetMovieImporterForDataRef(rAliasType, (Handle)myAlias, kGetMovieImporterDontConsiderGraphicsImporters, &myImporter);
242                         DisposeHandle((Handle)myAlias);
243                 }
244         }
245         
246         if ((err == noErr) && (myImporter != NULL)) {           // this file is a movie file
247                 isMovieFile = true;
248         }
249
250         return(isMovieFile);
251 }
252
253
254 void free_anim_quicktime (struct anim *anim) {
255         if (anim == NULL) return;
256         if (anim->qtime == NULL) return;
257
258         UnlockPixels(anim->qtime->offscreenPixMap);
259
260         if(anim->qtime->have_gw)
261                 DisposeGWorld( anim->qtime->offscreenGWorld );
262         if(anim->qtime->ibuf)
263                 IMB_freeImBuf(anim->qtime->ibuf);
264
265         DisposeMovie( anim->qtime->movie );
266         CloseMovieFile( anim->qtime->movieRefNum );
267
268         if(anim->qtime->frameIndex) MEM_freeN (anim->qtime->frameIndex);
269         if(anim->qtime) MEM_freeN (anim->qtime);
270
271         anim->qtime = NULL;
272
273         anim->duration = 0;
274 }
275
276
277 static OSErr QT_get_frameIndexes(struct anim *anim)
278 {
279         int i;
280         OSErr   anErr = noErr;
281         OSType  media = VideoMediaType;
282         TimeValue nextTime = 0;
283         TimeValue       startPoint;
284         TimeValue       tmpstartPoint;
285         long sampleCount = 0;
286
287         startPoint = -1;
288
289         GetMovieNextInterestingTime(anim->qtime->movie, nextTimeMediaSample+nextTimeEdgeOK, (TimeValue)1, &media, 0, 
290                                                                 1, &startPoint, NULL);
291
292         tmpstartPoint = startPoint;
293
294         anim->qtime->framecount = 0;
295
296         sampleCount = GetMediaSampleCount(anim->qtime->theMedia);
297         anErr = GetMoviesError();
298         if (anErr != noErr) return anErr;
299
300         anim->qtime->framecount = sampleCount;
301
302         anim->qtime->frameIndex = (TimeValue *) MEM_callocN(sizeof(TimeValue) * anim->qtime->framecount, "qtframeindex");
303
304         //rewind
305         GetMovieNextInterestingTime(anim->qtime->movie, nextTimeMediaSample, 1, &media, (TimeValue)1, 0, &tmpstartPoint, NULL);
306
307         anim->qtime->frameIndex[0] = startPoint;
308         for(i = 1; i < anim->qtime->framecount; i++) {
309                 nextTime = 0;
310                 GetMovieNextInterestingTime(anim->qtime->movie, nextTimeMediaSample, 1, &media, startPoint, 0, &nextTime, NULL);
311                 startPoint = nextTime;
312                 anim->qtime->frameIndex[i] = nextTime;
313         }
314
315         anErr = GetMoviesError();
316         return anErr;
317 }
318
319
320 ImBuf * qtime_fetchibuf (struct anim *anim, int position)
321 {
322         PixMapHandle                    myPixMap = NULL;
323         Ptr                                             myPtr;
324
325         register int            index;
326         register int            boxsize;
327
328         register uint32_t       *readPos;
329         register uint32_t       *changePos;
330
331         ImBuf *ibuf = NULL;
332         unsigned int *rect;
333 #ifdef __APPLE__
334         unsigned char *from, *to;
335 #endif
336 #ifdef _WIN32
337         unsigned char *crect;
338 #endif
339
340         if (anim == NULL) {
341                 return (NULL);
342         }
343
344         ibuf = IMB_allocImBuf (anim->x, anim->y, 32, IB_rect);
345         rect = ibuf->rect;
346
347         SetMovieTimeValue(anim->qtime->movie, anim->qtime->frameIndex[position]);
348         UpdateMovie(anim->qtime->movie);
349         MoviesTask(anim->qtime->movie, 0);
350
351
352         myPixMap = GetGWorldPixMap(anim->qtime->offscreenGWorld);
353         myPtr = GetPixBaseAddr(myPixMap);
354
355         if (myPtr == NULL) {
356                 printf ("Error reading frame from Quicktime");
357                 IMB_freeImBuf (ibuf);
358                 return NULL;
359         }
360
361         boxsize = anim->x * anim->y;
362         readPos = (uint32_t *) myPtr;
363         changePos = (uint32_t *) rect; //textureIMBuf *THE* data pointerrr
364
365 #ifdef __APPLE__
366         // Swap alpha byte to the end, so ARGB become RGBA;
367         from= (unsigned char *)readPos;
368         to= (unsigned char *)changePos;
369         
370         for( index = 0; index < boxsize; index++, from+=4, to+=4 ) {
371                 to[3] = from[0];
372                 to[0] = from[1];
373                 to[1] = from[2];
374                 to[2] = from[3];
375         }
376 #endif
377
378 #ifdef _WIN32
379         for( index = 0; index < boxsize; index++, changePos++, readPos++ )
380                 *( changePos ) =  *(readPos );
381
382         if(anim->qtime->depth < 32) {
383                 //add alpha to ibuf
384                 boxsize = anim->x * anim->y * 4;
385                 crect = (unsigned char *) rect;
386                 for( index = 0; index < boxsize; index+=4, crect+=4 )
387                          crect[3] = 0xFF;
388         }
389 #endif
390
391         ibuf->profile = IB_PROFILE_SRGB;
392         
393         IMB_flipy(ibuf);
394         return ibuf;
395 }
396
397
398 // following two functions only here to get movie pixeldepth
399
400 static int GetFirstVideoMedia(struct anim *anim)
401 {
402         long    numTracks;
403         OSType  mediaType;
404
405         numTracks = GetMovieTrackCount(anim->qtime->movie);
406
407         for (anim->qtime->trackIndex=1; anim->qtime->trackIndex<=numTracks; (anim->qtime->trackIndex)++) {
408                 anim->qtime->theTrack = GetMovieIndTrack(anim->qtime->movie, anim->qtime->trackIndex);
409
410                 if (anim->qtime->theTrack)
411                         anim->qtime->theMedia = GetTrackMedia(anim->qtime->theTrack);
412
413                 if (anim->qtime->theMedia)
414                         GetMediaHandlerDescription(anim->qtime->theMedia,&mediaType, nil, nil);
415                 if (mediaType == VideoMediaType) return 1;
416         }
417
418         anim->qtime->trackIndex = 0;  // trackIndex can't be 0
419         return 0;      // went through all tracks and no video
420 }
421
422 static short GetFirstVideoTrackPixelDepth(struct anim *anim)
423 {
424         SampleDescriptionHandle imageDescH =    (SampleDescriptionHandle)NewHandle(sizeof(Handle));
425 //      long    trackIndex = 0; /*unused*/
426         
427         if(!GetFirstVideoMedia(anim))
428                 return -1;
429
430         if (!anim->qtime->trackIndex || !anim->qtime->theMedia) return -1;  // we need both
431         GetMediaSampleDescription(anim->qtime->theMedia, anim->qtime->trackIndex, imageDescH);
432
433         return (*(ImageDescriptionHandle)imageDescH)->depth;
434 }
435
436
437 int startquicktime (struct anim *anim)
438 {
439         FSSpec          theFSSpec;
440
441         OSErr           err = noErr;
442         char            theFullPath[255];
443 #ifdef __APPLE__
444         FSRef           myRef;
445 #else
446         char            *qtname;
447         Str255          dst;
448 #endif
449         short depth = 0;
450
451         anim->qtime = MEM_callocN (sizeof(QuicktimeMovie),"animqt");
452         anim->qtime->have_gw = FALSE;
453
454         if (anim->qtime == NULL) {
455                 if(QTIME_DEBUG) printf("Can't alloc qtime: %s\n", anim->name);
456                 return -1;
457         }
458
459         if(QTIME_DEBUG) printf("qt: attempting to load as movie %s\n", anim->name);
460         
461 #ifdef __APPLE__
462         sprintf(theFullPath, "%s", anim->name);
463
464         err = FSPathMakeRef(theFullPath, &myRef, 0);
465         err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &theFSSpec, NULL);
466 #else
467         qtname = get_valid_qtname(anim->name);
468         sprintf(theFullPath, "%s", qtname);
469         MEM_freeN(qtname);
470
471         CopyCStringToPascal(theFullPath, dst);
472         FSMakeFSSpec(0, 0L, dst, &theFSSpec);
473 #endif
474         
475         err = OpenMovieFile(&theFSSpec, &anim->qtime->movieRefNum, fsRdPerm);
476
477         if (err == noErr) {
478                 if(QTIME_DEBUG) printf("qt: movie opened\n");
479                 err = NewMovieFromFile(&anim->qtime->movie,
480                                                    anim->qtime->movieRefNum,
481                                                    &anim->qtime->movieResId, NULL, newMovieActive, NULL);
482         }
483
484         if (err) {
485                 if(QTIME_DEBUG) printf("qt: bad movie %s\n", anim->name);
486                 if (anim->qtime->movie) {
487                         DisposeMovie(anim->qtime->movie);
488                         MEM_freeN(anim->qtime);
489                         if(QTIME_DEBUG) printf("qt: can't load %s\n", anim->name);
490                         return -1;
491                 }
492         }
493
494         GetMovieBox(anim->qtime->movie, &anim->qtime->movieBounds);
495         anim->x = anim->qtime->movWidth = RECT_WIDTH(anim->qtime->movieBounds);
496         anim->y = anim->qtime->movHeight = RECT_HEIGHT(anim->qtime->movieBounds);
497         if(QTIME_DEBUG) printf("qt: got bounds %s\n", anim->name);
498
499         if(anim->x == 0 && anim->y == 0) {
500                 if(QTIME_DEBUG) printf("qt: error, no dimensions\n");
501                 free_anim_quicktime(anim);
502                 return -1;
503         }
504
505         anim->qtime->ibuf = IMB_allocImBuf (anim->x, anim->y, 32, IB_rect);
506
507 #ifdef _WIN32
508         err = NewGWorldFromPtr(&anim->qtime->offscreenGWorld,
509                  k32RGBAPixelFormat,
510                  &anim->qtime->movieBounds,
511                  NULL, NULL, 0,
512                 (unsigned char *)anim->qtime->ibuf->rect,
513                 anim->x * 4);
514 #else
515         err = NewGWorldFromPtr(&anim->qtime->offscreenGWorld,
516                  k32ARGBPixelFormat,
517                  &anim->qtime->movieBounds,
518                  NULL, NULL, 0,
519                 (unsigned char *)anim->qtime->ibuf->rect,
520                 anim->x * 4);
521 #endif /* _WIN32 */
522
523         if(err == noErr) {
524                 anim->qtime->have_gw = TRUE;
525
526                 SetMovieGWorld(anim->qtime->movie,
527                                  anim->qtime->offscreenGWorld,
528                                  GetGWorldDevice(anim->qtime->offscreenGWorld));
529                 SetMoviePlayHints(anim->qtime->movie, hintsHighQuality, hintsHighQuality);
530                 
531                 // sets Media and Track!
532                 depth = GetFirstVideoTrackPixelDepth(anim);
533
534                 QT_get_frameIndexes(anim);
535         }
536
537         anim->qtime->offscreenPixMap = GetGWorldPixMap(anim->qtime->offscreenGWorld);
538         LockPixels(anim->qtime->offscreenPixMap);
539
540         //fill blender's anim struct
541         anim->qtime->depth = depth;
542         
543         anim->duration = anim->qtime->framecount;
544         anim->params = 0;
545
546         anim->interlacing = 0;
547         anim->orientation = 0;
548         anim->framesize = anim->x * anim->y * 4;
549
550         anim->curposition = 0;
551
552         if(QTIME_DEBUG) printf("qt: load %s %dx%dx%d frames %d\n", anim->name, anim->qtime->movWidth,
553                 anim->qtime->movHeight, anim->qtime->depth, anim->qtime->framecount);
554
555         return 0;
556 }
557
558 int imb_is_a_quicktime (char *name)
559 {
560         GraphicsImportComponent         theImporter = NULL;
561
562         FSSpec  theFSSpec;
563 #ifdef _WIN32
564         Str255  dst; /*unused*/
565 #endif
566         char    theFullPath[255];
567
568 //      Boolean                                         isMovieFile = false; /*unused*/
569 //      AliasHandle                                     myAlias = NULL; /*unused*/
570 //      Component                                       myImporter = NULL; /*unused*/
571 #ifdef __APPLE__
572 //      FInfo                                           myFinderInfo; /*unused*/
573         FSRef                                           myRef;
574 #endif
575         OSErr                                           err = noErr;
576
577         if(!G.have_quicktime) return 0;
578
579         if(QTIME_DEBUG) printf("qt: checking as image %s\n", name);
580
581         // dont let quicktime image import handle these
582         if( BLI_testextensie(name, ".swf") ||
583                 BLI_testextensie(name, ".txt") ||
584                 BLI_testextensie(name, ".mpg") ||
585                 BLI_testextensie(name, ".wav") ||
586                 BLI_testextensie(name, ".mov") ||       // not as image, doesn't work
587                 BLI_testextensie(name, ".avi") ||
588                 BLI_testextensie(name, ".mp3")) return 0;
589
590         sprintf(theFullPath, "%s", name);
591 #ifdef __APPLE__
592         err = FSPathMakeRef(theFullPath, &myRef, 0);
593         err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &theFSSpec, NULL);
594 #else
595         CopyCStringToPascal(theFullPath, dst);
596         err = FSMakeFSSpec(0, 0L, dst, &theFSSpec);
597 #endif
598
599         GetGraphicsImporterForFile(&theFSSpec, &theImporter);
600
601         if (theImporter != NULL) {
602                 if(QTIME_DEBUG) printf("qt: %s valid\n", name);
603                 CloseComponent(theImporter);
604                 return 1;
605         }
606
607         return 0;
608 }
609
610 ImBuf  *imb_quicktime_decode(unsigned char *mem, int size, int flags)
611 {
612         Rect                                            myRect;
613         OSErr                                           err = noErr;
614         GraphicsImportComponent         gImporter = NULL;
615
616         ImageDescriptionHandle          desc;
617
618         ComponentInstance                       dataHandler;
619         PointerDataRef dataref;
620
621         int x, y, depth;
622         int have_gw = FALSE;
623         ImBuf *ibuf = NULL;
624 //      ImBuf *imbuf = NULL; /*unused*/
625         GWorldPtr       offGWorld;
626         PixMapHandle            myPixMap = NULL;
627
628 #ifdef __APPLE__
629         Ptr                                     myPtr;
630
631         register int            index;
632         register int            boxsize;
633
634         register uint32_t       *readPos;
635         register uint32_t       *changePos;
636
637         ImBuf *wbuf = NULL;
638         unsigned int *rect;
639         unsigned char *from, *to;
640 #endif
641
642         if (mem == NULL || !G.have_quicktime)
643                 goto bail;
644         
645         if(QTIME_DEBUG) printf("qt: attempt to load mem as image\n");
646
647         dataref= (PointerDataRef)NewHandle(sizeof(PointerDataRefRecord));
648         (**dataref).data = mem;
649         (**dataref).dataLength = size;
650
651         err = OpenADataHandler((Handle)dataref,
652                                                         PointerDataHandlerSubType,
653                                                         nil,
654                                                         (OSType)0,
655                                                         nil,
656                                                         kDataHCanRead,
657                                                         &dataHandler);
658         if (err != noErr) {
659                 if(QTIME_DEBUG) printf("no datahandler\n");
660                 goto bail;
661         }
662
663         err = GetGraphicsImporterForDataRef((Handle)dataref, PointerDataHandlerSubType, &gImporter);
664         if (err != noErr) {
665                 if(QTIME_DEBUG) printf("no graphimport\n");
666                 goto bail;
667         }
668
669         err = GraphicsImportGetNaturalBounds(gImporter, &myRect);
670         if (err != noErr) {
671                 if(QTIME_DEBUG) printf("no bounds\n");
672                 goto bail;
673         }
674
675         err = GraphicsImportGetImageDescription (gImporter, &desc );
676         if (err != noErr) {
677                 if(QTIME_DEBUG) printf("no imagedescription\n");
678                 goto bail;
679         }
680
681         x = RECT_WIDTH(myRect);
682         y = RECT_HEIGHT(myRect);
683         depth = (**desc).depth;
684
685         if (flags & IB_test) {
686                 ibuf = IMB_allocImBuf(x, y, depth, 0);
687                 ibuf->ftype = QUICKTIME;
688                 DisposeHandle((Handle)dataref);
689                 if (gImporter != NULL)  CloseComponent(gImporter);
690                 return ibuf;
691         }
692
693 #ifdef __APPLE__
694         ibuf = IMB_allocImBuf (x, y, 32, IB_rect);
695         wbuf = IMB_allocImBuf (x, y, 32, IB_rect);
696
697         err = NewGWorldFromPtr(&offGWorld,
698                                                 k32ARGBPixelFormat,
699                                                 &myRect, NULL, NULL, 0,
700                                                 (unsigned char *)wbuf->rect, x * 4);
701 #else
702
703         ibuf = IMB_allocImBuf (x, y, 32, IB_rect);      
704
705         err = NewGWorldFromPtr(&offGWorld,
706                                                         k32RGBAPixelFormat,
707                                                         &myRect, NULL, NULL, 0,
708                                                         (unsigned char *)ibuf->rect, x * 4);
709 #endif
710         
711         if (err != noErr) {
712                 if(QTIME_DEBUG) printf("no newgworld\n");
713                 goto bail;
714         } else {
715                 have_gw = TRUE;
716         }
717
718         GraphicsImportSetGWorld(gImporter, offGWorld, NULL);
719         GraphicsImportDraw(gImporter);
720
721 #ifdef __APPLE__
722         rect = ibuf->rect;
723
724         myPixMap = GetGWorldPixMap(offGWorld);
725         LockPixels(myPixMap);
726         myPtr = GetPixBaseAddr(myPixMap);
727
728         if (myPtr == NULL) {
729                 printf ("Error reading frame from Quicktime");
730                 IMB_freeImBuf (ibuf);
731                 return NULL;
732         }
733
734         boxsize = x * y;
735         readPos = (uint32_t *) myPtr;
736         changePos = (uint32_t *) rect;
737
738         // Swap alpha byte to the end, so ARGB become RGBA;
739         from= (unsigned char *)readPos;
740         to= (unsigned char *)changePos;
741         
742         for( index = 0; index < boxsize; index++, from+=4, to+=4 ) {
743                 to[3] = from[0];
744                 to[0] = from[1];
745                 to[1] = from[2];
746                 to[2] = from[3];
747         }
748 #endif
749
750 bail:
751
752         DisposeHandle((Handle)dataref);
753         UnlockPixels(myPixMap);
754         if(have_gw) DisposeGWorld(offGWorld);
755
756 #ifdef __APPLE__
757         if (wbuf) {
758                 IMB_freeImBuf (wbuf);
759                 wbuf = NULL;
760         }
761 #endif
762
763         if (gImporter != NULL)  CloseComponent(gImporter);
764
765         if (err != noErr) {
766                 if(QTIME_DEBUG) printf("quicktime import unsuccesfull\n");
767                 if (ibuf) {
768                         IMB_freeImBuf (ibuf);
769                         ibuf = NULL;
770                 }
771         }
772
773         if(ibuf) {
774
775 #ifdef _WIN32
776 // add non transparent alpha layer, so images without alpha show up in the sequence editor
777 // exception for GIF images since these can be transparent without being 32 bit
778 // (might also be nescessary for OSX)
779                 int i;
780                 int box = x * y;
781                 unsigned char *arect = (unsigned char *) ibuf->rect;
782
783                 if( depth < 32 && (**desc).cType != kGIFCodecType) {
784                         for(i = 0; i < box; i++, arect+=4)
785                                  arect[3] = 0xFF;
786                 }
787 #endif
788
789                 IMB_flipy(ibuf);
790                 ibuf->ftype = QUICKTIME;
791         }
792         return ibuf;
793 }
794
795 #endif /* USE_QTKIT */
796 #endif /* _WIN32 || __APPLE__ */
797
798 #endif /* WITH_QUICKTIME */
799
800
801 #if 0
802
803 struct ImageDescription {
804          long         idSize;
805          CodecType    cType;
806          long         resvd1;
807          short        resvd2;
808          short        dataRefIndex;
809          short        version;
810          short        revisionLevel;
811          long         vendor;
812          CodecQ       temporalQuality;
813          CodecQ       spatialQuality;
814          short        width;
815          short        height;
816          Fixed        hRes;
817          Fixed        vRes;
818          long         dataSize;
819          short        frameCount;
820          Str31        name;
821          short        depth;
822          short        clutID;
823 };
824
825 #endif // 0