[f-spot] removing libfspot code, using Pinta blur



commit a95d411890637041385e8be2593436f5c22920c8
Author: Tim Howard <timothy howard gmail com>
Date:   Tue Feb 15 00:27:14 2011 -0500

    removing libfspot code, using Pinta blur

 lib/TagLib/sources.mk                              |  240 +++++-----
 lib/libfspot/Makefile.am                           |    5 -
 lib/libfspot/f-image-surface.c                     |   63 ---
 lib/libfspot/f-image-surface.h                     |    4 -
 lib/libfspot/f-pixbuf-unsharp.c                    |  481 --------------------
 lib/libfspot/f-pixbuf-utils.c                      |  187 --------
 lib/libfspot/f-pixbuf-utils.h                      |   29 --
 src/Clients/MainApp/CairoExtensions.cs             |   85 ++++
 src/Clients/MainApp/ColorBgra.cs                   |   77 ++++
 .../MainApp/FSpot.Editors/SoftFocusEditor.cs       |    4 +-
 src/Clients/MainApp/FSpot.Editors/TiltEditor.cs    |    6 +-
 src/Clients/MainApp/FSpot.Filters/SharpFilter.cs   |    2 +-
 src/Clients/MainApp/FSpot.Widgets/ImageInfo.cs     |    2 +-
 src/Clients/MainApp/FSpot.Widgets/Sharpener.cs     |  112 +++--
 src/Clients/MainApp/FSpot.Widgets/SoftFocus.cs     |   17 +-
 src/Clients/MainApp/FSpot/PhotoView.cs             |    2 +-
 src/Clients/MainApp/MainApp.csproj                 |    3 +
 src/Clients/MainApp/Makefile.am                    |    2 +
 src/Clients/MainApp/PixbufUtils.cs                 |  352 ++++++++++++++-
 src/Core/FSpot.Utils/FSpot.Utils.csproj            |    1 -
 src/Core/FSpot.Utils/FSpot.Utils/MemorySurface.cs  |  100 ----
 src/Core/FSpot.Utils/Makefile.am                   |    1 -
 22 files changed, 709 insertions(+), 1066 deletions(-)
---
diff --git a/lib/TagLib/sources.mk b/lib/TagLib/sources.mk
index 353ecf2..f0bcb8c 100644
--- a/lib/TagLib/sources.mk
+++ b/lib/TagLib/sources.mk
@@ -1,132 +1,103 @@
 # This file is autogenerated, do not edit!
-SOURCES = \
+SOURCES =  \
 	TagLib/src/TagLib/Aac/AudioHeader.cs \
 	TagLib/src/TagLib/Aac/BitStream.cs \
 	TagLib/src/TagLib/Aac/File.cs \
 	TagLib/src/TagLib/Aiff/File.cs \
 	TagLib/src/TagLib/Aiff/StreamHeader.cs \
-	TagLib/src/TagLib/Ape/Tag.cs \
-	TagLib/src/TagLib/Ape/Item.cs \
-	TagLib/src/TagLib/Ape/Footer.cs \
 	TagLib/src/TagLib/Ape/File.cs \
+	TagLib/src/TagLib/Ape/Footer.cs \
+	TagLib/src/TagLib/Ape/Item.cs \
 	TagLib/src/TagLib/Ape/StreamHeader.cs \
-	TagLib/src/TagLib/Asf/Guid.cs \
-	TagLib/src/TagLib/Asf/StreamPropertiesObject.cs \
-	TagLib/src/TagLib/Asf/UnknownObject.cs \
-	TagLib/src/TagLib/Asf/Tag.cs \
-	TagLib/src/TagLib/Asf/Object.cs \
-	TagLib/src/TagLib/Asf/ExtendedContentDescriptionObject.cs \
+	TagLib/src/TagLib/Ape/Tag.cs \
 	TagLib/src/TagLib/Asf/ContentDescriptionObject.cs \
-	TagLib/src/TagLib/Asf/MetadataLibraryObject.cs \
-	TagLib/src/TagLib/Asf/HeaderObject.cs \
-	TagLib/src/TagLib/Asf/HeaderExtensionObject.cs \
+	TagLib/src/TagLib/Asf/ContentDescriptor.cs \
+	TagLib/src/TagLib/Asf/DescriptionRecord.cs \
+	TagLib/src/TagLib/Asf/ExtendedContentDescriptionObject.cs \
 	TagLib/src/TagLib/Asf/File.cs \
 	TagLib/src/TagLib/Asf/FilePropertiesObject.cs \
+	TagLib/src/TagLib/Asf/Guid.cs \
+	TagLib/src/TagLib/Asf/HeaderExtensionObject.cs \
+	TagLib/src/TagLib/Asf/HeaderObject.cs \
+	TagLib/src/TagLib/Asf/MetadataLibraryObject.cs \
+	TagLib/src/TagLib/Asf/Object.cs \
 	TagLib/src/TagLib/Asf/PaddingObject.cs \
-	TagLib/src/TagLib/Asf/ContentDescriptor.cs \
-	TagLib/src/TagLib/Asf/DescriptionRecord.cs \
-	TagLib/src/TagLib/Mpc/StreamHeader.cs \
-	TagLib/src/TagLib/Mpc/File.cs \
-	TagLib/src/TagLib/Ogg/GroupedComment.cs \
-	TagLib/src/TagLib/Ogg/Bitstream.cs \
-	TagLib/src/TagLib/Ogg/Paginator.cs \
-	TagLib/src/TagLib/Ogg/Codec.cs \
-	TagLib/src/TagLib/Ogg/Codecs/Vorbis.cs \
-	TagLib/src/TagLib/Ogg/Codecs/Theora.cs \
-	TagLib/src/TagLib/Ogg/Page.cs \
-	TagLib/src/TagLib/Ogg/XiphComment.cs \
-	TagLib/src/TagLib/Ogg/PageHeader.cs \
-	TagLib/src/TagLib/Ogg/File.cs \
-	TagLib/src/TagLib/Png/Codec.cs \
-	TagLib/src/TagLib/Png/File.cs \
-	TagLib/src/TagLib/Png/PngTag.cs \
+	TagLib/src/TagLib/Asf/StreamPropertiesObject.cs \
+	TagLib/src/TagLib/Asf/Tag.cs \
+	TagLib/src/TagLib/Asf/UnknownObject.cs \
+	TagLib/src/TagLib/ByteVector.cs \
+	TagLib/src/TagLib/ByteVectorList.cs \
+	TagLib/src/TagLib/CombinedTag.cs \
+	TagLib/src/TagLib/CorruptFileException.cs \
+	TagLib/src/TagLib/File.cs \
+	TagLib/src/TagLib/FileTypes.cs \
 	TagLib/src/TagLib/Flac/Block.cs \
 	TagLib/src/TagLib/Flac/BlockHeader.cs \
-	TagLib/src/TagLib/Flac/StreamHeader.cs \
-	TagLib/src/TagLib/Flac/Picture.cs \
 	TagLib/src/TagLib/Flac/File.cs \
+	TagLib/src/TagLib/Flac/Picture.cs \
+	TagLib/src/TagLib/Flac/StreamHeader.cs \
+	TagLib/src/TagLib/Genres.cs \
 	TagLib/src/TagLib/Gif/Codec.cs \
 	TagLib/src/TagLib/Gif/File.cs \
 	TagLib/src/TagLib/Gif/GifCommentTag.cs \
-	TagLib/src/TagLib/Image/Codec.cs \
-	TagLib/src/TagLib/Image/CombinedImageTag.cs \
-	TagLib/src/TagLib/Image/File.cs \
-	TagLib/src/TagLib/Image/ImageBlockFile.cs \
-	TagLib/src/TagLib/Image/ImageTag.cs \
-	TagLib/src/TagLib/Image/ImageOrientation.cs \
-	TagLib/src/TagLib/Image/NoMetadata/File.cs \
-	TagLib/src/TagLib/Jpeg/Codec.cs \
-	TagLib/src/TagLib/Jpeg/File.cs \
-	TagLib/src/TagLib/Jpeg/JpegCommentTag.cs \
-	TagLib/src/TagLib/Jpeg/Marker.cs \
-	TagLib/src/TagLib/Jpeg/Table.cs \
-	TagLib/src/TagLib/Mpeg/XingHeader.cs \
-	TagLib/src/TagLib/Mpeg/VBRIHeader.cs \
-	TagLib/src/TagLib/Mpeg/File.cs \
-	TagLib/src/TagLib/Mpeg/AudioFile.cs \
-	TagLib/src/TagLib/Mpeg/AudioHeader.cs \
-	TagLib/src/TagLib/Mpeg/VideoHeader.cs \
-	TagLib/src/TagLib/NonContainer/EndTag.cs \
-	TagLib/src/TagLib/NonContainer/File.cs \
-	TagLib/src/TagLib/NonContainer/StartTag.cs \
-	TagLib/src/TagLib/NonContainer/Tag.cs \
-	TagLib/src/TagLib/Id3v1/Tag.cs \
+	TagLib/src/TagLib/ICodec.cs \
 	TagLib/src/TagLib/Id3v1/StringHandler.cs \
-	TagLib/src/TagLib/Id3v2/Frames/PopularimeterFrame.cs \
+	TagLib/src/TagLib/Id3v1/Tag.cs \
+	TagLib/src/TagLib/Id3v2/ExtendedHeader.cs \
+	TagLib/src/TagLib/Id3v2/Footer.cs \
+	TagLib/src/TagLib/Id3v2/Frame.cs \
+	TagLib/src/TagLib/Id3v2/FrameFactory.cs \
+	TagLib/src/TagLib/Id3v2/FrameHeader.cs \
+	TagLib/src/TagLib/Id3v2/Frames/AttachedPictureFrame.cs \
+	TagLib/src/TagLib/Id3v2/Frames/CommentsFrame.cs \
+	TagLib/src/TagLib/Id3v2/Frames/GeneralEncapsulatedObjectFrame.cs \
+	TagLib/src/TagLib/Id3v2/Frames/MusicCdIdentifierFrame.cs \
 	TagLib/src/TagLib/Id3v2/Frames/PlayCountFrame.cs \
+	TagLib/src/TagLib/Id3v2/Frames/PopularimeterFrame.cs \
 	TagLib/src/TagLib/Id3v2/Frames/PrivateFrame.cs \
 	TagLib/src/TagLib/Id3v2/Frames/RelativeVolumeFrame.cs \
+	TagLib/src/TagLib/Id3v2/Frames/SynchronizedLyricsFrame.cs \
+	TagLib/src/TagLib/Id3v2/Frames/TermsOfUseFrame.cs \
+	TagLib/src/TagLib/Id3v2/Frames/TextIdentificationFrame.cs \
 	TagLib/src/TagLib/Id3v2/Frames/UniqueFileIdentifierFrame.cs \
 	TagLib/src/TagLib/Id3v2/Frames/UnknownFrame.cs \
-	TagLib/src/TagLib/Id3v2/Frames/CommentsFrame.cs \
-	TagLib/src/TagLib/Id3v2/Frames/TextIdentificationFrame.cs \
-	TagLib/src/TagLib/Id3v2/Frames/AttachedPictureFrame.cs \
-	TagLib/src/TagLib/Id3v2/Frames/GeneralEncapsulatedObjectFrame.cs \
 	TagLib/src/TagLib/Id3v2/Frames/UnsynchronisedLyricsFrame.cs \
-	TagLib/src/TagLib/Id3v2/Frames/SynchronizedLyricsFrame.cs \
-	TagLib/src/TagLib/Id3v2/Frames/MusicCdIdentifierFrame.cs \
-	TagLib/src/TagLib/Id3v2/Frames/TermsOfUseFrame.cs \
-	TagLib/src/TagLib/Id3v2/FrameFactory.cs \
-	TagLib/src/TagLib/Id3v2/Frame.cs \
 	TagLib/src/TagLib/Id3v2/FrameTypes.cs \
-	TagLib/src/TagLib/Id3v2/Tag.cs \
-	TagLib/src/TagLib/Id3v2/FrameHeader.cs \
-	TagLib/src/TagLib/Id3v2/ExtendedHeader.cs \
-	TagLib/src/TagLib/Id3v2/SynchData.cs \
 	TagLib/src/TagLib/Id3v2/Header.cs \
-	TagLib/src/TagLib/Id3v2/Footer.cs \
+	TagLib/src/TagLib/Id3v2/SynchData.cs \
+	TagLib/src/TagLib/Id3v2/Tag.cs \
 	TagLib/src/TagLib/IFD/Entries/ByteIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/ByteVectorIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/LongArrayIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/LongIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/MakernoteIFDEntry.cs \
+	TagLib/src/TagLib/IFD/Entries/Rational.cs \
 	TagLib/src/TagLib/IFD/Entries/RationalArrayIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/RationalIFDEntry.cs \
-	TagLib/src/TagLib/IFD/Entries/Rational.cs \
 	TagLib/src/TagLib/IFD/Entries/SByteIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/ShortArrayIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/ShortIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/SLongArrayIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/SLongIFDEntry.cs \
+	TagLib/src/TagLib/IFD/Entries/SRational.cs \
 	TagLib/src/TagLib/IFD/Entries/SRationalArrayIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/SRationalIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/SShortArrayIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/SShortIFDEntry.cs \
-	TagLib/src/TagLib/IFD/Entries/SRational.cs \
 	TagLib/src/TagLib/IFD/Entries/StringIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/StripOffsetsIFDEntry.cs \
-	TagLib/src/TagLib/IFD/Entries/SubIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/SubIFDArrayEntry.cs \
+	TagLib/src/TagLib/IFD/Entries/SubIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/ThumbnailDataIFDEntry.cs \
-	TagLib/src/TagLib/IFD/Entries/UserCommentIFDEntry.cs \
 	TagLib/src/TagLib/IFD/Entries/UndefinedIFDEntry.cs \
+	TagLib/src/TagLib/IFD/Entries/UserCommentIFDEntry.cs \
+	TagLib/src/TagLib/IFD/IFDDirectory.cs \
 	TagLib/src/TagLib/IFD/IFDEntry.cs \
 	TagLib/src/TagLib/IFD/IFDEntryType.cs \
-	TagLib/src/TagLib/IFD/IFDTag.cs \
-	TagLib/src/TagLib/IFD/IFDDirectory.cs \
-	TagLib/src/TagLib/IFD/IFDStructure.cs \
 	TagLib/src/TagLib/IFD/IFDReader.cs \
 	TagLib/src/TagLib/IFD/IFDRenderer.cs \
+	TagLib/src/TagLib/IFD/IFDStructure.cs \
+	TagLib/src/TagLib/IFD/IFDTag.cs \
 	TagLib/src/TagLib/IFD/Makernotes/Nikon3MakernoteReader.cs \
 	TagLib/src/TagLib/IFD/Tags/CanonFileInfoEntryTag.cs \
 	TagLib/src/TagLib/IFD/Tags/CanonMakerNoteEntryTag.cs \
@@ -135,47 +106,87 @@ SOURCES = \
 	TagLib/src/TagLib/IFD/Tags/GPSEntryTag.cs \
 	TagLib/src/TagLib/IFD/Tags/IFDEntryTag.cs \
 	TagLib/src/TagLib/IFD/Tags/IOPEntryTag.cs \
-	TagLib/src/TagLib/IFD/Tags/PentaxMakerNoteEntryTag.cs \
-	TagLib/src/TagLib/IFD/Tags/OlympusMakerNoteEntryTag.cs \
 	TagLib/src/TagLib/IFD/Tags/Nikon3MakerNoteEntryTag.cs \
-	TagLib/src/TagLib/IFD/Tags/NikonLensData3EntryTag.cs \
 	TagLib/src/TagLib/IFD/Tags/NikonIsoInfoEntryTag.cs \
-	TagLib/src/TagLib/IFD/Tags/NikonPreviewMakerNoteEntryTag.cs \
+	TagLib/src/TagLib/IFD/Tags/NikonLensData3EntryTag.cs \
 	TagLib/src/TagLib/IFD/Tags/NikonPictureControlEntryTag.cs \
+	TagLib/src/TagLib/IFD/Tags/NikonPreviewMakerNoteEntryTag.cs \
 	TagLib/src/TagLib/IFD/Tags/NikonShotInfoEntryTag.cs \
 	TagLib/src/TagLib/IFD/Tags/NikonVibrationReductionEntryTag.cs \
 	TagLib/src/TagLib/IFD/Tags/NikonWorldTimeEntryTag.cs \
+	TagLib/src/TagLib/IFD/Tags/OlympusMakerNoteEntryTag.cs \
 	TagLib/src/TagLib/IFD/Tags/PanasonicMakerNoteEntryTag.cs \
+	TagLib/src/TagLib/IFD/Tags/PentaxMakerNoteEntryTag.cs \
 	TagLib/src/TagLib/IFD/Tags/SonyMakerNoteEntryTag.cs \
+	TagLib/src/TagLib/Image/Codec.cs \
+	TagLib/src/TagLib/Image/CombinedImageTag.cs \
+	TagLib/src/TagLib/Image/File.cs \
+	TagLib/src/TagLib/Image/ImageBlockFile.cs \
+	TagLib/src/TagLib/Image/ImageOrientation.cs \
+	TagLib/src/TagLib/Image/ImageTag.cs \
+	TagLib/src/TagLib/Image/NoMetadata/File.cs \
+	TagLib/src/TagLib/Jpeg/Codec.cs \
+	TagLib/src/TagLib/Jpeg/File.cs \
+	TagLib/src/TagLib/Jpeg/JpegCommentTag.cs \
+	TagLib/src/TagLib/Jpeg/Marker.cs \
+	TagLib/src/TagLib/Jpeg/Table.cs \
+	TagLib/src/TagLib/ListBase.cs \
+	TagLib/src/TagLib/Mpc/File.cs \
+	TagLib/src/TagLib/Mpc/StreamHeader.cs \
+	TagLib/src/TagLib/Mpeg/AudioFile.cs \
+	TagLib/src/TagLib/Mpeg/AudioHeader.cs \
+	TagLib/src/TagLib/Mpeg/File.cs \
+	TagLib/src/TagLib/Mpeg/VBRIHeader.cs \
+	TagLib/src/TagLib/Mpeg/VideoHeader.cs \
+	TagLib/src/TagLib/Mpeg/XingHeader.cs \
 	TagLib/src/TagLib/Mpeg4/AppleTag.cs \
 	TagLib/src/TagLib/Mpeg4/Box.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/AppleAdditionalInfoBox.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/AppleAnnotationBox.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/AppleDataBox.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/AppleElementaryStreamDescriptor.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/AppleItemListBox.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/FullBox.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/IsoAudioSampleEntry.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/IsoChunkLargeOffsetBox.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/IsoChunkOffsetBox.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/IsoFreeSpaceBox.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/IsoHandlerBox.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/IsoMetaBox.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/IsoMovieHeaderBox.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/IsoSampleDescriptionBox.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/IsoSampleEntry.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/IsoSampleTableBox.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/IsoUserDataBox.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/IsoVisualSampleEntry.cs \
+	TagLib/src/TagLib/Mpeg4/Boxes/UnknownBox.cs \
 	TagLib/src/TagLib/Mpeg4/BoxFactory.cs \
 	TagLib/src/TagLib/Mpeg4/BoxHeader.cs \
 	TagLib/src/TagLib/Mpeg4/BoxTypes.cs \
 	TagLib/src/TagLib/Mpeg4/File.cs \
 	TagLib/src/TagLib/Mpeg4/FileParser.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/IsoFreeSpaceBox.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/UnknownBox.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/IsoUserDataBox.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/IsoChunkOffsetBox.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/IsoChunkLargeOffsetBox.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/AppleItemListBox.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/AppleAnnotationBox.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/IsoSampleTableBox.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/IsoSampleEntry.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/IsoAudioSampleEntry.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/IsoVisualSampleEntry.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/IsoMetaBox.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/IsoSampleDescriptionBox.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/AppleAdditionalInfoBox.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/IsoHandlerBox.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/IsoMovieHeaderBox.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/FullBox.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/AppleElementaryStreamDescriptor.cs \
-	TagLib/src/TagLib/Mpeg4/Boxes/AppleDataBox.cs \
+	TagLib/src/TagLib/NonContainer/EndTag.cs \
+	TagLib/src/TagLib/NonContainer/File.cs \
+	TagLib/src/TagLib/NonContainer/StartTag.cs \
+	TagLib/src/TagLib/NonContainer/Tag.cs \
+	TagLib/src/TagLib/Ogg/Bitstream.cs \
+	TagLib/src/TagLib/Ogg/Codec.cs \
+	TagLib/src/TagLib/Ogg/Codecs/Theora.cs \
+	TagLib/src/TagLib/Ogg/Codecs/Vorbis.cs \
+	TagLib/src/TagLib/Ogg/File.cs \
+	TagLib/src/TagLib/Ogg/GroupedComment.cs \
+	TagLib/src/TagLib/Ogg/Page.cs \
+	TagLib/src/TagLib/Ogg/PageHeader.cs \
+	TagLib/src/TagLib/Ogg/Paginator.cs \
+	TagLib/src/TagLib/Ogg/XiphComment.cs \
+	TagLib/src/TagLib/Picture.cs \
+	TagLib/src/TagLib/Png/Codec.cs \
+	TagLib/src/TagLib/Png/File.cs \
+	TagLib/src/TagLib/Png/PngTag.cs \
+	TagLib/src/TagLib/Properties.cs \
+	TagLib/src/TagLib/ReadOnlyByteVector.cs \
 	TagLib/src/TagLib/Riff/AviHeaderList.cs \
 	TagLib/src/TagLib/Riff/AviStream.cs \
-	TagLib/src/TagLib/Riff/WaveFormatEx.cs \
 	TagLib/src/TagLib/Riff/BitmapInfoHeader.cs \
 	TagLib/src/TagLib/Riff/DivXTag.cs \
 	TagLib/src/TagLib/Riff/File.cs \
@@ -183,38 +194,27 @@ SOURCES = \
 	TagLib/src/TagLib/Riff/List.cs \
 	TagLib/src/TagLib/Riff/ListTag.cs \
 	TagLib/src/TagLib/Riff/MovieIdTag.cs \
+	TagLib/src/TagLib/Riff/WaveFormatEx.cs \
+	TagLib/src/TagLib/StringList.cs \
+	TagLib/src/TagLib/SupportedMimeType.cs \
+	TagLib/src/TagLib/Tag.cs \
+	TagLib/src/TagLib/Tiff/Arw/File.cs \
 	TagLib/src/TagLib/Tiff/BaseTiffFile.cs \
 	TagLib/src/TagLib/Tiff/Codec.cs \
-	TagLib/src/TagLib/Tiff/File.cs \
-	TagLib/src/TagLib/Tiff/Arw/File.cs \
 	TagLib/src/TagLib/Tiff/Cr2/File.cs \
 	TagLib/src/TagLib/Tiff/Dng/File.cs \
+	TagLib/src/TagLib/Tiff/File.cs \
 	TagLib/src/TagLib/Tiff/Nef/File.cs \
 	TagLib/src/TagLib/Tiff/Pef/File.cs \
 	TagLib/src/TagLib/Tiff/Rw2/File.cs \
 	TagLib/src/TagLib/Tiff/Rw2/IFDReader.cs \
 	TagLib/src/TagLib/Tiff/Rw2/IFDTag.cs \
+	TagLib/src/TagLib/UnsupportedFormatException.cs \
 	TagLib/src/TagLib/WavPack/File.cs \
 	TagLib/src/TagLib/WavPack/StreamHeader.cs \
 	TagLib/src/TagLib/Xmp/XmlNodeExtensions.cs \
-	TagLib/src/TagLib/Xmp/XmpTag.cs \
 	TagLib/src/TagLib/Xmp/XmpNode.cs \
 	TagLib/src/TagLib/Xmp/XmpNodeType.cs \
 	TagLib/src/TagLib/Xmp/XmpNodeVisitor.cs \
-	TagLib/src/TagLib/ICodec.cs \
-	TagLib/src/TagLib/Tag.cs \
-	TagLib/src/TagLib/ReadOnlyByteVector.cs \
-	TagLib/src/TagLib/ByteVector.cs \
-	TagLib/src/TagLib/ByteVectorList.cs \
-	TagLib/src/TagLib/CombinedTag.cs \
-	TagLib/src/TagLib/Genres.cs \
-	TagLib/src/TagLib/Properties.cs \
-	TagLib/src/TagLib/File.cs \
-	TagLib/src/TagLib/StringList.cs \
-	TagLib/src/TagLib/SupportedMimeType.cs \
-	TagLib/src/TagLib/UnsupportedFormatException.cs \
-	TagLib/src/TagLib/Picture.cs \
-	TagLib/src/TagLib/ListBase.cs \
-	TagLib/src/TagLib/FileTypes.cs \
-	TagLib/src/TagLib/CorruptFileException.cs
+	TagLib/src/TagLib/Xmp/XmpTag.cs
 
diff --git a/lib/libfspot/Makefile.am b/lib/libfspot/Makefile.am
index a002d13..767f7ce 100644
--- a/lib/libfspot/Makefile.am
+++ b/lib/libfspot/Makefile.am
@@ -15,11 +15,6 @@ fspotlibdir = $(libdir)/f-spot
 fspotlib_LTLIBRARIES = libfspot.la
 
 libfspot_la_SOURCES =				\
-	f-image-surface.c			\
-	f-image-surface.h			\
-	f-pixbuf-unsharp.c			\
-	f-pixbuf-utils.c			\
-	f-pixbuf-utils.h			\
 	f-screen-utils.c
 
 libfspot_la_LIBADD = 					\
diff --git a/src/Clients/MainApp/CairoExtensions.cs b/src/Clients/MainApp/CairoExtensions.cs
new file mode 100644
index 0000000..56d5a07
--- /dev/null
+++ b/src/Clients/MainApp/CairoExtensions.cs
@@ -0,0 +1,85 @@
+// 
+// CairoExtensions.cs
+//  
+// Author:
+//       Jonathan Pobst <monkey jpobst com>
+// 
+// Copyright (c) 2010 Jonathan Pobst
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+// Some functions are from Paint.NET:
+
+/////////////////////////////////////////////////////////////////////////////////
+// Paint.NET                                                                   //
+// Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors.     //
+// Portions Copyright (C) Microsoft Corporation. All Rights Reserved.          //
+// See license-pdn.txt for full licensing and attribution details.             //
+/////////////////////////////////////////////////////////////////////////////////
+
+using System;
+using Cairo;
+using System.Collections.Generic;
+
+namespace FSpot
+{
+	public static class CairoExtensions
+	{
+		public unsafe static Gdk.Pixbuf ToPixbuf (this Cairo.ImageSurface surfSource)
+		{
+			Cairo.ImageSurface surf = surfSource.Clone ();
+			surf.Flush ();
+
+			ColorBgra* dstPtr = (ColorBgra*)surf.DataPtr;
+			int len = surf.Data.Length / 4;
+
+			for (int i = 0; i < len; i++) {
+				if (dstPtr->A != 0)
+					*dstPtr = (ColorBgra.FromBgra (dstPtr->R, dstPtr->G, dstPtr->B, dstPtr->A));
+				dstPtr++;
+			}
+
+			Gdk.Pixbuf pb = new Gdk.Pixbuf (surf.Data, true, 8, surf.Width, surf.Height, surf.Stride);
+			(surf as IDisposable).Dispose ();
+			return pb;
+		}
+
+		public static unsafe ColorBgra* GetPointAddressUnchecked (this ImageSurface surf, int x, int y)
+		{
+			ColorBgra* dstPtr = (ColorBgra*)surf.DataPtr;
+
+			dstPtr += (x) + (y * surf.Width);
+
+			return dstPtr;
+		}
+
+		// This isn't really an extension method, since it doesn't use
+		// the passed in argument, but it's nice to have the same calling
+		// convention as the uncached version.  If you can use this one
+		// over the other, it is much faster in tight loops (like effects).
+		public static unsafe ColorBgra GetPointUnchecked (this ImageSurface surf, ColorBgra* surfDataPtr, int surfWidth, int x, int y)
+		{
+			ColorBgra* dstPtr = surfDataPtr;
+
+			dstPtr += (x) + (y * surfWidth);
+
+			return *dstPtr;
+		}
+	}
+}
diff --git a/src/Clients/MainApp/ColorBgra.cs b/src/Clients/MainApp/ColorBgra.cs
new file mode 100644
index 0000000..3e2f828
--- /dev/null
+++ b/src/Clients/MainApp/ColorBgra.cs
@@ -0,0 +1,77 @@
+/////////////////////////////////////////////////////////////////////////////////
+// Paint.NET                                                                   //
+// Copyright (C) Rick Brewster, Tom Jackson, and past contributors.            //
+// Portions Copyright (C) Microsoft Corporation. All Rights Reserved.          //
+// See license-pdn.txt for full licensing and attribution details.             //
+/////////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+namespace FSpot
+{
+    /// <summary>
+    /// This is our pixel format that we will work with. It is always 32-bits / 4-bytes and is
+    /// always laid out in BGRA order.
+    /// Generally used with the Surface class.
+    /// </summary>
+    [Serializable]
+    [StructLayout(LayoutKind.Explicit)]
+    public struct ColorBgra
+    {
+        [FieldOffset(0)] 
+        public byte B;
+
+        [FieldOffset(1)] 
+        public byte G;
+
+        [FieldOffset(2)] 
+        public byte R;
+
+        [FieldOffset(3)] 
+        public byte A;
+
+        /// <summary>
+        /// Lets you change B, G, R, and A at the same time.
+        /// </summary>
+        [NonSerialized]
+        [FieldOffset(0)] 
+        public uint Bgra;
+
+        public const int BlueChannel = 0;
+        public const int GreenChannel = 1;
+        public const int RedChannel = 2;
+        public const int AlphaChannel = 3;
+
+        public const int SizeOf = 4;
+
+        /// <summary>
+        /// Creates a new ColorBgra instance with the given color and alpha values.
+        /// </summary>
+        public static ColorBgra FromBgra(byte b, byte g, byte r, byte a)
+        {
+            ColorBgra color = new ColorBgra();
+            color.Bgra = BgraToUInt32(b, g, r, a);
+            return color;
+        }
+
+        /// <summary>
+        /// Packs color and alpha values into a 32-bit integer.
+        /// </summary>
+        public static UInt32 BgraToUInt32(byte b, byte g, byte r, byte a)
+        {
+            return (uint)b + ((uint)g << 8) + ((uint)r << 16) + ((uint)a << 24);
+        }
+
+        /// <summary>
+        /// Packs color and alpha values into a 32-bit integer.
+        /// </summary>
+        public static UInt32 BgraToUInt32(int b, int g, int r, int a)
+        {
+            return (uint)b + ((uint)g << 8) + ((uint)r << 16) + ((uint)a << 24);
+        }
+    }
+}
diff --git a/src/Clients/MainApp/FSpot.Editors/SoftFocusEditor.cs b/src/Clients/MainApp/FSpot.Editors/SoftFocusEditor.cs
index f510d27..e7b1065 100644
--- a/src/Clients/MainApp/FSpot.Editors/SoftFocusEditor.cs
+++ b/src/Clients/MainApp/FSpot.Editors/SoftFocusEditor.cs
@@ -79,7 +79,7 @@ namespace FSpot.Editors
 				using (Widgets.SoftFocus soft = new Widgets.SoftFocus (info)) {
 					soft.Radius = radius;
 
-					using (MemorySurface surface = new MemorySurface (Format.Argb32,
+					using (ImageSurface surface = new ImageSurface (Format.Argb32,
 										   input.Width,
 										   input.Height)) {
 
@@ -87,7 +87,7 @@ namespace FSpot.Editors
 							soft.Apply (ctx, info.Bounds);
 						}
 
-						result = MemorySurface.CreatePixbuf (surface);
+                        result = surface.ToPixbuf();
 						surface.Flush ();
 					}
 				}
diff --git a/src/Clients/MainApp/FSpot.Editors/TiltEditor.cs b/src/Clients/MainApp/FSpot.Editors/TiltEditor.cs
index 3adf8c2..5eee128 100644
--- a/src/Clients/MainApp/FSpot.Editors/TiltEditor.cs
+++ b/src/Clients/MainApp/FSpot.Editors/TiltEditor.cs
@@ -73,7 +73,7 @@ namespace FSpot.Editors
 		private Pixbuf ProcessImpl (Pixbuf input, Cms.Profile input_profile, bool fast) {
 			Pixbuf result;
 			using (ImageInfo info = new ImageInfo (input)) {
-				using (MemorySurface surface = new MemorySurface (Format.Argb32,
+				using (ImageSurface surface = new ImageSurface (Format.Argb32,
 									   input.Width,
 									   input.Height)) {
 					using (Context ctx = new Context (surface)) {
@@ -84,8 +84,8 @@ namespace FSpot.Editors
 							ctx.Source = p;
 							ctx.Paint ();
 						}
-						result = MemorySurface.CreatePixbuf (surface);
-						surface.Flush ();
+						result = surface.ToPixbuf();
+                        surface.Flush ();
 					}
 				}
 			}
diff --git a/src/Clients/MainApp/FSpot.Filters/SharpFilter.cs b/src/Clients/MainApp/FSpot.Filters/SharpFilter.cs
index 079e0fd..a4e3b6a 100644
--- a/src/Clients/MainApp/FSpot.Filters/SharpFilter.cs
+++ b/src/Clients/MainApp/FSpot.Filters/SharpFilter.cs
@@ -56,7 +56,7 @@ namespace FSpot.Filters {
 
             using (var img = ImageFile.Create (req.Current)) {
                 using (Pixbuf in_pixbuf = img.Load ()) {
-                    using (Pixbuf out_pixbuf = PixbufUtils.UnsharpMask (in_pixbuf, radius, amount, threshold)) {
+                    using (Pixbuf out_pixbuf = PixbufUtils.UnsharpMask (in_pixbuf, radius, amount, threshold, null)) {
                         PixbufUtils.CreateDerivedVersion (req.Current, dest_uri, 95, out_pixbuf);
                     }
                 }
diff --git a/src/Clients/MainApp/FSpot.Widgets/ImageInfo.cs b/src/Clients/MainApp/FSpot.Widgets/ImageInfo.cs
index 0de8208..55dbacd 100644
--- a/src/Clients/MainApp/FSpot.Widgets/ImageInfo.cs
+++ b/src/Clients/MainApp/FSpot.Widgets/ImageInfo.cs
@@ -94,7 +94,7 @@ namespace FSpot.Widgets {
 
 		private void SetPixbuf (Pixbuf pixbuf)
 		{
-			Surface = MemorySurface.CreateSurface (pixbuf);
+			Surface = Hyena.Gui.PixbufImageSurface.Create(pixbuf);
 			Bounds.Width = pixbuf.Width;
 			Bounds.Height = pixbuf.Height;
 		}
diff --git a/src/Clients/MainApp/FSpot.Widgets/Sharpener.cs b/src/Clients/MainApp/FSpot.Widgets/Sharpener.cs
index c903e08..6319d48 100644
--- a/src/Clients/MainApp/FSpot.Widgets/Sharpener.cs
+++ b/src/Clients/MainApp/FSpot.Widgets/Sharpener.cs
@@ -46,6 +46,9 @@ namespace FSpot.Widgets {
 		Gtk.SpinButton radius_spin = new Gtk.SpinButton (5.0, 50.0, .01);
 		Gtk.SpinButton threshold_spin = new Gtk.SpinButton (0.0, 50.0, .01);
 		Gtk.Dialog dialog;
+        ThreadProgressDialog progressDialog;
+
+        private bool okClicked;
 
 		public Sharpener (PhotoImageView view) : base (view)
 		{
@@ -53,17 +56,21 @@ namespace FSpot.Widgets {
 
 		protected override void UpdateSample ()
 		{
-			base.UpdateSample ();
-
-			if (overlay != null)
-				overlay.Dispose ();
-
-			overlay = null;
-			if (source != null)
-				overlay = PixbufUtils.UnsharpMask (source,
-								   radius_spin.Value,
-								   amount_spin.Value,
-								   threshold_spin.Value);
+            if (!okClicked)
+            {
+    			base.UpdateSample ();
+    
+    			if (overlay != null)
+    				overlay.Dispose ();
+    
+    			overlay = null;
+    			if (source != null)
+    				overlay = PixbufUtils.UnsharpMask (source,
+    								   radius_spin.Value,
+    								   amount_spin.Value,
+    								   threshold_spin.Value,
+                                       null);
+            }
 		}
 
 		private void HandleSettingsChanged (object sender, EventArgs args)
@@ -71,40 +78,61 @@ namespace FSpot.Widgets {
 			UpdateSample ();
 		}
 
+        public void doSharpening()
+        {
+            progressDialog.Fraction = 0.0;
+            progressDialog.Message = "Photo is being sharpened";
+
+            okClicked = true;
+            Photo photo = view.Item.Current as Photo;
+
+            if (photo == null)
+                return;
+
+            try {
+                Gdk.Pixbuf orig = view.Pixbuf;
+                Gdk.Pixbuf final = PixbufUtils.UnsharpMask (orig,
+                                        radius_spin.Value,
+                                        amount_spin.Value,
+                                        threshold_spin.Value,
+                                        progressDialog);
+
+                bool create_version = photo.DefaultVersion.IsProtected;
+
+                photo.SaveVersion (final, create_version);
+                photo.Changes.DataChanged = true;
+                App.Instance.Database.Photos.Commit (photo);
+            } catch (System.Exception e) {
+                string msg = Catalog.GetString ("Error saving sharpened photo");
+                string desc = String.Format (Catalog.GetString ("Received exception \"{0}\". Unable to save photo {1}"),
+                                 e.Message, photo.Name);
+
+                HigMessageDialog md = new HigMessageDialog (this, DialogFlags.DestroyWithParent,
+                                        Gtk.MessageType.Error,
+                                        ButtonsType.Ok,
+                                        msg,
+                                        desc);
+                md.Run ();
+                md.Destroy ();
+            }
+
+            progressDialog.Fraction = 1.0;
+            progressDialog.Message = "Sharpening complete!";
+            progressDialog.ButtonLabel = Gtk.Stock.Ok;
+
+            Destroy ();
+        }
+
 		private void HandleOkClicked (object sender, EventArgs args)
 		{
-			Photo photo = view.Item.Current as Photo;
-
-			if (photo == null)
-				return;
-
-			try {
-				Gdk.Pixbuf orig = view.Pixbuf;
-				Gdk.Pixbuf final = PixbufUtils.UnsharpMask (orig,
-									    radius_spin.Value,
-									    amount_spin.Value,
-									    threshold_spin.Value);
-
-				bool create_version = photo.DefaultVersion.IsProtected;
-
-				photo.SaveVersion (final, create_version);
-				photo.Changes.DataChanged = true;
-				App.Instance.Database.Photos.Commit (photo);
-			} catch (System.Exception e) {
-				string msg = Catalog.GetString ("Error saving sharpened photo");
-				string desc = String.Format (Catalog.GetString ("Received exception \"{0}\". Unable to save photo {1}"),
-							     e.Message, photo.Name);
-
-				HigMessageDialog md = new HigMessageDialog (this, DialogFlags.DestroyWithParent,
-									    Gtk.MessageType.Error,
-									    ButtonsType.Ok,
-									    msg,
-									    desc);
-				md.Run ();
-				md.Destroy ();
-			}
+            this.Hide();
+            dialog.Hide();
 
-			Destroy ();
+            System.Threading.Thread command_thread = new System.Threading.Thread (new System.Threading.ThreadStart (doSharpening));
+            command_thread.Name = "Sharpening";
+
+            progressDialog = new ThreadProgressDialog (command_thread, 1);
+            progressDialog.Start ();
 		}
 
 		public void HandleCancelClicked (object sender, EventArgs args)
diff --git a/src/Clients/MainApp/FSpot.Widgets/SoftFocus.cs b/src/Clients/MainApp/FSpot.Widgets/SoftFocus.cs
index 0a90aa7..a2bb5de 100644
--- a/src/Clients/MainApp/FSpot.Widgets/SoftFocus.cs
+++ b/src/Clients/MainApp/FSpot.Widgets/SoftFocus.cs
@@ -94,26 +94,25 @@ namespace FSpot.Widgets {
 								(int) Math.Ceiling (source.Bounds.Width * scale),
 								(int) Math.Ceiling (source.Bounds.Height * scale));
 
-			MemorySurface image = new MemorySurface (Format.Argb32,
+			ImageSurface image = new ImageSurface (Format.Argb32,
 								 small.Width,
 								 small.Height);
 
 			Context ctx = new Context (image);
-			//Pattern solid = new SolidPattern (0, 0, 0, 0);
-			//ctx.Source = solid;
-			//ctx.Paint ();
-			//solid.Destroy ();
+
 			ctx.Matrix = source.Fit (small);
 			ctx.Operator = Operator.Source;
 			Pattern p = new SurfacePattern (source.Surface);
 			ctx.Source = p;
-			//Log.Debug (small);
+
 			ctx.Paint ();
 			p.Destroy ();
 			((IDisposable)ctx).Dispose ();
-			Gdk.Pixbuf normal = MemorySurface.CreatePixbuf (image);
-			Gdk.Pixbuf blur = PixbufUtils.Blur (normal, 3);
-			ImageInfo overlay = new ImageInfo (blur);
+			Gdk.Pixbuf normal = image.ToPixbuf();
+
+            Gdk.Pixbuf blur = PixbufUtils.Blur (normal, 3, null);
+
+            ImageInfo overlay = new ImageInfo (blur);
 			blur.Dispose ();
 			normal.Dispose ();
 			image.Destroy ();
diff --git a/src/Clients/MainApp/FSpot/PhotoView.cs b/src/Clients/MainApp/FSpot/PhotoView.cs
index 28c2f75..389a127 100644
--- a/src/Clients/MainApp/FSpot/PhotoView.cs
+++ b/src/Clients/MainApp/FSpot/PhotoView.cs
@@ -167,7 +167,7 @@ namespace FSpot {
 		private void HandleButtonPressEvent (object sender, ButtonPressEventArgs args)
 		{
 			if (args.Event.Type == EventType.TwoButtonPress && args.Event.Button == 1 && DoubleClicked != null)
-				DoubleClicked (this, null);
+				    DoubleClicked (this, null);
 			if (args.Event.Type == EventType.ButtonPress
 			    && args.Event.Button == 3) {
 				PhotoPopup popup = new PhotoPopup ();
diff --git a/src/Clients/MainApp/MainApp.csproj b/src/Clients/MainApp/MainApp.csproj
index c16e64a..4bc35e0 100644
--- a/src/Clients/MainApp/MainApp.csproj
+++ b/src/Clients/MainApp/MainApp.csproj
@@ -205,6 +205,8 @@
     <Compile Include="FSpot.Widgets\SelectionCollectionGridView.cs" />
     <Compile Include="FSpot.Widgets\CollectionCellGridView.cs" />
     <Compile Include="FSpot.Widgets\BrowseablePointerGridView.cs" />
+    <Compile Include="ColorBgra.cs" />
+    <Compile Include="CairoExtensions.cs" />
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="..\..\..\COPYING">
@@ -332,6 +334,7 @@
     <Reference Include="nunit.framework, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77">
       <Package>mono-nunit</Package>
     </Reference>
+    <Reference Include="Mono.Simd" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\Core\FSpot.Core\FSpot.Core.csproj">
diff --git a/src/Clients/MainApp/Makefile.am b/src/Clients/MainApp/Makefile.am
index 4962f67..7eb037c 100644
--- a/src/Clients/MainApp/Makefile.am
+++ b/src/Clients/MainApp/Makefile.am
@@ -4,6 +4,8 @@ LINK = $(REF_FSPOT)
 ASSEMBLY_BUILD_FLAGS = -unsafe
 
 SOURCES =  \
+	CairoExtensions.cs \
+	ColorBgra.cs \
 	DependentListStore.cs \
 	FSpot.ColorAdjustment/Adjustment.cs \
 	FSpot.ColorAdjustment/AutoStretch.cs \
diff --git a/src/Clients/MainApp/PixbufUtils.cs b/src/Clients/MainApp/PixbufUtils.cs
index 70190c9..eab77e9 100644
--- a/src/Clients/MainApp/PixbufUtils.cs
+++ b/src/Clients/MainApp/PixbufUtils.cs
@@ -42,6 +42,8 @@ using FSpot.Utils;
 using FSpot.Imaging;
 using Hyena;
 using TagLib.Image;
+using Cairo;
+using FSpot.UI.Dialog;
 
 public static class PixbufUtils {
 	static Pixbuf error_pixbuf = null;
@@ -256,33 +258,351 @@ public static class PixbufUtils {
 		return flattened;
 	}
 
-	[DllImport ("libfspot")]
-	static extern IntPtr f_pixbuf_unsharp_mask (IntPtr src, double radius, double amount, double threshold);
+    unsafe public static byte[] Pixbuf_GetRow(byte* pixels, int row, int rowstride, int width, int channels, byte[] dest)
+    {
+        byte* ptr = ((byte*)pixels) + (row*rowstride);
 
-	public static Pixbuf UnsharpMask (Pixbuf src, double radius, double amount, double threshold)
-	{
-		IntPtr raw_ret = f_pixbuf_unsharp_mask (src.Handle, radius, amount, threshold);
-		Gdk.Pixbuf ret = (Gdk.Pixbuf) GLib.Object.GetObject(raw_ret, true);
-		return ret;
-	}
+        Marshal.Copy(((IntPtr)ptr), dest, 0, width*channels);
+
+        return dest;
+    }
+
+    unsafe public static void Pixbuf_SetRow(byte* pixels, byte[] dest, int row, int rowstride, int width, int channels)
+    {
+        byte* destPtr = pixels + row * rowstride;
+
+        for (int i=0; i < width*channels; i++)
+        {
+            destPtr[i] = dest[i];
+        }
+    }
+
+    unsafe public static Pixbuf UnsharpMask (Pixbuf src,
+                                             double radius,
+                                             double amount,
+                                             double threshold,
+                                             ThreadProgressDialog progressDialog)
+    {
+        // Make sure the pixbuf has an alpha channel before we try to blur it
+        src = src.AddAlpha(false, 0, 0, 0);
+
+        Pixbuf result = Blur(src, (int)radius, progressDialog);
+
+        int sourceRowstride = src.Rowstride;
+        int sourceHeight = src.Height;
+        int sourceChannels = src.NChannels;
+        int sourceWidth = src.Width;
+
+        int resultRowstride = result.Rowstride;
+        int resultHeight = result.Height;
+        int resultWidth = result.Width;
+        int resultChannels = result.NChannels;
+
+        byte[] srcRow = new byte[sourceRowstride];
+        byte[] destRow = new byte[resultRowstride];
+
+        byte* sourcePixels = (byte*)src.Pixels;
+        byte* resultPixels = (byte*)result.Pixels;
+
+        for (int row=0; row < sourceHeight; row++)
+        {
+            Pixbuf_GetRow(sourcePixels, row, sourceRowstride, sourceWidth, sourceChannels, srcRow);
+            Pixbuf_GetRow(resultPixels, row, resultRowstride, resultWidth, resultChannels, destRow);
+
+            int diff;
+            for (int i=0; i < sourceWidth*sourceChannels; i++)
+            {
+                diff = srcRow[i] - destRow[i];
+                if (Math.Abs(2*diff) < threshold)
+                    diff = 0;
+
+                int val = (int)(srcRow[i] + amount * diff);
+
+                if (val > 255)
+                    val = 255;
+                else if (val < 0)
+                    val = 0;
+
+                destRow[i] = (byte)val;
+            }
+
+            Pixbuf_SetRow(resultPixels, destRow, row, resultRowstride, resultWidth, resultChannels);
+
+            // This is the other half of the progress so start and halfway
+            if (progressDialog != null)
+            {
+                progressDialog.Fraction = ((double)row / ((double) sourceHeight - 1) ) * 0.25 + 0.75;
+            }
+        }
 
-	[DllImport ("libfspot")]
-	static extern IntPtr f_pixbuf_blur (IntPtr src, double radius);
+        return result;
+   }
 
-	public static Pixbuf Blur (Pixbuf src, double radius)
+    public static Pixbuf Blur (Pixbuf src, int radius, ThreadProgressDialog dialog)
 	{
-		IntPtr raw_ret = f_pixbuf_blur (src.Handle, radius);
-		Gdk.Pixbuf ret = (Gdk.Pixbuf) GLib.Object.GetObject(raw_ret, true);
-		return ret;
+        ImageSurface sourceSurface = Hyena.Gui.PixbufImageSurface.Create(src);
+        ImageSurface destinationSurface = new ImageSurface(Format.Rgb24, src.Width, src.Height);
+
+        // If we do it as a bunch of single lines (rectangles of one pixel) then we can give the progress
+        // here instead of going deeper to provide the feedback
+        for (int i=0; i < src.Height; i++)
+        {
+            RenderBlurEffect(sourceSurface, destinationSurface, new[] { new Gdk.Rectangle(0, i, src.Width, 1) }, radius);
+
+            if (dialog != null)
+            {
+                // This only half of the entire process
+                double fraction = ((double)i / (double)(src.Height-1)) *0.75;
+                dialog.Fraction = fraction;
+            }
+        }
+
+        return destinationSurface.ToPixbuf();
 	}
 
+    unsafe public static Gdk.Pixbuf ToPixbuf (this Cairo.ImageSurface surfSource)
+    {
+        Cairo.ImageSurface surf = surfSource.Clone ();
+        surf.Flush ();
+        
+        ColorBgra* dstPtr = (ColorBgra*)surf.DataPtr;
+        int len = surf.Data.Length / 4;
+        
+        for (int i = 0; i < len; i++) {
+            if (dstPtr->A != 0)
+                *dstPtr = (ColorBgra.FromBgra (dstPtr->R, dstPtr->G, dstPtr->B, dstPtr->A));
+            dstPtr++;
+        }
+        
+        Gdk.Pixbuf pb = new Gdk.Pixbuf (surf.Data, true, 8, surf.Width, surf.Height, surf.Stride);
+        (surf as IDisposable).Dispose ();
+        return pb;
+    }
+
+    public static ImageSurface Clone (this ImageSurface surf)
+    {
+        ImageSurface newsurf = new ImageSurface (surf.Format, surf.Width, surf.Height);
+
+        using (Context g = new Context (newsurf)) {
+            g.SetSource (surf);
+            g.Paint ();
+        }
+        
+        return newsurf;
+    }
+
+    public static int[] CreateGaussianBlurRow (int amount)
+    {
+        int size = 1 + (amount * 2);
+        int[] weights = new int[size];
+
+        for (int i = 0; i <= amount; ++i) {
+            // 1 + aa - aa + 2ai - ii
+            weights[i] = 16 * (i + 1);
+            weights[weights.Length - i - 1] = weights[i];
+        }
+
+        return weights;
+    }
+
+    unsafe public static void RenderBlurEffect (ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois, int radius)
+    {
+        int r = radius;
+        int[] w = CreateGaussianBlurRow (r);
+        int wlen = w.Length;
+
+        int localStoreSize = wlen * 6 * sizeof (long);
+        byte* localStore = stackalloc byte[localStoreSize];
+        byte* p = localStore;
+
+        long* waSums = (long*)p;
+        p += wlen * sizeof (long);
+
+        long* wcSums = (long*)p;
+        p += wlen * sizeof (long);
+
+        long* aSums = (long*)p;
+        p += wlen * sizeof (long);
+
+        long* bSums = (long*)p;
+        p += wlen * sizeof (long);
+
+        long* gSums = (long*)p;
+        p += wlen * sizeof (long);
+
+        long* rSums = (long*)p;
+        p += wlen * sizeof (long);
+
+        ulong arraysLength = (ulong)(sizeof (long) * wlen);
+
+        // Cache these for a massive performance boost
+        int src_width = src.Width;
+        int src_height = src.Height;
+        ColorBgra* src_data_ptr = (ColorBgra*)src.DataPtr;
+
+        foreach (Gdk.Rectangle rect in rois) {
+            if (rect.Height >= 1 && rect.Width >= 1) {
+                for (int y = rect.Top; y < rect.Bottom; ++y) {
+                    //Memory.SetToZero (localStore, (ulong)localStoreSize);
+
+                    long waSum = 0;
+                    long wcSum = 0;
+                    long aSum = 0;
+                    long bSum = 0;
+                    long gSum = 0;
+                    long rSum = 0;
+
+                    ColorBgra* dstPtr = dest.GetPointAddressUnchecked (rect.Left, y);
+
+                    for (int wx = 0; wx < wlen; ++wx) {
+                        int srcX = rect.Left + wx - r;
+                        waSums[wx] = 0;
+                        wcSums[wx] = 0;
+                        aSums[wx] = 0;
+                        bSums[wx] = 0;
+                        gSums[wx] = 0;
+                        rSums[wx] = 0;
+
+                        if (srcX >= 0 && srcX < src_width) {
+                            for (int wy = 0; wy < wlen; ++wy) {
+                                int srcY = y + wy - r;
+
+                                if (srcY >= 0 && srcY < src_height) {
+                                    ColorBgra c = src.GetPointUnchecked (src_data_ptr, src_width, srcX, srcY);
+                                    int wp = w[wy];
+
+                                    waSums[wx] += wp;
+                                    wp *= c.A + (c.A >> 7);
+                                    wcSums[wx] += wp;
+                                    wp >>= 8;
+
+                                    aSums[wx] += wp * c.A;
+                                    bSums[wx] += wp * c.B;
+                                    gSums[wx] += wp * c.G;
+                                    rSums[wx] += wp * c.R;
+                                }
+                            }
+
+                            int wwx = w[wx];
+                            waSum += wwx * waSums[wx];
+                            wcSum += wwx * wcSums[wx];
+                            aSum += wwx * aSums[wx];
+                            bSum += wwx * bSums[wx];
+                            gSum += wwx * gSums[wx];
+                            rSum += wwx * rSums[wx];
+                        }
+                    }
+
+                    wcSum >>= 8;
+
+                    if (waSum == 0 || wcSum == 0) {
+                        dstPtr->Bgra = 0;
+                    } else {
+                        int alpha = (int)(aSum / waSum);
+                        int blue = (int)(bSum / wcSum);
+                        int green = (int)(gSum / wcSum);
+                        int red = (int)(rSum / wcSum);
+
+                        dstPtr->Bgra = ColorBgra.BgraToUInt32 (blue, green, red, alpha);
+                    }
+
+                    ++dstPtr;
+
+                    for (int x = rect.Left + 1; x < rect.Right; ++x) {
+                        for (int i = 0; i < wlen - 1; ++i) {
+                            waSums[i] = waSums[i + 1];
+                            wcSums[i] = wcSums[i + 1];
+                            aSums[i] = aSums[i + 1];
+                            bSums[i] = bSums[i + 1];
+                            gSums[i] = gSums[i + 1];
+                            rSums[i] = rSums[i + 1];
+                        }
+
+                        waSum = 0;
+                        wcSum = 0;
+                        aSum = 0;
+                        bSum = 0;
+                        gSum = 0;
+                        rSum = 0;
+
+                        int wx;
+                        for (wx = 0; wx < wlen - 1; ++wx) {
+                            long wwx = (long)w[wx];
+                            waSum += wwx * waSums[wx];
+                            wcSum += wwx * wcSums[wx];
+                            aSum += wwx * aSums[wx];
+                            bSum += wwx * bSums[wx];
+                            gSum += wwx * gSums[wx];
+                            rSum += wwx * rSums[wx];
+                        }
+
+                        wx = wlen - 1;
+
+                        waSums[wx] = 0;
+                        wcSums[wx] = 0;
+                        aSums[wx] = 0;
+                        bSums[wx] = 0;
+                        gSums[wx] = 0;
+                        rSums[wx] = 0;
+
+                        int srcX = x + wx - r;
+
+                        if (srcX >= 0 && srcX < src_width) {
+                            for (int wy = 0; wy < wlen; ++wy) {
+                                int srcY = y + wy - r;
+
+                                if (srcY >= 0 && srcY < src_height) {
+                                    ColorBgra c = src.GetPointUnchecked (src_data_ptr, src_width, srcX, srcY);
+                                    int wp = w[wy];
+
+                                    waSums[wx] += wp;
+                                    wp *= c.A + (c.A >> 7);
+                                    wcSums[wx] += wp;
+                                    wp >>= 8;
+
+                                    aSums[wx] += wp * (long)c.A;
+                                    bSums[wx] += wp * (long)c.B;
+                                    gSums[wx] += wp * (long)c.G;
+                                    rSums[wx] += wp * (long)c.R;
+                                }
+                            }
+
+                            int wr = w[wx];
+                            waSum += (long)wr * waSums[wx];
+                            wcSum += (long)wr * wcSums[wx];
+                            aSum += (long)wr * aSums[wx];
+                            bSum += (long)wr * bSums[wx];
+                            gSum += (long)wr * gSums[wx];
+                            rSum += (long)wr * rSums[wx];
+                        }
+
+                        wcSum >>= 8;
+
+                        if (waSum == 0 || wcSum == 0) {
+                            dstPtr->Bgra = 0;
+                        } else {
+                            int alpha = (int)(aSum / waSum);
+                            int blue = (int)(bSum / wcSum);
+                            int green = (int)(gSum / wcSum);
+                            int red = (int)(rSum / wcSum);
+
+                            dstPtr->Bgra = ColorBgra.BgraToUInt32 (blue, green, red, alpha);
+                        }
+
+                        ++dstPtr;
+                    }
+                }
+            }
+        }
+    }
+
 	public unsafe static Gdk.Pixbuf RemoveRedeye (Gdk.Pixbuf src, Gdk.Rectangle area)
 	{
 		return RemoveRedeye (src, area, -15);
 	}
 
-	public unsafe static Gdk.Pixbuf RemoveRedeye (Gdk.Pixbuf src, Gdk.Rectangle area, int threshold)
-	//threshold, factors and comparisons borrowed from the gimp plugin 'redeye.c' by Robert Merkel
+    //threshold, factors and comparisons borrowed from the gimp plugin 'redeye.c' by Robert Merkel
+    public unsafe static Gdk.Pixbuf RemoveRedeye (Gdk.Pixbuf src, Gdk.Rectangle area, int threshold)
 	{
 		Gdk.Pixbuf copy = src.Copy ();
 		Gdk.Pixbuf selection = new Gdk.Pixbuf (copy, area.X, area.Y, area.Width, area.Height);
diff --git a/src/Core/FSpot.Utils/FSpot.Utils.csproj b/src/Core/FSpot.Utils/FSpot.Utils.csproj
index 7a72206..3f49241 100644
--- a/src/Core/FSpot.Utils/FSpot.Utils.csproj
+++ b/src/Core/FSpot.Utils/FSpot.Utils.csproj
@@ -55,7 +55,6 @@
     <Compile Include="FSpot.Utils\Tests\XdgThumbnailSpecTests.cs" />
     <Compile Include="FSpot.Utils\UriList.cs" />
     <Compile Include="FSpot.Utils\Vector.cs" />
-    <Compile Include="FSpot.Utils\MemorySurface.cs" />
     <Compile Include="FSpot.Utils\DelayedOperation.cs" />
     <Compile Include="FSpot.Utils\TargetListExtensionMethods.cs" />
   </ItemGroup>
diff --git a/src/Core/FSpot.Utils/Makefile.am b/src/Core/FSpot.Utils/Makefile.am
index 6f17140..8fc1650 100644
--- a/src/Core/FSpot.Utils/Makefile.am
+++ b/src/Core/FSpot.Utils/Makefile.am
@@ -11,7 +11,6 @@ SOURCES =  \
 	FSpot.Utils/GIOTagLibFileAbstraction.cs \
 	FSpot.Utils/GtkUtil.cs \
 	FSpot.Utils/HashUtils.cs \
-	FSpot.Utils/MemorySurface.cs \
 	FSpot.Utils/Metadata.cs \
 	FSpot.Utils/PixbufUtils.cs \
 	FSpot.Utils/RecursiveFileEnumerator.cs \



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]