123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- #define _CRT_SECURE_NO_WARNINGS
- #include "save-tiff.h"
- #include <cstdio>
- #ifdef MSDFGEN_USE_CPP11
- #include <cstdint>
- #else
- typedef int int32_t;
- typedef unsigned uint32_t;
- typedef unsigned short uint16_t;
- typedef unsigned char uint8_t;
- #endif
- namespace msdfgen {
- template <typename T>
- static bool writeValue(FILE *file, T value) {
- return fwrite(&value, sizeof(T), 1, file) == 1;
- }
- template <typename T>
- static void writeValueRepeated(FILE *file, T value, int times) {
- for (int i = 0; i < times; ++i)
- writeValue(file, value);
- }
- static bool writeTiffHeader(FILE *file, int width, int height, int channels) {
- #ifdef __BIG_ENDIAN__
- writeValue<uint16_t>(file, 0x4d4du);
- #else
- writeValue<uint16_t>(file, 0x4949u);
- #endif
- writeValue<uint16_t>(file, 42);
- writeValue<uint32_t>(file, 0x0008u); // Offset of first IFD
- // Offset = 0x0008
- writeValue<uint16_t>(file, 15); // Number of IFD entries
- // ImageWidth
- writeValue<uint16_t>(file, 0x0100u);
- writeValue<uint16_t>(file, 0x0004u);
- writeValue<uint32_t>(file, 1);
- writeValue<int32_t>(file, width);
- // ImageLength
- writeValue<uint16_t>(file, 0x0101u);
- writeValue<uint16_t>(file, 0x0004u);
- writeValue<uint32_t>(file, 1);
- writeValue<int32_t>(file, height);
- // BitsPerSample
- writeValue<uint16_t>(file, 0x0102u);
- writeValue<uint16_t>(file, 0x0003u);
- writeValue<uint32_t>(file, channels);
- if (channels > 1)
- writeValue<uint32_t>(file, 0x00c2u); // Offset of 32, 32, ...
- else {
- writeValue<uint16_t>(file, 32);
- writeValue<uint16_t>(file, 0);
- }
- // Compression
- writeValue<uint16_t>(file, 0x0103u);
- writeValue<uint16_t>(file, 0x0003u);
- writeValue<uint32_t>(file, 1);
- writeValue<uint16_t>(file, 1);
- writeValue<uint16_t>(file, 0);
- // PhotometricInterpretation
- writeValue<uint16_t>(file, 0x0106u);
- writeValue<uint16_t>(file, 0x0003u);
- writeValue<uint32_t>(file, 1);
- writeValue<uint16_t>(file, channels >= 3 ? 2 : 1);
- writeValue<uint16_t>(file, 0);
- // StripOffsets
- writeValue<uint16_t>(file, 0x0111u);
- writeValue<uint16_t>(file, 0x0004u);
- writeValue<uint32_t>(file, 1);
- writeValue<uint32_t>(file, 0x00d2u+(channels > 1)*channels*12); // Offset of pixel data
- // SamplesPerPixel
- writeValue<uint16_t>(file, 0x0115u);
- writeValue<uint16_t>(file, 0x0003u);
- writeValue<uint32_t>(file, 1);
- writeValue<uint16_t>(file, channels);
- writeValue<uint16_t>(file, 0);
- // RowsPerStrip
- writeValue<uint16_t>(file, 0x0116u);
- writeValue<uint16_t>(file, 0x0004u);
- writeValue<uint32_t>(file, 1);
- writeValue<int32_t>(file, height);
- // StripByteCounts
- writeValue<uint16_t>(file, 0x0117u);
- writeValue<uint16_t>(file, 0x0004u);
- writeValue<uint32_t>(file, 1);
- writeValue<int32_t>(file, sizeof(float)*channels*width*height);
- // XResolution
- writeValue<uint16_t>(file, 0x011au);
- writeValue<uint16_t>(file, 0x0005u);
- writeValue<uint32_t>(file, 1);
- writeValue<uint32_t>(file, 0x00c2u+(channels > 1)*channels*2); // Offset of 300, 1
- // YResolution
- writeValue<uint16_t>(file, 0x011bu);
- writeValue<uint16_t>(file, 0x0005u);
- writeValue<uint32_t>(file, 1);
- writeValue<uint32_t>(file, 0x00cau+(channels > 1)*channels*2); // Offset of 300, 1
- // ResolutionUnit
- writeValue<uint16_t>(file, 0x0128u);
- writeValue<uint16_t>(file, 0x0003u);
- writeValue<uint32_t>(file, 1);
- writeValue<uint16_t>(file, 2);
- writeValue<uint16_t>(file, 0);
- // SampleFormat
- writeValue<uint16_t>(file, 0x0153u);
- writeValue<uint16_t>(file, 0x0003u);
- writeValue<uint32_t>(file, channels);
- if (channels > 1)
- writeValue<uint32_t>(file, 0x00d2u+channels*2); // Offset of 3, 3, ...
- else {
- writeValue<uint16_t>(file, 3);
- writeValue<uint16_t>(file, 0);
- }
- // SMinSampleValue
- writeValue<uint16_t>(file, 0x0154u);
- writeValue<uint16_t>(file, 0x000bu);
- writeValue<uint32_t>(file, channels);
- if (channels > 1)
- writeValue<uint32_t>(file, 0x00d2u+channels*4); // Offset of 0.f, 0.f, ...
- else
- writeValue<float>(file, 0.f);
- // SMaxSampleValue
- writeValue<uint16_t>(file, 0x0155u);
- writeValue<uint16_t>(file, 0x000bu);
- writeValue<uint32_t>(file, channels);
- if (channels > 1)
- writeValue<uint32_t>(file, 0x00d2u+channels*8); // Offset of 1.f, 1.f, ...
- else
- writeValue<float>(file, 1.f);
- // Offset = 0x00be
- writeValue<uint32_t>(file, 0);
- if (channels > 1) {
- // 0x00c2 BitsPerSample data
- writeValueRepeated<uint16_t>(file, 32, channels);
- // 0x00c2 + 2*N XResolution data
- writeValue<uint32_t>(file, 300);
- writeValue<uint32_t>(file, 1);
- // 0x00ca + 2*N YResolution data
- writeValue<uint32_t>(file, 300);
- writeValue<uint32_t>(file, 1);
- // 0x00d2 + 2*N SampleFormat data
- writeValueRepeated<uint16_t>(file, 3, channels);
- // 0x00d2 + 4*N SMinSampleValue data
- writeValueRepeated<float>(file, 0.f, channels);
- // 0x00d2 + 8*N SMaxSampleValue data
- writeValueRepeated<float>(file, 1.f, channels);
- // Offset = 0x00d2 + 12*N
- } else {
- // 0x00c2 XResolution data
- writeValue<uint32_t>(file, 300);
- writeValue<uint32_t>(file, 1);
- // 0x00ca YResolution data
- writeValue<uint32_t>(file, 300);
- writeValue<uint32_t>(file, 1);
- // Offset = 0x00d2
- }
- return true;
- }
- template <int N>
- bool saveTiffFloat(const BitmapConstRef<float, N> &bitmap, const char *filename) {
- FILE *file = fopen(filename, "wb");
- if (!file)
- return false;
- writeTiffHeader(file, bitmap.width, bitmap.height, N);
- for (int y = bitmap.height-1; y >= 0; --y)
- fwrite(bitmap(0, y), sizeof(float), N*bitmap.width, file);
- return !fclose(file);
- }
- bool saveTiff(const BitmapConstRef<float, 1> &bitmap, const char *filename) {
- return saveTiffFloat(bitmap, filename);
- }
- bool saveTiff(const BitmapConstRef<float, 3> &bitmap, const char *filename) {
- return saveTiffFloat(bitmap, filename);
- }
- bool saveTiff(const BitmapConstRef<float, 4> &bitmap, const char *filename) {
- return saveTiffFloat(bitmap, filename);
- }
- }
|