changed wxImage::ComputeHistogram to use wxHashMap
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14056 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include "wx/string.h"
|
||||
#include "wx/gdicmn.h"
|
||||
#include "wx/bitmap.h"
|
||||
#include "wx/hashmap.h"
|
||||
|
||||
#if wxUSE_STREAMS
|
||||
# include "wx/stream.h"
|
||||
@@ -76,16 +77,25 @@ private:
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxImage
|
||||
// wxImageHistogram
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class WXDLLEXPORT wxHNode
|
||||
class WXDLLEXPORT wxImageHistogramEntry
|
||||
{
|
||||
public:
|
||||
wxImageHistogramEntry() : index(0), value(0) {}
|
||||
unsigned long index;
|
||||
unsigned long value;
|
||||
};
|
||||
|
||||
WX_DECLARE_EXPORTED_HASH_MAP(unsigned long, wxImageHistogramEntry,
|
||||
wxIntegerHash, wxIntegerEqual,
|
||||
wxImageHistogram);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxImage
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class WXDLLEXPORT wxImage: public wxObject
|
||||
{
|
||||
public:
|
||||
@@ -214,7 +224,14 @@ public:
|
||||
bool HasOption(const wxString& name) const;
|
||||
|
||||
unsigned long CountColours( unsigned long stopafter = (unsigned long) -1 );
|
||||
unsigned long ComputeHistogram( wxHashTable &h );
|
||||
|
||||
// Computes the histogram of the image and fills a hash table, indexed
|
||||
// with integer keys built as 0xRRGGBB, containing wxImageHistogramEntry
|
||||
// objects. Each of them contains an 'index' (useful to build a palette
|
||||
// with the image colours) and a 'value', which is the number of pixels
|
||||
// in the image with that colour.
|
||||
// Returned value: # of entries in the histogram
|
||||
unsigned long ComputeHistogram( wxImageHistogram &h );
|
||||
|
||||
wxImage& operator = (const wxImage& image)
|
||||
{
|
||||
|
@@ -725,10 +725,10 @@ bool wxImage::FindFirstUnusedColour(
|
||||
unsigned char *r, unsigned char *g, unsigned char *b,
|
||||
unsigned char startR, unsigned char startG, unsigned char startB)
|
||||
{
|
||||
wxHashTable hTable;
|
||||
wxImageHistogram histogram;
|
||||
unsigned long key;
|
||||
|
||||
ComputeHistogram( hTable );
|
||||
ComputeHistogram(histogram);
|
||||
|
||||
unsigned char r2 = startR;
|
||||
unsigned char g2 = startG;
|
||||
@@ -736,7 +736,7 @@ bool wxImage::FindFirstUnusedColour(
|
||||
|
||||
key = (r2 << 16) | (g2 << 8) | b2;
|
||||
|
||||
while ( (wxHNode *) hTable.Get(key) )
|
||||
while ( histogram.find(key) != histogram.end() )
|
||||
{
|
||||
// color already used
|
||||
r2++;
|
||||
@@ -1352,19 +1352,13 @@ unsigned long wxImage::CountColours( unsigned long stopafter )
|
||||
}
|
||||
|
||||
|
||||
// GRG, Dic/99
|
||||
// Computes the histogram of the image and fills a hash table, indexed
|
||||
// with integer keys built as 0xRRGGBB, containing wxHNode objects. Each
|
||||
// wxHNode contains an 'index' (useful to build a palette with the image
|
||||
// colours) and a 'value', which is the number of pixels in the image with
|
||||
// that colour.
|
||||
//
|
||||
unsigned long wxImage::ComputeHistogram( wxHashTable &h )
|
||||
unsigned long wxImage::ComputeHistogram( wxImageHistogram &h )
|
||||
{
|
||||
unsigned char r, g, b;
|
||||
unsigned char *p;
|
||||
unsigned long size, nentries, key;
|
||||
wxHNode *hnode;
|
||||
|
||||
h.clear();
|
||||
|
||||
p = GetData();
|
||||
size = GetWidth() * GetHeight();
|
||||
@@ -1377,18 +1371,9 @@ unsigned long wxImage::ComputeHistogram( wxHashTable &h )
|
||||
b = *(p++);
|
||||
key = (r << 16) | (g << 8) | b;
|
||||
|
||||
hnode = (wxHNode *) h.Get(key);
|
||||
|
||||
if (hnode)
|
||||
hnode->value++;
|
||||
else
|
||||
{
|
||||
hnode = new wxHNode();
|
||||
hnode->index = nentries++;
|
||||
hnode->value = 1;
|
||||
|
||||
h.Put(key, (wxObject *)hnode);
|
||||
}
|
||||
wxImageHistogramEntry& entry = h[key];
|
||||
if ( entry.value++ == 0 )
|
||||
entry.index = nentries++;
|
||||
}
|
||||
|
||||
return nentries;
|
||||
|
@@ -311,7 +311,7 @@ int SavePCX(wxImage *image, wxOutputStream& stream)
|
||||
unsigned int bytesperline; // bytes per line (each plane)
|
||||
int nplanes = 3; // number of planes
|
||||
int format = wxPCX_24BIT; // image format (8 bit, 24 bit)
|
||||
wxHashTable h(wxKEY_INTEGER); // image histogram
|
||||
wxImageHistogram histogram; // image histogram
|
||||
unsigned long key; // key in the hashtable
|
||||
unsigned int i;
|
||||
|
||||
@@ -319,7 +319,7 @@ int SavePCX(wxImage *image, wxOutputStream& stream)
|
||||
|
||||
if (image->CountColours(256) <= 256)
|
||||
{
|
||||
image->ComputeHistogram(h);
|
||||
image->ComputeHistogram(histogram);
|
||||
format = wxPCX_8BIT;
|
||||
nplanes = 1;
|
||||
}
|
||||
@@ -371,7 +371,6 @@ int SavePCX(wxImage *image, wxOutputStream& stream)
|
||||
case wxPCX_8BIT:
|
||||
{
|
||||
unsigned char r, g, b;
|
||||
wxHNode *hnode;
|
||||
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
@@ -380,8 +379,7 @@ int SavePCX(wxImage *image, wxOutputStream& stream)
|
||||
b = *(src++);
|
||||
key = (r << 16) | (g << 8) | b;
|
||||
|
||||
hnode = (wxHNode *) h.Get(key);
|
||||
p[i] = (unsigned char)hnode->index;
|
||||
p[i] = (unsigned char)histogram[key].index;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -402,26 +400,22 @@ int SavePCX(wxImage *image, wxOutputStream& stream)
|
||||
|
||||
free(p);
|
||||
|
||||
// For 8 bit images, build the palette and write it to the stream
|
||||
|
||||
// For 8 bit images, build the palette and write it to the stream:
|
||||
if (format == wxPCX_8BIT)
|
||||
{
|
||||
wxNode *node;
|
||||
wxHNode *hnode;
|
||||
|
||||
// zero unused colours
|
||||
memset(pal, 0, sizeof(pal));
|
||||
|
||||
h.BeginFind();
|
||||
while ((node = h.Next()) != NULL)
|
||||
unsigned long index;
|
||||
|
||||
for (wxImageHistogram::iterator entry = histogram.begin();
|
||||
entry != histogram.end(); entry++ )
|
||||
{
|
||||
key = node->GetKeyInteger();
|
||||
hnode = (wxHNode *) node->GetData();
|
||||
|
||||
pal[3 * hnode->index] = (unsigned char)(key >> 16);
|
||||
pal[3 * hnode->index + 1] = (unsigned char)(key >> 8);
|
||||
pal[3 * hnode->index + 2] = (unsigned char)(key);
|
||||
delete hnode;
|
||||
key = entry->first;
|
||||
index = entry->second.index;
|
||||
pal[3 * index] = (unsigned char)(key >> 16);
|
||||
pal[3 * index + 1] = (unsigned char)(key >> 8);
|
||||
pal[3 * index + 2] = (unsigned char)(key);
|
||||
}
|
||||
|
||||
stream.PutC(12);
|
||||
|
@@ -140,25 +140,23 @@ bool wxXPMHandler::SaveFile(wxImage * image,
|
||||
stream.Write(tmpbuf, strlen(tmpbuf));
|
||||
|
||||
// 3. create color symbols table:
|
||||
wxHashTable table(wxKEY_INTEGER);
|
||||
image->ComputeHistogram(table);
|
||||
wxImageHistogram histogram;
|
||||
image->ComputeHistogram(histogram);
|
||||
|
||||
char *symbols_data = new char[cols * (chars_per_pixel+1)];
|
||||
char **symbols = new char*[cols];
|
||||
|
||||
// 2a. find mask colour:
|
||||
long mask_key = -1;
|
||||
unsigned long mask_key = 0x1000000 /*invalid RGB value*/;
|
||||
if (image->HasMask())
|
||||
mask_key = (image->GetMaskRed() << 16) |
|
||||
(image->GetMaskGreen() << 8) | image->GetMaskBlue();
|
||||
|
||||
// 2b. generate colour table:
|
||||
table.BeginFind();
|
||||
wxNode *node = NULL;
|
||||
while ((node = table.Next()) != NULL)
|
||||
for (wxImageHistogram::iterator entry = histogram.begin();
|
||||
entry != histogram.end(); entry++ )
|
||||
{
|
||||
wxHNode *hnode = (wxHNode*) node->GetData();
|
||||
long index = hnode->index;
|
||||
unsigned long index = entry->second.index;
|
||||
symbols[index] = symbols_data + index * (chars_per_pixel+1);
|
||||
char *sym = symbols[index];
|
||||
|
||||
@@ -171,7 +169,7 @@ bool wxXPMHandler::SaveFile(wxImage * image,
|
||||
}
|
||||
sym[j] = '\0';
|
||||
|
||||
long key = node->GetKeyInteger();
|
||||
unsigned long key = entry->first;
|
||||
|
||||
if (key == 0)
|
||||
tmp.Printf(wxT("\"%s c Black\",\n"), sym);
|
||||
@@ -195,8 +193,7 @@ bool wxXPMHandler::SaveFile(wxImage * image,
|
||||
for (i = 0; i < image->GetWidth(); i++, data += 3)
|
||||
{
|
||||
unsigned long key = (data[0] << 16) | (data[1] << 8) | (data[2]);
|
||||
wxHNode *hnode = (wxHNode*) table.Get(key);
|
||||
stream.Write(symbols[hnode->index], chars_per_pixel);
|
||||
stream.Write(symbols[histogram[key].index], chars_per_pixel);
|
||||
}
|
||||
tmp_c = '\"'; stream.Write(&tmp_c, 1);
|
||||
if ( j + 1 < image->GetHeight() )
|
||||
@@ -212,13 +209,6 @@ bool wxXPMHandler::SaveFile(wxImage * image,
|
||||
delete[] symbols;
|
||||
delete[] symbols_data;
|
||||
|
||||
// FIXME: it will be better to use macros-based wxHashTable & DeleteContents(TRUE)
|
||||
table.BeginFind();
|
||||
while ((node = table.Next()) != NULL)
|
||||
{
|
||||
delete (wxHNode *) node->GetData();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@@ -205,42 +205,42 @@ wxCursor::wxCursor( const wxImage & image )
|
||||
//it seems a waste of effort to copy the image
|
||||
//but otherwise we need to remove the const modifier ??
|
||||
wxImage tmpImage = image.Copy();
|
||||
wxHashTable hTable;
|
||||
wxImageHistogram histogram;
|
||||
|
||||
//colors as rrggbb
|
||||
unsigned long key;
|
||||
unsigned long value;
|
||||
unsigned long keyMaskColor = 0;
|
||||
if (bHasMask) keyMaskColor = (r << 16) | (g << 8) | b;
|
||||
if (bHasMask)
|
||||
keyMaskColor = (r << 16) | (g << 8) | b;
|
||||
|
||||
tmpImage.ComputeHistogram( hTable );
|
||||
tmpImage.ComputeHistogram(histogram);
|
||||
|
||||
long MostFreqCol = 0 ; long nMost = 0;
|
||||
long NextFreqCol = 0 ; long nNext = 0;
|
||||
long value ;
|
||||
hTable.BeginFind();
|
||||
wxNode *node = NULL;
|
||||
while ((node = hTable.Next()) != NULL)
|
||||
long MostFreqCol = 0;
|
||||
unsigned long nMost = 0;
|
||||
long NextFreqCol = 0;
|
||||
unsigned long nNext = 0;
|
||||
wxImageHistogram::iterator entry = histogram.begin();
|
||||
|
||||
while ( entry != histogram.end() )
|
||||
{
|
||||
wxHNode *hnode = (wxHNode*) node->GetData();
|
||||
value = hnode->value;
|
||||
key = node->GetKeyInteger() ;
|
||||
if (!bHasMask || (key != keyMaskColor) )
|
||||
value = entry->second.value;
|
||||
key = entry->first;
|
||||
if ( !bHasMask || (key != keyMaskColor) )
|
||||
{
|
||||
if (value > nMost)
|
||||
if (value > nMost)
|
||||
{
|
||||
nMost = value;
|
||||
MostFreqCol = key;
|
||||
nMost = value;
|
||||
MostFreqCol = key;
|
||||
}
|
||||
else
|
||||
if (value > nNext)
|
||||
else if (value > nNext)
|
||||
{
|
||||
nNext = value ;
|
||||
NextFreqCol = key;
|
||||
nNext = value;
|
||||
NextFreqCol = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wxColour fg = wxColour ( (unsigned char)(MostFreqCol >> 16),
|
||||
(unsigned char)(MostFreqCol >> 8),
|
||||
(unsigned char)(MostFreqCol) ) ;
|
||||
@@ -249,20 +249,18 @@ wxCursor::wxCursor( const wxImage & image )
|
||||
(unsigned char)(NextFreqCol >> 8),
|
||||
(unsigned char)(NextFreqCol) ) ;
|
||||
|
||||
|
||||
|
||||
int hotSpotX=0;
|
||||
int hotSpotY=0;
|
||||
|
||||
if (image.HasOption(wxCUR_HOTSPOT_X))
|
||||
hotSpotX = image.GetOptionInt(wxCUR_HOTSPOT_X);
|
||||
hotSpotX = image.GetOptionInt(wxCUR_HOTSPOT_X);
|
||||
if (image.HasOption(wxCUR_HOTSPOT_Y))
|
||||
hotSpotY = image.GetOptionInt(wxCUR_HOTSPOT_Y);
|
||||
hotSpotY = image.GetOptionInt(wxCUR_HOTSPOT_Y);
|
||||
|
||||
if (hotSpotX < 0 || hotSpotX >= w)
|
||||
hotSpotX = 0;
|
||||
hotSpotX = 0;
|
||||
if (hotSpotY < 0 || hotSpotY >= h)
|
||||
hotSpotY = 0;
|
||||
hotSpotY = 0;
|
||||
|
||||
GdkBitmap *data = gdk_bitmap_create_from_data( wxGetRootWindow()->window, (gchar *) bits,
|
||||
w, h );
|
||||
@@ -278,7 +276,6 @@ wxCursor::wxCursor( const wxImage & image )
|
||||
gdk_bitmap_unref( mask );
|
||||
delete [] bits ;
|
||||
delete [] maskBits;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -205,42 +205,42 @@ wxCursor::wxCursor( const wxImage & image )
|
||||
//it seems a waste of effort to copy the image
|
||||
//but otherwise we need to remove the const modifier ??
|
||||
wxImage tmpImage = image.Copy();
|
||||
wxHashTable hTable;
|
||||
wxImageHistogram histogram;
|
||||
|
||||
//colors as rrggbb
|
||||
unsigned long key;
|
||||
unsigned long value;
|
||||
unsigned long keyMaskColor = 0;
|
||||
if (bHasMask) keyMaskColor = (r << 16) | (g << 8) | b;
|
||||
if (bHasMask)
|
||||
keyMaskColor = (r << 16) | (g << 8) | b;
|
||||
|
||||
tmpImage.ComputeHistogram( hTable );
|
||||
tmpImage.ComputeHistogram(histogram);
|
||||
|
||||
long MostFreqCol = 0 ; long nMost = 0;
|
||||
long NextFreqCol = 0 ; long nNext = 0;
|
||||
long value ;
|
||||
hTable.BeginFind();
|
||||
wxNode *node = NULL;
|
||||
while ((node = hTable.Next()) != NULL)
|
||||
long MostFreqCol = 0;
|
||||
unsigned long nMost = 0;
|
||||
long NextFreqCol = 0;
|
||||
unsigned long nNext = 0;
|
||||
wxImageHistogram::iterator entry = histogram.begin();
|
||||
|
||||
while ( entry != histogram.end() )
|
||||
{
|
||||
wxHNode *hnode = (wxHNode*) node->GetData();
|
||||
value = hnode->value;
|
||||
key = node->GetKeyInteger() ;
|
||||
if (!bHasMask || (key != keyMaskColor) )
|
||||
value = entry->second.value;
|
||||
key = entry->first;
|
||||
if ( !bHasMask || (key != keyMaskColor) )
|
||||
{
|
||||
if (value > nMost)
|
||||
if (value > nMost)
|
||||
{
|
||||
nMost = value;
|
||||
MostFreqCol = key;
|
||||
nMost = value;
|
||||
MostFreqCol = key;
|
||||
}
|
||||
else
|
||||
if (value > nNext)
|
||||
else if (value > nNext)
|
||||
{
|
||||
nNext = value ;
|
||||
NextFreqCol = key;
|
||||
nNext = value;
|
||||
NextFreqCol = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wxColour fg = wxColour ( (unsigned char)(MostFreqCol >> 16),
|
||||
(unsigned char)(MostFreqCol >> 8),
|
||||
(unsigned char)(MostFreqCol) ) ;
|
||||
@@ -249,20 +249,18 @@ wxCursor::wxCursor( const wxImage & image )
|
||||
(unsigned char)(NextFreqCol >> 8),
|
||||
(unsigned char)(NextFreqCol) ) ;
|
||||
|
||||
|
||||
|
||||
int hotSpotX=0;
|
||||
int hotSpotY=0;
|
||||
|
||||
if (image.HasOption(wxCUR_HOTSPOT_X))
|
||||
hotSpotX = image.GetOptionInt(wxCUR_HOTSPOT_X);
|
||||
hotSpotX = image.GetOptionInt(wxCUR_HOTSPOT_X);
|
||||
if (image.HasOption(wxCUR_HOTSPOT_Y))
|
||||
hotSpotY = image.GetOptionInt(wxCUR_HOTSPOT_Y);
|
||||
hotSpotY = image.GetOptionInt(wxCUR_HOTSPOT_Y);
|
||||
|
||||
if (hotSpotX < 0 || hotSpotX >= w)
|
||||
hotSpotX = 0;
|
||||
hotSpotX = 0;
|
||||
if (hotSpotY < 0 || hotSpotY >= h)
|
||||
hotSpotY = 0;
|
||||
hotSpotY = 0;
|
||||
|
||||
GdkBitmap *data = gdk_bitmap_create_from_data( wxGetRootWindow()->window, (gchar *) bits,
|
||||
w, h );
|
||||
@@ -278,7 +276,6 @@ wxCursor::wxCursor( const wxImage & image )
|
||||
gdk_bitmap_unref( mask );
|
||||
delete [] bits ;
|
||||
delete [] maskBits;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Reference in New Issue
Block a user