1

This function is supposed to take an image and convert it into data and from the data it will be converted back to image. when I used an image from an image library or when I take the photo in landscape mode it works fine. But when I take the photo in portrait mode the image will be rotated and stretched when its being converted back to an image. Is there any way to prevent that from happening?

func pixelCalculator (){
    let image = originalImage

    let height = Int((image.size.height))
    print(height)
    let width = Int((image.size.width))

    let bitsPerComponent = Int(8)
    let bytesPerRow = 4 * width
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    let rawData = UnsafeMutablePointer<RGBAPixel>.allocate(capacity: (width * height))
    let bitmapInfo: UInt32 = CGBitmapInfo.byteOrder32Big.rawValue | CGImageAlphaInfo.premultipliedLast.rawValue
    let CGPointZero = CGPoint(x: 0, y: 0)
    let rect = CGRect(origin: CGPointZero, size: (image.size))



    let imageContext = CGContext(data: rawData, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo)

    imageContext?.draw(image.cgImage!, in: rect)

    let pixels = UnsafeMutableBufferPointer<RGBAPixel>(start: rawData, count: width * height)

    let outContext = CGContext(data: pixels.baseAddress, width: width, height: height, bitsPerComponent: bitsPerComponent,bytesPerRow: bytesPerRow,space: colorSpace,bitmapInfo: bitmapInfo,releaseCallback: nil,releaseInfo: nil)

    let outImage = UIImage(cgImage: outContext!.makeImage()!)
    imageView.image = outImage

}
KUROYUKI
  • 113
  • 4
  • 16
  • Possible duplicate of [Resizing UIimages pulled from the Camera also ROTATES the UIimage?](https://stackoverflow.com/questions/1260249/resizing-uiimages-pulled-from-the-camera-also-rotates-the-uiimage) – James P Aug 14 '18 at 08:12
  • Check this answer might be helpful - https://stackoverflow.com/questions/38139850/imageview-rotating-when-using-imagepicker/38141626#38141626 – Sunil Sharma Aug 14 '18 at 10:14

2 Answers2

6

I use this extension to fix the orientation of image:

extension UIImage {
    func fixOrientation() -> UIImage {
        if self.imageOrientation == UIImageOrientation.up {
            return self
        }
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
        if let normalizedImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() {
            UIGraphicsEndImageContext()
            return normalizedImage
        } else {
            return self
        }
    }
}

And this is how I use this extension:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage{
        let fixedPickedImage = pickedImage.fixOrientation()//this is the new fixed orientation image.
    }
    parent?.dismiss(animated: true, completion: nil)
}

P.s: You can change orientation type according to your requirements. Just change:

 if self.imageOrientation == UIImageOrientation.up {//change orientation
        return self
    }

These are all types of orientations explained in degrees,

typedef NS_ENUM(NSInteger, UIImageOrientation) {
        UIImageOrientationUp,            // default orientation
        UIImageOrientationDown,          // 180 deg rotation
        UIImageOrientationLeft,          // 90 deg CCW
        UIImageOrientationRight,         // 90 deg CW
        UIImageOrientationUpMirrored,    // as above but image mirrored along other axis. horizontal flip
        UIImageOrientationDownMirrored,  // horizontal flip
        UIImageOrientationLeftMirrored,  // vertical flip
        UIImageOrientationRightMirrored, // vertical flip
    };

You can refer UIImage.Orientation Apple Documentation for more information.

Enea Dume
  • 3,014
  • 3
  • 21
  • 36
0

In some UIImages, its bitmap representation (CGImage) is rotated and UIImage draws it unrotated according to the imageOrientation property, which your code ignores.

You can write something like this:

func pixelCalculator() {
    let image = originalImage

    //### Keep scale and orientation.
    let scale = originalImage.scale
    let orientation = originalImage.imageOrientation

    let height = Int(image.size.height)
    let width = Int(image.size.width)

    let bitsPerComponent = 8
    let bytesPerRow = 4 * width
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    let rawData = UnsafeMutablePointer<RGBAPixel>.allocate(capacity: (width * height))
    let bitmapInfo: UInt32 = CGBitmapInfo.byteOrder32Big.rawValue | CGImageAlphaInfo.premultipliedLast.rawValue
    let rect = CGRect(origin: .zero, size: (image.size))

    let imageContext = CGContext(data: rawData, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo)

    imageContext?.draw(image.cgImage!, in: rect)

    let pixels = UnsafeMutableBufferPointer<RGBAPixel>(start: rawData, count: width * height)

    let outContext = CGContext(data: pixels.baseAddress, width: width, height: height, bitsPerComponent: bitsPerComponent,bytesPerRow: bytesPerRow,space: colorSpace,bitmapInfo: bitmapInfo,releaseCallback: nil,releaseInfo: nil)

    //### Create a UIImage with the same scale and orientation as the originalImage.
    let outImage = UIImage(cgImage: outContext!.makeImage()!, scale: scale, orientation: orientation)
    imageView.image = outImage
}

But, if you want to modify pixels and your algorithm depends on orientation, better use something like Enea Dume's answer.

OOPer
  • 47,149
  • 6
  • 107
  • 142