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
 Convert Alpha + TColor to TColor
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

w2m

USA
1990 Posts

Posted - Feb 13 2012 :  09:11:20  Show Profile  Reply
I looking for a way to convert alpha + TColor to just TColor. What I mean by this is similar to how an icon is dithered when it has an alphachanel to a similar color with no alpha.

For example... clBlack with alpha = 255 is black, clBlack with alpha = 155 is a shade of gray and clBlack with alpha = 100 is a lighter shade of gray.

So in essence what I am looking to do is remove the alpha channel then change the image back to 32-bit so the area outside of the actual icon is transparent, then change first 3 columns of each row to have the same color as they were before removing the alphachannel.

Is this possible?

I tried this but it is not changing the colors correctly...

procedure TFormMain.DitherTo24Bit1Click ( Sender: TObject );
// remove the alphachannel from a 32-bit image then reduce the alpha on the first 3 columns that have alpha = 255
var
  iRGB: TRGB;
  w: integer;
  h: integer;
  c1: integer;
  c2: integer;
  c3: integer;
  a1: integer;
  a2: integer;
  a3: integer;
  iMS: TMemoryStream;
begin
  if Assigned ( AdvOfficePager1.ActivePage ) then
  begin
    FImageENView := TImageEnView ( AdvOfficePager1.ActivePage.Controls [ 0 ] );

    if Assigned ( FImageENView ) then
    begin
      FImageENView.Proc.SaveUndoCaptioned ( 'Dither Alpha ' + IntToStr ( FImageENView.Proc.UndoCount ) );
      Undo1.Hint := 'Dither Alpha ' + IntToStr ( FImageENView.Proc.UndoCount + 1 );
      FImageENView.Proc.ClearAllRedo;
      // convert to 24 bit
      if FImageENView.HasAlphaChannel then
        FImageENView.RemoveAlphaChannel;
      // make the pixels outside of the bitmap transparent
      FImageENView.IO.Params.BitsPerSample := 8;
      FImageENView.IO.Params.SamplesPerPixel := 4;
      FImageENView.IO.Params.ICO_BitCount [ AdvOfficePager1.ActivePageIndex ] := 32;
      iRGB := FImageENView.IEBitmap.Pixels [ 0, FImageENView.IEBitmap.Height - 1 ];
      FImageENView.Proc.SetTransparentColors ( iRGB, iRGB, 0 );
      // dither the apparent alphachannel color on first 3 columns with alpha = 255 to a similar color
      for w := 0 to FImageENView.Bitmap.Width - 1 do
        for h := 0 to FImageENView.Bitmap.Height - 1 do
        begin
          // if alpha is 255 then change the color on next 3 cols
          if FImageENView.IEBitmap.Alpha[ w, h ] = 255 then
          begin
            c1 := w + 1;
            c2 := w + 2;
            c3 := w + 3;
            //if 1st column then (outermost column)
            if w = c1 then
              FImageENView.IEBitmap.Canvas.Pixels [ w, h ] := clLtGray;
            //if 2nd column then ( next column in )
            if w = c2 then
              FImageENView.IEBitmap.Canvas.Pixels [ w, h ] := clSilver;
            //if 3rd column then ( third column in )
            if w = c3 then
              FImageENView.IEBitmap.Canvas.Pixels [ w, w ] := clGray;          end;
        end;

      FImageENView.Update;
      FImageENView.Bitmap.Modified := True;
    end;
  end;

end;


William Miller

fab

1310 Posts

Posted - Feb 13 2012 :  11:31:56  Show Profile  Reply
quote:
For example... clBlack with alpha = 255 is black, clBlack with alpha = 155 is a shade of gray and clBlack with alpha = 100 is a lighter shade of gray.


It happens when the other color (ie background) is white. The alpha blend formula is (alpha is floating point 0..1):
dest_color = alpha * color + (1 - alpha) * background_color
So you can calculate RGB values, with a white background with:

R_OUT = alpha * R + (1-alpha)*255 <- 255 here stays for white
G_OUT = alpha * G + (1-alpha)*255 <- 255 here stays for white
B_OUT = alpha * B + (1-alpha)*255 <- 255 here stays for white

that is equivalent to (now alpha in the range 0..255):

R_OUT = alpha/255*R + (255-alpha)
G_OUT = alpha/255*G + (255-alpha)
B_OUT = alpha/255*B + (255-alpha)

If you want to work with TColor you could write:

var rgb:TRGB;

rgb := TColor2TRGB(mycolor);
rgb.r := trunc(alpha/255*rgb.r) + (255-alpha);
rgb.g := trunc(alpha/255*rgb.g) + (255-alpha);
rgb.b := trunc(alpha/255*rgb.b) + (255-alpha);
mycolor := TRGB2TColor(rgb);

Anyway I don't know if above help you to solve the rest of your problem...


Go to Top of Page

w2m

USA
1990 Posts

Posted - Feb 13 2012 :  13:17:07  Show Profile  Reply
This works reasonablty well except I do not think the last 3 columns on the right and bottom side of the image are rendered...

procedure TFormMain.Dither1Click ( Sender: TObject );
// Dither the AlphaColor to a TColor by removing the alphachannel from a 32-bit image then render the outside area as transparent then change the color on the first 3 columns that have alpha = 255 to match the old alpha shade
var
  iRGB: TRGB;
  w: integer;
  h: integer;
  iMS: TMemoryStream;
  iColor: TColor;
  iAlpha: integer;
  PointInsideImage: boolean;
  Column: integer;
begin
  if Assigned ( AdvOfficePager1.ActivePage ) then
  begin
    FImageENView := TImageEnView ( AdvOfficePager1.ActivePage.Controls [ 0 ] );

    if Assigned ( FImageENView ) then
    begin
      FImageENView.Proc.SaveUndoCaptioned ( 'Dither Alpha ' + IntToStr ( FImageENView.Proc.UndoCount ) );
      Undo1.Hint := 'Dither Alpha ' + IntToStr ( FImageENView.Proc.UndoCount + 1 );
      FImageENView.Proc.ClearAllRedo;
      // convert to 24 bit
      if FImageENView.HasAlphaChannel then
        FImageENView.RemoveAlphaChannel;
      // make the pixels outside of the bitmap transparent
      FImageENView.IO.Params.BitsPerSample := 8;
      FImageENView.IO.Params.SamplesPerPixel := 4;
      FImageENView.IO.Params.ICO_BitCount [ AdvOfficePager1.ActivePageIndex ] := 32;
      iRGB := FImageENView.IEBitmap.Pixels [ 0, FImageENView.IEBitmap.Height - 1 ];
      FImageENView.Proc.SetTransparentColors ( iRGB, iRGB, 0 );

      // dither the alpha channel on first 3 columns with alpha = 255
      for w := 0 to FImageENView.Bitmap.Width - 1 do
      begin

        for h := 0 to FImageENView.Bitmap.Height - 1 do
        begin

          Column := 0;
          // if alpha = 255 then point inside the image
          if FImageENView.IEBitmap.Alpha [ w, h ] = 255 then
          begin
            PointInsideImage := True;
            inc ( Column );
          end
          else
          begin
            PointInsideImage := False;
            Column := 0;
          end;

          if Column > 3 then
            Column := 0;

          // Only convert the colors for the first three columns
          if ( PointInsideImage ) and ( Column = 1 ) then
          begin
            //if 1st column then (outermost column)
            iColor := FImageENView.IEBitmap.Canvas.Pixels [ w, h ];
            iRGB := TColor2TRGB ( iColor );
            iAlpha := FImageENView.IEBitmap.Alpha [ w, h ];
            iRGB.r := Trunc ( iAlpha / 255 * iRGB.r ) + ( 255 - iAlpha );
            iRGB.g := Trunc ( iAlpha / 255 * iRGB.g ) + ( 255 - iAlpha );
            iRGB.b := Trunc ( iAlpha / 255 * iRGB.b ) + ( 255 - iAlpha );
            iColor := TRGB2TColor ( iRGB );
            FImageENView.IEBitmap.Canvas.Pixels [ w, h ] := iColor;
          end;

          if ( PointInsideImage ) and ( Column = 2 ) then
          begin
            //if 2nd column then (next column)
            iColor := FImageENView.IEBitmap.Canvas.Pixels [ w, h ];
            iRGB := TColor2TRGB ( iColor );
            iAlpha := FImageENView.IEBitmap.Alpha [ w, h ];
            iRGB.r := Trunc ( iAlpha / 255 * iRGB.r ) + ( 255 - iAlpha );
            iRGB.g := Trunc ( iAlpha / 255 * iRGB.g ) + ( 255 - iAlpha );
            iRGB.b := Trunc ( iAlpha / 255 * iRGB.b ) + ( 255 - iAlpha );
            iColor := TRGB2TColor ( iRGB );
            FImageENView.IEBitmap.Canvas.Pixels [ w, h ] := iColor;
          end;

          if ( PointInsideImage ) and ( Column = 3 ) then
          begin
            //if 3rd column then (next column)
            iColor := FImageENView.IEBitmap.Canvas.Pixels [ w, h ];
            iRGB := TColor2TRGB ( iColor );
            iAlpha := FImageENView.IEBitmap.Alpha [ w, h ];
            iRGB.r := Trunc ( iAlpha / 255 * iRGB.r ) + ( 255 - iAlpha );
            iRGB.g := Trunc ( iAlpha / 255 * iRGB.g ) + ( 255 - iAlpha );
            iRGB.b := Trunc ( iAlpha / 255 * iRGB.b ) + ( 255 - iAlpha );
            iColor := TRGB2TColor ( iRGB );
            FImageENView.IEBitmap.Canvas.Pixels [ w, h ] := iColor;
          end;

        end;

      end;

    end;

    FImageENView.Update;
    // update the preview
    iMS := TMemoryStream.Create;
    try

      FImageENView.LayersSaveToStream ( iMS );
      iMS.Position := 0;
      ImageEnView1.LayersLoadFromStream ( iMS );

    finally
      iMS.Free;
    end;

    FImageENView.Bitmap.Modified := True;
    ImageEnView1.Update;
  end;
end;


William Miller
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: