Skip to content

Commit

Permalink
Refactor TRImage (LostArtefacts#660)
Browse files Browse the repository at this point in the history
  • Loading branch information
lahm86 authored May 5, 2024
1 parent 80feae9 commit d1eae90
Show file tree
Hide file tree
Showing 52 changed files with 1,382 additions and 1,122 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ private List<EMTextureMap> BuildAndPackTextures<E, L>(TRTexturePacker<E, L> pack
Index = data.Background,
Texture = textures[data.Background]
};
TRImage tile = packer.Tiles[indexedTexture.Atlas].BitmapGraphics;
TRImage clip = new(tile.Extract(indexedTexture.Bounds));
clip.Overlay(new Bitmap(data.Overlay));
TRImage tile = packer.Tiles[indexedTexture.Atlas].Image;
TRImage clip = tile.Export(indexedTexture.Bounds);
clip.Overlay(new(data.Overlay));

IndexedTRObjectTexture texture = CreateTexture(clip.Bitmap.Size);
TexturedTileSegment segment = new(texture, clip.Bitmap);
IndexedTRObjectTexture texture = CreateTexture(clip.Size);
TexturedTileSegment segment = new(texture, clip);
packer.AddRectangle(segment);

mappings.Add(new()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ public class EMImportTextureFunction : BaseEMFunction

public override void ApplyToLevel(TR1Level level)
{
using TRImage bg = new(new Bitmap(Bitmap));
TRImage textile = new(Bitmap);
List<Color> palette = level.Palette.Select(c => c.ToTR1Color()).ToList();
Rectangle size = new(0, 0, bg.Bitmap.Width, bg.Bitmap.Height);
bg.Scan(size, (c, x, y) =>
textile.Read((c, x, y) =>
{
int colIndex;
if (c.A == 0)
Expand All @@ -27,27 +26,26 @@ public override void ApplyToLevel(TR1Level level)
else
{
colIndex = TRPalette8Control.FindClosestColour(c, palette);
c = palette[colIndex];
}

level.Images8[Tile].Pixels[(y + Y) * TRConsts.TPageWidth + x + X] = (byte)colIndex;
return c;
});
}

public override void ApplyToLevel(TR2Level level)
{
using TRImage bg = new(level.Images16[Tile].ToBitmap());
using Bitmap bmp = new(Bitmap);
bg.Import(bmp, new Rectangle(X, Y, bmp.Width, bmp.Height));
level.Images16[Tile].Pixels = TextureUtilities.ImportFromBitmap(bg.Bitmap);
Import(level.Images16);
}

public override void ApplyToLevel(TR3Level level)
{
using TRImage bg = new(level.Images16[Tile].ToBitmap());
using Bitmap bmp = new(Bitmap);
bg.Import(bmp, new Rectangle(X, Y, bmp.Width, bmp.Height));
level.Images16[Tile].Pixels = TextureUtilities.ImportFromBitmap(bg.Bitmap);
Import(level.Images16);
}

private void Import(List<TRTexImage16> images)
{
TRImage textile = new(images[Tile].Pixels);
textile.Import(new(Bitmap), new(X, Y));
images[Tile].Pixels = textile.ToRGB555();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class EMOverwriteTextureFunction : BaseEMFunction, ITextureModifier

public override void ApplyToLevel(TR1Level level)
{
using TR1TexturePacker packer = new(level);
TR1TexturePacker packer = new(level);
ApplyOverwrites(texture =>
{
return packer.GetObjectTextureSegments(new List<int> { texture })
Expand All @@ -24,7 +24,7 @@ public override void ApplyToLevel(TR1Level level)

public override void ApplyToLevel(TR2Level level)
{
using TR2TexturePacker packer = new(level);
TR2TexturePacker packer = new(level);
ApplyOverwrites(texture =>
{
return packer.GetObjectTextureSegments(new List<int> { texture })
Expand All @@ -37,7 +37,7 @@ public override void ApplyToLevel(TR2Level level)

public override void ApplyToLevel(TR3Level level)
{
using TR3TexturePacker packer = new(level);
TR3TexturePacker packer = new(level);
ApplyOverwrites(texture =>
{
return packer.GetObjectTextureSegments(new List<int> { texture })
Expand Down Expand Up @@ -73,20 +73,17 @@ private void ApplyOverwrites(Func<ushort, Tuple<TexturedTile, TexturedTileSegmen
foreach (TextureOverwrite overwrite in Overwrites)
{
Tuple<TexturedTile, TexturedTileSegment> segment = segmentAction(overwrite.Texture);
TRImage segmentBmp = new(segment.Item2.Bitmap);
Bitmap clipBmp = segmentBmp.Extract(overwrite.Clip);
TRImage clippedImage = segment.Item2.Image.Export(overwrite.Clip);

foreach (ushort targetTexture in overwrite.Targets.Keys)
{
Tuple<TexturedTile, TexturedTileSegment> targetSegment = segmentAction(targetTexture);
foreach (Point point in overwrite.Targets[targetTexture])
{
targetSegment.Item1.BitmapGraphics.Import(clipBmp, new Rectangle
targetSegment.Item1.Image.Import(clippedImage, new
(
targetSegment.Item2.Bounds.X + point.X,
targetSegment.Item2.Bounds.Y + point.Y,
clipBmp.Width,
clipBmp.Height
targetSegment.Item2.Bounds.Y + point.Y
), overwrite.RetainBackground);
}
}
Expand Down
4 changes: 2 additions & 2 deletions TRDataControl/Events/SegmentEventArgs.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System.Drawing;
using TRImageControl;

namespace TRModelTransporter.Events;

public class SegmentEventArgs : EventArgs
{
public int SegmentIndex { get; set; }
public Bitmap Bitmap { get; set; }
public TRImage Image { get; set; }
}
14 changes: 6 additions & 8 deletions TRDataControl/Handlers/Textures/AbstractTextureExportHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,9 @@ public void Export(L level, D definition, ITextureClassifier classifier, IEnumer

_allSegments = new List<TexturedTileSegment>();

using (_packer = CreatePacker())
{
CollateSegments();
ExportSegments();
}
_packer = CreatePacker();
CollateSegments();
ExportSegments();
}

protected abstract TRTexturePacker<E, L> CreatePacker();
Expand Down Expand Up @@ -108,7 +106,7 @@ protected virtual void ExportSegments()
return;
}

using DefaultTexturePacker segmentPacker = new();
DefaultTexturePacker segmentPacker = new();
segmentPacker.AddRectangles(_allSegments);

segmentPacker.Options = new PackingOptions
Expand Down Expand Up @@ -139,14 +137,14 @@ protected virtual void ExportSegments()
_definition.TextureSegments = rects.ToArray();

Rectangle region = tile.GetOccupiedRegion();
_definition.Bitmap = tile.BitmapGraphics.Extract(region);
_definition.Image = tile.Image.Export(region);

foreach (TexturedTileSegment segment in _allSegments)
{
SegmentExported?.Invoke(this, new SegmentEventArgs
{
SegmentIndex = segment.FirstTextureIndex,
Bitmap = segment.Bitmap
Image = segment.Image
});
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using RectanglePacker.Events;
using System.Drawing;
using TRImageControl.Packing;
using TRLevelControl.Model;
using TRModelTransporter.Data;
Expand Down Expand Up @@ -79,10 +78,9 @@ protected virtual void CollateSegments()
}

_importSegments[definition] = new List<TexturedTileSegment>();
using TRImage bg = new(definition.Bitmap);
foreach (int segmentIndex in definition.ObjectTextures.Keys)
{
Bitmap segmentClip = bg.Extract(definition.TextureSegments[segmentIndex]);
TRImage segmentClip = definition.Image.Export(definition.TextureSegments[segmentIndex]);
TexturedTileSegment segment = null;
foreach (IndexedTRObjectTexture texture in definition.ObjectTextures[segmentIndex])
{
Expand Down Expand Up @@ -117,7 +115,7 @@ protected virtual void CollateSegments()
Dictionary<int, List<IndexedTRSpriteTexture>> spriteTextures = definition.SpriteTextures[spriteEntity];
foreach (int segmentIndex in spriteTextures.Keys)
{
Bitmap segmentClip = bg.Extract(definition.TextureSegments[segmentIndex]);
TRImage segmentClip = definition.Image.Export(definition.TextureSegments[segmentIndex]);
TexturedTileSegment segment = null;
foreach (IndexedTRSpriteTexture texture in spriteTextures[segmentIndex])
{
Expand All @@ -137,7 +135,7 @@ protected virtual void CollateSegments()

protected virtual PackingResult<TexturedTile, TexturedTileSegment> Pack()
{
using TRTexturePacker<E, L> packer = CreatePacker();
TRTexturePacker<E, L> packer = CreatePacker();
packer.MaximumTiles = Data.TextureTileLimit;

ProcessRemovals(packer);
Expand Down
11 changes: 3 additions & 8 deletions TRDataControl/Model/TRBlobBase.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
using Newtonsoft.Json;
using System.Drawing;
using TRImageControl;
using TRImageControl.Packing;
using TRLevelControl.Model;

namespace TRModelTransporter.Model;

public abstract class TRBlobBase<E> : IDisposable where E : Enum
public abstract class TRBlobBase<E> where E : Enum
{
[JsonIgnore]
public E Entity { get; set; }
[JsonIgnore]
public E Alias { get; set; }
[JsonIgnore]
public Bitmap Bitmap { get; set; }
public TRImage Image { get; set; }
[JsonIgnore]
public bool HasGraphics => ObjectTextures.Count > 0;
[JsonIgnore]
Expand All @@ -23,10 +24,4 @@ public abstract class TRBlobBase<E> : IDisposable where E : Enum
public Dictionary<E, Dictionary<int, List<IndexedTRSpriteTexture>>> SpriteTextures { get; set; }
public Dictionary<E, TRSpriteSequence> SpriteSequences { get; set; }
public Rectangle[] TextureSegments { get; set; }

public void Dispose()
{
Bitmap?.Dispose();
GC.SuppressFinalize(this);
}
}
1 change: 0 additions & 1 deletion TRDataControl/Transport/TR1/TR1DataImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ protected override void Import(IEnumerable<TR1Blob> standardDefinitions, IEnumer
if (!IgnoreGraphics)
{
_textureHandler.ResetUnusedTextures();
PaletteManager.Dispose();
}
}
}
2 changes: 1 addition & 1 deletion TRDataControl/Transport/TRDataExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public D Export(L level, E entity)

_textureHandler.SegmentExported += segmentDelegate = delegate (object sender, SegmentEventArgs e)
{
e.Bitmap.Save(Path.Combine(segmentDir, e.SegmentIndex + ".png"), ImageFormat.Png);
e.Image.Save(Path.Combine(segmentDir, e.SegmentIndex + ".png"), ImageFormat.Png);
};

duplicateClips = new List<StaticTextureTarget>();
Expand Down
13 changes: 2 additions & 11 deletions TRDataControl/Transport/TRDataImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,9 @@ public void Import()
});
}

try
if (standardModelDefinitions.Count + soundModelDefinitions.Count > 0)
{
if (standardModelDefinitions.Count + soundModelDefinitions.Count > 0)
{
Import(standardModelDefinitions, soundModelDefinitions);
}
}
finally
{
// Bitmap cleanup
standardModelDefinitions.ForEach(d => d.Dispose());
soundModelDefinitions.ForEach(d => d.Dispose());
Import(standardModelDefinitions, soundModelDefinitions);
}
}

Expand Down
5 changes: 2 additions & 3 deletions TRDataControl/Transport/TRDataTransport.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Newtonsoft.Json;
using System.Drawing;
using System.Drawing.Imaging;
using TRModelTransporter.Data;
using TRModelTransporter.Handlers;
Expand Down Expand Up @@ -48,7 +47,7 @@ protected void StoreDefinition(D definition)

if (definition.HasGraphics)
{
definition.Bitmap.Save(Path.Combine(directory, _imageFileName), ImageFormat.Png);
definition.Image.Save(Path.Combine(directory, _imageFileName), ImageFormat.Png);
}
File.WriteAllText(Path.Combine(directory, _dataFileName), JsonConvert.SerializeObject(definition, Formatting.None));
}
Expand All @@ -73,7 +72,7 @@ public D LoadDefinition(E modelEntity)
{
throw new IOException(string.Format("Missing model data image file ({0})", imageFilePath));
}
definition.Bitmap = new Bitmap(imageFilePath);
definition.Image = new(imageFilePath);
}
return definition;
}
Expand Down
4 changes: 2 additions & 2 deletions TRDataControl/Utilities/AbstractMassTRTextureDeduplicator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public void Export()

private void ExportDuplicateLevelTextures(string lvlPath)
{
using TRTexturePacker<E, L> levelPacker = CreatePacker(ReadLevel(lvlPath));
TRTexturePacker<E, L> levelPacker = CreatePacker(ReadLevel(lvlPath));
Dictionary<TexturedTile, List<TexturedTileSegment>> allTextures = new();
foreach (TexturedTile tile in levelPacker.Tiles)
{
Expand All @@ -80,7 +80,7 @@ private void ExportDuplicateLevelTextures(string lvlPath)
Directory.CreateDirectory(dir);
foreach (TexturedTile tile in allTextures.Keys)
{
tile.BitmapGraphics.Bitmap.Save(Path.Combine(dir, tile.Index.ToString() + ".png"), ImageFormat.Png);
tile.Image.Save(Path.Combine(dir, tile.Index.ToString() + ".png"), ImageFormat.Png);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public AbstractTRLevelTextureDeduplicator()

public void Deduplicate(string remappingPath)
{
using TRTexturePacker<E, L> levelPacker = CreatePacker(Level);
TRTexturePacker<E, L> levelPacker = CreatePacker(Level);
Dictionary<TexturedTile, List<TexturedTileSegment>> allTextures = new();
foreach (TexturedTile tile in levelPacker.Tiles)
{
Expand Down
21 changes: 3 additions & 18 deletions TRDataControl/Utilities/TRTextureDeduplicator.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Drawing;
using System.Drawing.Imaging;
using TRImageControl;
using TRImageControl.Packing;

namespace TRModelTransporter.Utilities;
Expand Down Expand Up @@ -188,8 +188,8 @@ private void ProcessRemap(MappedSegment originalSegment, MappedSegment candidate
for (int y = 0; y <= yEnd; y++)
{
rect.Y = y;
using Bitmap bmp = containerSegment.Segment.Bitmap.Clone(rect, PixelFormat.Format32bppArgb);
if (CompareBitmaps(segmentToLocate.Segment.Bitmap, bmp))
TRImage bmp = containerSegment.Segment.Image.Export(rect);
if (segmentToLocate.Segment.Image.Equals(bmp))
{
return new Point(x, y);
}
Expand All @@ -198,21 +198,6 @@ private void ProcessRemap(MappedSegment originalSegment, MappedSegment candidate
return null;
}

private static bool CompareBitmaps(Bitmap bmp1, Bitmap bmp2)
{
for (int x = 0; x < bmp1.Width; x++)
{
for (int y = 0; y < bmp1.Height; y++)
{
if (bmp1.GetPixel(x, y) != bmp2.GetPixel(x, y))
{
return false;
}
}
}
return true;
}

private void RemoveStaleSegments()
{
foreach (TexturedTile tile in _segmentRemovalPositions.Keys)
Expand Down
Loading

0 comments on commit d1eae90

Please sign in to comment.