В конечном итоге я потратил довольно много времени на изучение материала в этой большой теме. Я сомневаюсь, что каждый хочет провести так много времени, поэтому я бы выделил краткое изложение того, что я узнал, и решение, которое я реализовал.
Краткая сводка
numeric_limits::epsilon()
, который аналогичен FLT_EPSILON в float.h. Это, однако, проблематично, потому что epsilon для сравнения значений типа 1.0, если не такой же, как epsilon, для значений, подобных 1E9. FLT_EPSILON определен для 1.0. fabs(a-b) <= epsilon
, однако это не работает, потому что по умолчанию epsilon определен для 1.0. Нам нужно масштабировать epsilon вверх или вниз в терминах a и b. max(a,b)
, либо можете получить следующие отображаемые числа вокруг a, а затем см., если b попадает в этот диапазон. Первый метод называется «относительным», а позже называется методом ULP. Реализация служебных функций (C ++ 11)
//implements relative method - do not use for comparing with zero
//use this most of the time, tolerance needs to be meaningful in your context
template<typename TReal>
static bool isApproximatelyEqual(TReal a, TReal b, TReal tolerance = std::numeric_limits<TReal>::epsilon())
{
TReal diff = std::fabs(a - b);
if (diff <= tolerance)
return true;
if (diff < std::fmax(std::fabs(a), std::fabs(b)) * tolerance)
return true;
return false;
}
//supply tolerance that is meaningful in your context
//for example, default tolerance may not work if you are comparing double with float
template<typename TReal>
static bool isApproximatelyZero(TReal a, TReal tolerance = std::numeric_limits<TReal>::epsilon())
{
if (std::fabs(a) <= tolerance)
return true;
return false;
}
//use this when you want to be on safe side
//for example, don't start rover unless signal is above 1
template<typename TReal>
static bool isDefinitelyLessThan(TReal a, TReal b, TReal tolerance = std::numeric_limits<TReal>::epsilon())
{
TReal diff = a - b;
if (diff < tolerance)
return true;
if (diff < std::fmax(std::fabs(a), std::fabs(b)) * tolerance)
return true;
return false;
}
template<typename TReal>
static bool isDefinitelyGreaterThan(TReal a, TReal b, TReal tolerance = std::numeric_limits<TReal>::epsilon())
{
TReal diff = a - b;
if (diff > tolerance)
return true;
if (diff > std::fmax(std::fabs(a), std::fabs(b)) * tolerance)
return true;
return false;
}
//implements ULP method
//use this when you are only concerned about floating point precision issue
//for example, if you want to see if a is 1.0 by checking if its within
//10 closest representable floating point numbers around 1.0.
template<typename TReal>
static bool isWithinPrecisionInterval(TReal a, TReal b, unsigned int interval_size = 1)
{
TReal min_a = a - (a - std::nextafter(a, std::numeric_limits<TReal>::lowest())) * interval_size;
TReal max_a = a + (std::nextafter(a, std::numeric_limits<TReal>::max()) - a) * interval_size;
return min_a <= b && max_a >= b;
}
Спасибо за вашу помощь. Теперь у меня это работает. Я все еще не уверен, в чем проблема.
Вот как я помещал изображения в мою базу данных & hellip;
Private Sub ButtonUpload_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Dim FileOpenStream As Stream = Nothing
Dim FileBox As New Microsoft.Win32.OpenFileDialog()
FileBox.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
FileBox.Filter = "Pictures (*.jpg;*.jpeg;*.gif;*.png)|*.jpg;*.jpeg;*.gif;*.png|" & _
"All Files (*.*)|*.*"
FileBox.FilterIndex = 1
FileBox.Multiselect = False
Dim FileSelected As Nullable(Of Boolean) = FileBox.ShowDialog(Me)
If FileSelected IsNot Nothing AndAlso FileSelected.Value = True Then
Try
FileOpenStream = FileBox.OpenFile()
If (FileOpenStream IsNot Nothing) Then
Dim ByteArray As Byte()
Using br As New BinaryReader(FileOpenStream)
ByteArray = br.ReadBytes(FileOpenStream.Length)
End Using
Dim g As New ZackGraphic
g.Id = Guid.NewGuid
g.ImageData = ByteArray
g.FileSize = CInt(ByteArray.Length)
g.FileName = FileBox.FileName.Split("\").Last
g.FileExtension = "." + FileBox.FileName.Split(".").Last.ToLower
g.DateAdded = Now
Dim bmp As New BitmapImage
bmp.BeginInit()
bmp.StreamSource = New MemoryStream(ByteArray)
bmp.EndInit()
bmp.Freeze()
g.PixelWidth = bmp.PixelWidth
g.PixelHeight = bmp.PixelHeight
db.AddToZackGraphic(g)
db.SaveChanges()
End If
Catch Ex As Exception
MessageBox.Show("Cannot read file from disk. " & Ex.Message, "Add a New Image", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK)
Finally
If (FileOpenStream IsNot Nothing) Then
FileOpenStream.Close()
End If
End Try
End If
End Sub
Это мой преобразователь значений, используемый для привязки байтового массива к изображению & hellip;
Class BinaryImageConverter
Implements IValueConverter
Private Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.Convert
If value IsNot Nothing AndAlso TypeOf value Is Byte() Then
Dim ByteArray As Byte() = TryCast(value, Byte())
Dim bmp As New BitmapImage()
bmp.BeginInit()
bmp.StreamSource = New MemoryStream(ByteArray)
bmp.EndInit()
Return bmp
End If
Return Nothing
End Function
Private Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
Throw New Exception("The method or operation is not implemented.")
End Function
End Class
Это мой XAML, который использует конвертер, отображающий изображение & hellip;
<Window xmlns:local="clr-namespace:MyProjectName" ... >
<Window.Resources>
<local:BinaryImageConverter x:Key="imgConverter" />
</Window.Resources>
...
<Image Source="{Binding Path=ImageData, Converter={StaticResource imgConverter}}" />
Попробуйте использовать
Dim imageSource as ImageSource
Dim bitmapDecoder = new PngBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
imageSource = bitmapDecoder.Frames[0];
imageSource.Freeze();
Return imageSource
Я предполагаю, что байты не являются законным форматом изображения. Я считаю, что код ошибки соответствует WINCODEC_ERR_COMPONENTNOTFOUND
, что согласуется с недопустимыми байтами.
В каком формате должен находиться массив байтов? Можете ли вы сохранить его на диск и попытаться открыть его с помощью другой программы обработки изображений?
Я считаю, что на самом деле это проблема с разрешением безопасности. Попробуйте запустить с правами администратора, и посмотрите, работает ли это, и оттуда.
EDIT: Я не согласен с нижним рейтингом и комментариями. Взгляните на эту ссылку:
http://social.expression.microsoft.com/Forums/en-US/wpf/thread/617f6711-0373-44cc-b72c-aeae20f0f7a8/
У этого пользователя была такая же ошибка, и это было вызвано параметрами безопасности. Поэтому я поддерживаю свой ответ (что может и не быть причиной, но, безусловно, стоит попробовать)