locked
Save image on disk RRS feed

  • Question

  • Save  an Image to disk after rotating it.

    The image is rotated on the display, but with the bellow code , the physical image is not rotated.

      BitmapImage logo = new BitmapImage(); 
    
      logo.BeginInit(); 
    
      logo.CacheOption = BitmapCacheOption.OnLoad;
    
      logo.UriSource = new Uri(path); 
    
      logo.EndInit(); 
    
      image.Source = logo; 
    
      BitmapSource img = (BitmapSource)(image.Source); 
    
      //rotate tif and save 
    
      CachedBitmap cache = new CachedBitmap(img, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); 
    
      TransformedBitmap tb = new TransformedBitmap(cache, new RotateTransform(90)); 
    
      TiffBitmapEncoder encoder = new TiffBitmapEncoder(); 
    
      encoder.Frames.Add(BitmapFrame.Create(tb));
    
      //cache 
    
      using (FileStream file = File.OpenWrite(path)) 
    
      {  
    
       encoder.Save(file); 
    
      }
    
    

    at file.open the following error occurs:

    The process cannot access the file 'D:\bin\Debug\images\201007231002001.tif' because it is being used by another process.

    Tuesday, November 2, 2010 9:21 AM

Answers

  • Hi Dot Net Avatar,

    The corresponding image file is locked at the moment you create the BitmapFrame in Photo class. So you cannot write to that file before it is released.

    You can cache this image to solve this issue. For example, try changing the constructor of Photo class to the following:

     public Photo(string path)
     {
      _path = path;
      _source = new Uri(path);
      _image = BitmapFrame.Create(_source, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
     }
    
    

    You can also check out http://stackoverflow.com/questions/767250/using-bitmapframe-for-metadata-without-locking-the-file for other solutions.

    Hope this helps.

    Best regards,

    Min

    This response contains a reference to a third party World Wide Web site. Microsoft is providing this information as a convenience to you. Microsoft does not control these sites and has not tested any software or information found on these sites; therefore, Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information found there. There are inherent dangers in the use of any software found on the Internet, and Microsoft cautions you to make sure that you completely understand the risk before retrieving any software from the Internet.


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    • Marked as answer by Dot Net Avatar Tuesday, November 9, 2010 5:45 AM
    • Edited by Min Zhu Tuesday, November 9, 2010 5:58 AM
    Tuesday, November 9, 2010 5:12 AM

All replies

  • You haven't closed the filestream.

     

    Tuesday, November 2, 2010 11:22 AM
  • error occurs when i try to open the file for writing closing the filestream doest help.

    	   try
            {
               FileStream file = File.OpenWrite(path);
              encoder.Save(file);
              file.Close();
            }
            catch (IOException ex)
            {
              MessageBox.Show(ex.Message);
            }

     

    The process cannot access the file 'D:\Drive D\Project\RnD\WPF ListBox DataBinding\DataBindingListBox\DataBindingListBox\bin\Debug\images\201007231002001.000' because it is being used by another process.

    Wednesday, November 3, 2010 5:10 AM
  • So what's got hold of it then?

    You must be using it somewhere on a page or piece of code.

    • Proposed as answer by Min Zhu Thursday, November 4, 2010 5:59 AM
    • Marked as answer by Min Zhu Monday, November 8, 2010 1:37 AM
    • Unmarked as answer by Dot Net Avatar Monday, November 8, 2010 11:24 AM
    Wednesday, November 3, 2010 8:18 AM
  • Hi Dot Net Avatar,

    I am marking this issue as "Answered". If you have any new findings or concerns about this issue, please feel free to let me know.

    Thank you and have a nice day!

    Best regards,

    Min


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    Monday, November 8, 2010 1:38 AM
  • using System;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.Windows.Media.Imaging;
    
    namespace DataBindingListBox
    {
      /// <summary>
      /// This class describes a single photo - its location, the image and 
      /// the metadata extracted from the image.
      /// </summary>
      public class Photo
      {
        public Photo(string path)
        {
          _path = path;
          _source = new Uri(path);
          _image = BitmapFrame.Create(_source);
        }
    
        public override string ToString()
        {
          return _source.ToString();
        }
    
        private string _path;
    
        private Uri _source;
        public string Source { get { return _path; } }
    
        private BitmapFrame _image;
        public BitmapFrame Image { get { return _image; } set { _image = value; } }
    
    
      }
    
      /// <summary>
      /// This class represents a collection of photos in a directory.
      /// </summary>
      public class PhotoCollection : ObservableCollection<Photo>
      {
        public PhotoCollection() { }
    
        public PhotoCollection(string path) : this(new DirectoryInfo(path)) { }
    
        public PhotoCollection(DirectoryInfo directory)
        {
          _directory = directory;
          Update();
        }
    
        public string Path
        {
          set
          {
            _directory = new DirectoryInfo(value);
            Update();
          }
          get { return _directory.FullName; }
        }
    
        public DirectoryInfo Directory
        {
          set
          {
            _directory = value;
            Update();
          }
          get { return _directory; }
        }
        private void Update()
        {
          this.Clear();
          try
          {
            foreach (FileInfo f in _directory.GetFiles("*.*"))
                    
                Add(new Photo(f.FullName));
              
    
          }
          catch (DirectoryNotFoundException)
          {
            System.Windows.MessageBox.Show("No Such Directory");
          }
        }
    
        DirectoryInfo _directory;
      }
    
    }
    
    Then Bind the images to a list box using
     private void Window_Loaded(object sender, RoutedEventArgs e)
        {
          
          this.Photos = (PhotoCollection)(Application.Current.Resources["Photos"] as ObjectDataProvider).Data;
          this.Photos.Path = Environment.CurrentDirectory + "\\images";
    }
    
    The Images are displayed as Thumbnails on the screen.(Listbox items)
    <Window x:Class="DataBindingListBox.Window1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:MySample="clr-namespace:DataBindingListBox" 
      Title="Window1" Height="775" Width="1285" Loaded="Window_Loaded" WindowStartupLocation="CenterScreen" WindowStyle="SingleBorderWindow">
    
      <Window.Resources>
        <DataTemplate DataType="{x:Type MySample:Photo}" >      
          <Border Name="ListItemBorder" Background="White" BorderBrush="#22000000" BorderThickness="4" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
            <Grid Name="ListItemGrid" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="2" ShowGridLines="True" Background="Transparent">
              <TextBlock ></TextBlock>
              <!-- Drop Shadow -->
              <Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="4" Background="Brown">
                <Border.RenderTransform>
                  <TranslateTransform X="2" Y="2" />
                </Border.RenderTransform>
                <Border.BitmapEffect>
                  <BlurBitmapEffect Radius="4" />
                </Border.BitmapEffect>
              </Border>
              <Border Name="ListItemBorder1" Background="White" BorderBrush="#22000000" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
              <Grid Name="ImageInfoGrid" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="2" >
                <Grid.RowDefinitions>
                  <RowDefinition Height="20"></RowDefinition>
                  <RowDefinition Height="*"></RowDefinition>
                  <RowDefinition Height="20"></RowDefinition>
                </Grid.RowDefinitions>
                <Viewbox Grid.Row="0">
                  <Label  HorizontalAlignment="Left" Content="SSPRD2010081800005.1000" ToolTip="BigExten2010081800006.1000">
                  </Label>
                </Viewbox>
                <Viewbox Grid.Row="1" Name="viewboxImage" >
                    <Image  
                      Name="ImageViewer" 
                      Source="{Binding Image}"
                    ></Image>
                
                  </Viewbox>
                <Viewbox Grid.Row="2">
                  <WrapPanel Orientation="Horizontal" >
                    <Viewbox Width="20" Height="20" >
                      <Button  Click="RotateLeft">
                        <Image Source="Images\RotateLeft.bmp" ToolTip="Rotate Left"></Image>
                      </Button>
                    </Viewbox>
                    <Viewbox Width="20" Height="20">
                      <Button Click="RotateRight">
                        <Image Source="Images\RotateRight.bmp" ToolTip="Rotate Right"></Image>
                      </Button>
                    </Viewbox>
                    <Viewbox Width="20" Height="20">
                      <Button Click= " Save" >
                        <Image Source="Images\Save.bmp" ToolTip="Save"></Image>
                      </Button>
                    </Viewbox>
                  </WrapPanel>
                </Viewbox>
              </Grid>
            </Border>
            </Grid>
          </Border>
        </DataTemplate>
        
        <Style TargetType="{x:Type ListBox}" x:Key="PhotoListBoxStyle">      
          <Setter Property="Foreground" Value="White" />
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type ListBox}" >
                <WrapPanel Margin="5" IsItemsHost="True" 
                       ItemHeight="178" 
              ItemWidth="190" />             
              </ControlTemplate>
            </Setter.Value>
          </Setter>
          
        </Style>    
        <!-- Style for an individual generic item -->
        <Style TargetType="{x:Type ListBoxItem}">
          <Setter Property="Background" Value="Transparent"/>
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type ListBoxItem}" >
                <Border Name="borderListItem" SnapsToDevicePixels="True" Background="{TemplateBinding Background}">
                  <ContentPresenter />
                </Border>
                <ControlTemplate.Triggers>
                  <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Background" Value="Blue"  />
                    <Setter Property="Background" Value="Red" />
                  </Trigger>
                </ControlTemplate.Triggers>
              </ControlTemplate>
            </Setter.Value>
          </Setter>       
        </Style>
        
        <!-- Default label style -->
        <Style TargetType="{x:Type Label}">
          <Setter Property="FontFamily" Value="Segoe UI" />
          <Setter Property="FontSize" Value="11" />
        </Style>
    <MySample:Window1 x:Key="ExposureTimeConverter" />
      </Window.Resources>
      <Grid DataContext="{Binding Source={StaticResource Photos}}" 
        Margin="10">
    
        <Grid.ColumnDefinitions>
           <ColumnDefinition Width="250" />
          <ColumnDefinition Width="*" />
         
        </Grid.ColumnDefinitions>
    
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <DockPanel Grid.Row="1" Grid.Column="0" >
          <DockPanel DockPanel.Dock="Top" >
            <ListView></ListView>
          </DockPanel>
    
          <DockPanel DockPanel.Dock="Bottom" >
            
              
              <StackPanel Orientation="Vertical" >            
                  <Button Name="btnReject" Content="Reject" >
                  </Button>  
                  <Button Name="btnUndoReject" Content="UndoReject">
                  </Button>
              </StackPanel>
            <StackPanel Orientation="Vertical" > 
              <Button Name="btnEndorse" Content="Endorse">
                  </Button>
              </StackPanel>
            
    
          </DockPanel>
        </DockPanel> 
        <GridSplitter Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Stretch" Width="45" Background="Transparent" ShowsPreview="True" Margin="0,0,0,6" Grid.Row="1" />
        <GroupBox Grid.Column="1" Grid.Row="1">
          <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
            <ListBox 
              IsSynchronizedWithCurrentItem="True"
              Name="listBox1" Margin="5"  
              Style="{StaticResource PhotoListBoxStyle}" 
              SelectionMode="Extended" 
              ItemsSource="{Binding}"          
              SelectedIndex="0" 
              MouseDoubleClick="OnPhotoClick" VerticalContentAlignment="Center">
            </ListBox>
          </ScrollViewer>
        </GroupBox>
      </Grid>
    </Window>
    
    on click of image rotate left on the thunmbnail the image rotates left.
     private void RotateLeft(object sender, RoutedEventArgs e)
        {
          Photo selectedPhoto = (Photo)listBox1.SelectedItem;
          BitmapSource img = (BitmapSource)(selectedPhoto.Image);
    
          CachedBitmap cache = new CachedBitmap(img, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
          selectedPhoto.Image = BitmapFrame.Create(new TransformedBitmap(cache, new RotateTransform(90.0)));
          listBox1.SelectedItem = (Photo)selectedPhoto;
          listBox1.Items.Refresh();
        }
    
    rotated image is refereshed on the screen.But the image is not physicaly saved to disk.
    Monday, November 8, 2010 12:48 PM
  • Let's try again.

    Is your file still bound in the page when you try and save it to the same file?

    Monday, November 8, 2010 1:21 PM
  • Yes the file is displayed as a Listbox Item (displayed like a thumbnail on the page).

    Monday, November 8, 2010 1:26 PM
  • That's your problem then.

    I've not got enough time to unravel all that code I'm afraid.

     Maybe try oneway.

     

    Monday, November 8, 2010 1:51 PM
  • Hi Dot Net Avatar,

    The corresponding image file is locked at the moment you create the BitmapFrame in Photo class. So you cannot write to that file before it is released.

    You can cache this image to solve this issue. For example, try changing the constructor of Photo class to the following:

     public Photo(string path)
     {
      _path = path;
      _source = new Uri(path);
      _image = BitmapFrame.Create(_source, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
     }
    
    

    You can also check out http://stackoverflow.com/questions/767250/using-bitmapframe-for-metadata-without-locking-the-file for other solutions.

    Hope this helps.

    Best regards,

    Min

    This response contains a reference to a third party World Wide Web site. Microsoft is providing this information as a convenience to you. Microsoft does not control these sites and has not tested any software or information found on these sites; therefore, Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information found there. There are inherent dangers in the use of any software found on the Internet, and Microsoft cautions you to make sure that you completely understand the risk before retrieving any software from the Internet.


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    • Marked as answer by Dot Net Avatar Tuesday, November 9, 2010 5:45 AM
    • Edited by Min Zhu Tuesday, November 9, 2010 5:58 AM
    Tuesday, November 9, 2010 5:12 AM
  • Hi Min

    change in Photo class constructor unlocked the file.

     "_image = BitmapFrame.Create(_source, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);"

    Thank you so much u made my day. :)

    Tuesday, November 9, 2010 5:48 AM
  • I save the image after rotating the image using the bellow code.

     

    Photo selectedPhoto = (Photo)listBox1.SelectedItem;
    TiffBitmapEncoder encoder = new TiffBitmapEncoder();
    
    string path = selectedPhoto.Source;
    BitmapSource img = (BitmapSource)(selectedPhoto.Image);
    encoder.Frames.Add(BitmapFrame.Create(img));
    
    try
    {
        FileStream file = File.OpenWrite(path);
        encoder.Save(file);
        file.Close();
    }
    catch (IOException ex)
    {
       MessageBox.Show(ex.Message);
    }
    

     The tiff image size which was originaly 200KB incresed to 6416KB. how can i compress the image or retain the original size of the image.

     

    I tried using Tiffbitmapencoder

     EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)EncoderValue.CompressionCCITT4);
          ImageCodecInfo TiffCodec = this.getEncoderInfo("image/tiff");
          if (TiffCodec == null)
            return;
    
          EncoderParameters encoderParams = new EncoderParameters(1);
          encoderParams.Param[0] = qualityParam;
          Photo selectedPhoto = (Photo)listBox1.SelectedItem;
          BitmapSource img = (BitmapSource)(selectedPhoto.Image);
          string path = selectedPhoto.Source;    
    
          FileStream fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
          System.Drawing.Bitmap bmp = new Bitmap(fs);
          bmp.Save(fs, TiffCodec, encoderParams);
          bmp.Dispose();
          fs.Close();
    

    but it is correpting the image.

    Tuesday, November 9, 2010 9:30 AM
  • You're best off with one question per thread mate.

    Once you've marked a thread as answered the chances are that people won't expect there to be a question still outstanding there.

    Plus of course when someone has a problem and searches threads for answers they may miss an answer if it's nothing to do with the original question.

    Tuesday, November 9, 2010 9:41 AM