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) 2023
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  const char *value;
203  value = getOption(theTextureOptions[i]);
204  if (value)
205  writeTextureOption(theTextureOptions[i], value);
206  }
207  return true;
208 }
209 
210 int
212 {
213  // If we're writing data, flush out the stream
214  if (myOS) myOS->flush(); // Flush out the data
215 
216  return 1; // return success
217 }
218 
219 static inline void
220 swapHeader(IMG_SampleHeader &header)
221 {
222  UTswapBytes((int *)&header, sizeof(header));
223 }
224 
225 int
226 IMG_Sample::readHeader()
227 {
228  IMG_SampleHeader header;
229  IMG_Plane *plane;
230 
231  if (!readBytes((char *)&header, sizeof(IMG_SampleHeader)))
232  return 0;
233 
234  if (header.magic == MAGIC_SWAP)
235  {
236  myByteSwap = 1;
237  swapHeader(header);
238  }
239  else if (header.magic != MAGIC)
240  return 0; // Magic number failed.
241 
242  myStat.setResolution(header.xres, header.yres);
243  plane = myStat.addDefaultPlane();
244  plane->setColorModel((IMG_ColorModel)header.model);
245  plane->setDataType((IMG_DataType)header.data);
246 
247  // Now, we're ready to read the data.
248  return 1;
249 }
250 
251 int
252 IMG_Sample::writeHeader()
253 {
254  IMG_SampleHeader header;
255 
256  header.magic = MAGIC; // Always create native byte order
257  header.xres = myStat.getXres();
258  header.yres = myStat.getYres();
259  header.model = myStat.getPlane()->getColorModel();
260  header.data = myStat.getPlane()->getDataType();
261 
262  if (!myOS->write((char *)&header, sizeof(IMG_SampleHeader)))
263  return 0;
264 
265  // Now, we're ready to write the scanlines...
266  return 1;
267 }
268 
269 int
271 {
272  int nbytes;
273 
274  if (y >= myStat.getYres()) return 0;
275 
276  nbytes = myStat.bytesPerScanline();
277  if (!readBytes((char *)buf, nbytes))
278  return 0;
279 
280  // If the file was written on a different architecture, we might need to
281  // swap the data.
282  if (myByteSwap)
283  {
284  switch (myStat.getPlane()->getDataType())
285  {
286  case IMG_UCHAR: break; // Nope
287  case IMG_FLOAT16:
288  case IMG_USHORT:
289  UTswapBytes((short *)buf, nbytes/sizeof(short));
290  break;
291  case IMG_UINT:
292  UTswapBytes((int *)buf, nbytes/sizeof(int));
293  break;
294  case IMG_FLOAT:
295  UTswapBytes((float *)buf, nbytes/sizeof(float));
296  break;
297  default:
298  break;
299  }
300  }
301 
302  return 1;
303 }
304 
305 int
306 IMG_Sample::writeScanline(int /*y*/, const void *buf)
307 {
308  // If we specified a translator in creation, the buf passed in will be in
309  // the format we want, that is, the translator will make sure the data is
310  // in the correct format.
311 
312  // Since we always write in native format, we don't have to swap
313  return (!myOS->write((char *)buf, myStat.bytesPerScanline())) ? 0 : 1;
314 }
315 
316 ////////////////////////////////////////////////////////////////////
317 //
318 // Now, we load the format
319 //
320 ////////////////////////////////////////////////////////////////////
321 void
323 {
324  new IMG_SampleFormat();
325 }
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)
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:45
GLint GLenum GLint x
Definition: glcorearb.h:409
#define IMG_DT_ALL
Definition: IMG_FileTypes.h:91
void newIMGFormat(void *)
Definition: IMG_Sample.C:322
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:211
void setColorModel(IMG_ColorModel cm)
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:2540
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:306
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
GLsizei const GLfloat * value
Definition: glcorearb.h:824
Contains the details of a specific image file, used by IMG_File. This class contains all the high-lev...
Definition: IMG_Stat.h:40
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:270
GLint y
Definition: glcorearb.h:103
~IMG_Sample() override
Definition: IMG_Sample.C:157