惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Darknet – Hacking Tools, Hacker News & Cyber Security
V
Vulnerabilities – Threatpost
Cloudbric
Cloudbric
G
GRAHAM CLULEY
S
Securelist
Schneier on Security
Schneier on Security
Help Net Security
Help Net Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Project Zero
Project Zero
Spread Privacy
Spread Privacy
P
Privacy International News Feed
C
Cyber Attacks, Cyber Crime and Cyber Security
Cisco Talos Blog
Cisco Talos Blog
T
Tailwind CSS Blog
博客园_首页
有赞技术团队
有赞技术团队
Simon Willison's Weblog
Simon Willison's Weblog
Stack Overflow Blog
Stack Overflow Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Latest news
Latest news
T
Tor Project blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Attack and Defense Labs
Attack and Defense Labs
www.infosecurity-magazine.com
www.infosecurity-magazine.com
O
OpenAI News
J
Java Code Geeks
T
Tenable Blog
K
Kaspersky official blog
AWS News Blog
AWS News Blog
S
Security @ Cisco Blogs
The GitHub Blog
The GitHub Blog
T
Threatpost
月光博客
月光博客
H
Heimdal Security Blog
Security Latest
Security Latest
The Hacker News
The Hacker News
Y
Y Combinator Blog
A
Arctic Wolf
Apple Machine Learning Research
Apple Machine Learning Research
C
Cisco Blogs
美团技术团队
Microsoft Security Blog
Microsoft Security Blog
Hugging Face - Blog
Hugging Face - Blog
T
The Blog of Author Tim Ferriss
C
CERT Recently Published Vulnerability Notes
D
Docker
Google Online Security Blog
Google Online Security Blog
D
DataBreaches.Net
V
Visual Studio Blog
H
Help Net Security

博客园 - Avlee

ArcGIS Server Manager 登录失败的解决方法 倡议以赞助的形式成立一个博客园的开发团队(博客园商业化尚早) 在WebGIS中试用Microsoft Silverlight有感 The MSVC project of the cairo library(version 1.4.6) WebGIS团队启用二级域名 Building the cairo graphic library using msvc Adobe 将停止对Adobe SVG Viewer的支持! SVG Authoring Guidelines[转] ArrayList.ToArray(Type) Or ArrayList.CopyTo(Array) Using Delegates with Data Readers to Control DAL Responsibility[转] 关于旧mdl程序向V8升级的问题 有了Flash和SVG,Adobe还想做什么呢? 基于Geomedia Professional平台的GIS应用开发(一) 根据权限创建页面上的功能按钮的一种简单有效的方法 如何让英文版的Adobe SVG Viewer显示中文文字 Adobe SVG Viewer 6.0 中自定义右键菜单 过年了,再忙也要回家...... 申请加入 “WebGIS” 团队 WebGIS团队刚刚成立
利用ArcSDE C API读取ArcSDE Raster数据
Avlee · 2007-08-27 · via 博客园 - Avlee

关于ArcSDE Raster的一些资料可以参见合金枪头的关于ArcSDE影像数据管理的系列文章。

本文包括访问ArcSDE Raster数据的三个应用,代码只是片段抽取,但是已经包括了该功能的所有代码。

1、获取ArcSDE中Raster数据列表

1 struct SdeRasterTableInfo
2 {
3     char TableName[SE_QUALIFIED_TABLE_NAME];
4     char RasterColumnName[SE_MAX_COLUMN_LEN];
5 };

 1 bool GetSdeRasterCatalog(SE_CONNECTION pConnection, std::vector<SdeRasterTableInfo> &rasterTables)
 2 {
 3     SE_RASCOLINFO *pRasterColumnList = 0;
 4     if (SE_rastercolumn_get_info_list(pConnection, &pRasterColumnList, &lRasterColumnCount) != SE_SUCCESS)
 5         return false;
 6 
 7     for (int i = 0; i < lRasterColumnCount; i++)
 8     {
 9         long privileges = 0;
10         if (SE_rascolinfo_get_access (pRasterColumnList[i], &privileges) != SE_SUCCESS)
11             continue;
12 
13         if (!(privileges & SE_SELECT_PRIVILEGE))
14             continue;
15 
16         SdeRasterTableInfo rasterTableInfo;
17 
18         // Get the raster table name and column name.
19         if (SE_rascolinfo_get_raster_column (pRasterColumnList[i],
20             rasterTableInfo.TableName, rasterTableInfo.RasterColumnName) != SE_SUCCESS)
21             continue;
22         
23         rasterTables.push_back(rasterTableInfo);
24     }
25 
26     SE_rastercolumn_free_info_list (lRasterColumnCount, pRasterColumnList);
27     
28     return true;
29 }

2、获取指定Raster数据的元数据

 1 struct SdeRasterSpec
 2 {
 3     long   ImageWidth;
 4     long   ImageHeight;
 5     
 6     double OriginX;
 7     double OriginY;
 8     
 9     double MinX;
10     double MinY;
11     double MaxX;
12     double MaxY;
13 };

  1 LONG GetSdeRasterSpec(SE_CONNECTION pConnection, 
  2     const string& tableName, const string& rasterColumn, const string& where
  3     SdeRasterSpec &rasterSpec)
  4 {
  5     // Get raster column info.
  6     SE_RASCOLINFO rasColInfo = 0;
  7     LONG rc = SE_rascolinfo_create(&rasColInfo);
  8     if (rc != SE_SUCCESS)
  9         return rc;
 10 
 11     LONG rasterColumnId = 0;
 12 
 13     do
 14     {
 15         rc = SE_rastercolumn_get_info_by_name(pConnection, tableName.c_str(), rasterColumn.c_str(), rasColInfo);
 16         if (rc != SE_SUCCESS)
 17             break;
 18 
 19         // Get raster column ID.
 20         rc = SE_rascolinfo_get_id(rasColInfo, &rasterColumnId);
 21         if (rc != SE_SUCCESS)
 22             break;
 23     }
 24     while(0);
 25 
 26     SE_rascolinfo_free(rasColInfo);
 27 
 28     if (rc != SE_SUCCESS)
 29         return rc;
 30 
 31     // Get raster ID.
 32     LONG rasterId = -1;
 33     rc = FetchRasterID(pConnection, tableName, rasterColumn, where&rasterId);
 34     if (rasterId == -1)
 35         return rc;
 36 
 37     // Get raster info.
 38     SE_RASTERINFO rasterInfo = 0;
 39     rc = SE_rasterinfo_create(&rasterInfo);
 40     if (rc != SE_SUCCESS)
 41         return rc;
 42 
 43     rc = SE_raster_get_info_by_id(pConnection, rasterColumnId, rasterId, rasterInfo);
 44     if (rc != SE_SUCCESS)
 45     {
 46         SE_rasterinfo_free(rasterInfo);
 47         return rc;
 48     }
 49 
 50     // Get raster band info list.
 51     SE_RASBANDINFO *rasterBands = 0;
 52     LONG bandCount = 0;
 53     rc = SE_raster_get_bands(pConnection, rasterInfo, &rasterBands, &bandCount);
 54     if (rc != SE_SUCCESS)
 55     {
 56         SE_rasterinfo_free (rasterInfo);
 57         return rc;
 58     }
 59 
 60     SE_rasterinfo_free(rasterInfo);
 61 
 62     // Get the raster band size and origin.
 63     LFLOAT bandOriginX = 0.0, bandOriginY = 0.0;
 64     LONG bandWidth = 0, bandHeight = 0;
 65     SE_ENVELOPE rasterEnv;
 66     if (bandCount > 0)
 67     {
 68         rc = SE_rasbandinfo_get_tile_origin(rasterBands[0], &rasterSpec.OriginX, &rasterSpec.OriginY);
 69 
 70         if (rc == SE_SUCCESS)
 71             rc = SE_rasbandinfo_get_band_size (rasterBands[0], &rasterSpec.ImageWidth, &rasterSpec.ImageHeight);
 72 
 73         if (rc == SE_SUCCESS)
 74             rc = SE_rasbandinfo_get_extent (rasterBands[0], &rasterEnv);
 75     }
 76 
 77     SE_rasterband_free_info_list(bandCount, rasterBands);
 78 
 79     if (rc == SE_SUCCESS)
 80     {
 81         rasterSpec.MinX = rasterEvn.minx;
 82         rasterSpec.MinY = rasterEvn.miny;
 83         rasterSpec.MaxX = rasterEvn.maxx;
 84         rasterSpec.MaxY = rasterEvn.maxy;
 85     }
 86 
 87     return rc;
 88 }
 89 
 90 LONG FetchRasterID (SE_CONNECTION pConnection, const string& tableName, 
 91     const string& rasterColumn, const string& where, LONG *rasterId) 
 92 {
 93     *rasterId = -1;
 94 
 95     SE_STREAM stream = 0;
 96     LONG rc = SE_stream_create (pConnection, &stream);
 97     if (rc != SE_SUCCESS)
 98         return rc;
 99 
100     // Set up SQL statement.
101     CHAR sqlstmt[128];
102     if (where.empty())
103         sprintf (sqlstmt,"SELECT %s FROM %s", rasterColumn.c_str(), tableName.c_str());
104     else
105         sprintf (sqlstmt,"SELECT %s FROM %s WHERE %s", rasterColumn.c_str(), tableName.c_str(), where.c_str());
106 
107     do
108     {
109         rc = SE_stream_prepare_sql (stream, sqlstmt);
110         if (rc != SE_SUCCESS)
111             break;
112 
113         // Bind the rasterId variable to receive the output of the stream.
114         SHORT raster_ind= SE_IS_NULL_VALUE;
115         rc = SE_stream_bind_output_column (stream, 1, (void *)rasterId, &raster_ind);
116         if (rc != SE_SUCCESS)
117             break;
118 
119         // Execute the query.
120         rc = SE_stream_execute (stream);
121         if (rc != SE_SUCCESS)
122             break;
123 
124         // Fetch the result from the cursor.
125         rc = SE_stream_fetch (stream);
126         if (rc == SE_SUCCESS || rc == SE_FINISHED) 
127         {
128             // If the query sets the indicator to NULL.
129             if (raster_ind == SE_IS_NULL_VALUE) 
130                 *rasterId = -1;
131         }
132     }
133     while(0);
134 
135     SE_stream_free (stream);
136 
137     return rc;
138 }

3、读取指定范围的Raster数据,并输出为PNG格式

  1 #ifndef __SDERASTERCLIP_H__
  2 #define __SDERASTERCLIP_H__
  3 
  4 #include "sderaster.h"
  5 #include "png.h"                         // for libpng
  6 
  7 class CSdeRasterClip
  8 {
  9 public:
 10     CSdeRasterClip(int nClipWidth, int nClipHeight, int nSourceWidth, int nSourceHeight)
 11     {
 12         m_pBuffer = 0;
 13         
 14         m_nClipWidth = nClipWidth;
 15         m_nClipHeight = nClipHeight;
 16         m_nSourceWidth = nSourceWidth;
 17         m_nSourceHeight = nSourceHeight;
 18     }
 19 
 20     ~CSdeRasterClip()
 21     {
 22         delete[] m_pBuffer;
 23     }
 24 
 25     bool Clip(SE_CONNECTION pConnection, 
 26         const string& tableName, const string& rasterColumn, const string& where)
 27     {
 28         bool bSuccess = false;
 29 
 30         try
 31         {
 32             LONG rc = ClipImage(pConnection, tableName, rasterColumn, where);
 33             if (rc == SE_SUCCESS)
 34             {
 35                 unsigned char **pRow = (unsigned char **)m_pBuffer;
 36             
 37                 // Write image buffer to png stream.
 38                 return WritePNG (pRow, m_nImageWidth, m_nImageHeight, 8, PNG_COLOR_TYPE_RGB);
 39             }
 40         }
 41         catch (const char *msg)
 42         {
 43             //
 44         }
 45         catch ()
 46         {
 47             //
 48         }
 49 
 50         return false;
 51     }
 52 
 53 private:
 54 
 55     LONG ClipImage(CXrbStream &tStream, SE_CONNECTION pConnection, 
 56         const string& tableName, const string& rasterColumn, const string& where)
 57     {
 58         // Create the queryinfo structure
 59         SE_QUERYINFO queryinfo = 0;
 60         LONG rc = SE_queryinfo_create (&queryinfo);
 61         if (rc != SE_SUCCESS)
 62         {
 63             return rc;
 64         }
 65 
 66         do
 67         {
 68             // Set query tables.
 69             const CHAR *tables[1];
 70             tables[0]= tableName.c_str();
 71 
 72             rc = SE_queryinfo_set_tables (queryinfo, 1, tables, NULL); 
 73             if (rc != SE_SUCCESS)
 74                 break;
 75 
 76             // Set query columns.
 77             const CHAR *columns[1];
 78             columns[0= rasterColumn.c_str();
 79 
 80             rc = SE_queryinfo_set_columns (queryinfo, 1, columns); 
 81             if (rc != SE_SUCCESS)
 82                 break;
 83 
 84             // Set query where clause.
 85             if (!where.empty())
 86             {
 87                 rc = SE_queryinfo_set_where_clause(queryinfo, where.c_str());
 88                 if (rc != SE_SUCCESS)
 89                     break;
 90             }
 91         }
 92         while(0);
 93 
 94         if (rc != SE_SUCCESS)
 95         {
 96             SE_queryinfo_free (queryinfo);
 97             return rc;
 98         }
 99 
100         // Create query stream
101         SE_STREAM stream = 0;
102         rc = SE_stream_create (pConnection, &stream);
103         if (rc != SE_SUCCESS)
104         {
105             SE_queryinfo_free (queryinfo);
106             return rc;
107         }
108 
109         // initializes query stream using query info.
110         rc = SE_stream_query_with_info (stream, queryinfo);
111         if (rc != SE_SUCCESS)
112         {
113             SE_queryinfo_free (queryinfo);
114             SE_stream_free (stream);
115             return rc;
116         }
117 
118         SE_queryinfo_free (queryinfo);
119 
120         SE_RASTERATTR raster_attrib = 0;
121         rc = SE_rasterattr_create (&raster_attrib, FALSE);
122         if (rc != SE_SUCCESS)
123         {
124             SE_stream_free (stream);
125             return rc;
126         }
127 
128         // Bind the rasterId variable to receive the output of the stream.
129         SHORT raster_ind= SE_IS_NULL_VALUE;
130         rc = SE_stream_bind_output_column (stream, 1, raster_attrib, &raster_ind);
131         if (rc != SE_SUCCESS)
132         {
133             SE_stream_free (stream);
134             SE_rasterattr_free (raster_attrib);
135             return rc;
136         }
137 
138         // Execute the query.
139         rc = SE_stream_execute (stream);
140         if (SE_SUCCESS == rc) 
141         {
142             // Fetch each record of the business table //
143             rc = SE_stream_fetch (stream);
144 
145             if (SE_FINISHED != rc) 
146             { 
147                 if (raster_ind == SE_IS_NOT_NULL_VALUE)
148                 {
149                     rc = GetRasterData(pConnection, stream, raster_attrib);
150                 }
151             }
152         }
153 
154         SE_stream_free (stream);
155         SE_rasterattr_free (raster_attrib);
156 
157         return rc;
158     }
159 
160     LONG GetRasterData(SE_CONNECTION connection, SE_STREAM stream, SE_RASTERATTR raster_attrib)
161     {
162         // determine number of images in pyramid
163         BOOL bSkipLevel = TRUE;
164         LONG nPyramidSize = 0;
165         LONG rc = SE_rasterattr_get_max_level ( raster_attrib, &nPyramidSize, &bSkipLevel);
166         if (rc != SE_SUCCESS)
167             return rc;
168 
169         // determine which image should be used
170         int nLevel = GetPyramidLevel(nPyramidSize);
171 
172         SE_ENVELOPE raster_env;
173         LFLOAT dOffsetX = 0.0, dOffsetY = 0.0;
174 
175         rc = SE_rasterattr_get_extent_by_level (raster_attrib, &raster_env, &dOffsetX, 
176             &dOffsetY, nLevel);
177         if (rc != SE_SUCCESS)
178             return rc;
179 
180         rc = SE_rasterattr_get_tile_size (raster_attrib, &m_nTileWidth, &m_nTileHeight);
181         if (rc != SE_SUCCESS)
182             return rc;
183 
184         LONG nBandsCount = 0;
185         LONG nSourceImageWidth = 0;
186         LONG nSourceImageHeight = 0;
187         LONG nSourceImageOffsetX = 0;
188         LONG nSourceImageOffsetY = 0;
189         rc = SE_rasterattr_get_image_size_by_level(raster_attrib, 
190             &nSourceImageWidth, 
191             &nSourceImageHeight, 
192             &nSourceImageOffsetX,
193             &nSourceImageOffsetY,
194             &nBandsCount,
195             nLevel);
196         if (rc != SE_SUCCESS)
197             return rc;
198 
199         // calculate the pixel cell size in world coordinates
200         LFLOAT nCellSize = (raster_env.maxx - raster_env.minx) / (nSourceImageWidth - 1);
201 
202         LONG nPixelType;
203         rc = SE_rasterattr_get_pixel_type (raster_attrib, &nPixelType);
204         if (rc != SE_SUCCESS)
205             return rc;
206 
207         // Dot not support other pixel type now.
208         if (nPixelType != SE_PIXEL_TYPE_8BIT_U) 
209             return SE_FAILURE;
210 
211         // compute the real world coordinate width and height
212         LFLOAT coord_tile_width = nCellSize * m_nTileWidth;
213         LFLOAT coord_tile_height = nCellSize * m_nTileHeight;
214 
215         LONG pixels_per_tile = m_nTileWidth * m_nTileHeight;
216 
217         // The testing code only request the full image.
218         LONG minx = raster_env.minx;
219         LONG maxx = raster_env.maxx;
220         LONG miny = raster_env.miny;
221         LONG maxy = raster_env.maxy;
222 
223         LONG relminx = (LONG) ((minx - (raster_env.minx - dOffsetX)) / coord_tile_width); 
224         LONG relmaxx = (LONG) ((maxx - (raster_env.minx - dOffsetX)) / coord_tile_width);
225         LONG relminy = (LONG) (((raster_env.maxy + dOffsetY) - maxy) / coord_tile_height);
226         LONG relmaxy = (LONG) (((raster_env.maxy + dOffsetY) - miny) / coord_tile_height);
227 
228         LONG nNumTilesX = relmaxx - relminx + 1;
229         LONG nNumTilesY = relmaxy - relminy + 1;
230 
231         m_nImageWidth = nNumTilesX * m_nTileWidth;
232         m_nImageHeight = nNumTilesY * m_nTileHeight;
233         
234         rc = SE_rasterattr_get_num_bands (raster_attrib, &nBandsCount);
235         if (rc != SE_SUCCESS)
236             return rc;
237 
238         //if (nBandsCount != 1 && nBandsCount != 3)
239         //    return;
240 
241         
242         SE_RASCONSTRAINT rasconstraint = 0;
243         rc = SE_rasconstraint_create (&rasconstraint);
244         if (rc != SE_SUCCESS)
245             return rc;
246 
247         SE_RASTILEINFO rastile_info = 0;
248         rc = SE_rastileinfo_create (&rastile_info);
249         if (rc != SE_SUCCESS)
250         {
251             SE_rasconstraint_free (rasconstraint);
252             return rc;
253         }
254 
255         do
256         {
257             rc =  SE_rasconstraint_set_envelope (rasconstraint, relminx, relminy, relmaxx, relmaxy);
258             if (rc != SE_SUCCESS)
259                 break;
260 
261             LONG aBandArray[3= {1,2,3};
262 
263             rc = SE_rasconstraint_set_bands ( rasconstraint, nBandsCount, aBandArray);
264             if (rc != SE_SUCCESS)
265                 break;
266 
267             rc = SE_rasconstraint_set_interleave (rasconstraint, SE_RASTER_INTERLEAVE_BSQ);
268             if (rc != SE_SUCCESS)
269                 break;
270 
271             rc = SE_rasconstraint_set_level (rasconstraint, nLevel);
272             if (rc != SE_SUCCESS)
273                 break;
274 
275             rc = SE_stream_query_raster_tile (stream, rasconstraint);
276             if (rc != SE_SUCCESS)
277                 break;
278         }
279         while(0);
280 
281         if (rc != SE_SUCCESS)
282         {
283             SE_rasconstraint_free (rasconstraint);
284             SE_rastileinfo_free (rastile_info);
285             return rc;
286         }
287 
288         int nBitesPerPixel = nPixelType >> 3;
289 
290         int nImageBytesPerPixel = 3;
291         // bytes across source tile
292         int nTileByteWidth = (m_nTileWidth * nBitesPerPixel + 7/ 8;//m_nTileWidth;
293         // bytes across tile when copied to output image buffer
294         int nBufferTileByteWidth = m_nTileWidth * nImageBytesPerPixel;
295         // width of output buffer in bytes
296         int nBufferByteWidth = nBufferTileByteWidth * nNumTilesX;
297 
298         // bytes in output buffer for complete row of tiles
299         int nBufferTileByteRow = nBufferByteWidth * m_nTileHeight;
300 
301         if (m_pBuffer != 0) delete[] m_pBuffer;
302 
303         m_pBuffer = new unsigned char[(m_nImageHeight * sizeof(char*)) + (nBufferTileByteRow * nNumTilesY)];
304 
305         // create pointer to actual image data
306         unsigned char *pBufferImage = m_pBuffer + (m_nImageHeight * sizeof(char*));
307 
308         // create pointer to tile buffer
309         unsigned char *pSingleTile = NULL;
310 
311         LONG length = 0;
312         LONG rasterband_id = 0;
313         LONG row = 0;
314         LONG column = 0;
315 
316         while (rc == SE_SUCCESS)
317         {
318             rc = SE_stream_get_raster_tile (stream, rastile_info);
319             if (rc != SE_SUCCESS)
320                 break;
321 
322             rc = SE_rastileinfo_get_band_id (rastile_info, &rasterband_id);
323             if (rc != SE_SUCCESS)
324                 break;
325 
326             rc = SE_rastileinfo_get_rowcol (rastile_info, &row, &column);
327             if (rc != SE_SUCCESS)
328                 break;
329 
330             rc = SE_rastileinfo_get_pixel_data (rastile_info, (void**)&pSingleTile, &length);
331             if (rc != SE_SUCCESS)
332                 break;
333 
334             unsigned char *pDst = pBufferImage + row * nBufferTileByteRow + column * nBufferTileByteWidth;
335             unsigned char *pSrc = pSingleTile;
336             for (int k = 0; k < m_nTileHeight; k++)
337             {
338                 ExpandBits(pDst, pSrc, pSrc + nTileByteWidth, rasterband_id % 3);
339 
340                 pSrc += nTileByteWidth;
341                 pDst += nBufferByteWidth;
342             }
343         }
344 
345         SE_rasconstraint_free (rasconstraint);
346         SE_rastileinfo_free (rastile_info);
347 
348         if (rc == SE_FINISHED)
349             rc = SE_SUCCESS;
350 
351         // Create array of row pointers at beginning of buffer for png write.
352         if (rc == SE_SUCCESS)
353         {
354             unsigned char **pCurPtr = (unsigned char **)m_pBuffer;
355             unsigned char **pEndPtr = pCurPtr + m_nImageHeight;
356             unsigned char *pCurSrc = pBufferImage;
357 
358             while (pCurPtr < pEndPtr)
359             {
360                 *pCurPtr = pCurSrc;
361                 pCurSrc += nBufferByteWidth;
362                 pCurPtr++;
363             }
364         }
365 
366         return rc;
367     }
368 
369     void ExpandBits(unsigned char *pDst, unsigned char *pSrc, unsigned char *pEndSrc, int nBits)
370     {
371         unsigned char *pCurSrc = pSrc;
372         unsigned char *pCurDst = pDst;
373         unsigned char pixel;
374 
375         switch (nBits)
376         {
377         case 1//r
378             for (; pCurSrc<pEndSrc; pCurSrc++)
379             {
380                 pixel = *pCurSrc;
381 
382                 *pCurDst = pixel & 0xff;
383                 pCurDst++;
384                 *pCurDst = 0;
385                 pCurDst++;
386                 *pCurDst = 0;
387                 pCurDst++;
388             }
389             break;
390 
391         case 2//g
392             for (; pCurSrc<pEndSrc; pCurSrc++)
393             {
394                 pixel = *pCurSrc;
395                 pCurDst++;
396                 *pCurDst = pixel & 0xff;
397                 pCurDst++;
398                 *pCurDst = 0;
399                 pCurDst++;
400             }
401             break;
402 
403         case 3//b
404             for (; pCurSrc<pEndSrc; pCurSrc++)
405             {
406                 pixel = *pCurSrc;
407                 pCurDst++;
408                 pCurDst++;
409                 *pCurDst = pixel & 0xff;
410                 pCurDst++;
411             }
412             break;
413 
414         default:
415             break;
416         }
417     }
418 
419     /**//**
420      * Get the zero-based index to the pyramid image that best fits the dimensions
421      * @return index in the pyramid
422      */
423     int GetPyramidLevel(int nMaxLevel)
424     {
425         int nWidthRatio = m_nSourceWidth/m_nClipWidth;
426         int nHeightRatio = m_nSourceHeight/m_nClipHeight;
427         int nRatio = (nWidthRatio < nHeightRatio)? nWidthRatio : nHeightRatio;
428         int nLevel = 0;
429         while (nRatio >>= 1) nLevel++;
430         if (nLevel > nMaxLevel) return nMaxLevel;
431         return nLevel;
432     }
433 
434     static void stdio_write_func (png_structp png, png_bytep data, png_size_t size)
435     {
436         FILE *fp;
437 
438         fp = (FILE *)png_get_io_ptr (png);
439         while (size) {
440         size_t ret = fwrite (data, 1, size, fp);
441         size -= ret;
442         data += ret;
443         if (size && ferror (fp))
444             png_error(png, "Write Error");
445         }
446     }
447 
448     bool WritePNG( const char *outputFile, unsigned char **pRows, 
449         int nWidth, int nHeight, int nBitDepth, 
450         int nColorType, int nFilterType = PNG_FILTER_TYPE_DEFAULT) 
451     {
452         png_structp   pPngPtr = 0;
453         png_infop     pInfoPtr = 0;
454 
455         FILE *fp = 0;
456 
457         fp = fopen (outputFile, "wb");
458         if (fp == 0)
459             return false;
460 
461 
462         pPngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, 00);
463         if (pPngPtr)
464         {
465             pInfoPtr = png_create_info_struct(pPngPtr);
466             if (pInfoPtr)
467             {
468                 png_set_IHDR(pPngPtr, pInfoPtr, nWidth, nHeight,
469                         nBitDepth, nColorType, PNG_INTERLACE_NONE,
470                         PNG_COMPRESSION_TYPE_DEFAULT, nFilterType);
471 
472                 // set up write functions
473                 png_set_write_fn(pPngPtr, fp, stdio_write_func, NULL);
474 
475                 // write header
476                 png_write_info(pPngPtr, pInfoPtr);
477 
478                 png_color_16 white;
479                 white.red = 0xff;
480                 white.blue = 0xff;
481                 white.green = 0xff;
482 
483                 png_set_bKGD (pPngPtr, pInfoPtr, &white);
484 
485                 // write image
486                 png_write_image(pPngPtr, pRows);
487 
488                 // finish write
489                 png_write_end(pPngPtr, 0);
490 
491                 // destroy structures
492                 png_destroy_write_struct(&pPngPtr, &pInfoPtr);
493 
494                 fclose (fp);
495                 return true;
496             }
497             else
498             {
499                 png_destroy_write_struct(&pPngPtr, &pInfoPtr);
500                 fclose (fp);
501 
502             }
503         }
504         return false;
505     }
506 
507     /**//** Buffer for image data. */
508     unsigned char *m_pBuffer;
509 
510     LONG m_nTileWidth;
511     LONG m_nTileHeight;
512     
513     int m_nImageWidth;
514     int m_nImageHeight;
515 
516     int m_nClipWidth;
517     int m_nClipHeight;
518     int m_nSourceWidth;
519     int m_nSourceHeight;
520 };
521 
522 #endif //__SDERASTERCLIP_H__

:本来这篇本章很早就写了,但是一直没有时间来总结一下,现在开始着手三维GIS方面的开发,看来以后一段时间将更加忙,也没有时间来更新Blog了,所以干脆将这篇草稿直接发布了,也许对一些有需要的朋友所有帮助。