grml...
[seabios.git] / src / jpeg.c
index b204345a10fb629ed35055472b90af09192843e2..a96a9d7fd5c3e9245b5e87ffc2d5db3a4db9fd34 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2001, Novell Inc.
+ * Copyright (C) 2010  Kevin O'Connor <kevin@koconnor.net>
  * All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
@@ -177,6 +178,8 @@ struct jpeg_decdata {
     unsigned char quant[4][64];
     struct dec_hufftbl dhuff[4];
     struct in in;
+
+    int height, width;
 };
 
 static int getbyte(struct jpeg_decdata *jpeg)
@@ -292,29 +295,11 @@ struct jpeg_decdata *jpeg_alloc(void)
     return jpeg;
 }
 
-int jpeg_check_size(struct jpeg_decdata *jpeg, unsigned char *buf
-                    , int width, int height)
-{
-    jpeg->datap = buf;
-    getbyte(jpeg);
-    getbyte(jpeg);
-    readtables(jpeg, M_SOF0);
-    getword(jpeg);
-    getbyte(jpeg);
-    if (height != getword(jpeg) || width != getword(jpeg))
-        return 0;
-    return 1;
-}
-
-int jpeg_decode(unsigned char *buf, unsigned char *pic,
-                int width, int height, int depth,
-                struct jpeg_decdata *jpeg)
+int jpeg_decode(struct jpeg_decdata *jpeg, unsigned char *buf)
 {
     int i, j, m, tac, tdc;
-    int mcusx, mcusy, mx, my;
-    int max[6];
 
-    if (!jpeg || !buf || !pic)
+    if (!jpeg || !buf)
         return -1;
     jpeg->datap = buf;
     if (getbyte(jpeg) != 0xff)
@@ -327,11 +312,9 @@ int jpeg_decode(unsigned char *buf, unsigned char *pic,
     i = getbyte(jpeg);
     if (i != 8)
         return ERR_NOT_8BIT;
-    if (((getword(jpeg) + 15) & ~15) != height)
-        return ERR_HEIGHT_MISMATCH;
-    if (((getword(jpeg) + 15) & ~15) != width)
-        return ERR_WIDTH_MISMATCH;
-    if ((height & 15) || (width & 15))
+    jpeg->height = getword(jpeg);
+    jpeg->width = getword(jpeg);
+    if ((jpeg->height & 15) || (jpeg->width & 15))
         return ERR_BAD_WIDTH_OR_HEIGHT;
     jpeg->info.nc = getbyte(jpeg);
     if (jpeg->info.nc > MAXCOMP)
@@ -387,10 +370,6 @@ int jpeg_decode(unsigned char *buf, unsigned char *pic,
         || jpeg->dscans[2].hv != 0x11)
         return ERR_NOT_YCBCR_221111;
 
-    mcusx = width >> 4;
-    mcusy = height >> 4;
-
-
     idctqtab(jpeg->quant[jpeg->dscans[0].tq], jpeg->dquant[0]);
     idctqtab(jpeg->quant[jpeg->dscans[1].tq], jpeg->dquant[1]);
     idctqtab(jpeg->quant[jpeg->dscans[2].tq], jpeg->dquant[2]);
@@ -406,6 +385,32 @@ int jpeg_decode(unsigned char *buf, unsigned char *pic,
 
     dec_initscans(jpeg);
 
+    return 0;
+}
+
+void jpeg_get_size(struct jpeg_decdata *jpeg, int *width, int *height)
+{
+    *width = jpeg->width;
+    *height = jpeg->height;
+}
+
+int jpeg_show(struct jpeg_decdata *jpeg, unsigned char *pic, int width
+              , int height, int depth, int bytes_per_line_dest)
+{
+    int m, mcusx, mcusy, mx, my, mloffset, jpgbpl;
+    int max[6];
+
+    if (jpeg->height != height)
+        return ERR_HEIGHT_MISMATCH;
+    if (jpeg->width != width)
+        return ERR_WIDTH_MISMATCH;
+
+    jpgbpl = width * depth / 8;
+    mloffset = bytes_per_line_dest > jpgbpl ? bytes_per_line_dest : jpgbpl;
+
+    mcusx = jpeg->width >> 4;
+    mcusy = jpeg->height >> 4;
+
     jpeg->dscans[0].next = 6 - 4;
     jpeg->dscans[1].next = 6 - 4 - 1;
     jpeg->dscans[2].next = 6 - 4 - 1 - 1;        /* 411 encoding */
@@ -420,30 +425,30 @@ int jpeg_decode(unsigned char *buf, unsigned char *pic,
                  IFIX(128.5), max[0]);
             idct(jpeg->dcts + 64, jpeg->out + 64, jpeg->dquant[0],
                  IFIX(128.5), max[1]);
-            idct(jpeg->dcts + 128, jpeg->out + 128,
-                 jpeg->dquant[0], IFIX(128.5), max[2]);
-            idct(jpeg->dcts + 192, jpeg->out + 192,
-                 jpeg->dquant[0], IFIX(128.5), max[3]);
-            idct(jpeg->dcts + 256, jpeg->out + 256,
-                 jpeg->dquant[1], IFIX(0.5), max[4]);
-            idct(jpeg->dcts + 320, jpeg->out + 320,
-                 jpeg->dquant[2], IFIX(0.5), max[5]);
+            idct(jpeg->dcts + 128, jpeg->out + 128, jpeg->dquant[0],
+                 IFIX(128.5), max[2]);
+            idct(jpeg->dcts + 192, jpeg->out + 192, jpeg->dquant[0],
+                 IFIX(128.5), max[3]);
+            idct(jpeg->dcts + 256, jpeg->out + 256, jpeg->dquant[1],
+                 IFIX(0.5), max[4]);
+            idct(jpeg->dcts + 320, jpeg->out + 320, jpeg->dquant[2],
+                 IFIX(0.5), max[5]);
 
             switch (depth) {
             case 32:
                 col221111_32(jpeg->out,
-                             pic + (my * 16 * mcusx + mx) * 16 * 4,
-                             mcusx * 16 * 4);
+                             pic + (my * 16 * mloffset + mx * 16 * 4),
+                             mloffset);
                 break;
             case 24:
                 col221111(jpeg->out,
-                          pic + (my * 16 * mcusx + mx) * 16 * 3,
-                          mcusx * 16 * 3);
+                          pic + (my * 16 * mloffset + mx * 16 * 3),
+                          mloffset);
                 break;
             case 16:
                 col221111_16(jpeg->out,
-                             pic + (my * 16 * mcusx + mx) * (16 * 2),
-                             mcusx * (16 * 2));
+                             pic + (my * 16 * mloffset + mx * 16 * 2),
+                             mloffset);
                 break;
             default:
                 return ERR_DEPTH_MISMATCH;
@@ -885,6 +890,15 @@ static void initcol(PREC q[][64])
 
 #endif
 
+#ifdef __LITTLE_ENDIAN
+#define PIC(yin, xin, p, xout)                   \
+(                                                \
+  y = outy[(yin) * 8 + xin],                     \
+  STORECLAMP(p[(xout) * 3 + 2], y + cr),         \
+  STORECLAMP(p[(xout) * 3 + 1], y - cg),         \
+  STORECLAMP(p[(xout) * 3 + 0], y + cb)          \
+)
+#else
 #define PIC(yin, xin, p, xout)                   \
 (                                                \
   y = outy[(yin) * 8 + xin],                     \
@@ -892,6 +906,7 @@ static void initcol(PREC q[][64])
   STORECLAMP(p[(xout) * 3 + 1], y - cg),         \
   STORECLAMP(p[(xout) * 3 + 2], y + cb)          \
 )
+#endif
 
 #ifdef __LITTLE_ENDIAN
 #define PIC_16(yin, xin, p, xout, add)           \