title: Loading Images from Online mysql database to UICollectionView Swift
body: <p>I am designing an iOS application which displays a lot of images and videos to the user in a <code>UICollectionView</code>. I handle videos by generating a thumbnail of the video and displaying that, the video is only loaded when the user clicks on the thumbnail. Now I store the images and videos as <code>base64</code> encoded <code>blobs</code> in my remote mysqli database. My question concerns the most efficient way of loading these images and videos back into the application. Currently, I use the following functions to generate thumbnails of the images as well as the video snapshots : </p>
  
  <pre><code>func RBSquareImageTo(image: UIImage, size: CGSize) -&gt; UIImage? {
      return RBResizeImage(RBSquareImage(image), targetSize: size)
  }
  
  func RBSquareImage(image: UIImage) -&gt; UIImage? {
      let originalWidth  = image.size.width
      let originalHeight = image.size.height
  
      var edge: CGFloat
      if originalWidth &gt; originalHeight {
          edge = originalHeight
      } else {
          edge = originalWidth
      }
  
      let posX = (originalWidth  - edge) / 2.0
      let posY = (originalHeight - edge) / 2.0
  
      let cropSquare = CGRectMake(posX, posY, edge, edge)
  
      let imageRef = CGImageCreateWithImageInRect(image.CGImage, cropSquare);
      return UIImage(CGImage: imageRef!, scale: UIScreen.mainScreen().scale, orientation: image.imageOrientation)
  }
  
  func RBResizeImage(image: UIImage?, targetSize: CGSize) -&gt; UIImage? {
      if let image = image {
          let size = image.size
  
          let widthRatio  = targetSize.width  / image.size.width
          let heightRatio = targetSize.height / image.size.height
  
          // Figure out what our orientation is, and use that to form the rectangle
          var newSize: CGSize
          if(widthRatio &gt; heightRatio) {
              newSize = CGSizeMake(size.width * heightRatio, size.height * heightRatio)
          } else {
              newSize = CGSizeMake(size.width * widthRatio,  size.height * widthRatio)
          }
  
          // This is the rect that we've calculated out and this is what is actually used below
          let rect = CGRectMake(0, 0, newSize.width, newSize.height)
  
          // Actually do the resizing to the rect using the ImageContext stuff
          UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
          image.drawInRect(rect)
          let newImage = UIGraphicsGetImageFromCurrentImageContext()
          UIGraphicsEndImageContext()
  
          return newImage
      } else {
          return nil
      }
  }
  func videoSnapshot(vidURL: NSURL) -&gt; UIImage? {
  
      let asset = AVURLAsset(URL: vidURL)
      let generator = AVAssetImageGenerator(asset: asset)
      generator.appliesPreferredTrackTransform = true
  
      let timestamp = CMTime(seconds: 1, preferredTimescale: 60)
  
      do {
          let imageRef = try generator.copyCGImageAtTime(timestamp, actualTime: nil)
          return UIImage(CGImage: imageRef)
      }
      catch let error as NSError
      {
          print("Image generation failed with error \(error)")
          return nil
      }
  }
  </code></pre>
  
  <p>I then use the following functions to compress the content as well as the thumbnails and send them to my database in a POST request : </p>
  
  <pre><code>func compressVideo(inputURL: NSURL, outputURL: NSURL, handler:(session: AVAssetExportSession)-&gt; Void)
  {
      let urlAsset = AVURLAsset(URL: inputURL, options: nil)
  
      let exportSession = AVAssetExportSession(asset: urlAsset, presetName: AVAssetExportPresetMediumQuality)
  
      exportSession!.outputURL = outputURL
  
      exportSession!.outputFileType = AVFileTypeQuickTimeMovie
  
      exportSession!.shouldOptimizeForNetworkUse = true
  
      exportSession!.exportAsynchronouslyWithCompletionHandler { () -&gt; Void in
  
          handler(session: exportSession!)
      }
  
  }
  
  func compressImage(image:UIImage) -&gt; NSData {
      // Reducing file size to a 10th
  
      var actualHeight : CGFloat = image.size.height
      var actualWidth : CGFloat = image.size.width
      let maxHeight : CGFloat = 1136.0
      let maxWidth : CGFloat = 640.0
      var imgRatio : CGFloat = actualWidth/actualHeight
      let maxRatio : CGFloat = maxWidth/maxHeight
      var compressionQuality : CGFloat = 0.5
  
      if (actualHeight &gt; maxHeight || actualWidth &gt; maxWidth){
          if(imgRatio &lt; maxRatio){
              //adjust width according to maxHeight
              imgRatio = maxHeight / actualHeight;
              actualWidth = imgRatio * actualWidth;
              actualHeight = maxHeight;
          }
          else if(imgRatio &gt; maxRatio){
              //adjust height according to maxWidth
              imgRatio = maxWidth / actualWidth;
              actualHeight = imgRatio * actualHeight;
              actualWidth = maxWidth;
          }
          else{
              actualHeight = maxHeight;
              actualWidth = maxWidth;
              compressionQuality = 1;
          }
      }
  
      let rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
      UIGraphicsBeginImageContext(rect.size);
      image.drawInRect(rect)
      let img = UIGraphicsGetImageFromCurrentImageContext();
      let imageData = UIImageJPEGRepresentation(img, compressionQuality);
      UIGraphicsEndImageContext();
  
      return imageData!;
  }
  </code></pre>
  
  <p>This results in the images and videos being between 500KB - 1.5MB and the thumbnails about 4-6 KB. I have tested this only with an ipad2, hence I suspect these sizes will increase significantly if a newer iPhone is used for taking the photos and videos. What I am currently doing is sending one request to my server, which returns the thumbnails of all the images and videos in the database, however the thumbnails are generally of low quality. I am wondering if there is a more efficient way of loading the full images and videos in this particular situation. I was thinking of doing something like sending a request which loads about 10 images only (the ones visible on screen) and when the user scrolls down, another request is sent for the next 10 images, the problem with this is, the cells will be blank until the request is complete if the user scrolls down fast enough. Is there any libraries you would recommend for this or maybe another approach which you would say is more efficient? Should I be using base64 encoding at all in this case?</p>