]> granicus.if.org Git - imagemagick/blob - coders/clipboard.c
https://github.com/ImageMagick/ImageMagick/issues/1286
[imagemagick] / coders / clipboard.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %        CCCC  L      IIIII  PPPP   BBBB    OOO    AAA   RRRR   DDDD          %
7 %       C      L        I    P   P  B   B  O   O  A   A  R   R  D   D         %
8 %       C      L        I    PPP    BBBB   O   O  AAAAA  RRRR   D   D         %
9 %       C      L        I    P      B   B  O   O  A   A  R R    D   D         %
10 %        CCCC  LLLLL  IIIII  P      BBBB    OOO   A   A  R  R   DDDD          %
11 %                                                                             %
12 %                                                                             %
13 %                        Read/Write Windows Clipboard.                        %
14 %                                                                             %
15 %                              Software Design                                %
16 %                             Leonard Rosenthol                               %
17 %                                 May 2002                                    %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    https://www.imagemagick.org/script/license.php                           %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 \f
39 /*
40   Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #if defined(MAGICKCORE_WINGDI32_DELEGATE)
44 #  if defined(__CYGWIN__)
45 #    include <windows.h>
46 #  else
47      /* All MinGW needs ... */
48 #    include "MagickCore/nt-base-private.h"
49 #    include <wingdi.h>
50 #  endif
51 #endif
52 #include "MagickCore/blob.h"
53 #include "MagickCore/blob-private.h"
54 #include "MagickCore/cache.h"
55 #include "MagickCore/exception.h"
56 #include "MagickCore/exception-private.h"
57 #include "MagickCore/image.h"
58 #include "MagickCore/image-private.h"
59 #include "MagickCore/list.h"
60 #include "MagickCore/magick.h"
61 #include "MagickCore/memory_.h"
62 #include "MagickCore/nt-feature.h"
63 #include "MagickCore/pixel-accessor.h"
64 #include "MagickCore/quantum-private.h"
65 #include "MagickCore/static.h"
66 #include "MagickCore/string_.h"
67 #include "MagickCore/module.h"
68 \f
69 #define BMP_HEADER_SIZE 14
70 \f
71 /*
72   Forward declarations.
73 */
74 #if defined(MAGICKCORE_WINGDI32_DELEGATE)
75 static MagickBooleanType
76   WriteCLIPBOARDImage(const ImageInfo *,Image *,ExceptionInfo *);
77 #endif
78 \f
79 /*
80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81 %                                                                             %
82 %                                                                             %
83 %                                                                             %
84 %   R e a d C L I P B O A R D I m a g e                                       %
85 %                                                                             %
86 %                                                                             %
87 %                                                                             %
88 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
89 %
90 %  ReadCLIPBOARDImage() reads an image from the system clipboard and returns
91 %  it.  It allocates the memory necessary for the new Image structure and
92 %  returns a pointer to the new image.
93 %
94 %  The format of the ReadCLIPBOARDImage method is:
95 %
96 %      Image *ReadCLIPBOARDImage(const ImageInfo *image_info,
97 %        ExceptionInfo exception)
98 %
99 %  A description of each parameter follows:
100 %
101 %    o image_info: the image info.
102 %
103 %    o exception: return any errors or warnings in this structure.
104 %
105 */
106 #if defined(MAGICKCORE_WINGDI32_DELEGATE)
107 static Image *ReadCLIPBOARDImage(const ImageInfo *image_info,
108   ExceptionInfo *exception)
109 {
110   unsigned char
111     *p;
112
113   HANDLE
114     clip_handle;
115
116   Image
117     *image;
118
119   ImageInfo
120     *read_info;
121
122   LPVOID
123     clip_mem;
124
125   MagickBooleanType
126     status;
127
128   register ssize_t
129     x;
130
131   register Quantum
132     *q;
133
134   size_t
135     clip_size,
136     total_size;
137
138   ssize_t
139     y;
140
141   unsigned int
142     offset;
143
144   void
145     *clip_data;
146
147   assert(image_info != (const ImageInfo *) NULL);
148   assert(image_info->signature == MagickCoreSignature);
149   if (image_info->debug != MagickFalse)
150     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
151       image_info->filename);
152   assert(exception != (ExceptionInfo *) NULL);
153   assert(exception->signature == MagickCoreSignature);
154   image=AcquireImage(image_info,exception);
155   if (!IsClipboardFormatAvailable(CF_BITMAP) &&
156       !IsClipboardFormatAvailable(CF_DIB) &&
157       !IsClipboardFormatAvailable(CF_DIBV5))
158     ThrowReaderException(CoderError,"NoBitmapOnClipboard");
159   if (!OpenClipboard(NULL))
160     ThrowReaderException(CoderError,"UnableToReadImageData");
161   clip_handle=GetClipboardData(CF_DIBV5);
162   if (!clip_handle)
163     clip_handle=GetClipboardData(CF_DIB);
164   if ((clip_handle == NULL) || (clip_handle == INVALID_HANDLE_VALUE))
165     {
166       CloseClipboard();
167       ThrowReaderException(CoderError,"UnableToReadImageData");
168     }
169   clip_size=(size_t) GlobalSize(clip_handle);
170   total_size=clip_size+BMP_HEADER_SIZE;
171   clip_data=AcquireMagickMemory(total_size);
172   if (clip_data == (void *) NULL)
173     {
174       CloseClipboard();
175       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
176     }
177   clip_mem=GlobalLock(clip_handle);
178   if (clip_mem == (LPVOID) NULL)
179     {
180       CloseClipboard();
181       ThrowReaderException(CoderError,"UnableToReadImageData");
182     }
183   p=(unsigned char *) clip_data;
184   p+=BMP_HEADER_SIZE;
185   (void) memcpy(p,clip_mem,clip_size);
186   (void) GlobalUnlock(clip_mem);
187   (void) CloseClipboard();
188   memset(clip_data,0,BMP_HEADER_SIZE);
189   offset=((unsigned int) p[0])+BMP_HEADER_SIZE;
190   p-=BMP_HEADER_SIZE;
191   p[0]='B';
192   p[1]='M';
193   p[2]=(unsigned char) total_size;
194   p[3]=(unsigned char) (total_size >> 8);
195   p[4]=(unsigned char) (total_size >> 16);
196   p[5]=(unsigned char) (total_size >> 24);
197   p[10]=offset;
198   read_info=CloneImageInfo(image_info);
199   (void) CopyMagickString(read_info->magick,"BMP",MaxTextExtent);
200   image=BlobToImage(read_info,clip_data,total_size,exception);
201   read_info=DestroyImageInfo(read_info);
202   clip_data=RelinquishMagickMemory(clip_data);
203   return(image);
204 }
205 #endif /* MAGICKCORE_WINGDI32_DELEGATE */
206 \f
207 /*
208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
209 %                                                                             %
210 %                                                                             %
211 %                                                                             %
212 %   R e g i s t e r C L I P B O A R D I m a g e                               %
213 %                                                                             %
214 %                                                                             %
215 %                                                                             %
216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
217 %
218 %  RegisterCLIPBOARDImage() adds attributes for the clipboard "image format" to
219 %  the list of supported formats.  The attributes include the image format
220 %  tag, a method to read and/or write the format, whether the format
221 %  supports the saving of more than one frame to the same file or blob,
222 %  whether the format supports native in-memory I/O, and a brief
223 %  description of the format.
224 %
225 %  The format of the RegisterCLIPBOARDImage method is:
226 %
227 %      size_t RegisterCLIPBOARDImage(void)
228 %
229 */
230 ModuleExport size_t RegisterCLIPBOARDImage(void)
231 {
232   MagickInfo
233     *entry;
234
235   entry=AcquireMagickInfo("CLIPBOARD","CLIPBOARD","The system clipboard");
236 #if defined(MAGICKCORE_WINGDI32_DELEGATE)
237   entry->decoder=(DecodeImageHandler *) ReadCLIPBOARDImage;
238   entry->encoder=(EncodeImageHandler *) WriteCLIPBOARDImage;
239 #endif
240   entry->flags^=CoderAdjoinFlag;
241   entry->format_type=ImplicitFormatType;
242   (void) RegisterMagickInfo(entry);
243   return(MagickImageCoderSignature);
244 }
245 \f
246 /*
247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
248 %                                                                             %
249 %                                                                             %
250 %                                                                             %
251 %   U n r e g i s t e r C L I P B O A R D I m a g e                           %
252 %                                                                             %
253 %                                                                             %
254 %                                                                             %
255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256 %
257 %  UnregisterCLIPBOARDImage() removes format registrations made by the
258 %  RGB module from the list of supported formats.
259 %
260 %  The format of the UnregisterCLIPBOARDImage method is:
261 %
262 %      UnregisterCLIPBOARDImage(void)
263 %
264 */
265 ModuleExport void UnregisterCLIPBOARDImage(void)
266 {
267   (void) UnregisterMagickInfo("CLIPBOARD");
268 }
269 \f
270 /*
271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
272 %                                                                             %
273 %                                                                             %
274 %                                                                             %
275 %   W r i t e C L I P B O A R D I m a g e                                     %
276 %                                                                             %
277 %                                                                             %
278 %                                                                             %
279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
280 %
281 %  WriteCLIPBOARDImage() writes an image to the system clipboard.
282 %
283 %  The format of the WriteCLIPBOARDImage method is:
284 %
285 %      MagickBooleanType WriteCLIPBOARDImage(const ImageInfo *image_info,
286 %        Image *image,ExceptionInfo *exception)
287 %
288 %  A description of each parameter follows.
289 %
290 %    o image_info: the image info.
291 %
292 %    o image:  The image.
293 %
294 %    o exception: return any errors or warnings in this structure.
295 %
296 */
297 #if defined(MAGICKCORE_WINGDI32_DELEGATE)
298 static MagickBooleanType WriteCLIPBOARDImage(const ImageInfo *image_info,
299   Image *image,ExceptionInfo *exception)
300 {
301   HANDLE
302     clip_handle;
303
304   ImageInfo
305     *write_info;
306
307   LPVOID
308     clip_mem;
309
310   size_t
311     length;
312
313   unsigned char
314     *p;
315
316   void
317     *clip_data;
318
319   assert(image_info != (const ImageInfo *) NULL);
320   assert(image_info->signature == MagickCoreSignature);
321   assert(image != (Image *) NULL);
322   assert(image->signature == MagickCoreSignature);
323   if (image->debug != MagickFalse)
324     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
325   if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
326     ThrowWriterException(CoderError,"UnableToWriteImageData");
327   write_info=CloneImageInfo(image_info);
328   if (image->alpha_trait == UndefinedPixelTrait)
329     (void) CopyMagickString(write_info->magick,"BMP3",MaxTextExtent);
330   else
331     (void) CopyMagickString(write_info->magick,"BMP",MaxTextExtent);
332   clip_data=ImageToBlob(write_info,image,&length,exception);
333   write_info=DestroyImageInfo(write_info);
334   if (clip_data == (void *) NULL)
335     ThrowWriterException(CoderError,"UnableToWriteImageData");
336   clip_handle=(HANDLE) GlobalAlloc(GMEM_MOVEABLE,length-BMP_HEADER_SIZE);
337   if (clip_handle == (HANDLE) NULL)
338     {
339       clip_data=RelinquishMagickMemory(clip_data);
340       ThrowWriterException(CoderError,"UnableToWriteImageData");
341     }
342   clip_mem=GlobalLock(clip_handle);
343   if (clip_handle == (LPVOID) NULL)
344     {
345       (void) GlobalFree((HGLOBAL) clip_handle);
346       clip_data=RelinquishMagickMemory(clip_data);
347       ThrowWriterException(CoderError,"UnableToWriteImageData");
348     }
349   p=(unsigned char *) clip_data;
350   p+=BMP_HEADER_SIZE;
351   (void) memcpy(clip_mem,p,length-BMP_HEADER_SIZE);
352   (void) GlobalUnlock(clip_mem);
353   clip_data=RelinquishMagickMemory(clip_data);
354   if (!OpenClipboard(NULL))
355     {
356       (void) GlobalFree((HGLOBAL) clip_handle);
357       ThrowWriterException(CoderError,"UnableToWriteImageData");
358     }
359   (void) EmptyClipboard();
360   if (image->alpha_trait == UndefinedPixelTrait)
361     SetClipboardData(CF_DIB,clip_handle);
362   else
363     SetClipboardData(CF_DIBV5,clip_handle);
364   (void) CloseClipboard();
365   return(MagickTrue);
366 }
367 #endif /* MAGICKCORE_WINGDI32_DELEGATE */