我目前正在使用 Cairo 进行 8 位渲染,并在 After Effects 插件中使用以下代码,使用 CAIRO_FORMAT_ARGB32 图像表面效果很好:
// Write pixel 8-bit
PF_Pixel* sampleIntegral8(PF_EffectWorld& def, int x, int y) {
return (PF_Pixel*)((char*)def.data +
(y * def.rowbytes) +
(x * sizeof(PF_Pixel)));
}
PF_Err cairoCopy8(void* refcon, A_long threadInd, A_long itemNum,
A_long iterTotal)
{
cairoRefcon* data = (cairoRefcon*)refcon;
int i = itemNum;
PF_Err err = PF_Err_NONE;
uint32_t* rowP;
PF_Pixel8* worldPtr = sampleIntegral8(data->output, 0, i);
rowP = (uint32_t*)(data->data + i * data->stride);
for (int x = 0; x < data->output.width; x++) {
worldPtr->alpha = rowP[x] >> 24;
if (worldPtr->alpha)
{
float rf = A_u_char(rowP[x] >> 16) / (float)worldPtr->alpha;
float gf = A_u_char(rowP[x] >> 8) / (float)worldPtr->alpha;
float bf = A_u_char(rowP[x] >> 0) / (float)worldPtr->alpha;
worldPtr->red = A_u_char(rf * PF_MAX_CHAN8);
worldPtr->green = A_u_char(gf * PF_MAX_CHAN8);
worldPtr->blue = A_u_char(bf * PF_MAX_CHAN8);
}
worldPtr++;
}
return err;
}
但是,我希望能够使用 CAIRO_FORMAT_RGBA128F 图像表面,它使用 4 个浮点,因此允许更灵活的 32 位颜色。这里有关于此的信息:https://cairographics.org/manual/cairo-Image-Surfaces.html#cairo-format-t
问题是我尝试以多种不同的方式调整 8 位代码,但没有成功使用浮点数,不幸的是,我找不到任何有关如何使用此浮点图像表面的示例。我所做的任何尝试都会发生很多崩溃,我相信这部分是由于代码需要从根本上进行调整,但同样,没有任何现有的示例,这很难做到。
任何人都可以帮助使用 CAIRO_FORMAT_RGBA128F 图像表面的浮点数来调整下面的代码吗?
谢谢你。
我找不到任何有关如何使用此浮点图像表面的示例
我尝试了一下,结果似乎立即见效。该程序在图像表面随机绘制一些内容,然后打印其内容。一次通过 ARGB32 表面,一次通过 RGBA128F。
#include <cairo.h>
#include <stdio.h>
#include <stdint.h>
//! Draw something to the surface
static void fill_it(cairo_surface_t *s) {
cairo_t *cr = cairo_create(s);
cairo_set_source_rgb(cr, 1, 0.75, 0);
cairo_paint(cr);
cairo_rectangle(cr, 0, 0, 1, 1);
cairo_set_source_rgb(cr, 0.5, 0, 0);
cairo_fill(cr);
cairo_rectangle(cr, 1, 0, 1, 1);
cairo_set_source_rgb(cr, 0.3333, 1, 0);
cairo_fill(cr);
cairo_rectangle(cr, 0, 1, 1, 1);
cairo_set_source_rgb(cr, 0, 0.1234, 1);
cairo_fill(cr);
cairo_destroy(cr);
}
static float uint8_to_float(uint8_t value) {
return value * 1.0 / 255.0;
}
static void print_it_argb32(cairo_surface_t *s) {
int width = cairo_image_surface_get_width(s);
int height = cairo_image_surface_get_width(s);
int stride = cairo_image_surface_get_stride(s);
unsigned char* data = cairo_image_surface_get_data(s);
for (int row = 0; row < height; row++) {
for (int column = 0; column < width; column++) {
uint32_t pixel = ((uint32_t*) data)[column];
printf("Pixel r=%g g=%g b=%g a=%g\n", uint8_to_float(pixel >> 16), uint8_to_float(pixel >> 8), uint8_to_float(pixel), uint8_to_float(pixel >> 24));
}
data += stride;
}
}
static void print_it_rgba128(cairo_surface_t *s) {
int width = cairo_image_surface_get_width(s);
int height = cairo_image_surface_get_width(s);
int stride = cairo_image_surface_get_stride(s);
unsigned char* data = cairo_image_surface_get_data(s);
for (int row = 0; row < height; row++) {
for (int column = 0; column < width; column++) {
float* pixels = ((float*) data) + column * 4;
printf("Pixel r=%g g=%g b=%g a=%g\n", pixels[0], pixels[1], pixels[2], pixels[3]);
}
data += stride;
}
}
static void print_it(cairo_surface_t *s) {
switch (cairo_image_surface_get_format(s)) {
case CAIRO_FORMAT_ARGB32:
return print_it_argb32(s);
case CAIRO_FORMAT_RGBA128F:
return print_it_rgba128(s);
default:
puts("Unsupported format");
}
}
static void try_it(cairo_format_t format) {
cairo_surface_t *s = cairo_image_surface_create(format, 2, 2);
fill_it(s);
print_it(s);
cairo_surface_destroy(s);
puts("");
}
int main() {
try_it(CAIRO_FORMAT_ARGB32);
try_it(CAIRO_FORMAT_RGBA128F);
}
任何人都可以帮助使用 CAIRO_FORMAT_RGBA128F 图像表面的浮点数来调整下面的代码吗?
嗯...随机猜测是:
// Write pixel 8-bit
PF_Pixel* sampleIntegral8(PF_EffectWorld& def, int x, int y) {
return (PF_Pixel*)((char*)def.data +
(y * def.rowbytes) +
(x * sizeof(PF_Pixel)));
}
PF_Err cairoCopy8(void* refcon, A_long threadInd, A_long itemNum,
A_long iterTotal)
{
cairoRefcon* data = (cairoRefcon*)refcon;
int i = itemNum;
PF_Err err = PF_Err_NONE;
float* rowP;
PF_Pixel8* worldPtr = sampleIntegral8(data->output, 0, i);
rowP = (float*)(data->data + i * data->stride);
for (int x = 0; x < data->output.width; x++) {
float red = rowP[4*x + 0];
float green = rowP[4*x + 1];
float blue = rowP[4*x + 2];
float alpha = rowP[4*x + 3];
worldPtr->alpha = alpha * 255.0;
if (worldPtr->alpha)
{
float rf = red / alpha;
float gf = green / alpha;
float bf = blue / alpha;
worldPtr->red = A_u_char(rf * PF_MAX_CHAN8);
worldPtr->green = A_u_char(gf * PF_MAX_CHAN8);
worldPtr->blue = A_u_char(bf * PF_MAX_CHAN8);
}
worldPtr++;
}
return err;
}
但请注意,我不知道这些行的一半应该是什么。
我添加了 alpha 乘以 255,因为我认为这是
PF_Pixel8
所期望的。至少之前似乎已经获得了该范围内的值。
颜色分量似乎不需要这样的乘法,因为除以 alpha 会自动校正不同的值范围。