jpeg.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2008 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <grub/bitmap.h>
  19. #include <grub/types.h>
  20. #include <grub/normal.h>
  21. #include <grub/dl.h>
  22. #include <grub/mm.h>
  23. #include <grub/misc.h>
  24. #include <grub/bufio.h>
  25. /* Uncomment following define to enable JPEG debug. */
  26. //#define JPEG_DEBUG
  27. #define JPEG_ESC_CHAR 0xFF
  28. #define JPEG_SAMPLING_1x1 0x11
  29. #define JPEG_MARKER_SOI 0xd8
  30. #define JPEG_MARKER_EOI 0xd9
  31. #define JPEG_MARKER_DHT 0xc4
  32. #define JPEG_MARKER_DQT 0xdb
  33. #define JPEG_MARKER_SOF0 0xc0
  34. #define JPEG_MARKER_SOS 0xda
  35. #define SHIFT_BITS 8
  36. #define CONST(x) ((int) ((x) * (1L << SHIFT_BITS) + 0.5))
  37. #define JPEG_UNIT_SIZE 8
  38. static const grub_uint8_t jpeg_zigzag_order[64] = {
  39. 0, 1, 8, 16, 9, 2, 3, 10,
  40. 17, 24, 32, 25, 18, 11, 4, 5,
  41. 12, 19, 26, 33, 40, 48, 41, 34,
  42. 27, 20, 13, 6, 7, 14, 21, 28,
  43. 35, 42, 49, 56, 57, 50, 43, 36,
  44. 29, 22, 15, 23, 30, 37, 44, 51,
  45. 58, 59, 52, 45, 38, 31, 39, 46,
  46. 53, 60, 61, 54, 47, 55, 62, 63
  47. };
  48. #ifdef JPEG_DEBUG
  49. static grub_command_t cmd;
  50. #endif
  51. typedef int jpeg_data_unit_t[64];
  52. struct grub_jpeg_data
  53. {
  54. grub_file_t file;
  55. struct grub_video_bitmap **bitmap;
  56. int image_width;
  57. int image_height;
  58. grub_uint8_t *huff_value[4];
  59. int huff_offset[4][16];
  60. int huff_maxval[4][16];
  61. grub_uint8_t quan_table[2][64];
  62. int comp_index[3][3];
  63. jpeg_data_unit_t ydu[4];
  64. jpeg_data_unit_t crdu;
  65. jpeg_data_unit_t cbdu;
  66. int vs, hs;
  67. int dc_value[3];
  68. int bit_mask, bit_save;
  69. };
  70. static grub_uint8_t
  71. grub_jpeg_get_byte (struct grub_jpeg_data *data)
  72. {
  73. grub_uint8_t r;
  74. r = 0;
  75. grub_file_read (data->file, &r, 1);
  76. return r;
  77. }
  78. static grub_uint16_t
  79. grub_jpeg_get_word (struct grub_jpeg_data *data)
  80. {
  81. grub_uint16_t r;
  82. r = 0;
  83. grub_file_read (data->file, &r, sizeof (grub_uint16_t));
  84. return grub_be_to_cpu16 (r);
  85. }
  86. static int
  87. grub_jpeg_get_bit (struct grub_jpeg_data *data)
  88. {
  89. int ret;
  90. if (data->bit_mask == 0)
  91. {
  92. data->bit_save = grub_jpeg_get_byte (data);
  93. if (data->bit_save == JPEG_ESC_CHAR)
  94. {
  95. if (grub_jpeg_get_byte (data) != 0)
  96. {
  97. grub_error (GRUB_ERR_BAD_FILE_TYPE,
  98. "jpeg: invalid 0xFF in data stream");
  99. return 0;
  100. }
  101. }
  102. data->bit_mask = 0x80;
  103. }
  104. ret = ((data->bit_save & data->bit_mask) != 0);
  105. data->bit_mask >>= 1;
  106. return ret;
  107. }
  108. static int
  109. grub_jpeg_get_number (struct grub_jpeg_data *data, int num)
  110. {
  111. int value, i, msb;
  112. if (num == 0)
  113. return 0;
  114. msb = value = grub_jpeg_get_bit (data);
  115. for (i = 1; i < num; i++)
  116. value = (value << 1) + (grub_jpeg_get_bit (data) != 0);
  117. if (!msb)
  118. value += 1 - (1 << num);
  119. return value;
  120. }
  121. static int
  122. grub_jpeg_get_huff_code (struct grub_jpeg_data *data, int id)
  123. {
  124. int code;
  125. unsigned i;
  126. code = 0;
  127. for (i = 0; i < ARRAY_SIZE (data->huff_maxval[id]); i++)
  128. {
  129. code <<= 1;
  130. if (grub_jpeg_get_bit (data))
  131. code++;
  132. if (code < data->huff_maxval[id][i])
  133. return data->huff_value[id][code + data->huff_offset[id][i]];
  134. }
  135. grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: huffman decode fails");
  136. return 0;
  137. }
  138. static grub_err_t
  139. grub_jpeg_decode_huff_table (struct grub_jpeg_data *data)
  140. {
  141. int id, ac, n, base, ofs;
  142. grub_uint32_t next_marker;
  143. grub_uint8_t count[16];
  144. unsigned i;
  145. next_marker = data->file->offset;
  146. next_marker += grub_jpeg_get_word (data);
  147. while (data->file->offset + sizeof (count) + 1 <= next_marker)
  148. {
  149. id = grub_jpeg_get_byte (data);
  150. ac = (id >> 4) & 1;
  151. id &= 0xF;
  152. if (id > 1)
  153. return grub_error (GRUB_ERR_BAD_FILE_TYPE,
  154. "jpeg: too many huffman tables");
  155. if (grub_file_read (data->file, &count, sizeof (count)) !=
  156. sizeof (count))
  157. return grub_errno;
  158. n = 0;
  159. for (i = 0; i < ARRAY_SIZE (count); i++)
  160. n += count[i];
  161. id += ac * 2;
  162. data->huff_value[id] = grub_malloc (n);
  163. if (grub_errno)
  164. return grub_errno;
  165. if (grub_file_read (data->file, data->huff_value[id], n) != n)
  166. return grub_errno;
  167. base = 0;
  168. ofs = 0;
  169. for (i = 0; i < ARRAY_SIZE (count); i++)
  170. {
  171. base += count[i];
  172. ofs += count[i];
  173. data->huff_maxval[id][i] = base;
  174. data->huff_offset[id][i] = ofs - base;
  175. base <<= 1;
  176. }
  177. }
  178. if (data->file->offset != next_marker)
  179. grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in huffman table");
  180. return grub_errno;
  181. }
  182. static grub_err_t
  183. grub_jpeg_decode_quan_table (struct grub_jpeg_data *data)
  184. {
  185. int id;
  186. grub_uint32_t next_marker;
  187. next_marker = data->file->offset;
  188. next_marker += grub_jpeg_get_word (data);
  189. while (data->file->offset + sizeof (data->quan_table[id]) + 1
  190. <= next_marker)
  191. {
  192. id = grub_jpeg_get_byte (data);
  193. if (id >= 0x10) /* Upper 4-bit is precision. */
  194. return grub_error (GRUB_ERR_BAD_FILE_TYPE,
  195. "jpeg: only 8-bit precision is supported");
  196. if (id > 1)
  197. return grub_error (GRUB_ERR_BAD_FILE_TYPE,
  198. "jpeg: too many quantization tables");
  199. if (grub_file_read (data->file, &data->quan_table[id],
  200. sizeof (data->quan_table[id]))
  201. != sizeof (data->quan_table[id]))
  202. return grub_errno;
  203. }
  204. if (data->file->offset != next_marker)
  205. grub_error (GRUB_ERR_BAD_FILE_TYPE,
  206. "jpeg: extra byte in quantization table");
  207. return grub_errno;
  208. }
  209. static grub_err_t
  210. grub_jpeg_decode_sof (struct grub_jpeg_data *data)
  211. {
  212. int i, cc;
  213. grub_uint32_t next_marker;
  214. next_marker = data->file->offset;
  215. next_marker += grub_jpeg_get_word (data);
  216. if (grub_jpeg_get_byte (data) != 8)
  217. return grub_error (GRUB_ERR_BAD_FILE_TYPE,
  218. "jpeg: only 8-bit precision is supported");
  219. data->image_height = grub_jpeg_get_word (data);
  220. data->image_width = grub_jpeg_get_word (data);
  221. if ((!data->image_height) || (!data->image_width))
  222. return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid image size");
  223. cc = grub_jpeg_get_byte (data);
  224. if (cc != 3)
  225. return grub_error (GRUB_ERR_BAD_FILE_TYPE,
  226. "jpeg: component count must be 3");
  227. for (i = 0; i < cc; i++)
  228. {
  229. int id, ss;
  230. id = grub_jpeg_get_byte (data) - 1;
  231. if ((id < 0) || (id >= 3))
  232. return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
  233. ss = grub_jpeg_get_byte (data); /* Sampling factor. */
  234. if (!id)
  235. {
  236. data->vs = ss & 0xF; /* Vertical sampling. */
  237. data->hs = ss >> 4; /* Horizontal sampling. */
  238. if ((data->vs > 2) || (data->hs > 2))
  239. return grub_error (GRUB_ERR_BAD_FILE_TYPE,
  240. "jpeg: sampling method not supported");
  241. }
  242. else if (ss != JPEG_SAMPLING_1x1)
  243. return grub_error (GRUB_ERR_BAD_FILE_TYPE,
  244. "jpeg: sampling method not supported");
  245. data->comp_index[id][0] = grub_jpeg_get_byte (data);
  246. }
  247. if (data->file->offset != next_marker)
  248. grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sof");
  249. return grub_errno;
  250. }
  251. static void
  252. grub_jpeg_idct_transform (jpeg_data_unit_t du)
  253. {
  254. int *pd;
  255. int i;
  256. int t0, t1, t2, t3, t4, t5, t6, t7;
  257. int v0, v1, v2, v3, v4;
  258. pd = du;
  259. for (i = 0; i < JPEG_UNIT_SIZE; i++, pd++)
  260. {
  261. if ((pd[JPEG_UNIT_SIZE * 1] | pd[JPEG_UNIT_SIZE * 2] |
  262. pd[JPEG_UNIT_SIZE * 3] | pd[JPEG_UNIT_SIZE * 4] |
  263. pd[JPEG_UNIT_SIZE * 5] | pd[JPEG_UNIT_SIZE * 6] |
  264. pd[JPEG_UNIT_SIZE * 7]) == 0)
  265. {
  266. pd[JPEG_UNIT_SIZE * 0] <<= SHIFT_BITS;
  267. pd[JPEG_UNIT_SIZE * 1] = pd[JPEG_UNIT_SIZE * 2]
  268. = pd[JPEG_UNIT_SIZE * 3] = pd[JPEG_UNIT_SIZE * 4]
  269. = pd[JPEG_UNIT_SIZE * 5] = pd[JPEG_UNIT_SIZE * 6]
  270. = pd[JPEG_UNIT_SIZE * 7] = pd[JPEG_UNIT_SIZE * 0];
  271. continue;
  272. }
  273. t0 = pd[JPEG_UNIT_SIZE * 0];
  274. t1 = pd[JPEG_UNIT_SIZE * 2];
  275. t2 = pd[JPEG_UNIT_SIZE * 4];
  276. t3 = pd[JPEG_UNIT_SIZE * 6];
  277. v4 = (t1 + t3) * CONST (0.541196100);
  278. v0 = ((t0 + t2) << SHIFT_BITS);
  279. v1 = ((t0 - t2) << SHIFT_BITS);
  280. v2 = v4 - t3 * CONST (1.847759065);
  281. v3 = v4 + t1 * CONST (0.765366865);
  282. t0 = v0 + v3;
  283. t3 = v0 - v3;
  284. t1 = v1 + v2;
  285. t2 = v1 - v2;
  286. t4 = pd[JPEG_UNIT_SIZE * 7];
  287. t5 = pd[JPEG_UNIT_SIZE * 5];
  288. t6 = pd[JPEG_UNIT_SIZE * 3];
  289. t7 = pd[JPEG_UNIT_SIZE * 1];
  290. v0 = t4 + t7;
  291. v1 = t5 + t6;
  292. v2 = t4 + t6;
  293. v3 = t5 + t7;
  294. v4 = (v2 + v3) * CONST (1.175875602);
  295. v0 *= CONST (0.899976223);
  296. v1 *= CONST (2.562915447);
  297. v2 = v2 * CONST (1.961570560) - v4;
  298. v3 = v3 * CONST (0.390180644) - v4;
  299. t4 = t4 * CONST (0.298631336) - v0 - v2;
  300. t5 = t5 * CONST (2.053119869) - v1 - v3;
  301. t6 = t6 * CONST (3.072711026) - v1 - v2;
  302. t7 = t7 * CONST (1.501321110) - v0 - v3;
  303. pd[JPEG_UNIT_SIZE * 0] = t0 + t7;
  304. pd[JPEG_UNIT_SIZE * 7] = t0 - t7;
  305. pd[JPEG_UNIT_SIZE * 1] = t1 + t6;
  306. pd[JPEG_UNIT_SIZE * 6] = t1 - t6;
  307. pd[JPEG_UNIT_SIZE * 2] = t2 + t5;
  308. pd[JPEG_UNIT_SIZE * 5] = t2 - t5;
  309. pd[JPEG_UNIT_SIZE * 3] = t3 + t4;
  310. pd[JPEG_UNIT_SIZE * 4] = t3 - t4;
  311. }
  312. pd = du;
  313. for (i = 0; i < JPEG_UNIT_SIZE; i++, pd += JPEG_UNIT_SIZE)
  314. {
  315. if ((pd[1] | pd[2] | pd[3] | pd[4] | pd[5] | pd[6] | pd[7]) == 0)
  316. {
  317. pd[0] >>= (SHIFT_BITS + 3);
  318. pd[1] = pd[2] = pd[3] = pd[4] = pd[5] = pd[6] = pd[7] = pd[0];
  319. continue;
  320. }
  321. v4 = (pd[2] + pd[6]) * CONST (0.541196100);
  322. v0 = (pd[0] + pd[4]) << SHIFT_BITS;
  323. v1 = (pd[0] - pd[4]) << SHIFT_BITS;
  324. v2 = v4 - pd[6] * CONST (1.847759065);
  325. v3 = v4 + pd[2] * CONST (0.765366865);
  326. t0 = v0 + v3;
  327. t3 = v0 - v3;
  328. t1 = v1 + v2;
  329. t2 = v1 - v2;
  330. t4 = pd[7];
  331. t5 = pd[5];
  332. t6 = pd[3];
  333. t7 = pd[1];
  334. v0 = t4 + t7;
  335. v1 = t5 + t6;
  336. v2 = t4 + t6;
  337. v3 = t5 + t7;
  338. v4 = (v2 + v3) * CONST (1.175875602);
  339. v0 *= CONST (0.899976223);
  340. v1 *= CONST (2.562915447);
  341. v2 = v2 * CONST (1.961570560) - v4;
  342. v3 = v3 * CONST (0.390180644) - v4;
  343. t4 = t4 * CONST (0.298631336) - v0 - v2;
  344. t5 = t5 * CONST (2.053119869) - v1 - v3;
  345. t6 = t6 * CONST (3.072711026) - v1 - v2;
  346. t7 = t7 * CONST (1.501321110) - v0 - v3;
  347. pd[0] = (t0 + t7) >> (SHIFT_BITS * 2 + 3);
  348. pd[7] = (t0 - t7) >> (SHIFT_BITS * 2 + 3);
  349. pd[1] = (t1 + t6) >> (SHIFT_BITS * 2 + 3);
  350. pd[6] = (t1 - t6) >> (SHIFT_BITS * 2 + 3);
  351. pd[2] = (t2 + t5) >> (SHIFT_BITS * 2 + 3);
  352. pd[5] = (t2 - t5) >> (SHIFT_BITS * 2 + 3);
  353. pd[3] = (t3 + t4) >> (SHIFT_BITS * 2 + 3);
  354. pd[4] = (t3 - t4) >> (SHIFT_BITS * 2 + 3);
  355. }
  356. for (i = 0; i < JPEG_UNIT_SIZE * JPEG_UNIT_SIZE; i++)
  357. {
  358. du[i] += 128;
  359. if (du[i] < 0)
  360. du[i] = 0;
  361. if (du[i] > 255)
  362. du[i] = 255;
  363. }
  364. }
  365. static void
  366. grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
  367. {
  368. int h1, h2, qt;
  369. unsigned pos;
  370. grub_memset (du, 0, sizeof (jpeg_data_unit_t));
  371. qt = data->comp_index[id][0];
  372. h1 = data->comp_index[id][1];
  373. h2 = data->comp_index[id][2];
  374. data->dc_value[id] +=
  375. grub_jpeg_get_number (data, grub_jpeg_get_huff_code (data, h1));
  376. du[0] = data->dc_value[id] * (int) data->quan_table[qt][0];
  377. pos = 1;
  378. while (pos < ARRAY_SIZE (data->quan_table[qt]))
  379. {
  380. int num, val;
  381. num = grub_jpeg_get_huff_code (data, h2);
  382. if (!num)
  383. break;
  384. val = grub_jpeg_get_number (data, num & 0xF);
  385. num >>= 4;
  386. pos += num;
  387. du[jpeg_zigzag_order[pos]] = val * (int) data->quan_table[qt][pos];
  388. pos++;
  389. }
  390. grub_jpeg_idct_transform (du);
  391. }
  392. static void
  393. grub_jpeg_ycrcb_to_rgb (int yy, int cr, int cb, grub_uint8_t * rgb)
  394. {
  395. int dd;
  396. cr -= 128;
  397. cb -= 128;
  398. /* Red */
  399. dd = yy + ((cr * CONST (1.402)) >> SHIFT_BITS);
  400. if (dd < 0)
  401. dd = 0;
  402. if (dd > 255)
  403. dd = 255;
  404. *(rgb++) = dd;
  405. /* Green */
  406. dd = yy - ((cb * CONST (0.34414) + cr * CONST (0.71414)) >> SHIFT_BITS);
  407. if (dd < 0)
  408. dd = 0;
  409. if (dd > 255)
  410. dd = 255;
  411. *(rgb++) = dd;
  412. /* Blue */
  413. dd = yy + ((cb * CONST (1.772)) >> SHIFT_BITS);
  414. if (dd < 0)
  415. dd = 0;
  416. if (dd > 255)
  417. dd = 255;
  418. *(rgb++) = dd;
  419. }
  420. static grub_err_t
  421. grub_jpeg_decode_sos (struct grub_jpeg_data *data)
  422. {
  423. int i, cc, r1, c1, nr1, nc1, vb, hb;
  424. grub_uint8_t *ptr1;
  425. grub_uint32_t data_offset;
  426. data_offset = data->file->offset;
  427. data_offset += grub_jpeg_get_word (data);
  428. cc = grub_jpeg_get_byte (data);
  429. if (cc != 3)
  430. return grub_error (GRUB_ERR_BAD_FILE_TYPE,
  431. "jpeg: component count must be 3");
  432. for (i = 0; i < cc; i++)
  433. {
  434. int id, ht;
  435. id = grub_jpeg_get_byte (data) - 1;
  436. if ((id < 0) || (id >= 3))
  437. return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
  438. ht = grub_jpeg_get_byte (data);
  439. data->comp_index[id][1] = (ht >> 4);
  440. data->comp_index[id][2] = (ht & 0xF) + 2;
  441. }
  442. grub_jpeg_get_byte (data); /* Skip 3 unused bytes. */
  443. grub_jpeg_get_word (data);
  444. if (data->file->offset != data_offset)
  445. return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos");
  446. if (grub_video_bitmap_create (data->bitmap, data->image_width,
  447. data->image_height,
  448. GRUB_VIDEO_BLIT_FORMAT_RGB_888))
  449. return grub_errno;
  450. data->bit_mask = 0x0;
  451. vb = data->vs * 8;
  452. hb = data->hs * 8;
  453. nr1 = (data->image_height + vb - 1) / vb;
  454. nc1 = (data->image_width + hb - 1) / hb;
  455. ptr1 = (*data->bitmap)->data;
  456. for (r1 = 0; r1 < nr1;
  457. r1++, ptr1 += (vb * data->image_width - hb * nc1) * 3)
  458. for (c1 = 0; c1 < nc1; c1++, ptr1 += hb * 3)
  459. {
  460. int r2, c2, nr2, nc2;
  461. grub_uint8_t *ptr2;
  462. for (r2 = 0; r2 < data->vs; r2++)
  463. for (c2 = 0; c2 < data->hs; c2++)
  464. grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]);
  465. grub_jpeg_decode_du (data, 1, data->cbdu);
  466. grub_jpeg_decode_du (data, 2, data->crdu);
  467. if (grub_errno)
  468. return grub_errno;
  469. nr2 = (r1 == nr1 - 1) ? (data->image_height - r1 * vb) : vb;
  470. nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb;
  471. ptr2 = ptr1;
  472. for (r2 = 0; r2 < nr2; r2++, ptr2 += (data->image_width - nc2) * 3)
  473. for (c2 = 0; c2 < nc2; c2++, ptr2 += 3)
  474. {
  475. int i0, yy, cr, cb;
  476. i0 = (r2 / data->vs) * 8 + (c2 / data->hs);
  477. cr = data->crdu[i0];
  478. cb = data->cbdu[i0];
  479. yy =
  480. data->ydu[(r2 / 8) * 2 + (c2 / 8)][(r2 % 8) * 8 + (c2 % 8)];
  481. grub_jpeg_ycrcb_to_rgb (yy, cr, cb, ptr2);
  482. }
  483. }
  484. return grub_errno;
  485. }
  486. static grub_uint8_t
  487. grub_jpeg_get_marker (struct grub_jpeg_data *data)
  488. {
  489. grub_uint8_t r;
  490. r = grub_jpeg_get_byte (data);
  491. if (r != JPEG_ESC_CHAR)
  492. {
  493. grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid maker");
  494. return 0;
  495. }
  496. return grub_jpeg_get_byte (data);
  497. }
  498. static grub_err_t
  499. grub_jpeg_decode_jpeg (struct grub_jpeg_data *data)
  500. {
  501. if (grub_jpeg_get_marker (data) != JPEG_MARKER_SOI) /* Start Of Image. */
  502. return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid jpeg file");
  503. while (grub_errno == 0)
  504. {
  505. grub_uint8_t marker;
  506. marker = grub_jpeg_get_marker (data);
  507. if (grub_errno)
  508. break;
  509. #ifdef JPEG_DEBUG
  510. grub_printf ("jpeg marker: %x\n", marker);
  511. #endif
  512. switch (marker)
  513. {
  514. case JPEG_MARKER_DHT: /* Define Huffman Table. */
  515. grub_jpeg_decode_huff_table (data);
  516. break;
  517. case JPEG_MARKER_DQT: /* Define Quantization Table. */
  518. grub_jpeg_decode_quan_table (data);
  519. break;
  520. case JPEG_MARKER_SOF0: /* Start Of Frame 0. */
  521. grub_jpeg_decode_sof (data);
  522. break;
  523. case JPEG_MARKER_SOS: /* Start Of Scan. */
  524. grub_jpeg_decode_sos (data);
  525. break;
  526. case JPEG_MARKER_EOI: /* End Of Image. */
  527. return grub_errno;
  528. default: /* Skip unrecognized marker. */
  529. {
  530. grub_uint16_t sz;
  531. sz = grub_jpeg_get_word (data);
  532. if (grub_errno)
  533. return (grub_errno);
  534. grub_file_seek (data->file, data->file->offset + sz - 2);
  535. }
  536. }
  537. }
  538. return grub_errno;
  539. }
  540. static grub_err_t
  541. grub_video_reader_jpeg (struct grub_video_bitmap **bitmap,
  542. const char *filename)
  543. {
  544. grub_file_t file;
  545. struct grub_jpeg_data *data;
  546. file = grub_buffile_open (filename, 0);
  547. if (!file)
  548. return grub_errno;
  549. data = grub_zalloc (sizeof (*data));
  550. if (data != NULL)
  551. {
  552. int i;
  553. data->file = file;
  554. data->bitmap = bitmap;
  555. grub_jpeg_decode_jpeg (data);
  556. for (i = 0; i < 4; i++)
  557. if (data->huff_value[i])
  558. grub_free (data->huff_value[i]);
  559. grub_free (data);
  560. }
  561. if (grub_errno != GRUB_ERR_NONE)
  562. {
  563. grub_video_bitmap_destroy (*bitmap);
  564. *bitmap = 0;
  565. }
  566. grub_file_close (file);
  567. return grub_errno;
  568. }
  569. #if defined(JPEG_DEBUG)
  570. static grub_err_t
  571. grub_cmd_jpegtest (grub_command_t cmd __attribute__ ((unused)),
  572. int argc, char **args)
  573. {
  574. struct grub_video_bitmap *bitmap = 0;
  575. if (argc != 1)
  576. return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
  577. grub_video_reader_jpeg (&bitmap, args[0]);
  578. if (grub_errno != GRUB_ERR_NONE)
  579. return grub_errno;
  580. grub_video_bitmap_destroy (bitmap);
  581. return GRUB_ERR_NONE;
  582. }
  583. #endif
  584. static struct grub_video_bitmap_reader jpg_reader = {
  585. .extension = ".jpg",
  586. .reader = grub_video_reader_jpeg,
  587. .next = 0
  588. };
  589. static struct grub_video_bitmap_reader jpeg_reader = {
  590. .extension = ".jpeg",
  591. .reader = grub_video_reader_jpeg,
  592. .next = 0
  593. };
  594. GRUB_MOD_INIT (jpeg)
  595. {
  596. grub_video_bitmap_reader_register (&jpg_reader);
  597. grub_video_bitmap_reader_register (&jpeg_reader);
  598. #if defined(JPEG_DEBUG)
  599. cmd = grub_register_command ("jpegtest", grub_cmd_jpegtest,
  600. "FILE", "Tests loading of JPEG bitmap.");
  601. #endif
  602. }
  603. GRUB_MOD_FINI (jpeg)
  604. {
  605. #if defined(JPEG_DEBUG)
  606. grub_unregister_command (cmd);
  607. #endif
  608. grub_video_bitmap_reader_unregister (&jpeg_reader);
  609. grub_video_bitmap_reader_unregister (&jpg_reader);
  610. }