readyuv.c 4.0 KB

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