1 /*************************************************************************
2
3 Copyright 2011 Yuri Dario <mc6530@mclink.it>
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 ************************************************************************/
18
19 #define INCL_WIN
20 #include <svpm.h>
21 #include <string.h>
22
23 #ifndef _OS2CLIPBOARD_HXX_
24 #include "Os2Clipboard.hxx"
25 #endif
26
27 // same typedefs from win32 sdk
28 typedef unsigned short WORD;
29 typedef unsigned long DWORD;
30
31 #pragma pack(push, 1)
32
33 typedef struct {
34 PM_BYTE rgbBlue;
35 PM_BYTE rgbGreen;
36 PM_BYTE rgbRed;
37 PM_BYTE rgbReserved;
38 } RGBQUAD, *LPRGBQUAD;
39
40 typedef struct
41 {
42 WORD bfType;
43 DWORD bfSize;
44 WORD bfReserved1;
45 WORD bfReserved2;
46 DWORD bfOffBits;
47 } W32_BITMAPFILEHEADER, *PW32_BITMAPFILEHEADER;
48
49 typedef struct
50 {
51 DWORD biSize;
52 LONG biWidth;
53 LONG biHeight;
54 WORD biPlanes;
55 WORD biBitCount;
56 DWORD biCompression;
57 DWORD biSizeImage;
58 LONG biXPelsPerMeter;
59 LONG biYPelsPerMeter;
60 DWORD biClrUsed;
61 DWORD biClrImportant;
62 } W32_BITMAPINFOHEADER, *PW32_BITMAPINFOHEADER;
63
64 #pragma pack(pop)
65
66 // store screen bitcount
67 LONG lBitCountScreen;
68
69 /*
70 * Convert an OOo bitmap to an OS/2 bitmap handle
71 *
72 * An OOo bitmap is a BITMAPFILEHEADER structure followed by a Windows DIB
73 *
74 * OS/2 InfoHeader is a superset of Win32 InhoHeader, so we can just copy
75 * the win32 memory over the os2 memory and fix the cbFix field.
76 * colortable and bitmap data share the same format.
77 *
78 */
OOoBmpToOS2Handle(Any & aAnyB)79 HBITMAP OOoBmpToOS2Handle( Any &aAnyB)
80 {
81 // copy bitmap to clipboard
82 Sequence<sal_Int8> ByteStream;
83 aAnyB >>= ByteStream;
84
85 // get w32 file header data
86 PW32_BITMAPFILEHEADER pbfh = (PW32_BITMAPFILEHEADER)ByteStream.getArray();
87 // get w32 info header
88 PW32_BITMAPINFOHEADER pbih = (PW32_BITMAPINFOHEADER) (pbfh+1);
89
90 // create os2 infoheader2 (same fields of w32)
91 BITMAPINFOHEADER2 bih2;
92 memset( &bih2, 0, sizeof( bih2));
93 memcpy( &bih2, pbih, pbih->biSize);
94 bih2.cbFix = sizeof(bih2);
95
96 // Determine size of color table
97 int iNumColors, numbits=bih2.cPlanes * bih2.cBitCount;
98 if (numbits != 24)
99 iNumColors = bih2.cclrUsed ? bih2.cclrUsed : 2<<numbits;
100 else
101 iNumColors = bih2.cclrUsed;
102 int iColorTableSize = iNumColors*sizeof(RGB2);
103
104 // allocate bitmap info2 (header2+colortable)
105 PBITMAPINFO2 pbi2=(PBITMAPINFO2) malloc( sizeof(BITMAPINFOHEADER2)+iColorTableSize);
106 // setup header fields
107 memcpy( pbi2, &bih2, sizeof(BITMAPINFOHEADER2));
108 // copy color palette (follows pbih)
109 memcpy( &pbi2->argbColor[0], (pbih+1), iColorTableSize);
110
111 // get bitmap data
112 PBYTE pbPelData = (PBYTE)ByteStream.getArray() + pbfh->bfOffBits;
113 HPS hps = WinGetPS(HWND_DESKTOP);
114 HBITMAP hbm = GpiCreateBitmap( hps, &bih2, CBM_INIT, pbPelData, pbi2);
115 debug_printf( "OOoBmpToOS2Handle hbm %x\n", hbm);
116 WinReleasePS(hps);
117
118 // return handle
119 return hbm;
120 }
121
122 /*
123 * Convert an OS/2 bitmap handle to OOo bitmap
124 *
125 * First we need to copy the bitmap to a PS, then we can get bitmap data.
126 *
127 */
OS2HandleToOOoBmp(HBITMAP hbm,Sequence<sal_Int8> * OOoDIBStream)128 int OS2HandleToOOoBmp( HBITMAP hbm, Sequence< sal_Int8 >* OOoDIBStream)
129 {
130 HAB hab = WinQueryAnchorBlock(HWND_DESKTOP);
131 HDC hdc;
132 SIZEL sizl;
133 HPS hps;
134 PM_BYTE* pbBuffer;
135 ULONG cbBuffer;
136
137 struct {
138 BITMAPINFOHEADER2 bmp2;
139 RGB2 argb2Color[0x100];
140 } bm;
141
142 if (!lBitCountScreen) {
143 HPS hps = WinGetPS(HWND_DESKTOP);
144 HDC hdc = GpiQueryDevice(hps);
145 DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1L, &lBitCountScreen);
146 WinReleasePS(hps);
147 }
148
149 // STEP 1: get OS/2 bitmap data and header
150 // get bitmap header
151 memset(&(bm.bmp2), 0, sizeof(bm.bmp2));
152 bm.bmp2.cbFix = 16;
153 GpiQueryBitmapInfoHeader(hbm, &bm.bmp2);
154
155 /* Data only actually stored in clipboard quality */
156 if ( lBitCountScreen < bm.bmp2.cBitCount )
157 bm.bmp2.cBitCount = lBitCountScreen;
158
159 if ( bm.bmp2.cBitCount == 16 )
160 bm.bmp2.cBitCount = 24;
161
162 if ( bm.bmp2.cPlanes != 1 ) {
163 return 0;
164 }
165
166 if ( (hdc = DevOpenDC(hab, OD_MEMORY, "*", 0L, (PDEVOPENDATA) NULL, (HDC) NULL)) == (HDC) NULL ) {
167 return 0;
168 }
169
170 sizl.cx = bm.bmp2.cx;
171 sizl.cy = bm.bmp2.cy;
172 if ( (hps = GpiCreatePS(hab, hdc, &sizl, PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC)) == (HPS) NULL ) {
173 DevCloseDC(hdc);
174 return 0;
175 }
176 // copy bitmap to hps
177 GpiSetBitmap(hps, hbm);
178
179 // buffer lengths
180 cbBuffer = (((bm.bmp2.cBitCount * bm.bmp2.cx) + 31) / 32) * 4 * bm.bmp2.cy * bm.bmp2.cPlanes;
181 pbBuffer = (PM_BYTE*) malloc( cbBuffer);
182 // now get bitmap data
183 GpiQueryBitmapBits(hps, 0L, (LONG) bm.bmp2.cy, pbBuffer, (BITMAPINFO2*)&bm);
184 // free OS/2 resources
185 GpiSetBitmap(hps, (HBITMAP) NULL);
186 GpiDestroyPS(hps);
187 DevCloseDC(hdc);
188
189 // STEP 2: now convert to Win32 DIB
190 // Determine size of color table
191 int iNumColors, numbits=bm.bmp2.cPlanes * bm.bmp2.cBitCount;
192 if (numbits != 24)
193 iNumColors = bm.bmp2.cclrUsed ? bm.bmp2.cclrUsed : 2<<numbits;
194 else
195 iNumColors = bm.bmp2.cclrUsed;
196 int iColorTableSize = iNumColors*sizeof(RGBQUAD);
197
198 // reallocate data stream object size
199 OOoDIBStream->realloc( sizeof( W32_BITMAPFILEHEADER )
200 + sizeof( W32_BITMAPINFOHEADER) + iColorTableSize + cbBuffer);
201
202 // fill w32 file header data
203 PW32_BITMAPFILEHEADER pbfh = (PW32_BITMAPFILEHEADER) OOoDIBStream->getArray();
204 memset( pbfh, 0, sizeof( W32_BITMAPFILEHEADER));
205 pbfh->bfType = 'MB';
206 pbfh->bfSize = sizeof( W32_BITMAPFILEHEADER )
207 + sizeof( W32_BITMAPINFOHEADER) + iColorTableSize + cbBuffer;
208 pbfh->bfOffBits = sizeof( W32_BITMAPFILEHEADER) + sizeof( W32_BITMAPINFOHEADER) + iColorTableSize;
209
210 // fill w32 info header
211 PW32_BITMAPINFOHEADER pbih = (PW32_BITMAPINFOHEADER) (pbfh+1);
212 // copy header fields (only win32 ones) and fix size
213 memcpy( pbih, &bm.bmp2, sizeof(W32_BITMAPINFOHEADER));
214 pbih->biSize = sizeof(W32_BITMAPINFOHEADER);
215
216 // fill color palette (follows pbih)
217 memcpy( (pbih+1), &bm.argb2Color[0], iColorTableSize);
218
219 // fill bitmap data
220 memcpy( (char*) pbfh + pbfh->bfOffBits, pbBuffer, cbBuffer);
221
222 // done
223 free( pbBuffer);
224 return 1;
225 }
226
227 #ifdef TESTBMP
228
229 #include <io.h>
230 #include <fcntl.h>
231 #include <stdio.h>
232
main(void)233 int main( void)
234 {
235 HAB hAB = WinQueryAnchorBlock( HWND_DESKTOP );
236
237 // query clipboard data to get mimetype
238 if( WinOpenClipbrd( hAB ) )
239 {
240 ULONG handle = WinQueryClipbrdData( hAB, CF_BITMAP);
241 if (handle) {
242 Sequence< sal_Int8 > winDIBStream;
243 // convert to oustring and return it
244 if (OS2HandleToOOoBmp( handle, &winDIBStream) == 1) {
245 printf( "Conversion ok.\n");
246 int fd = open( "test.bmp", O_BINARY | O_CREAT | O_TRUNC | O_RDWR);
247 printf( "writing to fd %d\n", fd);
248 write( fd, winDIBStream.getArray(), winDIBStream.getLength());
249 close( fd);
250 } else
251 printf( "failed conversion.\n");
252
253 }
254 WinCloseClipbrd( hAB);
255 }
256 return 0;
257 }
258
259 #endif //TESTBMP
260
261