| 1 | /*
|
|---|
| 2 |
|
|---|
| 3 | gbmscale.c - Scale bitmap to new size
|
|---|
| 4 |
|
|---|
| 5 | */
|
|---|
| 6 |
|
|---|
| 7 | /*...sincludes:0:*/
|
|---|
| 8 | #include <stdio.h>
|
|---|
| 9 | #include <stddef.h>
|
|---|
| 10 | #include <stdlib.h>
|
|---|
| 11 | #include <string.h>
|
|---|
| 12 | #include "gbm.h"
|
|---|
| 13 |
|
|---|
| 14 | /*...vgbm\46\h:0:*/
|
|---|
| 15 | /*...e*/
|
|---|
| 16 |
|
|---|
| 17 | /*...sgbm_simple_scale \45\ point sampled:0:*/
|
|---|
| 18 | /*...ssimple_scale_1:0:*/
|
|---|
| 19 | static void simple_scale_1(
|
|---|
| 20 | const byte *s,
|
|---|
| 21 | byte *d, int dw,
|
|---|
| 22 | const int xs[]
|
|---|
| 23 | )
|
|---|
| 24 | {
|
|---|
| 25 | int sx = 0;
|
|---|
| 26 | byte bit, value;
|
|---|
| 27 |
|
|---|
| 28 | for ( ; dw >= 8; dw -= 8 )
|
|---|
| 29 | {
|
|---|
| 30 | for ( value = 0, bit = 0x80; bit > 0; bit >>= 1 )
|
|---|
| 31 | {
|
|---|
| 32 | if ( s[(unsigned)sx>>3]&(0x80U>>((unsigned)sx&7U)) )
|
|---|
| 33 | value |= bit;
|
|---|
| 34 | sx += *xs++;
|
|---|
| 35 | }
|
|---|
| 36 | *d++ = value;
|
|---|
| 37 | }
|
|---|
| 38 |
|
|---|
| 39 | if ( dw > 0 )
|
|---|
| 40 | {
|
|---|
| 41 | for ( value = 0, bit = 0x80; dw-- > 0; bit >>= 1 )
|
|---|
| 42 | {
|
|---|
| 43 | if ( s[(unsigned)sx>>3]&(0x80U>>((unsigned)sx&7U)) )
|
|---|
| 44 | value |= bit;
|
|---|
| 45 | sx += *xs++;
|
|---|
| 46 | }
|
|---|
| 47 | *d = value;
|
|---|
| 48 | }
|
|---|
| 49 | }
|
|---|
| 50 | /*...e*/
|
|---|
| 51 | /*...ssimple_scale_4:0:*/
|
|---|
| 52 | static void simple_scale_4(
|
|---|
| 53 | const byte *s,
|
|---|
| 54 | byte *d, int dw,
|
|---|
| 55 | const int xs[]
|
|---|
| 56 | )
|
|---|
| 57 | {
|
|---|
| 58 | int sx = 0;
|
|---|
| 59 | for ( ;; )
|
|---|
| 60 | {
|
|---|
| 61 | if ( dw-- == 0 ) return;
|
|---|
| 62 | if ( sx&1 ) *d = (s[(unsigned)sx>>1] << 4 );
|
|---|
| 63 | else *d = (s[(unsigned)sx>>1]&0xf0U);
|
|---|
| 64 | sx += *xs++;
|
|---|
| 65 |
|
|---|
| 66 | if ( dw-- == 0 ) return;
|
|---|
| 67 | if ( sx&1 ) *d++ |= (s[(unsigned)sx>>1]&0x0fU);
|
|---|
| 68 | else *d++ |= (s[(unsigned)sx>>1] >> 4);
|
|---|
| 69 | sx += *xs++;
|
|---|
| 70 | }
|
|---|
| 71 | }
|
|---|
| 72 | /*...e*/
|
|---|
| 73 | /*...ssimple_scale_8:0:*/
|
|---|
| 74 | static void simple_scale_8(
|
|---|
| 75 | const byte *s,
|
|---|
| 76 | byte *d, int dw,
|
|---|
| 77 | const int xs[]
|
|---|
| 78 | )
|
|---|
| 79 | {
|
|---|
| 80 | while ( dw-- > 0 )
|
|---|
| 81 | {
|
|---|
| 82 | *d++ = *s;
|
|---|
| 83 | s += *xs++;
|
|---|
| 84 | }
|
|---|
| 85 | }
|
|---|
| 86 | /*...e*/
|
|---|
| 87 | /*...ssimple_scale_24:0:*/
|
|---|
| 88 | static void simple_scale_24(
|
|---|
| 89 | const byte *s,
|
|---|
| 90 | byte *d, int dw,
|
|---|
| 91 | const int xs[]
|
|---|
| 92 | )
|
|---|
| 93 | {
|
|---|
| 94 | while ( dw-- > 0 )
|
|---|
| 95 | {
|
|---|
| 96 | *d++ = s[0];
|
|---|
| 97 | *d++ = s[1];
|
|---|
| 98 | *d++ = s[2];
|
|---|
| 99 | s += ( 3 * *xs++ );
|
|---|
| 100 | }
|
|---|
| 101 | }
|
|---|
| 102 | /*...e*/
|
|---|
| 103 | /*...sfast_simple_scale_1:0:*/
|
|---|
| 104 | static void fast_simple_scale_1(
|
|---|
| 105 | const byte *s,
|
|---|
| 106 | byte *d, int dw,
|
|---|
| 107 | const int xs[]
|
|---|
| 108 | )
|
|---|
| 109 | {
|
|---|
| 110 | xs=xs; /* Suppress warnings */
|
|---|
| 111 | memcpy(d, s, (unsigned)(dw+7) >> 3);
|
|---|
| 112 | }
|
|---|
| 113 | /*...e*/
|
|---|
| 114 | /*...sfast_simple_scale_4:0:*/
|
|---|
| 115 | static void fast_simple_scale_4(
|
|---|
| 116 | const byte *s,
|
|---|
| 117 | byte *d, int dw,
|
|---|
| 118 | const int xs[]
|
|---|
| 119 | )
|
|---|
| 120 | {
|
|---|
| 121 | xs=xs; /* Suppress warnings */
|
|---|
| 122 | memcpy(d, s, (unsigned) (dw+1)>>1);
|
|---|
| 123 | }
|
|---|
| 124 | /*...e*/
|
|---|
| 125 | /*...sfast_simple_scale_8:0:*/
|
|---|
| 126 | static void fast_simple_scale_8(
|
|---|
| 127 | const byte *s,
|
|---|
| 128 | byte *d, int dw,
|
|---|
| 129 | const int xs[]
|
|---|
| 130 | )
|
|---|
| 131 | {
|
|---|
| 132 | xs=xs; /* Suppress warnings */
|
|---|
| 133 | memcpy(d, s, dw);
|
|---|
| 134 | }
|
|---|
| 135 | /*...e*/
|
|---|
| 136 | /*...sfast_simple_scale_24:0:*/
|
|---|
| 137 | static void fast_simple_scale_24(
|
|---|
| 138 | const byte *s,
|
|---|
| 139 | byte *d, int dw,
|
|---|
| 140 | const int xs[]
|
|---|
| 141 | )
|
|---|
| 142 | {
|
|---|
| 143 | xs=xs; /* Suppress warnings */
|
|---|
| 144 | memcpy(d, s, dw*3);
|
|---|
| 145 | }
|
|---|
| 146 | /*...e*/
|
|---|
| 147 |
|
|---|
| 148 | GBM_ERR gbm_simple_scale(
|
|---|
| 149 | const byte *s, int sw, int sh,
|
|---|
| 150 | byte *d, int dw, int dh,
|
|---|
| 151 | int bpp
|
|---|
| 152 | )
|
|---|
| 153 | {
|
|---|
| 154 | int sst = ( (sw * bpp + 31) / 32 ) * 4;
|
|---|
| 155 | int dst = ( (dw * bpp + 31) / 32 ) * 4;
|
|---|
| 156 | int *xs, *ys, i;
|
|---|
| 157 | void (*scaler)(const byte *s, byte *d, int dw, const int xs[]);
|
|---|
| 158 |
|
|---|
| 159 | /* Allocate memory for step arrays */
|
|---|
| 160 |
|
|---|
| 161 | if ( (xs = malloc((size_t) ((dw+1+dh+1)*sizeof(int)))) == NULL )
|
|---|
| 162 | return GBM_ERR_MEM;
|
|---|
| 163 | ys = xs + (dw+1);
|
|---|
| 164 |
|
|---|
| 165 | /* Make mapping to 0..dx from 0..sx (and same for y) */
|
|---|
| 166 |
|
|---|
| 167 | for ( i = 0; i <= dw; i++ )
|
|---|
| 168 | xs[i] = (i * sw) / dw;
|
|---|
| 169 |
|
|---|
| 170 | for ( i = 0; i <= dh; i++ )
|
|---|
| 171 | ys[i] = (i * sh) / dh;
|
|---|
| 172 |
|
|---|
| 173 | /* Compute step coefficients */
|
|---|
| 174 |
|
|---|
| 175 | for ( i = 0; i < dw; i++ )
|
|---|
| 176 | xs[i] = xs[i+1] - xs[i];
|
|---|
| 177 |
|
|---|
| 178 | for ( i = 0; i < dh; i++ )
|
|---|
| 179 | ys[i] = ys[i+1] - ys[i];
|
|---|
| 180 |
|
|---|
| 181 | /* Pick a scaling routine. Special optimisation to prevent
|
|---|
| 182 | excessive work scaling horizontally if widths are the same.
|
|---|
| 183 | Effectively reduces this code to a memcpy. */
|
|---|
| 184 |
|
|---|
| 185 | if ( dw == sw )
|
|---|
| 186 | switch ( bpp )
|
|---|
| 187 | {
|
|---|
| 188 | case 1 : scaler = fast_simple_scale_1 ; break;
|
|---|
| 189 | case 4 : scaler = fast_simple_scale_4 ; break;
|
|---|
| 190 | case 8 : scaler = fast_simple_scale_8 ; break;
|
|---|
| 191 | case 24: scaler = fast_simple_scale_24; break;
|
|---|
| 192 | }
|
|---|
| 193 | else
|
|---|
| 194 | switch ( bpp )
|
|---|
| 195 | {
|
|---|
| 196 | case 1 : scaler = simple_scale_1 ; break;
|
|---|
| 197 | case 4 : scaler = simple_scale_4 ; break;
|
|---|
| 198 | case 8 : scaler = simple_scale_8 ; break;
|
|---|
| 199 | case 24: scaler = simple_scale_24; break;
|
|---|
| 200 | }
|
|---|
| 201 |
|
|---|
| 202 | /* Now do guts of scaling */
|
|---|
| 203 |
|
|---|
| 204 | while ( dh-- > 0 )
|
|---|
| 205 | {
|
|---|
| 206 | (*scaler)(s, d, dw, xs);
|
|---|
| 207 | d += dst;
|
|---|
| 208 | s += (sst * *ys++);
|
|---|
| 209 | }
|
|---|
| 210 |
|
|---|
| 211 | free(xs);
|
|---|
| 212 | return GBM_ERR_OK;
|
|---|
| 213 | }
|
|---|
| 214 | /*...e*/
|
|---|