SWPCore/POC/PdfToImage/Program.cs

186 lines
5.3 KiB
C#
Raw Normal View History

2026-02-05 16:24:54 +01:00
using Docnet.Core;
using Docnet.Core.Models;
Console.WriteLine("=== PDF til Billede Konverter ===");
Console.WriteLine();
Console.Write("Indtast sti til PDF-fil: ");
string? pdfPath = Console.ReadLine()?.Trim().Trim('"');
if (string.IsNullOrEmpty(pdfPath))
{
Console.WriteLine("Fejl: Ingen fil angivet.");
Console.ReadKey();
return;
}
if (!File.Exists(pdfPath))
{
Console.WriteLine($"Fejl: Filen '{pdfPath}' blev ikke fundet.");
Console.ReadKey();
return;
}
Console.Write("Indtast output-mappe (tryk Enter for samme mappe som PDF): ");
string? outputInput = Console.ReadLine()?.Trim().Trim('"');
string outputFolder = string.IsNullOrEmpty(outputInput)
? Path.GetDirectoryName(pdfPath) ?? "."
: outputInput;
Directory.CreateDirectory(outputFolder);
string fileNameWithoutExt = Path.GetFileNameWithoutExtension(pdfPath);
Console.WriteLine($"Konverterer: {pdfPath}");
using var docReader = DocLib.Instance.GetDocReader(pdfPath, new PageDimensions(1080, 1920));
int pageCount = docReader.GetPageCount();
Console.WriteLine($"Antal sider: {pageCount}");
for (int i = 0; i < pageCount; i++)
{
using var pageReader = docReader.GetPageReader(i);
int width = pageReader.GetPageWidth();
int height = pageReader.GetPageHeight();
byte[] rawBytes = pageReader.GetImage();
string outputPath = Path.Combine(outputFolder, $"{fileNameWithoutExt}_side_{i + 1}.png");
SaveAsPng(rawBytes, width, height, outputPath);
Console.WriteLine($"Gemt: {outputPath}");
}
Console.WriteLine("Konvertering fuldført!");
Console.WriteLine();
Console.WriteLine("Tryk på en tast for at afslutte...");
Console.ReadKey();
static void SaveAsPng(byte[] bgraData, int width, int height, string outputPath)
{
using var fileStream = File.Create(outputPath);
using var bw = new BinaryWriter(fileStream);
// PNG Signature
bw.Write(new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A });
// IHDR chunk
byte[] ihdrData;
using (var ms = new MemoryStream())
{
WriteBigEndianInt(ms, width);
WriteBigEndianInt(ms, height);
ms.WriteByte(8); // bit depth
ms.WriteByte(6); // color type (RGBA)
ms.WriteByte(0); // compression
ms.WriteByte(0); // filter
ms.WriteByte(0); // interlace
ihdrData = ms.ToArray();
}
WriteChunk(bw, "IHDR", ihdrData);
// Byg uncompressed data (filter-byte + RGBA pixels per scanline)
int scanlineSize = 1 + width * 4; // 1 filter byte + RGBA
byte[] uncompressed = new byte[height * scanlineSize];
for (int y = 0; y < height; y++)
{
int rowStart = y * scanlineSize;
uncompressed[rowStart] = 0; // filter type: none
for (int x = 0; x < width; x++)
{
int srcIdx = (y * width + x) * 4;
int dstIdx = rowStart + 1 + x * 4;
// BGRA til RGBA
uncompressed[dstIdx + 0] = bgraData[srcIdx + 2]; // R
uncompressed[dstIdx + 1] = bgraData[srcIdx + 1]; // G
uncompressed[dstIdx + 2] = bgraData[srcIdx + 0]; // B
uncompressed[dstIdx + 3] = bgraData[srcIdx + 3]; // A
}
}
// Komprimer med Deflate
using var compressedStream = new MemoryStream();
using (var deflate = new System.IO.Compression.DeflateStream(compressedStream, System.IO.Compression.CompressionLevel.Fastest, true))
{
deflate.Write(uncompressed);
}
byte[] compressed = compressedStream.ToArray();
// Beregn Adler-32 på uncompressed data
uint adler = Adler32(uncompressed);
// Byg zlib stream: header + compressed + adler32
using var zlibStream = new MemoryStream();
zlibStream.WriteByte(0x78); // CMF
zlibStream.WriteByte(0x01); // FLG
zlibStream.Write(compressed);
WriteBigEndianUInt(zlibStream, adler);
WriteChunk(bw, "IDAT", zlibStream.ToArray());
// IEND chunk
WriteChunk(bw, "IEND", Array.Empty<byte>());
}
static void WriteChunk(BinaryWriter bw, string type, byte[] data)
{
byte[] lengthBytes = BitConverter.GetBytes(data.Length);
if (BitConverter.IsLittleEndian) Array.Reverse(lengthBytes);
bw.Write(lengthBytes);
byte[] typeBytes = System.Text.Encoding.ASCII.GetBytes(type);
bw.Write(typeBytes);
bw.Write(data);
// CRC32
byte[] crcData = new byte[4 + data.Length];
Array.Copy(typeBytes, crcData, 4);
Array.Copy(data, 0, crcData, 4, data.Length);
uint crc = Crc32(crcData);
byte[] crcBytes = BitConverter.GetBytes(crc);
if (BitConverter.IsLittleEndian) Array.Reverse(crcBytes);
bw.Write(crcBytes);
}
static void WriteBigEndianInt(Stream stream, int value)
{
byte[] bytes = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian) Array.Reverse(bytes);
stream.Write(bytes);
}
static void WriteBigEndianUInt(Stream stream, uint value)
{
byte[] bytes = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian) Array.Reverse(bytes);
stream.Write(bytes);
}
static uint Crc32(byte[] data)
{
uint crc = 0xFFFFFFFF;
foreach (byte b in data)
{
crc ^= b;
for (int i = 0; i < 8; i++)
crc = (crc >> 1) ^ (0xEDB88320 & ~((crc & 1) - 1));
}
return ~crc;
}
static uint Adler32(byte[] data)
{
uint a = 1, b = 0;
foreach (byte d in data)
{
a = (a + d) % 65521;
b = (b + a) % 65521;
}
return (b << 16) | a;
}