1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "bitmap.h"
18 #include "wx/palette.h"
19 #include "wx/bitmap.h"
22 #include "wx/control.h"
23 #include "wx/dcmemory.h"
28 #pragma message disable nosimpint
31 #pragma message enable nosimpint
34 #include "wx/x11/private.h"
42 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
)
43 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
)
45 wxBitmapRefData::wxBitmapRefData()
55 m_pixmap
= (WXPixmap
) 0;
56 m_display
= (WXDisplay
*) 0;
58 m_freePixmap
= TRUE
; //TODO: necessary?
59 m_freeColors
= (unsigned long*) 0;
60 m_freeColorsCount
= 0;
63 wxBitmapRefData::~wxBitmapRefData()
65 if (m_pixmap
&& m_freePixmap
)
66 XFreePixmap ((Display
*) m_display
, (Pixmap
) m_pixmap
);
70 int screen
= DefaultScreen((Display
*) m_display
);
71 Colormap cmp
= DefaultColormap((Display
*) m_display
,screen
);
73 for(llp
= 0;llp
< m_freeColorsCount
;llp
++)
74 XFreeColors((Display
*) m_display
, cmp
, &m_freeColors
[llp
], 1, 0L);
83 wxList
wxBitmap::sm_handlers
;
85 #define M_BMPDATA ((wxBitmapRefData *)m_refData)
96 wxBitmap::wxBitmap(const char bits
[], int width
, int height
, int depth
)
98 m_refData
= new wxBitmapRefData
;
100 (void) Create((void*) bits
, wxBITMAP_TYPE_XBM_DATA
, width
, height
, depth
);
103 wxBitmap::wxBitmap(int w
, int h
, int d
)
105 (void)Create(w
, h
, d
);
108 wxBitmap::wxBitmap(void *data
, long type
, int width
, int height
, int depth
)
110 (void) Create(data
, type
, width
, height
, depth
);
113 wxBitmap::wxBitmap(const wxString
& filename
, long type
)
115 LoadFile(filename
, (int)type
);
118 wxBitmap::wxBitmap(char **data
)
120 (void) Create((void *)data
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
123 bool wxBitmap::Create(int w
, int h
, int d
)
127 m_refData
= new wxBitmapRefData
;
130 d
= wxDisplayDepth();
132 M_BITMAPDATA
->m_width
= w
;
133 M_BITMAPDATA
->m_height
= h
;
134 M_BITMAPDATA
->m_depth
= d
;
135 M_BITMAPDATA
->m_freePixmap
= TRUE
;
137 Display
*dpy
= (Display
*) wxGetDisplay();
139 M_BITMAPDATA
->m_display
= dpy
; /* MATTHEW: [4] Remember the display */
141 M_BITMAPDATA
->m_pixmap
= (WXPixmap
) XCreatePixmap (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
144 M_BITMAPDATA
->m_ok
= (M_BITMAPDATA
->m_pixmap
!= (WXPixmap
) 0) ;
145 return M_BITMAPDATA
->m_ok
;
148 bool wxBitmap::LoadFile(const wxString
& filename
, long type
)
152 m_refData
= new wxBitmapRefData
;
154 wxBitmapHandler
*handler
= FindHandler(type
);
156 if ( handler
== NULL
) {
158 if (!image
.LoadFile( filename
, type
)) return FALSE
;
161 *this = image
.ConvertToBitmap();
167 return handler
->LoadFile(this, filename
, type
, -1, -1);
170 bool wxBitmap::Create(void *data
, long type
, int width
, int height
, int depth
)
174 m_refData
= new wxBitmapRefData
;
176 wxBitmapHandler
*handler
= FindHandler(type
);
178 if ( handler
== NULL
) {
179 wxLogWarning("no data bitmap handler for type %d defined.", type
);
184 return handler
->Create(this, data
, type
, width
, height
, depth
);
187 bool wxBitmap::SaveFile(const wxString
& filename
, int type
, const wxPalette
*palette
)
189 wxBitmapHandler
*handler
= FindHandler(type
);
191 if ( handler
== NULL
) { // try wxImage
192 wxImage
image( *this );
193 if (image
.Ok()) return image
.SaveFile( filename
, type
);
197 return handler
->SaveFile(this, filename
, type
, palette
);
200 void wxBitmap::SetWidth(int w
)
203 m_refData
= new wxBitmapRefData
;
205 M_BITMAPDATA
->m_width
= w
;
208 void wxBitmap::SetHeight(int h
)
211 m_refData
= new wxBitmapRefData
;
213 M_BITMAPDATA
->m_height
= h
;
216 void wxBitmap::SetDepth(int d
)
219 m_refData
= new wxBitmapRefData
;
221 M_BITMAPDATA
->m_depth
= d
;
224 void wxBitmap::SetQuality(int q
)
227 m_refData
= new wxBitmapRefData
;
229 M_BITMAPDATA
->m_quality
= q
;
232 void wxBitmap::SetOk(bool isOk
)
235 m_refData
= new wxBitmapRefData
;
237 M_BITMAPDATA
->m_ok
= isOk
;
240 void wxBitmap::SetPalette(const wxPalette
& palette
)
243 m_refData
= new wxBitmapRefData
;
245 M_BITMAPDATA
->m_bitmapPalette
= palette
;
248 void wxBitmap::SetMask(wxMask
*mask
)
251 m_refData
= new wxBitmapRefData
;
253 M_BITMAPDATA
->m_bitmapMask
= mask
;
256 wxBitmap
wxBitmap::GetSubBitmap( const wxRect
& rect
) const
259 (rect
.x
>= 0) && (rect
.y
>= 0) &&
260 (rect
.x
+rect
.width
<= M_BMPDATA
->m_width
) && (rect
.y
+rect
.height
<= M_BMPDATA
->m_height
),
261 wxNullBitmap
, wxT("invalid bitmap or bitmap region") );
263 wxBitmap
ret( rect
.width
, rect
.height
, 0 );
264 wxASSERT_MSG( ret
.Ok(), wxT("GetSubBitmap error") );
266 // The remaining still TODO
270 void wxBitmap::AddHandler(wxBitmapHandler
*handler
)
272 sm_handlers
.Append(handler
);
275 void wxBitmap::InsertHandler(wxBitmapHandler
*handler
)
277 sm_handlers
.Insert(handler
);
280 bool wxBitmap::RemoveHandler(const wxString
& name
)
282 wxBitmapHandler
*handler
= FindHandler(name
);
285 sm_handlers
.DeleteObject(handler
);
292 wxBitmapHandler
*wxBitmap::FindHandler(const wxString
& name
)
294 wxNode
*node
= sm_handlers
.First();
297 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
298 if ( handler
->GetName() == name
)
305 wxBitmapHandler
*wxBitmap::FindHandler(const wxString
& extension
, long bitmapType
)
307 wxNode
*node
= sm_handlers
.First();
310 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
311 if ( handler
->GetExtension() == extension
&&
312 (bitmapType
== -1 || handler
->GetType() == bitmapType
) )
319 wxBitmapHandler
*wxBitmap::FindHandler(long bitmapType
)
321 wxNode
*node
= sm_handlers
.First();
324 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
325 if (handler
->GetType() == bitmapType
)
338 m_pixmap
= (WXPixmap
) 0;
341 // Construct a mask from a bitmap and a colour indicating
342 // the transparent area
343 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
)
345 m_pixmap
= (WXPixmap
) 0;
347 Create(bitmap
, colour
);
350 // Construct a mask from a bitmap and a palette index indicating
351 // the transparent area
352 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
)
354 m_pixmap
= (WXPixmap
) 0;
356 Create(bitmap
, paletteIndex
);
359 // Construct a mask from a mono bitmap (copies the bitmap).
360 wxMask::wxMask(const wxBitmap
& bitmap
)
362 m_pixmap
= (WXPixmap
) 0;
369 // TODO: this may be the wrong display
371 XFreePixmap ((Display
*) wxGetDisplay(), (Pixmap
) m_pixmap
);
374 // Create a mask from a mono bitmap (copies the bitmap).
375 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
))
381 // Create a mask from a bitmap and a palette index indicating
382 // the transparent area
383 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
), int WXUNUSED(paletteIndex
))
389 // Create a mask from a bitmap and a colour indicating
390 // the transparent area
391 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
), const wxColour
& WXUNUSED(colour
))
401 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
)
403 bool wxBitmapHandler::Create(wxBitmap
*WXUNUSED(bitmap
), void *WXUNUSED(data
), long WXUNUSED(type
),
404 int WXUNUSED(width
), int WXUNUSED(height
), int WXUNUSED(depth
))
409 bool wxBitmapHandler::LoadFile(wxBitmap
*WXUNUSED(bitmap
), const wxString
& WXUNUSED(name
), long WXUNUSED(type
),
410 int WXUNUSED(desiredWidth
), int WXUNUSED(desiredHeight
))
415 bool wxBitmapHandler::SaveFile(wxBitmap
*WXUNUSED(bitmap
), const wxString
& WXUNUSED(name
), int WXUNUSED(type
),
416 const wxPalette
*WXUNUSED(palette
))
425 class WXDLLEXPORT wxXBMFileHandler
: public wxBitmapHandler
427 DECLARE_DYNAMIC_CLASS(wxXBMFileHandler
)
429 inline wxXBMFileHandler()
433 m_type
= wxBITMAP_TYPE_XBM
;
436 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
437 int desiredWidth
, int desiredHeight
);
439 IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler
, wxBitmapHandler
)
441 bool wxXBMFileHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long WXUNUSED(flags
),
442 int WXUNUSED(desiredWidth
), int WXUNUSED(desiredHeight
))
444 M_BITMAPHANDLERDATA
->m_freePixmap
= TRUE
;
450 Display
*dpy
= (Display
*) wxGetDisplay();
451 M_BITMAPDATA
->m_display
= (WXDisplay
*) dpy
;
453 int value
= XReadBitmapFile (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
454 (char*) (const char*) name
, &w
, &h
, &pixmap
, &hotX
, &hotY
);
455 M_BITMAPHANDLERDATA
->m_width
= w
;
456 M_BITMAPHANDLERDATA
->m_height
= h
;
457 M_BITMAPHANDLERDATA
->m_depth
= 1;
458 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
460 if ((value
== BitmapFileInvalid
) ||
461 (value
== BitmapOpenFailed
) ||
462 (value
== BitmapNoMemory
))
464 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
465 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) 0;
468 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
470 return M_BITMAPHANDLERDATA
->m_ok
;
473 class WXDLLEXPORT wxXBMDataHandler
: public wxBitmapHandler
475 DECLARE_DYNAMIC_CLASS(wxXBMDataHandler
)
477 inline wxXBMDataHandler()
481 m_type
= wxBITMAP_TYPE_XBM_DATA
;
484 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
, int width
, int height
, int depth
= 1);
486 IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler
, wxBitmapHandler
)
488 bool wxXBMDataHandler::Create( wxBitmap
*bitmap
, void *data
, long WXUNUSED(flags
),
489 int width
, int height
, int WXUNUSED(depth
))
491 M_BITMAPHANDLERDATA
->m_width
= width
;
492 M_BITMAPHANDLERDATA
->m_height
= height
;
493 M_BITMAPHANDLERDATA
->m_depth
= 1;
494 M_BITMAPHANDLERDATA
->m_freePixmap
= TRUE
;
496 Display
*dpy
= (Display
*) wxGetDisplay();
497 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
499 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) XCreateBitmapFromData (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)), (char*) data
, width
, height
);
500 M_BITMAPHANDLERDATA
->m_ok
= (M_BITMAPHANDLERDATA
->m_pixmap
!= (WXPixmap
) 0) ;
506 class WXDLLEXPORT wxXPMFileHandler
: public wxBitmapHandler
508 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler
)
510 inline wxXPMFileHandler()
514 m_type
= wxBITMAP_TYPE_XPM
;
517 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
518 int desiredWidth
, int desiredHeight
);
519 virtual bool SaveFile(wxBitmap
*bitmap
, const wxString
& name
, int type
, const wxPalette
*palette
= NULL
);
522 IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler
, wxBitmapHandler
)
524 bool wxXPMFileHandler::LoadFile( wxBitmap
*bitmap
, const wxString
& name
, long WXUNUSED(flags
),
525 int WXUNUSED(desiredWidth
), int WXUNUSED(desiredHeight
) )
527 Display
*dpy
= (Display
*) wxGetDisplay();
528 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
530 XpmAttributes xpmAttr
;
534 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
535 xpmAttr
.valuemask
= XpmReturnInfos
| XpmCloseness
;
536 xpmAttr
.closeness
= 40000;
537 int errorStatus
= XpmReadFileToPixmap(dpy
,
538 RootWindow(dpy
, DefaultScreen(dpy
)), (char*) (const char*) name
,
539 &pixmap
, &mask
, &xpmAttr
);
541 if (errorStatus
== XpmSuccess
)
543 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
546 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
547 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
550 unsigned int depthRet
;
552 unsigned int widthRet
, heightRet
, borderWidthRet
;
553 Window rootWindowRet
;
554 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
555 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
557 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
558 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
561 if ( xpmAttr.npixels > 2 )
563 M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ...
566 M_BITMAPHANDLERDATA->m_depth = 1; // mono
570 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
572 M_BITMAPHANDLERDATA
->m_numColors
= xpmAttr
.npixels
;
574 XpmFreeAttributes(&xpmAttr
);
576 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
580 // XpmDebugError(errorStatus, name);
581 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
586 bool wxXPMFileHandler::SaveFile( wxBitmap
*bitmap
, const wxString
& name
, int WXUNUSED(type
),
587 const wxPalette
*WXUNUSED(palette
))
589 if (M_BITMAPHANDLERDATA
->m_ok
&& M_BITMAPHANDLERDATA
->m_pixmap
)
591 Display
*dpy
= (Display
*) M_BITMAPHANDLERDATA
->m_display
;
592 int errorStatus
= XpmWriteFileFromPixmap(dpy
, (char*) (const char*) name
,
593 (Pixmap
) M_BITMAPHANDLERDATA
->m_pixmap
,
594 (M_BITMAPHANDLERDATA
->m_bitmapMask
? (Pixmap
) M_BITMAPHANDLERDATA
->m_bitmapMask
->GetPixmap() : (Pixmap
) 0),
595 (XpmAttributes
*) NULL
);
596 if (errorStatus
== XpmSuccess
)
605 class WXDLLEXPORT wxXPMDataHandler
: public wxBitmapHandler
607 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler
)
609 inline wxXPMDataHandler()
613 m_type
= wxBITMAP_TYPE_XPM_DATA
;
616 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
, int width
, int height
, int depth
= 1);
618 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler
, wxBitmapHandler
)
620 bool wxXPMDataHandler::Create( wxBitmap
*bitmap
, void *data
, long WXUNUSED(flags
),
621 int width
, int height
, int WXUNUSED(depth
))
623 M_BITMAPHANDLERDATA
->m_width
= width
;
624 M_BITMAPHANDLERDATA
->m_height
= height
;
625 M_BITMAPHANDLERDATA
->m_depth
= 1;
626 M_BITMAPHANDLERDATA
->m_freePixmap
= TRUE
;
628 Display
*dpy
= (Display
*) wxGetDisplay();
629 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
631 XpmAttributes xpmAttr
;
633 xpmAttr
.valuemask
= XpmReturnInfos
; /* nothing yet, but get infos back */
635 XpmColorSymbol symbolicColors
[4];
636 if (sg_Control
&& sg_Control
->GetMainWidget())
638 symbolicColors
[0].name
= "foreground";
639 symbolicColors
[0].value
= NULL
;
640 symbolicColors
[1].name
= "background";
641 symbolicColors
[1].value
= NULL
;
642 XtVaGetValues((Widget
) sg_Control
->GetMainWidget(),
643 XmNforeground
, &symbolicColors
[0].pixel
,
644 XmNbackground
, &symbolicColors
[1].pixel
,NULL
);
645 xpmAttr
.numsymbols
= 2;
646 xpmAttr
.colorsymbols
= symbolicColors
;
647 xpmAttr
.valuemask
|= XpmColorSymbols
; // add flag
652 int ErrorStatus
= XpmCreatePixmapFromData(dpy
, RootWindow(dpy
, DefaultScreen(dpy
)),
653 (char**) data
, &pixmap
, &mask
, &xpmAttr
);
654 if (ErrorStatus
== XpmSuccess
)
657 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
658 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
660 unsigned int depthRet
;
662 unsigned int widthRet
, heightRet
, borderWidthRet
;
663 Window rootWindowRet
;
664 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
665 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
668 if ( xpmAttr.npixels > 2 )
670 M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ...
673 M_BITMAPHANDLERDATA->m_depth = 1; // mono
677 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
679 M_BITMAPHANDLERDATA
->m_numColors
= xpmAttr
.npixels
;
680 XpmFreeAttributes(&xpmAttr
);
681 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
682 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
685 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
686 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
691 // XpmDebugError(ErrorStatus, NULL);
692 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
694 return M_BITMAPHANDLERDATA
->m_ok
;
697 #endif // wxHAVE_LIB_XPM
699 void wxBitmap::CleanUpHandlers()
701 wxNode
*node
= sm_handlers
.First();
704 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
705 wxNode
*next
= node
->Next();
712 void wxBitmap::InitStandardHandlers()
714 // Initialize all standard bitmap or derived class handlers here.
715 AddHandler(new wxXBMFileHandler
);
716 AddHandler(new wxXBMDataHandler
);
718 // XPM is considered standard for Motif, although it can be omitted if
719 // libXpm is not installed
721 AddHandler(new wxXPMFileHandler
);
722 AddHandler(new wxXPMDataHandler
);
723 #endif // wxHAVE_LIB_XPM
726 // We may need this sometime...
728 /****************************************************************************
731 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
734 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
737 This function creates a grayed-out copy of the argument pixmap, suitable
738 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
741 The return value is the new Pixmap id or zero on error. Errors include
742 a NULL display argument or an invalid Pixmap argument.
745 If one of the XLib functions fail, it will produce a X error. The
746 default X error handler prints a diagnostic and calls exit().
749 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
750 XFillRectangle(3), exit(2)
753 John R Veregge - john@puente.jpl.nasa.gov
754 Advanced Engineering and Prototyping Group (AEG)
755 Information Systems Technology Section (395)
756 Jet Propulsion Lab - Calif Institute of Technology
758 *****************************************************************************/
761 XCreateInsensitivePixmap( Display
*display
, Pixmap pixmap
)
764 static char stipple_data
[] =
766 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
767 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
768 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
769 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA
772 Pixmap ipixmap
, stipple
;
773 unsigned width
, height
, depth
;
775 Window window
; /* These return values */
776 unsigned border
; /* from XGetGeometry() */
777 int x
, y
; /* are not needed. */
781 if ( NULL
== display
|| 0 == pixmap
)
784 if ( 0 == XGetGeometry( display
, pixmap
, &window
, &x
, &y
,
785 &width
, &height
, &border
, &depth
)
787 return ipixmap
; /* BadDrawable: probably an invalid pixmap */
789 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
791 stipple
= XCreateBitmapFromData( display
, pixmap
, stipple_data
, 16, 16 );
794 gc
= XCreateGC( display
, pixmap
, (XtGCMask
)0, (XGCValues
*)NULL
);
797 /* Create an identical copy of the argument pixmap.
799 ipixmap
= XCreatePixmap( display
, pixmap
, width
, height
, depth
);
802 /* Copy the argument pixmap into the new pixmap.
804 XCopyArea( display
, pixmap
, ipixmap
,
805 gc
, 0, 0, width
, height
, 0, 0 );
807 /* Refill the new pixmap using the stipple algorithm/pixmap.
809 XSetStipple( display
, gc
, stipple
);
810 XSetFillStyle( display
, gc
, FillStippled
);
811 XFillRectangle( display
, ipixmap
, gc
, 0, 0, width
, height
);
813 XFreeGC( display
, gc
);
815 XFreePixmap( display
, stipple
);
820 // Creates a bitmap with transparent areas drawn in
822 wxBitmap
wxCreateMaskedBitmap(const wxBitmap
& bitmap
, wxColour
& colour
)
824 wxBitmap
newBitmap(bitmap
.GetWidth(),
829 srcDC
.SelectObject(bitmap
);
830 destDC
.SelectObject(newBitmap
);
832 wxBrush
brush(colour
, wxSOLID
);
833 destDC
.SetOptimization(FALSE
);
834 destDC
.SetBackground(brush
);
836 destDC
.Blit(0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), & srcDC
, 0, 0, wxCOPY
, TRUE
);
844 //-----------------------------------------------------------------------------
845 // wxImage conversion routines
846 //-----------------------------------------------------------------------------
850 Date: Wed, 05 Jan 2000 11:45:40 +0100
851 From: Frits Boel <boel@niob.knaw.nl>
852 To: julian.smart@ukonline.co.uk
853 Subject: Patch for Motif ConvertToBitmap
857 I've been working on a wxWin application for image processing. From the
858 beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
859 till I looked in the source code of image.cpp. I saw that converting a
860 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
861 to the 256 colors of the palet. A very time-consuming piece of code!
863 Because I wanted a faster application, I've made a 'patch' for this. In
864 short: every pixel of the image is compared to a sorted list with
865 colors. If the color is found in the list, the palette entry is
866 returned; if the color is not found, the color palette is searched and
867 then the palette entry is returned and the color added to the sorted
870 Maybe there is another method for this, namely changing the palette
871 itself (if the colors are known, as is the case with tiffs with a
872 colormap). I did not look at this, maybe someone else did?
874 The code of the patch is attached, have a look on it, and maybe you will
875 ship it with the next release of wxMotif?
880 Software engineer at Hubrecht Laboratory, The Netherlands.
887 wxSearchColor( void );
888 wxSearchColor( int size
, XColor
*colors
);
889 ~wxSearchColor( void );
891 int SearchColor( int r
, int g
, int b
);
893 int AddColor( unsigned int value
, int pos
);
904 wxSearchColor::wxSearchColor( void )
907 colors
= (XColor
*) NULL
;
908 color
= (unsigned int *) NULL
;
915 wxSearchColor::wxSearchColor( int size_
, XColor
*colors_
)
920 color
= new unsigned int[size
];
921 entry
= new int [size
];
923 for (i
= 0; i
< size
; i
++ ) {
927 bottom
= top
= ( size
>> 1 );
930 wxSearchColor::~wxSearchColor( void )
932 if ( color
) delete color
;
933 if ( entry
) delete entry
;
936 int wxSearchColor::SearchColor( int r
, int g
, int b
)
938 unsigned int value
= ( ( ( r
* 256 ) + g
) * 256 ) + b
;
943 while ( begin
<= end
) {
945 middle
= ( begin
+ end
) >> 1;
947 if ( value
== color
[middle
] ) {
948 return( entry
[middle
] );
949 } else if ( value
< color
[middle
] ) {
957 return AddColor( value
, middle
);
960 int wxSearchColor::AddColor( unsigned int value
, int pos
)
964 int max
= 3 * (65536);
965 for ( i
= 0; i
< 256; i
++ ) {
966 int rdiff
= ((value
>> 8) & 0xFF00 ) - colors
[i
].red
;
967 int gdiff
= ((value
) & 0xFF00 ) - colors
[i
].green
;
968 int bdiff
= ((value
<< 8) & 0xFF00 ) - colors
[i
].blue
;
969 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
970 if (sum
< max
) { pixel
= i
; max
= sum
; }
973 if ( entry
[pos
] < 0 ) {
976 } else if ( value
< color
[pos
] ) {
979 for ( i
= bottom
; i
< pos
; i
++ ) {
980 color
[i
-1] = color
[i
];
981 entry
[i
-1] = entry
[i
];
984 color
[pos
-1] = value
;
985 entry
[pos
-1] = pixel
;
986 } else if ( top
< size
-1 ) {
987 for ( i
= top
; i
>= pos
; i
-- ) {
988 color
[i
+1] = color
[i
];
989 entry
[i
+1] = entry
[i
];
998 if ( top
< size
-1 ) {
999 for ( i
= top
; i
> pos
; i
-- ) {
1000 color
[i
+1] = color
[i
];
1001 entry
[i
+1] = entry
[i
];
1004 color
[pos
+1] = value
;
1005 entry
[pos
+1] = pixel
;
1006 } else if ( bottom
> 0 ) {
1007 for ( i
= bottom
; i
< pos
; i
++ ) {
1008 color
[i
-1] = color
[i
];
1009 entry
[i
-1] = entry
[i
];
1022 bool wxBitmap::CreateFromImage( const wxImage
& image
, int depth
)
1024 wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") )
1025 wxCHECK_MSG( depth
== -1, FALSE
, wxT("invalid bitmap depth") )
1027 m_refData
= new wxBitmapRefData();
1029 int width
= image
.GetWidth();
1030 int height
= image
.GetHeight();
1032 SetHeight( height
);
1035 Display
*dpy
= (Display
*) wxGetDisplay();
1036 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1037 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1041 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1042 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1044 Create( width
, height
, bpp
);
1048 XImage
*mask_image
= (XImage
*) NULL
;
1049 if (image
.HasMask())
1051 mask_image
= XCreateImage( dpy
, vis
, 1, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1052 mask_image
->data
= (char*) malloc( mask_image
->bytes_per_line
* mask_image
->height
);
1055 // Retrieve depth info
1057 XVisualInfo vinfo_template
;
1060 vinfo_template
.visual
= vis
;
1061 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1062 vinfo_template
.depth
= bpp
;
1065 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1067 wxCHECK_MSG( vi
, FALSE
, wxT("no visual") );
1071 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1072 if (bpp
< 8) bpp
= 8;
1076 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1077 byte_order b_o
= RGB
;
1081 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1082 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1083 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1084 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1085 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1086 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1089 int r_mask
= image
.GetMaskRed();
1090 int g_mask
= image
.GetMaskGreen();
1091 int b_mask
= image
.GetMaskBlue();
1096 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
1098 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1099 XQueryColors( dpy
, cmap
, colors
, 256 );
1102 wxSearchColor
scolor( 256, colors
);
1103 unsigned char* data
= image
.GetData();
1105 bool hasMask
= image
.HasMask();
1108 for (int y
= 0; y
< height
; y
++)
1110 for (int x
= 0; x
< width
; x
++)
1112 int r
= data
[index
];
1114 int g
= data
[index
];
1116 int b
= data
[index
];
1121 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1122 XPutPixel( mask_image
, x
, y
, 0 );
1124 XPutPixel( mask_image
, x
, y
, 1 );
1131 #if 0 // Old, slower code
1134 if (wxTheApp->m_colorCube)
1136 pixel = wxTheApp->m_colorCube
1137 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1142 int max
= 3 * (65536);
1143 for (int i
= 0; i
< 256; i
++)
1145 int rdiff
= (r
<< 8) - colors
[i
].red
;
1146 int gdiff
= (g
<< 8) - colors
[i
].green
;
1147 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1148 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1149 if (sum
< max
) { pixel
= i
; max
= sum
; }
1156 // And this is all to get the 'right' color...
1157 int pixel
= scolor
.SearchColor( r
, g
, b
);
1158 XPutPixel( data_image
, x
, y
, pixel
);
1163 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1164 XPutPixel( data_image
, x
, y
, pixel
);
1169 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1170 XPutPixel( data_image
, x
, y
, pixel
);
1179 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1180 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1181 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1182 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1183 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1184 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1186 XPutPixel( data_image
, x
, y
, pixel
);
1196 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
1197 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
1198 XPutImage( dpy
, (Drawable
)GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
1200 XDestroyImage( data_image
);
1204 if (image
.HasMask())
1206 wxBitmap
maskBitmap(width
, height
, 1);
1208 GC gcMask
= XCreateGC( dpy
, (Pixmap
) maskBitmap
.GetPixmap(), (XtGCMask
) 0, (XGCValues
*)NULL
);
1209 XPutImage( dpy
, (Drawable
)maskBitmap
.GetPixmap(), gcMask
, mask_image
, 0, 0, 0, 0, width
, height
);
1211 XDestroyImage( mask_image
);
1212 XFreeGC( dpy
, gcMask
);
1214 wxMask
* mask
= new wxMask
;
1215 mask
->SetPixmap(maskBitmap
.GetPixmap());
1219 maskBitmap
.SetPixmapNull();
1226 wxImage
wxBitmap::ConvertToImage() const
1230 wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") );
1232 Display
*dpy
= (Display
*) wxGetDisplay();
1233 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1234 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1236 XImage
*ximage
= XGetImage( dpy
,
1237 (Drawable
)GetPixmap(),
1239 GetWidth(), GetHeight(),
1240 AllPlanes
, ZPixmap
);
1242 wxCHECK_MSG( ximage
, wxNullImage
, wxT("couldn't create image") );
1244 image
.Create( GetWidth(), GetHeight() );
1245 char unsigned *data
= image
.GetData();
1249 XDestroyImage( ximage
);
1250 wxFAIL_MSG( wxT("couldn't create image") );
1255 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1258 gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(),
1260 GetWidth(), GetHeight() );
1262 image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1266 // Retrieve depth info
1268 XVisualInfo vinfo_template
;
1271 vinfo_template
.visual
= vis
;
1272 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1273 vinfo_template
.depth
= bpp
;
1276 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1278 wxCHECK_MSG( vi
, wxNullImage
, wxT("no visual") );
1280 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1287 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
1289 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1290 XQueryColors( dpy
, cmap
, colors
, 256 );
1294 for (int j
= 0; j
< GetHeight(); j
++)
1296 for (int i
= 0; i
< GetWidth(); i
++)
1298 int pixel
= XGetPixel( ximage
, i
, j
);
1301 data
[pos
] = colors
[pixel
].red
>> 8;
1302 data
[pos
+1] = colors
[pixel
].green
>> 8;
1303 data
[pos
+2] = colors
[pixel
].blue
>> 8;
1304 } else if (bpp
== 15)
1306 data
[pos
] = (pixel
>> 7) & 0xf8;
1307 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1308 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1309 } else if (bpp
== 16)
1311 data
[pos
] = (pixel
>> 8) & 0xf8;
1312 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1313 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1316 data
[pos
] = (pixel
>> 16) & 0xff;
1317 data
[pos
+1] = (pixel
>> 8) & 0xff;
1318 data
[pos
+2] = pixel
& 0xff;
1324 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1325 if (mask_pixel == 0)
1338 XDestroyImage( ximage
);
1340 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );