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;
byte[] tempOriginalData = OriginalData;
if (destFormatDetails.IsDDS)
{
destStart = destFormatDetails.HeaderSize;
start = destStart;
int mipCount = 0;
if (mipToSave != 0)
{
mipCount = 1;
newWidth = MipMaps[mipToSave].Width;
newHeight = MipMaps[mipToSave].Height;
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
{
if (alphaSetting == AlphaSettings.RemoveAlphaChannel)
{
// Can't edit alpha directly in premultiplied formats. Not easily anyway.
if (destFormatDetails.IsPremultipliedFormat)
{
return(ImageEngine.Save(MipMaps, destFormatDetails, GenerateMips, alphaSetting, desiredMaxDimension, mipToSave));
}
// DDS Formats only
switch (destFormatDetails.Format)
{
// Excluded cos they have no true alpha
case ImageEngineFormat.DDS_A8:
case ImageEngineFormat.DDS_A8L8:
case ImageEngineFormat.DDS_ATI1:
case ImageEngineFormat.DDS_ATI2_3Dc:
case ImageEngineFormat.DDS_V8U8:
case ImageEngineFormat.DDS_G16_R16:
case ImageEngineFormat.DDS_G8_L8:
case ImageEngineFormat.DDS_R5G6B5:
case ImageEngineFormat.DDS_RGB_8:
case ImageEngineFormat.DDS_DXT1:
break;
// Exluded cos they're alpha isn't easily edited
case ImageEngineFormat.DDS_DXT2:
case ImageEngineFormat.DDS_DXT4:
break;
// Excluded cos they're currently unsupported
case ImageEngineFormat.DDS_CUSTOM:
case ImageEngineFormat.DDS_DX10:
case ImageEngineFormat.DDS_ARGB_4:
break;
case ImageEngineFormat.DDS_ABGR_8:
case ImageEngineFormat.DDS_ARGB_32F:
case ImageEngineFormat.DDS_ARGB_8:
case ImageEngineFormat.DDS_DXT3:
case ImageEngineFormat.DDS_DXT5:
tempOriginalData = new byte[OriginalData.Length];
Array.Copy(OriginalData, tempOriginalData, OriginalData.Length);
// Edit alpha values
int alphaStart = 128;
int alphaJump = 0;
byte[] alphaBlock = null;
if (destFormatDetails.IsBlockCompressed)
{
alphaJump = 16;
alphaBlock = new byte[8];
for (int i = 0; i < 8; i++)
{
alphaBlock[i] = 255;
}
}
else
{
alphaJump = destFormatDetails.ComponentSize * 4;
alphaBlock = new byte[destFormatDetails.ComponentSize];
switch (destFormatDetails.ComponentSize)
{
case 1:
alphaBlock[0] = 255;
break;
case 2:
alphaBlock = BitConverter.GetBytes(ushort.MaxValue);
break;
case 4:
alphaBlock = BitConverter.GetBytes(1f);
break;
}
}
for (int i = alphaStart; i < OriginalData.Length; i += alphaJump)
{
Array.Copy(alphaBlock, 0, tempOriginalData, i, alphaBlock.Length);
}
break;
}
}
switch (GenerateMips)
{
case MipHandling.KeepExisting:
mipCount = NumMipMaps;
break;
case MipHandling.Default:
if (NumMipMaps > 1)
{
mipCount = NumMipMaps;
}
else
{
goto case MipHandling.GenerateNew; // Eww goto...
}
break;
case MipHandling.GenerateNew:
ImageEngine.DestroyMipMaps(MipMaps);
ImageEngine.TestDDSMipSize(MipMaps, destFormatDetails, Width, Height, out double fixXScale, out double fixYScale, GenerateMips);
// Wrong sizing, so can't use original data anyway.
if (fixXScale != 0 || fixYScale != 0)
{
return(ImageEngine.Save(MipMaps, destFormatDetails, GenerateMips, alphaSetting, desiredMaxDimension, mipToSave));
}
mipCount = DDSGeneral.BuildMipMaps(MipMaps);
// Compress mipmaps excl top
byte[] formattedMips = DDSGeneral.Save(MipMaps.GetRange(1, MipMaps.Count - 1), destFormatDetails, alphaSetting);
if (formattedMips == null)
{
return(null);
}
// Get top mip size and create destination array
length = ImageFormats.GetCompressedSize(0, destFormatDetails, newWidth, newHeight); // Should be the length of the top mipmap.
data = new byte[formattedMips.Length + length];
// Copy smaller mips to destination
Array.Copy(formattedMips, destFormatDetails.HeaderSize, data, length, formattedMips.Length - destFormatDetails.HeaderSize);
break;
case MipHandling.KeepTopOnly:
mipCount = 1;
length = ImageFormats.GetCompressedSize(1, destFormatDetails, newWidth, newHeight);
break;
}
}
// Header
tempHeader = new DDS_Header(mipCount, newHeight, newWidth, destFormatDetails.Format, destFormatDetails.DX10Format);
}
// Use existing array, otherwise create one.
data = data ?? new byte[length];
Array.Copy(tempOriginalData, start, data, destStart, length - destStart);
// Write header if existing (DDS Only)
if (tempHeader != null)
{
tempHeader.WriteToArray(data, 0);
}
return(data);
}