Sample Aspect Ratio

本文详细介绍了SampleAspectRatio(SAR)的概念及其在视频处理中的应用。包括如何根据图像尺寸和显示长宽比计算SAR,以及在不同场景下如何正确设置SAR以避免图像失真。
引用:
1. Sample Aspect Ratio

* What is it?

The Sample Aspect Ratio (SAR) (sometimes called Pixel Aspect Ratio or just
Pel Aspect Ratio) is defined as the ratio of the width of the sample to the
height of the sample. While pixels on a computer monitor generally are
"square" meaning that their SAR is 1:1, digitized video usually has rather
odd SARs. Playback of material with a particular SAR on a system with
a different SAR will result in a stretched/squashed image. A correction is
necessary that relies on the knowledge of both SARs.

* How do I use it?

You can derive the SAR of an image from the width, height and the
display aspect ratio (DAR) of the image as follows:

SAR_x     DAR_x * height
-------- = --------------------
SAR_y     DAR_y * width

for example:
width x height = 704x576, DAR = 4:3 ==> SAR = 2304:2112 or 12:11

Please note that if your material is a digitized analog signal, you should
not use this equation to calculate the SAR. 

* Should I use this option?

In one word: yes. Most decoders/ media players nowadays support automatic
correction of aspect ratios, and there are just few exceptions. You should
even use it, if the SAR of your material is 1:1, as the default of x264 is
"SAR not defined".

译文:
引用:

1. Sample Aspect Ratio (参照长宽比 or 样本长宽比 - -!用中文真不好表达...)

* sar是什么?

Sample Aspect Ratio (SAR)(有时被称为Pixel Aspect Ratio或 just Pel Aspect Ratio)定义了样本(sample)的宽相对于高的比值,而电脑显示器中的像素(Pixel)往往是“正方形”的(我们的显示器是由点阵组成的,1024x768相当于横向有1024个点,纵向有768个点,所以说,图像的分辨率越高,画面越细腻,原因就是点变小了,我们的眼睛感觉不到它的存在了),它们的sar是1:1,而数据化的视频往往有一个odd sar,在一个系统上,素材的播放是根据特定的sar来的,不同的sar会导致图像的拉伸或者挤压,一个校正值是必须的,它依赖于两者的SAR必须是已知的(就是说,必须知道原始SAR和目标SAR,才能计算这个校正值)

* 我该怎么使用它?

你可以根据图像的宽,高以及display aspect ratio (DAR)[显示长宽比,就是你想让它在播放的时候有效图像显示的长宽比]来计算出sar,参考以下公式:

SAR_x     DAR_x * height
-------- = --------------------
SAR_y     DAR_y * width

举个例子:

宽(横向) x 高(纵向) = 704x576, DAR = 4:3 ==> SAR = 2304:2112 or 12:11

注意,如果你的素材是一个数字化的模拟信号,你不应该使用这个公式去计算sar

* 我该如何去使用这个选项?

引用一句话:是的。大部分的解码器/播放器 都支持自动校正长宽比,但也有少数例外。你甚至可以这样使用它,如果你的素材SAR是1:1,用x264默认值"SAR not defined"(- -!补上X264命令行用法--sar x:y )


OK,看完以上理论,你应该大致明白sar的计算方法了,下面来说说16:9DVD RIP成4:3后还原为16:9的方法

假如我把正统的可变形DVD 720x480 RIP成640x480,而我在播放的时候想重新拉伸成16:9

代入公式:
代码:
SAR_x   16 * 480           4 
----- = -------------- = ----- = 1.33333333333333...
SAR_y   9  * 640           3

公式解释:
输出高X比例宽                                                                                              480X16
------------------ =sar值     例如转一个720X480的16:9的视屏,根据公式得sar=----------=32:27
输出宽X比例高                                                                                              720X9

为什么psp中的480P的sar为40:33?原因psp只能显示704x480的视屏,720中的16像素被sony裁去,所以要以704X480代入公式计算,最后得出sar为40:33

但是每次都要人工计算sar,所以共享下面一个计算sar的小工具共大家使用

x264中sar计算工具.zip

5.37 KB, 下载次数: 170

/*---------------------------------------------------------------------- | AP4_AvcFrameParser::ParseHrd +---------------------------------------------------------------------*/ AP4_Result AP4_AvcFrameParser::ParseHrd(AP4_BitReader& bits, AP4_HrdParameterSet& hrd) { hrd.cpb_cnt_minus1 = ReadGolomb(bits); if (hrd.cpb_cnt_minus1 >= 32) { DBG_PRINTF_1("hrd.cpb_cnt_minus1[%d] >= 32\n", hrd.cpb_cnt_minus1); return AP4_ERROR_INVALID_FORMAT; } hrd.bit_rate_scale = bits.ReadBits(4); hrd.cpb_size_scale = bits.ReadBits(4); for (unsigned int i = 0; i <= hrd.cpb_cnt_minus1; i++) { hrd.bit_rate_value_minus1[i] = ReadGolomb(bits); hrd.cpb_size_value_minus1[i] = ReadGolomb(bits); hrd.cbr_flag[i] = bits.ReadBit(); } hrd.initial_cpb_removal_delay_length_minus1 = bits.ReadBits(5); hrd.cpb_removal_delay_length_minus1 = bits.ReadBits(5); hrd.dpb_output_delay_length_minus1 = bits.ReadBits(5); hrd.time_offset_length = bits.ReadBits(5); return AP4_SUCCESS; } /*---------------------------------------------------------------------- | AP4_AvcFrameParser::ParseVui +---------------------------------------------------------------------*/ AP4_Result AP4_AvcFrameParser::ParseVui(AP4_BitReader& bits, AP4_VuiParameterSet& vui) { vui.aspect_ratio_info_present_flag = bits.ReadBit(); if (vui.aspect_ratio_info_present_flag) { vui.aspect_ratio_idc = bits.ReadBits(8); // Appendix E. Table E-1 Meaning of sample aspect ratio indicator if (vui.aspect_ratio_idc == 255/*Extended_SAR*/) { vui.sar_width = bits.ReadBits(16); vui.sar_height = bits.ReadBits(16); } } vui.overscan_info_present_flag = bits.ReadBit(); if (vui.overscan_info_present_flag) { vui.overscan_appropriate_flag = bits.ReadBit(); } vui.video_signal_type_present_flag = bits.ReadBit(); if (vui.video_signal_type_present_flag) { vui.video_format = bits.ReadBits(3); vui.video_full_range_flag = bits.ReadBit(); vui.colour_description_present_flag = bits.ReadBit(); if (vui.colour_description_present_flag) { vui.colour_primaries = bits.ReadBits(8); vui.transfer_characteristics = bits.ReadBits(8); vui.matrix_coefficients = bits.ReadBits(8); } } vui.chroma_loc_info_present_flag = bits.ReadBit(); if (vui.chroma_loc_info_present_flag) { vui.chroma_sample_loc_type_top_field = ReadGolomb(bits); vui.chroma_sample_loc_type_bottom_field = ReadGolomb(bits); } vui.timing_info_present_flag = bits.ReadBit(); if (vui.timing_info_present_flag) { vui.num_units_in_tick = bits.ReadBits(32); vui.time_scale = bits.ReadBits(32); vui.fixed_frame_rate_flag = bits.ReadBit(); } vui.nal_hrd_parameters_present_flag = bits.ReadBit(); if (vui.nal_hrd_parameters_present_flag) { AP4_Result result = ParseHrd(bits, vui.nal_hrd); if (AP4_FAILED(result)) { return result; } } vui.vcl_hrd_parameters_present_flag = bits.ReadBit(); if (vui.vcl_hrd_parameters_present_flag) { AP4_Result result = ParseHrd(bits, vui.vcl_hrd); if (AP4_FAILED(result)) { return result; } } if (vui.nal_hrd_parameters_present_flag || vui.vcl_hrd_parameters_present_flag) { vui.low_delay_hrd_flag = bits.ReadBit(); } vui.pic_struct_present_flag = bits.ReadBit(); vui.bitstream_restriction_flag = bits.ReadBit(); if (vui.bitstream_restriction_flag) { vui.motion_vectors_over_pic_boundaries_flag = bits.ReadBit(); vui.max_bytes_per_pic_denom = ReadGolomb(bits); vui.max_bits_per_mb_denom = ReadGolomb(bits); vui.log2_max_mv_length_horizontal = ReadGolomb(bits); vui.log2_max_mv_length_vertical = ReadGolomb(bits); vui.num_reorder_frames = ReadGolomb(bits); vui.max_dec_frame_buffering = ReadGolomb(bits); } return AP4_SUCCESS; } 注释上述代码
09-24
/*---------------------------------------------------------------------- | AP4_HevcVuiParameterSet::AP4_HevcVuiParameterSet +---------------------------------------------------------------------*/ AP4_Result AP4_HevcVuiParameterSet::Parse(AP4_BitReader& bits) { aspect_ratio_info_present_flag = bits.ReadBit(); if (aspect_ratio_info_present_flag) { aspect_ratio_idc = bits.ReadBits(8); // Appendix E. Table E-1 Meaning of sample aspect ratio indicator if (aspect_ratio_idc == 255/*Extended_SAR*/) { sar_width = bits.ReadBits(16); sar_height = bits.ReadBits(16); } } overscan_info_present_flag = bits.ReadBit(); if (overscan_info_present_flag) { overscan_appropriate_flag = bits.ReadBit(); } video_signal_type_present_flag = bits.ReadBit(); if (video_signal_type_present_flag) { video_format = bits.ReadBits(3); video_full_range_flag = bits.ReadBit(); colour_description_present_flag = bits.ReadBit(); if (colour_description_present_flag) { colour_primaries = bits.ReadBits(8); transfer_characteristics = bits.ReadBits(8); matrix_coefficients = bits.ReadBits(8); } } chroma_loc_info_present_flag = bits.ReadBit(); if (chroma_loc_info_present_flag) { chroma_sample_loc_type_top_field = ReadGolomb(bits); chroma_sample_loc_type_bottom_field = ReadGolomb(bits); } neutral_chroma_indication_flag = bits.ReadBit(); field_seq_flag = bits.ReadBit(); frame_field_info_present_flag = bits.ReadBit(); default_display_window_flag = bits.ReadBit(); if (default_display_window_flag) { def_disp_win_left_offset = ReadGolomb(bits); def_disp_win_right_offset = ReadGolomb(bits); def_disp_win_top_offset = ReadGolomb(bits); def_disp_win_bottom_offset = ReadGolomb(bits); } timing_info_present_flag = bits.ReadBit(); if (timing_info_present_flag) { num_units_in_tick = bits.ReadBits(32); time_scale = bits.ReadBits(32); vui_poc_proportional_to_timing_flag = bits.ReadBit(); if (vui_poc_proportional_to_timing_flag) { vui_num_ticks_poc_diff_one_minus1 = ReadGolomb(bits); } } return AP4_SUCCESS; } /*---------------------------------------------------------------------- | AP4_HevcPictureParameterSet::AP4_HevcPictureParameterSet +---------------------------------------------------------------------*/ AP4_HevcPictureParameterSet::AP4_HevcPictureParameterSet() : pps_pic_parameter_set_id(0), pps_seq_parameter_set_id(0), dependent_slice_segments_enabled_flag(0), output_flag_present_flag(0), num_extra_slice_header_bits(0), sign_data_hiding_enabled_flag(0), cabac_init_present_flag(0), num_ref_idx_l0_default_active_minus1(0), num_ref_idx_l1_default_active_minus1(0), init_qp_minus26(0), constrained_intra_pred_flag(0), transform_skip_enabled_flag(0), cu_qp_delta_enabled_flag(0), diff_cu_qp_delta_depth(0), pps_cb_qp_offset(0), pps_cr_qp_offset(0), pps_slice_chroma_qp_offsets_present_flag(0), weighted_pred_flag(0), weighted_bipred_flag(0), transquant_bypass_enabled_flag(0), tiles_enabled_flag(0), entropy_coding_sync_enabled_flag(0), num_tile_columns_minus1(0), num_tile_rows_minus1(0), uniform_spacing_flag(1), loop_filter_across_tiles_enabled_flag(0), pps_loop_filter_across_slices_enabled_flag(0), deblocking_filter_control_present_flag(0), deblocking_filter_override_enabled_flag(0), pps_deblocking_filter_disabled_flag(0), pps_beta_offset_div2(0), pps_tc_offset_div2(0), pps_scaling_list_data_present_flag(0), lists_modification_present_flag(0), log2_parallel_merge_level_minus2(0), slice_segment_header_extension_present_flag(0) { } /*---------------------------------------------------------------------- | AP4_HevcPictureParameterSet::Parse +---------------------------------------------------------------------*/ AP4_Result AP4_HevcPictureParameterSet::Parse(const unsigned char* data, unsigned int data_size) { raw_bytes.SetData(data, data_size); AP4_DataBuffer unescaped(data, data_size); AP4_NalParser::Unescape(unescaped); AP4_BitReader bits(unescaped.GetData(), unescaped.GetDataSize()); bits.SkipBits(16); // NAL Unit Header pps_pic_parameter_set_id = ReadGolomb(bits); if (pps_pic_parameter_set_id > AP4_HEVC_PPS_MAX_ID) { DBG_PRINTF_2("pps_pic_parameter_set_id[%d] > AP4_HEVC_PPS_MAX_ID[%d]\n", pps_pic_parameter_set_id, AP4_HEVC_PPS_MAX_ID); return AP4_ERROR_INVALID_FORMAT; } pps_seq_parameter_set_id = ReadGolomb(bits); if (pps_seq_parameter_set_id > AP4_HEVC_SPS_MAX_ID) { DBG_PRINTF_2("pps_seq_parameter_set_id[%d] > AP4_HEVC_SPS_MAX_ID[%d]\n", pps_seq_parameter_set_id, AP4_HEVC_SPS_MAX_ID); return AP4_ERROR_INVALID_FORMAT; } dependent_slice_segments_enabled_flag = bits.ReadBit(); output_flag_present_flag = bits.ReadBit(); num_extra_slice_header_bits = bits.ReadBits(3); sign_data_hiding_enabled_flag = bits.ReadBit(); cabac_init_present_flag = bits.ReadBit(); num_ref_idx_l0_default_active_minus1 = ReadGolomb(bits); num_ref_idx_l1_default_active_minus1 = ReadGolomb(bits); init_qp_minus26 = SignedGolomb(ReadGolomb(bits)); constrained_intra_pred_flag = bits.ReadBit(); transform_skip_enabled_flag = bits.ReadBit(); cu_qp_delta_enabled_flag = bits.ReadBit(); if (cu_qp_delta_enabled_flag) { diff_cu_qp_delta_depth = ReadGolomb(bits); } pps_cb_qp_offset = SignedGolomb(ReadGolomb(bits)); pps_cr_qp_offset = SignedGolomb(ReadGolomb(bits)); pps_slice_chroma_qp_offsets_present_flag = bits.ReadBit(); weighted_pred_flag = bits.ReadBit(); weighted_bipred_flag = bits.ReadBit(); transquant_bypass_enabled_flag = bits.ReadBit(); tiles_enabled_flag = bits.ReadBit(); entropy_coding_sync_enabled_flag = bits.ReadBit(); if (tiles_enabled_flag) { num_tile_columns_minus1 = ReadGolomb(bits); num_tile_rows_minus1 = ReadGolomb(bits); uniform_spacing_flag = bits.ReadBit(); if (!uniform_spacing_flag) { for (unsigned int i=0; i<num_tile_columns_minus1; i++) { ReadGolomb(bits); // column_width_minus1[i] } for (unsigned int i = 0; i < num_tile_rows_minus1; i++) { ReadGolomb(bits); // row_height_minus1[i] } } loop_filter_across_tiles_enabled_flag = bits.ReadBit(); } pps_loop_filter_across_slices_enabled_flag = bits.ReadBit(); deblocking_filter_control_present_flag = bits.ReadBit(); if (deblocking_filter_control_present_flag) { deblocking_filter_override_enabled_flag = bits.ReadBit(); pps_deblocking_filter_disabled_flag = bits.ReadBit(); if (!pps_deblocking_filter_disabled_flag) { pps_beta_offset_div2 = SignedGolomb(ReadGolomb(bits)); pps_tc_offset_div2 = SignedGolomb(ReadGolomb(bits)); } } pps_scaling_list_data_present_flag = bits.ReadBit(); if (pps_scaling_list_data_present_flag) { scaling_list_data(bits); } lists_modification_present_flag = bits.ReadBit(); log2_parallel_merge_level_minus2 = ReadGolomb(bits); slice_segment_header_extension_present_flag = bits.ReadBit(); return AP4_SUCCESS; } 详细注释上述代码
09-25
### 使用方法 `aspect-ratio` 属性用于设置元素的宽高比,其使用方式是在CSS中为元素指定该属性,并设置相应的宽高比数值。可以使用分数形式,如 `2 / 1.732` 或 `16 / 9` 。 示例1:强制锁定宽高比,创建六边形容器 ```css .hex-container { width: 10vw; aspect-ratio: 2 / 1.732; /* 近似 2 : √3 */ background: #2c3e50; clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%); } ``` 示例2:让图片和视频在响应式设计中保持 16:9 的宽高比 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> img, video { max-width: 100%; /* 保持 16:9 的宽高比 */ aspect-ratio: 16 / 9; object-fit: cover; } </style> </head> <body> <img src="https://picsum.photos/800/450" alt="Sample Image"> <video controls> <source src="your-video.mp4" type="video/mp4"> Your browser does not support the video tag. </video> </body> </html> ``` 示例3:结合 `max-width`/`max-height` 限制极值 ```css .responsive-video { width: 100%; aspect-ratio: 16/9; max-height: 500px; /* 高度上限 */ } ``` ### 兼容性 截至目前,`aspect-ratio` 属性在现代浏览器中得到了广泛支持,包括 Chrome、Firefox、Safari、Edge 等主流浏览器。不过,在一些较旧的浏览器版本中可能不支持该属性,在使用时需要考虑目标用户群体所使用的浏览器情况,必要时提供替代方案。 ### 应用场景 - **响应式设计**:在响应式设计中,图片和视频经常需要根据屏幕大小自适应。使用 `aspect-ratio` 可以确保它们在不同尺寸下保持正确的比例,避免内容变形[^2]。 - **自定义形状元素**:可以通过 `aspect-ratio` 结合 `clip-path` 等属性,创建具有特定宽高比的自定义形状元素,如六边形等[^1]。 - **限制元素尺寸**:结合 `max-width`/`max-height` 等属性,在保持宽高比的同时,对元素的最大尺寸进行限制,避免元素过大影响页面布局[^4]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值