PGM格式图像详解及处理方法

ROS开发实践(十三)——ROS中SLAM地图(.pgm格式)编辑软件的安装与使用 一、应用背景 在ROS机器人通过SLAM算法构建好场景地图之后,为了保证ROS机器人的运行效果,我们通常会对场景地图进行修改,这里所说的场景地图通常为 .pgm 格式的文件,如下图所示。 二、地图的编辑与修改 1. ... 阅读详情

摘自:http://blog.youkuaiyun.com/gamer_gerald/archive/2007/06/08/1643623.aspx

 NET framework框架类库中的Image类和Bitmap类提供了常用图像格式的解析读取和存储,这些常用格式包括BMP,JEPG,GIF,PNG,EXIF,TIFF.但是可惜的是不支持PGM格式,我们要自己来处理PGM格式的文件.

1.PGM图像详解

PGM 是便携式灰度图像格式(portable graymap file format),在黑白超声图像系统中经常使用PGM格式的图像.文件的后缀名为".pgm",PGM格式图像格式分为两类:P2和P5类型.不管是P2还是P5类型的PGM文件,都由两部分组成,文件头部分和数据部分.

文件头部分

文件头包括的信息依次是:

1.PGM文件的格式类型(是P2还是P5);

2.图像的宽度;

3.图像的高度;

4.图像灰度值可能的最大值;

文件头的这四部分信息都是以ASCII码形式存储的,所以可以直接在将P2或P5格式的PGM文件在记事本中打开看到文件头的信息.

P5格式的PGM文件在记事本中打开(如下图)

P2格式的PGM文件在记事本中打开(如下图)

在P2或P5类型的PGM文件头的4个信息之间用分割符分开,PGM的合法分隔符包括:空格,TAB,回车符,换行符.PGM文件头的信息应该由合法分割符号分开,如上面两幅图所展.文件头的第4个信息,图像灰度值可能的最大值标明了文件数据部分可能出现的像素灰度值的最大值.上面两幅图都是指定的255,所以在数据区的像素数据取值范围在0到255.

数据部分

数据部分记录图像每个像素的灰度值,按照图像从上到下,从左到右的顺序依次存储每个像素的灰度值.对于像素灰度值的表示P2格式和P5格式有所不同.

P5格式

P5格式的文件,每个像素用可以用二进制表示.比如有一幅P5格式图像,灰度值可能的最大值为255,它的第一行第一列像素值为100,那么该图像每个像素使用一个字节表示,第一行第一列为数值为100的二进制一个字节表示.如果这副图灰度值可能的最大值是65535,那么它的第一行第一列为数值为100的二进制两个字节表示(因为表示到65535需要两个字节).每个像素数据之间没有间隔的连续存储,图像一行信息结束后从下一行第一列继续,两行图像数据之间也没有间隔的连续存储,直到将图像的所有信息表示完.因为是以二进制表示,所以数据部分在记事本中打开后看到的将会是乱码.

P2格式

P2格式的文件,每个像素使用字符串来表示,比如一副P2格式图像,灰度值可能的最大值为255,它的第一行第一列像素值为100,那么该图像图像每个像素使用3个ASCII字符表示,第一行第一列数据为ASII表示的"100".不同于P5格式,每个像素数据之间需要用一个空格符分开存储,在图像的每一行数据结束时需要换行.还有一点需要注意,P2格式文件数据部分当数据超过70个字节的时候,会自动换行.也就是说图像的每一行数据末尾,或者存储时超过70个字节时,需要进行换行.

如下图所示,这是一个P2格式的PGM文件在Visual Studio中查看的效果.我们可以看到,每超过70个自己时候需要换行,在图像数据一行结束时候也需要换行(在0 1 1 1结束后,图像第一行数据结束换行).

 

2.PGM图像处理方法

在清楚了PGM内部具体结构后,下面就可以对它进行处理了.因为我们实验室经常布置图像处理程序,由于都是超声设备上方面的图像处理,所以都是PGM格式的图像.于是我便将对PGM文件的操作自己写了类来进行实现,我是使用的C#语言来做的.如果有朋友也有这样的需要,欢迎使用我所贴出的代码.

代码如下,代码后面有说明, 

using  System;
using
 System.Collections.Generic;
using
 System.Text;
using
 System.IO;

namespace
 ImageHomeWork6
{
    
public enum PGMType { P2 , P5 , UNKOWN }
;

    
public class
 UnKonwPGMTypeException : Exception
    
{ }


    
public class PGMInformation
    
{
        
private PGMType type =
 PGMType.UNKOWN;
        
public
 PGMType Type
        
{
            
get { return type; }

            
set { type = value; }
        }


        
private UInt32 width;
        
public
 UInt32 Width
        
{
            
get { return width; }

            
set
            
{
                width 
=
 value;
                pixelCount 
= Convert.ToInt32(width *
 height);
            }

        }


        
private UInt32 height;
        
public
 UInt32 Height
        
{
            
get { return height; }

            
set 
            
{
                height 
=
 value;
                pixelCount 
= Convert.ToInt32(width *
 height);
            }

        }


        
private int pixelCount;
        
public int
 PixelCount
        
{
            
get { return pixelCount; }
            
        }


        
private byte grayMax;
        
public byte
 GrayMax
        
{
            
get { return grayMax; }

            
set { grayMax = value; }
        }


        
private byte[] pgmByteData = null;
        
public byte
[] PgmByteData
        
{
            
get { return pgmByteData; }

            
set { pgmByteData = value; }
        }


        
private string[,] pgmStringData = null;
        
public string
[,] PgmStringData
        
{
            
get { return pgmStringData; }

            
set { pgmStringData = value; }
        }


        
static private PGMInformation pgmInformation;
        
static public
 PGMInformation PGMinformationInstance
        
{
            
get

            
{
                
if (pgmInformation == null
)
                    pgmInformation 
= new
 PGMInformation();

                
return
 pgmInformation;
            }

        }


    }


    
public class PgmFileUtil
    
{
        
public
 PgmFileUtil()
        
{
            data 
=
 PGMInformation.PGMinformationInstance;
        }


        
private FileStream fileStream = null;
        
private BinaryReader binaryReader = null
;
        
private StreamReader stringReader = null
;

        
private BinaryWriter binaryWriter = null
;        
        
private StreamWriter stringWriter = null
;

        
private
 PGMInformation data;
        
public
 PGMInformation Data
        
{
            
get { return data; }

            
set { data = value; }
        }


        
static private PgmFileUtil instance = null;
        
static public
 PgmFileUtil Instance
        
{
            
get
 
            
{
                
if (instance == null
)
                    instance 
= new
 PgmFileUtil();
                
return
 instance;
            }

        }


        
public void LoadPgmFile(string path)
        
{
            fileStream 
= new
 FileStream(path, FileMode.Open);
            stringReader 
= new
 StreamReader(fileStream);

            
string typeHead =
 stringReader.ReadLine();
            
string sizeHead =
 stringReader.ReadLine();
            
if (typeHead[1] == '5'
)
            
{
                data.Type 
=
 PGMType.P5;
            }

            
else
            
{
                
if (typeHead[1] == '2'
)
                
{
                    data.Type 
=
 PGMType.P2;
                }

                
else
                
{
                    data.Type 
=
 PGMType.UNKOWN;
                    
throw new
 UnKonwPGMTypeException ();
                    
return
;
                }

            }

            
int midPosit = 0;
            
for (int posit = 0; posit < sizeHead.Length; posit++
)
            
{
                
if (sizeHead[posit] == ' '
)
                
{
                    midPosit 
=
 posit;
                    
break
;
                }

            }


            
if (midPosit == 0)
            
{
                data.Width 
=
 Convert.ToUInt32(sizeHead);
                sizeHead 
= null
;
                sizeHead 
=
 stringReader.ReadLine();
                data.Height 
=
 Convert.ToUInt32(sizeHead);
            }

            
else
            
{
                StringBuilder sizeHead2 
= new
 StringBuilder();
                
for(int posit = 0 ; posit < midPosit ; posit++
)
                
{
                    sizeHead2.Append(sizeHead[posit]);
                }

                data.Width 
= Convert.ToUInt32(sizeHead2.ToString());

                sizeHead2 
= new
 StringBuilder();
                
for (int posit = midPosit; posit < sizeHead.Length; posit++
)
                
{
                    sizeHead2.Append(sizeHead[posit]);
                }

                data.Height 
= Convert.ToUInt32(sizeHead2.ToString());
            }


            
string grayMax = stringReader.ReadLine();
            data.GrayMax 
=
 Convert.ToByte(grayMax);
           

            
if (data.Type ==
 PGMType.P5)
            
{                                
                binaryReader 
= new
 BinaryReader(fileStream);

                data.PgmByteData 
= new byte
[data.PixelCount];
                binaryReader.Read(data.PgmByteData, 
0
, data.PixelCount);

                stringReader.Close();
                binaryReader.Close();               
            }


            
if (data.Type == PGMType.P2)
            
{
                
                data.PgmStringData 
= new string
[data.Height,data.Width];
                data.PgmByteData 
= new byte
[data.PixelCount];
                
char
[] temp0, temp;
                
int lineLength = 0
;

                
for (int row = 0; row < data.Height; row++
)
                
{
                    
for (int col = 0; col < data.Width; col++
)
                    
{
                       

                        
if (row == 3&& col == 0x12
)
                           col 
=
 col;
                        temp0 
= new char[4
];
                        stringReader.Read(temp0, 
0, 4
);
                        lineLength 
+= 4
;

                        
int posit = 0
;
                        
for (int i = 0; i < 4; i++
)
                        
{
                            
if (temp0[i] == ' '
)
                            
{
                                posit 
=
 i;
                                
break
;
                            }

                        }


                        temp 
= new char[posit];
                        
for (int i = 0; i < posit; i++
)
                        
{
                            temp[i] 
=
 temp0[i];
                        }


                        data.PgmStringData[row, col] 
= new String(temp);
                        data.PgmByteData[row 
* data.Width + col] =

                            Convert.ToByte(data.PgmStringData[row, col]);



                        
if (lineLength >= 70)
                        
{
                            stringReader.Read();
                            lineLength 
= 0
;
                            
if (col == (data.Width - 1
))
                                
continue
;
                        }

                        
if (col == (data.Width - 1))
                        
{
                            stringReader.Read();
                            lineLength 
= 0
;
                        }

                    }

                }

            }




            
            
            fileStream.Close();

        }



    }

}

 

类PgmFileUtil是需要来进行PGM图像操作的类,这是一个Singleton的类,直接使用该类的LoadPgmFile方法可以读入P5和P2格式的PGM文件.在PgmFileUtil类里面有一个类型为PGMInformation的Data属性字段.该字段里面含有读入的PGM文件格式(P2,P5或Unkown),图像宽度,图像高度,灰度可能最大值.还有用字节流的图像数据和字符串流的图像数据.

唉,终于写完了,其实真是满简单的东西,希望对大家有帮助.我自己搞忘了的时候,也可以看看,发现自己记忆力也不如以前好了^_^

下周星期六(6月23日)就要考六级了,努力吧,希望这次自己考个好成绩吧,因为我是个好人啊,这也是最后一次考六级了,以后要把时间话到其它的英语考试上了.希望所有的六级考友都可以考到自己期望的分数.

I just believe there is nothing impossible to a willing heart. No pain, no gain......

使用GIMP 处理 PGM 格式ROS地图 PGM (Portable Gray Map) 是一种常见的灰度图像格式,特别在机器人地图、科学成像等领域广泛应用。 阅读详情

相关推荐

告别BMP!手把手教你将OpenMV4截图快速转成PGM模板(附在线转换工具)

本文详细介绍了如何将OpenMV4的BMP截图快速转换为PGM模板,以优化数字识别效果。通过解析PGM格式的优势、提供多种转换方法(包括在线工具、Python脚本和命令行工具)以及验证调试技巧,帮助开发者高效完成图像识别项目。

weixin_30367873的博客 448

pgm格式文件

PGM是Portable Gray Map的缩写,它是灰度图像格式中一种最简单的格式标准。PGM由两部分数据组成,分别是文件头部分和数据部分。 文件头部分 文件头包括的信息依次是: 1.PGM文件的格式类型(是P2还是P5); 2.图像的宽度; 3.图像的高度; 4.图像灰度值可能的最大值; 文件头的这四部分信息都是以ASCII码形式存储的,所以可以直接在将P2或P5格式的PGM文件在记事本中打开看到文件头的信息。 PGM文件头的4个信息之间用分割符分开,PGM的合法分隔符包括:空格,TAB

white_nights的博客 1万+

激光slam-- .pgm格式地图分析及修改方法

激光slam大部分算法基于ROS运行,生成的地图有map.pgm和map.yaml两个格式的文件。其中2D栅格地图的具体信息都存在这个.pgm格式文件中。下面详细之: .yaml格式文件 内容: image: /home/ggy/map.pgm resolution: 0.050000 origin: [-10.000000, -10.000000, 0.000000] negate: 0 occupied_thresh: 0.65 free_thresh: 0.196 .pgm格式 Window

GGY1102的博客 1万+

【Python】读取显示pgm图像文件

这学期要学多媒体信息隐藏对抗,发现其中的图像数据集文件都是pgm文件形式的。虽然是图像文件,但是却不能直接通过图像查看器来打开,上网一搜:”如何打开pgm文件?“多半是使用第三方软件photoshop之类的。都是能写代码的人了,难道为了看几张图片还要下一个几G软件吗?至此,我就开始考虑如何使用python读取pgm(Portable Gray Map)文件并显示出来。

HYY的博客 3931

pgm格式文件及其在matlab中的读取存储方法(2)

pgm图片格式再matlab里的导入与处理;matlab中imread函数所能处理的图片格式。

ds1231h的博客 8641

PPM、PGM、PBM图像格式剖析

本文首发在我的个人博客:https://jlice.top/p/7l2u9/。欢迎大家前去参观,么么哒~ 今天突然需要用到PPM这个图像文件格式,之前没见过,在此记录一下。 PPM、PGM、PBM这三个图像文件格式很少见,其实也不难,分别用于彩色图像、灰度图像、二值图像。这里以PPM格式为例。 PPM格式有两种类型:字节码和ASCII。前者是二进制文件,后者是纯文本文件。 使用convert...

文剑木然的专栏 3038

PictureStudio开发笔记03-PGM格式图像详解及处理方法

NET framework框架类库中的Image类和Bitmap类提供了常用图像格式的解析读取和存储,这些常用格式包括BMP,JEPG,GIF,PNG,EXIF,TIFF.但是可惜的是不支持PGM格式,我们要自己来处理PGM格式的文件. 1.PGM图像详解 PGM 是便携式灰度图像格式(portable graymap file format),在黑白超声图像系统中经常使...

weixin_34302561的博客 166

pgm图像修改java_【转】 PGM图像处理方法详解

机器学习中人脸识别程序中要用到的PGM图像格式说明NET framework框架类库中的Image类和Bitmap类提供了常用图像格式的解析读取和存储,这些常用格式包括 BMP,JEPG,GIF,PNG,EXIF,TIFF.但是可惜的是不支持PGM格式,我们要自己来处理PGM格式的文件.1.PGM 图像详解PGM 是便携式灰度图像格式(portable graymap file format),在...

weixin_29424607的博客 523

机器人地图后处理实战:栅格地图清理、标注与格式转换工具链解析

在机器人导航与定位系统中,SLAM建图完成后往往只是起点,原始栅格地图通常带有噪点、重影和未知区域,直接用于路径规划会导致定位偏差或决策失误。理解地图的像素坐标系与YAML元数据是处理地图的基础,其中分辨率、原点坐标和占据阈值直接影响物理空间映射。一个轻量级的地图后处理工具链,能够高效完成噪点清理、边界修正、语义标注和格式转换等关键操作,在仓储AMR、巡检机器人等实际场景中大幅降低人工修图成本。本文从地图数据模型出发,解析了地图读写、坐标换算、噪点分类处理、标注数据结构等核心细节,并分享了实操流程与排错经验

weixin_28273593的博客 320

ROS | PGM格式地图文件详解

ROS PGM格式文件详解   PGM,portable graymap file format,译为便携式灰度图像文件格式。由两部分组成,文件头部分和数据部分。此外,PGM还分为P2和P5两种不同的格式。 文件头包括如下信息: 1.PGM文件的格式类型; 2.图像的宽度; 3.图像的高度; 4.图像灰度值的可能的最大值;   文件头的这四部分信息都是以ASCII码形式存储的,所以可以直接将PGM格式的文件在记事本中打开看到文件头的信息。 数据部分   数据部分记录图像每个像素的灰度值,按照图像从上到下,从

九七的博客 4750

泛微E9开发 明细表字段赋值到主表字段,将各类型合计赋值到主表类型合计中

①绑定明细表类型、预计金额字段的值改变事件,每当有值发生改变,就需要重新计算供应商1、供应商2、供应商3的合计,如果不绑定这两个字段的话,会出现计算不及时或计算错误的问题。②当有明细行被删除时,也需要重新计算供应商1、供应商2、供应商3的合计,比如删除了供应商1的明细行,如果不重新计算,那么供应商1的值还是被删之前的值,合计错误。将各类型合计赋值到主表类型合计中。

a_waste_only的博客 3835

PGM格式图像详解

NET framework框架类库中的Image类和Bitmap类提供了常用图像格式的解析读取和存储,这些常用格式包括BMP,JEPG,GIF,PNG,EXIF,TIFF.但是可惜的是不支持PGM格式,但是只要知道了PGM格式的文件的组织结构,相信要解析他也不是难事了. 1.PGM图像详解 PGM 是便携式灰度图像格式(portable graymap file format),在黑白

xl928471061的博客 3522

保姆级教程如何进行本地局域网布署openclaw小龙虾

全网唯一一篇一步步实战教程,图文并茂方式的方式教你如何本地部署安装小龙虾openclaw

zzw17wei的专栏 1467

[多媒体] PGM格式图像详解

转: PGM格式图像详解_xiaoxin_ling的专栏-优快云博客NET framework框架类库中的Image类和Bitmap类提供了常用图像格式的解析读取和存储,这些常用格式包括BMP,JEPG,GIF,PNG,EXIF,TIFF.但是可惜的是不支持PGM格式,但是只要知道了PGM格式的文件的组织结构,相信要解析他也不是难事了.1.PGM图像详解PGM 是便携式灰度图像格式(portable graymap file format),在黑白超声图像https://blog.youkuaiyun.com/xi

ykun089的博客 1456

新能源车主必看:用高德API+充电站数据制作跨城出行充电规划工具(附完整代码)

本文为新能源车主提供了一份详细的跨城出行充电规划工具构建指南。通过整合高德地图API与充电站数据,手把手教你使用Python开发一个智能规划系统,可自动规划路线并推荐沿途充电站,有效缓解里程焦虑。文章包含完整代码、核心算法解析及可视化实现,帮助车主实现个性化、高效的出行规划。

tgb3456789的博客 899

Zephyr RTOS -- 学习笔记总述

文章目录摘要1. 开发基础部分2. 内核服务入门 本笔记基于 Zephyr 版本 2.6.0-rc2 摘要 1. 开发基础部分 2. 内核服务入门 2.1 线程简介 2.2 线程 2.3 工作队列线程 2.4 调度 2.5 中断 2.6 轮询 API 2.7 信号量

思想给了我们太多的自由,而我们拖累了思想...... 4824

对pgm格式图片的批量格式转换(pgm)

在图像处理的过程中,数据集中往往出现pgm、jpg、bmp等格式的图像,对于pgm图像无法预览打开,对数据集的浏览造成了一定的困难。这里以base-boss数据集为例,将10000张pgm图片批量转化为bmp、jpg等格式。

weixin_45843913的博客 4312

Hodgkin-Huxley Model

介绍了经典的动力学模型:HH Model

weixin_73557167的博客 2474

pgm格式图片

PGM(Portable Graymap Format)是一种便携式灰度图像格式,属于Netpbm图像格式家族。它支持ASCII文本(P2)和二进制(P5)两种存储模式,文件结构简单明了,包含文件头(标识符、尺寸、灰度极值)和像素数据。PGM格式因跨平台兼容性强、易于解析等特点,被广泛应用于计算机视觉算法测试、科学数据可视化和图像处理教学。主流图像处理库(如PIL、OpenCV)均支持PGM文件的读写操作,使其成为处理灰度图像的理想选择。

doubleintfloat的博客 1649

基于龙虾Claw的会议纪要自动提取与重点内容总结办公场景实践

本文介绍如何使用龙虾Claw构建会议纪要自动提取与重点内容总结系统,实现会议内容的智能处理。

一键难忘的博客 253

PLC为西门子的S7-1200,舵机为 DS3218,PLC控制舵机旋转程序实现?

🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。

**My Coding Family** 998

PGM 格式图像数据操作

1、结构定义 struct stPGMImage { int width; // 宽 int height; // 高 int type; // 类型 int maxraw; // 最大像素 unsigned char* data;// 数据 }; 2、文件读取 struct stPGMImage* OpenPGM(char* filename) { FILE* fp; if ((fp = fopen(filename, "rb")) == NULL) { printf("re

老狼的专栏 1245

Jenkins部署前后端分离项目最全图文教程(手把手教学)

最近Jenkins部署的热度比较高,于是就想出一篇关于我是如何使用Jenkins部署前后端分离项目的,本篇记录了我是如何一步一步去配置、搭建和部署的完整流程,每一行代码都进行了实测和讲解,通过图文的教学写成博客分享给大家!

黄团团的个人博客 4779

pgm图像修改java_PGM图片格式与代码

这两天在搞神经网络,里面的一个人脸数据库的图片格式是PGM,事实上之前早就知道了这个图片格式,可是没去深究这个图片格式的数据究竟是什么安排的。搜索了下百度百科,发现介绍的真是简单,以下就自己来系统地整理一下。PGM是Portable Gray Map的缩写。它是灰度图像格式中一种最简单的格式标准。另外两种与之相近的图片格式是PBM和PPM。它们分别相应着黑白图像和彩色图像。PGM的数据存放方式相比...

weixin_36381252的博客 731

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

[图像处理] PPM、PGM、PBM图像格式剖析

PBM头部用P1和P4分别表示ASCII类型和字节码类型,但没有像PPM第3行的最大值,ASCII类型的像素值都是0或1。最开始的50 36对应ASCII为P6,31 33 30 35对应ASCII为1305。第1行是P3,第2行是图像大小,第3行是最大值,一般是255。从第4行起就是每个像素的颜色值了,像素顺序一般是从左到右、从上到下,通道顺序一般是RGB。PPM、PGM、PBM这三个图像文件格式很少见,其实也不难,分别用于彩色图像、PPM格式有两种类型:字节码和ASCII。这里以PPM格式为例。

stm32stu的博客 1718

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

PGM檔案格式

PGM檔案格式PGM檔案格式參考連結 PGM檔案格式 PGM全文Portable Gray Map,是一種圖片檔案格式。PGM圖像包含了以下幾個元素: 一個magic number,代表檔案格式。PGM圖片的magic number是"P5"這兩個字元。 空白符(空格,tab,CR,LF) 寬度(W),用ASCII字元表示 空白符 高度(H),用ASCII字元表示 空白符 最大灰度值(Maxva...

keineahnung2345的博客 831

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

上一篇: 各种视频格式的详细介绍
下一篇: PGM文件格式
SearchLife
博客等级 码龄20年 51粉丝 22原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值