Skip to content

Commit

Permalink
Add partial support for the ColorKey content processor parameter.
Browse files Browse the repository at this point in the history
Update PNGQuant.
Stub out parts of System.Windows.Forms.Screen.
  • Loading branch information
kg committed May 29, 2012
1 parent a1dcc82 commit b02a7d7
Show file tree
Hide file tree
Showing 12 changed files with 354 additions and 109 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Tests/*Cases/*.js
/jsil.org/demos/Sully/*.js
/jsil.org/demos/Sully/Content
/jsil.org/demos/Soulcaster/*.js
/jsil.org/demos/Soulcaster/Content
/jsil.org/demos/Soulcaster/Soulcaster2Content
/jsil.org/demos/RPG/Content
/jsil.org/demos/Lumberjack/Content
/jsil.org/demos/Lumberjack/*.js
Expand Down
2 changes: 2 additions & 0 deletions Compiler/Profiles/XNA3/Profiles.XNA3.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
<CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\..\..\bin\</OutputPath>
Expand All @@ -36,6 +37,7 @@
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
<CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Build" />
Expand Down
2 changes: 2 additions & 0 deletions Compiler/Profiles/XNA4/Profiles.XNA4.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\..\..\bin\</OutputPath>
Expand All @@ -33,6 +34,7 @@
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
<CodeAnalysisFailOnMissingRules>true</CodeAnalysisFailOnMissingRules>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Build" />
Expand Down
242 changes: 156 additions & 86 deletions Compiler/Profiles/XNACommon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,115 @@ public static IEnumerable<CompressResult> CompressAudio (string fileName, string
}
}

public static CompressResult? CompressImage (string imageName, string sourceFolder, string outputFolder, Dictionary<string, object> settings, CompressResult? oldResult) {
const int CompressVersion = 3;
private static System.Drawing.Bitmap LoadBitmap (string filename, out bool hasAlphaChannel, out System.Drawing.Color? existingColorKeyColor) {
existingColorKeyColor = null;

switch (Path.GetExtension(filename).ToLower()) {
case ".bmp":
var hImage = LoadImage(IntPtr.Zero, filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
var texture = System.Drawing.Image.FromHbitmap(hImage);
try {
switch (texture.PixelFormat) {
case PixelFormat.Gdi:
case PixelFormat.Extended:
case PixelFormat.Canonical:
case PixelFormat.Undefined:
case PixelFormat.Format16bppRgb555:
case PixelFormat.Format16bppRgb565:
case PixelFormat.Format24bppRgb:
hasAlphaChannel = false;
return texture;

case PixelFormat.Format32bppArgb:
case PixelFormat.Format32bppPArgb:
case PixelFormat.Format32bppRgb: {
// Do an elaborate song and dance to extract the alpha channel from the PNG, because
// GDI+ is too utterly shitty to do that itself
var dc = CreateCompatibleDC(IntPtr.Zero);

var newImage = new System.Drawing.Bitmap(
texture.Width, texture.Height, PixelFormat.Format32bppArgb
);
var bits = newImage.LockBits(
new System.Drawing.Rectangle(0, 0, texture.Width, texture.Height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb
);

var info = new BITMAPINFO {
biBitCount = 32,
biClrImportant = 0,
biClrUsed = 0,
biCompression = 0,
biHeight = -texture.Height,
biPlanes = 1,
biSizeImage = bits.Stride * bits.Height,
biWidth = bits.Width,
};
info.biSize = Marshal.SizeOf(info);

var rv = GetDIBits(dc, hImage, 0, (uint)texture.Height, bits.Scan0, ref info, 0);

newImage.UnlockBits(bits);

DeleteObject(dc);

texture.Dispose();
hasAlphaChannel = true;
return newImage;
}

default:
Console.Error.WriteLine("// Unsupported bitmap format: '{0}' {1}", Path.GetFileNameWithoutExtension(filename), texture.PixelFormat);
texture.Dispose();
hasAlphaChannel = false;
return null;
}
} finally {
DeleteObject(hImage);
}

default: {
var result = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(filename, true);

switch (result.PixelFormat) {
case PixelFormat.Format8bppIndexed:
case PixelFormat.Format4bppIndexed:
case PixelFormat.Format1bppIndexed:
case PixelFormat.Indexed:
var palette = result.Palette;

for (var i = 0; i < palette.Entries.Length; i++) {
if (palette.Entries[i].A < 255) {
existingColorKeyColor = palette.Entries[i];
break;
}
}

hasAlphaChannel = (existingColorKeyColor.HasValue);
break;

case PixelFormat.Format32bppArgb:
case PixelFormat.Format32bppPArgb:
hasAlphaChannel = true;
break;

default:
hasAlphaChannel = false;
break;
}

return result;
}
}
}

public static CompressResult? CompressImage (
string imageName, string sourceFolder,
string outputFolder, Dictionary<string, object> settings,
Dictionary<string, ProjectMetadata> itemMetadata,
CompressResult? oldResult
) {
const int CompressVersion = 4;

EnsureDirectoryExists(outputFolder);

Expand All @@ -345,107 +452,69 @@ public static IEnumerable<CompressResult> CompressAudio (string fileName, string
var outputPath = Path.Combine(outputFolder, Path.GetFileNameWithoutExtension(imageName));
var justCopy = true;

Action<System.Drawing.Bitmap> saveJpeg = (bitmap) => {
Action<System.Drawing.Bitmap, String> saveJpeg = (bitmap, path) => {
var encoder = GetEncoder(ImageFormat.Jpeg);
var encoderParameters = new System.Drawing.Imaging.EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(
System.Drawing.Imaging.Encoder.Quality,
Convert.ToInt64(settings["JPEGQuality"])
);
bitmap.Save(outputPath, encoder, encoderParameters);
bitmap.Save(path, encoder, encoderParameters);
};

bool colorKey = true;
var colorKeyColor = System.Drawing.Color.FromArgb(255, 255, 0, 255);

if (itemMetadata.ContainsKey("ProcessorParameters_ColorKeyEnabled")) {
colorKey = Convert.ToBoolean(itemMetadata["ProcessorParameters_ColorKeyEnabled"].EvaluatedValue);
}

if (itemMetadata.ContainsKey("ProcessorParameters_ColorKeyColor")) {
var parts = itemMetadata["ProcessorParameters_ColorKeyColor"].EvaluatedValue.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);
colorKeyColor = System.Drawing.Color.FromArgb(
Convert.ToInt32(parts[3]),
Convert.ToInt32(parts[0]),
Convert.ToInt32(parts[1]),
Convert.ToInt32(parts[2])
);
}

justCopy &= !colorKey;

if (forceJpeg) {
justCopy = false;
outputPath += ".jpg";

using (var img = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(sourcePath))
saveJpeg(img);
bool temp;
System.Drawing.Color? temp2;
using (var img = LoadBitmap(sourcePath, out temp, out temp2))
saveJpeg(img, outputPath);
} else if (justCopy) {
outputPath += Path.GetExtension(sourcePath);

File.Copy(sourcePath, outputPath, true);
} else {
switch (Path.GetExtension(imageName).ToLower()) {
case ".jpg":
case ".jpeg":
bool hasAlphaChannel;
System.Drawing.Color? existingColorKey;

using (var img = LoadBitmap(sourcePath, out hasAlphaChannel, out existingColorKey)) {
if (hasAlphaChannel || colorKey || existingColorKey.HasValue)
outputPath += ".png";
else
outputPath += ".jpg";
break;

case ".bmp":
justCopy = false;

var hImage = LoadImage(IntPtr.Zero, sourcePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
try {
using (var texture = (System.Drawing.Bitmap)System.Drawing.Image.FromHbitmap(hImage)) {
switch (texture.PixelFormat) {
case PixelFormat.Gdi:
case PixelFormat.Extended:
case PixelFormat.Canonical:
case PixelFormat.Undefined:
case PixelFormat.Format16bppRgb555:
case PixelFormat.Format16bppRgb565:
case PixelFormat.Format24bppRgb:
outputPath += ".jpg";
saveJpeg(texture);
break;

case PixelFormat.Format32bppArgb:
case PixelFormat.Format32bppPArgb:
case PixelFormat.Format32bppRgb: {
// Do an elaborate song and dance to extract the alpha channel from the PNG, because
// GDI+ is too utterly shitty to do that itself
var dc = CreateCompatibleDC(IntPtr.Zero);

var newImage = new System.Drawing.Bitmap(
texture.Width, texture.Height, PixelFormat.Format32bppArgb
);
var bits = newImage.LockBits(
new System.Drawing.Rectangle(0, 0, texture.Width, texture.Height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb
);

var info = new BITMAPINFO {
biBitCount = 32,
biClrImportant = 0,
biClrUsed = 0,
biCompression = 0,
biHeight = -texture.Height,
biPlanes = 1,
biSizeImage = bits.Stride * bits.Height,
biWidth = bits.Width,
};
info.biSize = Marshal.SizeOf(info);

var rv = GetDIBits(dc, hImage, 0, (uint)texture.Height, bits.Scan0, ref info, 0);

newImage.UnlockBits(bits);

DeleteObject(dc);

outputPath += ".png";
newImage.Save(outputPath, ImageFormat.Png);
newImage.Dispose();

break;
}

default:
Console.Error.WriteLine("// Unsupported bitmap format: '{0}' {1}", Path.GetFileNameWithoutExtension(imageName), texture.PixelFormat);
return null;
}
}
} finally {
DeleteObject(hImage);
}
break;
if (existingColorKey.HasValue)
img.MakeTransparent(existingColorKey.Value);

case ".png":
default:
outputPath += Path.GetExtension(imageName);
break;
if (colorKey)
img.MakeTransparent(colorKeyColor);

if (hasAlphaChannel || colorKey || existingColorKey.HasValue)
img.Save(outputPath, ImageFormat.Png);
else
saveJpeg(img, outputPath);
}
}

if (justCopy)
File.Copy(sourcePath, outputPath, true);

bool usePNGQuant = Convert.ToBoolean(settings["UsePNGQuant"]);
var pngQuantParameters = String.Format(
"{0} {1}",
Expand Down Expand Up @@ -819,6 +888,7 @@ where bi.OutputPath.EndsWith(".xnb", StringComparison.OrdinalIgnoreCase)
);

continue;

case "FontTextureProcessor":
case "FontDescriptionProcessor":
copyRawXnb(item, xnbPath, "SpriteFont");
Expand All @@ -840,7 +910,7 @@ where bi.OutputPath.EndsWith(".xnb", StringComparison.OrdinalIgnoreCase)

var result = Common.CompressImage(
item.EvaluatedInclude, contentProjectDirectory, itemOutputDirectory,
configuration.ProfileSettings, existingJournalEntry
configuration.ProfileSettings, metadata, existingJournalEntry
);

if (result.HasValue) {
Expand Down
6 changes: 3 additions & 3 deletions Libraries/JSIL.Browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,8 @@ function loadBinaryFileAsync (uri, onComplete) {
}

var loadedFontCount = 0;
var loadingPollInterval = 25;
var loadingPollInterval = 10;
var maxAssetsLoading = 16;
var soundLoadTimeout = 30000;
var fontLoadTimeout = 15000;

Expand Down Expand Up @@ -822,7 +823,7 @@ function pollAssetQueue () {
};
};

while ((state.assetsLoading < state.maxAssetsLoading) && (state.loadIndex < state.assetCount)) {
while ((state.assetsLoading < maxAssetsLoading) && (state.loadIndex < state.assetCount)) {
try {
var assetSpec = state.assets[state.loadIndex];

Expand Down Expand Up @@ -906,7 +907,6 @@ function loadAssets (assets, onDoneLoading) {
assetsLoaded: 0,
assetsFinished: 0,
assetsLoading: 0,
maxAssetsLoading: 16,
onDoneLoading: onDoneLoading,
assets: assets,
interval: null,
Expand Down
9 changes: 8 additions & 1 deletion Libraries/System.Drawing.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ var $jsildrawing = JSIL.DeclareAssembly("JSIL.Drawing");
JSIL.DeclareNamespace("System");
JSIL.DeclareNamespace("System.Drawing");

var $sdasms = new JSIL.AssemblyCollection({
5: "mscorlib",
6: "System",
11: "System.Drawing",
15: "System.Windows.Forms",
});

if (JSIL.HostType.IsBrowser) {
JSIL.ImplementExternals("System.Drawing.Image", function ($) {
var mscorlib = JSIL.GetAssembly("mscorlib", true);
Expand Down Expand Up @@ -333,7 +340,7 @@ JSIL.ImplementExternals("System.Drawing.Rectangle", function ($) {
);

$.Method({Static:false, Public:true }, ".ctor",
(new JSIL.MethodSignature(null, [$asms[11].TypeRef("System.Drawing.Point"), $asms[11].TypeRef("System.Drawing.Size")], [])),
(new JSIL.MethodSignature(null, [$sdasms[11].TypeRef("System.Drawing.Point"), $sdasms[11].TypeRef("System.Drawing.Size")], [])),
function _ctor (location, size) {
this.x = location.X;
this.y = location.Y;
Expand Down
Loading

0 comments on commit b02a7d7

Please sign in to comment.