Пример #1
0
CPLErr GDALWMSRasterBand::ZeroBlock(int x, int y, int to_buffer_band, void *buffer) {
    CPLErr ret = CE_None;

    for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
        if (ret == CE_None) {
            void *p = NULL;
            GDALRasterBlock *b = NULL;
            if ((buffer != NULL) && (ib == to_buffer_band)) {
                p = buffer;
            } else {
                GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
                if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
                if (!band->IsBlockInCache(x, y)) {
                    b = band->GetLockedBlockRef(x, y, true);
                    if (b != NULL) {
                        p = b->GetDataRef();
                        if (p == NULL) {
                          CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: GetDataRef returned NULL.");
                          ret = CE_Failure;
                        }
                    }
                }
            }
            if (p != NULL) {
                unsigned char *b = reinterpret_cast<unsigned char *>(p);
                int block_size = nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
                for (int i = 0; i < block_size; ++i) b[i] = 0;
            }
            if (b != NULL) {
                b->DropLock();
            }
        }
    }

    return ret;
}
Пример #2
0
CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by0, int bx1, int by1, int advise_read) {
    CPLErr ret = CE_None;
    int i;

    int max_request_count = (bx1 - bx0 + 1) * (by1 - by0 + 1);
    int request_count = 0;
    CPLHTTPRequest *download_requests = NULL;
    GDALWMSCache *cache = m_parent_dataset->m_cache;
    struct BlockXY {
        int x, y;
    } *download_blocks = NULL;
    if (!m_parent_dataset->m_offline_mode) {
        download_requests = new CPLHTTPRequest[max_request_count];
        download_blocks = new BlockXY[max_request_count];
    }

    char **http_request_opts = NULL;
    if (m_parent_dataset->m_http_timeout != -1) {
	CPLString http_request_optstr;
        http_request_optstr.Printf("TIMEOUT=%d", m_parent_dataset->m_http_timeout);
        http_request_opts = CSLAddString(http_request_opts, http_request_optstr.c_str());
    }
    for (int iy = by0; iy <= by1; ++iy) {
        for (int ix = bx0; ix <= bx1; ++ix) {
            bool need_this_block = false;
            if (!advise_read) {
                for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
                    if ((ix == x) && (iy == y) && (ib == nBand)) {
                        need_this_block = true;
                    } else {
                        GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
                        if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
                        if (!band->IsBlockInCache(ix, iy)) need_this_block = true;
                    }
                }
            } else {
                need_this_block = true;
            }
            CPLString url;
            if (need_this_block) {
                CPLString file_name;
                AskMiniDriverForBlock(&url, ix, iy);
                if ((cache != NULL) && (cache->Read(url.c_str(), &file_name) == CE_None)) {
                    if (advise_read) {
                        need_this_block = false;
                    } else {
                        void *p = 0;
                        if ((ix == x) && (iy == y)) p = buffer;
                        if (ReadBlockFromFile(ix, iy, file_name.c_str(), nBand, p, 0) == CE_None) need_this_block = false;
                    }
                }
            }
            if (need_this_block) {
                if (m_parent_dataset->m_offline_mode) {
                    if (!advise_read) {
                        void *p = 0;
                        if ((ix == x) && (iy == y)) p = buffer;
                        if (ZeroBlock(ix, iy, nBand, p) != CE_None) {
                            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
                            ret = CE_Failure;
                        }
                    }
                } else {
                    CPLHTTPInitializeRequest(&download_requests[request_count], url.c_str(), http_request_opts);
                    download_blocks[request_count].x = ix;
                    download_blocks[request_count].y = iy;
                    ++request_count;
                }
            }
        }
    }
    if (http_request_opts != NULL) {
        CSLDestroy(http_request_opts);
    }

    if (request_count > 0) {
        char **opts = NULL;
        CPLString optstr;
        if (m_parent_dataset->m_http_max_conn != -1) {
            optstr.Printf("MAXCONN=%d", m_parent_dataset->m_http_max_conn);
            opts = CSLAddString(opts, optstr.c_str());
        }
        if (CPLHTTPFetchMulti(download_requests, request_count, opts) != CE_None) {
            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: CPLHTTPFetchMulti failed.");
            ret = CE_Failure;
        }
        if (opts != NULL) {
            CSLDestroy(opts);
        }
    }

    for (i = 0; i < request_count; ++i) {
        if (ret == CE_None) {
            if ((download_requests[i].nStatus == 200) && (download_requests[i].pabyData != NULL) && (download_requests[i].nDataLen > 0)) {
                CPLString file_name(BufferToVSIFile(download_requests[i].pabyData, download_requests[i].nDataLen));
                if (file_name.size() > 0) {
                    /* check for error xml */
                    if (download_requests[i].nDataLen >= 20) {
                        const char *download_data = reinterpret_cast<char *>(download_requests[i].pabyData);
                        if (EQUALN(download_data, "<?xml ", 6) 
                        || EQUALN(download_data, "<!DOCTYPE ", 10)
                        || EQUALN(download_data, "<ServiceException", 17)) {
                            if (ReportWMSException(file_name.c_str()) != CE_None) {
                                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned unknown exception.");
                            }
                            ret = CE_Failure;
                        }
                    }
                    if (ret == CE_None) {
                        if (advise_read && !m_parent_dataset->m_verify_advise_read) {
                            if (cache != NULL) {
                                cache->Write(download_requests[i].pszURL, file_name);
                            }
                        } else {
                            void *p = 0;
                            if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
                            if (ReadBlockFromFile(download_blocks[i].x, download_blocks[i].y, file_name.c_str(), nBand, p, advise_read) == CE_None) {
                                if (cache != NULL) {
                                    cache->Write(download_requests[i].pszURL, file_name);
                                }
                            } else {
                                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ReadBlockFromFile (%s) failed.",
                                         download_requests[i].pszURL);
                                ret = CE_Failure;
                            }
                        }
                    }
                    VSIUnlink(file_name.c_str());
                }
            } else if (download_requests[i].nStatus == 204) {
                if (!advise_read) {
                    void *p = 0;
                    if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
                    if (ZeroBlock(download_blocks[i].x, download_blocks[i].y, nBand, p) != CE_None) {
                        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
                        ret = CE_Failure;
                    }
                }
            } else {
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Unable to download block %d, %d.\n  URL: %s\n  HTTP status code: %d, error: %s.",
                    download_blocks[i].x, download_blocks[i].y, download_requests[i].pszURL, download_requests[i].nStatus, 
		    download_requests[i].pszError ? download_requests[i].pszError : "(null)");
                ret = CE_Failure;
            }
        }
        CPLHTTPCleanupRequest(&download_requests[i]);
    }
    if (!m_parent_dataset->m_offline_mode) {
        delete[] download_blocks;
        delete[] download_requests;
    }

    return ret;
}
Пример #3
0
CPLErr GDALWMSRasterBand::ReadBlockFromFile(int x, int y, const char *file_name, int to_buffer_band, void *buffer, int advise_read) {
    CPLErr ret = CE_None;
    GDALDataset *ds = 0;
    GByte *color_table = NULL;
    int i;

    //CPLDebug("WMS", "ReadBlockFromFile: to_buffer_band=%d, (x,y)=(%d, %d)", to_buffer_band, x, y);

    /* expected size */
    const int esx = MIN(MAX(0, (x + 1) * nBlockXSize), nRasterXSize) - MIN(MAX(0, x * nBlockXSize), nRasterXSize);
    const int esy = MIN(MAX(0, (y + 1) * nBlockYSize), nRasterYSize) - MIN(MAX(0, y * nBlockYSize), nRasterYSize);
    ds = reinterpret_cast<GDALDataset*>(GDALOpen(file_name, GA_ReadOnly));
    if (ds != NULL) {
        int sx = ds->GetRasterXSize();
        int sy = ds->GetRasterYSize();
        bool accepted_as_no_alpha = false;  // if the request is for 4 bands but the wms returns 3  
        /* Allow bigger than expected so pre-tiled constant size images work on corners */
        if ((sx > nBlockXSize) || (sy > nBlockYSize) || (sx < esx) || (sy < esy)) {
            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect size %d x %d of downloaded block, expected %d x %d, max %d x %d.",
                sx, sy, esx, esy, nBlockXSize, nBlockYSize);
            ret = CE_Failure;
        }
        if (ret == CE_None) {
            int nDSRasterCount = ds->GetRasterCount();
            if (nDSRasterCount != m_parent_dataset->nBands) {
                /* Maybe its an image with color table */
                bool accepted_as_ct = false;
                if ((eDataType == GDT_Byte) && (ds->GetRasterCount() == 1)) {
                    GDALRasterBand *rb = ds->GetRasterBand(1);
                    if (rb->GetRasterDataType() == GDT_Byte) {
                        GDALColorTable *ct = rb->GetColorTable();
                        if (ct != NULL) {
                            accepted_as_ct = true;
                            if (!advise_read) {
                                color_table = new GByte[256 * 4];
                                const int count = MIN(256, ct->GetColorEntryCount());
                                for (i = 0; i < count; ++i) {
                                    GDALColorEntry ce;
                                    ct->GetColorEntryAsRGB(i, &ce);
                                    color_table[i] = static_cast<GByte>(ce.c1);
                                    color_table[i + 256] = static_cast<GByte>(ce.c2);
                                    color_table[i + 512] = static_cast<GByte>(ce.c3);
                                    color_table[i + 768] = static_cast<GByte>(ce.c4);
                                }
                                for (i = count; i < 256; ++i) {
                                    color_table[i] = 0;
                                    color_table[i + 256] = 0;
                                    color_table[i + 512] = 0;
                                    color_table[i + 768] = 0;
                                }
                            }
                        }
                    }
                }

                if (nDSRasterCount == 4 && m_parent_dataset->nBands == 3)
                {
                    /* metacarta TMS service sometimes return a 4 band PNG instead of the expected 3 band... */
                }
                else if (!accepted_as_ct) {
                   if (ds->GetRasterCount()==3 && m_parent_dataset->nBands == 4 && (eDataType == GDT_Byte))
                   { // WMS returned a file with no alpha so we will fill the alpha band with "opaque" 
                      accepted_as_no_alpha = true;
                   }
                   else
                   {
                      CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect bands count %d in downloaded block, expected %d.",
                         nDSRasterCount, m_parent_dataset->nBands);
                      ret = CE_Failure;
                   }
                }
            }
        }
        if (!advise_read) {
            for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
                if (ret == CE_None) {
                    void *p = NULL;
                    GDALRasterBlock *b = NULL;
                    if ((buffer != NULL) && (ib == to_buffer_band)) {
                        p = buffer;
                    } else {
                        GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
                        if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
                        if (!band->IsBlockInCache(x, y)) {
                            b = band->GetLockedBlockRef(x, y, true);
                            if (b != NULL) {
                                p = b->GetDataRef();
                                if (p == NULL) {
                                  CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: GetDataRef returned NULL.");
                                  ret = CE_Failure;
                                }
                            }
                        }
                        else
                        {
                            //CPLDebug("WMS", "Band %d, block (x,y)=(%d, %d) already in cache", band->GetBand(), x, y);
                        }
                    }
                    if (p != NULL) {
                        int pixel_space = GDALGetDataTypeSize(eDataType) / 8;
                        int line_space = pixel_space * nBlockXSize;
                        if (color_table == NULL) {
                            if( ib <= ds->GetRasterCount()) {
                               if (ds->RasterIO(GF_Read, 0, 0, sx, sy, p, sx, sy, eDataType, 1, &ib, pixel_space, line_space, 0) != CE_None) {
                                   CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: RasterIO failed on downloaded block.");
                                   ret = CE_Failure;
                               }
                            }
                            else
                            {  // parent expects 4 bands but file only has 3 so generate a all "opaque" 4th band
                               if (accepted_as_no_alpha)
                               {
                                  // the file had 3 bands and we are reading band 4 (Alpha) so fill with 255 (no alpha)
                                  GByte *byte_buffer = reinterpret_cast<GByte *>(p);
                                  for (int y = 0; y < sy; ++y) {
                                     for (int x = 0; x < sx; ++x) {
                                        const int offset = x + y * line_space;
                                        byte_buffer[offset] = 255;  // fill with opaque
                                     }
                                  }
                               }
                               else
                               {  // we should never get here because this case was caught above
                                  CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect bands count %d in downloaded block, expected %d.",
                                     ds->GetRasterCount(), m_parent_dataset->nBands);
                                  ret = CE_Failure;
                               }     
                            }
                        } else if (ib <= 4) {
                            if (ds->RasterIO(GF_Read, 0, 0, sx, sy, p, sx, sy, eDataType, 1, NULL, pixel_space, line_space, 0) != CE_None) {
                                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: RasterIO failed on downloaded block.");
                                ret = CE_Failure;
                            }
                            if (ret == CE_None) {
                                GByte *band_color_table = color_table + 256 * (ib - 1);
                                GByte *byte_buffer = reinterpret_cast<GByte *>(p);
                                for (int y = 0; y < sy; ++y) {
                                    for (int x = 0; x < sx; ++x) {
                                        const int offset = x + y * line_space;
                                        byte_buffer[offset] = band_color_table[byte_buffer[offset]];
                                    }
                                }
                            }
                        } else {
                            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Color table supports at most 4 components.");
                            ret = CE_Failure;
                        }
                    }
                    if (b != NULL) {
                        b->DropLock();
                    }
                }
            }
        }
        GDALClose(ds);
    } else {
        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Unable to open downloaded block.");
        ret = CE_Failure;
    }

    if (color_table != NULL) {
        delete[] color_table;
    }

    return ret;
}