
This makes quicktime import (.mov & quicktime handled image files such as .gif) available also for 64bit OSX Unfortunately, Apple currently incomplete implementation of QTKit has much lower performance than old Carbon Quicktime. FYI, it spawns a 32bit process "QTKitserver" to place calls to Quicktime 7. So this is mostly meant as a "backup" for 64bit OSX builds, until Apple releases full Quicktime X. Export part will come just after. CMake scripts updated: set WITH_QUICKTIME and USE_QTKIT to ON
804 lines
19 KiB
C
804 lines
19 KiB
C
/**
|
|
* $Id$
|
|
*
|
|
* quicktime_import.c
|
|
*
|
|
* Code to use Quicktime to load images/movies as texture.
|
|
*
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
*
|
|
* The Original Code is written by Rob Haarsma (phase)
|
|
*
|
|
* Contributor(s): Stefan Gartner (sgefant)
|
|
*
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
*/
|
|
#ifdef WITH_QUICKTIME
|
|
|
|
#if defined(_WIN32) || defined(__APPLE__)
|
|
|
|
#include "IMB_anim.h"
|
|
#include "BLO_sys_types.h"
|
|
#include "BKE_global.h"
|
|
#include "BLI_dynstr.h"
|
|
|
|
#ifdef __APPLE__
|
|
#include <QuickTime/Movies.h>
|
|
#include <QuickTime/QuickTimeComponents.h>
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
#include <Movies.h>
|
|
#include <QTML.h>
|
|
#include <TextUtils.h>
|
|
#include <QuickTimeComponents.h>
|
|
#endif /* _WIN32 */
|
|
|
|
|
|
#include "quicktime_import.h"
|
|
#include "quicktime_export.h"
|
|
|
|
#define RECT_WIDTH(r) (r.right-r.left)
|
|
#define RECT_HEIGHT(r) (r.bottom-r.top)
|
|
|
|
#define QTIME_DEBUG 0
|
|
|
|
typedef struct _QuicktimeMovie {
|
|
|
|
GWorldPtr offscreenGWorld;
|
|
PixMapHandle offscreenPixMap;
|
|
Movie movie;
|
|
Rect movieBounds;
|
|
short movieRefNum;
|
|
short movieResId;
|
|
int movWidth, movHeight;
|
|
|
|
|
|
int framecount;
|
|
|
|
|
|
ImBuf *ibuf;
|
|
|
|
|
|
TimeValue *frameIndex;
|
|
Media theMedia;
|
|
Track theTrack;
|
|
long trackIndex;
|
|
short depth;
|
|
|
|
int have_gw; //ugly
|
|
} QuicktimeMovie;
|
|
|
|
|
|
|
|
void quicktime_init(void)
|
|
{
|
|
#ifdef _WIN32
|
|
if (InitializeQTML(0) != noErr)
|
|
G.have_quicktime = FALSE;
|
|
else
|
|
G.have_quicktime = TRUE;
|
|
#endif /* _WIN32 */
|
|
|
|
/* Initialize QuickTime */
|
|
#if defined(_WIN32) || defined (__APPLE__)
|
|
if (EnterMovies() != noErr)
|
|
G.have_quicktime = FALSE;
|
|
else
|
|
#endif /* _WIN32 || __APPLE__ */
|
|
#ifdef __linux__
|
|
/* inititalize quicktime codec registry */
|
|
lqt_registry_init();
|
|
#endif
|
|
G.have_quicktime = TRUE;
|
|
}
|
|
|
|
|
|
void quicktime_exit(void)
|
|
{
|
|
#if defined(_WIN32) || defined(__APPLE__)
|
|
#ifdef WITH_QUICKTIME
|
|
if(G.have_quicktime) {
|
|
free_qtcomponentdata();
|
|
ExitMovies();
|
|
#ifdef _WIN32
|
|
TerminateQTML();
|
|
#endif /* _WIN32 */
|
|
}
|
|
#endif /* WITH_QUICKTIME */
|
|
#endif /* _WIN32 || __APPLE__ */
|
|
}
|
|
|
|
|
|
#ifdef _WIN32
|
|
char *get_valid_qtname(char *name)
|
|
{
|
|
TCHAR Buffer[MAX_PATH];
|
|
DWORD dwRet;
|
|
char *qtname;
|
|
DynStr *ds= BLI_dynstr_new();
|
|
|
|
dwRet = GetCurrentDirectory(MAX_PATH, Buffer);
|
|
|
|
if(name[1] != ':') {
|
|
char drive[2];
|
|
|
|
if(name[0] == '/' || name[0] == '\\') {
|
|
drive[0] = Buffer[0];
|
|
drive[1] = '\0';
|
|
|
|
BLI_dynstr_append(ds, drive);
|
|
BLI_dynstr_append(ds, ":");
|
|
BLI_dynstr_append(ds, name);
|
|
} else {
|
|
BLI_dynstr_append(ds, Buffer);
|
|
BLI_dynstr_append(ds, "/");
|
|
BLI_dynstr_append(ds, name);
|
|
}
|
|
} else {
|
|
BLI_dynstr_append(ds, name);
|
|
}
|
|
|
|
qtname= BLI_dynstr_get_cstring(ds);
|
|
BLI_dynstr_free(ds);
|
|
|
|
return qtname;
|
|
}
|
|
#endif /* _WIN32 */
|
|
|
|
|
|
int anim_is_quicktime (char *name)
|
|
{
|
|
FSSpec theFSSpec;
|
|
char theFullPath[255];
|
|
|
|
Boolean isMovieFile = false;
|
|
AliasHandle myAlias = NULL;
|
|
Component myImporter = NULL;
|
|
#ifdef __APPLE__
|
|
FInfo myFinderInfo;
|
|
FSRef myRef;
|
|
#else
|
|
char *qtname;
|
|
Str255 dst;
|
|
#endif
|
|
OSErr err = noErr;
|
|
|
|
// dont let quicktime movie import handle these
|
|
if( BLI_testextensie(name, ".swf") ||
|
|
BLI_testextensie(name, ".txt") ||
|
|
BLI_testextensie(name, ".mpg") ||
|
|
BLI_testextensie(name, ".avi") || // wouldnt be appropriate ;)
|
|
BLI_testextensie(name, ".tga") ||
|
|
BLI_testextensie(name, ".png") ||
|
|
BLI_testextensie(name, ".bmp") ||
|
|
BLI_testextensie(name, ".jpg") ||
|
|
BLI_testextensie(name, ".wav") ||
|
|
BLI_testextensie(name, ".zip") ||
|
|
BLI_testextensie(name, ".mp3")) return 0;
|
|
|
|
if(QTIME_DEBUG) printf("qt: checking as movie: %s\n", name);
|
|
|
|
#ifdef __APPLE__
|
|
sprintf(theFullPath, "%s", name);
|
|
|
|
err = FSPathMakeRef(theFullPath, &myRef, 0);
|
|
err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &theFSSpec, NULL);
|
|
#else
|
|
qtname = get_valid_qtname(name);
|
|
sprintf(theFullPath, "%s", qtname);
|
|
MEM_freeN(qtname);
|
|
|
|
CopyCStringToPascal(theFullPath, dst);
|
|
err = FSMakeFSSpec(0, 0L, dst, &theFSSpec);
|
|
#endif
|
|
|
|
#ifdef __APPLE__
|
|
// see whether the file type is MovieFileType; to do this, get the Finder information
|
|
err = FSpGetFInfo(&theFSSpec, &myFinderInfo);
|
|
if (err == noErr) {
|
|
if (myFinderInfo.fdType == kQTFileTypeMovie) {
|
|
return(true);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* on mac os x this results in using quicktime for other formats as well
|
|
* not sure whether this is intended
|
|
*/
|
|
// if it isn't a movie file, see whether the file can be imported as a movie
|
|
err = QTNewAlias(&theFSSpec, &myAlias, true);
|
|
if (err == noErr) {
|
|
if (myAlias != NULL) {
|
|
err = GetMovieImporterForDataRef(rAliasType, (Handle)myAlias, kGetMovieImporterDontConsiderGraphicsImporters, &myImporter);
|
|
DisposeHandle((Handle)myAlias);
|
|
}
|
|
}
|
|
|
|
if ((err == noErr) && (myImporter != NULL)) { // this file is a movie file
|
|
isMovieFile = true;
|
|
}
|
|
|
|
return(isMovieFile);
|
|
}
|
|
|
|
|
|
void free_anim_quicktime (struct anim *anim) {
|
|
if (anim == NULL) return;
|
|
if (anim->qtime == NULL) return;
|
|
|
|
UnlockPixels(anim->qtime->offscreenPixMap);
|
|
|
|
if(anim->qtime->have_gw)
|
|
DisposeGWorld( anim->qtime->offscreenGWorld );
|
|
if(anim->qtime->ibuf)
|
|
IMB_freeImBuf(anim->qtime->ibuf);
|
|
|
|
DisposeMovie( anim->qtime->movie );
|
|
CloseMovieFile( anim->qtime->movieRefNum );
|
|
|
|
if(anim->qtime->frameIndex) MEM_freeN (anim->qtime->frameIndex);
|
|
if(anim->qtime) MEM_freeN (anim->qtime);
|
|
|
|
anim->qtime = NULL;
|
|
|
|
anim->duration = 0;
|
|
}
|
|
|
|
|
|
static OSErr QT_get_frameIndexes(struct anim *anim)
|
|
{
|
|
int i;
|
|
OSErr anErr = noErr;
|
|
OSType media = VideoMediaType;
|
|
TimeValue nextTime = 0;
|
|
TimeValue startPoint;
|
|
TimeValue tmpstartPoint;
|
|
long sampleCount = 0;
|
|
|
|
startPoint = -1;
|
|
|
|
GetMovieNextInterestingTime(anim->qtime->movie, nextTimeMediaSample+nextTimeEdgeOK, (TimeValue)1, &media, 0,
|
|
1, &startPoint, NULL);
|
|
|
|
tmpstartPoint = startPoint;
|
|
|
|
anim->qtime->framecount = 0;
|
|
|
|
sampleCount = GetMediaSampleCount(anim->qtime->theMedia);
|
|
anErr = GetMoviesError();
|
|
if (anErr != noErr) return anErr;
|
|
|
|
anim->qtime->framecount = sampleCount;
|
|
|
|
anim->qtime->frameIndex = (TimeValue *) MEM_callocN(sizeof(TimeValue) * anim->qtime->framecount, "qtframeindex");
|
|
|
|
//rewind
|
|
GetMovieNextInterestingTime(anim->qtime->movie, nextTimeMediaSample, 1, &media, (TimeValue)1, 0, &tmpstartPoint, NULL);
|
|
|
|
anim->qtime->frameIndex[0] = startPoint;
|
|
for(i = 1; i < anim->qtime->framecount; i++) {
|
|
nextTime = 0;
|
|
GetMovieNextInterestingTime(anim->qtime->movie, nextTimeMediaSample, 1, &media, startPoint, 0, &nextTime, NULL);
|
|
startPoint = nextTime;
|
|
anim->qtime->frameIndex[i] = nextTime;
|
|
}
|
|
|
|
anErr = GetMoviesError();
|
|
return anErr;
|
|
}
|
|
|
|
|
|
ImBuf * qtime_fetchibuf (struct anim *anim, int position)
|
|
{
|
|
PixMapHandle myPixMap = NULL;
|
|
Ptr myPtr;
|
|
|
|
register int index;
|
|
register int boxsize;
|
|
|
|
register uint32_t *readPos;
|
|
register uint32_t *changePos;
|
|
|
|
ImBuf *ibuf = NULL;
|
|
unsigned int *rect;
|
|
unsigned char *from, *to;
|
|
#ifdef _WIN32
|
|
unsigned char *crect;
|
|
#endif
|
|
|
|
if (anim == NULL) {
|
|
return (NULL);
|
|
}
|
|
|
|
ibuf = IMB_allocImBuf (anim->x, anim->y, 32, IB_rect, 0);
|
|
rect = ibuf->rect;
|
|
|
|
SetMovieTimeValue(anim->qtime->movie, anim->qtime->frameIndex[position]);
|
|
UpdateMovie(anim->qtime->movie);
|
|
MoviesTask(anim->qtime->movie, 0);
|
|
|
|
|
|
myPixMap = GetGWorldPixMap(anim->qtime->offscreenGWorld);
|
|
myPtr = GetPixBaseAddr(myPixMap);
|
|
|
|
if (myPtr == NULL) {
|
|
printf ("Error reading frame from Quicktime");
|
|
IMB_freeImBuf (ibuf);
|
|
return NULL;
|
|
}
|
|
|
|
boxsize = anim->x * anim->y;
|
|
readPos = (uint32_t *) myPtr;
|
|
changePos = (uint32_t *) rect; //textureIMBuf *THE* data pointerrr
|
|
|
|
#ifdef __APPLE__
|
|
// Swap alpha byte to the end, so ARGB become RGBA;
|
|
from= (unsigned char *)readPos;
|
|
to= (unsigned char *)changePos;
|
|
|
|
for( index = 0; index < boxsize; index++, from+=4, to+=4 ) {
|
|
to[3] = from[0];
|
|
to[0] = from[1];
|
|
to[1] = from[2];
|
|
to[2] = from[3];
|
|
}
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
for( index = 0; index < boxsize; index++, changePos++, readPos++ )
|
|
*( changePos ) = *(readPos );
|
|
|
|
if(anim->qtime->depth < 32) {
|
|
//add alpha to ibuf
|
|
boxsize = anim->x * anim->y * 4;
|
|
crect = (unsigned char *) rect;
|
|
for( index = 0; index < boxsize; index+=4, crect+=4 )
|
|
crect[3] = 0xFF;
|
|
}
|
|
#endif
|
|
|
|
IMB_flipy(ibuf);
|
|
return ibuf;
|
|
}
|
|
|
|
|
|
// following two functions only here to get movie pixeldepth
|
|
|
|
static int GetFirstVideoMedia(struct anim *anim)
|
|
{
|
|
long numTracks;
|
|
OSType mediaType;
|
|
|
|
numTracks = GetMovieTrackCount(anim->qtime->movie);
|
|
|
|
for (anim->qtime->trackIndex=1; anim->qtime->trackIndex<=numTracks; (anim->qtime->trackIndex)++) {
|
|
anim->qtime->theTrack = GetMovieIndTrack(anim->qtime->movie, anim->qtime->trackIndex);
|
|
|
|
if (anim->qtime->theTrack)
|
|
anim->qtime->theMedia = GetTrackMedia(anim->qtime->theTrack);
|
|
|
|
if (anim->qtime->theMedia)
|
|
GetMediaHandlerDescription(anim->qtime->theMedia,&mediaType, nil, nil);
|
|
if (mediaType == VideoMediaType) return 1;
|
|
}
|
|
|
|
anim->qtime->trackIndex = 0; // trackIndex can't be 0
|
|
return 0; // went through all tracks and no video
|
|
}
|
|
|
|
static short GetFirstVideoTrackPixelDepth(struct anim *anim)
|
|
{
|
|
SampleDescriptionHandle imageDescH = (SampleDescriptionHandle)NewHandle(sizeof(Handle));
|
|
// long trackIndex = 0; /*unused*/
|
|
|
|
if(!GetFirstVideoMedia(anim))
|
|
return -1;
|
|
|
|
if (!anim->qtime->trackIndex || !anim->qtime->theMedia) return -1; // we need both
|
|
GetMediaSampleDescription(anim->qtime->theMedia, anim->qtime->trackIndex, imageDescH);
|
|
|
|
return (*(ImageDescriptionHandle)imageDescH)->depth;
|
|
}
|
|
|
|
|
|
int startquicktime (struct anim *anim)
|
|
{
|
|
FSSpec theFSSpec;
|
|
|
|
OSErr err = noErr;
|
|
char theFullPath[255];
|
|
#ifdef __APPLE__
|
|
FSRef myRef;
|
|
#else
|
|
char *qtname;
|
|
Str255 dst;
|
|
#endif
|
|
short depth = 0;
|
|
|
|
anim->qtime = MEM_callocN (sizeof(QuicktimeMovie),"animqt");
|
|
anim->qtime->have_gw = FALSE;
|
|
|
|
if (anim->qtime == NULL) {
|
|
if(QTIME_DEBUG) printf("Can't alloc qtime: %s\n", anim->name);
|
|
return -1;
|
|
}
|
|
|
|
if(QTIME_DEBUG) printf("qt: attempting to load as movie %s\n", anim->name);
|
|
|
|
#ifdef __APPLE__
|
|
sprintf(theFullPath, "%s", anim->name);
|
|
|
|
err = FSPathMakeRef(theFullPath, &myRef, 0);
|
|
err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &theFSSpec, NULL);
|
|
#else
|
|
qtname = get_valid_qtname(anim->name);
|
|
sprintf(theFullPath, "%s", qtname);
|
|
MEM_freeN(qtname);
|
|
|
|
CopyCStringToPascal(theFullPath, dst);
|
|
FSMakeFSSpec(0, 0L, dst, &theFSSpec);
|
|
#endif
|
|
|
|
err = OpenMovieFile(&theFSSpec, &anim->qtime->movieRefNum, fsRdPerm);
|
|
|
|
if (err == noErr) {
|
|
if(QTIME_DEBUG) printf("qt: movie opened\n");
|
|
err = NewMovieFromFile(&anim->qtime->movie,
|
|
anim->qtime->movieRefNum,
|
|
&anim->qtime->movieResId, NULL, newMovieActive, NULL);
|
|
}
|
|
|
|
if (err) {
|
|
if(QTIME_DEBUG) printf("qt: bad movie %s\n", anim->name);
|
|
if (anim->qtime->movie) {
|
|
DisposeMovie(anim->qtime->movie);
|
|
MEM_freeN(anim->qtime);
|
|
if(QTIME_DEBUG) printf("qt: can't load %s\n", anim->name);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
GetMovieBox(anim->qtime->movie, &anim->qtime->movieBounds);
|
|
anim->x = anim->qtime->movWidth = RECT_WIDTH(anim->qtime->movieBounds);
|
|
anim->y = anim->qtime->movHeight = RECT_HEIGHT(anim->qtime->movieBounds);
|
|
if(QTIME_DEBUG) printf("qt: got bounds %s\n", anim->name);
|
|
|
|
if(anim->x == 0 && anim->y == 0) {
|
|
if(QTIME_DEBUG) printf("qt: error, no dimensions\n");
|
|
free_anim_quicktime(anim);
|
|
return -1;
|
|
}
|
|
|
|
anim->qtime->ibuf = IMB_allocImBuf (anim->x, anim->y, 32, IB_rect, 0);
|
|
|
|
#ifdef _WIN32
|
|
err = NewGWorldFromPtr(&anim->qtime->offscreenGWorld,
|
|
k32RGBAPixelFormat,
|
|
&anim->qtime->movieBounds,
|
|
NULL, NULL, 0,
|
|
(unsigned char *)anim->qtime->ibuf->rect,
|
|
anim->x * 4);
|
|
#else
|
|
err = NewGWorldFromPtr(&anim->qtime->offscreenGWorld,
|
|
k32ARGBPixelFormat,
|
|
&anim->qtime->movieBounds,
|
|
NULL, NULL, 0,
|
|
(unsigned char *)anim->qtime->ibuf->rect,
|
|
anim->x * 4);
|
|
#endif /* _WIN32 */
|
|
|
|
if(err == noErr) {
|
|
anim->qtime->have_gw = TRUE;
|
|
|
|
SetMovieGWorld(anim->qtime->movie,
|
|
anim->qtime->offscreenGWorld,
|
|
GetGWorldDevice(anim->qtime->offscreenGWorld));
|
|
SetMoviePlayHints(anim->qtime->movie, hintsHighQuality, hintsHighQuality);
|
|
|
|
// sets Media and Track!
|
|
depth = GetFirstVideoTrackPixelDepth(anim);
|
|
|
|
QT_get_frameIndexes(anim);
|
|
}
|
|
|
|
anim->qtime->offscreenPixMap = GetGWorldPixMap(anim->qtime->offscreenGWorld);
|
|
LockPixels(anim->qtime->offscreenPixMap);
|
|
|
|
//fill blender's anim struct
|
|
anim->qtime->depth = depth;
|
|
|
|
anim->duration = anim->qtime->framecount;
|
|
anim->params = 0;
|
|
|
|
anim->interlacing = 0;
|
|
anim->orientation = 0;
|
|
anim->framesize = anim->x * anim->y * 4;
|
|
|
|
anim->curposition = 0;
|
|
|
|
if(QTIME_DEBUG) printf("qt: load %s %dx%dx%d frames %d\n", anim->name, anim->qtime->movWidth,
|
|
anim->qtime->movHeight, anim->qtime->depth, anim->qtime->framecount);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int imb_is_a_quicktime (char *name)
|
|
{
|
|
GraphicsImportComponent theImporter = NULL;
|
|
|
|
FSSpec theFSSpec;
|
|
#ifdef _WIN32
|
|
Str255 dst; /*unused*/
|
|
#endif
|
|
char theFullPath[255];
|
|
|
|
// Boolean isMovieFile = false; /*unused*/
|
|
// AliasHandle myAlias = NULL; /*unused*/
|
|
// Component myImporter = NULL; /*unused*/
|
|
#ifdef __APPLE__
|
|
// FInfo myFinderInfo; /*unused*/
|
|
FSRef myRef;
|
|
#endif
|
|
OSErr err = noErr;
|
|
|
|
if(QTIME_DEBUG) printf("qt: checking as image %s\n", name);
|
|
|
|
// dont let quicktime image import handle these
|
|
if( BLI_testextensie(name, ".swf") ||
|
|
BLI_testextensie(name, ".txt") ||
|
|
BLI_testextensie(name, ".mpg") ||
|
|
BLI_testextensie(name, ".wav") ||
|
|
BLI_testextensie(name, ".mov") || // not as image, doesn't work
|
|
BLI_testextensie(name, ".avi") ||
|
|
BLI_testextensie(name, ".mp3")) return 0;
|
|
|
|
sprintf(theFullPath, "%s", name);
|
|
#ifdef __APPLE__
|
|
err = FSPathMakeRef(theFullPath, &myRef, 0);
|
|
err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &theFSSpec, NULL);
|
|
#else
|
|
CopyCStringToPascal(theFullPath, dst);
|
|
err = FSMakeFSSpec(0, 0L, dst, &theFSSpec);
|
|
#endif
|
|
|
|
GetGraphicsImporterForFile(&theFSSpec, &theImporter);
|
|
|
|
if (theImporter != NULL) {
|
|
if(QTIME_DEBUG) printf("qt: %s valid\n", name);
|
|
CloseComponent(theImporter);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
ImBuf *imb_quicktime_decode(unsigned char *mem, int size, int flags)
|
|
{
|
|
Rect myRect;
|
|
OSErr err = noErr;
|
|
GraphicsImportComponent gImporter = NULL;
|
|
|
|
ImageDescriptionHandle desc;
|
|
|
|
ComponentInstance dataHandler;
|
|
PointerDataRef dataref = (PointerDataRef)NewHandle(sizeof(PointerDataRefRecord));
|
|
|
|
int x, y, depth;
|
|
int have_gw = FALSE;
|
|
ImBuf *ibuf = NULL;
|
|
// ImBuf *imbuf = NULL; /*unused*/
|
|
GWorldPtr offGWorld;
|
|
PixMapHandle myPixMap = NULL;
|
|
|
|
#ifdef __APPLE__
|
|
Ptr myPtr;
|
|
|
|
register int index;
|
|
register int boxsize;
|
|
|
|
register uint32_t *readPos;
|
|
register uint32_t *changePos;
|
|
|
|
ImBuf *wbuf = NULL;
|
|
unsigned int *rect;
|
|
unsigned char *from, *to;
|
|
#endif
|
|
|
|
if (mem == NULL)
|
|
goto bail;
|
|
|
|
if(QTIME_DEBUG) printf("qt: attempt to load mem as image\n");
|
|
|
|
(**dataref).data = mem;
|
|
(**dataref).dataLength = size;
|
|
|
|
err = OpenADataHandler((Handle)dataref,
|
|
PointerDataHandlerSubType,
|
|
nil,
|
|
(OSType)0,
|
|
nil,
|
|
kDataHCanRead,
|
|
&dataHandler);
|
|
if (err != noErr) {
|
|
if(QTIME_DEBUG) printf("no datahandler\n");
|
|
goto bail;
|
|
}
|
|
|
|
err = GetGraphicsImporterForDataRef((Handle)dataref, PointerDataHandlerSubType, &gImporter);
|
|
if (err != noErr) {
|
|
if(QTIME_DEBUG) printf("no graphimport\n");
|
|
goto bail;
|
|
}
|
|
|
|
err = GraphicsImportGetNaturalBounds(gImporter, &myRect);
|
|
if (err != noErr) {
|
|
if(QTIME_DEBUG) printf("no bounds\n");
|
|
goto bail;
|
|
}
|
|
|
|
err = GraphicsImportGetImageDescription (gImporter, &desc );
|
|
if (err != noErr) {
|
|
if(QTIME_DEBUG) printf("no imagedescription\n");
|
|
goto bail;
|
|
}
|
|
|
|
x = RECT_WIDTH(myRect);
|
|
y = RECT_HEIGHT(myRect);
|
|
depth = (**desc).depth;
|
|
|
|
if (flags & IB_test) {
|
|
ibuf = IMB_allocImBuf(x, y, depth, 0, 0);
|
|
ibuf->ftype = QUICKTIME;
|
|
DisposeHandle((Handle)dataref);
|
|
if (gImporter != NULL) CloseComponent(gImporter);
|
|
return ibuf;
|
|
}
|
|
|
|
#ifdef __APPLE__
|
|
ibuf = IMB_allocImBuf (x, y, 32, IB_rect, 0);
|
|
wbuf = IMB_allocImBuf (x, y, 32, IB_rect, 0);
|
|
|
|
err = NewGWorldFromPtr(&offGWorld,
|
|
k32ARGBPixelFormat,
|
|
&myRect, NULL, NULL, 0,
|
|
(unsigned char *)wbuf->rect, x * 4);
|
|
#else
|
|
|
|
ibuf = IMB_allocImBuf (x, y, 32, IB_rect, 0);
|
|
|
|
err = NewGWorldFromPtr(&offGWorld,
|
|
k32RGBAPixelFormat,
|
|
&myRect, NULL, NULL, 0,
|
|
(unsigned char *)ibuf->rect, x * 4);
|
|
#endif
|
|
|
|
if (err != noErr) {
|
|
if(QTIME_DEBUG) printf("no newgworld\n");
|
|
goto bail;
|
|
} else {
|
|
have_gw = TRUE;
|
|
}
|
|
|
|
GraphicsImportSetGWorld(gImporter, offGWorld, NULL);
|
|
GraphicsImportDraw(gImporter);
|
|
|
|
#ifdef __APPLE__
|
|
rect = ibuf->rect;
|
|
|
|
myPixMap = GetGWorldPixMap(offGWorld);
|
|
LockPixels(myPixMap);
|
|
myPtr = GetPixBaseAddr(myPixMap);
|
|
|
|
if (myPtr == NULL) {
|
|
printf ("Error reading frame from Quicktime");
|
|
IMB_freeImBuf (ibuf);
|
|
return NULL;
|
|
}
|
|
|
|
boxsize = x * y;
|
|
readPos = (uint32_t *) myPtr;
|
|
changePos = (uint32_t *) rect;
|
|
|
|
// Swap alpha byte to the end, so ARGB become RGBA;
|
|
from= (unsigned char *)readPos;
|
|
to= (unsigned char *)changePos;
|
|
|
|
for( index = 0; index < boxsize; index++, from+=4, to+=4 ) {
|
|
to[3] = from[0];
|
|
to[0] = from[1];
|
|
to[1] = from[2];
|
|
to[2] = from[3];
|
|
}
|
|
#endif
|
|
|
|
bail:
|
|
|
|
DisposeHandle((Handle)dataref);
|
|
UnlockPixels(myPixMap);
|
|
if(have_gw) DisposeGWorld(offGWorld);
|
|
|
|
#ifdef __APPLE__
|
|
if (wbuf) {
|
|
IMB_freeImBuf (wbuf);
|
|
wbuf = NULL;
|
|
}
|
|
#endif
|
|
|
|
if (gImporter != NULL) CloseComponent(gImporter);
|
|
|
|
if (err != noErr) {
|
|
if(QTIME_DEBUG) printf("quicktime import unsuccesfull\n");
|
|
if (ibuf) {
|
|
IMB_freeImBuf (ibuf);
|
|
ibuf = NULL;
|
|
}
|
|
}
|
|
|
|
if(ibuf) {
|
|
|
|
#ifdef _WIN32
|
|
// add non transparent alpha layer, so images without alpha show up in the sequence editor
|
|
// exception for GIF images since these can be transparent without being 32 bit
|
|
// (might also be nescessary for OSX)
|
|
int i;
|
|
int box = x * y;
|
|
unsigned char *arect = (unsigned char *) ibuf->rect;
|
|
|
|
if( depth < 32 && (**desc).cType != kGIFCodecType) {
|
|
for(i = 0; i < box; i++, arect+=4)
|
|
arect[3] = 0xFF;
|
|
}
|
|
#endif
|
|
|
|
IMB_flipy(ibuf);
|
|
ibuf->ftype = QUICKTIME;
|
|
}
|
|
return ibuf;
|
|
}
|
|
|
|
#endif /* _WIN32 || __APPLE__ */
|
|
|
|
#endif /* WITH_QUICKTIME */
|
|
|
|
|
|
#if 0
|
|
|
|
struct ImageDescription {
|
|
long idSize;
|
|
CodecType cType;
|
|
long resvd1;
|
|
short resvd2;
|
|
short dataRefIndex;
|
|
short version;
|
|
short revisionLevel;
|
|
long vendor;
|
|
CodecQ temporalQuality;
|
|
CodecQ spatialQuality;
|
|
short width;
|
|
short height;
|
|
Fixed hRes;
|
|
Fixed vRes;
|
|
long dataSize;
|
|
short frameCount;
|
|
Str31 name;
|
|
short depth;
|
|
short clutID;
|
|
};
|
|
|
|
#endif // 0
|