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