Difference between revisions of "Io image raw"

From The Foundry MODO SDK wiki
Jump to: navigation, search
Line 250: Line 250:
 
Cleanup is called after a failed recognize or after load-object completes, regardless of the outcome. It closes the open file that we had been loading from and clears the pointer we had been using to access it.
 
Cleanup is called after a failed recognize or after load-object completes, regardless of the outcome. It closes the open file that we had been loading from and clears the pointer we had been using to access it.
  
 +
<syntaxhighlight>
 
         LxResult
 
         LxResult
 
  CRawLoader::load_Cleanup (
 
  CRawLoader::load_Cleanup (
Line 256: Line 257:
 
     ...
 
     ...
 
  }
 
  }
 +
</syntaxhighlight>
  
 
These next four functions are utilities that retrieve information that deal with the image in question
 
These next four functions are utilities that retrieve information that deal with the image in question
Line 261: Line 263:
 
First off, we have the CRawLoader loader class load the image in question and then retrieve its width and height objects(which we get when we load the image), in effect retrieving its size.
 
First off, we have the CRawLoader loader class load the image in question and then retrieve its width and height objects(which we get when we load the image), in effect retrieving its size.
  
 +
<syntaxhighlight>
 
<pre>
 
<pre>
 
         void
 
         void
Line 268: Line 271:
 
}
 
}
 
</pre>
 
</pre>
 +
</syntaxhighlight>
  
 
We do the same for our img_Format function, except this time with the file format of the image.  
 
We do the same for our img_Format function, except this time with the file format of the image.  
  
 +
<syntaxhighlight>
 
<pre>
 
<pre>
 
         LXtPixelFormat
 
         LXtPixelFormat
Line 278: Line 283:
 
}
 
}
 
</pre>
 
</pre>
 +
</syntaxhighlight>
  
 
The loader is again used in img_GetPixel to provide important information regarding the scan line size and channels that helps us perform the purpose of the function of the function, which is to access one pixel.  
 
The loader is again used in img_GetPixel to provide important information regarding the scan line size and channels that helps us perform the purpose of the function of the function, which is to access one pixel.  
  
 +
<syntaxhighlight>
 
<pre>
 
<pre>
 
         LxResult
 
         LxResult
Line 292: Line 299:
 
}
 
}
 
</pre>
 
</pre>
 +
</syntaxhighlight>
  
 
We also use the loader in ing_GetLine, which gets one line of the image, to load a scanline from the image directly into the buffer. This is a clever way of performing the intended function of the method, which is to load one line of the image.
 
We also use the loader in ing_GetLine, which gets one line of the image, to load a scanline from the image directly into the buffer. This is a clever way of performing the intended function of the method, which is to load one line of the image.
  
 +
<syntaxhighlight>
 
<pre>
 
<pre>
 
         const void *
 
         const void *
Line 305: Line 314:
 
}
 
}
 
</pre>
 
</pre>
 +
</syntaxhighlight>
  
 
To begin, this method verifies that the file we are saving is valid. Next we perform the reverse of the load-object method.  We extract pixels from the image (just to be different, although by line would be faster) and write them to the file, in effect saving it.
 
To begin, this method verifies that the file we are saving is valid. Next we perform the reverse of the load-object method.  We extract pixels from the image (just to be different, although by line would be faster) and write them to the file, in effect saving it.
  
 +
<syntaxhighlight>
 
<pre>
 
<pre>
 
         LxResult
 
         LxResult
Line 318: Line 329:
 
}
 
}
 
</pre>
 
</pre>
 +
</syntaxhighlight>
  
 
[[Category: SDK Examples]]
 
[[Category: SDK Examples]]

Revision as of 18:23, 16 September 2013

Io_image_raw is a basic example plugin. This wiki page is intended as a walkthrough of the code in order to help you better understand the SDK.

When installed, the Io_image_raw plugin adds a saver/loader functionality for RAW image files.

Code Walkthrough

Class Declarations

We want to be able to examine the image files, so here we declare an Interface for opaque image access called CRawImage that inherits from CLxImpl_Image. Of note is a pointer back to the active RAW loader. We use this pointer in all of our basic methods. We have the CRawLoader loader class load the image in question and then retrieve its width and height objects(which we get when we load the image), in effect retrieving its size. We do the same for our img_Format function, except this time with the file format of the image. The loader is again used in img_GetPixel to provide important information regarding the scan line size and channels that helps us perform the purpose of the function of the function, which is to access one pixel. We also use the loader in ing_GetLine, which gets one line of the image, to load a scanline from the image directly into the buffer. This is a clever way of performing the intended function of the method, which is to load one line of the image.

 class CRawImage : public CLxImpl_Image
 {
 public:
        CRawLoader		*rawLoader;
        ILxUnknownID		 inst_ifc;
        FILE			*open_file;
        CLxUser_ThreadService	 threadSvc;
 
        virtual			~CRawImage();
 
        virtual void		 img_Size (
                                        unsigned int	*w,
                                        unsigned int	*h);
 
        virtual LXtPixelFormat	 img_Format (void);
 
        virtual LxResult	 img_GetPixel (
                                        unsigned int	 x,
                                        unsigned int	 y,
                                        LXtPixelFormat	 type,
                                        void		*pixel);
 
        virtual const void *	 img_GetLine (
                                        unsigned int	 y,
                                        LXtPixelFormat	 type,
                                        void		*buf);
 };

We want to create a loader, so we inherit from [[1]]. Inside the class, we declare a factory. Factories are objects that allow attributes to be read and new server instances to be spawned. In this case, we declare it to be able to create an image interface for opaque image I/O.

Right above the factory declaration is a file pointer. The first method that must be run is our load_Recognize function, which checks if the file we are examining is a valid data type. Before anything else, though, we take the file we are loading(passed in as an argument) and set the aforementioned file pointer to it. The RAW image format is a bit unusual as there is no known data signature we can compare against so we instead call the GetImportOptions, which retrieves certain values regarding the parameters of the image file, and compare those parameters against the parameters of the file we have. The GetImportOptions additionally sets other object values that we will call in later functions. If the parameters match, the file is valid.

The next seven functions return certain values related to the image, such as image height and header size, which we set in the load_Recognize function(and some through the GetImportOptions function, which we called in the load_Recognize function).

Our LoadInstance function takes the file the file pointer points at and creates an instance of the image there.

Our LoadObject method is the function that actually loads the file. It creates an object, in this case an image, and fills it line by line with data from the file.

Once we are finally finished, our cleanup function closes the file that the file pointer points to.

<pre>
class CRawLoader : public CLxImpl_Loader1
{
        LXtImageTarget1		 img_target;
        FILE			*open_file;
 
        /*
         * Factory to create image interface for opaque image I/O.
         */
        CLxPolymorph<CRawImage>	 raw_factory;
 
        /*
         * Import options from the Image I/O panel.
         */
        unsigned		 width;
        unsigned		 height;
        unsigned		 channels;
        bool			 interleaved;
        unsigned		 depth;
        bool			 byteOrderPC;
        unsigned		 headerSize;
 
        void			 GetImportOptions ();
 
        size_t			 scanlineSize;
 
    public:
                                 CRawLoader ();
 
        LxResult		 load_Recognize  (LXtLoadAccess1 *) LXx_OVERRIDE;
 
        const LXtImageTarget1*	 load_GetImageTarget () const
        {
                return &img_target;
        }
 
        FILE *			 load_GetOpenFile () const
        {
                return open_file;
        }
 
        unsigned		 load_GetChannels () const
        {
                return channels;
        }
 
        unsigned		 load_GetDepth () const
        {
                return depth;
        }
 
        bool			 load_GetByteOrderPC () const
        {
                return byteOrderPC;
        }
 
        unsigned		 load_GetHeaderSize () const
        {
                return headerSize;
        }
 
        size_t			 load_GetScanlineSize () const
        {
                return scanlineSize;
        }
 
        LxResult		 load_LoadInstance (
                                        LXtLoadAccess1	*load,
                                        void		**ppvObj) LXx_OVERRIDE;
 
        LxResult		 load_LoadObject (
                                        LXtLoadAccess1	*load,
                                        ILxUnknownID	 dest) LXx_OVERRIDE;
 
        LxResult		 load_Cleanup    (LXtLoadAccess1 *load) LXx_OVERRIDE;
 
        static LXtTagInfoDesc	 descInfo[];
};</pre>

We want to create a saver object, so we have this class inherit from CLxImpl_Saver.

Normally a Saver class has a Verify method as well as a Save method but here we opt to only implement a Save method as in our Save method we verify that the file we are loading is valid. The Save method, other than verifying that the file is valid, only saves the file.

 class CRawSaver : public CLxImpl_Saver
 {
    public:
        virtual LxResult	 sav_Save (
                                        ILxUnknownID	 source,
                                        const char	*filename,
                                        ILxUnknownID	 monitor) LXx_OVERRIDE;
 
        static LXtTagInfoDesc	 descInfo[];
 };

Server Tags

Servers tags are examined when the server is initialized, and give information about the server. We set the tags in this case by taking descinfo[] arrays and associating the relevant data with the corresponding flags.

Here, the tags indicate that the saver class above saves objects of the image class with the file extension RAW.

 LXtTagInfoDesc	 CRawSaver::descInfo[] = {
        { LXsSAV_OUTCLASS,	LXa_IMAGE	},
        { LXsSAV_DOSTYPE,	"RAW"		},
        { LXsSRV_USERNAME,	"Raw Image"	},
        { 0 }
 };

Initialization

Intialize is called when we add the plugin to modo, and is the utility that exports the server. The LXx_ADD_SERVER method is simply a wrapper that is identical to normal method of adding a server, with the arguments being (interface_to_be_added, class_you_depend_on, server_name).

Here we indicate that we intend to add two servers to modo. One of them is of the type saver, depends on the class CRawSaver, and is called raw_RGB. The other does the same, but with Loader1, CRawLoader, and raw_RGB respectively.

        void
 initialize ()
 {
        LXx_ADD_SERVER (Saver,  CRawSaver,  "raw_RGB");
        LXx_ADD_SERVER (Loader1, CRawLoader, "raw_RGB");
 }

Helper Functions

This function uses the query function to query the user for an int value and returns that value. It is called in GetImportOptions to determine what parameters the user wants for the image file.

        static int
 GetUserInt (const char *prefKey, int defaultValue = 0)
 {
    ...
 }

Implementations

This method queries the user for the values of certain parameters of the image. It also sets certain objects inside the CRawLoader that are examined by other functions.

        void
 CRawLoader::GetImportOptions ()
 {
       ...
 }

The constructor indicates that the loader will be using the image interface.

 CRawLoader::CRawLoader ()
 {
        raw_factory.AddInterface (new CLxIfc_Image<CRawImage>);
 }

Recognize method scans the file to check if the file we are examining is a valid data type. Before anything else, though, we take the file we are loading(passed in as an argument) and set a file pointer that we reference in another function. The RAW image format is a bit unusual as there is no known data signature we can compare against so we instead call the GetImportOptions, which retrieves certain values regarding the parameters of the image file, and compare those parameters against the parameters of the file we have. The GetImportOptions additionally sets other object values that we will call in later functions. If the parameters match, the file is valid.

<pre>
        LxResult
CRawLoader::load_Recognize (
        LXtLoadAccess1		*load)
{
       ...
}
</pre>

This function takes the image from the file that other functions in the class had been referencing and creates an instance of it.

        LxResult
 CRawLoader::load_LoadInstance (LXtLoadAccess1 *load, void **ppvObj)
 {
        ...
 }

The load-object method gets an object to fill with data, in this case an image. Using a user wrapper for the image we proceed to fill it from the file line by line. An optional monitor is used to check for user abort. This method is essentially the 'meat' of the CRawLoader, as it actually loads the object in the file we had been accessing into a file.

        LxResult
 CRawLoader::load_LoadObject (
        LXtLoadAccess1		*load,
        ILxUnknownID		 dest)
 {
        ...
 }

Cleanup is called after a failed recognize or after load-object completes, regardless of the outcome. It closes the open file that we had been loading from and clears the pointer we had been using to access it.

        LxResult
 CRawLoader::load_Cleanup (
        LXtLoadAccess1		*load)
 {
     ...
 }

These next four functions are utilities that retrieve information that deal with the image in question

First off, we have the CRawLoader loader class load the image in question and then retrieve its width and height objects(which we get when we load the image), in effect retrieving its size.

<pre>
        void
CRawImage::img_Size (unsigned int *w, unsigned int *h)
{
        ...
}
</pre>

We do the same for our img_Format function, except this time with the file format of the image.

<pre>
        LXtPixelFormat
CRawImage::img_Format (void)
{
        ...
}
</pre>

The loader is again used in img_GetPixel to provide important information regarding the scan line size and channels that helps us perform the purpose of the function of the function, which is to access one pixel.

<pre>
        LxResult
CRawImage::img_GetPixel (
        unsigned int	 x,
        unsigned int	 y,
        LXtPixelFormat	 type,
        void		*pixel)
{
      ...
}
</pre>

We also use the loader in ing_GetLine, which gets one line of the image, to load a scanline from the image directly into the buffer. This is a clever way of performing the intended function of the method, which is to load one line of the image.

<pre>
        const void *
CRawImage::img_GetLine (
        unsigned int	 y,
        LXtPixelFormat	 type,
        void		*buf)
{
       ...
}
</pre>

To begin, this method verifies that the file we are saving is valid. Next we perform the reverse of the load-object method. We extract pixels from the image (just to be different, although by line would be faster) and write them to the file, in effect saving it.

<pre>
        LxResult
CRawSaver::sav_Save (
        ILxUnknownID		 source,
        const char		*filename,
        ILxUnknownID		 monitor)
{
       ...
}
</pre>