mirror of
https://github.com/ShareX/ShareX.git
synced 2024-10-01 09:47:22 +13:00
fixed #1261: Properly convert DIB to image
This commit is contained in:
parent
341784cc93
commit
db93b5a6dc
4 changed files with 198 additions and 40 deletions
|
@ -37,6 +37,8 @@ namespace ShareX.HelpersLib
|
|||
public static class ClipboardHelpers
|
||||
{
|
||||
private const int RetryTimes = 20, RetryDelay = 100;
|
||||
private const string FORMAT_PNG = "PNG";
|
||||
private const string FORMAT_17 = "Format17";
|
||||
|
||||
private static readonly object ClipboardLock = new object();
|
||||
|
||||
|
@ -267,46 +269,44 @@ private static Image GetImageAlternative()
|
|||
{
|
||||
string[] dataFormats = dataObject.GetFormats(false);
|
||||
|
||||
if (dataFormats.Contains("PNG"))
|
||||
if (dataFormats.Contains(FORMAT_PNG))
|
||||
{
|
||||
using (MemoryStream ms = (MemoryStream)dataObject.GetData("PNG"))
|
||||
using (MemoryStream ms = dataObject.GetData(FORMAT_PNG) as MemoryStream)
|
||||
{
|
||||
return (Image)Image.FromStream(ms).Clone();
|
||||
if (ms != null)
|
||||
{
|
||||
using (Image img = Image.FromStream(ms))
|
||||
{
|
||||
return (Image)img.Clone();
|
||||
}
|
||||
}
|
||||
|
||||
if (dataFormats.Contains(DataFormats.Dib))
|
||||
{
|
||||
byte[] dib;
|
||||
|
||||
using (MemoryStream ms = (MemoryStream)dataObject.GetData(DataFormats.Dib))
|
||||
{
|
||||
dib = ms.ToArray();
|
||||
}
|
||||
|
||||
short bpp = BitConverter.ToInt16(dib, 14);
|
||||
|
||||
if (bpp == 32)
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (string format in new[] { DataFormats.Dib, FORMAT_17 })
|
||||
{
|
||||
if (dataFormats.Contains(format))
|
||||
{
|
||||
using (MemoryStream ms = dataObject.GetData(format) as MemoryStream)
|
||||
{
|
||||
if (ms != null)
|
||||
{
|
||||
GCHandle gch = GCHandle.Alloc(dib, GCHandleType.Pinned);
|
||||
|
||||
try
|
||||
{
|
||||
int width = BitConverter.ToInt32(dib, 4);
|
||||
int height = BitConverter.ToInt32(dib, 8);
|
||||
int stride = width * 4;
|
||||
IntPtr ptr = new IntPtr((long)gch.AddrOfPinnedObject() + 40);
|
||||
Image img = GetDIBImage(ms);
|
||||
|
||||
using (Bitmap bmp = new Bitmap(width, height, stride, PixelFormat.Format32bppArgb, ptr))
|
||||
if (img != null)
|
||||
{
|
||||
Image img = (Image)bmp.Clone();
|
||||
img.RotateFlip(RotateFlipType.Rotate180FlipX);
|
||||
return img;
|
||||
}
|
||||
}
|
||||
finally
|
||||
catch (Exception e)
|
||||
{
|
||||
gch.Free();
|
||||
DebugHelper.WriteException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -319,5 +319,36 @@ private static Image GetImageAlternative()
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Image GetDIBImage(MemoryStream ms)
|
||||
{
|
||||
byte[] dib = ms.ToArray();
|
||||
|
||||
BITMAPINFOHEADER infoHeader = Helpers.ByteArrayToStructure<BITMAPINFOHEADER>(dib);
|
||||
|
||||
IntPtr gcHandle = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
GCHandle handle = GCHandle.Alloc(dib, GCHandleType.Pinned);
|
||||
gcHandle = GCHandle.ToIntPtr(handle);
|
||||
|
||||
if (infoHeader.biSizeImage == 0)
|
||||
{
|
||||
infoHeader.biSizeImage = (uint)(infoHeader.biWidth * infoHeader.biHeight * (infoHeader.biBitCount >> 3));
|
||||
}
|
||||
|
||||
return new Bitmap(infoHeader.biWidth, infoHeader.biHeight, -(int)(infoHeader.biSizeImage / infoHeader.biHeight),
|
||||
infoHeader.biBitCount == 32 ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb,
|
||||
new IntPtr((long)handle.AddrOfPinnedObject() + infoHeader.OffsetToPixels + (infoHeader.biHeight - 1) * (int)(infoHeader.biSizeImage / infoHeader.biHeight)));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gcHandle != IntPtr.Zero)
|
||||
{
|
||||
GCHandle.FromIntPtr(gcHandle).Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -38,6 +38,7 @@ You should have received a copy of the GNU General Public License
|
|||
using System.Net.NetworkInformation;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Security.Principal;
|
||||
|
@ -999,5 +1000,19 @@ public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
|
|||
CopyAll(diSourceSubDir, nextTargetSubDir);
|
||||
}
|
||||
}
|
||||
|
||||
public static T ByteArrayToStructure<T>(byte[] bytes) where T : struct
|
||||
{
|
||||
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
||||
|
||||
try
|
||||
{
|
||||
return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
|
||||
}
|
||||
finally
|
||||
{
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2833,4 +2833,14 @@ public enum ScrollInfoMask : uint
|
|||
SIF_TRACKPOS = 0x10,
|
||||
SIF_ALL = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS
|
||||
}
|
||||
|
||||
public enum BI_COMPRESSION : int
|
||||
{
|
||||
BI_RGB = 0,
|
||||
BI_RLE8 = 1,
|
||||
BI_RLE4 = 2,
|
||||
BI_BITFIELDS = 3,
|
||||
BI_JPEG = 4,
|
||||
BI_PNG = 5
|
||||
}
|
||||
}
|
|
@ -513,35 +513,137 @@ public struct AVICOMPRESSOPTIONS
|
|||
public int interleaveEvery;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 2)]
|
||||
public struct BITMAPFILEHEADER
|
||||
{
|
||||
public static readonly short BM = 0x4d42;
|
||||
public short bfType;
|
||||
public int bfSize;
|
||||
public short bfReserved1;
|
||||
public short bfReserved2;
|
||||
public int bfOffBits;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct BITMAPINFOHEADER
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public uint biSize;
|
||||
[FieldOffset(4)]
|
||||
public int biWidth;
|
||||
[FieldOffset(8)]
|
||||
public int biHeight;
|
||||
[FieldOffset(12)]
|
||||
public ushort biPlanes;
|
||||
[FieldOffset(14)]
|
||||
public ushort biBitCount;
|
||||
public BitmapCompressionMode biCompression;
|
||||
[FieldOffset(16)]
|
||||
public BI_COMPRESSION biCompression;
|
||||
[FieldOffset(20)]
|
||||
public uint biSizeImage;
|
||||
[FieldOffset(24)]
|
||||
public int biXPelsPerMeter;
|
||||
[FieldOffset(28)]
|
||||
public int biYPelsPerMeter;
|
||||
[FieldOffset(32)]
|
||||
public uint biClrUsed;
|
||||
[FieldOffset(36)]
|
||||
public uint biClrImportant;
|
||||
[FieldOffset(40)]
|
||||
public uint bV5RedMask;
|
||||
[FieldOffset(44)]
|
||||
public uint bV5GreenMask;
|
||||
[FieldOffset(48)]
|
||||
public uint bV5BlueMask;
|
||||
[FieldOffset(52)]
|
||||
public uint bV5AlphaMask;
|
||||
[FieldOffset(56)]
|
||||
public uint bV5CSType;
|
||||
[FieldOffset(60)]
|
||||
public CIEXYZTRIPLE bV5Endpoints;
|
||||
[FieldOffset(96)]
|
||||
public uint bV5GammaRed;
|
||||
[FieldOffset(100)]
|
||||
public uint bV5GammaGreen;
|
||||
[FieldOffset(104)]
|
||||
public uint bV5GammaBlue;
|
||||
[FieldOffset(108)]
|
||||
public uint bV5Intent;
|
||||
[FieldOffset(112)]
|
||||
public uint bV5ProfileData;
|
||||
[FieldOffset(116)]
|
||||
public uint bV5ProfileSize;
|
||||
[FieldOffset(120)]
|
||||
public uint bV5Reserved;
|
||||
|
||||
public BITMAPINFOHEADER(int width, int height, ushort bitCount)
|
||||
public const int DIB_RGB_COLORS = 0;
|
||||
|
||||
public BITMAPINFOHEADER(int width, int height, ushort bpp)
|
||||
{
|
||||
biSize = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADER));
|
||||
biPlanes = 1;
|
||||
biCompression = BI_COMPRESSION.BI_RGB;
|
||||
biWidth = width;
|
||||
biHeight = height;
|
||||
biPlanes = 1;
|
||||
biBitCount = bitCount;
|
||||
biCompression = BitmapCompressionMode.BI_RGB;
|
||||
biSizeImage = 0;
|
||||
biBitCount = bpp;
|
||||
biSizeImage = (uint)(width * height * (bpp >> 3));
|
||||
biXPelsPerMeter = 0;
|
||||
biYPelsPerMeter = 0;
|
||||
biClrUsed = 0;
|
||||
biClrImportant = 0;
|
||||
bV5RedMask = (uint)255 << 16;
|
||||
bV5GreenMask = (uint)255 << 8;
|
||||
bV5BlueMask = (uint)255;
|
||||
bV5AlphaMask = (uint)255 << 24;
|
||||
bV5CSType = 1934772034;
|
||||
bV5Endpoints = new CIEXYZTRIPLE();
|
||||
bV5Endpoints.ciexyzBlue = new CIEXYZ(0);
|
||||
bV5Endpoints.ciexyzGreen = new CIEXYZ(0);
|
||||
bV5Endpoints.ciexyzRed = new CIEXYZ(0);
|
||||
bV5GammaRed = 0;
|
||||
bV5GammaGreen = 0;
|
||||
bV5GammaBlue = 0;
|
||||
bV5Intent = 4;
|
||||
bV5ProfileData = 0;
|
||||
bV5ProfileSize = 0;
|
||||
bV5Reserved = 0;
|
||||
}
|
||||
|
||||
public uint OffsetToPixels
|
||||
{
|
||||
get
|
||||
{
|
||||
if (biCompression == BI_COMPRESSION.BI_BITFIELDS)
|
||||
{
|
||||
return biSize + 3 * 4;
|
||||
}
|
||||
|
||||
return biSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CIEXYZ
|
||||
{
|
||||
public uint ciexyzX;
|
||||
public uint ciexyzY;
|
||||
public uint ciexyzZ;
|
||||
|
||||
public CIEXYZ(uint FXPT2DOT30)
|
||||
{
|
||||
ciexyzX = FXPT2DOT30;
|
||||
ciexyzY = FXPT2DOT30;
|
||||
ciexyzZ = FXPT2DOT30;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CIEXYZTRIPLE
|
||||
{
|
||||
public CIEXYZ ciexyzRed;
|
||||
public CIEXYZ ciexyzGreen;
|
||||
public CIEXYZ ciexyzBlue;
|
||||
}
|
||||
|
||||
public struct INPUT
|
||||
|
|
Loading…
Reference in a new issue