cmake_minimum_required(VERSION 3.20)
project(srfdump VERSION 1.0)
-add_executable(srfdump srfdump.c surfacefile.h)
+add_executable(srfdump srfdump.c jpegrdr.c exif.c jpegrdr.h exif.h surfacefile.h)
target_compile_features(srfdump PRIVATE c_std_11)
if (WIN32)
target_compile_definitions(srfdump PRIVATE -DWIN32 -D_CRT_SECURE_NO_WARNINGS)
add_executable(jpegrdr jpegrdr.c exif.c exif.h)
target_compile_features(jpegrdr PRIVATE c_std_11)
if (WIN32)
- target_compile_definitions(jpegrdr PRIVATE -DWIN32 -D_CRT_SECURE_NO_WARNINGS)
+ target_compile_definitions(jpegrdr PRIVATE -DWIN32 _CRT_SECURE_NO_WARNINGS JPEGRDR_MAIN)
else()
#target_compile_options(jpegrdr PRIVATE -pedantic)
endif()
static const char *EXIF_TYPE_NAMES[11] = {
// 0 1 2 3 4 5
- "?", "byte", "ascii", "short", "long", "rational",
+ "?", "BYTE", "ASCII", "USHORT", "ULONG", "URATIONAL",
// 6 7 8 9 10
- "char", "binary", "sshort", "slong", "srational"
+ "CHAR", "BINARY", "SHORT", "LONG", "RATIONAL"
};
static bool big_endian_data = false;
return item_count;
}
-void exif_print_item(const exif_item_t* item)
+typedef struct tag_name_t {
+ uint16_t tag;
+ const char *name;
+} tag_name_t;
+
+tag_name_t tag_names[] = {
+ { 0x0100, "ImageWidth" },
+ { 0x0101, "ImageHeight" },
+ { 0x0102, "BitsPerSample" },
+ { 0x0103, "Compression" },
+ { 0x0106, "PhotometricInterpretation" },
+ { 0x0107, "Thresholding" },
+ { 0x010e, "ImageDescription" },
+ { 0x010f, "Make" },
+ { 0x0112, "Orientation" },
+ { 0x011a, "XResolution" },
+ { 0x011b, "YResolution" },
+ { 0x011c, "PlanarConfiguration" },
+ { 0x011e, "XPosition" },
+ { 0x011f, "YPosition" },
+ { 0x0128, "ResolutionUnit" },
+ { 0x0131, "Software" },
+ { 0x0132, "ModifyDate" },
+ { 0xa001, "ColorSpace" },
+ { 0xa002, "ExifImageWidth" },
+ { 0xa003, "ExifImageHeight" },
+ { 0xa20e, "FocalPlaneXResolution" },
+ { 0xa20f, "FocalPlaneYResolution" },
+ { 0xa210, "FocalPlaneResolutionUnit" },
+ /* Renishaw WiRE Custom Tags */
+ { 0xfea0, "WiREPosition" },
+ { 0xfea1, "WiREFoV" },
+ { 0xfea2, "WiREObjective" },
+ { 0xfea3, "WiRELUTLimits" },
+ { 0xfea4, "WiRERotationAngle" },
+ { 0xfea5, "WiRERotationCenter" },
+ { 0xfea6, "WiREZPosition" }
+};
+
+void exif_print_item(FILE *fp, const exif_item_t* item, const char *prefix)
{
- fprintf(stderr, " %04x %-10s %u: ",
- item->tag, EXIF_TYPE_NAMES[item->type], item->count);
+ char name_buf[5] = {0};
+ const char *name = NULL;
+ for (int ndx = 0; ndx < sizeof(tag_names)/sizeof(tag_names[0]); ++ndx)
+ {
+ if (item->tag == tag_names[ndx].tag)
+ {
+ name = tag_names[ndx].name;
+ break;
+ }
+ }
+ if (name == NULL)
+ {
+ sprintf(name_buf, "%04x", item->tag);
+ name = name_buf;
+ }
+
+ fprintf(fp, "%s%s %s[%u] ",
+ prefix == NULL ? "" : prefix,
+ name, EXIF_TYPE_NAMES[item->type], item->count);
if (item->type == EXIF_TYPE_ASCII)
- fprintf(stderr, "'%s'", item->u.strVal);
+ fprintf(fp, "'%s'", item->u.strVal);
else if ((item->type == EXIF_TYPE_UNDEFINED
|| item->type == EXIF_TYPE_BYTE) && item->count > 8)
{
- fprintf(stderr, "[%hu bytes]", item->count);
+ fprintf(fp, "[%hu bytes]", item->count);
}
else
{
{
case EXIF_TYPE_BYTE:
case EXIF_TYPE_UNDEFINED:
- fprintf(stderr, "%02x", item->u.values[n].byteVal);
+ fprintf(fp, "%02x", item->u.values[n].byteVal);
break;
case EXIF_TYPE_SBYTE:
- fprintf(stderr, "%d", item->u.values[n].cVal);
+ fprintf(fp, "%d", item->u.values[n].cVal);
break;
case EXIF_TYPE_SSHORT:
- fprintf(stderr, "%hd", item->u.values[0].hVal);
+ fprintf(fp, "%hd", item->u.values[0].hVal);
break;
case EXIF_TYPE_SHORT:
- fprintf(stderr, "%hu", item->u.values[0].uhVal);
+ fprintf(fp, "%hu", item->u.values[0].uhVal);
break;
case EXIF_TYPE_LONG:
- fprintf(stderr, "%u", item->u.values[0].ulVal);
+ fprintf(fp, "%u", item->u.values[0].ulVal);
break;
case EXIF_TYPE_SLONG:
- fprintf(stderr, "%d", item->u.values[0].lVal);
+ fprintf(fp, "%d", item->u.values[0].lVal);
break;
case EXIF_TYPE_RATIONAL:
- fprintf(stderr, "%u/%u",
+ fprintf(fp, "%u/%u",
item->u.values[n].rationalVal.numerator, item->u.values[n].rationalVal.denominator);
break;
case EXIF_TYPE_SRATIONAL:
- fprintf(stderr, "%d/%d",
+ fprintf(fp, "%d/%d",
item->u.values[n].srationalVal.numerator, item->u.values[n].srationalVal.denominator);
break;
case EXIF_TYPE_FLOAT32:
- fprintf(stderr, "%f", item->u.values[n].fltVal);
+ fprintf(fp, "%f", item->u.values[n].fltVal);
break;
case EXIF_TYPE_FLOAT64:
- fprintf(stderr, "%lf", item->u.values[n].dblVal);
+ fprintf(fp, "%lf", item->u.values[n].dblVal);
break;
case EXIF_TYPE_ASCII:
break;
}
if (n < item->count - 1)
- fprintf(stderr, ", ");
+ fprintf(fp, ", ");
}
}
- fprintf(stderr, "\n");
+ fprintf(fp, "\n");
}
void exif_free(exif_item_t *items)
#define _exif_h_INCLUDE
#include <stdint.h>
+#include <stdio.h>
typedef enum exif_type_t {
EXIF_TYPE_BYTE = 1, // uint8_t
} u;
} exif_item_t;
-void exif_print_item(const exif_item_t* item);
+void exif_print_item(FILE *fp, const exif_item_t* item, const char *prefix);
exif_item_t *exif_parse(const uint8_t *data, size_t datalen);
void exif_free(exif_item_t *items);
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
+#include <stdarg.h>
#include <assert.h>
#include "exif.h"
+#include "jpegrdr.h"
typedef uint16_t marker_t;
return frame;
}
-void jfif_read_app0(FILE *fp, size_t len)
+exif_item_t * jfif_read_app0(FILE *fp, size_t len, logfunc_t log)
{
+ exif_item_t *exif_items = NULL;
char label[6] = {0};
size_t count = fread(label, 1, 5, fp);
if (strncmp("JFIF", label, 4) == 0)
{
jfif_header_t *hdr = jfif_read_header(fp, len - 5);
- fprintf(stderr, " %s version %u.%u density %hu,%hu %s\n",
+ log(" %s version %u.%u density %hu,%hu %s\n",
label, hdr->major_version, hdr->minor_version,
hdr->x_density, hdr->y_density,
hdr->units == 1 ? "dpi" : "???");
else if (strncmp("Exif", label, 4) == 0)
{
uint8_t pad = 0;
- fprintf(stderr, " %s\n", label);
fread(&pad, 1, 1, fp); // read the pad char
// read the EXIF data into a buffer
uint8_t *data = (uint8_t*)calloc(len - 6, 1);
assert(data != NULL);
fread(data, len - 6, 1, fp);
- exif_item_t *items = exif_parse(data, len - 6);
+ exif_items = exif_parse(data, len - 6);
free(data);
-
- // print the items
- for (exif_item_t* item = items; item; item = item->nextPtr)
- exif_print_item(item);
- exif_free(items);
}
else
{
- fprintf(stderr, " %s\n", label);
+ log(" %s\n", label);
fseek(fp, (long)(len - 5), SEEK_CUR);
}
+ return exif_items;
}
+
//
// JFIF images have SOI APP0[JFIF] ...
// EXIF sections use APP0 as well and in JFIF must follow the JFIF segment.
//
-void get_jpeg_exif(FILE *fp)
+exif_item_t *jpegrdr_get_exif(FILE *fp, logfunc_t log)
{
size_t start = ftell(fp);
size_t len = 0;
{
case JFIF_SOI:
len = 0;
- fprintf(stderr, "%08lx SOI\n", ftell(fp));
+ log("%08lx SOI\n", ftell(fp));
break;
case JFIF_SOF0:
{
len = jfif_get_size(fp);
- fprintf(stderr, "%08lx SOF0 %04zx\n", ftell(fp), len);
+ log("%08lx SOF0 %04zx\n", ftell(fp), len);
jfif_frame_t* frame = jfif_read_frame(fp, len);
- fprintf(stderr, " image size %u,%u\n", frame->width, frame->height);
+ log(" image size %u,%u\n", frame->width, frame->height);
free(frame);
len = 0;
break;
}
case JFIF_DQT:
len = jfif_get_size(fp);
- fprintf(stderr, "%08lx DQT %04zx\n", ftell(fp), len);
+ log("%08lx DQT %04zx\n", ftell(fp), len);
break;
case JFIF_DHT:
len = jfif_get_size(fp);
- fprintf(stderr, "%08lx DHT %04zx\n", ftell(fp), len);
+ log("%08lx DHT %04zx\n", ftell(fp), len);
break;
case JFIF_SOS:
len = jfif_get_size(fp);
- fprintf(stderr, "%08lx SOS %04zx\n", ftell(fp), len);
- return;
+ log("%08lx SOS %04zx\n", ftell(fp), len);
+ return NULL;
default:
{
if (JFIF_IS_RST(mark) && JFIF_GET_RST_N(mark) < 8)
{
len = jfif_get_size(fp);
- fprintf(stderr, "%08lx RST%d %04zx\n", ftell(fp), JFIF_GET_RST_N(mark), len);
+ log("%08lx RST%d %04zx\n", ftell(fp), JFIF_GET_RST_N(mark), len);
}
else if (JFIF_IS_APP(mark))
{
len = jfif_get_size(fp);
- fprintf(stderr, "%08lx APP%u %04zx\n", ftell(fp), JFIF_GET_APP_N(mark), len);
- jfif_read_app0(fp, len);
+ log("%08lx APP%u %04zx\n", ftell(fp), JFIF_GET_APP_N(mark), len);
+ exif_item_t *items = jfif_read_app0(fp, len, log);
+ if (items != NULL)
+ return items;
len = 0;
}
else
{
- fprintf(stderr, "OOPS %04x\n", mark);
+ log("OOPS %04x\n", mark);
exit(1);
}
}
}
fseek(fp, (long)len, SEEK_CUR);
}
+ return NULL;
+}
+
+#ifdef JPEGRDR_MAIN
+
+static void _cdecl logger(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
}
int main(int argc, char const * const argv[])
{
FILE *fp = fopen(argv[1], "rb");
- get_jpeg_exif(fp);
+ exif_item_t *items = jpegrdr_get_exif(fp, logger);
+ for (exif_item_t *item = items; item; item = item->nextPtr)
+ exif_print_item(stderr, item, " ");
+ exif_free(items);
fclose(fp);
return 0;
}
+
+#endif
--- /dev/null
+#ifndef _jpegrdr_h_INCLUDE
+#define _jpegrdr_h_INCLUDE
+
+#include <stdio.h>
+#include "exif.h"
+
+typedef void (_cdecl * logfunc_t)(const char *format, ...);
+
+exif_item_t *jpegrdr_get_exif(FILE *fp, logfunc_t log);
+
+#endif /* _jpegrdr_h_INCLUDE */
*/
#include <stdlib.h>
+#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <sys/stat.h>
#include <assert.h>
#include "surfacefile.h"
+#include "exif.h"
+#include "jpegrdr.h"
#ifdef WIN32
#include <direct.h>
#include "compat/tchar.h"
#endif /* !WIN32 */
+static void _cdecl logger(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ //vfprintf(stderr, format, args);
+ va_end(args);
+}
+
static size_t fcopy(FILE *src, FILE *dst, size_t count)
{
char buf[4096];
return total;
}
-// For a single image the table just contains the end of the image.
+// Read a BSTR record from the current file position/.
+// Reads a uint32_t to get the size in bytes
+// Then allocates and returns a Unicode string with terminating NUL
+static wchar_t* read_name(FILE* fp)
+{
+ uint32_t length = 0;
+ fread(&length, sizeof(uint32_t), 1, fp);
+ wchar_t* name = NULL;
+ if (length)
+ {
+ name = (wchar_t*)calloc(1, length + sizeof(wchar_t));
+ fread(name, 1, length, fp);
+ }
+ return name;
+}
+
+// Read the image table and return an array of absolute file position offsets
+// to the start of each image information structure.
+// The final element in the array should point to the end of the final image
+// ie: the end of the file.
static uint32_t * ReadImageTable(SurfaceFileHeader *hdrPtr, FILE *fp)
{
uint32_t *table = NULL;
exit(1);
}
size_t check = fread(table + 1, sizeof(uint32_t), hdrPtr->num_images, fp);
- // set first image to the end of the table.
+ uint32_t table_end = ftell(fp);
+ // read the directory name from after the offset table for rev7+
+ if (hdrPtr->revision > 6)
+ {
+ hdrPtr->dirname = read_name(fp);
+ }
+ uint32_t name_end = ftell(fp);
+ // set first image offset to the current position (after all header info)
table[0] = (long)ftell(fp);
- // convert offsets from relative to table to file absolute positions
+ // The offsets in the table are relative to the end of the table but do not account for the
+ // directory name being inserted at the end.
+ // Convert offsets from relative to table to file absolute positions
for (uint32_t n = 1; n < hdrPtr->num_images + 1; ++n)
- table[n] += table[0];
+ table[n] += table_end;
}
return table;
}
return points;
}
-static int SrfDump(FILE *fp)
+static int SrfDump(const char *filename)
{
+ FILE *fp = fopen(filename, "rb");
+ if (fp == NULL) {
+ perror("fopen");
+ return 1;
+ }
+
int r = 0;
SurfaceFileHeader hdr = {0};
fread(&hdr, sizeof(SurfaceFileHeaderRev0), 1, fp);
hdrsize += sizeof(SurfaceFileHeaderRev4);
if (hdr.revision > 4)
hdrsize += sizeof(SurfaceFileHeaderRev5);
+ if (hdr.revision > 8)
+ hdrsize += sizeof(SurfaceFileHeaderRev9);
fseek(fp, 0, SEEK_SET);
fread(&hdr, hdrsize, 1, fp);
printf("use background removal: %s\n", hdr.use_background_removal ? "true" : "false");
if (hdr.revision > 4)
printf("extrapolation mode: %d\n", (int)hdr.extrapolation_mode);
+ if (hdr.revision > 8)
+ {
+ printf("objective: %.3lf\n", hdr.objective);
+ printf("motor info:\n");
+ printf(" stage min: %g, %g, %g\n",
+ hdr.motor_info.stage_min.x, hdr.motor_info.stage_min.y, hdr.motor_info.stage_min.z);
+ printf(" stage max: %g, %g, %g\n",
+ hdr.motor_info.stage_max.x, hdr.motor_info.stage_max.y, hdr.motor_info.stage_max.z);
+ printf(" reference: %g, %g\n", hdr.motor_info.reference.x, hdr.motor_info.reference.y);
+ printf(" resolution: %g, %g\n", hdr.motor_info.resolution.x, hdr.motor_info.resolution.y);
+ }
SurfacePoint *points = ReadPoints(&hdr, fp);
if (points)
{
+ printf("points:\n");
for (uint32_t n = 0; n < hdr.num_points; ++n)
{
printf(" point %u: %.6g %.6g %.6g\n",
}
uint32_t image_table = ftell(fp);
- printf(" image table: %#08x\n", image_table);
+ printf("image table: %#08x\n", image_table);
uint32_t *offsets = ReadImageTable(&hdr, fp);
- uint32_t table_base = ftell(fp);
+
if (offsets)
{
if (hdr.num_images < 10)
for (uint32_t n = 0; n < hdr.num_images + 1; ++n)
printf(" %u: %#08x\n", n, offsets[n]);
}
- printf(" image base: %#08x\n", table_base);
+#if 0
#ifdef WIN32
_tmkdir(_T("images"));
#else
mkdir("images", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
#endif // !WIN32
+#endif
for (uint32_t n = 0; n < hdr.num_images; ++n)
{
+ SurfaceImageInfo info = { 0 };
+ fseek(fp, offsets[n], SEEK_SET);
+ fread(&info, sizeof(SurfaceImageInfo5), 1, fp);
+ if (hdr.revision >= 8)
+ {
+ SurfaceImageInfo8 *ptr = (SurfaceImageInfo8 *)&info.rotation_angle;
+ fread(ptr, sizeof(SurfaceImageInfo8), 1, fp);
+ }
+ if (hdr.revision >= 9)
+ {
+ SurfaceImageInfo9 *ptr = (SurfaceImageInfo9 *)&info.objective;
+ fread(ptr, sizeof(SurfaceImageInfo9), 1, fp);
+ }
+
+ uint32_t image_size = 0;
+ exif_item_t *items = NULL;
+ if (hdr.revision < 7)
+ {
+ fread(&image_size, sizeof(uint32_t), 1, fp);
+ items = jpegrdr_get_exif(fp, logger);
+ }
+ else
+ {
+ fread(&info.width, sizeof(uint32_t), 2, fp);
+ info.imagepath = read_name(fp);
+ info.backuppath = read_name(fp);
+
+ wchar_t wfilename[260] = {0};
+
+ mbstowcs(wfilename, filename, strlen(filename));
+ wchar_t *ext = wcsrchr(wfilename, L'\\');
+ assert(ext != NULL);
+ ext[1] = L'\0';
+ wcscat(wfilename, hdr.dirname);
+ wcscat(wfilename, L"\\");
+ wcscat(wfilename, info.imagepath);
+ FILE *imagefp = _wfopen(wfilename, L"rb");
+ assert(imagefp != NULL);
+ items = jpegrdr_get_exif(imagefp, logger);
+ fclose(imagefp);
+ }
+
+#if 0
TCHAR name[32 + 16] = {0};
_stprintf(name, _T("images/img%u.jpg"), n);
+
FILE *fp2 = _tfopen(name, "wb");
if (fp2 == NULL) {
_tperror("fopen image file");
exit(1);
}
-
- uint32_t image_section_size = offsets[n + 1] - offsets[n] - sizeof(SurfaceImageInfo);
- SurfaceImageInfo info = { 0 };
- fseek(fp, offsets[n], SEEK_SET);
- fread(&info, sizeof(SurfaceImageInfo), 1, fp);
- size_t len = fcopy(fp, fp2, info.image_size);
+ size_t len = fcopy(fp, fp2, image_size);
fclose(fp2);
// For revision > 2 we have the size of the 'original' image if present and the image data.
if (hdr.revision > 2)
len += sizeof(backup_size) + backup_size; // account for 'backup image' and its size
printf(" orig:%u: %u\n", n, backup_size);
}
-
- printf(" img:%u: %#08x @(%.3f,%.3f,%.3f) fov:%.3f,%.3f res:%u,%u off:%d,%d siz:%#08x\n",
- n, offsets[n],
+#endif
+ printf(" img %u: %u@%#08x @(%.3f,%.3f,%.3f) fov:%.3f,%.3f res:%u,%u off:%d,%d\n",
+ n, image_size, offsets[n],
info.point.x, info.point.y, info.point.z,
info.image_width_microns, info.image_height_microns,
info.resolution_x, info.resolution_y,
- info.xoffset, info.yoffset, info.image_size);
- if ((len - image_section_size) != 0)
+ info.xoffset, info.yoffset);
+ if (hdr.revision >= 7)
+ {
+ char path[256] = { 0 };
+ wcstombs(path, info.imagepath, sizeof(path));
+ printf(" image: %s\n", path);
+ if (info.backuppath != NULL && info.backuppath[0] != L'\0')
+ {
+ wcstombs(path, info.backuppath, sizeof(path));
+ printf(" original: %s\n", path);
+ }
+ }
+ if (items)
{
- printf(" image size error of %zu bytes\n", (len - image_section_size));
+ for (exif_item_t* item = items; item; item = item->nextPtr)
+ {
+ if (!(item->tag == 0x010f || item->tag == 0x010e))
+ exif_print_item(stdout, item, " ");
+ }
+ exif_free(items);
}
+
+ free(info.imagepath);
+ free(info.backuppath);
}
free(offsets);
+ free(hdr.dirname);
}
+ fclose(fp);
return r;
}
-int _tmain(int argc, TCHAR *argv[])
+int main(int argc, char *const argv[])
{
+ // add `-debug` to enable more log output
+ // add `-info` to just read the main header and output csv
+ // add `-export dirname` to output the images for rev < 7 surfaces
if (argc != 2) {
- _fputts(_T("usage: srfdump filename"), stderr);
+ fputs("usage: srfdump filename", stderr);
return 1;
}
- FILE *fp = _tfopen(argv[1], _T("rb"));
- if (fp == NULL) {
- _tperror(_T("fopen"));
- return 1;
- }
-
- int r = SrfDump(fp);
-
- fclose(fp);
+ int r = SrfDump(argv[1]);
return r;
}
*
* Print out some header information from a surface file.
*/
-
+
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
hdrsize += sizeof(SurfaceFileHeaderRev4);
if (hdr.revision > 4)
hdrsize += sizeof(SurfaceFileHeaderRev5);
+ if (hdr.revision > 8)
+ hdrsize += sizeof(SurfaceFileHeaderRev9);
fseek(fp, 0, SEEK_SET);
fread(&hdr, hdrsize, 1, fp);
-
+
char ver[5] = { 0 };
memcpy(ver, &hdr.fileversion, 4);
char path[1024] = { 0 };
double max_y;
} SurfaceExtents;
+typedef struct SurfacePoint2 {
+ double x;
+ double y;
+} SurfacePoint2;
+
typedef struct SurfacePoint {
double x;
double y;
float ztrans;
} SurfaceTranslationCoords;
+typedef struct SurfaceMotorPositionInfo {
+ SurfacePoint stage_min; // minimum position in firmware steps
+ SurfacePoint stage_max; // maximum position in firmware steps
+ SurfacePoint2 reference; // reference position in firmware steps
+ SurfacePoint2 resolution; // motor steps per unit (x and y)
+} SurfaceMotorPositionInfo;
+
typedef struct SurfaceFileHeaderRev0 {
uint32_t fileversion;
uint16_t revision;
uint8_t extrapolation_mode;
} SurfaceFileHeaderRev5;
+typedef struct SurfaceFileHeaderRev7 {
+ wchar_t* dirname;
+} SurfaceFileHeaderRev7;
+
+typedef struct SurfaceFileHeaderRev9 {
+ double objective;
+ struct SurfaceMotorPositionInfo motor_info;
+} SurfaceFileHeaderRev9;
+
typedef struct SurfaceFileHeader {
struct {
uint32_t fileversion;
struct {
uint8_t extrapolation_mode;
};
+ struct {
+ double objective;
+ struct SurfaceMotorPositionInfo motor_info;
+ };
+ struct {
+ wchar_t* dirname;
+ };
} SurfaceFileHeader;
-typedef struct SurfaceImageInfo
+typedef struct SurfaceImageInfo5
{
/// Position of the top left point of the image in microns
/// EXIF custom field 0xFEA0
int xoffset;
/// Vertical offset in pixels (from where?)
int yoffset;
- /// Size of the stored image data in bytes.
- uint32_t image_size;
+} SurfaceImageInfo5;
+
+typedef struct SurfaceImageInfo7 {
+ uint32_t width;
+ uint32_t height;
+ wchar_t *imagepath;
+ wchar_t *backuppath;
+} SurfaceImageInfo7;
+
+typedef struct SurfaceImageInfo8 {
+ /// Rotation angle in degrees
+ double rotationAngle;
+ /// Rotation center in microns
+ SurfacePoint2 rotation_center;
+} SurfaceImageInfo8;
+
+typedef struct SurfaceImageInfo9 {
+ /// Objective magnification
+ double objective;
+} SurfaceImageInfo9;
+
+typedef struct SurfaceImageInfo {
+ struct {
+ struct SurfacePoint point;
+ double image_width_microns;
+ double image_height_microns;
+ uint32_t resolution_x;
+ uint32_t resolution_y;
+ int xoffset;
+ int yoffset;
+ };
+ struct { // rev 8
+ double rotation_angle;
+ SurfacePoint2 rotation_center;
+ };
+ struct { // rev 9
+ double objective;
+ };
+ struct { // rev 7
+ uint32_t width;
+ uint32_t height;
+ wchar_t *imagepath;
+ wchar_t *backuppath;
+ };
} SurfaceImageInfo;
#pragma pack(pop)