apple_png 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/ext/apple_png/apple_png.c +41 -3
  2. metadata +1 -1
@@ -6,18 +6,54 @@
6
6
  #define PNG_HEADER "\x89PNG\r\n\x1a\n"
7
7
  #define PNG_BYTES2UINT(char_ptr) (ntohl(*(uint32_t *)(char_ptr)))
8
8
 
9
+ #define DIV_CEIL(a,b) (((a) + (b) - 1) / (b))
10
+
9
11
  #define APPLE_PNG_OK 0
10
12
  #define APPLE_PNG_STREAM_ERROR Z_STREAM_ERROR
11
13
  #define APPLE_PNG_DATA_ERROR Z_DATA_ERROR
12
14
  #define APPLE_PNG_ZLIB_VERSION_ERROR Z_VERSION_ERROR
13
15
  #define APPLE_PNG_NO_MEM_ERROR Z_MEM_ERROR
14
16
 
17
+ /* calculate how many scanlines an adam7 interlaced png will result in */
18
+ static uint32_t interlaced_count_scanlines(uint32_t width, uint32_t height) {
19
+ uint32_t pass[7];
20
+
21
+ if (width == 0 || height == 0) return 0;
22
+
23
+ /* For each pass, calculate how many resulting scanlines there will be.
24
+ * I'm sure there is a more elegant solution to accomplish this.
25
+ * This makes use of the adam7 raster:
26
+ * 1 6 4 6 2 6 4 6
27
+ * 7 7 7 7 7 7 7 7
28
+ * 5 6 5 6 5 6 5 6
29
+ * 7 7 7 7 7 7 7 7
30
+ * 3 6 4 6 3 6 4 6
31
+ * 7 7 7 7 7 7 7 7
32
+ * 5 6 5 6 5 6 5 6
33
+ * 7 7 7 7 7 7 7 7
34
+ */
35
+ pass[0] = DIV_CEIL(height, 8u);
36
+ pass[1] = (width > 4) ? DIV_CEIL(height, 8u) : 0;
37
+ pass[2] = DIV_CEIL(height-4, 8u);
38
+ pass[3] = (width > 2) ? DIV_CEIL(height, 4u) : 0;
39
+ pass[4] = DIV_CEIL(height-2, 4u);
40
+ pass[5] = (width > 1) ? DIV_CEIL(height, 2u) : 0;
41
+ pass[6] = DIV_CEIL(height-1, 2u);
42
+
43
+ return pass[0] + pass[1] + pass[2] + pass[3] + pass[4] + pass[5] + pass[6];
44
+ }
45
+
15
46
  /* inflate from apple png file, don't expect headers */
16
- static int png_inflate(unsigned char *data, uint32_t length, uint32_t width, uint32_t height, unsigned char **out_buff, uint32_t *out_uncompressed_size) {
47
+ static int png_inflate(unsigned char *data, uint32_t length, uint32_t width, uint32_t height, int interlaced, unsigned char **out_buff, uint32_t *out_uncompressed_size) {
17
48
  int error;
18
49
  z_stream inflate_strm = {0};
19
50
 
20
- *out_uncompressed_size = height + width * height * 4;
51
+ if (interlaced) {
52
+ *out_uncompressed_size = interlaced_count_scanlines(width, height) + width * height * 4;
53
+ } else {
54
+ *out_uncompressed_size = height + width * height * 4;
55
+ }
56
+
21
57
  *out_buff = malloc(sizeof(char) * (*out_uncompressed_size));
22
58
  if (*out_buff == 0) {
23
59
  return APPLE_PNG_NO_MEM_ERROR;
@@ -114,6 +150,7 @@ static uint32_t png_crc32(const char *chunkType, const char *chunkData, uint32_t
114
150
  /* extract chunks from PNG data */
115
151
  static int readPngChunks(VALUE self, const char *oldPNG, size_t oldPngLength, dyn_arr *newPNG) {
116
152
  uint32_t width = 0, height = 0;
153
+ int interlaced = 0;
117
154
  size_t cursor = 8;
118
155
  dyn_arr *applePngCompressedPixelData = dyn_arr_create(oldPngLength);
119
156
  if (applePngCompressedPixelData == 0) {
@@ -133,6 +170,7 @@ static int readPngChunks(VALUE self, const char *oldPNG, size_t oldPngLength, dy
133
170
  /* extract dimensions from header */
134
171
  width = PNG_BYTES2UINT(&chunkData[0]);
135
172
  height = PNG_BYTES2UINT(&chunkData[4]);
173
+ interlaced = chunkData[12] == 1;
136
174
  rb_funcall(self, rb_intern("width="), 1, INT2NUM(width));
137
175
  rb_funcall(self, rb_intern("height="), 1, INT2NUM(height));
138
176
  } else if (strncmp(chunkType, "IDAT", 4) == 0) {
@@ -151,7 +189,7 @@ static int readPngChunks(VALUE self, const char *oldPNG, size_t oldPngLength, dy
151
189
  int error;
152
190
 
153
191
  /* decompress, flip color bytes, then compress again */
154
- error = png_inflate((unsigned char *)applePngCompressedPixelData->arr, (uint32_t)applePngCompressedPixelData->used, width, height, &decompressedPixelData, &uncompressed_size);
192
+ error = png_inflate((unsigned char *)applePngCompressedPixelData->arr, (uint32_t)applePngCompressedPixelData->used, width, height, interlaced, &decompressedPixelData, &uncompressed_size);
155
193
  if (error != APPLE_PNG_OK) {
156
194
  dyn_arr_free(applePngCompressedPixelData);
157
195
  return error;
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apple_png
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: