iOS Image Metadata how to get decimal values as fractions string? - ios

EDIT: Resolved, I answered the question below.
I am using the following to get metadata for PHAssets:
let data = NSData.init(contentsOf: url!)!
if let imageSource = CGImageSourceCreateWithData(data, nil) {
let metadata = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil)! as NSDictionary
}
The metadata dictionary has all the values I am looking for. However a few fields like ShutterSpeedValue, ExposureTime which have fractions get printed as decimals:
ExposureTime = "0.05"
ShutterSpeedValue = "4.321956769055745"
When I look at this data on my Mac's preview app and exiftool, it shows:
ExposureTime = 1/20
ShutterSpeedValue = 1/20
How can I get the correct fraction string instead of the decimal string?
EDIT: I tried simply converting the decimal to a fraction string using this from SO code but this isn't correct:
func rationalApproximation(of x0 : Double, withPrecision eps : Double = 1.0E-6) -> String {
var x = x0
var a = x.rounded(.down)
var (h1, k1, h, k) = (1, 0, Int(a), 1)
while x - a > eps * Double(k) * Double(k) {
x = 1.0/(x - a)
a = x.rounded(.down)
(h1, k1, h, k) = (h, k, h1 + Int(a) * h, k1 + Int(a) * k)
}
return "\(h)/\(k)"
}
As you notice, the decimal value of ShutterSpeedValue printed as 4.321956769055745 isn't even equal to 1/20.

Resolved.
As per
https://www.dpreview.com/forums/post/54376235
ShutterSpeedValue is defined as APEX value, where:
ShutterSpeed = -log2(ExposureTime)
So -log2(1/20) is 4.3219, just as what I observed.
So to get the ShutterSpeedValue, I use the following:
"1/\(ceil(pow(2, Double(4.321956769055745))))"
I tested 3 different photos and 1/20, 1/15 and 1/1919 were all correctly calculated using your formula.

Related

Percentage difference between 2 images

I have an app where I'm taking 2 UIImage instances as input with the goal of providing as output a percentage value indicating how different (or similar). Is there anything in UIKit or Core Graphics that I can use to do this? For example, 100% would indicate a perfect match.
Here's my input data:
]1
]2
I would expect less than 100% for the above, since they are clearly different.
Also open to 3rd party suggestions.
A very very simple way to achive this is to iterate over both images and comapre each pixel. With the width and the height of the pixel you'll be able to get the difference of the pixels as an percentage value.
Here is an example implementation in swift that shows how to iterate over the pixels of an image. It also shows how to get the R, G and B values for each pixel which (so I thnik) should be the base for the comparison:
import Foundation
import QuartzCore
import AppKit
let imagePath : NSURL? = NSURL( fileURLWithPath: "/Users/fabi/Desktop/Test.JPG" );
if imagePath != nil {
var image = CIImage( contentsOfURL: imagePath )
var imageProperties : NSDictionary = image.properties()
var imageWidth : NSNumber? = imageProperties.valueForKey( "PixelHeight" ) as? NSNumber
var imageHeight : NSNumber? = imageProperties.valueForKey( "PixelWidth" ) as? NSNumber
println( imageWidth?.integerValue )
println( imageHeight?.integerValue )
var bitmapImage : NSBitmapImageRep = NSBitmapImageRep( CIImage: image )
for var w = 0; w <= imageHeight?.integerValue; ++w {
for var h = 0; h <= imageWidth?.integerValue; ++h {
var pixelColor : NSColor? = bitmapImage.colorAtX( w, y: h )
println( "R: " + pixelColor?.redComponent );
println( "G: " + pixelColor?.greenComponent );
println( "B: " + pixelColor?.blueComponent );
}
}
}

Simple swapping code not working in swift

I am trying to take transpose of a 2d array in swift. But I don't know why the swapping is not happening.
The array remains the same after taking transpose. I am working with the following code:
var array_4x4 = [[Int]](count: 4, repeatedValue: [Int](count: 4, repeatedValue: 4))
for i in 0..<4
{
for j in 0..<4
{
let temp = Int(arc4random_uniform((100 + 1)) - 1) + 1
array_4x4[i][j] = temp
}
}
for i in 0..<4
{
for j in 0..<4 // code in this loop is not working
{
let temp = array_4x4[i][j]
array_4x4[i][j] = array_4x4[j][i]
array_4x4[j][i] = temp
}
}
Your nested loop runs over all possible array indices (i, j), which means that
each array element is swapped with the transposed element twice.
For example, when i=1 and j=2, the (1, 2) and the (2, 1) array elements are swapped.
Later, when i=2 and j=1, these elements are swapped back.
As a consequence, the matrix is identical to the original matrix in the end.
The solution is to iterate only over (i, j) pairs with i < j,
i.e. swap only the elements above the diagonal with their
counterpart below the diagonal:
for i in 0..<4 {
for j in (i + 1)..<4 {
let temp = array_4x4[i][j]
array_4x4[i][j] = array_4x4[j][i]
array_4x4[j][i] = temp
}
}
Note that the Swift standard library already has a function to
exchange two values:
for i in 0..<4 {
for j in (i + 1)..<4 {
swap(&array_4x4[i][j], &array_4x4[j][i])
}
}
And just for the sake of completeness:
an alternative solution would be to compute the transposed matrix as
a value, and assign it to the same (or a different) variable:
array_4x4 = (0..<4).map { i in (0..<4).map { j in array_4x4[j][i] } }

Swift metal parallel sum calculation of array on iOS

Based on #Kametrixom answer, I have made some test application for parallel calculation of sum in an array.
My test application looks like this:
import UIKit
import Metal
class ViewController: UIViewController {
// Data type, has to be the same as in the shader
typealias DataType = CInt
override func viewDidLoad() {
super.viewDidLoad()
let data = (0..<10000000).map{ _ in DataType(200) } // Our data, randomly generated
var start, end : UInt64
var result:DataType = 0
start = mach_absolute_time()
data.withUnsafeBufferPointer { buffer in
for elem in buffer {
result += elem
}
}
end = mach_absolute_time()
print("CPU result: \(result), time: \(Double(end - start) / Double(NSEC_PER_SEC))")
result = 0
start = mach_absolute_time()
result = sumParallel4(data)
end = mach_absolute_time()
print("Metal result: \(result), time: \(Double(end - start) / Double(NSEC_PER_SEC))")
result = 0
start = mach_absolute_time()
result = sumParralel(data)
end = mach_absolute_time()
print("Metal result: \(result), time: \(Double(end - start) / Double(NSEC_PER_SEC))")
result = 0
start = mach_absolute_time()
result = sumParallel3(data)
end = mach_absolute_time()
print("Metal result: \(result), time: \(Double(end - start) / Double(NSEC_PER_SEC))")
}
func sumParralel(data : Array<DataType>) -> DataType {
let count = data.count
let elementsPerSum: Int = Int(sqrt(Double(count)))
let device = MTLCreateSystemDefaultDevice()!
let parsum = device.newDefaultLibrary()!.newFunctionWithName("parsum")!
let pipeline = try! device.newComputePipelineStateWithFunction(parsum)
var dataCount = CUnsignedInt(count)
var elementsPerSumC = CUnsignedInt(elementsPerSum)
let resultsCount = (count + elementsPerSum - 1) / elementsPerSum // Number of individual results = count / elementsPerSum (rounded up)
let dataBuffer = device.newBufferWithBytes(data, length: strideof(DataType) * count, options: []) // Our data in a buffer (copied)
let resultsBuffer = device.newBufferWithLength(strideof(DataType) * resultsCount, options: []) // A buffer for individual results (zero initialized)
let results = UnsafeBufferPointer<DataType>(start: UnsafePointer(resultsBuffer.contents()), count: resultsCount) // Our results in convenient form to compute the actual result later
let queue = device.newCommandQueue()
let cmds = queue.commandBuffer()
let encoder = cmds.computeCommandEncoder()
encoder.setComputePipelineState(pipeline)
encoder.setBuffer(dataBuffer, offset: 0, atIndex: 0)
encoder.setBytes(&dataCount, length: sizeofValue(dataCount), atIndex: 1)
encoder.setBuffer(resultsBuffer, offset: 0, atIndex: 2)
encoder.setBytes(&elementsPerSumC, length: sizeofValue(elementsPerSumC), atIndex: 3)
// We have to calculate the sum `resultCount` times => amount of threadgroups is `resultsCount` / `threadExecutionWidth` (rounded up) because each threadgroup will process `threadExecutionWidth` threads
let threadgroupsPerGrid = MTLSize(width: (resultsCount + pipeline.threadExecutionWidth - 1) / pipeline.threadExecutionWidth, height: 1, depth: 1)
// Here we set that each threadgroup should process `threadExecutionWidth` threads, the only important thing for performance is that this number is a multiple of `threadExecutionWidth` (here 1 times)
let threadsPerThreadgroup = MTLSize(width: pipeline.threadExecutionWidth, height: 1, depth: 1)
encoder.dispatchThreadgroups(threadgroupsPerGrid, threadsPerThreadgroup: threadsPerThreadgroup)
encoder.endEncoding()
var result : DataType = 0
cmds.commit()
cmds.waitUntilCompleted()
for elem in results {
result += elem
}
return result
}
func sumParralel1(data : Array<DataType>) -> UnsafeBufferPointer<DataType> {
let count = data.count
let elementsPerSum: Int = Int(sqrt(Double(count)))
let device = MTLCreateSystemDefaultDevice()!
let parsum = device.newDefaultLibrary()!.newFunctionWithName("parsum")!
let pipeline = try! device.newComputePipelineStateWithFunction(parsum)
var dataCount = CUnsignedInt(count)
var elementsPerSumC = CUnsignedInt(elementsPerSum)
let resultsCount = (count + elementsPerSum - 1) / elementsPerSum // Number of individual results = count / elementsPerSum (rounded up)
let dataBuffer = device.newBufferWithBytes(data, length: strideof(DataType) * count, options: []) // Our data in a buffer (copied)
let resultsBuffer = device.newBufferWithLength(strideof(DataType) * resultsCount, options: []) // A buffer for individual results (zero initialized)
let results = UnsafeBufferPointer<DataType>(start: UnsafePointer(resultsBuffer.contents()), count: resultsCount) // Our results in convenient form to compute the actual result later
let queue = device.newCommandQueue()
let cmds = queue.commandBuffer()
let encoder = cmds.computeCommandEncoder()
encoder.setComputePipelineState(pipeline)
encoder.setBuffer(dataBuffer, offset: 0, atIndex: 0)
encoder.setBytes(&dataCount, length: sizeofValue(dataCount), atIndex: 1)
encoder.setBuffer(resultsBuffer, offset: 0, atIndex: 2)
encoder.setBytes(&elementsPerSumC, length: sizeofValue(elementsPerSumC), atIndex: 3)
// We have to calculate the sum `resultCount` times => amount of threadgroups is `resultsCount` / `threadExecutionWidth` (rounded up) because each threadgroup will process `threadExecutionWidth` threads
let threadgroupsPerGrid = MTLSize(width: (resultsCount + pipeline.threadExecutionWidth - 1) / pipeline.threadExecutionWidth, height: 1, depth: 1)
// Here we set that each threadgroup should process `threadExecutionWidth` threads, the only important thing for performance is that this number is a multiple of `threadExecutionWidth` (here 1 times)
let threadsPerThreadgroup = MTLSize(width: pipeline.threadExecutionWidth, height: 1, depth: 1)
encoder.dispatchThreadgroups(threadgroupsPerGrid, threadsPerThreadgroup: threadsPerThreadgroup)
encoder.endEncoding()
cmds.commit()
cmds.waitUntilCompleted()
return results
}
func sumParallel3(data : Array<DataType>) -> DataType {
var results = sumParralel1(data)
repeat {
results = sumParralel1(Array(results))
} while results.count >= 100
var result : DataType = 0
for elem in results {
result += elem
}
return result
}
func sumParallel4(data : Array<DataType>) -> DataType {
let queue = NSOperationQueue()
queue.maxConcurrentOperationCount = 4
var a0 : DataType = 0
var a1 : DataType = 0
var a2 : DataType = 0
var a3 : DataType = 0
let op0 = NSBlockOperation( block : {
for i in 0..<(data.count/4) {
a0 = a0 + data[i]
}
})
let op1 = NSBlockOperation( block : {
for i in (data.count/4)..<(data.count/2) {
a1 = a1 + data[i]
}
})
let op2 = NSBlockOperation( block : {
for i in (data.count/2)..<(3 * data.count/4) {
a2 = a2 + data[i]
}
})
let op3 = NSBlockOperation( block : {
for i in (3 * data.count/4)..<(data.count) {
a3 = a3 + data[i]
}
})
queue.addOperation(op0)
queue.addOperation(op1)
queue.addOperation(op2)
queue.addOperation(op3)
queue.suspended = false
queue.waitUntilAllOperationsAreFinished()
let aaa: DataType = a0 + a1 + a2 + a3
return aaa
}
}
And I have a shader that looks like this:
kernel void parsum(const device DataType* data [[ buffer(0) ]],
const device uint& dataLength [[ buffer(1) ]],
device DataType* sums [[ buffer(2) ]],
const device uint& elementsPerSum [[ buffer(3) ]],
const uint tgPos [[ threadgroup_position_in_grid ]],
const uint tPerTg [[ threads_per_threadgroup ]],
const uint tPos [[ thread_position_in_threadgroup ]]) {
uint resultIndex = tgPos * tPerTg + tPos; // This is the index of the individual result, this var is unique to this thread
uint dataIndex = resultIndex * elementsPerSum; // Where the summation should begin
uint endIndex = dataIndex + elementsPerSum < dataLength ? dataIndex + elementsPerSum : dataLength; // The index where summation should end
for (; dataIndex < endIndex; dataIndex++)
sums[resultIndex] += data[dataIndex];
}
On my surprise function sumParallel4 is the fastest, which I thought it shouldn't be. I noticed that when I call functions sumParralel and sumParallel3, the first function is always slower even if I change the order of function. (So if I call sumParralel first this is slower, if I call sumParallel3 this is slower.).
Why is this? Why is sumParallel3 not a lot faster than sumParallel ? Why is sumParallel4 the fastest, although it is calculated on CPU?
How can I update my GPU function with posix_memalign ? I know it should work faster because it would have shared memory between GPU and CPU, but I don't know witch array should be allocated this way (data or result) and how can I allocate data with posix_memalign if data is parameter passed in function?
In running these tests on an iPhone 6, I saw the Metal version run between 3x slower and 2x faster than the naive CPU summation. With the modifications I describe below, it was consistently faster.
I found that a lot of the cost in running the Metal version could be attributed not merely to the allocation of the buffers, though that was significant, but also to the first-time creation of the device and compute pipeline state. These are actions you'd normally perform once at application initialization, so it's not entirely fair to include them in the timing.
It should also be noted that if you're running these tests through Xcode with the Metal validation layer and GPU frame capture enabled, that has a significant run-time cost and will skew the results in the CPU's favor.
With those caveats, here's how you might use posix_memalign to allocate memory that can be used to back a MTLBuffer. The trick is to ensure that the memory you request is in fact page-aligned (i.e. its address is a multiple of getpagesize()), which may entail rounding up the amount of memory beyond how much you actually need to store your data:
let dataCount = 1_000_000
let dataSize = dataCount * strideof(DataType)
let pageSize = Int(getpagesize())
let pageCount = (dataSize + (pageSize - 1)) / pageSize
var dataPointer: UnsafeMutablePointer<Void> = nil
posix_memalign(&dataPointer, pageSize, pageCount * pageSize)
let data = UnsafeMutableBufferPointer(start: UnsafeMutablePointer<DataType>(dataPointer),
count: (pageCount * pageSize) / strideof(DataType))
for i in 0..<dataCount {
data[i] = 200
}
This does require making data an UnsafeMutableBufferPointer<DataType>, rather than an [DataType], since Swift's Array allocates its own backing store. You'll also need to pass along the count of data items to operate on, since the count of the mutable buffer pointer has been rounded up to make the buffer page-aligned.
To actually create a MTLBuffer backed with this data, use the newBufferWithBytesNoCopy(_:length:options:deallocator:) API. It's crucial that, once again, the length you provide is a multiple of the page size; otherwise this method returns nil:
let roundedUpDataSize = strideof(DataType) * data.count
let dataBuffer = device.newBufferWithBytesNoCopy(data.baseAddress, length: roundedUpDataSize, options: [], deallocator: nil)
Here, we don't provide a deallocator, but you should free the memory when you're done using it, by passing the baseAddress of the buffer pointer to free().

Swift- 'For' Loop not adding variable to total result

I am trying to create a function in Playground using Swift where a calculation is made several times, and then added to the total sum of calculations until the loop is over. Everything seems to be working, except that when I try to sum the every calculation to the last total, it just gives me the value of the calculation. Here is my code:
func Calc(diff: String, hsh: String, sperunit: Float, rate: Float, n: Int16, p: Float, length: Int16) -> Float {
//Divisions per Year
let a: Int16 = length/n
let rem = length - (a*n)
let spl = Calc(diff, hsh: hash, sperunit: sperunit, rate: rate)
for var i = 0; i < Int(a) ; i++ { //also tried for i in i..<a
var result: Float = 0
let h = (spl * Float(n) / pow (p,Float(i))) //This gives me a correct result
result += h //This gives me the same result from h
finalResult = result
}
finalResult = finalResult + (Float(rem) * spl / pow (p,Float(a))) //This line is meant to get the result variable out of the loop and do an extra calculation outside of the loop
print(finalResult)
return finalResult
}
Am I doing something wrong?
Currently your variable result is scoped to the loop and does not exist outside of it. Additionally every run of the loop creates a new result variable, initialized with 0.
What you have to do is move the line var result: Float = 0 in front of the for loop:
var result: Float = 0
for var i = 0; i < Int(a) ; i++ {
let h = (spl * Float(n) / pow (p,Float(i)))
result += h
finalResult = result
}
Additionally you can remove the repeated assignment of finalResult = result and just do it once after the loop is over.
You can probably remove the finalResult completely. Just write
var result: Float = 0
for var i = 0; i < Int(a) ; i++ {
let h = (spl * Float(n) / pow (p,Float(i)))
result += h
}
result += (Float(rem) * spl / pow (p,Float(a)))
print(result)
return result

Convert C code into F#

I am looking to convert the following C code into F# (this is the fast inverse square root algorithm):
float Q_rsqrt( float number )
{
long i;
float x2, y;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // Extract bit pattern
i = 0x5f3759df - ( i >> 1 );
y = * ( float * ) &i; // Convert back to float.
y = y * ( 1.5F - ( x2 * y * y ) );
return y;
}
First of all you should do some research. Then if you stuck specify with what you have problem.
Here is solution by Kit Eason.
let fastInvSqrt (n : float32) : float32 =
let MAGIC_NUMBER : int32 = 0x5f3759df
let THREE_HALVES = 1.5f
let x2 = n * 0.5f
let i = MAGIC_NUMBER - (System.BitConverter.ToInt32(System.BitConverter.GetBytes(n), 0) >>> 1)
let y = System.BitConverter.ToSingle(System.BitConverter.GetBytes(i), 0)
y * (THREE_HALVES - (x2 * y * y))
// Examples:
let x = fastInvSqrt 4.0f
// Output: val x : float32 = 0.499153584f
let x' = 1. / sqrt(4.0)
// Output: val x' : float = 0.5
When it comes to performance and low-level optimization it is often a good idea to measure before and after. The fast-inverse trick is very cool but it's approximates the inverse square and the question is if tricky code like this is truely necessary these days (in the DOOM days when float performace was crap the trick was amazing).
Anyway so I built a simple performance test bench in order to compare the trivial implementation with the solution provided by Kit Eason/lad2025 and another one that doesn't allocate byte arrays.
open System
open System.Diagnostics
open System.Runtime.InteropServices
[<Literal>]
let MAGIC_NUMBER : int32 = 0x5f3759df
[<Literal>]
let THREE_HALVES = 1.5F
[<Literal>]
let HALF = 0.5F
[<Literal>]
let OUTER = 1000
[<Literal>]
let INNER = 10000
let inline invSqr (x : float32) : float32 = 1.F / sqrt x
let fInvSqr (x : float32) : float32 =
let x2 = x * 0.5f
// Allocates two byte arrays creating GC pressure ==> hurts performance
let i = MAGIC_NUMBER - (BitConverter.ToInt32(BitConverter.GetBytes(x), 0) >>> 1)
let y = BitConverter.ToSingle(BitConverter.GetBytes(i), 0)
y * (THREE_HALVES - (x2 * y * y))
// Susceptible to race conditions & endianess issues
[<StructLayout (LayoutKind.Explicit)>]
type Bits =
struct
[<FieldOffset(0)>]
val mutable f: float32
[<FieldOffset(0)>]
val mutable i: int32
end
let mutable bits = Bits ()
let fInvSqr2 (x : float32) : float32 =
let x2 = x * 0.5F
bits.f <- x
let i = MAGIC_NUMBER - (bits.i >>> 1)
bits.i <- i
let y = bits.f
y * (THREE_HALVES - (x2 * y * y))
let timeIt n (a : unit -> 'T) : int64 * 'T =
let r = a ()
let sw = Stopwatch ()
sw.Start ()
for i = 1 to n do
ignore <| a ()
sw.Stop ()
sw.ElapsedMilliseconds, r
[<EntryPoint>]
let main argv =
let testCases =
[|
"invSqr" , fun () ->
let mutable sum = 0.F
for x = 1 to INNER do
sum <- sum + invSqr (float32 x)
sum
"fInvSqr" , fun () ->
let mutable sum = 0.F
for x = 1 to INNER do
sum <- sum + fInvSqr (float32 x)
sum
"fInvSqr2" , fun () ->
let mutable sum = 0.F
for x = 1 to INNER do
sum <- sum + fInvSqr2 (float32 x)
sum
|]
for name, action in testCases do
printfn "Running %s %d times..." name (OUTER*INNER)
let elapsed, result = timeIt OUTER action
printfn "... it took %d ms product result: %f" elapsed result
0
The performance test result on my machine:
Running invSqr 10000000 times...
... it took 78 ms product result: 198.544600
Running fInvSqr 10000000 times...
... it took 311 ms product result: 198.358200
Running fInvSqr2 10000000 times...
... it took 49 ms product result: 198.358200
Press any key to continue . . .
So we see that fInvSqr is actually 3 times slower than the trivial solution, most likely because of the byte allocation. In addition the cost of GC is hidden in these numbers and might add non-deterministic performance degration.
fInvSqr2 seems to perform slightly better but there are drawbacks here as well
The result is off by 0.1%
The Bits trick is susceptible to race conditions (fixable)
The Bits trick is suspectible to endian issues (if you are run the program on a CPU with different endianess it might break)
Is the performance gains worth the drawbacks? Since a program probably is not just built up from inverse square operations the effective performance gain might be much smaller in reality. I have a hard time imagining a scenario where I would so presurres for performance I opt for the fast inverse trick today but then it all depends on your context.

Resources