wxImage wxGISRasterRGBRenderer::Scale(unsigned char* pData, int nOrigX, int nOrigY, double rOrigX, double rOrigY, int nDestX, int nDestY, double rDeltaX, double rDeltaY, wxGISEnumDrawQuality Quality, ITrackCancel* pTrackCancel) { // //simple way // wxImage ResultImage(nOrigX, nOrigY, pData); //ResultImage = ResultImage.Scale(nDestX, nDestY, nQuality); // return ResultImage; wxImage ResultImage(nDestX, nDestY, false); unsigned char* pDestData = ResultImage.GetData(); //multithreaded int CPUCount(2); //check cpu count std::vector<wxRasterDrawThread*> threadarray; int nPartSize = nDestY / CPUCount; int nBegY(0), nEndY; for(int i = 0; i < CPUCount; i++) { if(i == CPUCount - 1) nEndY = nDestY; else nEndY = nPartSize * (i + 1); unsigned char* pDestInputData = pDestData + (nDestX * nBegY * 3); wxRasterDrawThread *thread = new wxRasterDrawThread(pData, pDestInputData, nOrigX, nOrigY, rOrigX, rOrigY, nDestX, nDestY, rDeltaX, rDeltaY, Quality, pTrackCancel, nBegY, nEndY); thread->Create(); thread->Run(); threadarray.push_back(thread); nBegY = nEndY/* + 1*/; } for(size_t i = 0; i < threadarray.size(); i++) { wgDELETE(threadarray[i], Wait()); } return ResultImage; }
void wxGISRasterRGBRenderer::Draw(wxGISDataset* pRasterDataset, wxGISEnumDrawPhase DrawPhase, IDisplay* pDisplay, ITrackCancel* pTrackCancel) { wxGISRasterDataset* pRaster = dynamic_cast<wxGISRasterDataset*>(pRasterDataset); if(!pRaster) return; IDisplayTransformation* pDisplayTransformation = pDisplay->GetDisplayTransformation(); OGRSpatialReference* pDisplaySpatialReference = pDisplayTransformation->GetSpatialReference(); OGRSpatialReference* pRasterSpatialReference = pRaster->GetSpatialReference(); bool IsSpaRefSame(true); if(pDisplaySpatialReference && pDisplaySpatialReference) IsSpaRefSame = pDisplaySpatialReference->IsSame(pRasterSpatialReference); OGREnvelope VisibleBounds = pDisplayTransformation->GetVisibleBounds(); OGREnvelope* pRasterExtent = pRaster->GetEnvelope(); OGREnvelope RasterEnvelope, DisplayEnvelope; if(!IsSpaRefSame) { RasterEnvelope = TransformEnvelope(pRasterExtent, pRasterSpatialReference, pDisplaySpatialReference); } else { RasterEnvelope = *pRasterExtent; } bool IsZoomIn(false); //IsZoomIn = RasterEnvelope.Contains(VisibleBounds); IsZoomIn = RasterEnvelope.MaxX > VisibleBounds.MaxX || RasterEnvelope.MaxY > VisibleBounds.MaxY || RasterEnvelope.MinX < VisibleBounds.MinX || RasterEnvelope.MinY < VisibleBounds.MinY; if(IsZoomIn) { //intersect bounds OGREnvelope DrawBounds; DrawBounds.MinX = MAX(RasterEnvelope.MinX, VisibleBounds.MinX); DrawBounds.MinY = MAX(RasterEnvelope.MinY, VisibleBounds.MinY); DrawBounds.MaxX = MIN(RasterEnvelope.MaxX, VisibleBounds.MaxX); DrawBounds.MaxY = MIN(RasterEnvelope.MaxY, VisibleBounds.MaxY); OGRRawPoint OGRRawPoints[2]; OGRRawPoints[0].x = DrawBounds.MinX; OGRRawPoints[0].y = DrawBounds.MinY; OGRRawPoints[1].x = DrawBounds.MaxX; OGRRawPoints[1].y = DrawBounds.MaxY; wxPoint* pDCPoints = pDisplayTransformation->TransformCoordWorld2DC(OGRRawPoints, 2); if(!pDCPoints) { wxDELETEA(pDCPoints); return; } int nDCXOrig = pDCPoints[0].x; int nDCYOrig = pDCPoints[1].y; int nWidth = pDCPoints[1].x - pDCPoints[0].x; int nHeight = pDCPoints[0].y - pDCPoints[1].y; wxDELETEA(pDCPoints); if(nWidth <= 20 || nHeight <= 20) return; GDALDataset* pGDALDataset = pRaster->GetRaster(); int nBandCount = pGDALDataset->GetRasterCount(); //hack! int bands[3]; if(nBandCount < 3) { bands[0] = 1; bands[1] = 1; bands[2] = 1; } else { bands[0] = 1; bands[1] = 2; bands[2] = 3; } double adfGeoTransform[6] = { 0, 0, 0, 0, 0, 0 }; double adfReverseGeoTransform[6] = { 0, 0, 0, 0, 0, 0 }; CPLErr err = pGDALDataset->GetGeoTransform(adfGeoTransform); bool bNoTransform(false); if(err != CE_None) { bNoTransform = true; } else { int nRes = GDALInvGeoTransform( adfGeoTransform, adfReverseGeoTransform ); } //2. get image data from raster - draw part of the raster if(IsSpaRefSame) { double rMinX, rMinY, rMaxX, rMaxY; int nXSize = pGDALDataset->GetRasterXSize(); int nYSize = pGDALDataset->GetRasterYSize(); if(bNoTransform) { rMinX = DrawBounds.MinX; rMaxX = DrawBounds.MaxX; rMaxY = nYSize - DrawBounds.MinY; rMinY = nYSize - DrawBounds.MaxY; } else { GDALApplyGeoTransform( adfReverseGeoTransform, DrawBounds.MinX, DrawBounds.MinY, &rMinX, &rMaxY ); GDALApplyGeoTransform( adfReverseGeoTransform, DrawBounds.MaxX, DrawBounds.MaxY, &rMaxX, &rMinY ); } //double rRealMinX, rRealMinY, rRealMaxX, rRealMaxY; //rRealMinX = MIN(rMinX, rMaxX); //rRealMinY = MIN(rMinY, rMaxY); //rRealMaxX = MAX(rMinX, rMaxX); //rRealMaxY = MAX(rMinY, rMaxY); double rImgWidth = rMaxX - rMinX; double rImgHeight = rMaxY - rMinY; int nImgWidth = ceil(rImgWidth) + 1; int nImgHeight = ceil(rImgHeight) + 1; //read in buffer int nMinX = floor(rMinX); int nMinY = floor(rMinY); if(nMinX < 0) nMinX = 0; if(nMinY < 0) nMinY = 0; if(nImgWidth > nXSize - nMinX) nImgWidth -= 1; if(nImgHeight > nYSize - nMinY) nImgHeight -= 1; //create buffer int nWidthOut = nWidth > nImgWidth ? nImgWidth : (double)nWidth + 1.0 /*/ 1.2 / 2 * 2/ 1.5 + 1) / 2*/; int nHeightOut = nHeight > nImgHeight ? nImgHeight : (double)nHeight + 1.0 /*/ 1.2 / 2 * 2 / 1.5 + 1) / 2*/; double rImgWidthOut = nWidth > nImgWidth ? rImgWidth : (double)nWidthOut * rImgWidth / nImgWidth; double rImgHeightOut = nHeight > nImgHeight ? rImgHeight : (double)nHeightOut * rImgHeight / nImgHeight; unsigned char* data = new unsigned char[nWidthOut * nHeightOut * 3]; err = pGDALDataset->AdviseRead(nMinX, nMinY, nImgWidth, nImgHeight, nWidthOut/*nImgWidth*/, nHeightOut/*nImgHeight*/, GDT_Byte, 3, bands, NULL); if(err != CE_None) { wxDELETEA(data);//delete[](data); return; } err = pGDALDataset->RasterIO(GF_Read, nMinX, nMinY, nImgWidth, nImgHeight, data, nWidthOut/*nImgWidth*/, nHeightOut/*nImgHeight*/, GDT_Byte, 3, bands, sizeof(unsigned char) * 3, 0, sizeof(unsigned char)); if(err != CE_None) { wxDELETEA(data);//delete[](data); return; } //scale pTempData to data using interpolation methods pDisplay->DrawBitmap(Scale(data, nWidthOut/*nImgWidth*/, nHeightOut/*nImgHeight*/, rImgWidthOut/*rImgWidth*/, rImgHeightOut/*rImgHeight*/, nWidth + 1 , nHeight + 1, rMinX - nMinX, rMinY - nMinY, /*enumGISQualityNearest*/enumGISQualityBilinear, pTrackCancel), nDCXOrig, nDCYOrig); wxDELETEA(data); } else { //void *hTransformArg = GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, NULL, pszDstWKT, FALSE, 0, 1 ); //GDALDestroyGenImgProjTransformer( hTransformArg ); //// //get new envelope - it may rotate //// OGRCoordinateTransformation *poCT = OGRCreateCoordinateTransformation( pDisplaySpatialReference, pRasterSpatialReference); ////// get real envelope ////// poCT->Transform(1, &pRasterExtent->MaxX, &pRasterExtent->MaxY); ////// poCT->Transform(1, &pRasterExtent->MinX, &pRasterExtent->MinY); ////// poCT->Transform(1, &pRasterExtent->MaxX, &pRasterExtent->MinY); ////// poCT->Transform(1, &pRasterExtent->MinX, &pRasterExtent->MaxY); //// OCTDestroyCoordinateTransformation(poCT); } } else { //1. convert newrasterenvelope to DC OGRRawPoint OGRRawPoints[2]; OGRRawPoints[0].x = RasterEnvelope.MinX; OGRRawPoints[0].y = RasterEnvelope.MinY; OGRRawPoints[1].x = RasterEnvelope.MaxX; OGRRawPoints[1].y = RasterEnvelope.MaxY; wxPoint* pDCPoints = pDisplayTransformation->TransformCoordWorld2DC(OGRRawPoints, 2); //2. get image data from raster - buffer size = DC_X and DC_Y - draw full raster if(!pDCPoints) { wxDELETEA(pDCPoints); return; } int nDCXOrig = pDCPoints[0].x; int nDCYOrig = pDCPoints[1].y; int nWidth = pDCPoints[1].x - pDCPoints[0].x; int nHeight = pDCPoints[0].y - pDCPoints[1].y; delete[](pDCPoints); GDALDataset* pGDALDataset = pRaster->GetRaster(); int nImgWidth = pGDALDataset->GetRasterXSize(); int nImgHeight = pGDALDataset->GetRasterYSize(); int nBandCount = pGDALDataset->GetRasterCount(); //hack! int bands[3]; if(nBandCount < 3) { bands[0] = 1; bands[1] = 1; bands[2] = 1; } else { bands[0] = 1; bands[1] = 2; bands[2] = 3; } //create buffer unsigned char* data = new unsigned char[nWidth * nHeight * 3]; if(IsSpaRefSame) { //read in buffer CPLErr err = pGDALDataset->RasterIO(GF_Read, 0, 0, nImgWidth, nImgHeight, data, nWidth, nHeight, GDT_Byte, 3, bands, sizeof(unsigned char) * 3, 0, sizeof(unsigned char)); if(err != CE_None) { wxDELETEA(data); return; } } else { //1. calc Width & Height of TempData with same aspect ratio of raster //2. create pTempData buffer unsigned char* pTempData; //3. fill data //4. for each pixel of data buffer get pixel from pTempData using OGRCreateCoordinateTransformation //delete[](data); } //3. draw //think about transparancy! wxImage ResultImage(nWidth, nHeight, data); pDisplay->DrawBitmap(ResultImage, nDCXOrig, nDCYOrig); //delete[](data); } }
/** * @brief CombineMultiImages Combine the input images to a single big image. * @param Images The input images. * @param NumberOfRows The number of the rows to put the input images. * @param NumberOfCols The number of the cols to put the input images. * @param Distance The distance between each image. * @param ImageWidth The width of each image in the big image. * @param ImageHeight The height of each image in the big image. * @return The big image if the operation is successed; * otherwise return empty image. * * @author sheng * @date 2015-03-24 * @version 0.1 * * @history * <author> <date> <version> <description> * sheng 2015-03-24 0.1 build the function * */ cv::Mat CombineMultiImages(const std::vector<cv::Mat>& Images, const int NumberOfRows, const int NumberOfCols, const int Distance, const int ImageWidth, const int ImageHeight) { // return empty mat if the Number of rows or cols is smaller than 1. assert((NumberOfRows > 0) && (NumberOfCols > 0)); if ((NumberOfRows < 1) || (NumberOfCols < 1)) { std::cout << "The number of the rows or the cols is smaller than 1." << std::endl; return cv::Mat(); } // return empty mat if the distance, the width or the height of image // is smaller than 1. assert((Distance > 0) && (ImageWidth > 0) && (ImageHeight > 0)); if ((Distance < 1) || (ImageWidth < 1) || (ImageHeight < 1)) { std::cout << "The distance, the width or the height of the image is smaller than 1." << std::endl; return cv::Mat(); } // Get the number of the input images const int NUMBEROFINPUTIMAGES = Images.size(); // return empty mat if the number of the input images is too big. assert(NUMBEROFINPUTIMAGES <= NumberOfRows * NumberOfCols); if (NUMBEROFINPUTIMAGES > NumberOfRows * NumberOfCols) { std::cout << "The number of images is too big." << std::endl; return cv::Mat(); } // return empty mat if the number of the input images is too low. assert(NUMBEROFINPUTIMAGES > 0); if (NUMBEROFINPUTIMAGES < 1) { std::cout << "The number of images is too low." << std::endl; return cv::Mat(); } // create the big image const int WIDTH = Distance * (NumberOfCols + 1) + ImageWidth * NumberOfCols; const int HEIGHT = Distance * (NumberOfRows + 1) + ImageHeight * NumberOfRows; cv::Scalar Color(255, 255, 255); if (Images[0].channels() == 1) { Color = cv::Scalar(255); } cv::Mat ResultImage(HEIGHT, WIDTH, Images[0].type(), Color); // copy the input images to the big image for (int Index = 0; Index < NUMBEROFINPUTIMAGES; Index++) { assert(Images[Index].type() == ResultImage.type()); if (Images[Index].type() != ResultImage.type()) { std::cout << "The No." << Index << "image has the different type." << std::endl; return cv::Mat(); } // Get the row and the col of No.Index image int Rows = Index / NumberOfCols; int Cols = Index % NumberOfCols; // The start point of No.Index image. int StartRows = Distance * (Rows + 1) + ImageHeight * Rows; int StartCols = Distance * (Cols + 1) + ImageWidth * Cols; // copy No.Index image to the big image cv::Mat ROI = ResultImage(cv::Rect(StartCols, StartRows, ImageWidth, ImageHeight)); cv::resize(Images[Index], ROI, cv::Size(ImageWidth, ImageHeight)); } return ResultImage; }