Doppler天气雷达格栅产品(RasterImage)

多普勒天气雷达的体扫产品处理代码。
包含RasterImage.java、RasterImageBlock.java、RasterProductBlock.java三个类。
由SymbologyImage.java类判断产品为Symbology且特征码为BA0F或BA07时调用。

 


RasterImage.java
001  /**
002    * PACKAGE      : cma.gmb.doppler
003    * FILENAME     : RasterImage.java
004    * DESCRIPTION  : 处理多普勒雷达产品数据(格栅产品Raster)
005    * AUTHOR       : 刘泽军
006    * EMAIL        : BJ0773@gmail.com
007    * Date         : 2007-06-02 23:52:38
008    * Update       : 2007-06-13 从SymbologyImage.java中独立出来
009    * Reference    : 《National Climatic Data Center DATA DOCUMENTATION FOR TD7000 -
010    *                 TD7599 NEXRAD LEVEL III》
011    *
012    */
013 
014  package  cma.gmb.doppler;
015 
016  import  java.io.*;
017  import  java.awt.*;
018 
019  import  cma.common.dataio.*;
020  import  cma.common.projection.*;
021  import  cma.micaps.diamond.*;
022  import  cma.gmb.doppler.datatype.*;
023 
024  public class  RasterImage  {
025       //外部传入的数据
026       public   MessageHeaderBlock          messageHeaderBlock;
027       public   ProductDescriptionBlock     productDescriptionBlock;
028       public   ProductSymbologyBlock       productSymbologyBlock;
029       public   ProductSymbologyLayerBlock  productSymbologyLayerBlock;
030       //需要读取的数据
031       public   RasterProductBlock          rasterProductBlock;
032       public   RasterImageBlock []           rasterImageBlock;
033 
034       public  static   Color []  levels  =  {
035           new  Color (   0 ,   0 ,   0 ) new  Color (   0 ,   0 , 246 ) new  Color (   1 , 159 , 246 ) new  Color (   0 , 236 , 236 ) ,
036           new  Color (   1 , 255 ,   0 ) new  Color (   0 , 200 ,   0 ) new  Color (   1 , 144 ,   0 ) new  Color ( 255 , 255 ,   0 ) ,
037           new  Color ( 231 , 192 ,   0 ) new  Color ( 255 , 144 ,   0 ) new  Color ( 254 ,   0 ,   0 ) new  Color ( 214 ,   0 ,   0 ) ,
038           new  Color ( 192 ,   0 ,   0 ) new  Color ( 255 ,   0 , 250 ) new  Color ( 174 , 144 , 240 ) new  Color ( 255 , 255 , 255 )
039       } ;
040 
041  /**
042    * 功能:构造函数
043    * 参数:
044    *      无
045    * 返回值:
046    *      无
047    */
048       public  RasterImage () {
049       }
050 
051  /**
052    * 功能:读取多普勒栅格数据Raster Image,不包括文件头信息,注意在调用前先定位好偏移量
053    * 参数:
054    *      fin     - 随机访问的文件对象
055    * 返回值:
056    *      是否成功
057    */
058       public  boolean  read ( RandomAccessFile fin throws  Exception  {
059 
060           if (      ! "BA0F" .equalsIgnoreCase ( productSymbologyLayerBlock.PacketCode &&
061                   ! "BA07" .equalsIgnoreCase ( productSymbologyLayerBlock.PacketCode ) ) { //非栅格数据 Raster Image
062               return ( false ) ;
063           }
064           boolean  ok  =  false ;
065           rasterProductBlock          =  new  RasterProductBlock () ;
066           ok  = rasterProductBlock.read ( fin ) ;
067           if rasterProductBlock.NumberOfRows >  ) {
068               rasterImageBlock    =  new  RasterImageBlock [ rasterProductBlock.NumberOfRows ] ;
069               for ( int  i= 0 ;i<rasterProductBlock.NumberOfRows;i++ ) {
070                   rasterImageBlock [ i new  RasterImageBlock () ;
071                   ok  = ok && rasterImageBlock [ i ] .read ( fin ) ;
072               }
073           }
074           return ( ok ) ;
075       }
076 
077  /**
078    * 2007-06-04增加,并在相关的类中增加 read(InputStream fin) 方法
079    *
080    * 功能:从数据流中读取多普勒栅格数据Raster,主要是考虑直接从 .tar.gz 中读取
081    * 参数:
082    *      fin     - InputStream,注意不能使用 fin.close() 方法,因为在函数外部可能还需要继续从 fin 读数据
083    * 返回值:
084    *      是否成功
085    */
086       public  boolean  read ( InputStream fin throws  Exception  {
087 
088           if (      ! "BA0F" .equalsIgnoreCase ( productSymbologyLayerBlock.PacketCode &&
089                   ! "BA07" .equalsIgnoreCase ( productSymbologyLayerBlock.PacketCode ) ) { //非栅格数据 Raster Image
090               return ( false ) ;
091           }
092           boolean  ok  =  false ;
093           rasterProductBlock          =  new  RasterProductBlock () ;
094           ok  = rasterProductBlock.read ( fin ) ;
095           if rasterProductBlock.NumberOfRows >  ) {
096               rasterImageBlock    =  new  RasterImageBlock [ rasterProductBlock.NumberOfRows ] ;
097               for ( int  i= 0 ;i<rasterProductBlock.NumberOfRows;i++ ) {
098                   rasterImageBlock [ i new  RasterImageBlock () ;
099                   ok  = ok && rasterImageBlock [ i ] .read ( fin ) ;
100                   //rasterImageBlock[i].print();
101               }
102           }
103           return ( ok ) ;
104       }
105 
106  /**
107    * 功能:绘制雷达背景图(图形区域为640*480,雷达图形区域为480*480,雷达站点信息区域为160*480)
108    * 参数:
109    *      z       - 缩放系数
110    *      g       - 图形设备
111    *      c       - 雷达中心位置
112    *      pc      - 极圈
113    *      agl     - 径线间隔,非正值则不画径线
114    *      bnd     - 省市县边界
115    * 返回值:
116    *      是否成功
117    */
118       public  boolean  drawBackground ( double  z, Graphics2D g, Point c,  boolean  pc,  double  agl,  boolean  bnd ) {
119           if z <=  0.0  ) {
120               return ( false ) ;
121           }
122           try  {
123               Polar   polar   =  new  Polar ( c,  0.001 *productDescriptionBlock.RadarLongitude,  0.001 *productDescriptionBlock.RadarLatitude ) ;
124               polar.setScale ( 1.0 *z ) ;
125               //以下两行改进线条的锯齿
126               RenderingHints renderHints =  new  RenderingHints ( RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON ) ;
127               g.setRenderingHints ( renderHints ) ;
128 
129  //          g.setColor(Color.black);//背景色
130  //          g.fillRect(c.x-(int)(z*240), c.y-(int)(z*240), (int)(z*240*2), (int)(z*240*2));
131 
132               g.setColor ( Color.white ) ; //雷达图形区域的边框颜色
133               g.drawRect ( c.x- ( int )( z* 240 ) , c.y- ( int )( z* 240 ) ( int )( z* 240 * 2 ) ( int )( z* 240 * 2 ) - 2 ) ;
134 
135               if bnd  ) { //画行政边界
136                   Coordinate  coordinate  =  new  Coordinate ( polar ) ;
137                   Diamond09.drawBorderline ( g,  new  Color ( 92 , 92 , 92 ) , coordinate,  "/GIMDR/gmiss/config/CountyMap.dat" ) ;
138                   Diamond09.drawBorderline ( g,  new  Color ( 160 , 160 , 160 ) , coordinate,  "/GIMDR/gmiss/config/ProvinceMap.dat" ) ;
139               }
140 
141               if pc  ) { //画极圈
142                   g.setColor ( new  Color ( 255 , 255 , 255 )) ;
143                   for ( int  i= 50 ;i<= 200 ;i=i+ 50 ) { //每50公里画一个圈
144                       g.drawArc ( c.x- ( int )( z*i ) , c.y- ( int )( z*i ) ( int )( z*i ) * 2 ( int )( z*i ) * 2 0 360 ) ;
145                   }
146                   g.drawArc ( c.x- ( int )( z* 240 ) , c.y- ( int )( z* 240 ) ( int )( z* 240 ) * 2 ( int )( z* 240 ) * 2 0 360 ) ; //外圈240公里
147               }
148 
149               if agl >=  1.0  ) { //画极径
150                   Point   pos1, pos2;
151                   for ( double  i= 0.0 ;i< 180.0 ;i=i+agl ) {
152                       pos1    = polar.getXY ( z* 240.0 ,    0.0 +i ) ;
153                       pos2    = polar.getXY ( z* 240.0 180.0 +i ) ;
154                       g.drawLine ( pos1.x, pos1.y, pos2.x, pos2.y ) ;
155                   }
156               }
157               return ( true ) ;
158           }
159           catch ( Exception ex ) {
160               System.out.println ( ex.getMessage ()) ;
161               ex.printStackTrace () ;
162               return ( false ) ;
163           }
164       }
165 
166  /**
167    * 功能:绘制雷达信息区域
168    * 参数:
169    *      g       - 图形设备
170    *      m       - 雷达信息区域左上角位置
171    * 返回值:
172    *      是否成功
173    */
174       public  boolean  drawInformation ( Graphics2D g, Point m ) {
175           //以下两行改进线条的锯齿
176           RenderingHints renderHints =  new  RenderingHints ( RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON ) ;
177           g.setRenderingHints ( renderHints ) ;
178           g.setColor ( Color.white ) ; //信息区域的边框颜色
179           g.drawRect ( m.x, m.y,  160 479 ) ; //住处区域的边框
180           return ( true ) ;
181       }
182 
183  /**
184    * 功能:绘制雷达产品图,根据不同类型分别调用相应的画图函数
185    * 参数:
186    *      z       - 缩放系数
187    *      g       - 图形设备
188    *      c       - 雷达中心位置
189    * 返回值:
190    *      是否成功
191    */
192       public  boolean  draw ( double  z, Graphics2D g, Point c ) {
193           return (
194               z <=  0.0  ||
195               null  == rasterProductBlock ||
196               rasterProductBlock.NumberOfRows <=  ||
197               drawRasterImage ( z, g, c )
198           ) ;
199       }
200 
201  /**
202    * 功能:绘制RasterImage栅格图像(采用多边形填充法代替弧形填充)
203    * 参数:
204    *      z       - 缩放系数
205    *      g       - 图形设备
206    *      c       - 雷达中心位置
207    * 返回值:
208    *      是否成功
209    */
210       public  boolean  drawRasterImage ( double  z, Graphics2D g, Point c ) {
211           Color []  colorRun    =  {
212               new  Color (   0 ,   0 ,   0 ) new  Color ( 156 , 156 , 156 ) new  Color ( 118 , 118 , 118 ) new  Color ( 250 , 170 , 170 ) ,
213               new  Color ( 238 , 140 , 140 ) new  Color ( 200 , 112 , 112 ) new  Color (   0 , 250 , 144 ) new  Color (   0 , 186 ,   0 ) ,
214               new  Color ( 254 , 254 , 112 ) new  Color ( 208 , 208 96 ) new  Color ( 254 96 96 ) new  Color ( 218 ,   0 ,   0 ) ,
215               new  Color ( 174 ,   0 ,   0 ) new  Color (   0 ,   0 , 254 ) new  Color ( 254 , 254 , 254 ) new  Color ( 230 ,   0 , 254 )
216           } ;
217  //      Polar   polar   = new Polar(c, 0.001*productDescriptionBlock.RadarLongitude, 0.001*productDescriptionBlock.RadarLatitude);
218  //      polar.setScale(1.0);
219  //背景
220           //以下两行改进线条的锯齿
221           RenderingHints renderHints =  new  RenderingHints ( RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON ) ;
222           g.setRenderingHints ( renderHints ) ;
223 
224           Point   pos =  new  Point ( rasterProductBlock.CoordinateStartI, rasterProductBlock.CoordinateStartJ ) ;
225           Polygon p   =  new  Polygon () ;
226           int      iRun    = - 1 ;
227           int      iColor  = - 1 ;
228           for ( int  i= 0 ;i<rasterProductBlock.NumberOfRows;i++ ) {
229               pos.x   = rasterProductBlock.CoordinateStartI +  8 ;
230               pos.y   = rasterProductBlock.CoordinateStartJ + i * rasterProductBlock.ScaleY +  8 ;
231               for ( int  j= 0 ;j<rasterImageBlock [ i ] .NumberOfBytesInRow;j++ ) {
232                   iRun    = rasterImageBlock [ i ] .Data [ j >>  0xF ;
233                   iColor  = rasterImageBlock [ i ] .Data [ j ]       0xF ;
234                   if iColor >= && iColor <  16  ) {
235                       g.setColor ( colorRun [ iColor ]) ;
236                       g.fillRect ( pos.x, pos.y,  ( int )( iRun*rasterProductBlock.ScaleX ) , rasterProductBlock.ScaleY ) ;
237                       g.drawRect ( pos.x, pos.y,  ( int )( iRun*rasterProductBlock.ScaleX ) , rasterProductBlock.ScaleY ) ;
238                   }
239                   pos.x   = pos.x + iRun*rasterProductBlock.ScaleX;
240               }
241           }
242           return ( true ) ;
243       }
244  }

 


RasterImageBlock.java
001  /**
002    * PACKAGE     : cma.gmb.doppler.datatype
003      FILENAME    : RasterImageBlock.java
004    * DESCRIPTION : 多普勒雷达产品数据结构(Raster格式)
005    * AUTHOR      : 刘泽军
006    * EMAIL       : BJ0773@gmail.com
007    * Date        : 2007-06-07 16:24:11
008    * Update      :
009    * Reference   : 《NEXRAD LEVEL II数据格式》中文版及英文版
010    */
011 
012  package  cma.gmb.doppler.datatype;
013 
014  import  java.io.*;
015  import  java.lang.*;
016 
017  import  cma.common.dataio.*;
018 
019  public class  RasterImageBlock  { //极坐标栅格图像数据
020 
021       public  static   int  SIZE    =  2 ;
022 
023       public   short    NumberOfBytesInRow;
024       public   byte []   Data;
025 
026  /**
027    * 功能:构造函数
028    * 参数:
029    *      无
030    * 返回:
031    *      无
032    */
033       public  RasterImageBlock () {
034       }
035 
036  /**
037    * 功能:从随机文件中读取数据,并进行BigEndian转换
038    * 参数:
039    *      raf     - 随机访问的文件对象
040    * 返回:
041    *      是否成功
042    */
043       public  boolean  read ( RandomAccessFile raf ) {
044           try  {
045               byte []   buf     =  new  byte [ RasterImageBlock.SIZE ] ;
046               int      len = raf.read ( buf ) ;
047               boolean  ok  = len == RasterImageBlock.SIZE ? parse ( buf,  0 false ;
048               if ok && NumberOfBytesInRow >  ) {
049                   Data    =  new  byte [ NumberOfBytesInRow ] ;
050                   len     = raf.read ( Data ) ;
051               }
052               return ( ok && len == NumberOfBytesInRow ) ;
053           }
054           catch ( Exception ex ) {
055               return ( false ) ;
056           }
057       }
058 
059  /**
060    * 功能:从输入流文件中读取数据,并进行BigEndian转换
061    *       (主要是为了从 .tar.gz 中读取)
062    * 参数:
063    *      in      - InputStream对象
064    * 返回:
065    *      是否成功
066    */
067       public  boolean  read ( InputStream in ) {
068           try  {
069               byte []   buf =  new  byte [ RasterImageBlock.SIZE ] ;
070               int      len = in.read ( buf ) ;
071               boolean  ok  = len == RasterImageBlock.SIZE ? parse ( buf,  0 false ;
072               if ok && NumberOfBytesInRow >  ) {
073                   Data    =  new  byte [ NumberOfBytesInRow ] ;
074                   len     = in.read ( Data ) ;
075               }
076               return ( ok && len == NumberOfBytesInRow ) ;
077           }
078           catch ( Exception ex ) {
079               return ( false ) ;
080           }
081       }
082 
083  /**
084    * 功能:从缓冲区中读取数据,并进行BigEndian转换
085    * 参数:
086    *      in      - InputStream对象
087    * 返回:
088    *      是否成功
089    */
090       public  int  read ( byte []  buf,  int  index ) {
091           boolean  ok  = parse ( buf, index ) ;
092           if ok && NumberOfBytesInRow >  && buf.length >= index+NumberOfBytesInRow  ) {
093               Data    =  new  byte [ NumberOfBytesInRow ] ;
094               for ( int  i= 0 ;i<NumberOfBytesInRow;i++ ) {
095                   Data [ i = buf [ index+i ] ;
096               }
097               return ( RasterImageBlock.SIZE+NumberOfBytesInRow ) ;
098           }
099           return ( 0 ) ;
100       }
101 
102  /**
103    * 功能:从缓冲区中分析出数据
104    * 参数:
105    *      buf     - 缓冲数据
106    * 返回:
107    *      是否成功
108    */
109       public  boolean  parse ( byte []  buf ) {
110           return ( parse ( buf,  0 )) ;
111       }
112 
113  /**
114    * 功能:从缓冲区中分析出数据
115    * 参数:
116    *      buf     - 缓冲数据
117    *      index   - 偏移
118    * 返回:
119    *      是否成功
120    */
121       public  boolean  parse ( byte []  buf,  int  index ) {
122           NumberOfBytesInRow  = DataConverterBE.getShort ( buf, index+  0 ) ;
123           return ( true ) ;
124       }
125 
126  /**
127    * 功能:获得数据信息
128    * 参数:
129    *      无
130    * 返回:
131    *      数据信息
132    */
133       public  String info () {
134           String  msg =
135               "/nRasterImageBlock.SIZE  = "  + String.valueOf ( RasterImageBlock.SIZE +
136               "/n    NumberOfBytesInRow = "  + String.valueOf ( NumberOfBytesInRow +
137               "/n" ;
138  /*      for(int i=0;i<NumberOfRadialRLE*2;i++) {
139               msg = msg + String.valueOf((new Byte(Data[i])).intValue()/16)+","+String.valueOf((new Byte(Data[i])).intValue()%16)+" ";
140           }
141           msg = msg + "/n";
142  */
143           return ( msg ) ;
144       }
145  /**
146    * 功能:打印数据,主要用于测试
147    * 参数:
148    *      无
149    * 返回:
150    *      无
151    */
152       public  void  print () {
153           System.out.println ( info ()) ;
154       }
155 
156  }

 


RasterProductBlock.java
001  /**
002    * PACKAGE     : cma.gmb.doppler.datatype
003      FILENAME    : RasterProductBlock.java
004    * DESCRIPTION : 多普勒雷达产品数据结构(Raster格式)
005    * AUTHOR      : 刘泽军
006    * EMAIL       : BJ0773@gmail.com
007    * Date        : 2007-06-07 17:09:47
008    * Update      :
009    * Reference   : 《NEXRAD LEVEL II数据格式》中文版及英文版
010    */
011 
012  package  cma.gmb.doppler.datatype;
013 
014  import  java.io.*;
015  import  java.lang.*;
016 
017  import  cma.common.dataio.*;
018 
019  public class  RasterProductBlock  { //层数据包
020 
021       public  static   int  SIZE    =  20 ;
022 
023       public   String  PacketCode1;
024       public   String  PacketCode2;
025       public   short    CoordinateStartI;
026       public   short    CoordinateStartJ;
027       public   short    ScaleX;
028       public   short    ScaleFractionalX;
029       public   short    ScaleY;
030       public   short    ScaleFractionalY;
031       public   short    NumberOfRows;
032       public   short    PackingDescriptor;
033 
034  /**
035    * 功能:构造函数
036    * 参数:
037    *      无
038    * 返回:
039    *      无
040    */
041       public  RasterProductBlock () {
042       }
043 
044  /**
045    * 功能:从文件中读取数据,并进行BigEndian转换
046    * 参数:
047    *      raf     - 随机访问的文件对象
048    * 返回:
049    *      是否成功
050    */
051       public  boolean  read ( RandomAccessFile raf ) {
052           try  {
053               byte []   buf =  new  byte [ RasterProductBlock.SIZE ] ;
054               int      len = raf.read ( buf ) ;
055               return ( len == RasterProductBlock.SIZE ? parse ( buf,  0 false ) ;
056           }
057           catch ( Exception ex ) {
058               return ( false ) ;
059           }
060       }
061 
062  /**
063    * 功能:从输入流文件中读取数据,并进行BigEndian转换
064    * 参数:
065    *      in      - InputStream对象
066    * 返回:
067    *      是否成功
068    */
069       public  boolean  read ( InputStream in ) {
070           try  {
071               byte []   buf =  new  byte [ RasterProductBlock.SIZE ] ;
072               int      len = in.read ( buf ) ;
073               return ( len == RasterProductBlock.SIZE ? parse ( buf,  0 false ) ;
074           }
075           catch ( Exception ex ) {
076               return ( false ) ;
077           }
078       }
079 
080  /**
081    * 功能:从缓冲区中读数据
082    *       (在外部方法中,一次性读入所有数据,然后逐类分析数据)
083    * 参数:
084    *      buf     - 缓冲数据
085    *      index   - 偏移
086    * 返回:
087    *      正确读出的数据字节数
088    */
089       public  int  read ( byte []  buf,  int  index ) {
090           return ( parse ( buf, index ) ?RasterProductBlock.SIZE: 0 ) ;
091       }
092 
093  /**
094    * 功能:从缓冲区中分析出数据
095    * 参数:
096    *      buf     - 缓冲数据
097    * 返回:
098    *      是否成功
099    */
100       public  boolean  parse ( byte []  buf ) {
101           return ( parse ( buf,  0 )) ;
102       }
103 
104  /**
105    * 功能:从缓冲区中分析出数据
106    * 参数:
107    *      buf     - 缓冲数据
108    *      index   - 偏移
109    * 返回:
110    *      是否成功
111    */
112       public  boolean  parse ( byte []  buf,  int  index ) {
113           PacketCode1         = DataConverterBE.getHex   ( buf, index+  0 2 ) ;
114           PacketCode2         = DataConverterBE.getHex   ( buf, index+  2 2 ) ;
115           CoordinateStartI    = DataConverterBE.getShort ( buf, index+  4 ) ;
116           CoordinateStartJ    = DataConverterBE.getShort ( buf, index+  6 ) ;
117           ScaleX              = DataConverterBE.getShort ( buf, index+  8 ) ;
118           ScaleFractionalX    = DataConverterBE.getShort ( buf, index+ 10 ) ;
119           ScaleY              = DataConverterBE.getShort ( buf, index+ 12 ) ;
120           ScaleFractionalY    = DataConverterBE.getShort ( buf, index+ 14 ) ;
121           NumberOfRows        = DataConverterBE.getShort ( buf, index+ 16 ) ;
122           PackingDescriptor   = DataConverterBE.getShort ( buf, index+ 18 ) ;
123           return ( true ) ;
124       }
125 
126  /**
127    * 功能:获得数据信息
128    * 参数:
129    *      无
130    * 返回:
131    *      数据信息
132    */
133       public  String info () {
134           String  msg =
135               "/nRasterProductBlock.SIZE = "  + String.valueOf ( RasterProductBlock.SIZE +
136               "/n    PacketCode1         = "  + String.valueOf ( PacketCode1 +
137               "/n    PacketCode2         = "  + String.valueOf ( PacketCode2 +
138               "/n    CoordinateStartI    = "  + String.valueOf ( CoordinateStartI +
139               "/n    CoordinateStartJ    = "  + String.valueOf ( CoordinateStartJ +
140               "/n    ScaleX              = "  + String.valueOf ( ScaleX +
141               "/n    ScaleFractionalX    = "  + String.valueOf ( ScaleFractionalX +
142               "/n    ScaleY              = "  + String.valueOf ( ScaleY +
143               "/n    ScaleFractionalY    = "  + String.valueOf ( ScaleFractionalY +
144               "/n    NumberOfRows        = "  + String.valueOf ( NumberOfRows +
145               "/n    PackingDescriptor   = "  + String.valueOf ( PackingDescriptor +
146               "/n" ;
147           return ( msg ) ;
148       }
149 
150  /**
151    * 功能:打印数据,主要用于测试
152    * 参数:
153    *      无
154    * 返回:
155    *      无
156    */
157       public  void  print () {
158           System.out.println ( info ()) ;
159       }
160 
161  }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值