Jump to content
Willicious

Applying hue change to font graphic on the fly

Recommended Posts

Hi all,

 

I'm attempting to hue shift a pre-loaded font graphic at a certain point on the screen where it appears as scroller text. I'm pretty sure I've entered everything correctly, but all I'm getting is completely blank text instead of hue-shifted text:

 

procedure TGameMenuScreen.PrepareNextReelText;
const
  HUE_SHIFT = 0.250;
var
  i, realI: Integer;
  S: String;

  SizeRect: TRect;

  ScrollerText: TBitmap32;
  HueShift: TColorDiff;
  x, y: Integer;
begin
  FillChar(HueShift, SizeOf(TColorDiff), 0);
  HueShift.HShift := HUE_SHIFT;
  ScrollerText := TBitmap32.Create;

  for i := 1 to fScrollerTextList.Count do
  begin
    if i = fScrollerTextList.Count then
    begin
      fDisableScroller := true;
      Exit;
    end;

    if fReelForceDirection < 0 then
    begin
      realI := (fReelTextIndex - i);
      if realI < 0 then
        realI := realI + fScrollerTextList.Count;
    end else
      realI := (fReelTextIndex + i) mod fScrollerTextList.Count;

    if Trim(fScrollerTextList[realI]) <> '' then
    begin
      S := Trim(fScrollerTextList[realI]);
      fReelTextIndex := realI;
      Break;
    end;
  end;

  try
    SizeRect := MenuFont.GetTextSize(S);
    ScrollerText.SetSize(SizeRect.Width, SizeRect.Height + 4);
    ScrollerText.Clear(0);
    MenuFont.DrawText(ScrollerText, S, 0, 4);

    for y := 0 to ScrollerText.Height-1 do
       for x := 0 to ScrollerText.Width-1 do
       begin
          ScrollerText[x, y] := ApplyColorShift(ScrollerText[x, y], HueShift);
        end;

    ScrollerText.DrawMode := dmBlend;
  finally
    ScrollerText.Free;
  end;

    if (fReelForceDirection < 0) then
      fReelTextPos := -ScrollerText.Width
    else
      fReelTextPos := LayoutInfo.ScrollerWidth;

  fLastReelUpdateTickCount := GetTickCount64;
  fSwitchedTextSinceForce := true;
end;

Any ideas what I'm either a) doing wrong or b) not doing at all?

 

Thanks in advance!

Share this post


Link to post

Please tag your post "Graphics32" or otherwise mention that's what you're using.

 

My first guess would be that you forgot to set the ALpha pixel value in ApplyColorShift, but then I realized that you aren't drawing the ScrollerText bitmap anywhere...

So, is it correct that you aren't getting any text even without the call to ApplyColorShift?

Share this post


Link to post
2 hours ago, Anders Melander said:

Please tag your post "Graphics32" or otherwise mention that's what you're using.

 

then I realized that you aren't drawing the ScrollerText bitmap anywhere...

So, is it correct that you aren't getting any text even without the call to ApplyColorShift?

Tag added, apologies for the oversight.

 

If I remove everything to do with the colour shifting, the text does display. The colour-shifting code is actually mostly copied over and then adapted from another part of the project (where it does work). The only thing I couldn't copy was a line which started "Result := ", so it's very likely that this line is what actually draws the hue-shifted bitmap.

 

Adding "Result :=" here generates an undeclared identifier error, so I just left it out and hoped for the best. Clearly, though, I need something to explicitly say "draw the hue-shifted bitmap."

Share this post


Link to post
1 hour ago, Willicious said:

Adding "Result :=" here generates an undeclared identifier error, so I just left it out and hoped for the best. Clearly, though, I need something to explicitly say "draw the hue-shifted bitmap."

Can you show us what ApplyColorShift looks like?

Share this post


Link to post
10 hours ago, Willicious said:

Tag added, apologies for the oversight.

 

If I remove everything to do with the colour shifting, the text does display. The colour-shifting code is actually mostly copied over and then adapted from another part of the project (where it does work). The only thing I couldn't copy was a line which started "Result := ", so it's very likely that this line is what actually draws the hue-shifted bitmap.

 

Adding "Result :=" here generates an undeclared identifier error, so I just left it out and hoped for the best. Clearly, though, I need something to explicitly say "draw the hue-shifted bitmap."

Result is only available in a Function, while your current code is in a Procedure.

 

Have you ever taken the time to read the Delphi Language Guide? It is part of the IDE main help file. It's a bit disturbing to see that such a basic thing has tripped you up...

Share this post


Link to post
15 hours ago, Anders Melander said:

Can you show us what ApplyColorShift looks like?

function ApplyColorShift(aBase: TColor32; aDiff: TColorDiff): TColor32;
var
  H, S, V: Single;
begin
  RGBToHSV(aBase, H, S, V);
  H := H + aDiff.HShift;
  S := S + aDiff.SShift;
  V := V + aDiff.VShift;

  while H >= 1 do
    H := H - 1;
  while H < 0 do
    H := H + 1;

  S := Max(0, Min(S, 1));
  V := Max(0, Min(V, 1));

  Result := (HSVToRGB(H, S, V) and $FFFFFF) or (aBase and $FF000000);

  Result := TColor32(Integer(Result) + (aDiff.RAdj * $10000) + (aDiff.GAdj * $100) + (aDiff.BAdj));
  // The typecasts avoid compiler warnings.
end;

 

Share this post


Link to post

Apart from this line...

Result := TColor32(Integer(Result) + (aDiff.RAdj * $10000) + (aDiff.GAdj * $100) + (aDiff.BAdj));

...it looks ok.

 

The above doesn't take overflow in the individual color components into account so I'm guessing that what's happening is that the overflow causes the alpha to overflow from 255 to 0 (or some very small value).

Do this instead:

Result := HSVToRGB(H, S, V, TColor32Entry(aBase).A);
TColor32Entry(Result).R := Max(255, TColor32Entry(Result).R + aDiff.RAdj);
TColor32Entry(Result).G := Max(255, TColor32Entry(Result).G + aDiff.GAdj);
TColor32Entry(Result).B := Max(255, TColor32Entry(Result).B + aDiff.BAdj);

 

  • Like 1

Share this post


Link to post
6 hours ago, PeterBelow said:

Result is only available in a Function, while your current code is in a Procedure.

 

Have you ever taken the time to read the Delphi Language Guide?

The problem here is not that I don't understand Delphi, as such. It's more that I'm working on a very old program which has had several developers in the past, and whose codebase is therefore that bit more impenetrable to a beginner.

 

As it happens, one of the previous devs was able to point me in the right direction with this. Basically, the Create; and Free; parts needed to be removed, since this is handled elsewhere. It only took a few small tweaks to what I'd done to put it right.

 

Unfortunately, contact with the previous devs is limited at best, and I do want to try to solve some of this stuff without always going to them for help.

 

To be quite honest, I didn't know that Result is only available in a function, but I do now, so thanks for pointing this out. I do take your point that something simple regarding structure is something I could perhaps learn better by swotting up a bit first, and I do plan on boosting my theoretical knowledge at some point, but this is likely to cost money (I'd prefer structured lessons with specific goals than just aimlessly reading books and/or worse, PDFs on a screen), so I'd prefer to wait until I can justify the expense a bit more. Since I'm currently working on a hobby project and getting a feel for programming in general, it doesn't seem worth shelling out just yet.

 

With that said, I've watched several introductory videos on Delphi and other coding languages, and I find that I instantly forget most of what is said in these videos because I'm not actually using any of it. I just remember that something vague was said about classes, functions, something about semicolons and brackets, and yeah I can print "Hello World" to the screen, but what good is that when you're working on a game or website or complex desktop application?

 

Don't get me wrong, I'm a former music teacher and I do understand the importance of theory in developing your skills, but my own personal preference is to have a go first, and then track back and see what I'm doing wrong if it doesn't work. I learn way more this way than by attempting to find that one video, article, chapter in a book, or - god forbid - Stack Overflow post that may or may not provide me with the knowledge I need to progress.

 

Apologies for the rant here, I'm just finding learning programming very frustrating tbh.

 

---

 

EDIT: I have downloaded the Delphi Language Guide. I'm taking a look at it 👍

Edited by Willicious

Share this post


Link to post

OK... here's a perfect example of what beginners to programming are up against.

 

"Classes" are something important, that much I can gather. But, I don't know what a "class" is or why it's important, so I look it up and here's what's presented:

 

Quote

Class Types

A class, or class type, defines a structure consisting of fields, methods, and properties. Instances of a class type are called objects. The fields, methods, and properties of a class are called its components or members.

 

This raises far more questions than it answers. Now I need to know what "fields, methods and properties" are. I also need to know why you would have different instances of a class, and remember that these are referred to as "objects." I also need to remember that, as well as being called "fields, methods and properties", these things - whatever they are - may also be referred to as "components or members".

 

And, there's 391 pages of this, with no index!

 

So, as a beginner, I'm bound to think "maybe some of this stuff doesn't actually matter, and is just jargon. I'll just start changing things in the project and see what happens. If I need to 'know' something, I can just pick it up later, when it matters."

 

So yes, I might occasionally not be aware that I'm incorrectly using a particular element of the language. But, I'm at a loss as to how else I could possibly learn everything.

 

As someone should probably have once said, if they haven't already: "Si quieres aprender a hablar Español, ve a España!!"

Edited by Willicious

Share this post


Link to post

Don't sweat it.

Take your time. Look at some code and try to understand what it does and how it does it. Don't rush it and eventually, it'll come to you.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×