From Stephan Huber (contains Registry.cpp changes from David Guthrie):

"Attached is the new source for the Quicktime-Plugin which adds the
ability to write pictures in various formats (tested: jpg, png, tif,
psd) (24bit + 32bit only, 8bit not tested)

There are changes in the attached osgDB::Registry, which allows osg to
find resources/plugins in the right folders under OS X"

Note, from Robert Osfield, changed the FilePathList* filepath + delete to a
FilePathList filepath to avoid possible memory leaks when expections are thrown/
make it more maintainable.  Also didn't merge the automatic playing of movies.
This commit is contained in:
Robert Osfield 2005-04-08 13:52:03 +00:00
parent d31cd3dce6
commit cd8634776d
3 changed files with 297 additions and 8 deletions

View File

@ -159,11 +159,15 @@ Registry::Registry()
addFileExtensionAlias("tiff", "qt");
addFileExtensionAlias("gif", "qt");
addFileExtensionAlias("png", "qt");
addFileExtensionAlias("psd", "qt");
addFileExtensionAlias("rgb", "qt");
addFileExtensionAlias("tga", "qt");
addFileExtensionAlias("mov", "qt");
addFileExtensionAlias("avi", "qt");
addFileExtensionAlias("mpg", "qt");
addFileExtensionAlias("mpv", "qt");
addFileExtensionAlias("dv", "qt");
addFileExtensionAlias("mp4", "qt");
#else
addFileExtensionAlias("jpg", "jpeg");
addFileExtensionAlias("jpe", "jpeg");
@ -245,6 +249,89 @@ static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENT
static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH <path>[;path]..","Paths for locating datafiles");
#endif
#if defined(__APPLE__)
//Executable packages should be able to load file resources from inside the packages.
//These resources should be stored in YourProgram.app/Contents/Resources, and so
//should the path list for the data files should include that path by default.
#include <CoreServices/CoreServices.h>
void Registry::initDataFilePathList()
{
FilePathList filepath;
//
// set up data file paths
//
char *ptr;
if( (ptr = getenv( "OSG_FILE_PATH" )) )
{
//notify(DEBUG_INFO) << "OSG_FILE_PATH("<<ptr<<")"<<std::endl;
convertStringPathIntoFilePathList(ptr, filepath);
}
else if( (ptr = getenv( "OSGFILEPATH" )) )
{
//notify(DEBUG_INFO) << "OSGFILEPATH("<<ptr<<")"<<std::endl;
convertStringPathIntoFilePathList(ptr, filepath);
}
const int MAX_OSX_PATH_SIZE = 1024;
char buffer[MAX_OSX_PATH_SIZE];
char bundlePathBuffer[MAX_OSX_PATH_SIZE];
CFURLRef url;
CFStringRef pathString;
CFBundleRef myBundle;
CFStringRef bundlePathString;
myBundle = CFBundleGetMainBundle();
if (myBundle != NULL) {
// Get the URL to the bundle
url = CFBundleCopyBundleURL( myBundle );
// Convert the URL to a CFString that looks like a Unix file path
bundlePathString = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle );
// Convert the CFString to a C string
CFStringGetCString( bundlePathString, bundlePathBuffer, MAX_OSX_PATH_SIZE, kCFStringEncodingUTF8 );
CFRelease( url );
// Now find the resources folder
url = CFBundleCopyResourcesDirectoryURL( myBundle );
//pathString = CFURLCopyPath( url );
// Convert the URL to a CFString that looks like a Unix file path
pathString = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle );
// Convert the CFString to a C string
CFStringGetCString( pathString, buffer, MAX_OSX_PATH_SIZE, kCFStringEncodingUTF8 );
// Combine the string and copy it into the FilePath list
filepath.push_back( std::string(bundlePathBuffer)
+ std::string("/")
+ std::string(buffer)
);
CFRelease( pathString );
CFRelease( bundlePathString );
CFRelease( url );
pathString = NULL;
bundlePathString = NULL;
url = NULL;
}
else
{
osg::notify( osg::DEBUG_INFO ) << "Couldn't find the Application Bundle" << std::endl;
}
setDataFilePathList(filepath);
//osg::notify(INFO)<<"Data FilePathList"<<std::endl;
//PrintFilePathList(osg::notify(INFO),getDataFilePathList());
}
#else
void Registry::initDataFilePathList()
{
//
@ -266,6 +353,8 @@ void Registry::initDataFilePathList()
//PrintFilePathList(osg::notify(INFO),getDataFilePathList());
}
#endif
void Registry::setDataFilePathList(const std::string& paths)
{
_dataFilePath.clear();

View File

@ -5,13 +5,12 @@
extern "C" {
#endif
unsigned char*
LoadBufferFromDarwinPath ( const char *fname, long *origWidth,
unsigned char* LoadBufferFromDarwinPath ( const char *fname, long *origWidth,
long *origHeight, long *origDepth,
long *buffWidth, long *buffHeight, long *buffDepth);
char *
QTfailureMessage(void);
char* QTfailureMessage(void);
FSSpec *darwinPathToFSSpec (char *fname );
#ifdef __cplusplus
}

View File

@ -16,12 +16,16 @@
#ifndef SEEK_SET
# define SEEK_SET 0
#endif
#include <Carbon/Carbon.h>
#include <Quicktime/Quicktime.h>
#include "QTtexture.h"
#include "QuicktimeImageStream.h"
using namespace osg;
class ReaderWriterQT : public osgDB::ReaderWriter
{
public:
@ -32,6 +36,7 @@ class ReaderWriterQT : public osgDB::ReaderWriter
return osgDB::equalCaseInsensitive(extension,"mov") ||
osgDB::equalCaseInsensitive(extension,"mpg") ||
osgDB::equalCaseInsensitive(extension,"mpv") ||
osgDB::equalCaseInsensitive(extension,"mp4") ||
osgDB::equalCaseInsensitive(extension,"dv");
}
@ -44,13 +49,13 @@ class ReaderWriterQT : public osgDB::ReaderWriter
osgDB::equalCaseInsensitive(extension,"jpg") ||
osgDB::equalCaseInsensitive(extension,"jpeg") ||
osgDB::equalCaseInsensitive(extension,"tif") ||
osgDB::equalCaseInsensitive(extension,"tiff") ||
osgDB::equalCaseInsensitive(extension,"pict") ||
osgDB::equalCaseInsensitive(extension,"tiff") ||
osgDB::equalCaseInsensitive(extension,"gif") ||
osgDB::equalCaseInsensitive(extension,"png") ||
osgDB::equalCaseInsensitive(extension,"pict") ||
osgDB::equalCaseInsensitive(extension,"pct") ||
osgDB::equalCaseInsensitive(extension,"tga") ||
osgDB::equalCaseInsensitive(extension,"psd") ||
acceptsMovieExtension(extension);
}
@ -120,8 +125,9 @@ class ReaderWriterQT : public osgDB::ReaderWriter
int i, j;
// swizzle entire image in-place
unsigned char r, g, b, a;
for (i=0; i<buffHeight; i++ ) {
unsigned char r, g, b, a;
switch (origDepth) {
/*
since 8-bit tgas will get expanded into colour, have to use RGB code for 8-bit images
@ -175,6 +181,8 @@ class ReaderWriterQT : public osgDB::ReaderWriter
}
}
}
Image* image = new Image();
image->setFileName(fileName.c_str());
@ -188,6 +196,199 @@ class ReaderWriterQT : public osgDB::ReaderWriter
notify(INFO) << "image read ok "<<buffWidth<<" "<<buffHeight<<std::endl;
return image;
}
virtual WriteResult writeImage(const osg::Image &img,const std::string& fileName, const osgDB::ReaderWriter::Options*) const
{
std::string ext = osgDB::getFileExtension(fileName);
if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
//Buidl map of extension <-> osFileTypes
std::map<std::string, OSType> extmap;
extmap.insert(std::pair<std::string, OSType>("jpg", kQTFileTypeJPEG));
extmap.insert(std::pair<std::string, OSType>("jpeg", kQTFileTypeJPEG));
extmap.insert(std::pair<std::string, OSType>("bmp", kQTFileTypeBMP));
extmap.insert(std::pair<std::string, OSType>("tif", kQTFileTypeTIFF));
extmap.insert(std::pair<std::string, OSType>("tiff", kQTFileTypeTIFF));
extmap.insert(std::pair<std::string, OSType>("png", kQTFileTypePNG));
extmap.insert(std::pair<std::string, OSType>("gif", kQTFileTypeGIF));
extmap.insert(std::pair<std::string, OSType>("psd", kQTFileTypePhotoShop));
// extmap.insert(std::pair<std::string, OSType>("tga", kQTFileTypeTargaImage));
extmap.insert(std::pair<std::string, OSType>("sgi", kQTFileTypeSGIImage));
extmap.insert(std::pair<std::string, OSType>("rgb", kQTFileTypeSGIImage));
extmap.insert(std::pair<std::string, OSType>("rgba", kQTFileTypeSGIImage));
std::map<std::string, OSType>::iterator cur = extmap.find(ext);
// can not handle this type of file, perhaps a movie?
if (cur == extmap.end())
return WriteResult::FILE_NOT_HANDLED;
OSType desiredType = cur->second;
GraphicsExportComponent geComp = NULL;
OSErr err = OpenADefaultComponent(GraphicsExporterComponentType, desiredType, &geComp);
if (err != noErr) {
osg::notify(osg::WARN) << "ReaderWriterQT: could not open Graphics epxorter for type " << ext << ", Err: " << err << std::endl;
return WriteResult::FILE_NOT_HANDLED;
}
GWorldPtr gw = NULL;
// we are converting the images back to 32bit, it seems, that quicktime can't handle others
unsigned long desiredPixelFormat = k32ARGBPixelFormat;
// we need to swizzle the colours again :)
unsigned int numBytes = img.computeNumComponents(img.getPixelFormat());
unsigned int buffWidth = img.s();
unsigned int buffHeight = img.t();
char * pixels = (char*) malloc(buffHeight * buffWidth * 4);
const unsigned char *srcp = img.data();
char *dstp=pixels;
unsigned int i, j;
for (i=0; i<buffHeight; i++ ) {
switch (numBytes) {
case 1 :
dstp[0] = 0;
dstp[1] = srcp[0];
dstp[2] = srcp[0];
dstp[3] = srcp[0];
srcp+=1;
dstp+=4;
break;
case 3 :
for (j=0; j<buffWidth; j++ ) {
dstp[0]=0;
dstp[1]=srcp[0];
dstp[2]=srcp[1];
dstp[3]=srcp[2];
srcp+=3;
dstp+=4;
}
break;
case 4 :
for (j=0; j<buffWidth; j++ ) {
dstp[0]=srcp[1];
dstp[1]=srcp[2];
dstp[2]=srcp[3];
dstp[3]=srcp[0];
srcp+=4;
dstp+=4;
}
break;
default :
// osg::notify(osg::WARN) << "ERROR IN RETURNED PIXEL DEPTH, CANNOT COPE" << std::endl;
return WriteResult::ERROR_IN_WRITING_FILE;
break;
}
}
// Flip the image
unsigned imageSize = buffWidth*buffHeight*4;
char *tBuffer = (char*)malloc((size_t)imageSize);
unsigned int rowBytes = buffWidth * 4;
for (i = 0, j = imageSize - rowBytes; i < imageSize; i += rowBytes, j -= rowBytes)
memcpy( &tBuffer[j], &pixels[i], (size_t)rowBytes );
memcpy(pixels, tBuffer, (size_t)imageSize);
free(tBuffer);
FSSpec* fileSpec = NULL;
try {
Rect bounds;
SetRect(&bounds, 0,0, img.s(), img.t());
err = NewGWorldFromPtr(&gw, desiredPixelFormat, &bounds, 0,0,0, pixels, buffWidth*4);
if (err != noErr) {
osg::notify(osg::WARN) << "ReaderWriterQT: could not create gworld for type " << ext << ", Err: " << err << std::endl;
throw err;
}
// create a dummy file at location
FILE *fp = fopen(fileName.c_str(), "wb");
if (!fp) {
osg::notify(osg::WARN) << "ReaderWriterQT: could not create file!" << std::endl;
throw err;
}
fclose(fp);
// get an FSSpec to the file, so quicktime can handle the file.
fileSpec = darwinPathToFSSpec( const_cast<char*>(fileName.c_str()) );
if (fileSpec == NULL) {
osg::notify(osg::WARN) << "ReaderWriterQT: could not get FSSpec" << std::endl;
throw err;
}
err = GraphicsExportSetInputGWorld(geComp, gw);
if (err != noErr) {
osg::notify(osg::WARN) << "ReaderWriterQT: could not set input gworld for type " << ext << ", Err: " << err << std::endl;
throw err;
}
err = GraphicsExportSetOutputFile(geComp, fileSpec);
if (err != noErr) {
osg::notify(osg::WARN) << "ReaderWriterQT: could not set output file for type " << ext << ", Err: " << err << std::endl;
throw err;
}
// Set the compression quality (needed for JPEG, not necessarily for other formats)
if (desiredType == kQTFileTypeJPEG) {
err = GraphicsExportSetCompressionQuality(geComp, codecLosslessQuality);
if (err != noErr) {
osg::notify(osg::WARN) << "ReaderWriterQT: could not set compression for type " << ext << ", Err: " << err << std::endl;
throw err;
}
}
// do the export
err = GraphicsExportDoExport(geComp, NULL);
if (err != noErr) {
osg::notify(osg::WARN) << "ReaderWriterQT: could not save file for type " << ext << ", Err: " << err << std::endl;
throw err;
}
if (geComp != NULL)
CloseComponent(geComp);
DisposeGWorld (gw);
if (fileSpec != NULL ) free(fileSpec);
if (pixels) free(pixels);
return WriteResult::FILE_SAVED;
}
catch (...) {
if (geComp != NULL) CloseComponent(geComp);
if (gw != NULL) DisposeGWorld (gw);
if (fileSpec != NULL ) free(fileSpec);
if (pixels) free(pixels);
return WriteResult::ERROR_IN_WRITING_FILE;
}
}
};