xref: /AOO41X/main/dtrans/source/os2/clipb/OS2Bitmap.cxx (revision e18b2daf38bb96874e2208adca92c27d00c35e00)
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