mirror of
https://github.com/greenshot/greenshot
synced 2025-07-14 17:13:44 -07:00
Code cleanup: 1) AbstractFilter: why did we serialize the bitmapbuffer? 2) Bitmapbuffer: removed serialization code, this object should NEVER be serialized as it's just a view which makes access faster. 3) QuantizerHelper.cs: Refactored to use the FastBitmap
git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@2474 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
parent
f34923e0d7
commit
e2be04a552
5 changed files with 59 additions and 199 deletions
|
@ -47,7 +47,9 @@ namespace Greenshot.Drawing.Filters {
|
||||||
get { return invert; }
|
get { return invert; }
|
||||||
set { invert=value; OnPropertyChanged("Invert"); }
|
set { invert=value; OnPropertyChanged("Invert"); }
|
||||||
}
|
}
|
||||||
|
[NonSerialized]
|
||||||
protected BitmapBuffer bbb;
|
protected BitmapBuffer bbb;
|
||||||
|
|
||||||
protected Rectangle applyRect;
|
protected Rectangle applyRect;
|
||||||
protected DrawableContainer parent;
|
protected DrawableContainer parent;
|
||||||
public DrawableContainer Parent {
|
public DrawableContainer Parent {
|
||||||
|
|
|
@ -28,7 +28,6 @@ namespace GreenshotPlugin.Core {
|
||||||
/// The BitmapBuffer is exactly what it says, it buffers a Bitmap.
|
/// The BitmapBuffer is exactly what it says, it buffers a Bitmap.
|
||||||
/// And it is possible to Draw on the Bitmap with direct memory access for better performance
|
/// And it is possible to Draw on the Bitmap with direct memory access for better performance
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable()]
|
|
||||||
public unsafe class BitmapBuffer : IDisposable {
|
public unsafe class BitmapBuffer : IDisposable {
|
||||||
private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(BitmapBuffer));
|
private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(BitmapBuffer));
|
||||||
private bool clone;
|
private bool clone;
|
||||||
|
@ -36,6 +35,7 @@ namespace GreenshotPlugin.Core {
|
||||||
// Used for indexed images
|
// Used for indexed images
|
||||||
private Color[] colorEntries;
|
private Color[] colorEntries;
|
||||||
|
|
||||||
|
|
||||||
public static Color BackgroundBlendColor {
|
public static Color BackgroundBlendColor {
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
|
@ -70,35 +70,21 @@ namespace GreenshotPlugin.Core {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NonSerialized]
|
|
||||||
private BitmapData bmData;
|
private BitmapData bmData;
|
||||||
[NonSerialized]
|
|
||||||
private Rectangle rect;
|
private Rectangle rect;
|
||||||
[NonSerialized]
|
|
||||||
private byte* pointer;
|
private byte* pointer;
|
||||||
[NonSerialized]
|
|
||||||
private int* intPointer;
|
private int* intPointer;
|
||||||
[NonSerialized]
|
|
||||||
private int stride; /* bytes per pixel row */
|
private int stride; /* bytes per pixel row */
|
||||||
[NonSerialized]
|
|
||||||
private int aIndex = -1;
|
private int aIndex = -1;
|
||||||
[NonSerialized]
|
|
||||||
private int rIndex = -1;
|
private int rIndex = -1;
|
||||||
[NonSerialized]
|
|
||||||
private int gIndex = -1;
|
private int gIndex = -1;
|
||||||
[NonSerialized]
|
|
||||||
private int bIndex = -1;
|
private int bIndex = -1;
|
||||||
[NonSerialized]
|
|
||||||
private int bytesPerPixel;
|
private int bytesPerPixel;
|
||||||
[NonSerialized]
|
|
||||||
private bool bitsLocked = false;
|
private bool bitsLocked = false;
|
||||||
|
|
||||||
public Size Size {
|
public Size Size {
|
||||||
get {return rect.Size;}
|
get {return rect.Size;}
|
||||||
}
|
}
|
||||||
public int Length {
|
|
||||||
get {return rect.Width*rect.Height;}
|
|
||||||
}
|
|
||||||
public int Width {
|
public int Width {
|
||||||
get {return rect.Width;}
|
get {return rect.Width;}
|
||||||
}
|
}
|
||||||
|
@ -205,29 +191,6 @@ namespace GreenshotPlugin.Core {
|
||||||
pointer = null;
|
pointer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This is called when deserializing the object
|
|
||||||
*/
|
|
||||||
public BitmapBuffer(SerializationInfo info, StreamingContext ctxt) {
|
|
||||||
this.bitmap = (Bitmap)info.GetValue("bitmap", typeof(Bitmap));
|
|
||||||
this.rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
|
|
||||||
// The rest will be set when Lock is called
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is called when serializing the object
|
|
||||||
*/
|
|
||||||
public void GetObjectData(SerializationInfo info, StreamingContext ctxt) {
|
|
||||||
bool isLocked = bitsLocked;
|
|
||||||
if (isLocked) {
|
|
||||||
Unlock();
|
|
||||||
}
|
|
||||||
info.AddValue("bitmap", this.bitmap);
|
|
||||||
if (isLocked) {
|
|
||||||
Lock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock the bitmap so we have direct access to the memory
|
* Lock the bitmap so we have direct access to the memory
|
||||||
*/
|
*/
|
||||||
|
@ -297,51 +260,6 @@ namespace GreenshotPlugin.Core {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieve the color index, for 8BPP, at location x,y
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="x">X coordinate</param>
|
|
||||||
/// <param name="y">Y Coordinate</param>
|
|
||||||
/// <returns>color index</returns>
|
|
||||||
public byte GetColorIndexAt(int x, int y) {
|
|
||||||
int offset = x*bytesPerPixel+y*stride;
|
|
||||||
return pointer[offset];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the color for an 8-bit image
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="x"></param>
|
|
||||||
/// <param name="y"></param>
|
|
||||||
/// <returns>Color from the palette</returns>
|
|
||||||
public Color GetColor(int x, int y) {
|
|
||||||
int offset = x * bytesPerPixel + y * stride;
|
|
||||||
byte colorIndex = pointer[offset];
|
|
||||||
return colorEntries[colorIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set the color index, for 8BPP, at location x,y
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="x">X coordinate</param>
|
|
||||||
/// <param name="y">Y Coordinate</param>
|
|
||||||
/// <param name="color">Color index to set</param>
|
|
||||||
public void SetColorIndexAt(int x, int y, byte colorIndex) {
|
|
||||||
int offset = x * bytesPerPixel + y * stride;
|
|
||||||
pointer[offset] = colorIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Use only when 32-bit bitmap!
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="x">x</param>
|
|
||||||
/// <param name="y">y</param>
|
|
||||||
/// <returns>int with argb value</returns>
|
|
||||||
public int GetARGB(int x, int y) {
|
|
||||||
int offset = (y * (stride >> 2)) + x;
|
|
||||||
return intPointer[offset];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use only when 32-bit bitmap!
|
/// Use only when 32-bit bitmap!
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -370,34 +288,6 @@ namespace GreenshotPlugin.Core {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieve the color, without alpha (is blended), at location x,y
|
|
||||||
/// Before the first time this is called the Lock() should be called once!
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="x">X coordinate</param>
|
|
||||||
/// <param name="y">Y Coordinate</param>
|
|
||||||
/// <returns>Color</returns>
|
|
||||||
public Color GetColorAtWithoutAlpha(int x, int y) {
|
|
||||||
if (x >= 0 && y >= 0 && x < rect.Width && y < rect.Height) {
|
|
||||||
int offset = x * bytesPerPixel + y * stride;
|
|
||||||
int a = (aIndex == -1) ? (byte)255 : pointer[aIndex + offset];
|
|
||||||
int red = pointer[rIndex + offset];
|
|
||||||
int green = pointer[gIndex + offset];
|
|
||||||
int blue = pointer[bIndex + offset];
|
|
||||||
|
|
||||||
if (a < 255) {
|
|
||||||
// As the request is to get without alpha, we blend.
|
|
||||||
int rem = 255 - a;
|
|
||||||
red = (red * a + BackgroundBlendColor.R * rem) / 255;
|
|
||||||
green = (green * a + BackgroundBlendColor.G * rem) / 255;
|
|
||||||
blue = (blue * a + BackgroundBlendColor.B * rem) / 255;
|
|
||||||
}
|
|
||||||
return Color.FromArgb(255, red, green, blue);
|
|
||||||
} else {
|
|
||||||
return Color.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the color at location x,y
|
* Set the color at location x,y
|
||||||
* Before the first time this is called the Lock() should be called once!
|
* Before the first time this is called the Lock() should be called once!
|
||||||
|
@ -412,20 +302,6 @@ namespace GreenshotPlugin.Core {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the color at location x,y as an array
|
|
||||||
* Before the first time this is called the Lock() should be called once!
|
|
||||||
*/
|
|
||||||
public byte[] GetColorArrayAt(int x, int y) {
|
|
||||||
if(x>=0 && y>=0 && x<rect.Width && y<rect.Height) {
|
|
||||||
int offset = x*bytesPerPixel+y*stride;
|
|
||||||
byte a = (aIndex==-1) ? (byte)255 : (byte)pointer[aIndex+offset];
|
|
||||||
return new byte[] { a, pointer[rIndex + offset], pointer[gIndex + offset], pointer[bIndex + offset] };
|
|
||||||
} else {
|
|
||||||
return new byte[] { 0, 0, 0, 0 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the color at location x,y to a byte[]
|
* Retrieve the color at location x,y to a byte[]
|
||||||
* Before the first time this is called the Lock() should be called once!
|
* Before the first time this is called the Lock() should be called once!
|
||||||
|
|
|
@ -33,9 +33,7 @@ namespace GreenshotPlugin.Core {
|
||||||
void SetColorAt(int x, int y, Color color);
|
void SetColorAt(int x, int y, Color color);
|
||||||
void Lock();
|
void Lock();
|
||||||
void Unlock();
|
void Unlock();
|
||||||
Bitmap Bitmap {
|
Bitmap UnlockAndReturnBitmap();
|
||||||
get;
|
|
||||||
}
|
|
||||||
Size Size {
|
Size Size {
|
||||||
get;
|
get;
|
||||||
}
|
}
|
||||||
|
@ -47,6 +45,7 @@ namespace GreenshotPlugin.Core {
|
||||||
}
|
}
|
||||||
bool NeedsDispose {
|
bool NeedsDispose {
|
||||||
get;
|
get;
|
||||||
|
set;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +60,7 @@ namespace GreenshotPlugin.Core {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool NeedsDispose {
|
public bool NeedsDispose {
|
||||||
get;
|
get;
|
||||||
protected set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -116,7 +115,7 @@ namespace GreenshotPlugin.Core {
|
||||||
public static IFastBitmap CreateEmpty(Size newSize, PixelFormat pixelFormat, Color backgroundColor) {
|
public static IFastBitmap CreateEmpty(Size newSize, PixelFormat pixelFormat, Color backgroundColor) {
|
||||||
Bitmap destination = ImageHelper.CreateEmpty(newSize.Width, newSize.Height, pixelFormat, backgroundColor, 96f, 96f);
|
Bitmap destination = ImageHelper.CreateEmpty(newSize.Width, newSize.Height, pixelFormat, backgroundColor, 96f, 96f);
|
||||||
IFastBitmap fastBitmap = Create(destination);
|
IFastBitmap fastBitmap = Create(destination);
|
||||||
((FastBitmap)fastBitmap).NeedsDispose = true;
|
fastBitmap.NeedsDispose = true;
|
||||||
return fastBitmap;
|
return fastBitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,16 +151,16 @@ namespace GreenshotPlugin.Core {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the underlying bitmap, do not dispose... if it's created for the FastBitmap it will be disposed!
|
/// Returns the underlying bitmap, unlocks it and prevents that it will be disposed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Bitmap Bitmap {
|
public Bitmap UnlockAndReturnBitmap() {
|
||||||
get {
|
|
||||||
if (bitsLocked) {
|
if (bitsLocked) {
|
||||||
throw new NotSupportedException("Can't get a locked bitmap!");
|
LOG.Warn("Unlocking the bitmap");
|
||||||
|
Unlock();
|
||||||
}
|
}
|
||||||
|
NeedsDispose = false;
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Destructor
|
/// Destructor
|
||||||
|
|
|
@ -111,19 +111,19 @@ namespace GreenshotPlugin.Core {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Private helper method for the FindAutoCropRectangle
|
/// Private helper method for the FindAutoCropRectangle
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="buffer"></param>
|
/// <param name="fastBitmap"></param>
|
||||||
/// <param name="colorPoint"></param>
|
/// <param name="colorPoint"></param>
|
||||||
/// <returns>Rectangle</returns>
|
/// <returns>Rectangle</returns>
|
||||||
private static Rectangle FindAutoCropRectangle(BitmapBuffer buffer, Point colorPoint, int cropDifference) {
|
private static Rectangle FindAutoCropRectangle(IFastBitmap fastBitmap, Point colorPoint, int cropDifference) {
|
||||||
Rectangle cropRectangle = Rectangle.Empty;
|
Rectangle cropRectangle = Rectangle.Empty;
|
||||||
Color referenceColor = buffer.GetColorAtWithoutAlpha(colorPoint.X,colorPoint.Y);
|
Color referenceColor = fastBitmap.GetColorAt(colorPoint.X, colorPoint.Y);
|
||||||
Point min = new Point(int.MaxValue, int.MaxValue);
|
Point min = new Point(int.MaxValue, int.MaxValue);
|
||||||
Point max = new Point(int.MinValue, int.MinValue);
|
Point max = new Point(int.MinValue, int.MinValue);
|
||||||
|
|
||||||
if (cropDifference > 0) {
|
if (cropDifference > 0) {
|
||||||
for(int y = 0; y < buffer.Height; y++) {
|
for (int y = 0; y < fastBitmap.Height; y++) {
|
||||||
for(int x = 0; x < buffer.Width; x++) {
|
for (int x = 0; x < fastBitmap.Width; x++) {
|
||||||
Color currentColor = buffer.GetColorAt(x, y);
|
Color currentColor = fastBitmap.GetColorAt(x, y);
|
||||||
int diffR = Math.Abs(currentColor.R - referenceColor.R);
|
int diffR = Math.Abs(currentColor.R - referenceColor.R);
|
||||||
int diffG = Math.Abs(currentColor.G - referenceColor.G);
|
int diffG = Math.Abs(currentColor.G - referenceColor.G);
|
||||||
int diffB = Math.Abs(currentColor.B - referenceColor.B);
|
int diffB = Math.Abs(currentColor.B - referenceColor.B);
|
||||||
|
@ -136,9 +136,9 @@ namespace GreenshotPlugin.Core {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(int y = 0; y < buffer.Height; y++) {
|
for (int y = 0; y < fastBitmap.Height; y++) {
|
||||||
for(int x = 0; x < buffer.Width; x++) {
|
for (int x = 0; x < fastBitmap.Width; x++) {
|
||||||
Color currentColor = buffer.GetColorAtWithoutAlpha(x, y);
|
Color currentColor = fastBitmap.GetColorAt(x, y);
|
||||||
if (referenceColor.Equals(currentColor)) {
|
if (referenceColor.Equals(currentColor)) {
|
||||||
if (x < min.X) min.X = x;
|
if (x < min.X) min.X = x;
|
||||||
if (y < min.Y) min.Y = y;
|
if (y < min.Y) min.Y = y;
|
||||||
|
@ -149,7 +149,7 @@ namespace GreenshotPlugin.Core {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(Point.Empty.Equals(min) && max.Equals(new Point(buffer.Width-1, buffer.Height-1)))) {
|
if (!(Point.Empty.Equals(min) && max.Equals(new Point(fastBitmap.Width - 1, fastBitmap.Height - 1)))) {
|
||||||
if (!(min.X == int.MaxValue || min.Y == int.MaxValue || max.X == int.MinValue || min.X == int.MinValue)) {
|
if (!(min.X == int.MaxValue || min.Y == int.MaxValue || max.X == int.MinValue || min.X == int.MinValue)) {
|
||||||
cropRectangle = new Rectangle(min.X, min.Y, max.X - min.X + 1, max.Y - min.Y + 1);
|
cropRectangle = new Rectangle(min.X, min.Y, max.X - min.X + 1, max.Y - min.Y + 1);
|
||||||
}
|
}
|
||||||
|
@ -164,8 +164,6 @@ namespace GreenshotPlugin.Core {
|
||||||
/// <returns>Rectangle</returns>
|
/// <returns>Rectangle</returns>
|
||||||
public static Rectangle FindAutoCropRectangle(Image image, int cropDifference) {
|
public static Rectangle FindAutoCropRectangle(Image image, int cropDifference) {
|
||||||
Rectangle cropRectangle = Rectangle.Empty;
|
Rectangle cropRectangle = Rectangle.Empty;
|
||||||
using (BitmapBuffer buffer = new BitmapBuffer((Bitmap)image, false)) {
|
|
||||||
buffer.Lock();
|
|
||||||
Rectangle currentRectangle = Rectangle.Empty;
|
Rectangle currentRectangle = Rectangle.Empty;
|
||||||
List<Point> checkPoints = new List<Point>();
|
List<Point> checkPoints = new List<Point>();
|
||||||
// Top Left
|
// Top Left
|
||||||
|
@ -176,10 +174,12 @@ namespace GreenshotPlugin.Core {
|
||||||
checkPoints.Add(new Point(image.Width - 1, 0));
|
checkPoints.Add(new Point(image.Width - 1, 0));
|
||||||
// Bottom Right
|
// Bottom Right
|
||||||
checkPoints.Add(new Point(image.Width - 1, image.Height - 1));
|
checkPoints.Add(new Point(image.Width - 1, image.Height - 1));
|
||||||
|
using (IFastBitmap fastBitmap = FastBitmap.Create((Bitmap)image)) {
|
||||||
|
fastBitmap.Lock();
|
||||||
|
|
||||||
// find biggest area
|
// find biggest area
|
||||||
foreach(Point checkPoint in checkPoints) {
|
foreach(Point checkPoint in checkPoints) {
|
||||||
currentRectangle = FindAutoCropRectangle(buffer, checkPoint, cropDifference);
|
currentRectangle = FindAutoCropRectangle(fastBitmap, checkPoint, cropDifference);
|
||||||
if (currentRectangle.Width * currentRectangle.Height > cropRectangle.Width * cropRectangle.Height) {
|
if (currentRectangle.Width * currentRectangle.Height > cropRectangle.Width * cropRectangle.Height) {
|
||||||
cropRectangle = currentRectangle;
|
cropRectangle = currentRectangle;
|
||||||
}
|
}
|
||||||
|
@ -1344,7 +1344,7 @@ namespace GreenshotPlugin.Core {
|
||||||
if (!includeAlpha) {
|
if (!includeAlpha) {
|
||||||
toCount = toCount & 0xffffff;
|
toCount = toCount & 0xffffff;
|
||||||
}
|
}
|
||||||
using (BitmapBuffer bb = new BitmapBuffer(sourceImage)) {
|
using (BitmapBuffer bb = new BitmapBuffer(sourceImage, false)) {
|
||||||
bb.Lock();
|
bb.Lock();
|
||||||
for (int y = 0; y < bb.Height; y++) {
|
for (int y = 0; y < bb.Height; y++) {
|
||||||
for (int x = 0; x < bb.Width; x++) {
|
for (int x = 0; x < bb.Width; x++) {
|
||||||
|
|
|
@ -147,21 +147,13 @@ namespace GreenshotPlugin.Core {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use a bitmap to store the initial match, which is just as good as an array and saves us 2x the storage
|
// Use a bitmap to store the initial match, which is just as good as an array and saves us 2x the storage
|
||||||
resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height, PixelFormat.Format8bppIndexed);
|
using (IFastBitmap sourceFastBitmap = FastBitmap.Create(sourceBitmap)) {
|
||||||
resultBitmap.SetResolution(sourceBitmap.HorizontalResolution, sourceBitmap.VerticalResolution);
|
sourceFastBitmap.Lock();
|
||||||
bool is8Bit = sourceBitmap.PixelFormat == PixelFormat.Format8bppIndexed;
|
using (FastChunkyBitmap destinationFastBitmap = FastBitmap.CreateEmpty(sourceBitmap.Size, PixelFormat.Format8bppIndexed, Color.White) as FastChunkyBitmap) {
|
||||||
using (BitmapBuffer bbbSrc = new BitmapBuffer(sourceBitmap, false)) {
|
destinationFastBitmap.Lock();
|
||||||
bbbSrc.Lock();
|
for (int y = 0; y < sourceFastBitmap.Height; y++) {
|
||||||
using (BitmapBuffer bbbDest = new BitmapBuffer(resultBitmap, false)) {
|
for (int x = 0; x < sourceFastBitmap.Width; x++) {
|
||||||
bbbDest.Lock();
|
Color color = sourceFastBitmap.GetColorAt(x, y);
|
||||||
for (int y = 0; y < bbbSrc.Height; y++) {
|
|
||||||
for (int x = 0; x < bbbSrc.Width; x++) {
|
|
||||||
Color color;
|
|
||||||
if (is8Bit) {
|
|
||||||
color = bbbSrc.GetColor(x, y);
|
|
||||||
} else {
|
|
||||||
color = bbbSrc.GetColorAtWithoutAlpha(x, y);
|
|
||||||
}
|
|
||||||
// To count the colors
|
// To count the colors
|
||||||
int index = color.ToArgb() & 0x00ffffff;
|
int index = color.ToArgb() & 0x00ffffff;
|
||||||
// Check if we already have this color
|
// Check if we already have this color
|
||||||
|
@ -183,9 +175,10 @@ namespace GreenshotPlugin.Core {
|
||||||
|
|
||||||
// Store the initial "match"
|
// Store the initial "match"
|
||||||
Int32 paletteIndex = (indexRed << 10) + (indexRed << 6) + indexRed + (indexGreen << 5) + indexGreen + indexBlue;
|
Int32 paletteIndex = (indexRed << 10) + (indexRed << 6) + indexRed + (indexGreen << 5) + indexGreen + indexBlue;
|
||||||
bbbDest.SetColorIndexAt(x, y, (byte)(paletteIndex & 0xff));
|
destinationFastBitmap.SetColorIndexAt(x, y, (byte)(paletteIndex & 0xff));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
resultBitmap = destinationFastBitmap.UnlockAndReturnBitmap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,20 +197,14 @@ namespace GreenshotPlugin.Core {
|
||||||
public Bitmap SimpleReindex() {
|
public Bitmap SimpleReindex() {
|
||||||
List<Color> colors = new List<Color>();
|
List<Color> colors = new List<Color>();
|
||||||
Dictionary<Color, byte> lookup = new Dictionary<Color, byte>();
|
Dictionary<Color, byte> lookup = new Dictionary<Color, byte>();
|
||||||
using (BitmapBuffer bbbDest = new BitmapBuffer(resultBitmap, false)) {
|
using (FastChunkyBitmap bbbDest = FastBitmap.Create(resultBitmap) as FastChunkyBitmap) {
|
||||||
bbbDest.Lock();
|
bbbDest.Lock();
|
||||||
using (BitmapBuffer bbbSrc = new BitmapBuffer(sourceBitmap, false)) {
|
using (IFastBitmap bbbSrc = FastBitmap.Create(sourceBitmap)) {
|
||||||
bbbSrc.Lock();
|
bbbSrc.Lock();
|
||||||
byte index;
|
byte index;
|
||||||
bool is8Bit = sourceBitmap.PixelFormat == PixelFormat.Format8bppIndexed;
|
|
||||||
for (int y = 0; y < bbbSrc.Height; y++) {
|
for (int y = 0; y < bbbSrc.Height; y++) {
|
||||||
for (int x = 0; x < bbbSrc.Width; x++) {
|
for (int x = 0; x < bbbSrc.Width; x++) {
|
||||||
Color color;
|
Color color = bbbSrc.GetColorAt(x, y);
|
||||||
if (is8Bit) {
|
|
||||||
color = bbbSrc.GetColor(x, y);
|
|
||||||
} else {
|
|
||||||
color = bbbSrc.GetColorAt(x, y);
|
|
||||||
}
|
|
||||||
if (lookup.ContainsKey(color)) {
|
if (lookup.ContainsKey(color)) {
|
||||||
index = lookup[color];
|
index = lookup[color];
|
||||||
} else {
|
} else {
|
||||||
|
@ -233,11 +220,12 @@ namespace GreenshotPlugin.Core {
|
||||||
|
|
||||||
// generates palette
|
// generates palette
|
||||||
ColorPalette imagePalette = resultBitmap.Palette;
|
ColorPalette imagePalette = resultBitmap.Palette;
|
||||||
|
Color[] entries = imagePalette.Entries;
|
||||||
for (Int32 paletteIndex = 0; paletteIndex < 256; paletteIndex++) {
|
for (Int32 paletteIndex = 0; paletteIndex < 256; paletteIndex++) {
|
||||||
if (paletteIndex < colorCount) {
|
if (paletteIndex < colorCount) {
|
||||||
imagePalette.Entries[paletteIndex] = colors[paletteIndex];
|
entries[paletteIndex] = colors[paletteIndex];
|
||||||
} else {
|
} else {
|
||||||
imagePalette.Entries[paletteIndex] = Color.Black;
|
entries[paletteIndex] = Color.Black;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resultBitmap.Palette = imagePalette;
|
resultBitmap.Palette = imagePalette;
|
||||||
|
@ -324,22 +312,16 @@ namespace GreenshotPlugin.Core {
|
||||||
|
|
||||||
LOG.Info("Starting bitmap reconstruction...");
|
LOG.Info("Starting bitmap reconstruction...");
|
||||||
|
|
||||||
using (BitmapBuffer bbbDest = new BitmapBuffer(resultBitmap, false)) {
|
using (FastChunkyBitmap bbbDest = FastBitmap.Create(resultBitmap) as FastChunkyBitmap) {
|
||||||
bbbDest.Lock();
|
bbbDest.Lock();
|
||||||
using (BitmapBuffer bbbSrc = new BitmapBuffer(sourceBitmap, false)) {
|
using (IFastBitmap bbbSrc = FastBitmap.Create(sourceBitmap)) {
|
||||||
bbbSrc.Lock();
|
bbbSrc.Lock();
|
||||||
Dictionary<Color, byte> lookup = new Dictionary<Color, byte>();
|
Dictionary<Color, byte> lookup = new Dictionary<Color, byte>();
|
||||||
byte bestMatch;
|
byte bestMatch;
|
||||||
bool is8Bit = sourceBitmap.PixelFormat == PixelFormat.Format8bppIndexed;
|
|
||||||
for (int y = 0; y < bbbSrc.Height; y++) {
|
for (int y = 0; y < bbbSrc.Height; y++) {
|
||||||
for (int x = 0; x < bbbSrc.Width; x++) {
|
for (int x = 0; x < bbbSrc.Width; x++) {
|
||||||
Color color;
|
// Consider WithoutAlpha
|
||||||
if (is8Bit) {
|
Color color = bbbSrc.GetColorAt(x, y);
|
||||||
color = bbbSrc.GetColor(x, y);
|
|
||||||
} else {
|
|
||||||
color = bbbSrc.GetColorAtWithoutAlpha(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// No need to a strip the alpha as before
|
// No need to a strip the alpha as before
|
||||||
|
|
||||||
// Check if we already matched the color
|
// Check if we already matched the color
|
||||||
|
@ -386,6 +368,7 @@ namespace GreenshotPlugin.Core {
|
||||||
|
|
||||||
// generates palette
|
// generates palette
|
||||||
ColorPalette imagePalette = resultBitmap.Palette;
|
ColorPalette imagePalette = resultBitmap.Palette;
|
||||||
|
Color[] entries = imagePalette.Entries;
|
||||||
for (Int32 paletteIndex = 0; paletteIndex < allowedColorCount; paletteIndex++) {
|
for (Int32 paletteIndex = 0; paletteIndex < allowedColorCount; paletteIndex++) {
|
||||||
if (sums[paletteIndex] > 0) {
|
if (sums[paletteIndex] > 0) {
|
||||||
reds[paletteIndex] /= sums[paletteIndex];
|
reds[paletteIndex] /= sums[paletteIndex];
|
||||||
|
@ -393,7 +376,7 @@ namespace GreenshotPlugin.Core {
|
||||||
blues[paletteIndex] /= sums[paletteIndex];
|
blues[paletteIndex] /= sums[paletteIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
imagePalette.Entries[paletteIndex] = Color.FromArgb(255, reds[paletteIndex], greens[paletteIndex], blues[paletteIndex]);
|
entries[paletteIndex] = Color.FromArgb(255, reds[paletteIndex], greens[paletteIndex], blues[paletteIndex]);
|
||||||
}
|
}
|
||||||
resultBitmap.Palette = imagePalette;
|
resultBitmap.Palette = imagePalette;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue