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:
Václav Slavík
2002-02-07 18:11:39 +00:00
parent d353bd452e
commit 952ae1e88b
6 changed files with 100 additions and 120 deletions

View File

@@ -19,6 +19,7 @@
#include "wx/string.h" #include "wx/string.h"
#include "wx/gdicmn.h" #include "wx/gdicmn.h"
#include "wx/bitmap.h" #include "wx/bitmap.h"
#include "wx/hashmap.h"
#if wxUSE_STREAMS #if wxUSE_STREAMS
# include "wx/stream.h" # include "wx/stream.h"
@@ -76,16 +77,25 @@ private:
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// wxImage // wxImageHistogram
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class WXDLLEXPORT wxHNode class WXDLLEXPORT wxImageHistogramEntry
{ {
public: public:
wxImageHistogramEntry() : index(0), value(0) {}
unsigned long index; unsigned long index;
unsigned long value; unsigned long value;
}; };
WX_DECLARE_EXPORTED_HASH_MAP(unsigned long, wxImageHistogramEntry,
wxIntegerHash, wxIntegerEqual,
wxImageHistogram);
//-----------------------------------------------------------------------------
// wxImage
//-----------------------------------------------------------------------------
class WXDLLEXPORT wxImage: public wxObject class WXDLLEXPORT wxImage: public wxObject
{ {
public: public:
@@ -214,7 +224,14 @@ public:
bool HasOption(const wxString& name) const; bool HasOption(const wxString& name) const;
unsigned long CountColours( unsigned long stopafter = (unsigned long) -1 ); 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) wxImage& operator = (const wxImage& image)
{ {

View File

@@ -725,10 +725,10 @@ bool wxImage::FindFirstUnusedColour(
unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *r, unsigned char *g, unsigned char *b,
unsigned char startR, unsigned char startG, unsigned char startB) unsigned char startR, unsigned char startG, unsigned char startB)
{ {
wxHashTable hTable; wxImageHistogram histogram;
unsigned long key; unsigned long key;
ComputeHistogram( hTable ); ComputeHistogram(histogram);
unsigned char r2 = startR; unsigned char r2 = startR;
unsigned char g2 = startG; unsigned char g2 = startG;
@@ -736,7 +736,7 @@ bool wxImage::FindFirstUnusedColour(
key = (r2 << 16) | (g2 << 8) | b2; key = (r2 << 16) | (g2 << 8) | b2;
while ( (wxHNode *) hTable.Get(key) ) while ( histogram.find(key) != histogram.end() )
{ {
// color already used // color already used
r2++; r2++;
@@ -1352,19 +1352,13 @@ unsigned long wxImage::CountColours( unsigned long stopafter )
} }
// GRG, Dic/99 unsigned long wxImage::ComputeHistogram( wxImageHistogram &h )
// 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 char r, g, b; unsigned char r, g, b;
unsigned char *p; unsigned char *p;
unsigned long size, nentries, key; unsigned long size, nentries, key;
wxHNode *hnode;
h.clear();
p = GetData(); p = GetData();
size = GetWidth() * GetHeight(); size = GetWidth() * GetHeight();
@@ -1377,18 +1371,9 @@ unsigned long wxImage::ComputeHistogram( wxHashTable &h )
b = *(p++); b = *(p++);
key = (r << 16) | (g << 8) | b; key = (r << 16) | (g << 8) | b;
hnode = (wxHNode *) h.Get(key); wxImageHistogramEntry& entry = h[key];
if ( entry.value++ == 0 )
if (hnode) entry.index = nentries++;
hnode->value++;
else
{
hnode = new wxHNode();
hnode->index = nentries++;
hnode->value = 1;
h.Put(key, (wxObject *)hnode);
}
} }
return nentries; return nentries;

View File

@@ -311,7 +311,7 @@ int SavePCX(wxImage *image, wxOutputStream& stream)
unsigned int bytesperline; // bytes per line (each plane) unsigned int bytesperline; // bytes per line (each plane)
int nplanes = 3; // number of planes int nplanes = 3; // number of planes
int format = wxPCX_24BIT; // image format (8 bit, 24 bit) 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 long key; // key in the hashtable
unsigned int i; unsigned int i;
@@ -319,7 +319,7 @@ int SavePCX(wxImage *image, wxOutputStream& stream)
if (image->CountColours(256) <= 256) if (image->CountColours(256) <= 256)
{ {
image->ComputeHistogram(h); image->ComputeHistogram(histogram);
format = wxPCX_8BIT; format = wxPCX_8BIT;
nplanes = 1; nplanes = 1;
} }
@@ -371,7 +371,6 @@ int SavePCX(wxImage *image, wxOutputStream& stream)
case wxPCX_8BIT: case wxPCX_8BIT:
{ {
unsigned char r, g, b; unsigned char r, g, b;
wxHNode *hnode;
for (i = 0; i < width; i++) for (i = 0; i < width; i++)
{ {
@@ -380,8 +379,7 @@ int SavePCX(wxImage *image, wxOutputStream& stream)
b = *(src++); b = *(src++);
key = (r << 16) | (g << 8) | b; key = (r << 16) | (g << 8) | b;
hnode = (wxHNode *) h.Get(key); p[i] = (unsigned char)histogram[key].index;
p[i] = (unsigned char)hnode->index;
} }
break; break;
} }
@@ -402,26 +400,22 @@ int SavePCX(wxImage *image, wxOutputStream& stream)
free(p); 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) if (format == wxPCX_8BIT)
{ {
wxNode *node;
wxHNode *hnode;
// zero unused colours // zero unused colours
memset(pal, 0, sizeof(pal)); memset(pal, 0, sizeof(pal));
h.BeginFind(); unsigned long index;
while ((node = h.Next()) != NULL)
{
key = node->GetKeyInteger();
hnode = (wxHNode *) node->GetData();
pal[3 * hnode->index] = (unsigned char)(key >> 16); for (wxImageHistogram::iterator entry = histogram.begin();
pal[3 * hnode->index + 1] = (unsigned char)(key >> 8); entry != histogram.end(); entry++ )
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); stream.PutC(12);

View File

@@ -140,25 +140,23 @@ bool wxXPMHandler::SaveFile(wxImage * image,
stream.Write(tmpbuf, strlen(tmpbuf)); stream.Write(tmpbuf, strlen(tmpbuf));
// 3. create color symbols table: // 3. create color symbols table:
wxHashTable table(wxKEY_INTEGER); wxImageHistogram histogram;
image->ComputeHistogram(table); image->ComputeHistogram(histogram);
char *symbols_data = new char[cols * (chars_per_pixel+1)]; char *symbols_data = new char[cols * (chars_per_pixel+1)];
char **symbols = new char*[cols]; char **symbols = new char*[cols];
// 2a. find mask colour: // 2a. find mask colour:
long mask_key = -1; unsigned long mask_key = 0x1000000 /*invalid RGB value*/;
if (image->HasMask()) if (image->HasMask())
mask_key = (image->GetMaskRed() << 16) | mask_key = (image->GetMaskRed() << 16) |
(image->GetMaskGreen() << 8) | image->GetMaskBlue(); (image->GetMaskGreen() << 8) | image->GetMaskBlue();
// 2b. generate colour table: // 2b. generate colour table:
table.BeginFind(); for (wxImageHistogram::iterator entry = histogram.begin();
wxNode *node = NULL; entry != histogram.end(); entry++ )
while ((node = table.Next()) != NULL)
{ {
wxHNode *hnode = (wxHNode*) node->GetData(); unsigned long index = entry->second.index;
long index = hnode->index;
symbols[index] = symbols_data + index * (chars_per_pixel+1); symbols[index] = symbols_data + index * (chars_per_pixel+1);
char *sym = symbols[index]; char *sym = symbols[index];
@@ -171,7 +169,7 @@ bool wxXPMHandler::SaveFile(wxImage * image,
} }
sym[j] = '\0'; sym[j] = '\0';
long key = node->GetKeyInteger(); unsigned long key = entry->first;
if (key == 0) if (key == 0)
tmp.Printf(wxT("\"%s c Black\",\n"), sym); 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) for (i = 0; i < image->GetWidth(); i++, data += 3)
{ {
unsigned long key = (data[0] << 16) | (data[1] << 8) | (data[2]); unsigned long key = (data[0] << 16) | (data[1] << 8) | (data[2]);
wxHNode *hnode = (wxHNode*) table.Get(key); stream.Write(symbols[histogram[key].index], chars_per_pixel);
stream.Write(symbols[hnode->index], chars_per_pixel);
} }
tmp_c = '\"'; stream.Write(&tmp_c, 1); tmp_c = '\"'; stream.Write(&tmp_c, 1);
if ( j + 1 < image->GetHeight() ) if ( j + 1 < image->GetHeight() )
@@ -212,13 +209,6 @@ bool wxXPMHandler::SaveFile(wxImage * image,
delete[] symbols; delete[] symbols;
delete[] symbols_data; 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; return TRUE;
} }

View File

@@ -205,25 +205,27 @@ wxCursor::wxCursor( const wxImage & image )
//it seems a waste of effort to copy the image //it seems a waste of effort to copy the image
//but otherwise we need to remove the const modifier ?? //but otherwise we need to remove the const modifier ??
wxImage tmpImage = image.Copy(); wxImage tmpImage = image.Copy();
wxHashTable hTable; wxImageHistogram histogram;
//colors as rrggbb //colors as rrggbb
unsigned long key; unsigned long key;
unsigned long value;
unsigned long keyMaskColor = 0; 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 MostFreqCol = 0;
long NextFreqCol = 0 ; long nNext = 0; unsigned long nMost = 0;
long value ; long NextFreqCol = 0;
hTable.BeginFind(); unsigned long nNext = 0;
wxNode *node = NULL; wxImageHistogram::iterator entry = histogram.begin();
while ((node = hTable.Next()) != NULL)
while ( entry != histogram.end() )
{ {
wxHNode *hnode = (wxHNode*) node->GetData(); value = entry->second.value;
value = hnode->value; key = entry->first;
key = node->GetKeyInteger() ;
if ( !bHasMask || (key != keyMaskColor) ) if ( !bHasMask || (key != keyMaskColor) )
{ {
if (value > nMost) if (value > nMost)
@@ -231,8 +233,7 @@ wxCursor::wxCursor( const wxImage & image )
nMost = value; nMost = value;
MostFreqCol = key; MostFreqCol = key;
} }
else else if (value > nNext)
if (value > nNext)
{ {
nNext = value; nNext = value;
NextFreqCol = key; NextFreqCol = key;
@@ -240,7 +241,6 @@ wxCursor::wxCursor( const wxImage & image )
} }
} }
wxColour fg = wxColour ( (unsigned char)(MostFreqCol >> 16), wxColour fg = wxColour ( (unsigned char)(MostFreqCol >> 16),
(unsigned char)(MostFreqCol >> 8), (unsigned char)(MostFreqCol >> 8),
(unsigned char)(MostFreqCol) ) ; (unsigned char)(MostFreqCol) ) ;
@@ -249,8 +249,6 @@ wxCursor::wxCursor( const wxImage & image )
(unsigned char)(NextFreqCol >> 8), (unsigned char)(NextFreqCol >> 8),
(unsigned char)(NextFreqCol) ) ; (unsigned char)(NextFreqCol) ) ;
int hotSpotX=0; int hotSpotX=0;
int hotSpotY=0; int hotSpotY=0;
@@ -278,7 +276,6 @@ wxCursor::wxCursor( const wxImage & image )
gdk_bitmap_unref( mask ); gdk_bitmap_unref( mask );
delete [] bits ; delete [] bits ;
delete [] maskBits; delete [] maskBits;
} }
#endif #endif

View File

@@ -205,25 +205,27 @@ wxCursor::wxCursor( const wxImage & image )
//it seems a waste of effort to copy the image //it seems a waste of effort to copy the image
//but otherwise we need to remove the const modifier ?? //but otherwise we need to remove the const modifier ??
wxImage tmpImage = image.Copy(); wxImage tmpImage = image.Copy();
wxHashTable hTable; wxImageHistogram histogram;
//colors as rrggbb //colors as rrggbb
unsigned long key; unsigned long key;
unsigned long value;
unsigned long keyMaskColor = 0; 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 MostFreqCol = 0;
long NextFreqCol = 0 ; long nNext = 0; unsigned long nMost = 0;
long value ; long NextFreqCol = 0;
hTable.BeginFind(); unsigned long nNext = 0;
wxNode *node = NULL; wxImageHistogram::iterator entry = histogram.begin();
while ((node = hTable.Next()) != NULL)
while ( entry != histogram.end() )
{ {
wxHNode *hnode = (wxHNode*) node->GetData(); value = entry->second.value;
value = hnode->value; key = entry->first;
key = node->GetKeyInteger() ;
if ( !bHasMask || (key != keyMaskColor) ) if ( !bHasMask || (key != keyMaskColor) )
{ {
if (value > nMost) if (value > nMost)
@@ -231,8 +233,7 @@ wxCursor::wxCursor( const wxImage & image )
nMost = value; nMost = value;
MostFreqCol = key; MostFreqCol = key;
} }
else else if (value > nNext)
if (value > nNext)
{ {
nNext = value; nNext = value;
NextFreqCol = key; NextFreqCol = key;
@@ -240,7 +241,6 @@ wxCursor::wxCursor( const wxImage & image )
} }
} }
wxColour fg = wxColour ( (unsigned char)(MostFreqCol >> 16), wxColour fg = wxColour ( (unsigned char)(MostFreqCol >> 16),
(unsigned char)(MostFreqCol >> 8), (unsigned char)(MostFreqCol >> 8),
(unsigned char)(MostFreqCol) ) ; (unsigned char)(MostFreqCol) ) ;
@@ -249,8 +249,6 @@ wxCursor::wxCursor( const wxImage & image )
(unsigned char)(NextFreqCol >> 8), (unsigned char)(NextFreqCol >> 8),
(unsigned char)(NextFreqCol) ) ; (unsigned char)(NextFreqCol) ) ;
int hotSpotX=0; int hotSpotX=0;
int hotSpotY=0; int hotSpotY=0;
@@ -278,7 +276,6 @@ wxCursor::wxCursor( const wxImage & image )
gdk_bitmap_unref( mask ); gdk_bitmap_unref( mask );
delete [] bits ; delete [] bits ;
delete [] maskBits; delete [] maskBits;
} }
#endif #endif