Forum > Graphics

Re: InplaceGrayscale

(1/1)

user5:
   The code below does a fine job but if the picture has a solid color background then only the foreground images
are changed to grayscale as is shown in Fig. 2. However, I could have sworn that on one run the same code
changed the entire image to grayscale though now it's not doing that.
    Is there a way to apply grayscale to the entire image including the background?


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---bgra := TBGRABitmap.create;mybitmap := TBitmap.create;mybitmap.width := image1.width;mybitmap.height := image1.height;mybitmap.assign(image1.picture.bitmap);bgra.assign(mybitmap);bgra.InplaceGrayscale;bgra.saveToFile('Gray.png');

paweld:
I checked and it converts the entire image to grayscale:
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.Button1Click(Sender: TObject);var  bgra: TBGRABitmap;  ms: TMemoryStream;begin  ms := TMemoryStream.Create;  bgra := TBGRABitmap.Create(imgorg.picture.Bitmap);  bgra.InplaceGrayscale;  bgra.SaveToStreamAsPng(ms);  ms.Position := 0;  imgcpy.Picture.PNG.LoadFromStream(ms);  bgra.Free;  ms.Free;end;

user5:
    I had some difficulties applying grayscale to pictures and videos but I finally got it right and just for the record
the code solution is shown below. I found some interesting articles on gray scaling in this forum and they were helpful.
    The user has two options. The entire picture or video object can be grayscaled or if the object has a solid
background color then the user can opt to preserve that color while applying grayscale only to foreground images.
    InplaceGrayscale is a bit faster than direct pixel access. InplaceGrayscale by itself works fine on a non-transparent
object but if the object has a solid background color then the grayscaling of that color would be too dark unless the
image is first saved as a PNG and then reloaded.
    Thank you for your response paweld.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.GetRGBColorNumbers(pixcolor:TColor; var rednum:integer; var greennum:integer; var bluenum:integer);var color1rstr,color1gstr,color1bstr:string;    code:integer;begin color1rstr := Format('%d', [Red(pixcolor)]); color1gstr := Format('%d', [Green(pixcolor)]); color1bstr := Format('%d', [Blue(pixcolor)]); val(color1rstr,rednum,code); val(color1gstr,greennum,code); val(color1bstr,bluenum,code);end; if transpix = false then  //Apply grayscale to the entire image. begin  mybitmap := TBitmap.create;  mybitmap.width := image1.width;  mybitmap.height := image1.height;  mypng := TPortableNetworkGraphic.create;  mypng.width := image1.width;  mypng.height := image1.height;  mybitmap.assign(image1.picture.bitmap);   mypng.assign(mybitmap);  mypng.savetofile('temp9999.png'); //The background grayscale would be too dark without this.  delay(150);  application.processmessages;  if FileExists('temp9999.png') then   begin    mypng.loadfromfile('temp9999.png');    mybitmap.assign(mypng);   end;   bgra := TBGRABitmap.create;  bgra.assign(mybitmap);  bgra.InplaceGrayscale; //Apply the grayscale.  mybitmap.assign(bgra);  mybitmap.savetofile('pkqjxzxx.bmp');  delay(100);  application.processmessages;  if FileExists('pkqjxzxx.bmp') = true then   image1.picture.bitmap.loadfromfile('pkqjxzxx.bmp')  else   image1.picture.bitmap.assign(mybitmap);   mypng.free;  mybitmap.free;  bgra.free;  if FileExists('temp9999.png') then   deletefile('temp9999.png'); endelse //Apply grayscale only to foreground images. begin   bgra := TBGRABitmap.create;  mybitmap := TBitmap.create;  mybitmap.width := image1.width;  mybitmap.height := image1.height;  mybitmap.assign(image1.picture.bitmap);  bgra.assign(mybitmap);   for y := 0 to (image1.height - 1) do   begin    for x := 0 to (image1.width - 1) do     begin      c := bgra.GetPixel(x,y);      newcolor := BGRAToColor(c);      if newcolor <> bkcolor then //If the pixel is not a background color then change it.       begin        GetRGBColorNumbers(newcolor,rednum,greennum,bluenum); //Get the color numbers.        average := (rednum + greennum + bluenum) div 3; //Get the average of those 3 numbers.        newcolor := RGBToColor(average,average,average); //Apply the grayscale        bgra.SetPixel(x,y,newcolor);       end;     end;   end;   mybitmap.assign(bgra);  mybitmap.savetofile('pkqjxzxx.bmp');  mybitmap.free;  bgra.free;  end;


circular:
Hello user5,

You can optimize your code with pixel access to actually have direct pixel access:

--- Code: ---var x,y: integer; p: PBGRAPixel; c: TBGRAPixel;
begin
  ...
  for y := 0 to (bgra.height - 1) do
  begin
    p := bgra.ScanLine[y];
    for x := 0 to (bgra.width - 1) do
    begin
      c := p^;
      newcolor := BGRAToColor(c);
      if newcolor <> bkcolor then //If the pixel is not a background color then change it.
        p^ := BGRAToGrayscale(c);
      inc(p);
    end;
  end;
end;

--- End code ---

Navigation

[0] Message Index

Go to full version