ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 Ugly holes from RoundCorners algorithm
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

PeterPanino

933 Posts

Posted - May 26 2013 :  14:29:57  Show Profile  Reply
Hi!

From this image:



I get this image:



using this code:
ImageEnView1.Proc.RoundImage(20, 20);
ImageEnView1.IO.Params.BitsPerSample := 8;
ImageEnView1.IO.Params.SamplesPerPixel := 4;
iRGB := ImageEnView1.IEBitmap.Pixels[0, ImageEnView1.IEBitmap.Height - 1];
ImageEnView1.Proc.SetTransparentColors(iRGB, iRGB, 0);

ImageEnView1.Height := ImageEnView1.Height + 23;
ImageEnView1.Width := ImageEnView1.Width + 23;
ImageEnView1.ScrollBars := ssNone;

ImageEnView1.Proc.AddSoftShadow(4, 4, 4, True, clBlack, 100);
ImageEnView1.Bitmap.Modified := True;
ImageEnView1.Update;


How could this be modified to prevent the ugly holes in the image?

w2m

USA
1990 Posts

Posted - May 26 2013 :  15:15:41  Show Profile  Reply
The color you use to set the transparent color must not be in the image or all pixels with the transparent color will be transparent. So use a color that is not in the image:
procedure TForm1.RoundCorners1Click(Sender: TObject);
var
  iColor: TColor;
  iRGB: TRGB;
begin
  ImageEnView1.Proc.RoundImage(20, 20);
  ImageEnView1.IO.Params.BitsPerSample := 8;
  ImageEnView1.IO.Params.SamplesPerPixel := 4;
  iColor := clFuchsia;
  iRGB := TColor2TRGB(iColor);
  ImageEnView1.Proc.SetTransparentColors(iRGB, iRGB, 0);

  ImageEnView1.Height := ImageEnView1.Height + 23;
  ImageEnView1.Width := ImageEnView1.Width + 23;
  ImageEnView1.ScrollBars := ssNone;

  ImageEnView1.Proc.AddSoftShadow(4, 4, 4, True, clBlack, 100);
  ImageEnView1.Bitmap.Modified := True;
  ImageEnView1.Update;
end;

William Miller
Adirondack Software & Graphics
Email: w2m@frontiernet.net
EBook: http://www.imageen.com/ebook/
Apprehend: http://www.frontiernet.net/~w2m/index.html
Go to Top of Page

PeterPanino

933 Posts

Posted - May 26 2013 :  16:24:55  Show Profile  Reply
Hi William! Thanks for the help!

How high is the probability that clFuchsia is not contained in any random image? Do you know an algorithm which automatically finds a color not contained in the image?
Go to Top of Page

w2m

USA
1990 Posts

Posted - May 26 2013 :  17:00:15  Show Profile  Reply
<GRIN> I figured that would be your next question.

Here is some beta code to do just that. I have not tested the functions very much yet. Note that the function Bitmap24UnusedColor only works for 24-bit bitmaps. I am hopeing that this will work most of the time for ImageEn because usually ImageEn stores the bitmaps as 24-bit. If not I have no solution for other bitdepths at this time.

b]function IsColorInBitmap(AImageEnView: TImageEnView; AColor: TColor): boolean;
{ Return True if AColor is contained in the AImageEnView.IEBitmap or False if not. }
var
  i: integer;
  j: integer;
  iColor: TColor;
  iRGB: TRGB;
begin
  for i := 0 to AImageEnView.IEBitmap.Width - 1 do
    for j := 0 to AImageEnView.IEBitmap.Height - 1 do
    begin
      iRGB := AImageEnView.IEBitmap.Pixels[0, AImageEnView.IEBitmap.Height - 1];
      iColor := TRGB2TColor(iRGB);
      if iColor = AColor then
        Result := True
      else
        Result := False;
    end;
end;

function Bitmap24UnusedColor(const ABitmap: TBitmap): TColor;
{ Return a unused color or -1 if all colors are used. }
var
  BitArray: Pointer;
  p: integer;
  ma: PByte;
  mb: integer;
  mc: integer;
  md: PByte;
  na: integer;
  nb: integer;
  nba: PByte;
  nbb: integer;
  oaa: PByte;
  oab: integer;
  ob, oc: integer;
  o: integer;
begin
{$IFDEF DEBUG}
  if ABitmap.PixelFormat <> pf24bit then
    raise Exception.Create('Intended only for 24bit bitmaps');
{$ENDIF}
  GetMem(BitArray, 8192);
  { p is the 'given' B value }
  for p := 0 to 255 do
  begin
    ZeroMemory(BitArray, 8192);
    { m is used to scan through the bitmap scanlines }
    ma := ABitmap.Scanline[0];
    mb := integer(ABitmap.Scanline[1]) - integer(ABitmap.Scanline[0]);
    for mc := 0 to ABitmap.Height - 1 do
    begin
      md := ma;
      { n is used to scan through the scanline's pixels }
      for na := 0 to ABitmap.Width - 1 do
      begin
        if md^ = p then
        begin
          Inc(md);
          nb := (md^ shl 8);
          Inc(md);
          nb := (nb or md^);
          Inc(md);
          { splitting up the 16bit value into a bit array index consisting of byte pointer and bit mask }
          nba := PByte(Cardinal(BitArray) + Cardinal(nb shr 3));
          nbb := (128 shr (nb and 7));
          { and making sure appropriate bit is set }
          nba^ := (nba^ or nbb);
        end
        else
          Inc(md, 3);
      end;
      Inc(ma, mb);
    end;
    oaa := BitArray;
    for oab := 0 to 8191 do
    begin
      if oaa^ <> 255 then
      begin
        ob := 0;
        oc := 128;
        while True do
        begin
          if (oaa^ and oc) = 0 then
            break;
          Inc(ob);
          oc := (oc shr 1);
        end;
        { making complete 16bit value }
        o := ((oab shl 3) or ob);
        { that's it }
        FreeMem(BitArray, 8192);
        Result := RGB((o and 255), (o shr 8), p);
        exit;
      end;
      Inc(oaa);
    end;
  end;
  FreeMem(BitArray, 8192);
  Result := TColor(-1);
end;

procedure TForm1.RoundCorners1Click(Sender: TObject);
var
  iColor1: TColor;
  iColor2: TColor;
  iRGB: TRGB;
begin
  iColor1 := clBlack;
  if not IsColorInBitmap(ImageEnView1, iColor1) then
  else
  begin
    MessageBox(0, PChar(ColorToString(iColor1) + ' is in the bitmap.'), 'Warning', MB_ICONWARNING
      or
      MB_OK);
    iColor2 := Bitmap24UnusedColor(ImageEnView1.Bitmap);
    MessageBox(0, PChar('Replacing ' + ColorToString(iColor1) + ' with ' + ColorToString(iColor2) +
      '.'), 'Warning', MB_ICONWARNING or
      MB_OK);
  end;
  if iColor2 = -1 then
  begin
    MessageBox(0, 'All colors are used', 'Warning', MB_ICONWARNING or MB_OK);
    exit;
  end;
  ImageEnView1.Proc.RoundImage(20, 20);
  ImageEnView1.IO.Params.BitsPerSample := 8;
  ImageEnView1.IO.Params.SamplesPerPixel := 4;

  iRGB := TColor2TRGB(iColor2);
  ImageEnView1.Proc.SetTransparentColors(iRGB, iRGB, 0);

  ImageEnView1.Height := ImageEnView1.Height + 23;
  ImageEnView1.Width := ImageEnView1.Width + 23;
  ImageEnView1.ScrollBars := ssNone;

  ImageEnView1.Proc.AddSoftShadow(4, 4, 4, True, clBlack, 100);
  ImageEnView1.Bitmap.Modified := True;
  ImageEnView1.Update;
end[/b];


William Miller
Adirondack Software & Graphics
Email: w2m@frontiernet.net
EBook: http://www.imageen.com/ebook/
Apprehend: http://www.frontiernet.net/~w2m/index.html
Go to Top of Page

fab

1310 Posts

Posted - May 29 2013 :  01:10:32  Show Profile  Reply
Sorry guys, but I don't understand very well this topic.
Just executing:

ImageEnView1.Proc.RoundImage(20, 20);
ImageEnView1.Proc.AddSoftShadow();

Produces following result:



RoundImage correctly sets the alpha channel around the borders and the same does AddSoftShadow.
Go to Top of Page

w2m

USA
1990 Posts

Posted - May 29 2013 :  06:07:32  Show Profile  Reply
Peter,

I do not know why my initial try with this failed, but I just retested this with the code Fabrizio suggested and it works as expected:
ImageEnView1.Proc.RoundImage(20, 20);
ImageEnView1.Proc.AddSoftShadow();

You do not have to deal with the transparent color at all.

William Miller
Adirondack Software & Graphics
Email: w2m@frontiernet.net
EBook: http://www.imageen.com/ebook/
Apprehend: http://www.frontiernet.net/~w2m/index.html
Go to Top of Page

PeterPanino

933 Posts

Posted - May 30 2013 :  10:12:50  Show Profile  Reply
You are right - it is so simple!
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: