blob: 3a95b75f83b74fc550ccf2e7ce3779cf4c6de3e2 [file] [log] [blame]
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
- This software is distributed in the hope that it will be
- useful, but with NO WARRANTY OF ANY KIND.
- No author or distributor accepts responsibility to anyone for the
- consequences of using this software, or for whether it serves any
- particular purpose or works at all, unless he or she says so in
- writing. Everyone is granted permission to copy, modify and
- redistribute this source code, for commercial or non-commercial
- purposes, with the following restrictions: (1) the origin of this
- source code must not be misrepresented; (2) modified versions must
- be plainly marked as such; and (3) this notice may not be removed
- or altered from any source or modified source distribution.
*====================================================================*/
/*
* rotateorth.c
*
* Top-level rotation by multiples of 90 degrees
* PIX *pixRotateOrth()
*
* 180-degree rotation
* PIX *pixRotate180()
*
* 90-degree rotation (both directions)
* PIX *pixRotate90()
*
* Left-right flip
* PIX *pixFlipLR()
*
* Top-bottom flip
* PIX *pixFlipTB()
*/
#include <stdio.h>
#include <stdlib.h>
#include "allheaders.h"
/*!
* pixRotateOrth()
*
* Input: pixs (all depths)
* quads (0-3; number of 90 degree cw rotations)
* Return: pixd, or null on error
*/
PIX *
pixRotateOrth(PIX *pixs,
l_int32 quads)
{
PROCNAME("pixRotateOrth");
if (!pixs)
return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
if (quads < 0 || quads > 4)
return (PIX *)ERROR_PTR("quads not in {0,1,2,3,4}", procName, NULL);
if (quads == 0 || quads == 4)
return pixCopy(NULL, pixs);
else if (quads == 1)
return pixRotate90(pixs, 1);
else if (quads == 2)
return pixRotate180(NULL, pixs);
else /* quads == 3 */
return pixRotate90(pixs, -1);
}
/*!
* pixRotate180()
*
* Input: pixd (<optional>; can be null, equal to pixs,
* or different from pixs)
* pixs (all depths)
* Return: pixd, or null on error
*
* Notes:
* (1) This does a 180 rotation of the image about the center,
* which is equivalent to a left-right flip about a vertical
* line through the image center, followed by a top-bottom
* flip about a horizontal line through the image center.
* (2) There are 3 cases for input:
* (a) pixd == null (creates a new pixd)
* (b) pixd == pixs (in-place operation)
* (c) pixd != pixs (existing pixd)
* (3) For clarity, use these three patterns, respectively:
* (a) pixd = pixRotate180(NULL, pixs);
* (b) pixRotate180(pixs, pixs);
* (c) pixRotate180(pixd, pixs);
*/
PIX *
pixRotate180(PIX *pixd,
PIX *pixs)
{
l_int32 d;
PROCNAME("pixRotate180");
if (!pixs)
return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
d = pixGetDepth(pixs);
if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
procName, NULL);
/* Prepare pixd for in-place operation */
if ((pixd = pixCopy(pixd, pixs)) == NULL)
return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
pixFlipLR(pixd, pixd);
pixFlipTB(pixd, pixd);
return pixd;
}
/*!
* pixRotate90()
*
* Input: pixs (all depths)
* direction (1 = clockwise, -1 = counter-clockwise)
* Return: pixd, or null on error
*
* Notes:
* (1) This does a 90 degree rotation of the image about the center,
* either cw or ccw, returning a new pix.
* (2) The direction must be either 1 (cw) or -1 (ccw).
*/
PIX *
pixRotate90(PIX *pixs,
l_int32 direction)
{
l_int32 wd, hd, d, wpls, wpld;
l_uint32 *datas, *datad;
PIX *pixd;
PROCNAME("pixRotate90");
if (!pixs)
return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
d = pixGetDepth(pixs);
if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
procName, NULL);
if (direction != 1 && direction != -1)
return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
hd = pixGetWidth(pixs);
wd = pixGetHeight(pixs);
if ((pixd = pixCreate(wd, hd, d)) == NULL)
return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
pixCopyColormap(pixd, pixs);
pixCopyResolution(pixd, pixs);
pixCopyInputFormat(pixd, pixs);
datas = pixGetData(pixs);
wpls = pixGetWpl(pixs);
datad = pixGetData(pixd);
wpld = pixGetWpl(pixd);
rotate90Low(datad, wd, hd, d, wpld, datas, wpls, direction);
return pixd;
}
/*!
* pixFlipLR()
*
* Input: pixd (<optional>; can be null, equal to pixs,
* or different from pixs)
* pixs (all depths)
* Return: pixd, or null on error
*
* Notes:
* (1) This does a left-right flip of the image, which is
* equivalent to a rotation out of the plane about a
* vertical line through the image center.
* (2) There are 3 cases for input:
* (a) pixd == null (creates a new pixd)
* (b) pixd == pixs (in-place operation)
* (c) pixd != pixs (existing pixd)
* (3) For clarity, use these three patterns, respectively:
* (a) pixd = pixFlipLR(NULL, pixs);
* (b) pixFlipLR(pixs, pixs);
* (c) pixFlipLR(pixd, pixs);
* (4) If an existing pixd is not the same size as pixs, the
* image data will be reallocated.
*/
PIX *
pixFlipLR(PIX *pixd,
PIX *pixs)
{
l_uint8 *tab;
l_int32 w, h, d, wpld;
l_uint32 *datad, *buffer;
PROCNAME("pixFlipLR");
if (!pixs)
return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
pixGetDimensions(pixs, &w, &h, &d);
if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
procName, NULL);
/* Prepare pixd for in-place operation */
if ((pixd = pixCopy(pixd, pixs)) == NULL)
return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
datad = pixGetData(pixd);
wpld = pixGetWpl(pixd);
switch (d)
{
case 1:
tab = makeReverseByteTab1();
break;
case 2:
tab = makeReverseByteTab2();
break;
case 4:
tab = makeReverseByteTab4();
break;
default:
tab = NULL;
break;
}
if ((buffer = (l_uint32 *)CALLOC(wpld, sizeof(l_uint32))) == NULL)
return (PIX *)ERROR_PTR("buffer not made", procName, NULL);
flipLRLow(datad, w, h, d, wpld, tab, buffer);
FREE(buffer);
if (tab) FREE(tab);
return pixd;
}
/*!
* pixFlipTB()
*
* Input: pixd (<optional>; can be null, equal to pixs,
* or different from pixs)
* pixs (all depths)
* Return: pixd, or null on error
*
* Notes:
* (1) This does a top-bottom flip of the image, which is
* equivalent to a rotation out of the plane about a
* horizontal line through the image center.
* (2) There are 3 cases for input:
* (a) pixd == null (creates a new pixd)
* (b) pixd == pixs (in-place operation)
* (c) pixd != pixs (existing pixd)
* (3) For clarity, use these three patterns, respectively:
* (a) pixd = pixFlipTB(NULL, pixs);
* (b) pixFlipTB(pixs, pixs);
* (c) pixFlipTB(pixd, pixs);
* (4) If an existing pixd is not the same size as pixs, the
* image data will be reallocated.
*/
PIX *
pixFlipTB(PIX *pixd,
PIX *pixs)
{
l_int32 h, d, wpld;
l_uint32 *datad, *buffer;
PROCNAME("pixFlipTB");
if (!pixs)
return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
pixGetDimensions(pixs, NULL, &h, &d);
if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
return (PIX *)ERROR_PTR("pixs not in {1,2,4,8,16,32} bpp",
procName, NULL);
/* Prepare pixd for in-place operation */
if ((pixd = pixCopy(pixd, pixs)) == NULL)
return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
datad = pixGetData(pixd);
wpld = pixGetWpl(pixd);
if ((buffer = (l_uint32 *)CALLOC(wpld, sizeof(l_uint32))) == NULL)
return (PIX *)ERROR_PTR("buffer not made", procName, NULL);
flipTBLow(datad, h, wpld, buffer);
FREE(buffer);
return pixd;
}