162306a36Sopenharmony_ci.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci.. _crop: 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci***************************************************** 662306a36Sopenharmony_ciImage Cropping, Insertion and Scaling -- the CROP API 762306a36Sopenharmony_ci***************************************************** 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci.. note:: 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci The CROP API is mostly superseded by the newer :ref:`SELECTION API 1262306a36Sopenharmony_ci <selection-api>`. The new API should be preferred in most cases, 1362306a36Sopenharmony_ci with the exception of pixel aspect ratio detection, which is 1462306a36Sopenharmony_ci implemented by :ref:`VIDIOC_CROPCAP <VIDIOC_CROPCAP>` and has no 1562306a36Sopenharmony_ci equivalent in the SELECTION API. See :ref:`selection-vs-crop` for a 1662306a36Sopenharmony_ci comparison of the two APIs. 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciSome video capture devices can sample a subsection of the picture and 1962306a36Sopenharmony_cishrink or enlarge it to an image of arbitrary size. We call these 2062306a36Sopenharmony_ciabilities cropping and scaling. Some video output devices can scale an 2162306a36Sopenharmony_ciimage up or down and insert it at an arbitrary scan line and horizontal 2262306a36Sopenharmony_cioffset into a video signal. 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ciApplications can use the following API to select an area in the video 2562306a36Sopenharmony_cisignal, query the default area and the hardware limits. 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci.. note:: 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci Despite their name, the :ref:`VIDIOC_CROPCAP <VIDIOC_CROPCAP>`, 3062306a36Sopenharmony_ci :ref:`VIDIOC_G_CROP <VIDIOC_G_CROP>` and :ref:`VIDIOC_S_CROP 3162306a36Sopenharmony_ci <VIDIOC_G_CROP>` ioctls apply to input as well as output devices. 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ciScaling requires a source and a target. On a video capture or overlay 3462306a36Sopenharmony_cidevice the source is the video signal, and the cropping ioctls determine 3562306a36Sopenharmony_cithe area actually sampled. The target are images read by the application 3662306a36Sopenharmony_cior overlaid onto the graphics screen. Their size (and position for an 3762306a36Sopenharmony_cioverlay) is negotiated with the :ref:`VIDIOC_G_FMT <VIDIOC_G_FMT>` 3862306a36Sopenharmony_ciand :ref:`VIDIOC_S_FMT <VIDIOC_G_FMT>` ioctls. 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ciOn a video output device the source are the images passed in by the 4162306a36Sopenharmony_ciapplication, and their size is again negotiated with the 4262306a36Sopenharmony_ci:ref:`VIDIOC_G_FMT <VIDIOC_G_FMT>` and :ref:`VIDIOC_S_FMT <VIDIOC_G_FMT>` 4362306a36Sopenharmony_ciioctls, or may be encoded in a compressed video stream. The target is 4462306a36Sopenharmony_cithe video signal, and the cropping ioctls determine the area where the 4562306a36Sopenharmony_ciimages are inserted. 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ciSource and target rectangles are defined even if the device does not 4862306a36Sopenharmony_cisupport scaling or the :ref:`VIDIOC_G_CROP <VIDIOC_G_CROP>` and 4962306a36Sopenharmony_ci:ref:`VIDIOC_S_CROP <VIDIOC_G_CROP>` ioctls. Their size (and position 5062306a36Sopenharmony_ciwhere applicable) will be fixed in this case. 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci.. note:: 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci All capture and output devices that support the CROP or SELECTION 5562306a36Sopenharmony_ci API will also support the :ref:`VIDIOC_CROPCAP <VIDIOC_CROPCAP>` 5662306a36Sopenharmony_ci ioctl. 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ciCropping Structures 5962306a36Sopenharmony_ci=================== 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci.. _crop-scale: 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci.. kernel-figure:: crop.svg 6562306a36Sopenharmony_ci :alt: crop.svg 6662306a36Sopenharmony_ci :align: center 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci Image Cropping, Insertion and Scaling 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci The cropping, insertion and scaling process 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ciFor capture devices the coordinates of the top left corner, width and 7562306a36Sopenharmony_ciheight of the area which can be sampled is given by the ``bounds`` 7662306a36Sopenharmony_cisubstructure of the struct :c:type:`v4l2_cropcap` returned 7762306a36Sopenharmony_ciby the :ref:`VIDIOC_CROPCAP <VIDIOC_CROPCAP>` ioctl. To support a wide 7862306a36Sopenharmony_cirange of hardware this specification does not define an origin or units. 7962306a36Sopenharmony_ciHowever by convention drivers should horizontally count unscaled samples 8062306a36Sopenharmony_cirelative to 0H (the leading edge of the horizontal sync pulse, see 8162306a36Sopenharmony_ci:ref:`vbi-hsync`). Vertically ITU-R line numbers of the first field 8262306a36Sopenharmony_ci(see ITU R-525 line numbering for :ref:`525 lines <vbi-525>` and for 8362306a36Sopenharmony_ci:ref:`625 lines <vbi-625>`), multiplied by two if the driver 8462306a36Sopenharmony_cican capture both fields. 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ciThe top left corner, width and height of the source rectangle, that is 8762306a36Sopenharmony_cithe area actually sampled, is given by struct 8862306a36Sopenharmony_ci:c:type:`v4l2_crop` using the same coordinate system as 8962306a36Sopenharmony_cistruct :c:type:`v4l2_cropcap`. Applications can use the 9062306a36Sopenharmony_ci:ref:`VIDIOC_G_CROP <VIDIOC_G_CROP>` and :ref:`VIDIOC_S_CROP <VIDIOC_G_CROP>` 9162306a36Sopenharmony_ciioctls to get and set this rectangle. It must lie completely within the 9262306a36Sopenharmony_cicapture boundaries and the driver may further adjust the requested size 9362306a36Sopenharmony_ciand/or position according to hardware limitations. 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ciEach capture device has a default source rectangle, given by the 9662306a36Sopenharmony_ci``defrect`` substructure of struct 9762306a36Sopenharmony_ci:c:type:`v4l2_cropcap`. The center of this rectangle 9862306a36Sopenharmony_cishall align with the center of the active picture area of the video 9962306a36Sopenharmony_cisignal, and cover what the driver writer considers the complete picture. 10062306a36Sopenharmony_ciDrivers shall reset the source rectangle to the default when the driver 10162306a36Sopenharmony_ciis first loaded, but not later. 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ciFor output devices these structures and ioctls are used accordingly, 10462306a36Sopenharmony_cidefining the *target* rectangle where the images will be inserted into 10562306a36Sopenharmony_cithe video signal. 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ciScaling Adjustments 10962306a36Sopenharmony_ci=================== 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ciVideo hardware can have various cropping, insertion and scaling 11262306a36Sopenharmony_cilimitations. It may only scale up or down, support only discrete scaling 11362306a36Sopenharmony_cifactors, or have different scaling abilities in horizontal and vertical 11462306a36Sopenharmony_cidirection. Also it may not support scaling at all. At the same time the 11562306a36Sopenharmony_cistruct :c:type:`v4l2_crop` rectangle may have to be aligned, 11662306a36Sopenharmony_ciand both the source and target rectangles may have arbitrary upper and 11762306a36Sopenharmony_cilower size limits. In particular the maximum ``width`` and ``height`` in 11862306a36Sopenharmony_cistruct :c:type:`v4l2_crop` may be smaller than the struct 11962306a36Sopenharmony_ci:c:type:`v4l2_cropcap`. ``bounds`` area. Therefore, as 12062306a36Sopenharmony_ciusual, drivers are expected to adjust the requested parameters and 12162306a36Sopenharmony_cireturn the actual values selected. 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ciApplications can change the source or the target rectangle first, as 12462306a36Sopenharmony_cithey may prefer a particular image size or a certain area in the video 12562306a36Sopenharmony_cisignal. If the driver has to adjust both to satisfy hardware 12662306a36Sopenharmony_cilimitations, the last requested rectangle shall take priority, and the 12762306a36Sopenharmony_cidriver should preferably adjust the opposite one. The 12862306a36Sopenharmony_ci:ref:`VIDIOC_TRY_FMT <VIDIOC_G_FMT>` ioctl however shall not change 12962306a36Sopenharmony_cithe driver state and therefore only adjust the requested rectangle. 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ciSuppose scaling on a video capture device is restricted to a factor 1:1 13262306a36Sopenharmony_cior 2:1 in either direction and the target image size must be a multiple 13362306a36Sopenharmony_ciof 16 × 16 pixels. The source cropping rectangle is set to defaults, 13462306a36Sopenharmony_ciwhich are also the upper limit in this example, of 640 × 400 pixels at 13562306a36Sopenharmony_cioffset 0, 0. An application requests an image size of 300 × 225 pixels, 13662306a36Sopenharmony_ciassuming video will be scaled down from the "full picture" accordingly. 13762306a36Sopenharmony_ciThe driver sets the image size to the closest possible values 304 × 224, 13862306a36Sopenharmony_cithen chooses the cropping rectangle closest to the requested size, that 13962306a36Sopenharmony_ciis 608 × 224 (224 × 2:1 would exceed the limit 400). The offset 0, 0 is 14062306a36Sopenharmony_cistill valid, thus unmodified. Given the default cropping rectangle 14162306a36Sopenharmony_cireported by :ref:`VIDIOC_CROPCAP <VIDIOC_CROPCAP>` the application can 14262306a36Sopenharmony_cieasily propose another offset to center the cropping rectangle. 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ciNow the application may insist on covering an area using a picture 14562306a36Sopenharmony_ciaspect ratio closer to the original request, so it asks for a cropping 14662306a36Sopenharmony_cirectangle of 608 × 456 pixels. The present scaling factors limit 14762306a36Sopenharmony_cicropping to 640 × 384, so the driver returns the cropping size 608 × 384 14862306a36Sopenharmony_ciand adjusts the image size to closest possible 304 × 192. 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ciExamples 15262306a36Sopenharmony_ci======== 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ciSource and target rectangles shall remain unchanged across closing and 15562306a36Sopenharmony_cireopening a device, such that piping data into or out of a device will 15662306a36Sopenharmony_ciwork without special preparations. More advanced applications should 15762306a36Sopenharmony_ciensure the parameters are suitable before starting I/O. 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci.. note:: 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci On the next two examples, a video capture device is assumed; 16262306a36Sopenharmony_ci change ``V4L2_BUF_TYPE_VIDEO_CAPTURE`` for other types of device. 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ciExample: Resetting the cropping parameters 16562306a36Sopenharmony_ci========================================== 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci.. code-block:: c 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci struct v4l2_cropcap cropcap; 17062306a36Sopenharmony_ci struct v4l2_crop crop; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci memset (&cropcap, 0, sizeof (cropcap)); 17362306a36Sopenharmony_ci cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci if (-1 == ioctl (fd, VIDIOC_CROPCAP, &cropcap)) { 17662306a36Sopenharmony_ci perror ("VIDIOC_CROPCAP"); 17762306a36Sopenharmony_ci exit (EXIT_FAILURE); 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci memset (&crop, 0, sizeof (crop)); 18162306a36Sopenharmony_ci crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 18262306a36Sopenharmony_ci crop.c = cropcap.defrect; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci /* Ignore if cropping is not supported (EINVAL). */ 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci if (-1 == ioctl (fd, VIDIOC_S_CROP, &crop) 18762306a36Sopenharmony_ci && errno != EINVAL) { 18862306a36Sopenharmony_ci perror ("VIDIOC_S_CROP"); 18962306a36Sopenharmony_ci exit (EXIT_FAILURE); 19062306a36Sopenharmony_ci } 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ciExample: Simple downscaling 19462306a36Sopenharmony_ci=========================== 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci.. code-block:: c 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci struct v4l2_cropcap cropcap; 19962306a36Sopenharmony_ci struct v4l2_format format; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci reset_cropping_parameters (); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* Scale down to 1/4 size of full picture. */ 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci memset (&format, 0, sizeof (format)); /* defaults */ 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci format.fmt.pix.width = cropcap.defrect.width >> 1; 21062306a36Sopenharmony_ci format.fmt.pix.height = cropcap.defrect.height >> 1; 21162306a36Sopenharmony_ci format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci if (-1 == ioctl (fd, VIDIOC_S_FMT, &format)) { 21462306a36Sopenharmony_ci perror ("VIDIOC_S_FORMAT"); 21562306a36Sopenharmony_ci exit (EXIT_FAILURE); 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci /* We could check the actual image size now, the actual scaling factor 21962306a36Sopenharmony_ci or if the driver can scale at all. */ 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ciExample: Selecting an output area 22262306a36Sopenharmony_ci================================= 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci.. note:: This example assumes an output device. 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci.. code-block:: c 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci struct v4l2_cropcap cropcap; 22962306a36Sopenharmony_ci struct v4l2_crop crop; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci memset (&cropcap, 0, sizeof (cropcap)); 23262306a36Sopenharmony_ci cropcap.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci if (-1 == ioctl (fd, VIDIOC_CROPCAP;, &cropcap)) { 23562306a36Sopenharmony_ci perror ("VIDIOC_CROPCAP"); 23662306a36Sopenharmony_ci exit (EXIT_FAILURE); 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci memset (&crop, 0, sizeof (crop)); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 24262306a36Sopenharmony_ci crop.c = cropcap.defrect; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci /* Scale the width and height to 50 % of their original size 24562306a36Sopenharmony_ci and center the output. */ 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci crop.c.width /= 2; 24862306a36Sopenharmony_ci crop.c.height /= 2; 24962306a36Sopenharmony_ci crop.c.left += crop.c.width / 2; 25062306a36Sopenharmony_ci crop.c.top += crop.c.height / 2; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci /* Ignore if cropping is not supported (EINVAL). */ 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci if (-1 == ioctl (fd, VIDIOC_S_CROP, &crop) 25562306a36Sopenharmony_ci && errno != EINVAL) { 25662306a36Sopenharmony_ci perror ("VIDIOC_S_CROP"); 25762306a36Sopenharmony_ci exit (EXIT_FAILURE); 25862306a36Sopenharmony_ci } 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ciExample: Current scaling factor and pixel aspect 26162306a36Sopenharmony_ci================================================ 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci.. note:: This example assumes a video capture device. 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci.. code-block:: c 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci struct v4l2_cropcap cropcap; 26862306a36Sopenharmony_ci struct v4l2_crop crop; 26962306a36Sopenharmony_ci struct v4l2_format format; 27062306a36Sopenharmony_ci double hscale, vscale; 27162306a36Sopenharmony_ci double aspect; 27262306a36Sopenharmony_ci int dwidth, dheight; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci memset (&cropcap, 0, sizeof (cropcap)); 27562306a36Sopenharmony_ci cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci if (-1 == ioctl (fd, VIDIOC_CROPCAP, &cropcap)) { 27862306a36Sopenharmony_ci perror ("VIDIOC_CROPCAP"); 27962306a36Sopenharmony_ci exit (EXIT_FAILURE); 28062306a36Sopenharmony_ci } 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci memset (&crop, 0, sizeof (crop)); 28362306a36Sopenharmony_ci crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci if (-1 == ioctl (fd, VIDIOC_G_CROP, &crop)) { 28662306a36Sopenharmony_ci if (errno != EINVAL) { 28762306a36Sopenharmony_ci perror ("VIDIOC_G_CROP"); 28862306a36Sopenharmony_ci exit (EXIT_FAILURE); 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci /* Cropping not supported. */ 29262306a36Sopenharmony_ci crop.c = cropcap.defrect; 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci memset (&format, 0, sizeof (format)); 29662306a36Sopenharmony_ci format.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci if (-1 == ioctl (fd, VIDIOC_G_FMT, &format)) { 29962306a36Sopenharmony_ci perror ("VIDIOC_G_FMT"); 30062306a36Sopenharmony_ci exit (EXIT_FAILURE); 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci /* The scaling applied by the driver. */ 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci hscale = format.fmt.pix.width / (double) crop.c.width; 30662306a36Sopenharmony_ci vscale = format.fmt.pix.height / (double) crop.c.height; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci aspect = cropcap.pixelaspect.numerator / 30962306a36Sopenharmony_ci (double) cropcap.pixelaspect.denominator; 31062306a36Sopenharmony_ci aspect = aspect * hscale / vscale; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci /* Devices following ITU-R BT.601 do not capture 31362306a36Sopenharmony_ci square pixels. For playback on a computer monitor 31462306a36Sopenharmony_ci we should scale the images to this size. */ 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci dwidth = format.fmt.pix.width / aspect; 31762306a36Sopenharmony_ci dheight = format.fmt.pix.height; 318