Пример #1
0
//
// ReadImage()
// read a PNG format image into memory, returning the image itself
// This version reads a subpart of an image
//
CImage* CImageIOPng::ReadImage(CNcbiIstream& istr,
                               size_t x, size_t y, size_t w, size_t h)
{
    png_structp png_ptr  = NULL;
    png_infop   info_ptr = NULL;
    png_infop   end_ptr  = NULL;
    CRef<CImage> image;

    try {
        // create our PNG structures
        s_PngReadInit(png_ptr, info_ptr, end_ptr);

        // begin reading our image
        png_set_read_fn(png_ptr, &istr, s_PngRead);
        png_read_info(png_ptr, info_ptr);

        // store and validate our image's parameters
        size_t width  = 0;
        size_t height = 0;
        size_t depth  = 0;
        s_PngReadValidate(png_ptr, info_ptr, width, height, depth,
                          x, y, w, h);

        // allocate our image
        image.Reset(new CImage(w, h, depth));
        unsigned char* to_data   = image->SetData();
        size_t         to_stride = image->GetWidth() * image->GetDepth();
        size_t         to_offs   = x * image->GetDepth();

        // allocate a scanline for this image
        vector<unsigned char> row(width * depth);
        unsigned char* row_ptr = &row[0];

        size_t i;

        // read up to our starting scan line
        for (i = 0;  i < y;  ++i) {
            png_read_row(png_ptr, row_ptr, NULL);
        }

        // read and convert the scanlines of interest
        for ( ;  i < y + h;  ++i) {
            png_read_row(png_ptr, row_ptr, NULL);
            memcpy(to_data, row_ptr + to_offs, to_stride);
            to_data += to_stride;
        }

        /**
        // read the rest of the image (do we need this?)
        for ( ;  i < height;  ++i) {
            png_read_row(png_ptr, row_ptr, NULL);
        }

        // read the end pointer
        png_read_end(png_ptr, end_ptr);
        **/

        // close and return
        s_PngReadFinalize(png_ptr, info_ptr, end_ptr);
    }
    catch (...) {
        // destroy everything
        s_PngReadFinalize(png_ptr, info_ptr, end_ptr);

        // rethrow
        throw;
    }

    return image.Release();
}