|
|
1.1 ! root 1: /* ! 2: * This file is part of the Scale2x project. ! 3: * ! 4: * Copyright (C) 2001-2003 Andrea Mazzoleni ! 5: * ! 6: * This program is free software; you can redistribute it and/or modify ! 7: * it under the terms of the GNU General Public License as published by ! 8: * the Free Software Foundation; either version 2 of the License, or ! 9: * (at your option) any later version. ! 10: * ! 11: * This program is distributed in the hope that it will be useful, ! 12: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: * GNU General Public License for more details. ! 15: * ! 16: * You should have received a copy of the GNU General Public License ! 17: * along with this program; if not, write to the Free Software ! 18: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 19: */ ! 20: ! 21: /* ! 22: * This file contains an example implementation of the Scale effect ! 23: * applyed to a generic bitmap. ! 24: * ! 25: * You can find an high level description of the effect at : ! 26: * ! 27: * http://scale2x.sourceforge.net/ ! 28: * ! 29: * Alternatively at the previous license terms, you are allowed to use this ! 30: * code in your program with these conditions: ! 31: * - the program is not used in commercial activities. ! 32: * - the whole source code of the program is released with the binary. ! 33: * - derivative works of the program are allowed. ! 34: */ ! 35: ! 36: #if HAVE_CONFIG_H ! 37: #include <config.h> ! 38: #endif ! 39: ! 40: #include "scale2x.h" ! 41: #include "scale3x.h" ! 42: ! 43: #if HAVE_ALLOCA_H ! 44: #include <alloca.h> ! 45: #endif ! 46: ! 47: #include <assert.h> ! 48: #include <stdlib.h> ! 49: ! 50: /** ! 51: * Apply the Scale2x effect on a group of rows. Used internally. ! 52: */ ! 53: static inline void stage_scale2x(void* dst0, void* dst1, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) ! 54: { ! 55: switch (pixel) { ! 56: #if defined(__GNUC__) && defined(__i386__) ! 57: case 1 : scale2x_8_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break; ! 58: case 2 : scale2x_16_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break; ! 59: case 4 : scale2x_32_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break; ! 60: #else ! 61: case 1 : scale2x_8_def(dst0, dst1, src0, src1, src2, pixel_per_row); break; ! 62: case 2 : scale2x_16_def(dst0, dst1, src0, src1, src2, pixel_per_row); break; ! 63: case 4 : scale2x_32_def(dst0, dst1, src0, src1, src2, pixel_per_row); break; ! 64: #endif ! 65: } ! 66: } ! 67: ! 68: /** ! 69: * Apply the Scale3x effect on a group of rows. Used internally. ! 70: */ ! 71: static inline void stage_scale3x(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) ! 72: { ! 73: switch (pixel) { ! 74: case 1 : scale3x_8_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break; ! 75: case 2 : scale3x_16_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break; ! 76: case 4 : scale3x_32_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break; ! 77: } ! 78: } ! 79: ! 80: /** ! 81: * Apply the Scale4x effect on a group of rows. Used internally. ! 82: */ ! 83: static inline void stage_scale4x(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, const void* src3, unsigned pixel, unsigned pixel_per_row) ! 84: { ! 85: stage_scale2x(dst0, dst1, src0, src1, src2, pixel, 2 * pixel_per_row); ! 86: stage_scale2x(dst2, dst3, src1, src2, src3, pixel, 2 * pixel_per_row); ! 87: } ! 88: ! 89: #define SCDST(i) (dst+(i)*dst_slice) ! 90: #define SCSRC(i) (src+(i)*src_slice) ! 91: #define SCMID(i) (mid[(i)]) ! 92: ! 93: /** ! 94: * Apply the Scale2x effect on a bitmap. ! 95: * The destination bitmap is filled with the scaled version of the source bitmap. ! 96: * The source bitmap isn't modified. ! 97: * The destination bitmap must be manually allocated before calling the function, ! 98: * note that the resulting size is exactly 2x2 times the size of the source bitmap. ! 99: * \param void_dst Pointer at the first pixel of the destination bitmap. ! 100: * \param dst_slice Size in bytes of a destination bitmap row. ! 101: * \param void_src Pointer at the first pixel of the source bitmap. ! 102: * \param src_slice Size in bytes of a source bitmap row. ! 103: * \param pixel Bytes per pixel of the source and destination bitmap. ! 104: * \param width Horizontal size in pixels of the source bitmap. ! 105: * \param height Vertical size in pixels of the source bitmap. ! 106: */ ! 107: static void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) ! 108: { ! 109: unsigned char* dst = (unsigned char*)void_dst; ! 110: const unsigned char* src = (unsigned char*)void_src; ! 111: unsigned count; ! 112: ! 113: assert(height >= 2); ! 114: ! 115: count = height; ! 116: ! 117: stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width); ! 118: ! 119: dst = SCDST(2); ! 120: ! 121: count -= 2; ! 122: while (count) { ! 123: stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width); ! 124: ! 125: dst = SCDST(2); ! 126: src = SCSRC(1); ! 127: ! 128: --count; ! 129: } ! 130: ! 131: stage_scale2x(SCDST(0), SCDST(1), SCSRC(1-1), SCSRC(2-1), SCSRC(2-1), pixel, width); ! 132: ! 133: #if defined(__GNUC__) && defined(__i386__) ! 134: scale2x_mmx_emms(); ! 135: #endif ! 136: } ! 137: ! 138: /** ! 139: * Apply the Scale32x effect on a bitmap. ! 140: * The destination bitmap is filled with the scaled version of the source bitmap. ! 141: * The source bitmap isn't modified. ! 142: * The destination bitmap must be manually allocated before calling the function, ! 143: * note that the resulting size is exactly 3x3 times the size of the source bitmap. ! 144: * \param void_dst Pointer at the first pixel of the destination bitmap. ! 145: * \param dst_slice Size in bytes of a destination bitmap row. ! 146: * \param void_src Pointer at the first pixel of the source bitmap. ! 147: * \param src_slice Size in bytes of a source bitmap row. ! 148: * \param pixel Bytes per pixel of the source and destination bitmap. ! 149: * \param width Horizontal size in pixels of the source bitmap. ! 150: * \param height Vertical size in pixels of the source bitmap. ! 151: */ ! 152: static void scale3x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) ! 153: { ! 154: unsigned char* dst = (unsigned char*)void_dst; ! 155: const unsigned char* src = (unsigned char*)void_src; ! 156: unsigned count; ! 157: ! 158: assert(height >= 2); ! 159: ! 160: count = height; ! 161: ! 162: stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width); ! 163: ! 164: dst = SCDST(3); ! 165: ! 166: count -= 2; ! 167: while (count) { ! 168: stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width); ! 169: ! 170: dst = SCDST(3); ! 171: src = SCSRC(1); ! 172: ! 173: --count; ! 174: } ! 175: ! 176: stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(1-1), SCSRC(2-1), SCSRC(2-1), pixel, width); ! 177: } ! 178: ! 179: /** ! 180: * Apply the Scale4x effect on a bitmap. ! 181: * The destination bitmap is filled with the scaled version of the source bitmap. ! 182: * The source bitmap isn't modified. ! 183: * The destination bitmap must be manually allocated before calling the function, ! 184: * note that the resulting size is exactly 4x4 times the size of the source bitmap. ! 185: * \note This function requires also a small buffer bitmap used internally to store ! 186: * intermediate results. This bitmap must have at least an horizontal size in bytes of 2*width*pixel, ! 187: * and a vertical size of 6 rows. The memory of this buffer must not be allocated ! 188: * in video memory because it's also read and not only written. Generally ! 189: * a heap (malloc) or a stack (alloca) buffer is the best choices. ! 190: * \param void_dst Pointer at the first pixel of the destination bitmap. ! 191: * \param dst_slice Size in bytes of a destination bitmap row. ! 192: * \param void_mid Pointer at the first pixel of the buffer bitmap. ! 193: * \param mid_slice Size in bytes of a buffer bitmap row. ! 194: * \param void_src Pointer at the first pixel of the source bitmap. ! 195: * \param src_slice Size in bytes of a source bitmap row. ! 196: * \param pixel Bytes per pixel of the source and destination bitmap. ! 197: * \param width Horizontal size in pixels of the source bitmap. ! 198: * \param height Vertical size in pixels of the source bitmap. ! 199: */ ! 200: static void scale4x_buf(void* void_dst, unsigned dst_slice, void* void_mid, unsigned mid_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) ! 201: { ! 202: unsigned char* dst = (unsigned char*)void_dst; ! 203: const unsigned char* src = (unsigned char*)void_src; ! 204: unsigned count; ! 205: unsigned char* mid[6]; ! 206: ! 207: assert(height >= 4); ! 208: ! 209: count = height; ! 210: ! 211: /* set the 6 buffer pointers */ ! 212: mid[0] = (unsigned char*)void_mid; ! 213: mid[1] = mid[0] + mid_slice; ! 214: mid[2] = mid[1] + mid_slice; ! 215: mid[3] = mid[2] + mid_slice; ! 216: mid[4] = mid[3] + mid_slice; ! 217: mid[5] = mid[4] + mid_slice; ! 218: ! 219: stage_scale2x(SCMID(-2+6), SCMID(-1+6), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width); ! 220: stage_scale2x(SCMID(0), SCMID(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width); ! 221: stage_scale2x(SCMID(2), SCMID(3), SCSRC(1), SCSRC(2), SCSRC(3), pixel, width); ! 222: stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-2+6), SCMID(-2+6), SCMID(-1+6), SCMID(0), pixel, width); ! 223: ! 224: dst = SCDST(4); ! 225: ! 226: stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-1+6), SCMID(0), SCMID(1), SCMID(2), pixel, width); ! 227: ! 228: dst = SCDST(4); ! 229: ! 230: count -= 4; ! 231: while (count) { ! 232: unsigned char* tmp; ! 233: ! 234: stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(4), pixel, width); ! 235: stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width); ! 236: ! 237: dst = SCDST(4); ! 238: src = SCSRC(1); ! 239: ! 240: tmp = SCMID(0); /* shift by 2 position */ ! 241: SCMID(0) = SCMID(2); ! 242: SCMID(2) = SCMID(4); ! 243: SCMID(4) = tmp; ! 244: tmp = SCMID(1); ! 245: SCMID(1) = SCMID(3); ! 246: SCMID(3) = SCMID(5); ! 247: SCMID(5) = tmp; ! 248: ! 249: --count; ! 250: } ! 251: ! 252: stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(3), pixel, width); ! 253: stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width); ! 254: ! 255: dst = SCDST(4); ! 256: ! 257: stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(3), SCMID(4), SCMID(5), SCMID(5), pixel, width); ! 258: ! 259: #if defined(__GNUC__) && defined(__i386__) ! 260: scale2x_mmx_emms(); ! 261: #endif ! 262: } ! 263: ! 264: /** ! 265: * Apply the Scale4x effect on a bitmap. ! 266: * The destination bitmap is filled with the scaled version of the source bitmap. ! 267: * The source bitmap isn't modified. ! 268: * The destination bitmap must be manually allocated before calling the function, ! 269: * note that the resulting size is exactly 4x4 times the size of the source bitmap. ! 270: * \note This function operates like ::scale4x_buf() but the intermediate buffer is ! 271: * automatically allocated in the stack. ! 272: * \param void_dst Pointer at the first pixel of the destination bitmap. ! 273: * \param dst_slice Size in bytes of a destination bitmap row. ! 274: * \param void_src Pointer at the first pixel of the source bitmap. ! 275: * \param src_slice Size in bytes of a source bitmap row. ! 276: * \param pixel Bytes per pixel of the source and destination bitmap. ! 277: * \param width Horizontal size in pixels of the source bitmap. ! 278: * \param height Vertical size in pixels of the source bitmap. ! 279: */ ! 280: static void scale4x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) ! 281: { ! 282: unsigned mid_slice; ! 283: void* mid; ! 284: ! 285: mid_slice = 2 * pixel * width; /* required space for 1 row buffer */ ! 286: ! 287: mid_slice = (mid_slice + 0x7) & ~0x7; /* align to 8 bytes */ ! 288: ! 289: #if HAVE_ALLOCA ! 290: mid = alloca(6 * mid_slice); /* allocate space for 6 row buffers */ ! 291: ! 292: assert(mid != 0); /* alloca should never fails */ ! 293: #else ! 294: mid = malloc(6 * mid_slice); /* allocate space for 6 row buffers */ ! 295: ! 296: if (!mid) ! 297: return; ! 298: #endif ! 299: ! 300: scale4x_buf(void_dst, dst_slice, mid, mid_slice, void_src, src_slice, pixel, width, height); ! 301: ! 302: #if !HAVE_ALLOCA ! 303: free(mid); ! 304: #endif ! 305: } ! 306: ! 307: /** ! 308: * Check if the scale implementation is applicable at the given arguments. ! 309: * \param scale Scale factor. 2, 3 or 4. ! 310: * \param src_slice Size in bytes of a source bitmap row. ! 311: * \param pixel Bytes per pixel of the source and destination bitmap. ! 312: * \param width Horizontal size in pixels of the source bitmap. ! 313: * \return ! 314: * - -1 on precondition violated. ! 315: * - 0 on success. ! 316: */ ! 317: int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height) ! 318: { ! 319: if (scale != 2 && scale != 3 && scale != 4) ! 320: return -1; ! 321: ! 322: if (pixel != 1 && pixel != 2 && pixel != 4) ! 323: return -1; ! 324: ! 325: switch (scale) { ! 326: case 2 : ! 327: case 3 : ! 328: if (height < 2) ! 329: return -1; ! 330: case 4 : ! 331: if (height < 4) ! 332: return -1; ! 333: } ! 334: ! 335: #if defined(__GNUC__) && defined(__i386__) ! 336: switch (scale) { ! 337: case 2 : ! 338: case 4 : ! 339: if (width < (16 / pixel)) ! 340: return -1; ! 341: if (width % (8 / pixel) != 0) ! 342: return -1; ! 343: case 3 : ! 344: if (width < 2) ! 345: return -1; ! 346: } ! 347: #else ! 348: if (width < 2) ! 349: return -1; ! 350: #endif ! 351: ! 352: return 0; ! 353: } ! 354: ! 355: /** ! 356: * Apply the Scale effect on a bitmap. ! 357: * This function is simply a common interface for ::scale2x(), ::scale3x() and ::scale4x(). ! 358: * \param scale Scale factor. 2, 3 or 4. ! 359: * \param void_dst Pointer at the first pixel of the destination bitmap. ! 360: * \param dst_slice Size in bytes of a destination bitmap row. ! 361: * \param void_src Pointer at the first pixel of the source bitmap. ! 362: * \param src_slice Size in bytes of a source bitmap row. ! 363: * \param pixel Bytes per pixel of the source and destination bitmap. ! 364: * \param width Horizontal size in pixels of the source bitmap. ! 365: * \param height Vertical size in pixels of the source bitmap. ! 366: */ ! 367: void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) ! 368: { ! 369: switch (scale) { ! 370: case 2 : scale2x(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; ! 371: case 3 : scale3x(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; ! 372: case 4 : scale4x(void_dst, dst_slice, void_src, src_slice, pixel, width, height); break; ! 373: } ! 374: } ! 375:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.