只是想跟你检查一件事。我正在使用WriteableBitmap创建一个我作为实时图块的图像。工作正常,但我注意到文本边缘有阴影。使文本看起来有点脏或乱。
看看下面的图片。左侧部分来自使用WriteableBitmap创建的实时磁贴,右侧部分是Windows Phone标准磁贴(Internet Explorer磁贴)。看到区别?
我能做些什么吗?你以前注意到了吗?
编辑: 嗯,我想我正在看错了功能。我认为可能是导致这种情况的wbmp.SaveJpeg?我将文本和背景图像放入网格,然后使用wbmp.SaveJpeg保存。这是什么原因?任何解决方法?
string sIsoStorePath = @"\Shared\ShellContent\tile.png";
using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
//ensure directory exists
String sDirectory = System.IO.Path.GetDirectoryName(sIsoStorePath);
if (!appStorage.DirectoryExists(sDirectory))
{
appStorage.CreateDirectory(sDirectory);
}
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(sIsoStorePath, System.IO.FileMode.Create, appStorage))
{
wbmp.SaveJpeg(stream, 173, 173, 0, 100);
}
}
答案 0 :(得分:1)
WritableBitmap.Pixels的文档指出“Silverlight WriteableBitmap使用的格式是ARGB32(预乘RGB)”。也许那时的实时图块需要非预乘的像素格式。
我在Silverlight中找不到任何API来更改格式,但我认为本文中的方法可能就是您所需要的:
编辑:
根据我的测试,似乎问题出在JPEG压缩工件上,因为即使你用.png扩展名命名,SaveJpeg也会以JPEG格式保存文件。
下面的示例代码对MakeNonPremultiplied(bitmap.Pixels)进行了注释调用,该调用显示了如果使用某个库将其保存为可以使用的文件格式,如何调用过滤器将像素格式修改为非预乘透明度并期望非预乘格式。
using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Windows;
using System.Windows.Media.Imaging;
using Microsoft.Phone.Shell;
namespace LiveTilePlayground
{
public partial class LiveTileGenerator
{
/// <summary>
/// Renders a FrameworkElement (control) to a bitmap
/// the size of a live tile or a custom sized square.
/// </summary>
/// <param name="element">The element.</param>
/// <param name="size">
/// The size of the bitmap (in each dimension).
/// </param>
/// <returns></returns>
public static WriteableBitmap RenderBitmap(
FrameworkElement element,
double size = 173.0)
{
element.Measure(new Size(size, size));
element.Arrange(new Rect(0, 0, size, size));
return new WriteableBitmap(element, null);
}
/// <summary>
/// Updates the primary tile with specific title and background image.
/// </summary>
/// <param name="title">The title.</param>
/// <param name="backgroundImage">The background image.</param>
public static void UpdatePrimaryTile(string title, Uri backgroundImage)
{
ShellTile primaryTile = ShellTile.ActiveTiles.First();
StandardTileData newTileData = new StandardTileData
{ Title = title, BackgroundImage = backgroundImage };
primaryTile.Update(newTileData);
}
/// <summary>
/// Saves the tile bitmap with a given file name and returns the URI.
/// </summary>
/// <param name="bitmap">The bitmap.</param>
/// <param name="fileName">Name of the file.</param>
/// <returns></returns>
public static Uri SaveTileBitmap(
WriteableBitmap bitmap, string fileName)
{
//MakeNonPremultiplied(bitmap.Pixels);
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (!store.DirectoryExists(@"Shared\ShellContent"))
{
store.CreateDirectory(@"Shared\ShellContent");
}
using (
var stream = store.OpenFile(
@"Shared\ShellContent\" + fileName,
FileMode.OpenOrCreate))
{
bitmap.SaveJpeg(stream, 173, 173, 0, 100);
}
}
return new Uri(
"isostore:/Shared/ShellContent/" + fileName, UriKind.Absolute);
}
/// <summary>
/// Transforms bitmap pixels to a non-alpha premultiplied format.
/// </summary>
/// <param name="bitmapPixels">The bitmap pixels.</param>
public static void MakeNonPremultiplied(int[] bitmapPixels)
{
int count = bitmapPixels.Length;
// Iterate through all pixels and
// make each semi-transparent pixel non-premultiplied
for (int i = 0; i < count; i++)
{
uint pixel = unchecked((uint)bitmapPixels[i]);
// Decompose ARGB structure from the uint into separate channels
// Shift by 3 bytes to get Alpha
double a = pixel >> 24;
// If alpha is 255 (solid color) or 0 (completely transparent) -
// skip this pixel.
if ((a == 255) || (a == 0))
{
continue;
}
// Shift 2 bytes and filter out the Alpha byte to get Red
double r = (pixel >> 16) & 255;
// Shift 1 bytes and filter out Alpha and Red bytes to get Green
double g = (pixel >> 8) & 255;
// Filter out Alpha, Red and Green bytes to get Blue
double b = (pixel) & 255;
// Divide by normalized Alpha to get non-premultiplied values
double factor = 256 / a;
uint newR = (uint)Math.Round(r * factor);
uint newG = (uint)Math.Round(g * factor);
uint newB = (uint)Math.Round(b * factor);
// Compose back to ARGB uint
bitmapPixels[i] =
unchecked((int)(
(pixel & 0xFF000000) |
(newR << 16) |
(newG << 8) |
newB));
}
}
}
}
答案 1 :(得分:0)
我有完全相同的问题,但对我来说简单的答案是检查使用的透明PNG。它被设置为使用16位颜色深度。将PNG更改为8位颜色深度解决了我的问题。