CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/ext/libpng17/pngwtran.c
Views: 1401
1
2
/* pngwtran.c - transforms the data in a row for PNG writers
3
*
4
* Last changed in libpng 1.7.0 [(PENDING RELEASE)]
5
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
6
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8
*
9
* This code is released under the libpng license.
10
* For conditions of distribution and use, see the disclaimer
11
* and license in png.h
12
*/
13
14
#include "pngpriv.h"
15
#define PNG_SRC_FILE PNG_SRC_FILE_pngwtran
16
17
#ifdef PNG_WRITE_PACK_SUPPORTED
18
/* Pack pixels into bytes. */
19
static void
20
png_do_write_pack(png_transformp *transform, png_transform_controlp tc)
21
{
22
png_alloc_size_t rowbytes = PNG_TC_ROWBYTES(*tc);
23
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
24
png_const_bytep ep = png_upcast(png_const_bytep, tc->sp) + rowbytes;
25
png_bytep dp = png_voidcast(png_bytep, tc->dp);
26
27
png_debug(1, "in png_do_pack");
28
29
# define png_ptr tc->png_ptr
30
31
switch ((*transform)->args)
32
{
33
case 1:
34
{
35
unsigned int mask = 0x80, v = 0;
36
37
while (sp < ep)
38
{
39
if (*sp++ != 0)
40
v |= mask;
41
42
mask >>= 1;
43
44
if (mask == 0)
45
{
46
mask = 0x80;
47
*dp++ = PNG_BYTE(v);
48
v = 0;
49
}
50
}
51
52
if (mask != 0x80)
53
*dp++ = PNG_BYTE(v);
54
break;
55
}
56
57
case 2:
58
{
59
unsigned int shift = 8, v = 0;
60
61
while (sp < ep)
62
{
63
shift -= 2;
64
v |= (*sp++ & 0x3) << shift;
65
66
if (shift == 0)
67
{
68
shift = 8;
69
*dp++ = PNG_BYTE(v);
70
v = 0;
71
}
72
}
73
74
if (shift != 8)
75
*dp++ = PNG_BYTE(v);
76
break;
77
}
78
79
case 4:
80
{
81
unsigned int shift = 8, v = 0;
82
83
while (sp < ep)
84
{
85
shift -= 4;
86
v |= ((*sp++ & 0xf) << shift);
87
88
if (shift == 0)
89
{
90
shift = 8;
91
*dp++ = PNG_BYTE(v);
92
v = 0;
93
}
94
}
95
96
if (shift != 8)
97
*dp++ = PNG_BYTE(v);
98
break;
99
}
100
101
default:
102
impossible("bit depth");
103
}
104
105
if ((tc->format & PNG_FORMAT_FLAG_COLORMAP) == 0 &&
106
--(tc->range) == 0)
107
tc->format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_RANGE);
108
109
tc->bit_depth = (*transform)->args;
110
tc->sp = tc->dp;
111
# undef png_ptr
112
}
113
114
void /* PRIVATE */
115
png_init_write_pack(png_transformp *transform, png_transform_controlp tc)
116
{
117
# define png_ptr tc->png_ptr
118
debug(tc->init);
119
# undef png_ptr
120
121
/* The init routine is called *forward* so the transform control we get has
122
* the required bit depth and the transform routine will increase it to 8
123
* bits per channel. The code doesn't really care how many channels there
124
* are, but the only way to get a channel depth of less than 8 is to have
125
* just one channel.
126
*/
127
if (tc->bit_depth < 8) /* else no packing/unpacking */
128
{
129
if (tc->init == PNG_TC_INIT_FINAL)
130
{
131
(*transform)->fn = png_do_write_pack;
132
/* Record this for the backwards run: */
133
(*transform)->args = tc->bit_depth & 0xf;
134
}
135
136
if ((tc->format & PNG_FORMAT_FLAG_COLORMAP) == 0)
137
{
138
tc->range++;
139
tc->format |= PNG_FORMAT_FLAG_RANGE; /* forwards: backwards cancels */
140
}
141
142
tc->bit_depth = 8;
143
}
144
145
else /* the transform is not applicable */
146
(*transform)->fn = NULL;
147
}
148
#endif /* WRITE_PACK */
149
150