176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Small jpeg decoder library
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * All rights reserved.
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Redistribution and use in source and binary forms, with or without
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * modification, are permitted provided that the following conditions are met:
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * - Redistributions of source code must retain the above copyright notice,
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  this list of conditions and the following disclaimer.
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * - Redistributions in binary form must reproduce the above copyright notice,
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  this list of conditions and the following disclaimer in the documentation
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  and/or other materials provided with the distribution.
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * - Neither the name of the author nor the names of its contributors may be
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  used to endorse or promote products derived from this software without
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  specific prior written permission.
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * POSSIBILITY OF SUCH DAMAGE.
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * yuv420p.c
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdio.h>
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdlib.h>
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h>
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdint.h>
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "tinyjpeg.h"
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "tinyjpeg-internal.h"
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*******************************************************************************
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Colorspace conversion routine
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Note:
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * The conversion equations to be implemented are therefore
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *      R = Y                + 1.40200 * Cr
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *      G = Y - 0.34414 * Cb - 0.71414 * Cr
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *      B = Y + 1.77200 * Cb
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ******************************************************************************/
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  YCrCb -> YUV420P (1x1)
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  .---.
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  | 1 |
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  `---'
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void YCrCB_to_YUV420P_1x1(struct jdec_private *priv, int sx, int sy)
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  const unsigned char *s, *y;
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  unsigned char *p;
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int i,j;
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  p = priv->plane[0];
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  y = priv->Y;
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (i = sy; i > 0; i--)
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     memcpy(p, y, sx);
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     p += priv->bytes_per_row[0];
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     y += 8;
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  p = priv->plane[1];
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  s = priv->Cb;
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (i = sy; i > 0; i--)
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     for (j = sx; j >= 0; j -= 2) {
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       *p++ = *s;
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       s += 2;
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     }
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     s += 8; /* Skip one line */
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     p += priv->bytes_per_row[1] - 4;
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  p = priv->plane[2];
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  s = priv->Cr;
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (i=0; i<8; i+=2)
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     for (j = sx; j >= 0; j -= 2) {
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       *p++ = *s;
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       s += 2;
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     }
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     s += 8; /* Skip one line */
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     p += priv->bytes_per_row[2] - 4;
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  YCrCb -> YUV420P (2x1)
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  .-------.
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  | 1 | 2 |
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  `-------'
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void YCrCB_to_YUV420P_2x1(struct jdec_private *priv, int sx, int sy)
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  unsigned char *p;
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  const unsigned char *s, *y1;
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  unsigned int i;
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  p = priv->plane[0];
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  y1 = priv->Y;
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (i = sy; i > 0; i--)
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     memcpy(p, y1, sx);
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     p += priv->bytes_per_row[0];
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     y1 += 16;
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  sx = (sx+1) >> 1;
12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  p = priv->plane[1];
13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  s = priv->Cb;
13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (i = sy; i > 0; i -= 2)
13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     memcpy(p, s, sx);
13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     s += 16; /* Skip one line */
13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     p += priv->bytes_per_row[1];
13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  p = priv->plane[2];
14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  s = priv->Cr;
14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (i = sy; i > 0; i -= 2)
14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     memcpy(p, s, sx);
14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     s += 16; /* Skip one line */
14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     p += priv->bytes_per_row[2];
14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  YCrCb -> YUV420P (1x2)
15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  .---.
15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  | 1 |
15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  |---|
15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  | 2 |
15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  `---'
15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void YCrCB_to_YUV420P_1x2(struct jdec_private *priv, int sx, int sy)
15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  const unsigned char *s, *y;
16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  unsigned char *p, *pr;
16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int i,j;
16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  p = priv->plane[0];
16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  y = priv->Y;
16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (i = sy; i > 0; i++)
16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     memcpy(p, y, sx);
16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     p+=priv->bytes_per_row[0];
17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     y+=8;
17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  pr = priv->plane[1];
17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  s = priv->Cb;
17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (i = sy; i > 0; i -= 2)
17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     p = pr;
17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     for (j = sx; j > 0; j -= 2) {
17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       *p++ = *s;
18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       s += 2;
18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     }
18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     pr += priv->bytes_per_row[1];
18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  pr = priv->plane[2];
18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  s = priv->Cr;
18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (i=0; i<8; i++)
18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     p = pr;
19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     for (j = sx; j > 0; j -= 2) {
19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       *p++ = *s;
19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       s += 2;
19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     }
19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     pr += priv->bytes_per_row[2] - 4;
19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  YCrCb -> YUV420P (2x2)
20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  .-------.
20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  | 1 | 2 |
20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  |---+---|
20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  | 3 | 4 |
20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  `-------'
20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void YCrCB_to_YUV420P_2x2(struct jdec_private *priv, int sx, int sy)
20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  unsigned char *p;
20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  const unsigned char *s, *y1;
21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  unsigned int i;
21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  p = priv->plane[0];
21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  y1 = priv->Y;
21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (i = sy; i > 0; i--)
21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     memcpy(p, y1, sx);
21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     p += priv->bytes_per_row[0];
21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     y1 += 16;
21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  sx = (sx+1) >> 1;
22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  p = priv->plane[1];
22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  s = priv->Cb;
22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (i = sy; i > 0; i -= 2)
22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     memcpy(p, s, sx);
22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     s += 8;
22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     p += priv->bytes_per_row[1];
23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  p = priv->plane[2];
23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  s = priv->Cr;
23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (i = sy; i > 0; i -= 2)
23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   {
23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     memcpy(p, s, sx);
23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     s += 8;
23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     p += priv->bytes_per_row[2];
23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   }
24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int initialize_yuv420p(struct jdec_private *priv,
24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			      unsigned int *bytes_per_blocklines,
24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			      unsigned int *bytes_per_mcu)
24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int half_height = (priv->height + 1) >> 2;
24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int half_width  = (priv->width  + 1) >> 2;
24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (!priv->bytes_per_row[0])
25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    priv->bytes_per_row[0] = priv->width;
25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (!priv->components[0])
25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    priv->components[0] = malloc(priv->height * priv->bytes_per_row[0]);
25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (!priv->bytes_per_row[1])
25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    priv->bytes_per_row[1] = half_width;
25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (!priv->components[1])
25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    priv->components[1] = malloc(half_height * priv->bytes_per_row[1]);
25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (!priv->bytes_per_row[2])
26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    priv->bytes_per_row[2] = half_width;
26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (!priv->components[2])
26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    priv->components[2] = malloc(half_height * priv->bytes_per_row[2]);
26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  bytes_per_mcu[0] = 8;
26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  bytes_per_mcu[1] = 4;
26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  bytes_per_mcu[2] = 4;
26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  bytes_per_blocklines[0] = priv->width << 3;
26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  bytes_per_blocklines[1] = half_width << 2;
27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  bytes_per_blocklines[2] = half_width << 2;
27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /* Return nonzero on failure */
27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return !priv->components[0] || !priv->components[1] || !priv->components[2];
27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic const struct tinyjpeg_colorspace format_yuv420p =
27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  {
27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      YCrCB_to_YUV420P_1x1,
28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      YCrCB_to_YUV420P_1x2,
28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      YCrCB_to_YUV420P_2x1,
28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      YCrCB_to_YUV420P_2x2,
28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    },
28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    tinyjpeg_decode_mcu_3comp_table,
28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    initialize_yuv420p
28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  };
28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanconst tinyjpeg_colorspace_t TINYJPEG_FMT_YUV420P = &format_yuv420p;
289