QuartzQuickTimeParser.C

Go to the documentation of this file.
00001 /*!@file Raster/QuartzQuickTimeParser.C */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Raster/QuartzQuickTimeParser.C $
00035 // $Id: QuartzQuickTimeParser.C 7958 2007-02-20 23:30:52Z rjpeters $
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   // Convert image path to CFString
00061   CFStringRef inPath = CFStringCreateWithCString(NULL, filename,
00062                                                  CFStringGetSystemEncoding());
00063   if (!inPath)
00064     LFATAL("Could not get CFString from %s", filename);
00065 
00066   // create the data reference
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: // RGB
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         // Yuck. CoreGraphics won't let us render directly into 24-bit
00151         // RGB pixels; instead we have to render into 32-bit ARGB
00152         // pixels with an ignored alpha field, and then copy the data
00153         // a second time from there into our desired 24-bit result.
00154 
00155         Image<byte> argb(4*CGImageGetWidth(imageRef),
00156                          CGImageGetHeight(imageRef),
00157                          NO_INIT);
00158 
00159         // see http://developer.apple.com/qa/qa2001/qa1037.html for a
00160         // list of the parameter combinations that are supported by
00161         // CGBitmapContextCreate()
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: // grayscale
00199       {
00200         // 34=>2-bit, 36=>4-bit, 40=>8-bit
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 /* So things look consistent in everyone's emacs... */
00277 /* Local Variables: */
00278 /* mode: c++ */
00279 /* indent-tabs-mode: nil */
00280 /* End: */
00281 
00282 #endif // RASTER_QUARTZQUICKTIMEPARSER_C_DEFINED
Generated on Sun May 8 08:05:34 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3