颜色到 ARGB 转换
Color to ARGB Convert
我有一个整数颜色值,例如 -16447153。以及如何将其转换为ARGB?
在c#中,他使用了颜色函数,
Color.FromArgb(buf[buf_pos])
delphi中是否有像上面那样的功能,否则我该如何转换?
我这样试过:
procedure TJP2RenderPreview.put_region(size : _Ckdu_coords; buf : array of Integer; offX, offY : Integer);
var
x, y : Integer;
width, height : Integer;
buf_pos : Integer;
RowPtr : PRGBQuad;
begin
width:= size.__property_get_x;
height:= size.__property_get_y;
buf_pos:=0;
for y := offY to offY + height - 1 do
begin
RowPtr:= formMain.imgPreview.Bitmap.ScanLine[y];
Inc(RowPtr, offX);
for x := 0 to width - 1 do
begin
RowPtr.rgbReserved:= (buf[buf_pos] div 00000);
RowPtr.rgbRed:= ((buf[buf_pos] mod 00000) div 000);
RowPtr.rgbGreen:= ((buf[buf_pos] mod 000) div 0);
RowPtr.rgbBlue:= (buf[buf_pos] mod 0);
Inc(RowPtr);
Inc(buf_pos);
end;
end;
formMain.imgPreview.Refresh;
formMain.imgPreview.Update;
end;
但事实并非如此,似乎是灰色的:/
您似乎混淆了频道。当您说它是 ARGB 时,您将输入视为 RGBA。在任何情况下,您使用 div
和 mod
的代码都是低效的。按位移位是惯用的方式。
对于 ARGB 输入,您可以这样做:
procedure ARGBtoColorChannels(ARGB: DWORD; out A, R, G, B: Byte);
begin
A := Byte(ARGB);
R := Byte(ARGB shr 8);
G := Byte(ARGB shr 16);
B := Byte(ARGB shr 24);
end;
或者,如果您从 RGBA 开始,那么它是这样的:
procedure RGBAtoColorChannels(RGBA: DWORD; out A, R, G, B: Byte);
begin
R := Byte(RGBA);
G := Byte(RGBA shr 8);
B := Byte(RGBA shr 16);
A := Byte(RGBA shr 24);
end;
这些是小端版本,因为 Delphi 在撰写本文时仅针对小端机器。
如果您正在寻找将 ARGB 转换为 RGBA 的函数,那么您可以像这样制作:
function ARGBtoRGBA(ARGB: DWORD): DWORD;
var
A, R, G, B: Byte;
begin
ARGBtoColorChannels(ARGB, A, R, G, B);
Result := R or (G shl 8) or (B shl 16) or (A shl 24);
end;
为了完整起见,相反的是:
function RGBAtoARGB(RGBA: DWORD): DWORD;
var
A, R, G, B: Byte;
begin
RGBAtoColorChannels(RGBA, A, R, G, B);
Result := A or (R shl 8) or (G shl 16) or (B shl 24);
end;
为了让您知道该做什么,您需要了解 buf
是什么。是ARGB还是RGBA?假设它是 ARGB,考虑到你的问题的内容,这似乎很可能,你正试图复制到 RowPtr
,它似乎也是 ARGB
。在这种情况下,你可以像这样 blit 颜色:
PInteger(RowPtr)^ := buf[buf_pos];
我还强烈建议您更改 buf
参数的类型。无符号类型在这里更好,因为您可能需要执行按位运算。更重要的是,你通过堆栈复制整个数组,这是非常低效的。对于大位图,您将遭受堆栈溢出。相反,该参数应该是:
const buf: array of DWORD;
或
const buf: array of Cardinal;
使用const
意味着传递数组的引用,而不是副本。
你也可以避免使用 PRGBQuad
并声明 RowPtr
为 PCardinal
类型,比如说。
那么你可以这样赋值:
RowPtr^ := buf[buf_pos];
那时你不需要一个像素一个像素地做。您可以使用 Move
复制整个扫描线,因为这是一个简单的 blit。
for y := offY to offY + height - 1 do
begin
RowPtr := formMain.imgPreview.Bitmap.ScanLine[y];
Inc(RowPtr, offX);
Move(buf[buf_pos], RowPtr^, width*SizeOf(RowPtr^));
Inc(buf_pos, width);
end;
调用 Refresh
和 Update
似乎毫无意义。我不确定您是否需要调用任何一个,但如果需要,只需调用 Invalidate
!
我有一个整数颜色值,例如 -16447153。以及如何将其转换为ARGB?
在c#中,他使用了颜色函数,
Color.FromArgb(buf[buf_pos])
delphi中是否有像上面那样的功能,否则我该如何转换?
我这样试过:
procedure TJP2RenderPreview.put_region(size : _Ckdu_coords; buf : array of Integer; offX, offY : Integer);
var
x, y : Integer;
width, height : Integer;
buf_pos : Integer;
RowPtr : PRGBQuad;
begin
width:= size.__property_get_x;
height:= size.__property_get_y;
buf_pos:=0;
for y := offY to offY + height - 1 do
begin
RowPtr:= formMain.imgPreview.Bitmap.ScanLine[y];
Inc(RowPtr, offX);
for x := 0 to width - 1 do
begin
RowPtr.rgbReserved:= (buf[buf_pos] div 00000);
RowPtr.rgbRed:= ((buf[buf_pos] mod 00000) div 000);
RowPtr.rgbGreen:= ((buf[buf_pos] mod 000) div 0);
RowPtr.rgbBlue:= (buf[buf_pos] mod 0);
Inc(RowPtr);
Inc(buf_pos);
end;
end;
formMain.imgPreview.Refresh;
formMain.imgPreview.Update;
end;
但事实并非如此,似乎是灰色的:/
您似乎混淆了频道。当您说它是 ARGB 时,您将输入视为 RGBA。在任何情况下,您使用 div
和 mod
的代码都是低效的。按位移位是惯用的方式。
对于 ARGB 输入,您可以这样做:
procedure ARGBtoColorChannels(ARGB: DWORD; out A, R, G, B: Byte);
begin
A := Byte(ARGB);
R := Byte(ARGB shr 8);
G := Byte(ARGB shr 16);
B := Byte(ARGB shr 24);
end;
或者,如果您从 RGBA 开始,那么它是这样的:
procedure RGBAtoColorChannels(RGBA: DWORD; out A, R, G, B: Byte);
begin
R := Byte(RGBA);
G := Byte(RGBA shr 8);
B := Byte(RGBA shr 16);
A := Byte(RGBA shr 24);
end;
这些是小端版本,因为 Delphi 在撰写本文时仅针对小端机器。
如果您正在寻找将 ARGB 转换为 RGBA 的函数,那么您可以像这样制作:
function ARGBtoRGBA(ARGB: DWORD): DWORD;
var
A, R, G, B: Byte;
begin
ARGBtoColorChannels(ARGB, A, R, G, B);
Result := R or (G shl 8) or (B shl 16) or (A shl 24);
end;
为了完整起见,相反的是:
function RGBAtoARGB(RGBA: DWORD): DWORD;
var
A, R, G, B: Byte;
begin
RGBAtoColorChannels(RGBA, A, R, G, B);
Result := A or (R shl 8) or (G shl 16) or (B shl 24);
end;
为了让您知道该做什么,您需要了解 buf
是什么。是ARGB还是RGBA?假设它是 ARGB,考虑到你的问题的内容,这似乎很可能,你正试图复制到 RowPtr
,它似乎也是 ARGB
。在这种情况下,你可以像这样 blit 颜色:
PInteger(RowPtr)^ := buf[buf_pos];
我还强烈建议您更改 buf
参数的类型。无符号类型在这里更好,因为您可能需要执行按位运算。更重要的是,你通过堆栈复制整个数组,这是非常低效的。对于大位图,您将遭受堆栈溢出。相反,该参数应该是:
const buf: array of DWORD;
或
const buf: array of Cardinal;
使用const
意味着传递数组的引用,而不是副本。
你也可以避免使用 PRGBQuad
并声明 RowPtr
为 PCardinal
类型,比如说。
那么你可以这样赋值:
RowPtr^ := buf[buf_pos];
那时你不需要一个像素一个像素地做。您可以使用 Move
复制整个扫描线,因为这是一个简单的 blit。
for y := offY to offY + height - 1 do
begin
RowPtr := formMain.imgPreview.Bitmap.ScanLine[y];
Inc(RowPtr, offX);
Move(buf[buf_pos], RowPtr^, width*SizeOf(RowPtr^));
Inc(buf_pos, width);
end;
调用 Refresh
和 Update
似乎毫无意义。我不确定您是否需要调用任何一个,但如果需要,只需调用 Invalidate
!