TBitmap.Scanline on NT Workstation

I made an application using Delphi 4.0 -TBitmap.Scanline on Windows 98 and it runs good, but when I run my application on Win NT Workstation 4.0 it causes Error "Access Violation bla bla at address bla bla". I won't install Borland Delphi 4.0 on my NT so I can debug it... it takes too long and need to be registered, I just want to fix from my win 98...
Is that any explaination about this case ?

Sincerely,

LexZEUS
LVL 5
LexZEUSAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

interCommented:
Hi,

I think we may solve the problem by examining the critical parts of your code. NT is strict on memory boundary leaks etc...Or if your program is commercially critical, just tell what you are doing with bitmap.

regards,
igor
0
LexZEUSAuthor Commented:
procedure TFSC.DoIt;
Type TMyRGB = record
     B,G,R : Byte;
     End;
     TArrMyRGB = Array[0..MaxWidth] of TMyRGB;
     PRGB  = ^TArrMyRGB;

Var i,j:integer;
    ZRGB,
    ZRGB2 :PRGB;
Begin
      Temp.Height:=BTList[CurImage].Height;
      Temp.Width:=BTList[CurImage].Width;
      IsTerminated:=False;
      Iteration:=0;

      Repeat
      inc(Iteration,5);
      Application.ProcessMessages;
      Temp.Canvas.Draw(0,0,BTList[CurImage]);
      For j:=0 to Temp.Height-1 do
         Begin
         ZRGB:=PRGB(Temp.ScanLine[j]);
         ZRGB2:=PRGB(BackGround.ScanLine[j+MyPosY]);
         For i:=0 to Temp.Width-1 do
           Begin
           If IsTerminated then Exit;
           ZRGB^[i].R:=Round(ZRGB^[i].R * (Iteration/255)) + Round(ZRGB2^[i+MyPosX].R * ((255-Iteration)/255));
           ZRGB^[i].G:=Round(ZRGB^[i].G * (Iteration/255)) + Round(ZRGB2^[i+MyPosX].G * ((255-Iteration)/255));
           ZRGB^[i].B:=Round(ZRGB^[i].B * (Iteration/255)) + Round(ZRGB2^[i+MyPosX].B * ((255-Iteration)/255));
           End;
         End;
      Image1.Canvas.Draw(0,0,BackGround);
      Image1.Canvas.Draw(MyPosX,MyPosY,Temp);
      Image1.Refresh;
      Until Iteration>=255;
End;

Basically, I want to do gradient transforming picture from Background ( TBitmap whic is larger ) to BTList[Curimage] ( TBitmap I'd like to show ), using Temp ( TBitmap too ).

Using scanline from Background then merge with scanline from Temp ( get from BTList[CurImage ), and show them using Image1. This work good on Win 98, but not on NT...
0
interCommented:
I am checking, I have NT with Delphi 3.
0
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

LexZEUSAuthor Commented:
I'm not sure it's all because of DoIt procedure.. but error shows every time I perform that procedure.

I've experienced several times, that using TBitmap.scanline cause access violation error, this happened on some of my previous programs. But this time I'm getting curious ...


sincerely,

LexZEUS
0
interCommented:
what are the default values for MyPosX and myPosY?
0
LexZEUSAuthor Commented:
You can put any number on MyPosX and MyPosY.

############################
############################
#########%%%%%##############
#########%%%%%##############
#########%%%%%##############
#########%%%%%##############
############################

Asume # is my big background, and % is my little picture, MyPosX,MyPosY is position that refer to Image1 not to Background.
0
interCommented:
I have run your source with not error by setting MyPosX, MyPosY to 0 and loading winnt256 bmp as background and first image. I think you should suspect a leak do to j+MyPosY and i+MyPosX, it will cause an error if

Temp.Width - i+MyPosX > Backgroud.Width OR
Temp.Height - j+MyPosY > Backgroud.Width

0
interCommented:
pardon,

Temp.Width - 1+MyPosX > Backgroud.Width OR
Temp.Height -1j+MyPosY > Backgroud.Width
0
LexZEUSAuthor Commented:
What a weird ? No error ? I even ever make a simplest scanline application which turning picture to greyscale but got the same error on NT.

No it can't be, cos before I perform DoIt, the two image themself had been properly placed on Image1.

Oh ya, I'm using pixelformat pf24bit, is that the problem ? Honestly, the pics I put on image1 are photos, so it must be 24 bit ( get the file from Adobe Photoshop 5.0 )

Sincerely,

LexZEUS
0
interCommented:
This is the code that I have no error, it is just for testing since I do not have you images:


....

const
  MaxWidth = 2000;
  CurImage = 0;
var
  Background, Temp : TBitmap;
  BtList : array[0..1] of TBitmap;
  IsTerminated: boolean=False;
  MyPosX, MyPosY, Iteration : Integer;


procedure TForm1.DoIt;
Type TMyRGB = record
     B,G,R : Byte;
     End;
     TArrMyRGB = Array[0..MaxWidth] of TMyRGB;
     PRGB  = ^TArrMyRGB;

Var i,j:integer;
    ZRGB,
    ZRGB2 :PRGB;
Begin
      Temp.Height:=BTList[CurImage].Height;
      Temp.Width:=BTList[CurImage].Width;
      IsTerminated:=False;
      Iteration:=0;

      Repeat
      inc(Iteration,5);
      Application.ProcessMessages;
      Temp.Canvas.Draw(0,0,BTList[CurImage]);
      For j:=0 to Temp.Height-1 do
         Begin
         ZRGB:=PRGB(Temp.ScanLine[j]);
         ZRGB2:=PRGB(BackGround.ScanLine[j+MyPosY]);
         For i:=0 to Temp.Width-1 do
           Begin
           If IsTerminated then Exit;
           ZRGB^[i].R:=Round(ZRGB^[i].R * (Iteration/255)) +
Round(ZRGB2^[i+MyPosX].R * ((255-Iteration)/255));
           ZRGB^[i].G:=Round(ZRGB^[i].G * (Iteration/255)) +
Round(ZRGB2^[i+MyPosX].G * ((255-Iteration)/255));
           ZRGB^[i].B:=Round(ZRGB^[i].B * (Iteration/255)) +
Round(ZRGB2^[i+MyPosX].B * ((255-Iteration)/255));
           End;
         End;
      Image1.Canvas.Draw(0,0,BackGround);
      Image1.Canvas.Draw(MyPosX,MyPosY,Temp);
      Image1.Refresh;
      Until Iteration>=255;
End;


procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Picture.LoadFromFile('D:\src\imgprocessing\ExImage\TestImg\winnt8gray.bmp');
end;

procedure TForm1.b4Click(Sender: TObject);
begin
  DoIt;
end;

initialization
  Temp := TBitmap.Create;
  BackGround := TBitmap.Create;
  BtList[0] := TBitmap.Create;
  BtList[0].LoadFromFile('D:\src\imgprocessing\ExImage\TestImg\winnt8gray.bmp');
  BackGround.LoadFromFile('D:\src\imgprocessing\ExImage\TestImg\winnt8gray.bmp');
  MyPosX := 0;
  MyPosY := 0;
finalization
  Temp.Free;
  BackGround.Free;
  BtList[0].Free;
end.

0
interCommented:
I just converted the winnt256 to 24 bit and have no error.
0
LexZEUSAuthor Commented:
Thanks Igor, I really appreciate your effort, but I run your code and still got error on NT.

Even minute ago, I tried to "ONLY" draw a horizontal line using scanline which is running "PERFECT" on win 98, but failed on Win NT...
Now I believe, this isn't matter on I'm using pf24bit or so. This is a matter of I can't use scanline on NT...
I don't think this is because of any hardware failure, cos it works on many application ....

I'll wait for the answer next three days, and if there's no progress, I'll gladly to give my point to you Igor...
Thanks very much.

LexZEUS
0
LexZEUSAuthor Commented:
What I mean is my NT ... I start to believe that there is "something" in my NT...
0
interCommented:
Ok then, just drop a comment if you need anything.
regards, igor
0
interCommented:
By the way, do you want to speed up the processing above?
0
eYesCommented:
where u compiled ur app? 98? NT?
u should re-compile ur app in NT.
0
tierCommented:
Do you run NT with Administrator privileges?
Just a thought...
0
LexZEUSAuthor Commented:
Yes Igor, if you're willing to increase the process speed, I'm willing to increase my points for that. I'll look forward for it.

For eYes, I can't compile the appl on NT cos we don't have Delphi on NT.. But have you encountered that appl compiled on Win 98 doesn't work on NT ?

For tier, maybe not, cos the NT I use is NT workstation, and I don't have admin access. But can it be that privileges restrict NT from using "scanline" ?

If I transform the code "Scanline" above using TCanvas.Pixels[i,j], the Appl works on NT and Win 98 but incredible slow... But it works.. So it means the problem is the "scanline" itself.

Sincrely,

LexZEUS
0
interCommented:
My friend,

I could not still catch up he cause. I am not familiar with 98 but your program is a normal user mode program which means that no special treatment is needed. Delphi produces the code but does not include any of the system files of win98 or winnt in your exe. If you want, send your exe and few test images to me and I'll check it on my NT.
let's talk a bit if you have time....
0
LexZEUSAuthor Commented:
To Igor, the procedure DoIt above is enough to represent my whole application cos I think the error is caught there...
I believe my appl's code must work on your NT cos it seems that my NT even "COULDN'T HANDLE A SINGLE HORIZONTAL LINE USING SCANLINE" ... :(
So forget about it, maybe my appl itself should work on many other NTs but not on mine...

You mentioned that you can make the procedure faster. I'm interested on it, I would like to increase my points to 100 if you can give me that trick.. But the pict must maintain the pixelformat pf24bit.


Sincerely,

LexZEUS.
0
interCommented:
Forget about the points by now, if you make use of it you will decide. Anyway, in your code I could catch that you already well know about the pointers. So the idea is to fasten the inner loop.

The code fragment

  ZRGB^[i].R:=Round(ZRGB^[i].R * (Iteration/255)) +
Round(ZRGB2^[i+MyPosX].R * ((255-Iteration)/255));
  ZRGB^[i].G:=Round(ZRGB^[i].G * (Iteration/255)) +
Round(ZRGB2^[i+MyPosX].G * ((255-Iteration)/255));
  ZRGB^[i].B:=Round(ZRGB^[i].B * (Iteration/255)) +
Round(ZRGB2^[i+MyPosX].B * ((255-Iteration)/255));

could be orders of magnitude faster if we avoid array access and unneccassary divisions. So instead of accessing elements by array we dereference the pointer and increment them. A faster fragment might be as follows: (follow the comments please)

procedure TForm1.DoIt;
Type PMyRGB = ^TMyRGB;
     TMyRGB = packed record
     B,G,R : Byte;
     End;
     TArrMyRGB = Array[0..MaxWidth] of TMyRGB;
     PRGB  = ^TArrMyRGB;

Var i,j:integer;
    S, D : PMyRGB; // do not point to whole array just point single pixel
    It : single;
Begin
      Temp.Height:=BTList[CurImage].Height;
      Temp.Width:=BTList[CurImage].Width;
      IsTerminated:=False;
      Iteration:=0;

      Repeat
      inc(Iteration,5);
      Application.ProcessMessages;
      Temp.Canvas.Draw(0,0,BTList[CurImage]);
      For j:=0 to Temp.Height-1 do
         Begin
         S := PMyRGB(Temp.ScanLine[j]);
         // no need to add the myposy and myposx in inner loop
         D := PMyRGB(@(PRGB(BackGround.ScanLine[j+MyPosY])[MyPosX]));
         For i:=0 to Temp.Width-1 do
           Begin
           If IsTerminated then Exit;
           It := Iteration/255; // avoid 1 division per channel
           S.R:=Round(S.R * It + D.R * (1-It));
           S.G:=Round(S.G * It + D.G * (1-It));
           S.B:=Round(S.B * It + D.B * (1-It));
           Inc(S); Inc(D);
           End;
         End;
      Image1.Canvas.Draw(0,0,BackGround); //why are we again an again draw to the image canvas for testing?
      Image1.Canvas.Draw(MyPosX,MyPosY,Temp);
      Image1.Refresh;
      Until Iteration>=255;
End;

regards, igor
0
interCommented:
this code saves about 1100 msecs on my PIII 450. when testing with every bitmap is set to winnt24bit.bmp...
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
LexZEUSAuthor Commented:
> why are we again an again draw to the
> image canvas for testing?

Not for testing, cos I want to gradually change the opacity of my little pic using TTimer, so each time I add and add the Iteration until >= 255

  But that is it, your answer do help me to open my eyes... I never think to do that.. thanx, I willingly accept it.


Sincerely,

LexZEUS
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.