[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] jpeg image reader
From: |
Marco Gerards |
Subject: |
Re: [PATCH] jpeg image reader |
Date: |
Sun, 13 Jan 2008 19:31:03 +0100 |
User-agent: |
Gnus/5.110006 (No Gnus v0.6) Emacs/21.4 (gnu/linux) |
Bean <address@hidden> writes:
Hi,
> change the handling of width/height that's not aligned, now it use the
> exact size instead of padding.
You forgot the changelog entry.
I'll do a quick review.
Especially the longjmp stuff should be changed, IMO. Otherwise the
code is of good quality and I hope it can be committed soon. Please
see the comments below.
--
Marco
> /*
> * GRUB -- GRand Unified Bootloader
> * Copyright (C) 2008 Free Software Foundation, Inc.
Did you write all the code yourself?
> * GRUB is free software: you can redistribute it and/or modify
> * it under the terms of the GNU General Public License as published by
> * the Free Software Foundation, either version 3 of the License, or
> * (at your option) any later version.
> *
> * GRUB is distributed in the hope that it will be useful,
> * but WITHOUT ANY WARRANTY; without even the implied warranty of
> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> * GNU General Public License for more details.
> *
> * You should have received a copy of the GNU General Public License
> * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
> */
>
> #include <grub/bitmap.h>
> #include <grub/types.h>
> #include <grub/normal.h>
> #include <grub/dl.h>
> #include <grub/mm.h>
> #include <grub/misc.h>
> #include <grub/arg.h>
> #include <grub/file.h>
> #include <grub/setjmp.h>
setjmp!?
> /* Uncomment following define to enable JPEG debug. */
> //#define JPEG_DEBUG
>
> typedef enum
> { /* JPEG marker codes */
> M_SOF0 = 0xc0,
> M_SOF1 = 0xc1,
> M_SOF2 = 0xc2,
> M_SOF3 = 0xc3,
>
> M_SOF5 = 0xc5,
> M_SOF6 = 0xc6,
> M_SOF7 = 0xc7,
>
> M_JPG = 0xc8,
> M_SOF9 = 0xc9,
> M_SOF10 = 0xca,
> M_SOF11 = 0xcb,
>
> M_SOF13 = 0xcd,
> M_SOF14 = 0xce,
> M_SOF15 = 0xcf,
>
> M_DHT = 0xc4,
>
> M_DAC = 0xcc,
>
> M_RST0 = 0xd0,
> M_RST1 = 0xd1,
> M_RST2 = 0xd2,
> M_RST3 = 0xd3,
> M_RST4 = 0xd4,
> M_RST5 = 0xd5,
> M_RST6 = 0xd6,
> M_RST7 = 0xd7,
>
> M_SOI = 0xd8,
> M_EOI = 0xd9,
> M_SOS = 0xda,
> M_DQT = 0xdb,
> M_DNL = 0xdc,
> M_DRI = 0xdd,
> M_DHP = 0xde,
> M_EXP = 0xdf,
>
> M_APP0 = 0xe0,
> M_APP1 = 0xe1,
> M_APP2 = 0xe2,
> M_APP3 = 0xe3,
> M_APP4 = 0xe4,
> M_APP5 = 0xe5,
> M_APP6 = 0xe6,
> M_APP7 = 0xe7,
> M_APP8 = 0xe8,
> M_APP9 = 0xe9,
> M_APP10 = 0xea,
> M_APP11 = 0xeb,
> M_APP12 = 0xec,
> M_APP13 = 0xed,
> M_APP14 = 0xee,
> M_APP15 = 0xef,
>
> M_JPG0 = 0xf0,
> M_JPG13 = 0xfd,
> M_COM = 0xfe,
>
> M_TEM = 0x01,
>
> M_ERROR = 0x100
> } JPEG_MARKER;
Please use jpeg_marker_t.
> typedef int jpeg_data_unit[64];
jpeg_data_unit_t
> struct grub_jpeg_data
> {
> grub_file_t file;
> grub_jmp_buf jumper;
>
> int image_width;
> int image_height;
>
> grub_uint8_t *huff_value[4];
> int huff_offset[4][16];
> int huff_maxval[4][16];
>
> grub_uint8_t quan_table[2][64];
> int comp_index[3][3];
>
> jpeg_data_unit ydu[4];
> jpeg_data_unit crdu;
> jpeg_data_unit cbdu;
>
> int Cr_r_tab[256], Cb_b_tab[256], Cr_g_tab[256], Cb_g_tab[256];
I do not like using uppercase for members.
> int vs, hs;
>
> int dc_value[3];
>
> int bit_mask, bit_save;
>
> struct grub_video_bitmap **bitmap;
> };
>
>
> static grub_uint8_t
> get_byte (struct grub_jpeg_data *data)
How about jpeg_get_byte or so? Or even add grub_. I have the feeling
this will clash someday.
> {
> grub_uint8_t r;
>
> if (grub_file_read (data->file, (char *) &r, 1) != 1)
> grub_longjmp (data->jumper, 1);
I don't like having longjmp here, please use the error handling as is
used in other parts of GRUB 2.
> return r;
> }
>
> static grub_uint16_t
> get_word (struct grub_jpeg_data *data)
> {
> grub_uint16_t r;
>
> if (grub_file_read (data->file, (char *) &r, 2) != 2)
> grub_longjmp (data->jumper, 1);
please replace the 2's by sizeof (grub_uint16_t). As for the error
handling, see the previous comment.
> return grub_be_to_cpu16 (r);
> }
>
> static int
> get_bit (struct grub_jpeg_data *data)
> {
> int ret;
>
> if (data->bit_mask == 0)
> {
> data->bit_save = get_byte (data);
> if (data->bit_save == 0xFF)
> {
> if (get_byte (data) != 0)
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE,
> "jpeg: invalid 0xFF in data stream");
> grub_longjmp (data->jumper, 1);
jongjmp...
> }
> }
> data->bit_mask = 0x80;
> }
>
> ret = (data->bit_save & data->bit_mask);
> data->bit_mask >>= 1;
> return ret;
How about "return !!ret" so you can directly use this bit in the other
functions that call this one?
> }
>
> static int
> get_number (struct grub_jpeg_data *data, int num)
> {
> int value, i, bit;
>
> if (num == 0)
> return 0;
>
> bit = get_bit (data);
> value = (bit != 0);
> for (i = 1; i < num; i++)
> value = value * 2 + (get_bit (data) != 0);
(value << 1)
> if (!bit)
> value += 1 - (1 << num);
>
> return value;
> }
>
> static int
> get_huff_code (struct grub_jpeg_data *data, int id)
> {
> int code, i;
>
> code = 0;
> for (i = 0; i < 16; i++)
> {
> code <<= 1;
> if (get_bit (data))
> code++;
> if (code < data->huff_maxval[id][i])
> return data->huff_value[id][code + data->huff_offset[id][i]];
> }
> grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: huffman decode fails");
> grub_longjmp (data->jumper, 1);
...
> return 0;
> }
>
> static void
> decode_huff_table (struct grub_jpeg_data *data)
> {
> int id, ac, i, n, base, ofs;
> grub_uint32_t next_marker;
> grub_uint8_t count[16];
>
> next_marker = data->file->offset;
> next_marker += get_word (data);
>
> id = get_byte (data);
> ac = (id >> 4);
> id &= 0xF;
> if (id > 1)
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: too many huffman table");
> grub_longjmp (data->jumper, 1);
> }
How many are normally supported? Max 4, IIRC?
> if (grub_file_read (data->file, (char *) &count, sizeof (count)) !=
> sizeof (count))
> grub_longjmp (data->jumper, 1);
>
> n = 0;
> for (i = 0; i < 16; i++)
> n += count[i];
What does this do?
> id += ac * 2;
> data->huff_value[id] = grub_malloc (n);
> if (data->huff_value[id] == NULL)
> grub_longjmp (data->jumper, 1);
How about "goto fail"? or a return?
>
> if (grub_file_read (data->file, (char *) data->huff_value[id], n) != n)
> grub_longjmp (data->jumper, 1);
...
> base = 0;
> ofs = 0;
> for (i = 0; i < 16; i++)
> {
> base += count[i];
> ofs += count[i];
>
> data->huff_maxval[id][i] = base;
> data->huff_offset[id][i] = ofs - base;
>
> base <<= 1;
> }
>
> if (data->file->offset != next_marker)
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE,
> "jpeg: extra byte in huffman table");
> grub_longjmp (data->jumper, 1);
> }
> }
>
> static void
> decode_quan_table (struct grub_jpeg_data *data)
> {
> int id;
> grub_uint32_t next_marker;
>
> next_marker = data->file->offset;
> next_marker += get_word (data);
>
> id = get_byte (data);
> if (id >= 0x10) /* upper 4-bit is precision */
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE,
> "jpeg: only 8-bit precision is supported");
> grub_longjmp (data->jumper, 1);
> }
>
> if (id > 1)
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE,
> "jpeg: too many quantization table");
table -> tables
> grub_longjmp (data->jumper, 1);
> }
>
> if (grub_file_read (data->file, (char *) &data->quan_table[id], 64) != 64)
> grub_longjmp (data->jumper, 1);
>
> if (data->file->offset != next_marker)
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE,
> "jpeg: extra byte in quantization table");
> grub_longjmp (data->jumper, 1);
> }
> }
>
> static void
> decode_sof (struct grub_jpeg_data *data)
> {
> int i, cc;
> grub_uint32_t next_marker;
>
> next_marker = data->file->offset;
> next_marker += get_word (data);
>
> if (get_byte (data) != 8)
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE,
> "jpeg: only 8-bit precision is supported");
> grub_longjmp (data->jumper, 1);
> }
>
> data->image_height = get_word (data);
> data->image_width = get_word (data);
>
> if ((!data->image_height) || (!data->image_width))
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid image size");
> grub_longjmp (data->jumper, 1);
> }
>
> cc = get_byte (data);
> if (cc != 3)
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: component count must be 3");
> grub_longjmp (data->jumper, 1);
> }
>
> for (i = 0; i < cc; i++)
> {
> int id, ss;
>
> id = get_byte (data) - 1;
> if ((id < 0) || (id >= 3))
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
> grub_longjmp (data->jumper, 1);
> }
> ss = get_byte (data);
> if (!id)
> {
> data->vs = ss & 0xF;
> data->hs = ss >> 4;
What's ss, vs, hs?
> if ((data->vs > 2) || (data->hs > 2))
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE,
> "jpeg: sampling method nor supported");
> grub_longjmp (data->jumper, 1);
> }
> }
> else if (ss != 0x11)
Magic value... Can you use a macro for this or so? I do not know
what this means.
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE,
> "jpeg: sampling method nor supported");
> grub_longjmp (data->jumper, 1);
> }
> data->comp_index[id][0] = get_byte (data);
> }
>
> if (data->file->offset != next_marker)
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sof");
> grub_longjmp (data->jumper, 1);
> }
> }
>
> #define DCTSIZE 8
>
> #define CONST_BITS 8
> #define PASS1_BITS 2
>
> #define FIX_1_082392200 ((int) 277) /* FIX(1.082392200) */
> #define FIX_1_414213562 ((int) 362) /* FIX(1.414213562) */
> #define FIX_1_847759065 ((int) 473) /* FIX(1.847759065) */
> #define FIX_2_613125930 ((int) 669) /* FIX(2.613125930) */
>
> #define ONE ((long) 1)
> #define DESCALE(x,n) (((x) + (ONE << ((n)-1))) >> (n))
>
> #define MULTIPLY(var,const) DESCALE((var) * (const), CONST_BITS)
>
> static const grub_uint8_t natural_order[64] = {
> 0, 1, 8, 16, 9, 2, 3, 10,
> 17, 24, 32, 25, 18, 11, 4, 5,
> 12, 19, 26, 33, 40, 48, 41, 34,
> 27, 20, 13, 6, 7, 14, 21, 28,
> 35, 42, 49, 56, 57, 50, 43, 36,
> 29, 22, 15, 23, 30, 37, 44, 51,
> 58, 59, 52, 45, 38, 31, 39, 46,
> 53, 60, 61, 54, 47, 55, 62, 63
> };
>
> static const int aanscales[64] = {
> /* precomputed values scaled up by 14 bits */
> 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
> 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
> 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
> 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
> 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
> 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
> 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
> 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
> };
>
> static void
> idct_transform (jpeg_data_unit du)
> {
> int *pd;
> int ctr;
> int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
> int tmp10, tmp11, tmp12, tmp13;
> int z5, z10, z11, z12, z13;
>
> /* Pass 1: process columns from input, store into work array. */
>
> pd = du;
> for (ctr = DCTSIZE; ctr > 0; ctr--)
> {
> if ((pd[DCTSIZE * 1] | pd[DCTSIZE * 2] | pd[DCTSIZE * 3] |
> pd[DCTSIZE * 4] | pd[DCTSIZE * 5] | pd[DCTSIZE * 6] |
> pd[DCTSIZE * 7]) == 0)
> {
> pd[DCTSIZE * 1] = pd[DCTSIZE * 2]
> = pd[DCTSIZE * 3] = pd[DCTSIZE * 4]
> = pd[DCTSIZE * 5] = pd[DCTSIZE * 6]
> = pd[DCTSIZE * 7] = pd[DCTSIZE * 0];
>
> pd++; /* advance pointers to next column */
> continue;
> }
>
> /* Even part */
>
> tmp0 = pd[DCTSIZE * 0];
> tmp1 = pd[DCTSIZE * 2];
> tmp2 = pd[DCTSIZE * 4];
> tmp3 = pd[DCTSIZE * 6];
>
> tmp10 = tmp0 + tmp2; /* phase 3 */
> tmp11 = tmp0 - tmp2;
>
> tmp13 = tmp1 + tmp3; /* phases 5-3 */
> tmp12 = MULTIPLY (tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4
> */
>
> tmp0 = tmp10 + tmp13; /* phase 2 */
> tmp3 = tmp10 - tmp13;
> tmp1 = tmp11 + tmp12;
> tmp2 = tmp11 - tmp12;
>
> /* Odd part */
>
> tmp4 = pd[DCTSIZE * 1];
> tmp5 = pd[DCTSIZE * 3];
> tmp6 = pd[DCTSIZE * 5];
> tmp7 = pd[DCTSIZE * 7];
>
> z13 = tmp6 + tmp5; /* phase 6 */
> z10 = tmp6 - tmp5;
> z11 = tmp4 + tmp7;
> z12 = tmp4 - tmp7;
>
> tmp7 = z11 + z13; /* phase 5 */
> tmp11 = MULTIPLY (z11 - z13, FIX_1_414213562); /* 2*c4 */
>
> z5 = MULTIPLY (z10 + z12, FIX_1_847759065); /* 2*c2 */
> tmp10 = MULTIPLY (z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
> tmp12 = MULTIPLY (z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */
>
>
> tmp6 = tmp12 - tmp7; /* phase 2 */
> tmp5 = tmp11 - tmp6;
> tmp4 = tmp10 + tmp5;
>
> pd[DCTSIZE * 0] = (int) (tmp0 + tmp7);
> pd[DCTSIZE * 7] = (int) (tmp0 - tmp7);
> pd[DCTSIZE * 1] = (int) (tmp1 + tmp6);
> pd[DCTSIZE * 6] = (int) (tmp1 - tmp6);
> pd[DCTSIZE * 2] = (int) (tmp2 + tmp5);
> pd[DCTSIZE * 5] = (int) (tmp2 - tmp5);
> pd[DCTSIZE * 4] = (int) (tmp3 + tmp4);
> pd[DCTSIZE * 3] = (int) (tmp3 - tmp4);
>
> pd++; /* advance pointers to next column */
> }
>
> /* Pass 2: process rows from work array, store into output array. */
> /* Note that we must descale the results by a factor of 8 == 2**3, */
> /* and also undo the PASS1_BITS scaling. */
>
> pd = du;
> for (ctr = 0; ctr < DCTSIZE; ctr++)
> {
> /* Even part */
>
> tmp10 = pd[0] + pd[4];
> tmp11 = pd[0] - pd[4];
>
> tmp13 = pd[2] + pd[6];
> tmp12 = MULTIPLY (pd[2] - pd[6], FIX_1_414213562) - tmp13;
>
> tmp0 = tmp10 + tmp13;
> tmp3 = tmp10 - tmp13;
> tmp1 = tmp11 + tmp12;
> tmp2 = tmp11 - tmp12;
>
> /* Odd part */
>
> z13 = pd[5] + pd[3];
> z10 = pd[5] - pd[3];
> z11 = pd[1] + pd[7];
> z12 = pd[1] - pd[7];
>
> tmp7 = z11 + z13; /* phase 5 */
> tmp11 = MULTIPLY (z11 - z13, FIX_1_414213562); /* 2*c4 */
>
> z5 = MULTIPLY (z10 + z12, FIX_1_847759065); /* 2*c2 */
> tmp10 = MULTIPLY (z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
> tmp12 = MULTIPLY (z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */
>
> tmp6 = tmp12 - tmp7; /* phase 2 */
> tmp5 = tmp11 - tmp6;
> tmp4 = tmp10 + tmp5;
>
> /* Final output stage: scale down by a factor of 8 and range-limit */
>
> pd[0] = DESCALE (tmp0 + tmp7, PASS1_BITS + 3) + 128;
> pd[7] = DESCALE (tmp0 - tmp7, PASS1_BITS + 3) + 128;
> pd[1] = DESCALE (tmp1 + tmp6, PASS1_BITS + 3) + 128;
> pd[6] = DESCALE (tmp1 - tmp6, PASS1_BITS + 3) + 128;
> pd[2] = DESCALE (tmp2 + tmp5, PASS1_BITS + 3) + 128;
> pd[5] = DESCALE (tmp2 - tmp5, PASS1_BITS + 3) + 128;
> pd[4] = DESCALE (tmp3 + tmp4, PASS1_BITS + 3) + 128;
> pd[3] = DESCALE (tmp3 - tmp4, PASS1_BITS + 3) + 128;
>
> pd += DCTSIZE; /* advance pointer to next row */
> }
>
> for (ctr = 0; ctr < 64; ctr++)
> {
> if (du[ctr] < 0)
> du[ctr] = 0;
> if (du[ctr] > 255)
> du[ctr] = 255;
> }
> }
>
> static void
> decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit du)
> {
> int pos, h1, h2, qt;
>
> grub_memset (du, 0, sizeof (jpeg_data_unit));
>
> qt = data->comp_index[id][0];
> h1 = data->comp_index[id][1];
> h2 = data->comp_index[id][2];
>
> data->dc_value[id] += get_number (data, get_huff_code (data, h1));
>
> du[0] =
> data->dc_value[id] * DESCALE ((int) data->quan_table[qt][0] *
> (int) aanscales[0], 14 - 2);
> pos = 1;
> while (pos < 64)
> {
> int num, val;
>
> num = get_huff_code (data, h2);
> if (!num)
> break;
> val = get_number (data, num & 0xF);
> num >>= 4;
> pos += num;
> du[natural_order[pos]] =
> val * DESCALE ((int) data->quan_table[qt][pos] *
> (int) aanscales[natural_order[pos]], 14 - 2);
14 - 2?
> pos++;
> }
>
> idct_transform (du);
> }
>
> #define SCALEBITS 16 /* speediest right-shift on some machines */
> #define ONE_HALF ((int) 1 << (SCALEBITS-1))
> #define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5))
>
> static void
> build_color_table (struct grub_jpeg_data *data)
> {
> int i, x;
>
> for (i = 0, x = -128; i <= 255; i++, x++)
> {
> data->Cr_r_tab[i] = (int) (FIX (1.40200) * x + ONE_HALF) >> SCALEBITS;
> data->Cb_b_tab[i] = (int) (FIX (1.77200) * x + ONE_HALF) >> SCALEBITS;
> data->Cr_g_tab[i] = (-FIX (0.71414)) * x;
> data->Cb_g_tab[i] = (-FIX (0.34414)) * x + ONE_HALF;
> }
> }
>
> static void
> decode_sos (struct grub_jpeg_data *data)
> {
> int i, cc, r1, c1, nr1, nc1, vb, hb;
> grub_uint8_t *ptr1;
> grub_uint32_t data_offset;
>
> data_offset = data->file->offset;
> data_offset += get_word (data);
>
> cc = get_byte (data);
>
> if (cc != 3)
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: component count must be 3");
> grub_longjmp (data->jumper, 1);
> }
>
> for (i = 0; i < cc; i++)
> {
> int id, ht;
>
> id = get_byte (data) - 1;
> if ((id < 0) || (id >= 3))
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
> grub_longjmp (data->jumper, 1);
> }
>
> ht = get_byte (data);
> data->comp_index[id][1] = (ht >> 4);
> data->comp_index[id][2] = (ht & 0xF) + 2;
> }
>
> get_byte (data); /* skip 3 unused bytes */
> get_word (data);
>
> if (data->file->offset != data_offset)
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos");
> grub_longjmp (data->jumper, 1);
> }
>
> if (grub_video_bitmap_create (data->bitmap, data->image_width,
> data->image_height,
> GRUB_VIDEO_BLIT_FORMAT_R8G8B8))
> grub_longjmp (data->jumper, 1);
>
> data->bit_mask = 0x0;
>
> vb = data->vs * 8;
> hb = data->hs * 8;
> nr1 = (data->image_height + vb - 1) / vb;
> nc1 = (data->image_width + hb - 1) / hb;
>
> ptr1 = (*data->bitmap)->data;
> for (r1 = 0; r1 < nr1; r1++, ptr1 += (vb * data->image_width - hb * nc1) *
> 3)
> for (c1 = 0; c1 < nc1; c1++, ptr1 += hb * 3)
> {
> int r2, c2, nr2, nc2;
> grub_uint8_t *ptr2;
>
> for (r2 = 0; r2 < data->vs; r2++)
> for (c2 = 0; c2 < data->hs; c2++)
> decode_du (data, 0, data->ydu[r2 * 2 + c2]);
>
> decode_du (data, 1, data->cbdu);
> decode_du (data, 2, data->crdu);
>
> nr2 = (r1 == nr1 - 1) ? (data->image_height - r1 * vb) : vb;
> nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb;
>
> ptr2 = ptr1;
> for (r2 = 0; r2 < nr2; r2++, ptr2 += (data->image_width - nc2) * 3)
> for (c2 = 0; c2 < nc2; c2++)
> {
> int i0, yy, cr, cb, dd;
>
> i0 = (r2 / data->vs) * 8 + (c2 / data->hs);
> cr = data->crdu[i0];
> cb = data->cbdu[i0];
>
> yy = data->ydu[(r2 / 8) * 2 + (c2 / 8)][(r2 % 8) * 8 + (c2 %
> 8)];
>
> /* Red */
> dd = yy + data->Cr_r_tab[cr];
> if (dd < 0)
> dd = 0;
> if (dd > 255)
> dd = 255;
> *(ptr2++) = dd;
>
> /* Green */
> dd = yy + ((data->Cb_g_tab[cb] + data->Cr_g_tab[cr]) >>
> SCALEBITS);
> if (dd < 0)
> dd = 0;
> if (dd > 255)
> dd = 255;
> *(ptr2++) = dd;
>
> /* Blue */
> dd = yy + data->Cb_b_tab[cb];
> if (dd < 0)
> dd = 0;
> if (dd > 255)
> dd = 255;
> *(ptr2++) = dd;
Perhaps it's useful to make a separate function for colorspace
conversion? (that's what's happening here, right?) Other loaders can
use it too.
> }
> }
> }
>
>
> static grub_uint8_t
> get_marker (struct grub_jpeg_data *data)
> {
> grub_uint8_t r;
>
> r = get_byte (data);
>
> if (r != 0xFF) /* escape character */
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid maker");
> grub_longjmp (data->jumper, 1);
> }
>
> return get_byte (data);
> }
>
> static void
> decode_jpeg (struct grub_jpeg_data *data)
> {
> build_color_table (data);
>
> if (get_marker (data) != M_SOI) /* Start Of Image */
> {
> grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid jpeg file");
> grub_longjmp (data->jumper, 1);
> }
>
> while (1)
> {
> grub_uint8_t marker;
>
> marker = get_marker (data);
> #ifdef JPEG_DEBUG
> grub_printf ("jpeg marker: %x\n", marker);
> #endif
> switch (marker)
> {
> case M_DHT: /* Define Huffman Table */
> decode_huff_table (data);
> break;
> case M_DQT: /* Define Quantization Table */
> decode_quan_table (data);
> break;
> case M_SOF0: /* Start Of Frame 0 */
> decode_sof (data);
> break;
> case M_SOS: /* Start Of Scan */
> decode_sos (data);
> break;
> case M_EOI: /* End Of Image */
> return;
> default: /* Skip unrecognized marker */
> {
> grub_uint16_t sz;
>
> sz = get_word (data);
> grub_file_seek (data->file, data->file->offset + sz - 2);
> }
> }
> }
> }
>
> static grub_err_t
> grub_video_reader_jpeg (struct grub_video_bitmap **bitmap,
> const char *filename)
> {
> grub_file_t file;
> struct grub_jpeg_data *data;
>
> file = grub_file_open (filename);
> if (!file)
> return grub_errno;
>
> data = grub_malloc (sizeof (*data));
> if (data != NULL)
> {
> int i;
>
> grub_memset (data, 0, sizeof (*data));
> data->file = file;
> data->bitmap = bitmap;
> if (!grub_setjmp (data->jumper))
> decode_jpeg (data);
>
> for (i = 0; i < 4; i++)
> if (data->huff_value[i])
> grub_free (data->huff_value[i]);
> grub_free (data);
> }
>
> if (grub_errno != GRUB_ERR_NONE)
> {
> grub_video_bitmap_destroy (*bitmap);
> *bitmap = 0;
> }
>
> grub_file_close (file);
> return grub_errno;
> }
>
> #if defined(JPEG_DEBUG)
> static grub_err_t
> grub_cmd_jpegtest (struct grub_arg_list *state __attribute__ ((unused)),
> int argc, char **args)
> {
> struct grub_video_bitmap *bitmap = 0;
>
> if (argc != 1)
> return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
>
> grub_video_reader_jpeg (&bitmap, args[0]);
> if (grub_errno != GRUB_ERR_NONE)
> return grub_errno;
>
> grub_video_bitmap_destroy (bitmap);
>
> return GRUB_ERR_NONE;
> }
> #endif
>
> static struct grub_video_bitmap_reader jpg_reader = {
> .extension = ".jpg",
> .reader = grub_video_reader_jpeg,
> .next = 0
> };
>
> static struct grub_video_bitmap_reader jpeg_reader = {
> .extension = ".jpeg",
> .reader = grub_video_reader_jpeg,
> .next = 0
> };
>
> GRUB_MOD_INIT (video_reader_jpeg)
> {
> grub_video_bitmap_reader_register (&jpg_reader);
> grub_video_bitmap_reader_register (&jpeg_reader);
> #if defined(JPEG_DEBUG)
> grub_register_command ("jpegtest", grub_cmd_jpegtest,
> GRUB_COMMAND_FLAG_BOTH, "jpegtest FILE",
> "Tests loading of JPEG bitmap.", 0);
> #endif
> }
>
> GRUB_MOD_FINI (video_reader_jpeg)
> {
> #if defined(JPEG_DEBUG)
> grub_unregister_command ("jpegtest");
> #endif
> grub_video_bitmap_reader_unregister (&jpeg_reader);
> grub_video_bitmap_reader_unregister (&jpg_reader);
> }
>
>
> --
> Bean
>
>
> _______________________________________________
> Grub-devel mailing list
> address@hidden
> http://lists.gnu.org/mailman/listinfo/grub-devel
- [PATCH] jpeg image reader, Bean, 2008/01/09
- Re: [PATCH] jpeg image reader, Bean, 2008/01/09
- Re: [PATCH] jpeg image reader, Vesa Jääskeläinen, 2008/01/09
- Re: [PATCH] jpeg image reader, Bean, 2008/01/10
- Re: [PATCH] jpeg image reader, Bean, 2008/01/12
- Re: [PATCH] jpeg image reader, Bean, 2008/01/13
- Re: [PATCH] jpeg image reader,
Marco Gerards <=
- Re: [PATCH] jpeg image reader, Bean, 2008/01/14
- Re: [PATCH] jpeg image reader, Marco Gerards, 2008/01/15
- Re: [PATCH] jpeg image reader, Robert Millan, 2008/01/15
- Re: [PATCH] jpeg image reader, Marco Gerards, 2008/01/15
- Re: [PATCH] jpeg image reader, Robert Millan, 2008/01/15
- Re: [PATCH] jpeg image reader, Marco Gerards, 2008/01/15
- Re: [PATCH] jpeg image reader, Bean, 2008/01/15
- Re: [PATCH] jpeg image reader, Marco Gerards, 2008/01/15
- Re: [PATCH] jpeg image reader, Bean, 2008/01/15
- Re: [PATCH] jpeg image reader, Marco Gerards, 2008/01/15