public ImageCache(FileDatabase fileDatabase) :
     base(fileDatabase)
 {
     this.CurrentDifferenceState = ImageDifference.Unaltered;
     this.differenceBitmapCache = new Dictionary<ImageDifference, BitmapSource>();
     this.mostRecentlyUsedIDs = new MostRecentlyUsedList<long>(Constant.Images.BitmapCacheSize);
     this.prefetechesByID = new ConcurrentDictionary<long, Task>();
     this.unalteredBitmapsByID = new ConcurrentDictionary<long, BitmapSource>();
 }
        public void MoveToNextStateInPreviousNextDifferenceCycle()
        {
            Debug.Assert((this.Current != null) && (this.Current.IsVideo == false), "No current file or current file is an image.");

            // always go to unaltered from combined difference
            if (this.CurrentDifferenceState == ImageDifference.Combined)
            {
                this.CurrentDifferenceState = ImageDifference.Unaltered;
                return;
            }

            if (!this.Current.IsDisplayable())
            {
                // can't calculate differences for files which aren't displayble
                this.CurrentDifferenceState = ImageDifference.Unaltered;
                return;
            }
            else
            {
                // move to next state in cycle, wrapping around as needed
                this.CurrentDifferenceState = (this.CurrentDifferenceState >= ImageDifference.Next) ? ImageDifference.Previous : ++this.CurrentDifferenceState;
            }

            // unaltered is always displayable; no more checks required
            if (this.CurrentDifferenceState == ImageDifference.Unaltered)
            {
                return;
            }

            // can't calculate previous or next difference for the first or last file in the image set, respectively
            // can't calculate difference if needed file isn't displayable
            if (this.CurrentDifferenceState == ImageDifference.Previous && this.CurrentRow == 0)
            {
                this.MoveToNextStateInPreviousNextDifferenceCycle();
            }
            else if (this.CurrentDifferenceState == ImageDifference.Next && this.CurrentRow == this.Database.CurrentlySelectedFileCount - 1)
            {
                this.MoveToNextStateInPreviousNextDifferenceCycle();
            }
            else if (this.CurrentDifferenceState == ImageDifference.Next && !this.Database.IsFileDisplayable(this.CurrentRow + 1))
            {
                this.MoveToNextStateInPreviousNextDifferenceCycle();
            }
            else if (this.CurrentDifferenceState == ImageDifference.Previous && !this.Database.IsFileDisplayable(this.CurrentRow - 1))
            {
                this.MoveToNextStateInPreviousNextDifferenceCycle();
            }
        }
        public void MoveToNextStateInCombinedDifferenceCycle()
        {
            Debug.Assert((this.Current != null) && (this.Current.IsVideo == false), "No current file or current file is an image.");

            // if this method and MoveToNextStateInPreviousNextDifferenceCycle() returned bool they'd be consistent MoveNext() and MovePrevious()
            // however, there's no way for them to fail and there's not value in always returning true
            if (this.CurrentDifferenceState == ImageDifference.Next ||
                this.CurrentDifferenceState == ImageDifference.Previous ||
                this.CurrentDifferenceState == ImageDifference.Combined)
            {
                this.CurrentDifferenceState = ImageDifference.Unaltered;
            }
            else
            {
                this.CurrentDifferenceState = ImageDifference.Combined;
            }
        }
Ejemplo n.º 4
0
        public static JArray Parse(MappedFile file, ImageDifference imageDiff)
        {
            if (imageDiff.IsLoad)
            {
                return(new JArray(new JObject
                {
                    ["Action"] = "Load",
                    ["Target"] = file.RelativeMappedPath,
                    ["FromFile"] = Path.Combine("assets", file.RelativeFilePath)
                }));
            }
            JArray changes = new JArray();

            foreach (Area change in imageDiff.Differences)
            {
                JObject newToken = new JObject
                {
                    ["Action"]   = "EditImage",
                    ["Target"]   = file.RelativeMappedPath,
                    ["FromFile"] = Path.Combine("assets", file.RelativeFilePath)
                };

                JObject area = new JObject
                {
                    ["X"]      = change.Left,
                    ["Y"]      = change.Top,
                    ["Width"]  = change.Width,
                    ["Height"] = change.Height
                };
                newToken["FromArea"] = area;
                newToken["ToArea"]   = area;

                changes.Add(newToken);
            }

            return(changes);
        }
 private void ResetDifferenceState(BitmapSource unalteredImage)
 {
     this.CurrentDifferenceState = ImageDifference.Unaltered;
     this.differenceBitmapCache[ImageDifference.Unaltered] = unalteredImage;
     this.differenceBitmapCache[ImageDifference.Previous] = null;
     this.differenceBitmapCache[ImageDifference.Next] = null;
     this.differenceBitmapCache[ImageDifference.Combined] = null;
 }
        public async Task<ImageDifferenceResult> TryCalculateCombinedDifferenceAsync(byte differenceThreshold)
        {
            if (this.CurrentDifferenceState != ImageDifference.Combined)
            {
                return ImageDifferenceResult.NotCalculable;
            }

            // three valid images are needed: the current one, the previous one, and the next one
            if (this.Current == null || this.Current.IsVideo || this.Current.IsDisplayable() == false)
            {
                this.CurrentDifferenceState = ImageDifference.Unaltered;
                return ImageDifferenceResult.CurrentImageNotAvailable;
            }

            WriteableBitmap previousBitmap = await this.TryGetPreviousBitmapAsWriteableAsync();
            if (previousBitmap == null)
            {
                return ImageDifferenceResult.PreviousImageNotAvailable;
            }

            WriteableBitmap nextBitmap = await this.TryGetNextBitmapAsWriteableAsync();
            if (nextBitmap == null)
            {
                return ImageDifferenceResult.NextImageNotAvailable;
            }

            BitmapSource unalteredBitmap = this.differenceBitmapCache[ImageDifference.Unaltered];
            Debug.Assert(unalteredBitmap != null, "Difference cache coherency error: unaltered bitmap is null.");
            WriteableBitmap unalteredWriteableBitmap = unalteredBitmap.AsWriteable();
            this.differenceBitmapCache[ImageDifference.Unaltered] = unalteredWriteableBitmap;

            // all three images are available, so calculate and cache difference
            BitmapSource differenceBitmap = await Task.Run(() => { return unalteredWriteableBitmap.Difference(previousBitmap, nextBitmap, differenceThreshold); });
            this.differenceBitmapCache[ImageDifference.Combined] = differenceBitmap;
            return differenceBitmap != null ? ImageDifferenceResult.Success : ImageDifferenceResult.NotCalculable;
        }
        public async Task<ImageDifferenceResult> TryCalculateDifferenceAsync()
        {
            if (this.Current == null || this.Current.IsVideo || this.Current.IsDisplayable() == false)
            {
                this.CurrentDifferenceState = ImageDifference.Unaltered;
                return ImageDifferenceResult.CurrentImageNotAvailable;
            }

            // determine which image to use for differencing
            WriteableBitmap comparisonBitmap = null;
            if (this.CurrentDifferenceState == ImageDifference.Previous)
            {
                comparisonBitmap = await this.TryGetPreviousBitmapAsWriteableAsync();
                if (comparisonBitmap == null)
                {
                    return ImageDifferenceResult.PreviousImageNotAvailable;
                }
            }
            else if (this.CurrentDifferenceState == ImageDifference.Next)
            {
                comparisonBitmap = await this.TryGetNextBitmapAsWriteableAsync();
                if (comparisonBitmap == null)
                {
                    return ImageDifferenceResult.NextImageNotAvailable;
                }
            }
            else
            {
                return ImageDifferenceResult.NotCalculable;
            }

            WriteableBitmap unalteredBitmap = this.differenceBitmapCache[ImageDifference.Unaltered].AsWriteable();
            this.differenceBitmapCache[ImageDifference.Unaltered] = unalteredBitmap;

            BitmapSource differenceBitmap = await Task.Run(() => { return unalteredBitmap.Difference(comparisonBitmap); });
            this.differenceBitmapCache[this.CurrentDifferenceState] = differenceBitmap;
            return differenceBitmap != null ? ImageDifferenceResult.Success : ImageDifferenceResult.NotCalculable;
        }