1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tools/stream.hxx>
22 #include <vcl/dibtools.hxx>
23 #include <vcl/svapp.hxx>
24 #include <vcl/bitmap.hxx>
25 #include <vcl/bitmapex.hxx>
26 #include <vcl/bitmap/BitmapSimpleColorQuantizationFilter.hxx>
28 #include <sal/log.hxx>
29 #include <unx/x11/xlimits.hxx>
39 static void writeLE( sal_uInt16 nNumber
, sal_uInt8
* pBuffer
)
41 pBuffer
[ 0 ] = (nNumber
& 0xff);
42 pBuffer
[ 1 ] = ((nNumber
>>8)&0xff);
45 static void writeLE( sal_uInt32 nNumber
, sal_uInt8
* pBuffer
)
47 pBuffer
[ 0 ] = (nNumber
& 0xff);
48 pBuffer
[ 1 ] = ((nNumber
>>8)&0xff);
49 pBuffer
[ 2 ] = ((nNumber
>>16)&0xff);
50 pBuffer
[ 3 ] = ((nNumber
>>24)&0xff);
53 static sal_uInt16
readLE16( const sal_uInt8
* pBuffer
)
55 //This is untainted data which comes from a controlled source
56 //so, using a byte-swapping pattern which coverity doesn't
58 //http://security.coverity.com/blog/2014/Apr/on-detecting-heartbleed-with-static-analysis.html
59 sal_uInt16 v
= pBuffer
[1]; v
<<= 8;
64 static sal_uInt32
readLE32( const sal_uInt8
* pBuffer
)
66 //This is untainted data which comes from a controlled source
67 //so, using a byte-swapping pattern which coverity doesn't
69 //http://security.coverity.com/blog/2014/Apr/on-detecting-heartbleed-with-static-analysis.html
70 sal_uInt32 v
= pBuffer
[3]; v
<<= 8;
71 v
|= pBuffer
[2]; v
<<= 8;
72 v
|= pBuffer
[1]; v
<<= 8;
81 static void X11_writeScanlinePixel( unsigned long nColor
, sal_uInt8
* pScanline
, int depth
, int x
)
86 pScanline
[ x
/8 ] &= ~(1 << (x
&7));
87 pScanline
[ x
/8 ] |= ((nColor
& 1) << (x
&7));
90 pScanline
[ x
/2 ] &= ((x
&1) ? 0x0f : 0xf0);
91 pScanline
[ x
/2 ] |= ((x
&1) ? (nColor
& 0x0f) : ((nColor
& 0x0f) << 4));
95 pScanline
[ x
] = (nColor
& 0xff);
100 static sal_uInt8
* X11_getPaletteBmpFromImage(
107 sal_uInt32 nColors
= 0;
111 sal_uInt8
* pBuffer
= nullptr;
112 sal_uInt32 nHeaderSize
, nScanlineSize
;
113 sal_uInt16 nBitCount
;
114 // determine header and scanline size
115 switch( pImage
->depth
)
119 nScanlineSize
= (pImage
->width
+31)/32;
124 nScanlineSize
= (pImage
->width
+1)/2;
130 nScanlineSize
= pImage
->width
;
134 // adjust scan lines to begin on %4 boundaries
135 if( nScanlineSize
& 3 )
137 nScanlineSize
&= 0xfffffffc;
141 // allocate buffer to hold header and scanlines, initialize to zero
142 rOutSize
= nHeaderSize
+ nScanlineSize
*pImage
->height
;
143 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateZeroMemory( rOutSize
));
144 for( int y
= 0; y
< pImage
->height
; y
++ )
146 sal_uInt8
* pScanline
= pBuffer
+ nHeaderSize
+ (pImage
->height
-1-y
)*nScanlineSize
;
147 for( int x
= 0; x
< pImage
->width
; x
++ )
149 unsigned long nPixel
= XGetPixel( pImage
, x
, y
);
150 if( nPixel
>= nColors
)
152 X11_writeScanlinePixel( nPixel
, pScanline
, pImage
->depth
, x
);
156 // fill in header fields
160 writeLE( nHeaderSize
, pBuffer
+10 );
161 writeLE( sal_uInt32(40), pBuffer
+14 );
162 writeLE( static_cast<sal_uInt32
>(pImage
->width
), pBuffer
+18 );
163 writeLE( static_cast<sal_uInt32
>(pImage
->height
), pBuffer
+22 );
164 writeLE( sal_uInt16(1), pBuffer
+26 );
165 writeLE( nBitCount
, pBuffer
+28 );
166 writeLE( static_cast<sal_uInt32
>(DisplayWidth(pDisplay
,DefaultScreen(pDisplay
))*1000/DisplayWidthMM(pDisplay
,DefaultScreen(pDisplay
))), pBuffer
+38);
167 writeLE( static_cast<sal_uInt32
>(DisplayHeight(pDisplay
,DefaultScreen(pDisplay
))*1000/DisplayHeightMM(pDisplay
,DefaultScreen(pDisplay
))), pBuffer
+42);
168 writeLE( nColors
, pBuffer
+46 );
169 writeLE( nColors
, pBuffer
+50 );
172 if( nColors
> (1U << nBitCount
) ) // paranoia
173 nColors
= (1U << nBitCount
);
174 for( unsigned long nPixel
= 0; nPixel
< nColors
; nPixel
++ )
176 aColors
[nPixel
].flags
= DoRed
| DoGreen
| DoBlue
;
177 aColors
[nPixel
].pixel
= nPixel
;
179 XQueryColors( pDisplay
, aColormap
, aColors
, nColors
);
180 for( sal_uInt32 i
= 0; i
< nColors
; i
++ )
182 pBuffer
[ 54 + i
*4 ] = static_cast<sal_uInt8
>(aColors
[i
].blue
>> 8);
183 pBuffer
[ 55 + i
*4 ] = static_cast<sal_uInt8
>(aColors
[i
].green
>> 8);
184 pBuffer
[ 56 + i
*4 ] = static_cast<sal_uInt8
>(aColors
[i
].red
>> 8);
192 static unsigned long doRightShift( unsigned long nValue
, int nShift
)
194 return (nShift
> 0) ? (nValue
>> nShift
) : (nValue
<< (-nShift
));
197 static unsigned long doLeftShift( unsigned long nValue
, int nShift
)
199 return (nShift
> 0) ? (nValue
<< nShift
) : (nValue
>> (-nShift
));
202 static void getShift( unsigned long nMask
, int& rShift
, int& rSigBits
, int& rShift2
)
204 unsigned long nUseMask
= nMask
;
206 while( nMask
& 0xffffff00 )
212 while( ! (nMask
& 0x00000080) )
218 int nRotate
= int(sizeof(unsigned long)*8) - rShift
;
220 nMask
= doRightShift( nUseMask
, rShift
) ;
230 rShift2
= 8-rSigBits
;
233 static sal_uInt8
* X11_getTCBmpFromImage(
240 // get masks from visual info (guesswork)
242 if( ! XMatchVisualInfo( pDisplay
, nScreenNo
, pImage
->depth
, TrueColor
, &aVInfo
) )
247 sal_uInt8
* pBuffer
= nullptr;
248 sal_uInt32 nHeaderSize
= 60;
249 sal_uInt32 nScanlineSize
= pImage
->width
*3;
251 // adjust scan lines to begin on %4 boundaries
252 if( nScanlineSize
& 3 )
254 nScanlineSize
&= 0xfffffffc;
257 int nRedShift
, nRedSig
, nRedShift2
= 0;
258 getShift( aVInfo
.red_mask
, nRedShift
, nRedSig
, nRedShift2
);
259 int nGreenShift
, nGreenSig
, nGreenShift2
= 0;
260 getShift( aVInfo
.green_mask
, nGreenShift
, nGreenSig
, nGreenShift2
);
261 int nBlueShift
, nBlueSig
, nBlueShift2
= 0;
262 getShift( aVInfo
.blue_mask
, nBlueShift
, nBlueSig
, nBlueShift2
);
264 // allocate buffer to hold header and scanlines, initialize to zero
265 rOutSize
= nHeaderSize
+ nScanlineSize
*pImage
->height
;
266 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateZeroMemory( rOutSize
));
267 for( int y
= 0; y
< pImage
->height
; y
++ )
269 sal_uInt8
* pScanline
= pBuffer
+ nHeaderSize
+ (pImage
->height
-1-y
)*nScanlineSize
;
270 for( int x
= 0; x
< pImage
->width
; x
++ )
272 unsigned long nPixel
= XGetPixel( pImage
, x
, y
);
274 sal_uInt8 nValue
= static_cast<sal_uInt8
>(doRightShift( nPixel
&aVInfo
.blue_mask
, nBlueShift
));
276 nValue
|= (nValue
>> nBlueShift2
);
277 *pScanline
++ = nValue
;
279 nValue
= static_cast<sal_uInt8
>(doRightShift( nPixel
&aVInfo
.green_mask
, nGreenShift
));
281 nValue
|= (nValue
>> nGreenShift2
);
282 *pScanline
++ = nValue
;
284 nValue
= static_cast<sal_uInt8
>(doRightShift( nPixel
&aVInfo
.red_mask
, nRedShift
));
286 nValue
|= (nValue
>> nRedShift2
);
287 *pScanline
++ = nValue
;
291 // fill in header fields
295 writeLE( nHeaderSize
, pBuffer
+10 );
296 writeLE( sal_uInt32(40), pBuffer
+14 );
297 writeLE( static_cast<sal_uInt32
>(pImage
->width
), pBuffer
+18 );
298 writeLE( static_cast<sal_uInt32
>(pImage
->height
), pBuffer
+22 );
299 writeLE( sal_uInt16(1), pBuffer
+26 );
300 writeLE( sal_uInt16(24), pBuffer
+28 );
301 writeLE( static_cast<sal_uInt32
>(DisplayWidth(pDisplay
,DefaultScreen(pDisplay
))*1000/DisplayWidthMM(pDisplay
,DefaultScreen(pDisplay
))), pBuffer
+38);
302 writeLE( static_cast<sal_uInt32
>(DisplayHeight(pDisplay
,DefaultScreen(pDisplay
))*1000/DisplayHeightMM(pDisplay
,DefaultScreen(pDisplay
))), pBuffer
+42);
309 sal_uInt8
* x11::X11_getBmpFromPixmap(
316 // get geometry of drawable
319 unsigned int w
, h
, bw
, d
;
320 XGetGeometry( pDisplay
, aDrawable
, &aRoot
, &x
, &y
, &w
, &h
, &bw
, &d
);
322 // find which screen we are on
323 int nScreenNo
= ScreenCount( pDisplay
);
326 if( RootWindow( pDisplay
, nScreenNo
) == aRoot
)
332 if( aColormap
== None
)
333 aColormap
= DefaultColormap( pDisplay
, nScreenNo
);
336 XImage
* pImage
= XGetImage( pDisplay
, aDrawable
, 0, 0, w
, h
, AllPlanes
, ZPixmap
);
340 sal_uInt8
* pBmp
= d
<= 8 ?
341 X11_getPaletteBmpFromImage( pDisplay
, pImage
, aColormap
, rOutSize
) :
342 X11_getTCBmpFromImage( pDisplay
, pImage
, rOutSize
, nScreenNo
);
343 XDestroyImage( pImage
);
352 PixmapHolder::PixmapHolder( Display
* pDisplay
)
353 : m_pDisplay(pDisplay
)
360 , m_nBlueShift2Mask(0)
361 , m_nRedShift2Mask(0)
362 , m_nGreenShift2Mask(0)
364 /* try to get a 24 bit true color visual, if that fails,
365 * revert to default visual
367 if( ! XMatchVisualInfo( m_pDisplay
, DefaultScreen( m_pDisplay
), 24, TrueColor
, &m_aInfo
) )
369 #if OSL_DEBUG_LEVEL > 1
370 SAL_INFO("vcl.unx.dtrans", "PixmapHolder reverting to default visual.");
372 Visual
* pVisual
= DefaultVisual( m_pDisplay
, DefaultScreen( m_pDisplay
) );
373 m_aInfo
.screen
= DefaultScreen( m_pDisplay
);
374 m_aInfo
.visual
= pVisual
;
375 m_aInfo
.visualid
= pVisual
->visualid
;
376 m_aInfo
.c_class
= pVisual
->c_class
;
377 m_aInfo
.red_mask
= pVisual
->red_mask
;
378 m_aInfo
.green_mask
= pVisual
->green_mask
;
379 m_aInfo
.blue_mask
= pVisual
->blue_mask
;
380 m_aInfo
.depth
= DefaultDepth( m_pDisplay
, m_aInfo
.screen
);
382 m_aColormap
= DefaultColormap( m_pDisplay
, m_aInfo
.screen
);
383 #if OSL_DEBUG_LEVEL > 1
384 static const char* pClasses
[] =
385 { "StaticGray", "GrayScale", "StaticColor", "PseudoColor", "TrueColor", "DirectColor" };
386 SAL_INFO("vcl.unx.dtrans", "PixmapHolder visual: id = "
387 << std::showbase
<< std::hex
390 << ((m_aInfo
.c_class
>= 0 &&
391 unsigned(m_aInfo
.c_class
) <
392 SAL_N_ELEMENTS(pClasses
)) ?
393 pClasses
[m_aInfo
.c_class
] :
401 << std::showbase
<< std::hex
404 if( m_aInfo
.c_class
!= TrueColor
)
410 int nRedSig
, nGreenSig
, nBlueSig
;
411 getShift( m_aInfo
.red_mask
, m_nRedShift
, nRedSig
, nRedShift2
);
412 getShift( m_aInfo
.green_mask
, m_nGreenShift
, nGreenSig
, nGreenShift2
);
413 getShift( m_aInfo
.blue_mask
, m_nBlueShift
, nBlueSig
, nBlueShift2
);
415 m_nBlueShift2Mask
= nBlueShift2
? ~static_cast<unsigned long>((1<<nBlueShift2
)-1) : ~0L;
416 m_nGreenShift2Mask
= nGreenShift2
? ~static_cast<unsigned long>((1<<nGreenShift2
)-1) : ~0L;
417 m_nRedShift2Mask
= nRedShift2
? ~static_cast<unsigned long>((1<<nRedShift2
)-1) : ~0L;
420 PixmapHolder::~PixmapHolder()
422 if( m_aPixmap
!= None
)
423 XFreePixmap( m_pDisplay
, m_aPixmap
);
424 if( m_aBitmap
!= None
)
425 XFreePixmap( m_pDisplay
, m_aBitmap
);
428 unsigned long PixmapHolder::getTCPixel( sal_uInt8 r
, sal_uInt8 g
, sal_uInt8 b
) const
430 unsigned long nPixel
= 0;
431 unsigned long nValue
= static_cast<unsigned long>(b
);
432 nValue
&= m_nBlueShift2Mask
;
433 nPixel
|= doLeftShift( nValue
, m_nBlueShift
);
435 nValue
= static_cast<unsigned long>(g
);
436 nValue
&= m_nGreenShift2Mask
;
437 nPixel
|= doLeftShift( nValue
, m_nGreenShift
);
439 nValue
= static_cast<unsigned long>(r
);
440 nValue
&= m_nRedShift2Mask
;
441 nPixel
|= doLeftShift( nValue
, m_nRedShift
);
446 void PixmapHolder::setBitmapDataPalette( const sal_uInt8
* pData
, XImage
* pImage
)
449 XColor aPalette
[256];
451 sal_uInt32 nColors
= readLE32( pData
+32 );
452 sal_uInt32 nWidth
= readLE32( pData
+4 );
453 sal_uInt32 nHeight
= readLE32( pData
+8 );
454 sal_uInt16 nDepth
= readLE16( pData
+14 );
456 for( sal_uInt32 i
= 0 ; i
< nColors
; i
++ )
458 if( m_aInfo
.c_class
!= TrueColor
)
460 //This is untainted data which comes from a controlled source
461 //so, using a byte-swapping pattern which coverity doesn't
463 //http://security.coverity.com/blog/2014/Apr/on-detecting-heartbleed-with-static-analysis.html
464 aPalette
[i
].red
= static_cast<unsigned short>(pData
[42 + i
*4]);
465 aPalette
[i
].red
<<= 8;
466 aPalette
[i
].red
|= static_cast<unsigned short>(pData
[42 + i
*4]);
468 aPalette
[i
].green
= static_cast<unsigned short>(pData
[41 + i
*4]);
469 aPalette
[i
].green
<<= 8;
470 aPalette
[i
].green
|= static_cast<unsigned short>(pData
[41 + i
*4]);
472 aPalette
[i
].blue
= static_cast<unsigned short>(pData
[40 + i
*4]);
473 aPalette
[i
].blue
<<= 8;
474 aPalette
[i
].blue
|= static_cast<unsigned short>(pData
[40 + i
*4]);
475 XAllocColor( m_pDisplay
, m_aColormap
, aPalette
+i
);
478 aPalette
[i
].pixel
= getTCPixel( pData
[42+i
*4], pData
[41+i
*4], pData
[40+i
*4] );
480 const sal_uInt8
* pBMData
= pData
+ readLE32( pData
) + 4*nColors
;
482 sal_uInt32 nScanlineSize
= 0;
486 nScanlineSize
= (nWidth
+31)/32;
489 nScanlineSize
= (nWidth
+1)/2;
492 nScanlineSize
= nWidth
;
495 // adjust scan lines to begin on %4 boundaries
496 if( nScanlineSize
& 3 )
498 nScanlineSize
&= 0xfffffffc;
502 // allocate buffer to hold header and scanlines, initialize to zero
503 for( unsigned int y
= 0; y
< nHeight
; y
++ )
505 const sal_uInt8
* pScanline
= pBMData
+ (nHeight
-1-y
)*nScanlineSize
;
506 for( unsigned int x
= 0; x
< nWidth
; x
++ )
511 case 1: nCol
= (pScanline
[ x
/8 ] & (0x80 >> (x
&7))) != 0 ? 0 : 1; break;
514 nCol
= static_cast<int>(pScanline
[ x
/2 ] >> 4);
516 nCol
= static_cast<int>(pScanline
[ x
/2 ] & 0x0f);
518 case 8: nCol
= static_cast<int>(pScanline
[x
]);
520 XPutPixel( pImage
, x
, y
, aPalette
[nCol
].pixel
);
525 void PixmapHolder::setBitmapDataTCDither( const sal_uInt8
* pData
, XImage
* pImage
)
527 XColor aPalette
[216];
531 for( int r
= 0; r
< 6; r
++ )
533 for( int g
= 0; g
< 6; g
++ )
535 for( int b
= 0; b
< 6; b
++ )
538 aPalette
[i
].red
= r
== 5 ? 0xffff : r
*10922;
539 aPalette
[i
].green
= g
== 5 ? 0xffff : g
*10922;
540 aPalette
[i
].blue
= b
== 5 ? 0xffff : b
*10922;
541 aPalette
[i
].pixel
= 0;
542 if( ! XAllocColor( m_pDisplay
, m_aColormap
, aPalette
+i
) )
550 XColor aRealPalette
[256];
551 int nColors
= 1 << m_aInfo
.depth
;
553 for( i
= 0; i
< nColors
; i
++ )
554 aRealPalette
[i
].pixel
= static_cast<unsigned long>(i
);
555 XQueryColors( m_pDisplay
, m_aColormap
, aRealPalette
, nColors
);
556 for( i
= 0; i
< nColors
; i
++ )
559 36*static_cast<sal_uInt8
>(aRealPalette
[i
].red
/10923) +
560 6*static_cast<sal_uInt8
>(aRealPalette
[i
].green
/10923) +
561 static_cast<sal_uInt8
>(aRealPalette
[i
].blue
/10923);
562 if( aPalette
[nIndex
].pixel
== 0 )
563 aPalette
[nIndex
] = aRealPalette
[i
];
567 sal_uInt32 nWidth
= readLE32( pData
+4 );
568 sal_uInt32 nHeight
= readLE32( pData
+8 );
570 const sal_uInt8
* pBMData
= pData
+ readLE32( pData
);
571 sal_uInt32 nScanlineSize
= nWidth
*3;
572 // adjust scan lines to begin on %4 boundaries
573 if( nScanlineSize
& 3 )
575 nScanlineSize
&= 0xfffffffc;
579 for( int y
= 0; y
< static_cast<int>(nHeight
); y
++ )
581 const sal_uInt8
* pScanline
= pBMData
+ (nHeight
-1-static_cast<sal_uInt32
>(y
))*nScanlineSize
;
582 for( int x
= 0; x
< static_cast<int>(nWidth
); x
++ )
584 sal_uInt8 b
= pScanline
[3*x
];
585 sal_uInt8 g
= pScanline
[3*x
+1];
586 sal_uInt8 r
= pScanline
[3*x
+2];
587 sal_uInt8 i
= 36*(r
/43) + 6*(g
/43) + (b
/43);
589 XPutPixel( pImage
, x
, y
, aPalette
[ i
].pixel
);
594 void PixmapHolder::setBitmapDataTC( const sal_uInt8
* pData
, XImage
* pImage
)
596 sal_uInt32 nWidth
= readLE32( pData
+4 );
597 sal_uInt32 nHeight
= readLE32( pData
+8 );
599 if (!nWidth
|| !nHeight
)
602 const sal_uInt8
* pBMData
= pData
+ readLE32( pData
);
603 sal_uInt32 nScanlineSize
= nWidth
*3;
604 // adjust scan lines to begin on %4 boundaries
605 if( nScanlineSize
& 3 )
607 nScanlineSize
&= 0xfffffffc;
611 for( int y
= 0; y
< static_cast<int>(nHeight
); y
++ )
613 const sal_uInt8
* pScanline
= pBMData
+ (nHeight
-1-static_cast<sal_uInt32
>(y
))*nScanlineSize
;
614 for( int x
= 0; x
< static_cast<int>(nWidth
); x
++ )
616 unsigned long nPixel
= getTCPixel( pScanline
[3*x
+2], pScanline
[3*x
+1], pScanline
[3*x
] );
617 XPutPixel( pImage
, x
, y
, nPixel
);
622 bool PixmapHolder::needsConversion( const sal_uInt8
* pData
) const
624 if( pData
[0] != 'B' || pData
[1] != 'M' )
628 sal_uInt32 nDepth
= readLE32( pData
+14 );
631 if( m_aInfo
.c_class
!= TrueColor
)
634 else if( nDepth
!= static_cast<sal_uInt32
>(m_aInfo
.depth
) )
636 if( m_aInfo
.c_class
!= TrueColor
)
643 Pixmap
PixmapHolder::setBitmapData( const sal_uInt8
* pData
)
645 if( pData
[0] != 'B' || pData
[1] != 'M' )
650 // reject compressed data
651 if( readLE32( pData
+ 16 ) != 0 )
654 sal_uInt32 nWidth
= readLE32( pData
+4 );
655 sal_uInt32 nHeight
= readLE32( pData
+8 );
657 if( m_aPixmap
!= None
)
659 XFreePixmap( m_pDisplay
, m_aPixmap
);
662 if( m_aBitmap
!= None
)
664 XFreePixmap( m_pDisplay
, m_aBitmap
);
668 m_aPixmap
= limitXCreatePixmap( m_pDisplay
,
669 RootWindow( m_pDisplay
, m_aInfo
.screen
),
670 nWidth
, nHeight
, m_aInfo
.depth
);
672 if( m_aPixmap
!= None
)
675 aImage
.width
= static_cast<int>(nWidth
);
676 aImage
.height
= static_cast<int>(nHeight
);
678 aImage
.format
= ZPixmap
;
679 aImage
.data
= nullptr;
680 aImage
.byte_order
= ImageByteOrder( m_pDisplay
);
681 aImage
.bitmap_unit
= BitmapUnit( m_pDisplay
);
682 aImage
.bitmap_bit_order
= BitmapBitOrder( m_pDisplay
);
683 aImage
.bitmap_pad
= BitmapPad( m_pDisplay
);
684 aImage
.depth
= m_aInfo
.depth
;
685 aImage
.red_mask
= m_aInfo
.red_mask
;
686 aImage
.green_mask
= m_aInfo
.green_mask
;
687 aImage
.blue_mask
= m_aInfo
.blue_mask
;
688 aImage
.bytes_per_line
= 0; // filled in by XInitImage
689 if( m_aInfo
.depth
<= 8 )
690 aImage
.bits_per_pixel
= m_aInfo
.depth
;
692 aImage
.bits_per_pixel
= 8*((m_aInfo
.depth
+7)/8);
693 aImage
.obdata
= nullptr;
695 XInitImage( &aImage
);
696 aImage
.data
= static_cast<char*>(std::malloc( nHeight
*aImage
.bytes_per_line
));
698 if( readLE32( pData
+14 ) == 24 )
700 if( m_aInfo
.c_class
== TrueColor
)
701 setBitmapDataTC( pData
, &aImage
);
703 setBitmapDataTCDither( pData
, &aImage
);
706 setBitmapDataPalette( pData
, &aImage
);
709 XPutImage( m_pDisplay
,
711 DefaultGC( m_pDisplay
, m_aInfo
.screen
),
718 std::free( aImage
.data
);
720 // prepare bitmap (mask)
721 m_aBitmap
= limitXCreatePixmap( m_pDisplay
,
722 RootWindow( m_pDisplay
, m_aInfo
.screen
),
723 nWidth
, nHeight
, 1 );
725 aVal
.function
= GXcopy
;
726 aVal
.foreground
= 0xffffffff;
727 GC aGC
= XCreateGC( m_pDisplay
, m_aBitmap
, GCFunction
| GCForeground
, &aVal
);
728 XFillRectangle( m_pDisplay
, m_aBitmap
, aGC
, 0, 0, nWidth
, nHeight
);
729 XFreeGC( m_pDisplay
, aGC
);
735 css::uno::Sequence
<sal_Int8
> x11::convertBitmapDepth(
736 css::uno::Sequence
<sal_Int8
> const & data
, int depth
)
740 } else if (depth
< 8) {
742 } else if (depth
> 8 && depth
< 24) {
747 const_cast<sal_Int8
*>(data
.getConstArray()), data
.getLength(),
750 ReadDIB(bm
, in
, true);
751 if (bm
.getPixelFormat() == vcl::PixelFormat::N24_BPP
&& depth
<= 8) {
754 if (vcl::pixelFormatBitCount(bm
.getPixelFormat()) != depth
) {
757 bm
.Convert(BmpConversion::N1BitThreshold
);
762 BitmapFilter::Filter(aBmpEx
, BitmapSimpleColorQuantizationFilter(1<<4));
763 bm
= aBmpEx
.GetBitmap();
770 BitmapFilter::Filter(aBmpEx
, BitmapSimpleColorQuantizationFilter(1<<8));
771 bm
= aBmpEx
.GetBitmap();
776 bm
.Convert(BmpConversion::N24Bit
);
781 WriteDIB(bm
, out
, false, true);
782 return css::uno::Sequence
<sal_Int8
>(
783 static_cast<sal_Int8
const *>(out
.GetData()), out
.GetEndOfData());
786 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */