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