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