Example #1
0
        public ManagedBitmap CreateTile(ManagedBitmap source, int offsetX, int offsetY, int drawWidth, int drawHeight, int targetWidth, int targetHeight, Profile profile)
        {
            EnsureStarted(profile);

            ManagedBitmap result;
            string        mapId;
            int           width, height;
            Profile       serverProfile;
            bool          succeeded = false;

            profile.Push("Remote call");
            ClientServerCommunication.SendMessage(
                null /*log*/,
                channel,
                ClientServerCommunication.Commands.CreateTileGDI,
                new object[]
            {
                (int)Thread.CurrentThread.Priority,
                (string)source.BackingName,
                (int)source.Width,
                (int)source.Height,
                (int)offsetX,
                (int)offsetY,
                (int)drawWidth,
                (int)drawHeight,
                (int)targetWidth,
                (int)targetHeight
            });
            try
            {
                ClientServerCommunication.WaitForPending(channel, out serverProfile, out mapId, out width, out height);
                profile.Add(serverProfile);
                result    = new ManagedBitmap32(width, height, mapId);
                succeeded = true;
            }
            catch (ClientServerCommunication.RemoteException)
            {
                result = ManagedBitmap.CreateFromGDI(new Bitmap(Properties.Resources.InvalidPlaceHolder));
            }
            profile.Pop();

            if (succeeded)
            {
                profile.Push("Remote call");
                ClientServerCommunication.SendMessage(
                    null /*log*/,
                    channel,
                    ClientServerCommunication.Commands.Clear,
                    null);
                ClientServerCommunication.WaitForDone(channel, out serverProfile);
                profile.Add(serverProfile);
                profile.Pop();
            }

            return(result);
        }
Example #2
0
        public ManagedBitmap LoadAndOrientGDI(string path, int rightRotations, Profile profile, out RotateFlipType exifOrientation)
        {
            EnsureStarted(profile);

            exifOrientation = RotateFlipType.RotateNoneFlipNone;

            ManagedBitmap result;
            string        mapId;
            int           width, height;
            Profile       serverProfile;
            bool          succeeded = false;

            profile.Push("Remote call");
            ClientServerCommunication.SendMessage(
                null /*log*/,
                channel,
                ClientServerCommunication.Commands.LoadAndOrientGDI,
                new object[]
            {
                (int)Thread.CurrentThread.Priority,
                (string)path,
                (int)rightRotations,
            });
            try
            {
                object[] extra = ClientServerCommunication.WaitForPending(channel, out serverProfile, out mapId, out width, out height);
                exifOrientation = (RotateFlipType)(int)extra[0];
                profile.Add(serverProfile);
                result    = new ManagedBitmap32(width, height, mapId);
                succeeded = true;
            }
            catch (ClientServerCommunication.RemoteException)
            {
                result = ManagedBitmap.CreateFromGDI(new Bitmap(Properties.Resources.InvalidPlaceHolder));
            }
            profile.Pop();

            if (succeeded)
            {
                profile.Push("Remote call");
                ClientServerCommunication.SendMessage(
                    null /*log*/,
                    channel,
                    ClientServerCommunication.Commands.Clear,
                    null);
                ClientServerCommunication.WaitForDone(channel, out serverProfile);
                profile.Add(serverProfile);
                profile.Pop();
            }

            return(result);
        }
Example #3
0
        private static void ResizeGDI(Profile profile, string sourceMapId, int sourceWidth, int sourceHeight, int targetWidth, int targetHeight, out ManagedBitmap targetBitmap)
        {
            profile.Push("Resize [GDI]");

            using (ManagedBitmap source = new ManagedBitmap32(sourceWidth, sourceHeight, sourceMapId))
            {
                profile.Push("Allocate");
                targetBitmap = new ManagedBitmap32(targetWidth, targetHeight);
                profile.Pop();

                Transforms.Resize(profile, source, targetBitmap);
            }

            profile.Pop();
        }
Example #4
0
        public ManagedBitmap ShrinkExpandWPF(ManagedBitmap source, double factor, Profile profile)
        {
            EnsureStarted(profile);

            ManagedBitmap result = new ManagedBitmap32(source.Width, source.Height);

            profile.Push("Remote call");
            ClientServerCommunication.SendMessage(
                null /*log*/,
                channel,
                ClientServerCommunication.Commands.ShrinkExpandWPF,
                new object[]
            {
                (int)Thread.CurrentThread.Priority,
                (int)source.Width,
                (int)source.Height,
                (string)source.BackingName,
                (string)result.BackingName,
                (double)factor,
            });
            Profile serverProfile;

            ClientServerCommunication.WaitForDone(channel, out serverProfile);
            profile.Add(serverProfile);
            profile.Pop();

            return(result);
        }
Example #5
0
        public Bitmap AsGDI(Profile profile = null)
        {
            bool pop = false;

            try
            {
                if (gdiBitmap != null)
                {
                    return(gdiBitmap);
                }

                if (profile != null)
                {
                    profile.Push("SmartBitmap.AsGDI");
                    pop = true;
                }

                if (wpfBitmap != null)
                {
                    Bitmap gdiBitmap = new Bitmap(wpfBitmap.PixelWidth, wpfBitmap.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
                    ApplyProperties();

                    BitmapData d      = gdiBitmap.LockBits(new Rectangle(0, 0, gdiBitmap.Width, gdiBitmap.Height), ImageLockMode.WriteOnly, ManagedBitmap32.Format);
                    int *      scan0  = (int *)d.Scan0.ToPointer();
                    int        stride = d.Stride;
                    Debug.Assert(stride > 0);

                    wpfBitmap.CopyPixels(new System.Windows.Int32Rect(0, 0, gdiBitmap.Width, gdiBitmap.Height), new IntPtr(scan0), stride, 0 /*offset*/);

                    gdiBitmap.UnlockBits(d);

                    wpfBitmap = null;

                    return(gdiBitmap);
                }

                if (managedBitmap != null)
                {
                    gdiBitmap = managedBitmap.CloneToGDI();

                    managedBitmap.Dispose();
                    managedBitmap = null;

                    return(gdiBitmap);
                }
            }
            finally
            {
                if ((profile != null) && pop)
                {
                    profile.Pop();
                }
            }

            Debug.Assert(false);
            throw new InvalidOperationException();
        }
Example #6
0
        private static void LoadAndOrientGDI(Profile profile, string sourceFilePath, int rightRotations, out ManagedBitmap bitmap, out RotateFlipType exifOrientation)
        {
            profile.Push("LoadAndOrient [GDI]");

            PropertyItem[] properties;
            bitmap = Transforms.LoadAndOrientManaged(profile, sourceFilePath, rightRotations, out properties, out exifOrientation);

            profile.Pop();
        }
Example #7
0
        public ImageServerProxy ObtainProxy(Profile profile)
        {
            profile.Push("ObtainProxy");
            int which = WaitHandle.WaitAny(proxyGates);
            ImageServerProxy result = proxies[which];

            profile.Pop();
            return(result);
        }
Example #8
0
        public BitmapFrame AsWPF(Profile profile = null)
        {
            bool pop = false;

            try
            {
                if (wpfBitmap != null)
                {
                    return(wpfBitmap);
                }

                if (profile != null)
                {
                    profile.Push("SmartBitmap.AsWPF");
                    pop = true;
                }

                if (gdiBitmap != null)
                {
                    BitmapData d      = gdiBitmap.LockBits(new Rectangle(0, 0, gdiBitmap.Width, gdiBitmap.Height), ImageLockMode.ReadOnly, ManagedBitmap32.Format);
                    int *      scan0  = (int *)d.Scan0.ToPointer();
                    int        stride = d.Stride;
                    Debug.Assert(stride > 0);

                    wpfBitmap = (BitmapFrame)BitmapFrame.Create(gdiBitmap.Width, gdiBitmap.Height, 96, 96, PixelFormats.Bgr32, null, new IntPtr(scan0), gdiBitmap.Width * gdiBitmap.Height * 4, stride);

                    gdiBitmap.UnlockBits(d);

                    gdiBitmap.Dispose();
                    gdiBitmap = null;

                    return(wpfBitmap);
                }

                if (managedBitmap != null)
                {
                    wpfBitmap = managedBitmap.CloneToWPF();

                    managedBitmap.Dispose();
                    managedBitmap = null;

                    return(wpfBitmap);
                }
            }
            finally
            {
                if ((profile != null) && pop)
                {
                    profile.Pop();
                }
            }

            Debug.Assert(false);
            throw new InvalidOperationException();
        }
Example #9
0
        private static void ShrinkExpandWPF(Profile profile, int width, int height, string sourceMapName, string targetMapName, double factor)
        {
            profile.Push("ShrinkExpand [WPF]");

            using (SmartBitmap source = new SmartBitmap(new ManagedBitmap32(width, height, sourceMapName)))
            {
                profile.Push("Convert to WPF");
                BitmapFrame wpfSource = source.AsWPF();
                profile.Pop();

                BitmapFrame wpfShrunkExpanded = Transforms.ShrinkExpand(profile, wpfSource, factor);

                profile.Push("Convert to Managed");
                using (ManagedBitmap target = new ManagedBitmap32(wpfShrunkExpanded, targetMapName)) // copy into shared memory
                {
                }
                profile.Pop();
            }

            profile.Pop();
        }
Example #10
0
        private static void ShrinkExpandGDI(Profile profile, int width, int height, string sourceMapName, string targetMapName, double factor)
        {
            profile.Push("ShrinkExpand [GDI]");

            using (ManagedBitmap source = new ManagedBitmap32(width, height, sourceMapName))
            {
                using (ManagedBitmap target = new ManagedBitmap32(width, height, targetMapName))
                {
                    Transforms.ShrinkExpand(profile, source, factor, target);
                }
            }

            profile.Pop();
        }
Example #11
0
        public static ManagedBitmap ShrinkExpandWPF(Profile profile, ManagedBitmap source, double factor)
        {
            profile.Push("ImageClient.ShrinkExpandWPF");
            ImageServerProxy server = serverPool.ObtainProxy(profile);

            try
            {
                ManagedBitmap result = server.ShrinkExpandWPF(source, factor, profile);
                return(result);
            }
            finally
            {
                serverPool.ReleaseProxy(server);
                profile.Pop();
            }
        }
Example #12
0
        public static ManagedBitmap CreateTileGDI(Profile profile, ManagedBitmap source, int offsetX, int offsetY, int drawWidth, int drawHeight, int targetWidth, int targetHeight)
        {
            profile.Push("ImageClient.CreateTileGDI");
            ImageServerProxy server = serverPool.ObtainProxy(profile);

            try
            {
                ManagedBitmap result = server.CreateTile(source, offsetX, offsetY, drawWidth, drawHeight, targetWidth, targetHeight, profile);
                return(result);
            }
            finally
            {
                serverPool.ReleaseProxy(server);
                profile.Pop();
            }
        }
Example #13
0
        public static ManagedBitmap ResizeGDI(Profile profile, ManagedBitmap source, int targetWidth, int targetHeight)
        {
            profile.Push("ImageClient.ResizeGDI");
            ImageServerProxy server = serverPool.ObtainProxy(profile);

            try
            {
                ManagedBitmap result = server.ResizeGDI(source, targetWidth, targetHeight, profile);
                return(result);
            }
            finally
            {
                serverPool.ReleaseProxy(server);
                profile.Pop();
            }
        }
Example #14
0
        public static ManagedBitmap LoadAndOrientGDI(Profile profile, string path, int rightRotations, out RotateFlipType exifOrientation)
        {
            profile.Push("ImageClient.LoadAndOrientGDI");
            ImageServerProxy server = serverPool.ObtainProxy(profile);

            try
            {
                ManagedBitmap result = server.LoadAndOrientGDI(path, rightRotations, profile, out exifOrientation);
                return(result);
            }
            finally
            {
                serverPool.ReleaseProxy(server);
                profile.Pop();
            }
        }
Example #15
0
        public ManagedBitmap AsManaged(Profile profile = null)
        {
            bool pop = false;

            try
            {
                if (managedBitmap != null)
                {
                    return(managedBitmap);
                }

                if (profile != null)
                {
                    profile.Push("SmartBitmap.AsManaged");
                    pop = true;
                }

                if (gdiBitmap != null)
                {
                    managedBitmap = ManagedBitmap.CreateFromGDI(gdiBitmap);

                    gdiBitmap.Dispose();
                    gdiBitmap = null;

                    return(managedBitmap);
                }

                if (wpfBitmap != null)
                {
                    managedBitmap = new ManagedBitmap32(wpfBitmap);

                    wpfBitmap = null;

                    return(managedBitmap);
                }
            }
            finally
            {
                if ((profile != null) && pop)
                {
                    profile.Pop();
                }
            }

            Debug.Assert(false);
            throw new InvalidOperationException();
        }
Example #16
0
        private void EnsureStarted(Profile profile)
        {
            if (!started)
            {
                profile.Push("EnsureStarted");

                string pipeName = Guid.NewGuid().ToString();

                // TODO: security - restrict access to child process

                channel = new NamedPipeServerStream(pipeName);

                if (!InProc)
                {
                    remote = new Process();
                    remote.StartInfo.Arguments        = String.Format("-server {0}", pipeName);
                    remote.StartInfo.CreateNoWindow   = true;
                    remote.StartInfo.FileName         = Assembly.GetExecutingAssembly().Location;
                    remote.StartInfo.UseShellExecute  = false;
                    remote.StartInfo.WorkingDirectory = Path.GetTempPath();
                    remote.Start();
                }
                else
                {
#pragma warning disable CS0162 // unreachable
                    simulatedRemote = new Thread(new ThreadStart(
                                                     delegate()
                    {
                        ImageServer.RunServer(pipeName);
                    }));
                    simulatedRemote.Name = "ImageServer - InProc";
                    simulatedRemote.Start();
#pragma warning restore CS0162
                }

                channel.WaitForConnection();

                started = true;

                profile.Pop();
            }
        }
Example #17
0
        // TODO: untested
        private unsafe static void CreateTileGDI(Profile profile, string sourceMapId, int sourceWidth, int sourceHeight, int offsetX, int offsetY, int drawWidth, int drawHeight, int targetWidth, int targetHeight, out ManagedBitmap targetBitmap)
        {
            profile.Push("CreateTileGDI");

            using (ManagedBitmap sourceBitmap = new ManagedBitmap32(sourceWidth, sourceHeight, sourceMapId))
            {
                using (Bitmap sourceBitmapGDI = new Bitmap(sourceWidth, sourceHeight, sourceBitmap.Stride, sourceBitmap.ImageFormat, new IntPtr(sourceBitmap.Scan0)))
                {
                    targetBitmap = new ManagedBitmap32(targetWidth, targetHeight);
                    using (Bitmap targetBitmapGDI = new Bitmap(targetWidth, targetHeight, targetBitmap.Stride, targetBitmap.ImageFormat, new IntPtr(targetBitmap.Scan0)))
                    {
                        using (Graphics graphics = Graphics.FromImage(targetBitmapGDI))
                        {
                            graphics.FillRectangle(System.Drawing.Brushes.Black, 0, 0, targetWidth, targetHeight);
                            graphics.DrawImage(sourceBitmapGDI, offsetX, offsetY, drawWidth, drawHeight);
                        }
                    }
                }
            }

            profile.Pop();
        }
Example #18
0
        // use highest quality transforms and no cached bitmaps
        public static void FinalOutputOne(Item item, Stats stats, Dictionary <string, bool> createdFiles, List <string> messages, CancellationTokenSource cancel)
        {
            Profile profile = new Profile("FinalOutput {0}", item.RenamedFileName);

            profile.Push("Item.WaitInit");
            item.WaitInit();
            profile.Pop();

            DateTime originalCreationTime  = File.GetCreationTime(item.SourcePath);
            DateTime originalLastWriteTime = File.GetLastWriteTime(item.SourcePath);

            string renamedTargetPath = Path.Combine(Path.GetDirectoryName(item.TargetPath), item.RenamedFileName);

            if (item.Delete)
            {
                // actual deletion occurs after end of run, by file being omitted from createdFiles
                Interlocked.Increment(ref stats.deleted);
            }
            else if (item.Valid)
            {
                // load source

                string tempFile = Path.GetTempFileName();
                File.Copy(item.SourcePath, tempFile, true /*overwrite*/);


                SmartBitmap bitmap = null;

                bool jpegTranRotationRequired = true;


                // initial lossy transforms

                if (item.NormalizeGeometry || (item.FineRotateDegrees != 0))
                {
                    if (bitmap == null)
                    {
                        bitmap = new SmartBitmap(Transforms.LoadAndOrientGDI(tempFile, profile));
                    }

                    jpegTranRotationRequired = false;
                    if (item.RightRotations != 0)
                    {
                        ManagedBitmap bitmap2 = bitmap.AsManaged().RotateFlip(Transforms.RotateFlipFromRightRotations(item.RightRotations));
                        bitmap.Dispose();
                        bitmap = new SmartBitmap(bitmap2);
                    }

                    Transforms.ApplyNormalizeGeometry(
                        profile,
                        item.SourceFileName,
                        bitmap.AsManaged(),
                        1,
                        new Transforms.NormalizeGeometryParameters(
                            item.CornerTL,
                            item.CornerTR,
                            item.CornerBL,
                            item.CornerBR,
                            item.NormalizeGeometryForcedAspectRatio,
                            item.FineRotateDegrees,
                            item.NormalizeGeometryFinalInterp),
                        delegate(string text) { },
                        cancel);
                }


                // lossless transform phase

                if (bitmap == null)
                {
                    List <string> jpegtranMessages = new List <string>();
                    string        error;

                    bool rotateOK = true;
                    if (jpegTranRotationRequired &&
                        ((item.RightRotations != 0) || (item.OriginalExifOrientation != RotateFlipType.RotateNoneFlipNone)))
                    {
                        rotateOK = false;
                        int combinedRotations = (item.RightRotations + Transforms.RightRotationsFromRotateFlipType(item.OriginalExifOrientation)) % 4;

                        // TODO: strip only Exif orientation after doing this - how? (currently strips all)
                        if (Transforms.LosslessRotateRightFinal(
                                tempFile,
                                tempFile,
                                combinedRotations,
                                out error))
                        {
                            Interlocked.Increment(ref stats.rotated);
                            rotateOK = true;
                        }
                        else
                        {
                            jpegtranMessages.Add(String.Format("Lossless rotate failed for \"{0}\" ({1}).", item.RenamedFileName, error));
                        }
                    }

                    bool cropOK = true;
                    if (!item.CropRect.IsEmpty)
                    {
                        cropOK = false;
                        if (Transforms.LosslessCropFinal(tempFile, tempFile, item.CropRect, out error))
                        {
                            Interlocked.Increment(ref stats.cropped);
                            cropOK = true;
                        }
                        else
                        {
                            jpegtranMessages.Add(String.Format("Lossless crop failed for \"{0}\" ({1}).", item.RenamedFileName, error));
                        }
                    }

                    if (!rotateOK || !cropOK)
                    {
                        // If jpegtran is unable to handle image (e.g. dimensions not integral multiples - as generated by
                        // some cameras), fall back to lossy rotation and log a message.

                        bitmap = new SmartBitmap(Transforms.LoadAndOrientGDI(tempFile, profile));

                        if (!rotateOK)
                        {
                            ManagedBitmap bitmap2 = bitmap.AsManaged().RotateFlip(Transforms.RotateFlipFromRightRotations(item.RightRotations));
                            bitmap.Dispose();
                            bitmap = new SmartBitmap(bitmap2);
                        }

                        if (!cropOK)
                        {
                            ManagedBitmap bitmap2 = bitmap.AsManaged().Crop(item.CropRect);
                            bitmap.Dispose();
                            bitmap = new SmartBitmap(bitmap2);
                        }

                        jpegtranMessages.Add("Using lossy rotation/crop instead.");
                        lock (messages)
                        {
                            messages.Add(String.Join(" ", jpegtranMessages.ToArray()));
                        }
                    }
                }
                else
                {
                    // whoops- preceding transform prevents jpegtran from being used (recreating jpeg would be lossy)

                    if (!item.CropRect.IsEmpty)
                    {
                        ManagedBitmap bitmap2 = bitmap.AsManaged().Crop(item.CropRect);
                        bitmap.Dispose();
                        bitmap = new SmartBitmap(bitmap2);
                    }
                }


                // following lossy transforms phase

                if (item.Unbias)
                {
                    if (bitmap == null)
                    {
                        bitmap = new SmartBitmap(Transforms.LoadAndOrientGDI(tempFile, profile));
                    }

                    Transforms.PolyUnbiasDiagnostics unused;
                    Transforms.ApplyPolyUnbias(
                        profile,
                        item.RenamedFileName,
                        bitmap.AsManaged(profile),
                        Rectangle.Empty /*already cropped*/,
                        new Transforms.PolyUnbiasParameters(
                            item.UnbiasMaxDegree,
                            item.UnbiasMaxChisq,
                            item.UnbiasMaxS,
                            item.UnbiasMinV),
                        null,
                        out unused,
                        cancel);

                    Interlocked.Increment(ref stats.polyUnbias);
                }

                if (item.BrightAdjust)
                {
                    if (bitmap == null)
                    {
                        bitmap = new SmartBitmap(Transforms.LoadAndOrientGDI(tempFile, profile));
                    }

                    Transforms.ApplyBrightAdjust(
                        profile,
                        item.RenamedFileName,
                        bitmap.AsManaged(profile),
                        Rectangle.Empty /*already cropped*/,
                        new Transforms.BrightAdjustParameters(item.BrightAdjustMinClusterFrac, item.BrightAdjustWhiteCorrect),
                        null,
                        cancel);

                    Interlocked.Increment(ref stats.brightAdjust);
                }

                if (item.StaticSaturate)
                {
                    if (bitmap == null)
                    {
                        bitmap = new SmartBitmap(Transforms.LoadAndOrientGDI(tempFile, profile));
                    }

                    Transforms.ApplyStaticSaturation(
                        profile,
                        item.RenamedFileName,
                        bitmap.AsManaged(profile),
                        Rectangle.Empty /*already cropped*/,
                        new Transforms.StaticSaturateParameters(item.StaticSaturateWhiteThreshhold, item.StaticSaturateBlackThreshhold, item.StaticSaturateExponent),
                        cancel);
                }

                if (item.Shrink)
                {
                    if (bitmap == null)
                    {
                        bitmap = new SmartBitmap(Transforms.LoadAndOrientGDI(tempFile, profile));
                    }

                    //Bitmap shrunk = Transforms.Shrink(profile, bitmap.AsGDI(profile), item.ShrinkFactor);
                    int           newWidth  = (int)Math.Floor(bitmap.Width / item.ShrinkFactor);
                    int           newHeight = (int)Math.Floor(bitmap.Height / item.ShrinkFactor);
                    ManagedBitmap bitmap2   = ImageClient.ResizeGDI(profile, bitmap.AsManaged(profile), newWidth, newHeight);
                    bitmap.Dispose();
                    bitmap = new SmartBitmap(bitmap2);

                    Interlocked.Increment(ref stats.shrunk);
                }

                // TODO: eliminate shrink and OneBit's expand if both are configured

                if (item.OneBit)
                {
                    if (bitmap == null)
                    {
                        bitmap = new SmartBitmap(Transforms.LoadAndOrientGDI(tempFile, profile));
                    }

                    SmartBitmap bitmap2 = new SmartBitmap(
                        Transforms.ApplyOneBit(
                            profile,
                            item.RenamedFileName,
                            bitmap,
                            new Transforms.OneBitParameters(item.OneBitChannel, item.OneBitThreshhold, item.OneBitScaleUp),
                            cancel));
                    bitmap.Dispose();
                    bitmap = bitmap2;

                    Interlocked.Increment(ref stats.oneBit);
                }

                if (bitmap != null)
                {
                    Transforms.SaveImage(profile, bitmap, tempFile, item.JpegQuality, item.JpegUseGdi, item.OutputFormat);
                    bitmap.Dispose();
                }


                // write target

                string targetPath;
                bool   extUpper = String.Equals(Path.GetExtension(renamedTargetPath), Path.GetExtension(renamedTargetPath).ToUpper());
                switch (item.OutputFormat)
                {
                default:
                    Debug.Assert(false);
                    throw new ArgumentException();

                case OutputFormat.Jpeg:
                    targetPath = Path.ChangeExtension(renamedTargetPath, extUpper ? ".JPG" : ".jpg");
                    break;

                case OutputFormat.Bmp:
                    targetPath = Path.ChangeExtension(renamedTargetPath, extUpper ? ".BMP" : ".bmp");
                    break;

                case OutputFormat.Png:
                    targetPath = Path.ChangeExtension(renamedTargetPath, extUpper ? ".PNG" : ".png");
                    break;
                }
                for (int i = 0; i <= RetryCount; i++)
                {
                    try
                    {
                        File.Copy(tempFile, targetPath, true /*overwrite*/);
                        File.SetCreationTime(targetPath, originalCreationTime);
                        File.SetLastWriteTime(targetPath, DateTime.Now);
                    }
                    catch (IOException) when(i < RetryCount)
                    {
                        // HACK: If folder is open, Explorer may have file locked to refresh thumbnail
                        Thread.Sleep(SleepRetry);
                    }
                }

                lock (createdFiles)
                {
                    createdFiles.Add(Path.GetFileName(targetPath).ToLowerInvariant(), false);
                }

                File.Delete(tempFile);
            }
            else
            {
                lock (createdFiles)
                {
                    createdFiles.Add(Path.GetFileName(renamedTargetPath).ToLowerInvariant(), false);
                }

                if (!String.Equals(item.SourcePath, renamedTargetPath, StringComparison.OrdinalIgnoreCase))
                {
                    File.Copy(item.SourcePath, renamedTargetPath, true /*overwrite*/);
                }
            }

            profile.End();
            Program.Log(LogCat.Perf, profile.Report());
        }
Example #19
0
        public void StartSwapOut(ImageCache cache)
        {
            lock (this)
            {
                Debug.Assert(Program.EnableSwap);

                if (this.outTask != null)
                {
                    return;
                }
                if (this.holders.Count != 0)
                {
                    return;
                }

                Stopwatch elapsed = Stopwatch.StartNew();

#if true // TODO: remove hack
                EventWaitHandle swapOutDelay = new EventWaitHandle(false, EventResetMode.AutoReset);
#endif
                Task <bool> serializationTask = null;

                Task <ManagedBitmap> oldBitmap = this.bitmap;

                // 'this' is not locked at the time 'cache' is used below in the task delegates

                this.outTask = new Task <bool>(
                    delegate()
                {
                    Profile profile = new Profile("SwapOut {0}", this.id);

#if true // TODO: remove hack
                    profile.Push("Hack delay for swapins");
                    // HACK: wait a little to allow swapins to start before swapouts
                    EventWaitHandle localSwapOutDelay = Interlocked.Exchange(ref swapOutDelay, null);
                    if (localSwapOutDelay != null)     // race: swapin can grab and clear this before we get here
                    {
                        localSwapOutDelay.WaitOne(100);
                    }
                    profile.Pop();
                    //
#endif
                    profile.Push("WaitSwapOutGate");
                    cache.WaitSwapOutGate();     // defer to in-flight swapins
                    profile.Pop();

                    lock (this)
                    {
                        Debug.Assert(this.swapFilePath == null);
                        Debug.Assert(this.swapFileStream == null);
                        this.swapFilePath   = Path.GetTempFileName();
                        this.swapFileStream = new FileStream(this.swapFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite, 4096, FileOptions.DeleteOnClose);
                    }

                    profile.Push("oldBitmap.Wait()");
                    oldBitmap.Wait();     // wait for an old in-flight creation to complete
                    profile.Pop();

                    profile.Push("Serialize");
                    serializationTask = new Task <bool>(
                        delegate()
                    {
                        SetIOPriority(this.swapFileStream, PRIORITY_HINT.IoPriorityHintLow);
                        ManagedBitmap.Serialize(this.swapFileStream, oldBitmap.Result);
                        SetIOPriority(this.swapFileStream, PRIORITY_HINT.IoPriorityHintNormal);
                        return(false);
                    });
                    SerializationManager.Manager.EnqueueWriteTask(serializationTask);
                    serializationTask.Wait();
                    profile.Pop();

                    profile.Push("Enqueue oldBitmap");
                    lock (this)
                    {
                        this.oldBitmaps.Add(oldBitmap.Result);     // remove current bitmap and enqueue for destruction upon zero refs
                    }
                    profile.Pop();

                    profile.Push("Epilog");
                    cache.Trace("swapout", this, elapsed);
                    cache.PurgeDisposeList();
                    profile.Pop();

                    profile.End();
                    //Program.Log(LogCat.Perf, profile.ToString());

                    return(false);
                });

                this.bitmap = new Task <ManagedBitmap>(
                    delegate()
                {
                    Profile profile = new Profile("SwapIn {0}", this.id);

                    profile.Push("outTask.Wait()");
#if true // TODO: remove hack
                    // HACK: release delay immediately if swapin is requested
                    EventWaitHandle localSwapOutDelay = Interlocked.Exchange(ref swapOutDelay, null);
                    if (localSwapOutDelay != null)
                    {
                        localSwapOutDelay.Set();
                    }
                    //
#endif
                    SerializationManager.Manager.Prioritize(serializationTask);
                    Debug.Assert(this.outTask != null);
                    this.outTask.Wait();     // ensure in-progress swapout finishes
                    profile.Pop();

                    profile.Push("cache.BeginSwapIn()");
                    cache.BeginSwapIn();
                    profile.Pop();
                    try
                    {
                        Stopwatch elapsed2 = Stopwatch.StartNew();

                        Debug.Assert(this.swapFilePath != null);
                        Debug.Assert(this.swapFileStream != null);

                        profile.Push("Deserialize");
                        ManagedBitmap bitmap            = null;
                        Task <bool> deserializationTask = new Task <bool>(
                            delegate()
                        {
                            bitmap = ManagedBitmap.Deserialize(this.swapFileStream);
                            return(false);
                        });
                        SerializationManager.Manager.EnqueueReadTask(deserializationTask);
                        deserializationTask.Wait();
                        this.swapFilePath          = null;
                        Stream localSwapFileStream = this.swapFileStream;
                        this.swapFileStream        = null;
                        localSwapFileStream.Dispose();
                        this.outTask = null;
                        profile.Pop();

                        profile.Push("Epilog");
                        cache.Trace("swapin", this, elapsed2);
                        cache.PurgeDisposeList();

                        StartBitmapCompleteWaiter();

                        return(bitmap);
                    }
                    finally
                    {
                        cache.EndSwapIn();
#if true // TODO: remove hack
                        if (localSwapOutDelay != null)
                        {
                            localSwapOutDelay.Dispose();
                        }
#endif
                        profile.Pop();     // Epilog - here to include cache.EndSwapIn()

                        profile.End();
                        //Program.Log(LogCat.Perf, profile.ToString());
                    }
                });

                this.outTask.Start();
            }
        }