关于ArcSDE Raster的一些资料可以参见合金枪头的关于ArcSDE影像数据管理的系列文章。
本文包括访问ArcSDE Raster数据的三个应用,代码只是片段抽取,但是已经包括了该功能的所有代码。
1、获取ArcSDE中Raster数据列表
2、获取指定Raster数据的元数据
3、读取指定范围的Raster数据,并输出为PNG格式
注:本来这篇本章很早就写了,但是一直没有时间来总结一下,现在开始着手三维GIS方面的开发,看来以后一段时间将更加忙,也没有时间来更新Blog了,所以干脆将这篇草稿直接发布了,也许对一些有需要的朋友所有帮助。
本文包括访问ArcSDE Raster数据的三个应用,代码只是片段抽取,但是已经包括了该功能的所有代码。
1、获取ArcSDE中Raster数据列表
1 struct SdeRasterTableInfo
2 {
3 char TableName[SE_QUALIFIED_TABLE_NAME];
4 char RasterColumnName[SE_MAX_COLUMN_LEN];
5 };
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 {
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 };
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 }
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, 0, 0);
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__
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, 0, 0);
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了,所以干脆将这篇草稿直接发布了,也许对一些有需要的朋友所有帮助。