shaunroselt / Roselt-Developer-Tools

Collection of utilities for developers.
https://store.steampowered.com/app/1223180/Roselt_Developer_Tools/
GNU General Public License v3.0
60 stars 22 forks source link

Color Picker (Eye Dropper Tool) #6

Open shaunroselt opened 1 year ago

shaunroselt commented 1 year ago

The Color Picker doesn't currently have an Eye Dropper Tool. This is pretty useful to have and should be implemented in the future.

shaunroselt commented 1 year ago

I tried implementing this, but it's not working correctly. My implementation can be found in this commit: https://github.com/shaunroselt/Roselt-Developer-Tools/commit/bcc3ced79703307af4958185843c030b73a39260

It's kind of working, but not really. It's selecting the wrong pixel color. I'm taking a screenshot of the screen, then putting that screenshot into a TImage component and with the OnClick event of the TImage, I'm trying to get the pixel color.

Here's how I'm taking the screenshot and then dynamically creating a TForm with a TImage in it:

  var bm := TBitmap.Create;
  TakeScreenshot(bm);

  var frmImageColor := TForm.CreateNew(Self);
  frmImageColor.Caption := 'Select Color';
  frmImageColor.BorderStyle := TFMXFormBorderStyle.ToolWindow;
  frmImageColor.WindowState := TWindowState.wsMaximized;

  var frmImage := TImage.Create(frmImageColor);
  frmImage.Parent := frmImageColor;
  frmImage.Align := TAlignLayout.Client;
  frmImage.WrapMode := TImageWrapMode.Original;
  frmImage.Cursor := crCross;
  frmImage.OnMouseDown := frmImageClick;
  frmImage.OnMouseMove := frmImageMouseMove;
  frmImage.Bitmap.Assign(bm);
  bm.Free;
  bm := nil;

  try
    if (frmImageColor.ShowModal = mrOk) then
    begin
      ColorPanel.Color := LastEyeDropperColor;
    end;
  finally
    FreeAndNil(frmImage);
    FreeAndNil(frmImageColor);
  end;

And then the OnClick event for the TImage:

procedure TFrame_ColorPicker.frmImageClick(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
var
  BitmapData: TBitmapData;
begin
  TImage(Sender).Bitmap.Map(TMapAccess.Read, BitmapData);
  try
    LastEyeDropperColor := BitmapData.GetPixel(Round(X), Round(Y));
  finally
    TImage(Sender).Bitmap.Unmap(BitmapData);
    TForm(TImage(Sender).Parent).ModalResult := mrOk;
  end;
end;

Does anyone have any ideas?

gorhinstroebel commented 1 year ago

Color picker works perfects on my side In Windows, but on MacOS i get a error of "System Error. Code 2: No such file or directory." Happens on "TakeScreenShot" Event once the button is clicked

Screenshot 2023-02-02 at 23 12 32

Using: Embarcadero® Delphi 11 Version 28.0.46141.0937 (Architect Edition) Updates: Delphi 11 and C++ Builder 11 (Update 2)

System Specs:

Windows Running on VM:

VM Application: Parallels Desktop (ARM) VM OS: Windows 11 ARM (22H2) (OS BUILD: 22621.1105) Processor: Apple Silicon 3.20 GHz (4 processors) RAM: 4,00 GB

MacBook Air M1 2020

Chip: Apple M1 Memory: 8GB 3733MHz LPDDR4X (unified memory) SSD: 256gb MacOS Version: 13.1 (Ventura)

shaunroselt commented 1 year ago

Interesting. Thanks for the added info on this.

So maybe it's something with the Windows version or the Delphi version.

image

I'm running latest Windows 11 Dev Insider Build and also Delphi 11.1 (I see you're on Delphi 11.2)

I'll update my Delphi to a newer version and test this code again. Maybe it's just broken in Delphi 11.1 (hopefully)

shaunroselt commented 1 year ago
image

I installed Delphi 11.2 Enterprise, but it still doesn't work on my side. It still doesn't actually select the pixel color on which I click.

Maybe it could be because I have 4 monitors?

image

All 4 monitors are 4K resolution, but they have different scaling values set. Monitor 2 is my primary monitor and Monitor 2 is the one I'm trying to use to select the pixel color.

I'll test it with just one monitor connected sometime soon and see if it works.