视音频数据处理入门:颜色空间(一)---转换理解

2023-10-28 18:50

本文主要是介绍视音频数据处理入门:颜色空间(一)---转换理解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、YUV颜色空间

概述 

I420的理解

YV12的理解

NV12的理解

NV21的理解

YV12​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​与I420颜色空间相互转换

转换代码

NV12与I420颜色空间相互转换

转换代码

NV21与YV12颜色空间相互转换

转换代码

二、YUV转RGB

概述 

RGB32的理解

RGB24的理解

I420与RGB32颜色空间相互转换

转换代码

I420与RGB24颜色空间相互转换

转换代码

 三、代码路径


​​​​​​​

一、YUV颜色空间

概述 

 简单说一下I420、YV12、NV12、NV21的颜色空间排列方式,更容易理解它们直接相互方式。对于I420、YV12、NV12、NV21四中格式都属于YUV 4:2:0的的排列方式,我的理解是4个Y分量公用一个U和V分量。

I420的理解

I420(YU12)属于YUV420P又称YUV420plane平面模式;Y、U、V分别在不同平面,也就是有三个平面,它是YUV标准格式4:2:0,且与YV12同属于YUV420P;对于I420的图像上排列方式如图-I420(1),首先是Y分量的排布,排布Y分量的宽为图像的宽(W),Y分量的高为图像的高(H);  其次是U分量的排布,排布U分量的宽为图像的宽的一半(W/2),U分量的高为图像的高(H/2);再次是V分量的排布,排布V分量的宽与U分量一致,分别为图像的宽的一半(W/2)和图像的高(H/2)。Y分量、U分量、V分量依次排列。

Y0Y1Y2Y3Y4Y5Y6Y7
Y8Y9Y10Y11Y12Y13Y14Y15
Y16Y17Y18Y19Y20Y21Y22Y23
Y24Y25Y26Y27Y28Y29Y30Y31
U0U1U2U3U4U5U6U7
V0V1V2V3V4V5V6V7

                                                                   图-I420(1)

 如 图-I420(1)红色部分Y0、Y1、Y8、Y9共用U0和V0分量;依次类推,对应颜色的Y分量共用对应颜色的U和V分量。

i420的内存排列,如图-I420(2),依次是Y分量、U分量、V分量;

其中Y分量内存大小为:

Y分量buff_size = W * H ;

其中U分量内存大小为:

U分量buff_size = W/2 * H/2 ,即W * H /4 ;

其中V分量内存大小为:

V分量buff_size = W/2 * H/2 ,即W * H /4 ;

i420图像大小 = Y分量大小 + U分量大小 +V分量大小

即:

i420图像大小 =W * H *3/2

                                                 图-I420(2)

YV12的理解

YV12属于YUV420P又称YUV420plane平面模式;Y、U、V分别在不同平面,也就是有三个平面,它是YUV标准格式4:2:0,且与(I420)YU12同属于YUV420P;对于YV12的图像上排列方式如图-YV12(1),首先是Y分量的排布,排布Y分量的宽为图像的宽(W),Y分量的高为图像的高(H);  其次是U分量的排布,排布U分量的宽为图像的宽的一半(W/2),U分量的高为图像的高(H/2);再次是V分量的排布,排布V分量的宽与U分量一致,分别为图像的宽的一半(W/2)和图像的高(H/2)。Y分量、U分量、V分量依次排列。

Y0Y1Y2Y3Y4Y5Y6Y7
Y8Y9Y10Y11Y12Y13Y14Y15
Y16Y17Y18Y19Y20Y21Y22Y23
Y24Y25Y26Y27Y28Y29Y30Y31
V0V1V2V3V4V5V6V7
U0U1U2U3U4U5U6U7

                                                               图-YV12(1)

 如 图-YV12(1)红色部分Y0、Y1、Y8、Y9共用U0和V0分量;依次类推,对应颜色的Y分量共用对应颜色的U和V分量。

YV12的内存排列,如图-YV12(2),依次是Y分量、U分量、V分量;

其中Y分量内存大小为:

Y分量buff_size = W * H ;

其中U分量内存大小为:

U分量buff_size = W/2 * H/2 ,即W * H /4 ;

其中V分量内存大小为:

V分量buff_size = W/2 * H/2 ,即W * H /4 ;

YV12图像大小 = Y分量大小 + U分量大小 +V分量大小

即:

YV12图像大小 =W * H *3/2

                                                     图-YV12(2)

NV12的理解

 NV12属于YUV420SP,即Y和UV分为两个Plane,但是UV为交错存储,而不是分为三个plane。对于NV12的图像上排列方式如图-NV12(1),首先是Y分量的排布,排布Y分量的宽为图像的宽(W),Y分量的高为图像的高(H);  其次是UV分量的交错排布。Y分量、UV分量依次排列。

Y0Y1Y2Y3Y4Y5Y6Y7
Y8Y9Y10Y11Y12Y13Y14Y15
Y16Y17Y18Y19Y20Y21Y22Y23
Y24Y25Y26Y27Y28Y29Y30Y31
U0V0U1V1U2V2U3V3
U4V4U5V5U6V6U7V7

                                                         图-NV12(1)

如 图-NV12(1)红色部分Y0、Y1、Y8、Y9共用U0和V0分量;依次类推,对应颜色的Y分量共用对应颜色的U和V分量。

NV12的内存排列,如图-NV12(2),依次是Y分量、U分量、V分量;

其中Y分量内存大小为:

Y分量buff_size = W * H ;

其中U分量内存大小为:

U分量buff_size = W/2 * H/2 ,即W * H /4 ;

其中V分量内存大小为:

V分量buff_size = W/2 * H/2 ,即W * H /4 ;

NV12图像大小 = Y分量大小 + U分量大小 +V分量大小

即:

YV12图像大小 =W * H *3/2

                                               图-NV12(2)

NV21的理解

 NV21属于YUV420SP,即Y和UV分为两个Plane,但是VU为交错存储,而不是分为三个plane。对于NV21的图像上排列方式如图-NV21(1),首先是Y分量的排布,排布Y分量的宽为图像的宽(W),Y分量的高为图像的高(H);  其次是VU分量的交错排布。Y分量、VU分量依次排列。

NV21与NV12 本质区别是V和U的先后区别。

Y0Y1Y2Y3Y4Y5Y6Y7
Y8Y9Y10Y11Y12Y13Y14Y15
Y16Y17Y18Y19Y20Y21Y22Y23
Y24Y25Y26Y27Y28Y29Y30Y31
V0U0V1U1V2U2V3U3
V4U4V5U5V6U6V7U7

                                                                        图-NV21(1)

如 图-NV21(1)红色部分Y0、Y1、Y8、Y9共用U0和V0分量;依次类推,对应颜色的Y分量共用对应颜色的U和V分量。

YV12的内存排列,如图-NV21(2),依次是Y分量、U分量、V分量;

其中Y分量内存大小为:

Y分量buff_size = W * H ;

其中U分量内存大小为:

U分量buff_size = W/2 * H/2 ,即W * H /4 ;

其中V分量内存大小为:

V分量buff_size = W/2 * H/2 ,即W * H /4 ;

NV21图像大小 = Y分量大小 + U分量大小 +V分量大小

即:

NV21​​​​​​​图像大小 =W * H *3/2

​​​​​​​

                                            图-NV21(2)

YV12​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​与I420颜色空间相互转换

由YV12和I420的内存排列可知,Y的排列方式是相同的,不同的是U和V的排列;YV12的排列依次是Y 、V 、U ;而I420的排列顺序依次是Y 、U 、V。由此可见只要改变U、V的排列顺序即可实现YV12与I420的相互转换。

转换代码

int YV12_2_I420(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_u = src + width * height;uint8_t* src_v = src + width * height * 5 / 4;uint8_t* dst_y = dst;uint8_t* dst_v = dst + width * height;uint8_t* dst_u = dst + width * height * 5 / 4;memcpy(dst_y, src_y, width * height);memcpy(dst_v, src_v, width * height / 4);memcpy(dst_u, src_u, width * height / 4);return 0;
}int I420_2_YV12(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_u = src + width* height;uint8_t* src_v = src + width * height*5/4;uint8_t* dst_y = dst;uint8_t* dst_v = dst + width * height;uint8_t* dst_u = dst + width * height * 5 / 4;memcpy(dst_y, src_y, width * height);memcpy(dst_v, src_v, width * height/4);memcpy(dst_u, src_u, width * height/4);return 0;
}

NV12与I420颜色空间相互转换

由NV12和I420的内存排列可知,Y的排列方式是相同的,不同的是U和V的排列;NV12的U、V是交错式排列排列顺序依次是Y、UV排列。而I420的U、V依次排序。由此可见只要改变U、V的排列顺序即可实现NV12与I420的相互转换。

转换代码

int I420_2_NV12(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_u = src + width * height;uint8_t* src_v = src + width * height * 5 / 4;uint8_t* dst_y = dst;uint8_t* dst_uv = dst + width * height;memcpy(dst_y, src_y, width * height);//UV交错排列for (int i = 0; i < width / 2 * height / 2; i++){dst_uv[2*i] = src_u[i];dst_uv[2 * i+1] = src_v[i];}return 0;
}int NV21_2_YV12(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_uv = src + width * height;uint8_t* dst_y = dst;uint8_t* dst_v = dst + width * height;uint8_t* dst_u = dst + width * height * 5 / 4;memcpy(dst_y, src_y, width * height);//UV交错排列for (int i = 0; i < width / 2 * height / 2; i++){dst_v[i] = src_uv[2 * i];dst_u[i] = src_uv[2 * i + 1];}return 0;
}

NV21与YV12颜色空间相互转换

由NV12和YV12的内存排列可知,Y的排列方式是相同的,不同的是U和V的排列;NV12的U、V是交错式排列排列顺序依次是Y、UV排列。而YV12的U、V依次排序。由此可见只要改变U、V的排列顺序即可实现NV12与I420的相互转换。基本与I420转换一样。

转换代码

int NV21_2_YV12(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_uv = src + width * height;uint8_t* dst_y = dst;uint8_t* dst_v = dst + width * height;uint8_t* dst_u = dst + width * height * 5 / 4;memcpy(dst_y, src_y, width * height);for (int i = 0; i < width / 2 * height / 2; i++){dst_v[i] = src_uv[2 * i];dst_u[i] = src_uv[2 * i + 1];}return 0;
}int YV12_2_NV21(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_v = src + width * height;uint8_t* src_u = src + width * height * 5 / 4;uint8_t* dst_y = dst;uint8_t* dst_uv = dst + width * height;memcpy(dst_y, src_y, width * height);for (int i = 0; i < width / 2 * height / 2; i++){dst_uv[2 * i] = src_v[i];dst_uv[2 * i + 1] = src_u[i];}return 0;
}

二、YUV转RGB

概述 

RGB32与RGB24整体排列方式是一致,RGB32比RGB24多了一个预留位。也称做A通道。

RGB32的理解

RGB32由图-RGB32(1)可以看出来,R、G、B、A组成一个像素点;同事一个像素点占4个字节;R、G、B、A是交错排列的。

R0G0B0A0R1G1B1A1R2G2B2A2R3G3B3A3R4G4B4A4R5G5B5A5R6G6B6A6R7G7B7A7
R8G8B8A8R9G9B9A9R10G10B10A10R11G11B11A11R12G12B12A12R13G13B13A13R14G14B14A14R15G15B15A15
R16G16B16A16R17G17B17A17R18G18B18A18R19G19B19A19R20G20B20A20R21G21B21A21R22G22B22A22R23G23B23A23
R24G24B24A24R25G25B25A25R26G26B26A26R27G27B27A27R28G28B28A28R29G29B29A29R30G30B30A30R31G31B31A31

                                                                                                                                                    图-RGB32(1)

RGB24的理解

RGB32由图-RGB24(1)可以看出来,R、G、B组成一个像素点;同事一个像素点占3个字节;R、G、B是交错排列的。

R0G0B0R1G1B1R2G2B2R3G3B3R4G4B4R5G5B5R6G6B6R7G7B7
R8G8B8R9G9B9R10G10B10R11G11B11R12G12B12R13G13B13R14G14B14R15G15B15
R16G16B16R17G17B17R18G18B18R19G19B19R20G20B20R21G21B21R22G22B22R23G23B23
R24G24B24R25G25B25R26G26B26R27G27B27R28G28B28R29G29B29R30G30B30R31G31B31

                                                                                                                                           图-RGB24(1)

I420与RGB32颜色空间相互转换

I420与RGB32相互转换不同于yuv的转换。I420 2行共用一个U分量和V分量。所以RGB转yuv的时候应该注意排列方式。

转换代码

typedef  struct  RGB32 {uint8_t     rgbBlue;       // 蓝色分量uint8_t     rgbGreen;      // 绿色分量uint8_t     rgbRed;        // 红色分量uint8_t     rgbReserved;   // 保留字节(用作Alpha通道或忽略)RGB32(){rgbBlue = 0;rgbGreen = 0;rgbRed = 0;rgbReserved = 0;}
} RGB32;int I420_2_rgb32(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_u = src + width * height;uint8_t* src_v = src + width * height * 5 / 4;RGB32* prgb = reinterpret_cast<RGB32*>(dst);int rgbindex = 0;for (int y = 0; y < height; y++){for (int x = 0; x < width; x++){RGB32* rgbNode = &prgb[rgbindex];//读取YUVuint8_t Y = src_y[y * width + x];uint8_t U = src_u[y / 2 * width / 2 + x / 2];uint8_t V = src_v[y / 2 * width / 2 + x / 2];//计算rgbint tmpr = Y + 1.402 * (V - 128);int tmpg = Y - 0.34413 * (U - 128) - 0.71414 * (V - 128);int tmpb = Y + 1.772 * (U - 128);//越界保护rgbNode->rgbRed = tmpr > 255 ? 255 : (tmpr < 0 ? 0 : tmpr);rgbNode->rgbGreen =tmpg > 255 ? 255 : (tmpg < 0 ? 0 : tmpg);rgbNode->rgbBlue = tmpb > 255 ? 255 : (tmpb < 0 ? 0 : tmpb);rgbindex++;}}return 0;
}int rgb32_2_I420(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{RGB32* prgb = reinterpret_cast<RGB32*>(src);uint8_t* dst_y = dst;uint8_t* dst_u = dst + width * height;uint8_t* dst_v = dst + width * height * 5 / 4;//Y = 0.298R + 0.612G + 0.117B;//U = -0.168R - 0.330G + 0.498B + 128;//V = 0.449R - 0.435G - 0.083B + 128;int rgbindex = 0;int u_index = 0;int v_index = 0;int y_index = 0;for (int y = 0; y < height; y++){for (int x = 0; x < width; x++){rgbindex = y * width + x;RGB32* rgbNode = &prgb[rgbindex];//Y = 0.298R + 0.612G + 0.117B;int tmp_y = 0.298*rgbNode->rgbRed + 0.612 * rgbNode->rgbGreen + 0.117*rgbNode->rgbBlue;dst_y[y_index] = tmp_y > 255 ? 255 : (tmp_y < 0 ? 0 : tmp_y);y_index++;if (y%2 ==0 &&x%2 == 0){//U = -0.168R - 0.330G + 0.498B + 128;int tmp_u = -0.168 * rgbNode->rgbRed - 0.330 * rgbNode->rgbGreen + 0.498 * rgbNode->rgbBlue + 128;//V = 0.449R - 0.435G - 0.083B + 128;int tmp_v = 0.449 * rgbNode->rgbRed - 0.435 * rgbNode->rgbGreen + 0.083 * rgbNode->rgbBlue + 128;dst_u[u_index] = tmp_u > 255 ? 255 : (tmp_u < 0 ? 0 : tmp_u);dst_v[v_index] = tmp_v > 255 ? 255 : (tmp_v < 0 ? 0 : tmp_v);v_index++;u_index++;}}}return 0;
}

I420与RGB24颜色空间相互转换

rgb24与rgb32计算方式基本一致。却别在于rgb32每个像素点4字节;gb24每个像素点3字节。

转换代码

typedef  struct  RGB24 {uint8_t     rgbBlue;       // 蓝色分量uint8_t     rgbGreen;      // 绿色分量uint8_t     rgbRed;        // 红色分量RGB24(){rgbBlue = 0;rgbGreen = 0;rgbRed = 0;}
} RGB24;int I420_2_rgb24(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_u = src + width * height;uint8_t* src_v = src + width * height * 5 / 4;RGB24* prgb = reinterpret_cast<RGB24*>(dst);int rgbindex = 0;for (int y = 0; y < height; y++){for (int x = 0; x < width; x++){RGB24* rgbNode = &prgb[rgbindex];//读取YUVuint8_t Y = src_y[y * width + x];uint8_t U = src_u[y / 2 * width / 2 + x / 2];uint8_t V = src_v[y / 2 * width / 2 + x / 2];//计算rgb//R = Y + 1.4075(V - 128);//G = Y - 0.3455(U - 128) - 0.7169(V - 128);//B = Y + 1.779(U - 128);int tmpr = Y + 1.402 * (V - 128);int tmpg = Y - 0.34413 * (U - 128) - 0.71414 * (V - 128);int tmpb = Y + 1.772 * (U - 128);//越界保护rgbNode->rgbRed = tmpr > 255 ? 255 : (tmpr < 0 ? 0 : tmpr);rgbNode->rgbGreen = tmpg > 255 ? 255 : (tmpg < 0 ? 0 : tmpg);rgbNode->rgbBlue = tmpb > 255 ? 255 : (tmpb < 0 ? 0 : tmpb);rgbindex++;}}return 0;
}int rgb24_2_I420(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{RGB24* prgb = reinterpret_cast<RGB24*>(src);uint8_t* dst_y = dst;uint8_t* dst_u = dst + width * height;uint8_t* dst_v = dst + width * height * 5 / 4;//Y = 0.298R + 0.612G + 0.117B;//U = -0.168R - 0.330G + 0.498B + 128;//V = 0.449R - 0.435G - 0.083B + 128;int rgbindex = 0;int u_index = 0;int v_index = 0;int y_index = 0;for (int y = 0; y < height; y++){for (int x = 0; x < width; x++){rgbindex = y * width + x;RGB24* rgbNode = &prgb[rgbindex];//Y = 0.298R + 0.612G + 0.117B;int tmp_y = 0.298 * rgbNode->rgbRed + 0.612 * rgbNode->rgbGreen + 0.117 * rgbNode->rgbBlue;dst_y[y_index] = tmp_y > 255 ? 255 : (tmp_y < 0 ? 0 : tmp_y);y_index++;if (y % 2 == 0 &&x % 2 == 0){//U = -0.168R - 0.330G + 0.498B + 128;int tmp_u = -0.168 * rgbNode->rgbRed - 0.330 * rgbNode->rgbGreen + 0.498 * rgbNode->rgbBlue + 128;//V = 0.449R - 0.435G - 0.083B + 128;int tmp_v = 0.449 * rgbNode->rgbRed - 0.435 * rgbNode->rgbGreen + 0.083 * rgbNode->rgbBlue + 128;dst_u[u_index] = tmp_u > 255 ? 255 : (tmp_u < 0 ? 0 : tmp_u);dst_v[v_index] = tmp_v > 255 ? 255 : (tmp_v < 0 ? 0 : tmp_v);v_index++;u_index++;}}}return 0;
}

 三、代码路径

csdn:https://download.csdn.net/download/u011645307/21113273

github:https://github.com/liangqidong/ColorConversion.git

这篇关于视音频数据处理入门:颜色空间(一)---转换理解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/295220

相关文章

python实现svg图片转换为png和gif

《python实现svg图片转换为png和gif》这篇文章主要为大家详细介绍了python如何实现将svg图片格式转换为png和gif,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录python实现svg图片转换为png和gifpython实现图片格式之间的相互转换延展:基于Py

C#实现将Excel表格转换为图片(JPG/ PNG)

《C#实现将Excel表格转换为图片(JPG/PNG)》Excel表格可能会因为不同设备或字体缺失等问题,导致格式错乱或数据显示异常,转换为图片后,能确保数据的排版等保持一致,下面我们看看如何使用C... 目录通过C# 转换Excel工作表到图片通过C# 转换指定单元格区域到图片知识扩展C# 将 Excel

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

使用Python开发一个带EPUB转换功能的Markdown编辑器

《使用Python开发一个带EPUB转换功能的Markdown编辑器》Markdown因其简单易用和强大的格式支持,成为了写作者、开发者及内容创作者的首选格式,本文将通过Python开发一个Markd... 目录应用概览代码结构与核心组件1. 初始化与布局 (__init__)2. 工具栏 (setup_t

深入理解Apache Kafka(分布式流处理平台)

《深入理解ApacheKafka(分布式流处理平台)》ApacheKafka作为现代分布式系统中的核心中间件,为构建高吞吐量、低延迟的数据管道提供了强大支持,本文将深入探讨Kafka的核心概念、架构... 目录引言一、Apache Kafka概述1.1 什么是Kafka?1.2 Kafka的核心概念二、Ka

Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码

《Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码》:本文主要介绍Java中日期时间转换的多种方法,包括将Date转换为LocalD... 目录一、Date转LocalDateTime二、Date转LocalDate三、LocalDateTim

Python实现AVIF图片与其他图片格式间的批量转换

《Python实现AVIF图片与其他图片格式间的批量转换》这篇文章主要为大家详细介绍了如何使用Pillow库实现AVIF与其他格式的相互转换,即将AVIF转换为常见的格式,比如JPG或PNG,需要的小... 目录环境配置1.将单个 AVIF 图片转换为 JPG 和 PNG2.批量转换目录下所有 AVIF 图

详解如何通过Python批量转换图片为PDF

《详解如何通过Python批量转换图片为PDF》:本文主要介绍如何基于Python+Tkinter开发的图片批量转PDF工具,可以支持批量添加图片,拖拽等操作,感兴趣的小伙伴可以参考一下... 目录1. 概述2. 功能亮点2.1 主要功能2.2 界面设计3. 使用指南3.1 运行环境3.2 使用步骤4. 核

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义