'height' is inaccessible due to 'internal' protection level error

I am coding a basic fps app on Xcode 12.5. As of right now, Im working on a file that acts as a bridge between UIKit and the game engine used for this game. The code is provided below:

Bitmap.swift

import UIKit

public struct Bitmap
{
  public private(set) var pixels: [Color]
  public let width: Int
   
  public init(width: Int, pixels: [Color])
  {
    self.width = width
    self.pixels = pixels
  }
}


public extension Bitmap
{
  var height: Int
  {
    return pixels.count / width
  }
  subscript(x: Int, y: Int) -> Color
  {
    get { return pixels[y * width + x] }
    set { pixels[y * width + x] = newValue}
  }
  init(width: Int, height: Int, color: Color) {
    self.pixels = Array(repeating: color, count: width * height)
    self.width = width
  }
}

UIImage+Bitmap.swift

import UIKit
import Engine

extension UIImage {
  convenience init?(bitmap: Bitmap) {
    let alphaInfo = CGImageAlphaInfo.premultipliedLast
    let bytesPerPixel = MemoryLayout<Color>.size
    let bytesPerRow = bitmap.width * bytesPerPixel

    guard let providerRef = CGDataProvider(data: Data(
      bytes: bitmap.pixels, count: bitmap.height * bytesPerRow
    ) as CFData) else {
      return nil
    }

    guard let cgImage = CGImage(
      width: bitmap.width,
      height: bitmap.height,
      bitsPerComponent: 8,
      bitsPerPixel: bytesPerPixel * 8,
      bytesPerRow: bytesPerRow,
      space: CGColorSpaceCreateDeviceRGB(),
      bitmapInfo: CGBitmapInfo(rawValue: alphaInfo.rawValue),
      provider: providerRef,
      decode: nil,
      shouldInterpolate: true,
      intent: .defaultIntent
    ) else {
      return nil
    }

    self.init(bitmap: cgImage)
  }
}

For my UIImage+Bitmap.swift code I get the following error: "'height' is inaccessible due to 'internal' protection level"

Any help will be appreciated!

Answered by Claude31 in 678780022

Update: I rewrote the last line in UIImage+Bitmap.swift to self.init(cgImage: cgImage) and it worked. Appreciate the help.

So, you don't call the convenience initialiser itself anymore.

Thanks for the feedback, don't forget to close the thread now.

Please tell where you get the error, exactly. Which line ?

What is Color ?

I get the error at the following lines in UIImage+Bitmap.swift

bytes: bitmap.pixels, count: bitmap.height * bytesPerRow

and

height: bitmap.height,

Try to change with this to see what you get:

extension UIImage {
  convenience init?(bitmap: Bitmap) {
    let alphaInfo = CGImageAlphaInfo.premultipliedLast
    let bytesPerPixel = MemoryLayout<Color>.size
    let bytesPerRow = bitmap.width * bytesPerPixel

    let theHeight = bitmap.height  // To have a local value
    guard let providerRef = CGDataProvider(data: Data(
      bytes: bitmap.pixels, count: theHeight * bytesPerRow
    ) as CFData) else {
      return nil
    }

Could you show how Color is defined ?

I tested, replacing Color by Int. I get an error on line

    self.init(bitmap: cgImage)

Cannot convert value of type 'CGImage' to expected argument type 'Bitmap' Which is logic, as cgImage is CGImage and not Bitmap

In addition, you call the convenience initialiser within itself… I must be missing something

Try to add, in public struct Bitmap ( }

     public init() {}

See here for details: https://stackoverflow.com/questions/40859139/initializer-is-inaccessable-due-to-internal-protection-level

You should not post code in comments, they mess it. So I had to rebuild it.

Note: I do find it confusing to name the class and the struct inside by the same name… Why do you declare public ? And not simply extension Bitmap {} for instance ?

You did not answer my other questions :

Cannot convert value of type 'CGImage' to expected argument type 'Bitmap' Which is logic, as cgImage is CGImage and not Bitmap

In addition, you call the convenience initialiser within itself… I must be missing something

import UIKit

class Color: UIViewController {
     public struct Color {
          public var r, g, b, a: UInt8
          public init(r: UInt8, g: UInt8, b: UInt8, a: UInt8 = 255)      {
               self.r = r
               self.g = g
               self.b = b
               self.a = a
               
          }
          
     }
     
     override func viewDidLoad() { 
     super.viewDidLoad()      // Do any additional setup after loading the view. 
   }
          
}

extension Color {
     static let clear = Color(r: 0, g: 0, b: 0, a: 0)
     static let black = Color(r: 0, g: 0, b: 0)
     static let white = Color(r: 255, g: 255, b: 255)
     static let gray = Color(r: 192, g: 192, b: 192)
     static let red = Color(r: 255, g: 0, b: 0)
     static let green = Color(r: 0, g: 255, b: 0)
     static let blue = Color(r: 0, g: 0, b: 255)
     
}
Accepted Answer

Update: I rewrote the last line in UIImage+Bitmap.swift to self.init(cgImage: cgImage) and it worked. Appreciate the help.

So, you don't call the convenience initialiser itself anymore.

Thanks for the feedback, don't forget to close the thread now.

Is UIImage+Bitmap.swift importing the Bitmap type through import Engine?

If so that would explain why height wouldn’t be visible if it’s internal…except that it shouldn’t be internal, since it’s in a public extension. Pretty strange all around.

There might be a bug in the compiler here, or at least a diagnostic that could be improved. Could you file a report through Feedback Assistant and attach your project so the Swift compiler team can take a look at it?

'height' is inaccessible due to 'internal' protection level error
 
 
Q