Ejemplo n.º 1
0
        public static void Serialize(Stream stream, ManagedBitmap bitmap)
        {
            stream.Position = 0;
            using (BinaryWriter writer = new BinaryWriter(stream, Encoding.ASCII, true /*leaveOpen*/))
            {
                if (bitmap is ManagedBitmap32)
                {
                    writer.Write((int)32);
                }
                else if (bitmap is ManagedBitmap1)
                {
                    writer.Write((int)1);
                }
                else
                {
                    throw new ArgumentException();
                }
                writer.Write((int)bitmap.Width);
                writer.Write((int)bitmap.Height);
            }
            int padding = (int)((PageSize - stream.Position) & (PageSize - 1));

            stream.Write(new byte[padding], 0, padding);

            bitmap.Serialize(stream);
            stream.SetLength(stream.Position);
        }
Ejemplo n.º 2
0
 public static void Serialize(string path, ManagedBitmap bitmap)
 {
     using (Stream stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))
     {
         Serialize(stream, bitmap);
     }
 }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
0
        private int Add(string id, BitmapProvider provider)
        {
            lock (this)
            {
                Task <ManagedBitmap> bitmap = new Task <ManagedBitmap>(
                    delegate()
                {
                    try
                    {
                        return(provider());
                    }
                    catch (Exception exception)
                    {
                        if (EnableTrace)
                        {
                            Program.Log(LogCat.Cache, String.Format(
                                            "{0} ImageCache: provider threw exception: {2}{1}",
                                            DateTime.Now,
                                            Environment.NewLine,
                                            exception));
                        }
                    }
                    return(ManagedBitmap.CreateFromGDI(new Bitmap(Properties.Resources.InvalidPlaceHolder)));
                });

                Entry entry = new Entry(id, bitmap);
                entry.BitmapCompleted += delegate(object sender, EventArgs args) { SwapOutOverLimit(); };
                entries.Insert(0, entry);
                Trace("add", entry);

                PurgeDisposeList();
                return(0);
            }
        }
Ejemplo n.º 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();
        }
Ejemplo n.º 6
0
        public ManagedBitmap AsManagedDetach(Profile profile = null)
        {
            ManagedBitmap bitmap = AsManaged(profile);

            Debug.Assert(managedBitmap != null);
            managedBitmap = null;
            GC.SuppressFinalize(this);
            return(bitmap);
        }
Ejemplo n.º 7
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);
        }
Ejemplo n.º 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();
        }
Ejemplo n.º 9
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);
        }
Ejemplo n.º 10
0
 public void Clear()
 {
     this.wpfBitmap = null;
     if (this.gdiBitmap != null)
     {
         this.gdiBitmap.Dispose();
         this.gdiBitmap = null;
     }
     if (this.managedBitmap != null)
     {
         this.managedBitmap.Dispose();
         this.managedBitmap = null;
     }
 }
Ejemplo n.º 11
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();
            }
        }
Ejemplo n.º 12
0
        public virtual void CopyTo(ManagedBitmap target)
        {
            // Generic implementation - override in subclass to provide optimized version
            Debug.Assert((this.Width == target.Width) && (this.Height == target.Height));

            int width  = this.Width;
            int height = this.Height;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    target[x, y] = this[x, y];
                }
            }
        }
Ejemplo n.º 13
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();
            }
        }
Ejemplo n.º 14
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();
            }
        }
Ejemplo n.º 15
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();
            }
        }
Ejemplo n.º 16
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();
        }
Ejemplo n.º 17
0
        // Return subsection of bitmap as new bitmap
        public virtual ManagedBitmap Crop(Rectangle rect)
        {
            // Generic implementation - override for optimized versions

            // constrain crop
            rect.Intersect(new Rectangle(Point.Empty, this.Size));

            ManagedBitmap result = this.NewCompatible(rect.Width, rect.Height);

            for (int i = 0; i < rect.Height; i++)
            {
                for (int j = 0; j < rect.Width; j++)
                {
                    result[j, i] = this[j + rect.X, i + rect.Y];
                }
            }

            return(result);
        }
Ejemplo n.º 18
0
 public void AbsorbManaged(ManagedBitmap managedBitmap)
 {
     Clear();
     this.managedBitmap = managedBitmap;
 }
Ejemplo n.º 19
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();
        }
Ejemplo n.º 20
0
 public SmartBitmap(ManagedBitmap managedBitmap)
 {
     this.managedBitmap = managedBitmap;
 }
Ejemplo n.º 21
0
        private const bool Logging = true; // TODO: turn off

        public static int RunServer(string pipeName)
        {
            TextWriter log;

            if (Logging)
            {
                int i = 0;
                while (true)
                {
                    try
                    {
                        log = new StreamWriter(Path.Combine(Path.GetTempPath(), String.Concat("ImageServerLog-", i, ".log")));
                    }
                    catch (Exception)
                    {
                        i++;
                        continue;
                    }
                    break;
                }
                log = TextWriter.Synchronized(log);
            }

            ManagedBitmap currentBitmap = null;

            try
            {
                ThreadPriority savedThreadPriority = Thread.CurrentThread.Priority;

                if (log != null)
                {
                    log.WriteLine("Connecting to pipe {0}", pipeName);
                    log.Flush();
                }
                using (NamedPipeClientStream channel = new NamedPipeClientStream(".", pipeName))
                {
                    channel.Connect();

                    Thread disconnectMonitorThread = new Thread(new ThreadStart(
                                                                    delegate()
                    {
                        TimeoutThread(channel);
                        if (log != null)
                        {
                            log.WriteLine("TimeoutThread terminated - connection broken, exiting");
                            log.Flush();
                        }
                    }));
                    disconnectMonitorThread.Start();

                    while (true)
                    {
                        if (log != null)
                        {
                            log.WriteLine("Waiting");
                            log.Flush();
                        }

                        ClientServerCommunication.Commands command;
                        object[] args;
                        ClientServerCommunication.ReceiveMessage(log, channel, out command, out args);

                        object[] extraResults = null;

                        if (log != null)
                        {
                            log.WriteLine("Processing command");
                            log.Flush();
                        }
                        Profile profile;
                        try
                        {
                            profile = new Profile("ImageServer process command");

                            if (log != null)
                            {
                                log.WriteLine("Command: {0}", command);
                                log.Flush();
                            }
                            switch (command)
                            {
                            default:
                                Debug.Assert(false);
                                throw new ArgumentException(command.ToString());

                            case ClientServerCommunication.Commands.Quit:
                                if (args.Length != 0)
                                {
                                    const string Message = "remote command: wrong number of arguments";
                                    Debug.Assert(false, Message);
                                    throw new ArgumentException(Message);
                                }
                                if (log != null)
                                {
                                    log.WriteLine("Main thread exiting");
                                    log.Flush();
                                    log.Close();
                                    log = null;
                                }
                                return(0);

                            case ClientServerCommunication.Commands.Clear:
                                if (args.Length != 0)
                                {
                                    const string Message = "remote command: wrong number of arguments";
                                    Debug.Assert(false, Message);
                                    throw new ArgumentException(Message);
                                }
                                if (currentBitmap == null)
                                {
                                    const string Message = "Current bitmap is null";
                                    Debug.Assert(false, Message);
                                    throw new InvalidOperationException(Message);
                                }
                                currentBitmap.Dispose();
                                currentBitmap = null;
                                break;

                            case ClientServerCommunication.Commands.LoadAndOrientGDI:
                                if (args.Length != 3)
                                {
                                    const string Message = "remote command: wrong number of arguments";
                                    Debug.Assert(false, Message);
                                    throw new ArgumentException(Message);
                                }
                                if (currentBitmap != null)
                                {
                                    const string Message = "Current bitmap hasn't been cleared";
                                    Debug.Assert(false, Message);
                                    throw new InvalidOperationException(Message);
                                }
                                Thread.CurrentThread.Priority = (ThreadPriority)args[0];
                                RotateFlipType exifOrientation;
                                LoadAndOrientGDI(
                                    profile,
                                    (string)args[1],
                                    (int)args[2],
                                    out currentBitmap,
                                    out exifOrientation);
                                extraResults = new object[] { (int)exifOrientation };
                                break;

                            case ClientServerCommunication.Commands.ResizeGDI:
                                if (args.Length != 6)
                                {
                                    const string Message = "remote command: wrong number of arguments";
                                    Debug.Assert(false, Message);
                                    throw new ArgumentException(Message);
                                }
                                if (currentBitmap != null)
                                {
                                    const string Message = "Current bitmap hasn't been cleared";
                                    Debug.Assert(false, Message);
                                    throw new InvalidOperationException(Message);
                                }
                                Thread.CurrentThread.Priority = (ThreadPriority)args[0];
                                ResizeGDI(
                                    profile,
                                    (string)args[1],
                                    (int)args[2],
                                    (int)args[3],
                                    (int)args[4],
                                    (int)args[5],
                                    out currentBitmap);
                                break;

                            case ClientServerCommunication.Commands.CreateTileGDI:
                                if (args.Length != 10)
                                {
                                    const string Message = "remote command: wrong number of arguments";
                                    Debug.Assert(false, Message);
                                    throw new ArgumentException(Message);
                                }
                                if (currentBitmap != null)
                                {
                                    const string Message = "Current bitmap hasn't been cleared";
                                    Debug.Assert(false, Message);
                                    throw new InvalidOperationException(Message);
                                }
                                Thread.CurrentThread.Priority = (ThreadPriority)args[0];
                                CreateTileGDI(
                                    profile,
                                    (string)args[1],
                                    (int)args[2],
                                    (int)args[3],
                                    (int)args[4],
                                    (int)args[5],
                                    (int)args[6],
                                    (int)args[7],
                                    (int)args[8],
                                    (int)args[9],
                                    out currentBitmap);
                                break;

                            case ClientServerCommunication.Commands.ShrinkExpandGDI:
                                if (args.Length != 6)
                                {
                                    const string Message = "remote command: wrong number of arguments";
                                    Debug.Assert(false, Message);
                                    throw new ArgumentException(Message);
                                }
                                Thread.CurrentThread.Priority = (ThreadPriority)args[0];
                                ShrinkExpandGDI(
                                    profile,
                                    (int)args[1],
                                    (int)args[2],
                                    (string)args[3],
                                    (string)args[4],
                                    (double)args[5]);
                                break;

                            case ClientServerCommunication.Commands.ShrinkExpandWPF:
                                if (args.Length != 6)
                                {
                                    const string Message = "remote command: wrong number of arguments";
                                    Debug.Assert(false, Message);
                                    throw new ArgumentException(Message);
                                }
                                Thread.CurrentThread.Priority = (ThreadPriority)args[0];
                                ShrinkExpandWPF(
                                    profile,
                                    (int)args[1],
                                    (int)args[2],
                                    (string)args[3],
                                    (string)args[4],
                                    (double)args[5]);
                                break;
                            }

                            profile.End();
                        }
                        catch (Exception exception)
                        {
                            if (log != null)
                            {
                                log.WriteLine("Recoverable exception: {0}", exception);
                                log.Flush();
                            }
                            ClientServerCommunication.SendMessage(
                                log,
                                channel,
                                ClientServerCommunication.Commands.Exception,
                                new object[] { exception.ToString() });
                            if (log != null)
                            {
                                log.WriteLine("Exception response sent");
                                log.Flush();
                            }
                            continue;
                        }
                        finally
                        {
                            Thread.CurrentThread.Priority = savedThreadPriority;
                        }

                        if (log != null)
                        {
                            log.WriteLine("Forming response");
                            log.Flush();
                        }
                        using (MemoryStream serializedProfileStream = new MemoryStream())
                        {
                            if (log != null)
                            {
                                log.WriteLine("Serializing profile");
                                log.Flush();
                            }
                            new BinaryFormatter().Serialize(serializedProfileStream, profile);

                            if (currentBitmap == null)
                            {
                                if (log != null)
                                {
                                    log.WriteLine("Sending 'Done'");
                                    log.Flush();
                                }
                                ClientServerCommunication.SendMessage(
                                    log,
                                    channel,
                                    ClientServerCommunication.Commands.Done,
                                    new object[] { serializedProfileStream.ToArray() });
                            }
                            else
                            {
                                if (log != null)
                                {
                                    log.WriteLine("Sending 'Pending'");
                                    log.Flush();
                                }
                                ClientServerCommunication.SendMessage(
                                    log,
                                    channel,
                                    ClientServerCommunication.Commands.Pending,
                                    new object[]
                                {
                                    (string)currentBitmap.BackingName,
                                    (int)currentBitmap.Width,
                                    (int)currentBitmap.Height,
                                    (byte[])serializedProfileStream.ToArray()
                                },
                                    extraResults);
                            }
                        }
                        if (log != null)
                        {
                            log.WriteLine("Sent");
                            log.Flush();
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                if (log != null)
                {
                    log.WriteLine("Unrecoverable exception: {0}", exception);
                    log.Flush();
                }
                if (currentBitmap != null)
                {
                    currentBitmap.Dispose();
                }
                if (!(exception is ClientServerCommunication.ChannelDisconnectedException))
                {
                    MessageBox.Show(exception.ToString());
                }
                if (log != null)
                {
                    log.WriteLine("Terminating abnormally");
                    log.Flush();
                    log.Close();
                    log = null;
                }
                return(1);
            }

#pragma warning disable CS0162 // unreachable
            if (log != null)
            {
                log.WriteLine("Terminating normally");
                log.Flush();
                log.Close();
                log = null;
            }
#pragma warning restore CS0162
            if (currentBitmap != null)
            {
                currentBitmap.Dispose();
            }
            return(0);
        }
Ejemplo n.º 22
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();
            }
        }
Ejemplo n.º 23
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();
        }
Ejemplo n.º 24
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());
        }
Ejemplo n.º 25
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();
        }