⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 image.cpp

📁 A*算法 A*算法 A*算法 A*算法A*算法A*算法
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/////////////////////////////////////////////////////////////////////////////
// Name:        image.cpp
// Purpose:     wxImage
// Author:      Robert Roebling
// RCS-ID:      $Id: image.cpp,v 1.202.2.3 2006/01/26 12:04:53 RR Exp $
// Copyright:   (c) Robert Roebling
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "image.h"
#endif

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#include "wx/defs.h"

#if wxUSE_IMAGE

#include "wx/image.h"
#include "wx/bitmap.h"
#include "wx/debug.h"
#include "wx/log.h"
#include "wx/app.h"
#include "wx/filefn.h"
#include "wx/wfstream.h"
#include "wx/intl.h"
#include "wx/module.h"
#include "wx/hash.h"
#include "wx/utils.h"
#include "wx/math.h"

#if wxUSE_XPM
#include "wx/xpmdecod.h"
#endif

// For memcpy
#include <string.h>

//-----------------------------------------------------------------------------
// wxImage
//-----------------------------------------------------------------------------

class wxImageRefData: public wxObjectRefData
{
public:
    wxImageRefData();
    virtual ~wxImageRefData();

    int             m_width;
    int             m_height;
    unsigned char  *m_data;

    bool            m_hasMask;
    unsigned char   m_maskRed,m_maskGreen,m_maskBlue;

    // alpha channel data, may be NULL for the formats without alpha support
    unsigned char  *m_alpha;

    bool            m_ok;

    // if true, m_data is pointer to static data and shouldn't be freed
    bool            m_static;

    // same as m_static but for m_alpha
    bool            m_staticAlpha;

#if wxUSE_PALETTE
    wxPalette       m_palette;
#endif // wxUSE_PALETTE

    wxArrayString   m_optionNames;
    wxArrayString   m_optionValues;

    DECLARE_NO_COPY_CLASS(wxImageRefData)
};

wxImageRefData::wxImageRefData()
{
    m_width = 0;
    m_height = 0;
    m_data =
    m_alpha = (unsigned char *) NULL;

    m_maskRed = 0;
    m_maskGreen = 0;
    m_maskBlue = 0;
    m_hasMask = false;

    m_ok = false;
    m_static =
    m_staticAlpha = false;
}

wxImageRefData::~wxImageRefData()
{
    if ( !m_static )
        free( m_data );
    if ( !m_staticAlpha )
        free( m_alpha );
}

wxList wxImage::sm_handlers;

wxImage wxNullImage;

//-----------------------------------------------------------------------------

#define M_IMGDATA ((wxImageRefData *)m_refData)

IMPLEMENT_DYNAMIC_CLASS(wxImage, wxObject)

wxImage::wxImage( int width, int height, bool clear )
{
    Create( width, height, clear );
}

wxImage::wxImage( int width, int height, unsigned char* data, bool static_data )
{
    Create( width, height, data, static_data );
}

wxImage::wxImage( int width, int height, unsigned char* data, unsigned char* alpha, bool static_data )
{
    Create( width, height, data, alpha, static_data );
}

wxImage::wxImage( const wxString& name, long type, int index )
{
    LoadFile( name, type, index );
}

wxImage::wxImage( const wxString& name, const wxString& mimetype, int index )
{
    LoadFile( name, mimetype, index );
}

#if wxUSE_STREAMS
wxImage::wxImage( wxInputStream& stream, long type, int index )
{
    LoadFile( stream, type, index );
}

wxImage::wxImage( wxInputStream& stream, const wxString& mimetype, int index )
{
    LoadFile( stream, mimetype, index );
}
#endif // wxUSE_STREAMS

wxImage::wxImage( const wxImage& image )
    : wxObject()
{
    Ref(image);
}

wxImage::wxImage( const wxImage* image )
{
    if (image) Ref(*image);
}

wxImage::wxImage( const char** xpmData )
{
    Create(xpmData);
}

wxImage::wxImage( char** xpmData )
{
    Create((const char**) xpmData);
}

bool wxImage::Create( const char** xpmData )
{
#if wxUSE_XPM
    UnRef();

    wxXPMDecoder decoder;
    (*this) = decoder.ReadData(xpmData);
    return Ok();
#else
    return false;
#endif
}

bool wxImage::Create( int width, int height, bool clear )
{
    UnRef();

    m_refData = new wxImageRefData();

    M_IMGDATA->m_data = (unsigned char *) malloc( width*height*3 );
    if (!M_IMGDATA->m_data)
    {
        UnRef();
        return false;
    }

    if (clear)
        memset(M_IMGDATA->m_data, 0, width*height*3);

    M_IMGDATA->m_width = width;
    M_IMGDATA->m_height = height;
    M_IMGDATA->m_ok = true;

    return true;
}

bool wxImage::Create( int width, int height, unsigned char* data, bool static_data )
{
    UnRef();

    wxCHECK_MSG( data, false, _T("NULL data in wxImage::Create") );

    m_refData = new wxImageRefData();

    M_IMGDATA->m_data = data;
    M_IMGDATA->m_width = width;
    M_IMGDATA->m_height = height;
    M_IMGDATA->m_ok = true;
    M_IMGDATA->m_static = static_data;

    return true;
}

bool wxImage::Create( int width, int height, unsigned char* data, unsigned char* alpha, bool static_data )
{
    UnRef();

    wxCHECK_MSG( data, false, _T("NULL data in wxImage::Create") );

    m_refData = new wxImageRefData();

    M_IMGDATA->m_data = data;
    M_IMGDATA->m_alpha = alpha;
    M_IMGDATA->m_width = width;
    M_IMGDATA->m_height = height;
    M_IMGDATA->m_ok = true;
    M_IMGDATA->m_static = static_data;

    return true;
}

void wxImage::Destroy()
{
    UnRef();
}

wxImage wxImage::Copy() const
{
    wxImage image;

    wxCHECK_MSG( Ok(), image, wxT("invalid image") );

    image.Create( M_IMGDATA->m_width, M_IMGDATA->m_height, false );

    unsigned char *data = image.GetData();

    wxCHECK_MSG( data, image, wxT("unable to create image") );

    image.SetMaskColour( M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue );
    image.SetMask( M_IMGDATA->m_hasMask );

    memcpy( data, GetData(), M_IMGDATA->m_width*M_IMGDATA->m_height*3 );

    wxImageRefData *imgData = (wxImageRefData *)image.m_refData;
    
    // also copy the alpha channel
    if (HasAlpha())
    {
        image.SetAlpha();
        unsigned char* alpha = image.GetAlpha();
        memcpy( alpha, GetAlpha(), M_IMGDATA->m_width*M_IMGDATA->m_height );
    }

    imgData->m_optionNames = M_IMGDATA->m_optionNames;
    imgData->m_optionValues = M_IMGDATA->m_optionValues;

    return image;
}

wxImage wxImage::ShrinkBy( int xFactor , int yFactor ) const
{
    if( xFactor == 1 && yFactor == 1 )
        return Copy() ;

    wxImage image;

    wxCHECK_MSG( Ok(), image, wxT("invalid image") );

    // can't scale to/from 0 size
    wxCHECK_MSG( (xFactor > 0) && (yFactor > 0), image,
                 wxT("invalid new image size") );

    long old_height = M_IMGDATA->m_height,
         old_width  = M_IMGDATA->m_width;

    wxCHECK_MSG( (old_height > 0) && (old_width > 0), image,
                 wxT("invalid old image size") );

    long width = old_width / xFactor ;
    long height = old_height / yFactor ;

    image.Create( width, height, false );

    char unsigned *data = image.GetData();

    wxCHECK_MSG( data, image, wxT("unable to create image") );

    bool hasMask = false ;
    unsigned char maskRed = 0;
    unsigned char maskGreen = 0;
    unsigned char maskBlue =0 ;

    unsigned char *source_data = M_IMGDATA->m_data;
    unsigned char *target_data = data;
    unsigned char *source_alpha = 0 ;
    unsigned char *target_alpha = 0 ;
    if (M_IMGDATA->m_hasMask)
    {
        hasMask = true ;
        maskRed = M_IMGDATA->m_maskRed;
        maskGreen = M_IMGDATA->m_maskGreen;
        maskBlue =M_IMGDATA->m_maskBlue ;

        image.SetMaskColour( M_IMGDATA->m_maskRed,
                             M_IMGDATA->m_maskGreen,
                             M_IMGDATA->m_maskBlue );
    }
    else
    {
        source_alpha = M_IMGDATA->m_alpha ;
        if ( source_alpha )
        {
            image.SetAlpha() ;
            target_alpha = image.GetAlpha() ;
        }
    }

    for (long y = 0; y < height; y++)
    {
        for (long x = 0; x < width; x++)
        {
            unsigned long avgRed = 0 ;
            unsigned long avgGreen = 0;
            unsigned long avgBlue = 0;
            unsigned long avgAlpha = 0 ;
            unsigned long counter = 0 ;
            // determine average
            for ( int y1 = 0 ; y1 < yFactor ; ++y1 )
            {
                long y_offset = (y * yFactor + y1) * old_width;
                for ( int x1 = 0 ; x1 < xFactor ; ++x1 )
                {
                    unsigned char *pixel = source_data + 3 * ( y_offset + x * xFactor + x1 ) ;
                    unsigned char red = pixel[0] ;
                    unsigned char green = pixel[1] ;
                    unsigned char blue = pixel[2] ;
                    unsigned char alpha = 255  ;
                    if ( source_alpha )
                        alpha = *(source_alpha + y_offset + x * xFactor + x1) ;
                    if ( !hasMask || red != maskRed || green != maskGreen || blue != maskBlue )
                    {
                        if ( alpha > 0 )
                        {
                            avgRed += red ;
                            avgGreen += green ;
                            avgBlue += blue ;
                        }
                        avgAlpha += alpha ;
                        counter++ ;
                    }
                }
            }
            if ( counter == 0 )
            {
                *(target_data++) = M_IMGDATA->m_maskRed ;
                *(target_data++) = M_IMGDATA->m_maskGreen ;
                *(target_data++) = M_IMGDATA->m_maskBlue ;
            }
            else
            {
                if ( source_alpha )
                    *(target_alpha++) = (unsigned char)(avgAlpha / counter ) ;
                *(target_data++) = (unsigned char)(avgRed / counter);
                *(target_data++) = (unsigned char)(avgGreen / counter);
                *(target_data++) = (unsigned char)(avgBlue / counter);
            }
        }
    }

    // In case this is a cursor, make sure the hotspot is scalled accordingly:
    if ( HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_X) )
        image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X,
                (GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X))/xFactor);
    if ( HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y) )
        image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y,
                (GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y))/yFactor);

    return image;
}

wxImage wxImage::Scale( int width, int height ) const
{
    wxImage image;

    wxCHECK_MSG( Ok(), image, wxT("invalid image") );

    // can't scale to/from 0 size
    wxCHECK_MSG( (width > 0) && (height > 0), image,
                 wxT("invalid new image size") );

    long old_height = M_IMGDATA->m_height,
         old_width  = M_IMGDATA->m_width;
    wxCHECK_MSG( (old_height > 0) && (old_width > 0), image,
                 wxT("invalid old image size") );

    if ( old_width % width == 0 && old_width >= width &&
        old_height % height == 0 && old_height >= height )
    {
        return ShrinkBy( old_width / width , old_height / height ) ;
    }
    image.Create( width, height, false );

    unsigned char *data = image.GetData();

    wxCHECK_MSG( data, image, wxT("unable to create image") );

    unsigned char *source_data = M_IMGDATA->m_data;
    unsigned char *target_data = data;
    unsigned char *source_alpha = 0 ;
    unsigned char *target_alpha = 0 ;

    if (M_IMGDATA->m_hasMask)
    {
        image.SetMaskColour( M_IMGDATA->m_maskRed,
                             M_IMGDATA->m_maskGreen,
                             M_IMGDATA->m_maskBlue );
    }
    else
    {
        source_alpha = M_IMGDATA->m_alpha ;
        if ( source_alpha )
        {
            image.SetAlpha() ;
            target_alpha = image.GetAlpha() ;
        }
    }

    long x_delta = (old_width<<16) / width;
    long y_delta = (old_height<<16) / height;

    unsigned char* dest_pixel = target_data;

    long y = 0;
    for ( long j = 0; j < height; j++ )
        {
        unsigned char* src_line = &source_data[(y>>16)*old_width*3];
        unsigned char* src_alpha_line = source_alpha ? &source_alpha[(y>>16)*old_width] : 0 ;

        long x = 0;
        for ( long i = 0; i < width; i++ )
        {
             unsigned char* src_pixel = &src_line[(x>>16)*3];
             unsigned char* src_alpha_pixel = source_alpha ? &src_alpha_line[(x>>16)] : 0 ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -