00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef RASTER_QUARTZQUICKTIMEPARSER_C_DEFINED
00039 #define RASTER_QUARTZQUICKTIMEPARSER_C_DEFINED
00040
00041 #include "Raster/QuartzQuickTimeParser.H"
00042
00043 #ifdef HAVE_QUICKTIME_QUICKTIME_H
00044
00045 #include "Raster/GenericFrame.H"
00046 #include "Util/Janitor.H"
00047 #include "Util/log.H"
00048
00049 #include <QuickTime/QuickTime.h>
00050
00051 struct QuartzQuickTimeParser::Rep
00052 {
00053 GenericFrame frame;
00054 };
00055
00056 QuartzQuickTimeParser::QuartzQuickTimeParser(const char* filename)
00057 :
00058 rep(new Rep)
00059 {
00060
00061 CFStringRef inPath = CFStringCreateWithCString(NULL, filename,
00062 CFStringGetSystemEncoding());
00063 if (!inPath)
00064 LFATAL("Could not get CFString from %s", filename);
00065
00066
00067 Handle myDataRef = NULL;
00068 OSType myDataRefType;
00069 OSErr result =
00070 QTNewDataReferenceFromFullPathCFString
00071 (inPath, (unsigned long) kQTNativeDefaultPathStyle,
00072 0, &myDataRef, &myDataRefType);
00073
00074 if (result != noErr)
00075 LFATAL("Could not get DataRef for %s (error %d)", filename, result);
00076
00077 Janitor<GraphicsImportComponent> importer(NULL, &CloseComponent);
00078 result = GetGraphicsImporterForDataRef(myDataRef, myDataRefType, &importer.it);
00079
00080 if (result != noErr)
00081 LFATAL("Could not get GraphicsImportComponent for %s (error %d)",
00082 filename, result);
00083
00084 unsigned long imageCount = 0;
00085 {
00086 ComponentResult res = GraphicsImportGetImageCount(importer.it, &imageCount);
00087 if (res != noErr)
00088 LFATAL("Could not get image count for %s (error %ld)",
00089 filename, res);
00090 }
00091
00092 if (imageCount == 0)
00093 LFATAL("Oops! No images found in %s", filename);
00094
00095 if (imageCount > 1)
00096 LFATAL("Oops! Found %lu images in %s, but can handle only 1",
00097 imageCount, filename);
00098
00099 ASSERT(imageCount == 1);
00100
00101 ImageDescriptionHandle desc;
00102
00103 {
00104 ComponentResult res = GraphicsImportGetImageDescription(importer.it, &desc);
00105 if (res != noErr)
00106 LFATAL("Could not get image description for %s (error %ld)",
00107 filename, res);
00108 }
00109
00110 LDEBUG("%s: dims are %dx%d, depth is %d, codec is '%4s'",
00111 filename, int((*desc)->width), int((*desc)->height),
00112 int((*desc)->depth),
00113 reinterpret_cast<const char*>(&(*desc)->cType));
00114
00115 Rect bounds;
00116 {
00117 ComponentResult res = GraphicsImportGetNaturalBounds(importer.it, &bounds);
00118 if (res != noErr)
00119 LFATAL("Could not get image bounds for %s (error %ld)",
00120 filename, res);
00121 }
00122
00123 CGImageRef imageRef = 0;
00124 if (noErr !=
00125 GraphicsImportCreateCGImage
00126 (importer.it, &imageRef,
00127 kGraphicsImportCreateCGImageUsingCurrentSettings))
00128 LFATAL("Could not create CGImage");
00129
00130 CGRect rect;
00131 rect.origin.x = 0;
00132 rect.origin.y = 0;
00133 rect.size.width = CGImageGetWidth(imageRef);
00134 rect.size.height = CGImageGetHeight(imageRef);
00135
00136 switch ((*desc)->depth)
00137 {
00138 case 1: case 2: case 4: case 8: case 16: case 24: case 32:
00139 {
00140 Janitor<CGColorSpaceRef> colorSpace
00141 (CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB),
00142 &CGColorSpaceRelease);
00143
00144 if (NULL == colorSpace.it)
00145 LFATAL("couldn't create rgb color space");
00146
00147 LDEBUG("rgb colorspace has %"ZU" components",
00148 CGColorSpaceGetNumberOfComponents(colorSpace.it));
00149
00150
00151
00152
00153
00154
00155 Image<byte> argb(4*CGImageGetWidth(imageRef),
00156 CGImageGetHeight(imageRef),
00157 NO_INIT);
00158
00159
00160
00161
00162
00163 Janitor<CGContextRef> bitmapContext
00164 (CGBitmapContextCreate(argb.getArrayPtr(),
00165 argb.getWidth() / 4,
00166 argb.getHeight(),
00167 8,
00168 argb.getWidth(),
00169 colorSpace.it,
00170 kCGImageAlphaNoneSkipLast),
00171 &CFRelease);
00172
00173 if (NULL == bitmapContext.it)
00174 LFATAL("couldn't create rgb bitmap context");
00175
00176 CGContextDrawImage(bitmapContext.it, rect, imageRef);
00177
00178 Image<PixRGB<byte> > rgb(CGImageGetWidth(imageRef),
00179 CGImageGetHeight(imageRef),
00180 NO_INIT);
00181 const byte* argbptr = argb.getArrayPtr();
00182 byte* rgbptr = reinterpret_cast<byte*>(rgb.getArrayPtr());
00183 const size_t n = rgb.getSize();
00184
00185 for (size_t i = 0; i < n; ++i)
00186 {
00187 rgbptr[0] = argbptr[0];
00188 rgbptr[1] = argbptr[1];
00189 rgbptr[2] = argbptr[2];
00190 rgbptr += 3;
00191 argbptr += 4;
00192 }
00193
00194 rep->frame = GenericFrame(rgb);
00195 }
00196 break;
00197
00198 case 34: case 36: case 40:
00199 {
00200
00201 const int depth = (*desc)->depth - 32;
00202 (void) depth;
00203
00204 Janitor<CGColorSpaceRef> colorSpace
00205 (CGColorSpaceCreateWithName(kCGColorSpaceGenericGray),
00206 &CGColorSpaceRelease);
00207
00208 if (NULL == colorSpace.it)
00209 LFATAL("couldn't create grayscale color space");
00210
00211 LDEBUG("grayscale colorspace has %"ZU" components",
00212 CGColorSpaceGetNumberOfComponents(colorSpace.it));
00213
00214 Image<byte> gray(CGImageGetWidth(imageRef),
00215 CGImageGetHeight(imageRef),
00216 NO_INIT);
00217
00218 Janitor<CGContextRef> bitmapContext
00219 (CGBitmapContextCreate(gray.getArrayPtr(),
00220 gray.getWidth(),
00221 gray.getHeight(),
00222 8,
00223 gray.getWidth(),
00224 colorSpace.it,
00225 kCGImageAlphaNone),
00226 &CFRelease);
00227
00228 if (NULL == bitmapContext.it)
00229 LFATAL("couldn't create grayscale bitmap context");
00230
00231 CGContextDrawImage(bitmapContext.it, rect, imageRef);
00232
00233 rep->frame = GenericFrame(gray);
00234 break;
00235 }
00236 }
00237 }
00238
00239 QuartzQuickTimeParser::~QuartzQuickTimeParser()
00240 {
00241 delete rep;
00242 }
00243
00244 GenericFrameSpec QuartzQuickTimeParser::getFrameSpec() const
00245 {
00246 return rep->frame.frameSpec();
00247 }
00248
00249 std::string QuartzQuickTimeParser::getComments() const
00250 {
00251 return std::string();
00252 }
00253
00254 uint QuartzQuickTimeParser::getTagCount() const
00255 {
00256 return 0;
00257 }
00258
00259 bool QuartzQuickTimeParser::getTag(uint tag,
00260 std::string &name,
00261 std::string &value) const
00262 {
00263 name = std::string();
00264 value = std::string();
00265 return false;
00266 }
00267
00268 GenericFrame QuartzQuickTimeParser::getFrame()
00269 {
00270 return rep->frame;
00271 }
00272
00273 #endif // HAVE_QUICKTIME_QUICKTIME_H
00274
00275
00276
00277
00278
00279
00280
00281
00282 #endif // RASTER_QUARTZQUICKTIMEPARSER_C_DEFINED