Skip to content
This repository has been archived by the owner on Nov 27, 2018. It is now read-only.

Commit

Permalink
Fixed use of original data not working as intended.
Browse files Browse the repository at this point in the history
Now uses original data where possible.
Updated build.
  • Loading branch information
KFreon committed Jan 31, 2017
1 parent 1203285 commit c7e2fda
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 88 deletions.
2 changes: 1 addition & 1 deletion CSharpImageLibrary/DDS/DDSGeneral.cs
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ internal static int BuildMipMaps(List<MipMap> MipMaps)
action(item);

MipMaps.AddRange(newmips);
return estimatedMips;
return MipMaps.Count;
}

/// <summary>
Expand Down
65 changes: 35 additions & 30 deletions CSharpImageLibrary/ImageEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -297,34 +297,7 @@ internal static byte[] Save(List<MipMap> MipMaps, ImageFormats.ImageEngineFormat
}

// KFreon: Ensure we have a power of two for dimensions FOR DDS ONLY
double fixXScale = 0;
double fixYScale = 0;
if (destFormatDetails.IsBlockCompressed && (!UsefulThings.General.IsPowerOfTwo(width) || !UsefulThings.General.IsPowerOfTwo(height)))
{
double newWidth = 0;
double newHeight = 0;

// Takes into account aspect ratio (a little bit)
double aspect = width / height;
if (aspect > 1)
{
newWidth = UsefulThings.General.RoundToNearestPowerOfTwo(width);
var tempScale = newWidth / width;
newHeight = UsefulThings.General.RoundToNearestPowerOfTwo((int)(height * tempScale));
}
else
{
newHeight = UsefulThings.General.RoundToNearestPowerOfTwo(height);
var tempScale = newHeight / height;
newWidth = UsefulThings.General.RoundToNearestPowerOfTwo((int)(width * tempScale));
}


// Little extra bit to allow integer cast from Double with the correct answer. Occasionally dimensions * scale would be 511.99999999998 instead of 512, so adding a little allows the integer cast to return correct value.
fixXScale = 1d * newWidth / width + 0.001;
fixYScale = 1d * newHeight / height + 0.001;
newMips[0] = Resize(newMips[0], fixXScale, fixYScale);
}
TestDDSMipSize(newMips, destFormatDetails, width, height, out double fixXScale, out double fixYScale);

if (fixXScale != 0 || fixYScale != 0 || mipChoice == MipHandling.KeepTopOnly)
DestroyMipMaps(newMips, mipToSave);
Expand Down Expand Up @@ -352,6 +325,38 @@ internal static byte[] Save(List<MipMap> MipMaps, ImageFormats.ImageEngineFormat

return destination;
}

internal static void TestDDSMipSize(List<MipMap> newMips, ImageFormats.ImageEngineFormatDetails destFormatDetails, int width, int height, out double fixXScale, out double fixYScale)
{
fixXScale = 0;
fixYScale = 0;
if (destFormatDetails.IsBlockCompressed && (!UsefulThings.General.IsPowerOfTwo(width) || !UsefulThings.General.IsPowerOfTwo(height)))
{
double newWidth = 0;
double newHeight = 0;

// Takes into account aspect ratio (a little bit)
double aspect = width / height;
if (aspect > 1)
{
newWidth = UsefulThings.General.RoundToNearestPowerOfTwo(width);
var tempScale = newWidth / width;
newHeight = UsefulThings.General.RoundToNearestPowerOfTwo((int)(height * tempScale));
}
else
{
newHeight = UsefulThings.General.RoundToNearestPowerOfTwo(height);
var tempScale = newHeight / height;
newWidth = UsefulThings.General.RoundToNearestPowerOfTwo((int)(width * tempScale));
}


// Little extra bit to allow integer cast from Double with the correct answer. Occasionally dimensions * scale would be 511.99999999998 instead of 512, so adding a little allows the integer cast to return correct value.
fixXScale = 1d * newWidth / width + 0.001;
fixYScale = 1d * newHeight / height + 0.001;
newMips[0] = Resize(newMips[0], fixXScale, fixYScale);
}
}

internal static MipMap Resize(MipMap mipMap, double scale)
{
Expand Down Expand Up @@ -465,9 +470,9 @@ internal static MipMap Resize(BitmapSource baseBMP, double xScale, double yScale
/// <param name="MipMaps">List of Mipmaps.</param>
/// <param name="mipToSave">Index of mipmap to save. 1 based, i.e. top is 1.</param>
/// <returns>Number of mips present.</returns>
private static int DestroyMipMaps(List<MipMap> MipMaps, int mipToSave)
internal static int DestroyMipMaps(List<MipMap> MipMaps, int mipToSave)
{
MipMaps.RemoveRange(mipToSave + 1, MipMaps.Count - 1); // +1 because mipToSave is 0 based and we want to keep it
MipMaps.RemoveRange(mipToSave, MipMaps.Count - 1); // +1 because mipToSave is 0 based and we want to keep it
return 1;
}

Expand Down
137 changes: 82 additions & 55 deletions CSharpImageLibrary/ImageEngineImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,81 +249,108 @@ public byte[] Save(ImageFormats.ImageEngineFormatDetails destFormatDetails, MipH
else if (destFormatDetails.Format == ImageEngineFormat.DDS_DXT2 || destFormatDetails.Format == ImageEngineFormat.DDS_DXT4)
alphaSetting = AlphaSettings.Premultiply;

// If same format and stuff, can just return original data, or chunks of it.
if (destFormatDetails.Format == Format)
return AttemptSaveUsingOriginalData(destFormatDetails, GenerateMips, desiredMaxDimension, mipToSave, alphaSetting);
else
return ImageEngine.Save(MipMaps, destFormatDetails, GenerateMips, alphaSetting, desiredMaxDimension, mipToSave);
}

bool requiresProperSave = GenerateMips == MipHandling.Default && NumMipMaps == 1 || GenerateMips == MipHandling.GenerateNew;
byte[] AttemptSaveUsingOriginalData(ImageFormats.ImageEngineFormatDetails destFormatDetails, MipHandling GenerateMips, int desiredMaxDimension, int mipToSave, AlphaSettings alphaSetting)
{
int start = 0;
int destStart = 0;
int length = OriginalData.Length;
int newWidth = Width;
int newHeight = Height;
DDS_Header tempHeader = null;
byte[] data = null;

if (destFormatDetails.IsDDS)
{
destStart = 128;
start = 128;

int mipCount = 0;

// If same format and stuff, can just return original data, or chunks of it.
if (destFormatDetails.Format == Format && !(alphaSetting == AlphaSettings.RemoveAlphaChannel) && !requiresProperSave)
{
int start = 0;
int destStart = 0;
int length = OriginalData.Length;
int newWidth = Width;
int newHeight = Height;
DDS_Header tempHeader = null;

if (destFormatDetails.IsDDS)
if (mipToSave != 0)
{
destStart = 128;
start = 128;
length = OriginalData.Length;
mipCount = 1;
newWidth = MipMaps[mipToSave].Width;
newHeight = MipMaps[mipToSave].Height;

int mipCount = 0;
switch(GenerateMips)
start = ImageFormats.GetCompressedSize(mipToSave, destFormatDetails, Width, Height);
length = ImageFormats.GetCompressedSize(1, destFormatDetails, newWidth, newHeight);
}
else if (desiredMaxDimension != 0 && desiredMaxDimension < Width && desiredMaxDimension < Height)
{
int index = MipMaps.FindIndex(t => t.Width < desiredMaxDimension && t.Height < desiredMaxDimension);

// If none found, do a proper save and see what happens.
if (index == -1)
return ImageEngine.Save(MipMaps, destFormatDetails, GenerateMips, alphaSetting, desiredMaxDimension, mipToSave);

mipCount -= index;
newWidth = MipMaps[index].Width;
newHeight = MipMaps[index].Height;

start = ImageFormats.GetCompressedSize(index, destFormatDetails, Width, Height);
length = ImageFormats.GetCompressedSize(mipCount, destFormatDetails, newWidth, newHeight);
}
else
{
switch (GenerateMips)
{
case MipHandling.KeepExisting:
case MipHandling.Default: // Case where need more mips is handled above.
mipCount = NumMipMaps;
break;
case MipHandling.KeepTopOnly:
mipCount = 1;
length = ImageFormats.GetCompressedSize(1, destFormatDetails, newWidth, newHeight);
case MipHandling.Default:
if (NumMipMaps > 1)
mipCount = NumMipMaps;
else
goto case MipHandling.GenerateNew; // Eww goto...
break;
}
case MipHandling.GenerateNew:
ImageEngine.DestroyMipMaps(MipMaps, 1);
ImageEngine.TestDDSMipSize(MipMaps, destFormatDetails, Width, Height, out double fixXScale, out double fixYScale);

if (mipToSave != 0)
{
mipCount = 1;
newWidth = MipMaps[mipToSave].Width;
newHeight = MipMaps[mipToSave].Height;
// Wrong sizing, so can't use original data anyway.
if (fixXScale != 0 || fixYScale != 0)
return ImageEngine.Save(MipMaps, destFormatDetails, GenerateMips, alphaSetting, desiredMaxDimension, mipToSave);

start = ImageFormats.GetCompressedSize(mipToSave, destFormatDetails, Width, Height);
length = ImageFormats.GetCompressedSize(1, destFormatDetails, newWidth, newHeight);
}
else if (desiredMaxDimension != 0 && desiredMaxDimension < Width && desiredMaxDimension < Height)
{
int index = MipMaps.FindIndex(t => t.Width < desiredMaxDimension && t.Height < desiredMaxDimension);

// If none found, do a proper save and see what happens.
if (index == -1)
return ImageEngine.Save(MipMaps, destFormatDetails, GenerateMips, alphaSetting, desiredMaxDimension, mipToSave);
mipCount = DDSGeneral.BuildMipMaps(MipMaps);

mipCount -= index;
newWidth = MipMaps[index].Width;
newHeight = MipMaps[index].Height;
// Compress mipmaps excl top
byte[] formattedMips = DDSGeneral.Save(MipMaps.GetRange(1, MipMaps.Count - 1), destFormatDetails, alphaSetting);

start = ImageFormats.GetCompressedSize(index, destFormatDetails, Width, Height);
length = ImageFormats.GetCompressedSize(mipCount, destFormatDetails, newWidth, newHeight);
}
// Get top mip size and create destination array
length = ImageFormats.GetCompressedSize(1, destFormatDetails, newWidth, newHeight);
data = new byte[formattedMips.Length + length];

// Header
tempHeader = new DDS_Header(mipCount, newWidth, newHeight, destFormatDetails.Format);
// Copy smaller mips to destination
Array.Copy(formattedMips, 128, data, length, formattedMips.Length - 128);
break;
case MipHandling.KeepTopOnly:
mipCount = 1;
length = ImageFormats.GetCompressedSize(1, destFormatDetails, newWidth, newHeight);
break;
}
}

byte[] data = new byte[length];
Array.Copy(OriginalData, start, data, destStart, length - destStart);
// Header
tempHeader = new DDS_Header(mipCount, newWidth, newHeight, destFormatDetails.Format);
}

// Use existing array, otherwise create one.
data = data ?? new byte[length];
Array.Copy(OriginalData, start, data, destStart, length - destStart);

// Write header if existing (DDS Only)
if (tempHeader != null)
tempHeader.WriteToArray(data, 0);
// Write header if existing (DDS Only)
if (tempHeader != null)
tempHeader.WriteToArray(data, 0);

return data;
}
else
{
return ImageEngine.Save(MipMaps, destFormatDetails, GenerateMips, alphaSetting, desiredMaxDimension, mipToSave);
}
return data;
}
#endregion Savers

Expand Down
4 changes: 2 additions & 2 deletions CSharpImageLibrary/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("4.1.0.0")]
[assembly: AssemblyFileVersion("4.1.0.0")]
[assembly: AssemblyVersion("4.1.1.0")]
[assembly: AssemblyFileVersion("4.1.1.0")]

0 comments on commit c7e2fda

Please sign in to comment.