• R/O
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Chiharu の個人的な作業スペースです。


Commit MetaInfo

Revision4 (tree)
Time2014-03-16 13:53:18
Authorchiharunpo

Log Message

・並列 PNG 圧縮のスケルトンを登録した。

Change Summary

Incremental Difference

--- trunk/ppng.c (nonexistent)
+++ trunk/ppng.c (revision 4)
@@ -0,0 +1,383 @@
1+#include "ppng.h"
2+
3+#include <windows.h>
4+#include <process.h>
5+
6+#include <pngstruct.h>
7+#include <pngpriv.h>
8+#include <zlib.h>
9+
10+#include <assert.h>
11+
12+typedef struct ppng_data {
13+ png_byte* data;
14+ size_t length;
15+} ppng_data;
16+
17+typedef struct ppng_node {
18+ struct ppng_node* prev;
19+ struct ppng_node* next;
20+ ppng_data* data;
21+} ppng_node;
22+
23+typedef struct ppng_list {
24+ CRITICAL_SECTION cs;
25+ HANDLE* events;
26+ ppng_node* first;
27+ ppng_node* last;
28+ ppng_node end_of_node;
29+ png_uint_32 count;
30+} ppng_list;
31+
32+typedef struct ppng_zdata {
33+ ppng_data data;
34+ png_uint_32 adler32;
35+ size_t input;
36+} ppng_zdata;
37+
38+typedef struct ppng_zdata_array {
39+ CRITICAL_SECTION cs;
40+ ppng_zdata* data;
41+ size_t length;
42+ size_t max;
43+} ppng_zdata_array;
44+
45+typedef struct ppng_context {
46+ void* obj;
47+ png_uint_32 index;
48+ HANDLE thread;
49+} ppng_context;
50+
51+struct ppng {
52+ png_structp png;
53+ png_infop info;
54+ png_uint_32 threads, joined;
55+ ppng_list input;
56+ ppng_zdata_array output;
57+
58+ ppng_context context[1];
59+};
60+
61+static unsigned CALLBACK ppng_work(void* arg);
62+
63+static void ppng_set_input(ppng* obj, ppng_data* data);
64+static ppng_data* ppng_get_input(ppng* obj, png_uint_32 thread, png_uint_32* index);
65+static void ppng_set_output(ppng* obj, png_uint_32 index, ppng_data* data, png_uint_32 adler32, size_t input);
66+
67+ppng* ppng_create(png_structp png, png_infop info, png_uint_32 height)
68+{
69+ ppng* obj;
70+ png_uint_32 ct;
71+
72+ SYSTEM_INFO system;
73+
74+ assert(png != NULL);
75+ assert(info != NULL);
76+
77+ GetSystemInfo(&system);
78+
79+ obj = malloc(offsetof(ppng, context) + system.dwNumberOfProcessors * sizeof(ppng_context));
80+ obj->png = png;
81+ obj->info = info;
82+ obj->threads = system.dwNumberOfProcessors;
83+ obj->joined = 0;
84+
85+ InitializeCriticalSection(&obj->input.cs);
86+ obj->input.events = malloc(obj->threads * sizeof(HANDLE));
87+ for (ct = 0; ct < obj->threads; ct++) {
88+ obj->input.events[ct] = CreateEvent(NULL, TRUE, FALSE, NULL);
89+ }
90+ obj->input.first = NULL;
91+ obj->input.last = NULL;
92+ obj->input.count = 0;
93+
94+ InitializeCriticalSection(&obj->output.cs);
95+ obj->output.data = NULL;
96+ obj->output.length = 0;
97+ obj->output.max = 0;
98+
99+ for (ct = 0; ct < obj->threads; ct++) {
100+ obj->context[ct].obj = obj;
101+ obj->context[ct].index = ct;
102+ obj->context[ct].thread = (HANDLE) _beginthreadex(NULL, 0, ppng_work, &obj->context[ct], 0, NULL);
103+ }
104+
105+ return obj;
106+}
107+
108+void ppng_destroy(ppng* obj)
109+{
110+ png_uint_32 ct;
111+
112+ assert(obj != NULL);
113+
114+ if (obj->joined == 0) {
115+ ppng_set_input(obj, NULL);
116+
117+ for (ct = 0; ct < obj->threads; ct++) {
118+ WaitForSingleObject(obj->context[ct].thread, INFINITE);
119+ }
120+ }
121+
122+ for (ct = 0; ct < obj->output.length; ct++) {
123+ free(obj->output.data[ct].data.data);
124+ }
125+
126+ for (ct = 0; ct < obj->threads; ct++) {
127+ CloseHandle(obj->input.events[ct]);
128+ }
129+ free(obj->input.events);
130+
131+ for (ct = 0; ct < obj->threads; ct++) {
132+ CloseHandle(obj->context[ct].thread);
133+ }
134+
135+ free(obj);
136+}
137+
138+ppng_result ppng_add(ppng* obj, const void* pixels, png_uint_32 rowbytes, png_uint_32 height)
139+{
140+ ppng_data* input;
141+ png_uint_32 prowbytes, ct;
142+
143+ png_byte* dst;
144+ const png_byte* src;
145+
146+ assert(pixels != NULL);
147+ assert(rowbytes > 0);
148+ assert(height > 0);
149+
150+ input = malloc(sizeof(ppng_data));
151+
152+ prowbytes = png_get_rowbytes(obj->png, obj->info);
153+
154+ input->data = malloc(prowbytes * height);
155+ input->length = prowbytes * height;
156+
157+ dst = input->data;
158+ src = pixels;
159+
160+ for (ct = 0; ct < height; ct++) {
161+ memcpy(dst, src, min(prowbytes, rowbytes));
162+ dst += prowbytes;
163+ src += rowbytes;
164+ }
165+
166+ ppng_set_input(obj, input);
167+
168+ return ppng_result_succeeded;
169+}
170+
171+ppng_result ppng_finalize(ppng* obj)
172+{
173+ png_uint_32 ct;
174+
175+ size_t length;
176+ png_byte* data;
177+ png_uint_32 adler32;
178+
179+ png_unknown_chunk chunk;
180+
181+ assert(obj != NULL);
182+ assert(obj->joined == 0);
183+
184+ ppng_set_input(obj, NULL);
185+
186+ for (ct = 0; ct < obj->threads; ct++) {
187+ WaitForSingleObject(obj->context[ct].thread, INFINITE);
188+ }
189+
190+ obj->joined = 1;
191+
192+ length = 4, adler32 = 0;
193+ for (ct = 0; ct < obj->output.length; ct++) {
194+ if (ct == 0) {
195+ length += obj->output.data[ct].data.length;
196+ } else {
197+ length += obj->output.data[ct].data.length - 2;
198+ }
199+ adler32 = adler32_combine(adler32, obj->output.data[ct].adler32, obj->output.data[ct].input);
200+ }
201+
202+ data = malloc(length);
203+
204+ data[0] = adler32;
205+ data[1] = adler32 >> 8;
206+ data[2] = adler32 >> 16;
207+ data[3] = adler32 >> 24;
208+
209+ length = 4;
210+ for (ct = 0; ct < obj->output.length; ct++) {
211+ if (ct == 0) {
212+ memcpy(data + length, obj->output.data[ct].data.data, obj->output.data[ct].data.length);
213+ length += obj->output.data[ct].data.length;
214+ } else {
215+ memcpy(data + length, obj->output.data[ct].data.data + 2, obj->output.data[ct].data.length - 2);
216+ length += obj->output.data[ct].data.length - 2;
217+ }
218+ adler32 = adler32_combine(adler32, obj->output.data[ct].adler32, obj->output.data[ct].input);
219+ }
220+
221+ obj->png->mode |= PNG_HAVE_IDAT;
222+
223+ memcpy(chunk.name, "IDAT", 4);
224+ chunk.data = data;
225+ chunk.size = length;
226+ chunk.location = PNG_AFTER_IDAT;
227+
228+ obj->png->flags |= 0x10000L; /* PNG_FLAG_KEEP_UNSAFE_CHUNKS */
229+
230+ png_set_unknown_chunks(obj->png, obj->info, &chunk, 1);
231+ png_set_unknown_chunk_location(obj->png, obj->info, 0, PNG_AFTER_IDAT);
232+
233+ png_write_end(obj->png, obj->info);
234+
235+ return ppng_result_succeeded;
236+}
237+
238+unsigned CALLBACK ppng_work(void* arg)
239+{
240+ ppng_context* context;
241+ ppng_data* input;
242+
243+ z_stream stream;
244+ ppng_data data;
245+ size_t max;
246+ png_uint_32 index;
247+
248+ assert(arg != NULL);
249+
250+ context = arg;
251+
252+ while ((input = ppng_get_input(context->obj, context->index, &index)) != NULL) {
253+ stream.zalloc = Z_NULL;
254+ stream.zfree = Z_NULL;
255+ stream.opaque = Z_NULL;
256+ deflateInit(&stream, 3);
257+
258+ stream.avail_in = input->length;
259+ stream.next_in = input->data;
260+
261+ data.data = NULL;
262+ data.length = 0, max = 0;
263+
264+ do {
265+ max += 4096;
266+ data.data = realloc(data.data, max);
267+
268+ stream.avail_out = max - data.length;
269+ stream.next_out = data.data + data.length;
270+
271+ data.length += 4096 - stream.avail_out;
272+
273+ } while (stream.avail_out == 0);
274+
275+ ppng_set_output(context->obj, index, &data, stream.adler, input->length);
276+
277+ deflateEnd(&stream);
278+
279+ free(input);
280+ }
281+
282+ return 0;
283+}
284+
285+void ppng_set_input(ppng* obj, ppng_data* data)
286+{
287+ ppng_node* node;
288+ png_uint_32 ct;
289+
290+ assert(obj != NULL);
291+ assert(data != NULL);
292+
293+ if (data != NULL) {
294+ node = malloc(sizeof(ppng_node));
295+ node->prev = NULL;
296+ node->next = NULL;
297+ node->data = data;
298+ } else {
299+ node = &obj->input.end_of_node;
300+ }
301+
302+ EnterCriticalSection(&obj->input.cs);
303+
304+ if (obj->input.first == NULL) {
305+ obj->input.first = node;
306+ }
307+ node->prev = obj->input.last;
308+ obj->input.last = node;
309+
310+ for (ct = 0; ct < obj->threads; ct++) {
311+ SetEvent(obj->input.events[ct]);
312+ }
313+
314+ LeaveCriticalSection(&obj->input.cs);
315+}
316+
317+ppng_data* ppng_get_input(ppng* obj, png_uint_32 thread, png_uint_32* index)
318+{
319+ ppng_data* data;
320+ png_uint_32 count;
321+
322+ ppng_node* node;
323+ HANDLE* event;
324+
325+ assert(obj != NULL);
326+ assert(index != NULL);
327+
328+ EnterCriticalSection(&obj->input.cs);
329+
330+ event = obj->input.events[thread];
331+
332+ while ((node = obj->input.first) == NULL) {
333+ ResetEvent(event);
334+ LeaveCriticalSection(&obj->input.cs);
335+
336+ WaitForSingleObject(event, INFINITE);
337+
338+ EnterCriticalSection(&obj->input.cs);
339+ }
340+
341+ if (node != &obj->input.end_of_node) {
342+ obj->input.first = node->next;
343+ if (node == obj->input.last) {
344+ obj->input.last = NULL;
345+ }
346+ } else {
347+ node = NULL;
348+ }
349+ count = obj->input.count++;
350+
351+ LeaveCriticalSection(&obj->input.cs);
352+
353+ data = NULL;
354+ if (node != NULL) {
355+ data = node->data;
356+ free(node);
357+ }
358+
359+ *index = count;
360+
361+ return data;
362+}
363+
364+void ppng_set_output(ppng* obj, png_uint_32 index, ppng_data* data, png_uint_32 adler32, size_t input)
365+{
366+ assert(obj != NULL);
367+ assert(data != NULL);
368+
369+ EnterCriticalSection(&obj->output.cs);
370+
371+ if (index >= obj->output.max) {
372+ obj->output.max = (index + 1023) & ~1024;
373+ obj->output.data = realloc(obj->output.data, obj->output.max * sizeof(ppng_zdata));
374+ }
375+
376+ obj->output.data[index].data = *data;
377+ obj->output.data[index].adler32 = adler32;
378+ obj->output.data[index].input = input;
379+
380+ obj->output.length = max(obj->output.length, index);
381+
382+ LeaveCriticalSection(&obj->output.cs);
383+}
--- trunk/ppng_main.c (nonexistent)
+++ trunk/ppng_main.c (revision 4)
@@ -0,0 +1,6 @@
1+#include "ppng.h"
2+
3+int main()
4+{
5+ return 0;
6+}
--- trunk/ppng.h (nonexistent)
+++ trunk/ppng.h (revision 4)
@@ -0,0 +1,28 @@
1+
2+#ifndef PPNG_H_INCLUDED
3+
4+#include <png.h>
5+
6+#ifdef __cplusplus
7+extern "C" {
8+#endif
9+
10+typedef struct ppng ppng;
11+
12+typedef enum ppng_result {
13+ ppng_result_succeeded,
14+ ppng_result_out_of_memory,
15+ ppng_result_io_error,
16+} ppng_result;
17+
18+ppng* ppng_create(png_structp png, png_infop info, png_uint_32 height);
19+void ppng_destroy(ppng* obj);
20+
21+ppng_result ppng_add(ppng* obj, const void* pixels, png_uint_32 rowbytes, png_uint_32 height);
22+ppng_result ppng_finalize(ppng* obj);
23+
24+#ifdef __cplusplus
25+}
26+#endif
27+
28+#endif