// VirtualDub - Video processing and capture application // Graphics support library // Copyright (C) 1998-2009 Avery Lee // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include "blt_spanutils.h" #include "bitutils.h" using namespace nsVDPixmapBitUtils; namespace nsVDPixmapSpanUtils { void horiz_expand2x_centered(uint8 *dst, const uint8 *src, sint32 w) { w = -w; *dst++ = *src; if (++w) { if (++w) { do { dst[0] = (uint8)((3*src[0] + src[1] + 2)>>2); dst[1] = (uint8)((src[0] + 3*src[1] + 2)>>2); dst += 2; ++src; } while((w+=2)<0); } if (!(w & 1)) { *dst = src[0]; } } } void horiz_expand2x_coaligned(uint8 *dst, const uint8 *src, sint32 w) { w = -w; if ((w+=2) < 0) { do { dst[0] = src[0]; dst[1] = (uint8)((src[0] + src[1] + 1)>>1); dst += 2; ++src; } while((w+=2)<0); } w -= 2; while(w < 0) { ++w; *dst++ = src[0]; } } void horiz_expand4x_coaligned(uint8 *dst, const uint8 *src, sint32 w) { w = -w; if ((w+=4) < 0) { do { dst[0] = src[0]; dst[1] = (uint8)((3*src[0] + src[1] + 2)>>2); dst[2] = (uint8)((src[0] + src[1] + 1)>>1); dst[3] = (uint8)((src[0] + 3*src[1] + 2)>>2); dst += 4; ++src; } while((w+=4)<0); } w -= 4; while(w < 0) { ++w; *dst++ = src[0]; } } void horiz_compress2x_coaligned(uint8 *dst, const uint8 *src, sint32 w) { if (w == 1) { *dst = *src; return; } *dst++ = (uint8)((3*src[0] + src[1] + 2) >> 2); ++src; --w; while(w >= 3) { w -= 2; *dst++ = (uint8)((src[0] + 2*src[1] + src[2] + 2) >> 2); src += 2; } if (w >= 2) *dst++ = (uint8)((src[0] + 3*src[1] + 2) >> 2); } void horiz_compress2x_centered(uint8 *dst, const uint8 *src, sint32 w) { if (w == 1) { *dst = *src; return; } if (w == 2) { *dst = (uint8)((src[0] + src[1] + 1) >> 1); return; } *dst++ = (uint8)((4*src[0] + 3*src[1] + src[2] + 4) >> 3); --w; ++src; while(w >= 4) { w -= 2; *dst++ = (uint8)(((src[0] + src[3]) + 3*(src[1] + src[2]) + 4) >> 3); src += 2; } switch(w) { case 3: *dst++ = (uint8)((src[0] + 3*src[1] + 4*src[2] + 4) >> 3); break; case 2: *dst++ = (uint8)((src[0] + 7*src[1] + 4) >> 3); break; } } void horiz_compress4x_coaligned(uint8 *dst, const uint8 *src, sint32 w) { if (w == 1) { *dst = *src; return; } if (w == 2) { *dst++ = (uint8)((11*src[0] + 5*src[1] + 8) >> 4); return; } *dst++ = (uint8)((11*src[0] + 4*src[1] + src[2] + 8) >> 4); src += 2; w -= 2; while(w >= 5) { w -= 4; *dst++ = (uint8)(((src[0] + src[4]) + 4*(src[1] + src[3]) + 6*src[2] + 8) >> 4); src += 4; } switch(w) { case 4: *dst = (uint8)((src[0] + 4*src[1] + 6*src[2] + 5*src[3] + 8) >> 4); break; case 3: *dst = (uint8)((src[0] + 4*src[1] + 11*src[2] + 8) >> 4); break; } } void horiz_compress4x_centered(uint8 *dst, const uint8 *src, sint32 w) { switch(w) { case 1: *dst = *src; return; case 2: // 29 99 *dst = (uint8)((29*src[0] + 99*src[1] + 64) >> 7); return; case 3: // 29 35 64 *dst = (uint8)((29*src[0] + 35*src[1] + 64*src[1] + 64) >> 7); return; case 4: // 29 35 35 29 *dst = (uint8)((29*src[0] + 35*(src[1] + src[2]) + 29*src[3] + 64) >> 7); return; case 5: // 29 35 35 21 8 // 1 7 120 dst[0] = (uint8)((29*src[0] + 35*(src[1] + src[2]) + 21*src[3] + 8*src[4] + 64) >> 7); dst[1] = (uint8)((src[2] + 7*src[3] + 120*src[4] + 64) >> 7); return; } *dst++ = (uint8)((29*src[0] + 35*(src[1] + src[2]) + 21*src[3] + 7*src[4] + src[5] + 64) >> 7); src += 2; w -= 2; while(w >= 8) { w -= 4; *dst++ = (uint8)(((src[0] + src[7]) + 7*(src[1] + src[6]) + 21*(src[2] + src[5]) + 35*(src[3] + src[4]) + 64) >> 7); src += 4; } switch(w) { case 4: // 1 7 21 99 *dst = (uint8)((src[0] + 7*src[1] + 21*src[2] + 99*src[3] + 64) >> 7); break; case 5: // 1 7 21 35 64 *dst = (uint8)((src[0] + 7*src[1] + 21*src[2] + 35*src[3] + 64*src[4] + 64) >> 7); break; case 6: // 1 7 21 35 35 29 *dst = (uint8)((src[0] + 7*src[1] + 21*src[2] + 29*src[5] + 35*(src[3] + src[4]) + 64) >> 7); break; case 7: // 1 7 21 35 35 21 8 // 1 7 120 dst[0] = (uint8)((src[0] + 7*src[1] + 8*src[6] + 21*(src[2] + src[5]) + 35*(src[3] + src[4]) + 64) >> 7); dst[1] = (uint8)((src[4] + 7*src[5] + 120*src[6] + 64) >> 7); break; } } void horiz_realign_to_centered(uint8 *dst, const uint8 *src, sint32 w) { // luma samples: Y Y Y Y Y // coaligned: C C C // centered: C C // // To realign coaligned samples to centered, we need to shift them // right by a quarter sample in chroma space. This can be done via // a [3 1]/4 filter. for(sint32 i=1; i> 2); ++dst; ++src; } *dst++ = *src++; } void horiz_realign_to_coaligned(uint8 *dst, const uint8 *src, sint32 w) { // luma samples: Y Y Y Y Y // coaligned: C C C // centered: C C // // To realign centered samples to coaligned, we need to shift them // left by a quarter sample in chroma space. This can be done via // a [1 3]/4 filter. *dst++ = *src++; for(sint32 i=1; i> 2); ++dst; ++src; } } void vert_expand2x_centered(uint8 *dst, const uint8 *const *srcs, sint32 w, uint8 phase) { const uint8 *src3 = srcs[0]; const uint8 *src1 = srcs[1]; if (phase >= 128) std::swap(src1, src3); sint32 w4 = w>>2; w &= 3; if (w4) { const uint32 *src34 = (const uint32 *)src3; const uint32 *src14 = (const uint32 *)src1; uint32 *dst4 = ( uint32 *)dst; do { const uint32 a = *src34++; const uint32 b = *src14++; const uint32 ab = (a&b) + (((a^b)&0xfefefefe)>>1); *dst4++ = (a|ab) - (((a^ab)&0xfefefefe)>>1); } while(--w4); src3 = (const uint8 *)src34; src1 = (const uint8 *)src14; dst = ( uint8 *)dst4; } if (w) { do { *dst++ = (uint8)((*src1++ + 3**src3++ + 2) >> 2); } while(--w); } } void vert_expand4x_centered(uint8 *dst, const uint8 *const *srcs, sint32 w, uint8 phase) { const uint8 *src3 = srcs[0]; const uint8 *src1 = srcs[1]; switch(phase & 0xc0) { case 0x00: do { *dst++ = (uint8)((1**src1++ + 7**src3++ + 4) >> 3); } while(--w); break; case 0x40: do { *dst++ = (uint8)((3**src1++ + 5**src3++ + 4) >> 3); } while(--w); break; case 0x80: do { *dst++ = (uint8)((5**src1++ + 3**src3++ + 4) >> 3); } while(--w); break; case 0xc0: do { *dst++ = (uint8)((7**src1++ + 1**src3++ + 4) >> 3); } while(--w); break; default: VDNEVERHERE; } } void vert_compress2x_centered_fast(uint8 *dst, const uint8 *const *srcarray, sint32 w, uint8 phase) { const uint8 *src1 = srcarray[0]; const uint8 *src2 = srcarray[1]; w = -w; w += 3; while(w < 0) { *(uint32 *)dst = avg_8888_11(*(uint32 *)src1, *(uint32 *)src2); dst += 4; src1 += 4; src2 += 4; w += 4; } w -= 3; while(w < 0) { *dst = (uint8)((*src1 + *src2 + 1)>>1); ++dst; ++src1; ++src2; ++w; } } void vert_compress2x_centered(uint8 *dst, const uint8 *const *srcarray, sint32 w, uint8 phase) { const uint8 *src1 = srcarray[0]; const uint8 *src2 = srcarray[1]; const uint8 *src3 = srcarray[2]; const uint8 *src4 = srcarray[3]; w = -w; while(w < 0) { *dst++ = (uint8)(((*src1++ + *src4++) + 3*(*src2++ + *src3++) + 4)>>3); ++w; } } void vert_compress4x_centered(uint8 *dst, const uint8 *const *srcarray, sint32 w, uint8 phase) { const uint8 *src1 = srcarray[0]; const uint8 *src2 = srcarray[1]; const uint8 *src3 = srcarray[2]; const uint8 *src4 = srcarray[3]; const uint8 *src5 = srcarray[4]; const uint8 *src6 = srcarray[5]; const uint8 *src7 = srcarray[6]; const uint8 *src8 = srcarray[7]; w = -w; while(w < 0) { int sum18 = *src1++ + *src8++; int sum27 = *src2++ + *src7++; int sum36 = *src3++ + *src6++; int sum45 = *src4++ + *src5++; *dst++ = (uint8)((sum18 + 7*sum27 + 21*sum36 + 35*sum45 + 64) >> 7); ++w; } } }