/*====================================================================* - 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; }