class_docstr: Implement the JPEG compression defence approach.
  
  For input images or videos with 3 color channels the compression is applied in mode `RGB`
  (3x8-bit pixels, true color), for all other numbers of channels the compression is applied for each channel with
  mode `L` (8-bit pixels, black and white).
  
  | Paper link: https://arxiv.org/abs/1705.02900, https://arxiv.org/abs/1608.00853
  
  
  | Please keep in mind the limitations of defences. For more information on the limitations of this defence,
      see https://arxiv.org/abs/1802.00420 . For details on how to evaluate classifier security in general, see
      https://arxiv.org/abs/1902.06705
docstr: Apply JPEG compression to sample `x`.
  
  For input images or videos with 3 color channels the compression is applied in mode `RGB`
  (3x8-bit pixels, true color), for all other numbers of channels the compression is applied for each channel with
  mode `L` (8-bit pixels, black and white).
  
  :param x: Sample to compress with shape of `NCHW`, `NHWC`, `NCFHW` or `NFHWC`. `x` values are expected to be in
            the data range [0, 1] or [0, 255].
  :param y: Labels of the sample `x`. This function does not affect them in any way.
  :return: compressed sample.
docstr_tok: ["Apply","JPEG","compression","to","sample","`","x","`",".","For","input","images","or","videos","with","3","color","channels","the","compression","is","applied","in","mode","`","RGB","`","(","3x8-bit","pixels",",","true","color",")",",","for","all","other","numbers","of","channels","the","compression","is","applied","for","each","channel","with","mode","`","L","`","(","8-bit","pixels",",","black","and","white",")",".",":","param","x",":","Sample","to","compress","with","shape","of","`","NCHW","`",",","`","NHWC","`",",","`","NCFHW","`","or","`","NFHWC","`",".","`","x","`","values","are","expected","to","be","in","the","data","range","[","0",",","1","]","or","[","0",",","255","]",".",":","param","y",":","Labels","of","the","sample","`","x","`",".","This","function","does","not","affect","them","in","any","way",".",":","return",":","compressed","sample","."]
code: def __call__(
      self, x: np.ndarray, y: Optional[np.ndarray] = None
  ) -> Tuple[np.ndarray, Optional[np.ndarray]]:
      """
      Apply JPEG compression to sample `x`.
  
      For input images or videos with 3 color channels the compression is applied in mode `RGB`
      (3x8-bit pixels, true color), for all other numbers of channels the compression is applied for each channel with
      mode `L` (8-bit pixels, black and white).
  
      :param x: Sample to compress with shape of `NCHW`, `NHWC`, `NCFHW` or `NFHWC`. `x` values are expected to be in
                the data range [0, 1] or [0, 255].
      :param y: Labels of the sample `x`. This function does not affect them in any way.
      :return: compressed sample.
      """
      x_ndim = x.ndim
      if x_ndim not in [4, 5]:
          raise ValueError(
              "Unrecognized input dimension. JPEG compression can only be applied to image and video data."
          )
  
      if x.min() < 0.0:
          raise ValueError(
              "Negative values in input `x` detected. The JPEG compression defence requires unnormalized input."
          )
  
      # Swap channel index
      if self.channels_first and x_ndim == 4:
          # image shape NCHW to NHWC
          x = np.transpose(x, (0, 2, 3, 1))
      elif self.channels_first and x_ndim == 5:
          # video shape NCFHW to NFHWC
          x = np.transpose(x, (0, 2, 3, 4, 1))
  
      # insert temporal dimension to image data
      if x_ndim == 4:
          x = np.expand_dims(x, axis=1)
  
      # Convert into uint8
      if self.clip_values[1] == 1.0:
          x = x * 255
      x = x.astype("uint8")
  
      # Compress one image at a time
      x_jpeg = x.copy()
      for idx in tqdm(np.ndindex(x.shape[:2]), desc="JPEG compression", disable=not self.verbose):  # type: ignore
          if x.shape[-1] == 3:
              x_jpeg[idx] = self._compress(x[idx], mode="RGB")
          else:
              for i_channel in range(x.shape[-1]):
                  x_channel = x[idx[0], idx[1], ..., i_channel]
                  x_channel = self._compress(x_channel, mode="L")
                  x_jpeg[idx[0], idx[1], :, :, i_channel] = x_channel
  
      # Convert to ART dtype
      if self.clip_values[1] == 1.0:
          x_jpeg = x_jpeg / 255.0
      x_jpeg = x_jpeg.astype(ART_NUMPY_DTYPE)
  
      # remove temporal dimension for image data
      if x_ndim == 4:
          x_jpeg = np.squeeze(x_jpeg, axis=1)
  
      # Swap channel index
      if self.channels_first and x_jpeg.ndim == 4:
          # image shape NHWC to NCHW
          x_jpeg = np.transpose(x_jpeg, (0, 3, 1, 2))
      elif self.channels_first and x_ndim == 5:
          # video shape NFHWC to NCFHW
          x_jpeg = np.transpose(x_jpeg, (0, 4, 1, 2, 3))
      return x_jpeg, y
  
file_path: adversarial-robustness-toolbox/art/defences/preprocessor/jpeg_compression.py
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  from io import BytesIO
  import logging
  from typing import Optional, Tuple, TYPE_CHECKING
  import numpy
  from tqdm.auto import tqdm
  from art.config import ART_NUMPY_DTYPE
  from art.defences.preprocessor.preprocessor import Preprocessor
label_desc: Use image node_id 3 for calling the JpegCompression obj's underlying member method code with example usage: obj.__call__(x, y) and returns: x_jpeg,  y