Skip to content

Commit

Permalink
Fixes and small improvements (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-rank authored May 16, 2024
1 parent 50c3b64 commit 9b69767
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 31 deletions.
10 changes: 5 additions & 5 deletions burstphoto/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ struct SettingsView: View {
Text($0)
}
}.pickerStyle(MenuPickerStyle()).frame(width: 216)
}.padding(.horizontal, 15).padding(.top, 20).padding(.bottom, 12)
}.padding(.horizontal, 15).padding(.top, 20).padding(.bottom, 11)

VStack(alignment: .leading) {

Expand All @@ -243,7 +243,7 @@ struct SettingsView: View {
? Text("max. ").foregroundColor(.accentColor) + Text("(simple average w/o alignment)")
: Text("\(Int(settings.noise_reduction))")
)).font(.system(size: 14, weight: .medium))
.opacity(user_changing_nr ? 0.75 : 1.0).padding(.top, 12)
.opacity(user_changing_nr ? 0.75 : 1.0).padding(.top, 15)

// the slider/stepper should provide haptic feedback when value changes
// but there's one exception: we don't provide feedback on the first click of the stepper,
Expand Down Expand Up @@ -276,7 +276,7 @@ struct SettingsView: View {
}.padding(.horizontal, 15)
Spacer()
.navigationTitle("Preferences")
}.tabItem {Label("Exposure & Noise ", image: "camera_icon")}
}.tabItem {Label("Exposure & Noise ", image: "camera_icon").imageScale(.large)}

VStack(alignment: .leading) {

Expand Down Expand Up @@ -321,9 +321,9 @@ struct SettingsView: View {
}.padding(.horizontal, 15).padding(.vertical, 11)
Spacer()
.navigationTitle("Preferences")
}.tabItem {Label("Stacking & Output ", image: "stack_icon")}
}.tabItem {Label("Stacking & Output ", image: "stack_icon").imageScale(.large)}
}
.frame(width: 390, height: 225)
.frame(width: 390, height: 222)
}
}

Expand Down
45 changes: 21 additions & 24 deletions burstphoto/texture/texture.swift
Original file line number Diff line number Diff line change
Expand Up @@ -512,30 +512,27 @@ func find_hotpixels(_ textures: [MTLTexture], _ hotpixel_weight_texture: MTLText
black_level3 += (black_level[comp_idx][3] == -1) ? 0.0 : Double(black_level[comp_idx][3])
}

// iterate over all images and correct hot pixels in each texture
for comp_idx in 0..<textures.count {

let command_buffer = command_queue.makeCommandBuffer()!
command_buffer.label = "Hotpixel Detection: \(comp_idx)"
let command_encoder = command_buffer.makeComputeCommandEncoder()!
let state = find_hotpixels_state
command_encoder.setComputePipelineState(state)
let threads_per_grid = MTLSize(width: average_texture.width-4, height: average_texture.height-4, depth: 1)
let threads_per_thread_group = get_threads_per_thread_group(state, threads_per_grid)
command_encoder.setTexture(average_texture, index: 0)
command_encoder.setTexture(hotpixel_weight_texture, index: 1)
command_encoder.setBuffer(mean_texture_buffer, offset: 0, index: 0)
command_encoder.setBytes([Float32(black_level0/Double(textures.count))], length: MemoryLayout<Float32>.stride, index: 1)
command_encoder.setBytes([Float32(black_level1/Double(textures.count))], length: MemoryLayout<Float32>.stride, index: 2)
command_encoder.setBytes([Float32(black_level2/Double(textures.count))], length: MemoryLayout<Float32>.stride, index: 3)
command_encoder.setBytes([Float32(black_level3/Double(textures.count))], length: MemoryLayout<Float32>.stride, index: 4)
command_encoder.setBytes([Float32(hot_pixel_threshold)], length: MemoryLayout<Float32>.stride, index: 5)
command_encoder.setBytes([Float32(hot_pixel_multiplicator)], length: MemoryLayout<Float32>.stride, index: 6)
command_encoder.setBytes([Float32(correction_strength)], length: MemoryLayout<Float32>.stride, index: 7)
command_encoder.dispatchThreads(threads_per_grid, threadsPerThreadgroup: threads_per_thread_group)
command_encoder.endEncoding()
command_buffer.commit()
}
// determine hot pixel probability for each pixel in the average texture
let command_buffer = command_queue.makeCommandBuffer()!
command_buffer.label = "Hotpixel Detection"
let command_encoder = command_buffer.makeComputeCommandEncoder()!
let state = find_hotpixels_state
command_encoder.setComputePipelineState(state)
let threads_per_grid = MTLSize(width: average_texture.width-4, height: average_texture.height-4, depth: 1)
let threads_per_thread_group = get_threads_per_thread_group(state, threads_per_grid)
command_encoder.setTexture(average_texture, index: 0)
command_encoder.setTexture(hotpixel_weight_texture, index: 1)
command_encoder.setBuffer(mean_texture_buffer, offset: 0, index: 0)
command_encoder.setBytes([Float32(black_level0/Double(textures.count))], length: MemoryLayout<Float32>.stride, index: 1)
command_encoder.setBytes([Float32(black_level1/Double(textures.count))], length: MemoryLayout<Float32>.stride, index: 2)
command_encoder.setBytes([Float32(black_level2/Double(textures.count))], length: MemoryLayout<Float32>.stride, index: 3)
command_encoder.setBytes([Float32(black_level3/Double(textures.count))], length: MemoryLayout<Float32>.stride, index: 4)
command_encoder.setBytes([Float32(hot_pixel_threshold)], length: MemoryLayout<Float32>.stride, index: 5)
command_encoder.setBytes([Float32(hot_pixel_multiplicator)], length: MemoryLayout<Float32>.stride, index: 6)
command_encoder.setBytes([Float32(correction_strength)], length: MemoryLayout<Float32>.stride, index: 7)
command_encoder.dispatchThreads(threads_per_grid, threadsPerThreadgroup: threads_per_thread_group)
command_encoder.endEncoding()
command_buffer.commit()
}
}

Expand Down
4 changes: 2 additions & 2 deletions docs/_pages/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The only *natively* supported image format is DNG. However, if you download and

### Processing images

To process a burst of images, please drag-and-drop them into the app. You can either drag-and-drop individual images or a folder containing the whole burst. The resulting image will be in the RAW-DNG format and its filename contains the most important settings selected. It can be further processed with the RAW converter of choice.
To process a burst of images, please drag-and-drop them into the app. You can either drag-and-drop individual images or a folder containing the whole burst. The resulting image will be either based on the middle frame of the burst (uniform exposure) or on the most central, darkest frame of the burst (bracketed exposure). The output file will be in the RAW-DNG format and its filename contains the most important settings selected. It can be further processed with the RAW converter of choice.

{% include figure image_path="/assets/images/help/drag-and-drop.jpg" %}

Expand Down Expand Up @@ -49,7 +49,7 @@ There are six settings in the preferences panel of the app. Their default values
- To improve tonality in the shadows, you can experiment with the various `Exposure control` options. The setting "Linear (full bit range)" is recommended as the starting point. In addition, you can try setting the `Output bit depth` to 16 bit.
- `Exposure control` only works if several exposure metadata information can be extracted correctly from the DNG. If you get any color casts for your files, you can try the setting „Off“, try to decrease `Noise reduction`, set `Output bit depth` to "Native" and/or use only bursts with uniform exposure. The setting "Off" should only be used as a fallback solution in case the setting "Linear (full bit range)" exhibits artifacts.
- When the exposure bias is derived from shutter speed, only a relative bias between the frames can be calculated. In that case, an absolute exposure bias of -2 EV is assumed for the darkest frame.
- If you see any motion artifacts or ghosting in the output image, decrease`Noise reduction`.
- If you see any motion artifacts, ghosting or color casts in the output image, decrease`Noise reduction`.
- If you see too much noise in the output image, increase `Noise reduction`.
- If you work on a tripod and capture a static scene, you may apply the "max." setting for `Noise reduction`, which applies simple averaging without alignment. This provides the best possible noise reduction at the expense of having no robustness against motion.

Expand Down

0 comments on commit 9b69767

Please sign in to comment.