Archive

Archive for April 29, 2012

Adjustable clipping for pixelrage

April 29, 2012 Leave a comment

This is an experimental clipping routine for pixelrage I wrote long ago. The idea being to have standard helper functions that are universal and that can be used anywhere, in this case it applies as much to pixelrage as it does TBitmap.

Pixel clipping

When copying graphics (blitting) to a surface that has a cliprect installed, there are several steps that needs to be taken (pixelrage takes care of these things for you naturally):

  1. If the source rectangle is larger or overlaps the cliprect, it must be adjusted
  2. the difference between source x1,y1 and target x1,y1 must be added to x1,y1
  3. the difference between source x2,y2 and target x2,y2 must be subtracted from source
  4. Once correctly adjusted, the input and output codec’s must be pre-fetched
  5. Copy over each scanline using codec->read to codec->write
With fast graphics, every pixel counts

With fast graphics, every pixel counts

When stretching however, the ordeal becomes somewhat different. You still have to adjust the source and target regions, but if the source is smaller than the target your copy routine must be smart enough to apply a fixed math scale factor (which basically means, some pixels will be read more than once in order for scaling to occur).

And clipping for all

I never really got to finish this one, so I release it into the wild (together with pixelrage and byterage). I use these libraries in various older products but I don’t mind sharing and giving back to the community. Hopefully people can re-cycle some of my work, or perhaps use it as inspiration for something better.


  Function  StretchClip(var srcRect:TRect;var targetRect:TRect;
            targetClip:TRect):Boolean;
  var
    srcWD:  Integer;
    srcHD:  Integer;
    dstWD:  Integer;
    dstHD:  Integer;
    clpWD:  Integer;
    clpHD:  Integer;
    xOff:   Integer;
    yOff:   Integer;
  Begin
    result:=False;

    srcWD:=srcRect.right-srcrect.left;
    srcHD:=srcRect.bottom-srcRect.Top;
    if (srcWD>0) and (srcHD>0) then
    begin
      dstWD:=targetRect.right-targetRect.left;
      dstHD:=targetRect.bottom-targetRect.Top;
      if (dstWD>0) and (dstHD>0) then
      begin
        clpWD:=targetClip.right-targetClip.left;
        clpHD:=targetClip.bottom-targetClip.Top;
        if (clpWD>0) and (clpHD>0) then
        Begin
          inc(srcWD);
          inc(srcHD);
          inc(dstWD);
          inc(dstHD);
          inc(clpWD);
          inc(clpHD);

          (* Check of target is within extreme Right and left of clip *)
          if  (targetRect.left<targetClip.Right)
          and (targetRect.top<targetClip.Bottom) then
          Begin

            (* Clip LEFT *)
            if targetrect.Left<targetclip.Left then
            Begin
              (* X Offset by how much? *)
              xOff:=abs(targetclip.Left - targetrect.Left);

              (* Is it off by less than the whole width? *)
              if xoff<srcWD then
              Begin
                srcRect.Left:=srcRect.left + xoff;
                targetRect.Left:=targetclip.Left;
                dec(dstWD,xoff);
                dec(srcWD,xoff);
              end else
              exit;
            end;

            (* CLIP TOP *)
            if targetrect.Top<targetclip.top then
            Begin
              (* Y offset by how much? *)
              yOff:=abs(targetclip.Top - targetrect.Top);

              (* is it off by less than the whole height? *)
              if yOff<srcHD then
              Begin
                srcRect.top:=srcRect.top + yOff;
                targetRect.top:=targetClip.Top;
                dec(dstHD,yoff);
                dec(srcHD,yoff);
              end else
              exit;
            end;

            (* CLIP RIGHT *)
            if (targetrect.right > targetClip.right) then
            Begin
              xOff:=abs(targetrect.right - targetClip.right);
              if xoff<srcWD then
              Begin
                srcRect.Right := srcRect.Right - xoff;
                targetRect.right:=targetClip.Right;
                dec(dstWD,xoff);
                dec(srcWD,xoff);
              end else
              exit;
            end;

            (* CLIP BOTTOM *)
            if (targetrect.bottom > targetClip.bottom) then
            Begin
              yOff:=abs(targetrect.bottom - targetClip.bottom);
              if yoff<srcHD then
              Begin
                srcRect.bottom := srcRect.bottom - yOff;
                targetRect.bottom:=targetClip.bottom;
                dec(dstHD,yOff);
                dec(srcHD,yOff);
              end else
              exit;
            end;

            (* Final verdict *)
            result:=(srcWD>0) and (srcHD>0)
            and (dstWD>0) and (dstHD>0)
            and (clpWD>0) and (clpHD>0);

          end;
        end;
      end;
    end;
  end;
Isnt clipper the name of a boat?

Isnt clipper the name of a boat?

When we apply our clipper on two unsuspecting rectangles passing by my lab on their way to a square dance, we see that it calculates the correct offset’s and adjusts the buffer values as expected. Now you can feed the adjusted source and target rectangles to your blitter without having to test each scanline or accidentally writing beyond the memory buffer.

Pixels are fun 🙂

  procedure TfrmTest.testClip;
  var
    srcRect, dstRect,Clip:TRect;
  begin
    Clip:=Rect(10,10,109,109);
    srcRect:=Rect(10,10,60,60);
    dstRect:=Rect(0,0,115,40);

    DrawOriginalCords(srcRect,dstRect,clip);

    if StretchClip(srcRect,dstRect,Clip) then
    Begin
      LogToMemo('Clip successfull:');
      LogtoMemo('Source = ' + pxlrage.TPXRRect.toString(srcRect));
      LogtoMemo('Target = ' + pxlrage.TPXRRect.toString(dstRect));

      DrawClippedCords(srcRect,dstRect,clip);

    end else
    logToMemo('Clipping resulted in no activity');
  end;

Pixelrage released on google code

April 29, 2012 Leave a comment

My personal graphics library, Pixelrage, was today released into the wild on google code

About Pixelrage

PXR is a slim, easy to use and innovative graphics library that represents a foundation for further, more advanced libraries. As such SL does not implement everything under the sun, but aims to provide a rock-solid basis that can be easily extended. By default the unit implements a RAW surface, which is basically a surface held in RAM without any device context. It also provides a Windows DIB implementation that does have a context and can thus be used with blitting and Delphi canvas operations.

PXR is not about the latest cool feature. It is about providing a platform independent foundation, assembly free, that other more advanced libraries can be based.

Features

  • 8, 15, 16, 24 and 32 bit pixelbuffers
  • Fast native blitter between pixel formats (e.g copy from 32bpp -> 8bpp)
  • Palette handling
  • Clipping
  • Basic primitives (circle, ellipse, rectangle)
  • Fill mechanism
  • Alpha blending
  • Transparency
  • DIB implementation
  • UNI implementation

Dependencies

As a part of the “rage” group of projects, pixelrage depends on byterage for memory manipulation.