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