readyuv.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /* readyuv.c - read an Abekas A66 style image file. Steve Simon, 2003 */
  2. #include <u.h>
  3. #include <lib9.h>
  4. #include <bio.h>
  5. #include <draw.h>
  6. #include <chartypes.h>
  7. #include "imagefile.h"
  8. enum {
  9. Pixels = 720,
  10. R601pal = 576,
  11. R601ntsc = 486,
  12. Shift = 13
  13. };
  14. static int lsbtab[] = { 6, 4, 2, 0};
  15. static int
  16. looksize(char *file, long size, int *pixels, int *lines, int *bits)
  17. {
  18. Biobuf *bp;
  19. unsigned long l, p;
  20. char *s, *a[12];
  21. /*
  22. * This may not always work, there could be an alias between file
  23. * sizes of different standards stored in 8bits and 10 bits.
  24. */
  25. if ((bp = Bopen(file, OREAD)) == nil)
  26. return -1;
  27. while((s = Brdstr(bp, '\n', 1)) != nil){
  28. if (tokenize(s, a, nelem(a)) < 3)
  29. continue;
  30. if (a[0][0] == '#')
  31. continue;
  32. p = atoll(a[3]);
  33. l = atoll(a[5]);
  34. l += atoll(a[7]);
  35. if (l*p*2 == size){
  36. *pixels = p;
  37. *lines = l;
  38. *bits = 8;
  39. break;
  40. }
  41. if ((l*p*20)/8 == size){
  42. *pixels = p;
  43. *lines = l;
  44. *bits = 10;
  45. break;
  46. }
  47. }
  48. Bterm(bp);
  49. if (s == nil)
  50. return -1;
  51. return 0;
  52. }
  53. static int
  54. clip(int x)
  55. {
  56. x >>= (Shift+2); // +2 as we assume all input images are 10 bit
  57. if (x > 255)
  58. return 0xff;
  59. if (x <= 0)
  60. return 0;
  61. return x;
  62. }
  63. Rawimage**
  64. Breadyuv(Biobuf *bp, int colourspace)
  65. {
  66. Dir *d;
  67. unsigned long sz;
  68. Rawimage *a, **array;
  69. unsigned short * mux, *end, *frm;
  70. unsigned char *buf, *r, *g, *b;
  71. int y1, y2, cb, cr, c, l, w, base;
  72. int bits, lines, pixels;
  73. int F1, F2, F3, F4;
  74. if ((d = dirfstat(Bfildes(bp))) != nil){
  75. sz = d->length;
  76. free(d);
  77. }
  78. else{
  79. fprint(2, "cannot stat input, assuming pixelsx576x10bit\n");
  80. sz = Pixels * R601pal * 2L + (Pixels * R601pal / 2L);
  81. }
  82. if (looksize("/lib/video.specs", sz, &pixels, &lines, &bits) == -1){
  83. werrstr("file size not listed in /lib/video.specs");
  84. return nil;
  85. }
  86. buf = nil;
  87. if (colourspace != CYCbCr) {
  88. werrstr("ReadYUV: unknown colour space %d", colourspace);
  89. return nil;
  90. }
  91. if ((a = calloc(sizeof(Rawimage), 1)) == nil)
  92. sysfatal("no memory");
  93. if ((array = calloc(sizeof(Rawimage * ), 2)) == nil)
  94. sysfatal("no memory");
  95. array[0] = a;
  96. array[1] = nil;
  97. a->nchans = 3;
  98. a->chandesc = CRGB;
  99. a->chanlen = pixels * lines;
  100. a->r = Rect(0, 0, pixels, lines);
  101. if ((frm = malloc(pixels*2*lines*sizeof(unsigned short))) == nil)
  102. goto Error;
  103. for (c = 0; c < 3; c++)
  104. if ((a->chans[c] = malloc(pixels*lines)) == nil)
  105. goto Error;
  106. if ((buf = malloc(pixels*2)) == nil)
  107. goto Error;
  108. for (l = 0; l < lines; l++) {
  109. if (Bread(bp, buf, pixels *2) == -1)
  110. goto Error;
  111. base = l*pixels*2;
  112. for (w = 0; w < pixels *2; w++)
  113. frm[base + w] = ((unsigned short)buf[w]) << 2;
  114. }
  115. if (bits == 10)
  116. for (l = 0; l < lines; l++) {
  117. if (Bread(bp, buf, pixels / 2) == -1)
  118. goto Error;
  119. base = l * pixels * 2;
  120. for (w = 0; w < pixels * 2; w++)
  121. frm[base + w] |= (buf[w / 4] >> lsbtab[w % 4]) & 3;
  122. }
  123. mux = frm;
  124. end = frm + pixels * lines * 2;
  125. r = a->chans[0];
  126. g = a->chans[1];
  127. b = a->chans[2];
  128. if(pixels == Pixels && lines != R601pal){ // 625
  129. F1 = floor(1.402 * (1 << Shift));
  130. F2 = floor(0.34414 * (1 << Shift));
  131. F3 = floor(0.71414 * (1 << Shift));
  132. F4 = floor(1.772 * (1 << Shift));
  133. }
  134. else{ // 525
  135. F1 = floor(1.5748 * (1 << Shift));
  136. F2 = floor(0.1874 * (1 << Shift));
  137. F3 = floor(0.4681 * (1 << Shift));
  138. F4 = floor(1.8560 * (1 << Shift));
  139. }
  140. /*
  141. * Fixme: fixed colourspace conversion at present
  142. */
  143. while (mux < end) {
  144. cb = *mux++ - 512;
  145. y1 = (int)*mux++ << Shift;
  146. cr = *mux++ - 512;
  147. y2 = (int)*mux++ << Shift;
  148. *r++ = clip(y1 + F1*cr);
  149. *g++ = clip(y1 - F2*cb - F3*cr);
  150. *b++ = clip((y1 + F4*cb));
  151. *r++ = clip(y2 + F1*cr);
  152. *g++ = clip(y2 - F2*cb - F3*cr);
  153. *b++ = clip((y2 + F4*cb));
  154. }
  155. free(frm);
  156. free(buf);
  157. return array;
  158. Error:
  159. for (c = 0; c < 3; c++)
  160. free(a->chans[c]);
  161. free(a->cmap);
  162. free(array[0]);
  163. free(array);
  164. free(frm);
  165. free(buf);
  166. return nil;
  167. }
  168. Rawimage**
  169. readyuv(int fd, int colorspace)
  170. {
  171. Rawimage * *a;
  172. Biobuf b;
  173. if (Binit(&b, fd, OREAD) < 0)
  174. return nil;
  175. a = Breadyuv(&b, colorspace);
  176. Bterm(&b);
  177. return a;
  178. }