Unsatisfactory Forward Error

I think an unsatisfactory forward usually happens when something is prototyped(forwarded) but not implemented. I think everything implemented properly in my code, though.

I made a unit to use in a program but the unit is not compiling.
Above implementation, I have a few functions prototyped. They are defined below the "implementation" keyword as I think they should. I copy and pasted the function headers from their definitions to make sure they are exactly the same.

I'm using Delphi 4, btw.

There is about 330 lines of code so it is probably too much to post here. It is documented and quite clear for me, atleast. If someone would be willing to help figure out this bug, please send a message. My email address is greijos@hotmail.com or you can use programmersheaven to contact me too.

thanks for reading about my problem

Comments

  • if ur experiencing the "unsatisfacted forwarded procedure/function" error then you have declared (prototyped) the procedure/function but have not implemented it (written the procedure/method itself) in the implementation part

    if you cant figure it out, send the code to netgert@hotmail.com

    : I think an unsatisfactory forward usually happens when something is prototyped(forwarded) but not implemented. I think everything implemented properly in my code, though.
    :
    : I made a unit to use in a program but the unit is not compiling.
    : Above implementation, I have a few functions prototyped. They are defined below the "implementation" keyword as I think they should. I copy and pasted the function headers from their definitions to make sure they are exactly the same.
    :
    : I'm using Delphi 4, btw.
    :
    : There is about 330 lines of code so it is probably too much to post here. It is documented and quite clear for me, atleast. If someone would be willing to help figure out this bug, please send a message. My email address is greijos@hotmail.com or you can use programmersheaven to contact me too.
    :
    : thanks for reading about my problem
    :
    :

    [hr][red][italic][b]N[/b][/red][blue]et[/blue][red][b]G[/b][/red][blue]ert[/italic][/blue][hr]

  • I still haven't found anyone that can figure out the error.

    Here is my code. I know it is a lot(about 330 lines) but I hope someone is willing to figure out the problem.

    [code]
    unit JGCompression;
    {
    Author: Josh Greig
    Date: June 30, 2004
    Purpose:
    Providing methods for manipulating JG compressed image files.
    }
    interface
    uses sysutils,graphics;

    function SaveBitmapToJGCF(bitmap1: graphics.tbitmap;fn: string): boolean;
    function SetExtention(fn,extention: string): string;

    const
    Threshold = 100;
    // a threshold for deciding whether to split a region or not to

    implementation

    type
    pixel = tColor;
    PixelArray = array[0..$FFFF] of pixel;
    pPixelArray = ^PixelArray;

    Colour24 = record
    red,green,blue: byte;
    end;

    // define a record that will basically point to all the pixel data in a bitmap
    BitmapReference = record
    Width,Height: Cardinal; // dimensions of the bitmap referred to
    Rows: array of pPixelarray; // dynamic array of pointers
    end;
    // this reference can allow for faster access to the pixel data in a tbitmap object
    // this is very useful for the pixel manipulation required by the compression algorithms

    procedure SaveCompressedPixelData(var f: file; bitmap1: tbitmap);
    procedure SaveCompressedRegion(var f: file;
    BR: BitmapReference;startX,startY: cardinal;N: byte);
    procedure SetReference(var bitmap1: tbitmap;BR: BitmapReference);
    function GetAverageColour(var BR: BitmapReference;top,left,size: cardinal): tColor;
    function GetColourVarience(var BR: BitmapReference;top,left,size: cardinal;var avgc: tcolor): real;
    procedure FreeBitmapReference(var BR: BitmapReference);


    function SaveBitmapToJGCF(bitmap1: tbitmap;fn: string): boolean;
    {
    purpose:
    storing a bitmap as a JGC file
    inputs:
    bitmap = the bitmap to save
    fn = name of file
    }
    var
    f: file;
    w: word; // a word to temperarily store some values
    b: byte; // temperarily stores 8-bit values
    const
    FormatKey = 'JGCF';
    begin
    result:=true;
    // assign file
    AssignFile(f,fn);

    try
    // rewrite file with a record size of 1
    Rewrite(f,1);
    except
    on EAbstractError do // this exception needs to be changed
    begin
    result:=false; // indicate failure
    end;
    end; // end of try-except statement
    if result then // if the exception did not occur
    begin
    // write the header section
    begin
    BlockWrite(f,FormatKey,4);
    w:=0;
    BlockWrite(f,w,2); // write the file format version number
    w:=bitmap1.width;
    BlockWrite(f,w,2); // write the width
    w:=bitmap1.height;
    BlockWrite(f,w,2); // write the height
    b:=24; // bits per pixel
    BlockWrite(f,b,1); // write the bits per pixel
    // now, the header has been written to file
    end;
    bitmap1.pixelformat:=pf32bit;
    // make sure the pixel data is stored using 32 bits for every pixel
    // this assumption is used when using direct pixel data access using pointers


    // write the compressed pixel data portion
    SaveCompressedPixelData(f,bitmap1);


    // close file
    Close(f);
    result:= true; // indicate success
    end;
    end;

    procedure SaveCompressedPixelData(var f: file; bitmap1: tbitmap);
    {
    purpose: compresses data and stores it in the file
    assumptions:
    f is already open in a binary writing mode.
    }
    var
    rx,ry: cardinal;
    maxRX,maxRY: cardinal;
    BR: BitmapReference;
    begin
    // make a reference to the bitmap so the data can be manipulated more efficiently
    SetReference(bitmap1,BR);

    // calculate the number of regions
    maxRX:=(BR.width shl 4)+1;
    maxRY:=(BR.Height shl 4)+1;
    {
    "shl 4" is a binary shift left 4 digits.
    This is the same as deviding by 16 but more efficient.
    }
    for rY:=0 to maxRY do
    // loop through rows of regions
    begin
    for rX:=0 to maxRX do
    // loop through each region in each row
    begin
    // for each 16 by 16 region, compress it and save the data to file
    SaveCompressedRegion(f,BR,rX shl 4,rY shl 4,16);
    end;
    end;
    FreeBitmapReference(BR);
    end;

    procedure SaveCompressedRegion(var f: file;
    BR: BitmapReference;startX,startY: cardinal;N: byte);
    {
    purpose: compressing information for a N by N pixel region
    inputs:
    f = file being written to (must be open in a binary writing mode)
    BR = a reference to the bitmap being compressed
    startX = coordinate of the left side of the region being compressed
    startY = coordinate of the top side of the region being compressed
    }
    var
    c: tcolor;
    c24: Colour24;
    p: pPixelArray;
    begin
    if (N=1) then// base case (individual pixel)
    begin
    p:= BR.Rows[startY];
    c := p[startX];
    c24.red := c;
    c24.green := c shr 8;
    c24.blue := c shr 16;

    BlockWrite(f,N,1);
    BlockWrite(f,c24,3);
    end
    else // general case
    begin
    if GetColourVarience(BR,top,left,N,c)>threshold then
    begin // if lots of detail is in the region
    // devide it up more
    N:= N shr 1; // devide size by 2.

    // compress each subregion separately
    SaveCompressedRegion(f,BR,startX,startY,N);
    SaveCompressedRegion(f,BR,startX+N,startY,N);
    SaveCompressedRegion(f,BR,startX,startY+N,N);
    SaveCompressedRegion(f,BR,startX+N,startY+N,N);
    end
    else // if very little detail is in the region
    begin
    // define the colour for the region
    c24.red := c;
    c24.green := c shr 8;
    c24.blue := c shr 16;
    BlockWrite(f,N,1); // define the size of the square
    BlockWrite(f,c24,3); // define the colour for the square
    end;
    end;
    end;

    function GetColourVarience(var BR: BitmapReference;top,left,size: cardinal;avgc: tcolor): real;
    {
    purpose:
    calculating the varience in colours throughout a region
    }
    var
    r,g,b: byte; // average red, green, and blue values
    c: tcolor; // average(mean) colour
    maxX,maxY: cardinal; // x and y boundaries
    x,y: cardinal; // coordinates of pixels
    Area: cardinal; // number of pixels in region
    total: double; // total of all variances
    begin
    maxX:=top+size-1;
    maxY:=left+size-1;
    if (maxX>=BR.Width) then
    maxX:=BR.Width-1;
    if (maxY>=BR.Height) then
    maxY:=BR.Height-1;
    avgc:=GetAverageColour(BR,top,left,size);

    // extract the red, green and blue values
    r:=avgc;
    g:=avgc shr 8;
    b:=avgc shr 16;

    total:=0;
    for y:=maxY downto top do
    // loop through the rows of pixels
    for x:=maxX downto left do
    begin
    c:=BR.Rows[y][x];
    total:=total+
    sqr((c and $FF)-r)+ // z-score squared
    sqr((c shr 8 and $FF)-g)+ // z-score squared
    sqr((c shr 16 and $FF)-b); // z-score squared
    end;
    Area:=(maxY-top+1)*(maxX-left+1);
    result:=total/3/Area;
    end;

    function GetAverageColour(var BR: BitmapReference;top,left,size: cardinal): tColor;
    {
    purpose: calculating the average colour for a square region
    inputs:
    BR = reference to the bitmap containing these picels being averaged
    top = top of the region
    left = left of the region
    size = length of a side of the square region(size must not be 0)
    }
    var
    red,green,blue: cardinal;
    Area: cardinal;
    c: tcolor;
    x,y: cardinal;
    maxX,maxY: cardinal;
    begin
    // initialize the values to 0 before counting up all red, green, and blue values
    red:=0;
    green:=0;
    blue:=0;
    maxX:=left+size-1;
    maxY:=top+size-1;

    if (BR.Height<=maxY) then // if region overlaps bottom of bitmap
    maxY:=BR.Height-1;
    if (BR.Width<=maxX) then // if region overlaps right side of bitmap
    maxX:=BR.Width-1;

    for y:=maxY downto top do
    for x:=maxX downto left do
    begin
    // get the colour of the pixel
    c := BR.rows[y][x];

    // add the red, green, and blue values to the counters
    red:=red+(c and $FF);
    green:=green+(c shr 8 and $FF);
    blue:=blue+(c shr 16 and $FF);
    end;
    Area:=(maxY-top+1)*(maxX-left+1);
    // calculate the number of pixels in the region

    result:=((red div Area) and $FF)
    or ((green div Area and $FF) shl 8)
    or ((blue div Area and $FF) shl 16);
    end;

    procedure SetReference(var bitmap1: graphics.tbitmap;BR: BitmapReference);
    {
    BR becomes a reference to bitmap1.
    }
    var
    y: cardinal; // y-coordinate or row number
    begin
    BR.Height:=bitmap1.height;
    BR.Width:=bitmap1.Width;
    SetLength(BR.Rows,BR.Height);
    for y:=BR.Height-1 downto 0 do
    // loop through rows
    begin
    // for each row, copy the address of pixel data in that row
    BR.Rows[y]:=Bitmap1.scanline[y];
    end;
    end;

    procedure FreeBitmapReference(var BR: BitmapReference);
    begin
    BR.Rows:=nil; // free the array of pointers
    end;

    function SetExtention(fn,extention: string): string;
    {
    purpose: setting the extention on the end of a file name
    }
    var
    pos1: integer;
    begin
    for pos1:=length(fn) downto 1 do
    begin
    if fn[pos1]='.' then
    break; // break the for-loop
    end;
    if pos1=1 then // if no '.' was found
    result:=fn+'.'+extention
    else
    result:=copy(fn,1,pos1)+extention;
    // replace the extention
    end; // end of SetExtention

    end.
    [/code]
  • : I still haven't found anyone that can figure out the error.
    :
    : Here is my code. I know it is a lot(about 330 lines) but I hope someone is willing to figure out the problem.
    :
    : [code]
    : unit JGCompression;
    : {
    : Author: Josh Greig
    : Date: June 30, 2004
    : Purpose:
    : Providing methods for manipulating JG compressed image files.
    : }
    : interface
    : uses sysutils,graphics;
    :
    : function SaveBitmapToJGCF(bitmap1: graphics.tbitmap;fn: string): boolean;
    : function SetExtention(fn,extention: string): string;
    :
    : const
    : Threshold = 100;
    : // a threshold for deciding whether to split a region or not to
    :
    : implementation
    :
    : type
    : pixel = tColor;
    : PixelArray = array[0..$FFFF] of pixel;
    : pPixelArray = ^PixelArray;
    :
    : Colour24 = record
    : red,green,blue: byte;
    : end;
    :
    : // define a record that will basically point to all the pixel data in a bitmap
    : BitmapReference = record
    : Width,Height: Cardinal; // dimensions of the bitmap referred to
    : Rows: array of pPixelarray; // dynamic array of pointers
    : end;
    : // this reference can allow for faster access to the pixel data in a tbitmap object
    : // this is very useful for the pixel manipulation required by the compression algorithms
    :
    : procedure SaveCompressedPixelData(var f: file; bitmap1: tbitmap);
    : procedure SaveCompressedRegion(var f: file;
    : BR: BitmapReference;startX,startY: cardinal;N: byte);
    : procedure SetReference(var bitmap1: tbitmap;BR: BitmapReference);
    : function GetAverageColour(var BR: BitmapReference;top,left,size: cardinal): tColor;
    : function GetColourVarience(var BR: BitmapReference;top,left,size: cardinal;var avgc: tcolor): real;
    : procedure FreeBitmapReference(var BR: BitmapReference);
    :
    :
    : function SaveBitmapToJGCF(bitmap1: tbitmap;fn: string): boolean;
    : {
    : purpose:
    : storing a bitmap as a JGC file
    : inputs:
    : bitmap = the bitmap to save
    : fn = name of file
    : }
    : var
    : f: file;
    : w: word; // a word to temperarily store some values
    : b: byte; // temperarily stores 8-bit values
    : const
    : FormatKey = 'JGCF';
    : begin
    : result:=true;
    : // assign file
    : AssignFile(f,fn);
    :
    : try
    : // rewrite file with a record size of 1
    : Rewrite(f,1);
    : except
    : on EAbstractError do // this exception needs to be changed
    : begin
    : result:=false; // indicate failure
    : end;
    : end; // end of try-except statement
    : if result then // if the exception did not occur
    : begin
    : // write the header section
    : begin
    : BlockWrite(f,FormatKey,4);
    : w:=0;
    : BlockWrite(f,w,2); // write the file format version number
    : w:=bitmap1.width;
    : BlockWrite(f,w,2); // write the width
    : w:=bitmap1.height;
    : BlockWrite(f,w,2); // write the height
    : b:=24; // bits per pixel
    : BlockWrite(f,b,1); // write the bits per pixel
    : // now, the header has been written to file
    : end;
    : bitmap1.pixelformat:=pf32bit;
    : // make sure the pixel data is stored using 32 bits for every pixel
    : // this assumption is used when using direct pixel data access using pointers
    :
    :
    : // write the compressed pixel data portion
    : SaveCompressedPixelData(f,bitmap1);
    :
    :
    : // close file
    : Close(f);
    : result:= true; // indicate success
    : end;
    : end;
    :
    : procedure SaveCompressedPixelData(var f: file; bitmap1: tbitmap);
    : {
    : purpose: compresses data and stores it in the file
    : assumptions:
    : f is already open in a binary writing mode.
    : }
    : var
    : rx,ry: cardinal;
    : maxRX,maxRY: cardinal;
    : BR: BitmapReference;
    : begin
    : // make a reference to the bitmap so the data can be manipulated more efficiently
    : SetReference(bitmap1,BR);
    :
    : // calculate the number of regions
    : maxRX:=(BR.width shl 4)+1;
    : maxRY:=(BR.Height shl 4)+1;
    : {
    : "shl 4" is a binary shift left 4 digits.
    : This is the same as deviding by 16 but more efficient.
    : }
    : for rY:=0 to maxRY do
    : // loop through rows of regions
    : begin
    : for rX:=0 to maxRX do
    : // loop through each region in each row
    : begin
    : // for each 16 by 16 region, compress it and save the data to file
    : SaveCompressedRegion(f,BR,rX shl 4,rY shl 4,16);
    : end;
    : end;
    : FreeBitmapReference(BR);
    : end;
    :
    : procedure SaveCompressedRegion(var f: file;
    : BR: BitmapReference;startX,startY: cardinal;N: byte);
    : {
    : purpose: compressing information for a N by N pixel region
    : inputs:
    : f = file being written to (must be open in a binary writing mode)
    : BR = a reference to the bitmap being compressed
    : startX = coordinate of the left side of the region being compressed
    : startY = coordinate of the top side of the region being compressed
    : }
    : var
    : c: tcolor;
    : c24: Colour24;
    : p: pPixelArray;
    : begin
    : if (N=1) then// base case (individual pixel)
    : begin
    : p:= BR.Rows[startY];
    : c := p[startX];
    : c24.red := c;
    : c24.green := c shr 8;
    : c24.blue := c shr 16;
    :
    : BlockWrite(f,N,1);
    : BlockWrite(f,c24,3);
    : end
    : else // general case
    : begin
    : if GetColourVarience(BR,top,left,N,c)>threshold then
    : begin // if lots of detail is in the region
    : // devide it up more
    : N:= N shr 1; // devide size by 2.
    :
    : // compress each subregion separately
    : SaveCompressedRegion(f,BR,startX,startY,N);
    : SaveCompressedRegion(f,BR,startX+N,startY,N);
    : SaveCompressedRegion(f,BR,startX,startY+N,N);
    : SaveCompressedRegion(f,BR,startX+N,startY+N,N);
    : end
    : else // if very little detail is in the region
    : begin
    : // define the colour for the region
    : c24.red := c;
    : c24.green := c shr 8;
    : c24.blue := c shr 16;
    : BlockWrite(f,N,1); // define the size of the square
    : BlockWrite(f,c24,3); // define the colour for the square
    : end;
    : end;
    : end;
    :
    : function GetColourVarience(var BR: BitmapReference;top,left,size: cardinal;avgc: tcolor): real;
    : {
    : purpose:
    : calculating the varience in colours throughout a region
    : }
    : var
    : r,g,b: byte; // average red, green, and blue values
    : c: tcolor; // average(mean) colour
    : maxX,maxY: cardinal; // x and y boundaries
    : x,y: cardinal; // coordinates of pixels
    : Area: cardinal; // number of pixels in region
    : total: double; // total of all variances
    : begin
    : maxX:=top+size-1;
    : maxY:=left+size-1;
    : if (maxX>=BR.Width) then
    : maxX:=BR.Width-1;
    : if (maxY>=BR.Height) then
    : maxY:=BR.Height-1;
    : avgc:=GetAverageColour(BR,top,left,size);
    :
    : // extract the red, green and blue values
    : r:=avgc;
    : g:=avgc shr 8;
    : b:=avgc shr 16;
    :
    : total:=0;
    : for y:=maxY downto top do
    : // loop through the rows of pixels
    : for x:=maxX downto left do
    : begin
    : c:=BR.Rows[y][x];
    : total:=total+
    : sqr((c and $FF)-r)+ // z-score squared
    : sqr((c shr 8 and $FF)-g)+ // z-score squared
    : sqr((c shr 16 and $FF)-b); // z-score squared
    : end;
    : Area:=(maxY-top+1)*(maxX-left+1);
    : result:=total/3/Area;
    : end;
    :
    : function GetAverageColour(var BR: BitmapReference;top,left,size: cardinal): tColor;
    : {
    : purpose: calculating the average colour for a square region
    : inputs:
    : BR = reference to the bitmap containing these picels being averaged
    : top = top of the region
    : left = left of the region
    : size = length of a side of the square region(size must not be 0)
    : }
    : var
    : red,green,blue: cardinal;
    : Area: cardinal;
    : c: tcolor;
    : x,y: cardinal;
    : maxX,maxY: cardinal;
    : begin
    : // initialize the values to 0 before counting up all red, green, and blue values
    : red:=0;
    : green:=0;
    : blue:=0;
    : maxX:=left+size-1;
    : maxY:=top+size-1;
    :
    : if (BR.Height<=maxY) then // if region overlaps bottom of bitmap
    : maxY:=BR.Height-1;
    : if (BR.Width<=maxX) then // if region overlaps right side of bitmap
    : maxX:=BR.Width-1;
    :
    : for y:=maxY downto top do
    : for x:=maxX downto left do
    : begin
    : // get the colour of the pixel
    : c := BR.rows[y][x];
    :
    : // add the red, green, and blue values to the counters
    : red:=red+(c and $FF);
    : green:=green+(c shr 8 and $FF);
    : blue:=blue+(c shr 16 and $FF);
    : end;
    : Area:=(maxY-top+1)*(maxX-left+1);
    : // calculate the number of pixels in the region
    :
    : result:=((red div Area) and $FF)
    : or ((green div Area and $FF) shl 8)
    : or ((blue div Area and $FF) shl 16);
    : end;
    :
    : procedure SetReference(var bitmap1: graphics.tbitmap;BR: BitmapReference);
    : {
    : BR becomes a reference to bitmap1.
    : }
    : var
    : y: cardinal; // y-coordinate or row number
    : begin
    : BR.Height:=bitmap1.height;
    : BR.Width:=bitmap1.Width;
    : SetLength(BR.Rows,BR.Height);
    : for y:=BR.Height-1 downto 0 do
    : // loop through rows
    : begin
    : // for each row, copy the address of pixel data in that row
    : BR.Rows[y]:=Bitmap1.scanline[y];
    : end;
    : end;
    :
    : procedure FreeBitmapReference(var BR: BitmapReference);
    : begin
    : BR.Rows:=nil; // free the array of pointers
    : end;
    :
    : function SetExtention(fn,extention: string): string;
    : {
    : purpose: setting the extention on the end of a file name
    : }
    : var
    : pos1: integer;
    : begin
    : for pos1:=length(fn) downto 1 do
    : begin
    : if fn[pos1]='.' then
    : break; // break the for-loop
    : end;
    : if pos1=1 then // if no '.' was found
    : result:=fn+'.'+extention
    : else
    : result:=copy(fn,1,pos1)+extention;
    : // replace the extention
    : end; // end of SetExtention
    :
    : end.
    : [/code]
    :
    Procedure declarations within the implementation section must be either marked by the "forward" directive, or must be implemented after the declaration. So the first SaveCompressedPixelData() must include the forward directive, as well as the other forwarded declarations.
  • : :
    : Procedure declarations within the implementation section must be either marked by the "forward" directive, or must be implemented after the declaration. So the first SaveCompressedPixelData() must include the forward directive, as well as the other forwarded declarations.
    :

    It works!

    thanks a lot

    netgert suggested that in an email before and I tried using forward with one function but it gave the same unsatisfactory forward error for that function. I just tried using the forward with all functions and it works fine now.
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories