ios - 将图像从 Online mysql 数据库加载到 UICollectionView Swift

标签 ios swift image video blob

我正在设计一个 iOS 应用程序,它在 UICollectionView 中向用户显示大量图像和视频。我通过生成视频的缩略图并显示该缩略图来处理视频,仅当用户单击缩略图时才会加载视频。现在,我将图像和视频以 base64 编码的 blob 形式存储在远程 mysqli 数据库中。我的问题涉及将这些图像和视频加载回应用程序的最有效方法。目前,我使用以下函数来生成图像的缩略图以及视频快照:

func RBSquareImageTo(image: UIImage, size: CGSize) -> UIImage? {
    return RBResizeImage(RBSquareImage(image), targetSize: size)
}

func RBSquareImage(image: UIImage) -> UIImage? {
    let originalWidth  = image.size.width
    let originalHeight = image.size.height

    var edge: CGFloat
    if originalWidth > 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) -> 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 > 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) -> 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
    }
}

然后,我使用以下函数来压缩内容和缩略图,并通过 POST 请求将它们发送到我的数据库:

func compressVideo(inputURL: NSURL, outputURL: NSURL, handler:(session: AVAssetExportSession)-> 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 { () -> Void in

        handler(session: exportSession!)
    }

}

func compressImage(image:UIImage) -> 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 > maxHeight || actualWidth > maxWidth){
        if(imgRatio < maxRatio){
            //adjust width according to maxHeight
            imgRatio = maxHeight / actualHeight;
            actualWidth = imgRatio * actualWidth;
            actualHeight = maxHeight;
        }
        else if(imgRatio > 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!;
}

这导致图像和视频大小在 500KB - 1.5MB 之间,缩略图大小约为 4-6 KB。我仅使用 ipad2 进行了测试,因此我怀疑如果使用较新的 iPhone 拍摄照片和视频,这些尺寸会显着增加。我目前正在做的事情是向我的服务器发送一个请求,该请求返回数据库中所有图像和视频的缩略图,但缩略图通常质量较低。我想知道在这种特殊情况下是否有更有效的方法来加载完整的图像和视频。我正在考虑做一些事情,比如发送一个仅加载大约 10 个图像(屏幕上可见的图像)的请求,当用户向下滚动时,会为接下来的 10 个图像发送另一个请求,这样做的问题是,单元格将被如果用户向下滚动得足够快,则在请求完成之前为空白。您是否会推荐任何库,或者您认为更有效的另一种方法?在这种情况下我应该使用 base64 编码吗?

最佳答案

the cells will be blank until the request is complete if the user scrolls down fast enough

没关系,只要从空白单元格平滑过渡到带有缩略图的单元格即可。它也出现在 Facebook 和 Instagram 等流行应用中。

Should I be using base64 encoding at all in this case?

如果您关心效率,可能不会。一般来说,人们会:

  • 为文件(缩略图/视频)分配标识符。
  • 将标识符存储在数据库中,并将文件存储在外部云中(最好使用 CDN)。
  • 客户端从服务器检索标识符,一次多个。
  • 客户端从外部位置下载文件并将其缓存。

关于ios - 将图像从 Online mysql 数据库加载到 UICollectionView Swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37775957/

相关文章:

arrays - 在字符串数组中搜索多个单词(或字符)(swift)

javascript - 模态图像弹出窗口

objective-c - 如何将自定义图像上传到 iPhone SDK 中的标签栏?

ios - iPhone 如何在按下音量键时隐藏音量覆盖

ios - PGO:为什么 XCode 会生成空的 .profdata 文件?

iphone - Swift 中的字典没有给出正确的响应

database - 我应该将图像二进制数据保存到数据库还是将图像保存为文件?

ios - 无法计算 iOS App 上的文件大小

ios - ApplicationDidLaunch 中的 RemoveFromSuperView UIImageView 延迟执行

ios - CloudKit - 无法从 iCloud 检索数据