本文包括访问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了,所以干脆将这篇草稿直接发布了,也许对一些有需要的朋友所有帮助。