Skip to content

Commit 878ab08

Browse files
committed
Fix a race condition in image loading.
If an attempt was made to load the full image before the metadata was loaded, the full image would never be loaded. Also, auto-sizing the list box in photocull was causing issues, so is now turned off.
1 parent f9ad560 commit 878ab08

File tree

3 files changed

+175
-145
lines changed

3 files changed

+175
-145
lines changed

PhotoCull/PhotoCullWindow.xaml

Lines changed: 151 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,9 @@
2929
</Window.Resources>
3030
<Grid>
3131
<Grid.ColumnDefinitions>
32-
<ColumnDefinition Width="Auto"/>
33-
<ColumnDefinition Width="Auto"/>
34-
<ColumnDefinition/>
35-
<ColumnDefinition/>
32+
<ColumnDefinition Width="*" />
33+
<ColumnDefinition Width="Auto" />
34+
<ColumnDefinition Width="7*" />
3635
</Grid.ColumnDefinitions>
3736
<Grid Grid.Column="0">
3837
<Grid.RowDefinitions>
@@ -67,146 +66,155 @@
6766
Grid.Column="1"
6867
ResizeBehavior="PreviousAndNext" />
6968
<Grid Grid.Column="2">
70-
<Grid.RowDefinitions>
71-
<RowDefinition />
72-
<RowDefinition Height="Auto"/>
73-
</Grid.RowDefinitions>
74-
<Button Grid.Row="0"
75-
VerticalContentAlignment="Stretch"
76-
HorizontalContentAlignment="Stretch"
69+
<Grid.ColumnDefinitions>
70+
<ColumnDefinition/>
71+
<ColumnDefinition/>
72+
</Grid.ColumnDefinitions>
73+
<Grid Grid.Column="0">
74+
<Grid.RowDefinitions>
75+
<RowDefinition />
76+
<RowDefinition Height="Auto"/>
77+
</Grid.RowDefinitions>
78+
<Button Grid.Row="0"
79+
VerticalContentAlignment="Stretch"
80+
HorizontalContentAlignment="Stretch"
7781
Click="onClickFirst">
78-
<Grid>
79-
<Grid.RowDefinitions>
80-
<RowDefinition Height="Auto"/>
81-
<RowDefinition />
82-
</Grid.RowDefinitions>
83-
<TextBlock Grid.Row="0">
84-
<TextBlock.Text>
85-
<PriorityBinding>
86-
<PriorityBinding.Bindings>
87-
<Binding ElementName="window"
88-
Path="SelectedPhotos[0].ShortTitle"/>
89-
<Binding ElementName="window"
90-
Path="Photos[0].ShortTitle"/>
91-
</PriorityBinding.Bindings>
92-
</PriorityBinding>
93-
</TextBlock.Text>
94-
<TextBlock.TextDecorations>
95-
<PriorityBinding>
96-
<PriorityBinding.Bindings>
97-
<Binding Path="SelectedPhotos[0].MarkedForDeletion"
98-
Converter="{StaticResource RejectedToStrikethroughValueConverter}"
99-
ElementName="window" />
100-
<Binding Path="Photos[0].MarkedForDeletion"
101-
Converter="{StaticResource RejectedToStrikethroughValueConverter}"
102-
ElementName="window" />
103-
</PriorityBinding.Bindings>
104-
</PriorityBinding>
105-
</TextBlock.TextDecorations>
106-
</TextBlock>
107-
<ptwpf:ImageZoomer Grid.Row="1"
108-
MoveToPan="True"
109-
Name="firstZoom">
110-
<ptwpf:ImageZoomer.Photo>
111-
<PriorityBinding>
112-
<PriorityBinding.Bindings>
113-
<Binding ElementName="window"
114-
Path="SelectedPhotos[0]"/>
115-
<Binding ElementName="window"
116-
Path="Photos[0]"/>
117-
</PriorityBinding.Bindings>
118-
</PriorityBinding>
119-
</ptwpf:ImageZoomer.Photo>
120-
<ptwpf:ImageZoomer.Scale>
121-
<Binding ElementName="secondZoom"
122-
Path="Scale" Mode="TwoWay"/>
123-
</ptwpf:ImageZoomer.Scale>
124-
<ptwpf:ImageZoomer.ImageX>
125-
<Binding ElementName="secondZoom"
126-
Path="ImageX" Mode="TwoWay"/>
127-
</ptwpf:ImageZoomer.ImageX>
128-
<ptwpf:ImageZoomer.ImageY>
129-
<Binding ElementName="secondZoom"
130-
Path="ImageY" Mode="TwoWay"/>
131-
</ptwpf:ImageZoomer.ImageY>
132-
</ptwpf:ImageZoomer>
133-
</Grid>
134-
</Button>
135-
<Button Grid.Row="1" Click="onDistinctFirst">
136-
<Button.Content>
137-
Move to next image group
138-
</Button.Content>
139-
<Button.IsEnabled>
140-
<Binding Path="Photos.Count"
141-
ElementName="window"
142-
Converter="{StaticResource AnyToEnabledValueConverter}"/>
143-
</Button.IsEnabled>
144-
</Button>
145-
</Grid>
146-
<Grid Grid.Column="3">
147-
<Grid.RowDefinitions>
148-
<RowDefinition />
149-
<RowDefinition Height="Auto"/>
150-
</Grid.RowDefinitions>
151-
<Button Grid.Row="0"
152-
VerticalContentAlignment="Stretch"
153-
HorizontalContentAlignment="Stretch"
154-
Click="onClickSecond">
155-
<Grid>
156-
<Grid.RowDefinitions>
157-
<RowDefinition Height="Auto"/>
158-
<RowDefinition />
159-
</Grid.RowDefinitions>
160-
<TextBlock Grid.Row="0">
161-
<TextBlock.Text>
162-
<PriorityBinding>
163-
<PriorityBinding.Bindings>
164-
<Binding ElementName="window"
165-
Path="SelectedPhotos[1].ShortTitle"/>
166-
<Binding ElementName="window"
167-
Path="Photos[1].ShortTitle"/>
168-
</PriorityBinding.Bindings>
169-
</PriorityBinding>
170-
</TextBlock.Text>
171-
<TextBlock.TextDecorations>
172-
<PriorityBinding>
173-
<PriorityBinding.Bindings>
174-
<Binding Path="SelectedPhotos[1].MarkedForDeletion"
175-
Converter="{StaticResource RejectedToStrikethroughValueConverter}"
176-
ElementName="window" />
177-
<Binding Path="Photos[1].MarkedForDeletion"
178-
Converter="{StaticResource RejectedToStrikethroughValueConverter}"
179-
ElementName="window" />
180-
</PriorityBinding.Bindings>
181-
</PriorityBinding>
182-
</TextBlock.TextDecorations>
183-
</TextBlock>
184-
<ptwpf:ImageZoomer Grid.Row="1"
185-
MoveToPan="True"
186-
x:Name="secondZoom">
187-
<ptwpf:ImageZoomer.Photo>
188-
<PriorityBinding>
189-
<PriorityBinding.Bindings>
190-
<Binding ElementName="window"
191-
Path="SelectedPhotos[1]"/>
192-
<Binding ElementName="window"
193-
Path="Photos[1]"/>
194-
</PriorityBinding.Bindings>
195-
</PriorityBinding>
196-
</ptwpf:ImageZoomer.Photo>
197-
</ptwpf:ImageZoomer>
198-
</Grid>
199-
</Button>
200-
<Button Grid.Row="1" Click="onDistinctSecond">
201-
<Button.Content>
202-
Move to next image group
203-
</Button.Content>
204-
<Button.IsEnabled>
205-
<Binding Path="Photos.Count"
206-
ElementName="window"
207-
Converter="{StaticResource AnyToEnabledValueConverter}"/>
208-
</Button.IsEnabled>
209-
</Button>
82+
<Grid>
83+
<Grid.RowDefinitions>
84+
<RowDefinition Height="Auto"/>
85+
<RowDefinition />
86+
</Grid.RowDefinitions>
87+
<TextBlock Grid.Row="0">
88+
<TextBlock.Text>
89+
<PriorityBinding>
90+
<PriorityBinding.Bindings>
91+
<Binding ElementName="window"
92+
Path="SelectedPhotos[0].ShortTitle"/>
93+
<Binding ElementName="window"
94+
Path="Photos[0].ShortTitle"/>
95+
</PriorityBinding.Bindings>
96+
</PriorityBinding>
97+
</TextBlock.Text>
98+
<TextBlock.TextDecorations>
99+
<PriorityBinding>
100+
<PriorityBinding.Bindings>
101+
<Binding Path="SelectedPhotos[0].MarkedForDeletion"
102+
Converter="{StaticResource RejectedToStrikethroughValueConverter}"
103+
ElementName="window" />
104+
<Binding Path="Photos[0].MarkedForDeletion"
105+
Converter="{StaticResource RejectedToStrikethroughValueConverter}"
106+
ElementName="window" />
107+
</PriorityBinding.Bindings>
108+
</PriorityBinding>
109+
</TextBlock.TextDecorations>
110+
</TextBlock>
111+
<ptwpf:ImageZoomer Grid.Row="1"
112+
MoveToPan="True"
113+
Name="firstZoom">
114+
<ptwpf:ImageZoomer.Photo>
115+
<PriorityBinding>
116+
<PriorityBinding.Bindings>
117+
<Binding ElementName="window"
118+
Path="SelectedPhotos[0]"/>
119+
<Binding ElementName="window"
120+
Path="Photos[0]"/>
121+
</PriorityBinding.Bindings>
122+
</PriorityBinding>
123+
</ptwpf:ImageZoomer.Photo>
124+
<ptwpf:ImageZoomer.Scale>
125+
<Binding ElementName="secondZoom"
126+
Path="Scale"
127+
Mode="TwoWay"/>
128+
</ptwpf:ImageZoomer.Scale>
129+
<ptwpf:ImageZoomer.ImageX>
130+
<Binding ElementName="secondZoom"
131+
Path="ImageX"
132+
Mode="TwoWay"/>
133+
</ptwpf:ImageZoomer.ImageX>
134+
<ptwpf:ImageZoomer.ImageY>
135+
<Binding ElementName="secondZoom"
136+
Path="ImageY"
137+
Mode="TwoWay"/>
138+
</ptwpf:ImageZoomer.ImageY>
139+
</ptwpf:ImageZoomer>
140+
</Grid>
141+
</Button>
142+
<Button Grid.Row="1" Click="onDistinctFirst">
143+
<Button.Content>
144+
Move to next image group
145+
</Button.Content>
146+
<Button.IsEnabled>
147+
<Binding Path="Photos.Count"
148+
ElementName="window"
149+
Converter="{StaticResource AnyToEnabledValueConverter}"/>
150+
</Button.IsEnabled>
151+
</Button>
152+
</Grid>
153+
<Grid Grid.Column="1">
154+
<Grid.RowDefinitions>
155+
<RowDefinition />
156+
<RowDefinition Height="Auto"/>
157+
</Grid.RowDefinitions>
158+
<Button Grid.Row="0"
159+
VerticalContentAlignment="Stretch"
160+
HorizontalContentAlignment="Stretch"
161+
Click="onClickSecond">
162+
<Grid>
163+
<Grid.RowDefinitions>
164+
<RowDefinition Height="Auto"/>
165+
<RowDefinition />
166+
</Grid.RowDefinitions>
167+
<TextBlock Grid.Row="0">
168+
<TextBlock.Text>
169+
<PriorityBinding>
170+
<PriorityBinding.Bindings>
171+
<Binding ElementName="window"
172+
Path="SelectedPhotos[1].ShortTitle"/>
173+
<Binding ElementName="window"
174+
Path="Photos[1].ShortTitle"/>
175+
</PriorityBinding.Bindings>
176+
</PriorityBinding>
177+
</TextBlock.Text>
178+
<TextBlock.TextDecorations>
179+
<PriorityBinding>
180+
<PriorityBinding.Bindings>
181+
<Binding Path="SelectedPhotos[1].MarkedForDeletion"
182+
Converter="{StaticResource RejectedToStrikethroughValueConverter}"
183+
ElementName="window" />
184+
<Binding Path="Photos[1].MarkedForDeletion"
185+
Converter="{StaticResource RejectedToStrikethroughValueConverter}"
186+
ElementName="window" />
187+
</PriorityBinding.Bindings>
188+
</PriorityBinding>
189+
</TextBlock.TextDecorations>
190+
</TextBlock>
191+
<ptwpf:ImageZoomer Grid.Row="1"
192+
MoveToPan="True"
193+
x:Name="secondZoom">
194+
<ptwpf:ImageZoomer.Photo>
195+
<PriorityBinding>
196+
<PriorityBinding.Bindings>
197+
<Binding ElementName="window"
198+
Path="SelectedPhotos[1]"/>
199+
<Binding ElementName="window"
200+
Path="Photos[1]"/>
201+
</PriorityBinding.Bindings>
202+
</PriorityBinding>
203+
</ptwpf:ImageZoomer.Photo>
204+
</ptwpf:ImageZoomer>
205+
</Grid>
206+
</Button>
207+
<Button Grid.Row="1" Click="onDistinctSecond">
208+
<Button.Content>
209+
Move to next image group
210+
</Button.Content>
211+
<Button.IsEnabled>
212+
<Binding Path="Photos.Count"
213+
ElementName="window"
214+
Converter="{StaticResource AnyToEnabledValueConverter}"/>
215+
</Button.IsEnabled>
216+
</Button>
217+
</Grid>
210218
</Grid>
211219
</Grid>
212220
</Window>

PhotoTagger.Imaging/Photo.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,17 @@ public Photo(string f) {
2626
public BitmapImage FullImage {
2727
get {
2828
var imageRef = this.fullImageRef;
29-
if (imageRef != null && imageRef.TryGetTarget(out BitmapImage target)) {
29+
if (imageRef != null &&
30+
imageRef.TryGetTarget(out BitmapImage target) &&
31+
target != null) {
3032
MemoryCache.Default.Set(
3133
this.FileName,
3234
target,
3335
cachePolicy);
3436
return target;
3537
} else {
36-
if (Interlocked.Exchange(ref this.fullIsLoading, 1) == 0) {
38+
if (this.setFrom != null &&
39+
Interlocked.Exchange(ref this.fullIsLoading, 1) == 0) {
3740
this.loader?.EnqueueFullSizeRead(this, this.setFrom);
3841
}
3942
return this.ThumbImage;
@@ -45,6 +48,7 @@ public BitmapImage FullImage {
4548
this.PropertyChanged?.Invoke(this,
4649
new PropertyChangedEventArgs(nameof(FullImage)));
4750
}
51+
MemoryCache.Default.Remove(this.FileName);
4852
return;
4953
} else if (this.fullImageRef == null) {
5054
this.fullImageRef = new WeakReference<BitmapImage>(value);

PhotoTagger.Wpf/ImageZoomer.xaml.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using PhotoTagger.Imaging;
22
using System;
3+
using System.ComponentModel;
34
using System.Linq;
45
using System.Windows;
56
using System.Windows.Controls;
@@ -224,10 +225,22 @@ private static void zoomChangedCallback(
224225
DependencyObject d,
225226
DependencyPropertyChangedEventArgs e) {
226227
if (d is ImageZoomer zoom && e.OldValue != e.NewValue) {
228+
if (e.OldValue is Photo po) {
229+
po.PropertyChanged -= zoom.imageUpdated;
230+
}
231+
if (e.NewValue is Photo pn) {
232+
pn.PropertyChanged += zoom.imageUpdated;
233+
}
227234
zoom.computeTransform();
228235
}
229236
}
230237

238+
private void imageUpdated(object sender, PropertyChangedEventArgs e) {
239+
if (e.PropertyName == nameof(Photo.FullImage)) {
240+
this.computeTransform();
241+
}
242+
}
243+
231244
public double Scale {
232245
get {
233246
return (double)GetValue(ScaleProperty);
@@ -306,6 +319,11 @@ private void setTransform(double scale, double x, double y) {
306319
}
307320

308321
private void sizeChanged(object sender, SizeChangedEventArgs e) {
322+
if (e.NewSize.Width == 0 && e.PreviousSize.Width != 0 ||
323+
e.NewSize.Height == 0 && e.PreviousSize.Height != 0 ||
324+
e.NewSize.Equals(e.PreviousSize)) {
325+
return;
326+
}
309327
this.computeTransform();
310328
}
311329
}

0 commit comments

Comments
 (0)