imagpcx.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 508 行 · 第 1/2 页

CPP
508
字号
                for (i = 0; i < width; i++)
                {
                    *(dst++) = p[i];
                    *(dst++) = p[i + bytesperline];
                    *(dst++) = p[i + 2 * bytesperline];
                }
                break;
            }
        }
    }

    free(p);

    // For 8 bit images, we read the palette, and then do a second
    // pass replacing indexes with their RGB values;

    if (format == wxPCX_8BIT)
    {
        unsigned char index;

        if (stream.GetC() != 12)
            return wxPCX_INVFORMAT;

        stream.Read(pal, 768);

        p = image->GetData();
        for (unsigned long k = height * width; k; k--)
        {
            index = *p;
            *(p++) = pal[3 * index];
            *(p++) = pal[3 * index + 1];
            *(p++) = pal[3 * index + 2];
        }

#if wxUSE_PALETTE
        unsigned char r[256];
        unsigned char g[256];
        unsigned char b[256];
        for (i = 0; i < 256; i++)
        {
            r[i] = pal[3*i + 0];
            g[i] = pal[3*i + 1];
            b[i] = pal[3*i + 2];
        }
        image->SetPalette(wxPalette(256, r, g, b));
#endif // wxUSE_PALETTE
    }

    return wxPCX_OK;
}

// SavePCX:
//  Saves a PCX file into the wxImage object pointed by image.
//  Returns wxPCX_OK on success, or an error code otherwise
//  (see above for error codes). Will try to save as 8-bit
//  PCX if possible, and then fall back to 24-bit if there
//  are more than 256 different colours.
//
int SavePCX(wxImage *image, wxOutputStream& stream)
{
    unsigned char hdr[128];         // PCX header
    unsigned char pal[768];         // palette for 8 bit images
    unsigned char *p;               // space to store one scanline
    unsigned char *src;             // pointer into wxImage data
    unsigned int width, height;     // size of the image
    unsigned int bytesperline;      // bytes per line (each plane)
    unsigned char nplanes = 3;      // number of planes
    int format = wxPCX_24BIT;       // image format (8 bit, 24 bit)
    wxImageHistogram histogram;     // image histogram
    unsigned long key;              // key in the hashtable
    unsigned int i;

    // See if we can save as 8 bit.

    if (image->CountColours(256) <= 256)
    {
        image->ComputeHistogram(histogram);
        format = wxPCX_8BIT;
        nplanes = 1;
    }

    // Get image dimensions, calculate bytesperline (must be even,
    // according to PCX specs) and allocate space for one complete
    // scanline.

    if (!image->Ok())
        return wxPCX_INVFORMAT;

    width = image->GetWidth();
    height = image->GetHeight();
    bytesperline = width;
    if (bytesperline % 2)
        bytesperline++;

    if ((p = (unsigned char *) malloc(bytesperline * nplanes)) == NULL)
        return wxPCX_MEMERR;

    // Build header data and write it to the stream. Initially,
    // set all bytes to zero (most values default to zero).

    memset(hdr, 0, sizeof(hdr));

    hdr[HDR_MANUFACTURER]     = 10;
    hdr[HDR_VERSION]          = 5;
    hdr[HDR_ENCODING]         = 1;
    hdr[HDR_NPLANES]          = nplanes;
    hdr[HDR_BITSPERPIXEL]     = 8;
    hdr[HDR_BYTESPERLINE]     = (unsigned char)(bytesperline % 256);
    hdr[HDR_BYTESPERLINE + 1] = (unsigned char)(bytesperline / 256);
    hdr[HDR_XMAX]             = (unsigned char)((width - 1)  % 256);
    hdr[HDR_XMAX + 1]         = (unsigned char)((width - 1)  / 256);
    hdr[HDR_YMAX]             = (unsigned char)((height - 1) % 256);
    hdr[HDR_YMAX + 1]         = (unsigned char)((height - 1) / 256);
    hdr[HDR_PALETTEINFO]      = 1;

    stream.Write(hdr, 128);

    // Encode image data line by line and write it to the stream

    src = image->GetData();

    for (; height; height--)
    {
        switch (format)
        {
            case wxPCX_8BIT:
            {
                unsigned char r, g, b;

                for (i = 0; i < width; i++)
                {
                    r = *(src++);
                    g = *(src++);
                    b = *(src++);
                    key = (r << 16) | (g << 8) | b;

                    p[i] = (unsigned char)histogram[key].index;
                }
                break;
            }
            case wxPCX_24BIT:
            {
                for (i = 0; i < width; i++)
                {
                    p[i] = *(src++);
                    p[i + bytesperline] = *(src++);
                    p[i + 2 * bytesperline] = *(src++);
                }
                break;
            }
        }

        RLEencode(p, bytesperline * nplanes, stream);
    }

    free(p);

    // For 8 bit images, build the palette and write it to the stream:
    if (format == wxPCX_8BIT)
    {
        // zero unused colours
        memset(pal, 0, sizeof(pal));

        unsigned long index;

        for (wxImageHistogram::iterator entry = histogram.begin();
             entry != histogram.end(); ++entry )
        {
            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.Write(pal, 768);
    }

    return wxPCX_OK;
}

//-----------------------------------------------------------------------------
// wxPCXHandler
//-----------------------------------------------------------------------------

bool wxPCXHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int WXUNUSED(index) )
{
    int error;

    if (!CanRead(stream))
    {
        if (verbose)
            wxLogError(_("PCX: this is not a PCX file."));

        return false;
    }

    image->Destroy();

    if ((error = ReadPCX(image, stream)) != wxPCX_OK)
    {
        if (verbose)
        {
            switch (error)
            {
                case wxPCX_INVFORMAT: wxLogError(_("PCX: image format unsupported")); break;
                case wxPCX_MEMERR:    wxLogError(_("PCX: couldn't allocate memory")); break;
                case wxPCX_VERERR:    wxLogError(_("PCX: version number too low")); break;
                default:              wxLogError(_("PCX: unknown error !!!"));
            }
        }
        image->Destroy();
        return false;
    }

    return true;
}

bool wxPCXHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbose )
{
    int error;

    if ((error = SavePCX(image, stream)) != wxPCX_OK)
    {
        if (verbose)
        {
            switch (error)
            {
                case wxPCX_INVFORMAT: wxLogError(_("PCX: invalid image")); break;
                case wxPCX_MEMERR:    wxLogError(_("PCX: couldn't allocate memory")); break;
                default:              wxLogError(_("PCX: unknown error !!!"));
            }
        }
    }

    return (error == wxPCX_OK);
}

bool wxPCXHandler::DoCanRead( wxInputStream& stream )
{
    unsigned char c = stream.GetC();
    if ( !stream )
        return false;

    // not very safe, but this is all we can get from PCX header :-(
    return c == 10;
}

#endif // wxUSE_STREAMS

#endif // wxUSE_IMAGE && wxUSE_PCX

⌨️ 快捷键说明

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