ALPRIM Ver 1.0 reference manual

Table of Contents
  1. Layer and CLUSTER structures
    1. Layer
    2. PRIMITIVE structure
    3. CLUSTER structure
    4. ALTABLE structure
    5. Library File Structure
  2. Specifics
    1. Constructing and destroying instances
      Updated on November 6, 2000 In addition to the license code, a license code file can also be specified.
    2. Configuring Images
    3. Bitmap to Primitive Conversion
    4. Cluster Extraction
    5. Cluster Angle Estimation
    6. Bounding Box Calculation for Clusters
    7. Table Extraction
    8. Primitive Selection Operations
    9. Character Selection by Straight Line
    10. Noise Selection
    11. Selection of Primitives in Contact with Frames
    12. Interlayer Movement of Primitives
    13. Layer Deletion
    14. Getting the Bitmap of the Layer
    15. Getting the Bitmap of the Cluster
    16. Getting the Bitmap of the Layer at Arbitrary Magnifications
    17. Primitive Feature Calculation
    18. Override (Cluster Extraction)
    19. Override (Interlayer Movement of Primitives)
    20. Override (Character Definition)
    21. Undo Function Support Functions (Added on October 10, 2000)
  3. Updated on July 13, 2000
    1. New Features Added by CJocrPrimEX Class
    2. Parameter File Specifications
  4. Updated on October 10, 2000
    1. Updates to CLUSTER Structure
    2. Updates to ABSTRACTPARAMETER Structure
    3. Addition of ABSTRACTPARAMETER::mcontrol Flag
    4. Angle Estimation by CJocrPrimEX Class
    5. Additional Functionality for Bounding Box Calculation of Clusters
    6. Addition of Undo Function Support Functions (Specifics: 21)
    7. Addition of DLL and Header Files
    8. Angle Estimation by CJocrPrimRD Class
  5. Updated on July 25, 2001
    1. Updates to PRIMFEATURE Structure
    2. Deletion of Manual Description of mgetvalidclusternum Function
  6. Updated on July 26, 2002
    1. Getting the Total Number of Bytes of Memory Allocated by the Library
    2. Primitives Editing Function
    3. Undo Function Support Functions (New Version)
    4. Addition of Interlayer Movement Function
    5. Addition of Initialization Check Function
    6. Getting the Bitmap of the Primitive
  7. Updated on July 31, 2002
    1. Extraction of Dashed Lines
    2. Estimating Character Extraction Parameters
  8. Updated on April 1, 2003
    1. Raster Editing Commands


manual homepage

user's manual


1."layer" and "CLUSTER" structure


1.1 Layer

In CJocrPrim, there are 255 layers ranging from 0 to 254. When a bitmap is converted into primitives, all primitives are stored in Layer 0. With batch processing functions such as user operations and noise removal, primitives can be moved to Layer 255, and operations such as bitmap inverse conversion, deletion, character recognition, and vector conversion can be performed on each layer.

For example, let's say only primitives corresponding to characters are moved to Layer 1. When Layer 0 is inverse converted to a bitmap, it becomes a bitmap image excluding characters. When Layer 1 is inverse converted to a bitmap, it becomes a bitmap image consisting only of the character parts.

Table of Contents


1.2 PRIMITIVE Structure


The structure of the primitive is as follows. Developers usually do not directly access this structure, except when developing subclasses of the text block extraction class (such as CJocrPrim class or CJocrPrim class). It is provided for reference purposes.
// Primitive feature structure
typedef struct _PRIMFEATURE {
    int                pixel;        // Area of the primitive region
    int                length;       // Perimeter of the primitive region
    double             cx;           // Centroid x
    double             cy;           // Centroid y

// featureex added on July 25, 2001
// Always NULL as of July 25, 2001. The content of the structure is also undetermined (no problem with compilation)
	PRIMFEATUREEX*	featureex;	     // Extended features (intended for future expansion, such as circularity, line width, second moment features, etc.)
} PRIMFEATURE;


typedef struct _PRIMITIVE {
    unsigned char   layer;      // Layer number of the primitive
    unsigned char   undo;       // Original layer of the primitive
    unsigned char   unused;     // 1 when not in use
    unsigned char   flag;       // General control flag
    int             xmin;       // Upper-left coordinate of the primitive region (if the positive direction of the Y-axis is down)
    int             ymin;
    int             xmax;       // Bottom-right coordinate of the primitive region (if the positive direction of the Y-axis is down)
    int             ymax;
    PRIMFEATURE*    feature;
} PRIMITIVE;
Table of Contents

1.3 CLUSTER Structure


The structure of the cluster is as follows:
typedef struct _CLUSTER {
    int             num;        // number of elements in the prim array
    int             validnum;   // number of valid elements in the prim array
    int             max;        // size of the prim array
    PRIMITIVE**     pprim;
    unsigned char   flag;       // 0...normal cluster (to be fused)
                                // 1...isolated cluster (not to be fused)
    unsigned char   loc;        // 0...far from the frame: unrelated to the adjacent segment clusters
                                // 1...near the top frame: to be fused with the top segment cluster
                                // 2...near the bottom frame: to be fused with the bottom segment cluster
                                // 4...near the left frame: to be fused with the left segment cluster
                                // 8...near the right frame: to be fused with the right segment cluster
    unsigned char   unused;     // 0...used
                                // 1...not used
    unsigned char   reserved2;
    short           line;       // line in case of a table
    short           column;     // column in case of a table
    PRIMITIVE*      parent;     // the primitive (such as a table) to which the cluster belongs
    long            pwidthmax;  // maximum width of elements inside the cluster
    long            pheightmax; // maximum height of elements inside the cluster
    long            xmin;       // coordinates of the top-left point of the cluster (when the positive Y-axis is downwards)
    long            ymin;
    long            xmax;       // coordinates of the bottom-right point of the cluster (when the positive Y-axis is downwards)
    long            ymax;

// angle added on October 10, 2000
    double          angle;      // estimated or specified angle of the cluster (for additional functionality)
    void*           pdata;      // reserved
} CLUSTER;
Table of Contents

1.4 ALTABLE Structure


The structure of the table is as follows.
typedef struct _ALTABLE {
    int             num;        // number of clusters
    int             max;        // size of cluster array
    CLUSTER**       ppcluster;  // cluster array
    PRIMITIVE*      prim;       // primitive corresponding to the table
    long            xmin;       // top-left (if the positive y-axis is downwards) coordinate of the table
    long            ymin;
    long            xmax;      // bottom-right (if the positive y-axis is downwards) coordinate of the table
    long            ymax;
} ALTABLE;

Table of Contents

reference manual Added DLL on October 10, 2000

1.5 Library File Structure

Class Name CJocrPrimRD or CJocrPrimEX or CJocrPrim
Header Files ocrdef.h
ocrco.h
primitive.h
cjocrprim.h
absparam.h
cjocrprimex.h
cjocrprimrd.h
errcode.h
Required LIB NGKOCR4.LIB
Required DLL NGKOCR1.DLL
NGKOCR2.DLL
NGKOCR4.DLL
ALVEC.DLL
ALPOLYGON.DLL
Compile Constant USENGKDLL4

2.Detail


2.1 Construction and Destruction of Instances

Table of Contents
Instantiate by specifying a 20-digit code supplied by the library licensee.
Alternatively, specify the path of the license code file supplied by the library licensee.
CJocrPrim* prim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
....
delete prim;
Alternatively,

CJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
....
delete prim;
Check if it is initialized using mchecklimit as follows. If the library cannot be used due to reasons such as expiration of the license code or hardware lock failure, the return value is 1. If an unlimited license file is used, there is no need for a check.
        if(mpjocrprim->mchecklimit(3)) {
            delete mpjocrrecognize;
            mpjocrrecognize = NULL;
        }
//      int         mchecklimit(int level)
//      Input:
//          int     level;      // Always 3 for library users
//      Returns 1 if not initialized

Table of Contents


2.2 Setting Images

Table of Contents

After creating an instance, set the starting address of the document image, background bit value, width, and height.
If the image is not on byte boundary, use the version of the function that specifies the number of bytes per scan line.
// Setting the document image
    void msetdocument(unsigned char* buffer, int background, int width, int height);
// Specifying the scan line size
    void msetdocument(unsigned char* buffer, int background, int width, int scanlinesize, int height);
    Input
    unsigned char*  buffer;         // starting address of the image
    int             background;     // background bit value (0...bit0 is background / 1...bit1 is background)
    int             width;          // width of the image (in pixels)
    int             scanlinesize;   // number of bytes per scan line
    int             height;         // height of the image (in pixels)

Table of Contents


2.3 Bitmap to Primitive Conversion

Table of Contents

Converts the document image, which is a bitmap data, into primitive data. It is also possible to convert only a part of the bitmap data. Normally, connected foreground regions that are connected by four directions are considered as primitives, but if the function has "8", the foreground regions connected by eight directions are considered as primitives.

Connected by 4 or 8 directions
// Bitmap to Primitive Conversion
// Conversion of the entire bitmap
    int makeprim();
    int makeprim8();
// Specify a rectangular region (not inclined) and only convert the interior
    int makeprim(int x1, int y1, int x2, int y2);
    int makeprim8(int x1, int y1, int x2, int y2);
    Input
    int        x1, y1;    Upper-left coordinates of the rectangle
    int        x2, y2;    Lower-right coordinates of the rectangle
    Return Value
        0................ Successful completion
        MEMORY_SHORTAGE... Insufficient memory

// Specify an arbitrary convex quadrangle region and only convert the interior
// Can also be an arbitrarily angled rectangle
    int makeprim(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
    int makeprim8(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
    Input
    int        x1, y1;   Four coordinates of the convex quadrangle (order does not matter)
    int        x2, y2;
    int        x3, y3;
    int        x4, y4;
    Return Value
        0............... Successful completion
        MEMORY_SHORTAGE. Insufficient memory
// Get the number of primitives
    int mgetvalidprimitivenum();
// Get the number of primitives on a layer
    int mgetvalidprimitivenum(int layer);
    Return Value
        Number of converted primitives

Table of Contents


example
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// Initialize the library by specifying a 20-digit code supplied by the licenser or the path to a license code file.
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// If using a license code path, use: CJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight);        // Monochrome image with background as 0 and foreground as 1
ret = pjocrprim->makeprim();
if(ret < 0) {
    Error;
}
delete pjocrprim;
...

Table of Contents


2.4 Cluster extraction

Table of Contents

Multiple primitives are extracted as clusters. To determine the criteria for clustering, specify the upper and lower limits of four parameters: size of each primitive, distance between each primitive, size of each cluster, and number of primitives that make up each cluster.
Cluster extraction can be fully customized by overriding virtual functions. For more details, please refer to Override (Cluster extraction).
// Setting dpi
// Set dpi to convert points to pixels
    void msetdpi(int dpi);
    Input
        int         dpi;        // resolution
// Setting font size
// Specify maximum and minimum primitive sizes
    void msetpoint(int maxpoint,int minpoint);
    Input
        int         maxpoint;   // maximum primitive size (above minpoint points (1 inch = 72 points))
        int         minpoint;   // minimum primitive size (at least 1 point (1 inch = 72 points))
// Setting document type
// The interpretation of the number of points in slanted cases changes
// If no slanting is specified, the angle estimate is limited to either 0 degrees or 90 degrees.
    void msetvflag(int vflag);
    Input
       int         vflag;       // 1...horizontal writing only (bit0)
                                // 2...vertical writing only (bit1)
                                // 3...horizontal writing + vertical writing (no slanting)
                                // 4...slanting (values of bit0 and bit1 are ignored)
// Setting number of characters per line, number of blocks per line, character spacing, line spacing
// Corresponds to specifying the size of the cluster and the distance between the primitives that make up one cluster
// charperline×lineperblock becomes the maximum number of primitives in one cluster
    void msetcharline(int charperline,int lineperblock,int charspace,int linespace);
    Input
        int         charperline;    // number of characters per line
        int         lineperblock;   // number of lines per paragraph
        int         chaspace;       // distance between primitives in the horizontal direction (or vertical direction in vertical writing)
                                    // (points (1 inch = 72 points))
        int         linespace;      // distance between primitives in the vertical direction (or horizontal direction in vertical writing)
                                    // (points (1 inch = 72 points))
// Minimum number of characters in one cluster
// Equivalent to the number of primitives included in one cluster
    void msetminnum(int aminnum);
    Input
        int         aminnum;    // minimum number of primitives
///////////////////////
// Estimation of minimum and maximum font size
    void minferpoint(int& amin,int& amax,int layer);
    Input
        int         layer;      // estimation within the layer
    Output
        int&        amin;       // minimum font size (points (1 inch = 72 points))
        int&        amax;       // maximum font size (points (1 inch = 72 points))
/////////////////
// Cluster extraction
// Extract clusters based on the above parameters
    int mabstractcluster(int from,int to);
    Input
        int         from;      // source layer to move from
        int         to;        // destination layer to move to
    Return Value
        0 or more...........number of extracted clusters
        MEMORY_SHORTAGE...running out of memory
// Getting extracted cluster data
// The calling side needs to allocate buffer pcluster
// The internal cluster area is kept statically, but it also includes invalid clusters that were discarded during calculation, so this function is provided to extract only valid clusters.
    void mgetvalidcluster(CLUSTER* pcluster);
    Input
        CLUSTER*        pcluster;       buffer to store clusters
                                        sizeof(CLUSTER) * number of extracted clusters
    Output
        CLUSTER*        pcluster;       extracted cluster data

Table of Contents


example
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// Initialize the library by specifying a 20-digit code supplied by the licenser or the path to a license code file
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// If using the license code path: CJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight);      // Monochrome image with 0 for background and 1 for foreground
ret = pjocrprim->makeprim();
if(ret < 0) {
    Error;
}
// Extract clusters
int clusternum = pjocrprim->mabstractcluster(0,1);
if(clusternum < 0) {
    Error;
}
CLUSTER* pcluster = (CLUSTER*)malloc(sizeof(CLUSTER) * clusternum);
if(pcluster) {
    // Get clusters
    mgetvalidcluster(pcluster);
}
delete pjocrprim;
...

Table of Contents


2.5 Cluster Angle Estimation

Table of Contents

We estimate the angle of a cluster when considering the extracted cluster as paragraphs of text. The angle is comprehensively estimated based on the connection angles between each primitive and the angle of the minimum area rectangle enclosing the cluster.
The angle is measured in radians and is positive clockwise when the y-axis is downwards and positive counterclockwise when the y-axis is upwards.
// Cluster angle estimation calculation
    void mcalcangle(CLUSTER* pcluster, double& angle);
    Input
        CLUSTER* pcluster: Cluster (obtained with mgetvalidcluster)
    Output
        double& angle: Estimated angle (in radians)
The angle is estimated within ±5 degrees range from the specified angle. Use this function when estimating the angle based on a user-specified angle in functions like moveprimlinestring.
// Cluster angle estimation calculation
    void mcalcanglespec(CLUSTER* pcluster, double& angle);
    Input
        CLUSTER* pcluster: Cluster (obtained with mgetvalidcluster)
        double& angle: Specified angle (in radians)
    Output
        double& angle: Estimated angle (in radians)

Table of Contents


example
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// Initialize the library by specifying a 20-digit code supplied by the licenser or the path to the license code file
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// Or if providing the path to the license code file, use: CJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata, 0, mwidth, mheight); // Monochrome image with background as 0 and foreground as 1
ret = pjocrprim->makeprim();
if (ret < 0) {
    Error;
}
// Extract clusters (move primitives belonging to clusters to Layer 1)
int clusternum = pjocrprim->mabstractcluster(0, 1);
if (clusternum < 0) {
    Error;
}
CLUSTER* pcluster = (CLUSTER*)malloc(sizeof(CLUSTER) * clusternum);
if (pcluster) {
    // Get clusters
    mgetvalidcluster(pcluster);
    for (int i = 0; i < clusternum; i++) {
        double angle;
        pjocrprim->mcalcangle(pcluster + i, angle); // Angle is the estimated angle (in radians)
                                                    // The actual baseline angle is either angle or angle + π/2
        ....
        ...
    }
}
delete pjocrprim;
...
Table of Contents


2.6 Calculation of Cluster Bounding Box

Table of Contents

This function is used to obtain the bounding box of a cluster. When considering it as a paragraph of text, it is necessary to estimate the position of the baseline (the line below the text for horizontal writing, the line to the right of the text for vertical writing) based on the result of this function.
For example, in horizontal writing:
  1. The lower edge closer to horizontal is the baseline.
  2. The lower edge of the longer side is the baseline.
These criteria can be considered, but there is a possibility of contradiction between these two criteria, making it difficult to estimate with 100% accuracy.
By default, the bounding box returned by this function has the outermost frame of the cluster (text block) placed one pixel outside the frame. If ext is specified as a value greater than or equal to 1.0, the frame will be placed outside the cluster by ext pixels (rounded down to the nearest integer).
The default calculation of the cluster's bounding box is the bounding box that surrounds the minimum bounding rectangle of the primitives that make up the cluster, so in a slanted cluster (text block), the bounding box may be separated from the actual shape.

Slanted frame
As of October 10, 2000, in the calculation of the bounding box, it is now possible to ensure that the bounding box does not separate from the actual shape even in slanted text blocks.

Addition of description regarding the 8th argument (2021/07/04)
This is used to calculate the bounding rectangle of a cluster (text block) after estimation of the angle using Cluster Angle Estimation (mcalcangle) or specifying the angle through user mouse operations, etc.
  1. If the angle is close to horizontal or vertical, the result does not change regardless of the value of recalcflag.
  2. Otherwise, when calculating the bounding box of a slanted frame, there may be a gap between the frame and the characters. If recalcflag is 1, the gap is reduced until it collides with the shape.
  3. If the value of ext in the 7th argument is not 0.0, the frame is scaled. However, scaling is performed after the reduction process based on recalcflag. It is not recommended to make ext negative because it may collide with the character frame.

// The order of the coordinates is as follows.
// [0]           |           [1]
//  +------------+------------+
//  |     2      |      1     |
// -+------------+------------+-axis line
//  |     3      |      4     |
//  +------------+------------+
// [3]           |           [2]
//        Coordinate arrangement by mcalcframe
//        0...Second quadrant with respect to the cluster center
//        1...First quadrant with respect to the cluster center
//        2...Fourth quadrant with respect to the cluster center
//        3...Third quadrant with respect to the cluster center
// Calculating the outer frame of the cluster
    void mcalcframe(CLUSTER* pcl, double angle, double* px, double* py, double& dh, double& dv, double ext = 0.0, int recalcflag);
    Input
    CLUSTER*        pcl;        // Cluster
    double          angle;      // Angle of the axis line (radians)
    double          ext;        // Expand all coordinates by ext pixels outside
                                // The default value is 0.0

// Added functionality on October 10, 2000
    int             recalcflag  // If set to 1, the outer frame will shrink until it touches the primitives
                                // Shrink the gap between the diagonal bounding rectangle and the primitive
                                // The default value is 0
    Output
    double*         px;         // px[4]...Coordinates of the outer frame
    double*         py;         // py[4]...Coordinates of the outer frame
mcalcframe
                                // When the angle of dh is angle (positive if the y-axis direction is downward)
                                                             (positive counterclockwise if the y-axis direction is upward)
    double&         dh;         // Length of the cluster's axis line (not necessarily close to horizontal)
    double&         dv;         // Length of the line intersecting the cluster's axis line vertically (not necessarily close to vertical)

Additional description of code example using mcalcangle/mcalcframe combination (2021/07/04)
The following is an example of code that calculates the coordinates of the external rectangular frame using mcalcangle for angle estimation and mcalcframe after that.
{
//  CLUSTER* pcluster;
//  Assume pcluster is a cluster extracted by some API
	double		angle;
	double		dh,dv;
	double		x[4];
	double		y[4];

	mpjocrprim->mcalcangle(pcluster,angle);         // Calculate angle based on pcluster
	mpjocrprim->mcalcframe(pcluster,angle,x,y,dh,dv,0.0,1); // Calculate x[4], y[4], dh, dv based on pcluster and angle
                                                    // Set recalcflag to 1 to eliminate extra space between the frame and characters even in diagonal cases
//  (x[3],y[3])-(x[2],y[2]) is the baseline of the text line
//  The height (width) of the line is dv
}
Table of Contents


example
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// Initialize the library by specifying a 20-digit code provided by the licenser or the path to a license code file
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// If using a license code file path: CJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight); // Monochrome image with background 0 and foreground 1
ret = pjocrprim->makeprim();
if(ret < 0) {
    Error;
}
// Extract clusters
int clusternum = pjocrprim->mabstractcluster(0,1);
if(clusternum < 0) {
    Error;
}
CLUSTER* pcluster = (CLUSTER*)malloc(sizeof(CLUSTER) * clusternum);
if(pcluster) {
    // Retrieve clusters
    mgetvalidcluster(pcluster);
    for(int i = 0 ; i < clusternum ; i++) {
        double x[4];
        double y[4];
        double dh;
        double dv;
        pjocrprim->mcalcframe(pcluster + i,0,x,y,dh,dv); // Get the bounding box as a rotation angle of 0 degrees
        ....
        ...
    }
}
delete pjocrprim;
...
Contents


2.7 Table Extraction

Table of Contents

Extracts tables. Place it after mabstractcluster. There are two types of tables:
  1. A single cluster enclosed in a frame.
  2. Multiple clusters with each cluster separated by line objects. The outermost frame is not necessary.
Tables can also include shapes other than the usual rectangular cells, such as the following example:

Strange Table
Tables must be individual primitives. The lines do not have to be straight.
///////////////////////
// Table Processing Operations
// Call after cluster extraction (mabstractcluster)
    int mabstracttable(int clusterlayer, int from, int to);
    Input
      int       clusterlayer;       // Layer on which clusters were extracted
      int       from;               // Layer from which to extract the table
      int       to;                 // Destination of the extracted table
    Return
        0 or more..........Number of extracted tables
        MEMORY_SHORTAGE...Insufficient memory
// Get the number of extracted tables
    int         mgettablenum();
// Get the extracted tables
    ALTABLE*    mgettable();        // Points to an internal pointer, so cannot be freed or modified
The address of a cluster belonging to a table is stored in the ALTABLE structure. The line and column to which each cluster belongs to in the table are assigned to the line and column members of the cluster structure. The counting of rows and columns starts from the 1st row and 1st column.
Table of Contents


example
#include    "ocrdef.h"
#include    "ocrco.h"
#include    "cjocrprim.h"
#include    "errcode.h"
...
....
// Initialize library by specifying a 20-digit code provided by the licenser or the path of the license code file
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// If using license code path, initialize library like this: CJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight);      // Monochrome image where background is 0 and foreground is 1
ret = pjocrprim->makeprim();
if(ret < 0) {
    Error;
}
// Extract clusters
ret = pjocrprim->mabstractcluster(0,1);
// Extract tables
ret = pjocrprim->mabstracttable(1,0,1);
int tablenum = pjocrprim->mgettablenum();
if(tablenum) {
    // Get tables
    ALTABLE* ptable = pjocrprim->mgettable();
    ....
}
delete pjocrprim;
...
Table of Contents


2.8 Primitive Selection Operations

Table of Contents

Functions used to select primitives when the user performs operations (such as with a mouse).
// Move primitives intersecting with a rectangle from 'from' to 'to'
    int moveprimrecthook(int x1,int y1,int x2,int y2,int from,int to,int mojiflag);
// Move primitives intersecting with a rectangle from 'from' to 'to' and cluster them
    int moveprimrecthookcluster(int x1,int y1,int x2,int y2,int from,int to,int mojiflag);
    Input
    int             x1,y1;      // Coordinates of rectangle
    int             x2,y2;
    int             from;       // Source layer
    int             to;         // Destination layer
    int             mojiflag;   // If 1, only move primitives that fit within the character size specified by 'msetpoint'
                                // If overridden by Override (Character Definition), prioritized over mojifilter function
    Return Value
    >= 0..........Number of moved primitives
    Negative.............MEMORY_SHORTAGE Memory shortage
// Move primitives intersecting with a diagonal rectangle from 'from' to 'to'
    int moveprimrecthook(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,int from,int to,int mojiflag);
// Move primitives intersecting with a diagonal rectangle from 'from' to 'to' and cluster them
    int moveprimrecthookcluster(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,int from,int to,int mojiflag);
    Input
    int             x1,y1;      // Coordinates of diagonal rectangle (order of coordinates is arbitrary)
    int             x2,y2;
    int             x3,y3;
    int             x4,y4;
    int             from;       // Source layer
    int             to;         // Destination layer
    int             mojiflag;   // If 1, only move primitives that fit within the character size specified by 'msetpoint'
                                // If overridden by Override (Character Definition), prioritized over mojifilter function
    Return Value
    >= 0..........Number of moved primitives
    Negative.............MEMORY_SHORTAGE Memory shortage
// Move primitives fully contained within a rectangle from 'from' to 'to'
    int moveprimrect(int x1,int y1,int x2,int y2,int from,int to,int mojiflag);
// Move primitives fully contained within a rectangle from 'from' to 'to' and cluster them
    int moveprimrectcluster(int x1,int y1,int x2,int y2,int from,int to,int mojiflag);
    Input
    int             x1,y1;      // Coordinates of rectangle
    int             x2,y2;
    int             from;       // Source layer
    int             to;         // Destination layer
    int             mojiflag;   // If 1, only move primitives that fit within the character size specified by 'msetpoint'
                                // If overridden by Override (Character Definition), prioritized over mojifilter function
    Return Value
    >= 0..........Number of moved primitives
    Negative.............MEMORY_SHORTAGE Memory shortage
// Move primitives fully contained within a diagonal rectangle from 'from' to 'to'
    int moveprimrect(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,int from,int to,int mojiflag);
// Move primitives fully contained within a diagonal rectangle from 'from' to 'to' and cluster them
    int moveprimrectcluster(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,int from,int to,int mojiflag);
    Input
    int             x1,y1;      // Coordinates of diagonal rectangle (order of coordinates is arbitrary)
    int             x2,y2;
    int             x3,y3;
    int             x4,y4;
    int             from;       // Source layer
    int             to;         // Destination layer
    int             mojiflag;   // If 1, only move primitives that fit within the character size specified by 'msetpoint'
                                // If overridden by Override (Character Definition), prioritized over mojifilter function
    Return Value
    >= 0..........Number of moved primitives
    Negative.............MEMORY_SHORTAGE Memory shortage
// Move primitives that intersect with a line from 'from' to 'to'
    int moveprimline(int x1,int y1,int x2,int y2,int from,int to);
// Move primitives that intersect with a line from 'from' to 'to' and cluster them
    int moveprimlinecluster(int x1,int y1,int x2,int y2,int from,int to);
    Input
    int             x1,y1;      // Starting point of the line
    int             x2,y2;      // End point of the line
    int             from;       // Source layer
    int             to;         // Destination layer
    Return Value
    >= 0..........Number of moved primitives
    Negative.............MEMORY_SHORTAGE Memory shortage

Table of Contents


2.9 Selecting Text Along a Straight Line

Table of Contents

Selects the text along a line specified by two points and moves it from "from" to "to". It also clusters the selected text. The function moves only primitives that fit within the text size specified by "msetpoint", but if mojifilter function is overridden in the character definition override, it takes precedence.

// Moves primitives that intersect with the line + primitives included in the rectangle formed by the primitives from "from" to "to"
    int moveprimlinestring(int x1, int y1, int x2, int y2, int from, int to, double* px, double* py);
    Input
    int             x1, y1;      // Starting point of the line
    int             x2, y2;      // End point of the line
    int             from;       // Source layer
    int             to;         // Destination layer
    double*         px;         // Address of an array of size sizeof(double) * 4 (for operation check)
    double*         py;         // Address of an array of size sizeof(double) * 4 (for operation check)
    Return Value
        Greater than or equal to 0.................. Number of moved primitives
        MEMORY_SHORTAGE...Insufficient memory

Sample Code
Selects and estimates the inclination of the text along a line and calculates the bounding box.
#include    "ocrdef.h"
#include    "ocrco.h"
#include    "cjocrprim.h"
#include    "errcode.h"
...
....
// Initialize the library by specifying a 20-digit code supplied by a license sensor or a path to a license code file
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// If using a license code file path, use CJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight);      // Monochrome image where the background is 0 and the foreground is 1
ret = pjocrprim->makeprim();
if(ret < 0) {
    // Error handling
}
...
// Specify the coordinates from (x1, y1) to (x2, y2) using the mouse or other input method
...
double  x[4];
double  y[4];
ret = pjocrprim->moveprimlinestring(x1, y1, x2, y2, from, to, x, y);
if(ret > 0) {
        CLUSTER cluster;
        pjocrprim->mgetvalidcluster(&cluster);
        double  angle;
        angle = atan2((double)(y2 - y1), (double)(x2 - x1));
        // Estimate the angle within ± 5 degrees from the user-specified line angle
        pjocrprim->mcalcanglespec(&cluster, angle);
        double  dh, dv;
        // Calculate the bounding box (bounding box of the primitives' outer frame)
        pjocrprim->mcalcframe(mpcluster, angle, x, y, dh, dv);
        ...
}
delete pjocrprim;
...
Table of Contents


2.10 Selecting Noise

Table of Contents
// Move noise to layer
    int movenoise(int xsize,int ysize,int from,int to);
    Input
    int         xsize;          // Width up to xsize pixels and height up to ysize pixels
    int         ysize;          // to process as noise
    int         from;           // Source layer
    int         to;             // Destination layer
    Return
    Greater than or equal to 0..........Number of primitives moved
    Negative.............MEMORY_SHORTAGE Not enough memory

Table of Contents


example
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// Initialize the library by specifying a 20-digit code or the path to a license code file supplied by the licenser.
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// If using the path to the license code file, use CJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight);        // Monochrome image where 0 represents background and 1 represents foreground
ret = pjocrprim->makeprim();
if(ret < 0) {
    Error;
}
// Noise selection
pjocrprim->movenoise(7,7,0,1);  // Select 4-connected bit 1 regions with up to 7 pixels in both vertical and horizontal directions as noise
                                // Move the primitives corresponding to noise to layer 1
// Noise removal
pjocrprim->mdeleteprim(1);      // Delete the primitives in layer 1
                                // Reflect the changes in the original data
delete pjocrprim;
...
Table of Contents


2.11 Selection of primitives that touch the frame

Table of Contents
// Move primitives that touch the outermost frame to the layer
    int movetouchframe(int from, int to);
    Input
        int        from;        // Source layer
        int        to;          // Destination layer
    Output
    0 or more..........Number of moved primitives
    Negative.............MEMORY_SHORTAGE Out of memory

Table of Contents


example
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// Initialize the library by specifying a 20-digit code supplied by the licenseor or the path to the license code file
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// If using a license code path, use this: CJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata,0,mwidth,mheight);        // monochrome image with background 0 and foreground 1
ret = pjocrprim->makeprim();
if(ret < 0) {
    Error;
}
// Select primitives that touch the frame
pjocrprim->movetouchframe(0,1);    // Move primitives that touch the outermost perimeter to layer 1
// Remove primitives that touch the frame
pjocrprim->mdeleteprim(1);         // Delete primitives in layer 1
                                   // Also update the original data
delete pjocrprim;
...
Table of Contents


2.12 Moving Primitives Between Layers

Table of Contents
// Move primitives from layer 'from' to layer 'to'
    int moveprim(int from = 0, int to = 1);
    Input
        int from;        // Source layer
        int to;          // Destination layer
    Return
        Number of primitives moved
// Move primitives from layer 'from' to layer 'to' with rectangle specification
    int moveprimloc(int x1, int y1, int x2, int y2, int from, int to);
    Input
        int x1, int y1, int x2, int y2; // (x1,y1)-(x2,y2) Left upper corner and right lower corner coordinates of rectangle
    Return
        Number of primitives moved
// Move primitives with pixel value amin <= pixel <= amax from layer 'from' to layer 'to'
    int moveprimpixel(int amin, int amax, int from = 0, int to = 1);
    Input
        int amin, int amax;              Minimum and maximum area of the primitive
    Return
        Number of primitives moved
// Move primitives with area amin <= area <= amax, heightmin <= height <= heightmax, widthmin <= width <= widthmax from layer 'from' to layer 'to'
    int moveprimsizepixel(int areamin, int areamax, int widthmin, int heightmin, int widthmax, int heightmax, int from, int to);
    Input
        int areamin, int areamax;    Range of area (in square pixels)
        int widthmin, heightmin;     Minimum width and height (in pixels)
        int widthmax, heightmax;     Maximum width and height (in pixels)
    Return
        Number of primitives moved

Table of Contents


2.13 Delete Layer

Table of Contents
// Remove primitives on the layer and reflect it in the original image
    void mdeleteprim(int layer);
    Input:
        int        layer;        // Layer to move to

Table of Contents


2.14 Get Bitmap of Layer

Table of Contents

Only available in monochrome.

// Primitive -> Bitmap conversion
// The width and height are the same as the original document
// The buffer should be allocated, managed, and freed by the calling function
// Input:
//     int             layer;      0 to 255...the layer to convert to bitmap
// Output:
//     unsigned char* pdata;       the bitmap
void makebitmap(int layer, unsigned char* pdata);

Table of Contents


2.15 Get Bitmap of a Cluster

Table of Contents

There may be primitives within the rectangle surrounding the cluster that do not belong to the cluster. By using this function, you can obtain only the bitmap of the primitives that belong purely to the cluster.
This function is called before processing such as character recognition.

// Buffer management is done internally in the library
// Input
//    CLUSTER*          pcluster;   Cluster
//    double            angle;      Rotation angle
// Output
//    unsigned char*&   pdata;      Bitmap
//    int&              width;      Width of the bitmap (in pixels)
//    int&              height;     Height of the bitmap (in pixels)
// Get Bitmap of a Cluster
void makebitmapcluster(CLUSTER* pcluster,unsigned char*& pdata,int& width,int& height);
// Return the bitmap of the primitives that belong to the cluster, rotated by the angle in radians
// Get Bitmap of a Cluster (angle rotation)
void makebitmapcluster(CLUSTER* pcluster,double angle,unsigned char*& pdata,int& width,int& height);

Table of Contents


example
#include "ocrdef.h"
#include "ocrco.h"
#include "cjocrprim.h"
#include "errcode.h"
...
....
// Initialize the library by specifying the 20-digit code supplied by the licenser or the path of the license code file
CJocrPrim* pjocrprim = new CJocrPrim("ABCDEFGHJKLMNPQ23456");
// If using the license code path, use: CJocrPrim* prim = new CJocrPrim("C:\\Program Files\\Foo\\primitive.kcd");
pjocrprim->msetdocument(mdata, 0, mwidth, mheight); // Monochrome image with background=0 and foreground=1
ret = pjocrprim->makeprim();
if(ret < 0) {
    Error;
}
// Move the primitive to layer 1 based on user operation
// Move the primitives within the diagonal rectangle from from to to + cluster the moved primitives
pjocrprim->moveprimrecthookcluster(x1, y1, x2, y2, x3, y3, y4, y4, 0, 1);
// Get the cluster
// Retrieve the bitmap of the cluster (rotated by angle radians)
double angle = atan2((double)(y2 - y1), (double)(x2 - x1));
mpjocrprim->makebitmapcluster(mpjocrprim->mgetcluster(), angle, pdata, width, height);
// The pdata array will contain width x height pixel data
// The rectangle (x1, y1)-(x2, y2) will be rotated angle degrees to be horizontal
delete pjocrprim;
...
Table of Contents


2.16 Get the bitmap of a layer with arbitrary magnification

Table of Contents

There are two ways to obtain the bitmap: in monochrome and in 255-color.

// Input
//      int             layer;      The layer to convert to display data (monochrome only)
//      int             width;      The width of the image to create
//      int             height;     The height of the image to create
//      int             offsetx;    The x-axis offset
//      int             offsety;    The y-axis offset
//      double          mag;        The magnification (1.0 for actual size)
// Output
//      unsigned char*  pdata;  The display data (sufficient size to hold a dib of width × height)
// Monochrome DIB (4-byte boundary)
    void makedispdatadib2(int layer,int width,int height,int offsetx,int offsety,double mag,unsigned char* pdata);
// DIB 255-color image data creation (4-byte boundary)
// The layer belongs to the palette index
    void makedispdatadib255(int width,int height,int offsetx,int offsety,double mag,unsigned char* pdata);

Table of Contents


2.17 Calculation of primitive features

Table of Contents

Calculates features such as area, perimeter, and centroid for all primitives.
Since the calculation of the perimeter and centroid requires a large computational cost, if they are not particularly needed, only the area is calculated using mcalcfeaturepixel.

// Calculation of primitive features
//      int             mcalcfeature();
// Calculation of primitive features (area only)
//      int             mcalcfeaturepixel();

Table of Contents


2.18 Override (Cluster Extraction)

Table of Contents

Override and customize the cluster extraction.

// Apply customization to cluster extraction
//      int             mabstractclusterfilter(int from,int to);
// Functions for override
// Target the ones with return value of 1 for clustering
//      virtual int     mprimitivefilter(PRIMITIVE* prim);
// Combine the ones with return value of 1 into one cluster
//      virtual int     mlocationfilter(PRIMITIVE* prim1,PRIMITIVE* prim2);
// Target the ones with return value of 1 for valid clusters
//      virtual int     mclusterfilter(CLUSTER* pcluster);
Customize the cluster extraction using the three virtual functions for override. To perform override, you need to define a subclass of the CJocrPrim class. In addition, within the override function mlocationfilter, you can use the following function:
// Returns 1 if there is a separator (part of a shape that does not belong to a cluster) between two primitives
//      virtual int     mlocationfilter(PRIMITIVE* prim1,PRIMITIVE* prim2);
Here is an example code for cluster extraction using override:
class CJocrSub : public CJocrPrim {
        public:
                CJocrSub(char* code) : CJocrPrim(alcode){}
                ~CJocrSub(){}
        private:
                int             minpixel;       // Minimum area of primitives
                int             maxpixel;       // Maximum area of primitives
                double  minrate;        // Minimum height/width ratio of primitives
                double  maxrate;        // Maximum height/width ratio of primitives
        private:
                double  mindist;        // Minimum distance between primitives
                double  maxdist;        // Maximum distance between primitives
        private:
                int             mleft;          // Cluster position (top-left)
                int             mtop;           // Cluster position (top-left)
                int             mright;         // Cluster position (bottom-right)
                int             mbottom;        // Cluster position (bottom-right)
        public:
                void    msetparameter(int aminpixel,int amaxpixel,double aminrate,double amaxrate)
                {
                        minpixel = aminpixel;   // Minimum area of primitives
                        maxpixel = amaxpixel;   // Maximum area of primitives
                        minrate = aminrate;             // Minimum height/width ratio of primitives
                        maxrate = amaxrate;             // Maximum height/width ratio of primitives
                }
                void    msetparameter(double amindist,double amaxdist)
                {
                        mindist = amindist;
                        maxdist = amaxdist;
                }
                void    msetparameter(int left,int top,int right,int bottom)
                {
                        mleft = left;           // Cluster position (top-left)
                        mtop = top;                     // Cluster position (top-left)
                        mright = right;         // Cluster position (bottom-right)
mbottom = bottom;       // Cluster position (bottom-right)
                }
        public:
                // Override
                virtual int     mprimitivefilter(PRIMITIVE* prim)
                {
                        PRIMFEATURE* feature = prim->feature;
                        if(feature && minpixel <= feature->pixel && feature->pixel <= maxpixel)
                                return 1;
                        return 0;
                }
                // Override
                virtual int     mlocationfilter(PRIMITIVE* prim1,PRIMITIVE* prim2)
                {
                        double  cx1 = (prim1->xmin + prim1->xmax) / 2.0;
                        double  cy1 = (prim1->ymin + prim1->ymax) / 2.0;
                        double  cx2 = (prim2->xmin + prim2->xmax) / 2.0;
                        double  cy2 = (prim2->ymin + prim2->ymax) / 2.0;
                        double  d = sqrt((cx2 - cx1) * (cx2 - cx1) + (cy2 - cy1) * (cy2 - cy1));
                        if(mindist <= d &&  d < maxdist && !mcheckseparator(prim1,prim2))
                                return 1;
                        return 0;
                }
                // Override
                virtual int     mclusterfilter(CLUSTER* pcluster)
                {
                        if(pcluster->xmin < mleft) return(0);
                        if(mright < pcluster->xmax) return(0);
                        if(pcluster->ymin < mtop) return(0);
                        if(mbottom < pcluster->ymax) return(0);
                        return(1);
                }
};
In the base class, clustering is determined based on the size of the primitives. However, in the subclass, clustering is determined based on the area and aspect ratio of the primitives.
In the base class, whether to combine primitives into the same cluster is determined based on the city distance between the primitives. However, in the subclass, this is determined using Euclidean distance.
In the base class, whether a cluster is valid is determined based on the size of the cluster and the number of primitives inside it. However, in the subclass, this is customized based on the position of the cluster.

Table of Contents


2.19 Override (Inter-layer Primitive Movement)

Table of Contents

Override and customize inter-layer primitive movement.

// Function to apply customized inter-layer movement
//      int             moveprimfilter(int from,int to);
// Function for override
// Move the ones with a return value of 1
//      virtual int     mprimitivefilter(PRIMITIVE* prim);
Customize inter-layer movement using one virtual function for override. To override, you need to define a subclass of the CJocrPrim class. Please refer to Override (Cluster Extraction) for more information.

Table of Contents


2.20 Override (Character Definition)

Table of Contents

Override the functions that define characters in Primitive Selection Operation with mojiflag and in String Selection by Straight Line. Normally, only primitives that fit in the character size specified by msetpoint in Cluster Extraction will be moved.

// Move the ones with return value 1
virtual int mojifilter(PRIMITIVE* prim);
Input
    PRIMITIVE* prim;    // Primitive to be evaluated
Return Value
    1...prim is all or part of a character
    0...prim is neither all nor part of a character

For example, by defining a function like the following in a subclass (mdpi is the resolution), primitives with a size of 0.5 inches or less, which is equivalent to 36 points, will be processed as all or part of a character.

virtual int mojifilter(PRIMITIVE* prim)
{
    int     width = prim->xmax - prim->xmin;
    int     height = prim->ymax - prim->ymin;
    if(width <= mdpi / 2 && height <= mdpi / 2)
        return(1);
    else
        return(0);
}

Table of Contents


2.21 Undo Function Support

Table of Contents
To support the undo function, several functions are provided to retrieve and reset the current primitives and clusters.
For each primitive and cluster:
  1. Get the size of the buffer required to retrieve the content.
  2. Allocate a buffer of the size obtained in step 1 and retrieve the content.
  3. Reflect the retrieved buffer on the current primitive or cluster.

The following functions are provided:
        // Primitives
        // Get the size to save the primitive area
        // Return:
        //   Size of buffer required to save all primitive content
        int           mgetsavesize();
        // Save the layers and other information of the primitives
        // Input/Output:
        //   char*    buffer;         Buffer to save the content of the primitives
        //                            The size obtained from mgetsavesize is required
        // The buffer contains the following data:
        // +----------------------+
        // | Number of valid primitives n | 4bytes
        // +----------------------+
        // |  PRIMITIVE 0         | sizeof(PRIMITIVE)
        // +----------------------+
        // |  PRIMITIVE 1         | sizeof(PRIMITIVE)
        // +----------------------+
        // |  PRIMITIVE ...       | sizeof(PRIMITIVE)
        // +----------------------+
        // |  PRIMITIVE n - 1     | sizeof(PRIMITIVE)
        // +----------------------+
        // Return:
        //  0....Normal termination
        //  Negative...Error
        int           makesavebuffer(char* buffer);
        // Load the layers and other information of the primitives
        // Assumption: The same image and the same connectivity conditions (4-connectivity or 8-connectivity) have been used in makeprim
        // Note: The buffer obtained from mgetsavesize and the buffer provided to mreflectloadbuffer are slightly different
        // Input:
        //   int      rvalidnum;      First 4 bytes of the buffer obtained from mgetsavebuffer (number of valid primitives)
        //   char*    buffer;         Buffer obtained from mgetsavebuffer without the first 4 bytes
        // +----------------------+
        // |  PRIMITIVE 0         | sizeof(PRIMITIVE)
        // +----------------------+
        // |  PRIMITIVE 1         | sizeof(PRIMITIVE)
        // +----------------------+
        // |  PRIMITIVE ...       | sizeof(PRIMITIVE)
        // +----------------------+
        // |  PRIMITIVE n - 1     | sizeof(PRIMITIVE)
        // +----------------------+
        int               mreflectloadbuffer(int rvalidnum,char* buffer);
        //  0....Normal termination
        //  Negative...Error (including cases where the image or makeprim conditions are different)

// Cluster information
        // Get the size to save the cluster
        // Input:
        //   CLUSTER*     pcluster;   Cluster to get the save size
        // Return:
        //   Size of buffer required to save the pcluster
        int              mgetsaveclustersize(CLUSTER* pcluster);
        // Generate a cluster save buffer
        // Input:
        //   CLUSTER*     pcluster;   Cluster to save
        // Input/Output:
        //   char*        buffer;     Content of the cluster, requires size obtained from mgetsaveclustersize/0
        // +----------------------+
        // |  CLUSTER             | sizeof(CLUSTER)
        // +----------------------+--------------------
        // |                      | sizeof(int)       Pass the following to the second argument of mrellectclusterbuffer
        // +----------------------+
        // |                      | sizeof(int)
        // +----------------------+
        // |                      | sizeof(int)
        // +----------------------+
        // Return:
        //  0....Normal termination
        //  Negative...Error
        int               makesaveclusterbuffer(CLUSTER* pcluster,char* buffer);
        // Load the cluster body (Load the cluster, allocate the pprim area, and then load the pprim area)
        // Load the layers and other information of the primitives
        // Assumption: The same image and the same connectivity conditions (4-connectivity or 8-connectivity) have been used in makeprim
        // Note: Before calling this function, allocate the space of sizeof(CLUSTER) and copy the first sizeof(CLUSTER) bytes of the buffer saved with mgetsaveclusterbuffer
        // Input:
        //   CLUSTER*     pcluster;   Refer to the "Note" above
        //   int*         pi;         Buffer obtained from mgetsavebuffer without the first sizeof(CLUSTER) bytes
        // Return:
        //  0....Normal termination
        //  Negative...Error
        int               mreflectclusterbuffer(CLUSTER* pcluster,int* pi);
Table of Contents


2.22 Get the total number of bytes of memory allocated within the library

Table of Contents
Get the total number of bytes of memory currently allocated within the library.
This can be used for purposes such as comparing with the memory size of the operating system and setting the size of an undo buffer.
        int               mgetmemoryinfo();
Table of Contents




2.23 Primitive editing functions

Table of Contents
Perform editing operations such as moving, deleting, and inserting primitives.
If new primitives are created during insertion or separation, the size of the insertion buffer area must be set using msetinsertmax.
msetinsertmax must be called before makeprim or makeprim8.
// Primitive structure editing
// Set the upper limit of the number of insertable primitives
// If the limit is reached, an error will be returned by medit_insert or medit_separate
// In that case, dispose of the class once, then new again, then re-insert after msetinsertmax
// Input:
//    int       insertmax;        The default value is 0, usually 10000 is sufficient for normal A3, 400dpi Japanese documents
void            msetinsertmax(int insertmax){minsertmax = insertmax;}

Basic operations for deleting, inserting, and moving primitives are as follows.
msetinsertmax is not necessary if only deletion and movement are performed.
The arguments that specify PRIMITIVE are editing operations for a single primitive.
The arguments that specify CLUSTER are editing operations for a single cluster.

// Delete a primitive
// Handles duplicate primitives
// Input:
//   int        flag;        1... Reflect in image data
//   PRIMITIVE* prim;        Primitive (copying is not allowed as it uses the address)
int             medit_delete(int flag,PRIMITIVE* prim);
int             medit_delete(int flag,CLUSTER* pcluster);
// Insert a primitive (if pjocrprim is this, it becomes a copy)
// Input:
//  int        flag;        1... Reflect in image data
//   CJocrPrim* pjocrprim;   Instance of CJocrPrim to which prim/pcluster belongs
//   PRIMITIVE* prim;        Inserted primitive (copying is not allowed as it uses the address)
//   CLUSTER*   pcluster;    Instance of CJocrPrim to which prim belongs
//   int        left,top;    Destination of movement
int             medit_insert(int flag,CJocrPrim* pjocrprim,PRIMITIVE* prim,int left,int top,PRIMITIVE*& priminsert);
int             medit_insert(int flag,CJocrPrim* pjocrprim,CLUSTER* pcluster,int left,int top);
// Move a primitive (it is better to use this to avoid the high cost of copy+delete)
// Input:
//   int        flag;        1... Reflect in image data
//   PRIMITIVE* prim;        Primitive (copying is not allowed as it uses the address)
//   int        left,top;    Destination of movement
int             medit_move(int flag,PRIMITIVE* prim,int left,int top);
int             medit_move(int flag,CLUSTER* pcluster,int left,int top);

To support movement at the cluster level, a function has been provided to cluster all primitives.
Getting the cluster is done as usual using the mgetcluster function (only one cluster can be obtained).

// Cluster all primitives
// Used for rendering and cluster movement
int             mallprim2cluster();

クラスタ分割では、プリミティブの数が増えるためmsertinsertmaxをあらかじめコールしておくことが必要となる。
medit_separateは、切断線は画素の間(画素の左上を端点とする)とみなされるため、切断によって画像が変化することは無い。
medit_severは、切断線は画素の上とみなされるため、切断線上の画素が消える。
いずれの場合も切断線は複数の線分(ポリラインではなく、それぞれ離れた線分)で指定する。
medit_separateとmedit_sever
// Separate clusters (Pixel data does not fluctuate. There are no visible seams)
// (Note: Initialization is faster than separation if there are many clusters to separate, as it is computationally expensive)
// Input
//    int         linenum;           Number of line segments
//    int*        px1;               x-coordinate value of the starting point of the line segment
//    int*        py1;               y-coordinate value of the starting point of the line segment
//    int*        px2;               x-coordinate value of the ending point of the line segment
//    int*        py2;               y-coordinate value of the ending point of the line segment
//    CLUSTER*    pcluster;          Cluster to be separated
// Return Value
//    0.......Successful completion
//    Negative......Error
int                medit_separate(int linenum,int* px1,int* py1,int* px2,int* py2,CLUSTER* pcluster);

int                medit_sever(int linenum,int* px1,int* py1,int* px2,int* py2,CLUSTER* pcluster);
// Separates line raster specified by a single primitive into line segments and line width

One can separate a connected set of line segments (polyline) into independent primitives. This can be applied to separating characters that come in contact with frame lines. medit_separateline
// Separates primitives along a polyline (connected set of line segments)
// Input
//    int            flag;            0...Not reflected in the bitmap
//                                    1...Reflected in the bitmap
//    int            bridgeflag;      0...No bridge processing
//                                    1...Bridge processing
//    int            horizontalflag;  0...Diagonal lines
//                                    1...Horizontal/vertical lines (usually 0 is fine)
//    int            pointnum;        Number of points in the polyline
//    int*           px;              x-coordinate values of pointnum points
//    int*           py;              y-coordinate values of pointnum points
//    int            lwidth;          Line width
//    PRIMITIVE*    prim;             Original primitive, the divided primitives are inserted after deletion of prim
// Return Value
//    0.......Successful completion
//    Negative......Error
int                    medit_separateline(int flag,int bridgeflag,int horizontalflag,int pointnum,int* px,int* py,int lwidth,PRIMITIVE* prim);
Table of Contents




2.24 Undo Function Support Functions (New Version)

Table of Contents

Return the primitive structure as a single buffer for undo and file saving.
Using makesavebuffer and mreflectloadbuffer can only save the state of layer movement, and cannot support primitive movement, insertion, and deletion.
Use this to reflect the results of primitive editing.
It is possible to save all primitive information (including some layer information).
It can also be used for saving images as it contains data for reproducing the images.
int mgetprim2rlbuffersize();
// Return the size of the buffer when converting the primitive structure to a buffer
int mprim2rl(unsigned char* retbuffer);
// Convert the primitive structure to a buffer
// Input:
//    unsigned char* retbuffer; a buffer with the size obtained from mgetprim2rlbuffersize
// Return:
//    0.......Normal termination
//    Negative......Error
int mrl2prim(unsigned char* buffer);
// Reproduce the primitive structure
// Input:
//    unsigned char* buffer; PRIMRL buffer obtained from mprim2rl
// Return:
//    0.......Normal termination
//    Negative......Error
Table of Contents


2.25 Get Bitmap of Primitives

Table of Contents
Get a bitmap image of the specified primitive as an argument.
// Buffer management is performed internally by the library
// Input
//    PRIMITIVE*        prim;       Primitive
// Output
//    unsigned char*&   pdata;      Bitmap
//    int&              width;      Width of bitmap (in pixels)
//    int&              height;     Height of bitmap (in pixels)
// Get bitmap of cluster
// Get bitmap of primitive
void          makebitmapprimitive(PRIMITIVE* prim,unsigned char*& pdata,int& width,int& height);


Table of Contents



manual homepage

user's manual