00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <inttypes.h>
00026
00027 #define FIXP (1 << 16)
00028 #define MY_PI 205887 // (M_PI * FIX)
00029
00030 static int64_t int_pow(int64_t a, int p)
00031 {
00032 int64_t v = FIXP;
00033
00034 for (; p; p--) {
00035 v *= a;
00036 v /= FIXP;
00037 }
00038
00039 return v;
00040 }
00041
00042 static int64_t int_sin(int64_t a)
00043 {
00044 if (a < 0)
00045 a = MY_PI - a;
00046 a %= 2 * MY_PI;
00047
00048 if (a >= MY_PI * 3 / 2)
00049 a -= 2 * MY_PI;
00050 if (a >= MY_PI / 2)
00051 a = MY_PI - a;
00052
00053 return a - int_pow(a, 3) / 6 + int_pow(a, 5) / 120 - int_pow(a, 7) / 5040;
00054 }
00055
00056 #define SCALEBITS 8
00057 #define ONE_HALF (1 << (SCALEBITS - 1))
00058 #define FIX(x) ((int) ((x) * (1L << SCALEBITS) + 0.5))
00059
00060 static void rgb24_to_yuv420p(unsigned char *lum, unsigned char *cb,
00061 unsigned char *cr, unsigned char *src,
00062 int width, int height)
00063 {
00064 int wrap, wrap3, x, y;
00065 int r, g, b, r1, g1, b1;
00066 unsigned char *p;
00067
00068 wrap = width;
00069 wrap3 = width * 3;
00070 p = src;
00071 for (y = 0; y < height; y += 2) {
00072 for (x = 0; x < width; x += 2) {
00073 r = p[0];
00074 g = p[1];
00075 b = p[2];
00076 r1 = r;
00077 g1 = g;
00078 b1 = b;
00079 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
00080 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
00081 r = p[3];
00082 g = p[4];
00083 b = p[5];
00084 r1 += r;
00085 g1 += g;
00086 b1 += b;
00087 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
00088 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
00089 p += wrap3;
00090 lum += wrap;
00091
00092 r = p[0];
00093 g = p[1];
00094 b = p[2];
00095 r1 += r;
00096 g1 += g;
00097 b1 += b;
00098 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
00099 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
00100 r = p[3];
00101 g = p[4];
00102 b = p[5];
00103 r1 += r;
00104 g1 += g;
00105 b1 += b;
00106 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
00107 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
00108
00109 cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
00110 FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
00111 cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
00112 FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
00113
00114 cb++;
00115 cr++;
00116 p += -wrap3 + 2 * 3;
00117 lum += -wrap + 2;
00118 }
00119 p += wrap3;
00120 lum += wrap;
00121 }
00122 }
00123
00124
00125 #define DEFAULT_WIDTH 352
00126 #define DEFAULT_HEIGHT 288
00127 #define DEFAULT_NB_PICT 50
00128
00129 static void pgmyuv_save(const char *filename, int w, int h,
00130 unsigned char *rgb_tab)
00131 {
00132 FILE *f;
00133 int i, h2, w2;
00134 unsigned char *cb, *cr;
00135 unsigned char *lum_tab, *cb_tab, *cr_tab;
00136
00137 lum_tab = malloc(w * h);
00138 cb_tab = malloc(w * h / 4);
00139 cr_tab = malloc(w * h / 4);
00140
00141 rgb24_to_yuv420p(lum_tab, cb_tab, cr_tab, rgb_tab, w, h);
00142
00143 f = fopen(filename, "wb");
00144 fprintf(f, "P5\n%d %d\n%d\n", w, h * 3 / 2, 255);
00145 fwrite(lum_tab, 1, w * h, f);
00146 h2 = h / 2;
00147 w2 = w / 2;
00148 cb = cb_tab;
00149 cr = cr_tab;
00150 for (i = 0; i < h2; i++) {
00151 fwrite(cb, 1, w2, f);
00152 fwrite(cr, 1, w2, f);
00153 cb += w2;
00154 cr += w2;
00155 }
00156 fclose(f);
00157
00158 free(lum_tab);
00159 free(cb_tab);
00160 free(cr_tab);
00161 }
00162
00163 unsigned char *rgb_tab;
00164 int width, height, wrap;
00165
00166 static void put_pixel(int x, int y, int r, int g, int b)
00167 {
00168 unsigned char *p;
00169
00170 if (x < 0 || x >= width ||
00171 y < 0 || y >= height)
00172 return;
00173
00174 p = rgb_tab + y * wrap + x * 3;
00175 p[0] = r;
00176 p[1] = g;
00177 p[2] = b;
00178 }
00179
00180 unsigned char tab_r[256 * 256];
00181 unsigned char tab_g[256 * 256];
00182 unsigned char tab_b[256 * 256];
00183
00184 int h_cos[360];
00185 int h_sin[360];
00186
00187 static int ipol(uint8_t *src, int x, int y)
00188 {
00189 int int_x = x >> 16;
00190 int int_y = y >> 16;
00191 int frac_x = x & 0xFFFF;
00192 int frac_y = y & 0xFFFF;
00193 int s00 = src[( int_x & 255) + 256 * ( int_y & 255)];
00194 int s01 = src[((int_x + 1) & 255) + 256 * ( int_y & 255)];
00195 int s10 = src[( int_x & 255) + 256 * ((int_y + 1) & 255)];
00196 int s11 = src[((int_x + 1) & 255) + 256 * ((int_y + 1) & 255)];
00197 int s0 = (((1 << 16) - frac_x) * s00 + frac_x * s01) >> 8;
00198 int s1 = (((1 << 16) - frac_x) * s10 + frac_x * s11) >> 8;
00199
00200 return (((1 << 16) - frac_y) * s0 + frac_y * s1) >> 24;
00201 }
00202
00203 static void gen_image(int num, int w, int h)
00204 {
00205 const int c = h_cos[num % 360];
00206 const int s = h_sin[num % 360];
00207
00208 const int xi = -(w / 2) * c;
00209 const int yi = (w / 2) * s;
00210
00211 const int xj = -(h / 2) * s;
00212 const int yj = -(h / 2) * c;
00213 int i, j;
00214
00215 int x, y;
00216 int xprime = xj;
00217 int yprime = yj;
00218
00219 for (j = 0; j < h; j++) {
00220 x = xprime + xi + FIXP * w / 2;
00221 xprime += s;
00222
00223 y = yprime + yi + FIXP * h / 2;
00224 yprime += c;
00225
00226 for (i = 0; i < w; i++) {
00227 x += c;
00228 y -= s;
00229 put_pixel(i, j,
00230 ipol(tab_r, x, y),
00231 ipol(tab_g, x, y),
00232 ipol(tab_b, x, y));
00233 }
00234 }
00235 }
00236
00237 #define W 256
00238 #define H 256
00239
00240 static int init_demo(const char *filename)
00241 {
00242 int i, j;
00243 int h;
00244 int radian;
00245 char line[3 * W];
00246
00247 FILE *input_file;
00248
00249 input_file = fopen(filename, "rb");
00250 if (!input_file) {
00251 perror(filename);
00252 return 1;
00253 }
00254
00255 if (fread(line, 1, 15, input_file) != 15)
00256 return 1;
00257 for (i = 0; i < H; i++) {
00258 if (fread(line, 1, 3 * W, input_file) != 3 * W)
00259 return 1;
00260 for (j = 0; j < W; j++) {
00261 tab_r[W * i + j] = line[3 * j ];
00262 tab_g[W * i + j] = line[3 * j + 1];
00263 tab_b[W * i + j] = line[3 * j + 2];
00264 }
00265 }
00266 fclose(input_file);
00267
00268
00269 for (i = 0; i < 360; i++) {
00270 radian = 2 * i * MY_PI / 360;
00271 h = 2 * FIXP + int_sin(radian);
00272 h_cos[i] = h * int_sin(radian + MY_PI / 2) / 2 / FIXP;
00273 h_sin[i] = h * int_sin(radian) / 2 / FIXP;
00274 }
00275
00276 return 0;
00277 }
00278
00279 int main(int argc, char **argv)
00280 {
00281 int w, h, i;
00282 char buf[1024];
00283
00284 if (argc != 3) {
00285 printf("usage: %s directory/ image.pnm\n"
00286 "generate a test video stream\n", argv[0]);
00287 return 1;
00288 }
00289
00290 w = DEFAULT_WIDTH;
00291 h = DEFAULT_HEIGHT;
00292
00293 rgb_tab = malloc(w * h * 3);
00294 wrap = w * 3;
00295 width = w;
00296 height = h;
00297
00298 if (init_demo(argv[2]))
00299 return 1;
00300
00301 for (i = 0; i < DEFAULT_NB_PICT; i++) {
00302 snprintf(buf, sizeof(buf), "%s%02d.pgm", argv[1], i);
00303 gen_image(i, w, h);
00304 pgmyuv_save(buf, w, h, rgb_tab);
00305 }
00306
00307 free(rgb_tab);
00308 return 0;
00309 }