0

I have an integer color values like -16447153. And how to convert it ARGB?

In c#, he used color function,

Color.FromArgb(buf[buf_pos])

is there a function in delphi as like above otherwise how can i convert ?

I tried like this:

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 $1000000);
      RowPtr.rgbRed:= ((buf[buf_pos] mod $1000000) div $10000);
      RowPtr.rgbGreen:= ((buf[buf_pos] mod $10000) div $100);
      RowPtr.rgbBlue:= (buf[buf_pos] mod $100);
      Inc(RowPtr);
      Inc(buf_pos);
    end;
  end;

  formMain.imgPreview.Refresh;
  formMain.imgPreview.Update;
end;

But this is not true, it seems grey :/

Dauezevy
  • 1,012
  • 4
  • 22
  • 46
  • There is no such function, but you can write a `helper for` the `TRGBQuad` record (assuming you are using Delphi XE6 as you tagged one of your questions). – TLama Feb 13 '15 at 10:19
  • By the way some times it helps knowing how it is implemented in C#. eg. Color.FromArgb can be looked up here: http://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/Color.cs,a4a64e5e79837053 – Jens Borrisholt Feb 13 '15 at 10:21
  • @TLama okay but i couldn' t convert mathematically. If i use PRGBTriple and delete reserved. It seems good, only white colors seem purple. So i must add alpha channel. But i am curious about Reserved is same with Alpha channel? – Dauezevy Feb 13 '15 at 10:22

1 Answers1

3

You appear to have got your channels mixed up. You are treating the input as RGBA when you say it is ARGB. In any case, your code using div and mod is inefficent. Bitwise shifting is the idiomatic way.

You can do it like this for ARGB input:

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;

Or if you start with RGBA then it goes like this:

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;

And these are little endian versions, since Delphi only targets on little endian machines, at the time of writing.

If you are looking for a function to convert ARGB to RGBA then you can make one like so:

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;

And for completeness the reverse is:

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;

In order for you to know what to do, you need to understand what buf is. Is it ARGB or RGBA? Assuming it it ARGB, which seems likely given the content of your question, you are attempting to copy to RowPtr, which also appears to be ARGB. In which case you can blit the color like this:

PInteger(RowPtr)^ := buf[buf_pos];

I would also strongly recommend that you change the type of the buf parameter. An unsigned type is better here, because you may need to perform bitwise operations. What's more you are copying the entire array via the stack which is very inefficient. For large bitmaps you will suffer stack overflow. Instead that parameter should be:

const buf: array of DWORD;

or

const buf: array of Cardinal;

Using const means that a reference to the array is passed, rather than a copy.

You may as well avoid using PRGBQuad and declare RowPtr to be of type PCardinal, say.

Then you can assign like this:

RowPtr^ := buf[buf_pos];

At that point you don't need to do it pixel by pixel. You can copy an entire scanline with Move because this is a simply 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;

Calling Refresh and Update seems pointless. I'm not sure you need to call either, but if you do, just call Invalidate instead!

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • If A, R, G and B are bytes, won't G shl 8, etc. be 0? I didn't try and can't try right now, so I am just asking. – Rudy Velthuis Feb 14 '15 at 15:24
  • @Rudy You might think so, but type promotion occurs: http://stackoverflow.com/questions/21362455/what-is-the-behaviour-of-shl-and-shr-for-non-register-sized-operands – David Heffernan Feb 14 '15 at 18:19