mirror of https://github.com/Chlumsky/msdfgen.git
TIFF file support
This commit is contained in:
parent
997e42f734
commit
f0b8f556d2
|
|
@ -305,6 +305,7 @@
|
||||||
<ClInclude Include="core\rasterization.h" />
|
<ClInclude Include="core\rasterization.h" />
|
||||||
<ClInclude Include="core\render-sdf.h" />
|
<ClInclude Include="core\render-sdf.h" />
|
||||||
<ClInclude Include="core\save-bmp.h" />
|
<ClInclude Include="core\save-bmp.h" />
|
||||||
|
<ClInclude Include="core\save-tiff.h" />
|
||||||
<ClInclude Include="core\Scanline.h" />
|
<ClInclude Include="core\Scanline.h" />
|
||||||
<ClInclude Include="core\shape-description.h" />
|
<ClInclude Include="core\shape-description.h" />
|
||||||
<ClInclude Include="core\Shape.h" />
|
<ClInclude Include="core\Shape.h" />
|
||||||
|
|
@ -328,6 +329,7 @@
|
||||||
<ClCompile Include="core\rasterization.cpp" />
|
<ClCompile Include="core\rasterization.cpp" />
|
||||||
<ClCompile Include="core\render-sdf.cpp" />
|
<ClCompile Include="core\render-sdf.cpp" />
|
||||||
<ClCompile Include="core\save-bmp.cpp" />
|
<ClCompile Include="core\save-bmp.cpp" />
|
||||||
|
<ClCompile Include="core\save-tiff.cpp" />
|
||||||
<ClCompile Include="core\Scanline.cpp" />
|
<ClCompile Include="core\Scanline.cpp" />
|
||||||
<ClCompile Include="core\shape-description.cpp" />
|
<ClCompile Include="core\shape-description.cpp" />
|
||||||
<ClCompile Include="core\Shape.cpp" />
|
<ClCompile Include="core\Shape.cpp" />
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,9 @@
|
||||||
<ClInclude Include="core\pixel-conversion.hpp">
|
<ClInclude Include="core\pixel-conversion.hpp">
|
||||||
<Filter>Core</Filter>
|
<Filter>Core</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="core\save-tiff.h">
|
||||||
|
<Filter>Core</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="main.cpp">
|
<ClCompile Include="main.cpp">
|
||||||
|
|
@ -167,6 +170,9 @@
|
||||||
<ClCompile Include="core\rasterization.cpp">
|
<ClCompile Include="core\rasterization.cpp">
|
||||||
<Filter>Core</Filter>
|
<Filter>Core</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="core\save-tiff.cpp">
|
||||||
|
<Filter>Core</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="Msdfgen.rc">
|
<ResourceCompile Include="Msdfgen.rc">
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
6
main.cpp
6
main.cpp
|
|
@ -28,6 +28,7 @@ enum Format {
|
||||||
AUTO,
|
AUTO,
|
||||||
PNG,
|
PNG,
|
||||||
BMP,
|
BMP,
|
||||||
|
TIFF,
|
||||||
TEXT,
|
TEXT,
|
||||||
TEXT_FLOAT,
|
TEXT_FLOAT,
|
||||||
BINARY,
|
BINARY,
|
||||||
|
|
@ -203,6 +204,7 @@ static const char * writeOutput(const BitmapConstRef<float, N> &bitmap, const ch
|
||||||
if (format == AUTO) {
|
if (format == AUTO) {
|
||||||
if (cmpExtension(filename, ".png")) format = PNG;
|
if (cmpExtension(filename, ".png")) format = PNG;
|
||||||
else if (cmpExtension(filename, ".bmp")) format = BMP;
|
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, ".txt")) format = TEXT;
|
||||||
else if (cmpExtension(filename, ".bin")) format = BINARY;
|
else if (cmpExtension(filename, ".bin")) format = BINARY;
|
||||||
else
|
else
|
||||||
|
|
@ -211,6 +213,7 @@ static const char * writeOutput(const BitmapConstRef<float, N> &bitmap, const ch
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case PNG: return savePng(bitmap, filename) ? NULL : "Failed to write output PNG image.";
|
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 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: {
|
case TEXT: case TEXT_FLOAT: {
|
||||||
FILE *file = fopen(filename, "w");
|
FILE *file = fopen(filename, "w");
|
||||||
if (!file) return "Failed to write output text file.";
|
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"
|
"\tSaves the shape description into a text file that can be edited and loaded using -shapedesc.\n"
|
||||||
" -fillrule <nonzero / evenodd / positive / negative>\n"
|
" -fillrule <nonzero / evenodd / positive / negative>\n"
|
||||||
"\tSets the fill rule for the scanline pass. Default is nonzero.\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"
|
"\tSpecifies the output format of the distance field. Otherwise it is chosen based on output file extension.\n"
|
||||||
" -guessorder\n"
|
" -guessorder\n"
|
||||||
"\tAttempts to detect if shape contours have the wrong winding and generates the SDF with the right one.\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;
|
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], "png")) SET_FORMAT(PNG, "png");
|
||||||
else if (!strcmp(argv[argPos+1], "bmp")) SET_FORMAT(BMP, "bmp");
|
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], "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], "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");
|
else if (!strcmp(argv[argPos+1], "bin") || !strcmp(argv[argPos+1], "binary")) SET_FORMAT(BINARY, "bin");
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "core/render-sdf.h"
|
#include "core/render-sdf.h"
|
||||||
#include "core/rasterization.h"
|
#include "core/rasterization.h"
|
||||||
#include "core/save-bmp.h"
|
#include "core/save-bmp.h"
|
||||||
|
#include "core/save-tiff.h"
|
||||||
#include "core/shape-description.h"
|
#include "core/shape-description.h"
|
||||||
|
|
||||||
#define MSDFGEN_VERSION "1.6"
|
#define MSDFGEN_VERSION "1.6"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue