/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Tomas Mšller * Portions created by Tomas Mšller are * Copyright (C) 2001 Tomas Mšller. Rights Reserved. * * Contributor(s): * Tomas Mšller * Tim Rowley */ #include #include #include "imgScaler.h" // Scaling code from Graphics Gems book III // http://www.acm.org/pubs/tog/GraphicsGems/gemsiii/fastBitmap.c // // License states - "All code here can be used without restrictions." // http://www.acm.org/pubs/tog/GraphicsGems/ /* Fast Bitmap Stretching Tomas Mšller */ static void Stretch32(unsigned x1, unsigned x2, unsigned y1, unsigned y2, unsigned yr, unsigned yw, unsigned aStartRow, unsigned aStartColumn, unsigned aEndColumn, unsigned char *aSrcImage, unsigned aSrcStride, unsigned char *aDstImage, unsigned aDstStride); static void Stretch24(unsigned x1, unsigned x2, unsigned y1, unsigned y2, unsigned yr, unsigned yw, unsigned aStartRow, unsigned aStartColumn, unsigned aEndColumn, unsigned char *aSrcImage, unsigned aSrcStride, unsigned char *aDstImage, unsigned aDstStride); static void Stretch8(unsigned x1, unsigned x2, unsigned y1, unsigned y2, unsigned yr, unsigned yw, unsigned aStartRow, unsigned aStartColumn, unsigned aEndColumn, unsigned char *aSrcImage, unsigned aSrcStride, unsigned char *aDstImage, unsigned aDstStride); static void Stretch1(unsigned x1, unsigned x2, unsigned y1, unsigned y2, unsigned yr, unsigned yw, unsigned aStartRow, unsigned aStartColumn, unsigned aEndColumn, unsigned char *aSrcImage, unsigned aSrcStride, unsigned char *aDstImage, unsigned aDstStride); /********************************************************** RectStretch enlarges or diminishes a source rectangle of a bitmap to a destination rectangle. The source rectangle is selected by the two points (xs1,ys1) and (xs2,ys2), and the destination rectangle by (xd1,yd1) and (xd2,yd2). Since readability of source-code is wanted, some optimizations have been left out for the reader: It's possible to read one line at a time, by first stretching in x-direction and then stretching that bitmap in y-direction. Entry: aSrcWidth, aSrcHeight - size of entire original image aDstWidth, aDstHeight - size of entire scaled image aStartColumn, aStartRow - upper corner of desired area (inclusive) aEndColumn, aEndRow - bottom corner of desired area (inclusive) unsigned char *aSrcImage, aSrcStride - start of original image data unsigned char *aDstStride, aDstStride - start of desired area image data unsigned aDepth - bit depth of image (24, 8, or 1) **********************************************************/ NS_GFX_(void) RectStretch(unsigned aSrcWidth, unsigned aSrcHeight, unsigned aDstWidth, unsigned aDstHeight, unsigned aStartColumn, unsigned aStartRow, unsigned aEndColumn, unsigned aEndRow, unsigned char *aSrcImage, unsigned aSrcStride, unsigned char *aDstImage, unsigned aDstStride, unsigned aDepth) { int e; unsigned dx, dy; void (*Stretch)(unsigned x1, unsigned x2, unsigned y1, unsigned y2, unsigned yr, unsigned yw, unsigned aStartRow, unsigned aStartColumn, unsigned aEndColumn, unsigned char *aSrcImage, unsigned aSrcStride, unsigned char *aDstImage, unsigned aDstStride); unsigned xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2; xs1 = ys1 = xd1 = yd1 = 0; xs2 = aSrcWidth - 1; ys2 = aSrcHeight - 1; xd2 = aDstWidth - 1; yd2 = aDstHeight - 1; // fprintf(stderr, "RS (%d %d)-(%d %d) (%d %d)-(%d %d) %d %d %d\n", // xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2, // aSrcStride, aDstStride, aDepth); switch (aDepth) { case 32: Stretch = Stretch32; break; case 24: Stretch = Stretch24; break; case 8: Stretch = Stretch8; break; case 1: Stretch = Stretch1; break; default: return; } dx = yd2 - yd1; dy = ys2 - ys1; e = dy - dx; dy += 1; if (!dx) dx = 1; for (yd1 = 0; yd1 <= aEndRow; yd1++) { if (yd1 >= aStartRow) Stretch(xd1, xd2, xs1, xs2, ys1, yd1, aStartRow, aStartColumn, aEndColumn, aSrcImage, aSrcStride, aDstImage, aDstStride); while (e >= 0) { ys1++; e -= dx; } e += dy; } } /********************************************************** Stretches a horizontal source line onto a horizontal destination line. Used by RectStretch. Entry: x1,x2 - x-coordinates of the destination line y1,y2 - x-coordinates of the source line yr - y-coordinate of source line yw - y-coordinate of destination line **********************************************************/ static void Stretch32(unsigned x1, unsigned x2, unsigned y1, unsigned y2, unsigned yr, unsigned yw, unsigned aStartRow, unsigned aStartColumn, unsigned aEndColumn, unsigned char *aSrcImage, unsigned aSrcStride, unsigned char *aDstImage, unsigned aDstStride) { int e; unsigned dx, dy, d; unsigned char *src, *dst; dx = x2 - x1; dy = y2 - y1; e = dy - dx; dy += 1; src = aSrcImage + yr * aSrcStride + 4 * y1; dst = aDstImage + (yw - aStartRow) * aDstStride; if (!dx) dx = 1; for (d = 0; d <= aEndColumn; d++) { if (d >= aStartColumn) { *dst++ = src[0]; *dst++ = src[1]; *dst++ = src[2]; *dst++ = src[3]; } while (e >= 0) { src += 4; e -= dx; } e += dy; } } static void Stretch24(unsigned x1, unsigned x2, unsigned y1, unsigned y2, unsigned yr, unsigned yw, unsigned aStartRow, unsigned aStartColumn, unsigned aEndColumn, unsigned char *aSrcImage, unsigned aSrcStride, unsigned char *aDstImage, unsigned aDstStride) { int e; unsigned dx, dy, d; unsigned char *src, *dst; dx = x2 - x1; dy = y2 - y1; e = dy - dx; dy += 1; src = aSrcImage + yr * aSrcStride + 3 * y1; dst = aDstImage + (yw - aStartRow) * aDstStride; if (!dx) dx = 1; for (d = 0; d <= aEndColumn; d++) { if (d >= aStartColumn) { *dst++ = src[0]; *dst++ = src[1]; *dst++ = src[2]; } while (e >= 0) { src += 3; e -= dx; } e += dy; } } static void Stretch8(unsigned x1, unsigned x2, unsigned y1, unsigned y2, unsigned yr, unsigned yw, unsigned aStartRow, unsigned aStartColumn, unsigned aEndColumn, unsigned char *aSrcImage, unsigned aSrcStride, unsigned char *aDstImage, unsigned aDstStride) { int e; unsigned dx, dy, d; unsigned char *src, *dst; dx = x2 - x1; dy = y2 - y1; e = dy - dx; dy += 1; src = aSrcImage + yr * aSrcStride + y1; dst = aDstImage + (yw - aStartRow) * aDstStride; if (!dx) dx = 1; for (d = 0; d <= aEndColumn; d++) { if (d >= aStartColumn) { *dst = *src; dst++; } while (e >= 0) { src++; e -= dx; } e += dy; } } static void Stretch1(unsigned x1, unsigned x2, unsigned y1, unsigned y2, unsigned yr, unsigned yw, unsigned aStartRow, unsigned aStartColumn, unsigned aEndColumn, unsigned char *aSrcImage, unsigned aSrcStride, unsigned char *aDstImage, unsigned aDstStride) { int e; unsigned dx, dy, d; dx = x2 - x1; dy = y2 - y1; e = dy - dx; dy += 1; if (!dx) dx = 1; for (d = 0; d <= aEndColumn; d++) { if ((d >= aStartColumn) && (*(aSrcImage + yr * aSrcStride + (y1 >> 3)) & 1 << (7 - y1 & 0x7))) *(aDstImage + (yw - aStartRow) * aDstStride + ((x1 - aStartColumn) >> 3)) |= 1 << (7 - x1 & 0x7); while (e >= 0) { y1++; e -= dx; } x1++; e += dy; } }