| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % CCCC L IIIII PPPP BBBB OOO AAA RRRR DDDD % |
| % C L I P P B B O O A A R R D D % |
| % C L I PPP BBBB O O AAAAA RRRR D D % |
| % C L I P B B O O A A R R D D % |
| % CCCC LLLLL IIIII P BBBB OOO A A R R DDDD % |
| % % |
| % % |
| % Read/Write Windows Clipboard. % |
| % % |
| % Software Design % |
| % Leonard Rosenthol % |
| % May 2002 % |
| % % |
| % % |
| % Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization % |
| % dedicated to making software imaging solutions freely available. % |
| % % |
| % You may not use this file except in compliance with the License. You may % |
| % obtain a copy of the License at % |
| % % |
| % https://imagemagick.org/script/license.php % |
| % % |
| % Unless required by applicable law or agreed to in writing, software % |
| % distributed under the License is distributed on an "AS IS" BASIS, % |
| % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % |
| % See the License for the specific language governing permissions and % |
| % limitations under the License. % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % |
| */ |
| |
| /* |
| Include declarations. |
| */ |
| #include "MagickCore/studio.h" |
| #if defined(MAGICKCORE_WINGDI32_DELEGATE) |
| # if defined(__CYGWIN__) |
| # include <windows.h> |
| # else |
| /* All MinGW needs ... */ |
| # include "MagickCore/nt-base-private.h" |
| # include <wingdi.h> |
| # endif |
| #endif |
| #include "MagickCore/blob.h" |
| #include "MagickCore/blob-private.h" |
| #include "MagickCore/cache.h" |
| #include "MagickCore/exception.h" |
| #include "MagickCore/exception-private.h" |
| #include "MagickCore/image.h" |
| #include "MagickCore/image-private.h" |
| #include "MagickCore/list.h" |
| #include "MagickCore/magick.h" |
| #include "MagickCore/memory_.h" |
| #include "MagickCore/nt-feature.h" |
| #include "MagickCore/pixel-accessor.h" |
| #include "MagickCore/quantum-private.h" |
| #include "MagickCore/static.h" |
| #include "MagickCore/string_.h" |
| #include "MagickCore/module.h" |
| |
| #define BMP_HEADER_SIZE 14 |
| |
| /* |
| Forward declarations. |
| */ |
| #if defined(MAGICKCORE_WINGDI32_DELEGATE) |
| static MagickBooleanType |
| WriteCLIPBOARDImage(const ImageInfo *,Image *,ExceptionInfo *); |
| #endif |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % R e a d C L I P B O A R D I m a g e % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % ReadCLIPBOARDImage() reads an image from the system clipboard and returns |
| % it. It allocates the memory necessary for the new Image structure and |
| % returns a pointer to the new image. |
| % |
| % The format of the ReadCLIPBOARDImage method is: |
| % |
| % Image *ReadCLIPBOARDImage(const ImageInfo *image_info, |
| % ExceptionInfo exception) |
| % |
| % A description of each parameter follows: |
| % |
| % o image_info: the image info. |
| % |
| % o exception: return any errors or warnings in this structure. |
| % |
| */ |
| #if defined(MAGICKCORE_WINGDI32_DELEGATE) |
| static Image *ReadCLIPBOARDImage(const ImageInfo *image_info, |
| ExceptionInfo *exception) |
| { |
| unsigned char |
| *p; |
| |
| HANDLE |
| clip_handle; |
| |
| Image |
| *image; |
| |
| ImageInfo |
| *read_info; |
| |
| LPVOID |
| clip_mem; |
| |
| size_t |
| clip_size, |
| total_size; |
| |
| unsigned char |
| offset; |
| |
| void |
| *clip_data; |
| |
| assert(image_info != (const ImageInfo *) NULL); |
| assert(image_info->signature == MagickCoreSignature); |
| if (image_info->debug != MagickFalse) |
| (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", |
| image_info->filename); |
| assert(exception != (ExceptionInfo *) NULL); |
| assert(exception->signature == MagickCoreSignature); |
| image=AcquireImage(image_info,exception); |
| if (!IsClipboardFormatAvailable(CF_DIB) && |
| !IsClipboardFormatAvailable(CF_DIBV5)) |
| ThrowReaderException(CoderError,"NoBitmapOnClipboard"); |
| if (!OpenClipboard(NULL)) |
| ThrowReaderException(CoderError,"UnableToReadImageData"); |
| clip_handle=GetClipboardData(CF_DIBV5); |
| if (!clip_handle) |
| clip_handle=GetClipboardData(CF_DIB); |
| if ((clip_handle == NULL) || (clip_handle == INVALID_HANDLE_VALUE)) |
| { |
| CloseClipboard(); |
| ThrowReaderException(CoderError,"UnableToReadImageData"); |
| } |
| clip_size=(size_t) GlobalSize(clip_handle); |
| total_size=clip_size+BMP_HEADER_SIZE; |
| clip_data=AcquireMagickMemory(total_size); |
| if (clip_data == (void *) NULL) |
| { |
| CloseClipboard(); |
| ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); |
| } |
| clip_mem=GlobalLock(clip_handle); |
| if (clip_mem == (LPVOID) NULL) |
| { |
| CloseClipboard(); |
| clip_data=RelinquishMagickMemory(clip_data); |
| ThrowReaderException(CoderError,"UnableToReadImageData"); |
| } |
| p=(unsigned char *) clip_data; |
| p+=BMP_HEADER_SIZE; |
| (void) memcpy(p,clip_mem,clip_size); |
| (void) GlobalUnlock(clip_mem); |
| (void) CloseClipboard(); |
| memset(clip_data,0,BMP_HEADER_SIZE); |
| offset=p[0]; |
| if ((p[0] == 40) && (p[16] == BI_BITFIELDS)) |
| offset+=12; |
| else |
| { |
| unsigned int |
| image_size; |
| |
| image_size=(unsigned int) p[20]; |
| image_size|=(unsigned int) p[21] << 8; |
| image_size|=(unsigned int) p[22] << 16; |
| image_size|=(unsigned int) p[23] << 24; |
| /* Hack for chrome where the offset seems to be incorrect */ |
| if (clip_size - offset - image_size == 12) |
| offset+=12; |
| } |
| offset+=BMP_HEADER_SIZE; |
| p-=BMP_HEADER_SIZE; |
| p[0]='B'; |
| p[1]='M'; |
| p[2]=(unsigned char) total_size; |
| p[3]=(unsigned char) (total_size >> 8); |
| p[4]=(unsigned char) (total_size >> 16); |
| p[5]=(unsigned char) (total_size >> 24); |
| p[10]=offset; |
| read_info=CloneImageInfo(image_info); |
| (void) CopyMagickString(read_info->magick,"BMP",MagickPathExtent); |
| image=BlobToImage(read_info,clip_data,total_size,exception); |
| read_info=DestroyImageInfo(read_info); |
| clip_data=RelinquishMagickMemory(clip_data); |
| return(image); |
| } |
| #endif /* MAGICKCORE_WINGDI32_DELEGATE */ |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % R e g i s t e r C L I P B O A R D I m a g e % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % RegisterCLIPBOARDImage() adds attributes for the clipboard "image format" to |
| % the list of supported formats. The attributes include the image format |
| % tag, a method to read and/or write the format, whether the format |
| % supports the saving of more than one frame to the same file or blob, |
| % whether the format supports native in-memory I/O, and a brief |
| % description of the format. |
| % |
| % The format of the RegisterCLIPBOARDImage method is: |
| % |
| % size_t RegisterCLIPBOARDImage(void) |
| % |
| */ |
| ModuleExport size_t RegisterCLIPBOARDImage(void) |
| { |
| MagickInfo |
| *entry; |
| |
| entry=AcquireMagickInfo("CLIPBOARD","CLIPBOARD","The system clipboard"); |
| #if defined(MAGICKCORE_WINGDI32_DELEGATE) |
| entry->decoder=(DecodeImageHandler *) ReadCLIPBOARDImage; |
| entry->encoder=(EncodeImageHandler *) WriteCLIPBOARDImage; |
| #endif |
| entry->flags^=CoderAdjoinFlag; |
| entry->format_type=ImplicitFormatType; |
| (void) RegisterMagickInfo(entry); |
| return(MagickImageCoderSignature); |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % U n r e g i s t e r C L I P B O A R D I m a g e % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % UnregisterCLIPBOARDImage() removes format registrations made by the |
| % RGB module from the list of supported formats. |
| % |
| % The format of the UnregisterCLIPBOARDImage method is: |
| % |
| % UnregisterCLIPBOARDImage(void) |
| % |
| */ |
| ModuleExport void UnregisterCLIPBOARDImage(void) |
| { |
| (void) UnregisterMagickInfo("CLIPBOARD"); |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % W r i t e C L I P B O A R D I m a g e % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % WriteCLIPBOARDImage() writes an image to the system clipboard. |
| % |
| % The format of the WriteCLIPBOARDImage method is: |
| % |
| % MagickBooleanType WriteCLIPBOARDImage(const ImageInfo *image_info, |
| % Image *image,ExceptionInfo *exception) |
| % |
| % A description of each parameter follows. |
| % |
| % o image_info: the image info. |
| % |
| % o image: The image. |
| % |
| % o exception: return any errors or warnings in this structure. |
| % |
| */ |
| #if defined(MAGICKCORE_WINGDI32_DELEGATE) |
| static MagickBooleanType WriteCLIPBOARDImage(const ImageInfo *image_info, |
| Image *image,ExceptionInfo *exception) |
| { |
| HANDLE |
| clip_handle; |
| |
| ImageInfo |
| *write_info; |
| |
| LPVOID |
| clip_mem; |
| |
| size_t |
| length; |
| |
| unsigned char |
| *p; |
| |
| void |
| *clip_data; |
| |
| assert(image_info != (const ImageInfo *) NULL); |
| assert(image_info->signature == MagickCoreSignature); |
| assert(image != (Image *) NULL); |
| assert(image->signature == MagickCoreSignature); |
| if (image->debug != MagickFalse) |
| (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); |
| if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) |
| ThrowWriterException(CoderError,"UnableToWriteImageData"); |
| write_info=CloneImageInfo(image_info); |
| if (image->alpha_trait == UndefinedPixelTrait) |
| (void) CopyMagickString(write_info->magick,"BMP3",MagickPathExtent); |
| else |
| (void) CopyMagickString(write_info->magick,"BMP",MagickPathExtent); |
| clip_data=ImageToBlob(write_info,image,&length,exception); |
| write_info=DestroyImageInfo(write_info); |
| if (clip_data == (void *) NULL) |
| ThrowWriterException(CoderError,"UnableToWriteImageData"); |
| clip_handle=(HANDLE) GlobalAlloc(GMEM_MOVEABLE,length-BMP_HEADER_SIZE); |
| if (clip_handle == (HANDLE) NULL) |
| { |
| clip_data=RelinquishMagickMemory(clip_data); |
| ThrowWriterException(CoderError,"UnableToWriteImageData"); |
| } |
| clip_mem=GlobalLock(clip_handle); |
| if (clip_mem == (LPVOID) NULL) |
| { |
| (void) GlobalFree((HGLOBAL) clip_handle); |
| clip_data=RelinquishMagickMemory(clip_data); |
| ThrowWriterException(CoderError,"UnableToWriteImageData"); |
| } |
| p=(unsigned char *) clip_data; |
| p+=BMP_HEADER_SIZE; |
| (void) memcpy(clip_mem,p,length-BMP_HEADER_SIZE); |
| (void) GlobalUnlock(clip_mem); |
| clip_data=RelinquishMagickMemory(clip_data); |
| if (!OpenClipboard(NULL)) |
| { |
| (void) GlobalFree((HGLOBAL) clip_handle); |
| ThrowWriterException(CoderError,"UnableToWriteImageData"); |
| } |
| (void) EmptyClipboard(); |
| if (image->alpha_trait == UndefinedPixelTrait) |
| SetClipboardData(CF_DIB,clip_handle); |
| else |
| SetClipboardData(CF_DIBV5,clip_handle); |
| (void) CloseClipboard(); |
| return(MagickTrue); |
| } |
| #endif /* MAGICKCORE_WINGDI32_DELEGATE */ |