imagbmp.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,492 行 · 第 1/4 页

CPP
1,492
字号

        // wxCountingOutputStream::Ok() always returns true for now and this
        // "if" provokes VC++ warnings in optimized build
#if 0
        if ( !cStream.Ok() )
        {
            if ( verbose )
                wxLogError(_("ICO: Error writing the image file!"));
            return false;
        }
#endif // 0

        offset = offset + sizeof(ICONDIRENTRY);

        icondirentry.bWidth = (wxUint8)image->GetWidth();
        icondirentry.bHeight = (wxUint8)(2 * image->GetHeight());
        icondirentry.bColorCount = 0;
        icondirentry.bReserved = 0;
        icondirentry.wPlanes = wxUINT16_SWAP_ON_BE(1);
        icondirentry.wBitCount = wxUINT16_SWAP_ON_BE(wxBMP_8BPP);
        if ( type == 2 /*CUR*/)
        {
            int hx = image->HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_X) ?
                         image->GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X) :
                         image->GetWidth() / 2;
            int hy = image->HasOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y) ?
                         image->GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y) :
                         image->GetHeight() / 2;

            // actually write the values of the hot spot here:
            icondirentry.wPlanes = wxUINT16_SWAP_ON_BE((wxUint16)hx);
            icondirentry.wBitCount = wxUINT16_SWAP_ON_BE((wxUint16)hy);
        }
        icondirentry.dwBytesInRes = wxUINT32_SWAP_ON_BE(Size);
        icondirentry.dwImageOffset = wxUINT32_SWAP_ON_BE(offset);

        // increase size to allow for the data written:
        offset += Size;

        // write to stream:
        stream.Write(&icondirentry.bWidth, sizeof(icondirentry.bWidth));
        stream.Write(&icondirentry.bHeight, sizeof(icondirentry.bHeight));
        stream.Write(&icondirentry.bColorCount, sizeof(icondirentry.bColorCount));
        stream.Write(&icondirentry.bReserved, sizeof(icondirentry.bReserved));
        stream.Write(&icondirentry.wPlanes, sizeof(icondirentry.wPlanes));
        stream.Write(&icondirentry.wBitCount, sizeof(icondirentry.wBitCount));
        stream.Write(&icondirentry.dwBytesInRes, sizeof(icondirentry.dwBytesInRes));
        stream.Write(&icondirentry.dwImageOffset, sizeof(icondirentry.dwImageOffset));
        if ( !stream.IsOk() )
        {
            if ( verbose )
                wxLogError(_("ICO: Error writing the image file!"));
            return false;
        }

        // actually save it:
        IsMask = false;
        bResult = SaveDib(image, stream, verbose, IsBmp, IsMask);
        if ( !bResult )
        {
            if ( verbose )
                wxLogError(_("ICO: Error writing the image file!"));
            return false;
        }
        IsMask = true;

        bResult = SaveDib(&mask, stream, verbose, IsBmp, IsMask);
        if ( !bResult )
        {
            if ( verbose )
                wxLogError(_("ICO: Error writing the image file!"));
            return false;
        }

    } // end of for loop

    return true;
}

bool wxICOHandler::LoadFile(wxImage *image, wxInputStream& stream,
                            bool verbose, int index)
{
    stream.SeekI(0);
    return DoLoadFile(image, stream, verbose, index);
}

bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream,
                            bool WXUNUSED(verbose), int index)
{
    bool bResult wxDUMMY_INITIALIZE(false);
    bool IsBmp = false;

    ICONDIR IconDir;

    wxFileOffset iPos = stream.TellI();
    stream.Read(&IconDir, sizeof(IconDir));
    wxUint16 nIcons = wxUINT16_SWAP_ON_BE(IconDir.idCount);
    // nType is 1 for Icons, 2 for Cursors:
    wxUint16 nType = wxUINT16_SWAP_ON_BE(IconDir.idType);

    // loop round the icons and choose the best one:
    ICONDIRENTRY *pIconDirEntry = new ICONDIRENTRY[nIcons];
    ICONDIRENTRY *pCurrentEntry = pIconDirEntry;
    int wMax = 0;
    int colmax = 0;
    int iSel = wxNOT_FOUND;

    for (int i = 0; i < nIcons; i++ )
    {
        stream.Read(pCurrentEntry, sizeof(ICONDIRENTRY));
        // bHeight and bColorCount are wxUint8
        if ( pCurrentEntry->bWidth >= wMax )
        {
            // see if we have more colors, ==0 indicates > 8bpp:
            if ( pCurrentEntry->bColorCount == 0 )
                pCurrentEntry->bColorCount = 255;
            if ( pCurrentEntry->bColorCount >= colmax )
            {
                iSel = i;
                wMax = pCurrentEntry->bWidth;
                colmax = pCurrentEntry->bColorCount;
            }
        }
        pCurrentEntry++;
    }

    if ( index != -1 )
    {
        // VS: Note that we *have* to run the loop above even if index != -1, because
        //     it reads ICONDIRENTRies.
        iSel = index;
    }

    if ( iSel == wxNOT_FOUND || iSel < 0 || iSel >= nIcons )
    {
        wxLogError(_("ICO: Invalid icon index."));
        bResult = false;
    }
    else
    {
        // seek to selected icon:
        pCurrentEntry = pIconDirEntry + iSel;
        stream.SeekI(iPos + wxUINT32_SWAP_ON_BE(pCurrentEntry->dwImageOffset), wxFromStart);
        bResult = LoadDib(image, stream, true, IsBmp);
        bool bIsCursorType = (this->GetType() == wxBITMAP_TYPE_CUR) || (this->GetType() == wxBITMAP_TYPE_ANI);
        if ( bResult && bIsCursorType && nType == 2 )
        {
            // it is a cursor, so let's set the hotspot:
            image->SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, wxUINT16_SWAP_ON_BE(pCurrentEntry->wPlanes));
            image->SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, wxUINT16_SWAP_ON_BE(pCurrentEntry->wBitCount));
        }
    }
    delete[] pIconDirEntry;
    return bResult;
}

int wxICOHandler::GetImageCount(wxInputStream& stream)
{
    ICONDIR IconDir;
    wxFileOffset iPos = stream.TellI();
    stream.SeekI(0);
    stream.Read(&IconDir, sizeof(IconDir));
    wxUint16 nIcons = wxUINT16_SWAP_ON_BE(IconDir.idCount);
    stream.SeekI(iPos);
    return (int)nIcons;
}

bool wxICOHandler::DoCanRead(wxInputStream& stream)
{
    stream.SeekI(0);
    unsigned char hdr[4];
    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
        return false;

    // hdr[2] is one for an icon and two for a cursor
    return hdr[0] == '\0' && hdr[1] == '\0' && hdr[2] == '\1' && hdr[3] == '\0';
}

#endif // wxUSE_STREAMS


//-----------------------------------------------------------------------------
// wxCURHandler
//-----------------------------------------------------------------------------

IMPLEMENT_DYNAMIC_CLASS(wxCURHandler, wxICOHandler)

#if wxUSE_STREAMS

bool wxCURHandler::DoCanRead(wxInputStream& stream)
{
    stream.SeekI(0);
    unsigned char hdr[4];
    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
        return false;

    // hdr[2] is one for an icon and two for a cursor
    return hdr[0] == '\0' && hdr[1] == '\0' && hdr[2] == '\2' && hdr[3] == '\0';
}

#endif // wxUSE_STREAMS

//-----------------------------------------------------------------------------
// wxANIHandler
//-----------------------------------------------------------------------------

IMPLEMENT_DYNAMIC_CLASS(wxANIHandler, wxCURHandler)

#if wxUSE_STREAMS

bool wxANIHandler::LoadFile(wxImage *image, wxInputStream& stream,
                            bool verbose, int index)
{
    wxInt32 FCC1, FCC2;
    wxUint32 datalen;

    wxInt32 riff32;
    memcpy( &riff32, "RIFF", 4 );
    wxInt32 list32;
    memcpy( &list32, "LIST", 4 );
    wxInt32 ico32;
    memcpy( &ico32, "icon", 4 );
    int iIcon = 0;

    stream.SeekI(0);
    stream.Read(&FCC1, 4);
    if ( FCC1 != riff32 )
        return false;

    // we have a riff file:
    while (stream.IsOk())
    {
        // we always have a data size
        stream.Read(&datalen, 4);
        datalen = wxINT32_SWAP_ON_BE(datalen) ;
        //data should be padded to make even number of bytes
        if (datalen % 2 == 1) datalen ++ ;
        //now either data or a FCC
        if ( (FCC1 == riff32) || (FCC1 == list32) )
        {
            stream.Read(&FCC2, 4);
        }
        else
        {
            if (FCC1 == ico32 && iIcon >= index)
            {
                return DoLoadFile(image, stream, verbose, -1);
            }
            else
            {
                stream.SeekI(stream.TellI() + datalen);
                if ( FCC1 == ico32 )
                    iIcon ++;
            }
        }

        // try to read next data chunk:
        stream.Read(&FCC1, 4);
    }
    return false;
}

bool wxANIHandler::DoCanRead(wxInputStream& stream)
{
    wxInt32 FCC1, FCC2;
    wxUint32 datalen ;

    wxInt32 riff32;
    memcpy( &riff32, "RIFF", 4 );
    wxInt32 list32;
    memcpy( &list32, "LIST", 4 );
    wxInt32 ico32;
    memcpy( &ico32, "icon", 4 );
    wxInt32 anih32;
    memcpy( &anih32, "anih", 4 );

    stream.SeekI(0);
    if ( !stream.Read(&FCC1, 4) )
        return false;

    if ( FCC1 != riff32 )
        return false;

    // we have a riff file:
    while ( stream.IsOk() )
    {
        if ( FCC1 == anih32 )
            return true;
        // we always have a data size:
        stream.Read(&datalen, 4);
        datalen = wxINT32_SWAP_ON_BE(datalen) ;
        //data should be padded to make even number of bytes
        if (datalen % 2 == 1) datalen ++ ;
        // now either data or a FCC:
        if ( (FCC1 == riff32) || (FCC1 == list32) )
        {
            stream.Read(&FCC2, 4);
        }
        else
        {
            stream.SeekI(stream.TellI() + datalen);
        }

        // try to read next data chunk:
        if ( !stream.Read(&FCC1, 4) )
        {
            // reading failed -- either EOF or IO error, bail out anyhow
            return false;
        }
    }

    return false;
}

int wxANIHandler::GetImageCount(wxInputStream& stream)
{
    wxInt32 FCC1, FCC2;
    wxUint32 datalen ;

    wxInt32 riff32;
    memcpy( &riff32, "RIFF", 4 );
    wxInt32 list32;
    memcpy( &list32, "LIST", 4 );
    wxInt32 ico32;
    memcpy( &ico32, "icon", 4 );
    wxInt32 anih32;
    memcpy( &anih32, "anih", 4 );

    stream.SeekI(0);
    stream.Read(&FCC1, 4);
    if ( FCC1 != riff32 )
        return wxNOT_FOUND;

    // we have a riff file:
    while ( stream.IsOk() )
    {
        // we always have a data size:
        stream.Read(&datalen, 4);
        datalen = wxINT32_SWAP_ON_BE(datalen) ;
        //data should be padded to make even number of bytes
        if (datalen % 2 == 1) datalen ++ ;
        // now either data or a FCC:
        if ( (FCC1 == riff32) || (FCC1 == list32) )
        {
            stream.Read(&FCC2, 4);
        }
        else
        {
            if ( FCC1 == anih32 )
            {
                wxUint32 *pData = new wxUint32[datalen/4];
                stream.Read(pData, datalen);
                int nIcons = wxINT32_SWAP_ON_BE(*(pData + 1));
                delete[] pData;
                return nIcons;
            }
            else
                stream.SeekI(stream.TellI() + datalen);
        }

        // try to read next data chunk:
        stream.Read(&FCC1, 4);
    }

    return wxNOT_FOUND;
}

#endif // wxUSE_STREAMS

#endif // wxUSE_ICO_CUR

#endif // wxUSE_IMAGE

⌨️ 快捷键说明

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