|
@@ -20,6 +20,11 @@ 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__
|
|
@@ -47,8 +52,8 @@ static bool writeTiffHeader(FILE *file, int width, int height, int channels) {
|
|
|
writeValue<uint16_t>(file, 0x0102u);
|
|
|
writeValue<uint16_t>(file, 0x0003u);
|
|
|
writeValue<uint32_t>(file, channels);
|
|
|
- if (channels == 3)
|
|
|
- writeValue<uint32_t>(file, 0x00c2u); // Offset of 32, 32, 32
|
|
|
+ if (channels > 1)
|
|
|
+ writeValue<uint32_t>(file, 0x00c2u); // Offset of 32, 32, ...
|
|
|
else {
|
|
|
writeValue<uint16_t>(file, 32);
|
|
|
writeValue<uint16_t>(file, 0);
|
|
@@ -63,13 +68,13 @@ static bool writeTiffHeader(FILE *file, int width, int height, int channels) {
|
|
|
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, 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, channels == 3 ? 0x00f6u : 0x00d2u); // Offset of pixel data
|
|
|
+ writeValue<uint32_t>(file, 0x00d2u+(channels > 1)*channels*12); // Offset of pixel data
|
|
|
// SamplesPerPixel
|
|
|
writeValue<uint16_t>(file, 0x0115u);
|
|
|
writeValue<uint16_t>(file, 0x0003u);
|
|
@@ -90,12 +95,12 @@ static bool writeTiffHeader(FILE *file, int width, int height, int channels) {
|
|
|
writeValue<uint16_t>(file, 0x011au);
|
|
|
writeValue<uint16_t>(file, 0x0005u);
|
|
|
writeValue<uint32_t>(file, 1);
|
|
|
- writeValue<uint32_t>(file, channels == 3 ? 0x00c8u : 0x00c2u); // Offset of 300, 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, channels == 3 ? 0x00d0u : 0x00cau); // Offset of 300, 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);
|
|
@@ -106,8 +111,8 @@ static bool writeTiffHeader(FILE *file, int width, int height, int channels) {
|
|
|
writeValue<uint16_t>(file, 0x0153u);
|
|
|
writeValue<uint16_t>(file, 0x0003u);
|
|
|
writeValue<uint32_t>(file, channels);
|
|
|
- if (channels == 3)
|
|
|
- writeValue<uint32_t>(file, 0x00d8u); // Offset of 3, 3, 3
|
|
|
+ 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);
|
|
@@ -116,46 +121,38 @@ static bool writeTiffHeader(FILE *file, int width, int height, int channels) {
|
|
|
writeValue<uint16_t>(file, 0x0154u);
|
|
|
writeValue<uint16_t>(file, 0x000bu);
|
|
|
writeValue<uint32_t>(file, channels);
|
|
|
- if (channels == 3)
|
|
|
- writeValue<uint32_t>(file, 0x00deu); // Offset of 0.f, 0.f, 0.f
|
|
|
+ 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 == 3)
|
|
|
- writeValue<uint32_t>(file, 0x00eau); // Offset of 1.f, 1.f, 1.f
|
|
|
+ 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 == 3) {
|
|
|
+ if (channels > 1) {
|
|
|
// 0x00c2 BitsPerSample data
|
|
|
- writeValue<uint16_t>(file, 32);
|
|
|
- writeValue<uint16_t>(file, 32);
|
|
|
- writeValue<uint16_t>(file, 32);
|
|
|
- // 0x00c8 XResolution data
|
|
|
+ writeValueRepeated<uint16_t>(file, 32, channels);
|
|
|
+ // 0x00c2 + 2*N XResolution data
|
|
|
writeValue<uint32_t>(file, 300);
|
|
|
writeValue<uint32_t>(file, 1);
|
|
|
- // 0x00d0 YResolution data
|
|
|
+ // 0x00ca + 2*N YResolution data
|
|
|
writeValue<uint32_t>(file, 300);
|
|
|
writeValue<uint32_t>(file, 1);
|
|
|
- // 0x00d8 SampleFormat data
|
|
|
- writeValue<uint16_t>(file, 3);
|
|
|
- writeValue<uint16_t>(file, 3);
|
|
|
- writeValue<uint16_t>(file, 3);
|
|
|
- // 0x00de SMinSampleValue data
|
|
|
- writeValue<float>(file, 0.f);
|
|
|
- writeValue<float>(file, 0.f);
|
|
|
- writeValue<float>(file, 0.f);
|
|
|
- // 0x00ea SMaxSampleValue data
|
|
|
- writeValue<float>(file, 1.f);
|
|
|
- writeValue<float>(file, 1.f);
|
|
|
- writeValue<float>(file, 1.f);
|
|
|
- // Offset = 0x00f6
|
|
|
+ // 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);
|
|
@@ -169,24 +166,25 @@ static bool writeTiffHeader(FILE *file, int width, int height, int channels) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-bool saveTiff(const BitmapConstRef<float, 1> &bitmap, const char *filename) {
|
|
|
+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, 1);
|
|
|
+ writeTiffHeader(file, bitmap.width, bitmap.height, N);
|
|
|
for (int y = bitmap.height-1; y >= 0; --y)
|
|
|
- fwrite(bitmap(0, y), sizeof(float), bitmap.width, file);
|
|
|
+ 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) {
|
|
|
- FILE *file = fopen(filename, "wb");
|
|
|
- if (!file)
|
|
|
- return false;
|
|
|
- writeTiffHeader(file, bitmap.width, bitmap.height, 3);
|
|
|
- for (int y = bitmap.height-1; y >= 0; --y)
|
|
|
- fwrite(bitmap(0, y), sizeof(float), 3*bitmap.width, file);
|
|
|
- return !fclose(file);
|
|
|
+ return saveTiffFloat(bitmap, filename);
|
|
|
+}
|
|
|
+bool saveTiff(const BitmapConstRef<float, 4> &bitmap, const char *filename) {
|
|
|
+ return saveTiffFloat(bitmap, filename);
|
|
|
}
|
|
|
|
|
|
}
|