1 module CPUblit.transform; 2 3 import CPUblit.colorspaces; 4 import bitleveld.datatypes; 5 6 /** 7 * Horizontal scaling using nearest integer algorithm for per-line operations. 8 * Works with most datatypes. Use a separate one for 4 bit. 9 * Lenght determines the source's length. 10 * trfmParam describes how the transformation is done. 1024 results in the same exact line. Larger values cause shrinkage, smaller omes growth. Negative values cause reflections. 11 */ 12 public void horizontalScaleNearest(T)(T* src, T* dest, sizediff_t length, int trfmParam) @nogc pure nothrow { 13 int trfmParamA = trfmParam; 14 sizediff_t offset; 15 length <<= 10; 16 if(trfmParam < 0){ 17 offset += length-1024; 18 trfmParamA *= -1; 19 } 20 while(length > 0){ 21 *dest = src[offset>>>10]; 22 offset += trfmParam; 23 length -= trfmParamA; 24 dest++; 25 } 26 } 27 /** 28 * Horizontal scaling and color lookup using nearest integer algorithm for per-line operations. 29 * Works with most datatypes. Use a separate one for 4 bit. 30 * Lenght determines the source's length. 31 * trfmParam describes how the transformation is done. 1024 results in the same exact line. Larger values cause shrinkage, smaller omes growth. Negative values cause reflections. 32 */ 33 public void horizontalScaleNearestAndCLU(T, U)(T* src, U* dest, U* palette, sizediff_t length, const int trfmParam) 34 @nogc pure nothrow { 35 int trfmParamA = trfmParam; 36 sizediff_t offset; 37 length <<= 10; 38 if(trfmParam < 0){ 39 offset += length-1024; 40 trfmParamA *= -1; 41 } 42 while(length > 0){ 43 *dest = palette[(src[offset>>>10])]; 44 offset += trfmParam; 45 length -= trfmParamA; 46 dest++; 47 } 48 } 49 /** 50 * Horizontal scaling using nearest integer algorithm for per-line operations. 51 * Works with 4 bit datatypes. 52 * Lenght determines the source's length. 53 * trfmParam describes how the transformation is done. 1024 results in the same exact line. Larger values cause shrinkage, smaller omes growth. Negative values cause reflections. 54 */ 55 public void horizontalScaleNearest4Bit(ubyte* src, ubyte* dest, sizediff_t length, sizediff_t offset, 56 const int trfmParam) @nogc pure nothrow { 57 int trfmParamA = trfmParam; 58 length <<= 10; 59 offset <<= 10; 60 if(trfmParam < 0){ 61 offset += length-1024; 62 trfmParamA *= -1; 63 } 64 while(length > 0){ 65 const ubyte temp = (offset>>>10) & 1 ? src[offset>>>11] & 0x0F : src[offset>>>11] >> 4; 66 *dest |= length & 1 ? temp : temp << 4; 67 offset += trfmParam; 68 length -= trfmParamA; 69 dest++; 70 } 71 } 72 /** 73 * Horizontal scaling using nearest integer algorithm for per-line operations. 74 * Works with 16, 8, 4, and 2 bit datatypes. 75 * Lenght determines the source's length. 76 * trfmParam describes how the transformation is done. 1024 results in the same exact line. Larger values cause shrinkage, smaller omes growth. Negative values cause reflections. 77 * `ArrayType` should be bitleveld's NibbleArray or QuadArray, but also works with regular D arrays. 78 */ 79 public void horizontalScaleNearest(ArrayType)(ArrayType src, ArrayType dest, sizediff_t length, sizediff_t offset, 80 const int trfmParam) @nogc pure nothrow { 81 int trfmParamA = trfmParam; 82 size_t destPtr; 83 length <<= 10; 84 offset <<= 10; 85 if(trfmParam < 0){ 86 offset += length-1024; 87 trfmParamA *= -1; 88 } 89 while(length > 0){ 90 dest[destPtr] = src[offset>>>10]; 91 offset += trfmParam; 92 length -= trfmParamA; 93 destPtr++; 94 } 95 } 96 /** 97 * Horizontal scaling and color lookup using nearest integer algorithm for per-line operations. 98 * Works with 4 bit datatypes. 99 * Lenght determines the source's length. 100 * trfmParam describes how the transformation is done. 1024 results in the same exact line. Larger values cause shrinkage, smaller omes growth. Negative values cause reflections. 101 */ 102 public void horizontalScaleNearest4BitAndCLU(U)(ubyte* src, U* dest, U* palette, sizediff_t length, sizediff_t offset, 103 const int trfmParam) @nogc pure nothrow { 104 int trfmParamA = trfmParam; 105 length <<= 10; 106 offset <<= 10; 107 if(trfmParam < 0){ 108 offset += length-1024; 109 trfmParamA *= -1; 110 } 111 while(length > 0){ 112 const ubyte temp = (offset>>>10) & 1 ? src[offset>>>11] & 0x0F : src[offset>>>11] >> 4; 113 *dest = palette[temp]; 114 offset += trfmParam; 115 length -= trfmParam; 116 dest++; 117 } 118 } 119 /** 120 * Horizontal scaling and color lookup using nearest integer algorithm for per-line operations. 121 * Works with 16, 8, 4, and 2 bit datatypes. 122 * Lenght determines the source's length. 123 * trfmParam describes how the transformation is done. 1024 results in the same exact line. Larger values cause shrinkage, smaller omes growth. Negative values cause reflections. 124 * `ArrayType` should be bitleveld's NibbleArray or QuadArray, but also works with regular D arrays. 125 */ 126 public void horizontalScaleNearestAndCLU(PaletteType, ArrayType)(ArrayType src, PaletteType* dest, PaletteType* palette, 127 sizediff_t length, sizediff_t offset, const int trfmParam) @nogc pure nothrow { 128 int trfmParamA = trfmParam; 129 length <<= 10; 130 offset <<= 10; 131 if(trfmParam < 0){ 132 offset += length-1024; 133 trfmParamA *= -1; 134 } 135 while(length > 0){ 136 *dest = palette[src[offset>>>10]]; 137 offset += trfmParam; 138 length -= trfmParamA; 139 dest++; 140 } 141 } 142 /** 143 * Returns the needed length of dest for the given trfmParam if the "nearest integer algorithm" used. 144 * Works with both horizontal and vertical algorithms. 145 */ 146 public size_t scaleNearestLength(size_t origLen, int trfmParam) @nogc @safe pure nothrow { 147 if(trfmParam < 0) 148 trfmParam *= -1; 149 return cast(size_t)(cast(double)origLen * (1024.0 / cast(double)trfmParam)); 150 } 151 pure nothrow unittest{ 152 import std.conv : to; 153 uint[256] a, b; 154 ubyte[256] c; 155 NibbleArray d = NibbleArray(c[0..$], 512); 156 QuadArray e = QuadArray(c[0..$], 1024); 157 //force the compiler to check the scalers 158 horizontalScaleNearest(a.ptr, b.ptr, 16, 2048); 159 horizontalScaleNearestAndCLU(c.ptr,a.ptr,b.ptr,16,2048); 160 horizontalScaleNearest4BitAndCLU(c.ptr,a.ptr,b.ptr,16,0,2048); 161 horizontalScaleNearestAndCLU(d, a.ptr, b.ptr, 256, 0, 2048); 162 horizontalScaleNearestAndCLU(e, a.ptr, b.ptr, 256, 0, 2048); 163 assert(20 == scaleNearestLength(10, 512), "Error while testing function `scaleNearestLength`. Expected value: 20 " ~ 164 "Returned value: " ~ to!string(scaleNearestLength(10, 512))); 165 assert(20 == scaleNearestLength(10, -512), "Error while testing function `scaleNearestLength`. Expected value: 20 " ~ 166 "Returned value: " ~ to!string(scaleNearestLength(10, -512))); 167 }