     static var unconstrained: CGFloat {
         infinity
     }
+
+    var isLandscape: Bool {
+        self > 1.0 && self < .infinity
+    }
+
+    var isPortrait: Bool {
+        self > 0.0 && self < 1.0
+    }
+
+    var isSquare: Bool {
+        self == 1.0
+    }
 }
 
 public extension CGSize {

        let ratio = imageSize.aspectRatio

        if widthIsUnconstrained && heightIsUnconstrained {
            if ratio > 1.0 {
                return Int(round(imageSize.width))
            }
            return Int(round(imageSize.height))

        } else if widthIsUnconstrained {
            if ratio > 1.0 {
                return Int(imageSize.proportionalWidth(forHeight: self.height, precision: .rounded))
            }
            return Int(round(self.height))

        } else if heightIsUnconstrained {
            if ratio > 1.0 {
                return Int(round(self.width))
            }
            return Int(imageSize.proportionalHeight(forWidth: self.width, precision: .rounded))
        }

        return Int(round(min(self.width, self.height)))

        return self.width / self.height
    }

    func proportionalSize(for imageSize: CGSize, precision: PrecisionScheme = .defaultPrecisionScheme) -> CGSize {
        let maximumDimension = CGFloat(maximumPixelSize(forImageSize: imageSize))
        let ratio = imageSize.aspectRatio
        if ratio.isLandscape {
            return CGSize(width: precision.applied(to: maximumDimension), height: precision.applied(to: maximumDimension / ratio))
        } else {
            return CGSize(width: precision.applied(to: ratio * maximumDimension), height: precision.applied(to: maximumDimension))
