Using part of an .png for an AlphaImageList

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #35040
    Whookie
    Participant

    Hi!

    At the moment I want to using TPNGGraphic and some TAlphaImageLists. What I want to do, is loading a bigger .png Image with a lot of little

    Images (they could be organized in “stripes”). Now at Runtime i want to clear the AlphaImageList and load it with such a stripe of new images.

    The point here is to preserve the alpha-channel.

    So one way would be to “cut” out image by image from the original .png and add it to the ImageList, but I have not found a way to do that.

    I thought of creating a new png in the size of one image and then copy pixel by pixel but I would need to retrieve and set the alpha-value

    of each pixel ….

    It would be even better to build a Stream or Resource to us AlphaImageList.LoadFromStream/Resource and load the list in one single call.

    But at the moment any hint how to achieve my goal would be be great!

    #47801
    Support
    Keymaster

    Hello

    I have not a solution at moment. Alphacontrols can't make a new Png files (only read them).

    #47823
    Whookie
    Participant

    Hi again! I've found a way to do what I wanted. The following code might help someone else and is based on MakeIcon32Rect() from acPng.pas

    Code:
    unit SkinImgLstLoader;

    interface

    Uses
    Windows, SysUtils, acPng, acAlphaImageList, Graphics, sConst, sAlphaGraph;

    Type
    TAlphaImageListLoader = Class
    private
    fGraphic: TPNGGraphic;
    fW: Integer;
    fH: Integer;
    fMaskBitmap: TBitmap;
    fFast32Src: TacFast32;
    fDstBmp: TBitmap;
    fFast32Dst: TacFast32;
    fError: Boolean;
    function MakeIcon32Rect(SrcX, SrcY: Integer): HICON;
    public
    constructor Create(const AGraphic: TPNGGraphic; AImgWidth, AImgHeight: Integer); Virtual;
    procedure LoadFrom(AX, AY, ACount: Integer; AImgList: TsAlphaImageList; ReplaceImages: Boolean=TRUE);
    property Error: Boolean read fError;
    End;

    implementation

    Uses
    CommCtrl;

    { TAlphaImageListLoader }

    constructor TAlphaImageListLoader.Create(const AGraphic: TPNGGraphic; AImgWidth, AImgHeight: Integer);
    begin
    fGraphic := AGraphic;
    fW := AImgWidth;
    fH := AImgHeight;
    end;

    procedure TAlphaImageListLoader.LoadFrom(AX, AY, ACount: Integer; AImgList: TsAlphaImageList; ReplaceImages: Boolean);
    var
    iCnt: Integer;
    ico: HICON;
    begin
    fMaskBitmap := TBitmap.Create;
    fMaskBitmap.PixelFormat := pf1bit; // doesnt matter, when bmDDB is used (otherwise pf8bit need)
    fMaskBitmap.HandleType := bmDDB; // doesnt work when bmDIB (works but needs MaskBitmap.Canvas.Pixels[x,y]:=C.A)?
    fMaskBitmap.Width := fW;
    fMaskBitmap.Height := fH;
    //
    fDstBmp := TBitmap.Create;
    fDstBmp.PixelFormat := pf32Bit;
    fDstBmp.Width := fW;
    fDstBmp.Height := fH;
    //
    fFast32Src := TacFast32.Create;
    fFast32Dst := TacFast32.Create;
    //
    if fFast32Src.Attach(fGraphic) And fFast32Dst.Attach(fDstBmp) then
    begin
    AImgList.AcBeginUpdate;
    if ReplaceImages then //else add images to this list(!)
    AImgList.Clear;
    AImgList.Width := fW;
    AImgList.Height := fH;
    fError := FALSE;
    //
    for iCnt := 0 to ACount – 1 do
    begin
    ico := MakeIcon32Rect(AX, AY);
    if ico 0 then
    begin
    fError := fError Or (ImageList_AddIcon(AImgList.Handle, Ico) < 0);
    DestroyIcon(Ico);
    end;
    Inc(AX, fW); // LoadFromRow (LoadFromCol = Inc(AY, fH))
    end;
    AImgList.AcEndUpdate;

    end;
    fFast32Src.Free;
    fFast32Dst.Free;
    fMaskBitmap.Free;
    fDstBmp.Free;
    end;

    function TAlphaImageListLoader.MakeIcon32Rect(SrcX,SrcY: Integer): HICON;
    var
    IconInfo: TIconInfo;
    X, Y : integer;
    begin
    for y := 0 to fH – 1 do
    begin
    for x := 0 to fW – 1 do
    begin
    fFast32Dst[x,y] := fFast32Src[SrcX+x,SrcY+y];
    end;
    end;

    IconInfo.fIcon := True;
    IconInfo.hbmColor := fDstBmp.Handle;
    IconInfo.hbmMask := fMaskBitmap.Handle;

    Result := CreateIconIndirect(IconInfo);
    end;

    end.

    Now one can use that class to load some images from a greater png like:

    Code:
    fImgList := TsAlphaImageList.Create(nil); // create an image list

    // AGraphic … is a png image loaded from somewhere
    // iW, iH … the width/height of one image in the image list
    iLoader := TAlphaImageListLoader.Create(AGraphic, iW, iH);
    //
    // now load some image into the list
    // iX, iY … position (upper left corner) of the first image inside the png
    // iCn … number of images to load (images have to be horizontally side by side)
    // fImgList … img list to add the images to (you could call LoadFrom more than once to have more than one row of images
    // using iLoader.LoadFrom(iX, iY, iCn, fImgList, FALSE);)
    iLoader.LoadFrom(iX, iY, iCn, fImgList);
    iLoader.Free;
    //

Viewing 3 posts - 1 through 3 (of 3 total)
  • You must be logged in to reply to this topic.