text: # ------------------------------------------------------------------------------
  # classification.pytorch
  # Copyright (c) 2018-present Microsoft
  # Licensed under The Apache-2.0 License [see LICENSE for details]
  # Written by Bin Xiao (Bin.Xiao@microsoft.com)
  # ------------------------------------------------------------------------------
  
  from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  
  import io
  import logging
  import zipfile
  
  import torch.utils.data as data
  
  from PIL import Image
  import cv2
  import numpy as np
  
  import utils.phillyzip as phillyzip
  
  
  logger = logging.getLogger(__name__)
  
  
  def has_file_allowed_extension(filename, extensions):
      """Checks if a file is an allowed extension.
  
      Args:
          filename (string): path to a file
          extensions (iterable of strings): extensions to consider (lowercase)
  
      Returns:
          bool: True if the filename ends with one of given extensions
      """
      filename_lower = filename.lower()
      return any(filename_lower.endswith(ext) for ext in extensions)
  
  
  def is_image_file(filename):
      """Checks if a file is an allowed image extension.
  
      Args:
          filename (string): path to a file
  
      Returns:
          bool: True if the filename ends with a known image extension
      """
      return has_file_allowed_extension(filename, IMG_EXTENSIONS)
  
  
  def find_classes(dirs):
      classes = [d for d in dirs]
      classes.sort()
      class_to_idx = {classes[i]: i for i in range(len(classes))}
      return classes, class_to_idx
  
  
  def get_zip_info(zip_file):
      dirs = []
      files = []
  
      all_namelist = zip_file.namelist()
      for name in all_namelist:
          if name.endswith('/'):
              dirs.append(name.strip('/'))
          else:
              files.append(name)
  
      return dirs, files
  
  
  def make_dataset(zip_file_name, extensions):
      dirs = []
      files = []
      images = []
      classes = []
      class_to_idx = {}
  
      with zipfile.ZipFile(zip_file_name, 'r') as zip_file:
          dirs, files = get_zip_info(zip_file)
          classes, class_to_idx = find_classes(dirs)
  
          for f in files:
              dir = f.split('/')[0]
              if dir in classes and is_image_file(f):
                  images.append((zip_file.read(f), class_to_idx[dir]))
  
      return classes, class_to_idx, images
  
  
  class CachedZipFolder(data.Dataset):
      """A generic data loader where the samples are arranged in this way: ::
  
          zip_file@/class_x/xxx.ext
          zip_file@/class_x/xxy.ext
          zip_file@/class_x/xxz.ext
  
          zip_file@/class_y/123.ext
          zip_file@/class_y/nsdf3.ext
          zip_file@/class_y/asd932_.ext
  
      Args:
          zip_file (string): Zip file path.
          loader (callable): A function to load a sample given its path.
          extensions (list[string]): A list of allowed extensions.
          transform (callable, optional): A function/transform that takes in
              a sample and returns a transformed version.
              E.g, ``transforms.RandomCrop`` for images.
          target_transform (callable, optional): A function/transform that takes
              in the target and transforms it.
  
       Attributes:
          classes (list): List of the class names.
          class_to_idx (dict): Dict with items (class_name, class_index).
          samples (list): List of (sample path, class_index) tuples
          targets (list): The class_index value for each image in the dataset
      """
  
      def __init__(self, zip_file_name, loader, extensions, transform=None, target_transform=None):
          classes, class_to_idx, samples = make_dataset(zip_file_name, extensions)
          logger.info('=> {} classes are added'.format(len(classes)))
          logger.info('=> {} samples are added'.format(len(samples)))
  
          if len(samples) == 0:
              raise(RuntimeError("Found 0 files in subfolders of: " + zip_file_name + "\n"))
  
          self.loader = loader
          self.extensions = extensions
  
          self.classes = classes
          self.class_to_idx = class_to_idx
          self.samples = samples
          self.targets = [s[1] for s in samples]
  
          self.transform = transform
          self.target_transform = target_transform
  
      def __getitem__(self, index):
          """
          Args:
              index (int): Index
  
          Returns:
              tuple: (sample, target) where target is class_index of the target class.
          """
          buffer, target = self.samples[index]
          sample = self.loader(io.BytesIO(buffer))
          if self.transform is not None:
              sample = self.transform(sample)
          if self.target_transform is not None:
              target = self.target_transform(target)
  
          return sample, target
  
      def __len__(self):
          return len(self.samples)
  
      def __repr__(self):
          fmt_str = 'Dataset ' + self.__class__.__name__ + '\n'
          fmt_str += '    Number of datapoints: {}\n'.format(self.__len__())
          fmt_str += '    Root Location: {}\n'.format(self.root)
          tmp = '    Transforms (if any): '
          fmt_str += '{0}{1}\n'.format(tmp, self.transform.__repr__().replace('\n', '\n' + ' ' * len(tmp)))
          tmp = '    Target Transforms (if any): '
          fmt_str += '{0}{1}'.format(tmp, self.target_transform.__repr__().replace('\n', '\n' + ' ' * len(tmp)))
          return fmt_str
  
  
  IMG_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.ppm', '.bmp', '.pgm', '.tif']
  
  
  def pil_loader(file):
      # open path as file to avoid ResourceWarning (https://github.com/python-pillow/Pillow/issues/835)
      img = Image.open(file)
      return img.convert('RGB')
  
  
  # def cv2_loader(data):
  #     img = cv2.imdecode(np.frombuffer(data, np.uint8), cv2.IMREAD_COLOR)
  #     img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  #     return Image.fromarray(img)
  
  
  def default_loader(file):
      return pil_loader(file)
  
  
  class ImageZipFolder(CachedZipFolder):
      """A generic data loader where the images are arranged in this way: ::
          zip_file@/class_x/xxx.ext
          zip_file@/class_x/xxy.ext
          zip_file@/class_x/xxz.ext
  
          zip_file@/class_y/123.ext
          zip_file@/class_y/nsdf3.ext
          zip_file@/class_y/asd932_.ext
  
      Args:
          zip_file_name (string): Zip file path.
          transform (callable, optional): A function/transform that  takes in an PIL image
              and returns a transformed version. E.g, ``transforms.RandomCrop``
          target_transform (callable, optional): A function/transform that takes in the
              target and transforms it.
          loader (callable, optional): A function to load an image given its path.
  
       Attributes:
          classes (list): List of the class names.
          class_to_idx (dict): Dict with items (class_name, class_index).
          imgs (list): List of (image path, class_index) tuples
      """
      def __init__(self, zip_file_name, transform=None, target_transform=None,
                   loader=default_loader):
          super(ImageZipFolder, self).__init__(zip_file_name, loader, IMG_EXTENSIONS,
                                          transform=transform,
                                          target_transform=target_transform)
          self.imgs = self.samples
  