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\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" />
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
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");
|
||||
|
|
|
|||
Loading…
Reference in New Issue