2
0
Viktor Chlumský 6 жил өмнө
parent
commit
f0b8f556d2

+ 2 - 0
Msdfgen.vcxproj

@@ -305,6 +305,7 @@
     <ClInclude Include="core\rasterization.h" />
     <ClInclude Include="core\render-sdf.h" />
     <ClInclude Include="core\save-bmp.h" />
+    <ClInclude Include="core\save-tiff.h" />
     <ClInclude Include="core\Scanline.h" />
     <ClInclude Include="core\shape-description.h" />
     <ClInclude Include="core\Shape.h" />
@@ -328,6 +329,7 @@
     <ClCompile Include="core\rasterization.cpp" />
     <ClCompile Include="core\render-sdf.cpp" />
     <ClCompile Include="core\save-bmp.cpp" />
+    <ClCompile Include="core\save-tiff.cpp" />
     <ClCompile Include="core\Scanline.cpp" />
     <ClCompile Include="core\shape-description.cpp" />
     <ClCompile Include="core\Shape.cpp" />

+ 6 - 0
Msdfgen.vcxproj.filters

@@ -99,6 +99,9 @@
     <ClInclude Include="core\pixel-conversion.hpp">
       <Filter>Core</Filter>
     </ClInclude>
+    <ClInclude Include="core\save-tiff.h">
+      <Filter>Core</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="main.cpp">
@@ -167,6 +170,9 @@
     <ClCompile Include="core\rasterization.cpp">
       <Filter>Core</Filter>
     </ClCompile>
+    <ClCompile Include="core\save-tiff.cpp">
+      <Filter>Core</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="Msdfgen.rc">

+ 192 - 0
core/save-tiff.cpp

@@ -0,0 +1,192 @@
+
+#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;
+}
+
+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 == 3)
+        writeValue<uint32_t>(file, 0x00c2u); // Offset of 32, 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, channels == 3 ? 0x00f6u : 0x00d2u); // 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, channels == 3 ? 0x00c8u : 0x00c2u); // 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
+    // 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 == 3)
+        writeValue<uint32_t>(file, 0x00d8u); // Offset of 3, 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 == 3)
+        writeValue<uint32_t>(file, 0x00deu); // Offset of 0.f, 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
+    else
+        writeValue<float>(file, 1.f);
+    // Offset = 0x00be
+
+    writeValue<uint32_t>(file, 0);
+
+    if (channels == 3) {
+        // 0x00c2 BitsPerSample data
+        writeValue<uint16_t>(file, 32);
+        writeValue<uint16_t>(file, 32);
+        writeValue<uint16_t>(file, 32);
+        // 0x00c8 XResolution data
+        writeValue<uint32_t>(file, 300);
+        writeValue<uint32_t>(file, 1);
+        // 0x00d0 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
+    } 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;
+}
+
+bool saveTiff(const BitmapConstRef<float, 1> &bitmap, const char *filename) {
+    FILE *file = fopen(filename, "wb");
+    if (!file)
+        return false;
+    writeTiffHeader(file, bitmap.width, bitmap.height, 1);
+    for (int y = bitmap.height-1; y >= 0; --y)
+        fwrite(bitmap(0, y), sizeof(float), bitmap.width, file);
+    return !fclose(file);
+}
+
+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);
+}
+
+}

+ 12 - 0
core/save-tiff.h

@@ -0,0 +1,12 @@
+
+#pragma once
+
+#include "BitmapRef.hpp"
+
+namespace msdfgen {
+
+/// Saves the bitmap as an uncompressed floating-point TIFF file.
+bool saveTiff(const BitmapConstRef<float, 1> &bitmap, const char *filename);
+bool saveTiff(const BitmapConstRef<float, 3> &bitmap, const char *filename);
+
+}

+ 5 - 1
main.cpp

@@ -28,6 +28,7 @@ enum Format {
     AUTO,
     PNG,
     BMP,
+    TIFF,
     TEXT,
     TEXT_FLOAT,
     BINARY,
@@ -203,6 +204,7 @@ static const char * writeOutput(const BitmapConstRef<float, N> &bitmap, const ch
         if (format == AUTO) {
             if (cmpExtension(filename, ".png")) format = PNG;
             else if (cmpExtension(filename, ".bmp")) format = BMP;
+            else if (cmpExtension(filename, ".tif") || cmpExtension(filename, ".tiff")) format = TIFF;
             else if (cmpExtension(filename, ".txt")) format = TEXT;
             else if (cmpExtension(filename, ".bin")) format = BINARY;
             else
@@ -211,6 +213,7 @@ static const char * writeOutput(const BitmapConstRef<float, N> &bitmap, const ch
         switch (format) {
             case PNG: return savePng(bitmap, filename) ? NULL : "Failed to write output PNG image.";
             case BMP: return saveBmp(bitmap, filename) ? NULL : "Failed to write output BMP image.";
+            case TIFF: return saveTiff(bitmap, filename) ? NULL : "Failed to write output BMP image.";
             case TEXT: case TEXT_FLOAT: {
                 FILE *file = fopen(filename, "w");
                 if (!file) return "Failed to write output text file.";
@@ -289,7 +292,7 @@ static const char *helpText =
         "\tSaves the shape description into a text file that can be edited and loaded using -shapedesc.\n"
     "  -fillrule <nonzero / evenodd / positive / negative>\n"
         "\tSets the fill rule for the scanline pass. Default is nonzero.\n"
-    "  -format <png / bmp / text / textfloat / bin / binfloat / binfloatbe>\n"
+    "  -format <png / bmp / tiff / text / textfloat / bin / binfloat / binfloatbe>\n"
         "\tSpecifies the output format of the distance field. Otherwise it is chosen based on output file extension.\n"
     "  -guessorder\n"
         "\tAttempts to detect if shape contours have the wrong winding and generates the SDF with the right one.\n"
@@ -477,6 +480,7 @@ int main(int argc, const char * const *argv) {
             if (!strcmp(argv[argPos+1], "auto")) format = AUTO;
             else if (!strcmp(argv[argPos+1], "png")) SET_FORMAT(PNG, "png");
             else if (!strcmp(argv[argPos+1], "bmp")) SET_FORMAT(BMP, "bmp");
+            else if (!strcmp(argv[argPos+1], "tiff")) SET_FORMAT(TIFF, "tif");
             else if (!strcmp(argv[argPos+1], "text") || !strcmp(argv[argPos+1], "txt")) SET_FORMAT(TEXT, "txt");
             else if (!strcmp(argv[argPos+1], "textfloat") || !strcmp(argv[argPos+1], "txtfloat")) SET_FORMAT(TEXT_FLOAT, "txt");
             else if (!strcmp(argv[argPos+1], "bin") || !strcmp(argv[argPos+1], "binary")) SET_FORMAT(BINARY, "bin");

+ 1 - 0
msdfgen.h

@@ -24,6 +24,7 @@
 #include "core/render-sdf.h"
 #include "core/rasterization.h"
 #include "core/save-bmp.h"
+#include "core/save-tiff.h"
 #include "core/shape-description.h"
 
 #define MSDFGEN_VERSION "1.6"