mirror of http://192.168.1.51:8099/lmh188/twain3.0
369 lines
11 KiB
C
369 lines
11 KiB
C
/*====================================================================*
|
|
- Copyright (C) 2001 Leptonica. All rights reserved.
|
|
-
|
|
- Redistribution and use in source and binary forms, with or without
|
|
- modification, are permitted provided that the following conditions
|
|
- are met:
|
|
- 1. Redistributions of source code must retain the above copyright
|
|
- notice, this list of conditions and the following disclaimer.
|
|
- 2. Redistributions in binary form must reproduce the above
|
|
- copyright notice, this list of conditions and the following
|
|
- disclaimer in the documentation and/or other materials
|
|
- provided with the distribution.
|
|
-
|
|
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
|
|
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*====================================================================*/
|
|
|
|
/*!
|
|
* \file leptwin.c
|
|
* <pre>
|
|
*
|
|
* This file contains Leptonica routines needed only on Microsoft Windows
|
|
*
|
|
* Currently it only contains one public function
|
|
* (based on dibsectn.c by jmh, 03-30-98):
|
|
*
|
|
* HBITMAP pixGetWindowsHBITMAP(PIX *pix)
|
|
* </pre>
|
|
*/
|
|
|
|
#ifdef _WIN32
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "allheaders.h"
|
|
#include "leptwin.h"
|
|
|
|
/* Macro to determine the number of bytes per line in the DIB bits.
|
|
* This accounts for DWORD alignment by adding 31 bits,
|
|
* then dividing by 32, then rounding up to the next highest
|
|
* count of 4-bytes. Then, we multiply by 4 to get the total byte count. */
|
|
#define BYTESPERLINE(Width, BPP) ((l_int32)((((DWORD)(Width) * (DWORD)(BPP) + 31) >> 5)) << 2)
|
|
|
|
|
|
/* **********************************************************************
|
|
DWORD DSImageBitsSize(LPBITMAPINFO pbmi)
|
|
|
|
PARAMETERS:
|
|
LPBITMAPINFO - pointer to a BITMAPINFO describing a DIB
|
|
|
|
RETURNS:
|
|
DWORD - the size, in bytes, of the DIB's image bits
|
|
|
|
REMARKS:
|
|
Calculates and returns the size, in bytes, of the image bits for
|
|
the DIB described by the BITMAPINFO.
|
|
********************************************************************** */
|
|
static DWORD
|
|
DSImageBitsSize(LPBITMAPINFO pbmi)
|
|
{
|
|
switch(pbmi->bmiHeader.biCompression)
|
|
{
|
|
case BI_RLE8: /* wrong if haven't called DSCreateDIBSection or
|
|
* CreateDIBSection with this pbmi */
|
|
case BI_RLE4:
|
|
return pbmi->bmiHeader.biSizeImage;
|
|
break;
|
|
default: /* should not have to use "default" */
|
|
case BI_RGB:
|
|
case BI_BITFIELDS:
|
|
return BYTESPERLINE(pbmi->bmiHeader.biWidth, \
|
|
pbmi->bmiHeader.biBitCount * pbmi->bmiHeader.biPlanes) *
|
|
pbmi->bmiHeader.biHeight;
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* **********************************************************************
|
|
DWORD ImageBitsSize(HBITMAP hbitmap)
|
|
|
|
PARAMETERS:
|
|
HBITMAP - hbitmap
|
|
|
|
RETURNS:
|
|
DWORD - the size, in bytes, of the HBITMAP's image bits
|
|
|
|
REMARKS:
|
|
Calculates and returns the size, in bytes, of the image bits for
|
|
the DIB described by the HBITMAP.
|
|
********************************************************************** */
|
|
static DWORD
|
|
ImageBitsSize(HBITMAP hBitmap)
|
|
{
|
|
DIBSECTION ds;
|
|
|
|
GetObject(hBitmap, sizeof(DIBSECTION), &ds);
|
|
switch( ds.dsBmih.biCompression )
|
|
{
|
|
case BI_RLE8: /* wrong if haven't called DSCreateDIBSection or
|
|
* CreateDIBSection with this pbmi */
|
|
case BI_RLE4:
|
|
return ds.dsBmih.biSizeImage;
|
|
break;
|
|
default: /* should not have to use "default" */
|
|
case BI_RGB:
|
|
case BI_BITFIELDS:
|
|
return BYTESPERLINE(ds.dsBmih.biWidth, \
|
|
ds.dsBmih.biBitCount * ds.dsBmih.biPlanes) *
|
|
ds.dsBmih.biHeight;
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief setColormap(LPBITMAPINFO pbmi, PIXCMAP *cmap)
|
|
*
|
|
* \param[in] pbmi pointer to a BITMAPINFO describing a DIB
|
|
* \param[in] cmap leptonica colormap
|
|
* \return number of colors in cmap
|
|
*/
|
|
static int
|
|
setColormap(LPBITMAPINFO pbmi,
|
|
PIXCMAP *cmap)
|
|
{
|
|
l_int32 i, nColors, rval, gval, bval;
|
|
|
|
nColors = pixcmapGetCount(cmap);
|
|
for (i = 0; i < nColors; i++) {
|
|
pixcmapGetColor(cmap, i, &rval, &gval, &bval);
|
|
pbmi->bmiColors[i].rgbRed = rval;
|
|
pbmi->bmiColors[i].rgbGreen = gval;
|
|
pbmi->bmiColors[i].rgbBlue = bval;
|
|
pbmi->bmiColors[i].rgbReserved = 0;
|
|
}
|
|
pbmi->bmiHeader.biClrUsed = nColors;
|
|
return nColors;
|
|
}
|
|
|
|
/* **********************************************************************
|
|
HBITMAP DSCreateBitmapInfo(l_int32 width, l_int32 height, l_int32 depth,
|
|
PIXCMAP *cmap)
|
|
|
|
PARAMETERS:
|
|
l_int32 width - Desired width of the DIBSection
|
|
l_int32 height - Desired height of the DIBSection
|
|
l_int32 depth - Desired bit-depth of the DIBSection
|
|
PIXCMAP cmap - leptonica colormap for depths < 16
|
|
|
|
RETURNS:
|
|
LPBITMAPINFO - a ptr to BITMAPINFO of the desired size and bit-depth
|
|
NULL on failure
|
|
|
|
REMARKS:
|
|
Creates a BITMAPINFO based on the criteria passed in as parameters.
|
|
|
|
********************************************************************** */
|
|
static LPBITMAPINFO
|
|
DSCreateBitmapInfo(l_int32 width,
|
|
l_int32 height,
|
|
l_int32 depth,
|
|
PIXCMAP *cmap)
|
|
{
|
|
l_int32 nInfoSize;
|
|
LPBITMAPINFO pbmi;
|
|
LPDWORD pMasks;
|
|
|
|
nInfoSize = sizeof(BITMAPINFOHEADER);
|
|
if( depth <= 8 )
|
|
nInfoSize += sizeof(RGBQUAD) * (1 << depth);
|
|
if((depth == 16) || (depth == 32))
|
|
nInfoSize += (3 * sizeof(DWORD));
|
|
|
|
/* Create the header big enough to contain color table and
|
|
* bitmasks if needed. */
|
|
pbmi = (LPBITMAPINFO)malloc(nInfoSize);
|
|
if (!pbmi)
|
|
return NULL;
|
|
|
|
ZeroMemory(pbmi, nInfoSize);
|
|
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
pbmi->bmiHeader.biWidth = width;
|
|
pbmi->bmiHeader.biHeight = height;
|
|
pbmi->bmiHeader.biPlanes = 1;
|
|
pbmi->bmiHeader.biBitCount = depth;
|
|
|
|
/* override below for 16 and 32 bpp */
|
|
pbmi->bmiHeader.biCompression = BI_RGB;
|
|
|
|
/* ?? not sure if this is right? */
|
|
pbmi->bmiHeader.biSizeImage = DSImageBitsSize(pbmi);
|
|
|
|
pbmi->bmiHeader.biXPelsPerMeter = 0;
|
|
pbmi->bmiHeader.biYPelsPerMeter = 0;
|
|
pbmi->bmiHeader.biClrUsed = 0; /* override below */
|
|
pbmi->bmiHeader.biClrImportant = 0;
|
|
|
|
switch(depth)
|
|
{
|
|
case 24:
|
|
/* 24bpp requires no special handling */
|
|
break;
|
|
case 16:
|
|
/* if it's 16bpp, fill in the masks and override the
|
|
* compression. These are the default masks -- you
|
|
* could change them if needed. */
|
|
pMasks = (LPDWORD)(pbmi->bmiColors);
|
|
pMasks[0] = 0x00007c00;
|
|
pMasks[1] = 0x000003e0;
|
|
pMasks[2] = 0x0000001f;
|
|
pbmi->bmiHeader.biCompression = BI_BITFIELDS;
|
|
break;
|
|
case 32:
|
|
/* if it's 32 bpp, fill in the masks and override
|
|
* the compression */
|
|
pMasks = (LPDWORD)(pbmi->bmiColors);
|
|
/*pMasks[0] = 0x00ff0000; */
|
|
/*pMasks[1] = 0x0000ff00; */
|
|
/*pMasks[2] = 0x000000ff; */
|
|
pMasks[0] = 0xff000000;
|
|
pMasks[1] = 0x00ff0000;
|
|
pMasks[2] = 0x0000ff00;
|
|
|
|
pbmi->bmiHeader.biCompression = BI_BITFIELDS;
|
|
break;
|
|
case 8:
|
|
case 4:
|
|
case 1:
|
|
setColormap(pbmi, cmap);
|
|
break;
|
|
}
|
|
return pbmi;
|
|
}
|
|
|
|
/* **********************************************************************
|
|
HBITMAP DSCreateDIBSection(l_int32 width, l_int32 height, l_int32 depth,
|
|
PIXCMAP *cmap)
|
|
|
|
PARAMETERS:
|
|
l_int32 width - Desired width of the DIBSection
|
|
l_int32 height - Desired height of the DIBSection
|
|
l_int32 depth - Desired bit-depth of the DIBSection
|
|
PIXCMAP cmap - leptonica colormap for depths < 16
|
|
|
|
RETURNS:
|
|
HBITMAP - a DIBSection HBITMAP of the desired size and bit-depth
|
|
NULL on failure
|
|
|
|
REMARKS:
|
|
Creates a DIBSection based on the criteria passed in as parameters.
|
|
|
|
********************************************************************** */
|
|
static HBITMAP
|
|
DSCreateDIBSection(l_int32 width,
|
|
l_int32 height,
|
|
l_int32 depth,
|
|
PIXCMAP *cmap)
|
|
{
|
|
HBITMAP hBitmap;
|
|
l_int32 nInfoSize;
|
|
LPBITMAPINFO pbmi;
|
|
HDC hRefDC;
|
|
LPBYTE pBits;
|
|
|
|
pbmi = DSCreateBitmapInfo (width, height, depth, cmap);
|
|
if (!pbmi)
|
|
return NULL;
|
|
|
|
hRefDC = GetDC(NULL);
|
|
hBitmap = CreateDIBSection(hRefDC, pbmi, DIB_RGB_COLORS,
|
|
(void **) &pBits, NULL, 0);
|
|
nInfoSize = GetLastError();
|
|
ReleaseDC(NULL, hRefDC);
|
|
free(pbmi);
|
|
|
|
return hBitmap;
|
|
}
|
|
|
|
|
|
/*!
|
|
* \brief pixGetWindowsHBITMAP()
|
|
*
|
|
* \param[in] pix
|
|
* \return Windows hBitmap, or NULL on error
|
|
*
|
|
* <pre>
|
|
* Notes:
|
|
* (1) It's the responsibility of the caller to destroy the
|
|
* returned hBitmap with a call to DeleteObject (or with
|
|
* something that eventually calls DeleteObject).
|
|
* </pre>
|
|
*/
|
|
HBITMAP
|
|
pixGetWindowsHBITMAP(PIX *pix)
|
|
{
|
|
l_int32 width, height, depth;
|
|
l_uint32 *data;
|
|
HBITMAP hBitmap = NULL;
|
|
BITMAP bm;
|
|
DWORD imageBitsSize;
|
|
PIX *pixt = NULL;
|
|
PIXCMAP *cmap;
|
|
|
|
PROCNAME("pixGetWindowsHBITMAP");
|
|
if (!pix)
|
|
return (HBITMAP)ERROR_PTR("pix not defined", procName, NULL);
|
|
|
|
pixGetDimensions(pix, &width, &height, &depth);
|
|
cmap = pixGetColormap(pix);
|
|
|
|
if (depth == 24) depth = 32;
|
|
if (depth == 2) {
|
|
pixt = pixConvert2To8(pix, 0, 85, 170, 255, TRUE);
|
|
if (!pixt)
|
|
return (HBITMAP)ERROR_PTR("unable to convert pix from 2bpp to 8bpp",
|
|
procName, NULL);
|
|
depth = pixGetDepth(pixt);
|
|
cmap = pixGetColormap(pixt);
|
|
}
|
|
|
|
if (depth < 16) {
|
|
if (!cmap)
|
|
cmap = pixcmapCreateLinear(depth, 1<<depth);
|
|
}
|
|
|
|
hBitmap = DSCreateDIBSection(width, height, depth, cmap);
|
|
if (!hBitmap)
|
|
return (HBITMAP)ERROR_PTR("Unable to create HBITMAP", procName, NULL);
|
|
|
|
/* By default, Windows assumes bottom up images */
|
|
if (pixt)
|
|
pixt = pixFlipTB(pixt, pixt);
|
|
else
|
|
pixt = pixFlipTB(NULL, pix);
|
|
|
|
/* "standard" color table assumes bit off=black */
|
|
if (depth == 1) {
|
|
pixInvert(pixt, pixt);
|
|
}
|
|
|
|
/* Don't byte swap until done manipulating pix! */
|
|
if (depth <= 16)
|
|
pixEndianByteSwap(pixt);
|
|
|
|
GetObject (hBitmap, sizeof(BITMAP), &bm);
|
|
imageBitsSize = ImageBitsSize(hBitmap);
|
|
data = pixGetData(pixt);
|
|
if (data) {
|
|
memcpy (bm.bmBits, data, imageBitsSize);
|
|
} else {
|
|
DeleteObject (hBitmap);
|
|
hBitmap = NULL;
|
|
}
|
|
pixDestroy(&pixt);
|
|
|
|
return hBitmap;
|
|
}
|
|
|
|
#endif /* _WIN32 */
|