Skip to content

Commit d6efaae

Browse files
committed
import images now writes the g1 element data and thus graphics can be saved into dat now
1 parent 56ae0c1 commit d6efaae

File tree

7 files changed

+172
-89
lines changed

7 files changed

+172
-89
lines changed

Core/Objects/TrainStationObject.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-

1+
22
using System.ComponentModel;
33
using OpenLoco.ObjectEditor.Data;
44
using OpenLoco.ObjectEditor.DatFileParsing;
@@ -11,7 +11,7 @@ public enum TrainStationObjectFlags : uint8_t
1111
{
1212
None = 0,
1313
Recolourable = 1 << 0,
14-
unk1 = 1 << 1, // Has no canopy??
14+
NoGlass = 1 << 1,
1515
};
1616

1717
[TypeConverter(typeof(ExpandableObjectConverter))]

Gui/MainForm.Designer.cs

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gui/MainForm.cs

Lines changed: 67 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public MainForm()
9898
//model = new MainFormModel(logger, SettingsFile, palette);
9999

100100
var paletteBitmap = SixLabors.ImageSharp.Image.Load<Rgb24>(stream!);
101-
var palette = PaletteHelpers.PaletteFromBitmapIS(paletteBitmap);
101+
var palette = new PaletteMap(paletteBitmap);
102102
model = new MainFormModel(logger, SettingsFile, palette);
103103
}
104104

@@ -204,7 +204,7 @@ static ImageList MakeImageList(MainFormModel model, ILogger? logger = null)
204204
var objectTypes = Enum.GetValues<ObjectType>().Length;
205205
var g1TabElements = model.G1.G1Elements.Skip(Constants.G1ObjectTabsOffset).Take(objectTypes).ToList();
206206

207-
var images = CreateImages(g1TabElements, model.Palette, true, logger).ToArray();
207+
var images = CreateImages(g1TabElements, model.PaletteMap, true, logger).ToArray();
208208
imageList.Images.AddRange(images);
209209
}
210210

@@ -633,16 +633,32 @@ public void ImportImages()
633633

634634
if (fbDialog.ShowDialog() == DialogResult.OK)
635635
{
636-
currentUIObjectImages.Clear();
637636
var files = Directory.GetFiles(fbDialog.SelectedPath);
638-
var sorted = files.OrderBy(f => int.Parse(Path.GetFileNameWithoutExtension(f)[5..]));
639-
foreach (var file in sorted)
637+
var sorted = files.OrderBy(f => int.Parse(Path.GetFileNameWithoutExtension(f).Split('-')[0]));
638+
639+
if (CurrentUIObject is IUiObjectWithGraphics uiObjHasGraphics)
640640
{
641-
var img = (Bitmap)Image.FromFile(file);
642-
currentUIObjectImages.Add(img);
641+
//var g1Elements = new List<G1Element32>();
642+
var i = 0;
643+
foreach (var file in sorted)
644+
{
645+
var img = SixLabors.ImageSharp.Image.Load<Rgb24>(file);
646+
var data = model.PaletteMap.ConvertRgb24ImageToG1Data(img);
647+
var hasTransparency = data.Any(b => b == 0);
648+
var oldImage = uiObjHasGraphics.G1Elements[i++];
649+
oldImage.ImageData = model.PaletteMap.ConvertRgb24ImageToG1Data(img);
650+
//var g1Element = new G1Element32(0, (short)img.Width, (short)img.Height, oldImage.XOffset, oldImage.YOffset, hasTransparency ? G1ElementFlags.HasTransparency : G1ElementFlags.None, oldImage.ZoomOffset)
651+
//{
652+
// ImageData = model.PaletteMap.ConvertRgb24ImageToG1Data(img)
653+
//};
654+
//g1Elements.Add(g1Element);
655+
}
656+
657+
//uiObjHasGraphics.G1Elements = g1Elements;
658+
currentUIObjectImages = CreateImages(uiObjHasGraphics.G1Elements, model.PaletteMap).ToList();
659+
RefreshImageControls();
643660
}
644661

645-
RefreshImageControls();
646662
}
647663
}
648664
}
@@ -979,8 +995,12 @@ IEnumerable<Control> CreateImageControls(IEnumerable<Bitmap> images)
979995
// todo: on these controls we could add a right_click handler to replace image with user-created one
980996
var count = 0;
981997

998+
var uiObjHasGraphics = CurrentUIObject as IUiObjectWithGraphics;
999+
1000+
int counter = 0;
9821001
foreach (var img in images)
9831002
{
1003+
var ele = uiObjHasGraphics.G1Elements[counter++];
9841004
var panel = new FlowLayoutPanel
9851005
{
9861006
AutoSize = true,
@@ -1002,8 +1022,8 @@ IEnumerable<Control> CreateImageControls(IEnumerable<Bitmap> images)
10021022
var text = GetImageName(CurrentUIObject, count);
10031023
var tb = new TextBox
10041024
{
1005-
Text = GetImageName(CurrentUIObject, count),
1006-
Dock = DockStyle.Top
1025+
Text = GetImageName(CurrentUIObject, count) + $" - {ele}",
1026+
Dock = DockStyle.Top,
10071027
};
10081028
var size = TextRenderer.MeasureText(text, tb.Font);
10091029
tb.MinimumSize = new Size(size.Width, 16);
@@ -1017,11 +1037,11 @@ IEnumerable<Control> CreateImageControls(IEnumerable<Bitmap> images)
10171037
}
10181038
}
10191039

1020-
static IEnumerable<Bitmap> CreateImages(List<G1Element32> G1Elements, SixLabors.ImageSharp.Color[] palette, bool useTransparency = false, ILogger? logger = null)
1040+
static IEnumerable<Bitmap> CreateImages(List<G1Element32> G1Elements, PaletteMap paletteMap, bool useTransparency = false, ILogger? logger = null)
10211041
{
1022-
if (palette is null)
1042+
if (paletteMap is null)
10231043
{
1024-
logger.Error("Palette was empty; please load a valid palette file");
1044+
logger?.Error("Palette was empty; please load a valid palette file");
10251045
yield break;
10261046
}
10271047

@@ -1036,35 +1056,38 @@ static IEnumerable<Bitmap> CreateImages(List<G1Element32> G1Elements, SixLabors.
10361056

10371057
if (currElement.Flags.HasFlag(G1ElementFlags.IsR8G8B8Palette))
10381058
{
1039-
var imageData = currElement.ImageData;
1040-
var dstImg = new Bitmap(currElement.Width, currElement.Height);
1041-
var rect = new Rectangle(0, 0, currElement.Width, currElement.Height);
1042-
var dstImgData = dstImg.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
1043-
1044-
var k = 0;
1045-
for (var j = 0; j < currElement.Width; ++j) // += 4 for a 32-bit ptr++
1046-
{
1047-
var b = imageData[k++];
1048-
var g = imageData[k++];
1049-
var r = imageData[k++];
1050-
ImageHelpers.SetPixel(dstImgData, j, 1, Color.FromArgb(r, g, b));
1051-
}
1052-
1053-
dstImg.UnlockBits(dstImgData);
1054-
yield return dstImg;
1059+
var bmp = G1RGBToBitmap(currElement);
1060+
yield return bmp;
10551061
}
10561062
else
10571063
{
1058-
var bmp = G1ElementToBitmap(currElement, palette, useTransparency);
1059-
if (bmp != null)
1060-
{
1061-
yield return bmp;
1062-
}
1064+
var bmp = G1IndexedToBitmap(currElement, paletteMap, useTransparency);
1065+
yield return bmp;
10631066
}
10641067
}
10651068
}
10661069

1067-
static Bitmap? G1ElementToBitmap(G1Element32 currElement, SixLabors.ImageSharp.Color[] palette, bool useTransparency = false)
1070+
static Bitmap G1RGBToBitmap(G1Element32 currElement)
1071+
{
1072+
var imageData = currElement.ImageData;
1073+
var bmp = new Bitmap(currElement.Width, currElement.Height);
1074+
var rect = new Rectangle(0, 0, currElement.Width, currElement.Height);
1075+
var dstImgData = bmp.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
1076+
1077+
var k = 0;
1078+
for (var j = 0; j < currElement.Width; ++j) // += 4 for a 32-bit ptr++
1079+
{
1080+
var b = imageData[k++];
1081+
var g = imageData[k++];
1082+
var r = imageData[k++];
1083+
ImageHelpers.SetPixel(dstImgData, j, 1, Color.FromArgb(r, g, b));
1084+
}
1085+
1086+
bmp.UnlockBits(dstImgData);
1087+
return bmp;
1088+
}
1089+
1090+
static Bitmap G1IndexedToBitmap(G1Element32 currElement, PaletteMap paletteMap, bool useTransparency = false)
10681091
{
10691092
var imageData = currElement.ImageData;
10701093
var dstImg = new Bitmap(currElement.Width, currElement.Height);
@@ -1088,7 +1111,7 @@ static IEnumerable<Bitmap> CreateImages(List<G1Element32> G1Elements, SixLabors.
10881111
//{
10891112
// //Debugger.Break();
10901113
//}
1091-
var colour = palette[paletteIndex];
1114+
var colour = paletteMap.Palette[paletteIndex].Color;
10921115
var pixel = colour.ToPixel<Rgb24>();
10931116
ImageHelpers.SetPixel(dstImgData, x, y, Color.FromArgb(pixel.R, pixel.G, pixel.B));
10941117
}
@@ -1099,22 +1122,25 @@ static IEnumerable<Bitmap> CreateImages(List<G1Element32> G1Elements, SixLabors.
10991122
return dstImg;
11001123
}
11011124

1125+
string lastPaletteDirectory = Directory.GetCurrentDirectory();
1126+
11021127
void SelectNewPalette()
11031128
{
11041129
using (var openFileDialog = new OpenFileDialog())
11051130
{
1106-
openFileDialog.InitialDirectory = Directory.GetCurrentDirectory();
1131+
openFileDialog.InitialDirectory = lastPaletteDirectory;
11071132
openFileDialog.Filter = "Palette Image Files(*.png)|*.png|All files (*.*)|*.*";
11081133
openFileDialog.FilterIndex = 1;
11091134
openFileDialog.RestoreDirectory = true;
11101135

11111136
if (openFileDialog.ShowDialog() == DialogResult.OK && File.Exists(openFileDialog.FileName))
11121137
{
11131138
//model.PaletteFile = openFileDialog.FileName;
1114-
var paletteBitmap = (Bitmap)Image.FromFile(openFileDialog.FileName);
1115-
model.Palette = PaletteHelpers.PaletteFromBitmap(paletteBitmap);
1139+
var paletteBitmap = SixLabors.ImageSharp.Image.Load<Rgb24>(openFileDialog.FileName);
1140+
model.PaletteMap = new PaletteMap(paletteBitmap);
11161141

11171142
RefreshObjectUI();
1143+
lastPaletteDirectory = Path.GetDirectoryName(openFileDialog.FileName) ?? lastPaletteDirectory;
11181144
}
11191145
}
11201146
}
@@ -1166,7 +1192,7 @@ void RefreshObjectUI()
11661192
// return;
11671193
//}
11681194

1169-
currentUIObjectImages = CreateImages(uiLocoObj.LocoObject.G1Elements, model.Palette, logger: logger).ToList();
1195+
currentUIObjectImages = CreateImages(uiLocoObj.LocoObject.G1Elements, model.PaletteMap, logger: logger).ToList();
11701196
RefreshImageControls();
11711197
}
11721198

@@ -1206,7 +1232,7 @@ void RefreshObjectUI()
12061232
if (CurrentUIObject is UiG1 uiG1)
12071233
{
12081234
pgS5Header.SelectedObject = uiG1.G1.G1Header;
1209-
currentUIObjectImages = CreateImages(uiG1.G1.G1Elements, model.Palette).ToList();
1235+
currentUIObjectImages = CreateImages(uiG1.G1.G1Elements, model.PaletteMap).ToList();
12101236
RefreshImageControls();
12111237
}
12121238

Gui/MainFormModel.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class MainFormModel
6060
// //}
6161
//}
6262

63-
public SixLabors.ImageSharp.Color[] Palette { get; private set; }
63+
public PaletteMap PaletteMap { get; set; }
6464

6565
public G1Dat? G1 { get; set; }
6666

@@ -74,10 +74,10 @@ class MainFormModel
7474

7575
public List<string> MiscFiles { get; set; } = [];
7676

77-
public MainFormModel(ILogger logger, string settingsFile, SixLabors.ImageSharp.Color[] palette)
77+
public MainFormModel(ILogger logger, string settingsFile, PaletteMap paletteMap)
7878
{
7979
this.logger = logger;
80-
Palette = palette;
80+
PaletteMap = paletteMap;
8181

8282
LoadSettings(settingsFile);
8383

Gui/PaletteHelpers.cs

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,58 +5,41 @@ namespace OpenLoco.ObjectEditor.Gui
55
{
66
public static class PaletteHelpers
77
{
8-
//public static System.Drawing.Color[] PaletteFromBitmap(Bitmap img)
9-
//{
10-
// var palette = new System.Drawing.Color[256];
11-
// var rect = new System.Drawing.Rectangle(0, 0, img.Width, img.Height);
12-
// var imgData = img.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
13-
// for (var y = 0; y < img.Width; ++y)
14-
// {
15-
// for (var x = 0; x < img.Height; ++x)
16-
// {
17-
// palette[(y * img.Height) + x] = ImageHelpers.GetPixel(imgData, x, y);
18-
// }
19-
// }
20-
21-
// img.UnlockBits(imgData);
22-
// return palette;
23-
//}
24-
25-
public static SixLabors.ImageSharp.Color[] PaletteFromBitmapIS(Image<Rgb24> img)
8+
public static byte[] ConvertRgb24ImageToG1Data(this PaletteMap paletteMap, Image<Rgb24> img)
269
{
27-
var palette = new SixLabors.ImageSharp.Color[256];
10+
var pixels = img.Width * img.Height;
11+
var bytes = new byte[pixels];
2812

2913
for (var y = 0; y < img.Height; ++y)
3014
{
3115
for (var x = 0; x < img.Width; ++x)
3216
{
33-
palette[(y * img.Height) + x] = img[x, y];
17+
var dstIndex = (y * img.Width) + x;
18+
bytes[dstIndex] = paletteMap.ColorToPaletteIndex(img[x, y]);
3419
}
3520
}
3621

37-
return palette;
22+
return bytes;
3823
}
3924

40-
//public static byte[] Palettise(Bitmap img)
41-
//{
42-
// var pixels = img.Width * img.Height;
43-
// var bytes = new byte[pixels];
44-
45-
// var rect = new Rectangle(0, 0, img.Width, img.Height);
46-
// var imgData = img.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
25+
static byte ColorToPaletteIndex(this PaletteMap paletteMap, SixLabors.ImageSharp.Color c)
26+
{
27+
var reserved = paletteMap.ReservedColours.Where(cc => cc.Color == c);
28+
if (reserved.Any())
29+
{
30+
return reserved.Single().Index;
31+
}
4732

48-
// for (var y = 0; y < img.Height; ++y)
49-
// {
50-
// for (var x = 0; x < img.Width; ++x)
51-
// {
52-
// var paletteIndex = (y * img.Width) + x;
53-
// bytes[paletteIndex] = ColorToPaletteIndex(ImageHelpers.GetPixel(imgData, x, y));
54-
// }
55-
// }
33+
return paletteMap.ValidColours.MinBy(vc => DistanceSquared(c, vc.Color)).Index;
34+
}
5635

57-
// return bytes;
58-
//}
36+
static int DistanceSquared(SixLabors.ImageSharp.Color c1, SixLabors.ImageSharp.Color c2)
37+
{
38+
var rr = c2.ToPixel<Rgb24>().R - c1.ToPixel<Rgb24>().R;
39+
var gg = c2.ToPixel<Rgb24>().G - c1.ToPixel<Rgb24>().G;
40+
var bb = c2.ToPixel<Rgb24>().B - c1.ToPixel<Rgb24>().B;
5941

60-
//static byte ColorToPaletteIndex(Color c) => 0;
42+
return (rr * rr) + (gg * gg) + (bb * bb);
43+
}
6144
}
6245
}

0 commit comments

Comments
 (0)