apple_png 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: