Asked  9 Months ago    Answers:  5   Viewed   182 times

If I add a DropShadowEffect to an parent element the text of the child elements are blurred. Why?

<Grid>
    <Grid.Effect>
        <DropShadowEffect />
    </Grid.Effect>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition />
    </Grid.RowDefinitions>
    <TextBlock Background="White">Test</TextBlock>
</Grid>

Update:

with shadow

without shadow

 Answers

3

The reason why the text is blurred is because Effects cause the elements and all sub-elements to be rendered into a Bitmap first. This means that sub-pixel rendering (ClearType) cannot take place and therefore the text appears lower-quality.

You can work around this by applying the effect to only parts of your visual tree. The parts that don't contain the text.

In your case you probably want something like this:

<Grid>
    <Border>
        <Border.Effect>
            <DropShadowEffect />
        </Border.Effect>
    </Border>
    <TextBlock Background="White">Test</TextBlock>
</Grid>
Saturday, September 11, 2021
 
4

ObservableCollection<T> is defined in the System assembly, so your namespace should read:

xmlns:coll="clr-namespace:System.Collections.ObjectModel;assembly=System"

You can find that information in MSDN at the top where it says:

Namespace: System.Collections.ObjectModel
Assembly: System (in System.dll)
XMLNS for XAML: Not mapped to an xmlns.

Note that the assembly has changed between v3.5 and v4.0. In v3.5 it was defined in the WindowsBase assembly. However, this was a drawback since you often would like to use the class without any WPF assemblies referenced. So maybe that is why they changed it.

Furthermore, you should also check this blog post, which says that the new XAML features are not completely available in VS yet!

Friday, July 30, 2021
 
5

I believe a Viewbox will do what you want. It has a single child which is always given its desired size, and it applies a ScaleTransform to the child so that it fits inside the Viewbox. By default it will apply a uniform stretch, but you can change this by setting the Stretch property.

Something like this:

<ItemsControl ItemsSource="{Binding myUIrelatedDataList}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Viewbox Width="160" Height="80">
                <my:DynamicUIPresenter />
            </Viewbox>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
Saturday, August 7, 2021
 
5

Updated code (now much faster, requires use of UNSAFE keyword)

static void Main(string[] args)
{
    Bitmap bitmap = new Bitmap("C:\Users\erik\test.png");
    bitmap = Blur(bitmap, 10);
    bitmap.Save("C:\Users\erik\test2.png");
}

private static Bitmap Blur(Bitmap image, Int32 blurSize)
{
    return Blur(image, new Rectangle(0, 0, image.Width, image.Height), blurSize);
}

private unsafe static Bitmap Blur(Bitmap image, Rectangle rectangle, Int32 blurSize)
{
    Bitmap blurred = new Bitmap(image.Width, image.Height);

    // make an exact copy of the bitmap provided
    using (Graphics graphics = Graphics.FromImage(blurred))
        graphics.DrawImage(image, new Rectangle(0, 0, image.Width, image.Height),
            new Rectangle(0, 0, image.Width, image.Height), GraphicsUnit.Pixel);

    // Lock the bitmap's bits
    BitmapData blurredData = blurred.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, blurred.PixelFormat);

    // Get bits per pixel for current PixelFormat
    int bitsPerPixel = Image.GetPixelFormatSize(blurred.PixelFormat);

    // Get pointer to first line
    byte* scan0 = (byte*)blurredData.Scan0.ToPointer();

    // look at every pixel in the blur rectangle
    for (int xx = rectangle.X; xx < rectangle.X + rectangle.Width; xx++)
    {
        for (int yy = rectangle.Y; yy < rectangle.Y + rectangle.Height; yy++)
        {
            int avgR = 0, avgG = 0, avgB = 0;
            int blurPixelCount = 0;

            // average the color of the red, green and blue for each pixel in the
            // blur size while making sure you don't go outside the image bounds
            for (int x = xx; (x < xx + blurSize && x < image.Width); x++)
            {
                for (int y = yy; (y < yy + blurSize && y < image.Height); y++)
                {
                    // Get pointer to RGB
                    byte* data = scan0 + y * blurredData.Stride + x * bitsPerPixel / 8;

                    avgB += data[0]; // Blue
                    avgG += data[1]; // Green
                    avgR += data[2]; // Red

                    blurPixelCount++;
                }
            }

            avgR = avgR / blurPixelCount;
            avgG = avgG / blurPixelCount;
            avgB = avgB / blurPixelCount;

            // now that we know the average for the blur size, set each pixel to that color
            for (int x = xx; x < xx + blurSize && x < image.Width && x < rectangle.Width; x++)
            {
                for (int y = yy; y < yy + blurSize && y < image.Height && y < rectangle.Height; y++)
                {
                    // Get pointer to RGB
                    byte* data = scan0 + y * blurredData.Stride + x * bitsPerPixel / 8;

                    // Change values
                    data[0] = (byte)avgB;
                    data[1] = (byte)avgG;
                    data[2] = (byte)avgR;
                }
            }
        }
    }

    // Unlock the bits
    blurred.UnlockBits(blurredData);

    return blurred;
}

Took 2.356 seconds to process 256x256 image with blur value 10.

Original Code (from Github - slightly altered)

static void Main(string[] args)
{
    Bitmap bitmap = new Bitmap("C:\Users\erik\test.png");

    bitmap = Blur(bitmap, 10);

    bitmap.Save("C:\Users\erik\test2.png");
}

private static Bitmap Blur(Bitmap image, Int32 blurSize)
{
    return Blur(image, new Rectangle(0, 0, image.Width, image.Height), blurSize);
}

private static Bitmap Blur(Bitmap image, Rectangle rectangle, Int32 blurSize)
{
    Bitmap blurred = new Bitmap(image.Width, image.Height);

    // make an exact copy of the bitmap provided
    using (Graphics graphics = Graphics.FromImage(blurred))
        graphics.DrawImage(image, new Rectangle(0, 0, image.Width, image.Height),
            new Rectangle(0, 0, image.Width, image.Height), GraphicsUnit.Pixel);

    // look at every pixel in the blur rectangle
    for (int xx = rectangle.X; xx < rectangle.X + rectangle.Width; xx++)
    {
        for (int yy = rectangle.Y; yy < rectangle.Y + rectangle.Height; yy++)
        {
            int avgR = 0, avgG = 0, avgB = 0;
            int blurPixelCount = 0;

            // average the color of the red, green and blue for each pixel in the
            // blur size while making sure you don't go outside the image bounds
            for (int x = xx; (x < xx + blurSize && x < image.Width); x++)
            {
                for (int y = yy; (y < yy + blurSize && y < image.Height); y++)
                {
                    Color pixel = blurred.GetPixel(x, y);

                    avgR += pixel.R;
                    avgG += pixel.G;
                    avgB += pixel.B;

                    blurPixelCount++;
                }
            }

            avgR = avgR / blurPixelCount;
            avgG = avgG / blurPixelCount;
            avgB = avgB / blurPixelCount;

            // now that we know the average for the blur size, set each pixel to that color
            for (int x = xx; x < xx + blurSize && x < image.Width && x < rectangle.Width; x++)
                for (int y = yy; y < yy + blurSize && y < image.Height && y < rectangle.Height; y++)
                    blurred.SetPixel(x, y, Color.FromArgb(avgR, avgG, avgB));
        }
    }

    return blurred;
}

Took 7.594 seconds to process 256x256 image with blur value 10.

Orignal Image

Blurred Image (blur level 10)

Image from: https://www.pexels.com/search/landscape/

Monday, August 16, 2021
 
jezrael
 
5

Yes, this is possible, but not with the class template parameter directly. boost::enable_if can only be used with a template parameter on the method itself. So, with a little typedef usage:

template<typename T, typename BASE>
class MyClass  : public BASE
{
public:
  typedef Utility2<BASE> util;

  typename T& operator() (const Utility1<BASE>& foo);

  template<typename U>
  typename boost::enable_if<boost::is_same<util, U>, T>::type const &
  operator() (const U& foo) const;
};

This works, because Utility2 can only be created from a certain BASE type. So if the BASE type is something else, the const version of operator() won't exist.

So, it's a very minor thing. It doesn't gain me much. But it was neat to do.

Monday, August 23, 2021
 
sohum
 
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :