1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "bitmap.h"
17 #define XtParent XTPARENT
22 #include "wx/palette.h"
23 #include "wx/bitmap.h"
26 #include "wx/dcmemory.h"
32 #pragma message disable nosimpint
36 #pragma message enable nosimpint
41 #include <X11/Intrinsic.h>
49 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
)
50 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
)
52 wxBitmapRefData::wxBitmapRefData()
62 m_pixmap
= (WXPixmap
) 0;
63 m_display
= (WXDisplay
*) 0;
65 // m_freePixmap = TRUE; //TODO: necessary?
67 m_freeColors
= (unsigned long*) 0;
68 m_freeColorsCount
= 0;
71 // These 5 variables are for wxControl
73 m_insensPixmap
= (WXPixmap
) 0;
74 m_labelPixmap
= (WXPixmap
) 0;
75 m_armPixmap
= (WXPixmap
) 0;
78 m_image
= (WXImage
*) 0;
79 m_insensImage
= (WXImage
*) 0;
83 wxBitmapRefData::~wxBitmapRefData()
87 XmDestroyPixmap (DefaultScreenOfDisplay ((Display
*) m_display
), (Pixmap
) m_labelPixmap
);
90 XmDestroyPixmap (DefaultScreenOfDisplay ((Display
*) m_display
), (Pixmap
) m_armPixmap
);
93 XmDestroyPixmap (DefaultScreenOfDisplay ((Display
*) m_display
), (Pixmap
) m_insensPixmap
);
99 XmUninstallImage ((XImage
*) m_image
);
100 XtFree ((char *) (XImage
*) m_image
);
107 XmUninstallImage ((XImage
*) m_insensImage
);
108 delete[] ((XImage
*) m_insensImage
)->data
;
109 XtFree ((char *) (XImage
*) m_insensImage
);
112 if (m_pixmap
/* && m_freePixmap */)
113 XFreePixmap ((Display
*) m_display
, (Pixmap
) m_pixmap
);
118 int screen
= DefaultScreen((Display
*) m_display
);
119 Colormap cmp
= DefaultColormap((Display
*) m_display
,screen
);
121 for(llp
= 0;llp
< m_freeColorsCount
;llp
++)
122 XFreeColors((Display
*) m_display
, cmp
, &m_freeColors
[llp
], 1, 0L);
132 #define M_BMPDATA ((wxBitmapRefData *)m_refData)
139 wxBitmap::~wxBitmap()
143 wxBitmap::wxBitmap(const char bits
[], int width
, int height
, int depth
)
145 m_refData
= new wxBitmapRefData
;
147 (void) Create((void*) bits
, wxBITMAP_TYPE_XBM_DATA
, width
, height
, depth
);
150 wxBitmap::wxBitmap(int w
, int h
, int d
)
152 (void)Create(w
, h
, d
);
155 wxBitmap::wxBitmap(void *data
, wxBitmapType type
,
156 int width
, int height
, int depth
)
158 (void) Create(data
, type
, width
, height
, depth
);
161 wxBitmap::wxBitmap(const wxString
& filename
, wxBitmapType type
)
163 LoadFile(filename
, type
);
167 // Create from XPM data
168 static wxControl
* sg_Control
= NULL
;
169 wxBitmap::wxBitmap(char **data
, wxControl
* control
)
171 // Pass the control to the Create function using a global
172 sg_Control
= control
;
174 (void) Create((void *)data
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
176 sg_Control
= (wxControl
*) NULL
;
180 bool wxBitmap::CreateFromXpm(const char **bits
)
182 wxCHECK_MSG( bits
, FALSE
, _T("NULL pointer in wxBitmap::CreateFromXpm") );
184 return Create(bits
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
187 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
)
193 bool wxBitmap::Create(int w
, int h
, int d
)
197 m_refData
= new wxBitmapRefData
;
200 d
= wxDisplayDepth();
202 M_BITMAPDATA
->m_width
= w
;
203 M_BITMAPDATA
->m_height
= h
;
204 M_BITMAPDATA
->m_depth
= d
;
205 // M_BITMAPDATA->m_freePixmap = TRUE;
207 Display
*dpy
= (Display
*) wxGetDisplay();
209 M_BITMAPDATA
->m_display
= dpy
; /* MATTHEW: [4] Remember the display */
211 M_BITMAPDATA
->m_pixmap
= (WXPixmap
) XCreatePixmap (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
214 M_BITMAPDATA
->m_ok
= (M_BITMAPDATA
->m_pixmap
!= (WXPixmap
) 0) ;
215 return M_BITMAPDATA
->m_ok
;
218 bool wxBitmap::LoadFile(const wxString
& filename
, wxBitmapType type
)
222 m_refData
= new wxBitmapRefData
;
224 wxBitmapHandler
*handler
= FindHandler(type
);
226 if ( handler
== NULL
) {
228 if (!image
.LoadFile( filename
, type
)) return FALSE
;
231 *this = wxBitmap(image
);
237 return handler
->LoadFile(this, filename
, type
, -1, -1);
240 bool wxBitmap::Create(void *data
, wxBitmapType type
,
241 int width
, int height
, int depth
)
245 m_refData
= new wxBitmapRefData
;
247 wxBitmapHandler
*handler
= FindHandler(type
);
249 if ( handler
== NULL
) {
250 wxLogWarning("no data bitmap handler for type %ld defined.",
256 return handler
->Create(this, data
, type
, width
, height
, depth
);
259 bool wxBitmap::SaveFile(const wxString
& filename
, wxBitmapType type
,
260 const wxPalette
*palette
) const
262 wxBitmapHandler
*handler
= FindHandler(type
);
264 if ( handler
== NULL
) { // try wxImage
265 wxImage image
= this->ConvertToImage();
266 if (image
.Ok()) return image
.SaveFile( filename
, type
);
270 return handler
->SaveFile(this, filename
, type
, palette
);
273 void wxBitmap::SetWidth(int w
)
276 m_refData
= new wxBitmapRefData
;
278 M_BITMAPDATA
->m_width
= w
;
281 void wxBitmap::SetHeight(int h
)
284 m_refData
= new wxBitmapRefData
;
286 M_BITMAPDATA
->m_height
= h
;
289 void wxBitmap::SetDepth(int d
)
292 m_refData
= new wxBitmapRefData
;
294 M_BITMAPDATA
->m_depth
= d
;
300 void wxBitmap::SetQuality(int q
)
303 m_refData
= new wxBitmapRefData
;
305 M_BITMAPDATA
->m_quality
= q
;
310 void wxBitmap::SetOk(bool isOk
)
313 m_refData
= new wxBitmapRefData
;
315 M_BITMAPDATA
->m_ok
= isOk
;
318 void wxBitmap::SetPalette(const wxPalette
& palette
)
321 m_refData
= new wxBitmapRefData
;
323 M_BITMAPDATA
->m_bitmapPalette
= palette
;
326 void wxBitmap::SetMask(wxMask
*mask
)
329 m_refData
= new wxBitmapRefData
;
331 M_BITMAPDATA
->m_bitmapMask
= mask
;
334 wxBitmap
wxBitmap::GetSubBitmap( const wxRect
& rect
) const
337 (rect
.x
>= 0) && (rect
.y
>= 0) &&
338 (rect
.x
+rect
.width
<= M_BMPDATA
->m_width
) && (rect
.y
+rect
.height
<= M_BMPDATA
->m_height
),
339 wxNullBitmap
, wxT("invalid bitmap or bitmap region") );
341 wxBitmap
ret( rect
.width
, rect
.height
, 0 );
342 wxASSERT_MSG( ret
.Ok(), wxT("GetSubBitmap error") );
344 // The remaining still TODO
354 m_pixmap
= (WXPixmap
) 0;
357 // Construct a mask from a bitmap and a colour indicating
358 // the transparent area
359 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
)
361 m_pixmap
= (WXPixmap
) 0;
363 Create(bitmap
, colour
);
366 // Construct a mask from a bitmap and a palette index indicating
367 // the transparent area
368 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
)
370 m_pixmap
= (WXPixmap
) 0;
372 Create(bitmap
, paletteIndex
);
375 // Construct a mask from a mono bitmap (copies the bitmap).
376 wxMask::wxMask(const wxBitmap
& bitmap
)
378 m_pixmap
= (WXPixmap
) 0;
385 // TODO: this may be the wrong display
387 XFreePixmap ((Display
*) wxGetDisplay(), (Pixmap
) m_pixmap
);
390 // Create a mask from a mono bitmap (copies the bitmap).
391 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
))
397 // Create a mask from a bitmap and a palette index indicating
398 // the transparent area
399 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
), int WXUNUSED(paletteIndex
))
405 // Create a mask from a bitmap and a colour indicating
406 // the transparent area
407 bool wxMask::Create(const wxBitmap
& WXUNUSED(bitmap
), const wxColour
& WXUNUSED(colour
))
417 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
)
423 class WXDLLEXPORT wxXBMFileHandler
: public wxBitmapHandler
425 DECLARE_DYNAMIC_CLASS(wxXBMFileHandler
)
427 inline wxXBMFileHandler()
431 m_type
= wxBITMAP_TYPE_XBM
;
434 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
435 int desiredWidth
, int desiredHeight
);
438 IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler
, wxBitmapHandler
)
440 bool wxXBMFileHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
,
441 long WXUNUSED(flags
),
442 int WXUNUSED(desiredWidth
),
443 int WXUNUSED(desiredHeight
))
445 // M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
451 Display
*dpy
= (Display
*) wxGetDisplay();
452 M_BITMAPDATA
->m_display
= (WXDisplay
*) dpy
;
454 int value
= XReadBitmapFile (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)),
455 wxConstCast(name
.c_str(), char), &w
, &h
, &pixmap
, &hotX
, &hotY
);
456 M_BITMAPHANDLERDATA
->m_width
= w
;
457 M_BITMAPHANDLERDATA
->m_height
= h
;
458 M_BITMAPHANDLERDATA
->m_depth
= 1;
459 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
461 if ((value
== BitmapFileInvalid
) ||
462 (value
== BitmapOpenFailed
) ||
463 (value
== BitmapNoMemory
))
465 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
466 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) 0;
469 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
471 return M_BITMAPHANDLERDATA
->m_ok
;
474 class WXDLLEXPORT wxXBMDataHandler
: public wxBitmapHandler
476 DECLARE_DYNAMIC_CLASS(wxXBMDataHandler
)
478 inline wxXBMDataHandler()
482 m_type
= wxBITMAP_TYPE_XBM_DATA
;
485 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
,
486 int width
, int height
, int depth
= 1);
488 IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler
, wxBitmapHandler
)
490 bool wxXBMDataHandler::Create( wxBitmap
*bitmap
, void *data
,
491 long WXUNUSED(flags
),
492 int width
, int height
, int WXUNUSED(depth
))
494 M_BITMAPHANDLERDATA
->m_width
= width
;
495 M_BITMAPHANDLERDATA
->m_height
= height
;
496 M_BITMAPHANDLERDATA
->m_depth
= 1;
497 // M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
499 Display
*dpy
= (Display
*) wxGetDisplay();
500 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
502 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) XCreateBitmapFromData (dpy
, RootWindow (dpy
, DefaultScreen (dpy
)), (char*) data
, width
, height
);
503 M_BITMAPHANDLERDATA
->m_ok
= (M_BITMAPHANDLERDATA
->m_pixmap
!= (WXPixmap
) 0) ;
506 // code for wxControl. TODO: can we avoid doing this until we need it?
507 // E.g. have CreateButtonPixmaps which is called on demand.
508 XImage
* image
= (XImage
*) XtMalloc (sizeof (XImage
));
509 image
->width
= width
;
510 image
->height
= height
;
511 image
->data
= (char*) data
;
514 image
->format
= XYBitmap
;
515 image
->byte_order
= LSBFirst
;
516 image
->bitmap_unit
= 8;
517 image
->bitmap_bit_order
= LSBFirst
;
518 image
->bitmap_pad
= 8;
519 image
->bytes_per_line
= (width
+ 7) >> 3;
522 sprintf (tmp
, "Im%x", (unsigned int) image
);
523 XmInstallImage (image
, tmp
);
525 // Build our manually stipped pixmap.
527 int bpl
= (width
+ 7) / 8;
528 char *data1
= new char[height
* bpl
];
529 char* bits
= (char*) data
;
531 for (i
= 0; i
< height
; i
++)
533 int mask
= i
% 2 ? 0x55 : 0xaa;
535 for (j
= 0; j
< bpl
; j
++)
536 data1
[i
* bpl
+ j
] = bits
[i
* bpl
+ j
] & mask
;
538 XImage
* insensImage
= (XImage
*) XtMalloc (sizeof (XImage
));
539 insensImage
->width
= width
;
540 insensImage
->height
= height
;
541 insensImage
->data
= data1
;
542 insensImage
->depth
= 1;
543 insensImage
->xoffset
= 0;
544 insensImage
->format
= XYBitmap
;
545 insensImage
->byte_order
= LSBFirst
;
546 insensImage
->bitmap_unit
= 8;
547 insensImage
->bitmap_bit_order
= LSBFirst
;
548 insensImage
->bitmap_pad
= 8;
549 insensImage
->bytes_per_line
= bpl
;
551 sprintf (tmp
, "Not%x", (unsigned int)insensImage
);
552 XmInstallImage (insensImage
, tmp
);
554 M_BITMAPHANDLERDATA
->m_image
= (WXImage
*) image
;
555 M_BITMAPHANDLERDATA
->m_insensImage
= (WXImage
*) insensImage
;
564 class WXDLLEXPORT wxXPMFileHandler
: public wxBitmapHandler
566 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler
)
568 inline wxXPMFileHandler()
572 m_type
= wxBITMAP_TYPE_XPM
;
575 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
576 int desiredWidth
, int desiredHeight
);
577 virtual bool SaveFile(const wxBitmap
*bitmap
, const wxString
& name
,
578 wxBitmapType type
, const wxPalette
*palette
= NULL
);
581 IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler
, wxBitmapHandler
)
583 bool wxXPMFileHandler::LoadFile( wxBitmap
*bitmap
, const wxString
& name
,
584 long WXUNUSED(flags
),
585 int WXUNUSED(desiredWidth
),
586 int WXUNUSED(desiredHeight
) )
588 Display
*dpy
= (Display
*) wxGetDisplay();
589 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
591 XpmAttributes xpmAttr
;
595 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
596 xpmAttr
.valuemask
= XpmReturnInfos
| XpmCloseness
;
597 xpmAttr
.closeness
= 40000;
598 int errorStatus
= XpmReadFileToPixmap(dpy
,
599 RootWindow(dpy
, DefaultScreen(dpy
)),
600 wxConstCast(name
.c_str(), char),
601 &pixmap
, &mask
, &xpmAttr
);
603 if (errorStatus
== XpmSuccess
)
605 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
608 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
609 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
612 unsigned int depthRet
;
614 unsigned int widthRet
, heightRet
, borderWidthRet
;
615 Window rootWindowRet
;
616 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
617 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
619 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
620 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
623 if ( xpmAttr.npixels > 2 )
625 M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ...
628 M_BITMAPHANDLERDATA->m_depth = 1; // mono
632 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
634 // M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
636 XpmFreeAttributes(&xpmAttr
);
638 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
642 // XpmDebugError(errorStatus, name);
643 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
648 bool wxXPMFileHandler::SaveFile( const wxBitmap
*bitmap
, const wxString
& name
,
649 wxBitmapType
WXUNUSED(type
),
650 const wxPalette
*WXUNUSED(palette
))
652 if (M_BITMAPHANDLERDATA
->m_ok
&& M_BITMAPHANDLERDATA
->m_pixmap
)
654 Display
*dpy
= (Display
*) M_BITMAPHANDLERDATA
->m_display
;
655 int errorStatus
= XpmWriteFileFromPixmap(dpy
,
656 wxConstCast(name
.c_str(), char),
657 (Pixmap
) M_BITMAPHANDLERDATA
->m_pixmap
,
658 (M_BITMAPHANDLERDATA
->m_bitmapMask
? (Pixmap
) M_BITMAPHANDLERDATA
->m_bitmapMask
->GetPixmap() : (Pixmap
) 0),
659 (XpmAttributes
*) NULL
);
660 if (errorStatus
== XpmSuccess
)
669 class WXDLLEXPORT wxXPMDataHandler
: public wxBitmapHandler
671 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler
)
673 inline wxXPMDataHandler()
677 m_type
= wxBITMAP_TYPE_XPM_DATA
;
680 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
,
681 int width
, int height
, int depth
= 1);
683 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler
, wxBitmapHandler
)
685 bool wxXPMDataHandler::Create( wxBitmap
*bitmap
, void *data
,
686 long WXUNUSED(flags
),
687 int width
, int height
, int WXUNUSED(depth
))
689 M_BITMAPHANDLERDATA
->m_width
= width
;
690 M_BITMAPHANDLERDATA
->m_height
= height
;
691 M_BITMAPHANDLERDATA
->m_depth
= 1;
692 // M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
694 Display
*dpy
= (Display
*) wxGetDisplay();
695 M_BITMAPHANDLERDATA
->m_display
= (WXDisplay
*) dpy
;
697 XpmAttributes xpmAttr
;
699 xpmAttr
.valuemask
= XpmReturnInfos
; /* nothing yet, but get infos back */
702 XpmColorSymbol symbolicColors
[4];
703 if (sg_Control
&& sg_Control
->GetMainWidget())
705 symbolicColors
[0].name
= "foreground";
706 symbolicColors
[0].value
= NULL
;
707 symbolicColors
[1].name
= "background";
708 symbolicColors
[1].value
= NULL
;
709 XtVaGetValues((Widget
) sg_Control
->GetMainWidget(),
710 XmNforeground
, &symbolicColors
[0].pixel
,
711 XmNbackground
, &symbolicColors
[1].pixel
,NULL
);
712 xpmAttr
.numsymbols
= 2;
713 xpmAttr
.colorsymbols
= symbolicColors
;
714 xpmAttr
.valuemask
|= XpmColorSymbols
; // add flag
720 int ErrorStatus
= XpmCreatePixmapFromData(dpy
, RootWindow(dpy
, DefaultScreen(dpy
)),
721 (char**) data
, &pixmap
, &mask
, &xpmAttr
);
722 if (ErrorStatus
== XpmSuccess
)
725 M_BITMAPHANDLERDATA
->m_width
= xpmAttr
.width
;
726 M_BITMAPHANDLERDATA
->m_height
= xpmAttr
.height
;
728 unsigned int depthRet
;
730 unsigned int widthRet
, heightRet
, borderWidthRet
;
731 Window rootWindowRet
;
732 XGetGeometry(dpy
, pixmap
, &rootWindowRet
, &xRet
, &yRet
,
733 &widthRet
, &heightRet
, &borderWidthRet
, &depthRet
);
736 if ( xpmAttr.npixels > 2 )
738 M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ...
741 M_BITMAPHANDLERDATA->m_depth = 1; // mono
745 M_BITMAPHANDLERDATA
->m_depth
= depthRet
;
747 // M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
748 XpmFreeAttributes(&xpmAttr
);
749 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
750 M_BITMAPHANDLERDATA
->m_pixmap
= (WXPixmap
) pixmap
;
753 M_BITMAPHANDLERDATA
->m_bitmapMask
= new wxMask
;
754 M_BITMAPHANDLERDATA
->m_bitmapMask
->SetPixmap((WXPixmap
) mask
);
759 // XpmDebugError(ErrorStatus, NULL);
760 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
762 return M_BITMAPHANDLERDATA
->m_ok
;
765 #endif // wxHAVE_LIB_XPM
767 void wxBitmap::InitStandardHandlers()
769 // Initialize all standard bitmap or derived class handlers here.
770 AddHandler(new wxXBMFileHandler
);
771 AddHandler(new wxXBMDataHandler
);
773 // XPM is considered standard for Motif, although it can be omitted if
774 // libXpm is not installed
776 AddHandler(new wxXPMFileHandler
);
777 AddHandler(new wxXPMDataHandler
);
778 #endif // wxHAVE_LIB_XPM
782 WXPixmap
wxBitmap::GetLabelPixmap (WXWidget w
)
785 return (WXPixmap
)NULL
;
786 // if (M_BITMAPDATA->m_image == (WXPixmap) 0)
787 return M_BITMAPDATA
->m_pixmap
;
790 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
795 if (labelPixmap) return labelPixmap;
796 things can be wrong, because colors can have been changed.
800 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
801 we got BadDrawable if the pixmap is referenced by multiples widgets
805 So, before doing thing really clean, I just do nothing; if the pixmap is
806 referenced by many widgets, Motif performs caching functions.
807 And if pixmap is referenced with multiples colors, we just have some
808 memory leaks... I hope we can deal with them...
810 // Must be destroyed, because colours can have been changed!
811 if (M_BITMAPDATA
->m_labelPixmap
)
812 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), M_BITMAPDATA
->m_labelPixmap
);
816 sprintf (tmp
, "Im%x", (unsigned int) M_BITMAPDATA
->m_image
);
819 Widget widget
= (Widget
) w
;
821 while (XmIsGadget ( widget
))
822 widget
= XtParent (widget
);
823 XtVaGetValues (widget
, XmNbackground
, &bg
, XmNforeground
, &fg
, NULL
);
825 M_BITMAPDATA
->m_labelPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
827 return M_BITMAPDATA
->m_labelPixmap
;
831 WXPixmap
wxBitmap::GetArmPixmap (WXWidget w
)
833 // if (M_BITMAPDATA->m_image == (WXPixmap) 0)
834 return M_BITMAPDATA
->m_pixmap
;
837 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
839 // See GetLabelPixmap () comment
841 // Must be destroyed, because colours can have been changed!
842 if (M_BITMAPDATA
->m_armPixmap
)
843 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), M_BITMAPDATA
->m_armPixmap
);
847 sprintf (tmp
, "Im%x", (unsigned int) M_BITMAPDATA
->m_image
);
850 Widget widget
= (Widget
) w
;
852 XtVaGetValues (widget
, XmNarmColor
, &bg
, NULL
);
853 while (XmIsGadget (widget
))
854 widget
= XtParent (widget
);
855 XtVaGetValues (widget
, XmNforeground
, &fg
, NULL
);
857 M_BITMAPDATA
->m_armPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
859 return M_BITMAPDATA
->m_armPixmap
;
863 WXPixmap
wxBitmap::GetInsensPixmap (WXWidget w
)
865 Display
*dpy
= (Display
*) M_BITMAPDATA
->m_display
;
868 return (WXPixmap
)NULL
;
869 if (M_BITMAPDATA
->m_insensPixmap
)
870 return M_BITMAPDATA
->m_insensPixmap
;
874 M_BITMAPDATA
->m_insensPixmap
= (WXPixmap
) XCreateInsensitivePixmap(dpy
, (Pixmap
) M_BITMAPDATA
->m_pixmap
);
875 if (M_BITMAPDATA
->m_insensPixmap
)
876 return M_BITMAPDATA
->m_insensPixmap
;
878 return M_BITMAPDATA
->m_pixmap
;
881 // if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0)
882 return M_BITMAPDATA
->m_pixmap
;
886 See
GetLabelPixmap () comment
887 // Must be destroyed, because colours can have been changed!
888 if (M_BITMAPDATA
->m_insensPixmap
)
889 XmDestroyPixmap (DefaultScreenOfDisplay (dpy
), (Pixmap
) M_BITMAPDATA
->m_insensPixmap
);
893 sprintf (tmp
, "Not%x", (unsigned int) M_BITMAPDATA
->m_insensImage
);
896 Widget widget
= (Widget
) w
;
898 while (XmIsGadget (widget
))
899 widget
= XtParent (widget
);
900 XtVaGetValues (widget
, XmNbackground
, &bg
, XmNforeground
, &fg
, NULL
);
902 M_BITMAPDATA
->m_insensPixmap
= (WXPixmap
) XmGetPixmap (DefaultScreenOfDisplay (dpy
), tmp
, fg
, bg
);
904 return M_BITMAPDATA
->m_insensPixmap
;
909 // Creates a bitmap with transparent areas drawn in
911 wxBitmap
wxCreateMaskedBitmap(const wxBitmap
& bitmap
, wxColour
& colour
)
913 wxBitmap
newBitmap(bitmap
.GetWidth(),
918 srcDC
.SelectObject(bitmap
);
919 destDC
.SelectObject(newBitmap
);
921 wxBrush
brush(colour
, wxSOLID
);
922 destDC
.SetOptimization(FALSE
);
923 destDC
.SetBackground(brush
);
925 destDC
.Blit(0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), & srcDC
, 0, 0, wxCOPY
, TRUE
);
933 //-----------------------------------------------------------------------------
934 // wxImage conversion routines
935 //-----------------------------------------------------------------------------
939 Date: Wed, 05 Jan 2000 11:45:40 +0100
940 From: Frits Boel <boel@niob.knaw.nl>
941 To: julian.smart@ukonline.co.uk
942 Subject: Patch for Motif ConvertToBitmap
946 I've been working on a wxWin application for image processing. From the
947 beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
948 till I looked in the source code of image.cpp. I saw that converting a
949 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
950 to the 256 colors of the palet. A very time-consuming piece of code!
952 Because I wanted a faster application, I've made a 'patch' for this. In
953 short: every pixel of the image is compared to a sorted list with
954 colors. If the color is found in the list, the palette entry is
955 returned; if the color is not found, the color palette is searched and
956 then the palette entry is returned and the color added to the sorted
959 Maybe there is another method for this, namely changing the palette
960 itself (if the colors are known, as is the case with tiffs with a
961 colormap). I did not look at this, maybe someone else did?
963 The code of the patch is attached, have a look on it, and maybe you will
964 ship it with the next release of wxMotif?
969 Software engineer at Hubrecht Laboratory, The Netherlands.
976 wxSearchColor( void );
977 wxSearchColor( int size
, XColor
*colors
);
978 ~wxSearchColor( void );
980 int SearchColor( int r
, int g
, int b
);
982 int AddColor( unsigned int value
, int pos
);
993 wxSearchColor::wxSearchColor( void )
996 colors
= (XColor
*) NULL
;
997 color
= (unsigned int *) NULL
;
1004 wxSearchColor::wxSearchColor( int size_
, XColor
*colors_
)
1009 color
= new unsigned int[size
];
1010 entry
= new int [size
];
1012 for (i
= 0; i
< size
; i
++ ) {
1016 bottom
= top
= ( size
>> 1 );
1019 wxSearchColor::~wxSearchColor( void )
1021 if ( color
) delete[] color
;
1022 if ( entry
) delete[] entry
;
1025 int wxSearchColor::SearchColor( int r
, int g
, int b
)
1027 unsigned int value
= ( ( ( r
* 256 ) + g
) * 256 ) + b
;
1032 while ( begin
<= end
) {
1034 middle
= ( begin
+ end
) >> 1;
1036 if ( value
== color
[middle
] ) {
1037 return( entry
[middle
] );
1038 } else if ( value
< color
[middle
] ) {
1046 return AddColor( value
, middle
);
1049 int wxSearchColor::AddColor( unsigned int value
, int pos
)
1053 int max
= 3 * (65536);
1054 for ( i
= 0; i
< 256; i
++ ) {
1055 int rdiff
= ((value
>> 8) & 0xFF00 ) - colors
[i
].red
;
1056 int gdiff
= ((value
) & 0xFF00 ) - colors
[i
].green
;
1057 int bdiff
= ((value
<< 8) & 0xFF00 ) - colors
[i
].blue
;
1058 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1059 if (sum
< max
) { pixel
= i
; max
= sum
; }
1062 if ( entry
[pos
] < 0 ) {
1065 } else if ( value
< color
[pos
] ) {
1068 for ( i
= bottom
; i
< pos
; i
++ ) {
1069 color
[i
-1] = color
[i
];
1070 entry
[i
-1] = entry
[i
];
1073 color
[pos
-1] = value
;
1074 entry
[pos
-1] = pixel
;
1075 } else if ( top
< size
-1 ) {
1076 for ( i
= top
; i
>= pos
; i
-- ) {
1077 color
[i
+1] = color
[i
];
1078 entry
[i
+1] = entry
[i
];
1087 if ( top
< size
-1 ) {
1088 for ( i
= top
; i
> pos
; i
-- ) {
1089 color
[i
+1] = color
[i
];
1090 entry
[i
+1] = entry
[i
];
1093 color
[pos
+1] = value
;
1094 entry
[pos
+1] = pixel
;
1095 } else if ( bottom
> 0 ) {
1096 for ( i
= bottom
; i
< pos
; i
++ ) {
1097 color
[i
-1] = color
[i
];
1098 entry
[i
-1] = entry
[i
];
1111 bool wxBitmap::CreateFromImage( const wxImage
& image
, int depth
)
1113 wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") )
1114 wxCHECK_MSG( depth
== -1, FALSE
, wxT("invalid bitmap depth") )
1116 m_refData
= new wxBitmapRefData();
1118 int width
= image
.GetWidth();
1119 int height
= image
.GetHeight();
1121 SetHeight( height
);
1124 Display
*dpy
= (Display
*) wxGetDisplay();
1125 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1126 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1130 XImage
*data_image
= XCreateImage( dpy
, vis
, bpp
, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1131 data_image
->data
= (char*) malloc( data_image
->bytes_per_line
* data_image
->height
);
1133 Create( width
, height
, bpp
);
1137 XImage
*mask_image
= (XImage
*) NULL
;
1138 if (image
.HasMask())
1140 mask_image
= XCreateImage( dpy
, vis
, 1, ZPixmap
, 0, 0, width
, height
, 32, 0 );
1141 mask_image
->data
= (char*) malloc( mask_image
->bytes_per_line
* mask_image
->height
);
1144 // Retrieve depth info
1146 XVisualInfo vinfo_template
;
1149 vinfo_template
.visual
= vis
;
1150 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1151 vinfo_template
.depth
= bpp
;
1154 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
,
1155 &vinfo_template
, &nitem
);
1157 wxCHECK_MSG( vi
, FALSE
, wxT("no visual") );
1159 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1160 if (bpp
< 8) bpp
= 8;
1164 enum byte_order
{ RGB
, RBG
, BRG
, BGR
, GRB
, GBR
};
1165 byte_order b_o
= RGB
;
1169 if ((vi
->red_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->blue_mask
)) b_o
= RGB
;
1170 else if ((vi
->red_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->green_mask
)) b_o
= RGB
;
1171 else if ((vi
->blue_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->green_mask
)) b_o
= BRG
;
1172 else if ((vi
->blue_mask
> vi
->green_mask
) && (vi
->green_mask
> vi
->red_mask
)) b_o
= BGR
;
1173 else if ((vi
->green_mask
> vi
->red_mask
) && (vi
->red_mask
> vi
->blue_mask
)) b_o
= GRB
;
1174 else if ((vi
->green_mask
> vi
->blue_mask
) && (vi
->blue_mask
> vi
->red_mask
)) b_o
= GBR
;
1179 int r_mask
= image
.GetMaskRed();
1180 int g_mask
= image
.GetMaskGreen();
1181 int b_mask
= image
.GetMaskBlue();
1186 Colormap cmap
= (Colormap
) wxTheApp
->GetMainColormap( dpy
);
1188 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1189 XQueryColors( dpy
, cmap
, colors
, 256 );
1192 wxSearchColor
scolor( 256, colors
);
1193 unsigned char* data
= image
.GetData();
1195 bool hasMask
= image
.HasMask();
1198 for (int y
= 0; y
< height
; y
++)
1200 for (int x
= 0; x
< width
; x
++)
1202 int r
= data
[index
];
1204 int g
= data
[index
];
1206 int b
= data
[index
];
1211 if ((r
== r_mask
) && (b
== b_mask
) && (g
== g_mask
))
1212 XPutPixel( mask_image
, x
, y
, 0 );
1214 XPutPixel( mask_image
, x
, y
, 1 );
1221 #if 0 // Old, slower code
1224 if (wxTheApp->m_colorCube)
1226 pixel = wxTheApp->m_colorCube
1227 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1232 int max
= 3 * (65536);
1233 for (int i
= 0; i
< 256; i
++)
1235 int rdiff
= (r
<< 8) - colors
[i
].red
;
1236 int gdiff
= (g
<< 8) - colors
[i
].green
;
1237 int bdiff
= (b
<< 8) - colors
[i
].blue
;
1238 int sum
= abs (rdiff
) + abs (gdiff
) + abs (bdiff
);
1239 if (sum
< max
) { pixel
= i
; max
= sum
; }
1246 // And this is all to get the 'right' color...
1247 int pixel
= scolor
.SearchColor( r
, g
, b
);
1248 XPutPixel( data_image
, x
, y
, pixel
);
1253 int pixel
= ((r
& 0xf8) << 7) | ((g
& 0xf8) << 2) | ((b
& 0xf8) >> 3);
1254 XPutPixel( data_image
, x
, y
, pixel
);
1259 int pixel
= ((r
& 0xf8) << 8) | ((g
& 0xfc) << 3) | ((b
& 0xf8) >> 3);
1260 XPutPixel( data_image
, x
, y
, pixel
);
1269 case RGB
: pixel
= (r
<< 16) | (g
<< 8) | b
; break;
1270 case RBG
: pixel
= (r
<< 16) | (b
<< 8) | g
; break;
1271 case BRG
: pixel
= (b
<< 16) | (r
<< 8) | g
; break;
1272 case BGR
: pixel
= (b
<< 16) | (g
<< 8) | r
; break;
1273 case GRB
: pixel
= (g
<< 16) | (r
<< 8) | b
; break;
1274 case GBR
: pixel
= (g
<< 16) | (b
<< 8) | r
; break;
1276 XPutPixel( data_image
, x
, y
, pixel
);
1286 gcvalues
.foreground
= BlackPixel( dpy
, DefaultScreen( dpy
) );
1287 GC gc
= XCreateGC( dpy
, RootWindow ( dpy
, DefaultScreen(dpy
) ), GCForeground
, &gcvalues
);
1288 XPutImage( dpy
, (Drawable
)GetPixmap(), gc
, data_image
, 0, 0, 0, 0, width
, height
);
1290 XDestroyImage( data_image
);
1294 if (image
.HasMask())
1296 wxBitmap
maskBitmap(width
, height
, 1);
1298 GC gcMask
= XCreateGC( dpy
, (Pixmap
) maskBitmap
.GetPixmap(), (XtGCMask
) 0, (XGCValues
*)NULL
);
1299 XPutImage( dpy
, (Drawable
)maskBitmap
.GetPixmap(), gcMask
, mask_image
, 0, 0, 0, 0, width
, height
);
1301 XDestroyImage( mask_image
);
1302 XFreeGC( dpy
, gcMask
);
1304 wxMask
* mask
= new wxMask
;
1305 mask
->SetPixmap(maskBitmap
.GetPixmap());
1309 maskBitmap
.SetPixmapNull();
1316 wxImage
wxBitmap::ConvertToImage() const
1320 wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") );
1322 Display
*dpy
= (Display
*) wxGetDisplay();
1323 Visual
* vis
= DefaultVisual( dpy
, DefaultScreen( dpy
) );
1324 int bpp
= DefaultDepth( dpy
, DefaultScreen( dpy
) );
1326 XImage
*ximage
= XGetImage( dpy
,
1327 (Drawable
)GetPixmap(),
1329 GetWidth(), GetHeight(),
1330 AllPlanes
, ZPixmap
);
1332 wxCHECK_MSG( ximage
, wxNullImage
, wxT("couldn't create image") );
1334 image
.Create( GetWidth(), GetHeight() );
1335 char unsigned *data
= image
.GetData();
1339 XDestroyImage( ximage
);
1340 wxFAIL_MSG( wxT("couldn't create image") );
1345 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1348 gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(),
1350 GetWidth(), GetHeight() );
1352 image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1356 // Retrieve depth info
1358 XVisualInfo vinfo_template
;
1361 vinfo_template
.visual
= vis
;
1362 vinfo_template
.visualid
= XVisualIDFromVisual( vis
);
1363 vinfo_template
.depth
= bpp
;
1366 vi
= XGetVisualInfo( dpy
, VisualIDMask
|VisualDepthMask
, &vinfo_template
, &nitem
);
1368 wxCHECK_MSG( vi
, wxNullImage
, wxT("no visual") );
1370 if ((bpp
== 16) && (vi
->red_mask
!= 0xf800)) bpp
= 15;
1377 Colormap cmap
= (Colormap
)wxTheApp
->GetMainColormap( dpy
);
1379 for (int i
= 0; i
< 256; i
++) colors
[i
].pixel
= i
;
1380 XQueryColors( dpy
, cmap
, colors
, 256 );
1384 for (int j
= 0; j
< GetHeight(); j
++)
1386 for (int i
= 0; i
< GetWidth(); i
++)
1388 int pixel
= XGetPixel( ximage
, i
, j
);
1391 data
[pos
] = colors
[pixel
].red
>> 8;
1392 data
[pos
+1] = colors
[pixel
].green
>> 8;
1393 data
[pos
+2] = colors
[pixel
].blue
>> 8;
1394 } else if (bpp
== 15)
1396 data
[pos
] = (pixel
>> 7) & 0xf8;
1397 data
[pos
+1] = (pixel
>> 2) & 0xf8;
1398 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1399 } else if (bpp
== 16)
1401 data
[pos
] = (pixel
>> 8) & 0xf8;
1402 data
[pos
+1] = (pixel
>> 3) & 0xfc;
1403 data
[pos
+2] = (pixel
<< 3) & 0xf8;
1406 data
[pos
] = (pixel
>> 16) & 0xff;
1407 data
[pos
+1] = (pixel
>> 8) & 0xff;
1408 data
[pos
+2] = pixel
& 0xff;
1414 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1415 if (mask_pixel == 0)
1428 XDestroyImage( ximage
);
1430 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );