Merge branch 'image-better'
This commit is contained in:
commit
0bb891a18b
3 changed files with 58 additions and 26 deletions
|
|
@ -457,7 +457,7 @@ pub fn renderWallpaper(output: *Output) !void {
|
||||||
}
|
}
|
||||||
// Scale our loaded image and then copy it into the Buffer's pixman.Image
|
// Scale our loaded image and then copy it into the Buffer's pixman.Image
|
||||||
const wallpaper_image = context.wallpaper_image orelse return error.MissingWallpaperImage;
|
const wallpaper_image = context.wallpaper_image orelse return error.MissingWallpaperImage;
|
||||||
const image = wallpaper_image.image;
|
const image = wallpaper_image.pix_image;
|
||||||
const image_data = image.getData();
|
const image_data = image.getData();
|
||||||
const image_width = image.getWidth();
|
const image_width = image.getWidth();
|
||||||
const image_height = image.getHeight();
|
const image_height = image.getHeight();
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,15 @@
|
||||||
|
|
||||||
const WallpaperImage = @This();
|
const WallpaperImage = @This();
|
||||||
|
|
||||||
image: *pixman.Image,
|
// This is used as the backing store for the pixman image
|
||||||
pixels: std.ArrayList(u32),
|
// It's the actual image (png, jpeg, etc.) decoded into pixels.
|
||||||
|
zigimg_image: zigimg.Image,
|
||||||
|
// Only used on big-endian; holds manually converted ARGB pixel data.
|
||||||
|
// On BE: std.ArrayList(u32), on LE: void
|
||||||
|
argb_pixels: if (native_endian == .big) std.ArrayList(u32) else void = if (native_endian == .big) .empty else {},
|
||||||
|
|
||||||
|
// This is the actual scaled, transformed, and rendered image
|
||||||
|
pix_image: *pixman.Image,
|
||||||
|
|
||||||
// TODO: Make image_path nullable, if null, do a single color with a single_pixel_buffer instead(?)
|
// TODO: Make image_path nullable, if null, do a single color with a single_pixel_buffer instead(?)
|
||||||
pub fn create(image_path: []const u8) !*WallpaperImage {
|
pub fn create(image_path: []const u8) !*WallpaperImage {
|
||||||
|
|
@ -13,44 +20,69 @@ pub fn create(image_path: []const u8) !*WallpaperImage {
|
||||||
errdefer utils.gpa.destroy(wallpaper_image);
|
errdefer utils.gpa.destroy(wallpaper_image);
|
||||||
|
|
||||||
var read_buf: [zigimg.io.DEFAULT_BUFFER_SIZE]u8 = undefined;
|
var read_buf: [zigimg.io.DEFAULT_BUFFER_SIZE]u8 = undefined;
|
||||||
var image = try zigimg.Image.fromFilePath(utils.gpa, image_path, &read_buf);
|
wallpaper_image.zigimg_image = try zigimg.Image.fromFilePath(utils.gpa, image_path, &read_buf);
|
||||||
defer image.deinit(utils.gpa);
|
errdefer wallpaper_image.zigimg_image.deinit(utils.gpa);
|
||||||
|
|
||||||
// We don't want to deal with all the possible formats,
|
// We don't want to deal with all the possible formats,
|
||||||
// so let's just convert to one we can use with pixman.
|
// so let's just convert to one we can use with pixman.
|
||||||
if (image.pixelFormat() != .rgba32) {
|
if (wallpaper_image.zigimg_image.pixelFormat() != .rgba32) {
|
||||||
try image.convert(utils.gpa, .rgba32);
|
try wallpaper_image.zigimg_image.convert(utils.gpa, .rgba32);
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("image loaded ({}x{})", .{ image.width, image.height });
|
log.debug("image loaded ({}x{})", .{ wallpaper_image.zigimg_image.width, wallpaper_image.zigimg_image.height });
|
||||||
|
|
||||||
const pixels = image.pixels.rgba32;
|
const pixels = wallpaper_image.zigimg_image.pixels.rgba32;
|
||||||
// We have to manually convert to argb --
|
const width: c_int = @intCast(wallpaper_image.zigimg_image.width);
|
||||||
// It's only guaranteed that Wayland compositors will have xrgb and argb support but zigimg doesn't have either of those.
|
const height: c_int = @intCast(wallpaper_image.zigimg_image.height);
|
||||||
wallpaper_image.pixels = try std.ArrayList(u32).initCapacity(utils.gpa, pixels.len);
|
const stride: c_int = @intCast(wallpaper_image.zigimg_image.width * wallpaper_image.zigimg_image.pixelFormat().pixelStride());
|
||||||
errdefer wallpaper_image.pixels.deinit(utils.gpa);
|
|
||||||
for (0..pixels.len) |i| {
|
// zigimg's Rgba32 is an extern struct {r, g, b, a}, which actually matches pixman's a8b8g8r8
|
||||||
const a: u32 = @intCast(pixels[i].a);
|
// (u32 with R at bits 0-7, A at bits 24-31) on little endian machines. That means we can actually
|
||||||
const r: u32 = @intCast(pixels[i].r);
|
// use zigimg's pixel data directly. On big-endian we keep the manual conversion I used to use.
|
||||||
const g: u32 = @intCast(pixels[i].g);
|
switch (native_endian) {
|
||||||
const b: u32 = @intCast(pixels[i].b);
|
.little => {
|
||||||
const new_val: u32 = (a << 24) + (r << 16) + (g << 8) + b;
|
wallpaper_image.pix_image = pixman.Image.createBits(
|
||||||
wallpaper_image.pixels.appendAssumeCapacity(new_val);
|
.a8b8g8r8,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
@ptrCast(@alignCast(pixels.ptr)),
|
||||||
|
stride,
|
||||||
|
) orelse return error.FailedToCreatePixmanImage;
|
||||||
|
},
|
||||||
|
.big => {
|
||||||
|
wallpaper_image.argb_pixels = try std.ArrayList(u32).initCapacity(utils.gpa, pixels.len);
|
||||||
|
errdefer wallpaper_image.argb_pixels.deinit(utils.gpa);
|
||||||
|
for (pixels) |px| {
|
||||||
|
const a: u32 = px.a;
|
||||||
|
const r: u32 = px.r;
|
||||||
|
const g: u32 = px.g;
|
||||||
|
const b: u32 = px.b;
|
||||||
|
wallpaper_image.argb_pixels.appendAssumeCapacity((a << 24) | (r << 16) | (g << 8) | b);
|
||||||
|
}
|
||||||
|
wallpaper_image.pix_image = pixman.Image.createBits(
|
||||||
|
.a8r8g8b8,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
@ptrCast(@alignCast(wallpaper_image.argb_pixels.items.ptr)),
|
||||||
|
stride,
|
||||||
|
) orelse return error.FailedToCreatePixmanImage;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
wallpaper_image.image = pixman.Image.createBits(.a8r8g8b8, @intCast(image.width), @intCast(image.height), @ptrCast(@alignCast(wallpaper_image.pixels.items.ptr)), @intCast(image.width * image.pixelFormat().pixelStride())) orelse return error.FailedToCreatePixmanImage;
|
|
||||||
|
|
||||||
return wallpaper_image;
|
return wallpaper_image;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(wallpaper_image: *WallpaperImage) void {
|
pub fn destroy(wallpaper_image: *WallpaperImage) void {
|
||||||
_ = wallpaper_image.image.unref();
|
_ = wallpaper_image.pix_image.unref();
|
||||||
wallpaper_image.pixels.deinit(utils.gpa);
|
if (native_endian == .big) wallpaper_image.argb_pixels.deinit(utils.gpa);
|
||||||
|
wallpaper_image.zigimg_image.deinit(utils.gpa);
|
||||||
|
|
||||||
utils.gpa.destroy(wallpaper_image);
|
utils.gpa.destroy(wallpaper_image);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
const native_endian = builtin.cpu.arch.endian();
|
||||||
|
|
||||||
const pixman = @import("pixman");
|
const pixman = @import("pixman");
|
||||||
const zigimg = @import("zigimg");
|
const zigimg = @import("zigimg");
|
||||||
|
|
|
||||||
|
|
@ -155,9 +155,9 @@ pub fn tokenizeToOwnedSlices(input: []const u8, delimiter: u8) ![][]const u8 {
|
||||||
var it = std.mem.tokenizeScalar(u8, input, delimiter);
|
var it = std.mem.tokenizeScalar(u8, input, delimiter);
|
||||||
while (it.next()) |part| {
|
while (it.next()) |part| {
|
||||||
const duped = try gpa.dupe(u8, part);
|
const duped = try gpa.dupe(u8, part);
|
||||||
try list.append(utils.gpa, duped);
|
try list.append(gpa, duped);
|
||||||
}
|
}
|
||||||
return list.toOwnedSlice(utils.gpa);
|
return list.toOwnedSlice(gpa);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stripQuotes(s: []const u8) []const u8 {
|
pub fn stripQuotes(s: []const u8) []const u8 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue