如何获得光滑的壁纸?

发布于 2024-12-09 14:36:01 字数 2043 浏览 0 评论 0原文

我正在尝试设置壁纸,但出现条带。我有一个大的渐变 JPG,保存在我的设备上。我从文件中读取它,对其进行缩放,使其高度与设备的高度相匹配,然后设置壁纸和壁纸提示。缩放步骤似乎是将其转换为 RGB565 格式而不是原始的 ARGB888 格式。另外,我似乎没有任何可能有助于减轻条带的抖动。

这是我的代码:

public class WallpaperSetter {

public static void setWallpaper(String url, Context context) throws IOException {
    FileCache cache = new FileCache(context);
    File f = cache.getFile(url);
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inPreferredConfig = Bitmap.Config.ARGB_8888;
    options.inDither = true;
    Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, options);

    Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();

    int targetHeight = display.getHeight() > display.getWidth() ? display.getHeight() : display.getWidth() - 10;
    int targetWidth = (int) ((float) targetHeight / (float) bmp.getHeight() * (float) bmp.getWidth());
    Bitmap resizedBitmap = resize(bmp, targetHeight, targetWidth);

    WallpaperManager manager = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
    manager.setBitmap(resizedBitmap);

    int displayHeight = display.getHeight() > display.getWidth() ? display.getHeight() : display.getWidth();
    int displayWidth = display.getHeight() > display.getWidth() ? display.getWidth() : display.getHeight();
    int height = resizedBitmap.getHeight() > displayHeight ? resizedBitmap.getHeight() : displayHeight;
    int width = resizedBitmap.getWidth() < displayWidth ? displayWidth : resizedBitmap.getWidth();
    manager.suggestDesiredDimensions(width, height);
}

private static Bitmap resize(Bitmap bitmap, int targetHeight, int targetWidth) {
    System.out.println("config start: " + bitmap.getConfig().name().toString());
    Bitmap b = Bitmap.createScaledBitmap(bitmap, targetWidth, targetHeight, false);
    System.out.println("config: " + b.getConfig().name().toString());
    return b;
}

}

我正在使用 CyanogenMod 在 SGS2 上进行开发,如果这有什么不同的话。

I'm trying to set a wallpaper but I get banding. I have a large gradient JPG which is saved on my device. I read it from file, scale it so that its height matches the height of the device then I set the wallpaper and the wallpaper hints. The scaling step seems to be converting it to a RGB565 format rather than the original ARGB888 format. Also, I dont seem to have any dither which might help aleviate the banding.

Here is my code:

public class WallpaperSetter {

public static void setWallpaper(String url, Context context) throws IOException {
    FileCache cache = new FileCache(context);
    File f = cache.getFile(url);
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inPreferredConfig = Bitmap.Config.ARGB_8888;
    options.inDither = true;
    Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, options);

    Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();

    int targetHeight = display.getHeight() > display.getWidth() ? display.getHeight() : display.getWidth() - 10;
    int targetWidth = (int) ((float) targetHeight / (float) bmp.getHeight() * (float) bmp.getWidth());
    Bitmap resizedBitmap = resize(bmp, targetHeight, targetWidth);

    WallpaperManager manager = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
    manager.setBitmap(resizedBitmap);

    int displayHeight = display.getHeight() > display.getWidth() ? display.getHeight() : display.getWidth();
    int displayWidth = display.getHeight() > display.getWidth() ? display.getWidth() : display.getHeight();
    int height = resizedBitmap.getHeight() > displayHeight ? resizedBitmap.getHeight() : displayHeight;
    int width = resizedBitmap.getWidth() < displayWidth ? displayWidth : resizedBitmap.getWidth();
    manager.suggestDesiredDimensions(width, height);
}

private static Bitmap resize(Bitmap bitmap, int targetHeight, int targetWidth) {
    System.out.println("config start: " + bitmap.getConfig().name().toString());
    Bitmap b = Bitmap.createScaledBitmap(bitmap, targetWidth, targetHeight, false);
    System.out.println("config: " + b.getConfig().name().toString());
    return b;
}

}

I'm developing on a SGS2 with CyanogenMod if that makes a difference.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

維他命╮ 2024-12-16 14:36:01

我发现向渐变图像添加一些噪声或微妙的随机性有助于减少条带,但我怀疑使用至少包含 alpha 像素(奇怪但有效)和 RGB565 格式的 .png 是正确的方法。我还发现,使用“raw”资源文件夹而不是“drawable”文件夹会阻止 Android 假设它可以在内部压缩图像。不管怎样,这是我使用的代码:

    private void generateBackgroundGraphic() {
        background = BitmapFactory.decodeResource(res, R.raw.gradient);

        //create local copy of 'background' bitmap size
        Bitmap tempB = Bitmap.createBitmap(background.getWidth(), background.getHeight(), Bitmap.Config.RGB_565);
        backgroundPaint.setDither(true);

        //wrap a canvas around 'background' bitmap
        Canvas tempC = new Canvas (tempB);
        tempC.drawBitmap(background, 0, 0, null);
        background = Bitmap.createScaledBitmap(tempB, globalCanvasSize.x, globalCanvasSize.y, false);
        tempB.recycle();
        tempB = null;
        tempC = null;
    }

我希望这对你有一些用处......Android有时会奇怪地处理图像:-/

Chris

I found that adding some noise or subtle randomness to a gradient image helps reduce banding, but I suspect using a .png containing at least a pixel of alpha (weird but works) and RGB565 format is the way to go. Also I found that using the 'raw' resources folder instead of 'drawable' folder prevented Android assuming it could compress the image internally. Here's the code I used anyway:

    private void generateBackgroundGraphic() {
        background = BitmapFactory.decodeResource(res, R.raw.gradient);

        //create local copy of 'background' bitmap size
        Bitmap tempB = Bitmap.createBitmap(background.getWidth(), background.getHeight(), Bitmap.Config.RGB_565);
        backgroundPaint.setDither(true);

        //wrap a canvas around 'background' bitmap
        Canvas tempC = new Canvas (tempB);
        tempC.drawBitmap(background, 0, 0, null);
        background = Bitmap.createScaledBitmap(tempB, globalCanvasSize.x, globalCanvasSize.y, false);
        tempB.recycle();
        tempB = null;
        tempC = null;
    }

I hope this is of some use to you... Android deals with images strangely sometimes :-/

Chris

蓝色星空 2024-12-16 14:36:01

尽管我怀疑有一种更简单的方法可以做到这一点,但我的最终代码仍然有效:

public class WallpaperSetter {

public static void setWallpaper(String url, Context context) throws IOException {
    FileCache cache = new FileCache(context);
    File f = cache.getFile(url);

    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(new FileInputStream(f), null, o);

    // Find the correct scale value. It should be the power of 2.
    int width_tmp = o.outWidth, height_tmp = o.outHeight;
    int scale = 1;

    Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
    int targetHeight = display.getHeight() > display.getWidth() ? display.getHeight() : display.getWidth() - 10;
    int targetWidth = (int) ((float) targetHeight / (float) o.outHeight * (float) o.outWidth);

    while (true) {
        if (width_tmp / 2 < targetWidth || height_tmp / 2 < targetHeight)
            break;
        width_tmp /= 2;
        height_tmp /= 2;
        scale++;
    }

    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize = scale;
    o2.inPreferredConfig = Bitmap.Config.ARGB_8888;
    o2.inDither = false;
    Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f), null, o2);

    Bitmap b565 = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.RGB_565);
    Canvas c = new Canvas(b565);
    c.drawBitmap(b, 0, 0, null);
    b = Bitmap.createScaledBitmap(b565, targetWidth, targetHeight, false);
    b565.recycle();
    b565 = null;
    c = null;

    WallpaperManager manager = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
    manager.setBitmap(b);

    int displayHeight = display.getHeight() > display.getWidth() ? display.getHeight() : display.getWidth();
    int displayWidth = display.getHeight() > display.getWidth() ? display.getWidth() : display.getHeight();
    int height = b.getHeight() > displayHeight ? b.getHeight() : displayHeight;
    int width = b.getWidth() < displayWidth ? displayWidth : b.getWidth();
    manager.suggestDesiredDimensions(width, height);
}

}

My final code which works even though I suspect there is a much simpler way to do this:

public class WallpaperSetter {

public static void setWallpaper(String url, Context context) throws IOException {
    FileCache cache = new FileCache(context);
    File f = cache.getFile(url);

    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(new FileInputStream(f), null, o);

    // Find the correct scale value. It should be the power of 2.
    int width_tmp = o.outWidth, height_tmp = o.outHeight;
    int scale = 1;

    Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
    int targetHeight = display.getHeight() > display.getWidth() ? display.getHeight() : display.getWidth() - 10;
    int targetWidth = (int) ((float) targetHeight / (float) o.outHeight * (float) o.outWidth);

    while (true) {
        if (width_tmp / 2 < targetWidth || height_tmp / 2 < targetHeight)
            break;
        width_tmp /= 2;
        height_tmp /= 2;
        scale++;
    }

    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize = scale;
    o2.inPreferredConfig = Bitmap.Config.ARGB_8888;
    o2.inDither = false;
    Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f), null, o2);

    Bitmap b565 = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.RGB_565);
    Canvas c = new Canvas(b565);
    c.drawBitmap(b, 0, 0, null);
    b = Bitmap.createScaledBitmap(b565, targetWidth, targetHeight, false);
    b565.recycle();
    b565 = null;
    c = null;

    WallpaperManager manager = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
    manager.setBitmap(b);

    int displayHeight = display.getHeight() > display.getWidth() ? display.getHeight() : display.getWidth();
    int displayWidth = display.getHeight() > display.getWidth() ? display.getWidth() : display.getHeight();
    int height = b.getHeight() > displayHeight ? b.getHeight() : displayHeight;
    int width = b.getWidth() < displayWidth ? displayWidth : b.getWidth();
    manager.suggestDesiredDimensions(width, height);
}

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文