2

I would like to draw some text on a WriteableBitmap. This doesn't seem possible, but I found converting WriteableBitmap to Bitmap in C# here and this.

Here's the call (with conversion method included, too):

     // Draw dino names...
            Graphics g = Graphics.FromImage(BitmapFromWriteableBitmap(writeableBitmap));
            g.DrawString(Dinosaurs[i].PersonalName, new Font("Tahoma", 40), System.Drawing.Brushes.White, new PointF((float)Dinosaurs[i].Head.X, (float)Dinosaurs[i].Head.Y));

        } // for i

    }// DrawDinos2d

    private System.Drawing.Bitmap BitmapFromWriteableBitmap(WriteableBitmap writeBmp)
    {
        System.Drawing.Bitmap bmp;
        using (MemoryStream outStream = new MemoryStream())
        {
            BitmapEncoder enc = new BmpBitmapEncoder();
            enc.Frames.Add(BitmapFrame.Create((BitmapSource)writeBmp));
            enc.Save(outStream);
            bmp = new System.Drawing.Bitmap(outStream);
        }
        return bmp;
    }

I've checked in the debugger and g has a good values (not null) but nothing is drawing on the screen. I should also mention that the string that is being passed to DrawString is good and the X,Y of the point is good (positive integers about 1000,800). I think it's either drawing off the screen or maybe the X,Y coordinates aren't translating correctly.

Any ideas? Thanks.

Here's the XAML (if this helps):

<Window x:Class="DinosaurIsland.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Dinosaur Island" Height="600" Width="600" WindowState="Normal"  Icon="/DinosaurIsland;component/Icon1.ico" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" WindowStartupLocation="CenterOwner">
<Window.Resources>
    <ResourceDictionary>
        <DataTemplate DataType="{x:Type BitmapImage}">
            <Image Source="{Binding}" />
        </DataTemplate>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Resources.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>

<DockPanel>
    <Menu x:Name="MainMenu" DockPanel.Dock="Top">
        <MenuItem Header="_File">
            <MenuItem Header="_Open Dinosaur Island 'snapshot' file..." x:Name="OpenSnapshotFile" Click="OpenSnapshotFile_click" />
            <MenuItem Header="_Save"/>
            <MenuItem Header="_Exit" x:Name="ExitApp" Click="ExitAppClick" />
        </MenuItem>
        <MenuItem Header="_Height Map">
            <MenuItem Header="Load Height Map..." Name="LoadHeightMap" Click="LoadHeightMapClick" />
            <Separator />
            <MenuItem Header="Display Height Map" x:Name="DisplayHeightMap" Click="DisplayHeightMapClick" />
        </MenuItem>
        <MenuItem Header="Terrain">
            <MenuItem Header="Load Terrain Map..." x:Name="LoadTerrainMap" Click="LoadTerrainMap_Click" />
            <MenuItem Header="Draw Terrain..." x:Name="DrawTerrain" Click="DisplayTerrainPaintBoxClick" />
            <MenuItem Header="Save Terrain Map..." x:Name="SaveTerrainMap" Click="SaveTerrainMap_Click"/>
            <MenuItem Header="Get Terrain Data From BMP..." x:Name="TerrainFromBMP" Click="TerrainFromBMP_Click" />
            <Separator />
            <MenuItem Header="Adjust Terrain Transparency..." x:Name="AdjustTerrainTransparency"  Click="AdjustTerrainTransparency_Click"/>
            <MenuItem Header="Display Terrain Map" x:Name="DisplayTerrainMap"  Click="DisplayTerrainMap_Click"/>
        </MenuItem>

        <MenuItem Header="_Vegetation">
            <MenuItem Header="Plant Vegetation..." x:Name="PlantVegetation" Click="PlantVegetation_Click" />
            <Separator />
            <MenuItem Header="Load Vegetation Map..." x:Name="LoadVegetation" Click="LoadVegetation_Click" />
            <MenuItem Header="Save Vegetation Map..." x:Name="SaveVegetation" Click="SaveVegetation_Click" />
            <Separator />
            <MenuItem Header="Display Vegetation"  Click="DisplayVegetation_Click" />

        </MenuItem>

        <MenuItem Header="Dinosaurs">
            <MenuItem Header="Edit / Place Dinosaurs..." x:Name="EditDinosaurs" Click="EditDinosaurs_Click" />
            <Separator />
            <MenuItem Header="Load Dinosaur Map" Name="LoadDinosaurnMap" Click="LoadDinosaurs_Click"/>
            <MenuItem Header="Save Dinosaur Map" Name="SaveDinosaurMap" Click="SaveDinosaurs_Click"/>
            <Separator />
            <MenuItem Header="Terrain/Slope Effect..." Name="TerrainSlope"  Click="TerrainSlope_Click"/>
            <MenuItem Header="Probability of Smelling Dinosaur..." Name="SmellProbability"  Click="SmellProbability_Click"/>
        </MenuItem>

        <MenuItem Header="Time">
            <MenuItem Header="Start..." x:Name="AdvanceTime" Click="StartTime_Click" />
            <MenuItem Header="Stop..." x:Name="StopTime" Click="StopTime_Click" />
            <Separator />
            <MenuItem Header="Adjust Time Step..." x:Name="AdjustTimeStep"  Click="AdjustTimeStep_Click"/>
        </MenuItem>

        <MenuItem Header="Debug">
            <MenuItem Header="A* trace" Name="AStarTrace" Click="AStarTrace_Click" />
            <MenuItem Header="Show Dinosaur Goals" Name="DinoGoals" Click="DinoGoals_Click" />
            <MenuItem Header="Show Dinosaur Path" Name="DinoPath" IsChecked="False"  Click="DinoPath_Click" />
            <MenuItem Header="Show Predator Scent Path" Name="StinkPath" IsChecked="False"  Click="StinkPath_Click" />
            <MenuItem Header="Show Dinosaur Vision Angles" Name="VisionAngles" IsChecked="True"  Click="VisionAngles_Click" />
            <MenuItem Header="Show Dinosaur Axis" Name="DinoAxis" IsChecked="True"  Click="DinoAxis_Click" />
        </MenuItem>

        <MenuItem Header="Help">
            <MenuItem Header="About Dinosaur Island" Name="AboutDinosaurIsland" Click="AboutDinoIslandClick" />
        </MenuItem>
    </Menu>

    <StatusBar DockPanel.Dock="Bottom">
        <TextBlock Name="StatusBarField1">Location = X,Y</TextBlock>
        <Separator/>
        <TextBlock Name="StatusBarField2">Elevation = X</TextBlock>
        <Separator/>
        <TextBlock Name="StatusBarField3">Terrain = None</TextBlock>
        <Separator/>
        <TextBlock Name="StatusBarField4">Plants = None</TextBlock>
        <Separator/>
        <TextBlock Name="StatusBarField5">Dinosaurs = None</TextBlock>
        <Separator/>
        <TextBlock Name="StatusBarField6">Zoom</TextBlock>
        <Separator/>
        <TextBlock Name="StatusBarField7">Time 0:00</TextBlock>
        <Separator/>
        <TextBlock Name="StatusBarField8">Wind direction: 000</TextBlock>
        <Separator/>
        <TextBlock Name="StatusBarField9">Speed: 000</TextBlock>
    </StatusBar>

    <Label DockPanel.Dock="Bottom" Content="Scale = 2000 meters" Height="23" HorizontalAlignment="Center"  Name="HorizScaleDisplayText"  Width="127" />
    <Label DockPanel.Dock="Bottom" Content="└───────────────────────────────┴───────────────────────────────────┘" Height="20" HorizontalAlignment="Center"  Name="HorizScaleDisplayLine"  Width="423" />
    <Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

        <Slider Grid.Column="0" Orientation="Vertical" HorizontalAlignment="Left" Minimum="1" x:Name="slider"/>
    <ScrollViewer Name="scrollViewer" Grid.Column="1" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible" Margin="0,0,0,6">

        <Grid Name="grid" Width="400" Height="400" RenderTransformOrigin="0.5,0.5">
                <Grid.RowDefinitions>
                    <RowDefinition Height="37*" />
                    <RowDefinition Height="363*" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="297*" />
                    <ColumnDefinition Width="103*" />
                </Grid.ColumnDefinitions>
                <Grid.LayoutTransform>
                <TransformGroup>
                    <ScaleTransform x:Name="scaleTransform"/>
                </TransformGroup>
            </Grid.LayoutTransform>
            <Viewbox x:Name="viewBox" Margin="-35,-12,-22,22" Grid.ColumnSpan="2" Grid.RowSpan="2">
                    <ContentPresenter x:Name="contentPresenter" Width="350" Height="350" >
                        <ContentPresenter.Content>
                            <Image x:Name="image" Width="350" Height="350">
                                <Image.Source >
                                    <BitmapImage x:Name="HeightMapImage" UriSource="DinoIslandLogo.bmp" />
                                </Image.Source>
                            </Image>
                        </ContentPresenter.Content>
                    </ContentPresenter>
                </Viewbox>
            </Grid>
        </ScrollViewer>
    </Grid>
</DockPanel>

And this is how I display the bitmap:

this.image.Source = writeableBitmap;
Community
  • 1
  • 1
zetar
  • 1,225
  • 2
  • 20
  • 45
  • How do you check if something was drawn to the bitmap? I just wonder because you didn't add some code where you save or display the bmp you got from BtimapFromWriteableBitmap. –  Oct 17 '13 at 15:22
  • What contains your bitmap? Maybe try drawing the text to the same container that hosts the bitmap. Of course, the drawback of this is that the text does not persist in the bitmap. (That's why this is a comment and not an answer -- the drawback is too much.) – philologon Oct 17 '13 at 15:24
  • Just added the XAML code (so you can see what contains the bitmap). – zetar Oct 17 '13 at 15:29
  • I think you can do this by adding a TextBox to the Viewbox via viewBox.AddLogicalChild(aTextBox); You will also need to work with the position of each TextBox on the Viewbox. Also, be on the lookout for problems with the textboxes drawing on the viewbox behind the bitmap. Also, you probably want your textboxes' backgrounds transparent. http://msdn.microsoft.com/en-us/library/system.windows.controls.decorator.aspx – philologon Oct 17 '13 at 15:40
  • possible duplicate of [How can i write string on WriteableBitmap?](http://stackoverflow.com/questions/5425950/how-can-i-write-string-on-writeablebitmap) –  Oct 17 '13 at 16:27
  • I don't know if this involves Silverlight or not, but using the answer 'string on WriteableBitmap' throws errors: Error 1 'System.Windows.Media.Imaging.WriteableBitmap' does not contain a definition for 'Render' and no extension method 'Render' accepting a first argument of type 'System.Windows.Media.Imaging.WriteableBitmap' could be found and Error 2 'System.Windows.Media.Imaging.WriteableBitmap' does not contain a definition for 'Invalidate' and no extension method 'Invalidate' accepting a first argument of type 'System.Windows.Media.Imaging.WriteableBitmap' – zetar Oct 17 '13 at 17:08
  • Not having any luck creating this: viewBox.AddLogicalChild(atextBox); throws the error Error 1 Cannot access protected member 'System.Windows.FrameworkElement.AddLogicalChild(object)' via a qualifier of type 'System.Windows.Controls.Viewbox'; the qualifier must be of type 'DinosaurIsland.MainWindow' (or derived from it). private System.Windows.Forms.TextBox atextBox; is declared in DinosaurIland.MainWindow, too – zetar Oct 17 '13 at 17:27

1 Answers1

0

This solved the problem:

        public void DrawDinoNames()
    {
        System.Drawing.Bitmap bmp;
        bmp = BitmapFromWriteableBitmap(writeableBitmap);
        Graphics g = Graphics.FromImage(bmp);
        for (int i = 0; i < Dinosaurs.Count; i++)
        {
            g.DrawString(Dinosaurs[i].PersonalName, new Font("Tahoma", 14), System.Drawing.Brushes.White, new PointF((float)Dinosaurs[i].Head.X, (float)Dinosaurs[i].Head.Y));

        }
        this.image.Source = BitmapToImageSource(bmp, System.Drawing.Imaging.ImageFormat.Bmp);
    }
zetar
  • 1,225
  • 2
  • 20
  • 45