mirror of
https://github.com/greenshot/greenshot
synced 2025-08-22 06:23:24 -07:00
Merge branch 'release/1.3' into feature/ImproveFileFormatSupport
This commit is contained in:
commit
43a1e964d5
4 changed files with 292 additions and 88 deletions
|
@ -667,8 +667,8 @@ EndSelection:<<<<<<<4
|
|||
if (imageStream != null)
|
||||
{
|
||||
byte[] dibBuffer = new byte[imageStream.Length];
|
||||
imageStream.Read(dibBuffer, 0, dibBuffer.Length);
|
||||
var infoHeader = BinaryStructHelper.FromByteArray<BITMAPINFOHEADER>(dibBuffer);
|
||||
_ = imageStream.Read(dibBuffer, 0, dibBuffer.Length);
|
||||
var infoHeader = BinaryStructHelper.FromByteArray<BITMAPINFOHEADERV5>(dibBuffer);
|
||||
if (!infoHeader.IsDibV5)
|
||||
{
|
||||
Log.InfoFormat("Using special DIB <v5 format reader with biCompression {0}", infoHeader.biCompression);
|
||||
|
@ -816,8 +816,6 @@ EndSelection:<<<<<<<4
|
|||
return sb.ToString();
|
||||
}
|
||||
|
||||
private const int BITMAPFILEHEADER_LENGTH = 14;
|
||||
|
||||
/// <summary>
|
||||
/// Set an Image to the clipboard
|
||||
/// This method will place images to the clipboard depending on the ClipboardFormats setting.
|
||||
|
@ -869,7 +867,7 @@ EndSelection:<<<<<<<4
|
|||
{
|
||||
// Create the stream for the clipboard
|
||||
dibStream = new MemoryStream();
|
||||
var dibBytes = DibHelper.ConvertToDib(imageToSave);
|
||||
var dibBytes = ((Bitmap)imageToSave).ConvertToDib();
|
||||
dibStream.Write(dibBytes,0, dibBytes.Length);
|
||||
|
||||
// Set the DIB to the clipboard DataObject
|
||||
|
@ -890,7 +888,7 @@ EndSelection:<<<<<<<4
|
|||
dibV5Stream = new MemoryStream();
|
||||
|
||||
// Create the BITMAPINFOHEADER
|
||||
BITMAPINFOHEADER header = new BITMAPINFOHEADER(imageToSave.Width, imageToSave.Height, 32)
|
||||
var header = new BITMAPINFOHEADERV5(imageToSave.Width, imageToSave.Height, 32)
|
||||
{
|
||||
// Make sure we have BI_BITFIELDS, this seems to be normal for Format17?
|
||||
biCompression = BI_COMPRESSION.BI_BITFIELDS
|
||||
|
@ -1127,7 +1125,7 @@ EndSelection:<<<<<<<4
|
|||
/// <returns></returns>
|
||||
public static IEnumerable<string> GetImageFilenames(IDataObject dataObject)
|
||||
{
|
||||
string[] dropFileNames = (string[]) dataObject.GetData(DataFormats.FileDrop);
|
||||
string[] dropFileNames = (string[])dataObject.GetData(DataFormats.FileDrop);
|
||||
if (dropFileNames != null && dropFileNames.Length > 0)
|
||||
{
|
||||
var supportedExtensions = FileFormatHandlerRegistry.ExtensionsFor(FileFormatHandlerActions.LoadFromStream).ToList();
|
||||
|
|
|
@ -1,4 +1,25 @@
|
|||
using System;
|
||||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: https://getgreenshot.org/
|
||||
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Runtime.InteropServices;
|
||||
|
@ -9,77 +30,91 @@ namespace Greenshot.Base.Core
|
|||
/// <summary>
|
||||
/// Though Greenshot implements the specs for the DIB image format,
|
||||
/// it seems to cause a lot of issues when using the clipboard.
|
||||
/// There is some research done about the DIB on the clipboard, this code was taking from:
|
||||
/// There is some research done about the DIB on the clipboard, this code is based upon the information
|
||||
/// <a href="https://stackoverflow.com/questions/44177115/copying-from-and-to-clipboard-loses-image-transparency">here</a>
|
||||
/// </summary>
|
||||
internal static class DibHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts the image to Device Independent Bitmap format of type BITFIELDS.
|
||||
/// This is (wrongly) accepted by many applications as containing transparency,
|
||||
/// so I'm abusing it for that.
|
||||
/// Converts the Bitmap to a Device Independent Bitmap format of type BITFIELDS.
|
||||
/// </summary>
|
||||
/// <param name="image">Image to convert to DIB</param>
|
||||
/// <param name="sourceBitmap">Bitmap to convert to DIB</param>
|
||||
/// <returns>The image converted to DIB, in bytes.</returns>
|
||||
public static byte[] ConvertToDib(Image image)
|
||||
public static byte[] ConvertToDib(this Bitmap sourceBitmap)
|
||||
{
|
||||
byte[] bm32bData;
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
// Ensure image is 32bppARGB by painting it on a new 32bppARGB image.
|
||||
using (var bm32b = ImageHelper.CreateEmptyLike(image, Color.Transparent, PixelFormat.Format32bppArgb))
|
||||
{
|
||||
using (var graphics = Graphics.FromImage(bm32b))
|
||||
{
|
||||
graphics.DrawImage(image, new Rectangle(0, 0, bm32b.Width, bm32b.Height));
|
||||
}
|
||||
// Bitmap format has its lines reversed.
|
||||
bm32b.RotateFlip(RotateFlipType.Rotate180FlipX);
|
||||
bm32bData = GetImageData(bm32b, out var stride);
|
||||
}
|
||||
// BITMAPINFOHEADER struct for DIB.
|
||||
uint hdrSize = 0x28;
|
||||
var fullImage = new byte[hdrSize + 12 + bm32bData.Length];
|
||||
var bitmapInfoHeader = MemoryMarshal.Cast<byte, BITMAPINFOHEADER>(fullImage.AsSpan());
|
||||
if (sourceBitmap == null) throw new ArgumentNullException(nameof(sourceBitmap));
|
||||
|
||||
bitmapInfoHeader[0].biSize = hdrSize;
|
||||
bitmapInfoHeader[0].biWidth = width;
|
||||
bitmapInfoHeader[0].biHeight = height;
|
||||
bool needsDisposal = false;
|
||||
if (sourceBitmap.PixelFormat != PixelFormat.Format32bppArgb)
|
||||
{
|
||||
needsDisposal = true;
|
||||
var clonedImage = ImageHelper.CreateEmptyLike(sourceBitmap, Color.Transparent, PixelFormat.Format32bppArgb);
|
||||
using (var graphics = Graphics.FromImage(clonedImage))
|
||||
{
|
||||
graphics.DrawImage(sourceBitmap, new Rectangle(0, 0, clonedImage.Width, clonedImage.Height));
|
||||
}
|
||||
sourceBitmap = clonedImage;
|
||||
}
|
||||
|
||||
var bitmapSize = 4 * sourceBitmap.Width * sourceBitmap.Height;
|
||||
var bitmapInfoHeaderSize = Marshal.SizeOf(typeof(BITMAPINFOHEADER));
|
||||
var bitmapInfoSize = bitmapInfoHeaderSize + 3 * Marshal.SizeOf(typeof(RGBQUAD));
|
||||
|
||||
// Create a byte [] to contain the DIB
|
||||
var fullBmpBytes = new byte[bitmapInfoSize + bitmapSize];
|
||||
var fullBmpSpan = fullBmpBytes.AsSpan();
|
||||
// Cast the span to be of type BITMAPINFOHEADER so we can assign values
|
||||
// TODO: in .NET 6 we could do a AsRef
|
||||
var bitmapInfoHeader = MemoryMarshal.Cast<byte, BITMAPINFOHEADER>(fullBmpSpan);
|
||||
|
||||
bitmapInfoHeader[0].biSize = (uint)bitmapInfoHeaderSize;
|
||||
bitmapInfoHeader[0].biWidth = sourceBitmap.Width;
|
||||
bitmapInfoHeader[0].biHeight = sourceBitmap.Height;
|
||||
bitmapInfoHeader[0].biPlanes = 1;
|
||||
bitmapInfoHeader[0].biBitCount = 32;
|
||||
bitmapInfoHeader[0].biCompression = BI_COMPRESSION.BI_BITFIELDS;
|
||||
bitmapInfoHeader[0].biSizeImage = (uint)bm32bData.Length;
|
||||
bitmapInfoHeader[0].biXPelsPerMeter = (int)(image.HorizontalResolution * 39.3701);
|
||||
bitmapInfoHeader[0].biYPelsPerMeter = (int)(image.VerticalResolution * 39.3701);
|
||||
bitmapInfoHeader[0].biSizeImage = (uint)bitmapSize;
|
||||
bitmapInfoHeader[0].biXPelsPerMeter = (int)(sourceBitmap.HorizontalResolution * 39.3701);
|
||||
bitmapInfoHeader[0].biYPelsPerMeter = (int)(sourceBitmap.VerticalResolution * 39.3701);
|
||||
|
||||
// The aforementioned "BITFIELDS": color masks applied to the Int32 pixel value to get the R, G and B values.
|
||||
var rgbQuads = MemoryMarshal.Cast<byte, RGBQUAD>(fullBmpSpan.Slice(Marshal.SizeOf(typeof(BITMAPINFOHEADER))));
|
||||
rgbQuads[0].rgbRed = 255;
|
||||
rgbQuads[1].rgbGreen = 255;
|
||||
rgbQuads[2].rgbBlue = 255;
|
||||
|
||||
// The aforementioned "BITFIELDS": colour masks applied to the Int32 pixel value to get the R, G and B values.
|
||||
bitmapInfoHeader[0].bV5RedMask = 0x00FF0000;
|
||||
bitmapInfoHeader[0].bV5GreenMask = 0x0000FF00;
|
||||
bitmapInfoHeader[0].bV5BlueMask = 0x000000FF;
|
||||
// Now copy the lines, in reverse to the byte array
|
||||
var sourceBitmapData = sourceBitmap.LockBits(new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), ImageLockMode.ReadOnly, sourceBitmap.PixelFormat);
|
||||
try
|
||||
{
|
||||
// Get a span for the real bitmap bytes, which starts after the header
|
||||
var bitmapSpan = fullBmpSpan.Slice(bitmapInfoSize);
|
||||
// Make sure we also have a span to copy from
|
||||
Span<byte> bitmapSourceSpan;
|
||||
unsafe
|
||||
{
|
||||
bitmapSourceSpan = new Span<byte>(sourceBitmapData.Scan0.ToPointer(), sourceBitmapData.Stride * sourceBitmapData.Height);
|
||||
}
|
||||
|
||||
// These are all 0. Since .net clears new arrays, don't bother writing them.
|
||||
//Int32 biClrUsed = 0;
|
||||
//Int32 biClrImportant = 0;
|
||||
// Loop over all the lines and copy the top line to the bottom (flipping the image)
|
||||
for (int y = 0; y < sourceBitmap.Height; y++)
|
||||
{
|
||||
var sourceY = (sourceBitmap.Height - 1) - y;
|
||||
var sourceLine = bitmapSourceSpan.Slice(sourceBitmapData.Stride * sourceY, 4 * sourceBitmap.Width);
|
||||
var destinationLine = bitmapSpan.Slice(y * 4 * sourceBitmap.Width);
|
||||
sourceLine.CopyTo(destinationLine);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
sourceBitmap.UnlockBits(sourceBitmapData);
|
||||
}
|
||||
|
||||
Array.Copy(bm32bData, 0, fullImage, hdrSize + 12, bm32bData.Length);
|
||||
return fullImage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the raw bytes from an image.
|
||||
/// </summary>
|
||||
/// <param name="sourceImage">The image to get the bytes from.</param>
|
||||
/// <param name="stride">Stride of the retrieved image data.</param>
|
||||
/// <returns>The raw bytes of the image</returns>
|
||||
public static byte[] GetImageData(Bitmap sourceImage, out int stride)
|
||||
{
|
||||
BitmapData sourceData = sourceImage.LockBits(new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), ImageLockMode.ReadOnly, sourceImage.PixelFormat);
|
||||
stride = sourceData.Stride;
|
||||
byte[] data = new byte[stride * sourceImage.Height];
|
||||
Marshal.Copy(sourceData.Scan0, data, 0, data.Length);
|
||||
sourceImage.UnlockBits(sourceData);
|
||||
return data;
|
||||
if (needsDisposal)
|
||||
{
|
||||
sourceBitmap.Dispose();
|
||||
}
|
||||
return fullBmpBytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -332,13 +332,13 @@ namespace Greenshot.Base.Core
|
|||
}
|
||||
|
||||
// Create BITMAPINFOHEADER for CreateDIBSection
|
||||
BITMAPINFOHEADER bmi = new BITMAPINFOHEADER(captureBounds.Width, captureBounds.Height, 24);
|
||||
BITMAPINFOHEADERV5 bmi = new BITMAPINFOHEADERV5(captureBounds.Width, captureBounds.Height, 24);
|
||||
|
||||
// Make sure the last error is set to 0
|
||||
Win32.SetLastError(0);
|
||||
|
||||
// create a bitmap we can copy it to, using GetDeviceCaps to get the width/height
|
||||
using SafeDibSectionHandle safeDibSectionHandle = GDI32.CreateDIBSection(desktopDcHandle, ref bmi, BITMAPINFOHEADER.DIB_RGB_COLORS, out _, IntPtr.Zero, 0);
|
||||
using SafeDibSectionHandle safeDibSectionHandle = GDI32.CreateDIBSection(desktopDcHandle, ref bmi, BITMAPINFOHEADERV5.DIB_RGB_COLORS, out _, IntPtr.Zero, 0);
|
||||
if (safeDibSectionHandle.IsInvalid)
|
||||
{
|
||||
// Get Exception before the error is lost
|
||||
|
|
|
@ -261,7 +261,7 @@ namespace Greenshot.Base.UnmanagedHelpers
|
|||
public static extern SafeCompatibleDCHandle CreateCompatibleDC(SafeHandle hDC);
|
||||
|
||||
[DllImport("gdi32", SetLastError = true)]
|
||||
public static extern SafeDibSectionHandle CreateDIBSection(SafeHandle hdc, ref BITMAPINFOHEADER bmi, uint Usage, out IntPtr bits, IntPtr hSection, uint dwOffset);
|
||||
public static extern SafeDibSectionHandle CreateDIBSection(SafeHandle hdc, ref BITMAPINFOHEADERV5 bmi, uint usage, out IntPtr bits, IntPtr hSection, uint dwOffset);
|
||||
|
||||
[DllImport("gdi32", SetLastError = true)]
|
||||
public static extern SafeRegionHandle CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
|
||||
|
@ -314,6 +314,15 @@ namespace Greenshot.Base.UnmanagedHelpers
|
|||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct RGBQUAD
|
||||
{
|
||||
public byte rgbBlue;
|
||||
public byte rgbGreen;
|
||||
public byte rgbRed;
|
||||
public byte rgbReserved;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CIEXYZTRIPLE
|
||||
{
|
||||
|
@ -348,15 +357,168 @@ namespace Greenshot.Base.UnmanagedHelpers
|
|||
[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;
|
||||
|
||||
public const int DIB_RGB_COLORS = 0;
|
||||
|
||||
public BITMAPINFOHEADER(int width, int height, ushort bpp)
|
||||
{
|
||||
biSize = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADER)); // BITMAPINFOHEADER < DIBV4 is 40 bytes
|
||||
biPlanes = 1; // Should allways be 1
|
||||
biCompression = BI_COMPRESSION.BI_RGB;
|
||||
biWidth = width;
|
||||
biHeight = height;
|
||||
biBitCount = bpp;
|
||||
biSizeImage = (uint)(width * height * (bpp >> 3));
|
||||
biXPelsPerMeter = 0;
|
||||
biYPelsPerMeter = 0;
|
||||
biClrUsed = 0;
|
||||
biClrImportant = 0;
|
||||
}
|
||||
|
||||
public bool IsDibV4
|
||||
{
|
||||
get
|
||||
{
|
||||
uint sizeOfBMI = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADERV4));
|
||||
return biSize >= sizeOfBMI;
|
||||
}
|
||||
}
|
||||
public bool IsDibV5
|
||||
{
|
||||
get
|
||||
{
|
||||
uint sizeOfBMI = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADERV5));
|
||||
return biSize >= sizeOfBMI;
|
||||
}
|
||||
}
|
||||
|
||||
public uint OffsetToPixels
|
||||
{
|
||||
get
|
||||
{
|
||||
if (biCompression == BI_COMPRESSION.BI_BITFIELDS)
|
||||
{
|
||||
// Add 3x4 bytes for the bitfield color mask
|
||||
return biSize + 3 * 4;
|
||||
}
|
||||
|
||||
return biSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct BITMAPINFOHEADERV4
|
||||
{
|
||||
[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;
|
||||
[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 bV4RedMask;
|
||||
[FieldOffset(44)] public uint bV4GreenMask;
|
||||
[FieldOffset(48)] public uint bV4BlueMask;
|
||||
[FieldOffset(52)] public uint bV4AlphaMask;
|
||||
[FieldOffset(56)] public uint bV4CSType;
|
||||
[FieldOffset(60)] public CIEXYZTRIPLE bV4Endpoints;
|
||||
[FieldOffset(96)] public uint bV4GammaRed;
|
||||
[FieldOffset(100)] public uint bV4GammaGreen;
|
||||
[FieldOffset(104)] public uint bV4GammaBlue;
|
||||
|
||||
public const int DIB_RGB_COLORS = 0;
|
||||
|
||||
public BITMAPINFOHEADERV4(int width, int height, ushort bpp)
|
||||
{
|
||||
biSize = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADERV4)); // BITMAPINFOHEADER < DIBV5 is 40 bytes
|
||||
biPlanes = 1; // Should allways be 1
|
||||
biCompression = BI_COMPRESSION.BI_RGB;
|
||||
biWidth = width;
|
||||
biHeight = height;
|
||||
biBitCount = bpp;
|
||||
biSizeImage = (uint)(width * height * (bpp >> 3));
|
||||
biXPelsPerMeter = 0;
|
||||
biYPelsPerMeter = 0;
|
||||
biClrUsed = 0;
|
||||
biClrImportant = 0;
|
||||
|
||||
// V4
|
||||
bV4RedMask = (uint)255 << 16;
|
||||
bV4GreenMask = (uint)255 << 8;
|
||||
bV4BlueMask = 255;
|
||||
bV4AlphaMask = (uint)255 << 24;
|
||||
bV4CSType = 0x73524742; // LCS_sRGB
|
||||
bV4Endpoints = new CIEXYZTRIPLE
|
||||
{
|
||||
ciexyzBlue = new CIEXYZ(0),
|
||||
ciexyzGreen = new CIEXYZ(0),
|
||||
ciexyzRed = new CIEXYZ(0)
|
||||
};
|
||||
bV4GammaRed = 0;
|
||||
bV4GammaGreen = 0;
|
||||
bV4GammaBlue = 0;
|
||||
}
|
||||
|
||||
public bool IsDibV4
|
||||
{
|
||||
get
|
||||
{
|
||||
uint sizeOfBMI = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADERV4));
|
||||
return biSize >= sizeOfBMI;
|
||||
}
|
||||
}
|
||||
public bool IsDibV5
|
||||
{
|
||||
get
|
||||
{
|
||||
uint sizeOfBMI = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADERV5));
|
||||
return biSize >= sizeOfBMI;
|
||||
}
|
||||
}
|
||||
|
||||
public uint OffsetToPixels
|
||||
{
|
||||
get
|
||||
{
|
||||
if (biCompression == BI_COMPRESSION.BI_BITFIELDS)
|
||||
{
|
||||
// Add 3x4 bytes for the bitfield color mask
|
||||
return biSize + 3 * 4;
|
||||
}
|
||||
|
||||
return biSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct BITMAPINFOHEADERV5
|
||||
{
|
||||
[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;
|
||||
[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 bV4RedMask;
|
||||
[FieldOffset(44)] public uint bV4GreenMask;
|
||||
[FieldOffset(48)] public uint bV4BlueMask;
|
||||
[FieldOffset(52)] public uint bV4AlphaMask;
|
||||
[FieldOffset(56)] public uint bV4CSType;
|
||||
[FieldOffset(60)] public CIEXYZTRIPLE bV4Endpoints;
|
||||
[FieldOffset(96)] public uint bV4GammaRed;
|
||||
[FieldOffset(100)] public uint bV4GammaGreen;
|
||||
[FieldOffset(104)] public uint bV4GammaBlue;
|
||||
[FieldOffset(108)] public uint bV5Intent; // Rendering intent for bitmap
|
||||
[FieldOffset(112)] public uint bV5ProfileData;
|
||||
[FieldOffset(116)] public uint bV5ProfileSize;
|
||||
|
@ -364,9 +526,9 @@ namespace Greenshot.Base.UnmanagedHelpers
|
|||
|
||||
public const int DIB_RGB_COLORS = 0;
|
||||
|
||||
public BITMAPINFOHEADER(int width, int height, ushort bpp)
|
||||
public BITMAPINFOHEADERV5(int width, int height, ushort bpp)
|
||||
{
|
||||
biSize = (uint) Marshal.SizeOf(typeof(BITMAPINFOHEADER)); // BITMAPINFOHEADER < DIBV5 is 40 bytes
|
||||
biSize = (uint) Marshal.SizeOf(typeof(BITMAPINFOHEADERV5)); // BITMAPINFOHEADER < DIBV5 is 40 bytes
|
||||
biPlanes = 1; // Should allways be 1
|
||||
biCompression = BI_COMPRESSION.BI_RGB;
|
||||
biWidth = width;
|
||||
|
@ -378,32 +540,41 @@ namespace Greenshot.Base.UnmanagedHelpers
|
|||
biClrUsed = 0;
|
||||
biClrImportant = 0;
|
||||
|
||||
// V5
|
||||
bV5RedMask = (uint) 255 << 16;
|
||||
bV5GreenMask = (uint) 255 << 8;
|
||||
bV5BlueMask = 255;
|
||||
bV5AlphaMask = (uint) 255 << 24;
|
||||
bV5CSType = 0x73524742; // LCS_sRGB
|
||||
bV5Endpoints = new CIEXYZTRIPLE
|
||||
// V4
|
||||
bV4RedMask = (uint) 255 << 16;
|
||||
bV4GreenMask = (uint) 255 << 8;
|
||||
bV4BlueMask = 255;
|
||||
bV4AlphaMask = (uint) 255 << 24;
|
||||
bV4CSType = 0x73524742; // LCS_sRGB
|
||||
bV4Endpoints = new CIEXYZTRIPLE
|
||||
{
|
||||
ciexyzBlue = new CIEXYZ(0),
|
||||
ciexyzGreen = new CIEXYZ(0),
|
||||
ciexyzRed = new CIEXYZ(0)
|
||||
};
|
||||
bV5GammaRed = 0;
|
||||
bV5GammaGreen = 0;
|
||||
bV5GammaBlue = 0;
|
||||
bV4GammaRed = 0;
|
||||
bV4GammaGreen = 0;
|
||||
bV4GammaBlue = 0;
|
||||
// V5
|
||||
bV5Intent = 4;
|
||||
bV5ProfileData = 0;
|
||||
bV5ProfileSize = 0;
|
||||
bV5Reserved = 0;
|
||||
}
|
||||
|
||||
public bool IsDibV4
|
||||
{
|
||||
get
|
||||
{
|
||||
uint sizeOfBMI = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADERV4));
|
||||
return biSize >= sizeOfBMI;
|
||||
}
|
||||
}
|
||||
public bool IsDibV5
|
||||
{
|
||||
get
|
||||
{
|
||||
uint sizeOfBMI = (uint) Marshal.SizeOf(typeof(BITMAPINFOHEADER));
|
||||
uint sizeOfBMI = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADERV5));
|
||||
return biSize >= sizeOfBMI;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue