mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-26 23:10:38 +00:00
8eb773888f
Previously at 1.7.0beta35.
149 lines
3.5 KiB
C
149 lines
3.5 KiB
C
|
|
/* pngwtran.c - transforms the data in a row for PNG writers
|
|
*
|
|
* Last changed in libpng 1.7.0 [(PENDING RELEASE)]
|
|
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
|
|
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
|
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
|
*
|
|
* This code is released under the libpng license.
|
|
* For conditions of distribution and use, see the disclaimer
|
|
* and license in png.h
|
|
*/
|
|
|
|
#include "pngpriv.h"
|
|
#define PNG_SRC_FILE PNG_SRC_FILE_pngwtran
|
|
|
|
#ifdef PNG_WRITE_PACK_SUPPORTED
|
|
/* Pack pixels into bytes. */
|
|
static void
|
|
png_do_write_pack(png_transformp *transform, png_transform_controlp tc)
|
|
{
|
|
png_alloc_size_t rowbytes = PNG_TC_ROWBYTES(*tc);
|
|
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
|
|
png_const_bytep ep = png_upcast(png_const_bytep, tc->sp) + rowbytes;
|
|
png_bytep dp = png_voidcast(png_bytep, tc->dp);
|
|
|
|
png_debug(1, "in png_do_pack");
|
|
|
|
# define png_ptr tc->png_ptr
|
|
|
|
switch ((*transform)->args)
|
|
{
|
|
case 1:
|
|
{
|
|
unsigned int mask = 0x80, v = 0;
|
|
|
|
while (sp < ep)
|
|
{
|
|
if (*sp++ != 0)
|
|
v |= mask;
|
|
|
|
mask >>= 1;
|
|
|
|
if (mask == 0)
|
|
{
|
|
mask = 0x80;
|
|
*dp++ = PNG_BYTE(v);
|
|
v = 0;
|
|
}
|
|
}
|
|
|
|
if (mask != 0x80)
|
|
*dp++ = PNG_BYTE(v);
|
|
break;
|
|
}
|
|
|
|
case 2:
|
|
{
|
|
unsigned int shift = 8, v = 0;
|
|
|
|
while (sp < ep)
|
|
{
|
|
shift -= 2;
|
|
v |= (*sp++ & 0x3) << shift;
|
|
|
|
if (shift == 0)
|
|
{
|
|
shift = 8;
|
|
*dp++ = PNG_BYTE(v);
|
|
v = 0;
|
|
}
|
|
}
|
|
|
|
if (shift != 8)
|
|
*dp++ = PNG_BYTE(v);
|
|
break;
|
|
}
|
|
|
|
case 4:
|
|
{
|
|
unsigned int shift = 8, v = 0;
|
|
|
|
while (sp < ep)
|
|
{
|
|
shift -= 4;
|
|
v |= ((*sp++ & 0xf) << shift);
|
|
|
|
if (shift == 0)
|
|
{
|
|
shift = 8;
|
|
*dp++ = PNG_BYTE(v);
|
|
v = 0;
|
|
}
|
|
}
|
|
|
|
if (shift != 8)
|
|
*dp++ = PNG_BYTE(v);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
impossible("bit depth");
|
|
}
|
|
|
|
if ((tc->format & PNG_FORMAT_FLAG_COLORMAP) == 0 &&
|
|
--(tc->range) == 0)
|
|
tc->format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_RANGE);
|
|
|
|
tc->bit_depth = (*transform)->args;
|
|
tc->sp = tc->dp;
|
|
# undef png_ptr
|
|
}
|
|
|
|
void /* PRIVATE */
|
|
png_init_write_pack(png_transformp *transform, png_transform_controlp tc)
|
|
{
|
|
# define png_ptr tc->png_ptr
|
|
debug(tc->init);
|
|
# undef png_ptr
|
|
|
|
/* The init routine is called *forward* so the transform control we get has
|
|
* the required bit depth and the transform routine will increase it to 8
|
|
* bits per channel. The code doesn't really care how many channels there
|
|
* are, but the only way to get a channel depth of less than 8 is to have
|
|
* just one channel.
|
|
*/
|
|
if (tc->bit_depth < 8) /* else no packing/unpacking */
|
|
{
|
|
if (tc->init == PNG_TC_INIT_FINAL)
|
|
{
|
|
(*transform)->fn = png_do_write_pack;
|
|
/* Record this for the backwards run: */
|
|
(*transform)->args = tc->bit_depth & 0xf;
|
|
}
|
|
|
|
if ((tc->format & PNG_FORMAT_FLAG_COLORMAP) == 0)
|
|
{
|
|
tc->range++;
|
|
tc->format |= PNG_FORMAT_FLAG_RANGE; /* forwards: backwards cancels */
|
|
}
|
|
|
|
tc->bit_depth = 8;
|
|
}
|
|
|
|
else /* the transform is not applicable */
|
|
(*transform)->fn = NULL;
|
|
}
|
|
#endif /* WRITE_PACK */
|