Bug 460969 - Fix image to clipboard code; r=netzen

This commit is contained in:
Eddy Bruel 2012-07-31 14:11:55 +02:00
parent 5f2eb8fa49
commit 76e80f4db0
3 changed files with 46 additions and 42 deletions

View File

@ -78,7 +78,7 @@ UINT nsClipboard::GetFormat(const char* aMimeStr)
else if (strcmp(aMimeStr, kJPEGImageMime) == 0 ||
strcmp(aMimeStr, kJPGImageMime) == 0 ||
strcmp(aMimeStr, kPNGImageMime) == 0)
format = CF_DIB;
format = CF_DIBV5;
else if (strcmp(aMimeStr, kFileMime) == 0 ||
strcmp(aMimeStr, kFilePromiseMime) == 0)
format = CF_HDROP;
@ -191,7 +191,7 @@ nsresult nsClipboard::SetupNativeDataObject(nsITransferable * aTransferable, IDa
strcmp(flavorStr, kNativeImageMime) == 0 ) {
// if we're an image, register the native bitmap flavor
FORMATETC imageFE;
SET_FORMATETC(imageFE, CF_DIB, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
SET_FORMATETC(imageFE, CF_DIBV5, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL)
dObj->AddDataFlavor(flavorStr, &imageFE);
}
else if ( strcmp(flavorStr, kFilePromiseMime) == 0 ) {
@ -371,7 +371,7 @@ static HRESULT FillSTGMedium(IDataObject * aDataObject, UINT aFormat, LPFORMATET
//-------------------------------------------------------------------------
// If aFormat is CF_DIB, aMIMEImageFormat must be a type for which we have
// If aFormat is CF_DIBV5, aMIMEImageFormat must be a type for which we have
// an image encoder (e.g. image/png).
// For other values of aFormat, it is OK to pass null for aMIMEImageFormat.
nsresult nsClipboard::GetNativeDataOffClipboard(IDataObject * aDataObject, UINT aIndex, UINT aFormat, const char * aMIMEImageFormat, void ** aData, PRUint32 * aLen)
@ -435,7 +435,7 @@ nsresult nsClipboard::GetNativeDataOffClipboard(IDataObject * aDataObject, UINT
}
} break;
case CF_DIB :
case CF_DIBV5:
if (aMIMEImageFormat)
{
PRUint32 allocLen = 0;

View File

@ -503,7 +503,7 @@ STDMETHODIMP nsDataObj::GetData(LPFORMATETC aFormat, LPSTGMEDIUM pSTM)
return GetFile(*aFormat, *pSTM);
// Someone is asking for an image
case CF_DIB:
case CF_DIBV5:
return GetDib(df, *aFormat, *pSTM);
default:

View File

@ -13,6 +13,8 @@
#include "nsLiteralString.h"
#include "nsComponentManagerUtils.h"
#define BFH_LENGTH 14
/* Things To Do 11/8/00
Check image metrics, can we support them? Do we need to?
@ -116,47 +118,49 @@ nsImageToClipboard::CreateFromImage ( imgIContainer* inImage, HANDLE* outBitmap
nsresult rv = inImage->CopyFrame(imgIContainer::FRAME_CURRENT,
imgIContainer::FLAG_SYNC_DECODE,
getter_AddRefs(frame));
if (NS_FAILED(rv))
return rv;
NS_ENSURE_SUCCESS(rv, rv);
const PRUint32 imageSize = frame->GetDataSize();
const PRInt32 bitmapSize = sizeof(BITMAPINFOHEADER) + imageSize;
HGLOBAL glob = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, bitmapSize);
if (!glob) {
return NS_ERROR_OUT_OF_MEMORY;
}
// Create the buffer where we'll copy the image bits (and header) into and lock it
void *data = (void*)::GlobalLock(glob);
BITMAPINFOHEADER *header = (BITMAPINFOHEADER*)data;
header->biSize = sizeof(BITMAPINFOHEADER);
header->biWidth = frame->Width();
header->biHeight = frame->Height();
header->biPlanes = 1;
if (frame->Format() == gfxASurface::ImageFormatARGB32)
header->biBitCount = 32;
else if (frame->Format() == gfxASurface::ImageFormatRGB24)
header->biBitCount = 24;
header->biCompression = BI_RGB;
header->biSizeImage = imageSize;
const PRUint32 bpr = frame->Stride();
BYTE *dstBits = (BYTE*)data + sizeof(BITMAPINFOHEADER);
BYTE *srcBits = frame->Data();
for (PRInt32 i = 0; i < header->biHeight; ++i) {
PRUint32 srcOffset = imageSize - (bpr * (i + 1));
PRUint32 dstOffset = i * bpr;
::CopyMemory(dstBits + dstOffset, srcBits + srcOffset, bpr);
}
nsCOMPtr<imgIEncoder> encoder = do_CreateInstance("@mozilla.org/image/encoder;2?type=image/bmp", &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 format;
nsAutoString options;
options.AppendASCII("version=5;bpp=");
switch (frame->Format()) {
case gfxASurface::ImageFormatARGB32:
format = imgIEncoder::INPUT_FORMAT_HOSTARGB;
options.AppendInt(32);
break;
case gfxASurface::ImageFormatRGB24:
format = imgIEncoder::INPUT_FORMAT_RGB;
options.AppendInt(24);
break;
default:
return NS_ERROR_INVALID_ARG;
}
rv = encoder->InitFromData(frame->Data(), 0, frame->Width(),
frame->Height(), frame->Stride(),
format, options);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 size;
encoder->GetImageBufferUsed(&size);
NS_ENSURE_TRUE(size > BFH_LENGTH, NS_ERROR_FAILURE);
HGLOBAL glob = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT,
size - BFH_LENGTH);
if (!glob)
return NS_ERROR_OUT_OF_MEMORY;
char *dst = (char*) ::GlobalLock(glob);
char *src;
rv = encoder->GetImageBuffer(&src);
NS_ENSURE_SUCCESS(rv, rv);
::CopyMemory(dst, src + BFH_LENGTH, size - BFH_LENGTH);
::GlobalUnlock(glob);
*outBitmap = (HANDLE)glob;
return NS_OK;
}