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