@@ -204,31 +204,30 @@ void EDIDParser::parseScreenSize()
204204{
205205 qCDebug (appLog) << " Parsing screen size from EDID" ;
206206
207- // Detailed Timing: 字节66-68 (第4行字节2-4)包含详细屏幕尺寸信息
208- // 字节66: Active Image Width低8位
209- // 字节67: Active Image Height低8位
210- // 字节68: 高4位(0xF0)=宽度高4位, 低4位(0x0F)=高度高4位
211- // 注意:大端模式下,字节位置会交换:byte 2<->3, byte 4->5
212- QString s66 = getBytes (4 , m_LittleEndianMode ? 2 : 3 ), // 宽度低8位
213- s67 = getBytes (4 , m_LittleEndianMode ? 3 : 2 ), // 高度低8位
214- s68 = getBytes (4 , m_LittleEndianMode ? 4 : 5 ); // [宽度高4位|高度高4位]
215-
216- if (!s66.isEmpty () && !s67.isEmpty () && !s68.isEmpty ()) {
217- int byte68_val = hexToDec (s68).toInt ();
218- // 宽度 = (byte68高4位 << 8) + s66
219- m_Width = ((byte68_val & 0xF0 ) << 4 ) + hexToDec (s66).toInt ();
220- // 高度 = (byte68低4位 << 8) + s67
221- m_Height = ((byte68_val & 0x0F ) << 8 ) + hexToDec (s67).toInt ();
222- }
223-
224- // edid中的 15H和16H就是屏幕大小 , 与Detailed Timing相差超10mm 则用15H和16H的。
225- int width15 = hexToDec (getBytes (1 , m_LittleEndianMode ? 5 : 4 )).toInt ()*10 ;
226- int height16 = hexToDec (getBytes (1 , m_LittleEndianMode ? 6 : 7 )).toInt ()*10 ;
227- qCDebug (appLog) << " Parsed width and height from bytes 15H/16H:" << width15 << " x" << height16;
228- if (m_Width+10 < width15 || m_Height+10 < height16) {
229- qCDebug (appLog) << " Detailed timing differs significantly, using 15H/16H values." ;
207+ parseDTDs ();
208+ // edid中的 15H和16H是基本屏幕大小(单位cm), 与 Detailed Timing 相差超10mm 则用15H和16H的。
209+ int width15 = hexToDec (getBytes (1 , m_LittleEndianMode ? 5 : 4 )).toInt () * 10 ;
210+ int height16 = hexToDec (getBytes (1 , m_LittleEndianMode ? 6 : 7 )).toInt () * 10 ;
211+ if (width15 != 0 && height16 != 0 ) {
230212 m_Width = width15;
231213 m_Height = height16;
214+ // 从所有的详细尺寸中寻找接近基本屏幕大小的值
215+ for (int i = 0 ; i < m_DTDSizeInfoList.size (); ++i) {
216+ if (abs (m_DTDSizeInfoList.at (i).width - width15) < 10
217+ && abs (m_DTDSizeInfoList.at (i).height - height16) < 10 ) {
218+ m_Width = m_DTDSizeInfoList.at (i).width ;
219+ m_Height = m_DTDSizeInfoList.at (i).height ;
220+ break ;
221+ }
222+ }
223+ } else {
224+ if (!m_DTDSizeInfoList.isEmpty ()) {
225+ m_Width = m_DTDSizeInfoList.at (0 ).width ;
226+ m_Height = m_DTDSizeInfoList.at (0 ).height ;
227+ } else {
228+ m_Width = 0 ;
229+ m_Height = 0 ;
230+ }
232231 }
233232
234233 if (Common::specialComType == Common::kSpecialType7 ){ // sepcial task:378963
@@ -237,8 +236,8 @@ void EDIDParser::parseScreenSize()
237236 }
238237 double inch = sqrt ((m_Width / 2.54 ) * (m_Width / 2.54 ) + (m_Height / 2.54 ) * (m_Height / 2.54 ))/10 ;
239238 m_ScreenSize = QString (" %1 %2(%3mm×%4mm)" )
240- .arg (QString::number (inch, ' 0' , Common::specialComType == Common::kSpecialType7 ? 0 : 1 ))
241- .arg (QObject::tr (" inch" )).arg (m_Width).arg (m_Height);
239+ .arg (QString::number (inch, ' 0' , Common::specialComType == Common::kSpecialType7 ? 0 : 1 ))
240+ .arg (QObject::tr (" inch" )).arg (m_Width).arg (m_Height);
242241 qCDebug (appLog) << " Screen size parsed:" << m_ScreenSize << " Width:" << m_Width << " Height:" << m_Height;
243242}
244243
@@ -302,6 +301,101 @@ void EDIDParser::parseMonitorName()
302301 m_MonitorName = " Unknown Monitor" ;
303302}
304303
304+ void EDIDParser::parseDTDs ()
305+ {
306+ // 清空之前的 DTD 信息列表
307+ m_DTDSizeInfoList.clear ();
308+
309+ // 基础块中最多有 4 个 DTD,起始字节为 54, 72, 90, 108
310+ for (int i = 0 ; i < 4 ; i++) {
311+ int startByte = 54 + i * 18 ;
312+ parseOneDTD (startByte, i, true );
313+ }
314+ }
315+
316+ void EDIDParser::parseOneDTD (int startByte, int dtdIndex, bool isBaseBlock)
317+ {
318+ // 字节布局(在 DTD 内的相对位置):
319+ // 字节0-1: 像素时钟(2字节,用于验证是否为有效 DTD)
320+ // 字节2-3: H Active(水平主动像素数)低字节 | H Blank
321+ // 字节4-5: V Active(垂直主动像素数)低字节 | V Blank
322+ // 字节12: Image Size Width(物理宽度)低8位
323+ // 字节13: Image Size Height(物理高度)低8位
324+ // 字节14: 高4位=宽度高4位,低4位=高度高4位
325+
326+ // 注意:在 EDID 的 16 进制字符串格式中
327+ // 每行 16 字节 = 32 个字符
328+ // 每字节 = 2 个字符
329+
330+ // 注意:大端模式下,字节位置会交换:
331+ // - 相邻字节对会交换(如 byte12 <-> byte13)
332+ // - byte14 会变成 byte15
333+
334+ // 计算 DTD 内的字节位置对应的 EDID 位置
335+ int line = startByte / 16 ;
336+ int byteInLine = startByte % 16 ;
337+
338+ // 获取像素时钟(字节0-1),用于验证 DTD 是否有效
339+ // 大端模式下字节0和字节1交换
340+ QString pixelClockByte0 = getBytes (line, m_LittleEndianMode ? byteInLine : byteInLine + 1 );
341+ QString pixelClockByte1 = getBytes (line, m_LittleEndianMode ? byteInLine + 1 : byteInLine);
342+
343+ if (pixelClockByte0.isEmpty () || pixelClockByte1.isEmpty ()) {
344+ return ;
345+ }
346+
347+ int pixelClockLow = hexToDec (pixelClockByte0).toInt ();
348+ int pixelClockHigh = hexToDec (pixelClockByte1).toInt ();
349+ int pixelClock = pixelClockLow + (pixelClockHigh << 8 );
350+
351+ // 如果像素时钟为 0,说明这不是一个有效的 DTD
352+ if (pixelClock == 0 ) {
353+ return ;
354+ }
355+
356+ // 获取物理尺寸信息
357+ // 字节12: 宽度低8位
358+ // 字节13: 高度低8位
359+ // 字节14: 高4位=宽度高位,低4位=高度高位
360+ // 大端模式下:byte12 <-> byte13 交换,byte14 -> byte15
361+
362+ int byte12Pos = m_LittleEndianMode ? (startByte + 12 ) : (startByte + 13 );
363+ int byte13Pos = m_LittleEndianMode ? (startByte + 13 ) : (startByte + 12 );
364+ int byte14Pos = m_LittleEndianMode ? (startByte + 14 ) : (startByte + 15 );
365+
366+ int lineWidthByte12 = byte12Pos / 16 ;
367+ int byteInLineWidthByte12 = byte12Pos % 16 ;
368+
369+ int lineWidthByte13 = byte13Pos / 16 ;
370+ int byteInLineWidthByte13 = byte13Pos % 16 ;
371+
372+ int lineWidthByte14 = byte14Pos / 16 ;
373+ int byteInLineWidthByte14 = byte14Pos % 16 ;
374+
375+ QString s12 = getBytes (lineWidthByte12, byteInLineWidthByte12); // 宽度低8位
376+ QString s13 = getBytes (lineWidthByte13, byteInLineWidthByte13); // 高度低8位
377+ QString s14 = getBytes (lineWidthByte14, byteInLineWidthByte14); // [宽度高4位|高度高4位]
378+
379+ if (s12.isEmpty () || s13.isEmpty () || s14.isEmpty ()) {
380+ return ;
381+ }
382+
383+ int byte14_val = hexToDec (s14).toInt ();
384+ // 宽度(mm) = (byte14高4位 << 8) + s12
385+ int width = ((byte14_val & 0xF0 ) << 4 ) + hexToDec (s12).toInt ();
386+ // 高度(mm) = (byte14低4位 << 8) + s13
387+ int height = ((byte14_val & 0x0F ) << 8 ) + hexToDec (s13).toInt ();
388+
389+ // 保存 DTD 尺寸信息
390+ DTDSizeInfo info;
391+ info.dtdIndex = dtdIndex;
392+ info.width = width;
393+ info.height = height;
394+ info.isBaseBlock = isBaseBlock;
395+
396+ m_DTDSizeInfoList.append (info);
397+ }
398+
305399QString EDIDParser::binToDec (QString strBin) // 二进制转十进制
306400{
307401 // qCDebug(appLog) << "Converting binary to decimal";
0 commit comments