make sure input bitmaps are 32bpp everywhere

This commit is contained in:
UnknownShadow200 2017-01-24 09:11:47 +11:00
parent c35692a8c6
commit 69d6bd228e
13 changed files with 70 additions and 88 deletions

View File

@ -86,8 +86,6 @@ namespace ClassicalSharp.Entities {
Bitmap bmp = (Bitmap)item.Data; Bitmap bmp = (Bitmap)item.Data;
game.Graphics.DeleteTexture(ref TextureId); game.Graphics.DeleteTexture(ref TextureId);
if (!Platform.Is32Bpp(bmp))
game.Drawer2D.ConvertTo32Bpp(ref bmp);
uScale = 1; vScale = 1; uScale = 1; vScale = 1;
EnsurePow2(ref bmp); EnsurePow2(ref bmp);

View File

@ -38,6 +38,13 @@ namespace ClassicalSharp {
Graphics.MakeApiInfo(); Graphics.MakeApiInfo();
ErrorHandler.AdditionalInfo = Graphics.ApiInfo; ErrorHandler.AdditionalInfo = Graphics.ApiInfo;
#if ANDROID
Drawer2D = new CanvasDrawer2D(Graphics);
#else
Drawer2D = new GdiPlusDrawer2D(Graphics);
#endif
Options.Load(); Options.Load();
Entities = new EntityList(this); Entities = new EntityList(this);
AcceptedUrls.Load(); AcceptedUrls.Load();
@ -66,15 +73,9 @@ namespace ClassicalSharp {
BlockInfo.Init(); BlockInfo.Init();
ModelCache = new ModelCache(this); ModelCache = new ModelCache(this);
ModelCache.InitCache(); ModelCache.InitCache();
AsyncDownloader = AddComponent(new AsyncDownloader()); AsyncDownloader = AddComponent(new AsyncDownloader(Drawer2D));
Lighting = AddComponent(new BasicLighting()); Lighting = AddComponent(new BasicLighting());
#if ANDROID
Drawer2D = new CanvasDrawer2D(Graphics);
#else
Drawer2D = new GdiPlusDrawer2D(Graphics);
#endif
Drawer2D.UseBitmappedChat = ClassicMode || !Options.GetBool(OptionsKey.ArialChatFont, false); Drawer2D.UseBitmappedChat = ClassicMode || !Options.GetBool(OptionsKey.ArialChatFont, false);
Drawer2D.BlackTextShadows = Options.GetBool(OptionsKey.BlackTextShadows, false); Drawer2D.BlackTextShadows = Options.GetBool(OptionsKey.BlackTextShadows, false);

View File

@ -352,9 +352,8 @@ namespace ClassicalSharp {
/// <summary> Reads a bitmap from the stream (converting it to 32 bits per pixel if necessary), /// <summary> Reads a bitmap from the stream (converting it to 32 bits per pixel if necessary),
/// and updates the native texture for it. </summary> /// and updates the native texture for it. </summary>
public bool UpdateTexture(ref int texId, string file, byte[] data, bool setSkinType) { public bool UpdateTexture(ref int texId, string file, byte[] data, bool setSkinType) {
MemoryStream stream = new MemoryStream(data);
int maxSize = Graphics.MaxTextureDimensions; int maxSize = Graphics.MaxTextureDimensions;
using (Bitmap bmp = Platform.ReadBmp(stream)) { using (Bitmap bmp = Platform.ReadBmp32Bpp(Drawer2D, data)) {
if (bmp.Width > maxSize || bmp.Height > maxSize) { if (bmp.Width > maxSize || bmp.Height > maxSize) {
Chat.Add("&cUnable to use " + file + " from the texture pack."); Chat.Add("&cUnable to use " + file + " from the texture pack.");
Chat.Add("&c Its size is (" + bmp.Width + "," + bmp.Height Chat.Add("&c Its size is (" + bmp.Width + "," + bmp.Height
@ -376,12 +375,7 @@ namespace ClassicalSharp {
throw new NotSupportedException("char.png has invalid dimensions"); throw new NotSupportedException("char.png has invalid dimensions");
} }
if (!Platform.Is32Bpp(bmp)) { texId = Graphics.CreateTexture(bmp, true);
using (Bitmap bmp32 = Drawer2D.ConvertTo32Bpp(bmp))
texId = Graphics.CreateTexture(bmp32, true);
} else {
texId = Graphics.CreateTexture(bmp, true);
}
return true; return true;
} }
} }
@ -428,18 +422,13 @@ namespace ClassicalSharp {
void TextureChangedCore(object sender, TextureEventArgs e) { void TextureChangedCore(object sender, TextureEventArgs e) {
byte[] data = e.Data; byte[] data = e.Data;
if (e.Name == "terrain.png") { if (e.Name == "terrain.png") {
MemoryStream stream = new MemoryStream(data); Bitmap atlas = Platform.ReadBmp32Bpp(Drawer2D, data);
Bitmap atlas = Platform.ReadBmp(stream);
if (ChangeTerrainAtlas(atlas, null)) return; if (ChangeTerrainAtlas(atlas, null)) return;
atlas.Dispose(); atlas.Dispose();
} else if (e.Name == "cloud.png" || e.Name == "clouds.png") { } else if (e.Name == "cloud.png" || e.Name == "clouds.png") {
UpdateTexture(ref CloudsTex, e.Name, data, false); UpdateTexture(ref CloudsTex, e.Name, data, false);
} else if (e.Name == "default.png") { } else if (e.Name == "default.png") {
MemoryStream stream = new MemoryStream(data); Bitmap bmp = Platform.ReadBmp32Bpp(Drawer2D, data);
Bitmap bmp = Platform.ReadBmp(stream);
if (!Platform.Is32Bpp(bmp))
Drawer2D.ConvertTo32Bpp(ref bmp);
Drawer2D.SetFontBitmap(bmp); Drawer2D.SetFontBitmap(bmp);
Events.RaiseChatFontChanged(); Events.RaiseChatFontChanged();
} }

View File

@ -22,15 +22,26 @@ namespace ClassicalSharp.Network {
readonly object downloadedLocker = new object(); readonly object downloadedLocker = new object();
Dictionary<string, DownloadedItem> downloaded = new Dictionary<string, DownloadedItem>(); Dictionary<string, DownloadedItem> downloaded = new Dictionary<string, DownloadedItem>();
string skinServer = null; string skinServer = null;
readonly IDrawer2D drawer;
public Request CurrentItem; public Request CurrentItem;
public int CurrentItemProgress = -3; public int CurrentItemProgress = -3;
public IDrawer2D Drawer;
public AsyncDownloader(IDrawer2D drawer) { this.drawer = drawer; }
public AsyncDownloader() { }
public AsyncDownloader(string skinServer) { Init(skinServer); }
public void Init(Game game) { Init(game.skinServer); } public void Init(Game game) { Init(game.skinServer); }
public void Ready(Game game) { }
public void Reset(Game game) {
lock (requestLocker)
requests.Clear();
handle.Set();
}
void Init(string skinServer) { public void OnNewMap(Game game) { }
public void OnNewMapLoaded(Game game) { }
public void Init(string skinServer) {
this.skinServer = skinServer; this.skinServer = skinServer;
WebRequest.DefaultWebProxy = null; WebRequest.DefaultWebProxy = null;
@ -39,15 +50,7 @@ namespace ClassicalSharp.Network {
worker.IsBackground = true; worker.IsBackground = true;
worker.Start(); worker.Start();
} }
public void Ready(Game game) { }
public void Reset(Game game) {
lock(requestLocker)
requests.Clear();
handle.Set();
}
public void OnNewMap(Game game) { }
public void OnNewMapLoaded(Game game) { }
/// <summary> Asynchronously downloads a skin. If 'skinName' points to the url then the skin is /// <summary> Asynchronously downloads a skin. If 'skinName' points to the url then the skin is
/// downloaded from that url, otherwise it is downloaded from the url 'defaultSkinServer'/'skinName'.png </summary> /// downloaded from that url, otherwise it is downloaded from the url 'defaultSkinServer'/'skinName'.png </summary>
@ -100,7 +103,7 @@ namespace ClassicalSharp.Network {
void AddRequest(string url, bool priority, string identifier, void AddRequest(string url, bool priority, string identifier,
RequestType type, DateTime lastModified, string etag) { RequestType type, DateTime lastModified, string etag) {
lock(requestLocker) { lock (requestLocker) {
Request request = new Request(url, identifier, type, lastModified, etag); Request request = new Request(url, identifier, type, lastModified, etag);
if (priority) { if (priority) {
requests.Insert(0, request); requests.Insert(0, request);
@ -116,7 +119,7 @@ namespace ClassicalSharp.Network {
/// Note that this will *block** the calling thread as the method waits until the asynchronous /// Note that this will *block** the calling thread as the method waits until the asynchronous
/// thread has exited the for loop. </summary> /// thread has exited the for loop. </summary>
public void Dispose() { public void Dispose() {
lock(requestLocker) { lock (requestLocker) {
requests.Insert(0, null); requests.Insert(0, null);
} }
@ -248,7 +251,7 @@ namespace ClassicalSharp.Network {
object DownloadContent(Request request, HttpWebResponse response) { object DownloadContent(Request request, HttpWebResponse response) {
if (request.Type == RequestType.Bitmap) { if (request.Type == RequestType.Bitmap) {
MemoryStream data = DownloadBytes(response); MemoryStream data = DownloadBytes(response);
return Platform.ReadBmp(data); return Platform.ReadBmp32Bpp(drawer, data);
} else if (request.Type == RequestType.String) { } else if (request.Type == RequestType.String) {
MemoryStream data = DownloadBytes(response); MemoryStream data = DownloadBytes(response);
byte[] rawBuffer = data.GetBuffer(); byte[] rawBuffer = data.GetBuffer();

View File

@ -11,7 +11,17 @@ using System.Drawing.Imaging;
namespace ClassicalSharp { namespace ClassicalSharp {
public static class Platform { public static class Platform {
public static Bitmap ReadBmp32Bpp(IDrawer2D drawer, byte[] data) {
return ReadBmp32Bpp(drawer, new MemoryStream(data));
}
public static Bitmap ReadBmp32Bpp(IDrawer2D drawer, Stream src) {
Bitmap bmp = ReadBmp(src);
if (!Is32Bpp(bmp)) drawer.ConvertTo32Bpp(ref bmp);
return bmp;
}
public static Bitmap CreateBmp(int width, int height) { public static Bitmap CreateBmp(int width, int height) {
#if !ANDROID #if !ANDROID
return new Bitmap(width, height); return new Bitmap(width, height);

View File

@ -40,8 +40,8 @@ namespace ClassicalSharp.Textures {
void TextureChanged(object sender, TextureEventArgs e) { void TextureChanged(object sender, TextureEventArgs e) {
if (e.Name == "animations.png" || e.Name == "animation.png") { if (e.Name == "animations.png" || e.Name == "animation.png") {
MemoryStream stream = new MemoryStream(e.Data); animBmp = Platform.ReadBmp32Bpp(game.Drawer2D, e.Data);
SetAtlas(Platform.ReadBmp(stream)); animsBuffer = new FastBitmap(animBmp, true, true);
} else if (e.Name == "animations.txt" || e.Name == "animation.txt") { } else if (e.Name == "animations.txt" || e.Name == "animation.txt") {
MemoryStream stream = new MemoryStream(e.Data); MemoryStream stream = new MemoryStream(e.Data);
StreamReader reader = new StreamReader(stream); StreamReader reader = new StreamReader(stream);
@ -51,14 +51,6 @@ namespace ClassicalSharp.Textures {
} }
} }
/// <summary> Sets the atlas bitmap that animation frames are contained within. </summary>
void SetAtlas(Bitmap bmp) {
if (!Platform.Is32Bpp(bmp))
game.Drawer2D.ConvertTo32Bpp(ref bmp);
this.animBmp = bmp;
animsBuffer = new FastBitmap(bmp, true, true);
}
/// <summary> Runs through all animations and if necessary updates the terrain atlas. </summary> /// <summary> Runs through all animations and if necessary updates the terrain atlas. </summary>
public unsafe void Tick(ScheduledTask task) { public unsafe void Tick(ScheduledTask task) {
if (useLavaAnim) { if (useLavaAnim) {

View File

@ -25,11 +25,6 @@ namespace ClassicalSharp {
/// <summary> Updates the underlying atlas bitmap, fields, and texture. </summary> /// <summary> Updates the underlying atlas bitmap, fields, and texture. </summary>
public void UpdateState(BlockInfo info, Bitmap bmp) { public void UpdateState(BlockInfo info, Bitmap bmp) {
if (!Platform.Is32Bpp(bmp)) {
Utils.LogDebug("Converting terrain atlas to 32bpp image");
drawer.ConvertTo32Bpp(ref bmp);
}
AtlasBitmap = bmp; AtlasBitmap = bmp;
elementSize = bmp.Width / ElementsPerRow; elementSize = bmp.Width / ElementsPerRow;
using (FastBitmap fastBmp = new FastBitmap(bmp, true, true)) using (FastBitmap fastBmp = new FastBitmap(bmp, true, true))

View File

@ -57,10 +57,6 @@ namespace ClassicalSharp.Textures {
game.World.TextureUrl = item.Url; game.World.TextureUrl = item.Url;
game.Events.RaiseTexturePackChanged(); game.Events.RaiseTexturePackChanged();
if (!Platform.Is32Bpp(bmp)) {
Utils.LogDebug("Converting terrain atlas to 32bpp image");
game.Drawer2D.ConvertTo32Bpp(ref bmp);
}
if (!game.ChangeTerrainAtlas(bmp, null)) { bmp.Dispose(); return; } if (!game.ChangeTerrainAtlas(bmp, null)) { bmp.Dispose(); return; }
TextureCache.Add(item.Url, bmp); TextureCache.Add(item.Url, bmp);
@ -71,7 +67,7 @@ namespace ClassicalSharp.Textures {
if (data == null) { // e.g. 404 errors if (data == null) { // e.g. 404 errors
ExtractDefault(game); ExtractDefault(game);
} else if (url != game.World.TextureUrl) { } else if (url != game.World.TextureUrl) {
Bitmap bmp = GetBitmap(data); Bitmap bmp = GetBitmap(game.Drawer2D, data);
if (bmp == null) { data.Dispose(); return; } if (bmp == null) { data.Dispose(); return; }
game.World.TextureUrl = url; game.World.TextureUrl = url;
@ -110,9 +106,9 @@ namespace ClassicalSharp.Textures {
} }
} }
static Bitmap GetBitmap(FileStream fs) { static Bitmap GetBitmap(IDrawer2D drawer, Stream src) {
try { try {
return Platform.ReadBmp(fs); return Platform.ReadBmp32Bpp(drawer, src);
} catch (ArgumentException ex) { } catch (ArgumentException ex) {
ErrorHandler.LogError("Cache.GetBitmap", ex); ErrorHandler.LogError("Cache.GetBitmap", ex);
return null; return null;

View File

@ -1,21 +1,21 @@
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT // ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
using System; using System;
using System.Drawing; using System.Drawing;
using OpenTK.Platform; using ClassicalSharp;
namespace Launcher.Drawing { namespace Launcher.Drawing {
/// <summary> Per-platform class used to transfer a framebuffer directly to the native window. </summary> /// <summary> Per-platform class used to transfer a framebuffer directly to the native window. </summary>
public abstract class PlatformDrawer { public abstract class PlatformDrawer {
/// <summary> Data describing the native window. </summary> /// <summary> Data describing the native window. </summary>
internal IWindowInfo info; internal OpenTK.Platform.IWindowInfo info;
/// <summary> Initialises the variables for this platform drawer. </summary> /// <summary> Initialises the variables for this platform drawer. </summary>
public abstract void Init(); public abstract void Init();
/// <summary> Creates a framebuffer bitmap of the given dimensions. </summary> /// <summary> Creates a framebuffer bitmap of the given dimensions. </summary>
public virtual Bitmap CreateFrameBuffer(int width, int height) { public virtual Bitmap CreateFrameBuffer(int width, int height) {
return new Bitmap(width, height); return Platform.CreateBmp(width, height);
} }
/// <summary> Updates the variables when the native window changes dimensions. </summary> /// <summary> Updates the variables when the native window changes dimensions. </summary>

View File

@ -41,7 +41,7 @@ namespace Launcher.Gui.Screens {
if (!fetcher.Done) return; if (!fetcher.Done) return;
if (ResourceList.Files.Count > 0) { if (ResourceList.Files.Count > 0) {
ResourcePatcher patcher = new ResourcePatcher(fetcher); ResourcePatcher patcher = new ResourcePatcher(fetcher, drawer);
patcher.Run(); patcher.Run();
} }
@ -74,8 +74,10 @@ namespace Launcher.Gui.Screens {
} }
void DownloadResources(int mouseX, int mouseY) { void DownloadResources(int mouseX, int mouseY) {
if (game.Downloader == null) if (game.Downloader == null) {
game.Downloader = new AsyncDownloader("null"); game.Downloader = new AsyncDownloader(drawer);
game.Downloader.Init("");
}
if (fetcher != null) return; if (fetcher != null) return;
fetcher = game.fetcher; fetcher = game.fetcher;

View File

@ -47,25 +47,17 @@ namespace Launcher {
} }
void ProcessZipEntry(string filename, byte[] data, ZipEntry entry) { void ProcessZipEntry(string filename, byte[] data, ZipEntry entry) {
MemoryStream stream = new MemoryStream(data);
if (filename == "default.png") { if (filename == "default.png") {
if (fontPng) return; if (fontPng) return;
Bitmap bmp = new Bitmap(stream); Bitmap bmp = Platform.ReadBmp32Bpp(Drawer, data);
if (!Platform.Is32Bpp(bmp))
Drawer.ConvertTo32Bpp(ref bmp);
Drawer.SetFontBitmap(bmp); Drawer.SetFontBitmap(bmp);
useBitmappedFont = !Options.GetBool(OptionsKey.ArialChatFont, false); useBitmappedFont = !Options.GetBool(OptionsKey.ArialChatFont, false);
fontPng = true; fontPng = true;
} else if (filename == "terrain.png") { } else if (filename == "terrain.png") {
if (terrainPng) return; if (terrainPng) return;
Bitmap bmp = new Bitmap(stream); Bitmap bmp = Platform.ReadBmp32Bpp(Drawer, data);
if (!Platform.Is32Bpp(bmp))
Drawer.ConvertTo32Bpp(ref bmp);
MakeClassicTextures(bmp); MakeClassicTextures(bmp);
bmp.Dispose(); bmp.Dispose();
terrainPng = true; terrainPng = true;
@ -80,7 +72,7 @@ namespace Launcher {
void MakeClassicTextures(Bitmap bmp) { void MakeClassicTextures(Bitmap bmp) {
int elemSize = bmp.Width / 16; int elemSize = bmp.Width / 16;
Size size = new Size(tileSize, tileSize); Size size = new Size(tileSize, tileSize);
terrainBmp = new Bitmap(tileSize * 2, tileSize); terrainBmp = Platform.CreateBmp(tileSize * 2, tileSize);
terrainPixels = new FastBitmap(terrainBmp, true, false); terrainPixels = new FastBitmap(terrainBmp, true, false);
// Precompute the scaled background // Precompute the scaled background

View File

@ -2,6 +2,7 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using ClassicalSharp;
namespace Launcher.Patcher { namespace Launcher.Patcher {
@ -29,7 +30,7 @@ namespace Launcher.Patcher {
unsafe void PatchDefault(byte[] data, int y) { unsafe void PatchDefault(byte[] data, int y) {
// Sadly files in modern are 24 rgb, so we can't use fastbitmap here // Sadly files in modern are 24 rgb, so we can't use fastbitmap here
using (Bitmap bmp = new Bitmap(new MemoryStream(data))) { using (Bitmap bmp = Platform.ReadBmp32Bpp(drawer, data)) {
for (int tile = 0; tile < bmp.Height; tile += 16) { for (int tile = 0; tile < bmp.Height; tile += 16) {
CopyTile(tile, tile, y, bmp); CopyTile(tile, tile, y, bmp);
} }
@ -37,7 +38,7 @@ namespace Launcher.Patcher {
} }
unsafe void PatchCycle(byte[] data, int y) { unsafe void PatchCycle(byte[] data, int y) {
using (Bitmap bmp = new Bitmap(new MemoryStream(data))) { using (Bitmap bmp = Platform.ReadBmp32Bpp(drawer, data)) {
int dst = 0; int dst = 0;
for (int tile = 0; tile < bmp.Height; tile += 16, dst += 16) { for (int tile = 0; tile < bmp.Height; tile += 16, dst += 16) {
CopyTile(tile, dst, y, bmp); CopyTile(tile, dst, y, bmp);

View File

@ -11,14 +11,17 @@ namespace Launcher.Patcher {
public partial class ResourcePatcher { public partial class ResourcePatcher {
public ResourcePatcher(ResourceFetcher fetcher) { public ResourcePatcher(ResourceFetcher fetcher, IDrawer2D drawer) {
jarClassic = fetcher.jarClassic; jarClassic = fetcher.jarClassic;
jar162 = fetcher.jar162; jar162 = fetcher.jar162;
pngTerrainPatch = fetcher.pngTerrainPatch; pngTerrainPatch = fetcher.pngTerrainPatch;
pngGuiPatch = fetcher.pngGuiPatch; pngGuiPatch = fetcher.pngGuiPatch;
this.drawer = drawer;
} }
ZipReader reader; ZipReader reader;
ZipWriter writer; ZipWriter writer;
IDrawer2D drawer;
Bitmap animBitmap; Bitmap animBitmap;
List<string> existing = new List<string>(); List<string> existing = new List<string>();
@ -40,8 +43,8 @@ namespace Launcher.Patcher {
ExtractClassic(); ExtractClassic();
ExtractModern(); ExtractModern();
if (pngGuiPatch != null) { if (pngGuiPatch != null) {
using (Bitmap guiBitmap = new Bitmap(new MemoryStream(pngGuiPatch))) using (Bitmap gui = Platform.ReadBmp32Bpp(drawer, pngGuiPatch))
writer.WriteNewImage(guiBitmap, "gui.png"); writer.WriteNewImage(gui, "gui.png");
} }
writer.WriteCentralDirectoryRecords(); writer.WriteCentralDirectoryRecords();
} }
@ -100,10 +103,10 @@ namespace Launcher.Patcher {
writer.WriteZipEntry(entry, data); writer.WriteZipEntry(entry, data);
return; return;
} else if (!existing.Contains("terrain.png")){ } else if (!existing.Contains("terrain.png")){
using (Bitmap dstBitmap = new Bitmap(new MemoryStream(data)), using (Bitmap dst = Platform.ReadBmp32Bpp(drawer, data),
maskBitmap = new Bitmap(new MemoryStream(pngTerrainPatch))) { mask = Platform.ReadBmp32Bpp(drawer, pngTerrainPatch)) {
PatchImage(dstBitmap, maskBitmap); PatchImage(dst, mask);
writer.WriteNewImage(dstBitmap, "terrain.png"); writer.WriteNewImage(dst, "terrain.png");
} }
} }
} }
@ -117,7 +120,7 @@ namespace Launcher.Patcher {
using (Stream src = new MemoryStream(jar162)) { using (Stream src = new MemoryStream(jar162)) {
// Grab animations and snow // Grab animations and snow
animBitmap = new Bitmap(1024, 64, PixelFormat.Format32bppArgb); animBitmap = Platform.CreateBmp(1024, 64);
reader.ShouldProcessZipEntry = ShouldProcessZipEntry_Modern; reader.ShouldProcessZipEntry = ShouldProcessZipEntry_Modern;
reader.ProcessZipEntry = ProcessZipEntry_Modern; reader.ProcessZipEntry = ProcessZipEntry_Modern;
reader.Extract(src); reader.Extract(src);