imagbmp.cpp

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

CPP
1,492
字号
                                for (int k = 0; k < absolute; k++)
                                {
                                    linepos++;
                                    aByte = stream.GetC();
                                    ptr[poffset    ] = cmap[aByte].r;
                                    ptr[poffset + 1] = cmap[aByte].g;
                                    ptr[poffset + 2] = cmap[aByte].b;
                                    column++;
                                }
                                if ( absolute & 0x01 )
                                    aByte = stream.GetC();
                            }
                        }
                        else
                        {
                            for ( int l = 0; l < first && column < width; l++ )
                            {
                                ptr[poffset    ] = cmap[aByte].r;
                                ptr[poffset + 1] = cmap[aByte].g;
                                ptr[poffset + 2] = cmap[aByte].b;
                                column++;
                                linepos++;
                            }
                        }
                    }
                    else
                    {
                        ptr[poffset    ] = cmap[aByte].r;
                        ptr[poffset + 1] = cmap[aByte].g;
                        ptr[poffset + 2] = cmap[aByte].b;
                        column++;
                        // linepos += size;    seems to be wrong, RR
                    }
                }
            }
            else if ( bpp == 24 )
            {
                stream.Read(bbuf, 3);
                linepos += 3;
                ptr[poffset    ] = (unsigned char)bbuf[2];
                ptr[poffset + 1] = (unsigned char)bbuf[1];
                ptr[poffset + 2] = (unsigned char)bbuf[0];
                column++;
            }
            else if ( bpp == 16 )
            {
                unsigned char temp;
                stream.Read(&aWord, 2);
                aWord = wxUINT16_SWAP_ON_BE(aWord);
                linepos += 2;
                /* use the masks and calculated amonut of shift
                   to retrieve the color data out of the word.  Then
                   shift it left by (8 - number of bits) such that
                   the image has the proper dynamic range */
                temp = (unsigned char)((aWord & rmask) >> rshift << (8-rbits));
                ptr[poffset] = temp;
                temp = (unsigned char)((aWord & gmask) >> gshift << (8-gbits));
                ptr[poffset + 1] = temp;
                temp = (unsigned char)((aWord & bmask) >> bshift << (8-bbits));
                ptr[poffset + 2] = temp;
                column++;
            }
            else
            {
                unsigned char temp;
                stream.Read(&aDword, 4);
                aDword = wxINT32_SWAP_ON_BE(aDword);
                linepos += 4;
                temp = (unsigned char)((aDword & rmask) >> rshift);
                ptr[poffset] = temp;
                temp = (unsigned char)((aDword & gmask) >> gshift);
                ptr[poffset + 1] = temp;
                temp = (unsigned char)((aDword & bmask) >> bshift);
                ptr[poffset + 2] = temp;
                column++;
            }
        }
        while ( (linepos < linesize) && (comp != 1) && (comp != 2) )
        {
            stream.Read(&aByte, 1);
            linepos += 1;
            if ( !stream )
                break;
        }
    }

    delete[] cmap;

    image->SetMask(false);

    const wxStreamError err = stream.GetLastError();
    return err == wxSTREAM_NO_ERROR || err == wxSTREAM_EOF;
}

bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream,
                           bool verbose, bool IsBmp)
{
    wxUint16        aWord;
    wxInt32         dbuf[4];
    wxInt8          bbuf[4];

    wxFileOffset offset = 0; // keep gcc quiet
    if ( IsBmp )
    {
        // read the header off the .BMP format file

        offset = stream.TellI();
        if (offset == wxInvalidOffset)
            offset = 0;

        stream.Read(bbuf, 2);
        stream.Read(dbuf, 16);
    }
    else
    {
        stream.Read(dbuf, 4);
    }
    #if 0 // unused
        wxInt32 size = wxINT32_SWAP_ON_BE(dbuf[0]);
    #endif
    offset = offset + wxINT32_SWAP_ON_BE(dbuf[2]);

    stream.Read(dbuf, 4 * 2);
    int width = wxINT32_SWAP_ON_BE((int)dbuf[0]);
    int height = wxINT32_SWAP_ON_BE((int)dbuf[1]);
    if ( !IsBmp)height = height  / 2; // for icons divide by 2

    if ( width > 32767 )
    {
        if (verbose)
            wxLogError( _("DIB Header: Image width > 32767 pixels for file.") );
        return false;
    }
    if ( height > 32767 )
    {
        if (verbose)
            wxLogError( _("DIB Header: Image height > 32767 pixels for file.") );
        return false;
    }

    stream.Read(&aWord, 2);
    /*
            TODO
            int planes = (int)wxUINT16_SWAP_ON_BE( aWord );
        */
    stream.Read(&aWord, 2);
    int bpp = wxUINT16_SWAP_ON_BE((int)aWord);
    if ( bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32 )
    {
        if (verbose)
            wxLogError( _("DIB Header: Unknown bitdepth in file.") );
        return false;
    }

    stream.Read(dbuf, 4 * 4);
    int comp = wxINT32_SWAP_ON_BE((int)dbuf[0]);
    if ( comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 &&
         comp != BI_BITFIELDS )
    {
        if (verbose)
            wxLogError( _("DIB Header: Unknown encoding in file.") );
        return false;
    }

    stream.Read(dbuf, 4 * 2);
    int ncolors = wxINT32_SWAP_ON_BE( (int)dbuf[0] );
    if (ncolors == 0)
        ncolors = 1 << bpp;
    /* some more sanity checks */
    if (((comp == BI_RLE4) && (bpp != 4)) ||
        ((comp == BI_RLE8) && (bpp != 8)) ||
        ((comp == BI_BITFIELDS) && (bpp != 16 && bpp != 32)))
    {
        if (verbose)
            wxLogError( _("DIB Header: Encoding doesn't match bitdepth.") );
        return false;
    }

    //read DIB; this is the BMP image or the XOR part of an icon image
    if ( !DoLoadDib(image, width, height, bpp, ncolors, comp, offset, stream,
                    verbose, IsBmp, true) )
    {
        if (verbose)
            wxLogError( _("Error in reading image DIB .") );
        return false;
    }

    if ( !IsBmp )
    {
        //read Icon mask which is monochrome
        //there is no palette, so we will create one
        wxImage mask;
        if ( !DoLoadDib(&mask, width, height, 1, 2, BI_RGB, offset, stream,
                        verbose, IsBmp, false) )
        {
            if (verbose)
                wxLogError( _("ICO: Error in reading mask DIB.") );
            return false;
        }
        image->SetMaskFromImage(mask, 255, 255, 255);

    }

    return true;
}

bool wxBMPHandler::LoadFile(wxImage *image, wxInputStream& stream,
                            bool verbose, int WXUNUSED(index))
{
    // Read a single DIB fom the file:
    return LoadDib(image, stream, verbose, true/*isBmp*/);
}

bool wxBMPHandler::DoCanRead(wxInputStream& stream)
{
    unsigned char hdr[2];

    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
        return false;

    // do we have the BMP file signature?
    return hdr[0] == 'B' && hdr[1] == 'M';
}

#endif // wxUSE_STREAMS


#if wxUSE_ICO_CUR
//-----------------------------------------------------------------------------
// wxICOHandler
//-----------------------------------------------------------------------------

IMPLEMENT_DYNAMIC_CLASS(wxICOHandler, wxBMPHandler)

#if wxUSE_STREAMS

struct ICONDIRENTRY
{
    wxUint8         bWidth;               // Width of the image
    wxUint8         bHeight;              // Height of the image (times 2)
    wxUint8         bColorCount;          // Number of colors in image (0 if >=8bpp)
    wxUint8         bReserved;            // Reserved

    // these two are different in icons and cursors:
                                          // icon           or  cursor
    wxUint16        wPlanes;              // Color Planes   or  XHotSpot
    wxUint16        wBitCount;            // Bits per pixel or  YHotSpot

    wxUint32        dwBytesInRes;         // how many bytes in this resource?
    wxUint32        dwImageOffset;        // where in the file is this image
};

struct ICONDIR
{
    wxUint16     idReserved;   // Reserved
    wxUint16     idType;       // resource type (1 for icons, 2 for cursors)
    wxUint16     idCount;      // how many images?
};


bool wxICOHandler::SaveFile(wxImage *image,
                            wxOutputStream& stream,
                            bool verbose)

{
    //sanity check; icon must be less than 127 pixels high and 255 wide
    if ( image->GetHeight () > 127 )
    {
        if ( verbose )
            wxLogError(_("ICO: Image too tall for an icon."));
        return false;
    }
    if ( image->GetWidth () > 255 )
    {
        if ( verbose )
            wxLogError(_("ICO: Image too wide for an icon."));
        return false;
    }

    const int images = 1; // only generate one image

    // VS: This is a hack of sort - since ICO and CUR files are almost
    //     identical, we have all the meat in wxICOHandler and check for
    //     the actual (handler) type when the code has to distinguish between
    //     the two formats
    int type = (this->GetType() == wxBITMAP_TYPE_CUR) ? 2 : 1;

    // write a header, (ICONDIR)
    // Calculate the header size
    wxUint32 offset = 3 * sizeof(wxUint16);

    ICONDIR IconDir;
    IconDir.idReserved = 0;
    IconDir.idType = wxUINT16_SWAP_ON_BE((wxUint16)type);
    IconDir.idCount = wxUINT16_SWAP_ON_BE((wxUint16)images);
    stream.Write(&IconDir.idReserved, sizeof(IconDir.idReserved));
    stream.Write(&IconDir.idType, sizeof(IconDir.idType));
    stream.Write(&IconDir.idCount, sizeof(IconDir.idCount));
    if ( !stream.IsOk() )
    {
        if ( verbose )
            wxLogError(_("ICO: Error writing the image file!"));
        return false;
    }

    // for each iamage write a description ICONDIRENTRY:
    ICONDIRENTRY icondirentry;
    for (int img = 0; img < images; img++)
    {
        wxImage mask;

        if ( image->HasMask() )
        {
            // make another image with black/white:
            mask = image->ConvertToMono (image->GetMaskRed(), image->GetMaskGreen(), image->GetMaskBlue() );

            // now we need to change the masked regions to black:
            unsigned char r = image->GetMaskRed();
            unsigned char g = image->GetMaskGreen();
            unsigned char b = image->GetMaskBlue();
            if ( (r != 0) || (g != 0) || (b != 0) )
            {
                // Go round and apply black to the masked bits:
                int i, j;
                for (i = 0; i < mask.GetWidth(); i++)
                {
                    for (j = 0; j < mask.GetHeight(); j++)
                    {
                        if ((r == mask.GetRed(i, j)) &&
                            (g == mask.GetGreen(i, j))&&
                            (b == mask.GetBlue(i, j)) )
                                image->SetRGB(i, j, 0, 0, 0 );
                    }
                }
            }
        }
        else
        {
            // just make a black mask all over:
            mask = image->Copy();
            int i, j;
            for (i = 0; i < mask.GetWidth(); i++)
                for (j = 0; j < mask.GetHeight(); j++)
                    mask.SetRGB(i, j, 0, 0, 0 );
        }
        // Set the formats for image and mask
        // (Windows never saves with more than 8 colors):
        image->SetOption(wxIMAGE_OPTION_BMP_FORMAT, wxBMP_8BPP);

        // monochome bitmap:
        mask.SetOption(wxIMAGE_OPTION_BMP_FORMAT, wxBMP_1BPP_BW);
        bool IsBmp = false;
        bool IsMask = false;

        //calculate size and offset of image and mask
        wxCountingOutputStream cStream;
        bool bResult = SaveDib(image, cStream, verbose, IsBmp, IsMask);
        if ( !bResult )
        {
            if ( verbose )
                wxLogError(_("ICO: Error writing the image file!"));
            return false;
        }
        IsMask = true;

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

⌨️ 快捷键说明

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