|
@@ -25,31 +25,46 @@ namespace TEAMModelOS.SDK.PngQuant
|
|
|
/// <param name="Width"></param>
|
|
|
/// <param name="height"></param>
|
|
|
/// <returns></returns>
|
|
|
- public Image QuantizeImageFromBase64(Stream base64, int Width = 0, int height = 0)
|
|
|
- {
|
|
|
- var oldbmp = new Bitmap(base64);
|
|
|
-
|
|
|
- if (Width > 0 && height > 0)
|
|
|
+ public Image QuantizeImage(Stream base64, int width = 0, int height = 0, int alphaThreshold = 10, int alphaFader = 70)
|
|
|
+ {
|
|
|
+ Bitmap oldbmp = new Bitmap(base64);
|
|
|
+ Bitmap newbmp = null;
|
|
|
+ try
|
|
|
{
|
|
|
- var newbmp = new Bitmap(oldbmp, new Size(Width, height)); //縮圖時自動保存為Format32bppArgb無須另外處理
|
|
|
- oldbmp.Dispose();
|
|
|
- return QuantizeImage(newbmp, 10, 70);
|
|
|
+ int neww = width;
|
|
|
+ int newh = height;
|
|
|
+ //先處理縮圖計算,指定宽,高按比例
|
|
|
+ if (width == 0 || height == 0)
|
|
|
+ {
|
|
|
+ neww = oldbmp.Width > 1024 ? 1024 : oldbmp.Width;
|
|
|
+ newh = Convert.ToInt32(oldbmp.Height * neww / oldbmp.Width);
|
|
|
+ }
|
|
|
+
|
|
|
+ //縮圖時自動保存為Format32bppArgb無須另外處理
|
|
|
+ newbmp = new Bitmap(oldbmp, new Size(neww, newh));
|
|
|
+ return QuantizeImage(newbmp, alphaThreshold, alphaFader);
|
|
|
+
|
|
|
+ //TODO 判斷圖片是否非32位元和8位元,處理轉換,這個不准,已改為取字節判斷
|
|
|
+ //var d = Image.GetPixelFormatSize(oldbmp.PixelFormat);
|
|
|
+
|
|
|
+ //TODO 此段碼為轉換32位元,但上面縮圖保存時以自帶,後面研究能否解決8位元保存問題
|
|
|
+ // newbmp = new Bitmap(neww, newh, PixelFormat.Format8bppIndexed);
|
|
|
+ // using (var gr = Graphics.FromImage(newbmp))
|
|
|
+ // gr.DrawImage(oldbmp, new Rectangle(0, 0, oldbmp.Width, oldbmp.Height));
|
|
|
+ // return QuantizeImage(newbmp, alphaThreshold, alphaFader);
|
|
|
}
|
|
|
- else
|
|
|
+ catch
|
|
|
{
|
|
|
- if (oldbmp.PixelFormat != PixelFormat.Format32bppArgb) //不縮圖時,要處理保存為Format32bppArgb
|
|
|
- {
|
|
|
- var newbmp = new Bitmap(oldbmp.Width, oldbmp.Height, PixelFormat.Format32bppArgb);
|
|
|
- using (var gr = Graphics.FromImage(newbmp))
|
|
|
- gr.DrawImage(oldbmp, new Rectangle(0, 0, oldbmp.Width, oldbmp.Height));
|
|
|
- oldbmp.Dispose();
|
|
|
- oldbmp = newbmp;
|
|
|
- }
|
|
|
- return QuantizeImage(oldbmp, 10, 70);
|
|
|
+ return null;
|
|
|
}
|
|
|
- }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ oldbmp.Dispose();
|
|
|
+ newbmp.Dispose();
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- public Image QuantizeImage(Bitmap image, int alphaThreshold = 10, int alphaFader = 70)
|
|
|
+ private Image QuantizeImage(Bitmap image, int alphaThreshold, int alphaFader)
|
|
|
{
|
|
|
var colorCount = MaxColor;
|
|
|
var data = BuildHistogram(image, alphaThreshold, alphaFader);
|
|
@@ -57,7 +72,7 @@ namespace TEAMModelOS.SDK.PngQuant
|
|
|
var cubes = SplitData(ref colorCount, data);
|
|
|
var palette = GetQuantizedPalette(colorCount, data, cubes, alphaThreshold);
|
|
|
return ProcessImagePixels(image, palette);
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
private static Bitmap ProcessImagePixels(Image sourceImage, QuantizedPalette palette)
|
|
|
{
|
|
@@ -102,7 +117,7 @@ namespace TEAMModelOS.SDK.PngQuant
|
|
|
}
|
|
|
finally
|
|
|
{
|
|
|
- if(targetData != null)
|
|
|
+ if (targetData != null)
|
|
|
result.UnlockBits(targetData);
|
|
|
}
|
|
|
|
|
@@ -116,7 +131,7 @@ namespace TEAMModelOS.SDK.PngQuant
|
|
|
|
|
|
BitmapData data = sourceImage.LockBits(
|
|
|
Rectangle.FromLTRB(0, 0, bitmapWidth, bitmapHeight),
|
|
|
- ImageLockMode.ReadOnly,
|
|
|
+ ImageLockMode.ReadOnly,
|
|
|
sourceImage.PixelFormat);
|
|
|
ColorData colorData = new ColorData(MaxSideIndex, bitmapWidth, bitmapHeight);
|
|
|
|
|
@@ -132,7 +147,7 @@ namespace TEAMModelOS.SDK.PngQuant
|
|
|
var value = new Byte[byteCount];
|
|
|
|
|
|
Marshal.Copy(data.Scan0, buffer, 0, buffer.Length);
|
|
|
-
|
|
|
+
|
|
|
for (int y = 0; y < bitmapHeight; y++)
|
|
|
{
|
|
|
var index = 0;
|
|
@@ -162,15 +177,15 @@ namespace TEAMModelOS.SDK.PngQuant
|
|
|
colorData.MomentsGreen[indexAlpha, indexRed, indexGreen, indexBlue] += value[Green];
|
|
|
colorData.MomentsBlue[indexAlpha, indexRed, indexGreen, indexBlue] += value[Blue];
|
|
|
colorData.MomentsAlpha[indexAlpha, indexRed, indexGreen, indexBlue] += value[Alpha];
|
|
|
- colorData.Moments[indexAlpha, indexRed, indexGreen, indexBlue] += (value[Alpha]*value[Alpha]) +
|
|
|
- (value[Red]*value[Red]) +
|
|
|
- (value[Green]*value[Green]) +
|
|
|
- (value[Blue]*value[Blue]);
|
|
|
+ colorData.Moments[indexAlpha, indexRed, indexGreen, indexBlue] += (value[Alpha] * value[Alpha]) +
|
|
|
+ (value[Red] * value[Red]) +
|
|
|
+ (value[Green] * value[Green]) +
|
|
|
+ (value[Blue] * value[Blue]);
|
|
|
}
|
|
|
|
|
|
colorData.AddPixel(
|
|
|
new Pixel(value[Alpha], value[Red], value[Green], value[Blue]),
|
|
|
- BitConverter.ToInt32 (new[] { indexAlpha, indexRed, indexGreen, indexBlue }, 0));
|
|
|
+ BitConverter.ToInt32(new[] { indexAlpha, indexRed, indexGreen, indexBlue }, 0));
|
|
|
index += bitDepth;
|
|
|
}
|
|
|
|
|
@@ -390,7 +405,7 @@ namespace TEAMModelOS.SDK.PngQuant
|
|
|
return new CubeCut(cutPoint, result);
|
|
|
}
|
|
|
|
|
|
- private bool Cut(ColorData data, ref Box first,ref Box second)
|
|
|
+ private bool Cut(ColorData data, ref Box first, ref Box second)
|
|
|
{
|
|
|
int direction;
|
|
|
var wholeAlpha = Volume(first, data.MomentsAlpha);
|
|
@@ -399,10 +414,10 @@ namespace TEAMModelOS.SDK.PngQuant
|
|
|
var wholeBlue = Volume(first, data.MomentsBlue);
|
|
|
var wholeWeight = Volume(first, data.Weights);
|
|
|
|
|
|
- var maxAlpha = Maximize(data, first, Alpha, (byte) (first.AlphaMinimum + 1), first.AlphaMaximum, wholeAlpha, wholeRed, wholeGreen, wholeBlue, wholeWeight);
|
|
|
- var maxRed = Maximize(data, first, Red, (byte) (first.RedMinimum + 1), first.RedMaximum, wholeAlpha, wholeRed, wholeGreen, wholeBlue, wholeWeight);
|
|
|
- var maxGreen = Maximize(data, first, Green, (byte) (first.GreenMinimum + 1), first.GreenMaximum, wholeAlpha, wholeRed, wholeGreen, wholeBlue, wholeWeight);
|
|
|
- var maxBlue = Maximize(data, first, Blue, (byte) (first.BlueMinimum + 1), first.BlueMaximum, wholeAlpha, wholeRed, wholeGreen, wholeBlue, wholeWeight);
|
|
|
+ var maxAlpha = Maximize(data, first, Alpha, (byte)(first.AlphaMinimum + 1), first.AlphaMaximum, wholeAlpha, wholeRed, wholeGreen, wholeBlue, wholeWeight);
|
|
|
+ var maxRed = Maximize(data, first, Red, (byte)(first.RedMinimum + 1), first.RedMaximum, wholeAlpha, wholeRed, wholeGreen, wholeBlue, wholeWeight);
|
|
|
+ var maxGreen = Maximize(data, first, Green, (byte)(first.GreenMinimum + 1), first.GreenMaximum, wholeAlpha, wholeRed, wholeGreen, wholeBlue, wholeWeight);
|
|
|
+ var maxBlue = Maximize(data, first, Blue, (byte)(first.BlueMinimum + 1), first.BlueMaximum, wholeAlpha, wholeRed, wholeGreen, wholeBlue, wholeWeight);
|
|
|
|
|
|
if ((maxAlpha.Value >= maxRed.Value) && (maxAlpha.Value >= maxGreen.Value) && (maxAlpha.Value >= maxBlue.Value))
|
|
|
{
|
|
@@ -427,28 +442,28 @@ namespace TEAMModelOS.SDK.PngQuant
|
|
|
switch (direction)
|
|
|
{
|
|
|
case Alpha:
|
|
|
- second.AlphaMinimum = first.AlphaMaximum = (byte) maxAlpha.Position;
|
|
|
+ second.AlphaMinimum = first.AlphaMaximum = (byte)maxAlpha.Position;
|
|
|
second.RedMinimum = first.RedMinimum;
|
|
|
second.GreenMinimum = first.GreenMinimum;
|
|
|
second.BlueMinimum = first.BlueMinimum;
|
|
|
break;
|
|
|
|
|
|
case Red:
|
|
|
- second.RedMinimum = first.RedMaximum = (byte) maxRed.Position;
|
|
|
+ second.RedMinimum = first.RedMaximum = (byte)maxRed.Position;
|
|
|
second.AlphaMinimum = first.AlphaMinimum;
|
|
|
second.GreenMinimum = first.GreenMinimum;
|
|
|
second.BlueMinimum = first.BlueMinimum;
|
|
|
break;
|
|
|
|
|
|
case Green:
|
|
|
- second.GreenMinimum = first.GreenMaximum = (byte) maxGreen.Position;
|
|
|
+ second.GreenMinimum = first.GreenMaximum = (byte)maxGreen.Position;
|
|
|
second.AlphaMinimum = first.AlphaMinimum;
|
|
|
second.RedMinimum = first.RedMinimum;
|
|
|
second.BlueMinimum = first.BlueMinimum;
|
|
|
break;
|
|
|
|
|
|
case Blue:
|
|
|
- second.BlueMinimum = first.BlueMaximum = (byte) maxBlue.Position;
|
|
|
+ second.BlueMinimum = first.BlueMaximum = (byte)maxBlue.Position;
|
|
|
second.AlphaMinimum = first.AlphaMinimum;
|
|
|
second.RedMinimum = first.RedMinimum;
|
|
|
second.GreenMinimum = first.GreenMinimum;
|
|
@@ -584,12 +599,12 @@ namespace TEAMModelOS.SDK.PngQuant
|
|
|
if (weight <= 0) continue;
|
|
|
|
|
|
var lookup = new Lookup
|
|
|
- {
|
|
|
- Alpha = (int) (Volume(cube, data.MomentsAlpha)/weight),
|
|
|
- Red = (int) (Volume(cube, data.MomentsRed)/weight),
|
|
|
- Green = (int) (Volume(cube, data.MomentsGreen)/weight),
|
|
|
- Blue = (int) (Volume(cube, data.MomentsBlue)/weight)
|
|
|
- };
|
|
|
+ {
|
|
|
+ Alpha = (int)(Volume(cube, data.MomentsAlpha) / weight),
|
|
|
+ Red = (int)(Volume(cube, data.MomentsRed) / weight),
|
|
|
+ Green = (int)(Volume(cube, data.MomentsGreen) / weight),
|
|
|
+ Blue = (int)(Volume(cube, data.MomentsBlue) / weight)
|
|
|
+ };
|
|
|
lookups.Lookups.Add(lookup);
|
|
|
}
|
|
|
return lookups;
|