diff --git a/BlastIMG/BlastIMG.csproj b/BlastIMG/BlastIMG.csproj
new file mode 100644
index 0000000..c79f317
--- /dev/null
+++ b/BlastIMG/BlastIMG.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/BlastIMG/BlastImage.cs b/BlastIMG/BlastImage.cs
new file mode 100644
index 0000000..700a27f
--- /dev/null
+++ b/BlastIMG/BlastImage.cs
@@ -0,0 +1,41 @@
+namespace BlastIMG;
+
+public enum FileFormat
+{
+ BMP,
+ PNG,
+ JPEG,
+ QOI
+}
+
+public class Pixel
+{
+ public int X { get; }
+ public int Y { get; }
+ public byte R { get; }
+ public byte G { get; }
+ public byte B { get; }
+ public byte A { get; }
+}
+
+public class Image
+{
+ public FileFormat Format { get; }
+ public int Width { get; }
+ public int Height { get; }
+ public Pixel[,] Pixels { get; }
+
+ public Pixel GetPixel(int x, int y)
+ {
+ return Pixels[x, y];
+ }
+
+ public static Image Load(string imagePath)
+ {
+ if (string.IsNullOrWhiteSpace(imagePath))
+ throw new ArgumentException("Image path cannot be null or whitespace.", nameof(imagePath));
+
+
+ return new Image();
+ }
+}
\ No newline at end of file
diff --git a/BlastIMG/ImageLoaders/BmpLoader.cs b/BlastIMG/ImageLoaders/BmpLoader.cs
new file mode 100644
index 0000000..67ca951
--- /dev/null
+++ b/BlastIMG/ImageLoaders/BmpLoader.cs
@@ -0,0 +1,117 @@
+using System.Text;
+using System.Text.Json.Serialization;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using JsonConverter = Newtonsoft.Json.JsonConverter;
+
+namespace BlastIMG.ImageLoaders;
+
+enum CompressionMethod
+{
+ BI_RGB, // 0
+ BI_RLE8, // 1
+ BI_RLE4, // 2
+ BI_BITFIELDS, // 3
+ BI_JPEG, // 4
+ BI_PNG, // 5
+ BI_ALPHABITFIELDS, // 6
+ BI_CMYK, // 11
+ BI_CMYKRLE8, // 12
+ BI_CMYKRLE4, // 13
+}
+
+class BitmapFileHeader
+{
+ public string MagicNumber { get; set; }
+ public int FileSize { get; set; }
+ // there are 4 bytes that are set by the program that creates the image but we probably don't need it
+ public int PixelArrayOffset { get; set; }
+}
+
+class BitmapInfoHeader
+{
+ public int HeaderSize { get; set; }
+ public int BitmapWidth { get; set; }
+ public int BitmapHeight { get; set; }
+ public short ColorPlanes { get; set; } // must be 1
+ public short BitsPerPixel { get; set; }
+ public CompressionMethod CompressionMethod { get; set; }
+ public int RawImageSize { get; set; } // can be set to 0
+ public int HorizontalResolution { get; set; } // ppm
+ public int VerticalResolution { get; set; } // ppm
+ public int ColorPalette { get; set; } // 0 for all
+ public int ImportantColors { get; set; }
+}
+
+public static class BmpLoader
+{
+ public static Image Load(string filepath)
+ {
+ using var imageFile = File.OpenRead(filepath);
+
+ var fileHeader = imageFile.ReadBytes(0, 14);
+ var parsedFileHeader = new BitmapFileHeader
+ {
+ MagicNumber = Encoding.Default.GetString(fileHeader[..2]),
+ FileSize = BitConverter.ToInt32(fileHeader[2..6]),
+ PixelArrayOffset = BitConverter.ToInt32(fileHeader[10..14])
+ };
+
+ var headerSize = BitConverter.ToInt32(imageFile.ReadBytes(14, 4));
+ var dibHeader = imageFile.ReadBytes(14, headerSize);
+ // TODO pull more of the header data here if the header isn't the default header
+ var parsedDibHeader = new BitmapInfoHeader
+ {
+ HeaderSize = headerSize,
+ BitmapWidth = BitConverter.ToInt32(dibHeader[4..8]),
+ BitmapHeight = BitConverter.ToInt32(dibHeader[8..12]),
+ ColorPlanes = BitConverter.ToInt16(dibHeader[12..14]),
+ BitsPerPixel = BitConverter.ToInt16(dibHeader[14..16]),
+ CompressionMethod = BitConverter.ToInt32(dibHeader[16..20]).GetCompressionMethod(),
+ RawImageSize = BitConverter.ToInt32(dibHeader[20..24]),
+ HorizontalResolution = BitConverter.ToInt32(dibHeader[24..28]),
+ VerticalResolution = BitConverter.ToInt32(dibHeader[28..32]),
+ ColorPalette = BitConverter.ToInt32(dibHeader[32..36]),
+ ImportantColors = BitConverter.ToInt32(dibHeader[36..40]),
+ };
+
+ Console.Out.WriteLine($"{parsedFileHeader.MagicNumber}");
+ Console.Out.WriteLine($"{parsedFileHeader.FileSize}");
+ Console.Out.WriteLine($"{parsedFileHeader.PixelArrayOffset}");
+ Console.Out.WriteLine($"Width: {parsedDibHeader.BitmapWidth}");
+ Console.Out.WriteLine($"Height: {parsedDibHeader.BitmapHeight}");
+ Console.Out.WriteLine(JsonConvert.SerializeObject(parsedDibHeader, Formatting.Indented, new JsonConverter[] {new StringEnumConverter()}));
+
+ return new Image(); // DUMMY FOR NOW
+ }
+}
+
+static class MyExtensions {
+ public static CompressionMethod GetCompressionMethod(this int method)
+ {
+ return method switch
+ {
+ 0 => CompressionMethod.BI_RGB,
+ 1 => CompressionMethod.BI_RLE8,
+ 2 => CompressionMethod.BI_RLE4,
+ 3 => CompressionMethod.BI_BITFIELDS,
+ 4 => CompressionMethod.BI_JPEG,
+ 5 => CompressionMethod.BI_PNG,
+ 6 => CompressionMethod.BI_ALPHABITFIELDS,
+ 11 => CompressionMethod.BI_CMYK,
+ 12 => CompressionMethod.BI_CMYKRLE8,
+ 13 => CompressionMethod.BI_CMYKRLE4,
+ _ => throw new ArgumentException("Unknown Bitmap Compression Method", nameof(method))
+ };
+ }
+
+ public static byte[] ReadBytes(this Stream stream, int fileOffset, int count)
+ {
+ var buffer = new byte[count];
+ stream.Seek(fileOffset, SeekOrigin.Begin);
+ var bytesRead = stream.Read(buffer, 0, count);
+ if (bytesRead != count)
+ Console.Error.WriteLine("Didn't read the correct amount of bytes");
+ return buffer;
+ }
+}
\ No newline at end of file
diff --git a/BlastPDF.sln b/BlastPDF.sln
index 173e32a..dd8ed78 100644
--- a/BlastPDF.sln
+++ b/BlastPDF.sln
@@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShowCase", "ShowCase\ShowCa
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlastPDF.Test", "BlastPDF.Test\BlastPDF.Test.csproj", "{331127D4-4996-4D21-A808-09CA2B2CC975}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlastIMG", "BlastIMG\BlastIMG.csproj", "{DA68CCF5-1B74-4539-8827-1BDC385BA4BE}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -58,5 +60,17 @@ Global
{331127D4-4996-4D21-A808-09CA2B2CC975}.Release|x64.Build.0 = Release|Any CPU
{331127D4-4996-4D21-A808-09CA2B2CC975}.Release|x86.ActiveCfg = Release|Any CPU
{331127D4-4996-4D21-A808-09CA2B2CC975}.Release|x86.Build.0 = Release|Any CPU
+ {DA68CCF5-1B74-4539-8827-1BDC385BA4BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DA68CCF5-1B74-4539-8827-1BDC385BA4BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DA68CCF5-1B74-4539-8827-1BDC385BA4BE}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {DA68CCF5-1B74-4539-8827-1BDC385BA4BE}.Debug|x64.Build.0 = Debug|Any CPU
+ {DA68CCF5-1B74-4539-8827-1BDC385BA4BE}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {DA68CCF5-1B74-4539-8827-1BDC385BA4BE}.Debug|x86.Build.0 = Debug|Any CPU
+ {DA68CCF5-1B74-4539-8827-1BDC385BA4BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DA68CCF5-1B74-4539-8827-1BDC385BA4BE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DA68CCF5-1B74-4539-8827-1BDC385BA4BE}.Release|x64.ActiveCfg = Release|Any CPU
+ {DA68CCF5-1B74-4539-8827-1BDC385BA4BE}.Release|x64.Build.0 = Release|Any CPU
+ {DA68CCF5-1B74-4539-8827-1BDC385BA4BE}.Release|x86.ActiveCfg = Release|Any CPU
+ {DA68CCF5-1B74-4539-8827-1BDC385BA4BE}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/BlastPDF/BlastPDF.csproj b/BlastPDF/BlastPDF.csproj
index 12b1dac..8431fce 100644
--- a/BlastPDF/BlastPDF.csproj
+++ b/BlastPDF/BlastPDF.csproj
@@ -9,4 +9,8 @@
+
+
+
+
diff --git a/ShowCase/ImageParsingExample.cs b/ShowCase/ImageParsingExample.cs
new file mode 100644
index 0000000..e17392e
--- /dev/null
+++ b/ShowCase/ImageParsingExample.cs
@@ -0,0 +1,17 @@
+using System;
+using BlastIMG;
+using BlastIMG.ImageLoaders;
+
+namespace ShowCase;
+
+public class ImageParsingExample
+{
+ public static void Run(string imagePath)
+ {
+ var loaded = BmpLoader.Load(imagePath);
+
+ Console.WriteLine($"Loaded: {imagePath}");
+ Console.WriteLine($"Width: {loaded.Width}");
+ Console.WriteLine($"Height: {loaded.Height}");
+ }
+}
\ No newline at end of file
diff --git a/ShowCase/PdfBuilderExample.cs b/ShowCase/PdfBuilderExample.cs
new file mode 100644
index 0000000..ae6e3db
--- /dev/null
+++ b/ShowCase/PdfBuilderExample.cs
@@ -0,0 +1,69 @@
+using System;
+using System.IO;
+using BlastPDF.Builder;
+using BlastPDF.Builder.Graphics;
+using BlastPDF.Builder.Graphics.Drawing;
+using BlastPDF.Exporter.Basic;
+
+namespace ShowCase;
+
+public class PdfBuilderExample
+{
+ public static void Run(string outputPdfName)
+ {
+ if (File.Exists(outputPdfName)) {
+ File.Delete(outputPdfName);
+ }
+
+ var graphicsGroup = PdfGraphicsGroup.Create();
+
+ var triangleWidth = 5.0M;
+ for(int i = 0; i < 96; i++) {
+ graphicsGroup.Add(
+ PdfGraphicsObject.Create()
+ .Translate(500, 500)
+ .Rotate(i * (decimal)Math.PI / 96)
+ .LineWidth(2)
+ .SetStrokeRGB(i / 96.0M, 0.0M, 1.0M - (i / 96.0M))
+ .DrawTriangle(0, 0, triangleWidth)
+ .ResetState()
+ );
+ triangleWidth *= 1.070M;
+ }
+
+ using FileStream fs = File.Create(outputPdfName);
+ PdfDocument.Create()
+ .AddPage(PdfPage.Create()
+ .DotsPerInch(100)
+ .Width(10)
+ .Height(10)
+ .AddResource("GoodImage", PdfImage.FromFile("cat.png", PdfColorSpace.DeviceRGB))
+ .AddGraphics(PdfGraphicsObject.Create()
+ .SetCMYK(0.0M, 0.0M, 1.0M, 0.0M)
+ .Rect(0, 0, 1000, 1000)
+ .Paint(PaintModeEnum.CloseFillStroke))
+ .AddGraphics(graphicsGroup)
+ .AddGraphics(PdfGraphicsObject.Create()
+ .Translate(250, 702)
+ .Resource("GoodImage")))
+ .Save(fs);
+ }
+}
+
+public static class MyExtension {
+ public static PdfGraphicsObject DrawTriangle(this PdfGraphicsObject path, decimal x, decimal y, decimal length)
+ {
+ var radius = length / (2 * (decimal)Math.Cos(Math.PI / 6));
+ var apothem = length * (decimal)Math.Tan(Math.PI / 6) / 2;
+
+ var top = (x, y + radius);
+ var left = (x - (length / 2), y - apothem);
+ var right = (x + (length / 2), y - apothem);
+
+ return path
+ .Move(top.Item1, top.Item2)
+ .Line(left.Item1, left.Item2)
+ .Line(right.Item1, right.Item2)
+ .Paint(PaintModeEnum.CloseStroke);
+ }
+}
\ No newline at end of file
diff --git a/ShowCase/Program.cs b/ShowCase/Program.cs
index 7837658..8105c83 100644
--- a/ShowCase/Program.cs
+++ b/ShowCase/Program.cs
@@ -1,67 +1,10 @@
-using BlastPDF.Exporter.Basic;
-using BlastPDF.Builder;
-using BlastPDF.Builder.Graphics;
-using BlastPDF.Builder.Graphics.Drawing;
-using System;
-using System.IO;
-
+
namespace ShowCase;
public class Program {
public static void Main(string[] args) {
- string path = "test.pdf";
-
- if (File.Exists(path)) {
- File.Delete(path);
- }
-
- var graphicsGroup = PdfGraphicsGroup.Create();
-
- var triangleWidth = 5.0M;
- for(int i = 0; i < 96; i++) {
- graphicsGroup.Add(
- PdfGraphicsObject.Create()
- .Translate(500, 500)
- .Rotate(i * (decimal)Math.PI / 96)
- .LineWidth(2)
- .SetStrokeRGB(i / 96.0M, 0.0M, 1.0M - (i / 96.0M))
- .DrawTriangle(0, 0, triangleWidth)
- .ResetState()
- );
- triangleWidth *= 1.070M;
- }
-
- using FileStream fs = File.Create(path);
- PdfDocument.Create()
- .AddPage(PdfPage.Create()
- .DotsPerInch(100)
- .Width(10)
- .Height(10)
- .AddGraphics(PdfGraphicsObject.Create()
- .SetCMYK(0.0M, 0.0M, 1.0M, 0.0M)
- .Rect(0, 0, 1000, 1000)
- .Paint(PaintModeEnum.CloseFillStroke))
- .AddGraphics(graphicsGroup))
- .Save(fs);
+ //PdfBuilderExample.Run("test.pdf");
+ ImageParsingExample.Run("../../../images/w3c_home_256.bmp");
}
-
-
}
-public static class MyExtension {
- public static PdfGraphicsObject DrawTriangle(this PdfGraphicsObject path, decimal x, decimal y, decimal length)
- {
- var radius = length / (2 * (decimal)Math.Cos(Math.PI / 6));
- var apothem = length * (decimal)Math.Tan(Math.PI / 6) / 2;
-
- var top = (x, y + radius);
- var left = (x - (length / 2), y - apothem);
- var right = (x + (length / 2), y - apothem);
-
- return path
- .Move(top.Item1, top.Item2)
- .Line(left.Item1, left.Item2)
- .Line(right.Item1, right.Item2)
- .Paint(PaintModeEnum.CloseStroke);
- }
-}
\ No newline at end of file
diff --git a/ShowCase/cat.png b/ShowCase/cat.png
new file mode 100644
index 0000000..b57f4cf
Binary files /dev/null and b/ShowCase/cat.png differ
diff --git a/ShowCase/images/cat.bmp b/ShowCase/images/cat.bmp
new file mode 100644
index 0000000..1bcddce
Binary files /dev/null and b/ShowCase/images/cat.bmp differ
diff --git a/ShowCase/images/w3c_home.bmp b/ShowCase/images/w3c_home.bmp
new file mode 100644
index 0000000..eaaac6d
Binary files /dev/null and b/ShowCase/images/w3c_home.bmp differ
diff --git a/ShowCase/images/w3c_home_2.bmp b/ShowCase/images/w3c_home_2.bmp
new file mode 100644
index 0000000..47cb2c7
Binary files /dev/null and b/ShowCase/images/w3c_home_2.bmp differ
diff --git a/ShowCase/images/w3c_home_256.bmp b/ShowCase/images/w3c_home_256.bmp
new file mode 100644
index 0000000..4b714ff
Binary files /dev/null and b/ShowCase/images/w3c_home_256.bmp differ
diff --git a/ShowCase/images/w3c_home_gray.bmp b/ShowCase/images/w3c_home_gray.bmp
new file mode 100644
index 0000000..6eb7bfe
Binary files /dev/null and b/ShowCase/images/w3c_home_gray.bmp differ