HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
IMG_Sample.C
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024
3  * Side Effects Software Inc. All rights reserved.
4  *
5  * Redistribution and use of Houdini Development Kit samples in source and
6  * binary forms, with or without modification, are permitted provided that the
7  * following conditions are met:
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. The name of Side Effects Software may not be used to endorse or
11  * promote products derived from this software without specific prior
12  * written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17  * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
20  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
23  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  *----------------------------------------------------------------------------
26  * Read/Write raw files
27  */
28 
29 #include <sys/types.h>
30 #include <time.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <limits.h>
34 #include <UT/UT_Endian.h> // For byte swapping
35 #include <UT/UT_DSOVersion.h>
36 #include <UT/UT_SysClone.h>
37 #include <IMG/IMG_Format.h>
38 #include "IMG_Sample.h"
39 
40 #define MAGIC 0x1234567a
41 #define MAGIC_SWAP 0xa7654321 // Swapped magic number
42 
43 namespace HDK_Sample {
44 typedef struct {
45  unsigned int magic; // Magic number
46  unsigned int xres; // Width of image
47  unsigned int yres; // Height of image
48  unsigned int model; // My color model
49  unsigned int data; // Data type
51 
52 /// Custom image file format definition. This class defines the properties of
53 /// the custom image format.
54 /// @see IMG_Sample
55 class IMG_SampleFormat : public IMG_Format {
56 public:
58  ~IMG_SampleFormat() override {}
59 
60  const char *getFormatName() const override;
61  const char *getFormatLabel() const override;
62  const char *getFormatDescription() const override;
63  const char *getDefaultExtension() const override;
64  IMG_File *createFile() const override;
65 
66  // Methods to determine if this is one of our recognized files.
67  // The extension is the first try. If there are multiple matches,
68  // then we resort to the magic number (when reading)
69  int checkExtension(const char *filename) const override;
70  int checkMagic(unsigned int) const override;
72  { return IMG_DT_ALL; }
74  { return IMG_CM_ALL; }
75 
76  // Configuration information for the format
77  void getMaxResolution(unsigned &x,
78  unsigned &y) const override;
79 
80  int isReadRandomAccess() const override { return 0; }
81  int isWriteRandomAccess() const override { return 0; }
82 };
83 } // End HDK_Sample namespace
84 
85 using namespace HDK_Sample;
86 
87 const char *
89 {
90  // Very brief label (no spaces)
91  return "Sample";
92 }
93 
94 const char *
96 {
97  // A simple description of the format
98  return "Sample HDK Format";
99 }
100 
101 const char *
103 {
104  // A more verbose description of the image format. Things you might put in
105  // here are the version of the format, etc.
106  return "HDK Sample image format. Not very useful";
107 }
108 
109 const char *
111 {
112  // The default extension for the format files. If there is no default
113  // extension, the format won't appear in the menus to choose image format
114  // types.
115  return "smp";
116 }
117 
118 IMG_File *
120 {
121  return new IMG_Sample;
122 }
123 
124 int
126 {
127  static const char *extensions[] = { "smp", ".SMP", 0 };
128  return matchExtensions(filename, extensions);
129 }
130 
131 int
132 IMG_SampleFormat::checkMagic(unsigned int magic) const
133 {
134  // Check if we hit our magic number
135  return (magic == MAGIC || magic == MAGIC_SWAP);
136 }
137 
138 void
139 IMG_SampleFormat::getMaxResolution(unsigned &x, unsigned &y) const
140 {
141  x = UINT_MAX; // Stored as shorts
142  y = UINT_MAX;
143 }
144 
145 
146 //////////////////////////////////////////////////////////////////
147 //
148 // Sample file loader/saver
149 //
150 //////////////////////////////////////////////////////////////////
151 
153 {
154  myByteSwap = 0;
155 }
156 
158 {
159  close();
160 }
161 
162 int
164 {
165  return readHeader();
166 }
167 
168 /// Default texture options passed down by mantra.
169 /// See also the vm_saveoption SOHO setting.
170 static const char *theTextureOptions[] = {
171  "camera:orthowidth", // Orthographic camera width
172  "camera:zoom", // Perspective camera zoom
173  "camera:projection", // 0 = perspective, 1 = orthographic, etc.
174  "image:crop", // Crop window (xmin, xmax, ymin, ymax)
175  "image:window", // Screen window (x0, x1, y0, y1)
176  "image:pixelaspect", // Pixel aspect ratio (not frame aspect)
177  "image:samples", // Sampling information
178  "space:world", // World space transform of camera
179  NULL
180 };
181 
182 static void
183 writeTextureOption(const char *token, const char *value)
184 {
185  //cout << "Sample: " << token << " := " << value << endl;
186 }
187 
188 int
190 {
191  // Store the image stats and write out the header.
192  myStat = stat;
193  if (!writeHeader())
194  return 0;
195 
196  // When mantra renders to this format, options set in the vm_saveoption
197  // string will be passed down to the image format. This allows you to
198  // query information about the renderer settings. This is optional of
199  // course.
200  for (int i = 0; theTextureOptions[i]; ++i)
201  {
202  UT_StringHolder value = getFileOption(theTextureOptions[i]);
203  if (value)
204  writeTextureOption(theTextureOptions[i], value);
205  }
206  return true;
207 }
208 
209 int
211 {
212  // If we're writing data, flush out the stream
213  if (myOS) myOS->flush(); // Flush out the data
214 
215  return 1; // return success
216 }
217 
218 static inline void
219 swapHeader(IMG_SampleHeader &header)
220 {
221  UTswapBytes((int *)&header, sizeof(header));
222 }
223 
224 int
225 IMG_Sample::readHeader()
226 {
227  IMG_SampleHeader header;
228  IMG_Plane *plane;
229 
230  if (!readBytes((char *)&header, sizeof(IMG_SampleHeader)))
231  return 0;
232 
233  if (header.magic == MAGIC_SWAP)
234  {
235  myByteSwap = 1;
236  swapHeader(header);
237  }
238  else if (header.magic != MAGIC)
239  return 0; // Magic number failed.
240 
241  myStat.setResolution(header.xres, header.yres);
242  plane = myStat.addDefaultPlane();
243  plane->setColorModel((IMG_ColorModel)header.model);
244  plane->setDataType((IMG_DataType)header.data);
245 
246  // Now, we're ready to read the data.
247  return 1;
248 }
249 
250 int
251 IMG_Sample::writeHeader()
252 {
253  IMG_SampleHeader header;
254 
255  header.magic = MAGIC; // Always create native byte order
256  header.xres = myStat.getXres();
257  header.yres = myStat.getYres();
258  header.model = myStat.getPlane()->getColorModel();
259  header.data = myStat.getPlane()->getDataType();
260 
261  if (!myOS->write((char *)&header, sizeof(IMG_SampleHeader)))
262  return 0;
263 
264  // Now, we're ready to write the scanlines...
265  return 1;
266 }
267 
268 int
270 {
271  int nbytes;
272 
273  if (y >= myStat.getYres()) return 0;
274 
275  nbytes = myStat.bytesPerScanline();
276  if (!readBytes((char *)buf, nbytes))
277  return 0;
278 
279  // If the file was written on a different architecture, we might need to
280  // swap the data.
281  if (myByteSwap)
282  {
283  switch (myStat.getPlane()->getDataType())
284  {
285  case IMG_UCHAR: break; // Nope
286  case IMG_FLOAT16:
287  case IMG_USHORT:
288  UTswapBytes((short *)buf, nbytes/sizeof(short));
289  break;
290  case IMG_UINT:
291  UTswapBytes((int *)buf, nbytes/sizeof(int));
292  break;
293  case IMG_FLOAT:
294  UTswapBytes((float *)buf, nbytes/sizeof(float));
295  break;
296  default:
297  break;
298  }
299  }
300 
301  return 1;
302 }
303 
304 int
305 IMG_Sample::writeScanline(int /*y*/, const void *buf)
306 {
307  // If we specified a translator in creation, the buf passed in will be in
308  // the format we want, that is, the translator will make sure the data is
309  // in the correct format.
310 
311  // Since we always write in native format, we don't have to swap
312  return (!myOS->write((char *)buf, myStat.bytesPerScanline())) ? 0 : 1;
313 }
314 
315 ////////////////////////////////////////////////////////////////////
316 //
317 // Now, we load the format
318 //
319 ////////////////////////////////////////////////////////////////////
320 void
322 {
323  new IMG_SampleFormat();
324 }
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:2540
GT_API const UT_StringHolder filename
const char * getDefaultExtension() const override
Definition: IMG_Sample.C:110
#define MAGIC_SWAP
Definition: IMG_Sample.C:41
int isWriteRandomAccess() const override
Definition: IMG_Sample.C:81
#define MAGIC
Definition: IMG_Sample.C:40
void setDataType(IMG_DataType dt)
GLint y
Definition: glcorearb.h:103
int checkExtension(const char *filename) const override
Definition: IMG_Sample.C:125
void close() override
static int matchExtensions(const char *filename, const char *ext[])
Describes the format and layout of a single plane in an image The plane specifies the format and name...
Definition: IMG_Plane.h:48
#define IMG_DT_ALL
void newIMGFormat(void *)
Definition: IMG_Sample.C:321
int isReadRandomAccess() const override
Definition: IMG_Sample.C:80
IMG_File * createFile() const override
Definition: IMG_Sample.C:119
IMG_DataType
Definition: IMG_FileTypes.h:17
const char * getFormatDescription() const override
Definition: IMG_Sample.C:102
const char * getFormatName() const override
Definition: IMG_Sample.C:88
const char * getFormatLabel() const override
Definition: IMG_Sample.C:95
IMG_ColorModel getSupportedColorModels() const override
Definition: IMG_Sample.C:73
int closeFile() override
Definition: IMG_Sample.C:210
void setColorModel(IMG_ColorModel cm)
GLint GLenum GLint x
Definition: glcorearb.h:409
void getMaxResolution(unsigned &x, unsigned &y) const override
Definition: IMG_Sample.C:139
#define IMG_CM_ALL
int open() override
Definition: IMG_Sample.C:163
int writeScanline(int scan, const void *buf) override
Definition: IMG_Sample.C:305
IMG_ColorModel
Definition: IMG_FileTypes.h:53
UT_API void UTswapBytes(int16 *values, int64 num)
IMG_DataType getSupportedTypes() const override
Returns a bitfield of data types supported by this format.
Definition: IMG_Sample.C:71
Contains the details of a specific image file, used by IMG_File. This class contains all the high-lev...
Definition: IMG_Stat.h:38
int create(const IMG_Stat &stat) override
Definition: IMG_Sample.C:189
Definition: core.h:1131
int checkMagic(unsigned int) const override
Definition: IMG_Sample.C:132
int readScanline(int y, void *buf) override
Definition: IMG_Sample.C:269
~IMG_Sample() override
Definition: IMG_Sample.C:157