13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy// This may look like C code, but it is really -*- C++ -*-
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy//
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy// Copyright Bob Friesenhahn, 1999, 2000, 2003
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy//
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy// Test reading/writing BLOBs using Magick++
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy//
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include <Magick++.h>
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include <string>
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include <iostream>
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include <fstream>
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MISSING_STD_IOS_BINARY)
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  define IOS_IN_BINARY ios::in
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else
163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#  define IOS_IN_BINARY ios::in | ios::binary
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristyusing namespace std;
203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
213ed852eea50f9d4cd633efb8c2b054b8e33c253cristyusing namespace Magick;
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy// A derived Blob class to exercise updateNoCopy()
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristyclass myBlob : public Blob
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
263ed852eea50f9d4cd633efb8c2b054b8e33c253cristypublic:
273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  // Construct from open binary stream
283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  myBlob( ifstream &stream_ )
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    : Blob()
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      unsigned char* blobData = new unsigned char[100000];
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      char* c= reinterpret_cast<char *>(blobData);
333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      size_t blobLen=0;
343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      while( (blobLen< 100000) && stream_.get(*c) )
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          c++;
373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          blobLen++;
383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if ((!stream_.eof()) || (blobLen == 0))
403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          cout << "Failed to stream into blob!" << endl;
423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          exit(1);
433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      // Insert data into blob
463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      updateNoCopy( reinterpret_cast<unsigned char*>(blobData), blobLen,
473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                    Blob::NewAllocator );
483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy};
503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
523ed852eea50f9d4cd633efb8c2b054b8e33c253cristyint main( int /*argc*/, char ** argv)
533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  // Initialize ImageMagick install location for Windows
563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  InitializeMagick(*argv);
573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int failures=0;
593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  try
613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      string srcdir("");
633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if(getenv("SRCDIR") != 0)
643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        srcdir = getenv("SRCDIR");
653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      string testimage;
673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      //
693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      // Test reading BLOBs
703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      //
713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        string signature("");
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Image image(srcdir + "test_image.miff");
753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          signature = image.signature();
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        // Read raw data from file into BLOB
793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        testimage = srcdir + "test_image.miff";
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ifstream in( testimage.c_str(), ios::in | IOS_IN_BINARY );
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if( !in )
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            cout << "Failed to open file " << testimage << " for input!" << endl;
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            exit(1);
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        unsigned char* blobData = new unsigned char[100000];
873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        char* c=reinterpret_cast<char *>(blobData);
883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        size_t blobLen=0;
893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        while( (blobLen< 100000) && in.get(*c) )
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            c++;
923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            blobLen++;
933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ((!in.eof()) || (blobLen == 0))
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            cout << "Failed to read file " << testimage << " for input!" << endl;
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            exit(1);
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        in.close();
1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        // Construct Magick++ Blob
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Blob blob(static_cast<const unsigned char*>(blobData), blobLen);
1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        delete [] blobData;
1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        // If construction of image fails, an exception should be thrown
1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          // Construct with blob data only
1083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Image image( blob );
1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ( image.signature() != signature )
1103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
1113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ++failures;
1123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              cout << "Line: " << __LINE__
1133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << "  Image signature "
1143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << image.signature()
1153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << " != "
1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << signature << endl;
1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
1183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          // Construct with image geometry and blob data
1223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Image image(  blob, Geometry(148,99));
1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ( image.signature() != signature )
1243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ++failures;
1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              cout << "Line: " << __LINE__
1273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << "  Image signature "
1283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << image.signature()
1293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << " != "
1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << signature << endl;
1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
1323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
1333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
1353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          // Construct default image, and then read in blob data
1363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Image image;
1373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image.read( blob );
1383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ( image.signature() != signature )
1393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
1403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ++failures;
1413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              cout << "Line: " << __LINE__
1423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << "  Image signature "
1433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << image.signature()
1443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << " != "
1453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << signature << endl;
1463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
1473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
1483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
1503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          // Construct default image, and then read in blob data with
1513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          // image geometry
1523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Image image;
1533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image.read( blob, Geometry(148,99) );
1543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ( image.signature() != signature )
1553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
1563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ++failures;
1573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              cout << "Line: " << __LINE__
1583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << "  Image signature "
1593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << image.signature()
1603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << " != "
1613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << signature << endl;
1623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
1633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
1643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      // Test writing BLOBs
1683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
1693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Blob blob;
1703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        string signature("");
1713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
1723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Image image(srcdir + "test_image.miff");
1733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image.magick("MIFF");
1743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          image.write( &blob );
1753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          signature = image.signature();
1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
1773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Image image(blob);
1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          if ( image.signature() != signature )
1803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            {
1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              ++failures;
1823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              cout << "Line: " << __LINE__
1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << "  Image signature "
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << image.signature()
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << " != "
1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                   << signature << endl;
1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy              image.display();
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            }
1893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      // Test writing BLOBs via STL writeImages
1933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Blob blob;
1953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        list<Image> first;
1973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        readImages( &first, srcdir + "test_image_anim.miff" );
1983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        writeImages( first.begin(), first.end(), &blob, true );
1993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
2003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      // Test constructing a BLOB from a derived class
2023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
2033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        string signature("");
2053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
2063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          Image image(srcdir + "test_image.miff");
2073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          signature = image.signature();
2083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
2093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        // Read raw data from file into BLOB
2113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        testimage = srcdir + "test_image.miff";
2123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ifstream in( testimage.c_str(), ios::in | IOS_IN_BINARY );
2133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if( !in )
2143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            cout << "Failed to open file for input!" << endl;
2163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            exit(1);
2173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        myBlob blob( in );
2203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        in.close();
2213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        Image image( blob );
2233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        if ( image.signature() != signature )
2243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          {
2253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            ++failures;
2263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy            cout << "Line: " << __LINE__
2273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 << "  Image signature "
2283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 << image.signature()
2293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 << " != "
2303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy                 << signature << endl;
2313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy          }
2323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
2333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  catch( Exception &error_ )
2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      cout << "Caught exception: " << error_.what() << endl;
2383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return 1;
2393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  catch( exception &error_ )
2413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      cout << "Caught exception: " << error_.what() << endl;
2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return 1;
2443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if ( failures )
2473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      cout << failures << " failures" << endl;
2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return 1;
2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return 0;
2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
2543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
256