Victor Library User's Guide

Getting Started

System Requirements

The Victor Image Processing Library and the device support modules are Dynamic Link Libraries (DLLs) and your programming environment must be able to produce an application capable of calling functions contained in a DLL.

The Victor Image Processing Library is available in versions for 32- or 64-bit Windows.

Desktop Applications: A programming language that supports the calling of functions in DLLs (for example, C/C++, C#, VB6, VB.NET) is required to create a Victor Library desktop application.

Online Server Applications: A Windows server supporting ASP.NET (programming in C# or VB.NET) is required to create a Victor Library internet application that can be run by users using any browser.

Software Installation

Unzip all the downloaded files and place them in a new directory.

For use with Visual Basic place Victor Library DLLs in the subdirectory with the VB executable program, vb5.exe or vb6.exe. It is not necessary to register the Victor Library. It is not a COM object. It is not an ActiveX control.

For use with .NET place Victor Library DLLs in the \bin subdirectory under the application you are creating. It is not necessary to register the Victor Library. It is not a COM object. It is not an ActiveX control.

Victor Features

The Victor Image Processing Library for Windows can be used to create applications for working with images in the Microsoft Windows environment.

Capabilities that can be built into a Windows desktop or web server application by using the Victor Library include:

These features are described in the pages that follow. The implementation is straightforward and easily accomplished by reading the function description and following the examples.

How to Use this Manual

Begin this manual by loading viclibquide.html into your browser.

This manual was written with the assumption that you are generally familiar with Windows programming.

The first section of this manual is the User's Guide and provides information necessary to successfully incorporate Victor functions into Windows programs. It should be read and understood.

The second section is the Library Reference which begins in viclibref-a-c.html. This reference contains detailed information about all Victor functions.

The Return Codes list contains the summary of function return codes and the Data Types list contains all the user-defined data structures used by the library.

Demonstration Programs

The Victor Library demonstration programs include the source code for C#, Visual Basic, VB.NET, ASP.NET, Java, and C/C++ desktop and web server applications. To download the latest example programs visit

www.catenary.com
Free Downloads
Apps & Extras

Some of these sample applications include a time-limited eval version of the vic32.dll file.

VicImager, VB ASP.NET

The advanced image processing application VicImager demonstrates the use of the Victor Library on a remote server for fast and easy image processing. Source code for VicImager is included with purchase of the Victor Library.

Other aspx demo programs with source code are Image Cropping, Simple Image Processing, and Select Process.

Tiffpageview, C# ASP.NET

Tiffpageview is a C# .NET server application accessing the Victor Library through the viclib namespace. Use this app to load and display any page from a tiff multipage file.

VicDemo, online C# ASP.NET

Vicdemo_cs.zip ASP.NET C# online function exerciser for multiple images.

Tester, 64-bit C#

Tester.zip is a C# desktop sample application for use with the 64-bit version of the Victor Library.

Comparator, C#

Comparator is a C# .NET MDI desktop application accessing the Victor Library through the viclib namespace. Use this app to combine, compare, and analyze multiple images.

Vicnet1, VB.Net

Vicnet1 is a VB.NET desktop application to load, save, display, scan, print images.

Loadpic, VB6

Loadpic is a Visual Basic program to load and save, display, and print an image. It also includes Twain support to select a source and capture an image. Loadpic allows you to load and save bmp, gif, jpeg, png, and tiff files. It will automatically convert between file types as necessary.

This is the first program you should create using Visual Basic and the Victor Library to make sure VB can find all the necessary components.

Place the VIC32.DLL and VICTW32.DLL in the subdirectory with the VB executable program, vb6.exe.

LoadNSho, C/C++

LoadNSho is a simple program to load and display a single image. This is the first program you should compile using your C compiler and the Victor Library to make sure the compiler can find all the necessary components. Project files are included for Microsoft and Borland compilers.

loadnsho.zip for 64-bit C/C++
loadnsho.zip for 32-bit C/C++

VicDemo, C/C++

VicDemo is a fully functional image processing program that can be used for scanning, printing, file conversion, and enhancing images.

VicDemo illustrates some of the features and functions available in the Victor Library, and provides practical examples of using Victor functions. It should be used as a guide in calling Victor routines in your applications.

For information about the VicDemo commands and image processing tips and techniques select the Help command. VicDemo has an extensive Help system describing the program and the library.

VicDemo is a multi-module program. The source code is provided. Refer to the project file to compile the modules and link the program.




Programming Considerations

Your application can call Victor functions as easily as it calls Windows functions, because the Victor Library for Windows is a dynamic link library (DLL).

Dynamic Link Libraries

DLLs contain the Victor functions called by your application during execution. The main image handling functions are in the main DLL, VIC32.DLL or VIC64.DLL. Additional functions for special processing, analysis, and TWAIN device support are contained in additional DLLs.

Victor 32-bit library Victor 64-bit library Contains
VIC32.DLL VIC64.DLL Image processing & file load/save
VICFX.DLL VICFX64.DLL Additional multi-image processing
VICSTATS.DLL VICSTATS64.DLL Image analysis
VICTW32.DLL VICTW64.DLL TWAIN support

Namespace File

The namespace file VICLIB.DLL or VICLIB64.DLL is used for .Net programming with VB or C# and serves as the interface into the Victor Library dlls.

Include Files

The include files are used when programming directly into the Victor Library dlls. These files contain function declarations, data structure definitions, and error codes for different programming languages.

Language Include file
C/C++, 32-bit VICDEFS.H
C/C++, 64-bit VIC7DEFS.H
VB6 VICDEF32.BAS
ASP.NET VICDEFS.ASPX obsolete, please use viclib.dll or viclib64.dll
C# VICDEFS.CS obsolete, please use viclib.dll or viclib64.dll
VB.NET VICDEF32.VB obsolete, please use viclib.dll or viclib64.dll

Import Libraries

Import libraries are used with the C/C++ programming language only. The import library is linked to your application at compilation time and relates function calls to actual entry points in the corresponding DLL.

Victor 32-bit import library Corresponding DLL
VIC32MS.LIB VIC32.DLL
VICFXMS.LIB VICFX.DLL
VICSTATSMS.LIB VICSTATS.DLL
VCTW32MS.LIB VICTW32.DLL

Victor 64-bit import library Corresponding DLL
VIC64.LIB VIC64.DLL
VICFX64.LIB VICFX64.DLL
VICSTATS64.LIB VICSTATS64.DLL
VICTW64.LIB VICTW64.DLL


Creating an ASP.NET Application

The Victor Library functions are accessed through the viclib namespace.

Place the viclib.dll, vic32.dll, vicfx.dll, and vicstats.dll in the \bin subdirectory of your application.

Follow these steps to create your application:

Creating a VB.NET Desktop Application

The Victor Library functions are accessed through the Victor .NET interface: viclib or viclib64 namespace.

Follow these steps to create your application:

Creating a C# Desktop Application

The Victor Library functions are accessed through the Victor .NET interface: viclib  or viclib64 namespace.

Follow these steps to create your application:

Creating a C/C++ Application

There are three Victor Library components necessary for creating a C/C++ application: dynamic link libraries, import libraries, and the header file. Keep in mind that the 32- or 64-bit versions of the Victor Library can only be used for creating the corresponding 32- or 64-bit applications.

Follow these steps to create your application:

For additional information on compiling and linking your application see the README file.

Creating a Visual Basic Application

Place the VIC32.DLL and any other required dlls in the subdirectory with the Visual Basic executable program, vb6.exe. Before creating your own application using Victor functions, run the LOADPIC sample. This will ensure that VIC32.DLL, VICTW32.DLL, and the source files can be found by VB. To run LOADPIC, start Visual Basic, load the project file LOADPIC, and choose Run Start.

Follow these steps to create your own application:

For additional information on compiling and linking your application see the VBREAD.DOC file.

Creating a Java Application

Create your app and at the top of the app source file insert

		import vic.*;

To invoke a Victor function from a Java app precede the function name with the prefix "vic.vic32jni." Precede the definition of any Victor data structures with the prefix "vic."

Place the dlls:

To compile and run:
		javac -classpath x:\java myapp.java
		java -classpath x:\java;x:\java\vic myapp

For complete information on compiling and linking your application see the vic32jni.txt file.

Creating an App with Unicode Support

To create a C/C++ application with Unicode support place the following two lines at the top of each source file:

		#include <tchar.h>
		#define UNICODE TRUE 

(Normally, you would also #define _UNICODE TRUE for proper Unicode string handling in your app.)

This will cause the Unicode version of Victor functions to be used. If Unicode is defined it is not possible to use the ANSI version of a Victor function, the Unicode version will always be used.

Or you may call the Unicode version of the Victor function directly. The Unicode version of a Victor function has a "W" appended to the end of the function name. For example, bmpinfo takes an ANSI string as the first argument, and bmpinfoW takes a Unicode character string as the first argument.

Troubleshooting

Windows can be a difficult environment to program under. If you have problems using Victor functions in your application you may benefit from the following suggestions.

Make sure your application can find the Victor Library dlls.

If a Victor function returns a value other than NO_ERROR or the function doesn't behave as you expect it to, examine the data being sent to the function.

Trace program execution and examine variables and Windows messages. Most problems result from incorrect data being passed to functions. Examine the contents of the image descriptor and make sure the element values are reasonable.

Several Victor Functions allocate memory for image buffers or file data buffers. Every allocimage() should be balanced with a freeimage() when done with the image and every savefiletobuffer() should be balanced with a freebuffer() so that excessive memory is not consumed by your application.

Technical Support

Visit the website http://www.catenary.com for more code examples of using Victor to accomplish various tasks:

http://www.catenary.com
Sample Code

If you need additional assistance using the Victor Library you may contact Catenary Systems for technical support during normal business hours 9 am to 5 pm (USA Central Time) Monday through Friday:

voice: (636) 285-9624

e-mail: support@catenary.com

url: www.catenary.com




Victor Images

Device Independent Bitmap (DIB) Review

Victor Library functions operate on an image stored in memory as an uncompressed Device IndependentBitmap (DIB).

The Microsoft Windows Programmer's Reference defines a DIB as follows:

"A Windows DIB consists of two distinct parts: a BITMAPINFO structure, which describes the dimensions and colors of the bitmap, and an array of bytes defining the pixels of the bitmap. The bits in the array are packed together, but each scan line must be zero-padded to end on a LONG boundary. Segment boundaries, however, can appear anywhere in the bitmap. The origin of the bitmap is the lower-left corner."

A DIB provides a uniform format for moving bitmaps between different devices. Windows uses a DIB to create a bitmap or display image data on a display device.

The DIB is composed of header, palette, and pixel data. There are two forms of DIB, the original packed DIB and the now widely used DIB Section. Victor functions operate on both types.

The original packed DIB format has all the image data together in a single contiguous block of memory. The packed DIB is used when a DIB is placed in the Windows clipboard and the data is referred to as type CF_DIB. This was the only type of DIB available in 16-bit Windows

The DIB Section is used in 32- and 64-bit Windows and has the header and palette data in one memory location while the pixel data reside in another location. This DIB format also includes a bitmap handle that makes the DIB usable with the Windows graphics functions.

How Victor Images Differ from Windows DIBs

Victor functions operate on a subset of Windows DIBs. The differences lie in compression, bits per pixel, and palette.

The Image Descriptor Defined

Victor's most important data structure is the image descriptor. All of the information necessary for a Victor function to operate on an image area is contained in the image descriptor data structure that describes that image. The image descriptor is defined of type imgdes and is a required argument for most Victor functions. The image descriptor is defined as follows:

typedef struct {
   unsigned char huge *ibuff;     Image buffer address
   unsigned stx, sty, endx, endy; Image area of interest
   unsigned buffwidth;            Image buffer width in bytes
   RGBQUAD far *palette;          Palette address
   int colors;                    Number of palette colors
   int imgtype;                   Image type: bit 0 = 1 
                                  if image is grayscale
   BITMAPINFOHEADER far *bmh;     BITMAPINFOHEADER address
   HBITMAP hBitmap;               Device Independent Bitmap handle
} imgdes;

The Elements of the Image Descriptor

ibuff
The ibuff element of the image descriptor holds the address of the image bits. The data is organized by rows of pixels beginning with the bottom row. Each row begins with the leftmost pixel and may be right-padded so the number of bytes in the row is a multiple of four.
 
The format of the image data is dependent on bits per pixel contained in the BITMAPINFOHEADER element biBitCount. Bits per pixel refers to the number of bits necessary to represent the value of a single picture element. 1, 8, and 24 bits per pixel are supported by Victor functions.
 
1-bit images (bilevel or monochrome images) contain two colors, typically black and white. Each pixel is represented by 1 bit and each byte represents 8 pixels. The leftmost pixel is the most significant bit of the first byte. A 0 bit represents a pixel color given by the first entry in the palette, and a 1 bit represents a pixel color given by the second entry.

8-bit images (grayscale or palette color) contain up to 256 colors. Each pixel is represented by a single byte and can range from 0 to 255. The pixel value is an index into the 256 entries in the palette.

24-bit images (RGB) contain up to 16 million colors. Each pixel is represented by 3 bytes containing the relative intensities of blue, green, and red for that pixel. (Note that the byte order in an RGB pixel is blue, green, red.) A 24-bit image has no palette.

The origin of the bitmap is the lower-left corner. This means that the address ibuff represents is the first pixel in the last row of image data as viewed on the screen.



stx, sty, endx, endy
Upper left and lower right corners of the image area of interest in pixels. (0,0) represents the upper left corner of the image as displayed on the screen. Unlike some Windows GDI functions, such as Rectangle, Victor functions process every pixel within the image area. Thus the processed area width and length are:
area width = endx - stx + 1
area length = endy - sty + 1
buffwidth
Width of the image buffer in bytes. The buffer width is always a multiple of 4 to end on a LONG boundary, and is calculated:
buffwidth = (image width * bitcount + 31) / 32 * 4

palette
The palette element contains the address of the palette data stored as an array of RGBQUADs. Each color is described by one RGBQUAD, defined in WINDOWS.H as:
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;

colors
Number of colors in the palette, dependent on bits per pixel:
Bits per pixel Maximum palette colors
1 2
8 256
16 0
24 0
32 0



For a 1-bit per pixel image, colors must be 0 or 2. Palette holds the address of the 2-member array of RGBQUADs (the array size is 8 bytes).

For an 8-bit per pixel image, colors must be between 0 and 256. Palette contains the address of the 256-member array of RGBQUADs (the array size is 1024 bytes).

For a 16-, 24-, or 32-bit per pixel image, there are no palette data. Colors and palette are ignored by Victor functions.

imgtype
Image type: bit 0 is set to 1 if the image is grayscale. This is used primarily when saving grayscale images. The remaining bits are not used.

bmh
Address of the BITMAPINFO and the BITMAPINFOHEADER structures. This is also used as the address of the DIB. The structures are defined in WINDOWS.H as:
        typedef struct tagBITMAPINFO {
            BITMAPINFOHEADER bmiHeader;
            RGBQUAD    bmiColors[1];
        } BITMAPINFO;

        typedef struct tagBITMAPINFOHEADER {
            DWORD  biSize;
            DWORD  biWidth;
            DWORD  biHeight;
            WORD   biPlanes;
            WORD   biBitCount;
            DWORD  biCompression;
            DWORD  biSizeImage;
            DWORD  biXPelsPerMeter;
            DWORD  biYPelsPerMeter;
            DWORD  biClrUsed;
            DWORD  biClrImportant;
        } BITMAPINFOHEADER;

hBitmap
The hBitmap element contains the handle to the device independent bitmap (DIB). hBitmap can be used with Windows GDI functions for drawing on the DIB, displaying the DIB, or whenever the handle to a bitmap is required.

A nonzero value of hBitmap indicates that the image is a DIB section. A value of zero indicates that the image is a packed DIB.

Using Victor Functions in a Windows Application

When working with images, a general procedure to follow is

Allocate memory for the image
Load the image
Set the image area to be modified
Modify the image area
Display/save/print the image
Free the image

Allocating Memory for an Image

To allocate an image buffer and assign the elements of an image descriptor, use the allocimage function. Allocimage allocates space for the image, including the header, palette, and image data.

Allocimage enters the correct values into the image descriptor and DIB header and the image buffer is ready to receive an image.

For example, to allocate space for a 8-bit image the following C# code can be used:

   
   vicwin.imgdes image1;                  // Define an image descriptor 
   int width=640, length=480;      // Desired image buffer size (pixels)
   int bppixel=8;                  // 8 bits per pixel

   // Allocate space for the image 
   rcode = vicwin.allocimage(ref image1, width, length, bppixel);

   // Ready to load an image 

Loading and Saving an Image

After an image buffer has been allocated, a Victor loadfile function can be called to place the image in the buffer. For example, to load an 8-bit TIFF image into the previously allocated image buffer:

   string filename = "car.tif";
   rcode = vicwin.loadtif(ref filename, ref image1);

The Victor Library supports all the popular image file formats to load and save bilevel, grayscale, and color images. Table 1 lists the supported file formats and the corresponding Victor functions.

Table 1. Image File Formats Supported by Victor
Format Function Description
BMP loadbmp
loadbmpfrombuffer
savebmp
loads 1-, 4-, 8-, 16-, 24-, and 32-bit

saves 1-, 8-, and 24-bit
TIFF loadtif
loadtiffrombuffer
loadtifpage
loadtifpagebyindex
loadtifwithalpha
savetif
savetifpage
savetiftobuffer
loads 1-, 4-, 8-, 16-, 24-, and 32-bit




saves 1-, 8-, 16-, and 24-bit
EPS saveeps saves 8-bit
JPEG loadjpg
loadjpgex
loadjpgfrombuffer
loadjpgfrombufferex
loadjpgthumbnail
loadjpgthumbnailfrombuffer
savejpg
savejpgex
savejpgtobuffer
savejpgtobufferex
loads 8- and 24-bit





saves 8- and 24-bit
GIF loadgif
loadgifframe
loadgifframefrombuffer
loadgiffrombuffer
savegif
savegifex
savegifframe
savegifframetobuffer
savegiftobufferex
loads 1- through 8-bit



saves 1- and 8-bit
saves 1- through 8-bit
PCX loadpcx
savepcx
loads 1-, 4-, 8-, and 24-bit
saves 1- and 8-bit
PNG loadpng
loadpngfrombuffer
savepng
savepngex
savepngtobuffer
loads 1-, 4-, 8-, 16-, 24-, and 32-bit

saves 1-, 8-, and 24-bit
BIF loadbif
savebif
loads 8-bit
saves 8-bit
TGA loadtga
loadtgawithalpha
savetga
loads 8-, 16-, 24-, and 32-bit

saves 24-bit

To determine the size of the image before loading and to allocate exactly the correct amount of space to hold the image use one of the fileinfo functions. For example for the TIFF image:

   vicwin.imgdes image1;      // Define an image descriptor 
   vicwin.TiffData tdat;      // TIFF info data structure
   int width, length;  // Desired image size (pixels)
   int bppixel ;       // 8 bits per pixel
   int rcode;

   // Get image info on the file we're to load 
   rcode = vicwin.tiffinfo(ref filename, ref tdat);

   if(rcode != vicwin.NO_ERROR) {
      MessageBox(hWnd,"Error in reading file", 0, MB_OK);
      return(rcode);
      }

   width = tdat.width;
   length = tdat.length;
   bppixel = tdat.vbitcount;

   // Allocate space for the image 
   vicwin.allocimage(ref image1, width, length, bppixel);
   rcode = vicwin.loadtif(ref filename, ref image1);

   If (rcode == vicwin.NO_ERROR)
      // Image is in memory ready to display or process 
To save an 8-bit TIFF image after processing:
   string newfilename = "newcar.tif";
   int compression = 0;

   rcode = vicwin.savetif(ref newfilename, ref image1, compression);

The Victor file functions automatically load and save any palette data along with the image data.



Setting an Image Area

The coordinate system describing the image buffer places the origin, (0,0), at the upper left of the image as displayed on the computer screen. Victor functions require valid starting and ending coordinates that define the image area. The image area is defined by the image descriptor elements stx, sty, endx, and endy. All coordinates are in pixels.

Operations can be performed on any rectangular area within the image buffer. When an image buffer is allocated with allocimage, the allocation function sets the image area to include the entire image, that is:

stx = 0,
sty = 0,
endx = bmh.biWidth - 1, and
endy = bmh.biHeight - 1


A smaller image area can be set with the setimagearea or recttoimagearea functions. For example, to define an image area 100 x 200 within the image image1 starting at (0,0) use:

   vicwin.setimagearea(ref image1, 0, 0, 99, 199);

To use C/C++ and the Windows SetRect function to set an area based on values contained in a RECT structure:

   SetRect(&rect, 0, 0, 99, 199);    // The Windows function SetRect 
   recttoimagearea(rect, &image1);

Alternatively, the image area coordinates can be set with individual assignment statements:

   image1.stx  = 0;
   image1.sty  = 0;
   image1.endx = 99;
   image1.endy = 199;

Modifying an Image with Victor Functions

Images may be modified using Victor image processing or manipulation functions. These functions require that source and result image descriptors be specified. The data of the source image is used to create the result image. Functions that combine two images to produce the result, like wtaverage, require an operator image descriptor as well. It is always the address of the image descriptor that is used as the argument to Victor functions.

Image data is read from the specified image area in the source buffer and written to the image area in the result buffer. If the same image descriptor can be used for both source and result, the source data will be replaced by the result data. For example, to sharpen an image and increase its brightness by 10 use:

   // Using C/C++ 
   sharpen(&image1, &image1);
   changebright(10, &image1, &image1);

   // Using C# 
   vicwin.sharpen(ref image1, ref image1);
   vicwin.changebright(10, ref image1, ref image1);

If the source and result image areas overlap in memory (but are not identical), the source data may be corrupted during an image processing operation by the result data. In this case, first copy the source image area to the result image area with the copyimage function. The copyimage function will work correctly, even if the source and result areas overlap. Then process the result image area.


Copy an Image to the Clipboard

In .NET we can use the Windows clipboard function SetDataObject to copy an image to the clipboard.

					
private void mnu_copy_Click(object sender, System.EventArgs e)
        {
            Bitmap bm;
            uint swidth = 0, slength = 0;
            int bpp;
            int rcode;
            vicwin.imgdes timage;
 
            timage = new vicwin.imgdes();

            swidth = vimage.endx - vimage.stx + 1;
            slength = vimage.endy - vimage.sty + 1;
 
            bpp = vicwinex.getbpp(ref vimage);
            rcode = vicwin.allocimage(ref timage, (int)swidth, (int)slength, bpp);
            if (rcode == vicwin.NO_ERROR)
                rcode = vicwin.copyimage(ref vimage, ref timage);
 
            bm = Bitmap.FromHbitmap((IntPtr)timage.hBitmap); 
            Clipboard.SetDataObject(bm, true);    // The .NET function does all the work of putting the copy on the clipboard
            vicwin.freeimage(ref timage);
        }

For a thorough discussion of copying and pasting using the Windows Clipboard refer to the section below Using the Windows Clipboard.


Displaying an Image

When creating desktop apps using VB6, VB.NET, or C# the easiest way to disply an image is to put it into a PictureBox. The sample applications include the functions to display the image.

Sample application functions to display an image
C# vicimagetoPicturebox(myimgdes, pictureBox1);
VB.NET vicimagetopicturebox(vimage, PictureBox1)
VB6 MainWnd.Picture1 = image_to_picturebox(vimage)

 

This is an example of displaying an image in a 64-bit C# .NET picturebox.

       // Generic function to put a Victor image into a Picturebox
        public void vicimagetoPicturebox(ref vicwin.imgdes srcimg, PictureBox pb)
        {
            System.IntPtr bmhandle;
            uint swidth = 0, slength = 0;
 
            if (srcimg.hBitmap != null)
            {
            swidth = (uint)srcimg.bmh->biWidth;
            slength = (uint)srcimg.bmh->biHeight;
 
                bmhandle = srcimg.hBitmap;
                pb.Image = Image.FromHbitmap(bmhandle);
                pb.Width = (int)swidth;
                pb.Height = (int)slength;
            }
        }
                
                

Using C/C++ you have to display the image manually. A Victor image can be displayed easily with the viewimageex function. For example, to view the image loaded from the TIFF file above:

   HDC hDC;
   PAINTSTRUCT ps;
   HPALETTE hpal;

   hDC = BeginPaint(hWnd, &ps);
   /* Display the image beginning at (0,0) */
   viewimageex(hWnd, hDC, &hpal, 0, 0, &image1,0,0,VIEWDITHER);      
   EndPaint(hWnd, &ps);

The viewimageex function displays the image in the window and automatically uses color reduction if necessary. You can also specify the starting position for the image and the scroll positions.

Your program can also use viewimage or the Windows functions SetDIBitstoDevice, StretchDIBits, or CreateDIBitmap to display an image.

The viewimageex function automatically uses color reduction to display a 24-bit image on in a display mode limited to 256 or fewer colors. The color reduction method will be one of the following defined constants:



VIEWOPTPAL creates an optimized palette
VIEWDITHER a fast ordered dither using a standard palette
VIEWSCATTER a diffusion scatter pattern using a standard palette


Freeing an Image

Call freeimage to release memory associated with an image after the image is no longer needed. Failure to release memory may cause memory shortages. To release the memory associated with the image image1, use:

   // C/C++
   freeimage(&image1);

   // C#
   vicwin.freeimage(ref image1);

Range Checking

All functions that access an image buffer call the function checkrange_ to perform range checking. The source code for checkrange_ is included with the library in the module VICCORE.C. (All functions and variables that are used internally by Victor contain a trailing underscore as part of the name.)

If a range error occurs, the function returns BAD_RANGE. This indicates that one of the following conditions exists:

endx >= bmh->biWidth, or
endy >= bmh->biHeight

ibuff == 0, or
bmh == 0
bmh->biWidth * bmh->biBitCount / 8 > buffwidth


If necessary, checkrange_ also reorders x and y coordinate data so that the starting position of an area is at upper left, and the ending position is at lower right.

Range checking also includes pointer validation to make sure the image buffer address passed to Victor functions is valid. That is, that the image buffer can be read and written. This should help catch uninitialized or corrupted image descriptors before they cause General Protection Faults or access violations. If checkrange_ determines that the image buffer address is invalid, a BAD_IBUF error code will be returned.




Color Palettes

What is a Color Palette?

In a 1- or 8-bit image, each pixel value is an index into a color lookup table -- the palette. The palette is arranged as an array of RGBQUADs, in which four bytes (blue, green, red, and reserved) represent each palette color. The byte values represent the relative intensities of blue, green, and red, and can range from 0 to 255.

For example, to access the components of an individual color, use the image descriptor element palette which points to the palette table.

   red = image.palette[color_number].rgbRed;
   green = image.palette[color_number].rgbGreen;
   blue = image.palette[color_number].rgbBlue;

A 24-bit RGB image does not have a color palette since each pixel consists of blue, green, and red bytes that represent the color intensities.

Creating a Palette

Version 6.0 of the Victor Library introduced a new function to create a palette, makepalette. The makepalette function takes palette index values and the corresponding red, green, and blue intensities. These are defined in an array of PALETTEPOINT data structures. If you supply 256 elements you can explicitly define each palette entry. If you supply fewer elements the makepalette function will create a smooth gradation of color between the explicitly defined entries.

For example, using C/C++ to create a 256-level grayscale palette define the first palette entry with index zero and the last palette entry with index set to 255. The makepalette function will create all the entries in between:

					
		PALETTEPOINT ppa[2];
		int j;

		ppa[0].index = 0;
		ppa[0].red = 0;
		ppa[0].green = 0;
		ppa[0].blue = 0;

		ppa[1].index = 255;
		ppa[1].red = 255;
		ppa[1].green = 255;
		ppa[1].blue = 255;

		rcode = makepalette(&Image, ppa, 2);
					

This example uses the makepalette function in C# to create a 256-level palette that will gradually change from black to white but includes any two colors in between for a smooth colorful transition. This would be similar to a photographic duotone effect.

      // Creates a 3-stage color palette between 4 colors: black - color0 - color1 - white into an 8-bit result image
       public static int colorramp(int lo, int r0, int g0, int b0, int hi, int r1, int g1, int b1, ref vicwin.imgdes srcimg, ref vicwin.imgdes resimg)
       {
           int rcode;
           vicwin.RGBQUAD[] mypalette = new vicwin.RGBQUAD[256];
           vicwin.PALETTEPOINT[] ppa = new vicwin.PALETTEPOINT[4];

           // Establish 4 palette points between which to smooth the colors
           ppa[0].index = 0;
           ppa[0].red = 0;
           ppa[0].green = 0;
           ppa[0].blue = 0;

           ppa[1].index = (byte)lo;
           ppa[1].red = (byte)r0;
           ppa[1].green = (byte)g0;
           ppa[1].blue = (byte)b0;

           ppa[2].index = (byte)hi;
           ppa[2].red = (byte)r1;
           ppa[2].green = (byte)g1;
           ppa[2].blue = (byte)b1;

           ppa[3].index = 255;
           ppa[3].red = 255;
           ppa[3].green = 255;
           ppa[3].blue = 255;

           rcode = vicwin.colortogray(ref srcimg, ref resimg);
           if (rcode == vicwin.NO_ERROR)
               rcode = vicwin.makepalette(ref resimg, ref ppa[0], 4);  // makepalette can take 2 to 256 entries for smoothing the palette
           return (rcode);
       }					
					

Changing a Palette

Each red, green, or blue value can range from 0 (no intensity) to 255 (maximum intensity). To increase the red, green, or blue contribution of a color, add a quantity to the rgbRed, rgbGreen, or rgbBlue element of the corresponding RGBQUAD. For example, to increase by 20 the red contribution to color number 43:

   red = image.palette[43].rgbRed;
   red = red + 20;
   if(red > 255) red = 255;
   image.palette[43].rgbRed = red;

With color palette images a quick method of brightening an image is to increase the intensity of the entire palette. To brighten an individual color add the same amount to the red, green, and blue components. To brighten an entire image add the same amount to the red, green, and blue components of every color in the palette.

For example, to brighten an image by 30:

void altermypalette(imgdes *image)
{
   int j, red, green, blue;

   for(j = 0; j < 256; j++) {
      red = image->palette[j].rgbRed;
      red = red + 30;
      if(red > 255) red = 255;
      image->palette[j].rgbRed = red;

      green = image->palette[j].rgbGreen;
      green = green + 30;
      if(green > 255) green = 255;
      image->palette[j].rgbGreen = green;

      blue = image->palette[j].rgbBlue;
      blue = blue + 30;
      if(blue > 255) blue = 255;
      image->palette[j].rgbBlue = blue;
      }
}

Displaying an Altered Palette

In a C/C++ desktop application it is necessary to tell Windows that the palette has changed. To redisplay the image with the altered palette, use victowinpal to create a Windows logical palette. Then select the palette into the device context and realize the palette. A palette has to be "realized" for its color entries to be added to the system palette.

Modern programming languages like VB6, VB.NET, and C# do not require this "realization."

   HPALETTE hpal;

   hDC = GetDC(hWnd);
   // Convert palette associated with image to a Windows palette
   victowinpal(&image, &hpal);

   // Select the palette into the DC and realize the palette
   holdpal = SelectPalette(hDC, hpal, 0); 
   RealizePalette(hDC); 

   // Deselect the palette before releasing DC
   SelectPalette(hDC, holdpal, 0); 
   DeleteObject(hpal);
   ReleaseDC(hWnd, hDC);

Color Reduction: Creating a Palette Color Image from an RGB Image

A 24-bit RGB image can be converted to an 8-bit palette color image by several Victor functions. The main reason to use color reduction is to reduce the image storage requirements. Converting an image from 24-bit to 8-bit automatically reduces the image size to one-third of the original.

The choice of color reduction function depends upon your requirements for speed of execution, image quality, and ability to display multiple images at the same time. The Victor color reduction functions and performance estimates are listed in Table 2.

Table 2. Color Reduction Functions
Function Speed Quality Description
colordither(16)1 very fast fair 16 standard colors
colordither(256)1 very fast good 256 standard colors
colorscatter(16)1 fast fair 16 standard colors
colorscatter(256)1 fast very good 256 standard colors
matchcolorimage good varies based on palette specified programmer specifies palette, uses error diffusion
matchcolorimageex 2 good varies based on palette specified programmer specifies palette, error diffusion is optional
convertrgbtopal good excellent creates optimum palette
convertrgbtopalex 2 good excellent creates optimum palette, diffusion is optional
colortogray fast excellent 256 shades of gray
1 The numbers in parentheses refer to the size of the standard palette. Refer to individual function descriptions in the Victor Library Reference for additional information.

2 These functions allow you to specify the color matching method and whether or not error diffusion scatter is used.



To convert an RGB image into a palette color image with optimized palette and save it as a TIFF file, use the following sequence:

   // Allocate an 8-bit image 
   allocimage(&image8, (int)rgbimage.bmh->biWidth,
       (int)rgbimage.bmh->biHeight, 8);

    // Convert RGB to 8-bit image
   convertrgbtopal(256, &rgbimage, &image8); 
   savetif("ANY.TIF", &image8, compression = 0); // Save the image
   freeimage(&image8);

Where rgbimage is a 24-bit RGB color image and image8 is an 8-bit palette color image.

To convert an RGB image into a palette color image with an existing palette and save it as a TIFF file, use the following sequence:

// Allocate an 8-bit image 
allocimage(&image8, (int)rgbimage.bmh->biWidth,
(int)rgbimage.bmh->biHeight, 8);

// Copy an existing palette to the new image
copyimagepalette(&anotherimage, &image8);
// Convert RGB to 8-bit image
matchcolorimage(&rgbimage, &image8); 
savetif("NEW.TIF", &image8, compression); // Save the image 
freeimage(&image8);

Where rgbimage is a 24-bit RGB color image, anotherimage is an existing image with the palette of interest, and image8 is an 8-bit palette color image.



DIBs, Bitmaps, and Images

Converting an Existing DIB to an Image

A device independent bitmap can be operated on by Victor functions if the DIB is Victor compatible and is described by an image descriptor. A Victor-compatible DIB is a DIB that is 1-, 8-, or 24-bits per pixel, uncompressed, and contains explicit RGB palette values.

To make a DIB Victor-compatible, select the function based on the type of DIB.



DIB Description      Victor Library Function
Victor-compatible packed DIB
    1-, 8-, or 24-bits per pixel
    uncompressed
    RGB palette
     setupimgdes
Any packed DIB      dibtoimage
DIB section      dibsecttoimage

Converting a Victor-compatible packed DIB

The setupimgdes function provides an easy way to enter the correct values into an image descriptor for a Victor-compatible DIB. For example, to save an existing DIB as a TIFF image directly from the clipboard, the following code can be used:

int SaveClippingasTiff(HWND hwnd, char *fname)
{
   unsigned char huge *dib;
   int rcode=NO_ERROR;
   HGLOBAL hMem;
   imgdes image;

   OpenClipboard(hwnd);   // Open clipboard
    // Get DIB from clipboard
   hMem = GetClipboardData(CF_DIB);
   // Get address of DIB
   dib = (unsigned char huge *)GlobalLock(hMem);

   // Fill in an image descriptor for the Victor-compatible DIB
   rcode = setupimgdes(dib, &image);
   if(rcode == NO_ERROR)
      rcode = savetif(fname, &image, 0);
   if(hMem)  // Unlock memory before closing the clipboard
      GlobalUnlock(hMem);
   CloseClipboard();      // Close the clipboard
   return(rcode);
}

Converting any packed DIB

If a DIB is not Victor compatible (i.e., it is 4-bits per pixel or compressed), a Victor image has to be created from the DIB for Victor functions to operate on it. The dibtoimage function creates a Victor image based on any packed DIB.

In the following example, a new image is created and saved as a BMP file from a DIB on the clipboard.

int SaveClippingasBMP(HWND hwnd, char *fname)
{
   unsigned char huge *dib;
   imgdes image;
   int rcode=NO_ERROR;
   HGLOBAL hMem;

   // Open clipboard
   OpenClipboard(hwnd);
   // Get DIB from clipboard
   if(hMem = GetClipboardData(CF_DIB)) {
      // Get address of DIB
      dib = (unsigned char huge *)GlobalLock(hMem);

      // Create a new image from the DIB
      rcode = dibtoimage(dib, &image);
      if(rcode == NO_ERROR) {
         savebmp(fname, &image, 0);
         // Free memory allocated by dibtoimage
         freeimage(&image);  
         }
      GlobalUnlock(hMem);
      }
   CloseClipboard();
   return(rcode);
}

Converting a DIB Section

A DIB section is a Win 32 system object with an HBITMAP handle. To convert a DIB section into a Victor image use the dibsecttoimage function. For example, to save an existing DIB section as a TIFF file use the following:

int SaveDIBSectToTiffFile(HBITMAP hBitmap)
{
   int rcode;
   imgdes timage;
   char *fname = "bitmap.tif";
   
   rcode = dibsecttoimage(hBitmap, &timage);
   if(rcode == NO_ERROR) {
      // Save captured image
      rcode = savetif(fname, &timage, 0);
      freeimage(&timage);
      }
   return(rcode);
}

Converting a Device Dependent Bitmap to an Image

A device dependent bitmap is a Windows system object represented by a bitmap handle. Victor functions can operate on a device dependent bitmap only if it is first converted into a Victor image. Use the ddbtoimage function to create a Victor image. For example, to save a bitmap as a TIFF file use the following:

int SaveHBitmaptoTiffFile(HBITMAP hBitmap)
{
   int rcode;
   imgdes timage;
   char *fname = "bitmap.tif";
   HPALETTE hPal = 0;

   rcode = ddbtoimage(hBitmap, hPal, &timage);
   if(rcode == NO_ERROR) {
      // Save captured image
      rcode = savetif(fname, &timage, 0);
      freeimage(&timage);
      }
   return(rcode);
}

In the above example, a palette handle is one of the arguments to ddbtoimage. By specifying zero for the palette handle the Windows system palette is used.

Converting a dot Net bitmap to a Victor Image

A dot Net bitmap is an object that holds image data and has its own functions for accessing the data. To prepare to copy the pixel data we use the bitmap functions to set the access to read and write, and to lock the bitmap while we access the data. Then simply copy the data into a Victor Image.

' Declaration of the copy function
  Declare Sub  CopyBitmaptoVicImage Lib "kernel32" Alias "RtlMoveMemory" \
  (ByVal des As Integer, Byval src As system.intptr, ByVal cnt As Integer)
'''''''''''''''''''''''
...
''''''''''''''''''''''''
 width = 400
 length = 200
 bpp = 24
 
 ' Allocate a Victor Image
 rcode = vicwin.allocimage(tempimage, width, length, bpp)

 ' Create a bitmap of the same dimensions
 bm = New bitmap(width, length)

 ' For this example fill the rect with green	
 g1 = graphics.fromimage(bm)
 g1.fillrectangle(brushes.green, 0, 0, width, length)

 ' Lock the bitmap and get a pointer to the pixel data
 bmrect.width = width
 bmrect.height = length
 mode = imagelockmode.readwrite
 format = pixelformat.Format24bppRgb
 bmd = bm.lockbits(bmrect, mode, format)
 bitmapbuff = bmd.scan0

 ' Copy pixel data from the bitmap to the Victor image
 CopyBitmaptoVicImage(tempimage.ibuff, bitmapbuff, width * length * bpp / 8)

 ' Release the bitmap memory
 bm.unlockbits(bmd)
			
				
				

In the above VB.NET example, a dot Net bitmap is created and filled with pixel data then copied into a Victor Image for processing.

Converting a Victor Image to a Device Dependent Bitmap

An image allocated with the allocimage function has a DIB handle, that is, the hBitmap element of the image descriptor is non-zero. This hBitmap can be used wherever a device dependent bitmap handle is requested, thus eliminating the need to convert to a device dependent bitmap (DDB).

But if the hBitmap element is zero and a device dependent bitmap is required then it is necessary to convert a Victor image to a DDB. The following function creates a device dependent bitmap from a Victor image:

int ConvertImageToBitmap(HDC hDC, imgdes *image, HBITMAP *hBitmap)
{
   int rcode;
   HPALETTE hPal;

   // Create a logical palette from Victor palette
   rcode = victowinpal(image, &hPal);
   if(rcode == NO_ERROR) {
      if(image->bmh->biBitCount <= 8) {
         // Select and realize the palette
         hPal = SelectPalette(hDC, hPal, 0);
         RealizePalette(hDC);
         }
      // Convert the DIB into a DDB
      // and return the DDB handle in hBitmap
      rcode = dibtobitmap(hDC, 
         (UCHAR huge *)image->bmh, hBitmap);
      if(image->bmh->biBitCount <= 8) 
         // Remove logpalette before releasing DC
         SelectPalette(hDC, hPal, 0);
      }
   return(rcode);
}

The bits per pixel of the resulting bitmap is dependent upon the display mode, i.e., a 256-color display mode produces an 8-bit DDB, and a 16-color display mode produces a 4-bit DDB. This is independent of the bits per pixel of the source image.


Converting a Victor Image to a dot Net bitmap

To convert a Victor Image into a dot Net bitmap we get the address of the image data (ibuff element of the image descriptor) and use it as one of the paramenters in the bitmap constructor.

   getbmhfromimage(bmh, myimage)
   width = bmh.biWidth
   length =  bmh.biHeight
   bpp = bmh.biBitCount
   bitmapbuff = IntPtr.op_Explicit(myimage.ibuff)

   ' Create a bitmap inside a Victor image	
   select case bpp 
	   case "1" 
		   format = pixelformat.Format1bppIndexed
	   exit select
	   case "8"
		   format = pixelformat.Format8bppIndexed
	   exit select
	   case "24"
		   format = pixelformat.Format24bppRgb
	   exit select
   end select      
   bm = New bitmap(width, length, myimage.buffwidth, format, bitmapbuff)

In the above VB.NET example, a dot Net bitmap is created inside a Victor image and ready to be operated on by any .NET graphics functions.


Adding Graphic Elements to an Image

Graphics elements such as text, lines, rectangles, and ellipses can be added to an image using the dot Net graphics functions.

   getbmhfromimage(bmh, myimage)
   width = bmh.biWidth
   length =  bmh.biHeight
   bpp = bmh.biBitCount
   bitmapbuff = IntPtr.op_Explicit(myimage.ibuff)

   ' Create a bitmap inside a Victor image	
   select case bpp 
	   case "1" 
		   format = pixelformat.Format1bppIndexed
	   exit select
	   case "8"
		   format = pixelformat.Format8bppIndexed
	   exit select
	   case "24"
		   format = pixelformat.Format24bppRgb
	   exit select
   end select      
   bm = New bitmap(width, length, myimage.buffwidth, format, bitmapbuff)
   g1 = graphics.fromimage(bm)

   action_requested = input_string
   if(action_requested <> "") then ' Add a graphic 
	   select case action_requested 
		   ' Add .NET graphic element
		   case "rectangle" 
			   g1.drawrectangle(pens.red, 50, 50, width-100, length-100)
		   exit select
		   case "block"
			   g1.fillrectangle(brushes.blue, 270, 200, 40, 30)
		   exit select
		   case "text"
			   g1.drawstring("hello", drawfont, brushes.green, 10, 10 )
		   exit select
	   end select
   end if

   vicwin.savetif("changedimage.tif", myimage, 0)

In the above VB.NET example, a dot Net bitmap is created inside a Victor image, a graphics object is created, and graphic elements and text are added to it. The changed image is saved as a tif file.


Windows DIB Functions

Windows provides the functions SetDIBitsToDevice, StretchDIBits, CreateDIBitmap, SetDIBits, and GetDIBits for working with device independent bitmaps. These functions can be used directly with Victor images. The use of image descriptor elements as arguments to the Windows functions is illustrated below.



SetDIBitsToDevice

SetDIBitsToDevice sets the bits from a DIB directly on a device context. This function copies a rectangle of image data from the DIB to a device context. To display the image beginning at (8,8) on a device context:

SetDIBitsToDevice(hdc, 8, 8, // x,y position on device context
   (unsigned)image.bmh->biWidth, // Image width
   (unsigned)image.bmh->biHeight, // Image height
   0, 0,    // Starting x,y in image 
   0U,    // Starting scanline
   (unsigned)image.bmh->biHeight,  // Number of lines to display
   image.ibuff,   // Address of image buffer
   (BITMAPINFO far *)image.bmh, // Address of BITMAPINFO 
   DIB_RGB_COLORS);  // Color usage constant


StretchDIBits

StretchDIBits moves a source rectangle from a DIB into a rectangle on a device context, stretching or compressing the image data to fit the dimensions of the destination rectangle.

When using this function to stretch an image area, remember that the parameters describing the DIB's starting x and y coordinates are in an upside down system. This function assumes y = 0 is at the bottom of the image.

To resize an image area to fit a 640 x 480 area beginning at (8,8) on a device context:

StretchDIBits(hdc, 8, 8,  // x,y position on device context
   640, 480,    // Width, height of DC rect 
   image.stx,    // Starting x in image
   image.bmh->biHeight - 1 - image.endy, // Starting y pos in DIB
   image.endx - image.stx + 1, // Image area width
   image.endy - image.sty + 1,  // Image area height
   image.ibuff,   // Address of image buffer
   (BITMAPINFO far *)image.bmh, // Address of BITMAPINFO 
   DIB_RGB_COLORS,  // Color usage constant
   SRCCOPY);   // Raster op

CreateDIBitmap

CreateDIBitmap creates a device dependent bitmap from a DIB.

To create a device dependent bitmap from an entire image:

CreateDIBitmap(hdc,     // Device context
   (BITMAPINFOHEADER far *)image.bmh, // BITMAPINFOHEADER 
   CBM_INIT,      // Initialize bitmap 
   image.ibuff,    // Address of image buffer
   (BITMAPINFO far *)image.bmh,   // Address of BITMAPINFO 
   DIB_RGB_COLORS);    // Color usage constant

SetDIBits

SetDIBits sets the bits of a bitmap to the values given in a DIB. That is, this function copies a specified number of rows of image data from a DIB to a device dependent bitmap.



GetDIBits

GetDIBits converts the bits in a device dependent bitmap into device independent format, and stores the values in a specified number of rows in a DIB. See Converting a Device Dependent Bitmap to an Image above for an example.

If GetDiBits is called with the lpBits parameter set to NULL, no image data is returned, only the biSizeImage field and color table of a BITMAPINFO structure are filled in.




Using the Windows Clipboard

The Windows clipboard is a common area for exchanging data between applications. The clipboard supports passing image data as DIB, bitmap, and palette objects.

When working with the clipboard, it is very important to remember that the clipboard maintains ownership of all objects passed to it. When passing an image to the clipboard, always pass a copy of the image. And when receiving an image from the clipboard, make a copy of the image owned by the clipboard.

Copying an Image to the Clipboard in .NET

In .NET we can use the Windows clipboard function SetDataObject to copy an image to the clipboard.

					
private void mnu_copy_Click(object sender, System.EventArgs e)
        {
            Bitmap bm;
            uint swidth = 0, slength = 0;
            int bpp;
            int rcode;
            vicwin.imgdes timage;
 
            timage = new vicwin.imgdes();

            swidth = vimage.endx - vimage.stx + 1;
            slength = vimage.endy - vimage.sty + 1;
 
            bpp = vicwinex.getbpp(ref vimage);
            rcode = vicwin.allocimage(ref timage, (int)swidth, (int)slength, bpp);
            if (rcode == vicwin.NO_ERROR)
                rcode = vicwin.copyimage(ref vimage, ref timage);
 
            bm = Bitmap.FromHbitmap((IntPtr)timage.hBitmap); 
            Clipboard.SetDataObject(bm, true);    // The .NET function does all the work of putting the copy on the clipboard
            vicwin.freeimage(ref timage);
        }

Copying an Image to the Clipboard as a DIB

In C/C++ we don't have access to the .NET functions so there are more steps involved.

In the following code imagetodib allocates space for a new DIB and copies the image area into the new DIB for passing to the clipboard.

void CopyDIBToClipboard(HWND hWnd, imgdes *image)
{
   unsigned char huge *dib;
   int rcode;
   HGLOBAL hMem;

   if(OpenClipboard(hWnd)) {
      EmptyClipboard(); // Clean clipboard of contents

      // Create a new DIB to pass to the clipboard
      rcode = imagetodib(image, &dib);
      if(rcode == NO_ERROR) { 
         // Get a handle to the new DIB
         hMem = (HGLOBAL)GlobalHandle(dib);
         // Unlock the handle to the DIB
         // Handle passed to clipboard must be unlocked!
         GlobalUnlock(hMem);
         // Copy the DIB to the clipboard
         SetClipboardData(CF_DIB, hMem);
         CloseClipboard();
         }
      }
   else
      MessageBox(hWnd,"Could not open clipboard", 0, MB_OK);
}

Copying an Image to the Clipboard as a Bitmap

The above routine can be modified to create a device dependent bitmap. In the code that follows, the bitmap handle to be passed to the clipboard is returned in the variable hBitmap.

   HBITMAP hBitmap;

   . . .

   hdc = GetDC(hWnd);
   // Convert image to a bitmap
   rcode = ConvertImageToBitmap(hdc, image, &hBitmap);
   if(rcode == NO_ERROR)
      // Copy the bitmap to the clipboard
      SetClipboardData(CF_BITMAP, hBitmap);
   ReleaseDC(hWnd, hdc);

The ConvertImageToBitmap function was presented in the earlier section, see Converting an Image to a Device Dependent Bitmap.

Copying a Palette to the Clipboard

The victowinpal function converts the palette associated with an image into a logical palette object and enters the logical palette handle in the hPal variable. The logical palette is then copied to the clipboard.

void CopyPaletteToClipboard(HWND hWnd, imgdes *image)
{
   HPALETTE hPal;

   if(OpenClipboard(hWnd)) {
      EmptyClipboard(); // Clean clipboard of contents

      // Create a PALETTE object from the image
      victowinpal(image, &hPal);
      if(hPal) {
         // Copy the palette to the clipboard
         SetClipboardData(CF_PALETTE, hPal);
         CloseClipboard();
         }
      }
   else
      MessageBox(hWnd,"Could not open clipboard", 0, MB_OK);
}

Pasting a DIB from the Clipboard

The dibtoimage function is used to allocate space for a new image and copy the DIB from the clipboard into the new image buffer.

// Get clipping from clipboard
void PasteDIBfromClipboard(HWND hWnd, imgdes *image)
{
   unsigned char huge *dib;
   int rcode=NO_ERROR;
   HGLOBAL hMem;

   if(OpenClipboard(hWnd)) {
      // Get DIB from clipboard
      if((hMem = GetClipboardData(CF_DIB)) != 0) {
         // Get address of DIB
         dib = (unsigned char huge *)GlobalLock(hMem);
         // Create a new image from the DIB
         dibtoimage(dib, image);
         // Unlock memory before closing
         GlobalUnlock(hMem);  
         }
      else 
         MessageBox(hWnd, "No DIB on clipboard", 0, MB_OK);
      CloseClipboard();      // Close the clipboard
      }
   else
      MessageBox(hWnd, "Could not open clipboard", 0,
         MB_OK);
}





Scanning Images

TWAIN Support

Victor TWAIN functions allow you to easily create an application to import images from any device that has a TWAIN data source (a broad range of scanners and video capture devices). An added benefit is that an optimal user interface is provided so you don't have to design a new interface for each device.

TWAIN Architecture

There are four components in the TWAIN architecture:

This relationship can be depicted as follows:

                      Application
                           |
                           |
                  Victor TWAIN module
                           |
                           |
                  TWAIN Source Manager
                    /             \
                   /               \
            Data Source 1       Data Source 2

Additional files necessary to acquire an image from a TWAIN data source are listed below.

Filename Description
TWAIN.DLL TWAIN 16-bit source manager
TWAIN_32.DLL TWAIN 32-bit source manager
TWAINDSM.DLL TWAIN 64-bit source manager
TWUNK_32.EXE Thunking module
TWUNK_16.EXE Thunking module
MSVCRT20.DLL Runtime library used by the source manager
xxx.DS TWAIN data source for device xxx

The thunking modules allow a 16- or 32-bit application to use a 16- or 32-bit data source. Data sources are available from the device manufacturers.

The Twain data source managers and thunking modules listed above should be installed in the \Windows directory. MSVCRT20.DLL should be installed in the \Windows\System directory (Windows 9x) or in the \Windows\System32 directory (Windows NT). Data source files xxx.DS should be in the \Windows\Twain, \Windows\Twain_32, or \Windows\Twain_64 directory, (based on the operating system).

Using the Victor TWAIN functions

The most common method of using the Victor TWAIN functions is to add two menu items to an application under the File menu: Select Source, which will call TWselectsource or TWselectsourcebyname and Acquire, which will call one of the Victor scan functions. You may also want to use TWdetecttwain to enable or disable these menu items.

The Victor scan functions are

TWscanimage Capture one image
TWscanimageex Capture one image without displaying the acquire dialog box
TWscancountimages Capture one or more images without displaying the acquire dialog box
TWscanmultipleimages Capture one or more images
TWscanmultipleimagesex Capture one or more images without displaying the acquire dialog box

The get-parameter functions (TWgetbrightness, TWgetcontrast, TWgetmeasurementunit, TWgetpixeltype, TWgetxresolution, TWgetyresolution ) are used to get the valid range of parameter values before calling the set-parameter functions. The get functions may not be able to verify a parameter change made by a set function because the new value to set is not sent to the device until a scan image function is called.

It is important to recognize that using a set-parameter function (TWsetbrightness, TWsetcontrast, TWsetmeasurementunit, TWsetpixeltype, TWsetxresolution, TWsetyresolution) does not guarantee a change in that parameter. A TWAIN device is under no obligation to allow a parameter to be modified. This is especially true if an acquire dialog box is displayed, since the user may change the selected parameter anyway. To learn more about TWAIN, the TWAIN toolkit may be downloaded from ftp://caere.com/pub/twain.

A TWAIN Example

Here are two examples of simple implementation to acquire an image from a TWAIN device.

     // C# .NET example 
     public static int getscanedimage(ref vicwin.imgdes newimage)
       {
           vicwin.imgdes tempimg;
           int swidth = 0, slength = 0, bpp = 0;
           int rcode;
           int hwnd;

           tempimg = new vicwin.imgdes();


           hwnd = GetActiveWindow();
           rcode = vicwin.TWscanimage(hwnd, ref  newimage);
           calc_image_dimensions(ref newimage, ref swidth, ref slength);
           bpp = getbpp(ref newimage);

           if (rcode == vicwin.NO_ERROR)
           {
               if (newimage.hBitmap == 0)
               { //  if it's a packed dib, use dibtoimage
                   rcode = vicwin.allocimage(ref  tempimg, swidth, slength, bpp);
                   if (rcode == vicwin.NO_ERROR)
                   {
                       rcode = vicwin.dibtoimage(newimage.bmh, ref  tempimg);
                       if (rcode == vicwin.NO_ERROR)
                       {
                           vicwin.freeimage(ref newimage); // Release original scanned image
                           vicwin.copyimgdes(ref tempimg, ref newimage);  // Replace with new image
                       }
                   }
               }
           }
           return (rcode);
       }					
					

    // C/C++ traditional Windows example
    // Select source command selected
void DoMenuSelectSource(HWND hWnd)
{
   int rcode;
   
   // Call the TWAIN source manager to select a source 
   // for image acquisition
   rcode = TWselectsource(hWnd);
   if(rcode != NO_ERROR)
     // Handle any errors here
}

// Acquire command selected
void DoMenuAcquire(HWND hWnd, 
   imgdes far *simage) // Store captured image in simage
{
   int rcode;
  
   // Use App name to display in Source dialog box.
   TWsetproductname("MyApp");

   // Display the device user interface dialog box and 
   // capture an image
   rcode = TWscanimage(hWnd, simage);
   if(rcode != NO_ERROR)
      // Handle any errors here
}
For additional examples see the individual scan functions in the Library Reference section.




Victor Functions by Category

Memory Management

These functions allocate or free global memory for image storage.

allocDIB                     allocate space for an image in memory
allocimage                   allocate space for an image in global memory
freebuffer                   release memory from a savefiletobuffer function
freeimage                    free an allocated image
getbuffersize                determine size of a buffer from a savefiletobuffer function

File Handling

The save and load operations transfer image data between an image area and the disk. The info routines provide information about a file before loading. Binary, BMP, GIF, JPEG, PCX, TGA and TIFF file formats are supported.

loadbif                         load binary image data file
loadbmp                         load BMP or DIB file
loadbmpfrombuffer               load BMP or DIB file from memory
loadbmppalette                  load BMP palette
loadbmppalettefrombuffer        load BMP palette from memory
loadgif                         load GIF image
loadgifframe                    load GIF image from multiframe file
loadgifframefrombuffer          load GIF image from multiframe file in memory
loadgiffrombuffer               load GIF file from memory
loadgifpalette                  load GIF palette
loadgifpalettefrombuffer        load GIF palette from memory
loadgifglobalpalette            load GIF global palette
loadgifglobalpalettefrombuffer  load GIF global palette from memory
loadgifframepalette             load GIF frame palette
loadgifframepalettefrombuffer   load GIF frame palette from memory
loadjpg                         load JPEG file
loadjpgex                       load JPEG file without converting from ycc to rgb
loadjpgfrombuffer               load JPEG file from memory buffer
loadjpgfrombufferex             load JPEG file without converting from ycc to rgb
loadjpgthumbnail                load a thumbnail image from a JPEG file
loadjpgthumbnailfrombuffer      load a thumbnail image from a JPEG file in memory
loadpcx                         load PCX file
loadpcxpalette                  load PCX palette
loadpng                         load PNG file
loadpngfrombuffer               load PNG file from memory
loadpngwithalpha                load PNG image and alpha channel          
loadpngfrombufferwithalpha      load PNG image and alpha channel from memory
loadpngpalette                  load PNG palette
loadpngpalettefrombuffer        load PNG palette from memory
loadtga                         load TGA file
loadtgapalette                  load TGA palette
loadtgawithalpha                load TGA image and alpha channel
loadtif                         load TIFF file
loadtiffrombuffer               load image from TIFF file in memory
loadtifpage                     load image from TIFF multipage file
loadtifpagebyindex              load image from TIFF multipage file
loadtifpagebyindexfrombuffer    load image from TIFF multipage file in memory
loadtifpagebyindexfrombufferwithalpha  load image and alpha channel image from file in memory
loadtifpalette                  load palette from TIFF file
loadtifpalettefrombuffer        load palette from TIFF file from memory
loadtifpalettepage              load palette from TIFF multipage file
loadtifpalettepagebyindex       load palette from TIFF multipage file
loadtifwithalpha                load TIFF image and alpha channel
savebif                         save image as binary data file
savebmp                         save image as BMP file
savebmptobuffer                 save image as BMP file in memory
saveeps                         save image as EPS file
savegif                         save image as GIF file
savegifex                       save image as GIF file with transparency and interlace options
savegiftobufferex               save image as GIF file with transparency,
                                   interlace, and compression options to memory 
savegifframe                    save image as a frame in a multiframe GIF file
savegifmultiframetobuffer       save images as frames in a multiframe GIF file in memory
savejpg                         save image as JPEG file
savejpgex                       save image as JPEG file with mode option
savejpgtobuffer                 save image as JPEG file in memory
savejpgtobufferex               save image as JPEG file with mode option in memory
savepcx                         save image as PCX file
savepng                         save image as PNG file
savepngex                       save image as PNG with transparent color
savepngtobuffer                 save image as PNG file to memory
savepngtobufferex               save image as PNG with transparent color to memory
savetga                         save image as TGA file
savetif                         save image as TIFF file
savetifpage                     save image in a multipage TIFF file
savetiftobuffer                 save image as TIFF file to memory
getgifcomment                   read comment from a GIF file
getpngcomment                   read comment from a PNG file
setgifcomment                   set comment and version for saving a GIF file
bmpinfo                         BMP file information 
bmpinfofrombuffer               BMP file information from memory
gifframecount                   get number of frames in GIF file
gifframecountfrombuffer         get number of frames in GIF file in memory
gifinfo                         GIF file information 
gifinfoallframes                get image info about all frames in GIF file
gifinfoallframesfrombuffer      get image info about all frames in GIF file in memory
gifinfoframe                    get image info about one frame in GIF file
gifinfoframefrombuffer          get image info about one frame in GIF file in memory
gifinfofrombuffer               GIF file information from memory
jpeginfo                        JPEG file information 
jpeginfoex                      JPEG file information 
jpeginfofrombuffer              JPEG file information from memory buffer
jpeginfofrombufferex            JPEG file information from memory buffer
jpegsetthumbnailsize            set JPEG thumbnail size
jpegsetxyresolution             set resolution dta for saving JPEG files
pcxinfo                         PCX file information 
pnginfo                         PNG file information 
pnginfofrombuffer               PNG file information from memory
pnggetxyresolution              get resolution data from a PNG file
pngsetxyresolution              set resolution data for saving PNG files
tgainfo                         TGA file information 
tiffinfo                        TIFF file information 
tiffinfofrombuffer              TIFF file information from memory
tiffinfopage                    TIFF information about a single page in a multipage TIFF file
tiffinfopagebyindex             TIFF information about a single page in a multipage TIFF file
tiffinfopagebyindexfrombuffer   TIFF info about a single page from memory
tiffinfopagebyindexex           expanded TIFF info about a single page  
tiffinfopagebyindexfrombufferex expanded TIFF info about a single page from memory
tiffgetdnstring                 get document name from TIFF file
tiffgetpageinfo                 TIFF file information about all pages
tiffgetpageinfofrombuffer       TIFF file info about all pages in memory
tiffgetSOIofspagebyindex        get offset of JPEG-compressed data
tiffgetSOIofspagebyindexfrombuffer get offset of JPEG-compressed data
tiffgetxyresolution             get resolution data from a TIFF file
tiffgetxyresolutionpagebyindex  get resolution data about a single page from a TIFF file
tiffsetdnstring                 set document name for saving TIFF file
tiffsetxyresolution             set resolution data for saving a TIFF file
jpeggeterror                    report last JPEG error
pnggeterror                     report last PNG error
tiffgeterror                    report last TIFF error
unlockLZW                       enable LZW compression/decompression (requires license agreement with Unisys)

Image Processing

Image processing functions alter the brightness level values of 8- or 24-bit images. Functions marked with "+1" also operate on 1-bit images. Image processing functions can operate on the entire image or any rectangular area within the image.

addnoise               add random noise
addtext                add text 
addtextex              add text	
blur                   smoothing filter
blurthresh             smoothing filter with threshold
brightenmidrange       raise brightness of intermediate levels
changebright           increase or decrease brightness
dilate                 darken by enlarging dark areas (+1)
divide                 divide by factor
dropbits               remove noise by dropping less significant bits
emboss                 emboss filter
embossongray           emboss filter onto a gray background
erode                  brighten by enlarging bright areas (+1)
exchangelevel          change range of levels to new value
expandcontrast         increase contrast
gammabrighten          apply a gamma brightness correction
gaussianblur           normal distribution smoothing filter
histobrighten          histogram brightening
histoequalize          histogram equalization
kodalith               create high contrast image
limitlevel             set maximum brightness level
matrixconv             matrix convolution, 3 x 3 kernel
matrixconvex           matrix convolution, 63 x 63 kernel
medianfilter           remove noise by median filter, 3- to 11-pixel edge
multiply               multiply by factor
multiplyex             multiply by floating point factor
negative               negative image (+1)
outline                edge detection filter
outlineongray          edge detection filter onto a gray background
pixellize              pixellation
removenoise            remove noise by median filter
sharpen                sharpening filter
sharpengentle          gentle sharpening filter
threshold              set minimum brightness level
tile                   fill with multiple copies of an image 
usetable               set pixel values based on table
zeroimage              set all pixels to the same value (+1)

Multi-Image Processing

addimage               add two images
addtexture             impose operator texture onto source
andimage               AND two images (+1)
bleachimage            multiply negatives of two images    
correlateimages        fill result image with pixel data representing correlation coefficients
cover                  overlay two images
coverclear             overlay two images, transparent color
darker                 combine darker pixels of two images
difference             calculate difference onto gray background	 
differenceab           calculate absolute value of difference
displace               offset source based on operator
divideimage            divide source by operator	
isolate                isolate source based on mask
lighter                combine lighter pixels of two images	
multnegimage           negative of bleachimage
multiplyimage          multiply two images
orimage                OR two images (+1)
screen                 high contrast using dither screen filter
subimage               subtract operator from source
wtaverage              weighted average of two images, uniform wt
wtaveragemask          weighted average of two images, wt based on mask
xorimage               XOR two images (+1)

Image Manipulation

These operations alter an image area's shape, dimensions, position, or orientation. Image data is read from a source image area, modified, and written to a result area.

copyimage              copy image and palette (+1)
copyimagebits          copy image data only (+1)
displace               alter pixel positions 
extractcolorrange      create mask based on color range
extractplane           copy R-, G-, B- or H-, S-, V-plane
flipimage              flip image top to bottom (+1)
insertplane            replace R-, G-, B- or H-, S-, V-plane
mirrorimage            reverse image left to right (+1)
resize                 resize image (+1)
resizeex               resize image with interpolation
rotate                 rotate image any angle (+1)
rotateex               rotate image any angle with pixel replication (+1)
rotate90               rotate image 90 degrees (+1)
tile                   fill with multiple copies of an image 

Image Descriptor Modification

The image descriptor is a data structure that contains information that describes an image. These functions simplify the entry of data into an image descriptor.

copyimgdes             copy all image descriptor elements
imageareatorect        set RECT coordinates from an image area
recttoimagearea        set an image area from a RECT data structure
setimagearea           set the image area of interest 
setupimgdes            assign image descriptor fields based on the BITMAPINFOHEADER of a packed DIB
zeroimgdes             set all image descriptor elements to zero

Color Reduction and Image Conversion

Images and color palettes are converted between formats.

clienttoimage             capture window client area to image
cmykimagetorgbimage       convert 32-bit CMYK image to 24-bit RGB
colordither               create dithered color image, 16- or 256-color palette
colorscatter              create scatter color image, 16- or 256-color palette
colortogray               color image to grayscale
convert1bitto8bit         1-bit image to 8-bit image
convert1bitto8bitsmooth   1-bit image to 8-bit image with smoothing
convert8bitto1bit         8-bit image to 1-bit image with dither, scatter, or threshold options
convert8bitto1bitex       convert 8- to 1-bit with dither matrix
convertgray8to16          8-bitgrayscale to 16-bit grayscale image
convertgray16to8          16-bitgrayscale to 8-bit grayscale image
convertgray16to8ex        convert 16- to 8-bit with contrast expansion 
convertgray32to8          convert 32- to 8-bit grayscale 
convertgray32to16         convert 32- to 16-bit grayscale
convertrgbpal             24-bit RGB image to 8-bit with optimum palette 
convertrgbpalex           24-bit RGB image to 8-bit with optimum palette with diffusion scatter and color matching options
convertpalrgb             8-bit image to 24-bit RGB
ddbtoimage                device dependent bitmap to image
dibtobitmap               DIB to a device specific bitmap
dibtoimage                DIB to a Victor-compatible image
dibsecttoimage            DIB section to a Victor-compatible image
hsvimagetorgbimage        convert 24-bit HSV image to 24-bit RGB image 
imagetodib                extract an image area and create a new DIB
matchcolorimage           match image to a specified palette
matchcolorimageex         match image to a specified palette with diffusion scatter and color matching options
reduceimagecolors         decrease the number of colors used in an image
rgbimagetocmykimage       convert 24-bit RGB image to 32-bit CMYK image
rgbimagetohsvimage        convert 24-bit RGB image to 24-bit HSV image 
windowtoimage             capture window to imag

Color Palette Operations

copyimagepalette          copy image palette data only
defaultpalette            establish a 16-color palette consisting of the default Windows colors
makepalette               create a color palette
rainbowpalette            create a 256-color rainbow palette
standardpalette           establish a 256-color palette consisting of the default Windows colors
hsv2rgb                   convert hue, saturation, value table to red, green, blue palette
rgb2hsv                   convert red, green, blue palette to hue, saturation, value table
updatebitmapcolortable    update internal color info (32-bit only)
victowinpal               convert image palette to Windows logical palette
wintovicpal               convert Windows logical palette to image palette

Display Functions

drawhisto                 display histogram on a device context
viewimage                 display image on a device context
viewimageex               display image at specified position with automatic color reduction

Printer Functions

The printer functions print an image area at any size and position on a printer device context.

printimage                print image 
printimagenoeject         print image without ejecting the page
printimageenddoc          end print-document and eject page
printimagestartdoc        begin print-document

Image Analysis

calcavglevel             calculate average brightness level
calcavglevelfloat        calculate average brightness level as a float
calchisto                calculate histogram
calchistorgb             calculate histogram treating palette color image as an RGB image
calcminmax               calculate minimum and maximum pixel values
correlationcoef          calculate correlation coefficient between two images
correlationcoefRGB       calculate correlation coefficient between two RGB images
correlateimages          fill result image with pixel data representing correlation coefficients
getpixelcolor            read pixel value at buffer (x,y)
isgrayscaleimage         determine if image is grayscale 
pixelcount               count pixels within a brightness level range
setpixelcolor            set pixel at buffer (x,y) to value
sortpixelsbyval          sort pixel intensities into an array

System Information

Victorversion            get Victor Library version number 
Victorversiondate        get Victor Library version and date
Victorversionex          get Victor Library version information
VicStaticLibStart        initialize static library
VicStaticLibTerm         terminate static library

TWAIN Device Control Functions

Control a TWAIN-compliant scanner and Automatic Document Feeder (ADF), set parameters, get parameters, and capture images.

TWopen                  open TWAIN data source and data source manager
TWclose                 close TWAIN data source and data source manager
TWdetecttwain           detect TWAIN source manager 
TWgetbrightness         set scanner brightness
Twgetcontrast           set scanner contrast
TWgeterror              get extended error information
TWgetfeeder             get document feeder status
TWgetmeasureunit        get valid measurement units
TWgetpixeltype          restrict pixel type
TWgetphysicalsize       get maximum image size
TWgetsourcenames        get names of available data sources
TWgetxresolution        set scanner horizontal resolution
TWgetyresolution        set scanner vertical resolution
TWscancountimages       acquire specified number of images
TWscanimage             acquire image from TWAIN data source
TWscanimageex           acquire image from TWAIN data source
                           without displaying Acquire dialog box
TWscanmultipleimages    acquire multiple images
TWscanmultipleimagesex  acquire multiple images without displaying
                           Acquire dialog box
TWselectsource          select a new data source
TWselectsourcebyname    select a data source by name
TWsetbrightness         set scanner brightness
TWsetcontrast           set scanner contrast
TWsetduplex             set duplex operation
TWsetfeeder             set document feeder
TWsetmeasureunit        set measurement unit type
TWsetpagesize           set maximum image size
TWsetpixeltype          restrict pixel type
TWsetproductname        inform data source of application name
TWsetxresolution        set scanner horizontal resolution
TWsetyresolution        set scanner vertical resolution
TWStaticLibStart        initialize static library
TWStaticLibTerm         terminate static library
TWvicversion            return Victor Library TWAIN support module version number

Return to top