mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-23 04:12:12 +00:00
Export selection to image: added option to scale the output image to a higher resolution
This commit is contained in:
parent
cf61c74e35
commit
f2f0e1bae1
4 changed files with 93 additions and 22 deletions
|
@ -674,7 +674,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
ImageExportSettingsForm form = new ImageExportSettingsForm();
|
ImageExportSettingsForm form = new ImageExportSettingsForm();
|
||||||
if (form.ShowDialog() == DialogResult.OK)
|
if (form.ShowDialog() == DialogResult.OK)
|
||||||
{
|
{
|
||||||
ImageExportSettings settings = new ImageExportSettings(Path.GetDirectoryName(form.FilePath), Path.GetFileNameWithoutExtension(form.FilePath), Path.GetExtension(form.FilePath), form.Floor, form.Fullbright, form.Brightmap, form.Tiles, form.GetPixelFormat(), form.GetImageFormat());
|
ImageExportSettings settings = new ImageExportSettings(Path.GetDirectoryName(form.FilePath), Path.GetFileNameWithoutExtension(form.FilePath), Path.GetExtension(form.FilePath), form.Floor, form.Fullbright, form.Brightmap, form.Tiles, form.ImageScale, form.GetPixelFormat(), form.GetImageFormat());
|
||||||
ImageExporter exporter = new ImageExporter(sectors, settings);
|
ImageExporter exporter = new ImageExporter(sectors, settings);
|
||||||
|
|
||||||
string text = "The following images will be created:\n\n" + string.Join("\n", exporter.GetImageNames());
|
string text = "The following images will be created:\n\n" + string.Join("\n", exporter.GetImageNames());
|
||||||
|
|
|
@ -50,8 +50,9 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
public bool Tiles;
|
public bool Tiles;
|
||||||
public PixelFormat PixelFormat;
|
public PixelFormat PixelFormat;
|
||||||
public ImageFormat ImageFormat;
|
public ImageFormat ImageFormat;
|
||||||
|
public float Scale;
|
||||||
|
|
||||||
public ImageExportSettings(string path, string name, string extension, bool floor, bool fullbright, bool brightmap, bool tiles, PixelFormat pformat, ImageFormat iformat)
|
public ImageExportSettings(string path, string name, string extension, bool floor, bool fullbright, bool brightmap, bool tiles, float scale, PixelFormat pformat, ImageFormat iformat)
|
||||||
{
|
{
|
||||||
Path = path;
|
Path = path;
|
||||||
Name = name;
|
Name = name;
|
||||||
|
@ -62,6 +63,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
Fullbright = fullbright;
|
Fullbright = fullbright;
|
||||||
PixelFormat = pformat;
|
PixelFormat = pformat;
|
||||||
ImageFormat = iformat;
|
ImageFormat = iformat;
|
||||||
|
Scale = scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,10 +107,10 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
GetSizeAndOffset(out size, out offset);
|
GetSizeAndOffset(out size, out offset);
|
||||||
|
|
||||||
// Use the same image for the normal texture and the brightmap because of memory concerns
|
// Use the same image for the normal texture and the brightmap because of memory concerns
|
||||||
using (Bitmap image = new Bitmap((int)size.x, (int)size.y, settings.PixelFormat))
|
using (Bitmap image = new Bitmap((int)(size.x * settings.Scale), (int)(size.y * settings.Scale), settings.PixelFormat))
|
||||||
{
|
{
|
||||||
// Normal texture image
|
// Normal texture image
|
||||||
CreateImage(image, offset, false);
|
CreateImage(image, offset, settings.Scale, false);
|
||||||
|
|
||||||
if (settings.Tiles)
|
if (settings.Tiles)
|
||||||
SaveImageAsTiles(image);
|
SaveImageAsTiles(image);
|
||||||
|
@ -118,7 +120,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
// The brightmap
|
// The brightmap
|
||||||
if (settings.Brightmap)
|
if (settings.Brightmap)
|
||||||
{
|
{
|
||||||
CreateImage(image, offset, true);
|
CreateImage(image, offset, settings.Scale, true);
|
||||||
|
|
||||||
if (settings.Tiles)
|
if (settings.Tiles)
|
||||||
SaveImageAsTiles(image, "_brightmap");
|
SaveImageAsTiles(image, "_brightmap");
|
||||||
|
@ -135,7 +137,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
/// <param name="offset">The offset of the selection in map space</param>
|
/// <param name="offset">The offset of the selection in map space</param>
|
||||||
/// <param name="asbrightmap">True if the image should be a brightmap, false if normally textured</param>
|
/// <param name="asbrightmap">True if the image should be a brightmap, false if normally textured</param>
|
||||||
/// <returns>The image to be exported</returns>
|
/// <returns>The image to be exported</returns>
|
||||||
private void CreateImage(Bitmap texturebitmap, Vector2D offset, bool asbrightmap)
|
private void CreateImage(Bitmap texturebitmap, Vector2D offset, float scale, bool asbrightmap)
|
||||||
{
|
{
|
||||||
Graphics gtexture = null;
|
Graphics gtexture = null;
|
||||||
|
|
||||||
|
@ -161,9 +163,9 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
for (int i = 0; i < s.Triangles.Vertices.Count / 3; i++)
|
for (int i = 0; i < s.Triangles.Vertices.Count / 3; i++)
|
||||||
{
|
{
|
||||||
// The GDI image has the 0/0 coordinate in the top left, so invert the y component
|
// The GDI image has the 0/0 coordinate in the top left, so invert the y component
|
||||||
Vector2D v1 = s.Triangles.Vertices[i * 3] - offset; v1.y *= -1.0;
|
Vector2D v1 = (s.Triangles.Vertices[i * 3] - offset) * scale; v1.y *= -1.0;
|
||||||
Vector2D v2 = s.Triangles.Vertices[i * 3 + 1] - offset; v2.y *= -1.0;
|
Vector2D v2 = (s.Triangles.Vertices[i * 3 + 1] - offset) * scale; v2.y *= -1.0;
|
||||||
Vector2D v3 = s.Triangles.Vertices[i * 3 + 2] - offset; v3.y *= -1.0;
|
Vector2D v3 = (s.Triangles.Vertices[i * 3 + 2] - offset) * scale; v3.y *= -1.0;
|
||||||
|
|
||||||
gpath.AddLine((float)v1.x, (float)v1.y, (float)v2.x, (float)v2.y);
|
gpath.AddLine((float)v1.x, (float)v1.y, (float)v2.x, (float)v2.y);
|
||||||
gpath.AddLine((float)v2.x, (float)v2.y, (float)v3.x, (float)v3.y);
|
gpath.AddLine((float)v2.x, (float)v2.y, (float)v3.x, (float)v3.y);
|
||||||
|
@ -188,11 +190,11 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
// but doesn't applie the color correction if we set UseColorCorrection to false first
|
// but doesn't applie the color correction if we set UseColorCorrection to false first
|
||||||
ImageData imagedata = General.Map.Data.GetFlatImage(s.FloorTexture);
|
ImageData imagedata = General.Map.Data.GetFlatImage(s.FloorTexture);
|
||||||
imagedata.UseColorCorrection = false;
|
imagedata.UseColorCorrection = false;
|
||||||
brushtexture = imagedata.LocalGetBitmap();
|
brushtexture = new Bitmap(imagedata.LocalGetBitmap());
|
||||||
imagedata.UseColorCorrection = true;
|
imagedata.UseColorCorrection = true;
|
||||||
|
|
||||||
textureoffset.x = s.Fields.GetValue("xpanningfloor", 0.0);
|
textureoffset.x = s.Fields.GetValue("xpanningfloor", 0.0) * scale;
|
||||||
textureoffset.y = s.Fields.GetValue("ypanningfloor", 0.0);
|
textureoffset.y = s.Fields.GetValue("ypanningfloor", 0.0) * scale;
|
||||||
|
|
||||||
// GZDoom uses bigger numbers for smaller scales (i.e. a scale of 2 will halve the size), so we need to change the scale
|
// GZDoom uses bigger numbers for smaller scales (i.e. a scale of 2 will halve the size), so we need to change the scale
|
||||||
texturescale.x = 1.0 / s.Fields.GetValue("xscalefloor", 1.0);
|
texturescale.x = 1.0 / s.Fields.GetValue("xscalefloor", 1.0);
|
||||||
|
@ -204,11 +206,11 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
// but doesn't applie the color correction if we set UseColorCorrection to false first
|
// but doesn't applie the color correction if we set UseColorCorrection to false first
|
||||||
ImageData imagedata = General.Map.Data.GetFlatImage(s.CeilTexture);
|
ImageData imagedata = General.Map.Data.GetFlatImage(s.CeilTexture);
|
||||||
imagedata.UseColorCorrection = false;
|
imagedata.UseColorCorrection = false;
|
||||||
brushtexture = imagedata.LocalGetBitmap();
|
brushtexture = new Bitmap(imagedata.LocalGetBitmap());
|
||||||
imagedata.UseColorCorrection = true;
|
imagedata.UseColorCorrection = true;
|
||||||
|
|
||||||
textureoffset.x = s.Fields.GetValue("xpanningceiling", 0.0);
|
textureoffset.x = s.Fields.GetValue("xpanningceiling", 0.0) * scale;
|
||||||
textureoffset.y = s.Fields.GetValue("ypanningceiling", 0.0);
|
textureoffset.y = s.Fields.GetValue("ypanningceiling", 0.0) * scale;
|
||||||
|
|
||||||
// GZDoom uses bigger numbers for smaller scales (i.e. a scale of 2 will halve the size), so we need to change the scale
|
// GZDoom uses bigger numbers for smaller scales (i.e. a scale of 2 will halve the size), so we need to change the scale
|
||||||
texturescale.x = 1.0 / s.Fields.GetValue("xscaleceiling", 1.0);
|
texturescale.x = 1.0 / s.Fields.GetValue("xscaleceiling", 1.0);
|
||||||
|
@ -218,13 +220,16 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
// Create the transformation matrix
|
// Create the transformation matrix
|
||||||
Matrix matrix = new Matrix();
|
Matrix matrix = new Matrix();
|
||||||
matrix.Rotate(rotation);
|
matrix.Rotate(rotation);
|
||||||
matrix.Translate((float)(-offset.x * rotationvector.x), (float)(offset.x * rotationvector.y)); // Left/right offset from the map origin
|
matrix.Translate((float)(-offset.x*scale * rotationvector.x), (float)(offset.x*scale * rotationvector.y)); // Left/right offset from the map origin
|
||||||
matrix.Translate((float)(offset.y * rotationvector.y), (float)(offset.y * rotationvector.x)); // Up/down offset from the map origin
|
matrix.Translate((float)(offset.y*scale * rotationvector.y), (float)(offset.y*scale * rotationvector.x)); // Up/down offset from the map origin
|
||||||
matrix.Translate(-(float)textureoffset.x, -(float)textureoffset.y); // Texture offset
|
matrix.Translate(-(float)textureoffset.x, -(float)textureoffset.y); // Texture offset
|
||||||
matrix.Scale((float)texturescale.x, (float)texturescale.y);
|
matrix.Scale((float)texturescale.x, (float)texturescale.y);
|
||||||
|
|
||||||
if (!settings.Fullbright)
|
if (!settings.Fullbright)
|
||||||
AdjustBrightness(brushtexture, s.Brightness > 0 ? s.Brightness / 255.0f : 0.0f);
|
AdjustBrightness(ref brushtexture, s.Brightness > 0 ? s.Brightness / 255.0f : 0.0f);
|
||||||
|
|
||||||
|
if (scale > 1.0f)
|
||||||
|
ResizeImage(ref brushtexture, brushtexture.Width * (int)scale, brushtexture.Height * (int)scale);
|
||||||
|
|
||||||
// Create the texture brush and apply the matrix
|
// Create the texture brush and apply the matrix
|
||||||
TextureBrush tbrush = new TextureBrush(brushtexture);
|
TextureBrush tbrush = new TextureBrush(brushtexture);
|
||||||
|
@ -367,7 +372,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="image">The image to adjust</param>
|
/// <param name="image">The image to adjust</param>
|
||||||
/// <param name="brightness">Brightness between 0.0f and 1.0f</param>
|
/// <param name="brightness">Brightness between 0.0f and 1.0f</param>
|
||||||
private void AdjustBrightness(Image image, float brightness)
|
private void AdjustBrightness(ref Bitmap image, float brightness)
|
||||||
{
|
{
|
||||||
// Make the ColorMatrix.
|
// Make the ColorMatrix.
|
||||||
float b = brightness;
|
float b = brightness;
|
||||||
|
@ -403,6 +408,40 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
image = bm;
|
image = bm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resize the image to the specified width and height. Taken from https://stackoverflow.com/a/24199315 (with some modifications)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="image">The image to resize.</param>
|
||||||
|
/// <param name="width">The width to resize to.</param>
|
||||||
|
/// <param name="height">The height to resize to.</param>
|
||||||
|
/// <returns>The resized image.</returns>
|
||||||
|
private void ResizeImage(ref Bitmap image, int width, int height)
|
||||||
|
{
|
||||||
|
var destRect = new Rectangle(0, 0, width, height);
|
||||||
|
var destImage = new Bitmap(width, height);
|
||||||
|
|
||||||
|
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
|
||||||
|
|
||||||
|
using (var graphics = Graphics.FromImage(destImage))
|
||||||
|
{
|
||||||
|
graphics.CompositingMode = CompositingMode.SourceCopy;
|
||||||
|
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||||
|
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||||
|
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||||
|
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||||
|
|
||||||
|
using (var wrapMode = new ImageAttributes())
|
||||||
|
{
|
||||||
|
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
|
||||||
|
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
image.Dispose();
|
||||||
|
|
||||||
|
image = destImage;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,8 @@
|
||||||
this.cbFullbright = new System.Windows.Forms.CheckBox();
|
this.cbFullbright = new System.Windows.Forms.CheckBox();
|
||||||
this.cbBrightmap = new System.Windows.Forms.CheckBox();
|
this.cbBrightmap = new System.Windows.Forms.CheckBox();
|
||||||
this.cbTiles = new System.Windows.Forms.CheckBox();
|
this.cbTiles = new System.Windows.Forms.CheckBox();
|
||||||
|
this.cbScale = new System.Windows.Forms.ComboBox();
|
||||||
|
this.label4 = new System.Windows.Forms.Label();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// tbExportPath
|
// tbExportPath
|
||||||
|
@ -194,6 +196,29 @@
|
||||||
this.cbTiles.Text = "Create 64x64 tiles";
|
this.cbTiles.Text = "Create 64x64 tiles";
|
||||||
this.cbTiles.UseVisualStyleBackColor = true;
|
this.cbTiles.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
|
// cbScale
|
||||||
|
//
|
||||||
|
this.cbScale.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||||
|
this.cbScale.FormattingEnabled = true;
|
||||||
|
this.cbScale.Items.AddRange(new object[] {
|
||||||
|
"100%",
|
||||||
|
"200%",
|
||||||
|
"400%",
|
||||||
|
"800%"});
|
||||||
|
this.cbScale.Location = new System.Drawing.Point(102, 89);
|
||||||
|
this.cbScale.Name = "cbScale";
|
||||||
|
this.cbScale.Size = new System.Drawing.Size(71, 21);
|
||||||
|
this.cbScale.TabIndex = 17;
|
||||||
|
//
|
||||||
|
// label4
|
||||||
|
//
|
||||||
|
this.label4.AutoSize = true;
|
||||||
|
this.label4.Location = new System.Drawing.Point(12, 92);
|
||||||
|
this.label4.Name = "label4";
|
||||||
|
this.label4.Size = new System.Drawing.Size(37, 13);
|
||||||
|
this.label4.TabIndex = 18;
|
||||||
|
this.label4.Text = "Scale:";
|
||||||
|
//
|
||||||
// ImageExportSettingsForm
|
// ImageExportSettingsForm
|
||||||
//
|
//
|
||||||
this.AcceptButton = this.export;
|
this.AcceptButton = this.export;
|
||||||
|
@ -201,6 +226,8 @@
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.CancelButton = this.cancel;
|
this.CancelButton = this.cancel;
|
||||||
this.ClientSize = new System.Drawing.Size(447, 188);
|
this.ClientSize = new System.Drawing.Size(447, 188);
|
||||||
|
this.Controls.Add(this.label4);
|
||||||
|
this.Controls.Add(this.cbScale);
|
||||||
this.Controls.Add(this.cbTiles);
|
this.Controls.Add(this.cbTiles);
|
||||||
this.Controls.Add(this.cbBrightmap);
|
this.Controls.Add(this.cbBrightmap);
|
||||||
this.Controls.Add(this.cbFullbright);
|
this.Controls.Add(this.cbFullbright);
|
||||||
|
@ -242,5 +269,7 @@
|
||||||
private System.Windows.Forms.CheckBox cbFullbright;
|
private System.Windows.Forms.CheckBox cbFullbright;
|
||||||
private System.Windows.Forms.CheckBox cbBrightmap;
|
private System.Windows.Forms.CheckBox cbBrightmap;
|
||||||
private System.Windows.Forms.CheckBox cbTiles;
|
private System.Windows.Forms.CheckBox cbTiles;
|
||||||
|
private System.Windows.Forms.ComboBox cbScale;
|
||||||
|
private System.Windows.Forms.Label label4;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -44,6 +44,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Interface
|
||||||
public bool Fullbright { get { return cbFullbright.Checked; } }
|
public bool Fullbright { get { return cbFullbright.Checked; } }
|
||||||
public bool Brightmap { get { return cbBrightmap.Checked; } }
|
public bool Brightmap { get { return cbBrightmap.Checked; } }
|
||||||
public bool Tiles { get { return cbTiles.Checked; } }
|
public bool Tiles { get { return cbTiles.Checked; } }
|
||||||
|
public float ImageScale { get { return (float)Math.Pow(2, cbScale.SelectedIndex); } }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -73,6 +74,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Interface
|
||||||
cbFullbright.Checked = General.Settings.ReadPluginSetting("imageexportfullbright", true);
|
cbFullbright.Checked = General.Settings.ReadPluginSetting("imageexportfullbright", true);
|
||||||
cbBrightmap.Checked = General.Settings.ReadPluginSetting("imageexportbrightmap", false);
|
cbBrightmap.Checked = General.Settings.ReadPluginSetting("imageexportbrightmap", false);
|
||||||
cbTiles.Checked = General.Settings.ReadPluginSetting("imageexporttiles", false);
|
cbTiles.Checked = General.Settings.ReadPluginSetting("imageexporttiles", false);
|
||||||
|
cbScale.SelectedIndex = General.Settings.ReadPluginSetting("imageexportscale", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -133,9 +135,10 @@ namespace CodeImp.DoomBuilder.BuilderModes.Interface
|
||||||
|
|
||||||
private void export_Click(object sender, EventArgs e)
|
private void export_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
General.Settings.WritePluginSetting("imageexportfullbright", cbFullbright.Checked);
|
General.Settings.WritePluginSetting("imageexportfullbright", cbFullbright.Checked);
|
||||||
General.Settings.WritePluginSetting("imageexportbrightmap", cbBrightmap.Checked);
|
General.Settings.WritePluginSetting("imageexportbrightmap", cbBrightmap.Checked);
|
||||||
General.Settings.WritePluginSetting("imageexporttiles", cbTiles.Checked);
|
General.Settings.WritePluginSetting("imageexporttiles", cbTiles.Checked);
|
||||||
|
General.Settings.WritePluginSetting("imageexportscale", cbScale.SelectedIndex);
|
||||||
|
|
||||||
this.DialogResult = DialogResult.OK;
|
this.DialogResult = DialogResult.OK;
|
||||||
this.Close();
|
this.Close();
|
||||||
|
|
Loading…
Reference in a new issue