Added imreadmulti API to read multi-paged images into a vector of Mat.
authorAshod Nakashian <ashodnakashian@yahoo.com>
Mon, 29 Dec 2014 15:50:42 +0000 (10:50 -0500)
committerAshod Nakashian <ashodnakashian@yahoo.com>
Sat, 3 Jan 2015 05:09:35 +0000 (00:09 -0500)
modules/imgcodecs/include/opencv2/imgcodecs.hpp
modules/imgcodecs/src/loadsave.cpp

index f8c6900..a22d3dc 100644 (file)
@@ -134,6 +134,16 @@ returns an empty matrix ( Mat::data==NULL ). Currently, the following file forma
  */
 CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR );
 
+/** @brief Loads a multi-page image from a file. (see imread for details.)
+
+@param filename Name of file to be loaded.
+@param flags Flags specifying the color type of a loaded image (see imread).
+            Defaults to IMREAD_ANYCOLOR, as each page may be different.
+@param mats A vector of Mat objects holding each page, if more than one.
+
+*/
+CV_EXPORTS_W bool imreadmulti(const String& filename, std::vector<Mat>& mats, int flags = IMREAD_ANYCOLOR);
+
 /** @brief Saves an image to a specified file.
 
 @param filename Name of the file.
index 7359871..c06b42a 100644 (file)
@@ -320,6 +320,84 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0 )
         hdrtype == LOAD_IMAGE ? (void*)image : (void*)mat;
 }
 
+
+/**
+* Read an image into memory and return the information
+*
+* @param[in] filename File to load
+* @param[in] flags Flags
+* @param[in] mats Reference to C++ vector<Mat> object to hold the images
+*
+*/
+static bool
+imreadmulti_(const String& filename, int flags, std::vector<Mat>& mats)
+{
+    /// Search for the relevant decoder to handle the imagery
+    ImageDecoder decoder;
+
+#ifdef HAVE_GDAL
+    if ((flags & IMREAD_LOAD_GDAL) == IMREAD_LOAD_GDAL){
+        decoder = GdalDecoder().newDecoder();
+    }
+    else{
+#endif
+        decoder = findDecoder(filename);
+#ifdef HAVE_GDAL
+    }
+#endif
+
+    /// if no decoder was found, return nothing.
+    if (!decoder){
+        return 0;
+    }
+
+    /// set the filename in the driver
+    decoder->setSource(filename);
+
+    // read the header to make sure it succeeds
+    if (!decoder->readHeader())
+        return 0;
+
+    for (;;)
+    {
+        // grab the decoded type
+        int type = decoder->type();
+        if (flags != -1)
+        {
+            if ((flags & CV_LOAD_IMAGE_ANYDEPTH) == 0)
+                type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
+
+            if ((flags & CV_LOAD_IMAGE_COLOR) != 0 ||
+                ((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1))
+                type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
+            else
+                type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
+        }
+
+        // established the required input image size.
+        CvSize size;
+        size.width = decoder->width();
+        size.height = decoder->height();
+
+        Mat mat;
+        mat.create(size.height, size.width, type);
+
+        // read the image data
+        if (!decoder->readData(mat))
+        {
+            break;
+        }
+
+        mats.push_back(mat);
+        if (!decoder->nextPage())
+        {
+            break;
+        }
+    }
+
+    return !mats.empty();
+}
+
 /**
  * Read an image
  *
@@ -340,6 +418,21 @@ Mat imread( const String& filename, int flags )
     return img;
 }
 
+/**
+* Read a multi-page image
+*
+*  This function merely calls the actual implementation above and returns itself.
+*
+* @param[in] filename File to load
+* @param[in] mats Reference to C++ vector<Mat> object to hold the images
+* @param[in] flags Flags you wish to set.
+*
+*/
+bool imreadmulti(const String& filename, std::vector<Mat>& mats, int flags)
+{
+    return imreadmulti_(filename, flags, mats);
+}
+
 static bool imwrite_( const String& filename, const Mat& image,
                       const std::vector<int>& params, bool flipv )
 {