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