Re: Saving a series of BitmapReps as Quicktime
Re: Saving a series of BitmapReps as Quicktime
- Subject: Re: Saving a series of BitmapReps as Quicktime
- From: Sarwat Khan <email@hidden>
- Date: Sun, 26 Aug 2001 16:17:34 -0400
This is a Very Long Reply, because I'm hoping that other people
working on this can shed some light. I have to do something like
this too.
Firstly is there an objective-c class/wrapper for the quicktime API.
Nope. You may be able to get away with using the QT Java
framework, but it's probably more convenient to use the C API.
I don't know much about the Quicktime API but it seems very
complex and I would like something really simple.
Well, take some consolation in the fact that you only want to
use a small, well understood part of QuickTime :)
In any case, what are the basic steps to do this in Cocoa?
Here's a rough overview:
1. Open a new QT movie for compressing
2. For each NSBitmapImageRep, convert it to a GWorld.
3. Tell QT to add the gworld to your movie
4. Dispose the gworld and return to step 2 until you're done
5. Close the movie
You're probably better off building your NSBitmapImageReps from
a GWorld source. I give an example that might work below. The
problem is that QT only understands GWorlds. It may be
convenient, for step 2, to do the following:
a. create a gworld with the same width & height as the source
bitmap rep.
b. create a new bitmap rep that uses the gworld as a source of pixels
c. use NSImage/whatever to copy the image from the souce bitmap
rep to the bitmap rep created in step b.
d. dispose the new nsbitmapimagerep (and use the gworld until
you've added it to the movie).
I checked NSMovie, but that seems to just be a wrapper to
display movies rather than writing them. Pls yell and scream at
me if I am wrong.
If you want to use QuickTime with Cocoa, and you want to do more
than play back a movie through the AppKit, I suggest you stay
away from NSMovie :P SetMovieGWorld didn't seem to have an
effect on the NSMovie's QTMovie. You don't know what that means
yet, but you will :)
The first thing you need to do is learn how to take an offscreen
bitmap and turn it into a movie. There's a good piece of sample
code here:
http://developer.apple.com/samplecode/Sample_Code/QuickTime/Basics/QTCreateMovie.
htm
Download that sample (non-Mac OS X) and take a look at
QTVideo.c. It won't be that useful without reading the related
QT documentation. I strongly suggest you take some time out and
just read. You won't have to read that much.
The main documentation page is at:
http://developer.apple.com/techpubs/quicktime
And then click the 'main starting point.' It's a bit messy and
overwhelming for the beginner, but it makes more sense once you
know how QT works and what you want to get it to do for you. I
suggest starting here:
http://developer.apple.com/techpubs/quicktime/qtdevdocs/INMAC/QT/iqMovieToolbox.
1.htm
And read the "Introduction to Movies" paragraph. You'll need to
understand Time and the Movie Toolbox. This documents how to
display the standard image compression dialog (what QuickTime
Player shows when you click the Options button in QT Player's
Export dialog), and comrpess a movie from the information that
the user specified:
http://developer.apple.com/techpubs/quicktime/qtdevdocs/apiref/SOURCESV/uimagecpiondls.
htm
That should give you all the info you need without having to use
the sample code. The problem with the sample code is that it
doesn't display a GUI for selecting what compressor or what
compression parameters you want. The good thing about the sample
code is that it works :)
Finally, I suggest subscribing to the QuickTime API list on
lists.apple.com.
Now, once you've understood that, you need to get QT to work
with your NSBitmapImageReps. It's not going to be able to do
that directly. Unfortunately, QuickTime is tied to QuickDraw's
graphics model. If you want to compress an image, it needs to be
in a QuickDraw GWorld.
So for every NSBitmapImageRep you need to compress, you have to
convert it to a GWorld, and then tell QuickTime to add that
GWorld as a frame of your QuickTime movie. You may not find this
process fun.
What I suggest you do (and I haven't tried it), is to create an
NSBitmapImageRep from a GWorld. Something like this:
GWorldPtr myGWorld; //a drawing port with a pixmap structure
PixMapHandle gworldPixMap; //the pixmap structure
Ptr gworldPixels; //actual, raw pixels
long rowBytes; //number of bytes that make up a row of the image
Ptr planes[1]; //source data for NSBitmapImageRep
Rect gworldRectangle = {0, 0, 128, 128};
theErr = QTNewGWorld(&myGWorld, k32RGBAPixelFormat,
&gworldRectangle, nil, nil, 0);
gworldPixMap = GetGWorldPixMap(myGWorld);
LockPixels(gworldPixMap); //does this matter in OS X? prevents
pixels from moving around in memory
gworldPixels = GetPixBaseAddr(gworldPixMap)
rowBytes = GetPixRowBytes(gworldPixMap);
planes[0] = gworldPixels;
myBitmap = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:planes
pixelsWide:(gworldRectangle.right - gworldRectangle.left)
pixelsHigh:(gworldRectangle.bottom - gworldRectangle.top)
bitsPerSample:8
samplesPerPixel:3 //8 * 3 = 24 bits. extra 8 bits for useless alpha.
hasAlpha:NO //yes? setting to no tells it to
ignore alpha values, which is good
isPlanar:NO //gworlds are one plane of meshed pixels.
colorSpaceName:NSDeviceRGBColorSpace //this is a guess
bytesPerRow:rowBytes
bitsPerPixel:32
];
With that code, you should have an NSBitmapImageRep that
references a GWorld. You should be able to draw into the
NSBitmap and end up drawing into the GWorld, but I haven't tried
it! It would be really helpful if someone from Apple could throw
some sample code together. I strongly recommend reading up on
GWorlds too
(
http://developer.apple.com/techpubs/mac/QuickDraw/QuickDraw-302.html).
I don't think you would actually be able to use QuickDraw with
this setup. I used QTNewGWorld so I could get an RGBA pixel
format, which is what I think NSBitmapImageRep expects.
QuickDraw normally uses ARGB (that's what you get if you use
NewGWorld instead of QTNewGWorld). This means you won't be able
to use ForeColor(blueColor); PaintRect(&gworldRect) and expect
to get a blue rectangle. However, if you do all your drawing
with Quartz 2D (and the bitmap rep) or QuickTime, you should be
fine. Hopefully someone from Apple can shed some light on this,
and develop sample code :)
When you're done with your bitmap,
[myBitmap release];
DisposeGWorld(myGWorld);
It may be useful to make your own NSBitmapImageRep subclass to
handle some of these details for you.
I hope this helped,
Sarwat.
{sarwat khan : email@hidden :
http://sarwat.net}