#include "matlab.h" #include #include #include #include // The .MAT file header (see // www.mathworks.com/access/helpdesk/help/pdf_doc/matlab/matfile_format.pdf). struct header { char text[116]; uint32 subsys_offset; uint32 subsys_offset_2; uint16 version; uint16 endian; } __attribute__((packed)); struct data { uint32 type; uint32 size; }; #define miINT8 1 #define miUINT8 2 #define miINT16 3 #define miUINT16 4 #define miINT32 5 #define miUINT32 6 #define miSINGLE 7 #define miMATRIX 14 // Pad to 64 bits void pad(FILE * out) { unsigned long now = ftell(out); if (now % 8 != 0) { now += 8; now -= now % 8; fseek(out, now, SEEK_SET); } } // Write a u32. Error if failed void write_u32(FILE * out, uint32 data) { if (fwrite(&data, 4, 1, out) != 1) error("write failed"); } void write_str(FILE * out, const char * data) { while (*data) { if (fwrite(data, 1, 1, out) != 1) error("write failed"); data++; } fwrite(data, 1, 1, out); } // Go back to a location and fill in the size field void fill_size(FILE * out, unsigned long pos) { uint32 data; unsigned long now = ftell(out); fseek(out, pos - 4, SEEK_SET); data = now - pos; if (fwrite(&data, 4, 1, out) != 1) error("write failed"); fseek(out, 0, SEEK_END); } // Fill in a header, returning a position to be passed to fill_size unsigned long write_header(FILE * out, uint32 type) { pad(out); write_u32(out, type); write_u32(out, 0); return ftell(out); } // Write floating-point data out to a .MAT file as an array // width x height x 3. The samples are grouped per pixel. void writeFile(float * data, uint32 width, uint32 height, const char * name, const char * input, const char * varname) { struct header head; unsigned long matrix_start; unsigned long other_start; uint32 i, j, k, idx; float * rearr_data = _TIFFmalloc(width * height * 3 * sizeof(float)); FILE * out = fopen(name, "wb"); memset(&head, ' ', sizeof(head)); if (rearr_data == NULL) error("out of memory"); if (out == NULL) error("couldn\'t open output file"); sprintf(head.text, "MATLAB 5.0 MAT-file, written by tiff2mat: %ux%ux3 floating-point data from %s\n", (unsigned)width, (unsigned)height, input); head.version = 0x100; head.endian = 0x4D49; //head.subsys_offset = 0; //head.subsys_offset_2 = 0; if (fwrite(&head, sizeof(head), 1, out) != 1) error("write failed"); // Write out the matrix information... matrix_start = write_header(out, miMATRIX); // Single-precision array other_start = write_header(out, miUINT32); write_u32(out, 0x07); write_u32(out, 0); fill_size(out, other_start); // Dimensions are height x width x 3 other_start = write_header(out, miINT32); write_u32(out, height); write_u32(out, width); write_u32(out, 3); fill_size(out, other_start); // The array name other_start = write_header(out, miINT8); write_str(out, varname); fill_size(out, other_start); // Now comes the data... // It has to be stored in reverse order, so flip everything around idx = 0; for (i = 0; i < 3; i++) for (j = 0; j < width; j++) for (k = 0; k < height; k++) { rearr_data[idx] = data[i + j * 3 + k * 3 * width]; idx++; } other_start = write_header(out, miSINGLE); if (fwrite(rearr_data, width * height * 3 * sizeof(float), 1, out) != 1) error("write error"); fill_size(out, other_start); // Fix the matrix size pad(out); fill_size(out, matrix_start); fclose(out); free(rearr_data); }