View Issue Details

IDProjectCategoryView StatusLast Update
0038759LazarusTAChartpublic2021-04-16 18:36
ReporterArmands Murans Assigned Towp  
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
Product Version2.0.12 
Target Version2.2 
Summary0038759: TACHART TManhattanSeries red and blue color bits are switched.
DescriptionIf you use tachart with TManhattanSeries then using blue color you get red and vice versa.
Steps To ReproduceCreate simple project with Tachart and TManhattanSeries .
Use blue as the only color.
You will get red.
//===========
Use red as the only color.
You will get blue.
Additional InformationIt is possible to swap back colors in right order.
procedure TManhattanSeries.Draw(ADrawer: IChartDrawer);
var
  img: TLazIntfImage;
  topLeft, pt: TPoint;
  i, cnt: Integer;
  ext: TDoubleRect;
  rawImage: TRawImage;
  r: TRect;
 // n1,n2:integer;
   procedure PutPixel2(const APoint: TPoint; AColor: TColor); inline;
  begin
    PCardinal(rawImage.Data)[APoint.Y * r.Right + APoint.X] := Cardinal(ColorDef(AColor, SeriesColor)) or $FF000000; // Opacity.
  // PCardinal(rawImage.Data)[APoint.Y * r.Right + APoint.X] := Cardinal(AColor) or $FF000000; // Opacity.
    cnt += 1;
  end;
  function SwapRedBlue(AColor: TColor): TColor;inline;
var
  R, G, B: Byte;
begin
  RedGreenBlue(AColor, R, G, B);
  Result := RGBToColor(B, G, R);
end;

begin
  with Extent do begin
    ext.a := AxisToGraph(a);
    ext.b := AxisToGraph(b);
  end;
  NormalizeRect(ext);
  if not RectIntersectsRect(ext, ParentChart.CurrentExtent) then exit;

  // Do not cache graph points to reduce memory overhead.
  FindExtentInterval(ext, true);
  topLeft := ParentChart.ClipRect.TopLeft;
  r := BoundsSize(0, 0, ParentChart.ClipRect.BottomRight - topLeft);

  cnt := 0;
  img := CreateLazIntfImage(rawImage, r.BottomRight);
// n1:=0;
// n2:=0;
  try
    // AxisToGraph is slow, so split loop to optimize non-transformed case.
    if (AxisIndexX = -1) and (AxisIndexY = -1) then
      for i := FLoBound to FUpBound do
        with Source[i]^ do begin
          pt := ParentChart.GraphToImage(Point) - topLeft;
          if PtInRect(r, pt) then
            PutPixel2(pt, SwapRedBlue(Color));
          // n1:=n1+1;
        end
    else
      for i := FLoBound to FUpBound do
        with Source[i]^ do begin
          pt := ParentChart.GraphToImage(AxisToGraph(Point)) - topLeft;
          if PtInRect(r, pt) then
            PutPixel2(pt, SwapRedBlue(Color));
           // n2:=n2+1;
        end;
    if cnt > 0 then
      ADrawer.PutImage(topLeft.X, topLeft.Y, img);
  finally
    img.Free;
  end;
// showmessage('n1='+Inttostr(n1)+' n2='+IntTostr(n2));
end;
TagsNo tags attached.
Fixed in Revision65002, 65005, 65006
LazTarget-
WidgetsetWin32/Win64
Attached Files

Relationships

has duplicate 0038758 resolvedwp Tachart TManhattanSeries blue and red color bits are swapped 

Activities

Armands Murans

2021-04-15 14:23

reporter  

Main.pas (2,803 bytes)   
unit Main;

{$mode objfpc}{$H+}

interface

uses
  Classes, ExtCtrls, Spin, StdCtrls, SysUtils, FileUtil, Forms, Controls,
  Graphics, Dialogs, TAGraph, TASeries, TASources, TACustomSource;

type
  TForm1 = class(TForm)
    btnGenerate: TButton;
    Chart1: TChart;
    Chart1LineSeries1: TLineSeries;
    Chart1ManhattanSeries1: TManhattanSeries;
    lblTime: TLabel;
    pnlControls: TPanel;
    seCount: TSpinEdit;
    UserDefinedChartSource1: TUserDefinedChartSource;
    procedure btnGenerateClick(Sender: TObject);
    procedure Chart1AfterDrawBackground(
      ASender: TChart; ACanvas: TCanvas; const ARect: TRect);
    procedure Chart1AfterPaint(ASender: TChart);
    procedure UserDefinedChartSource1GetChartDataItem(
      ASource: TUserDefinedChartSource; AIndex: Integer;
      var AItem: TChartDataItem);
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

uses
  LCLIntf, TAChartUtils;

var
  GaussDevAvail: Boolean = false;
  GaussDev: Double = 0.0;

// Create a random number with normal distribution, mean value 0, standard
// deviation 1. See Numerical Recipes.
function RndNormal: Double;
var
  fac, r, v1, v2: Double;
begin
  if GaussDevAvail then
    Result := GaussDev
  else begin
    repeat
      v1 := 2.0 * Random - 1.0;
      v2 := 2.0 * Random - 1.0;
      r := Sqr(v1) + Sqr(v2);
    until (r > 0.0) and (r < 1.0);
    fac := Sqrt(-2.0 * Ln(r) / r);
    GaussDev := v1 * fac;
    Result := v2 * fac;
  end;
  GaussDevAvail := not GaussDevAvail;
end;

var
  VData: array of record X, Y: Double; Color: TColor; end;
  t0: Int64;

{ TForm1 }

procedure TForm1.btnGenerateClick(Sender: TObject);
{const
  COLORS: array [1..5] of TColor = (clYellow, clBlue, clGreen, clMaroon, clFuchsia); }
var
  i: Integer;
begin
  SetLength(VData, seCount.Value);
  for i := 0 to High(VData) do
    with VData[i] do begin
      X := Random(1000);
      Y := Abs(RndNormal);
      //Color := COLORS[Trunc(X / 1000 * Length(COLORS)) + 1];
      Color:=clBlue;
    end;
  UserDefinedChartSource1.PointsNumber := seCount.Value;
  UserDefinedChartSource1.Reset;
end;

procedure TForm1.Chart1AfterDrawBackground(
  ASender: TChart; ACanvas: TCanvas; const ARect: TRect);
begin
  Unused(ASender);
  Unused(ACanvas, ARect);
  t0 := GetTickCount64;
end;

procedure TForm1.Chart1AfterPaint(ASender: TChart);
begin
  Unused(ASender);
  lblTime.Caption := Format('Time: %d ms', [GetTickCount64 - t0]);
end;

procedure TForm1.UserDefinedChartSource1GetChartDataItem(
  ASource: TUserDefinedChartSource; AIndex: Integer; var AItem: TChartDataItem);
begin
  Unused(ASource);
  with VData[AIndex] do begin
    AItem.X := X;
    AItem.Y := Y;
    AItem.Color := Color;
  end;
end;

end.

Main.pas (2,803 bytes)   
Main.lfm (2,848 bytes)   
object Form1: TForm1
  Left = 406
  Height = 354
  Top = 135
  Width = 752
  Caption = 'Form1'
  ClientHeight = 354
  ClientWidth = 752
  LCLVersion = '2.0.12.0'
  object Chart1: TChart
    Left = 0
    Height = 354
    Top = 0
    Width = 640
    AxisList = <    
      item
        Marks.LabelBrush.Style = bsClear
        Minors = <>
        Title.LabelFont.Orientation = 900
        Title.LabelBrush.Style = bsClear
      end    
      item
        Visible = False
        Alignment = calBottom
        Marks.LabelBrush.Style = bsClear
        Minors = <>
        Title.LabelBrush.Style = bsClear
      end>
    BackColor = clCream
    Foot.Brush.Color = clBtnFace
    Foot.Font.Color = clBlue
    Title.Brush.Color = clBtnFace
    Title.Font.Color = clBlue
    Title.Text.Strings = (
      'TAChart'
    )
    OnAfterDrawBackground = Chart1AfterDrawBackground
    OnAfterPaint = Chart1AfterPaint
    Align = alClient
    object Chart1LineSeries1: TLineSeries
      LineType = ltNone
      Pointer.HorizSize = 1
      Pointer.OverrideColor = [ocBrush, ocPen]
      Pointer.VertSize = 1
      Pointer.Visible = True
      ShowPoints = True
    end
    object Chart1ManhattanSeries1: TManhattanSeries
      Source = UserDefinedChartSource1
    end
  end
  object pnlControls: TPanel
    Left = 640
    Height = 354
    Top = 0
    Width = 112
    Align = alRight
    ClientHeight = 354
    ClientWidth = 112
    TabOrder = 1
    object btnGenerate: TButton
      AnchorSideLeft.Control = seCount
      AnchorSideTop.Control = seCount
      AnchorSideTop.Side = asrBottom
      Left = 10
      Height = 25
      Top = 40
      Width = 73
      AutoSize = True
      BorderSpacing.Top = 8
      Caption = 'Generate'
      OnClick = btnGenerateClick
      TabOrder = 0
    end
    object seCount: TSpinEdit
      AnchorSideLeft.Control = pnlControls
      AnchorSideTop.Control = pnlControls
      AnchorSideRight.Control = pnlControls
      AnchorSideRight.Side = asrBottom
      Left = 10
      Height = 23
      Top = 9
      Width = 92
      Anchors = [akTop, akLeft, akRight]
      BorderSpacing.Left = 9
      BorderSpacing.Top = 8
      BorderSpacing.Right = 9
      Increment = 100000
      MaxValue = 100000000
      TabOrder = 1
      Value = 1000000
    end
    object lblTime: TLabel
      AnchorSideLeft.Control = btnGenerate
      AnchorSideTop.Control = btnGenerate
      AnchorSideTop.Side = asrBottom
      Left = 10
      Height = 15
      Top = 89
      Width = 29
      BorderSpacing.Top = 24
      Caption = 'Time:'
      ParentColor = False
    end
  end
  object UserDefinedChartSource1: TUserDefinedChartSource
    OnGetChartDataItem = UserDefinedChartSource1GetChartDataItem
    Left = 284
    Top = 80
  end
end
Main.lfm (2,848 bytes)   
manhattandemo.lpi (2,689 bytes)   
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
  <ProjectOptions>
    <Version Value="11"/>
    <PathDelim Value="\"/>
    <General>
      <SessionStorage Value="InProjectDir"/>
      <MainUnit Value="0"/>
      <Title Value="manhattandemo"/>
      <ResourceType Value="res"/>
      <UseXPManifest Value="True"/>
    </General>
    <i18n>
      <EnableI18N LFM="False"/>
    </i18n>
    <BuildModes Count="1">
      <Item1 Name="Default" Default="True"/>
    </BuildModes>
    <PublishOptions>
      <Version Value="2"/>
    </PublishOptions>
    <RunParams>
      <FormatVersion Value="2"/>
      <Modes Count="1">
        <Mode0 Name="default"/>
      </Modes>
    </RunParams>
    <RequiredPackages Count="2">
      <Item1>
        <PackageName Value="TAChartLazarusPkg"/>
      </Item1>
      <Item2>
        <PackageName Value="LCL"/>
      </Item2>
    </RequiredPackages>
    <Units Count="2">
      <Unit0>
        <Filename Value="manhattandemo.lpr"/>
        <IsPartOfProject Value="True"/>
      </Unit0>
      <Unit1>
        <Filename Value="Main.pas"/>
        <IsPartOfProject Value="True"/>
        <ComponentName Value="Form1"/>
        <HasResources Value="True"/>
        <ResourceBaseClass Value="Form"/>
      </Unit1>
    </Units>
  </ProjectOptions>
  <CompilerOptions>
    <Version Value="11"/>
    <PathDelim Value="\"/>
    <Target>
      <Filename Value="manhattandemo"/>
    </Target>
    <SearchPaths>
      <IncludeFiles Value="$(ProjOutDir)"/>
      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
    </SearchPaths>
    <Parsing>
      <SyntaxOptions>
        <IncludeAssertionCode Value="True"/>
      </SyntaxOptions>
    </Parsing>
    <CodeGeneration>
      <Checks>
        <IOChecks Value="True"/>
        <RangeChecks Value="True"/>
        <OverflowChecks Value="True"/>
        <StackChecks Value="True"/>
      </Checks>
      <VerifyObjMethodCallValidity Value="True"/>
      <Optimizations>
        <OptimizationLevel Value="4"/>
      </Optimizations>
    </CodeGeneration>
    <Linking>
      <Debugging>
        <GenerateDebugInfo Value="False"/>
        <StripSymbols Value="True"/>
      </Debugging>
      <Options>
        <Win32>
          <GraphicApplication Value="True"/>
        </Win32>
      </Options>
    </Linking>
  </CompilerOptions>
  <Debugging>
    <Exceptions Count="3">
      <Item1>
        <Name Value="EAbort"/>
      </Item1>
      <Item2>
        <Name Value="ECodetoolError"/>
      </Item2>
      <Item3>
        <Name Value="EFOpenError"/>
      </Item3>
    </Exceptions>
  </Debugging>
</CONFIG>
manhattandemo.lpi (2,689 bytes)   
manhattandemo.lpr (405 bytes)   
program manhattandemo;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Interfaces, // this includes the LCL widgetset
  Forms, Main, tachartlazaruspkg
  { you can add units after this };

{$R *.res}

begin
  RequireDerivedFormResource := True;
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

manhattandemo.lpr (405 bytes)   
manhattandemo.lps (978 bytes)   
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
  <ProjectSession>
    <PathDelim Value="\"/>
    <Version Value="11"/>
    <BuildModes Active="Default"/>
    <Units Count="2">
      <Unit0>
        <Filename Value="manhattandemo.lpr"/>
        <IsPartOfProject Value="True"/>
        <UsageCount Value="20"/>
      </Unit0>
      <Unit1>
        <Filename Value="Main.pas"/>
        <IsPartOfProject Value="True"/>
        <ComponentName Value="Form1"/>
        <HasResources Value="True"/>
        <ResourceBaseClass Value="Form"/>
        <IsVisibleTab Value="True"/>
        <TopLine Value="66"/>
        <CursorPos X="2" Y="72"/>
        <UsageCount Value="20"/>
        <Loaded Value="True"/>
        <LoadedDesigner Value="True"/>
      </Unit1>
    </Units>
    <JumpHistory HistoryIndex="-1"/>
    <RunParams>
      <FormatVersion Value="2"/>
      <Modes Count="0" ActiveMode="default"/>
    </RunParams>
  </ProjectSession>
</CONFIG>
manhattandemo.lps (978 bytes)   
manhattandemo.res (1,779 bytes)

wp

2021-04-15 23:55

developer   ~0130399

Thanks for reporting. Fixed. Please test and close if ok. Tested myself for win32/64, gtk2, gtk3, qt5.

Armands Murans

2021-04-16 17:44

reporter   ~0130410

Tested on windows. The problem is fixed. Can be closed.

wp

2021-04-16 18:36

developer   ~0130413

Some kind of "ceremony": The developer "resolves" the issue, the reporter does a final check and "closes" it. So, its's your turn: you find the "Close" button below the introductory report description.

Issue History

Date Modified Username Field Change
2021-04-15 14:23 Armands Murans New Issue
2021-04-15 14:23 Armands Murans File Added: Main.pas
2021-04-15 14:23 Armands Murans File Added: Main.lfm
2021-04-15 14:23 Armands Murans File Added: manhattandemo.lpi
2021-04-15 14:23 Armands Murans File Added: manhattandemo.lpr
2021-04-15 14:23 Armands Murans File Added: manhattandemo.lps
2021-04-15 14:23 Armands Murans File Added: manhattandemo.res
2021-04-15 17:43 wp Relationship added has duplicate 0038758
2021-04-15 17:44 wp Assigned To => wp
2021-04-15 17:44 wp Status new => assigned
2021-04-15 23:55 wp Status assigned => resolved
2021-04-15 23:55 wp Resolution open => fixed
2021-04-15 23:55 wp Fixed in Revision => 65002, 65005
2021-04-15 23:55 wp LazTarget => -
2021-04-15 23:55 wp Widgetset Win32/Win64 => Win32/Win64
2021-04-15 23:55 wp Note Added: 0130399
2021-04-16 00:04 wp Status resolved => assigned
2021-04-16 00:04 wp Resolution fixed => open
2021-04-16 00:05 wp Status assigned => resolved
2021-04-16 00:05 wp Resolution open => fixed
2021-04-16 00:05 wp Fixed in Revision 65002, 65005 => 65002, 65005, 65006
2021-04-16 00:05 wp Widgetset Win32/Win64 => Win32/Win64
2021-04-16 00:05 wp Target Version => 2.2
2021-04-16 00:05 wp Widgetset Win32/Win64 => Win32/Win64
2021-04-16 17:44 Armands Murans Note Added: 0130410
2021-04-16 18:36 wp Note Added: 0130413