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/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)
|
||||||
{
|
{
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user