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