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 */ 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 */ 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 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