
Hidden Content: C# source
using System;
using System.Collections.Generic;
using System.Text;
using PaintDotNet;
using PaintDotNet.Data;
using PaintDotNet.Rendering;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Linq;
namespace DotExeFileType
{
public class MyFileType : FileType
{
public MyFileType()
: base("Exe File",
FileTypeFlags.SupportsSaving,
new String[] { ".exe" })
{
}
protected override void OnSave(Document input, Stream output, SaveConfigToken token,
Surface scratchSurface, ProgressEventHandler callback)
{
RenderArgs ra = new RenderArgs(new Surface(input.Size));
// input.Render(ra);
input.Render(ra, false);
var img = ra.Bitmap;
Bitmap cells = new Bitmap(80 * 8, 25 * 12);
Graphics ctx = Graphics.FromImage(cells);
ctx.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
ctx.DrawImage(img, 0, 0, 80 * 8, 25 * 12);
ctx.Dispose();
byte[] outArr = new byte[80*25*4];
// Downsample to 4-bit colors
for (int y = 0; y < 25*12; y++)
{
for (int x = 0; x < 80*8; x++)
{
Color c = cells.GetPixel(x, y);
cells.SetPixel(x, y, bestMatch(ColorBgra.FromColor(cells.GetPixel(x, y))));
}
}
// Histogram the 8x12 characters and find
// the closest match
for (int y = 0; y < 25; y++)
{
for (int x = 0; x < 80; x++)
{
Dictionary<ColorBgra, int> histo = new Dictionary<ColorBgra, int>();
for (int j = 0; j < 12; j++)
{
for (int i = 0; i < 8; i++)
{
ColorBgra col = ColorBgra.FromColor(cells.GetPixel(i + x * 8, j + y * 12));
if (!histo.ContainsKey(col))
histo.Add(col, 1);
else histo[col]++;
}
}
var histoList = histo
.OrderByDescending(k => k.Value).Select(k => k.Key)
.ToList();
byte foreground = (byte)Enumerable.Range(0, ConsoleColors.Length)
.Where(i => ConsoleColors[i] == histoList[0])
.First();
byte background;
if (histoList.Count > 1)
{
background = (byte)Enumerable.Range(0, ConsoleColors.Length)
.Where(i => ConsoleColors[i] == histoList[1])
.First();
}
else { background = foreground; }
double ratio;
if (histoList.Count > 1)
ratio = 96 * histo[histoList[0]] / (histo[histoList[0]] + histo[histoList[1]]);
else ratio = 0;
int bestCodepoint = 0;
double bestRatioDiff = Double.MaxValue;
for (int i = 0; i < CP437.Length; i++)
{
if (Math.Abs((double)(CP437[i]) - ratio) < bestRatioDiff)
{
bestRatioDiff = Math.Abs((double)(CP437[i]) - ratio);
bestCodepoint = i;
}
}
var index = (y * 80 + x) * 4;
outArr[index] = (byte)bestCodepoint;
outArr[index + 1] = (byte)0;
outArr[index + 2] = (byte)(foreground | (background << 4));
outArr[index + 3] = (byte)0;
}
}
output.Write(ExeOut.OutExe, 0, (int)ArrayOffset);
output.Write(outArr, 0, outArr.Length);
output.Write(ExeOut.OutExe, (int)(ArrayOffset + outArr.Length),
(int)(ExeOut.OutExe.Length - (ArrayOffset + outArr.Length)));
}
protected override Document OnLoad(Stream input)
{
throw new NotImplementedException();
}
ColorBgra[] ConsoleColors = {
ColorBgra.FromOpaqueInt32(0x000000),
ColorBgra.FromOpaqueInt32(0x000080),
ColorBgra.FromOpaqueInt32(0x008000),
ColorBgra.FromOpaqueInt32(0x008080),
ColorBgra.FromOpaqueInt32(0x800000),
ColorBgra.FromOpaqueInt32(0x800080),
ColorBgra.FromOpaqueInt32(0x808000),
ColorBgra.FromOpaqueInt32(0xC0C0C0),
ColorBgra.FromOpaqueInt32(0x808080),
ColorBgra.FromOpaqueInt32(0x0000FF),
ColorBgra.FromOpaqueInt32(0x00FF00),
ColorBgra.FromOpaqueInt32(0x00FFFF),
ColorBgra.FromOpaqueInt32(0xFF0000),
ColorBgra.FromOpaqueInt32(0xFF00FF),
ColorBgra.FromOpaqueInt32(0xFFFF00),
ColorBgra.FromOpaqueInt32(0xFFFFFF)
};
// Generated from CodeLab and a screenshot!
int[] CP437 = { 00, 38, 60, 38, 32, 40, 44, 20, 76, 32, 64, 37, 32, 32, 48, 40,
29, 29, 30, 28, 47, 40, 21, 36, 24, 24, 15, 15, 13, 20, 32, 32,
00, 22, 14, 42, 30, 20, 40, 08, 18, 18, 24, 14, 08, 08, 06, 14,
45, 23, 30, 27, 32, 29, 30, 27, 38, 30, 12, 16, 18, 12, 18, 20,
40, 36, 41, 30, 38, 35, 33, 34, 38, 22, 28, 38, 30, 45, 45, 34,
33, 41, 40, 31, 26, 36, 34, 38, 34, 30, 35, 22, 14, 22, 12, 08,
24, 33, 20, 33, 24, 26, 32, 33, 22, 28, 32, 24, 30, 25, 24, 32,
32, 23, 20, 22, 25, 22, 26, 22, 28, 22, 20, 16, 20, 14, 24, 23
};
double colorDistance(ColorBgra a, ColorBgra <img src='http://forums.getpaint.net/public/style_emoticons/<#EMO_DIR#>/boltbait.cool.png' class='bbc_emoticon' alt='B)' />
{
HsvColor aH = HsvColor.FromColor(a.ToColor());
HsvColor bH = HsvColor.FromColor(b.ToColor());
return Math.Abs(bH.Hue - aH.Hue) +
Math.Abs(bH.Saturation - aH.Saturation) +
Math.Abs(bH.Value - aH.Value);
}
ColorBgra bestMatch(ColorBgra c)
{
double bestDist = Double.MaxValue;
ColorBgra bestCol = ColorBgra.Black;
for (int n = 0; n < 16; n++)
{
double curDist = colorDistance(c, ConsoleColors[n]);
if (curDist < bestDist)
{
bestCol = ConsoleColors[n];
bestDist = curDist;
}
}
return bestCol;
}
uint ArrayOffset = 0x418;
}
public class MyFileTypeFactory : IFileTypeFactory
{
public FileType[] GetFileTypeInstances()
{
return new FileType[] { new MyFileType() };
}
}
}
Hidden Content: c++ source
Compile as x86, use /MERGE:".rdata=.text", /NODEFAULTLIB, and /MANIFEST:NO to link.
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
// Stuff to pass WriteConsoleOutputW. These are in the
// .data segment (0x2400 in the .exe) in whatever order
// the compiler felt like.
CONSOLE_SCREEN_BUFFER_INFO outInfo;
COORD outSize = {80, 25};
COORD outPos = {0, 0};
// Const, so it will be in (because we merged .rdata
// into it) .text at 0x400 in the .exe.
// Totally note I got the order wrong here but it doesn't
// really matter since we're filling in these values elsewhere.
const CHAR_INFO outChar[80][25] = { { {L'0', 0xf} } };
// Custom entry-point to remind you not to link this
// with the Visual C Run-Time library.
int Main()
{
// Even though we use Unicode output, it's rare for
// a Windows console to use Unicode.
HANDLE conOut = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE conIn = GetStdHandle(STD_INPUT_HANDLE );
GetConsoleScreenBufferInfo(conOut, &outInfo);
outInfo.dwCursorPosition.X = 0;
WriteConsoleOutputW(conOut, (CHAR_INFO*)outChar,
outSize, outPos, &outInfo.srWindow);
ReadConsoleW(conIn, (LPVOID)&outInfo, 1, 0, 0);
outInfo.dwCursorPosition.Y += 25;
SetConsoleCursorPosition(conOut, outInfo.dwCursorPosition);
return 0;
}
Compile as x86, use /MERGE:".rdata=.text", /NODEFAULTLIB, and /MANIFEST:NO to link.
Download:
DotExeFileType.zip 5.67K
87 downloads(Edited: Messed up the 'ratio' variable)
















